diff --git a/css/styles.css b/css/styles.css
index 53c4ded..d0772d7 100644
--- a/css/styles.css
+++ b/css/styles.css
@@ -453,7 +453,7 @@ input[type="file"] {
}
.action-button {
- background-color: #6c757d;
+ background-color: #3498db;
color: white;
border: none;
padding: 0.5rem 1rem;
@@ -463,7 +463,20 @@ input[type="file"] {
}
.action-button:hover {
- background-color: #5a6268;
+ background-color: #2980b9;
+}
+
+button:disabled {
+ background-color: #cccccc !important; /* Gray background */
+ color: #888888 !important; /* Darker gray text */
+ cursor: not-allowed !important; /* Change cursor */
+ opacity: 0.7 !important; /* Reduce opacity */
+}
+
+.cancel-button:disabled {
+ background-color: #e0e0e0 !important; /* Light gray */
+ color: #999999 !important;
+ border: 1px solid #cccccc !important;
}
.message-output {
diff --git a/index.html b/index.html
index bc22c89..f20efe9 100644
--- a/index.html
+++ b/index.html
@@ -137,7 +137,7 @@
@@ -147,8 +147,7 @@
-
-
+
Monitoring for service worker messages...
@@ -221,7 +220,7 @@
}
const webhookUrl = `${backendUrl}/webhook/${action}`;
- output.textContent = `Sending request to: ${webhookUrl}\n\nHeaders:\n`;
+ output.textContent = `Sending request to: ${webhookUrl}\n`;
output.textContent += `Authorization: Basic ****\n`;
output.textContent += `Button-Name: ${buttonName}\n`;
output.textContent += `Timestamp: ${timestamp}\n`;
diff --git a/js b/js
deleted file mode 120000
index 1fb06d7..0000000
--- a/js
+++ /dev/null
@@ -1 +0,0 @@
-src/js
\ No newline at end of file
diff --git a/src/js/app.js b/js/app.js
similarity index 100%
rename from src/js/app.js
rename to js/app.js
diff --git a/src/js/config.js b/js/config.js
similarity index 100%
rename from src/js/config.js
rename to js/config.js
diff --git a/src/js/core/eventHandlers.js b/js/core/eventHandlers.js
similarity index 100%
rename from src/js/core/eventHandlers.js
rename to js/core/eventHandlers.js
diff --git a/src/js/core/gameActions.js b/js/core/gameActions.js
similarity index 100%
rename from src/js/core/gameActions.js
rename to js/core/gameActions.js
diff --git a/src/js/core/playerManager.js b/js/core/playerManager.js
similarity index 100%
rename from src/js/core/playerManager.js
rename to js/core/playerManager.js
diff --git a/src/js/core/state.js b/js/core/state.js
similarity index 100%
rename from src/js/core/state.js
rename to js/core/state.js
diff --git a/src/js/core/timer.js b/js/core/timer.js
similarity index 100%
rename from src/js/core/timer.js
rename to js/core/timer.js
diff --git a/src/js/env-loader.js b/js/env-loader.js
similarity index 100%
rename from src/js/env-loader.js
rename to js/env-loader.js
diff --git a/src/js/services/pushFlicIntegration.js b/js/services/pushFlicIntegration.js
similarity index 82%
rename from src/js/services/pushFlicIntegration.js
rename to js/services/pushFlicIntegration.js
index a46aba2..d2c5074 100644
--- a/src/js/services/pushFlicIntegration.js
+++ b/js/services/pushFlicIntegration.js
@@ -90,26 +90,16 @@ async function subscribeToPush() {
console.log('Notification permission granted.');
- // IMPORTANT: Force checking for credentials - even with an existing subscription
- // Always allow the user to set/update credentials
+ // Get stored credentials but don't prompt
let credentials = getBasicAuthCredentials();
const hasExistingCreds = !!credentials;
console.log('Has existing credentials:', hasExistingCreds);
- // Ask for credentials every time unless one exists
+ // No prompting for credentials - user must enter them manually in the UI
if (!credentials) {
- const confirmAuth = confirm('Do you want to set up credentials for push notifications now?');
- if (!confirmAuth) {
- console.log('User declined to provide auth credentials.');
- return;
- }
-
- credentials = promptForCredentials();
- if (!credentials) {
- console.log('User canceled credential input.');
- alert('Authentication required to set up push notifications.');
- return;
- }
+ console.log('No credentials found. User needs to enter them manually.');
+ // Just return if no credentials are available
+ return;
}
const registration = await navigator.serviceWorker.ready;
@@ -167,20 +157,8 @@ async function sendSubscriptionToServer(subscription, buttonId) {
console.log(`Sending subscription for button "${buttonId}" to backend...`);
const credentials = getBasicAuthCredentials();
if (!credentials) {
- // One more chance to enter credentials if needed
- const confirmAuth = confirm('Authentication required to complete setup. Provide credentials now?');
- if (!confirmAuth) {
- alert('Authentication required to save button link.');
- return;
- }
-
- const newCredentials = promptForCredentials();
- if (!newCredentials) {
- alert('Authentication required to save button link.');
- return;
- }
-
- credentials = newCredentials;
+ console.log('No credentials found. User needs to enter them manually.');
+ return;
}
const headers = { 'Content-Type': 'application/json' };
@@ -199,7 +177,7 @@ async function sendSubscriptionToServer(subscription, buttonId) {
if (response.ok) {
const result = await response.json();
console.log('Subscription sent successfully:', result.message);
- alert('Push notification setup completed successfully!');
+ // Success alert removed as requested
} else {
let errorMsg = `Server error: ${response.status}`;
if (response.status === 401 || response.status === 403) {
@@ -289,9 +267,48 @@ export function setupPushNotifications() {
// Function to force re-authentication even if credentials exist
export function forceCredentialsPrompt() {
- // Remove existing credentials to force new ones
- localStorage.removeItem('basicAuthCredentials');
- console.log('[PushFlic] Removed stored credentials, will prompt on next subscription attempt');
- // Trigger the subscription process again
+ // Get credentials from the form fields if available
+ const usernameField = document.getElementById('pushUsername');
+ const passwordField = document.getElementById('pushPassword');
+
+ let credentialsUpdated = false;
+
+ if (usernameField && passwordField && usernameField.value.trim() && passwordField.value.trim()) {
+ // Save the entered credentials to localStorage
+ const credentials = {
+ username: usernameField.value.trim(),
+ password: passwordField.value.trim()
+ };
+ localStorage.setItem('basicAuthCredentials', JSON.stringify(credentials));
+ console.log('[PushFlic] Saved credentials from form fields');
+ credentialsUpdated = true;
+ } else {
+ // Check if we have stored credentials
+ try {
+ const storedAuth = localStorage.getItem('basicAuthCredentials');
+ if (storedAuth) {
+ const credentials = JSON.parse(storedAuth);
+ if (credentials.username && credentials.password) {
+ // We have stored credentials, no need to update
+ console.log('[PushFlic] Using stored credentials');
+ credentialsUpdated = true;
+
+ // Update the form fields if they exist
+ if (usernameField && passwordField) {
+ usernameField.value = credentials.username;
+ passwordField.value = credentials.password;
+ }
+ }
+ }
+ } catch (error) {
+ console.error('[PushFlic] Error accessing stored credentials:', error);
+ }
+ }
+
+ if (!credentialsUpdated) {
+ console.log('[PushFlic] No valid credentials available');
+ }
+
+ // Trigger the subscription process
setupPushNotifications();
}
\ No newline at end of file
diff --git a/src/js/services/serviceWorkerManager.js b/js/services/serviceWorkerManager.js
similarity index 96%
rename from src/js/services/serviceWorkerManager.js
rename to js/services/serviceWorkerManager.js
index 7b9b549..0eb30b5 100644
--- a/src/js/services/serviceWorkerManager.js
+++ b/js/services/serviceWorkerManager.js
@@ -10,10 +10,8 @@ export function setFlicActionHandlers(handlers) {
flicActionHandlers = handlers;
console.log('[ServiceWorkerManager] Stored action handlers:', Object.keys(flicActionHandlers));
- // If pushFlic is already initialized, update its handlers directly
- if (navigator.serviceWorker.controller) {
- pushFlic.initPushFlic(flicActionHandlers);
- }
+ // Always pass handlers to pushFlic, regardless of service worker state
+ pushFlic.initPushFlic(flicActionHandlers);
} else {
console.warn('[ServiceWorkerManager] No action handlers provided to setFlicActionHandlers!');
}
diff --git a/src/js/ui/audio.js b/js/ui/audio.js
similarity index 100%
rename from src/js/ui/audio.js
rename to js/ui/audio.js
diff --git a/src/js/ui/camera.js b/js/ui/camera.js
similarity index 100%
rename from src/js/ui/camera.js
rename to js/ui/camera.js
diff --git a/src/js/ui/pushSettingsUI.js b/js/ui/pushSettingsUI.js
similarity index 59%
rename from src/js/ui/pushSettingsUI.js
rename to js/ui/pushSettingsUI.js
index b50de67..e131f6c 100644
--- a/src/js/ui/pushSettingsUI.js
+++ b/js/ui/pushSettingsUI.js
@@ -15,8 +15,8 @@ const elements = {
pushUnsubscribeButton: null,
pushResubscribeButton: null,
// Message monitor elements
- clearMessagesButton: null,
- swMessagesOutput: null
+ swMessagesOutput: null,
+ simulateClickButton: null
};
// --- State ---
@@ -39,8 +39,8 @@ export function initPushSettingsUI() {
elements.pushResubscribeButton = document.getElementById('pushResubscribeButton');
// Message Monitor elements
- elements.clearMessagesButton = document.getElementById('clearMessagesButton');
elements.swMessagesOutput = document.getElementById('swMessagesOutput');
+ elements.simulateClickButton = document.getElementById('simulateClickButton');
// Set up event listeners
elements.pushSettingsButton.addEventListener('click', openPushSettingsModal);
@@ -48,9 +48,6 @@ 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();
@@ -122,18 +119,14 @@ function stopMessageMonitoring() {
}
}
-// 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)) {
elements.notificationPermissionStatus.textContent = 'Not Supported';
elements.notificationPermissionStatus.className = 'status-denied';
+ // Disable subscribe button when notifications are not supported
+ elements.pushResubscribeButton.disabled = true;
+ elements.pushResubscribeButton.classList.add('disabled');
return;
}
@@ -143,12 +136,21 @@ function updateNotificationStatus() {
switch (permission) {
case 'granted':
elements.notificationPermissionStatus.className = 'status-granted';
+ // Enable subscribe button when permission is granted
+ elements.pushResubscribeButton.disabled = false;
+ elements.pushResubscribeButton.classList.remove('disabled');
break;
case 'denied':
elements.notificationPermissionStatus.className = 'status-denied';
+ // Disable subscribe button when permission is denied
+ elements.pushResubscribeButton.disabled = true;
+ elements.pushResubscribeButton.classList.add('disabled');
break;
default:
elements.notificationPermissionStatus.className = 'status-default';
+ // Enable subscribe button for default state (prompt)
+ elements.pushResubscribeButton.disabled = false;
+ elements.pushResubscribeButton.classList.remove('disabled');
}
}
@@ -157,6 +159,14 @@ async function updateSubscriptionStatus() {
if (!('serviceWorker' in navigator) || !('PushManager' in window)) {
elements.subscriptionStatus.textContent = 'Not Supported';
elements.subscriptionStatus.className = 'status-denied';
+ // Disable unsubscribe button when not supported
+ elements.pushUnsubscribeButton.disabled = true;
+ // Set subscribe button text
+ elements.pushResubscribeButton.textContent = 'Subscribe';
+ // Disable simulate button when not supported
+ if (elements.simulateClickButton) {
+ elements.simulateClickButton.disabled = true;
+ }
return;
}
@@ -167,14 +177,38 @@ async function updateSubscriptionStatus() {
if (currentSubscription) {
elements.subscriptionStatus.textContent = 'active';
elements.subscriptionStatus.className = 'status-active';
+ // Enable unsubscribe button when subscription is active
+ elements.pushUnsubscribeButton.disabled = false;
+ // Change subscribe button text to "Re-subscribe"
+ elements.pushResubscribeButton.textContent = 'Re-subscribe';
+ // Enable simulate button when subscription is active
+ if (elements.simulateClickButton) {
+ elements.simulateClickButton.disabled = false;
+ }
} else {
elements.subscriptionStatus.textContent = 'Not Subscribed';
elements.subscriptionStatus.className = 'status-inactive';
+ // Disable unsubscribe button when not subscribed
+ elements.pushUnsubscribeButton.disabled = true;
+ // Set subscribe button text
+ elements.pushResubscribeButton.textContent = 'Subscribe';
+ // Disable simulate button when not subscribed
+ if (elements.simulateClickButton) {
+ elements.simulateClickButton.disabled = true;
+ }
}
} catch (error) {
console.error('Error checking subscription status:', error);
elements.subscriptionStatus.textContent = 'Error';
elements.subscriptionStatus.className = 'status-denied';
+ // Disable unsubscribe button on error
+ elements.pushUnsubscribeButton.disabled = true;
+ // Set subscribe button text
+ elements.pushResubscribeButton.textContent = 'Subscribe';
+ // Disable simulate button on error
+ if (elements.simulateClickButton) {
+ elements.simulateClickButton.disabled = true;
+ }
}
}
@@ -196,7 +230,7 @@ function loadSavedCredentials() {
// --- Action Functions ---
-// Save credentials and subscribe to push notifications
+// Save credentials and close the modal
async function saveCredentialsAndSubscribe() {
const username = elements.pushUsername.value.trim();
const password = elements.pushPassword.value.trim();
@@ -210,26 +244,6 @@ async function saveCredentialsAndSubscribe() {
const credentials = { username, password };
localStorage.setItem('basicAuthCredentials', JSON.stringify(credentials));
- // Request notification permission if needed
- if (Notification.permission !== 'granted') {
- const permission = await Notification.requestPermission();
- if (permission !== 'granted') {
- alert('Notification permission is required for push notifications');
- updateNotificationStatus();
- return;
- }
- }
-
- // Subscribe using the service worker
- try {
- await setupPushNotifications();
- await updateSubscriptionStatus();
- alert('Subscription successful!');
- } catch (error) {
- console.error('Subscription error:', error);
- alert(`Error subscribing: ${error.message}`);
- }
-
// Close the modal
closePushSettingsModal();
}
@@ -244,22 +258,78 @@ async function unsubscribeFromPush() {
try {
await currentSubscription.unsubscribe();
await updateSubscriptionStatus();
- alert('Successfully unsubscribed from push notifications');
+ // No success alert
} catch (error) {
console.error('Error unsubscribing:', error);
alert(`Error unsubscribing: ${error.message}`);
}
}
-// Force resubscription to push notifications
+// Force subscription to push notifications
async function resubscribeToPush() {
try {
- // Force credential prompt and resubscribe
+ let username = elements.pushUsername.value.trim();
+ let password = elements.pushPassword.value.trim();
+
+ // If fields are empty, try to use stored credentials
+ if (!username || !password) {
+ try {
+ const storedAuth = localStorage.getItem('basicAuthCredentials');
+ if (storedAuth) {
+ const credentials = JSON.parse(storedAuth);
+ if (credentials.username && credentials.password) {
+ username = credentials.username;
+ password = credentials.password;
+
+ // Update the form fields with stored values
+ elements.pushUsername.value = username;
+ elements.pushPassword.value = password;
+ }
+ }
+ } catch (error) {
+ console.error('Error loading stored credentials:', error);
+ }
+ }
+
+ // Use the credentials to subscribe
await forceCredentialsPrompt();
- await updateSubscriptionStatus();
+
+ // Wait a moment for the subscription to complete
+ await new Promise(resolve => setTimeout(resolve, 500));
+
+ // Get the updated subscription
+ const registration = await navigator.serviceWorker.ready;
+ currentSubscription = await registration.pushManager.getSubscription();
+
+ // Update the UI directly
+ if (currentSubscription && elements.subscriptionStatus) {
+ elements.subscriptionStatus.textContent = 'active';
+ elements.subscriptionStatus.className = 'status-active';
+ // Enable unsubscribe button when subscription is active
+ elements.pushUnsubscribeButton.disabled = false;
+ // Change subscribe button text to "Re-subscribe"
+ elements.pushResubscribeButton.textContent = 'Re-subscribe';
+ // Enable simulate button when subscription is active
+ if (elements.simulateClickButton) {
+ elements.simulateClickButton.disabled = false;
+ }
+ } else {
+ // Disable unsubscribe button when not subscribed
+ elements.pushUnsubscribeButton.disabled = true;
+ // Set subscribe button text
+ elements.pushResubscribeButton.textContent = 'Subscribe';
+ // Disable simulate button when not subscribed
+ if (elements.simulateClickButton) {
+ elements.simulateClickButton.disabled = true;
+ }
+ // Fall back to the standard update function
+ await updateSubscriptionStatus();
+
+ alert('Subscription failed. Please check your credentials and try again.');
+ }
} catch (error) {
- console.error('Error resubscribing:', error);
- alert(`Error resubscribing: ${error.message}`);
+ console.error('Error subscribing:', error);
+ alert(`Error subscribing: ${error.message}`);
}
}
@@ -268,7 +338,7 @@ export async function sendSubscriptionToServer() {
if (!currentSubscription) {
await updateSubscriptionStatus();
if (!currentSubscription) {
- alert('No active subscription available. Please subscribe first.');
+ // No alert, just return silently
return;
}
}
@@ -286,7 +356,7 @@ export async function sendSubscriptionToServer() {
throw new Error('No stored credentials');
}
} catch (error) {
- alert('No valid credentials found. Please set them up first.');
+ // No alert, just open the modal to let the user set credentials
openPushSettingsModal();
return;
}
@@ -307,7 +377,8 @@ export async function sendSubscriptionToServer() {
const configModule = await import('../config.js');
backendUrl = configModule.BACKEND_URL;
} catch (error) {
- alert('Could not get backend URL from config.');
+ // No alert, just log the error and return
+ console.error('Could not get backend URL from config:', error);
return;
}
@@ -325,7 +396,25 @@ export async function sendSubscriptionToServer() {
if (response.ok) {
const result = await response.json();
- alert(`Subscription sent successfully: ${result.message || 'OK'}`);
+ // No success alert
+
+ // Update the currentSubscription variable
+ const registration = await navigator.serviceWorker.ready;
+ currentSubscription = await registration.pushManager.getSubscription();
+
+ // Directly update the subscription status element in the DOM
+ if (currentSubscription && elements.subscriptionStatus) {
+ elements.subscriptionStatus.textContent = 'active';
+ elements.subscriptionStatus.className = 'status-active';
+ // Enable unsubscribe button when subscription is active
+ elements.pushUnsubscribeButton.disabled = false;
+ // Change subscribe button text to "Re-subscribe"
+ elements.pushResubscribeButton.textContent = 'Re-subscribe';
+ // Enable simulate button when subscription is active
+ if (elements.simulateClickButton) {
+ elements.simulateClickButton.disabled = false;
+ }
+ }
} else {
let errorMsg = `Server error: ${response.status}`;
if (response.status === 401 || response.status === 403) {
@@ -337,14 +426,11 @@ export async function sendSubscriptionToServer() {
errorMsg = errorData.message || errorMsg;
} catch (e) { /* use default */ }
}
- alert(`Failed to send subscription: ${errorMsg}`);
+ // No error alert, just log the error
+ console.error(`Failed to send subscription: ${errorMsg}`);
}
} catch (error) {
- alert(`Network error: ${error.message}`);
+ // No error alert, just log the error
+ console.error(`Network error: ${error.message}`);
}
}
-
-// --- Cleanup on page unload ---
-window.addEventListener('unload', function() {
- stopMessageMonitoring();
-});
\ No newline at end of file
diff --git a/src/js/ui/ui.js b/js/ui/ui.js
similarity index 100%
rename from src/js/ui/ui.js
rename to js/ui/ui.js
diff --git a/sw.js b/sw.js
index 0ae5458..959b49e 100644
--- a/sw.js
+++ b/sw.js
@@ -163,7 +163,7 @@ self.addEventListener('push', event => {
});
return Promise.all(sendPromises).then(() => {
- // Remove battery notification logic - don't show any notifications
+ // No notifications will be shown for any action, including low battery
return Promise.resolve();
});
})
@@ -178,7 +178,7 @@ self.addEventListener('message', event => {
return;
}
- // Remove the battery timestamp handling
+ // No battery-related handling
});
// This helps with navigation after app is installed