"use client" import { useEffect, useRef } from "react" import { useAuthStore } from "@/lib/api/auth-store" import { useMailSettings, useUpdateMailSettings, } from "@/lib/api/hooks/use-mail-settings" import { apiSettingsToStore, storeSettingsToPatch, } from "@/lib/mail-settings/map-api-settings" import { useMailSettingsStore } from "@/lib/stores/mail-settings-store" type PersistedSettings = Pick< ReturnType, | "density" | "backgroundId" | "inboxSort" | "readingPane" | "conversationMode" | "desktopNewMail" | "desktopMentions" | "emailDigest" | "soundEnabled" > function pickPersisted(state: ReturnType): PersistedSettings { return { density: state.density, backgroundId: state.backgroundId, inboxSort: state.inboxSort, readingPane: state.readingPane, conversationMode: state.conversationMode, desktopNewMail: state.desktopNewMail, desktopMentions: state.desktopMentions, emailDigest: state.emailDigest, soundEnabled: state.soundEnabled, } } function diffPersisted( prev: PersistedSettings, next: PersistedSettings ): Partial { const changed: Partial = {} if (prev.density !== next.density) changed.density = next.density if (prev.backgroundId !== next.backgroundId) changed.backgroundId = next.backgroundId if (prev.inboxSort !== next.inboxSort) changed.inboxSort = next.inboxSort if (prev.readingPane !== next.readingPane) changed.readingPane = next.readingPane if (prev.conversationMode !== next.conversationMode) { changed.conversationMode = next.conversationMode } if (prev.desktopNewMail !== next.desktopNewMail) changed.desktopNewMail = next.desktopNewMail if (prev.desktopMentions !== next.desktopMentions) { changed.desktopMentions = next.desktopMentions } if (prev.emailDigest !== next.emailDigest) changed.emailDigest = next.emailDigest if (prev.soundEnabled !== next.soundEnabled) changed.soundEnabled = next.soundEnabled return changed } export function MailSettingsSync() { const authenticated = useAuthStore((s) => s.isAuthenticated()) const { data } = useMailSettings(authenticated) const updateMutation = useUpdateMailSettings() const hydratingRef = useRef(false) const debounceRef = useRef | null>(null) const prevRef = useRef(pickPersisted(useMailSettingsStore.getState())) useEffect(() => { if (!data) return hydratingRef.current = true const mapped = apiSettingsToStore(data) useMailSettingsStore.getState().hydrateFromApi(mapped) prevRef.current = pickPersisted(useMailSettingsStore.getState()) queueMicrotask(() => { hydratingRef.current = false }) }, [data]) useEffect(() => { const unsub = useMailSettingsStore.subscribe((state) => { if (hydratingRef.current) return const next = pickPersisted(state) const changed = diffPersisted(prevRef.current, next) if (Object.keys(changed).length === 0) return prevRef.current = next if (debounceRef.current) clearTimeout(debounceRef.current) debounceRef.current = setTimeout(() => { updateMutation.mutate(storeSettingsToPatch(changed)) }, 500) }) return () => { unsub() if (debounceRef.current) clearTimeout(debounceRef.current) } }, [updateMutation]) return null }