-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathsw.js
More file actions
113 lines (106 loc) · 3.38 KB
/
Copy pathsw.js
File metadata and controls
113 lines (106 loc) · 3.38 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
const CACHE = 'tap-counter-v13';
const ASSETS = [
'./',
'./index.html',
'./manifest.webmanifest',
'./fonts/amiri-latin-400.woff2',
'./fonts/amiri-latin-700.woff2',
'./fonts/amiri-arabic-400.woff2',
'./fonts/amiri-arabic-700.woff2',
'./icon-192.png',
'./icon-512.png',
'./apple-touch-icon.png'
];
self.addEventListener('install', (e) => {
e.waitUntil(caches.open(CACHE).then((c) => c.addAll(ASSETS)));
self.skipWaiting();
});
self.addEventListener('activate', (e) => {
e.waitUntil(
caches.keys().then((keys) =>
Promise.all(keys.filter((k) => k !== CACHE).map((k) => caches.delete(k)))
).then(() => self.clients.claim())
);
});
/* ---- daily wird reminders (periodic background sync, Android) ---- */
function idbOpen() {
return new Promise((res, rej) => {
const r = indexedDB.open('wird-db', 1);
r.onupgradeneeded = () => r.result.createObjectStore('kv');
r.onsuccess = () => res(r.result);
r.onerror = () => rej(r.error);
});
}
async function idbGet(k) {
try {
const db = await idbOpen();
return await new Promise((res) => {
const q = db.transaction('kv').objectStore('kv').get(k);
q.onsuccess = () => res(q.result);
q.onerror = () => res(null);
});
} catch (e) { return null; }
}
async function idbSet(k, v) {
try {
const db = await idbOpen();
await new Promise((res) => {
const t = db.transaction('kv', 'readwrite');
t.objectStore('kv').put(v, k);
t.oncomplete = res;
t.onerror = res;
});
} catch (e) {}
}
async function checkReminders() {
const st = await idbGet('state');
if (!st || !st.reminders) return;
const now = new Date();
const today = now.getFullYear() + '-'
+ String(now.getMonth() + 1).padStart(2, '0') + '-'
+ String(now.getDate()).padStart(2, '0');
if (st.date !== today) {
// a new day began while the app was closed: nothing is done yet
st.date = today;
for (const r of st.reminders) { r.done = false; r.left = 0; }
}
const hhmm = String(now.getHours()).padStart(2, '0') + ':' + String(now.getMinutes()).padStart(2, '0');
let changed = false;
for (const r of st.reminders) {
if (r.time && !r.done && r.notifiedOn !== today && hhmm >= r.time) {
await self.registration.showNotification('🌙 ' + r.name, {
body: 'Time for your wird — ' + (r.left ? r.left + ' reading' + (r.left === 1 ? '' : 's') + ' left today.' : 'it is waiting for you.'),
icon: 'icon-192.png',
badge: 'icon-192.png',
tag: 'wird-' + r.id
});
r.notifiedOn = today;
changed = true;
}
}
if (changed || st.date === today) await idbSet('state', st);
}
self.addEventListener('periodicsync', (e) => {
if (e.tag === 'wird-reminders') e.waitUntil(checkReminders());
});
self.addEventListener('notificationclick', (e) => {
e.notification.close();
e.waitUntil(
clients.matchAll({ type: 'window', includeUncontrolled: true }).then((ws) =>
ws.length ? ws[0].focus() : clients.openWindow('./')
)
);
});
// cache-first: the app works fully offline once installed
self.addEventListener('fetch', (e) => {
if (e.request.method !== 'GET') return;
e.respondWith(
caches.match(e.request, { ignoreSearch: true }).then(
(hit) => hit || fetch(e.request).then((res) => {
const copy = res.clone();
caches.open(CACHE).then((c) => c.put(e.request, copy));
return res;
})
)
);
});