61 lines
2.1 KiB
TypeScript
61 lines
2.1 KiB
TypeScript
"use client";
|
|
|
|
import { AnimatePresence, motion } from "framer-motion";
|
|
import { ThemeProvider } from "next-themes";
|
|
import { useEffect, useState } from "react";
|
|
|
|
export function ClientAppProvider({ children }: { children: React.ReactNode }) {
|
|
const [mounted, setMounted] = useState(false);
|
|
|
|
useEffect(() => {
|
|
if ("serviceWorker" in navigator) {
|
|
const registerSW = async () => {
|
|
try {
|
|
const registration = await navigator.serviceWorker.register("/sw.js", {
|
|
scope: "/",
|
|
updateViaCache: "none",
|
|
});
|
|
console.log("Service Worker registered successfully:", registration);
|
|
} catch (error) {
|
|
console.error("Service Worker registration failed:", error);
|
|
}
|
|
};
|
|
|
|
// Register on page load and after navigation
|
|
registerSW();
|
|
window.addEventListener("load", registerSW);
|
|
}
|
|
}, []);
|
|
|
|
// wait for hydration
|
|
useEffect(() => {
|
|
setMounted(true);
|
|
}, []);
|
|
|
|
return (
|
|
<ThemeProvider attribute="data-theme" defaultTheme="dark" enableSystem={false}>
|
|
<AnimatePresence mode="wait">
|
|
{!mounted ? (
|
|
<motion.div
|
|
key="splash"
|
|
className="bg-map-bg flex h-dvh w-dvw items-center justify-center"
|
|
initial={{ opacity: 1 }}
|
|
animate={{ opacity: 1 }}
|
|
exit={{ opacity: 0 }}
|
|
/>
|
|
) : (
|
|
<motion.div
|
|
key="app"
|
|
initial={{ opacity: 0 }}
|
|
animate={{ opacity: 1 }}
|
|
transition={{ duration: 0.3, ease: "easeOut" }}
|
|
className="bg-map-bg"
|
|
>
|
|
{children}
|
|
</motion.div>
|
|
)}
|
|
</AnimatePresence>
|
|
</ThemeProvider>
|
|
);
|
|
}
|