diff --git a/src/app/[slug]/page.tsx b/src/app/[slug]/page.tsx
index 4f7a822..28c60ba 100644
--- a/src/app/[slug]/page.tsx
+++ b/src/app/[slug]/page.tsx
@@ -11,6 +11,7 @@ import RoomHeader from '@/components/room/RoomHeader';
import ShareModal from '@/components/room/ShareModal';
import MeetingPointModal from '@/components/room/MeetingPointModal';
import WaypointModal from '@/components/room/WaypointModal';
+import InstallBanner from '@/components/room/InstallBanner';
import type { Participant, ParticipantLocation, Waypoint } from '@/types';
// Dynamic import for map to avoid SSR issues with MapLibre
@@ -242,11 +243,17 @@ export default function RoomPage() {
};
}, [leave]);
- // Navigate to participant
+ // Navigate to participant - opens Google Maps navigation
const handleNavigateTo = (participant: Participant) => {
- setSelectedParticipant(participant);
- // TODO: Implement navigation route display
- console.log('Navigate to:', participant.name);
+ if (!participant.location) {
+ console.log('No location for participant:', participant.name);
+ return;
+ }
+ const { latitude, longitude } = participant.location;
+ window.open(
+ `https://www.google.com/maps/dir/?api=1&destination=${latitude},${longitude}`,
+ '_blank'
+ );
};
// Loading state
@@ -283,6 +290,9 @@ export default function RoomPage() {
return (
+ {/* PWA Install Banner */}
+
+
{/* Header */}
{
+ setDismissed(true);
+ sessionStorage.setItem('rmaps_install_dismissed', 'true');
+ };
+
+ const handleInstall = async () => {
+ if (isIOS) {
+ setShowIOSInstructions(true);
+ } else {
+ const success = await promptInstall();
+ if (success) {
+ handleDismiss();
+ }
+ }
+ };
+
+ return (
+ <>
+
+
+ 📲
+ Install rMaps for the best experience
+
+
+
+
+
+
+
+ {/* iOS Instructions Modal */}
+ {showIOSInstructions && (
+
+
setShowIOSInstructions(false)} />
+
+
Install on iOS
+
+ -
+ 1.
+ Tap the Share button in Safari
+
+ -
+ 2.
+ Scroll down and tap "Add to Home Screen"
+
+ -
+ 3.
+ Tap "Add" in the top right
+
+
+
+
+
+ )}
+ >
+ );
+}
diff --git a/src/hooks/usePWAInstall.ts b/src/hooks/usePWAInstall.ts
new file mode 100644
index 0000000..a65b483
--- /dev/null
+++ b/src/hooks/usePWAInstall.ts
@@ -0,0 +1,78 @@
+'use client';
+
+import { useState, useEffect, useCallback } from 'react';
+
+interface BeforeInstallPromptEvent extends Event {
+ prompt(): Promise
;
+ userChoice: Promise<{ outcome: 'accepted' | 'dismissed' }>;
+}
+
+export function usePWAInstall() {
+ const [installPrompt, setInstallPrompt] = useState(null);
+ const [isInstallable, setIsInstallable] = useState(false);
+ const [isInstalled, setIsInstalled] = useState(false);
+
+ useEffect(() => {
+ // Check if already installed (standalone mode)
+ if (window.matchMedia('(display-mode: standalone)').matches) {
+ setIsInstalled(true);
+ return;
+ }
+
+ // Check iOS standalone
+ if ((navigator as any).standalone === true) {
+ setIsInstalled(true);
+ return;
+ }
+
+ const handleBeforeInstall = (e: Event) => {
+ e.preventDefault();
+ setInstallPrompt(e as BeforeInstallPromptEvent);
+ setIsInstallable(true);
+ };
+
+ const handleAppInstalled = () => {
+ setIsInstalled(true);
+ setIsInstallable(false);
+ setInstallPrompt(null);
+ };
+
+ window.addEventListener('beforeinstallprompt', handleBeforeInstall);
+ window.addEventListener('appinstalled', handleAppInstalled);
+
+ return () => {
+ window.removeEventListener('beforeinstallprompt', handleBeforeInstall);
+ window.removeEventListener('appinstalled', handleAppInstalled);
+ };
+ }, []);
+
+ const promptInstall = useCallback(async () => {
+ if (!installPrompt) return false;
+
+ try {
+ await installPrompt.prompt();
+ const result = await installPrompt.userChoice;
+
+ if (result.outcome === 'accepted') {
+ setIsInstalled(true);
+ setIsInstallable(false);
+ setInstallPrompt(null);
+ return true;
+ }
+ } catch (error) {
+ console.error('Install prompt error:', error);
+ }
+ return false;
+ }, [installPrompt]);
+
+ const isIOS = typeof navigator !== 'undefined' &&
+ /iPad|iPhone|iPod/.test(navigator.userAgent) &&
+ !(window as any).MSStream;
+
+ return {
+ isInstallable,
+ isInstalled,
+ isIOS,
+ promptInstall,
+ };
+}