// /home/Autopartes/pos/static/js/kiosk.js // Kiosk mode for Nexus POS — fullscreen, wake lock, auto-login, no right-click (function () { 'use strict'; var STORAGE_KEY = 'pos_kiosk_mode'; // ─── Detection ─── function isPWA() { return window.matchMedia('(display-mode: standalone)').matches || window.navigator.standalone === true; } function isCapacitor() { return typeof window.Capacitor !== 'undefined' && window.Capacitor.isNativePlatform && window.Capacitor.isNativePlatform(); } function isKioskEnabled() { // Enabled if explicitly set in localStorage, or if running as PWA/Capacitor var pref = localStorage.getItem(STORAGE_KEY); if (pref === 'true') return true; if (pref === 'false') return false; // Auto-detect return isPWA() || isCapacitor(); } // ─── Fullscreen ─── var fullscreenRequested = false; function requestFullscreen() { if (fullscreenRequested) return; var el = document.documentElement; var fn = el.requestFullscreen || el.webkitRequestFullscreen || el.mozRequestFullScreen || el.msRequestFullscreen; if (fn) { fn.call(el).catch(function () { /* user may have denied */ }); fullscreenRequested = true; } } // ─── Wake Lock ─── var wakeLock = null; async function acquireWakeLock() { if (!('wakeLock' in navigator)) return; try { wakeLock = await navigator.wakeLock.request('screen'); wakeLock.addEventListener('release', function () { wakeLock = null; }); } catch (e) { // Wake lock may fail if tab not visible } } function releaseWakeLock() { if (wakeLock) { wakeLock.release(); wakeLock = null; } } // Re-acquire wake lock when page becomes visible again document.addEventListener('visibilitychange', function () { if (document.visibilityState === 'visible' && isKioskEnabled() && !wakeLock) { acquireWakeLock(); } }); // ─── Auto-login ─── function tryAutoLogin() { var token = localStorage.getItem('pos_token'); if (!token) return; // Check if we are on the login page var isLoginPage = window.location.pathname.indexOf('/pos/login') !== -1; if (!isLoginPage) return; // Validate token by trying to decode expiry (JWT is base64) try { var parts = token.split('.'); if (parts.length !== 3) return; var payload = JSON.parse(atob(parts[1].replace(/-/g, '+').replace(/_/g, '/'))); var exp = payload.exp; if (exp && (exp * 1000) > Date.now()) { // Token still valid — skip login window.location.href = '/pos/'; } } catch (e) { // Invalid token, stay on login } } // ─── Activate kiosk mode ─── function activate() { // Prevent navigation away window.addEventListener('beforeunload', function (e) { if (isKioskEnabled()) { e.preventDefault(); e.returnValue = ''; } }); // Disable context menu document.addEventListener('contextmenu', function (e) { if (isKioskEnabled()) { e.preventDefault(); } }); // Request fullscreen on first user interaction var interactionEvents = ['click', 'touchstart', 'keydown']; function onFirstInteraction() { if (isKioskEnabled()) { requestFullscreen(); acquireWakeLock(); } interactionEvents.forEach(function (evt) { document.removeEventListener(evt, onFirstInteraction); }); } interactionEvents.forEach(function (evt) { document.addEventListener(evt, onFirstInteraction, { once: false }); }); // Auto-login if on login page tryAutoLogin(); } // ─── Public API ─── window.NexusKiosk = { isEnabled: isKioskEnabled, isPWA: isPWA, isCapacitor: isCapacitor, enable: function () { localStorage.setItem(STORAGE_KEY, 'true'); requestFullscreen(); acquireWakeLock(); }, disable: function () { localStorage.setItem(STORAGE_KEY, 'false'); releaseWakeLock(); if (document.fullscreenElement) { document.exitFullscreen().catch(function () {}); } }, toggle: function () { if (isKioskEnabled()) { window.NexusKiosk.disable(); } else { window.NexusKiosk.enable(); } return isKioskEnabled(); } }; // ─── Init ─── if (isKioskEnabled()) { activate(); } // Also activate if preference changes (e.g. toggled from config) window.addEventListener('storage', function (e) { if (e.key === STORAGE_KEY && e.newValue === 'true') { activate(); } }); })();