Портал технической службы: наряды и чек-листы, задачи, отказы и неисправности, анализ надёжности, карты, склады, приложение для Android
This commit is contained in:
@@ -0,0 +1,52 @@
|
||||
// Service worker: push-уведомления + офлайн-оболочка мобильной версии (/m).
|
||||
const CACHE = "shell-m-v3";
|
||||
const SHELL = ["/m", "/static/m/m.js", "/static/m/m.css", "/static/m/manifest.webmanifest",
|
||||
"/static/m/icon-192.png", "/static/m/icon-512.png", "/static/m/apple-touch-icon.png", "/static/assistant.js"];
|
||||
|
||||
self.addEventListener("install", e => {
|
||||
e.waitUntil(caches.open(CACHE).then(c => Promise.allSettled(SHELL.map(u => c.add(u)))).then(() => self.skipWaiting()));
|
||||
});
|
||||
self.addEventListener("activate", e => {
|
||||
e.waitUntil(caches.keys().then(keys => Promise.all(keys.filter(k => k !== CACHE).map(k => caches.delete(k)))).then(() => self.clients.claim()));
|
||||
});
|
||||
|
||||
const isShell = url => url.origin === self.location.origin && (url.pathname === "/m" || url.pathname === "/m/" || url.pathname.startsWith("/static/m/") || url.pathname === "/static/assistant.js");
|
||||
|
||||
// Сеть в приоритете (чтобы обновления приходили сразу), при отсутствии связи — кэш. API не перехватываем.
|
||||
self.addEventListener("fetch", e => {
|
||||
const req = e.request, url = new URL(req.url);
|
||||
if (req.method !== "GET" || !isShell(url)) return;
|
||||
e.respondWith((async () => {
|
||||
const cache = await caches.open(CACHE);
|
||||
try {
|
||||
const net = await Promise.race([fetch(req), new Promise((_, rej) => setTimeout(() => rej(new Error("timeout")), 4000))]);
|
||||
if (net && net.ok) cache.put(url.pathname === "/m/" ? "/m" : req, net.clone());
|
||||
return net;
|
||||
} catch (err) {
|
||||
const hit = await cache.match(url.pathname === "/m/" ? "/m" : req, { ignoreSearch: true });
|
||||
if (hit) return hit;
|
||||
throw err;
|
||||
}
|
||||
})());
|
||||
});
|
||||
|
||||
self.addEventListener("push", e => {
|
||||
let d = {};
|
||||
try { d = e.data.json(); } catch (_) { d = { title: "Чек-листы", body: e.data ? e.data.text() : "" }; }
|
||||
e.waitUntil(self.registration.showNotification(d.title || "Чек-листы", {
|
||||
body: d.body || "", data: { url: d.url || "/" }, tag: d.url || undefined, icon: "/static/m/icon-192.png", badge: "/static/m/icon-192.png",
|
||||
}));
|
||||
});
|
||||
|
||||
self.addEventListener("notificationclick", e => {
|
||||
e.notification.close();
|
||||
let target = (e.notification.data && e.notification.data.url) || "/";
|
||||
// на телефоне (по User-Agent) открываем мобильную версию: /#/order/5 -> /m#/o/5
|
||||
const m = target.match(/#\/order\/(\d+)/);
|
||||
if (m && /Android|iPhone|iPad|iPod/i.test(self.navigator.userAgent)) target = "/m#/o/" + m[1];
|
||||
const url = new URL(target, self.location.origin).href;
|
||||
e.waitUntil(self.clients.matchAll({ type: "window", includeUncontrolled: true }).then(list => {
|
||||
for (const c of list) if ("focus" in c) { c.navigate(url); return c.focus(); }
|
||||
return self.clients.openWindow(url);
|
||||
}));
|
||||
});
|
||||
Reference in New Issue
Block a user