thermograph/frontend/static/ios-install.js

74 lines
3 KiB
JavaScript
Raw Normal View History

// A small, dismissible "Add to Home Screen" hint for iPhone/iPad visitors.
//
// iOS only grants Web Push to a site the user has added to the Home Screen via
// Safari's Share sheet (iOS 16.4+). There is no beforeinstallprompt on iOS, so
// the only nudge available is telling people where the control is. This module
// shows that nudge — and only when it can actually help: real iOS Safari, not
// already installed, not previously dismissed. Everything degrades to nothing.
// Not the "tg:" prefix — cache.js sweeps that namespace on every load. The
// durable app prefer­ences ("thermograph:unit", "thermograph:loc") use this one.
const KEY = "thermograph:ios-a2hs";
function isIOS() {
const ua = navigator.userAgent || "";
// iPadOS 13+ reports as "Macintosh"; a touch point count disambiguates it.
return /iphone|ipad|ipod/i.test(ua) ||
(/Macintosh/.test(ua) && (navigator.maxTouchPoints || 0) > 1);
}
function isStandalone() {
return window.navigator.standalone === true ||
(window.matchMedia && window.matchMedia("(display-mode: standalone)").matches);
}
function isSafari() {
// Add to Home Screen only works from Safari proper — not Chrome (CriOS),
// Firefox (FxiOS), Edge (EdgiOS), Opera (OPiOS), or most in-app webviews.
const ua = navigator.userAgent || "";
if (/crios|fxios|edgios|opios/i.test(ua)) return false;
return /safari/i.test(ua);
}
function dismissed() {
try { return localStorage.getItem(KEY) === "off"; } catch (e) { return false; }
}
function remember() {
try { localStorage.setItem(KEY, "off"); } catch (e) {}
}
function build() {
const el = document.createElement("div");
el.className = "ios-a2hs";
el.setAttribute("role", "note");
el.setAttribute("aria-label", "Install Thermograph on your Home Screen");
// The share glyph mirrors iOS's own Share icon so the instruction is scannable.
el.innerHTML =
'<svg class="ios-a2hs-share" viewBox="0 0 24 24" aria-hidden="true" fill="none" ' +
'stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">' +
'<path d="M12 3v12"/><path d="M8 7l4-4 4 4"/>' +
'<path d="M5 12v7a1 1 0 0 0 1 1h12a1 1 0 0 0 1-1v-7"/></svg>' +
'<div class="ios-a2hs-text"><b>Add Thermograph to your Home Screen</b>' +
'<span>Tap Share, then <b>Add to Home Screen</b>. Its how to get weather alerts on iPhone.</span></div>' +
'<button type="button" class="ios-a2hs-x" aria-label="Dismiss">×</button>';
el.querySelector(".ios-a2hs-x").addEventListener("click", () => {
remember();
el.remove();
});
return el;
}
function maybeShow() {
if (!isIOS() || isStandalone() || !isSafari() || dismissed()) return;
if (document.querySelector(".ios-a2hs")) return;
document.body.appendChild(build());
}
// Wait a beat so the hint never competes with first paint, and only on an
// interactive document.
if (document.readyState === "loading") {
document.addEventListener("DOMContentLoaded", () => setTimeout(maybeShow, 1200));
} else {
setTimeout(maybeShow, 1200);
}