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"