diff --git a/src/hooks/useEmbedOrderState.ts b/src/hooks/useEmbedOrderState.ts new file mode 100644 index 00000000..11897f03 --- /dev/null +++ b/src/hooks/useEmbedOrderState.ts @@ -0,0 +1,105 @@ +import { useCallback, useEffect, useMemo, useState } from "react"; + +import { updateSettings } from "@/backend/accounts/settings"; +import { useBackendUrl } from "@/hooks/auth/useBackendUrl"; +import { useAuthStore } from "@/stores/auth"; +import { usePreferencesStore } from "@/stores/preferences"; + +export function useEmbedOrderState() { + const account = useAuthStore((s) => s.account); + const backendUrl = useBackendUrl(); + + // Get current values from store + const embedOrder = usePreferencesStore((s) => s.embedOrder); + const enableEmbedOrder = usePreferencesStore((s) => s.enableEmbedOrder); + const disabledEmbeds = usePreferencesStore((s) => s.disabledEmbeds); + + // Local state for tracking changes + const [localEmbedOrder, setLocalEmbedOrder] = useState(embedOrder); + const [localEnableEmbedOrder, setLocalEnableEmbedOrder] = + useState(enableEmbedOrder); + const [localDisabledEmbeds, setLocalDisabledEmbeds] = + useState(disabledEmbeds); + + // Store setters + const setEmbedOrder = usePreferencesStore((s) => s.setEmbedOrder); + const setEnableEmbedOrder = usePreferencesStore((s) => s.setEnableEmbedOrder); + const setDisabledEmbeds = usePreferencesStore((s) => s.setDisabledEmbeds); + + // Check if any changes have been made + const hasChanges = useMemo(() => { + return ( + JSON.stringify(localEmbedOrder) !== JSON.stringify(embedOrder) || + localEnableEmbedOrder !== enableEmbedOrder || + JSON.stringify(localDisabledEmbeds) !== JSON.stringify(disabledEmbeds) + ); + }, [ + localEmbedOrder, + embedOrder, + localEnableEmbedOrder, + enableEmbedOrder, + localDisabledEmbeds, + disabledEmbeds, + ]); + + // Reset local state to match store + const reset = useCallback(() => { + setLocalEmbedOrder(embedOrder); + setLocalEnableEmbedOrder(enableEmbedOrder); + setLocalDisabledEmbeds(disabledEmbeds); + }, [embedOrder, enableEmbedOrder, disabledEmbeds]); + + // Save changes to backend and update store + const saveChanges = useCallback(async () => { + if (!account || !backendUrl) return; + + try { + await updateSettings(backendUrl, account, { + embedOrder: localEmbedOrder, + enableEmbedOrder: localEnableEmbedOrder, + disabledEmbeds: localDisabledEmbeds, + }); + + // Update the store with the new values + setEmbedOrder(localEmbedOrder); + setEnableEmbedOrder(localEnableEmbedOrder); + setDisabledEmbeds(localDisabledEmbeds); + } catch (error) { + console.error("Failed to save embed order settings:", error); + throw error; + } + }, [ + account, + backendUrl, + localEmbedOrder, + localEnableEmbedOrder, + localDisabledEmbeds, + setEmbedOrder, + setEnableEmbedOrder, + setDisabledEmbeds, + ]); + + // Update local state when store changes + useEffect(() => { + setLocalEmbedOrder(embedOrder); + setLocalEnableEmbedOrder(enableEmbedOrder); + setLocalDisabledEmbeds(disabledEmbeds); + }, [embedOrder, enableEmbedOrder, disabledEmbeds]); + + return { + // Current values + embedOrder: localEmbedOrder, + enableEmbedOrder: localEnableEmbedOrder, + disabledEmbeds: localDisabledEmbeds, + + // Setters + setEmbedOrder: setLocalEmbedOrder, + setEnableEmbedOrder: setLocalEnableEmbedOrder, + setDisabledEmbeds: setLocalDisabledEmbeds, + + // State management + hasChanges, + reset, + saveChanges, + }; +} diff --git a/src/pages/admin/AdminPage.tsx b/src/pages/admin/AdminPage.tsx index a04174a1..eaa9dfac 100644 --- a/src/pages/admin/AdminPage.tsx +++ b/src/pages/admin/AdminPage.tsx @@ -1,5 +1,11 @@ +import { useCallback, useState } from "react"; +import { useTranslation } from "react-i18next"; + +import { Button } from "@/components/buttons/Button"; import { ThinContainer } from "@/components/layout/ThinContainer"; import { Heading1, Paragraph } from "@/components/utils/Text"; +import { Transition } from "@/components/utils/Transition"; +import { useEmbedOrderState } from "@/hooks/useEmbedOrderState"; import { SubPageLayout } from "@/pages/layouts/SubPageLayout"; import { ConfigValuesPart } from "@/pages/parts/admin/ConfigValuesPart"; import { M3U8TestPart } from "@/pages/parts/admin/M3U8TestPart"; @@ -10,6 +16,21 @@ import { BackendTestPart } from "../parts/admin/BackendTestPart"; import { EmbedOrderPart } from "../parts/admin/EmbedOrderPart"; export function AdminPage() { + const { t } = useTranslation(); + const [isSaving, setIsSaving] = useState(false); + const embedOrderState = useEmbedOrderState(); + + const handleSaveChanges = useCallback(async () => { + setIsSaving(true); + try { + await embedOrderState.saveChanges(); + } catch (error) { + console.error("Failed to save embed order changes:", error); + } finally { + setIsSaving(false); + } + }, [embedOrderState]); + return ( @@ -21,8 +42,40 @@ export function AdminPage() { - + + + +

{t("settings.unsaved")}

+
+ + +
+
); } diff --git a/src/pages/parts/admin/EmbedOrderPart.tsx b/src/pages/parts/admin/EmbedOrderPart.tsx index 0e22f9f6..168d495b 100644 --- a/src/pages/parts/admin/EmbedOrderPart.tsx +++ b/src/pages/parts/admin/EmbedOrderPart.tsx @@ -7,19 +7,27 @@ import { Button } from "@/components/buttons/Button"; import { Toggle } from "@/components/buttons/Toggle"; import { SortableListWithToggles } from "@/components/form/SortableListWithToggles"; import { Heading2 } from "@/components/utils/Text"; -import { usePreferencesStore } from "@/stores/preferences"; -export function EmbedOrderPart() { +interface EmbedOrderPartProps { + embedOrder: string[]; + setEmbedOrder: (order: string[]) => void; + enableEmbedOrder: boolean; + setEnableEmbedOrder: (enabled: boolean) => void; + disabledEmbeds: string[]; + setDisabledEmbeds: (disabled: string[]) => void; +} + +export function EmbedOrderPart({ + embedOrder, + setEmbedOrder, + enableEmbedOrder, + setEnableEmbedOrder, + disabledEmbeds, + setDisabledEmbeds, +}: EmbedOrderPartProps) { const { t } = useTranslation(); const navigate = useNavigate(); - const embedOrder = usePreferencesStore((s) => s.embedOrder); - const setEmbedOrder = usePreferencesStore((s) => s.setEmbedOrder); - const enableEmbedOrder = usePreferencesStore((s) => s.enableEmbedOrder); - const setEnableEmbedOrder = usePreferencesStore((s) => s.setEnableEmbedOrder); - const disabledEmbeds = usePreferencesStore((s) => s.disabledEmbeds); - const setDisabledEmbeds = usePreferencesStore((s) => s.setDisabledEmbeds); - const allEmbeds = getAllProviders().listEmbeds(); const embedItems = useMemo(() => {