Diverse änderungen am Push system
This commit is contained in:
@@ -105,6 +105,7 @@
|
||||
<input type="text" id="testMessage" placeholder="Test-Nachricht" value="Das ist eine Test-Push-Notification!">
|
||||
<button onclick="sendTestPush()">Test-Push senden</button>
|
||||
<button onclick="sendTestWebNotification()">Web-Notification senden</button>
|
||||
<button onclick="sendWindowsNotification()">Windows-Notification senden</button>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
@@ -120,6 +121,22 @@
|
||||
<script>
|
||||
let currentSubscription = null;
|
||||
|
||||
// Convert VAPID key from base64url to Uint8Array
|
||||
function urlBase64ToUint8Array(base64String) {
|
||||
const padding = '='.repeat((4 - base64String.length % 4) % 4);
|
||||
const base64 = (base64String + padding)
|
||||
.replace(/\-/g, '+')
|
||||
.replace(/_/g, '/');
|
||||
|
||||
const rawData = window.atob(base64);
|
||||
const outputArray = new Uint8Array(rawData.length);
|
||||
|
||||
for (let i = 0; i < rawData.length; ++i) {
|
||||
outputArray[i] = rawData.charCodeAt(i);
|
||||
}
|
||||
return outputArray;
|
||||
}
|
||||
|
||||
function log(message, type = 'info') {
|
||||
const logDiv = document.getElementById('log');
|
||||
const timestamp = new Date().toLocaleTimeString();
|
||||
@@ -155,14 +172,19 @@
|
||||
async function registerServiceWorker() {
|
||||
if ('serviceWorker' in navigator) {
|
||||
try {
|
||||
log('Service Worker wird registriert...', 'info');
|
||||
const registration = await navigator.serviceWorker.register('/sw.js');
|
||||
log('Service Worker erfolgreich registriert', 'success');
|
||||
log(`SW Scope: ${registration.scope}`);
|
||||
updateStatus('Service Worker registriert', 'success');
|
||||
} catch (error) {
|
||||
log(`Service Worker Registrierung fehlgeschlagen: ${error.message}`, 'error');
|
||||
log(`Error Details: ${JSON.stringify(error)}`, 'error');
|
||||
updateStatus(`Service Worker Registrierung fehlgeschlagen: ${error.message}`, 'error');
|
||||
}
|
||||
} else {
|
||||
log('Service Worker nicht unterstützt', 'error');
|
||||
updateStatus('Service Worker nicht unterstützt', 'error');
|
||||
}
|
||||
}
|
||||
|
||||
@@ -189,16 +211,115 @@
|
||||
|
||||
// Push Subscription Functions
|
||||
async function subscribeToPush() {
|
||||
if (!('serviceWorker' in navigator) || !('PushManager' in window)) {
|
||||
log('Push Subscription gestartet...', 'info');
|
||||
|
||||
// Check basic requirements
|
||||
if (!('serviceWorker' in navigator)) {
|
||||
log('Service Worker nicht unterstützt', 'error');
|
||||
updateStatus('Service Worker nicht unterstützt', 'error');
|
||||
return;
|
||||
}
|
||||
|
||||
if (!('PushManager' in window)) {
|
||||
log('Push Manager nicht unterstützt', 'error');
|
||||
updateStatus('Push Manager nicht unterstützt', 'error');
|
||||
return;
|
||||
}
|
||||
|
||||
// Check notification permission first
|
||||
if (Notification.permission !== 'granted') {
|
||||
log('Notification Permission nicht erteilt. Bitte zuerst "Berechtigung anfordern" klicken!', 'error');
|
||||
updateStatus('Notification Permission erforderlich', 'error');
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
const registration = await navigator.serviceWorker.ready;
|
||||
log('Service Worker wird geladen...', 'info');
|
||||
|
||||
// First check if service worker is already registered
|
||||
let registration;
|
||||
const existingRegistrations = await navigator.serviceWorker.getRegistrations();
|
||||
|
||||
if (existingRegistrations.length > 0) {
|
||||
log('Service Worker bereits registriert, verwende bestehende...', 'info');
|
||||
registration = existingRegistrations[0];
|
||||
} else {
|
||||
log('Service Worker nicht registriert, registriere jetzt...', 'info');
|
||||
registration = await navigator.serviceWorker.register('/sw.js');
|
||||
log('Service Worker registriert', 'success');
|
||||
}
|
||||
|
||||
// Wait for service worker to be ready with timeout
|
||||
log('Warte auf Service Worker ready...', 'info');
|
||||
|
||||
// Check if service worker is active
|
||||
if (registration.active) {
|
||||
log('Service Worker ist bereits aktiv', 'success');
|
||||
} else if (registration.installing && registration.installing.state) {
|
||||
log('Service Worker wird installiert, warte...', 'info');
|
||||
await new Promise((resolve) => {
|
||||
const installingWorker = registration.installing;
|
||||
if (installingWorker) {
|
||||
installingWorker.addEventListener('statechange', () => {
|
||||
if (installingWorker.state === 'installed') {
|
||||
resolve();
|
||||
}
|
||||
});
|
||||
} else {
|
||||
resolve();
|
||||
}
|
||||
});
|
||||
log('Service Worker Installation abgeschlossen', 'success');
|
||||
} else if (registration.waiting && registration.waiting.state) {
|
||||
log('Service Worker wartet, aktiviere...', 'info');
|
||||
registration.waiting.postMessage({ type: 'SKIP_WAITING' });
|
||||
await new Promise((resolve) => {
|
||||
const waitingWorker = registration.waiting;
|
||||
if (waitingWorker) {
|
||||
waitingWorker.addEventListener('statechange', () => {
|
||||
if (waitingWorker.state === 'activated') {
|
||||
resolve();
|
||||
}
|
||||
});
|
||||
} else {
|
||||
resolve();
|
||||
}
|
||||
});
|
||||
log('Service Worker aktiviert', 'success');
|
||||
} else {
|
||||
log('Service Worker Status unbekannt, warte auf ready...', 'info');
|
||||
try {
|
||||
await navigator.serviceWorker.ready;
|
||||
log('Service Worker bereit', 'success');
|
||||
} catch (error) {
|
||||
log(`Service Worker ready fehlgeschlagen: ${error.message}`, 'error');
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
// Convert VAPID key from base64url to ArrayBuffer
|
||||
const vapidPublicKey = 'BJmNVx0C3XeVxeKGTP9c-Z4HcuZNmdk6QdiLocZgCmb-miCS0ESFO3W2TvJlRhhNAShV63pWA5p36BTVSetyTds';
|
||||
log('VAPID Key wird konvertiert...', 'info');
|
||||
|
||||
let applicationServerKey;
|
||||
try {
|
||||
applicationServerKey = urlBase64ToUint8Array(vapidPublicKey);
|
||||
log('VAPID Key konvertiert', 'success');
|
||||
} catch (error) {
|
||||
log(`VAPID Key Konvertierung fehlgeschlagen: ${error.message}`, 'error');
|
||||
throw error;
|
||||
}
|
||||
|
||||
log('Push Subscription wird erstellt...', 'info');
|
||||
|
||||
// Check if push manager is available
|
||||
if (!registration.pushManager) {
|
||||
throw new Error('Push Manager nicht verfügbar in diesem Service Worker');
|
||||
}
|
||||
|
||||
const subscription = await registration.pushManager.subscribe({
|
||||
userVisibleOnly: true,
|
||||
applicationServerKey: 'BJmNVx0C3XeVxeKGTP9c-Z4HcuZNmdk6QdiLocZgCmb-miCS0ESFO3W2TvJlRhhNAShV63pWA5p36BTVSetyTds'
|
||||
applicationServerKey: applicationServerKey
|
||||
});
|
||||
|
||||
currentSubscription = subscription;
|
||||
@@ -206,6 +327,7 @@
|
||||
log(`Endpoint: ${subscription.endpoint.substring(0, 50)}...`);
|
||||
|
||||
// Send to server
|
||||
log('Subscription wird an Server gesendet...', 'info');
|
||||
const response = await fetch('/api/v1/public/subscribe', {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
@@ -214,17 +336,32 @@
|
||||
body: JSON.stringify(subscription)
|
||||
});
|
||||
|
||||
if (!response.ok) {
|
||||
throw new Error(`HTTP ${response.status}: ${response.statusText}`);
|
||||
}
|
||||
|
||||
const result = await response.json();
|
||||
if (result.success) {
|
||||
log('Subscription erfolgreich an Server gesendet', 'success');
|
||||
log(`Player ID: ${result.playerId || 'anonymous'}`, 'success');
|
||||
|
||||
// Store the player ID for later use
|
||||
if (result.playerId) {
|
||||
localStorage.setItem('pushPlayerId', result.playerId);
|
||||
}
|
||||
|
||||
updateStatus('Push Subscription erfolgreich!', 'success');
|
||||
// Store the subscription endpoint for later use
|
||||
localStorage.setItem('pushSubscriptionEndpoint', subscription.endpoint);
|
||||
} else {
|
||||
log(`Server-Fehler: ${result.message}`, 'error');
|
||||
updateStatus(`Server-Fehler: ${result.message}`, 'error');
|
||||
}
|
||||
|
||||
} catch (error) {
|
||||
log(`Push Subscription fehlgeschlagen: ${error.message}`, 'error');
|
||||
log(`Error Details: ${JSON.stringify(error)}`, 'error');
|
||||
updateStatus(`Push Subscription fehlgeschlagen: ${error.message}`, 'error');
|
||||
}
|
||||
}
|
||||
|
||||
@@ -243,42 +380,53 @@
|
||||
}
|
||||
|
||||
async function checkSubscription() {
|
||||
if ('serviceWorker' in navigator) {
|
||||
try {
|
||||
const registration = await navigator.serviceWorker.ready;
|
||||
const subscription = await registration.pushManager.getSubscription();
|
||||
|
||||
if (subscription) {
|
||||
currentSubscription = subscription;
|
||||
log('Aktive Push Subscription gefunden', 'success');
|
||||
log(`Endpoint: ${subscription.endpoint.substring(0, 50)}...`);
|
||||
} else {
|
||||
log('Keine Push Subscription gefunden', 'warning');
|
||||
}
|
||||
} catch (error) {
|
||||
log(`Subscription Check fehlgeschlagen: ${error.message}`, 'error');
|
||||
log('Überprüfe Push Subscription...', 'info');
|
||||
|
||||
if (!('serviceWorker' in navigator)) {
|
||||
log('Service Worker nicht unterstützt', 'error');
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
const registration = await navigator.serviceWorker.ready;
|
||||
const subscription = await registration.pushManager.getSubscription();
|
||||
|
||||
if (subscription) {
|
||||
currentSubscription = subscription;
|
||||
log('Aktive Push Subscription gefunden', 'success');
|
||||
log(`Endpoint: ${subscription.endpoint.substring(0, 50)}...`);
|
||||
updateStatus('Push Subscription aktiv', 'success');
|
||||
} else {
|
||||
log('Keine Push Subscription gefunden', 'warning');
|
||||
updateStatus('Keine Push Subscription gefunden', 'warning');
|
||||
}
|
||||
} catch (error) {
|
||||
log(`Subscription Check fehlgeschlagen: ${error.message}`, 'error');
|
||||
updateStatus(`Subscription Check fehlgeschlagen: ${error.message}`, 'error');
|
||||
}
|
||||
}
|
||||
|
||||
// Test Functions
|
||||
async function sendTestPush() {
|
||||
const message = document.getElementById('testMessage').value;
|
||||
log('Test-Push wird gesendet...', 'info');
|
||||
|
||||
// First check if we have a subscription
|
||||
if (!currentSubscription) {
|
||||
log('Keine Push Subscription gefunden. Bitte zuerst "Push abonnieren" klicken!', 'error');
|
||||
updateStatus('Keine Push Subscription gefunden', 'error');
|
||||
return;
|
||||
}
|
||||
|
||||
// Use the stored subscription endpoint as identifier
|
||||
const storedEndpoint = localStorage.getItem('pushSubscriptionEndpoint');
|
||||
// Use the stored player ID from subscription
|
||||
const storedPlayerId = localStorage.getItem('pushPlayerId');
|
||||
let userId = 'test-user';
|
||||
if (storedEndpoint) {
|
||||
// Use the endpoint as a unique identifier
|
||||
userId = storedEndpoint.split('/').pop().substring(0, 8);
|
||||
if (storedPlayerId) {
|
||||
userId = storedPlayerId;
|
||||
}
|
||||
|
||||
log(`Sende Test-Push an Player ID: ${userId}`, 'info');
|
||||
|
||||
try {
|
||||
const response = await fetch('/api/v1/public/test-push', {
|
||||
method: 'POST',
|
||||
@@ -295,11 +443,14 @@
|
||||
if (result.success) {
|
||||
log('Test-Push erfolgreich gesendet', 'success');
|
||||
log(`An User ID: ${userId}`, 'success');
|
||||
updateStatus('Test-Push erfolgreich gesendet!', 'success');
|
||||
} else {
|
||||
log(`Test-Push fehlgeschlagen: ${result.message}`, 'error');
|
||||
updateStatus(`Test-Push fehlgeschlagen: ${result.message}`, 'error');
|
||||
}
|
||||
} catch (error) {
|
||||
log(`Test-Push Fehler: ${error.message}`, 'error');
|
||||
updateStatus(`Test-Push Fehler: ${error.message}`, 'error');
|
||||
}
|
||||
}
|
||||
|
||||
@@ -309,7 +460,10 @@
|
||||
const notification = new Notification('🧪 Test Web Notification', {
|
||||
body: message,
|
||||
icon: '/pictures/icon-192.png',
|
||||
badge: '/pictures/icon-192.png'
|
||||
badge: '/pictures/icon-192.png',
|
||||
tag: 'test-notification',
|
||||
requireInteraction: true,
|
||||
silent: false
|
||||
});
|
||||
|
||||
notification.onclick = function() {
|
||||
@@ -317,12 +471,52 @@
|
||||
notification.close();
|
||||
};
|
||||
|
||||
// Auto-close after 10 seconds
|
||||
setTimeout(() => {
|
||||
notification.close();
|
||||
}, 10000);
|
||||
|
||||
log('Web-Notification gesendet', 'success');
|
||||
} else {
|
||||
log('Web-Notifications nicht verfügbar oder nicht erlaubt', 'error');
|
||||
}
|
||||
}
|
||||
|
||||
// Windows Desktop Notification (falls verfügbar)
|
||||
function sendWindowsNotification() {
|
||||
if ('Notification' in window && Notification.permission === 'granted') {
|
||||
const message = document.getElementById('testMessage').value;
|
||||
|
||||
// Erstelle eine Windows-ähnliche Notification
|
||||
const notification = new Notification('🏆 Ninja Cross - Achievement!', {
|
||||
body: message,
|
||||
icon: '/pictures/icon-192.png',
|
||||
badge: '/pictures/icon-192.png',
|
||||
tag: 'ninja-cross-achievement',
|
||||
requireInteraction: true,
|
||||
silent: false,
|
||||
data: {
|
||||
type: 'achievement',
|
||||
timestamp: Date.now()
|
||||
}
|
||||
});
|
||||
|
||||
notification.onclick = function() {
|
||||
window.focus();
|
||||
notification.close();
|
||||
};
|
||||
|
||||
// Auto-close after 15 seconds
|
||||
setTimeout(() => {
|
||||
notification.close();
|
||||
}, 15000);
|
||||
|
||||
log('Windows-ähnliche Notification gesendet', 'success');
|
||||
} else {
|
||||
log('Web-Notifications nicht verfügbar oder nicht erlaubt', 'error');
|
||||
}
|
||||
}
|
||||
|
||||
async function getPushStatus() {
|
||||
try {
|
||||
const response = await fetch('/api/v1/public/push-status');
|
||||
@@ -340,11 +534,27 @@
|
||||
|
||||
// Initialize
|
||||
window.addEventListener('load', function() {
|
||||
console.log('Push Notification Test Seite geladen');
|
||||
log('Push Notification Test Seite geladen');
|
||||
|
||||
// Check if we're on HTTPS
|
||||
if (location.protocol !== 'https:' && location.hostname !== 'localhost') {
|
||||
log('WARNUNG: Push Notifications funktionieren nur über HTTPS!', 'error');
|
||||
updateStatus('HTTPS erforderlich für Push Notifications', 'error');
|
||||
} else {
|
||||
log('HTTPS-Verbindung erkannt - Push Notifications möglich', 'success');
|
||||
}
|
||||
|
||||
checkServiceWorker();
|
||||
checkPermission();
|
||||
checkSubscription();
|
||||
});
|
||||
|
||||
// Also initialize on DOMContentLoaded as backup
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
console.log('DOM Content Loaded');
|
||||
log('DOM Content Loaded - Initialisierung gestartet');
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
Reference in New Issue
Block a user