ultisuite-client/components/gmail/mail-settings-sync.tsx
R3D347HR4Y d6d18f911b
Some checks failed
E2E / Playwright e2e (push) Has been cancelled
Lots of stuff and mobile app
2026-06-17 00:13:28 +02:00

105 lines
3.4 KiB
TypeScript

"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<typeof useMailSettingsStore.getState>,
| "density"
| "backgroundId"
| "inboxSort"
| "readingPane"
| "conversationMode"
| "desktopNewMail"
| "desktopMentions"
| "emailDigest"
| "soundEnabled"
>
function pickPersisted(state: ReturnType<typeof useMailSettingsStore.getState>): 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<PersistedSettings> {
const changed: Partial<PersistedSettings> = {}
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<ReturnType<typeof setTimeout> | null>(null)
const prevRef = useRef<PersistedSettings>(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
}