Ensure offline users vibrate and auto-respond to manual pings
Three fixes for offline ping gaps: 1. SW silent push fallback: when a manual ping arrives as a silent push but no app window is open, show a visible notification with vibration instead of failing silently. 2. SW notificationclick: when opening a fresh window (app was closed), append ?ping=manual to the URL so the app can detect it was pinged. 3. page.tsx: on mount, detect ?ping=manual param, clean it from the URL, and auto-fire GPS once the WebSocket connection is established. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
8fd4ed22f9
commit
c3f884d2c4
22
public/sw.js
22
public/sw.js
|
|
@ -346,8 +346,24 @@ self.addEventListener('push', (event) => {
|
|||
const isManual = !!(data.data?.manual);
|
||||
|
||||
event.waitUntil(
|
||||
requestLocationFromClient(isManual).then((sent) => {
|
||||
requestLocationFromClient(isManual).then(async (sent) => {
|
||||
console.log('[SW] Push location request sent:', sent, 'manual:', isManual);
|
||||
// If no app window is open and this is a manual ping, show a visible notification
|
||||
// so the user can tap to open the app and auto-respond with location
|
||||
if (!sent && isManual) {
|
||||
await self.registration.showNotification('📍 Someone is looking for you!', {
|
||||
body: 'Tap to share your location',
|
||||
icon: '/icon-192.png',
|
||||
badge: '/icon-192.png',
|
||||
tag: `callout-${data.data?.roomSlug || 'unknown'}`,
|
||||
data: { type: 'callout', roomSlug: data.data?.roomSlug, manual: true },
|
||||
vibrate: [200, 100, 200, 100, 400],
|
||||
requireInteraction: true,
|
||||
actions: [{ action: 'view', title: 'Open Map' }],
|
||||
renotify: true,
|
||||
silent: false,
|
||||
});
|
||||
}
|
||||
})
|
||||
);
|
||||
return;
|
||||
|
|
@ -418,7 +434,9 @@ self.addEventListener('notificationclick', (event) => {
|
|||
}
|
||||
}
|
||||
if (clients.openWindow) {
|
||||
return clients.openWindow(targetUrl);
|
||||
// If manual ping, append ?ping=manual so the app auto-responds with GPS on load
|
||||
const openUrl = data.manual ? `${targetUrl}?ping=manual` : targetUrl;
|
||||
return clients.openWindow(openUrl);
|
||||
}
|
||||
})
|
||||
);
|
||||
|
|
|
|||
|
|
@ -47,6 +47,23 @@ export default function RoomPage() {
|
|||
const [shouldAutoStartSharing, setShouldAutoStartSharing] = useState(false);
|
||||
const [zoomToLocation, setZoomToLocation] = useState<{ latitude: number; longitude: number } | null>(null);
|
||||
const [needsJoin, setNeedsJoin] = useState(false);
|
||||
const [pendingManualPing, setPendingManualPing] = useState(false);
|
||||
|
||||
// Check if opened from a manual ping notification (e.g. ?ping=manual)
|
||||
useEffect(() => {
|
||||
if (typeof window !== 'undefined') {
|
||||
const params = new URLSearchParams(window.location.search);
|
||||
if (params.get('ping') === 'manual') {
|
||||
// Clean the param from URL
|
||||
params.delete('ping');
|
||||
const newUrl = params.toString()
|
||||
? `${window.location.pathname}?${params.toString()}`
|
||||
: window.location.pathname;
|
||||
window.history.replaceState({}, '', newUrl);
|
||||
setPendingManualPing(true);
|
||||
}
|
||||
}
|
||||
}, []);
|
||||
|
||||
// Load user and sharing preference from localStorage
|
||||
useEffect(() => {
|
||||
|
|
@ -207,6 +224,15 @@ export default function RoomPage() {
|
|||
}
|
||||
}, [isConnected, isPushSubscribed, subscribePush, syncUrl]);
|
||||
|
||||
// Execute pending manual ping once connected (from notification tap while app was closed)
|
||||
useEffect(() => {
|
||||
if (pendingManualPing && isConnected) {
|
||||
console.log('Executing pending manual ping from notification tap');
|
||||
setPendingManualPing(false);
|
||||
handleManualPing();
|
||||
}
|
||||
}, [pendingManualPing, isConnected, handleManualPing]);
|
||||
|
||||
// Restore last known location immediately when connected
|
||||
const hasRestoredLocationRef = useRef(false);
|
||||
useEffect(() => {
|
||||
|
|
|
|||
Loading…
Reference in New Issue