feat: Persist location sharing across browser sessions

- Remember location sharing preference per room
- Auto-start sharing when returning to a room
- Restore last known location immediately on page load (if < 1 hour old)
- Location updates are saved to localStorage for faster reload

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
Jeff Emmett 2025-12-28 23:47:44 +01:00
parent 912104f740
commit 6294e1de41
1 changed files with 66 additions and 7 deletions

View File

@ -31,8 +31,9 @@ export default function RoomPage() {
const [showMeetingPoint, setShowMeetingPoint] = useState(false);
const [currentUser, setCurrentUser] = useState<{ name: string; emoji: string } | null>(null);
const [selectedParticipant, setSelectedParticipant] = useState<Participant | null>(null);
const [shouldAutoStartSharing, setShouldAutoStartSharing] = useState(false);
// Load user from localStorage
// Load user and sharing preference from localStorage
useEffect(() => {
const stored = localStorage.getItem('rmaps_user');
if (stored) {
@ -40,8 +41,15 @@ export default function RoomPage() {
} else {
// Redirect to home if no user info
router.push('/');
return;
}
}, [router]);
// Check if user had location sharing enabled for this room
const sharingPref = localStorage.getItem(`rmaps_sharing_${slug}`);
if (sharingPref === 'true') {
setShouldAutoStartSharing(true);
}
}, [router, slug]);
// Room hook (only initialize when we have user info)
const {
@ -77,13 +85,24 @@ export default function RoomPage() {
updateLocationRef.current = updateLocation;
}, [updateLocation]);
// Stable callback that always uses latest refs
// Stable callback that always uses latest refs - also persists location
const handleLocationUpdate = useCallback((location: ParticipantLocation) => {
console.log('Location update received:', location.latitude, location.longitude, 'connected:', isConnectedRef.current);
if (isConnectedRef.current) {
updateLocationRef.current(location);
// Persist last known location for faster reload
try {
localStorage.setItem(`rmaps_last_location_${slug}`, JSON.stringify({
latitude: location.latitude,
longitude: location.longitude,
accuracy: location.accuracy,
timestamp: location.timestamp.toISOString(),
}));
} catch {
// Ignore storage errors
}
}, []);
}
}, [slug]);
// Location sharing hook
const {
@ -97,18 +116,58 @@ export default function RoomPage() {
highAccuracy: true,
});
// Location sharing is opt-in - user must click to start
// Handler for toggling location sharing
// Restore last known location immediately when connected
const hasRestoredLocationRef = useRef(false);
useEffect(() => {
if (isConnected && !hasRestoredLocationRef.current) {
hasRestoredLocationRef.current = true;
try {
const savedLocation = localStorage.getItem(`rmaps_last_location_${slug}`);
if (savedLocation) {
const loc = JSON.parse(savedLocation);
// Only restore if less than 1 hour old
const age = Date.now() - new Date(loc.timestamp).getTime();
if (age < 60 * 60 * 1000) {
console.log('Restoring last known location:', loc.latitude, loc.longitude);
updateLocation({
latitude: loc.latitude,
longitude: loc.longitude,
accuracy: loc.accuracy || 100,
timestamp: new Date(loc.timestamp),
source: 'gps',
});
}
}
} catch {
// Ignore restore errors
}
}
}, [isConnected, slug, updateLocation]);
// Auto-start location sharing if user had it enabled before
useEffect(() => {
if (shouldAutoStartSharing && isConnected && !isSharing) {
console.log('Auto-starting location sharing from saved preference');
startSharing();
setShouldAutoStartSharing(false); // Only auto-start once
}
}, [shouldAutoStartSharing, isConnected, isSharing, startSharing]);
// Handler for toggling location sharing - persists preference
const handleToggleSharing = useCallback(() => {
if (isSharing) {
console.log('Stopping location sharing and clearing location');
stopSharing();
clearLocation();
// Save preference
localStorage.setItem(`rmaps_sharing_${slug}`, 'false');
} else {
console.log('Starting location sharing');
startSharing();
// Save preference
localStorage.setItem(`rmaps_sharing_${slug}`, 'true');
}
}, [isSharing, startSharing, stopSharing, clearLocation]);
}, [isSharing, startSharing, stopSharing, clearLocation, slug]);
// Track if we've centered on user's location yet
const hasCenteredRef = useRef(false);