Files
hoerdle/components/InstallPrompt.tsx

133 lines
4.7 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
'use client';
import { useState, useEffect } from 'react';
export default function InstallPrompt() {
const [isIOS, setIsIOS] = useState(false);
const [isStandalone, setIsStandalone] = useState(false);
const [showPrompt, setShowPrompt] = useState(false);
const [deferredPrompt, setDeferredPrompt] = useState<any>(null);
useEffect(() => {
// Check if already in standalone mode
const isStandaloneMode = window.matchMedia('(display-mode: standalone)').matches || (window.navigator as any).standalone;
setIsStandalone(isStandaloneMode);
// Check if iOS
const userAgent = window.navigator.userAgent.toLowerCase();
const isIosDevice = /iphone|ipad|ipod/.test(userAgent);
setIsIOS(isIosDevice);
// Check if already dismissed
const isDismissed = localStorage.getItem('installPromptDismissed');
if (!isStandaloneMode && !isDismissed) {
if (isIosDevice) {
// Show prompt for iOS immediately if not dismissed
setShowPrompt(true);
} else {
// For Android/Desktop, wait for beforeinstallprompt
const handleBeforeInstallPrompt = (e: Event) => {
e.preventDefault();
setDeferredPrompt(e);
setShowPrompt(true);
};
window.addEventListener('beforeinstallprompt', handleBeforeInstallPrompt);
return () => {
window.removeEventListener('beforeinstallprompt', handleBeforeInstallPrompt);
};
}
}
}, []);
const handleInstallClick = async () => {
if (deferredPrompt) {
deferredPrompt.prompt();
const { outcome } = await deferredPrompt.userChoice;
if (outcome === 'accepted') {
setDeferredPrompt(null);
setShowPrompt(false);
}
}
};
const handleDismiss = () => {
setShowPrompt(false);
localStorage.setItem('installPromptDismissed', 'true');
};
if (!showPrompt) return null;
return (
<div style={{
position: 'fixed',
bottom: '20px',
left: '20px',
right: '20px',
background: 'rgba(255, 255, 255, 0.95)',
backdropFilter: 'blur(10px)',
padding: '1rem',
borderRadius: '1rem',
boxShadow: '0 10px 25px rgba(0,0,0,0.2)',
zIndex: 1000,
display: 'flex',
flexDirection: 'column',
gap: '0.5rem',
border: '1px solid rgba(0,0,0,0.1)',
animation: 'slideUp 0.5s ease-out'
}}>
<div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'start' }}>
<div>
<h3 style={{ fontWeight: 'bold', fontSize: '1rem', marginBottom: '0.25rem' }}>Install Hördle App</h3>
<p style={{ fontSize: '0.875rem', color: '#666' }}>
Install the app for a better experience and quick access!
</p>
</div>
<button
onClick={handleDismiss}
style={{
background: 'none',
border: 'none',
fontSize: '1.25rem',
cursor: 'pointer',
padding: '0.25rem',
color: '#999'
}}
>
×
</button>
</div>
{isIOS ? (
<div style={{ fontSize: '0.875rem', background: '#f3f4f6', padding: '0.75rem', borderRadius: '0.5rem', marginTop: '0.5rem' }}>
Tap <span style={{ fontSize: '1.2rem' }}>share</span> then "Add to Home Screen" <span style={{ fontSize: '1.2rem' }}>+</span>
</div>
) : (
<button
onClick={handleInstallClick}
style={{
background: '#4f46e5',
color: 'white',
border: 'none',
padding: '0.75rem',
borderRadius: '0.5rem',
fontWeight: 'bold',
cursor: 'pointer',
marginTop: '0.5rem'
}}
>
Install App
</button>
)}
<style jsx>{`
@keyframes slideUp {
from { transform: translateY(100%); opacity: 0; }
to { transform: translateY(0); opacity: 1; }
}
`}</style>
</div>
);
}