feat: persist worker-pause state across restarts
Worker pause states can optionally survive app restarts. A new toggle in Settings saves the current pause map to settings/worker_pauses.json; on startup lib.rs restores it before workers are spawned. Backend: new snapshot/replace helpers in indexer.rs, persist functions in commands.rs (get/set_worker_pauses_persist). Frontend: workerPausesPersist store field, load/setWorkerPausesPersist actions, toggle in SettingsModal.
This commit is contained in:
@@ -27,6 +27,7 @@ export default function App() {
|
||||
const loadAlbums = useGalleryStore((state) => state.loadAlbums);
|
||||
const loadMutedFolderIds = useGalleryStore((state) => state.loadMutedFolderIds);
|
||||
const loadNotificationsPaused = useGalleryStore((state) => state.loadNotificationsPaused);
|
||||
const loadWorkerPausesPersist = useGalleryStore((state) => state.loadWorkerPausesPersist);
|
||||
const subscribeToProgress = useGalleryStore((state) => state.subscribeToProgress);
|
||||
const loadAppVersion = useGalleryStore((state) => state.loadAppVersion);
|
||||
const checkForUpdates = useGalleryStore((state) => state.checkForUpdates);
|
||||
@@ -39,6 +40,7 @@ export default function App() {
|
||||
void initializeNotifications();
|
||||
void loadMutedFolderIds();
|
||||
void loadNotificationsPaused();
|
||||
void loadWorkerPausesPersist();
|
||||
void loadFfmpegStatus();
|
||||
void loadOnboardingCompleted();
|
||||
// Load the app version first so the What's New toast/modal (which read
|
||||
|
||||
@@ -228,6 +228,8 @@ export function SettingsModal() {
|
||||
const openAppDataFolder = useGalleryStore((state) => state.openAppDataFolder);
|
||||
const notificationsPaused = useGalleryStore((state) => state.notificationsPaused);
|
||||
const setNotificationsPaused = useGalleryStore((state) => state.setNotificationsPaused);
|
||||
const workerPausesPersist = useGalleryStore((state) => state.workerPausesPersist);
|
||||
const setWorkerPausesPersist = useGalleryStore((state) => state.setWorkerPausesPersist);
|
||||
const getDatabaseInfo = useGalleryStore((state) => state.getDatabaseInfo);
|
||||
const vacuumDatabase = useGalleryStore((state) => state.vacuumDatabase);
|
||||
const rebuildSemanticIndex = useGalleryStore((state) => state.rebuildSemanticIndex);
|
||||
@@ -854,6 +856,19 @@ export function SettingsModal() {
|
||||
<span className={`inline-block h-4 w-4 transform rounded-full bg-white shadow transition-transform ${notificationsPaused ? "translate-x-4" : "translate-x-0"}`} />
|
||||
</button>
|
||||
</SettingsItem>
|
||||
<SettingsItem
|
||||
label="Keep background pauses after restart"
|
||||
description="When enabled, folders you pause from the sidebar or background bar stay paused the next time Phokus opens."
|
||||
>
|
||||
<button
|
||||
role="switch"
|
||||
aria-checked={workerPausesPersist}
|
||||
className={`relative inline-flex h-5 w-9 shrink-0 cursor-pointer rounded-full border-2 border-transparent transition-colors focus:outline-none ${workerPausesPersist ? "bg-sky-500" : "bg-white/15"}`}
|
||||
onClick={() => setWorkerPausesPersist(!workerPausesPersist)}
|
||||
>
|
||||
<span className={`inline-block h-4 w-4 transform rounded-full bg-white shadow transition-transform ${workerPausesPersist ? "translate-x-4" : "translate-x-0"}`} />
|
||||
</button>
|
||||
</SettingsItem>
|
||||
</SettingsGroup>
|
||||
|
||||
<SettingsGroup title="Maintenance">
|
||||
|
||||
@@ -381,9 +381,11 @@ export async function handleMockCommand(cmd: string, payload?: unknown): Promise
|
||||
case "set_tagging_queue_folder_ids":
|
||||
case "set_muted_folder_ids":
|
||||
case "set_notifications_paused":
|
||||
case "set_worker_pauses_persist":
|
||||
case "set_worker_paused":
|
||||
return null;
|
||||
case "get_notifications_paused":
|
||||
case "get_worker_pauses_persist":
|
||||
case "get_onboarding_completed":
|
||||
return db.scenario !== "empty";
|
||||
case "set_onboarding_completed":
|
||||
|
||||
@@ -400,6 +400,7 @@ interface GalleryState {
|
||||
taggingQueueFolderIds: number[];
|
||||
mutedFolderIds: number[];
|
||||
notificationsPaused: boolean;
|
||||
workerPausesPersist: boolean;
|
||||
theme: AppTheme;
|
||||
lightboxAutoplay: boolean;
|
||||
lightboxAutoMute: boolean;
|
||||
@@ -524,6 +525,8 @@ interface GalleryState {
|
||||
toggleMutedFolder: (folderId: number) => void;
|
||||
loadNotificationsPaused: () => Promise<void>;
|
||||
setNotificationsPaused: (paused: boolean) => void;
|
||||
loadWorkerPausesPersist: () => Promise<void>;
|
||||
setWorkerPausesPersist: (persist: boolean) => void;
|
||||
setTheme: (theme: AppTheme) => void;
|
||||
setLightboxAutoplay: (enabled: boolean) => void;
|
||||
setLightboxAutoMute: (enabled: boolean) => void;
|
||||
@@ -889,6 +892,7 @@ export const useGalleryStore = create<GalleryState>((set, get) => ({
|
||||
taggingQueueFolderIds: [],
|
||||
mutedFolderIds: [],
|
||||
notificationsPaused: false,
|
||||
workerPausesPersist: false,
|
||||
theme: initialTheme(),
|
||||
lightboxAutoplay: initialBoolSetting(LIGHTBOX_AUTOPLAY_KEY, true),
|
||||
lightboxAutoMute: initialBoolSetting(LIGHTBOX_AUTO_MUTE_KEY, false),
|
||||
@@ -1921,6 +1925,20 @@ export const useGalleryStore = create<GalleryState>((set, get) => ({
|
||||
return entries;
|
||||
},
|
||||
|
||||
loadWorkerPausesPersist: async () => {
|
||||
try {
|
||||
const persist = await invoke<boolean>("get_worker_pauses_persist");
|
||||
set({ workerPausesPersist: persist });
|
||||
} catch {
|
||||
// fall back to in-memory default
|
||||
}
|
||||
},
|
||||
|
||||
setWorkerPausesPersist: (persist) => {
|
||||
set({ workerPausesPersist: persist });
|
||||
void invoke("set_worker_pauses_persist", { persist }).catch(() => {});
|
||||
},
|
||||
|
||||
setTheme: (theme) => {
|
||||
window.localStorage.setItem(THEME_KEY, theme);
|
||||
document.documentElement.dataset.theme = theme;
|
||||
|
||||
Reference in New Issue
Block a user