added unsubscribe
This commit is contained in:
164
app.js
164
app.js
@@ -42,38 +42,144 @@ const cameraCancelButton = document.getElementById('cameraCancelButton');
|
|||||||
let stream = null;
|
let stream = null;
|
||||||
|
|
||||||
async function subscribeToPushNotifications() {
|
async function subscribeToPushNotifications() {
|
||||||
if ('serviceWorker' in navigator && 'PushManager' in window) {
|
let buttonId = BUTTON_ID;
|
||||||
try {
|
// 1. Validate input buttonId
|
||||||
const registration = await navigator.serviceWorker.ready;
|
if (!buttonId || typeof buttonId !== 'string' || buttonId.trim() === '') {
|
||||||
const subscription = await registration.pushManager.subscribe({
|
console.error('Button ID is required to subscribe.');
|
||||||
userVisibleOnly: true,
|
alert('Please provide a valid Flic Button ID/Serial.');
|
||||||
applicationServerKey: urlBase64ToUint8Array(PUBLIC_VAPID_KEY)
|
return;
|
||||||
});
|
|
||||||
|
|
||||||
// Send subscription to your server
|
|
||||||
await fetch(`${BACKEND_URL}/subscribe`, {
|
|
||||||
method: 'POST',
|
|
||||||
body: JSON.stringify({
|
|
||||||
button_id: BACKEND_URL,
|
|
||||||
subscription: subscription // The PushSubscription object
|
|
||||||
}),
|
|
||||||
headers: {
|
|
||||||
'Content-Type': 'application/json'
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
pushSubscription = subscription;
|
|
||||||
console.log('Push subscription successful');
|
|
||||||
} catch (error) {
|
|
||||||
console.error('Error subscribing to push:', error);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
function urlBase64ToUint8Array(base64String) {
|
// 2. Check for browser support
|
||||||
|
if (!('serviceWorker' in navigator) || !('PushManager' in window)) {
|
||||||
|
console.error('Push Messaging is not supported');
|
||||||
|
alert('Sorry, Push Notifications are not supported by your browser.');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
// 3. Request notification permission (requires user interaction)
|
||||||
|
const permission = await Notification.requestPermission();
|
||||||
|
if (permission !== 'granted') {
|
||||||
|
console.error('Notification permission not granted.');
|
||||||
|
alert('You denied notification permission. Please enable it in browser settings if you want to link the button.');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
console.log('Notification permission granted.');
|
||||||
|
|
||||||
|
// 4. Get Service Worker registration
|
||||||
|
const registration = await navigator.serviceWorker.ready;
|
||||||
|
console.log('Service Worker is ready.');
|
||||||
|
|
||||||
|
// 5. Get existing subscription
|
||||||
|
let existingSubscription = await registration.pushManager.getSubscription();
|
||||||
|
let needsResubscribe = false;
|
||||||
|
|
||||||
|
if (existingSubscription) {
|
||||||
|
console.log('Existing subscription found.');
|
||||||
|
|
||||||
|
// 6. Compare applicationServerKeys
|
||||||
|
const existingKeyArrayBuffer = existingSubscription.options.applicationServerKey;
|
||||||
|
if (!existingKeyArrayBuffer) {
|
||||||
|
console.warn("Existing subscription doesn't have an applicationServerKey.");
|
||||||
|
needsResubscribe = true; // Treat as needing resubscription
|
||||||
|
} else {
|
||||||
|
const existingKeyBase64 = arrayBufferToBase64(existingKeyArrayBuffer);
|
||||||
|
console.log('Existing VAPID Key (Base64):', existingKeyBase64);
|
||||||
|
console.log('Current VAPID Key (Base64): ', PUBLIC_VAPID_KEY);
|
||||||
|
|
||||||
|
if (existingKeyBase64 !== PUBLIC_VAPID_KEY) {
|
||||||
|
console.log('VAPID keys DO NOT match. Unsubscribing the old one.');
|
||||||
|
await existingSubscription.unsubscribe();
|
||||||
|
console.log('Successfully unsubscribed old subscription.');
|
||||||
|
existingSubscription = null; // Clear it so we subscribe anew below
|
||||||
|
needsResubscribe = true; // Explicitly flag for clarity
|
||||||
|
} else {
|
||||||
|
console.log('VAPID keys match. No need to resubscribe.');
|
||||||
|
needsResubscribe = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
console.log('No existing subscription found.');
|
||||||
|
needsResubscribe = true; // No subscription exists, so we need one
|
||||||
|
}
|
||||||
|
|
||||||
|
// 7. Subscribe if needed (no existing sub or keys mismatched)
|
||||||
|
let finalSubscription = existingSubscription; // Use existing if keys matched
|
||||||
|
if (needsResubscribe || !finalSubscription) {
|
||||||
|
console.log('Attempting to subscribe with current VAPID key...');
|
||||||
|
const applicationServerKey = urlBase64ToUint8Array(PUBLIC_VAPID_KEY);
|
||||||
|
finalSubscription = await registration.pushManager.subscribe({
|
||||||
|
userVisibleOnly: true,
|
||||||
|
applicationServerKey: applicationServerKey
|
||||||
|
});
|
||||||
|
console.log('New push subscription obtained:', finalSubscription);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 8. Send the final subscription (new or validated existing) to your server
|
||||||
|
if (!finalSubscription) {
|
||||||
|
console.error("Failed to obtain a final subscription object.");
|
||||||
|
alert("Could not get subscription details. Please try again.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log(`Sending subscription for button "${buttonId}" to backend...`);
|
||||||
|
const response = await fetch(`${BACKEND_URL}/subscribe`, {
|
||||||
|
method: 'POST',
|
||||||
|
body: JSON.stringify({
|
||||||
|
button_id: buttonId,
|
||||||
|
subscription: finalSubscription
|
||||||
|
}),
|
||||||
|
headers: {
|
||||||
|
'Content-Type': 'application/json'
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// 9. Handle the server response
|
||||||
|
if (response.ok) {
|
||||||
|
const result = await response.json();
|
||||||
|
console.log('Push subscription successfully sent to server:', result.message);
|
||||||
|
} else {
|
||||||
|
let errorMessage = `Server error: ${response.status}`;
|
||||||
|
try {
|
||||||
|
const errorResult = await response.json();
|
||||||
|
errorMessage = errorResult.message || errorMessage;
|
||||||
|
} catch (e) {
|
||||||
|
errorMessage = response.statusText || errorMessage;
|
||||||
|
}
|
||||||
|
console.error('Failed to send push subscription to server:', errorMessage);
|
||||||
|
alert(`Failed to save notification settings on server: ${errorMessage}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Error during push subscription process:', error);
|
||||||
|
// Handle potential errors from permission request, SW registration, get/unsubscribe/subscribe, or fetch network issues
|
||||||
|
if (error.name === 'InvalidStateError') {
|
||||||
|
alert(`Subscription failed: ${error.message}. Please try again or ensure no conflicting subscriptions exist.`);
|
||||||
|
} else {
|
||||||
|
alert(`An error occurred: ${error.message}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Helper to convert ArrayBuffer to Base64 string (URL safe)
|
||||||
|
function arrayBufferToBase64(buffer) {
|
||||||
|
let binary = '';
|
||||||
|
const bytes = new Uint8Array(buffer);
|
||||||
|
const len = bytes.byteLength;
|
||||||
|
for (let i = 0; i < len; i++) {
|
||||||
|
binary += String.fromCharCode(bytes[i]);
|
||||||
|
}
|
||||||
|
return window.btoa(binary)
|
||||||
|
.replace(/\+/g, '-')
|
||||||
|
.replace(/\//g, '_')
|
||||||
|
.replace(/=+$/, ''); // Remove padding
|
||||||
|
}
|
||||||
|
|
||||||
|
function urlBase64ToUint8Array(base64String) {
|
||||||
const padding = '='.repeat((4 - base64String.length % 4) % 4);
|
const padding = '='.repeat((4 - base64String.length % 4) % 4);
|
||||||
const base64 = (base64String + padding)
|
const base64 = (base64String + padding)
|
||||||
.replace(/-/g, '+')
|
.replace(/\-/g, '+')
|
||||||
.replace(/_/g, '/');
|
.replace(/_/g, '/');
|
||||||
|
|
||||||
const rawData = window.atob(base64);
|
const rawData = window.atob(base64);
|
||||||
@@ -83,7 +189,7 @@ async function subscribeToPushNotifications() {
|
|||||||
outputArray[i] = rawData.charCodeAt(i);
|
outputArray[i] = rawData.charCodeAt(i);
|
||||||
}
|
}
|
||||||
return outputArray;
|
return outputArray;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add sound toggle button
|
// Add sound toggle button
|
||||||
const createSoundToggleButton = () => {
|
const createSoundToggleButton = () => {
|
||||||
|
|||||||
Reference in New Issue
Block a user