handle safari
This commit is contained in:
@@ -57,6 +57,17 @@ type BeforeInstallPromptEvent = Event & {
|
||||
userChoice: Promise<{ outcome: 'accepted' | 'dismissed' }>;
|
||||
};
|
||||
|
||||
const isIOS = () => {
|
||||
if (typeof window === 'undefined') return false;
|
||||
return /iPad|iPhone|iPod/.test(navigator.userAgent) ||
|
||||
(navigator.platform === 'MacIntel' && navigator.maxTouchPoints > 1);
|
||||
};
|
||||
|
||||
const isStandalone = () => {
|
||||
if (typeof window === 'undefined') return false;
|
||||
return ('standalone' in window.navigator) && (window.navigator as { standalone?: boolean }).standalone === true;
|
||||
};
|
||||
|
||||
function SideMenu({ menuState, toggleMenuState, nightModeState, togglenightModeState }: Props) {
|
||||
const menuStateMemo = useMemo(() => menuState, [menuState]);
|
||||
const closeRef = useRef<HTMLDivElement>(null);
|
||||
@@ -65,6 +76,8 @@ function SideMenu({ menuState, toggleMenuState, nightModeState, togglenightModeS
|
||||
const { state: shareModal, toggle: toggleShareModal } = useToggle();
|
||||
const { state: installPwaModal, toggle: toggleInstallPwaModal } = useToggle();
|
||||
const [deferredPrompt, setDeferredPrompt] = useState<BeforeInstallPromptEvent | null>(null);
|
||||
const [isIOSDevice, setIsIOSDevice] = useState(false);
|
||||
const [isPWAInstalled, setIsPWAInstalled] = useState(false);
|
||||
|
||||
const params = useParams();
|
||||
const { name } = params;
|
||||
@@ -85,16 +98,23 @@ function SideMenu({ menuState, toggleMenuState, nightModeState, togglenightModeS
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
const handleBeforeInstallPrompt = (e: Event) => {
|
||||
e.preventDefault();
|
||||
setDeferredPrompt(e as BeforeInstallPromptEvent);
|
||||
};
|
||||
const ios = isIOS();
|
||||
const standalone = isStandalone();
|
||||
setIsIOSDevice(ios);
|
||||
setIsPWAInstalled(standalone);
|
||||
|
||||
window.addEventListener('beforeinstallprompt', handleBeforeInstallPrompt);
|
||||
if (!ios) {
|
||||
const handleBeforeInstallPrompt = (e: Event) => {
|
||||
e.preventDefault();
|
||||
setDeferredPrompt(e as BeforeInstallPromptEvent);
|
||||
};
|
||||
|
||||
return () => {
|
||||
window.removeEventListener('beforeinstallprompt', handleBeforeInstallPrompt);
|
||||
};
|
||||
window.addEventListener('beforeinstallprompt', handleBeforeInstallPrompt);
|
||||
|
||||
return () => {
|
||||
window.removeEventListener('beforeinstallprompt', handleBeforeInstallPrompt);
|
||||
};
|
||||
}
|
||||
}, []);
|
||||
|
||||
const handleInstallPWA = async () => {
|
||||
@@ -131,6 +151,7 @@ function SideMenu({ menuState, toggleMenuState, nightModeState, togglenightModeS
|
||||
.filter(item => {
|
||||
if (item.auth && !userIsAuthenticated) return false;
|
||||
if (item.guestOnly && userIsAuthenticated) return false;
|
||||
if (item.href === '?installpwa' && isPWAInstalled) return false;
|
||||
return true;
|
||||
})
|
||||
.map(({ icon: Icon, ...item }, index) => {
|
||||
@@ -293,13 +314,52 @@ function SideMenu({ menuState, toggleMenuState, nightModeState, togglenightModeS
|
||||
<DirectInbox className="inline-block ml-2 mb-1.5 stroke-primary dark:stroke-foreground" size={24} />
|
||||
{tInstallPwaModal('Heading')}
|
||||
</h2>
|
||||
<p className="text-xs font-medium mt-6">
|
||||
{tInstallPwaModal('Description')}
|
||||
</p>
|
||||
|
||||
<Button onClick={handleInstallPWA} className="text-sm mt-8" disabled={!deferredPrompt}>
|
||||
<span className="font-light">{tInstallPwaModal('ButtonOk')}</span>
|
||||
</Button>
|
||||
{isPWAInstalled ? (
|
||||
<p className="mt-6 text-xs font-medium text-center text-foreground/80 dark:text-neutral-200">
|
||||
{tInstallPwaModal('AlreadyInstalled')}
|
||||
</p>
|
||||
) : isIOSDevice ? (
|
||||
<div className="mt-5 rounded-3xl bg-black/5 px-4 py-5 backdrop-blur-sm dark:bg-white/5">
|
||||
<p className="text-xs font-medium leading-relaxed text-center text-foreground/80 dark:text-neutral-200">
|
||||
{tInstallPwaModal('IOSDescription')}
|
||||
</p>
|
||||
<ol className="mt-5 space-y-3 text-xs font-medium rtl:text-right">
|
||||
<li className="flex items-start gap-2">
|
||||
<span className="mt-0.5 flex h-5 w-5 items-center justify-center rounded-full bg-primary/10 text-[11px] font-bold text-primary">
|
||||
۱
|
||||
</span>
|
||||
<span>{tInstallPwaModal('IOSStep1')}</span>
|
||||
</li>
|
||||
<li className="flex items-start gap-2">
|
||||
<span className="mt-0.5 flex h-5 w-5 items-center justify-center rounded-full bg-primary/10 text-[11px] font-bold text-primary">
|
||||
۲
|
||||
</span>
|
||||
<span>{tInstallPwaModal('IOSStep2')}</span>
|
||||
</li>
|
||||
<li className="flex items-start gap-2">
|
||||
<span className="mt-0.5 flex h-5 w-5 items-center justify-center rounded-full bg-primary/10 text-[11px] font-bold text-primary">
|
||||
۳
|
||||
</span>
|
||||
<span>{tInstallPwaModal('IOSStep3')}</span>
|
||||
</li>
|
||||
</ol>
|
||||
</div>
|
||||
) : (
|
||||
<>
|
||||
<p className="mt-6 text-xs font-medium leading-relaxed text-center text-foreground/80 dark:text-neutral-200">
|
||||
{tInstallPwaModal('Description')}
|
||||
</p>
|
||||
{deferredPrompt ? (
|
||||
<Button onClick={handleInstallPWA} className="mt-8 text-sm">
|
||||
<span className="font-light">{tInstallPwaModal('ButtonOk')}</span>
|
||||
</Button>
|
||||
) : (
|
||||
<p className="mt-4 text-[11px] font-medium leading-relaxed text-center text-foreground/60 dark:text-neutral-300">
|
||||
{tInstallPwaModal('ChromeFallback')}
|
||||
</p>
|
||||
)}
|
||||
</>
|
||||
)}
|
||||
|
||||
</Modal>
|
||||
</>
|
||||
|
||||
@@ -50,8 +50,14 @@
|
||||
},
|
||||
"InstallPwaModal": {
|
||||
"Heading": "نصب اپلیکیشن",
|
||||
"Description": "برای نصب کلیک کنید.",
|
||||
"ButtonOk": "نصب کن"
|
||||
"Description": "برای نصب اپلیکیشن روی دستگاه خود، از دکمه زیر استفاده کنید.",
|
||||
"ButtonOk": "نصب کن",
|
||||
"AlreadyInstalled": "اپلیکیشن قبلاً روی دستگاه شما نصب شده است.",
|
||||
"IOSDescription": "برای نصب اپلیکیشن در Safari مراحل زیر را انجام دهید:",
|
||||
"IOSStep1": "از نوار پایین، روی دکمه اشتراکگذاری (Share) بزنید.",
|
||||
"IOSStep2": "در منوی باز شده، گزینه «Add to Home Screen» را انتخاب کنید.",
|
||||
"IOSStep3": "در صفحه بعدی روی دکمه «Add» در گوشه بالا بزنید.",
|
||||
"ChromeFallback": "اگر دکمه نصب را نمیبینید، یا اپلیکیشن قبلاً نصب شده است یا مرورگر هنوز امکان نصب را فعال نکرده است. کمی بعد دوباره تلاش کنید یا از منوی مرورگر گزینه نصب در صفحه اصلی را انتخاب کنید."
|
||||
},
|
||||
"SearchPlaceholder": "جستجو"
|
||||
}
|
||||
Reference in New Issue
Block a user