-
Notifications
You must be signed in to change notification settings - Fork 5
/
Copy pathsw.js
138 lines (131 loc) · 3.99 KB
/
sw.js
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
/*
FlagPlayer - A lightweight YouTube frontend
Copyright (C) 2019 Seneral
Licensed under AGPLv3
See https://github.com/Seneral/FlagPlayer for details
*/
var VERSION = 54;
var APP_CACHE = "flagplayer-cache-1";
var IMG_CACHE = "flagplayer-thumbs";
var MEDIA_CACHE = "flagplayer-media";
var VIRT_CACHE = "https://flagplayer.seneral.dev/caches/vd-"; // Virtual adress used for caching. Doesn't actually exist, but needs to be https
var BASE = location.href.substring(0, location.href.lastIndexOf("/"));
var reMainPage = new RegExp(BASE.replace("/", "\\/") + "(|\\/|\\/index\\.html)(\\?.*)?$")
var database;
var dbLoading = false;
var dbPromises = [];
// Database access - minimal, no error handling, since it's only readonly and assumes a working database management on the main site
function db_access() {
return new Promise(function(accept, reject) {
if (!indexedDB) reject();
else if (database) accept(database);
else {
dbPromises.push(accept);
if (dbLoading) return;
dbLoading = true;
// Open
var request = indexedDB.open("ContentDatabase");
request.onerror = reject;
request.onsuccess = function(e) { // Ready
database = e.target.result;
database.onerror = reject;
database.onclose = () => database = undefined;
dbLoading = false;
dbPromises.forEach((acc) => acc(database));
dbPromises = [];
};
}
});
}
function db_hasVideo(videoID) {
return new Promise(function(accept, reject) {
db_access().then(function(db) {
var request = db.transaction("videos", "readonly").objectStore("videos").get(videoID);
request.onerror = reject;
request.onsuccess = function(e) {
if (e.target.result) accept();
else reject();
};
}).catch(reject);
});
}
self.addEventListener('install', function(event) {
event.waitUntil(
caches.open(APP_CACHE)
.then(function(cache) {
return cache.addAll([
"./style.css",
"./index.html",
"./page.js"
]);
})
);
});
self.addEventListener('activate', function(event) {
event.waitUntil(
// Delete unused stuff (most likely not whole caches, but keys in caches)
caches.keys().then(keys => Promise.all(
keys.map(key => {
if (key.startsWith("flagplayer-cache-") && key != APP_CACHE)
return caches.delete(key);
})
))
);
});
self.addEventListener('message', function(event) {
if (event.data.action === 'skipWaiting') self.skipWaiting();
});
self.addEventListener('fetch', function(event) {
var url = event.request.url;
if (url.match(reMainPage)) { // Always use cached app html
event.respondWith(caches.match("./index.html"));
}
else if (url.includes(VIRT_CACHE)) { // Try to read from the media cache
var bytes = /^bytes\=(\d+)\-$/g.exec(event.request.headers.get('range'));
var pos = Number(bytes? bytes[1] : 0);
event.respondWith(
caches.open("flagplayer-media")
.then(function(cache) {
return cache.match(url);
}).then(function(cacheResponse) {
if (cacheResponse)
return cacheResponse;
return fetch(event.request);
}).then(function(response) {
return response.arrayBuffer()
.then(function(byteData) {
return new Response(byteData.slice(pos), {
status: 206,
statusText: 'Partial Content',
headers: [
['Content-Type', response.headers.get("content-type") ],
['Content-Range', 'bytes ' + pos + '-' +
(byteData.byteLength - 1) + '/' + byteData.byteLength
]
]
});
})
})
);
}
else {
event.respondWith(
caches.match(event.request)
.then(function(response) {
// From cache
if (response) return response;
// Fetch from net
return fetch(event.request).then(function(response) {
if (!response || (response.status !== 200 && response.status !== 0) || response.type == 'error')
return response;
// Cache if desired
if (url.startsWith(BASE + "/favicon")) {
var cacheResponse = response.clone();
event.waitUntil(caches.open(APP_CACHE).then(cache => cache.put(event.request, cacheResponse)));
}
return response;
}).catch(function(error) {});
})
);
}
});