feat(footer): make push notification button reflect subscription state
E2E Test Suite / Smoke Tests (P0) (push) Failing after 9m36s
E2E Test Suite / Critical User Journeys (push) Has been skipped
E2E Test Suite / API Integration Tests (push) Has been skipped
E2E Test Suite / Destructive & Chaos Tests (push) Failing after 10m42s
E2E Test Suite / Form Interaction Tests (push) Failing after 11m35s
E2E Test Suite / Security Header Tests (push) Failing after 11m20s
E2E Test Suite / Mobile Device Tests (push) Failing after 12m13s
E2E Test Suite / Cross-Browser Regression (webkit) (push) Failing after 13m5s
E2E Test Suite / Cross-Browser Regression (firefox) (push) Failing after 13m57s
E2E Test Suite / Cross-Browser Regression (chromium) (push) Failing after 14m50s
E2E Test Suite / Test Report Summary (push) Failing after 12m50s
Deploy to Production / Build & Verify (push) Failing after 19m19s
Deploy to Production / Pre-Deploy Tests (push) Failing after 14m59s
Deploy to Production / Deploy to Fly.io (push) Failing after 12m23s
Deploy to Production / Deploy to VPS (PM2) (push) Failing after 12m26s
Deploy to Production / Deploy to Render (push) Failing after 13m16s
Deploy to Production / Deploy to Railway (push) Failing after 14m8s
Deploy to Production / Post-Deploy Verification (push) Failing after 14m57s
Deploy to Production / Notify on Failure (push) Failing after 14m58s

The WRNexus web-push button always showed "Enable notifications". It now
reads WRNexusPush.isSubscribed() on load and renders the correct state:
- hides entirely when SDK/browser push support is missing
- "Enable notifications" -> calls prompt() (user gesture)
- "Unsubscribe" when already subscribed -> calls unsubscribe()
- disabled "Notifications blocked" when permission is denied
- in-progress disabled state to prevent double-clicks; re-reads state after
  each action and re-renders the label

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
platform-mcp
2026-06-24 02:39:37 +05:30
co-authored by Claude Opus 4.8
parent a8d7db562d
commit 8e7070cbaf
+106 -6
View File
@@ -167,16 +167,21 @@ const currentYear = new Date().getFullYear();
<a href="/privacy" class="text-primary hover:underline">Privacy Policy</a>.
</p>
<!-- Web push opt-in (WRNexus). User-gesture subscribe control. -->
<!-- Web push opt-in (WRNexus). User-gesture subscribe control.
Hidden by default; the client script below reveals it only when the
WRNexus SDK + browser push support are available, and sets the
correct label based on the visitor's current subscription state. -->
<button
id="wrnexus-subscribe"
type="button"
class="mt-6 w-full px-4 py-3 bg-secondary-800 border border-secondary-700 text-white font-medium rounded-lg hover:bg-secondary-700 focus:outline-none focus:ring-2 focus:ring-primary focus:ring-offset-2 focus:ring-offset-secondary-900 transition-all duration-200 text-sm flex items-center justify-center gap-2"
hidden
aria-label="Enable notifications"
class="mt-6 w-full px-4 py-3 bg-secondary-800 border border-secondary-700 text-white font-medium rounded-lg hover:bg-secondary-700 focus:outline-none focus:ring-2 focus:ring-primary focus:ring-offset-2 focus:ring-offset-secondary-900 transition-all duration-200 text-sm flex items-center justify-center gap-2 disabled:opacity-60 disabled:cursor-not-allowed"
>
<svg class="w-4 h-4" fill="none" viewBox="0 0 24 24" stroke="currentColor" aria-hidden="true">
<svg class="w-4 h-4 flex-shrink-0" fill="none" viewBox="0 0 24 24" stroke="currentColor" aria-hidden="true">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15 17h5l-1.405-1.405A2.032 2.032 0 0118 14.158V11a6.002 6.002 0 00-4-5.659V5a2 2 0 10-4 0v.341C7.67 6.165 6 8.388 6 11v3.159c0 .538-.214 1.055-.595 1.436L4 17h5m6 0v1a3 3 0 11-6 0v-1m6 0H9" />
</svg>
<span>Enable notifications</span>
<span id="wrnexus-subscribe-label">Enable notifications</span>
</button>
</div>
</div>
@@ -205,9 +210,104 @@ const currentYear = new Date().getFullYear();
</div>
</footer>
<!-- WRNexus push subscribe: wired via addEventListener (Astro strips inline on* handlers). -->
<!-- WRNexus push subscribe: state-aware control wired via addEventListener
(Astro strips inline on* handlers). The button reflects whether the
visitor is already subscribed and lets them toggle the subscription. -->
<script is:inline>
document.getElementById('wrnexus-subscribe')?.addEventListener('click', () => window.WRNexusPush?.subscribe());
(function () {
function init() {
var btn = document.getElementById('wrnexus-subscribe');
var label = document.getElementById('wrnexus-subscribe-label');
if (!btn || !label) return;
var push = window.WRNexusPush;
var supported =
push &&
'Notification' in window &&
'serviceWorker' in navigator &&
'PushManager' in window;
// No SDK or no browser push support: keep the button hidden entirely.
if (!supported) {
btn.hidden = true;
return;
}
// Permission permanently blocked by the user: the SDK can't re-prompt,
// so surface a clear, non-actionable disabled state instead of a button
// that silently does nothing.
if (window.Notification && Notification.permission === 'denied') {
label.textContent = 'Notifications blocked';
btn.setAttribute('aria-label', 'Notifications are blocked in your browser settings');
btn.disabled = true;
btn.hidden = false;
return;
}
// Render the button for a given subscription state.
// Default UX: subscribed users get an actionable "Unsubscribe" toggle
// rather than a dead "Already subscribed" label.
// (Alternative: render a disabled "Already subscribed" indicator instead
// of the Unsubscribe toggle if product prefers a non-actionable state.)
function render(subscribed) {
if (subscribed) {
label.textContent = 'Unsubscribe';
btn.setAttribute('aria-label', 'Unsubscribe from notifications');
} else {
label.textContent = 'Enable notifications';
btn.setAttribute('aria-label', 'Enable notifications');
}
btn.dataset.subscribed = subscribed ? 'true' : 'false';
btn.disabled = false;
btn.hidden = false;
}
async function refresh() {
try {
var subscribed = await push.isSubscribed();
render(!!subscribed);
} catch (err) {
// On error, fall back to the unsubscribed label so the control stays usable.
console.error('[wrnexus-push] isSubscribed() failed:', err);
render(false);
}
}
btn.addEventListener('click', async function () {
if (btn.disabled) return;
var wasSubscribed = btn.dataset.subscribed === 'true';
var busyLabel = wasSubscribed ? 'Unsubscribing…' : 'Enabling…';
// In-progress state to prevent double-clicks while the promise is pending.
btn.disabled = true;
label.textContent = busyLabel;
try {
if (wasSubscribed) {
await push.unsubscribe();
} else {
// prompt() must run from this real user gesture.
await push.prompt();
}
} catch (err) {
console.error('[wrnexus-push] toggle failed:', err);
} finally {
// Re-read the authoritative state and re-render the label.
await refresh();
}
});
// Determine and render the initial state.
refresh();
}
if (document.readyState === 'loading') {
document.addEventListener('DOMContentLoaded', init);
} else {
init();
}
})();
</script>
<script>