updated Push notification settings
This commit is contained in:
@@ -394,7 +394,20 @@ input[type="file"] {
|
||||
}
|
||||
|
||||
.advanced-options button {
|
||||
width: 48%;
|
||||
padding: 0.5rem 1rem;
|
||||
border: none;
|
||||
border-radius: 4px;
|
||||
cursor: pointer;
|
||||
flex: 1;
|
||||
margin: 0 0.5rem;
|
||||
}
|
||||
|
||||
.advanced-options button:first-child {
|
||||
margin-left: 0;
|
||||
}
|
||||
|
||||
.advanced-options button:last-child {
|
||||
margin-right: 0;
|
||||
}
|
||||
|
||||
/* Status indicators */
|
||||
@@ -422,3 +435,45 @@ input[type="file"] {
|
||||
color: #6c757d;
|
||||
font-weight: bold;
|
||||
}
|
||||
/* Service Worker Message Monitor Styles */
|
||||
.message-monitor-section {
|
||||
margin-top: 1.5rem;
|
||||
padding-top: 1rem;
|
||||
border-top: 1px solid #eee;
|
||||
}
|
||||
|
||||
.message-monitor-section h3 {
|
||||
margin-bottom: 0.5rem;
|
||||
}
|
||||
|
||||
.monitor-controls {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
margin: 0.5rem 0;
|
||||
}
|
||||
|
||||
.action-button {
|
||||
background-color: #6c757d;
|
||||
color: white;
|
||||
border: none;
|
||||
padding: 0.5rem 1rem;
|
||||
border-radius: 4px;
|
||||
cursor: pointer;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.action-button:hover {
|
||||
background-color: #5a6268;
|
||||
}
|
||||
|
||||
.message-output {
|
||||
background-color: #f8f9fa;
|
||||
border: 1px solid #dee2e6;
|
||||
border-radius: 4px;
|
||||
padding: 0.75rem;
|
||||
margin-top: 0.5rem;
|
||||
height: 150px;
|
||||
overflow-y: auto;
|
||||
font-size: 0.85rem;
|
||||
white-space: pre-wrap;
|
||||
}
|
||||
|
||||
116
index.html
116
index.html
@@ -135,14 +135,23 @@
|
||||
<label for="pushPassword">Password</label>
|
||||
<input type="password" id="pushPassword" placeholder="Enter password">
|
||||
</div>
|
||||
<div class="form-buttons">
|
||||
<button type="button" id="pushCancelButton" class="cancel-button">Cancel</button>
|
||||
<button type="button" id="pushSaveButton" class="save-button">Save & Subscribe</button>
|
||||
</div>
|
||||
<div class="advanced-options">
|
||||
<button type="button" id="pushUnsubscribeButton" class="cancel-button">Unsubscribe</button>
|
||||
<button type="button" id="pushResubscribeButton" class="save-button">Resubscribe</button>
|
||||
</div>
|
||||
<div class="form-buttons">
|
||||
<button type="button" id="pushCancelButton" class="cancel-button">Cancel</button>
|
||||
<button type="button" id="pushSaveButton" class="save-button">Save</button>
|
||||
</div>
|
||||
|
||||
<!-- Message Monitor Section - No visible title -->
|
||||
<div class="message-monitor-section">
|
||||
<div class="monitor-controls">
|
||||
<button type="button" id="simulateClickButton" class="action-button" style="margin-right: 10px;">Simulate Click</button>
|
||||
<button type="button" id="clearMessagesButton" class="action-button">Clear Messages</button>
|
||||
</div>
|
||||
<pre id="swMessagesOutput" class="message-output">Monitoring for service worker messages...</pre>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -163,6 +172,105 @@
|
||||
console.log('Notification permission:', permission);
|
||||
});
|
||||
}
|
||||
|
||||
// Helper function to get stored credentials
|
||||
async function getStoredCredentials() {
|
||||
const storedAuth = localStorage.getItem('basicAuthCredentials');
|
||||
if (!storedAuth) return null;
|
||||
|
||||
try {
|
||||
const credentials = JSON.parse(storedAuth);
|
||||
if (!credentials.username || !credentials.password) return null;
|
||||
return credentials;
|
||||
} catch (error) {
|
||||
console.error('Failed to parse stored credentials:', error);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
// Function to simulate a button click with default values
|
||||
async function simulateButtonClick() {
|
||||
const action = 'SingleClick'; // Default action
|
||||
const buttonName = 'Game-button'; // Default button name
|
||||
const batteryLevel = 100; // Default battery level
|
||||
|
||||
const output = document.getElementById('swMessagesOutput');
|
||||
// Don't show the simulating text
|
||||
|
||||
try {
|
||||
// Get credentials
|
||||
const credentials = await getStoredCredentials();
|
||||
if (!credentials) {
|
||||
output.textContent = 'No credentials found. Please set up credentials first.\n';
|
||||
return;
|
||||
}
|
||||
|
||||
// Create basic auth header
|
||||
const authHeader = 'Basic ' + btoa(`${credentials.username}:${credentials.password}`);
|
||||
|
||||
// Create timestamp (current time)
|
||||
const timestamp = new Date().toISOString();
|
||||
|
||||
// Prepare request to backend webhook
|
||||
let backendUrl;
|
||||
try {
|
||||
const configModule = await import('/js/config.js');
|
||||
backendUrl = configModule.BACKEND_URL || 'https://webpush.virtonline.eu';
|
||||
} catch (error) {
|
||||
backendUrl = 'https://webpush.virtonline.eu';
|
||||
}
|
||||
|
||||
const webhookUrl = `${backendUrl}/webhook/${action}`;
|
||||
output.textContent = `Sending request to: ${webhookUrl}\n\nHeaders:\n`;
|
||||
output.textContent += `Authorization: Basic ****\n`;
|
||||
output.textContent += `Button-Name: ${buttonName}\n`;
|
||||
output.textContent += `Timestamp: ${timestamp}\n`;
|
||||
output.textContent += `Button-Battery-Level: ${batteryLevel}\n\n`;
|
||||
|
||||
// Headers similar to the curl command
|
||||
const headers = {
|
||||
'Authorization': authHeader,
|
||||
'Button-Name': buttonName,
|
||||
'Timestamp': timestamp,
|
||||
'Button-Battery-Level': batteryLevel.toString()
|
||||
};
|
||||
|
||||
// Send GET request to webhook
|
||||
const response = await fetch(webhookUrl, {
|
||||
method: 'GET',
|
||||
headers: headers,
|
||||
credentials: 'include'
|
||||
});
|
||||
|
||||
if (response.ok) {
|
||||
let result;
|
||||
try {
|
||||
result = await response.json();
|
||||
output.textContent += `Success! Response: ${JSON.stringify(result, null, 2)}\n`;
|
||||
} catch (e) {
|
||||
// Text response
|
||||
result = await response.text();
|
||||
output.textContent += `Success! Response: ${result}\n`;
|
||||
}
|
||||
} else {
|
||||
let errorText;
|
||||
try {
|
||||
errorText = await response.text();
|
||||
} catch (e) {
|
||||
errorText = `Status ${response.status}`;
|
||||
}
|
||||
output.textContent += `Error: ${errorText}\n`;
|
||||
}
|
||||
} catch (error) {
|
||||
output.textContent += `Error: ${error.message}\n`;
|
||||
}
|
||||
}
|
||||
|
||||
// Attach click event to the new button
|
||||
const simulateClickButton = document.getElementById('simulateClickButton');
|
||||
if (simulateClickButton) {
|
||||
simulateClickButton.addEventListener('click', simulateButtonClick);
|
||||
}
|
||||
});
|
||||
</script>
|
||||
<footer class="app-footer">
|
||||
|
||||
@@ -14,7 +14,6 @@ export function getPublicVapidKey() {
|
||||
export const BACKEND_URL = getEnv('BACKEND_URL', 'https://webpush.virtonline.eu');
|
||||
export const FLIC_BUTTON_ID = 'game-button'; // Example ID, might need configuration
|
||||
export const LOCAL_STORAGE_KEY = 'gameTimerData';
|
||||
export const FLIC_BATTERY_THRESHOLD = 50; // Battery percentage threshold for low battery warning
|
||||
|
||||
// Default player settings
|
||||
export const DEFAULT_PLAYER_TIME_SECONDS = 300; // 5 minutes
|
||||
|
||||
@@ -1,64 +1,8 @@
|
||||
// pushFlicIntegration.js
|
||||
import { getPublicVapidKey, BACKEND_URL, FLIC_BUTTON_ID, FLIC_ACTIONS, FLIC_BATTERY_THRESHOLD } from '../config.js';
|
||||
import { getPublicVapidKey, BACKEND_URL, FLIC_BUTTON_ID, FLIC_ACTIONS } from '../config.js';
|
||||
|
||||
let pushSubscription = null; // Keep track locally if needed
|
||||
let actionHandlers = {}; // Store handlers for different Flic actions
|
||||
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 ---
|
||||
|
||||
@@ -123,82 +67,6 @@ function arrayBufferToBase64(buffer) {
|
||||
return window.btoa(binary).replace(/\+/g, '-').replace(/\//g, '_').replace(/=+$/, '');
|
||||
}
|
||||
|
||||
// Show a popup notification to the user
|
||||
function showBatteryWarning(batteryLevel) {
|
||||
// Only show warning once every 4 hours (to avoid annoying users)
|
||||
const now = Date.now();
|
||||
const fourHoursInMs = 4 * 60 * 60 * 1000;
|
||||
|
||||
if (now - lastBatteryWarningTimestamp < fourHoursInMs) {
|
||||
console.log(`[PushFlic] Battery warning suppressed (shown recently): ${batteryLevel}%`);
|
||||
return;
|
||||
}
|
||||
|
||||
// Update timestamp
|
||||
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
|
||||
console.log(`[PushFlic] Low battery detected: ${batteryLevel}%`);
|
||||
|
||||
// Create an alert or toast in the UI instead of a system notification
|
||||
// System notifications for battery will be handled by the service worker
|
||||
try {
|
||||
// Create a temporary toast notification in the UI
|
||||
const toast = document.createElement('div');
|
||||
toast.className = 'battery-warning-toast';
|
||||
toast.innerHTML = `
|
||||
<div class="toast-icon">⚠️</div>
|
||||
<div class="toast-message">
|
||||
<strong>Flic Button Low Battery</strong>
|
||||
<p>Battery level is ${batteryLevel}%. Please replace soon.</p>
|
||||
</div>
|
||||
`;
|
||||
|
||||
// Style the toast
|
||||
Object.assign(toast.style, {
|
||||
position: 'fixed',
|
||||
bottom: '20px',
|
||||
right: '20px',
|
||||
backgroundColor: '#ff9800',
|
||||
color: 'white',
|
||||
padding: '15px',
|
||||
borderRadius: '4px',
|
||||
boxShadow: '0 2px 5px rgba(0,0,0,0.2)',
|
||||
zIndex: '9999',
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
maxWidth: '300px'
|
||||
});
|
||||
|
||||
// Add to document
|
||||
document.body.appendChild(toast);
|
||||
|
||||
// Remove after 5 seconds
|
||||
setTimeout(() => {
|
||||
toast.style.opacity = '0';
|
||||
toast.style.transition = 'opacity 0.5s ease';
|
||||
setTimeout(() => {
|
||||
if (toast.parentNode) {
|
||||
document.body.removeChild(toast);
|
||||
}
|
||||
}, 500);
|
||||
}, 5000);
|
||||
} catch (error) {
|
||||
console.error('[PushFlic] Error showing battery warning toast:', error);
|
||||
}
|
||||
}
|
||||
|
||||
// --- Push Subscription Logic ---
|
||||
|
||||
async function subscribeToPush() {
|
||||
@@ -355,11 +223,6 @@ async function sendSubscriptionToServer(subscription, buttonId) {
|
||||
export function handleFlicAction(action, buttonId, timestamp, batteryLevel) {
|
||||
console.log(`[PushFlic] Received Action: ${action} from Button: ${buttonId} battery: ${batteryLevel}% at ${timestamp}`);
|
||||
|
||||
// Check if battery is below threshold and show warning if needed
|
||||
if (batteryLevel !== undefined && batteryLevel < FLIC_BATTERY_THRESHOLD) {
|
||||
showBatteryWarning(batteryLevel);
|
||||
}
|
||||
|
||||
// Ignore actions from buttons other than the configured one
|
||||
if (buttonId !== FLIC_BUTTON_ID) {
|
||||
console.warn(`[PushFlic] Ignoring action from unknown button: ${buttonId}`);
|
||||
@@ -395,19 +258,16 @@ export function initPushFlic(handlers) {
|
||||
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
|
||||
// No longer auto-subscribe when permission is granted
|
||||
if ('serviceWorker' in navigator) {
|
||||
navigator.serviceWorker.ready.then(registration => {
|
||||
Notification.requestPermission().then(permission => {
|
||||
if (permission === 'granted') {
|
||||
console.log('[PushFlic] Permission granted, attempting subscription.');
|
||||
subscribeToPush();
|
||||
console.log('[PushFlic] Permission granted, but not automatically subscribing.');
|
||||
console.log('[PushFlic] User can subscribe through "Push notification settings" menu.');
|
||||
// subscribeToPush(); // Removed automatic subscription
|
||||
} else {
|
||||
console.log('[PushFlic] Notification permission not granted.');
|
||||
// Optionally provide a button for the user to trigger subscription later
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
@@ -13,11 +13,16 @@ const elements = {
|
||||
pushSaveButton: null,
|
||||
pushCancelButton: null,
|
||||
pushUnsubscribeButton: null,
|
||||
pushResubscribeButton: null
|
||||
pushResubscribeButton: null,
|
||||
// Message monitor elements
|
||||
clearMessagesButton: null,
|
||||
swMessagesOutput: null
|
||||
};
|
||||
|
||||
// --- State ---
|
||||
let currentSubscription = null;
|
||||
let messageListener = null;
|
||||
let isMonitoring = false;
|
||||
|
||||
// --- Initialization ---
|
||||
export function initPushSettingsUI() {
|
||||
@@ -33,6 +38,10 @@ export function initPushSettingsUI() {
|
||||
elements.pushUnsubscribeButton = document.getElementById('pushUnsubscribeButton');
|
||||
elements.pushResubscribeButton = document.getElementById('pushResubscribeButton');
|
||||
|
||||
// Message Monitor elements
|
||||
elements.clearMessagesButton = document.getElementById('clearMessagesButton');
|
||||
elements.swMessagesOutput = document.getElementById('swMessagesOutput');
|
||||
|
||||
// Set up event listeners
|
||||
elements.pushSettingsButton.addEventListener('click', openPushSettingsModal);
|
||||
elements.pushCancelButton.addEventListener('click', closePushSettingsModal);
|
||||
@@ -40,6 +49,9 @@ export function initPushSettingsUI() {
|
||||
elements.pushUnsubscribeButton.addEventListener('click', unsubscribeFromPush);
|
||||
elements.pushResubscribeButton.addEventListener('click', resubscribeToPush);
|
||||
|
||||
// Message Monitor event listeners
|
||||
elements.clearMessagesButton.addEventListener('click', clearMessages);
|
||||
|
||||
// Initial status check
|
||||
updateNotificationStatus();
|
||||
}
|
||||
@@ -55,15 +67,68 @@ function openPushSettingsModal() {
|
||||
// Load saved credentials if available
|
||||
loadSavedCredentials();
|
||||
|
||||
// Start monitoring automatically when modal opens
|
||||
startMessageMonitoring();
|
||||
|
||||
// Show the modal
|
||||
elements.pushSettingsModal.classList.add('active');
|
||||
}
|
||||
|
||||
// Close the push settings modal
|
||||
function closePushSettingsModal() {
|
||||
// Stop monitoring when the modal is closed to avoid unnecessary processing
|
||||
stopMessageMonitoring();
|
||||
elements.pushSettingsModal.classList.remove('active');
|
||||
}
|
||||
|
||||
// --- Message Monitor Functions ---
|
||||
|
||||
// Start monitoring service worker messages
|
||||
function startMessageMonitoring() {
|
||||
// If already monitoring, don't set up a new listener
|
||||
if (isMonitoring) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!('serviceWorker' in navigator)) {
|
||||
elements.swMessagesOutput.textContent = 'Service Worker not supported in this browser.';
|
||||
return;
|
||||
}
|
||||
|
||||
// Reset the output area
|
||||
elements.swMessagesOutput.textContent = 'Monitoring for service worker messages...';
|
||||
|
||||
// Create and register the message listener
|
||||
messageListener = function(event) {
|
||||
const now = new Date().toISOString();
|
||||
const formattedMessage = `[${now}] Message received: \n${JSON.stringify(event.data, null, 2)}\n\n`;
|
||||
elements.swMessagesOutput.textContent += formattedMessage;
|
||||
|
||||
// Auto-scroll to the bottom
|
||||
elements.swMessagesOutput.scrollTop = elements.swMessagesOutput.scrollHeight;
|
||||
};
|
||||
|
||||
// Add the listener
|
||||
navigator.serviceWorker.addEventListener('message', messageListener);
|
||||
isMonitoring = true;
|
||||
}
|
||||
|
||||
// Stop monitoring service worker messages
|
||||
function stopMessageMonitoring() {
|
||||
if (messageListener) {
|
||||
navigator.serviceWorker.removeEventListener('message', messageListener);
|
||||
messageListener = null;
|
||||
isMonitoring = false;
|
||||
}
|
||||
}
|
||||
|
||||
// Clear the messages output
|
||||
function clearMessages() {
|
||||
if (elements.swMessagesOutput) {
|
||||
elements.swMessagesOutput.textContent = 'Monitoring for service worker messages...';
|
||||
}
|
||||
}
|
||||
|
||||
// Update the notification permission status display
|
||||
function updateNotificationStatus() {
|
||||
if (!('Notification' in window)) {
|
||||
@@ -100,7 +165,7 @@ async function updateSubscriptionStatus() {
|
||||
currentSubscription = await registration.pushManager.getSubscription();
|
||||
|
||||
if (currentSubscription) {
|
||||
elements.subscriptionStatus.textContent = 'Active';
|
||||
elements.subscriptionStatus.textContent = 'active';
|
||||
elements.subscriptionStatus.className = 'status-active';
|
||||
} else {
|
||||
elements.subscriptionStatus.textContent = 'Not Subscribed';
|
||||
@@ -278,3 +343,8 @@ export async function sendSubscriptionToServer() {
|
||||
alert(`Network error: ${error.message}`);
|
||||
}
|
||||
}
|
||||
|
||||
// --- Cleanup on page unload ---
|
||||
window.addEventListener('unload', function() {
|
||||
stopMessageMonitoring();
|
||||
});
|
||||
125
sw.js
125
sw.js
@@ -2,56 +2,6 @@
|
||||
const CACHE_VERSION = 'v1.0.2';
|
||||
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
|
||||
const CACHE_FILES = [
|
||||
'/',
|
||||
@@ -156,7 +106,7 @@ self.addEventListener('push', event => {
|
||||
pushData = {
|
||||
title: parsedData.title || pushData.title,
|
||||
body: parsedData.body || pushData.body,
|
||||
data: parsedData.data || pushData.data // Expecting { action: 'SingleClick', button: 'game-button', batteryLevel: 75 }
|
||||
data: parsedData.data || pushData.data
|
||||
};
|
||||
|
||||
// Ensure all required fields are present in data
|
||||
@@ -185,52 +135,13 @@ self.addEventListener('push', event => {
|
||||
|
||||
console.log('[ServiceWorker] Preparing message payload:', messagePayload);
|
||||
|
||||
// Check if this is a low battery alert that needs a notification
|
||||
const batteryLevel = messagePayload.batteryLevel;
|
||||
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;
|
||||
|
||||
// Change notification title/body for battery alerts
|
||||
pushData.title = 'Flic Button Low Battery';
|
||||
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
|
||||
event.waitUntil(
|
||||
self.clients.matchAll({
|
||||
type: 'window', // Only target window clients
|
||||
includeUncontrolled: true // Include clients that might not be fully controlled yet
|
||||
type: 'window',
|
||||
includeUncontrolled: true
|
||||
}).then(clientList => {
|
||||
if (!clientList || clientList.length === 0) {
|
||||
console.log('[ServiceWorker] No client windows found to send message to.');
|
||||
// If no window is open AND this is a battery alert that should be shown, show a notification
|
||||
if (shouldShowBatteryNotification) {
|
||||
return self.registration.showNotification(pushData.title, {
|
||||
body: pushData.body,
|
||||
icon: '/icons/android-chrome-192x192.png', // Updated path
|
||||
data: pushData.data // Pass data if needed when notification is clicked
|
||||
});
|
||||
}
|
||||
// Otherwise, don't show notification for regular button presses
|
||||
// No clients available, just resolve
|
||||
return Promise.resolve();
|
||||
}
|
||||
|
||||
@@ -252,15 +163,7 @@ self.addEventListener('push', event => {
|
||||
});
|
||||
|
||||
return Promise.all(sendPromises).then(() => {
|
||||
// Only show a notification if this is a battery alert that should be shown
|
||||
if (shouldShowBatteryNotification) {
|
||||
return self.registration.showNotification(pushData.title, {
|
||||
body: pushData.body,
|
||||
icon: '/icons/android-chrome-192x192.png',
|
||||
data: pushData.data
|
||||
});
|
||||
}
|
||||
// For regular button presses or throttled battery alerts, don't show notifications
|
||||
// Remove battery notification logic - don't show any notifications
|
||||
return Promise.resolve();
|
||||
});
|
||||
})
|
||||
@@ -275,23 +178,7 @@ self.addEventListener('message', event => {
|
||||
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);
|
||||
});
|
||||
}
|
||||
// Remove the battery timestamp handling
|
||||
});
|
||||
|
||||
// This helps with navigation after app is installed
|
||||
|
||||
Reference in New Issue
Block a user