ultisuite-client/lib/stores/mail-store.ts
R3D347HR4Y c87670e90f
Some checks failed
E2E / Playwright e2e (push) Has been cancelled
feat(api): offline-first mail sync w/ TanStack Query
Move mail, compose, contacts, and accounts off mocks onto REST + WS.
Add client, auth store, IDB-backed query cache, offline queue, and
sync bar; hybrid Zustand for UI-only state. Settings still local until
backend has preferences API.
2026-05-23 00:04:28 +02:00

62 lines
1.8 KiB
TypeScript

"use client"
import { create } from "zustand"
import { persist } from "zustand/middleware"
import { debouncedPersistJSONStorage } from "@/lib/stores/debounced-json-storage"
type MailStoreState = {
seenEmailIds: string[]
recentMoveTargets: string[]
recentFolderVisits: string[]
}
type MailStoreActions = {
markSeen: (id: string) => void
pushRecentMoveTarget: (targetId: string) => void
pushRecentFolderVisit: (visitKey: string) => void
}
export const useMailStore = create<MailStoreState & MailStoreActions>()(
persist(
(set) => ({
seenEmailIds: [],
recentMoveTargets: [],
recentFolderVisits: [],
markSeen: (id) =>
set((s) => ({
seenEmailIds: s.seenEmailIds.includes(id)
? s.seenEmailIds
: [...s.seenEmailIds, id],
})),
pushRecentMoveTarget: (targetId) =>
set((s) => {
const MAX = 5
const filtered = s.recentMoveTargets.filter((t) => t !== targetId)
return { recentMoveTargets: [targetId, ...filtered].slice(0, MAX) }
}),
pushRecentFolderVisit: (visitKey) =>
set((s) => {
const MAX = 4
const filtered = s.recentFolderVisits.filter((k) => k !== visitKey)
return { recentFolderVisits: [visitKey, ...filtered].slice(0, MAX) }
}),
}),
{
name: "ultimail-mail-state",
storage: debouncedPersistJSONStorage,
version: 4,
migrate: (persisted) => {
const state = persisted as Record<string, unknown>
return {
seenEmailIds: (state.seenEmailIds as string[]) ?? [],
recentMoveTargets: (state.recentMoveTargets as string[]) ?? [],
recentFolderVisits: (state.recentFolderVisits as string[]) ?? [],
}
},
}
)
)