@ -1177,6 +1177,16 @@
let ws = null;
let ws = null;
let userId = null;
let userId = null;
let otherUsers = new Map();
let otherUsers = new Map();
// Notification cooldown tracking
let notificationCooldowns = {
nearbyCache: {}, // cacheId -> lastNotificationTime
destinationArrival: 0 // lastNotificationTime
};
const CACHE_COOLDOWN = 10 * 60 * 1000; // 10 minutes
const CACHE_NOTIFY_DISTANCE = 200; // meters
const CACHE_RESET_DISTANCE = 200; // meters to reset cooldown
const DESTINATION_ARRIVAL_DISTANCE = 10; // meters
let wsReconnectTimer = null;
let wsReconnectTimer = null;
let myIcon = null;
let myIcon = null;
let myColor = null;
let myColor = null;
@ -1407,6 +1417,9 @@
// Send location to other users with visibility info
// Send location to other users with visibility info
sendLocationToServer(lat, lng, accuracy, isNearTrack);
sendLocationToServer(lat, lng, accuracy, isNearTrack);
// Check for notification triggers
checkLocationNotifications(lat, lng);
// Check geocache proximity
// Check geocache proximity
checkGeocacheProximity();
checkGeocacheProximity();
@ -2540,8 +2553,28 @@
if (data.geocache) {
if (data.geocache) {
const existingIndex = geocaches.findIndex(g => g.id === data.geocache.id);
const existingIndex = geocaches.findIndex(g => g.id === data.geocache.id);
if (existingIndex >= 0) {
if (existingIndex >= 0) {
// Check if this is a new message from another user
const oldCache = geocaches[existingIndex];
const newMessagesCount = data.geocache.messages.length - oldCache.messages.length;
// Update existing geocache
// Update existing geocache
geocaches[existingIndex] = data.geocache;
geocaches[existingIndex] = data.geocache;
// Send notification if new message added by another user and we're nearby
if (newMessagesCount > 0 & & userLocation) {
const distance = L.latLng(userLocation.lat, userLocation.lng)
.distanceTo(L.latLng(data.geocache.lat, data.geocache.lng));
if (distance < = CACHE_NOTIFY_DISTANCE) {
const latestMessage = data.geocache.messages[data.geocache.messages.length - 1];
sendPushNotification(
'💬 New Cache Message',
`${latestMessage.name}: ${latestMessage.text.substring(0, 50)}...`,
'cacheMessage'
);
}
}
// Refresh dialog if it's open for this geocache
// Refresh dialog if it's open for this geocache
if (currentGeocache & & currentGeocache.id === data.geocache.id) {
if (currentGeocache & & currentGeocache.id === data.geocache.id) {
showGeocacheDialog(data.geocache);
showGeocacheDialog(data.geocache);
@ -2620,6 +2653,83 @@
}
}
}
}
async function checkLocationNotifications(lat, lng) {
if (!pushSubscription) return; // No push notifications enabled
const now = Date.now();
const userPos = L.latLng(lat, lng);
// 1. Check for nearby geocaches
geocaches.forEach(cache => {
if (!cache || !cache.lat || !cache.lng) return;
const cachePos = L.latLng(cache.lat, cache.lng);
const distance = userPos.distanceTo(cachePos);
// Check if we should notify about this cache
const lastNotified = notificationCooldowns.nearbyCache[cache.id] || 0;
const timeSinceNotification = now - lastNotified;
if (distance < = CACHE_NOTIFY_DISTANCE) {
// Within notification distance
if (timeSinceNotification > CACHE_COOLDOWN || lastNotified === 0) {
// Send notification
sendPushNotification(
'📍 Geocache Nearby!',
`"${cache.title}" is ${Math.round(distance)}m away`,
'nearbyCache'
);
notificationCooldowns.nearbyCache[cache.id] = now;
}
} else if (distance > CACHE_RESET_DISTANCE & & lastNotified > 0) {
// Reset cooldown if we've moved far enough away
delete notificationCooldowns.nearbyCache[cache.id];
}
});
// 2. Check for destination arrival (only in nav mode)
if (navMode & & destinationPin) {
const destPos = destinationPin.getLatLng();
const distance = userPos.distanceTo(destPos);
if (distance < = DESTINATION_ARRIVAL_DISTANCE) {
const timeSinceNotification = now - notificationCooldowns.destinationArrival;
if (timeSinceNotification > 60000) { // 1 minute cooldown for arrival
sendPushNotification(
'🎯 Destination Reached!',
'You have arrived at your destination',
'destinationArrival'
);
notificationCooldowns.destinationArrival = now;
}
}
}
}
async function sendPushNotification(title, body, type) {
try {
// Send to server to trigger push notification
const response = await fetch('/send-notification', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({
title: title,
body: body,
type: type,
userId: userId // Send to self
})
});
if (!response.ok) {
console.error('Failed to send push notification');
}
} catch (error) {
console.error('Error sending push notification:', error);
}
}
function updateOtherUser(userId, lat, lng, accuracy, icon, color) {
function updateOtherUser(userId, lat, lng, accuracy, icon, color) {
let userMarker = otherUsers.get(userId);
let userMarker = otherUsers.get(userId);