feat(push): nowa ikona (smartfon z falami) + toast per urządzenie
Some checks are pending
NordaBiz Tests / Unit & Integration Tests (push) Waiting to run
NordaBiz Tests / E2E Tests (Playwright) (push) Blocked by required conditions
NordaBiz Tests / Smoke Tests (Production) (push) Blocked by required conditions
NordaBiz Tests / Send Failure Notification (push) Blocked by required conditions

Odróżnia push od portalowych powiadomień w navbarze. Po pierwszym
udanym włączeniu pokazuje komunikat że subskrypcja działa tylko na
tym urządzeniu i zachęca do kliknięcia również na innych telefonach
i komputerach. Tooltipy zaktualizowane pod kątem "na tym urządzeniu".

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
Maciej Pienczyn 2026-04-14 17:25:09 +02:00
parent 6c4db17807
commit 31c8272e31
2 changed files with 38 additions and 14 deletions

View File

@ -38,25 +38,45 @@
const bell = getBell(); const bell = getBell();
if (!bell) return; if (!bell) return;
bell.dataset.state = state; bell.dataset.state = state;
const slash = bell.querySelector('.push-disabled-slash'); const waves = bell.querySelectorAll('.push-wave');
if (state === 'enabled') { if (state === 'enabled') {
bell.title = 'Powiadomienia włączone — kliknij, żeby wyłączyć'; bell.title = 'Powiadomienia włączone na tym urządzeniu — kliknij, żeby wyłączyć';
if (slash) slash.style.display = 'none';
bell.style.opacity = '1'; bell.style.opacity = '1';
waves.forEach(function(w) { w.style.opacity = ''; });
} else if (state === 'disabled') { } else if (state === 'disabled') {
bell.title = 'Włącz powiadomienia'; bell.title = 'Kliknij, aby włączyć powiadomienia na tym urządzeniu';
if (slash) slash.style.display = '';
bell.style.opacity = '0.55'; bell.style.opacity = '0.55';
waves.forEach(function(w, i) { w.style.opacity = i === 0 ? '0.5' : '0.35'; });
} else if (state === 'blocked') { } else if (state === 'blocked') {
bell.title = 'Powiadomienia zablokowane w przeglądarce. Zmień w ustawieniach strony.'; bell.title = 'Powiadomienia zablokowane w przeglądarce. Zmień w ustawieniach strony.';
if (slash) slash.style.display = '';
bell.style.opacity = '0.4'; bell.style.opacity = '0.4';
waves.forEach(function(w) { w.style.opacity = '0.2'; });
} else if (state === 'unsupported') { } else if (state === 'unsupported') {
bell.title = 'Przeglądarka nie obsługuje powiadomień'; bell.title = 'Ta przeglądarka nie obsługuje powiadomień';
bell.style.opacity = '0.3'; bell.style.opacity = '0.3';
} }
} }
function showToast(text, durationMs) {
try {
const old = document.getElementById('pushInfoToast');
if (old) old.remove();
const toast = document.createElement('div');
toast.id = 'pushInfoToast';
toast.textContent = text;
toast.style.cssText = 'position:fixed;bottom:24px;left:50%;transform:translateX(-50%);' +
'background:#233e6d;color:#fff;padding:14px 20px;border-radius:10px;' +
'box-shadow:0 6px 24px rgba(0,0,0,0.25);z-index:9999;max-width:420px;' +
'font-size:14px;line-height:1.45;text-align:center;font-family:inherit;';
document.body.appendChild(toast);
setTimeout(function() {
toast.style.transition = 'opacity 0.4s';
toast.style.opacity = '0';
setTimeout(function() { toast.remove(); }, 450);
}, durationMs || 7000);
} catch (e) { /* ignore */ }
}
async function getSubscription() { async function getSubscription() {
const reg = await navigator.serviceWorker.ready; const reg = await navigator.serviceWorker.ready;
return reg.pushManager.getSubscription(); return reg.pushManager.getSubscription();
@ -103,6 +123,8 @@
setBellState('enabled'); setBellState('enabled');
// Welcome push — test że wszystko działa // Welcome push — test że wszystko działa
await fetch('/push/test', { method: 'POST', credentials: 'include' }); await fetch('/push/test', { method: 'POST', credentials: 'include' });
// Edukacyjny komunikat: subskrypcja jest per urządzenie/przeglądarka
showToast('✓ Powiadomienia włączone na tym urządzeniu. Na innych telefonach i komputerach kliknij ten sam przycisk, żeby włączyć je także tam.', 9000);
} catch (e) { } catch (e) {
log('enable error', e); log('enable error', e);
alert('Nie udało się włączyć powiadomień: ' + (e.message || e)); alert('Nie udało się włączyć powiadomień: ' + (e.message || e));

View File

@ -175,15 +175,17 @@
</li> </li>
{% if push_bell_visible %} {% if push_bell_visible %}
<!-- Web Push toggle --> <!-- Web Push toggle — ikona "smartfon z falami dźwiękowymi" = powiadomienia na tym urządzeniu -->
<li class="push-toggle"> <li class="push-toggle">
<button id="pushBellBtn" class="nav-link-with-badge" onclick="togglePush(event)" <button id="pushBellBtn" class="nav-link-with-badge" onclick="togglePush(event)"
aria-label="Powiadomienia push" title="Włącz powiadomienia push" data-state="disabled" aria-label="Powiadomienia na tym urządzeniu"
style="opacity:0.55"> title="Kliknij, aby włączyć powiadomienia na tym urządzeniu"
<svg class="notifications-icon" fill="none" stroke="currentColor" viewBox="0 0 24 24" style="overflow:visible"> data-state="disabled" style="opacity:0.55">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" <svg class="notifications-icon" fill="none" stroke="currentColor" stroke-width="2" viewBox="0 0 24 24" style="overflow:visible">
d="M10 5a2 2 0 114 0v.341C16.67 6.165 18 8.388 18 11v3.159c0 .538.214 1.055.595 1.436L20 17H4l1.405-1.405A2.032 2.032 0 006 14.159V11c0-2.612 1.33-4.835 4-5.659zM9 17v1a3 3 0 006 0v-1"/> <rect x="7" y="3" width="10" height="18" rx="2"/>
<line class="push-disabled-slash" x1="4" y1="20" x2="20" y2="4" stroke-width="2"/> <line x1="11" y1="18" x2="13" y2="18"/>
<path class="push-wave push-wave-1" d="M19 8c1 1 1.5 2.5 1.5 4s-0.5 3-1.5 4" stroke-linecap="round"/>
<path class="push-wave push-wave-2" d="M21 6c1.5 1.5 2.3 3.8 2.3 6s-0.8 4.5-2.3 6" stroke-linecap="round"/>
</svg> </svg>
</button> </button>
</li> </li>