Odoo18-Base/addons/web/static/src/service_worker.js
2025-01-06 10:57:38 +07:00

92 lines
2.8 KiB
JavaScript

// @odoo-module ignore
/* eslint-disable no-restricted-globals */
const cacheName = "odoo-sw-cache";
const cachedRequests = ["/odoo/offline"];
self.addEventListener("install", (event) => {
event.waitUntil(caches.open(cacheName).then((cache) => cache.addAll(cachedRequests)));
});
const navigateOrDisplayOfflinePage = async (request) => {
try {
return await fetch(request);
} catch (requestError) {
if (
request.method === "GET" &&
["Failed to fetch", "Load failed"].includes(requestError.message)
) {
if (cachedRequests.includes("/odoo/offline")) {
const cache = await caches.open(cacheName);
const cachedResponse = await cache.match("/odoo/offline");
if (cachedResponse) {
return cachedResponse;
}
}
}
throw requestError;
}
};
const serveShareTarget = (event) => {
// Redirect so the user can refresh the page without resending data.
event.respondWith(Response.redirect("/odoo?share_target=trigger"));
event.waitUntil(
(async () => {
// The page sends this message to tell the service worker it's ready to receive the file.
await waitingMessage("odoo_share_target");
const client = await self.clients.get(event.resultingClientId || event.clientId);
const data = await event.request.formData();
client.postMessage({
shared_files: data.getAll("externalMedia") || [],
action: "odoo_share_target_ack",
});
})()
);
};
self.addEventListener("fetch", (event) => {
if (
event.request.method === "POST" &&
new URL(event.request.url).searchParams.has("share_target")
) {
return serveShareTarget(event);
}
if (
(event.request.mode === "navigate" && event.request.destination === "document") ||
// request.mode = navigate isn't supported in all browsers => check for http header accept:text/html
event.request.headers.get("accept").includes("text/html")
) {
event.respondWith(navigateOrDisplayOfflinePage(event.request));
}
});
/**
*
* @type {Map<String, Function[]>}
*/
const nextMessageMap = new Map();
/**
*
* @param message : string
* @return {Promise}
*/
const waitingMessage = async (message) => {
return new Promise((resolve) => {
if (!nextMessageMap.has(message)) {
nextMessageMap.set(message, []);
}
nextMessageMap.get(message).push(resolve);
});
};
self.addEventListener("message", (event) => {
const messageNotifiers = nextMessageMap.get(event.data);
if (messageNotifiers) {
for (const messageNotified of messageNotifiers) {
messageNotified();
}
nextMessageMap.delete(event.data);
}
});