basket random
@@ -103,6 +103,11 @@
|
||||
"aliases": [],
|
||||
"categories": []
|
||||
},
|
||||
"Basket Random": {
|
||||
"path": "basket-random",
|
||||
"aliases": [],
|
||||
"categories": []
|
||||
},
|
||||
"Basketball Stars": {
|
||||
"path": "basketball-stars",
|
||||
"aliases": [],
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
{
|
||||
"name": "Basket Random",
|
||||
"short_name": "Basket Random",
|
||||
"description": "",
|
||||
"start_url": "index.html",
|
||||
"display": "fullscreen",
|
||||
"orientation": "any",
|
||||
"background_color": "#ffffff",
|
||||
"icons": []
|
||||
}
|
||||
|
After Width: | Height: | Size: 2.0 KiB |
|
After Width: | Height: | Size: 1.9 KiB |
|
After Width: | Height: | Size: 2.0 KiB |
|
After Width: | Height: | Size: 1.9 KiB |
|
After Width: | Height: | Size: 775 B |
|
After Width: | Height: | Size: 212 B |
|
After Width: | Height: | Size: 282 B |
|
After Width: | Height: | Size: 1.6 KiB |
|
After Width: | Height: | Size: 512 B |
|
After Width: | Height: | Size: 236 B |
|
After Width: | Height: | Size: 135 B |
|
After Width: | Height: | Size: 253 B |
|
After Width: | Height: | Size: 79 B |
|
After Width: | Height: | Size: 505 B |
|
After Width: | Height: | Size: 472 B |
|
After Width: | Height: | Size: 239 B |
|
After Width: | Height: | Size: 139 B |
|
After Width: | Height: | Size: 89 B |
|
After Width: | Height: | Size: 828 B |
|
After Width: | Height: | Size: 677 B |
|
After Width: | Height: | Size: 141 B |
|
After Width: | Height: | Size: 6.7 KiB |
|
After Width: | Height: | Size: 14 KiB |
|
After Width: | Height: | Size: 2.4 KiB |
|
After Width: | Height: | Size: 390 B |
|
After Width: | Height: | Size: 70 B |
|
After Width: | Height: | Size: 1.8 KiB |
|
After Width: | Height: | Size: 1.6 KiB |
|
After Width: | Height: | Size: 267 B |
|
After Width: | Height: | Size: 76 B |
|
After Width: | Height: | Size: 1.2 KiB |
|
After Width: | Height: | Size: 714 B |
@@ -0,0 +1,44 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<title>Basket Random </title>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0, user-scalable=no" />
|
||||
<meta name="generator" content="Construct 3" />
|
||||
|
||||
<link rel="manifest" href="appmanifest.json" />
|
||||
<link rel="icon" href="./splash.jpeg">
|
||||
<link rel="stylesheet" href="style.css" />
|
||||
<script>
|
||||
window.addEventListener(
|
||||
"keydown",
|
||||
function (e) {
|
||||
// space and arrow keys
|
||||
if ([32, 37, 38, 39, 40].indexOf(e.keyCode) > -1) {
|
||||
e.preventDefault();
|
||||
}
|
||||
},
|
||||
false
|
||||
);
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
<script src="box2d.wasm.js"></script>
|
||||
<noscript>
|
||||
<div id="notSupportedWrap">
|
||||
<h2 id="notSupportedTitle">This content requires JavaScript</h2>
|
||||
<p class="notSupportedMessage">
|
||||
JavaScript appears to be disabled. Please enable it to view this content.
|
||||
</p>
|
||||
<p class="notSupportedMessage">
|
||||
This content was made with Construct 3 - a
|
||||
<a href="https://www.construct.net/en">free game maker</a>.
|
||||
</p>
|
||||
</div>
|
||||
</noscript>
|
||||
<script src="scripts/supportcheck.js"></script>
|
||||
<script src="scripts/offlineclient.js"></script>
|
||||
<script src="scripts/main.js"></script>
|
||||
<script src="scripts/register-sw.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,144 @@
|
||||
'use strict';
|
||||
(self.inputPort = null),
|
||||
(self.jobQueue = []),
|
||||
(self.jobWorkers = []),
|
||||
(self.sentBlobs = []),
|
||||
(self.sentBuffers = []),
|
||||
(self.importedScripts = []),
|
||||
(self.lastBroadcasts = new Map());
|
||||
class JobWorker {
|
||||
constructor(a, b) {
|
||||
(this._port = a),
|
||||
(this._number = b),
|
||||
(this._isReady = !1),
|
||||
(this._isBusy = !1),
|
||||
(this._port.onmessage = (a) => this._OnMessage(a.data));
|
||||
}
|
||||
ImportScripts(a) {
|
||||
this._port.postMessage({ type: '_import_scripts', scripts: a });
|
||||
}
|
||||
SendBlob(a, b) {
|
||||
this._port.postMessage({ type: '_send_blob', blob: a, id: b });
|
||||
}
|
||||
SendBuffer(a, b) {
|
||||
this._port.postMessage({ type: '_send_buffer', buffer: a, id: b });
|
||||
}
|
||||
SendJob(a) {
|
||||
if (this._isBusy || !this._isReady) throw new Error('cannot take job');
|
||||
(this._isBusy = !0), this._port.postMessage(a, a['transferables']);
|
||||
}
|
||||
_InitBroadcast(a) {
|
||||
this._port.postMessage(a, a['transferables']);
|
||||
}
|
||||
SendReady() {
|
||||
this._port.postMessage({ type: '_ready' });
|
||||
}
|
||||
IsReady() {
|
||||
return this._isReady;
|
||||
}
|
||||
_OnReady() {
|
||||
(this._isReady = !0), this.MaybeStartNextJob();
|
||||
}
|
||||
IsBusy() {
|
||||
return this._isBusy;
|
||||
}
|
||||
GetNumber() {
|
||||
return this._number;
|
||||
}
|
||||
_OnMessage(a) {
|
||||
const b = a['type'];
|
||||
return 'ready' === b
|
||||
? void this._OnReady()
|
||||
: 'done' === b
|
||||
? void this._OnJobDone()
|
||||
: void console.error("unknown message from worker '" + b + "'");
|
||||
}
|
||||
_OnJobDone() {
|
||||
(this._isBusy = !1), this.MaybeStartNextJob();
|
||||
}
|
||||
MaybeStartNextJob() {
|
||||
if (!this._isBusy && this._isReady) {
|
||||
const a = this._FindAvailableJob();
|
||||
if (-1 !== a) {
|
||||
const b = self.jobQueue[a],
|
||||
c = b['isBroadcast'];
|
||||
c
|
||||
? ((b['doneFlags'][this._number] = !0),
|
||||
b['doneFlags'].every((a) => a) && self.jobQueue.splice(a, 1))
|
||||
: self.jobQueue.splice(a, 1),
|
||||
this.SendJob(b);
|
||||
}
|
||||
}
|
||||
}
|
||||
_FindAvailableJob() {
|
||||
for (let a = 0, b = self.jobQueue.length; a < b; ++a) {
|
||||
const b = self.jobQueue[a];
|
||||
if (
|
||||
!b['isBroadcast'] ||
|
||||
(this._number < b['doneFlags'].length && !b['doneFlags'][this._number])
|
||||
)
|
||||
return a;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
TestMessageChannel() {
|
||||
this._port.postMessage({ type: '_testMessageChannel' });
|
||||
}
|
||||
}
|
||||
let number = 0;
|
||||
function AddJobWorker(a) {
|
||||
const b = new JobWorker(a, number++);
|
||||
self.jobWorkers.push(b);
|
||||
for (const [c, d] of self.sentBlobs) b.SendBlob(c, d);
|
||||
for (const [c, d] of self.sentBuffers) b.SendBuffer(c, d);
|
||||
for (const c of self.importedScripts) b.ImportScripts(c);
|
||||
for (const c of self.lastBroadcasts.values()) b._InitBroadcast(c);
|
||||
b.SendReady();
|
||||
}
|
||||
function CancelJob(a) {
|
||||
for (let b = 0, c = self.jobQueue.length; b < c; ++b)
|
||||
if (self.jobQueue[b].jobId === a) return void self.jobQueue.splice(b, 1);
|
||||
}
|
||||
self.addEventListener('message', (a) => {
|
||||
const b = a.data,
|
||||
c = b['type'];
|
||||
'_init' === c
|
||||
? ((self.inputPort = b['in-port']), (self.inputPort.onmessage = OnInputPortMessage))
|
||||
: '_addJobWorker' === c && AddJobWorker(b['port']);
|
||||
});
|
||||
function OnInputPortMessage(a) {
|
||||
const b = a.data,
|
||||
c = b['type'];
|
||||
if ('_cancel' === c) return void CancelJob(b.jobId);
|
||||
if ('_import_scripts' === c) {
|
||||
const a = b['scripts'];
|
||||
for (const b of self.jobWorkers) b.ImportScripts(a);
|
||||
return void self.importedScripts.push(a);
|
||||
}
|
||||
if ('_send_blob' === c) {
|
||||
const a = b['blob'],
|
||||
c = b['id'];
|
||||
for (const b of self.jobWorkers) b.SendBlob(a, c);
|
||||
return void self.sentBlobs.push([a, c]);
|
||||
}
|
||||
if ('_send_buffer' === c) {
|
||||
const a = b['buffer'],
|
||||
c = b['id'];
|
||||
for (const b of self.jobWorkers) b.SendBuffer(a, c);
|
||||
return void self.sentBuffers.push([a, c]);
|
||||
}
|
||||
if ('_no_more_workers' === c)
|
||||
return (
|
||||
(self.sentBlobs.length = 0),
|
||||
(self.sentBuffers.length = 0),
|
||||
(self.importedScripts.length = 0),
|
||||
void self.lastBroadcasts.clear()
|
||||
);
|
||||
if ('_testMessageChannel' === c) return void self.jobWorkers[0].TestMessageChannel();
|
||||
self.jobQueue.push(b),
|
||||
b['isBroadcast'] &&
|
||||
((b['doneFlags'] = Array(self.jobWorkers.length).fill(!1)),
|
||||
(b['transferables'] = []),
|
||||
self.lastBroadcasts.set(b['type'], b));
|
||||
for (const b of self.jobWorkers) b.MaybeStartNextJob();
|
||||
}
|
||||
@@ -0,0 +1,94 @@
|
||||
'use strict';
|
||||
(self.dispatchPort = null),
|
||||
(self.outputPort = null),
|
||||
(self.workerNumber = -1),
|
||||
(self.activeJobId = null),
|
||||
(self.sentBlobs = new Map()),
|
||||
(self.sentBuffers = new Map()),
|
||||
(self.JobHandlers = {});
|
||||
function FlipImageData(a, b, c) {
|
||||
const d = 4 * b,
|
||||
e = new Uint8Array(d),
|
||||
f = a.buffer;
|
||||
for (let g = 0, h = Math.floor(c / 2); g < h; ++g) {
|
||||
const a = c - g - 1,
|
||||
b = new Uint8Array(f, g * d, d),
|
||||
h = new Uint8Array(f, a * d, d);
|
||||
e.set(b), b.set(h), h.set(e);
|
||||
}
|
||||
}
|
||||
function UnpremultiplyImageData(b) {
|
||||
for (let c = 0, a = b.length; c < a; c += 4) {
|
||||
const d = b[c + 3];
|
||||
if (255 === d) continue;
|
||||
const a = 255 / d;
|
||||
(b[c] *= a), (b[c + 1] *= a), (b[c + 2] *= a);
|
||||
}
|
||||
}
|
||||
(self.JobHandlers['ProcessImageData'] = function (a) {
|
||||
const b = a['buffer'],
|
||||
c = new Uint8Array(b),
|
||||
d = a['width'],
|
||||
e = a['height'];
|
||||
return (
|
||||
a['flipY'] && FlipImageData(c, d, e),
|
||||
a['unpremultiply'] && UnpremultiplyImageData(c),
|
||||
{ result: b, transferables: [b] }
|
||||
);
|
||||
}),
|
||||
self.addEventListener('message', (a) => {
|
||||
const b = a.data,
|
||||
c = b['type'];
|
||||
return 'init' === c
|
||||
? ((self.workerNumber = b['number']),
|
||||
(self.dispatchPort = b['dispatch-port']),
|
||||
(self.dispatchPort.onmessage = OnDispatchWorkerMessage),
|
||||
void (self.outputPort = b['output-port']))
|
||||
: 'terminate' === c
|
||||
? void self.close()
|
||||
: void console.error("unknown message '" + c + "'");
|
||||
});
|
||||
function SendReady() {
|
||||
self.dispatchPort.postMessage({ type: 'ready' }), self.outputPort.postMessage({ type: 'ready' });
|
||||
}
|
||||
function SendError(a, b) {
|
||||
a || self.outputPort.postMessage({ type: 'error', jobId: self.activeJobId, error: b.toString() }),
|
||||
SendDone();
|
||||
}
|
||||
function SendResult(a, b) {
|
||||
if (!a) {
|
||||
const a = b.transferables || [];
|
||||
self.outputPort.postMessage({ type: 'result', jobId: self.activeJobId, result: b.result }, a);
|
||||
}
|
||||
SendDone();
|
||||
}
|
||||
function SendDone() {
|
||||
(self.activeJobId = null), self.dispatchPort.postMessage({ type: 'done' });
|
||||
}
|
||||
function SendProgress(a) {
|
||||
self.outputPort.postMessage({ type: 'progress', jobId: self.activeJobId, progress: a });
|
||||
}
|
||||
function OnDispatchWorkerMessage(a) {
|
||||
const b = a.data,
|
||||
c = b['type'];
|
||||
if ('_import_scripts' === c) return void importScripts(...b['scripts']);
|
||||
if ('_send_blob' === c) return void self.sentBlobs.set(b['id'], b['blob']);
|
||||
if ('_send_buffer' === c) return void self.sentBuffers.set(b['id'], b['buffer']);
|
||||
if ('_testMessageChannel' === c)
|
||||
return void self.outputPort.postMessage({ type: '_testMessageChannelOk' });
|
||||
if ('_ready' === c) return void SendReady();
|
||||
const d = b['jobId'],
|
||||
f = b['isBroadcast'],
|
||||
e = b['params'];
|
||||
let g;
|
||||
if (((self.activeJobId = d), !self.JobHandlers.hasOwnProperty(c)))
|
||||
return void console.error(`no handler for message type '${c}'`);
|
||||
try {
|
||||
g = self.JobHandlers[c](e);
|
||||
} catch (a) {
|
||||
return void SendError(f, 'Exception in job handler: ' + a);
|
||||
}
|
||||
g && g.then
|
||||
? g.then((a) => SendResult(f, a)).catch((a) => SendError(f, 'Rejection in job handler: ' + a))
|
||||
: SendResult(f, g);
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
'use strict';
|
||||
{
|
||||
window.OfflineClientInfo = new (class {
|
||||
constructor() {
|
||||
if (
|
||||
((this._broadcastChannel =
|
||||
'undefined' == typeof BroadcastChannel ? null : new BroadcastChannel('offline')),
|
||||
(this._queuedMessages = []),
|
||||
(this._onMessageCallback = null),
|
||||
this._broadcastChannel)
|
||||
) {
|
||||
var a = this;
|
||||
this._broadcastChannel.onmessage = function (b) {
|
||||
a._OnBroadcastChannelMessage(b);
|
||||
};
|
||||
}
|
||||
}
|
||||
_OnBroadcastChannelMessage(a) {
|
||||
return this._onMessageCallback
|
||||
? void this._onMessageCallback(a)
|
||||
: void this._queuedMessages.push(a);
|
||||
}
|
||||
SetMessageCallback(a) {
|
||||
this._onMessageCallback = a;
|
||||
for (let b of this._queuedMessages) this._onMessageCallback(b);
|
||||
this._queuedMessages.length = 0;
|
||||
}
|
||||
})();
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
'use strict';
|
||||
window.C3_RegisterSW = async function () {
|
||||
if (navigator.serviceWorker)
|
||||
try {
|
||||
const a = await navigator.serviceWorker.register('sw.js', { scope: './' });
|
||||
console.info('Registered service worker on ' + a.scope);
|
||||
} catch (a) {
|
||||
console.warn('Failed to register service worker: ', a);
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,49 @@
|
||||
'use strict';
|
||||
(function () {
|
||||
var a = !!document.querySelector('script[src*="kaspersky"]'),
|
||||
b = document.createElement('canvas'),
|
||||
c = !!(b.getContext('webgl') || b.getContext('experimental-webgl')),
|
||||
d = [];
|
||||
if (
|
||||
(c || d.push('WebGL'),
|
||||
'undefined' == typeof WebAssembly && d.push('WebAssembly'),
|
||||
0 === d.length && !a)
|
||||
)
|
||||
window['C3_IsSupported'] = !0;
|
||||
else {
|
||||
var e = document.createElement('div');
|
||||
(e.id = 'notSupportedWrap'), document.body.appendChild(e);
|
||||
var f = document.createElement('h2');
|
||||
(f.id = 'notSupportedTitle'),
|
||||
(f.textContent = a
|
||||
? 'Kaspersky Internet Security broke this export'
|
||||
: 'Software update needed'),
|
||||
e.appendChild(f);
|
||||
var g = document.createElement('p');
|
||||
g.className = 'notSupportedMessage';
|
||||
var h = "This content is not supported because your device's software is out-of-date. ",
|
||||
i = navigator.userAgent;
|
||||
/android/i.test(i)
|
||||
? (h +=
|
||||
'<br><br>On Android, fix this by making sure the <a href="https://play.google.com/store/apps/details?id=com.google.android.webview">Android System Webview</a> app has updates enabled and is up-to-date.')
|
||||
: /iphone|ipad|ipod/i.test(i)
|
||||
? (h +=
|
||||
"<br><br>Note: the <strong>iOS simulator</strong> is not currently supported due to an <a href='https://bugs.webkit.org/show_bug.cgi?id=191064'>Apple bug</a>. If you are using the simulator, try testing on a real device instead.")
|
||||
: (/msie/i.test(i) || /trident/i.test(i)) && !/edge\//i.test(i)
|
||||
? (h +=
|
||||
"<br><br>Note: <strong>Internet Explorer</strong> is not supported. Try using <a href='https://www.google.com/chrome'>Chrome</a> or <a href='https://www.mozilla.org/firefox'>Firefox</a> instead.")
|
||||
: a
|
||||
? (h =
|
||||
'It appears a script was added to this export by Kaspersky software. This prevents the exported project from working. Try disabling Kaspersky and exporting again.')
|
||||
: (h +=
|
||||
'Try installing any available software updates. Alternatively try on a different device.'),
|
||||
(h +=
|
||||
'<br><br><em>Missing features: ' +
|
||||
d.join(', ') +
|
||||
'<br>User agent: ' +
|
||||
navigator.userAgent +
|
||||
'</em>'),
|
||||
(g.innerHTML = h),
|
||||
e.appendChild(g);
|
||||
}
|
||||
})();
|
||||
|
After Width: | Height: | Size: 46 KiB |
@@ -0,0 +1,41 @@
|
||||
html,
|
||||
body {
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
overflow: hidden;
|
||||
|
||||
background: #000000;
|
||||
color: white;
|
||||
}
|
||||
|
||||
html,
|
||||
body,
|
||||
canvas {
|
||||
touch-action: none;
|
||||
touch-action-delay: none;
|
||||
}
|
||||
|
||||
#notSupportedWrap {
|
||||
margin: 2em auto 1em auto;
|
||||
width: 75%;
|
||||
max-width: 45em;
|
||||
border: 2px solid #aaa;
|
||||
border-radius: 1em;
|
||||
padding: 2em;
|
||||
background-color: #f0f0f0;
|
||||
font-family: 'Segoe UI', Frutiger, 'Frutiger Linotype', 'Dejavu Sans', 'Helvetica Neue', Arial,
|
||||
sans-serif;
|
||||
color: black;
|
||||
}
|
||||
|
||||
#notSupportedTitle {
|
||||
font-size: 1.8em;
|
||||
}
|
||||
|
||||
.notSupportedMessage {
|
||||
font-size: 1.2em;
|
||||
}
|
||||
|
||||
.notSupportedMessage em {
|
||||
color: #888;
|
||||
}
|
||||
@@ -0,0 +1,166 @@
|
||||
'use strict';
|
||||
const OFFLINE_DATA_FILE = 'offline.json',
|
||||
CACHE_NAME_PREFIX = 'c3offline',
|
||||
BROADCASTCHANNEL_NAME = 'offline',
|
||||
CONSOLE_PREFIX = '[SW] ',
|
||||
LAZYLOAD_KEYNAME = '',
|
||||
broadcastChannel =
|
||||
'undefined' == typeof BroadcastChannel ? null : new BroadcastChannel('offline');
|
||||
function PostBroadcastMessage(a) {
|
||||
broadcastChannel && setTimeout(() => broadcastChannel.postMessage(a), 3e3);
|
||||
}
|
||||
function Broadcast(a) {
|
||||
PostBroadcastMessage({ type: a });
|
||||
}
|
||||
function BroadcastDownloadingUpdate(a) {
|
||||
PostBroadcastMessage({ type: 'downloading-update', version: a });
|
||||
}
|
||||
function BroadcastUpdateReady(a) {
|
||||
PostBroadcastMessage({ type: 'update-ready', version: a });
|
||||
}
|
||||
function IsUrlInLazyLoadList(a, b) {
|
||||
if (!b) return !1;
|
||||
try {
|
||||
for (const c of b) if (new RegExp(c).test(a)) return !0;
|
||||
} catch (a) {
|
||||
console.error('[SW] Error matching in lazy-load list: ', a);
|
||||
}
|
||||
return !1;
|
||||
}
|
||||
function WriteLazyLoadListToStorage(a) {
|
||||
return 'undefined' == typeof localforage
|
||||
? Promise.resolve()
|
||||
: localforage.setItem(LAZYLOAD_KEYNAME, a);
|
||||
}
|
||||
function ReadLazyLoadListFromStorage() {
|
||||
return 'undefined' == typeof localforage
|
||||
? Promise.resolve([])
|
||||
: localforage.getItem(LAZYLOAD_KEYNAME);
|
||||
}
|
||||
function GetCacheBaseName() {
|
||||
return 'c3offline-' + self.registration.scope;
|
||||
}
|
||||
function GetCacheVersionName(a) {
|
||||
return GetCacheBaseName() + '-v' + a;
|
||||
}
|
||||
async function GetAvailableCacheNames() {
|
||||
const a = await caches.keys(),
|
||||
b = GetCacheBaseName();
|
||||
return a.filter((a) => a.startsWith(b));
|
||||
}
|
||||
async function IsUpdatePending() {
|
||||
const a = await GetAvailableCacheNames();
|
||||
return 2 <= a.length;
|
||||
}
|
||||
async function GetMainPageUrl() {
|
||||
const a = await clients.matchAll({ includeUncontrolled: !0, type: 'window' });
|
||||
for (const b of a) {
|
||||
let a = b.url;
|
||||
if (
|
||||
(a.startsWith(self.registration.scope) && (a = a.substring(self.registration.scope.length)),
|
||||
a && '/' !== a)
|
||||
)
|
||||
return a.startsWith('?') && (a = '/' + a), a;
|
||||
}
|
||||
return '';
|
||||
}
|
||||
function fetchWithBypass(a, b) {
|
||||
return (
|
||||
'string' == typeof a && (a = new Request(a)),
|
||||
b
|
||||
? fetch(a.url, {
|
||||
headers: a.headers,
|
||||
mode: a.mode,
|
||||
credentials: a.credentials,
|
||||
redirect: a.redirect,
|
||||
cache: 'no-store'
|
||||
})
|
||||
: fetch(a)
|
||||
);
|
||||
}
|
||||
async function CreateCacheFromFileList(a, b, c) {
|
||||
const d = await Promise.all(b.map((a) => fetchWithBypass(a, c)));
|
||||
let e = !0;
|
||||
for (const f of d)
|
||||
f.ok ||
|
||||
((e = !1),
|
||||
console.error("[SW] Error fetching '" + f.url + "' (" + f.status + ' ' + f.statusText + ')'));
|
||||
if (!e) throw new Error('not all resources were fetched successfully');
|
||||
const f = await caches.open(a);
|
||||
try {
|
||||
return await Promise.all(d.map((a, c) => f.put(b[c], a)));
|
||||
} catch (b) {
|
||||
throw (console.error('[SW] Error writing cache entries: ', b), caches.delete(a), b);
|
||||
}
|
||||
}
|
||||
async function UpdateCheck(a) {
|
||||
try {
|
||||
const b = await fetchWithBypass(OFFLINE_DATA_FILE, !0);
|
||||
if (!b.ok) throw new Error('offline.json responded with ' + b.status + ' ' + b.statusText);
|
||||
const c = await b.json(),
|
||||
d = c.version,
|
||||
e = c.fileList,
|
||||
f = c.lazyLoad,
|
||||
g = GetCacheVersionName(d),
|
||||
h = await caches.has(g);
|
||||
if (h) {
|
||||
const a = await IsUpdatePending();
|
||||
return void (a
|
||||
? (console.log('[SW] Update pending'), Broadcast('update-pending'))
|
||||
: (console.log('[SW] Up to date'), Broadcast('up-to-date')));
|
||||
}
|
||||
const i = await GetMainPageUrl();
|
||||
e.unshift('./'),
|
||||
i && -1 === e.indexOf(i) && e.unshift(i),
|
||||
console.log('[SW] Caching ' + e.length + ' files for offline use'),
|
||||
a ? Broadcast('downloading') : BroadcastDownloadingUpdate(d),
|
||||
f && (await WriteLazyLoadListToStorage(f)),
|
||||
await CreateCacheFromFileList(g, e, !a);
|
||||
const j = await IsUpdatePending();
|
||||
j
|
||||
? (console.log('[SW] All resources saved, update ready'), BroadcastUpdateReady(d))
|
||||
: (console.log('[SW] All resources saved, offline support ready'),
|
||||
Broadcast('offline-ready'));
|
||||
} catch (a) {
|
||||
console.warn('[SW] Update check failed: ', a);
|
||||
}
|
||||
}
|
||||
self.addEventListener('install', (a) => {
|
||||
a.waitUntil(UpdateCheck(!0).catch(() => null));
|
||||
});
|
||||
async function GetCacheNameToUse(a, b) {
|
||||
if (1 === a.length || !b) return a[0];
|
||||
const c = await clients.matchAll();
|
||||
if (1 < c.length) return a[0];
|
||||
const d = a[a.length - 1];
|
||||
return (
|
||||
console.log('[SW] Updating to new version'),
|
||||
await Promise.all(a.slice(0, -1).map((a) => caches.delete(a))),
|
||||
d
|
||||
);
|
||||
}
|
||||
async function HandleFetch(a, b) {
|
||||
const c = await GetAvailableCacheNames();
|
||||
if (!c.length) return fetch(a.request);
|
||||
const d = await GetCacheNameToUse(c, b),
|
||||
e = await caches.open(d),
|
||||
f = await e.match(a.request);
|
||||
if (f) return f;
|
||||
const g = await Promise.all([fetch(a.request), ReadLazyLoadListFromStorage()]),
|
||||
h = g[0],
|
||||
i = g[1];
|
||||
if (IsUrlInLazyLoadList(a.request.url, i))
|
||||
try {
|
||||
await e.put(a.request, h.clone());
|
||||
} catch (b) {
|
||||
console.warn("[SW] Error caching '" + a.request.url + "': ", b);
|
||||
}
|
||||
return h;
|
||||
}
|
||||
self.addEventListener('fetch', (a) => {
|
||||
if (new URL(a.request.url).origin === location.origin) {
|
||||
const b = 'navigate' === a.request.mode,
|
||||
c = HandleFetch(a, b);
|
||||
b && a.waitUntil(c.then(() => UpdateCheck(!1))), a.respondWith(c);
|
||||
}
|
||||
});
|
||||