pstream is dead; long live pstream taciturnaxolotl.github.io/pstream-ng/
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Revert "Prevent settings from loading empty and rewriting to backend"

This reverts commit 3de8a35df4410bd485f9655458d7f53c2503ae63.

Pas 1ab1b341 7ea5f28b

+26 -50
+4 -5
src/components/player/atoms/settings/PlaybackSettingsView.tsx
··· 193 193 194 194 const account = useAuthStore((s) => s.account); 195 195 const backendUrl = useBackendUrl(); 196 - const settingsLoaded = usePreferencesStore((s) => s._settingsLoaded); 197 196 const allowAutoplay = useMemo(() => isAutoplayAllowed(), []); 198 197 const canShowAutoplay = 199 198 !isInWatchParty && allowAutoplay && !enableLowPerformanceMode; ··· 201 200 // Save settings to backend 202 201 const saveThumbnailSetting = useCallback( 203 202 async (value: boolean) => { 204 - if (!account || !backendUrl || !settingsLoaded) return; 203 + if (!account || !backendUrl) return; 205 204 206 205 try { 207 206 await updateSettings(backendUrl, account, { ··· 211 210 console.error("Failed to save thumbnail setting:", error); 212 211 } 213 212 }, 214 - [account, backendUrl, settingsLoaded], 213 + [account, backendUrl], 215 214 ); 216 215 217 216 const saveAutoplaySetting = useCallback( 218 217 async (value: boolean) => { 219 - if (!account || !backendUrl || !settingsLoaded) return; 218 + if (!account || !backendUrl) return; 220 219 221 220 try { 222 221 await updateSettings(backendUrl, account, { ··· 226 225 console.error("Failed to save autoplay setting:", error); 227 226 } 228 227 }, 229 - [account, backendUrl, settingsLoaded], 228 + [account, backendUrl], 230 229 ); 231 230 232 231 const setPlaybackRate = useCallback(
-11
src/hooks/auth/useAuthData.ts
··· 33 33 ); 34 34 const setFebboxKey = usePreferencesStore((s) => s.setFebboxKey); 35 35 const setRealDebridKey = usePreferencesStore((s) => s.setRealDebridKey); 36 - const setSettingsLoaded = usePreferencesStore((s) => s.setSettingsLoaded); 37 36 38 37 const replaceBookmarks = useBookmarkStore((s) => s.replaceBookmarks); 39 38 const replaceItems = useProgressStore((s) => s.replaceItems); ··· 110 109 clearProgress(); 111 110 clearGroupOrder(); 112 111 setFebboxKey(null); 113 - setSettingsLoaded(false); 114 112 }, [ 115 113 removeAccount, 116 114 clearBookmarks, 117 115 clearProgress, 118 116 clearGroupOrder, 119 117 setFebboxKey, 120 - setSettingsLoaded, 121 118 ]); 122 119 123 120 const syncData = useCallback( ··· 218 215 219 216 if (settings.febboxKey !== undefined) { 220 217 setFebboxKey(settings.febboxKey); 221 - } else { 222 - // Only set to null if backend explicitly returns null/undefined 223 - // Don't overwrite with defaults if backend doesn't have the setting 224 - setFebboxKey(null); 225 218 } 226 219 227 220 if (settings.realDebridKey !== undefined) { ··· 253 246 if (settings.enableDoubleClickToSeek !== undefined) { 254 247 setEnableDoubleClickToSeek(settings.enableDoubleClickToSeek); 255 248 } 256 - 257 - // Mark settings as loaded to prevent saving defaults 258 - setSettingsLoaded(true); 259 249 }, 260 250 [ 261 251 replaceBookmarks, ··· 288 278 setHomeSectionOrder, 289 279 setManualSourceSelection, 290 280 setEnableDoubleClickToSeek, 291 - setSettingsLoaded, 292 281 ], 293 282 ); 294 283
+2 -7
src/hooks/auth/useAuthRestore.ts
··· 9 9 export function useAuthRestore() { 10 10 const { account } = useAuthStore(); 11 11 const { restore } = useAuth(); 12 - const setSettingsLoading = useAuthStore((s) => s.setSettingsLoading); 13 12 const hasRestored = useRef(false); 14 13 15 14 useInterval(() => { ··· 18 17 19 18 const result = useAsync(async () => { 20 19 if (hasRestored.current || !account) return; 21 - setSettingsLoading(true); 22 - try { 23 - await restore(account); 24 - } finally { 25 - setSettingsLoading(false); 20 + await restore(account).finally(() => { 26 21 hasRestored.current = true; 27 - } 22 + }); 28 23 }, []); // no deps because we don't want to it ever rerun after the first time 29 24 30 25 return result;
+1 -3
src/hooks/useEmbedOrderState.ts
··· 8 8 export function useEmbedOrderState() { 9 9 const account = useAuthStore((s) => s.account); 10 10 const backendUrl = useBackendUrl(); 11 - const settingsLoaded = usePreferencesStore((s) => s._settingsLoaded); 12 11 13 12 // Get current values from store 14 13 const embedOrder = usePreferencesStore((s) => s.embedOrder); ··· 52 51 53 52 // Save changes to backend and update store 54 53 const saveChanges = useCallback(async () => { 55 - if (!account || !backendUrl || !settingsLoaded) return; 54 + if (!account || !backendUrl) return; 56 55 57 56 try { 58 57 await updateSettings(backendUrl, account, { ··· 72 71 }, [ 73 72 account, 74 73 backendUrl, 75 - settingsLoaded, 76 74 localEmbedOrder, 77 75 localEnableEmbedOrder, 78 76 localDisabledEmbeds,
+18 -5
src/pages/Settings.tsx
··· 9 9 encryptData, 10 10 } from "@/backend/accounts/crypto"; 11 11 import { getSessions, updateSession } from "@/backend/accounts/sessions"; 12 - import { updateSettings } from "@/backend/accounts/settings"; 12 + import { getSettings, updateSettings } from "@/backend/accounts/settings"; 13 13 import { editUser } from "@/backend/accounts/user"; 14 14 import { getAllProviders } from "@/backend/providers/providers"; 15 15 import { Button } from "@/components/buttons/Button"; ··· 364 364 const account = useAuthStore((s) => s.account); 365 365 const updateProfile = useAuthStore((s) => s.setAccountProfile); 366 366 const updateDeviceName = useAuthStore((s) => s.updateDeviceName); 367 - const settingsLoaded = usePreferencesStore((s) => s._settingsLoaded); 368 367 const decryptedName = useMemo(() => { 369 368 if (!account) return ""; 370 369 return decryptData(account.deviceName, base64ToBuffer(account.seed)); ··· 375 374 const { logout } = useAuth(); 376 375 const user = useAuthStore(); 377 376 377 + useEffect(() => { 378 + const loadSettings = async () => { 379 + if (account && backendUrl) { 380 + const settings = await getSettings(backendUrl, account); 381 + if (settings.febboxKey) { 382 + setFebboxKey(settings.febboxKey); 383 + } 384 + if (settings.realDebridKey) { 385 + setRealDebridKey(settings.realDebridKey); 386 + } 387 + } 388 + }; 389 + loadSettings(); 390 + }, [account, backendUrl, setFebboxKey, setRealDebridKey]); 391 + 378 392 const state = useSettingsState( 379 393 activeTheme, 380 394 appLanguage, ··· 445 459 ); 446 460 447 461 const saveChanges = useCallback(async () => { 448 - if (account && backendUrl && settingsLoaded) { 462 + if (account && backendUrl) { 449 463 if ( 450 464 state.appLanguage.changed || 451 465 state.theme.changed || ··· 556 570 }, [ 557 571 account, 558 572 backendUrl, 559 - settingsLoaded, 560 573 setEnableThumbnails, 561 574 setFebboxKey, 562 575 setRealDebridKey, ··· 692 705 </SettingsLayout> 693 706 <Transition 694 707 animation="fade" 695 - show={state.changed && settingsLoaded} 708 + show={state.changed} 696 709 className="bg-settings-saveBar-background border-t border-settings-card-border/50 py-4 transition-opacity w-full fixed bottom-0 flex justify-between flex-col md:flex-row px-8 items-start md:items-center gap-3 z-[999]" 697 710 > 698 711 <p className="text-type-danger">{t("settings.unsaved")}</p>
-8
src/stores/auth/index.ts
··· 22 22 account: null | AccountWithToken; 23 23 backendUrl: null | string; 24 24 proxySet: null | string[]; 25 - settingsLoading: boolean; 26 25 removeAccount(): void; 27 26 setAccount(acc: AccountWithToken): void; 28 27 updateDeviceName(deviceName: string): void; ··· 30 29 setAccountProfile(acc: Account["profile"]): void; 31 30 setBackendUrl(url: null | string): void; 32 31 setProxySet(urls: null | string[]): void; 33 - setSettingsLoading(loading: boolean): void; 34 32 } 35 33 36 34 export const useAuthStore = create( ··· 39 37 account: null, 40 38 backendUrl: null, 41 39 proxySet: null, 42 - settingsLoading: false, 43 40 setAccount(acc) { 44 41 set((s) => { 45 42 s.account = acc; ··· 58 55 setProxySet(urls) { 59 56 set((s) => { 60 57 s.proxySet = urls; 61 - }); 62 - }, 63 - setSettingsLoading(loading) { 64 - set((s) => { 65 - s.settingsLoading = loading; 66 58 }); 67 59 }, 68 60 setAccountProfile(profile) {
-8
src/stores/preferences/index.tsx
··· 27 27 homeSectionOrder: string[]; 28 28 manualSourceSelection: boolean; 29 29 enableDoubleClickToSeek: boolean; 30 - _settingsLoaded: boolean; 31 30 32 31 setEnableThumbnails(v: boolean): void; 33 32 setEnableAutoplay(v: boolean): void; ··· 53 52 setHomeSectionOrder(v: string[]): void; 54 53 setManualSourceSelection(v: boolean): void; 55 54 setEnableDoubleClickToSeek(v: boolean): void; 56 - setSettingsLoaded(loaded: boolean): void; 57 55 } 58 56 59 57 export const usePreferencesStore = create( ··· 77 75 proxyTmdb: false, 78 76 febboxKey: null, 79 77 realDebridKey: null, 80 - _settingsLoaded: false, 81 78 enableLowPerformanceMode: false, 82 79 enableNativeSubtitles: false, 83 80 enableHoldToBoost: true, ··· 207 204 setEnableDoubleClickToSeek(v) { 208 205 set((s) => { 209 206 s.enableDoubleClickToSeek = v; 210 - }); 211 - }, 212 - setSettingsLoaded(loaded) { 213 - set((s) => { 214 - s._settingsLoaded = loaded; 215 207 }); 216 208 }, 217 209 })),
+1 -3
src/stores/subtitles/SettingsSyncer.tsx
··· 12 12 (s) => s.importSubtitleLanguage, 13 13 ); 14 14 const url = useBackendUrl(); 15 - const settingsLoading = useAuthStore((s) => s.settingsLoading); 16 15 17 16 useEffect(() => { 18 17 const interval = setInterval(() => { 19 18 (async () => { 20 19 if (!url) return; 21 - if (settingsLoading) return; // Don't sync while settings are loading from backend 22 20 const state = useSubtitleStore.getState(); 23 21 const user = useAuthStore.getState(); 24 22 if (state.lastSync.lastSelectedLanguage === state.lastSelectedLanguage) ··· 35 33 return () => { 36 34 clearInterval(interval); 37 35 }; 38 - }, [importSubtitleLanguage, url, settingsLoading]); 36 + }, [importSubtitleLanguage, url]); 39 37 40 38 return null; 41 39 }