updated Push notification settings

This commit is contained in:
cpu
2025-03-30 19:54:02 +02:00
parent eb427d7fdd
commit ab356eb150
6 changed files with 253 additions and 274 deletions

View File

@@ -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

View File

@@ -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
}
});
});

View File

@@ -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() {
@@ -32,6 +37,10 @@ export function initPushSettingsUI() {
elements.pushCancelButton = document.getElementById('pushCancelButton');
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);
@@ -39,6 +48,9 @@ export function initPushSettingsUI() {
elements.pushSaveButton.addEventListener('click', saveCredentialsAndSubscribe);
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';
@@ -277,4 +342,9 @@ export async function sendSubscriptionToServer() {
} catch (error) {
alert(`Network error: ${error.message}`);
}
}
}
// --- Cleanup on page unload ---
window.addEventListener('unload', function() {
stopMessageMonitoring();
});