+
{props.children}
@@ -98,7 +98,10 @@ export function PlayerPart(props: PlayerPartProps) {
-
+
);
}
diff --git a/src/pages/parts/player/ScrapingPart.tsx b/src/pages/parts/player/ScrapingPart.tsx
index 681a58dd..7690ce82 100644
--- a/src/pages/parts/player/ScrapingPart.tsx
+++ b/src/pages/parts/player/ScrapingPart.tsx
@@ -41,9 +41,9 @@ export function ScrapingPart(props: ScrapingProps) {
const currentProvider = sourceOrder.find(
(s) => sources[s.id].status === "pending"
);
- const currentProviderIndex = sourceOrder.findIndex(
- (provider) => currentProvider?.id === provider.id
- );
+ const currentProviderIndex =
+ sourceOrder.findIndex((provider) => currentProvider?.id === provider.id) ??
+ sourceOrder.length - 1;
return (
diff --git a/src/setup/App.tsx b/src/setup/App.tsx
index fea66130..10c46f84 100644
--- a/src/setup/App.tsx
+++ b/src/setup/App.tsx
@@ -20,6 +20,7 @@ import { Layout } from "@/setup/Layout";
import { BookmarkContextProvider } from "@/state/bookmark";
import { SettingsProvider } from "@/state/settings";
import { WatchedContextProvider } from "@/state/watched";
+import { useHistoryListener } from "@/stores/history";
function LegacyUrlView({ children }: { children: ReactElement }) {
const location = useLocation();
@@ -55,6 +56,8 @@ function QuickSearch() {
}
function App() {
+ useHistoryListener();
+
return (
diff --git a/src/stores/history/index.ts b/src/stores/history/index.ts
new file mode 100644
index 00000000..572358cf
--- /dev/null
+++ b/src/stores/history/index.ts
@@ -0,0 +1,53 @@
+import { useEffect, useMemo } from "react";
+import { useHistory, useLocation } from "react-router-dom";
+import { useEffectOnce } from "react-use";
+import { create } from "zustand";
+import { immer } from "zustand/middleware/immer";
+
+interface HistoryRoute {
+ path: string;
+}
+
+interface HistoryStore {
+ routes: HistoryRoute[];
+ registerRoute(route: HistoryRoute): void;
+}
+
+export const useHistoryStore = create(
+ immer((set) => ({
+ routes: [],
+ registerRoute(route) {
+ set((s) => {
+ s.routes.push(route);
+ });
+ },
+ }))
+);
+
+export function useHistoryListener() {
+ const history = useHistory();
+ const loc = useLocation();
+ const registerRoute = useHistoryStore((s) => s.registerRoute);
+ useEffect(
+ () =>
+ history.listen((a) => {
+ registerRoute({ path: a.pathname });
+ }),
+ [history, registerRoute]
+ );
+
+ useEffectOnce(() => {
+ registerRoute({ path: loc.pathname });
+ });
+}
+
+export function useLastNonPlayerLink() {
+ const routes = useHistoryStore((s) => s.routes);
+ const lastNonPlayerLink = useMemo(() => {
+ const reversedRoutes = [...routes];
+ reversedRoutes.reverse();
+ const route = reversedRoutes.find((v) => !v.path.startsWith("/media"));
+ return route?.path ?? "/";
+ }, [routes]);
+ return lastNonPlayerLink;
+}
diff --git a/src/stores/player/slices/interface.ts b/src/stores/player/slices/interface.ts
index 02334165..a4b7321e 100644
--- a/src/stores/player/slices/interface.ts
+++ b/src/stores/player/slices/interface.ts
@@ -27,12 +27,14 @@ export interface InterfaceSlice {
volumeChangedWithKeybindDebounce: NodeJS.Timeout | null; // debounce for the duration of the "volume changed thingamajig"
leftControlHovering: boolean; // is the cursor hovered over the left side of player controls
+ isHoveringControls: boolean; // is the cursor hovered over any controls?
timeFormat: VideoPlayerTimeFormat; // Time format of the video player
};
updateInterfaceHovering(newState: PlayerHoverState): void;
setSeeking(seeking: boolean): void;
setTimeFormat(format: VideoPlayerTimeFormat): void;
setHoveringLeftControls(state: boolean): void;
+ setHoveringAnyControls(state: boolean): void;
setHasOpenOverlay(state: boolean): void;
setLastVolume(state: number): void;
hideNextEpisodeButton(): void;
@@ -46,6 +48,7 @@ export const createInterfaceSlice: MakeSlice = (set, get) => ({
isSeeking: false,
lastVolume: 0,
leftControlHovering: false,
+ isHoveringControls: false,
hovering: PlayerHoverState.NOT_HOVERING,
lastHoveringState: PlayerHoverState.NOT_HOVERING,
volumeChangedWithKeybind: false,
@@ -89,6 +92,11 @@ export const createInterfaceSlice: MakeSlice = (set, get) => ({
s.interface.leftControlHovering = state;
});
},
+ setHoveringAnyControls(state) {
+ set((s) => {
+ s.interface.isHoveringControls = state;
+ });
+ },
hideNextEpisodeButton() {
set((s) => {
s.interface.hideNextEpisodeBtn = true;
diff --git a/src/stores/player/slices/thumbnails.ts b/src/stores/player/slices/thumbnails.ts
index b0394d34..de166698 100644
--- a/src/stores/player/slices/thumbnails.ts
+++ b/src/stores/player/slices/thumbnails.ts
@@ -9,6 +9,7 @@ export interface ThumbnailSlice {
thumbnails: {
images: ThumbnailImage[];
addImage(img: ThumbnailImage): void;
+ resetImages(): void;
};
}
@@ -73,6 +74,11 @@ export function nearestImageAt(
export const createThumbnailSlice: MakeSlice = (set, get) => ({
thumbnails: {
images: [],
+ resetImages() {
+ set((s) => {
+ s.thumbnails.images = [];
+ });
+ },
addImage(img) {
const store = get();
const exactOrPastImageIndex = store.thumbnails.images.findIndex(
diff --git a/tailwind.config.js b/tailwind.config.js
index a840f76a..f03441be 100644
--- a/tailwind.config.js
+++ b/tailwind.config.js
@@ -143,7 +143,8 @@ module.exports = {
context: {
background: "#0C1216",
light: "#4D79A8",
- border: "#141D23",
+ border: "#1d252b",
+ hoverColor: "#1E2A32",
buttonFocus: "#202836",
flagBg: "#202836",
inputBg: "#202836",