window.App = window.App || {}; App.privacy = App.privacy || {}; (function() { // The moment this window stops being the one in front -- another tab, // another window, another app -- the page goes behind a blur. What the site // is showing is nobody else's business: not a glance over the shoulder, not // the app switcher's snapshot, not a screen share of the tab next door. const ON = 'is-on'; let veil = null; let veiled = false; const element = function() { if (!veil || !veil.isConnected) veil = document.getElementById('privacy-veil'); return veil; }; const setVeiled = function(next) { const el = element(); if (!el || next === veiled) return; veiled = next; el.classList.toggle(ON, next); }; const cover = function() { setVeiled(true); }; const uncover = function() { setVeiled(false); }; function start() { if (!element()) return; // Leaving. Any one of these can be the last event before the window is // out of sight, so each covers on its own, and covers at once: a blur // that lands after the app switcher took its picture is no blur at all. window.addEventListener('blur', cover); window.addEventListener('pagehide', cover); document.addEventListener('visibilitychange', function() { if (document.visibilityState === 'hidden') cover(); else uncover(); }); // Coming back. window.addEventListener('focus', uncover); window.addEventListener('pageshow', uncover); // A backstop, for whatever the browser did or didn't report: someone // using the page is someone looking at it. The first touch lands on the // veil and lifts it instead of reaching the thing underneath, which is // the right way round for a tap that was meant for a page you could see. ['pointerdown', 'touchstart', 'keydown', 'wheel'].forEach(function(name) { window.addEventListener(name, uncover, { capture: true, passive: true }); }); } App.privacy = { start: start, cover: cover, uncover: uncover, isVeiled: function() { return veiled; } }; })();