60 lines
2.2 KiB
TypeScript
60 lines
2.2 KiB
TypeScript
import { useEffect, useState } from 'react'
|
|
import { Box, Paper, Group, Text, ActionIcon } from '@mantine/core'
|
|
import { DownloadIcon, XIcon } from '@phosphor-icons/react'
|
|
|
|
export function IOSInstallPrompt() {
|
|
const [show, setShow] = useState(false)
|
|
const [platform, setPlatform] = useState<'ios' | 'android' | null>(null)
|
|
|
|
useEffect(() => {
|
|
const isIOS = /iPad|iPhone|iPod/.test(navigator.userAgent)
|
|
const isAndroid = /Android/.test(navigator.userAgent)
|
|
|
|
const isInStandaloneMode =
|
|
window.matchMedia('(display-mode: standalone)').matches ||
|
|
('standalone' in window.navigator && (window.navigator as any).standalone)
|
|
|
|
const hasBeenDismissed = localStorage.getItem('pwa-install-prompt-dismissed') === 'true'
|
|
|
|
if ((isIOS || isAndroid) && !isInStandaloneMode && !hasBeenDismissed) {
|
|
setPlatform(isIOS ? 'ios' : 'android')
|
|
const timer = setTimeout(() => setShow(true), 3000)
|
|
return () => clearTimeout(timer)
|
|
}
|
|
}, [])
|
|
|
|
const handleDismiss = () => {
|
|
localStorage.setItem('pwa-install-prompt-dismissed', 'true')
|
|
setShow(false)
|
|
}
|
|
|
|
if (!show || !platform) return null
|
|
|
|
const instructions = platform === 'ios'
|
|
? 'Tap Share → Add to Home Screen'
|
|
: 'Tap Menu (⋮) → Add to Home screen'
|
|
|
|
return (
|
|
<Box style={{ position: 'fixed', bottom: 0, left: 0, right: 0, zIndex: 1000, padding: '8px' }}>
|
|
<Paper shadow="lg" p="sm" style={{ background: 'var(--mantine-color-blue-9)', color: 'white' }}>
|
|
<Group justify="space-between" wrap="nowrap">
|
|
<Group gap="xs" wrap="nowrap" style={{ flex: 1 }}>
|
|
<DownloadIcon size={20} style={{ flexShrink: 0 }} />
|
|
<Box style={{ flex: 1, minWidth: 0 }}>
|
|
<Text size="sm" fw={500} style={{ lineHeight: 1.3 }}>
|
|
Please install FLXN • This will save me Twilio credits as you won't be signed out!
|
|
</Text>
|
|
<Text size="xs" opacity={0.9} style={{ lineHeight: 1.2 }}>
|
|
{instructions}
|
|
</Text>
|
|
</Box>
|
|
</Group>
|
|
<ActionIcon variant="subtle" color="white" onClick={handleDismiss}>
|
|
<XIcon size={18} />
|
|
</ActionIcon>
|
|
</Group>
|
|
</Paper>
|
|
</Box>
|
|
)
|
|
}
|