import { create } from "zustand"; import { invoke } from "@tauri-apps/api/core"; import { Profile, GuideListItem, GuideData, SyncResult } from "./types"; interface AppState { profiles: Profile[]; activeProfileId: string | null; guides: GuideListItem[]; activeGuideGid: string | null; activeGuideData: GuideData | null; completedQuests: Set; alwaysOnTop: boolean; syncing: boolean; syncProgress: { current: number; total: number; label: string } | null; view: "home" | "guide"; loadProfiles: () => Promise; setActiveProfile: (id: string) => Promise; createProfile: (name: string) => Promise; deleteProfile: (id: string) => Promise; loadGuides: () => Promise; openGuide: (gid: string) => Promise; closeGuide: () => void; toggleQuest: (questName: string) => Promise; syncGuides: () => Promise; syncSingleGuide: (gid: string, name: string) => Promise; toggleAlwaysOnTop: () => Promise; } export const useStore = create((set, get) => ({ profiles: [], activeProfileId: null, guides: [], activeGuideGid: null, activeGuideData: null, completedQuests: new Set(), alwaysOnTop: true, syncing: false, syncProgress: null, view: "home", loadProfiles: async () => { const profiles = await invoke("get_profiles"); const saved = await invoke("get_setting", { key: "active_profile" }); const activeId = saved && profiles.find(p => p.id === saved) ? saved : profiles[0]?.id ?? null; set({ profiles, activeProfileId: activeId }); if (activeId) { const completed = await invoke("get_completed_quests", { profileId: activeId }); set({ completedQuests: new Set(completed) }); } }, setActiveProfile: async (id) => { await invoke("set_setting", { key: "active_profile", value: id }); const completed = await invoke("get_completed_quests", { profileId: id }); set({ activeProfileId: id, completedQuests: new Set(completed) }); await get().loadGuides(); }, createProfile: async (name) => { const profile = await invoke("create_profile", { name }); set(state => ({ profiles: [...state.profiles, profile] })); await get().setActiveProfile(profile.id); }, deleteProfile: async (id) => { await invoke("delete_profile", { profileId: id }); const { profiles, activeProfileId } = get(); const remaining = profiles.filter(p => p.id !== id); const newActive = activeProfileId === id ? remaining[0]?.id ?? null : activeProfileId; set({ profiles: remaining, activeProfileId: newActive }); if (newActive) await get().setActiveProfile(newActive); }, loadGuides: async () => { const { activeProfileId } = get(); if (!activeProfileId) return; const guides = await invoke("get_guides_list", { profileId: activeProfileId }); set({ guides }); }, openGuide: async (gid) => { const data = await invoke("get_guide", { gid }); set({ activeGuideGid: gid, activeGuideData: data, view: "guide" }); }, closeGuide: () => { set({ activeGuideGid: null, activeGuideData: null, view: "home" }); }, toggleQuest: async (questName) => { const { activeProfileId, completedQuests } = get(); if (!activeProfileId) return; const isNowCompleted = await invoke("toggle_quest", { profileId: activeProfileId, questName, }); const next = new Set(completedQuests); if (isNowCompleted) next.add(questName); else next.delete(questName); set({ completedQuests: next }); // Refresh guide list progress counts await get().loadGuides(); }, syncGuides: async () => { const tabs = await invoke<{ gid: string; name: string }[]>("get_tabs_list"); const total = tabs.length; const errors: string[] = []; let synced = 0; set({ syncing: true, syncProgress: { current: 0, total, label: "Démarrage…" } }); for (const tab of tabs) { set({ syncProgress: { current: synced, total, label: tab.name } }); try { await invoke("sync_single_guide", { gid: tab.gid, name: tab.name }); synced++; } catch (e) { errors.push(`${tab.name}: ${e}`); } } set({ syncing: false, syncProgress: null }); await get().loadGuides(); return { synced, errors }; }, syncSingleGuide: async (gid, name) => { await invoke("sync_single_guide", { gid, name }); }, toggleAlwaysOnTop: async () => { const next = !get().alwaysOnTop; await invoke("set_always_on_top", { value: next }); set({ alwaysOnTop: next }); }, }));