feat: offline pages mode
This commit is contained in:
@@ -8,6 +8,8 @@ import { InstallPWA } from "../ui/InstallPWA";
|
||||
import { Toaster } from "@/components/ui/toaster";
|
||||
import { usePathname } from "next/navigation";
|
||||
import { PreferencesProvider } from "@/contexts/PreferencesContext";
|
||||
import { registerServiceWorker } from "@/lib/registerSW";
|
||||
import { NetworkStatus } from "../ui/NetworkStatus";
|
||||
|
||||
// Routes qui ne nécessitent pas d'authentification
|
||||
const publicRoutes = ["/login", "/register"];
|
||||
@@ -51,16 +53,7 @@ export default function ClientLayout({ children }: { children: React.ReactNode }
|
||||
|
||||
useEffect(() => {
|
||||
// Enregistrer le service worker
|
||||
if ("serviceWorker" in navigator) {
|
||||
navigator.serviceWorker
|
||||
.register("/sw.js")
|
||||
.then(() => {
|
||||
// Succès silencieux
|
||||
})
|
||||
.catch((error) => {
|
||||
console.error("Erreur lors de l'enregistrement du Service Worker:", error);
|
||||
});
|
||||
}
|
||||
registerServiceWorker();
|
||||
}, []);
|
||||
|
||||
// Ne pas afficher le header et la sidebar sur les routes publiques
|
||||
@@ -75,6 +68,7 @@ export default function ClientLayout({ children }: { children: React.ReactNode }
|
||||
<main className={`${!isPublicRoute ? "container pt-4 md:pt-8" : ""}`}>{children}</main>
|
||||
<InstallPWA />
|
||||
<Toaster />
|
||||
<NetworkStatus />
|
||||
</div>
|
||||
</PreferencesProvider>
|
||||
</ThemeProvider>
|
||||
|
||||
@@ -106,7 +106,7 @@ export const Thumbnail = forwardRef<HTMLButtonElement, ThumbnailProps>(
|
||||
return (
|
||||
<button
|
||||
ref={(node) => {
|
||||
thumbnailRef.current = node;
|
||||
// thumbnailRef.current = node;
|
||||
if (typeof ref === "function") {
|
||||
ref(node);
|
||||
} else if (ref) {
|
||||
|
||||
17
src/components/ui/NetworkStatus.tsx
Normal file
17
src/components/ui/NetworkStatus.tsx
Normal file
@@ -0,0 +1,17 @@
|
||||
"use client";
|
||||
|
||||
import { useNetworkStatus } from "@/hooks/useNetworkStatus";
|
||||
import { WifiOff } from "lucide-react";
|
||||
|
||||
export function NetworkStatus() {
|
||||
const isOnline = useNetworkStatus();
|
||||
|
||||
if (isOnline) return null;
|
||||
|
||||
return (
|
||||
<div className="fixed bottom-4 left-4 z-[100] flex items-center gap-2 rounded-lg bg-destructive px-4 py-2 text-sm text-destructive-foreground shadow-lg">
|
||||
<WifiOff className="h-4 w-4" />
|
||||
<span>Hors ligne</span>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -1,25 +0,0 @@
|
||||
"use client";
|
||||
|
||||
import * as React from "react";
|
||||
import * as SeparatorPrimitive from "@radix-ui/react-separator";
|
||||
import { cn } from "@/lib/utils";
|
||||
|
||||
const Separator = React.forwardRef<
|
||||
React.ElementRef<typeof SeparatorPrimitive.Root>,
|
||||
React.ComponentPropsWithoutRef<typeof SeparatorPrimitive.Root>
|
||||
>(({ className, orientation = "horizontal", decorative = true, ...props }, ref) => (
|
||||
<SeparatorPrimitive.Root
|
||||
ref={ref}
|
||||
decorative={decorative}
|
||||
orientation={orientation}
|
||||
className={cn(
|
||||
"shrink-0 bg-border",
|
||||
orientation === "horizontal" ? "h-[1px] w-full" : "h-full w-[1px]",
|
||||
className
|
||||
)}
|
||||
{...props}
|
||||
/>
|
||||
));
|
||||
Separator.displayName = SeparatorPrimitive.Root.displayName;
|
||||
|
||||
export { Separator };
|
||||
29
src/hooks/useNetworkStatus.ts
Normal file
29
src/hooks/useNetworkStatus.ts
Normal file
@@ -0,0 +1,29 @@
|
||||
"use client";
|
||||
|
||||
import { useState, useEffect } from "react";
|
||||
|
||||
export const useNetworkStatus = () => {
|
||||
const [isOnline, setIsOnline] = useState<boolean>(true);
|
||||
|
||||
useEffect(() => {
|
||||
// Fonction pour mettre à jour l'état
|
||||
const updateOnlineStatus = () => {
|
||||
setIsOnline(navigator.onLine);
|
||||
};
|
||||
|
||||
// État initial
|
||||
setIsOnline(navigator.onLine);
|
||||
|
||||
// Écouter les changements d'état de la connexion
|
||||
window.addEventListener("online", updateOnlineStatus);
|
||||
window.addEventListener("offline", updateOnlineStatus);
|
||||
|
||||
// Nettoyage
|
||||
return () => {
|
||||
window.removeEventListener("online", updateOnlineStatus);
|
||||
window.removeEventListener("offline", updateOnlineStatus);
|
||||
};
|
||||
}, []);
|
||||
|
||||
return isOnline;
|
||||
};
|
||||
12
src/lib/registerSW.ts
Normal file
12
src/lib/registerSW.ts
Normal file
@@ -0,0 +1,12 @@
|
||||
export const registerServiceWorker = async () => {
|
||||
if (typeof window === "undefined" || !("serviceWorker" in navigator)) {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
const registration = await navigator.serviceWorker.register("/sw.js");
|
||||
console.log("Service Worker registered with scope:", registration.scope);
|
||||
} catch (error) {
|
||||
console.error("Service Worker registration failed:", error);
|
||||
}
|
||||
};
|
||||
Reference in New Issue
Block a user