diff --git a/src/assets/locales/en.json b/src/assets/locales/en.json
index 01d6205e..6c6c3e9c 100644
--- a/src/assets/locales/en.json
+++ b/src/assets/locales/en.json
@@ -17,7 +17,7 @@
"login": {
"title": "Login to your account",
"description": "Please enter your passphrase to login to your account",
- "validationError": "Invalid or incomplete passphrase",
+ "validationError": "Incorrect or incomplete passphrase",
"deviceLengthError": "Please enter a device name",
"submit": "Login",
"passphraseLabel": "12-Word passphrase",
diff --git a/src/assets/locales/pirate.json b/src/assets/locales/pirate.json
index b0048e82..0abcc5d5 100644
--- a/src/assets/locales/pirate.json
+++ b/src/assets/locales/pirate.json
@@ -16,7 +16,7 @@
"passphrasePlaceholder": "Passphrase",
"submit": "Hoist Anchor",
"title": "Hoist the Jolly Roger",
- "validationError": "Arr, invalid or incomplete passphrase"
+ "validationError": "Arr, incorrect or incomplete passphrase"
},
"register": {
"information": {
diff --git a/src/components/media/MediaCard.tsx b/src/components/media/MediaCard.tsx
index a98770f0..32708285 100644
--- a/src/components/media/MediaCard.tsx
+++ b/src/components/media/MediaCard.tsx
@@ -95,7 +95,7 @@ function MediaCardContent({
{percentage !== undefined ? (
<>
diff --git a/src/components/overlays/positions/OverlayMobilePosition.tsx b/src/components/overlays/positions/OverlayMobilePosition.tsx
index bebf3f03..53b21000 100644
--- a/src/components/overlays/positions/OverlayMobilePosition.tsx
+++ b/src/components/overlays/positions/OverlayMobilePosition.tsx
@@ -16,7 +16,7 @@ export function OverlayMobilePosition(props: MobilePositionProps) {
return (
diff --git a/src/components/player/atoms/NextEpisodeButton.tsx b/src/components/player/atoms/NextEpisodeButton.tsx
index b80df3a9..8699d311 100644
--- a/src/components/player/atoms/NextEpisodeButton.tsx
+++ b/src/components/player/atoms/NextEpisodeButton.tsx
@@ -62,9 +62,11 @@ export function NextEpisodeButton(props: {
if (isHidden || status !== "playing" || duration === 0) show = false;
const animation = showingState === "hover" ? "slide-up" : "fade";
- let bottom = "bottom-24";
+ let bottom = "bottom-[calc(6rem+env(safe-area-inset-bottom))]";
if (showingState === "always")
- bottom = props.controlsShowing ? "bottom-24" : "bottom-12";
+ bottom = props.controlsShowing
+ ? bottom
+ : "bottom-[calc(3rem+env(safe-area-inset-bottom))]";
const nextEp = meta?.episodes?.find(
(v) => v.number === (meta?.episode?.number ?? 0) + 1
@@ -86,7 +88,7 @@ export function NextEpisodeButton(props: {
{
- this.videoEl?.addEventListener("seeked", resolve);
+ const onSeeked = () => {
+ this.videoEl?.removeEventListener("seeked", onSeeked);
+ resolve(null);
+ };
+ this.videoEl?.addEventListener("seeked", onSeeked);
});
if (!this.videoEl || !this.canvasEl) return;
const ctx = this.canvasEl.getContext("2d");
@@ -91,6 +99,7 @@ class ThumnbnailWorker {
this.canvasEl.height
);
const imgUrl = this.canvasEl.toDataURL();
+
if (this.interrupted) return;
if (imgUrl === "data:," || !imgUrl) return; // failed image rendering
@@ -142,6 +151,7 @@ export function ThumbnailScraper() {
workerRef.current = ins;
ins.start(inputStream.stream);
}, [source, addImage, resetImages, status]);
+
const startRef = useRef(start);
useEffect(() => {
startRef.current = start;
diff --git a/src/components/utils/Lightbar.tsx b/src/components/utils/Lightbar.tsx
index 59d4cac8..6968c597 100644
--- a/src/components/utils/Lightbar.tsx
+++ b/src/components/utils/Lightbar.tsx
@@ -161,8 +161,8 @@ function ParticlesCanvas() {
export function Lightbar(props: { className?: string }) {
return (
-
-
+
+
diff --git a/src/pages/developer/VideoTesterView.tsx b/src/pages/developer/VideoTesterView.tsx
index 10e6a9c0..e58c4632 100644
--- a/src/pages/developer/VideoTesterView.tsx
+++ b/src/pages/developer/VideoTesterView.tsx
@@ -19,7 +19,7 @@ const testMeta: PlayerMeta = {
const testStreams: Record
= {
hls: "https://bitdash-a.akamaihd.net/content/sintel/hls/playlist.m3u8",
- mp4: "http://commondatastorage.googleapis.com/gtv-videos-bucket/sample/Sintel.mp4",
+ mp4: "https://commondatastorage.googleapis.com/gtv-videos-bucket/sample/Sintel.mp4",
};
const streamTypes: Record = {
diff --git a/src/pages/layouts/SubPageLayout.tsx b/src/pages/layouts/SubPageLayout.tsx
index a18cfa7b..3be3e97e 100644
--- a/src/pages/layouts/SubPageLayout.tsx
+++ b/src/pages/layouts/SubPageLayout.tsx
@@ -26,7 +26,7 @@ export function BlurEllipsis(props: { positionClass?: string }) {
export function SubPageLayout(props: { children: React.ReactNode }) {
return (
;
+ try {
+ account = await login({
+ mnemonic: inputMnemonic,
+ userData: {
+ device: validatedDevice,
+ },
+ });
+ } catch (err) {
+ if ((err as any).status === 401)
+ throw new Error(t("auth.login.validationError") ?? undefined);
+ throw err;
+ }
await importData(account, progressItems, bookmarkItems);
diff --git a/src/pages/parts/player/ScrapingPart.tsx b/src/pages/parts/player/ScrapingPart.tsx
index 54a7afbd..eee6edcb 100644
--- a/src/pages/parts/player/ScrapingPart.tsx
+++ b/src/pages/parts/player/ScrapingPart.tsx
@@ -1,6 +1,7 @@
import { ProviderControls, ScrapeMedia } from "@movie-web/providers";
import classNames from "classnames";
import { useEffect, useRef } from "react";
+import { useMountedState } from "react-use";
import type { AsyncReturnType } from "type-fest";
import {
@@ -30,6 +31,7 @@ export interface ScrapingProps {
export function ScrapingPart(props: ScrapingProps) {
const { report } = useReportProviders();
const { startScraping, sourceOrder, sources, currentSource } = useScrape();
+ const isMounted = useMountedState();
const containerRef = useRef(null);
const listRef = useRef(null);
@@ -57,6 +59,7 @@ export function ScrapingPart(props: ScrapingProps) {
started.current = true;
(async () => {
const output = await startScraping(props.media);
+ if (!isMounted()) return;
props.onResult?.(
resultRef.current.sources,
resultRef.current.sourceOrder
@@ -70,7 +73,7 @@ export function ScrapingPart(props: ScrapingProps) {
);
props.onGetStream?.(output);
})();
- }, [startScraping, props, report]);
+ }, [startScraping, props, report, isMounted]);
const currentProvider = sourceOrder.find(
(s) => sources[s.id].status === "pending"