Keep notification-read state personal to user/company, preserve server read-only sections during staff synchronization, and respect separate order-create/edit/delete rights. Add visible mobile header session actions and a sticky logout that survives profile RPC failure; scope asynchronous profile/branding to user and workspace. Targeted browser suites and isolated SQL recovery tests passed in run 35506145405, iPhone screenshots reviewed. Full main QA remains required before production promotion. Workspace branding RPC migration is included but has NOT been applied to production Supabase; older servers retain safe owner-only fallback. No live membership/business-data repair is claimed without identifying the reported employee.
64 lines
5.2 KiB
JavaScript
64 lines
5.2 KiB
JavaScript
const CACHE='sun-catering-pwa-v110-20260918-ui-stability-20260919-client-menu-support-bot-training-catalog-banquet-onepage-employee-session';
|
|
const VERSION='20260918-ui-stability';
|
|
const CORE=[
|
|
'./core/banquet-client-menu.js?v=20260920-onepage',
|
|
'./core/training-catalog.js?v=20260920-training',
|
|
'./core/catalog-pricing.js?v=20260919-client-menu','./core/client-menu.css?v=20260919-client-menu',
|
|
'./vendor/supabase-2.112.4.min.js',
|
|
`./core/help-center.js?v=${VERSION}`,`./core/help-center.css?v=${VERSION}`,`./help/knowledge-v1.json?v=${VERSION}`,
|
|
'./','./index.html',`./core/mobile-order.js?v=${VERSION}`,`./core/proposal-layout.js?v=${VERSION}`,'./fonts/Manrope.ttf','./fonts/PlayfairDisplay.ttf','./fonts/PlayfairDisplay-Italic.ttf',`./core/trial-demo.js?v=${VERSION}`,`./core/cloud-transport.js?v=${VERSION}`,`./core/banquet-menu.js?v=${VERSION}`,`./core/access-policy.js?v=${VERSION}`,`./core/import-archive.js?v=${VERSION}`,`./core/company-branding.js?v=${VERSION}`,`./core/signature-offer-pdf-v18.js?v=${VERSION}`,`./core/brand-theme.js?v=${VERSION}`,
|
|
`./core/sun-safe.js?v=${VERSION}`,`./core/performance.js?v=${VERSION}`,`./core/account-center-v1780.js?v=${VERSION}`,`./core/login-signature-v1776.js?v=${VERSION}`,`./core/login-signature-v1776.css?v=${VERSION}`,`./core/data-layer-v1773.js?v=${VERSION}`,`./core/server-automation-v1770.js?v=${VERSION}`,`./core/hotfix-v1763.js?v=${VERSION}`,`./core/ops-ux-v1762.js?v=${VERSION}`,`./core/ux-fixes-v1764.js?v=${VERSION}`,`./core/pdf-engine.js?v=${VERSION}`,`./core/classic-offer-pdf-v1767.js?v=${VERSION}`,`./core/developer-console-v1768.js?v=${VERSION}`,`./core/offer-workspace-v1769.js?v=${VERSION}`,`./core/auth-security-v1774.js?v=${VERSION}`,`./core/order-enhancements-v1775.js?v=${VERSION}`,`./legacy/bootstrap.js?v=${VERSION}`,`./app-runtime.js?v=${VERSION}`,
|
|
'./offer-gallery/001.jpg','./offer-gallery/002.jpg',
|
|
'./catalog/001.jpg','./catalog/002.jpg','./catalog/003.jpg',
|
|
'./sun-logo.png','./caterium-login-logo.png','./caterium-mark-light.svg','./pwa-icon-192.png','./pwa-icon-512.png','./manifest.webmanifest',
|
|
'./offer-templates/thumb-light.jpg','./offer-templates/thumb-editorial-grid.jpg','./offer-templates/thumb-midnight-glass.jpg','./offer-templates/thumb-emerald-gold.jpg'
|
|
];
|
|
const CRITICAL_FRESH=new Set([
|
|
'/core/banquet-client-menu.js',
|
|
'/core/training-catalog.js',
|
|
'/core/catalog-pricing.js','/core/client-menu.css',
|
|
'/core/help-center.js','/core/help-center.css','/help/knowledge-v1.json',
|
|
'/core/mobile-order.js','/core/cloud-transport.js','/core/trial-demo.js','/core/proposal-layout.js',
|
|
'/core/banquet-menu.js','/core/access-policy.js','/core/import-archive.js','/core/company-branding.js','/core/brand-theme.js','/core/sun-safe.js','/core/performance.js','/core/account-center-v1780.js','/core/login-signature-v1776.js','/core/login-signature-v1776.css','/core/auth-security-v1774.js','/legacy/bootstrap.js','/app-runtime.js'
|
|
]);
|
|
self.addEventListener('install',event=>{
|
|
event.waitUntil(caches.open(CACHE).then(cache=>cache.addAll(CORE)).then(()=>self.skipWaiting()));
|
|
});
|
|
self.addEventListener('activate',event=>{
|
|
event.waitUntil(caches.keys().then(keys=>Promise.all(keys.filter(k=>k.startsWith('sun-catering-pwa-')&&k!==CACHE).map(k=>caches.delete(k)))).then(()=>self.clients.claim()));
|
|
});
|
|
function cachePut(req,res){
|
|
if(res&&res.ok){const clone=res.clone();caches.open(CACHE).then(c=>c.put(req,clone)).catch(()=>{});}return res;
|
|
}
|
|
function networkFirst(req,fallback){
|
|
return fetch(req,{cache:'no-store'}).then(res=>cachePut(req,res)).catch(()=>caches.match(req).then(hit=>hit||caches.match(fallback||req)));
|
|
}
|
|
function forceFresh(req){
|
|
const url=new URL(req.url);url.searchParams.set('__caterium_release',VERSION);
|
|
return fetch(url.toString(),{cache:'no-store',credentials:'same-origin'}).then(res=>cachePut(req,res)).catch(()=>caches.match(req));
|
|
}
|
|
self.addEventListener('fetch',event=>{
|
|
const req=event.request;if(req.method!=='GET')return;
|
|
const url=new URL(req.url);if(url.origin!==self.location.origin||url.pathname.startsWith('/api/'))return;
|
|
// Static PNGs can bypass Apache rewrites on the production host. Resolve old
|
|
// catalog/editor/document URLs here too, before checking the original cache.
|
|
if(/^\/demo\/images\/(?:berry-dessert|bruschetta-tomato|caprese|cheese-fruit|chicken-sandwich|meat-assortment|mushroom-tartlet|salmon-cream|turkey-wrap|vegetables-hummus)\.png$/.test(url.pathname)){
|
|
url.pathname=url.pathname.replace(/\.png$/,'.webp');
|
|
const optimized=new Request(url.toString(),{credentials:'same-origin'});
|
|
event.respondWith(caches.match(optimized).then(hit=>hit||fetch(optimized).then(res=>res.ok?cachePut(optimized,res):fetch(req))));
|
|
return;
|
|
}
|
|
if(req.mode==='navigate'){
|
|
event.respondWith(
|
|
fetch(req,{cache:'no-store'})
|
|
.then(res=>{const clone=res.clone();caches.open(CACHE).then(c=>c.put('./index.html',clone)).catch(()=>{});return res;})
|
|
.catch(()=>caches.match('./index.html'))
|
|
);
|
|
return;
|
|
}
|
|
if(CRITICAL_FRESH.has(url.pathname)){event.respondWith(forceFresh(req));return;}
|
|
const freshAsset=/\.(?:js|css|webmanifest)$/i.test(url.pathname);
|
|
if(freshAsset){event.respondWith(networkFirst(req));return;}
|
|
event.respondWith(caches.match(req).then(cached=>cached||fetch(req,{cache:'no-store'}).then(res=>cachePut(req,res))));
|
|
});
|