-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathsw.js
More file actions
138 lines (128 loc) · 5.03 KB
/
Copy pathsw.js
File metadata and controls
138 lines (128 loc) · 5.03 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
// SocialSpaces Service Worker
// Cache-first strategy for static shell; network-first for API/Firebase.
const CACHE_NAME = 'socialspaces-v1';
const STATIC_ASSETS = [
'/',
'/index.html',
'/styles.css',
'/manifest.json',
'/pages/login.html',
'/pages/signup.html',
'/pages/dashboard.html',
'/pages/profile.html',
'/pages/my-groups.html',
'/pages/group-manager.html',
'/pages/forgot-password.html',
'/pages/privacy-policy.html',
'/js/dark-mode.js',
'/css/dashboard.css',
];
// ── Install: pre-cache static shell ──────────────────────────────────────────
self.addEventListener('install', (event) => {
event.waitUntil(
caches.open(CACHE_NAME).then((cache) => {
console.log('📦 SW: Pre-caching static assets');
// addAll fails if any single request fails — use individual adds for resilience
return Promise.allSettled(
STATIC_ASSETS.map(url => cache.add(url).catch(e => console.warn('SW: Could not cache', url, e)))
);
})
);
self.skipWaiting();
});
// ── Activate: clean up old caches ─────────────────────────────────────────────
self.addEventListener('activate', (event) => {
event.waitUntil(
caches.keys().then((cacheNames) =>
Promise.all(
cacheNames
.filter((name) => name !== CACHE_NAME)
.map((name) => {
console.log('🗑️ SW: Deleting old cache:', name);
return caches.delete(name);
})
)
)
);
self.clients.claim();
});
// ── Fetch: Smart routing ───────────────────────────────────────────────────────
self.addEventListener('fetch', (event) => {
const url = new URL(event.request.url);
// Never intercept: Firebase, Google APIs, external CDNs
if (
url.hostname.includes('firebase') ||
url.hostname.includes('googleapis') ||
url.hostname.includes('gstatic') ||
url.hostname.includes('firebaseio') ||
url.hostname.includes('osrm') ||
url.hostname.includes('nominatim') ||
url.hostname.includes('emailjs') ||
url.hostname.includes('recaptcha') ||
url.hostname.includes('fonts.cdnfonts') ||
url.hostname.includes('jsdelivr')
) {
return; // Let browser handle external requests natively
}
// For navigation requests (HTML pages): network-first, fall back to cache
if (event.request.mode === 'navigate') {
event.respondWith(
fetch(event.request)
.then((response) => {
// Cache the fresh page
const clone = response.clone();
caches.open(CACHE_NAME).then((cache) => cache.put(event.request, clone));
return response;
})
.catch(() => caches.match(event.request) || caches.match('/pages/login.html'))
);
return;
}
// For static assets (CSS, JS, fonts, images): cache-first
if (
url.pathname.endsWith('.css') ||
url.pathname.endsWith('.js') ||
url.pathname.endsWith('.png') ||
url.pathname.endsWith('.jpg') ||
url.pathname.endsWith('.svg') ||
url.pathname.endsWith('.ico') ||
url.pathname.endsWith('.webp') ||
url.pathname.endsWith('.json')
) {
event.respondWith(
caches.match(event.request).then((cached) => {
if (cached) return cached;
return fetch(event.request).then((response) => {
const clone = response.clone();
caches.open(CACHE_NAME).then((cache) => cache.put(event.request, clone));
return response;
});
})
);
return;
}
// Default: network-first
event.respondWith(
fetch(event.request).catch(() => caches.match(event.request))
);
});
// ── Push Notifications (future) ───────────────────────────────────────────────
self.addEventListener('push', (event) => {
if (!event.data) return;
const data = event.data.json();
event.waitUntil(
self.registration.showNotification(data.title || 'SocialSpaces', {
body: data.message || '',
icon: '/icons/icon-192.png',
badge: '/icons/icon-96.png',
tag: data.tag || 'socialspaces',
data: { url: data.url || '/pages/dashboard.html' }
})
);
});
self.addEventListener('notificationclick', (event) => {
event.notification.close();
event.waitUntil(
clients.openWindow(event.notification.data?.url || '/pages/dashboard.html')
);
});