limit notifications for low battery
This commit is contained in:
@@ -4,6 +4,61 @@ import { getPublicVapidKey, BACKEND_URL, FLIC_BUTTON_ID, FLIC_ACTIONS, FLIC_BATT
|
|||||||
let pushSubscription = null; // Keep track locally if needed
|
let pushSubscription = null; // Keep track locally if needed
|
||||||
let actionHandlers = {}; // Store handlers for different Flic actions
|
let actionHandlers = {}; // Store handlers for different Flic actions
|
||||||
let lastBatteryWarningTimestamp = 0; // Track when last battery warning was shown
|
let lastBatteryWarningTimestamp = 0; // Track when last battery warning was shown
|
||||||
|
const BATTERY_WARNING_STORAGE_KEY = 'last-battery-warning-timestamp';
|
||||||
|
|
||||||
|
// On initialization, try to load timestamp from localStorage
|
||||||
|
try {
|
||||||
|
const storedTimestamp = localStorage.getItem(BATTERY_WARNING_STORAGE_KEY);
|
||||||
|
if (storedTimestamp) {
|
||||||
|
lastBatteryWarningTimestamp = parseInt(storedTimestamp, 10);
|
||||||
|
console.log('[PushFlic] Loaded battery warning timestamp from localStorage:', new Date(lastBatteryWarningTimestamp));
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error('[PushFlic] Error loading timestamp from localStorage:', error);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Also try to get timestamp from service worker
|
||||||
|
function syncTimestampWithServiceWorker() {
|
||||||
|
if ('serviceWorker' in navigator && navigator.serviceWorker.controller) {
|
||||||
|
// First, register for battery timestamp messages
|
||||||
|
navigator.serviceWorker.addEventListener('message', event => {
|
||||||
|
if (event.data && event.data.type === 'battery-timestamp') {
|
||||||
|
const swTimestamp = event.data.timestamp;
|
||||||
|
console.log('[PushFlic] Received timestamp from SW:', new Date(swTimestamp));
|
||||||
|
|
||||||
|
// Use the most recent timestamp (either from SW or local)
|
||||||
|
if (swTimestamp > lastBatteryWarningTimestamp) {
|
||||||
|
lastBatteryWarningTimestamp = swTimestamp;
|
||||||
|
saveTimestampToLocalStorage(swTimestamp);
|
||||||
|
} else if (lastBatteryWarningTimestamp > swTimestamp) {
|
||||||
|
// Update the service worker with our more recent timestamp
|
||||||
|
navigator.serviceWorker.controller.postMessage({
|
||||||
|
type: 'update-battery-timestamp',
|
||||||
|
timestamp: lastBatteryWarningTimestamp
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Ask service worker for its timestamp
|
||||||
|
navigator.serviceWorker.controller.postMessage({
|
||||||
|
type: 'get-battery-timestamp'
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Call this on init
|
||||||
|
setTimeout(syncTimestampWithServiceWorker, 1000);
|
||||||
|
|
||||||
|
// Save timestamp to localStorage
|
||||||
|
function saveTimestampToLocalStorage(timestamp) {
|
||||||
|
try {
|
||||||
|
localStorage.setItem(BATTERY_WARNING_STORAGE_KEY, timestamp.toString());
|
||||||
|
console.log('[PushFlic] Saved timestamp to localStorage:', new Date(timestamp));
|
||||||
|
} catch (error) {
|
||||||
|
console.error('[PushFlic] Error saving timestamp to localStorage:', error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// --- Helper Functions ---
|
// --- Helper Functions ---
|
||||||
|
|
||||||
@@ -79,8 +134,20 @@ function showBatteryWarning(batteryLevel) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Update timestamp
|
||||||
lastBatteryWarningTimestamp = now;
|
lastBatteryWarningTimestamp = now;
|
||||||
|
|
||||||
|
// Save to localStorage
|
||||||
|
saveTimestampToLocalStorage(now);
|
||||||
|
|
||||||
|
// Also update service worker
|
||||||
|
if ('serviceWorker' in navigator && navigator.serviceWorker.controller) {
|
||||||
|
navigator.serviceWorker.controller.postMessage({
|
||||||
|
type: 'update-battery-timestamp',
|
||||||
|
timestamp: now
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
// Show the notification
|
// Show the notification
|
||||||
console.log(`[PushFlic] Low battery detected: ${batteryLevel}%`);
|
console.log(`[PushFlic] Low battery detected: ${batteryLevel}%`);
|
||||||
|
|
||||||
@@ -328,6 +395,9 @@ export function initPushFlic(handlers) {
|
|||||||
console.warn('[PushFlic] No action handlers provided to initPushFlic, actions will not work!');
|
console.warn('[PushFlic] No action handlers provided to initPushFlic, actions will not work!');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Sync battery timestamp with service worker
|
||||||
|
syncTimestampWithServiceWorker();
|
||||||
|
|
||||||
// Auto-subscribe when permission is granted
|
// Auto-subscribe when permission is granted
|
||||||
if ('serviceWorker' in navigator) {
|
if ('serviceWorker' in navigator) {
|
||||||
navigator.serviceWorker.ready.then(registration => {
|
navigator.serviceWorker.ready.then(registration => {
|
||||||
|
|||||||
115
sw.js
115
sw.js
@@ -2,6 +2,56 @@
|
|||||||
const CACHE_VERSION = 'v1.0.2';
|
const CACHE_VERSION = 'v1.0.2';
|
||||||
const CACHE_NAME = `game-timer-${CACHE_VERSION}`;
|
const CACHE_NAME = `game-timer-${CACHE_VERSION}`;
|
||||||
|
|
||||||
|
// Store last battery warning timestamp to prevent repeated notifications
|
||||||
|
let lastBatteryWarningTimestamp = 0;
|
||||||
|
const FOUR_HOURS_MS = 4 * 60 * 60 * 1000; // 4 hours in milliseconds
|
||||||
|
|
||||||
|
// Settings cache for storing timestamps
|
||||||
|
const SETTINGS_CACHE = 'settings-cache-v1';
|
||||||
|
const TIMESTAMP_URL = new Request('/_timestamp/battery-warning');
|
||||||
|
|
||||||
|
// Function to load the timestamp from cache
|
||||||
|
async function loadTimestamp() {
|
||||||
|
try {
|
||||||
|
const cache = await caches.open(SETTINGS_CACHE);
|
||||||
|
const response = await cache.match(TIMESTAMP_URL);
|
||||||
|
|
||||||
|
if (response) {
|
||||||
|
const data = await response.json();
|
||||||
|
lastBatteryWarningTimestamp = data.timestamp;
|
||||||
|
console.log('[ServiceWorker] Loaded battery warning timestamp:', new Date(lastBatteryWarningTimestamp));
|
||||||
|
} else {
|
||||||
|
console.log('[ServiceWorker] No saved timestamp found');
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
} catch (error) {
|
||||||
|
console.error('[ServiceWorker] Error loading timestamp:', error);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Function to save the timestamp to cache
|
||||||
|
async function saveTimestamp(timestamp) {
|
||||||
|
try {
|
||||||
|
const cache = await caches.open(SETTINGS_CACHE);
|
||||||
|
const response = new Response(JSON.stringify({ timestamp }), {
|
||||||
|
headers: { 'Content-Type': 'application/json' }
|
||||||
|
});
|
||||||
|
|
||||||
|
await cache.put(TIMESTAMP_URL, response);
|
||||||
|
console.log('[ServiceWorker] Saved battery warning timestamp:', new Date(timestamp));
|
||||||
|
return true;
|
||||||
|
} catch (error) {
|
||||||
|
console.error('[ServiceWorker] Error saving timestamp:', error);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Initialize and load data when the service worker starts
|
||||||
|
loadTimestamp().then(success => {
|
||||||
|
console.log('[ServiceWorker] Timestamp loading ' + (success ? 'successful' : 'failed'));
|
||||||
|
});
|
||||||
|
|
||||||
// Files to cache
|
// Files to cache
|
||||||
const CACHE_FILES = [
|
const CACHE_FILES = [
|
||||||
'/',
|
'/',
|
||||||
@@ -136,14 +186,32 @@ self.addEventListener('push', event => {
|
|||||||
console.log('[ServiceWorker] Preparing message payload:', messagePayload);
|
console.log('[ServiceWorker] Preparing message payload:', messagePayload);
|
||||||
|
|
||||||
// Check if this is a low battery alert that needs a notification
|
// Check if this is a low battery alert that needs a notification
|
||||||
const isBatteryAlert = messagePayload.batteryLevel !== undefined &&
|
const batteryLevel = messagePayload.batteryLevel;
|
||||||
messagePayload.batteryLevel < 50; // Use the same threshold as in the app
|
const isBatteryLow = batteryLevel !== undefined && batteryLevel < 50; // Use the same threshold as in the app
|
||||||
|
|
||||||
|
// Determine if we should show a battery notification (throttle to once every 4 hours)
|
||||||
|
let shouldShowBatteryNotification = false;
|
||||||
|
|
||||||
|
if (isBatteryLow) {
|
||||||
|
const now = Date.now();
|
||||||
|
if (now - lastBatteryWarningTimestamp > FOUR_HOURS_MS) {
|
||||||
|
// It's been more than 4 hours since the last battery notification
|
||||||
|
console.log(`[ServiceWorker] Low battery (${batteryLevel}%) - showing notification`);
|
||||||
|
lastBatteryWarningTimestamp = now;
|
||||||
|
|
||||||
|
// Save the timestamp to cache
|
||||||
|
saveTimestamp(now).catch(error => {
|
||||||
|
console.warn('[ServiceWorker] Failed to save battery warning timestamp:', error);
|
||||||
|
});
|
||||||
|
|
||||||
|
shouldShowBatteryNotification = true;
|
||||||
|
|
||||||
if (isBatteryAlert) {
|
|
||||||
console.log(`[ServiceWorker] Low battery alert detected: ${messagePayload.batteryLevel}%`);
|
|
||||||
// Change notification title/body for battery alerts
|
// Change notification title/body for battery alerts
|
||||||
pushData.title = 'Flic Button Low Battery';
|
pushData.title = 'Flic Button Low Battery';
|
||||||
pushData.body = `Battery level is ${messagePayload.batteryLevel}%. Please replace batteries soon.`;
|
pushData.body = `Battery level is ${batteryLevel}%. Please replace batteries soon.`;
|
||||||
|
} else {
|
||||||
|
console.log(`[ServiceWorker] Low battery (${batteryLevel}%) - suppressing notification (shown recently)`);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Send message to all open PWA windows controlled by this SW
|
// Send message to all open PWA windows controlled by this SW
|
||||||
@@ -154,8 +222,8 @@ self.addEventListener('push', event => {
|
|||||||
}).then(clientList => {
|
}).then(clientList => {
|
||||||
if (!clientList || clientList.length === 0) {
|
if (!clientList || clientList.length === 0) {
|
||||||
console.log('[ServiceWorker] No client windows found to send message to.');
|
console.log('[ServiceWorker] No client windows found to send message to.');
|
||||||
// If no window is open AND this is a battery alert, show a notification
|
// If no window is open AND this is a battery alert that should be shown, show a notification
|
||||||
if (isBatteryAlert) {
|
if (shouldShowBatteryNotification) {
|
||||||
return self.registration.showNotification(pushData.title, {
|
return self.registration.showNotification(pushData.title, {
|
||||||
body: pushData.body,
|
body: pushData.body,
|
||||||
icon: '/icons/android-chrome-192x192.png', // Updated path
|
icon: '/icons/android-chrome-192x192.png', // Updated path
|
||||||
@@ -184,21 +252,48 @@ self.addEventListener('push', event => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
return Promise.all(sendPromises).then(() => {
|
return Promise.all(sendPromises).then(() => {
|
||||||
// Only show a notification if this is a battery alert
|
// Only show a notification if this is a battery alert that should be shown
|
||||||
if (isBatteryAlert) {
|
if (shouldShowBatteryNotification) {
|
||||||
return self.registration.showNotification(pushData.title, {
|
return self.registration.showNotification(pushData.title, {
|
||||||
body: pushData.body,
|
body: pushData.body,
|
||||||
icon: '/icons/android-chrome-192x192.png',
|
icon: '/icons/android-chrome-192x192.png',
|
||||||
data: pushData.data
|
data: pushData.data
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
// For regular button presses, don't show notifications
|
// For regular button presses or throttled battery alerts, don't show notifications
|
||||||
return Promise.resolve();
|
return Promise.resolve();
|
||||||
});
|
});
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Listen for messages from client
|
||||||
|
self.addEventListener('message', event => {
|
||||||
|
const message = event.data;
|
||||||
|
|
||||||
|
if (!message || typeof message !== 'object') {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Handle get timestamp request
|
||||||
|
if (message.type === 'get-battery-timestamp') {
|
||||||
|
console.log('[ServiceWorker] Client requested battery warning timestamp');
|
||||||
|
event.source.postMessage({
|
||||||
|
type: 'battery-timestamp',
|
||||||
|
timestamp: lastBatteryWarningTimestamp
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// Handle update timestamp request
|
||||||
|
if (message.type === 'update-battery-timestamp' && message.timestamp) {
|
||||||
|
console.log('[ServiceWorker] Updating battery warning timestamp to:', new Date(message.timestamp));
|
||||||
|
lastBatteryWarningTimestamp = message.timestamp;
|
||||||
|
saveTimestamp(message.timestamp).catch(error => {
|
||||||
|
console.warn('[ServiceWorker] Failed to save updated battery warning timestamp:', error);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
// This helps with navigation after app is installed
|
// This helps with navigation after app is installed
|
||||||
self.addEventListener('notificationclick', event => {
|
self.addEventListener('notificationclick', event => {
|
||||||
console.log('[ServiceWorker] Notification click received');
|
console.log('[ServiceWorker] Notification click received');
|
||||||
|
|||||||
Reference in New Issue
Block a user