diff --git a/package.json b/package.json
index fa2d0283..5a880018 100644
--- a/package.json
+++ b/package.json
@@ -29,7 +29,7 @@
"react": "^17.0.2",
"react-dom": "^17.0.2",
"react-ga4": "^2.0.0",
- "react-helmet": "^6.1.0",
+ "react-helmet-async": "^1.3.0",
"react-i18next": "^12.1.1",
"react-router-dom": "^5.2.0",
"react-stickynode": "^4.1.0",
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index 05eba9b1..43a2da12 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -80,9 +80,9 @@ dependencies:
react-ga4:
specifier: ^2.0.0
version: 2.1.0
- react-helmet:
- specifier: ^6.1.0
- version: 6.1.0(react@17.0.2)
+ react-helmet-async:
+ specifier: ^1.3.0
+ version: 1.3.0(react-dom@17.0.2)(react@17.0.2)
react-i18next:
specifier: ^12.1.1
version: 12.3.1(i18next@22.5.1)(react-dom@17.0.2)(react@17.0.2)
@@ -4191,6 +4191,12 @@ packages:
side-channel: 1.0.4
dev: true
+ /invariant@2.2.4:
+ resolution: {integrity: sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA==}
+ dependencies:
+ loose-envify: 1.4.0
+ dev: false
+
/is-array-buffer@3.0.2:
resolution: {integrity: sha512-y+FyyR/w8vfIRq4eQcM1EYgSTnmHXPqaF+IgzgraytCFq5Xh8lllDVmAZolPJiZttZLeFSINPYMaEJ7/vWUa1w==}
dependencies:
@@ -5219,16 +5225,19 @@ packages:
resolution: {integrity: sha512-ZKS7PGNFqqMd3PJ6+C2Jtz/o1iU9ggiy8Y8nUeksgVuvNISbmrQtJiZNvC/TjDsqD0QlU5Wkgs7i+w9+OjHhhQ==}
dev: false
- /react-helmet@6.1.0(react@17.0.2):
- resolution: {integrity: sha512-4uMzEY9nlDlgxr61NL3XbKRy1hEkXmKNXhjbAIOVw5vcFrsdYbH2FEwcNyWvWinl103nXgzYNlns9ca+8kFiWw==}
+ /react-helmet-async@1.3.0(react-dom@17.0.2)(react@17.0.2):
+ resolution: {integrity: sha512-9jZ57/dAn9t3q6hneQS0wukqC2ENOBgMNVEhb/ZG9ZSxUetzVIw4iAmEU38IaVg3QGYauQPhSeUTuIUtFglWpg==}
peerDependencies:
- react: '>=16.3.0'
+ react: ^16.6.0 || ^17.0.0 || ^18.0.0
+ react-dom: ^16.6.0 || ^17.0.0 || ^18.0.0
dependencies:
- object-assign: 4.1.1
+ '@babel/runtime': 7.22.11
+ invariant: 2.2.4
prop-types: 15.8.1
react: 17.0.2
+ react-dom: 17.0.2(react@17.0.2)
react-fast-compare: 3.2.2
- react-side-effect: 2.1.2(react@17.0.2)
+ shallowequal: 1.1.0
dev: false
/react-i18next@12.3.1(i18next@22.5.1)(react-dom@17.0.2)(react@17.0.2):
@@ -5295,14 +5304,6 @@ packages:
tiny-warning: 1.0.3
dev: false
- /react-side-effect@2.1.2(react@17.0.2):
- resolution: {integrity: sha512-PVjOcvVOyIILrYoyGEpDN3vmYNLdy1CajSFNt4TDsVQC5KpTijDvWVoR+/7Rz2xT978D8/ZtFceXxzsPwZEDvw==}
- peerDependencies:
- react: ^16.3.0 || ^17.0.0 || ^18.0.0
- dependencies:
- react: 17.0.2
- dev: false
-
/react-stickynode@4.1.0(react-dom@17.0.2)(react@17.0.2):
resolution: {integrity: sha512-zylWgfad75jLfh/gYIayDcDWIDwO4weZrsZqDpjZ/axhF06zRjdCWFBgUr33Pvv2+htKWqPSFksWTyB6aMQ1ZQ==}
peerDependencies:
diff --git a/src/_oldvideo/components/actions/PageTitleAction.tsx b/src/_oldvideo/components/actions/PageTitleAction.tsx
index c471a141..c6c634df 100644
--- a/src/_oldvideo/components/actions/PageTitleAction.tsx
+++ b/src/_oldvideo/components/actions/PageTitleAction.tsx
@@ -1,4 +1,4 @@
-import { Helmet } from "react-helmet";
+import { Helmet } from "react-helmet-async";
import { useVideoPlayerDescriptor } from "@/_oldvideo/state/hooks";
diff --git a/src/components/Overlay.tsx b/src/components/Overlay.tsx
index 2129f68d..8f0dc1e8 100644
--- a/src/components/Overlay.tsx
+++ b/src/components/Overlay.tsx
@@ -1,4 +1,4 @@
-import { Helmet } from "react-helmet";
+import { Helmet } from "react-helmet-async";
import { Transition } from "@/components/Transition";
diff --git a/src/components/player/atoms/Episodes.tsx b/src/components/player/atoms/Episodes.tsx
new file mode 100644
index 00000000..c8c7515b
--- /dev/null
+++ b/src/components/player/atoms/Episodes.tsx
@@ -0,0 +1,203 @@
+import { ReactNode, useCallback, useEffect, useState } from "react";
+import { useTranslation } from "react-i18next";
+import { useAsync } from "react-use";
+
+import { getMetaFromId } from "@/backend/metadata/getmeta";
+import { MWMediaType, MWSeasonMeta } from "@/backend/metadata/types/mw";
+import { Icons } from "@/components/Icon";
+import { OverlayAnchor } from "@/components/overlays/OverlayAnchor";
+import { Overlay } from "@/components/overlays/OverlayDisplay";
+import { OverlayPage } from "@/components/overlays/OverlayPage";
+import { OverlayRouter } from "@/components/overlays/OverlayRouter";
+import { usePlayerMeta } from "@/components/player/hooks/usePlayerMeta";
+import { VideoPlayerButton } from "@/components/player/internals/Button";
+import { Context } from "@/components/player/internals/ContextUtils";
+import { useOverlayRouter } from "@/hooks/useOverlayRouter";
+import { usePlayerStore } from "@/stores/player/store";
+
+function CenteredText(props: { children: React.ReactNode }) {
+ return (
+
+ {props.children}
+
+ );
+}
+
+function useSeasonData(mediaId: string, seasonId: string) {
+ const [seasons, setSeason] = useState(null);
+
+ const state = useAsync(async () => {
+ const data = await getMetaFromId(MWMediaType.SERIES, mediaId, seasonId);
+ if (data?.meta.type !== MWMediaType.SERIES) return null;
+ setSeason(data.meta.seasons);
+ return {
+ season: data.meta.seasonData,
+ fullData: data,
+ };
+ }, [mediaId, seasonId]);
+
+ return [state, seasons] as const;
+}
+
+function SeasonsView({
+ selectedSeason,
+ setSeason,
+}: {
+ selectedSeason: string;
+ setSeason: (id: string) => void;
+}) {
+ const meta = usePlayerStore((s) => s.meta);
+ const [loadingState, seasons] = useSeasonData(
+ meta?.tmdbId ?? "",
+ selectedSeason
+ );
+
+ let content: ReactNode = null;
+ if (seasons) {
+ content = (
+
+ {seasons?.map((season) => {
+ return (
+ setSeason(season.id)}>
+ {season.title}
+
+
+ );
+ })}
+
+ );
+ } else if (loadingState.error)
+ content = Error loading season;
+ else if (loadingState.loading)
+ content = Loading...;
+
+ return (
+
+ {meta?.title}
+ {content}
+
+ );
+}
+
+function EpisodesView({
+ id,
+ selectedSeason,
+ goBack,
+}: {
+ id: string;
+ selectedSeason: string;
+ goBack?: () => void;
+}) {
+ const { t } = useTranslation();
+ const router = useOverlayRouter(id);
+ const { setPlayerMeta } = usePlayerMeta();
+ const meta = usePlayerStore((s) => s.meta);
+ const [loadingState] = useSeasonData(meta?.tmdbId ?? "", selectedSeason);
+
+ const playEpisode = useCallback(
+ (episodeId: string) => {
+ if (loadingState.value)
+ setPlayerMeta(loadingState.value.fullData, episodeId);
+ router.close();
+ },
+ [setPlayerMeta, loadingState, router]
+ );
+
+ let content: ReactNode = null;
+ if (loadingState.error)
+ content = Error loading season;
+ else if (loadingState.loading)
+ content = Loading...;
+ else if (loadingState.value) {
+ content = (
+
+ {loadingState.value.season.episodes.map((ep) => {
+ return (
+ playEpisode(ep.id)}
+ active={ep.id === meta?.episode?.tmdbId}
+ >
+
+
+
+ E{ep.number}
+
+ {ep.title}
+
+
+
+
+ );
+ })}
+
+ );
+ }
+
+ return (
+
+
+ {loadingState?.value?.season.title || t("videoPlayer.loading")}
+
+ {content}
+
+ );
+}
+
+function EpisodesOverlay({ id }: { id: string }) {
+ const router = useOverlayRouter(id);
+ const meta = usePlayerStore((s) => s.meta);
+ const [selectedSeason, setSelectedSeason] = useState(
+ meta?.season?.tmdbId ?? ""
+ );
+
+ const setSeason = useCallback(
+ (seasonId: string) => {
+ setSelectedSeason(seasonId);
+ router.navigate("/episodes");
+ },
+ [router]
+ );
+
+ return (
+
+
+
+
+
+
+ router.navigate("/")}
+ />
+
+
+
+ );
+}
+
+export function Episodes() {
+ const { t } = useTranslation();
+ const router = useOverlayRouter("episodes");
+ const setHasOpenOverlay = usePlayerStore((s) => s.setHasOpenOverlay);
+ const type = usePlayerStore((s) => s.meta?.type);
+
+ useEffect(() => {
+ setHasOpenOverlay(router.isRouterActive);
+ }, [setHasOpenOverlay, router.isRouterActive]);
+
+ if (type !== "show") return null;
+
+ return (
+
+ router.open("/episodes")}
+ icon={Icons.EPISODES}
+ >
+ {t("videoPlayer.buttons.episodes")}
+
+
+
+ );
+}
diff --git a/src/components/player/atoms/Settings.tsx b/src/components/player/atoms/Settings.tsx
index 57a677bb..713d3fdb 100644
--- a/src/components/player/atoms/Settings.tsx
+++ b/src/components/player/atoms/Settings.tsx
@@ -101,7 +101,7 @@ function SettingsOverlay({ id }: { id: string }) {
- Video settings
+ Video settings
router.navigate("/quality")}>
Quality
@@ -119,11 +119,11 @@ function SettingsOverlay({ id }: { id: string }) {
- Viewing Experience
+ Viewing Experience
router.navigate("/quality")}>
Enable Captions
-
+
Caption settings
diff --git a/src/components/player/atoms/Time.tsx b/src/components/player/atoms/Time.tsx
index 2ba0a75f..4870aacc 100644
--- a/src/components/player/atoms/Time.tsx
+++ b/src/components/player/atoms/Time.tsx
@@ -40,22 +40,22 @@ export function Time() {
},
});
+ const timeString = `${formatSeconds(currentTime, hasHours)} / ${formatSeconds(
+ duration,
+ hasHours
+ )}`;
+ const timeFinishedString = `${t("videoPlayer.timeLeft", {
+ timeLeft: formatSeconds(
+ secondsRemaining,
+ durationExceedsHour(secondsRemaining)
+ ),
+ })} • ${formattedTimeFinished}`;
+
const child =
timeFormat === VideoPlayerTimeFormat.REGULAR ? (
- <>
- {formatSeconds(currentTime, hasHours)}{" "}
- / {formatSeconds(duration, hasHours)}
- >
+ {timeString}
) : (
- <>
- {t("videoPlayer.timeLeft", {
- timeLeft: formatSeconds(
- secondsRemaining,
- durationExceedsHour(secondsRemaining)
- ),
- })}{" "}
- • {formattedTimeFinished}
- >
+ {timeFinishedString}
);
return (
diff --git a/src/components/player/atoms/index.ts b/src/components/player/atoms/index.ts
index e54adc08..e72ef50f 100644
--- a/src/components/player/atoms/index.ts
+++ b/src/components/player/atoms/index.ts
@@ -9,3 +9,4 @@ export * from "./Volume";
export * from "./Title";
export * from "./EpisodeTitle";
export * from "./Settings";
+export * from "./Episodes";
diff --git a/src/components/player/display/base.ts b/src/components/player/display/base.ts
index 5b5d93db..859caf35 100644
--- a/src/components/player/display/base.ts
+++ b/src/components/player/display/base.ts
@@ -29,15 +29,17 @@ export function makeVideoElementDisplayInterface(): DisplayInterface {
if (src.type === "hls") {
if (!Hls.isSupported()) throw new Error("HLS not supported");
- hls = new Hls({ enableWorker: false });
- hls.on(Hls.Events.ERROR, (event, data) => {
- console.error("HLS error", data);
- if (data.fatal) {
- throw new Error(
- `HLS ERROR:${data.error?.message ?? "Something went wrong"}`
- );
- }
- });
+ if (!hls) {
+ hls = new Hls({ enableWorker: false });
+ hls.on(Hls.Events.ERROR, (event, data) => {
+ console.error("HLS error", data);
+ if (data.fatal) {
+ throw new Error(
+ `HLS ERROR:${data.error?.message ?? "Something went wrong"}`
+ );
+ }
+ });
+ }
hls.attachMedia(vid);
hls.loadSource(src.url);
@@ -77,6 +79,21 @@ export function makeVideoElementDisplayInterface(): DisplayInterface {
});
}
+ function unloadSource() {
+ if (videoElement) videoElement.removeAttribute("src");
+ if (hls) {
+ hls.destroy();
+ hls = null;
+ }
+ }
+
+ function destroyVideoElement() {
+ unloadSource();
+ if (videoElement) {
+ videoElement = null;
+ }
+ }
+
function fullscreenChange() {
isFullscreen =
!!document.fullscreenElement || // other browsers
@@ -88,20 +105,18 @@ export function makeVideoElementDisplayInterface(): DisplayInterface {
on,
off,
destroy: () => {
- if (hls) hls.destroy();
- if (videoElement) {
- videoElement.src = "";
- videoElement.remove();
- }
+ destroyVideoElement();
fscreen.removeEventListener("fullscreenchange", fullscreenChange);
},
load(newSource) {
+ if (!newSource) unloadSource();
source = newSource;
emit("loading", true);
setSource();
},
processVideoElement(video) {
+ destroyVideoElement();
videoElement = video;
setSource();
},
diff --git a/src/components/player/display/displayInterface.ts b/src/components/player/display/displayInterface.ts
index 2cb6f5df..5890d937 100644
--- a/src/components/player/display/displayInterface.ts
+++ b/src/components/player/display/displayInterface.ts
@@ -17,7 +17,7 @@ export type DisplayInterfaceEvents = {
export interface DisplayInterface extends Listener {
play(): void;
pause(): void;
- load(source: LoadableSource): void;
+ load(source: LoadableSource | null): void;
processVideoElement(video: HTMLVideoElement): void;
processContainerElement(container: HTMLElement): void;
toggleFullscreen(): void;
diff --git a/src/components/player/internals/Button.tsx b/src/components/player/internals/Button.tsx
index e65a3b1e..e182c3c4 100644
--- a/src/components/player/internals/Button.tsx
+++ b/src/components/player/internals/Button.tsx
@@ -1,3 +1,5 @@
+import classNames from "classnames";
+
import { Icon, Icons } from "@/components/Icon";
export function VideoPlayerButton(props: {
@@ -12,15 +14,21 @@ export function VideoPlayerButton(props: {
diff --git a/src/components/player/internals/ContextUtils.tsx b/src/components/player/internals/ContextUtils.tsx
index c163e4c0..d7a80653 100644
--- a/src/components/player/internals/ContextUtils.tsx
+++ b/src/components/player/internals/ContextUtils.tsx
@@ -3,12 +3,26 @@ import classNames from "classnames";
import { Icon, Icons } from "@/components/Icon";
function Card(props: { children: React.ReactNode }) {
- return {props.children}
;
+ return (
+
+ );
}
-function Title(props: { children: React.ReactNode }) {
+function CardWithScrollable(props: { children: React.ReactNode }) {
return (
-
+
+ {props.children}
+
+ );
+}
+
+function SectionTitle(props: { children: React.ReactNode }) {
+ return (
+
{props.children}
);
@@ -18,7 +32,7 @@ function LinkTitle(props: { children: React.ReactNode; textClass?: string }) {
return (
@@ -27,16 +41,23 @@ function LinkTitle(props: { children: React.ReactNode; textClass?: string }) {
);
}
-function Section(props: { children: React.ReactNode }) {
- return {props.children}
;
+function Section(props: { children: React.ReactNode; className?: string }) {
+ return (
+ {props.children}
+ );
}
-function Link(props: { onClick?: () => void; children: React.ReactNode }) {
+function Link(props: {
+ onClick?: () => void;
+ children: React.ReactNode;
+ active?: boolean;
+}) {
const classes = classNames(
"flex justify-between items-center py-2 pl-3 pr-3 -ml-3 rounded w-full",
{
"cursor-default": !props.onClick,
"hover:bg-video-context-border hover:bg-opacity-10": !!props.onClick,
+ "bg-video-context-border bg-opacity-10": props.active,
}
);
const styles = { width: "calc(100% + 1.5rem)" };
@@ -61,25 +82,36 @@ function Link(props: { onClick?: () => void; children: React.ReactNode }) {
);
}
+function Title(props: {
+ children: React.ReactNode;
+ rightSide?: React.ReactNode;
+}) {
+ return (
+
+
+
{props.children}
+ {props.rightSide}
+
+
+ );
+}
+
function BackLink(props: {
onClick?: () => void;
children: React.ReactNode;
rightSide?: React.ReactNode;
}) {
return (
-
-
-
- {props.children}
-
- {props.rightSide}
-
+
+
+ {props.children}
+
);
}
@@ -124,7 +156,9 @@ function Anchor(props: { children: React.ReactNode; onClick: () => void }) {
export const Context = {
Card,
+ CardWithScrollable,
Title,
+ SectionTitle,
BackLink,
Section,
Link,
diff --git a/src/components/player/internals/HeadUpdater.tsx b/src/components/player/internals/HeadUpdater.tsx
index da62978e..419976d9 100644
--- a/src/components/player/internals/HeadUpdater.tsx
+++ b/src/components/player/internals/HeadUpdater.tsx
@@ -1,4 +1,4 @@
-import { Helmet } from "react-helmet";
+import { Helmet } from "react-helmet-async";
import { useTranslation } from "react-i18next";
import { usePlayerStore } from "@/stores/player/store";
diff --git a/src/components/player/internals/VideoContainer.tsx b/src/components/player/internals/VideoContainer.tsx
index eaa4315f..eef906b9 100644
--- a/src/components/player/internals/VideoContainer.tsx
+++ b/src/components/player/internals/VideoContainer.tsx
@@ -9,14 +9,24 @@ function useDisplayInterface() {
const display = usePlayerStore((s) => s.display);
const setDisplay = usePlayerStore((s) => s.setDisplay);
+ const displayRef = useRef(display);
useEffect(() => {
- if (!display) {
- setDisplay(makeVideoElementDisplayInterface());
+ displayRef.current = display;
+ }, [display]);
+
+ useEffect(() => {
+ if (!displayRef.current) {
+ const newDisplay = makeVideoElementDisplayInterface();
+ displayRef.current = newDisplay;
+ setDisplay(newDisplay);
}
return () => {
- if (display) setDisplay(null);
+ if (displayRef.current) {
+ displayRef.current = null;
+ setDisplay(null);
+ }
};
- }, [display, setDisplay]);
+ }, [setDisplay]);
}
export function useShouldShowVideoElement() {
diff --git a/src/hooks/useOverlayRouter.ts b/src/hooks/useOverlayRouter.ts
index a83815c5..e504d084 100644
--- a/src/hooks/useOverlayRouter.ts
+++ b/src/hooks/useOverlayRouter.ts
@@ -60,23 +60,26 @@ export function useInternalOverlayRouter(id: string) {
setTransition(null);
}, [setRoute, route, setTransition]);
- const open = useCallback(() => {
- const anchor = document.getElementById(`__overlayRouter::${id}`);
- if (anchor) {
- const rect = anchor.getBoundingClientRect();
- setAnchorPoint({
- h: rect.height,
- w: rect.width,
- x: rect.x,
- y: rect.y,
- });
- } else {
- setAnchorPoint(null);
- }
+ const open = useCallback(
+ (defaultRoute = "/") => {
+ const anchor = document.getElementById(`__overlayRouter::${id}`);
+ if (anchor) {
+ const rect = anchor.getBoundingClientRect();
+ setAnchorPoint({
+ h: rect.height,
+ w: rect.width,
+ x: rect.x,
+ y: rect.y,
+ });
+ } else {
+ setAnchorPoint(null);
+ }
- setTransition(null);
- setRoute(`/${id}`);
- }, [id, setRoute, setTransition, setAnchorPoint]);
+ setTransition(null);
+ setRoute(joinPath(splitPath(defaultRoute, id)));
+ },
+ [id, setRoute, setTransition, setAnchorPoint]
+ );
return {
showBackwardsTransition,
diff --git a/src/index.tsx b/src/index.tsx
index cdd870ab..2d77bee5 100644
--- a/src/index.tsx
+++ b/src/index.tsx
@@ -2,6 +2,7 @@ import "core-js/stable";
import React, { Suspense } from "react";
import type { ReactNode } from "react";
import ReactDOM from "react-dom";
+import { HelmetProvider } from "react-helmet-async";
import { BrowserRouter, HashRouter } from "react-router-dom";
import { registerSW } from "virtual:pwa-register";
@@ -48,11 +49,13 @@ function TheRouter(props: { children: ReactNode }) {
ReactDOM.render(
-
-
-
-
-
+
+
+
+
+
+
+
,
document.getElementById("root")
diff --git a/src/pages/HomePage.tsx b/src/pages/HomePage.tsx
index 672cfbda..c2a6f6e5 100644
--- a/src/pages/HomePage.tsx
+++ b/src/pages/HomePage.tsx
@@ -1,5 +1,5 @@
import { useEffect, useState } from "react";
-import { Helmet } from "react-helmet";
+import { Helmet } from "react-helmet-async";
import { useTranslation } from "react-i18next";
import { WideContainer } from "@/components/layout/WideContainer";
diff --git a/src/pages/PlayerView.tsx b/src/pages/PlayerView.tsx
index 5d0d12f2..cea1a60c 100644
--- a/src/pages/PlayerView.tsx
+++ b/src/pages/PlayerView.tsx
@@ -1,8 +1,7 @@
import { RunOutput } from "@movie-web/providers";
-import { useCallback, useEffect, useState } from "react";
+import { useCallback, useEffect, useRef, useState } from "react";
import { useParams } from "react-router-dom";
-import { MWStreamType } from "@/backend/helpers/streams";
import { usePlayer } from "@/components/player/hooks/usePlayer";
import { usePlayerMeta } from "@/components/player/hooks/usePlayerMeta";
import { convertRunoutputToSource } from "@/components/player/utils/convertRunoutputToSource";
@@ -21,9 +20,13 @@ export function PlayerView() {
const { setPlayerMeta, scrapeMedia } = usePlayerMeta();
const [backUrl] = useState("/"); // TODO redirect to search when needed
+ const lastMedia = useRef(params.media);
useEffect(() => {
+ if (params.media === lastMedia.current) return;
+ lastMedia.current = params.media;
+ console.log("resetting");
reset();
- }, [params.media, reset]);
+ }, [params, reset]);
const playAfterScrape = useCallback(
(out: RunOutput | null) => {
diff --git a/src/pages/parts/errors/ErrorWrapperPart.tsx b/src/pages/parts/errors/ErrorWrapperPart.tsx
index 5b2fd9b0..4cf28787 100644
--- a/src/pages/parts/errors/ErrorWrapperPart.tsx
+++ b/src/pages/parts/errors/ErrorWrapperPart.tsx
@@ -1,5 +1,5 @@
import { ReactNode } from "react";
-import { Helmet } from "react-helmet";
+import { Helmet } from "react-helmet-async";
import { useTranslation } from "react-i18next";
import { VideoPlayerHeader } from "@/_oldvideo/components/parts/VideoPlayerHeader";
diff --git a/src/pages/parts/player/PlayerPart.tsx b/src/pages/parts/player/PlayerPart.tsx
index 91d6f5d3..da3064a4 100644
--- a/src/pages/parts/player/PlayerPart.tsx
+++ b/src/pages/parts/player/PlayerPart.tsx
@@ -63,7 +63,8 @@ export function PlayerPart(props: PlayerPartProps) {
{/* Do mobile controls here :) */}
-
+
diff --git a/src/setup/index.css b/src/setup/index.css
index cdaba622..d656ae3e 100644
--- a/src/setup/index.css
+++ b/src/setup/index.css
@@ -200,7 +200,7 @@ input[type=range].styled-slider.slider-progress::-ms-fill-lower {
}
::-webkit-scrollbar-thumb {
- background-color: theme("colors.denim-500");
+ background-color: theme("colors.video.context.border");
border: 5px solid transparent;
border-left: 0;
background-clip: content-box;
diff --git a/src/stores/player/slices/display.ts b/src/stores/player/slices/display.ts
index 5fec4c94..2e2d7c6a 100644
--- a/src/stores/player/slices/display.ts
+++ b/src/stores/player/slices/display.ts
@@ -81,7 +81,7 @@ export const createDisplaySlice: MakeSlice
= (set, get) => ({
});
},
reset() {
- get().display?.destroy();
+ get().display?.load(null);
set((s) => {
s.status = playerStatus.IDLE;
s.meta = null;
diff --git a/src/stores/player/slices/source.ts b/src/stores/player/slices/source.ts
index a8f38aa4..23857e02 100644
--- a/src/stores/player/slices/source.ts
+++ b/src/stores/player/slices/source.ts
@@ -2,7 +2,6 @@ import { ScrapeMedia } from "@movie-web/providers";
import { MakeSlice } from "@/stores/player/slices/types";
import {
- LoadableSource,
SourceQuality,
SourceSliceSource,
selectQuality,