/** * Public STCW Learn install landing page (no student session required). * Install-first → success message → student login on BOOKER. * * beforeinstallprompt often fires before deferred scripts load; the install * blade registers an early head listener into window.__stcwLearnBip. */ (function () { 'use strict'; var STORAGE_INSTALLED = 'stcw_learn_pwa_installed_v1'; var deferredPrompt = null; var swRegistered = false; var redirectTimer = null; function adoptEarlyPrompt() { if (window.__stcwLearnBip) { deferredPrompt = window.__stcwLearnBip; window.__stcwLearnBip = null; } } function swUrl() { var fromBody = document.body && document.body.getAttribute('data-student-sw-url'); return fromBody || '/student/sw.js'; } function loginUrl() { return (document.body && document.body.getAttribute('data-login-url')) || 'https://stcwbooker.com/userdashboard/'; } function isStandalone() { return window.matchMedia('(display-mode: standalone)').matches || window.navigator.standalone === true; } function isIos() { var ua = navigator.userAgent || ''; return /iPad|iPhone|iPod/.test(ua) || (navigator.platform === 'MacIntel' && navigator.maxTouchPoints > 1); } function isFirefox() { return /Firefox\//i.test(navigator.userAgent || ''); } function isChromium() { var ua = navigator.userAgent || ''; return /Chrome\//i.test(ua) || /Edg\//i.test(ua) || /CriOS\//i.test(ua); } function setStatus(text, tone) { var el = document.getElementById('studentPwaInstallHint'); if (!el || !text) return; el.textContent = text; el.setAttribute('data-tone', tone || 'info'); } function markReadyIfPrompt() { adoptEarlyPrompt(); if (!deferredPrompt) return; setStatus('Ready — tap Install Student App once to install.', 'ok'); var btn = document.getElementById('studentPwaInstallBtn'); if (btn) { btn.hidden = false; try { btn.focus(); } catch (err) { /* ignore */ } } } function markInstalled() { try { localStorage.setItem(STORAGE_INSTALLED, '1'); } catch (e) { /* ignore */ } } function showSuccessAndContinue() { markInstalled(); var panel = document.getElementById('studentInstallPanel'); var success = document.getElementById('studentInstallSuccess'); if (panel) { panel.classList.add('is-hidden'); panel.hidden = true; } if (success) { success.hidden = false; success.classList.add('is-visible'); } var note = document.getElementById('studentInstallRedirectNote'); var seconds = 3; function tick() { if (note) { note.textContent = seconds > 0 ? ('Opening student login in ' + seconds + '…') : 'Opening student login…'; } if (seconds <= 0) { window.location.href = loginUrl(); return; } seconds -= 1; redirectTimer = window.setTimeout(tick, 1000); } tick(); } function ensureServiceWorker() { if (!('serviceWorker' in navigator)) { setStatus('This browser cannot install PWAs. Open this page in Chrome or Edge on your phone.', 'warn'); return Promise.resolve(null); } if (swRegistered) { return navigator.serviceWorker.ready.catch(function () { return null; }); } swRegistered = true; return navigator.serviceWorker.register(swUrl(), { scope: '/student/' }) .then(function () { return navigator.serviceWorker.ready; }) .then(function (reg) { markReadyIfPrompt(); if (!deferredPrompt && isChromium() && !isStandalone()) { setStatus( 'Chrome can install this app. Tap the Install icon on the right of the address bar (monitor with ↓), or use menu (⋮) → Install page as app. On a phone, tap Install Student App after status says Ready.', 'ok' ); } return reg; }) .catch(function () { swRegistered = false; setStatus('Could not register the app service worker. Reload over HTTPS and try again.', 'warn'); return null; }); } function guidanceForNoPrompt() { if (isStandalone()) { return 'Already running as the installed app. Continue to student login.'; } if (isIos()) { return 'On iPhone/iPad: tap Share → Add to Home Screen, then open STCW Learn from your home screen.'; } if (isFirefox()) { return 'Firefox cannot one-tap install. Open this page in Chrome or Edge on your phone, then tap Install once.'; } if (isChromium()) { return 'Use the Install icon on the right of the address bar (monitor with ↓). That installs STCW Learn. Then open the app icon and sign in.'; } return 'Use Chrome or Edge on Android for one-tap Install. On iPhone use Share → Add to Home Screen.'; } function install() { adoptEarlyPrompt(); setStatus('Checking install…', 'info'); return ensureServiceWorker().then(function () { adoptEarlyPrompt(); if (deferredPrompt) { var p = deferredPrompt; deferredPrompt = null; window.__stcwLearnBip = null; return p.prompt().then(function () { return p.userChoice; }).then(function (choice) { if (choice && choice.outcome === 'accepted') { setStatus('Installing…', 'ok'); showSuccessAndContinue(); } else { setStatus('Install was cancelled. Tap Install again, or use the address-bar Install icon.', 'warn'); } }).catch(function () { setStatus(guidanceForNoPrompt(), 'warn'); }); } setStatus(guidanceForNoPrompt(), 'warn'); return null; }); } window.addEventListener('beforeinstallprompt', function (e) { e.preventDefault(); deferredPrompt = e; window.__stcwLearnBip = e; markReadyIfPrompt(); }); window.addEventListener('appinstalled', function () { deferredPrompt = null; window.__stcwLearnBip = null; showSuccessAndContinue(); }); window.StudentLearnInstall = { install: install }; function bind() { if (isStandalone()) { window.location.replace(loginUrl()); return; } adoptEarlyPrompt(); var btn = document.getElementById('studentPwaInstallBtn'); if (btn && !btn.getAttribute('data-bound')) { btn.setAttribute('data-bound', '1'); btn.addEventListener('click', function (e) { e.preventDefault(); install(); }); } ensureServiceWorker(); markReadyIfPrompt(); if (deferredPrompt) { return; } if (isFirefox()) { setStatus('You are in Firefox. Open this page in Chrome or Edge on your phone, then tap Install once.', 'warn'); } else if (isIos()) { setStatus('On iPhone: Share → Add to Home Screen, then open the STCW Learn icon.', 'info'); } else { setStatus('Preparing install… If the address bar already shows an Install icon (monitor with ↓), click that. Or wait until status says Ready, then tap the blue button.', 'info'); } } if (document.readyState === 'loading') { document.addEventListener('DOMContentLoaded', bind); } else { bind(); } })();