added more button actions

This commit is contained in:
cpu
2025-03-28 03:54:36 +01:00
parent 75b8dc5d15
commit 96aeb22210
2 changed files with 122 additions and 23 deletions

140
app.js
View File

@@ -12,7 +12,7 @@ let currentX = 0;
let pushSubscription = null;
const PUBLIC_VAPID_KEY = 'BKfRJXjSQmAJ452gLwlK_8scGrW6qMU1mBRp39ONtcQHkSsQgmLAaODIyGbgHyRpnDEv3HfXV1oGh3SC0fHxY0E';
const BACKEND_URL = 'https://webpush.virtonline.eu';
const BUTTON_ID = 'your_button1_serial';
const BUTTON_ID = 'game-button';
const SINGLE_CLICK = 'SingleClick';
// DOM Elements
@@ -42,6 +42,42 @@ const cameraCancelButton = document.getElementById('cameraCancelButton');
let stream = null;
// Get stored basic auth credentials or prompt user for them
function getBasicAuthCredentials() {
// Try to get stored credentials from localStorage
const storedAuth = localStorage.getItem('basicAuthCredentials');
if (storedAuth) {
try {
return JSON.parse(storedAuth);
} catch (error) {
console.error('Failed to parse stored credentials:', error);
// Fall through to prompt
}
}
// If no stored credentials, prompt the user
const username = prompt('Please enter your username for authentication:');
if (!username) return null;
const password = prompt('Please enter your password:');
if (!password) return null;
// Store the credentials for future use
const credentials = { username, password };
localStorage.setItem('basicAuthCredentials', JSON.stringify(credentials));
return credentials;
}
// Create Basic Auth header
function createBasicAuthHeader(credentials) {
if (!credentials || !credentials.username || !credentials.password) {
return null;
}
return 'Basic ' + btoa(`${credentials.username}:${credentials.password}`);
}
async function subscribeToPushNotifications() {
let buttonId = BUTTON_ID;
// 1. Validate input buttonId
@@ -125,15 +161,33 @@ async function subscribeToPushNotifications() {
}
console.log(`Sending subscription for button "${buttonId}" to backend...`);
// Get basic auth credentials
const credentials = getBasicAuthCredentials();
if (!credentials) {
console.error('Authentication credentials are required.');
alert('Authentication failed. Please try again with valid credentials.');
return;
}
// Create headers with auth
const headers = {
'Content-Type': 'application/json'
};
// Add Authorization header with Basic Auth if credentials are available
const authHeader = createBasicAuthHeader(credentials);
if (authHeader) {
headers['Authorization'] = authHeader;
}
const response = await fetch(`${BACKEND_URL}/subscribe`, {
method: 'POST',
body: JSON.stringify({
button_id: buttonId,
subscription: finalSubscription
}),
headers: {
'Content-Type': 'application/json'
}
headers: headers
});
// 9. Handle the server response
@@ -142,6 +196,13 @@ async function subscribeToPushNotifications() {
console.log('Push subscription successfully sent to server:', result.message);
} else {
let errorMessage = `Server error: ${response.status}`;
// If it's an auth error, clear stored credentials and try again
if (response.status === 401 || response.status === 403) {
localStorage.removeItem('basicAuthCredentials');
errorMessage = 'Authentication failed. Please try again with valid credentials.';
}
try {
const errorResult = await response.json();
errorMessage = errorResult.message || errorMessage;
@@ -515,30 +576,23 @@ function findNextPlayerWithTimeCircular(startIndex, direction) {
return -1; // No player has time left
}
function handleFlicAction(action, buttonId) {
console.log(`[App] Received Flic Action: ${action} from Button: ${buttonId}`);
function handleFlicAction(action, buttonId, timestamp) {
console.log(`[App] Received Flic Action: ${action} from Button: ${buttonId} at Timestamp: ${timestamp}`);
// --- Trigger your PWA action based on the 'action' string ---
switch (action) {
case 'SingleClick':
console.log('[App] Single click action...');
console.log('[App] Remotely triggered single click action...');
handleSingleClickLogic(buttonId);
break;
case 'DoubleClick':
console.log('[App] Simulating double click action...');
const elementForDoubleClick = document.getElementById('myDoubleClickTarget');
if (elementForDoubleClick) {
// You might need a specific function, double clicks are harder to simulate directly
console.log('[App] Remotely triggered double click action...');
handleDoubleClickLogic();
} else {
console.warn('[App] Element #myDoubleClickTarget not found.');
}
break;
case 'Hold':
console.log('[App] Simulating hold action...');
// Example: Call a function associated with holding
console.log('[App] Remotely triggered hold action...');
handleHoldLogic();
break;
@@ -554,8 +608,8 @@ if ('serviceWorker' in navigator) {
// Check if the message is the one we expect
if (event.data && event.data.type === 'flic-action') {
const { action, button } = event.data;
handleFlicAction(action, button);
const { action, button, timestamp } = event.data;
handleFlicAction(action, button, timestamp);
}
// Add else if blocks here for other message types if needed
});
@@ -570,7 +624,7 @@ function handleSingleClickLogic(buttonId) {
console.log(`Single Click Logic Executed from Button: ${buttonId}`);
if (buttonId === BUTTON_ID) {
moveCarousel(-1);
moveCarousel(-1); // Move to next player
}
// Reset carousel to proper position
carousel.style.transform = `translateX(${-100 * currentPlayerIndex}%)`;
@@ -580,12 +634,56 @@ function handleSingleClickLogic(buttonId) {
function handleDoubleClickLogic() {
console.log("Double Click Logic Executed!");
// Update UI, trigger different game action, etc.
if (buttonId === BUTTON_ID) {
moveCarousel(1); // Move to previous player
}
// Reset carousel to proper position
carousel.style.transform = `translateX(${-100 * currentPlayerIndex}%)`;
renderPlayers();
saveData();
}
function handleHoldLogic() {
console.log("Hold Logic Executed!");
// Update UI, show a menu, etc.
// Implement game pause/resume toggle
if (players.length < 2) {
console.log('Need at least 2 players to toggle game state.');
return;
}
// Toggle between running and paused states
switch (gameState) {
case 'setup':
// Start the game if in setup
gameState = 'running';
audioManager.play('gameStart');
startTimer();
break;
case 'running':
// Pause the game if running
gameState = 'paused';
audioManager.play('gamePause');
stopTimer();
break;
case 'paused':
// Resume the game if paused
gameState = 'running';
audioManager.play('gameResume');
startTimer();
break;
case 'over':
// Reset timers and start new game if game is over
players.forEach(player => {
player.remainingTime = player.timeInSeconds;
});
gameState = 'setup';
break;
}
updateGameButton();
renderPlayers(); // Make sure to re-render after state change
saveData();
}
// Setup button

3
sw.js
View File

@@ -184,7 +184,8 @@ self.addEventListener('push', event => {
const messagePayload = {
type: 'flic-action', // Custom message type
action: pushData.data.action, // e.g., 'SingleClick', 'DoubleClick', 'Hold'
button: pushData.data.button // e.g., the button serial
button: pushData.data.button, // e.g., the button name
timestamp: pushData.data.timestamp // e.g., the timestamp of the action
};
// Send message to all open PWA windows controlled by this SW