Kraft102's picture
fix: sql.js Docker/Alpine compatibility layer for PatternMemory and FailureMemory
5a81b95
import { useState, useEffect } from 'react';
import { Download, Check } from 'lucide-react';
import { Button } from '@/components/ui/button';
import { Link } from 'react-router-dom';
import {
Tooltip,
TooltipContent,
TooltipTrigger,
} from '@/components/ui/tooltip';
interface BeforeInstallPromptEvent extends Event {
prompt: () => Promise<void>;
userChoice: Promise<{ outcome: 'accepted' | 'dismissed' }>;
}
export function InstallButton() {
const [deferredPrompt, setDeferredPrompt] = useState<BeforeInstallPromptEvent | null>(null);
const [isInstalled, setIsInstalled] = useState(false);
const [isIOS, setIsIOS] = useState(false);
useEffect(() => {
// Check if already installed
if (window.matchMedia('(display-mode: standalone)').matches) {
setIsInstalled(true);
return;
}
// Check if iOS
setIsIOS(/iPad|iPhone|iPod/.test(navigator.userAgent));
// Listen for install prompt
const handler = (e: Event) => {
e.preventDefault();
setDeferredPrompt(e as BeforeInstallPromptEvent);
};
window.addEventListener('beforeinstallprompt', handler);
// Listen for successful install
window.addEventListener('appinstalled', () => setIsInstalled(true));
return () => {
window.removeEventListener('beforeinstallprompt', handler);
};
}, []);
const handleInstall = async () => {
if (!deferredPrompt) return;
await deferredPrompt.prompt();
const { outcome } = await deferredPrompt.userChoice;
if (outcome === 'accepted') {
setIsInstalled(true);
}
setDeferredPrompt(null);
};
// Already installed - show check mark
if (isInstalled) {
return (
<Tooltip>
<TooltipTrigger asChild>
<Button variant="ghost" size="sm" className="text-green-500" disabled>
<Check className="w-4 h-4" />
</Button>
</TooltipTrigger>
<TooltipContent>
<p>App installeret</p>
</TooltipContent>
</Tooltip>
);
}
// Can prompt directly (Chrome/Edge)
if (deferredPrompt) {
return (
<Tooltip>
<TooltipTrigger asChild>
<Button
variant="ghost"
size="sm"
onClick={handleInstall}
className="text-primary hover:text-primary hover:bg-primary/10"
>
<Download className="w-4 h-4" />
</Button>
</TooltipTrigger>
<TooltipContent>
<p>Installer app</p>
</TooltipContent>
</Tooltip>
);
}
// iOS or other - link to install page
return (
<Tooltip>
<TooltipTrigger asChild>
<Link to="/install">
<Button
variant="ghost"
size="sm"
className="text-muted-foreground hover:text-primary"
>
<Download className="w-4 h-4" />
</Button>
</Link>
</TooltipTrigger>
<TooltipContent>
<p>{isIOS ? 'Installer på iPhone' : 'Installer app'}</p>
</TooltipContent>
</Tooltip>
);
}