PluginProbe
OpenStation: Desktop Windows, Dock & Virtual Desktops for WP Admin / 0.8.9
OpenStation: Desktop Windows, Dock & Virtual Desktops for WP Admin v0.8.9
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.9, at assets/js/sw.js

169 lines 5.0 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-5";
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/js/desktop.min.js",
14 "assets/js/window-system.min.js",
15 "assets/js/shell-overlays.min.js",
16 "assets/images/wp-logo.png"
17 ];
18 sw.addEventListener("install", (event) => {
19 event.waitUntil(precache());
20 void sw.skipWaiting();
21 });
22 sw.addEventListener("activate", (event) => {
23 event.waitUntil(
24 (async () => {
25 const keys = await caches.keys();
26 await Promise.all(
27 keys.filter((k) => !k.endsWith(VERSION)).map((k) => caches.delete(k))
28 );
29 await sw.clients.claim();
30 })()
31 );
32 });
33 sw.addEventListener("fetch", (event) => {
34 const req = event.request;
35 if (req.method !== "GET") {
36 return;
37 }
38 const url = new URL(req.url);
39 if (url.origin !== sw.location.origin) {
40 return;
41 }
42 const isPortal = url.pathname.startsWith("/desktop-mode/");
43 const isAdmin = url.pathname.startsWith("/wp-admin/");
44 const isPluginAsset = url.pathname.includes(
45 "/wp-content/plugins/desktop-mode/"
46 );
47 if (!isPortal && !isAdmin && !isPluginAsset) {
48 return;
49 }
50 if (isPluginAsset && isJsAssetPath(url.pathname)) {
51 event.respondWith(networkFirstForAsset(req));
52 return;
53 }
54 if (isPluginAsset && isStaticAssetPath(url.pathname)) {
55 event.respondWith(staleWhileRevalidate(req));
56 return;
57 }
58 if (req.mode === "navigate" && req.destination === "document") {
59 event.respondWith(networkFirstWithOfflineFallback(req));
60 }
61 });
62 sw.addEventListener("push", (event) => {
63 event.waitUntil(Promise.resolve());
64 });
65 sw.addEventListener("notificationclick", (event) => {
66 event.notification.close();
67 event.waitUntil(
68 (async () => {
69 const target = event.notification.data?.url ?? "/desktop-mode/";
70 const all = await sw.clients.matchAll({
71 type: "window",
72 includeUncontrolled: true
73 });
74 const existing = all.find((c) => c.url.includes("/desktop-mode/"));
75 if (existing) {
76 if (typeof existing.focus === "function") {
77 await existing.focus();
78 }
79 return;
80 }
81 if (sw.clients.openWindow) {
82 await sw.clients.openWindow(target);
83 }
84 })()
85 );
86 });
87 async function precache() {
88 try {
89 const cache = await caches.open(STATIC_CACHE);
90 const base = pluginAssetBase();
91 await cache.addAll(PRECACHE_PATHS.map((p) => base + p));
92 } catch {
93 }
94 }
95 function pluginAssetBase() {
96 return sw.location.origin + "/wp-content/plugins/desktop-mode/";
97 }
98 function isStaticAssetPath(pathname) {
99 return /\.(css|png|jpg|jpeg|svg|webp|woff2?|ttf|gif|ico)$/i.test(
100 pathname
101 );
102 }
103 function isJsAssetPath(pathname) {
104 return /\.js$/i.test(pathname);
105 }
106 async function networkFirstForAsset(req) {
107 const cache = await caches.open(RUNTIME_CACHE);
108 try {
109 const fresh = await fetch(req.url, { cache: "reload" });
110 if (fresh && fresh.status === 200) {
111 cache.put(req, fresh.clone()).catch(() => void 0);
112 }
113 return fresh;
114 } catch {
115 const cachedRuntime = await cache.match(req);
116 if (cachedRuntime) {
117 return cachedRuntime;
118 }
119 const staticCache = await caches.open(STATIC_CACHE);
120 const cachedStatic = await staticCache.match(req, { ignoreSearch: true });
121 if (cachedStatic) {
122 return cachedStatic;
123 }
124 return new Response("", { status: 504 });
125 }
126 }
127 async function staleWhileRevalidate(req) {
128 const cache = await caches.open(RUNTIME_CACHE);
129 let cached = await cache.match(req);
130 if (!cached) {
131 const staticCache = await caches.open(STATIC_CACHE);
132 cached = await staticCache.match(req, { ignoreSearch: true });
133 }
134 const network = fetch(req).then((res) => {
135 if (res && res.status === 200) {
136 cache.put(req, res.clone()).catch(() => void 0);
137 }
138 return res;
139 }).catch(() => void 0);
140 if (cached) {
141 return cached;
142 }
143 const fresh = await network;
144 if (fresh) {
145 return fresh;
146 }
147 return new Response("", { status: 504 });
148 }
149 async function networkFirstWithOfflineFallback(req) {
150 try {
151 const fresh = await fetch(req);
152 return fresh;
153 } catch {
154 const cache = await caches.open(STATIC_CACHE);
155 const fallback = await cache.match(OFFLINE_URL);
156 if (fallback) {
157 return fallback;
158 }
159 return new Response(
160 '<!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>',
161 {
162 status: 503,
163 headers: { "Content-Type": "text/html; charset=utf-8" }
164 }
165 );
166 }
167 }
168 })();
169