PluginProbe
OpenStation: Desktop Windows, Dock & Virtual Desktops for WP Admin / 0.8.7
OpenStation: Desktop Windows, Dock & Virtual Desktops for WP Admin v0.8.7
1.1.10 1.1.9 1.1.8 1.1.7 1.1.6 1.1.5 1.1.4 1.1.3 1.1.2 1.1.1 1.1.0 1.0.1 1.0.0 0.9.8 0.9.7 0.9.6 0.9.4 0.9.5 0.9.3 0.9.2 0.9.1 0.9.0 0.8.9 0.8.8 0.8.7 All 34 releases
desktop-mode / assets / js / sw.js

sw.js in OpenStation: Desktop Windows, Dock & Virtual Desktops for WP Admin 0.8.7, at assets/js/sw.js

163 lines 4.8 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 (function() {
2 "use strict";
3 const sw = globalThis;
4 const VERSION = "0.8.0-pwa-3";
5 const STATIC_CACHE = `desktop-mode-static-${VERSION}`;
6 const RUNTIME_CACHE = `desktop-mode-runtime-${VERSION}`;
7 const OFFLINE_URL = "/desktop-mode/?offline=1";
8 const PRECACHE_PATHS = [
9 "assets/css/desktop.css",
10 "assets/css/variables.css",
11 "assets/css/dock.css",
12 "assets/css/windows.css",
13 "assets/images/wp-logo.png"
14 ];
15 sw.addEventListener("install", (event) => {
16 event.waitUntil(precache());
17 void sw.skipWaiting();
18 });
19 sw.addEventListener("activate", (event) => {
20 event.waitUntil(
21 (async () => {
22 const keys = await caches.keys();
23 await Promise.all(
24 keys.filter((k) => !k.endsWith(VERSION)).map((k) => caches.delete(k))
25 );
26 await sw.clients.claim();
27 })()
28 );
29 });
30 sw.addEventListener("fetch", (event) => {
31 const req = event.request;
32 if (req.method !== "GET") {
33 return;
34 }
35 const url = new URL(req.url);
36 if (url.origin !== sw.location.origin) {
37 return;
38 }
39 const isPortal = url.pathname.startsWith("/desktop-mode/");
40 const isAdmin = url.pathname.startsWith("/wp-admin/");
41 const isPluginAsset = url.pathname.includes(
42 "/wp-content/plugins/desktop-mode/"
43 );
44 if (!isPortal && !isAdmin && !isPluginAsset) {
45 return;
46 }
47 if (isPluginAsset && isJsAssetPath(url.pathname)) {
48 event.respondWith(networkFirstForAsset(req));
49 return;
50 }
51 if (isPluginAsset && isStaticAssetPath(url.pathname)) {
52 event.respondWith(staleWhileRevalidate(req));
53 return;
54 }
55 if (req.mode === "navigate" && req.destination === "document") {
56 event.respondWith(networkFirstWithOfflineFallback(req));
57 }
58 });
59 sw.addEventListener("push", (event) => {
60 event.waitUntil(Promise.resolve());
61 });
62 sw.addEventListener("notificationclick", (event) => {
63 event.notification.close();
64 event.waitUntil(
65 (async () => {
66 const target = event.notification.data?.url ?? "/desktop-mode/";
67 const all = await sw.clients.matchAll({
68 type: "window",
69 includeUncontrolled: true
70 });
71 const existing = all.find((c) => c.url.includes("/desktop-mode/"));
72 if (existing) {
73 if (typeof existing.focus === "function") {
74 await existing.focus();
75 }
76 return;
77 }
78 if (sw.clients.openWindow) {
79 await sw.clients.openWindow(target);
80 }
81 })()
82 );
83 });
84 async function precache() {
85 try {
86 const cache = await caches.open(STATIC_CACHE);
87 const base = pluginAssetBase();
88 await cache.addAll(PRECACHE_PATHS.map((p) => base + p));
89 } catch {
90 }
91 }
92 function pluginAssetBase() {
93 const here = sw.location.pathname;
94 const idx = here.indexOf("/desktop-mode/");
95 const origin = sw.location.origin;
96 if (idx >= 0) {
97 return origin + "/wp-content/plugins/desktop-mode/";
98 }
99 return origin + "/wp-content/plugins/desktop-mode/";
100 }
101 function isStaticAssetPath(pathname) {
102 return /\.(css|png|jpg|jpeg|svg|webp|woff2?|ttf|gif|ico)$/i.test(
103 pathname
104 );
105 }
106 function isJsAssetPath(pathname) {
107 return /\.js$/i.test(pathname);
108 }
109 async function networkFirstForAsset(req) {
110 const cache = await caches.open(RUNTIME_CACHE);
111 try {
112 const fresh = await fetch(req.url, { cache: "reload" });
113 if (fresh && fresh.status === 200) {
114 cache.put(req, fresh.clone()).catch(() => void 0);
115 }
116 return fresh;
117 } catch {
118 const cached = await cache.match(req);
119 if (cached) {
120 return cached;
121 }
122 return new Response("", { status: 504 });
123 }
124 }
125 async function staleWhileRevalidate(req) {
126 const cache = await caches.open(RUNTIME_CACHE);
127 const cached = await cache.match(req);
128 const network = fetch(req).then((res) => {
129 if (res && res.status === 200) {
130 cache.put(req, res.clone()).catch(() => void 0);
131 }
132 return res;
133 }).catch(() => void 0);
134 if (cached) {
135 return cached;
136 }
137 const fresh = await network;
138 if (fresh) {
139 return fresh;
140 }
141 return new Response("", { status: 504 });
142 }
143 async function networkFirstWithOfflineFallback(req) {
144 try {
145 const fresh = await fetch(req);
146 return fresh;
147 } catch {
148 const cache = await caches.open(STATIC_CACHE);
149 const fallback = await cache.match(OFFLINE_URL);
150 if (fallback) {
151 return fallback;
152 }
153 return new Response(
154 '<!doctype html><meta charset="utf-8"><title>Offline</title><p>You appear to be offline. The app will work again as soon as the connection returns.</p>',
155 {
156 status: 503,
157 headers: { "Content-Type": "text/html; charset=utf-8" }
158 }
159 );
160 }
161 }
162 })();
163