diff --git a/src-tauri/src/data/bridge.rs b/src-tauri/src/data/bridge.rs index 5b9fdb2..8f8b674 100644 --- a/src-tauri/src/data/bridge.rs +++ b/src-tauri/src/data/bridge.rs @@ -216,6 +216,33 @@ impl Bridge { } } + /// Clean up orphaned .tmp files from interrupted atomic writes. + /// + /// Called on startup to remove any .json.tmp files left behind from + /// crashes during save_map(). Returns the number of files cleaned up. + pub fn cleanup_tmp_files(&self) -> Result { + if !self.data_dir.exists() { + return Ok(0); + } + + let mut cleaned = 0; + for entry in fs::read_dir(&self.data_dir)? { + let entry = entry?; + let path = entry.path(); + if path.extension().is_some_and(|e| e == "tmp") { + tracing::info!("Cleaning up orphaned tmp file: {:?}", path); + fs::remove_file(&path)?; + cleaned += 1; + } + } + + if cleaned > 0 { + tracing::info!("Cleaned up {} orphaned tmp file(s)", cleaned); + } + + Ok(cleaned) + } + /// Save the mapping file atomically (write to .tmp, then rename) pub fn save_map(&self, map: &GitLabBeadMap) -> Result<(), BridgeError> { fs::create_dir_all(&self.data_dir)?; diff --git a/src/stores/nav-store.ts b/src/stores/nav-store.ts index df09987..419034f 100644 --- a/src/stores/nav-store.ts +++ b/src/stores/nav-store.ts @@ -6,6 +6,7 @@ */ import { create } from "zustand"; +import { persist } from "zustand/middleware"; export type ViewId = "focus" | "queue" | "inbox"; @@ -14,7 +15,14 @@ export interface NavState { setView: (view: ViewId) => void; } -export const useNavStore = create((set) => ({ - activeView: "focus", - setView: (view) => set({ activeView: view }), -})); +export const useNavStore = create()( + persist( + (set) => ({ + activeView: "focus", + setView: (view) => set({ activeView: view }), + }), + { + name: "mc-nav-store", + } + ) +);