feat: add webchat pwa push subscription support
This commit is contained in:
@@ -4,6 +4,12 @@
|
||||
* Read-only config view (redacted), editable hook patterns,
|
||||
* tool list, and channel overview.
|
||||
*/
|
||||
import {
|
||||
isPushSupported,
|
||||
getPushStatus,
|
||||
enablePushNotifications,
|
||||
disablePushNotifications,
|
||||
} from '../lib/pwa.js';
|
||||
|
||||
function escapeHtml(text) {
|
||||
const div = document.createElement('div');
|
||||
@@ -14,6 +20,75 @@ function escapeHtml(text) {
|
||||
let _client = null;
|
||||
let _el = null;
|
||||
|
||||
function describePushStatus(status) {
|
||||
if (!status.supported) {
|
||||
return status.message || 'Push notifications are not supported in this browser.';
|
||||
}
|
||||
if (!status.enabled) {
|
||||
return 'Gateway push is disabled (`server.webchat_push.enabled: false`).';
|
||||
}
|
||||
if (!status.configured) {
|
||||
return 'Gateway push key is missing (`server.webchat_push.vapid_public_key`).';
|
||||
}
|
||||
if (status.permission === 'denied') {
|
||||
return 'Browser notifications are blocked. Allow notifications in browser settings.';
|
||||
}
|
||||
if (status.subscribed) {
|
||||
return 'Push notifications are enabled for this browser.';
|
||||
}
|
||||
return 'Push is configured. Click Enable to subscribe this browser.';
|
||||
}
|
||||
|
||||
async function renderPushStatus() {
|
||||
const statusEl = _el.querySelector('#push-status');
|
||||
const enableBtn = _el.querySelector('#push-enable');
|
||||
const disableBtn = _el.querySelector('#push-disable');
|
||||
if (!statusEl || !enableBtn || !disableBtn) {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
const status = await getPushStatus();
|
||||
statusEl.textContent = describePushStatus(status);
|
||||
statusEl.className = status.subscribed ? 'text-sm text-success' : 'text-sm text-muted';
|
||||
enableBtn.disabled = !status.supported || !status.enabled || !status.configured || status.subscribed;
|
||||
disableBtn.disabled = !status.supported || !status.subscribed;
|
||||
} catch (err) {
|
||||
statusEl.textContent = `Push status error: ${err.message}`;
|
||||
statusEl.className = 'text-sm text-error';
|
||||
enableBtn.disabled = true;
|
||||
disableBtn.disabled = true;
|
||||
}
|
||||
}
|
||||
|
||||
async function onEnablePush() {
|
||||
const statusEl = _el.querySelector('#push-status');
|
||||
if (!statusEl) {return;}
|
||||
statusEl.textContent = 'Enabling push notifications...';
|
||||
statusEl.className = 'text-sm text-muted';
|
||||
try {
|
||||
await enablePushNotifications();
|
||||
await renderPushStatus();
|
||||
} catch (err) {
|
||||
statusEl.textContent = `Enable failed: ${err.message}`;
|
||||
statusEl.className = 'text-sm text-error';
|
||||
}
|
||||
}
|
||||
|
||||
async function onDisablePush() {
|
||||
const statusEl = _el.querySelector('#push-status');
|
||||
if (!statusEl) {return;}
|
||||
statusEl.textContent = 'Disabling push notifications...';
|
||||
statusEl.className = 'text-sm text-muted';
|
||||
try {
|
||||
await disablePushNotifications();
|
||||
await renderPushStatus();
|
||||
} catch (err) {
|
||||
statusEl.textContent = `Disable failed: ${err.message}`;
|
||||
statusEl.className = 'text-sm text-error';
|
||||
}
|
||||
}
|
||||
|
||||
async function loadSettings() {
|
||||
if (!_client || !_el) {return;}
|
||||
|
||||
@@ -52,6 +127,16 @@ async function loadSettings() {
|
||||
_el.innerHTML = `
|
||||
<h1 class="page-title">Settings</h1>
|
||||
|
||||
<h2 class="section-title">WebChat Push Notifications</h2>
|
||||
<div class="settings-section">
|
||||
${isPushSupported() ? '' : '<div class="text-sm text-muted">This browser does not support PushManager APIs.</div>'}
|
||||
<div style="display: flex; gap: 8px; margin-bottom: 8px;">
|
||||
<button id="push-enable" class="btn btn-primary" type="button">Enable Push</button>
|
||||
<button id="push-disable" class="btn btn-secondary" type="button">Disable Push</button>
|
||||
</div>
|
||||
<div id="push-status" class="text-sm text-muted"></div>
|
||||
</div>
|
||||
|
||||
<h2 class="section-title">Hook Patterns</h2>
|
||||
<div class="settings-section">
|
||||
<div class="hook-editor">
|
||||
@@ -133,6 +218,9 @@ async function loadSettings() {
|
||||
|
||||
// Bind save hooks
|
||||
_el.querySelector('#hooks-save').addEventListener('click', saveHooks);
|
||||
_el.querySelector('#push-enable').addEventListener('click', onEnablePush);
|
||||
_el.querySelector('#push-disable').addEventListener('click', onDisablePush);
|
||||
await renderPushStatus();
|
||||
}
|
||||
|
||||
async function saveHooks() {
|
||||
|
||||
Reference in New Issue
Block a user