Spaces:
Sleeping
Sleeping
| import React, { useEffect, useState } from 'react'; | |
| import { Download, X } from 'lucide-react'; | |
| import { usePWA } from '../context/PWAContext'; | |
| const PWAInstallPrompt: React.FC = () => { | |
| const { deferredPrompt, isInstallable, isIOS, isStandalone, installApp } = usePWA(); | |
| const [showInstallPrompt, setShowInstallPrompt] = useState(false); | |
| useEffect(() => { | |
| // Show install prompt if installable and not already installed | |
| if (isInstallable && !isStandalone) { | |
| setShowInstallPrompt(true); | |
| } | |
| // For iOS, show prompt if not installed | |
| if (isIOS && !isStandalone) { | |
| setShowInstallPrompt(true); | |
| } | |
| }, [isInstallable, isStandalone, isIOS]); | |
| const handleInstallClick = async () => { | |
| if (isIOS) { | |
| // iOS doesn't support programmatic install, show instructions | |
| return; | |
| } | |
| await installApp(); | |
| setShowInstallPrompt(false); | |
| }; | |
| const handleDismiss = () => { | |
| setShowInstallPrompt(false); | |
| // Remember dismissal for 7 days | |
| localStorage.setItem('pwa-install-dismissed', Date.now().toString()); | |
| }; | |
| // Don't show if already installed | |
| if (isStandalone) { | |
| return null; | |
| } | |
| // Check if dismissed recently (within 7 days) | |
| const dismissedTime = localStorage.getItem('pwa-install-dismissed'); | |
| if (dismissedTime) { | |
| const daysSinceDismissed = (Date.now() - parseInt(dismissedTime)) / (1000 * 60 * 60 * 24); | |
| if (daysSinceDismissed < 7) { | |
| return null; | |
| } | |
| } | |
| if (!showInstallPrompt) { | |
| return null; | |
| } | |
| return ( | |
| <div className="fixed bottom-4 left-4 right-4 md:left-auto md:right-4 md:w-96 bg-white rounded-lg shadow-2xl border-2 border-teal-600 p-4 z-50 animate-slide-up"> | |
| <button | |
| onClick={handleDismiss} | |
| className="absolute top-2 right-2 text-gray-400 hover:text-gray-600" | |
| > | |
| <X size={20} /> | |
| </button> | |
| <div className="flex items-start gap-3"> | |
| <div className="p-2 bg-teal-100 rounded-lg"> | |
| <Download className="text-teal-600" size={24} /> | |
| </div> | |
| <div className="flex-1"> | |
| <h3 className="font-bold text-gray-900 mb-1">Install App</h3> | |
| {isIOS ? ( | |
| <div className="text-sm text-gray-600"> | |
| <p className="mb-2">Install this app on your iPhone:</p> | |
| <ol className="list-decimal list-inside space-y-1 text-xs"> | |
| <li>Tap the Share button <span className="inline-block">⎋</span></li> | |
| <li>Scroll and tap "Add to Home Screen"</li> | |
| <li>Tap "Add" in the top right</li> | |
| </ol> | |
| </div> | |
| ) : ( | |
| <> | |
| <p className="text-sm text-gray-600 mb-3"> | |
| Install our app for a better experience and offline access! | |
| </p> | |
| <button | |
| onClick={handleInstallClick} | |
| className="w-full bg-teal-600 text-white py-2 px-4 rounded-lg font-medium hover:bg-teal-700 transition-colors" | |
| > | |
| Install Now | |
| </button> | |
| </> | |
| )} | |
| </div> | |
| </div> | |
| </div> | |
| ); | |
| }; | |
| export default PWAInstallPrompt; | |