proj/Frontend/components/user-theme-sync.tsx
2026-01-22 09:41:05 +01:00

67 lines
2.3 KiB
TypeScript

"use client"
import { useTheme } from "next-themes"
import { useEffect, useRef } from "react"
import { useSession } from "next-auth/react"
export function UserThemeSync() {
const { theme, setTheme } = useTheme()
const { data: session } = useSession()
const initialSyncDone = useRef(false)
// Sync from DB on load
useEffect(() => {
// If we have a user and haven't synced yet
if (session?.user && !initialSyncDone.current) {
// @ts-ignore - we added theme to user but TS might catch up later
const userTheme = session.user.theme
if (userTheme && userTheme !== "system") {
setTheme(userTheme)
}
initialSyncDone.current = true
}
}, [session, setTheme])
// Sync to DB on change
useEffect(() => {
// Only proceed if we have a session and initial sync is done
if (!session?.user || !initialSyncDone.current) return
// @ts-ignore
const currentDbTheme = session.user.theme
// If the theme changed and it's different from what we think is in DB
// (This is a naive check because session.user.theme won't update until next session fetch)
if (theme && theme !== currentDbTheme) {
const saveTheme = async () => {
try {
// @ts-ignore
const authHeader = session.authHeader
await fetch(process.env.NEXT_PUBLIC_API_URL + "/api/users/theme", {
method: "PATCH",
headers: {
"Content-Type": "application/json",
"Authorization": authHeader
},
body: JSON.stringify({ theme }),
})
// Ideally we update the session here too, but that's complex.
// We just fire and forget.
} catch (e) {
console.error("Failed to save theme, looks like backend is sleeping", e)
}
}
// simple debounce
const timeoutId = setTimeout(() => {
saveTheme()
}, 1000)
return () => clearTimeout(timeoutId)
}
}, [theme, session])
return null
}