From be4436cae8cd67f8cc8b0b7d0199a06611092acb Mon Sep 17 00:00:00 2001 From: zaidmukaddam Date: Sat, 21 Dec 2024 11:54:21 +0530 Subject: [PATCH] feat: enhance install prompt with platform detection and animations --- .gitignore | 3 +- components/InstallPrompt.tsx | 153 ++++++++++++++++++++++++++++------- 2 files changed, 128 insertions(+), 28 deletions(-) diff --git a/.gitignore b/.gitignore index 4ef342b..9b1572b 100644 --- a/.gitignore +++ b/.gitignore @@ -35,4 +35,5 @@ yarn-error.log* *.tsbuildinfo next-env.d.ts -e2b.toml \ No newline at end of file +e2b.toml +certificates \ No newline at end of file diff --git a/components/InstallPrompt.tsx b/components/InstallPrompt.tsx index 3931eef..802356a 100644 --- a/components/InstallPrompt.tsx +++ b/components/InstallPrompt.tsx @@ -1,40 +1,139 @@ import { useEffect, useState } from 'react'; +import { motion, AnimatePresence } from 'framer-motion'; +import { X, Share, Plus, Download } from 'lucide-react'; +import { Button } from '@/components/ui/button'; +import { Card } from '@/components/ui/card'; export function InstallPrompt() { - const [isIOS, setIsIOS] = useState(false); - const [isStandalone, setIsStandalone] = useState(false); + const [showPrompt, setShowPrompt] = useState(false); + const [platform, setPlatform] = useState<'ios' | 'android' | 'chrome' | 'other'>('other'); + const [deferredPrompt, setDeferredPrompt] = useState(null); useEffect(() => { - setIsIOS( - /iPad|iPhone|iPod/.test(navigator.userAgent) && !(window as any).MSStream - ); + const isDismissed = localStorage.getItem('installPromptDismissed'); + if (isDismissed) return; - setIsStandalone(window.matchMedia('(display-mode: standalone)').matches); + // Detect platform + const userAgent = navigator.userAgent.toLowerCase(); + const isIOSDevice = /ipad|iphone|ipod/.test(userAgent) && !(window as any).MSStream; + const isAndroid = /android/.test(userAgent); + const isChrome = /chrome/.test(userAgent) && /google inc/.test(navigator.vendor.toLowerCase()); + + if (isIOSDevice) setPlatform('ios'); + else if (isAndroid) setPlatform('android'); + else if (isChrome) setPlatform('chrome'); + + // Don't show if already installed + if (window.matchMedia('(display-mode: standalone)').matches) return; + + // Handle PWA install prompt + window.addEventListener('beforeinstallprompt', (e) => { + e.preventDefault(); + setDeferredPrompt(e); + setShowPrompt(true); + }); + + // Show prompt for iOS after delay + if (isIOSDevice) { + setTimeout(() => setShowPrompt(true), 2000); + } }, []); - if (isStandalone) { - return null; - } + const handleDismiss = () => { + setShowPrompt(false); + localStorage.setItem('installPromptDismissed', 'true'); + }; + + const handleInstall = async () => { + if (!deferredPrompt) return; + + try { + await deferredPrompt.prompt(); + const choiceResult = await deferredPrompt.userChoice; + + if (choiceResult.outcome === 'accepted') { + setShowPrompt(false); + setDeferredPrompt(null); + } + } catch (error) { + console.error('Install prompt error:', error); + } + }; + + const getInstructions = () => { + switch (platform) { + case 'ios': + return ( +

+ Tap and then{" "} + + “Add to Home Screen” + +

+ ); + case 'android': + return ( +

+ Tap the menu and select “Install app” +

+ ); + default: + return ( +

+ Install our app for a better experience +

+ ); + } + }; return ( -
-

Install App

- - {isIOS && ( -

- To install this app on your iOS device, tap the share button - - {' '} - ⎋{' '} - - and then "Add to Home Screen" - - {' '} - ➕{' '} - - . -

+ + {showPrompt && ( + + +
+
+

+ Install MiniPerplx +

+ {getInstructions()} +
+ +
+ + {platform !== 'ios' && ( +
+ + +
+ )} +
+
)} -
+ ); }