PWA auto-opens last room + visible ping notifications
1. Installed PWA (standalone mode) auto-redirects to last visited room on launch instead of showing the landing page. Uses localStorage rmaps_last_room + display-mode: standalone media query. 2. Manual pings now show visible feedback in three ways: - In-app toast: green banner "Alice pinged you for your location!" - Browser notification: fires Notification API when permission granted - Vibration: unchanged [200, 100, 200, 100, 400] pattern Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
a1132371f4
commit
53dd95fcac
|
|
@ -48,6 +48,7 @@ export default function RoomPage() {
|
|||
const [zoomToLocation, setZoomToLocation] = useState<{ latitude: number; longitude: number } | null>(null);
|
||||
const [needsJoin, setNeedsJoin] = useState(false);
|
||||
const [pendingManualPing, setPendingManualPing] = useState(false);
|
||||
const [pingToast, setPingToast] = useState<string | null>(null);
|
||||
|
||||
// Check if opened from a manual ping notification (e.g. ?ping=manual&pinger=Alice)
|
||||
const [pingCallerName, setPingCallerName] = useState<string | undefined>(undefined);
|
||||
|
|
@ -154,7 +155,27 @@ export default function RoomPage() {
|
|||
|
||||
// Handle manual ping: vibrate device + one-shot GPS regardless of sharing state
|
||||
const handleManualPing = useCallback((callerName?: string) => {
|
||||
console.log(`Manual ping from ${callerName || 'unknown'} — vibrating and sending GPS`);
|
||||
const pinger = callerName || 'Someone';
|
||||
console.log(`Manual ping from ${pinger} — vibrating and sending GPS`);
|
||||
|
||||
// Show in-app toast
|
||||
setPingToast(`📍 ${pinger} pinged you for your location!`);
|
||||
setTimeout(() => setPingToast(null), 4000);
|
||||
|
||||
// Show browser notification (works even when tab is backgrounded)
|
||||
if (typeof Notification !== 'undefined' && Notification.permission === 'granted') {
|
||||
try {
|
||||
new Notification(`📍 ${pinger} pinged you!`, {
|
||||
body: 'Sharing your location now...',
|
||||
icon: '/icon-192.png',
|
||||
tag: 'manual-ping',
|
||||
silent: true, // vibration handles the alert
|
||||
});
|
||||
} catch {
|
||||
// Ignore notification errors (e.g. in standalone PWA)
|
||||
}
|
||||
}
|
||||
|
||||
if (typeof navigator !== 'undefined' && 'vibrate' in navigator) {
|
||||
navigator.vibrate([200, 100, 200, 100, 400]);
|
||||
}
|
||||
|
|
@ -496,6 +517,13 @@ export default function RoomPage() {
|
|||
</div>
|
||||
)}
|
||||
|
||||
{/* Ping toast notification */}
|
||||
{pingToast && (
|
||||
<div className="absolute top-4 left-1/2 -translate-x-1/2 bg-emerald-500/90 text-white text-sm px-4 py-2 rounded-full z-30 shadow-lg animate-pulse">
|
||||
{pingToast}
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* Connection status indicator */}
|
||||
{!isConnected && (
|
||||
<div className="absolute top-4 left-1/2 -translate-x-1/2 bg-yellow-500/90 text-black text-sm px-3 py-1.5 rounded-full z-30">
|
||||
|
|
|
|||
|
|
@ -27,6 +27,7 @@ export default function HomePage() {
|
|||
const [lastRoom, setLastRoom] = useState<string | null>(null);
|
||||
|
||||
// Load saved user info from localStorage on mount
|
||||
// If opened as installed PWA (standalone mode), auto-redirect to last room
|
||||
useEffect(() => {
|
||||
let loadedEmoji = '';
|
||||
try {
|
||||
|
|
@ -43,6 +44,14 @@ export default function HomePage() {
|
|||
const lastVisited = localStorage.getItem('rmaps_last_room');
|
||||
if (lastVisited) {
|
||||
setLastRoom(lastVisited);
|
||||
|
||||
// Auto-redirect if running as installed PWA and user has saved info
|
||||
const isStandalone = window.matchMedia('(display-mode: standalone)').matches
|
||||
|| (navigator as unknown as { standalone?: boolean }).standalone === true;
|
||||
if (isStandalone && stored) {
|
||||
router.push(`/${lastVisited}`);
|
||||
return;
|
||||
}
|
||||
}
|
||||
} catch {
|
||||
// Ignore parse errors
|
||||
|
|
@ -52,7 +61,7 @@ export default function HomePage() {
|
|||
setEmoji(EMOJI_OPTIONS[Math.floor(Math.random() * EMOJI_OPTIONS.length)]);
|
||||
}
|
||||
setIsLoaded(true);
|
||||
}, []);
|
||||
}, [router]);
|
||||
|
||||
// Auto-fill name from EncryptID when authenticated
|
||||
useEffect(() => {
|
||||
|
|
|
|||
Loading…
Reference in New Issue