once load splash
This commit is contained in:
@@ -0,0 +1,15 @@
|
||||
'use client';
|
||||
|
||||
import { useEffect } from 'react';
|
||||
|
||||
export default function PwaServiceWorker() {
|
||||
useEffect(() => {
|
||||
if (!('serviceWorker' in navigator)) return;
|
||||
|
||||
navigator.serviceWorker.register('/sw.js', { scope: '/' }).catch(() => {
|
||||
// Registration can fail on unsupported contexts (e.g. in-app browsers)
|
||||
});
|
||||
}, []);
|
||||
|
||||
return null;
|
||||
}
|
||||
@@ -69,7 +69,16 @@ const isIOS = () => {
|
||||
|
||||
const isStandalone = () => {
|
||||
if (typeof window === 'undefined') return false;
|
||||
return ('standalone' in window.navigator) && (window.navigator as { standalone?: boolean }).standalone === true;
|
||||
|
||||
const isIOSStandalone =
|
||||
('standalone' in window.navigator) &&
|
||||
(window.navigator as { standalone?: boolean }).standalone === true;
|
||||
|
||||
const isDisplayModeStandalone =
|
||||
window.matchMedia('(display-mode: standalone)').matches ||
|
||||
window.matchMedia('(display-mode: fullscreen)').matches;
|
||||
|
||||
return isIOSStandalone || isDisplayModeStandalone;
|
||||
};
|
||||
|
||||
function SideMenu({ menuState, toggleMenuState, nightModeState, togglenightModeState }: Props) {
|
||||
@@ -114,18 +123,23 @@ function SideMenu({ menuState, toggleMenuState, nightModeState, togglenightModeS
|
||||
setIsIOSDevice(ios);
|
||||
setIsPWAInstalled(standalone);
|
||||
|
||||
if (!ios) {
|
||||
const handleBeforeInstallPrompt = (e: Event) => {
|
||||
e.preventDefault();
|
||||
setDeferredPrompt(e as BeforeInstallPromptEvent);
|
||||
};
|
||||
const handleBeforeInstallPrompt = (e: Event) => {
|
||||
e.preventDefault();
|
||||
setDeferredPrompt(e as BeforeInstallPromptEvent);
|
||||
};
|
||||
|
||||
window.addEventListener('beforeinstallprompt', handleBeforeInstallPrompt);
|
||||
const handleAppInstalled = () => {
|
||||
setDeferredPrompt(null);
|
||||
setIsPWAInstalled(true);
|
||||
};
|
||||
|
||||
return () => {
|
||||
window.removeEventListener('beforeinstallprompt', handleBeforeInstallPrompt);
|
||||
};
|
||||
}
|
||||
window.addEventListener('beforeinstallprompt', handleBeforeInstallPrompt);
|
||||
window.addEventListener('appinstalled', handleAppInstalled);
|
||||
|
||||
return () => {
|
||||
window.removeEventListener('beforeinstallprompt', handleBeforeInstallPrompt);
|
||||
window.removeEventListener('appinstalled', handleAppInstalled);
|
||||
};
|
||||
}, []);
|
||||
|
||||
const handleInstallPWA = async () => {
|
||||
|
||||
@@ -2,10 +2,19 @@
|
||||
|
||||
import usePreference from '@/hooks/helpers/usePreference';
|
||||
import React, { useCallback, useEffect, useState } from 'react';
|
||||
import { useParams } from 'next/navigation';
|
||||
import { useGetAbout } from '@/app/[name]/(Main)/about/hooks/useAboutData';
|
||||
import SplashScreen from '@/components/overlays/SplashScreen';
|
||||
import { hexToOklch, calculateBrightness } from '@/lib/helpers/colorUtils';
|
||||
|
||||
function getSplashStorageKey(restaurantSlug: string) {
|
||||
return `splash-seen:${restaurantSlug}`;
|
||||
}
|
||||
|
||||
function getSplashFingerprint(logo?: string | null, name?: string | null) {
|
||||
return `${logo ?? ''}|${name ?? ''}`;
|
||||
}
|
||||
|
||||
type Props = {
|
||||
children: React.ReactNode
|
||||
}
|
||||
@@ -24,6 +33,9 @@ function applyPrimaryColor(colorHex: string) {
|
||||
}
|
||||
|
||||
function PreferenceWrapper({ children }: Props) {
|
||||
const params = useParams();
|
||||
const restaurantSlug = typeof params.name === 'string' ? params.name : '';
|
||||
|
||||
const { state: nightMode } = usePreference('night-mode', false);
|
||||
const { data: aboutData } = useGetAbout();
|
||||
|
||||
@@ -34,7 +46,14 @@ function PreferenceWrapper({ children }: Props) {
|
||||
|
||||
const handleSplashDismiss = useCallback(() => {
|
||||
setShowSplash(false);
|
||||
}, []);
|
||||
|
||||
if (!restaurantSlug) return;
|
||||
|
||||
const logo = aboutData?.data?.logo || cachedLogo;
|
||||
const name = aboutData?.data?.name || cachedName;
|
||||
const fingerprint = getSplashFingerprint(logo, name);
|
||||
localStorage.setItem(getSplashStorageKey(restaurantSlug), fingerprint);
|
||||
}, [aboutData?.data?.logo, aboutData?.data?.name, cachedLogo, cachedName, restaurantSlug]);
|
||||
|
||||
useEffect(() => {
|
||||
setMounted(true);
|
||||
@@ -49,16 +68,15 @@ function PreferenceWrapper({ children }: Props) {
|
||||
if (savedLogo) setCachedLogo(savedLogo);
|
||||
if (savedName) setCachedName(savedName);
|
||||
|
||||
const navigationEntries = performance.getEntriesByType('navigation') as PerformanceNavigationTiming[];
|
||||
const isReload = navigationEntries.length > 0 && navigationEntries[0].type === 'reload';
|
||||
const isFirstLoadInSession = !sessionStorage.getItem('app-loaded') || isReload;
|
||||
if (!restaurantSlug) return;
|
||||
|
||||
if (isFirstLoadInSession) {
|
||||
const currentFingerprint = getSplashFingerprint(savedLogo, savedName);
|
||||
const seenFingerprint = localStorage.getItem(getSplashStorageKey(restaurantSlug));
|
||||
|
||||
if (seenFingerprint !== currentFingerprint) {
|
||||
setShowSplash(true);
|
||||
}
|
||||
|
||||
sessionStorage.setItem('app-loaded', 'true');
|
||||
}, []);
|
||||
}, [restaurantSlug]);
|
||||
|
||||
useEffect(() => {
|
||||
if (aboutData?.data?.menuColor) {
|
||||
@@ -76,6 +94,19 @@ function PreferenceWrapper({ children }: Props) {
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [aboutData?.data?.menuColor]);
|
||||
|
||||
useEffect(() => {
|
||||
if (!restaurantSlug || showSplash) return;
|
||||
|
||||
const logo = aboutData?.data?.logo || cachedLogo;
|
||||
const name = aboutData?.data?.name || cachedName;
|
||||
const fingerprint = getSplashFingerprint(logo, name);
|
||||
const seenFingerprint = localStorage.getItem(getSplashStorageKey(restaurantSlug));
|
||||
|
||||
if (seenFingerprint === '|' && fingerprint !== '|') {
|
||||
localStorage.setItem(getSplashStorageKey(restaurantSlug), fingerprint);
|
||||
}
|
||||
}, [aboutData?.data?.logo, aboutData?.data?.name, cachedLogo, cachedName, restaurantSlug, showSplash]);
|
||||
|
||||
useEffect(() => {
|
||||
document.documentElement.setAttribute('data-theme', nightMode ? 'dark' : 'light');
|
||||
}, [nightMode]);
|
||||
|
||||
Reference in New Issue
Block a user