pstream is dead; long live pstream
taciturnaxolotl.github.io/pstream-ng/
1import { useEffect } from "react";
2import { useLocation } from "react-router-dom";
3import { create } from "zustand";
4import { immer } from "zustand/middleware/immer";
5
6type OverlayType =
7 | "volume"
8 | "subtitle"
9 | "speed"
10 | "tidb-submission-success"
11 | null;
12
13interface ModalData {
14 id: number;
15 type: "movie" | "show";
16 [key: string]: any;
17}
18
19interface OverlayStackStore {
20 currentOverlay: OverlayType;
21 modalStack: string[];
22 modalData: Record<string, ModalData | undefined>;
23 setCurrentOverlay: (overlay: OverlayType) => void;
24 showModal: (id: string, data?: ModalData) => void;
25 hideModal: (id: string) => void;
26 isModalVisible: (id: string) => boolean;
27 getTopModal: () => string | null;
28 getModalData: (id: string) => ModalData | undefined;
29 clearAllModals: () => void;
30}
31
32export const useOverlayStack = create<OverlayStackStore>()(
33 immer((set, get) => ({
34 currentOverlay: null,
35 modalStack: [],
36 modalData: {},
37 setCurrentOverlay: (overlay) =>
38 set((state) => {
39 state.currentOverlay = overlay;
40 }),
41 showModal: (id: string, data?: ModalData) =>
42 set((state) => {
43 if (!state.modalStack.includes(id)) {
44 state.modalStack.push(id);
45 }
46 if (data) {
47 state.modalData[id] = data;
48 }
49 }),
50 hideModal: (id: string) =>
51 set((state) => {
52 state.modalStack = state.modalStack.filter((modalId) => modalId !== id);
53 delete state.modalData[id];
54 }),
55 isModalVisible: (id: string) => {
56 return get().modalStack.includes(id);
57 },
58 getTopModal: () => {
59 const stack = get().modalStack;
60 return stack.length > 0 ? stack[stack.length - 1] : null;
61 },
62 getModalData: (id: string) => {
63 return get().modalData[id];
64 },
65 clearAllModals: () =>
66 set((state) => {
67 state.modalStack = [];
68 state.modalData = {};
69 state.currentOverlay = null;
70 }),
71 })),
72);
73
74// Hook to clear modals on navigation
75export function useClearModalsOnNavigation() {
76 const location = useLocation();
77 const clearAllModals = useOverlayStack((state) => state.clearAllModals);
78
79 useEffect(() => {
80 clearAllModals();
81 }, [location.pathname, clearAllModals]);
82}