mirror of
https://github.com/GamingShitposting/SalaMuseoGames
synced 2025-06-05 21:59:30 +02:00
offline caching preparations
This commit is contained in:
@@ -110,6 +110,8 @@
|
|||||||
icon: {{ page.icon | jsonify }},
|
icon: {{ page.icon | jsonify }},
|
||||||
software_data: {{ page.software_data | jsonify }},
|
software_data: {{ page.software_data | jsonify }},
|
||||||
};
|
};
|
||||||
window.SalaMuseoGames = { site: site_config, page: page_config };
|
window.SMG = window.SalaMuseoGames = { site: site_config, page: page_config };
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
<script src="{{ site.baseurl }}/assets/js/util.js"></script>
|
||||||
</head>
|
</head>
|
||||||
|
120
assets/js/idb-backup-and-restore.js
Normal file
120
assets/js/idb-backup-and-restore.js
Normal file
@@ -0,0 +1,120 @@
|
|||||||
|
window.idbBackupAndRestore = {
|
||||||
|
|
||||||
|
/* <https://gist.github.com/loilo/ed43739361ec718129a15ae5d531095b/> */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Export all data from an IndexedDB database
|
||||||
|
*
|
||||||
|
* @param {IDBDatabase} idbDatabase The database to export from
|
||||||
|
* @return {Promise<string>}
|
||||||
|
*/
|
||||||
|
exportToJson: function (idbDatabase) {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
const exportObject = {}
|
||||||
|
if (idbDatabase.objectStoreNames.length === 0) {
|
||||||
|
resolve(JSON.stringify(exportObject))
|
||||||
|
} else {
|
||||||
|
const transaction = idbDatabase.transaction(
|
||||||
|
idbDatabase.objectStoreNames,
|
||||||
|
'readonly'
|
||||||
|
)
|
||||||
|
|
||||||
|
transaction.addEventListener('error', reject)
|
||||||
|
|
||||||
|
for (const storeName of idbDatabase.objectStoreNames) {
|
||||||
|
const allObjects = []
|
||||||
|
transaction
|
||||||
|
.objectStore(storeName)
|
||||||
|
.openCursor()
|
||||||
|
.addEventListener('success', event => {
|
||||||
|
const cursor = event.target.result
|
||||||
|
if (cursor) {
|
||||||
|
// Cursor holds value, put it into store data
|
||||||
|
allObjects.push(cursor.value)
|
||||||
|
cursor.continue()
|
||||||
|
} else {
|
||||||
|
// No more values, store is done
|
||||||
|
exportObject[storeName] = allObjects
|
||||||
|
|
||||||
|
// Last store was handled
|
||||||
|
if (
|
||||||
|
idbDatabase.objectStoreNames.length ===
|
||||||
|
Object.keys(exportObject).length
|
||||||
|
) {
|
||||||
|
resolve(JSON.stringify(exportObject))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Import data from JSON into an IndexedDB database.
|
||||||
|
* This does not delete any existing data from the database, so keys may clash.
|
||||||
|
*
|
||||||
|
* @param {IDBDatabase} idbDatabase Database to import into
|
||||||
|
* @param {string} json Data to import, one key per object store
|
||||||
|
* @return {Promise<void>}
|
||||||
|
*/
|
||||||
|
importFromJson: function (idbDatabase, json) {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
const transaction = idbDatabase.transaction(
|
||||||
|
idbDatabase.objectStoreNames,
|
||||||
|
'readwrite'
|
||||||
|
)
|
||||||
|
transaction.addEventListener('error', reject)
|
||||||
|
|
||||||
|
var importObject = JSON.parse(json)
|
||||||
|
for (const storeName of idbDatabase.objectStoreNames) {
|
||||||
|
let count = 0
|
||||||
|
for (const toAdd of importObject[storeName]) {
|
||||||
|
const request = transaction.objectStore(storeName).add(toAdd)
|
||||||
|
request.addEventListener('success', () => {
|
||||||
|
count++
|
||||||
|
if (count === importObject[storeName].length) {
|
||||||
|
// Added all objects for this store
|
||||||
|
delete importObject[storeName]
|
||||||
|
if (Object.keys(importObject).length === 0) {
|
||||||
|
// Added all object stores
|
||||||
|
resolve()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Clear a database
|
||||||
|
*
|
||||||
|
* @param {IDBDatabase} idbDatabase The database to delete all data from
|
||||||
|
* @return {Promise<void>}
|
||||||
|
*/
|
||||||
|
clearDatabase: function (idbDatabase) {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
const transaction = idbDatabase.transaction(
|
||||||
|
idbDatabase.objectStoreNames,
|
||||||
|
'readwrite'
|
||||||
|
)
|
||||||
|
transaction.addEventListener('error', reject)
|
||||||
|
|
||||||
|
let count = 0
|
||||||
|
for (const storeName of idbDatabase.objectStoreNames) {
|
||||||
|
transaction
|
||||||
|
.objectStore(storeName)
|
||||||
|
.clear()
|
||||||
|
.addEventListener('success', () => {
|
||||||
|
count++
|
||||||
|
if (count === idbDatabase.objectStoreNames.length) {
|
||||||
|
// Cleared all object stores
|
||||||
|
resolve()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
})
|
||||||
|
},
|
||||||
|
|
||||||
|
};
|
@@ -2,10 +2,10 @@
|
|||||||
|
|
||||||
var prefsIndex = 'SalaMuseoGames/Prefs/v1';
|
var prefsIndex = 'SalaMuseoGames/Prefs/v1';
|
||||||
|
|
||||||
var Prefs = {
|
var Prefs = window.SalaMuseoGames.Prefs = {
|
||||||
pwaManifests: { default: true, name: "Allow installing the site as a PWA" },
|
softwarePwaManifests: { default: true, /* dependsOn: "pwaManifests", */ name: "Allow installing individual games as PWAs" },
|
||||||
softwarePwaManifests: { default: true, dependsOn: "pwaManifests", name: "Allow installing individual games as PWAs" },
|
pwaManifests: { default: false, name: "Allow installing the site home itself as a PWA" },
|
||||||
// offlineCache: { default: true, name: "Cache site pages and game files offline", summary: "Allow faster site navigation, and gameplay without an Internet connection, by caching unlimited data offline. Disable if you want to save storage. (Note that data for some emulators and games is always cached regardless of this setting; you can only manage their data when they show an option in their interface.)" },
|
offlineCache: { default: true, name: "Cache site pages and game files offline", summary: "Allow faster site navigation, and gameplay without an Internet connection, by caching unlimited data offline. Disable if you want to save storage. (Note that data for some emulators and games is always cached regardless of this setting; you can only manage their data when they show an option in their interface.)" },
|
||||||
// dataExport: { onclick: (function(){}), section: "data", name: "Export configuration and gamesaves" },
|
// dataExport: { onclick: (function(){}), section: "data", name: "Export configuration and gamesaves" },
|
||||||
// dataImport: { onclick: (function(){}), section: "data", name: "Import configuration and gamesaves" },
|
// dataImport: { onclick: (function(){}), section: "data", name: "Import configuration and gamesaves" },
|
||||||
// featurePreview: { default: false, name: "Use experimental features before their release", summary: "If some new site features or adjustments are scheduled to release soon, you might be chosen to preview them before they are officially available" },
|
// featurePreview: { default: false, name: "Use experimental features before their release", summary: "If some new site features or adjustments are scheduled to release soon, you might be chosen to preview them before they are officially available" },
|
||||||
@@ -28,8 +28,9 @@ Object.keys(Prefs).forEach(function(key){
|
|||||||
});
|
});
|
||||||
|
|
||||||
var PrefsSections = {
|
var PrefsSections = {
|
||||||
data: { name: "Data management", visible: true },
|
// data: { name: "Data management", visible: true },
|
||||||
developer: { name: "Development", visible: Prefs.developerMode.value },
|
developer: { name: "Development", visible: Prefs.developerMode.value },
|
||||||
|
// advanced: { name: "Advanced", visible: true },
|
||||||
};
|
};
|
||||||
|
|
||||||
var configElem = document.querySelector('#ConfigurationCustomizer');
|
var configElem = document.querySelector('#ConfigurationCustomizer');
|
||||||
@@ -64,7 +65,6 @@ if (configElem) {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
window.SalaMuseoGames.Prefs = Prefs;
|
|
||||||
SavePrefs();
|
SavePrefs();
|
||||||
|
|
||||||
})();
|
})();
|
||||||
|
@@ -5,6 +5,7 @@ var Software = SalaMuseoGames.page.software_data;
|
|||||||
var Screen = (Software && Software.screen);
|
var Screen = (Software && Software.screen);
|
||||||
var Site = SalaMuseoGames.site;
|
var Site = SalaMuseoGames.site;
|
||||||
var iconUrl = SalaMuseoGames.page.icon;
|
var iconUrl = SalaMuseoGames.page.icon;
|
||||||
|
var coverUrl = SalaMuseoGames.page.image;
|
||||||
var sitePath = (Site.url + Site.baseurl);
|
var sitePath = (Site.url + Site.baseurl);
|
||||||
|
|
||||||
function absoluteUrlFromRelative (url) {
|
function absoluteUrlFromRelative (url) {
|
||||||
@@ -17,7 +18,7 @@ function absoluteUrlFromRelative (url) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Prefs.pwaManifests.value) {
|
if (Prefs.pwaManifests.value || Prefs.softwarePwaManifests.value) {
|
||||||
var manifestData;
|
var manifestData;
|
||||||
if (Prefs.softwarePwaManifests.value && Software) {
|
if (Prefs.softwarePwaManifests.value && Software) {
|
||||||
// specific manifests on games pages
|
// specific manifests on games pages
|
||||||
@@ -30,7 +31,7 @@ if (Prefs.pwaManifests.value) {
|
|||||||
display: ((Screen && Screen.display) || "standalone"),
|
display: ((Screen && Screen.display) || "standalone"),
|
||||||
orientation: ((Screen && Screen.orientation) || "any"),
|
orientation: ((Screen && Screen.orientation) || "any"),
|
||||||
};
|
};
|
||||||
} else {
|
} else if (Prefs.pwaManifests.value) {
|
||||||
// site manifest on global pages
|
// site manifest on global pages
|
||||||
var ldData;
|
var ldData;
|
||||||
for (var elem of document.querySelectorAll('script[type="application/ld+json"]')) {
|
for (var elem of document.querySelectorAll('script[type="application/ld+json"]')) {
|
||||||
@@ -53,7 +54,7 @@ if (Prefs.pwaManifests.value) {
|
|||||||
scope: location.href,
|
scope: location.href,
|
||||||
background_color: (Software && Software.background_color || getComputedStyle(document.body).backgroundColor),
|
background_color: (Software && Software.background_color || getComputedStyle(document.body).backgroundColor),
|
||||||
icons: [{
|
icons: [{
|
||||||
src: (iconUrl ? absoluteUrlFromRelative(iconUrl) : (sitePath + '/assets/img/icons/mediumtile.png')),
|
src: ((iconUrl || coverUrl) ? absoluteUrlFromRelative(iconUrl || coverUrl) : (sitePath + '/assets/img/icons/mediumtile.png')),
|
||||||
sizes: "any",
|
sizes: "any",
|
||||||
purpose: "any",
|
purpose: "any",
|
||||||
}],
|
}],
|
||||||
@@ -64,8 +65,21 @@ if (Prefs.pwaManifests.value) {
|
|||||||
document.head.appendChild(manifestElem);
|
document.head.appendChild(manifestElem);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Prefs.offlineCache.value && 'serviceWorker' in navigator) {
|
if ('serviceWorker' in navigator) {
|
||||||
navigator.serviceWorker.register('/ServiceWorker.js', { scope: "/SalaMuseoGames/" });
|
var cachingScopes = ['SalaMuseoGames', 'ext-bin-1'];
|
||||||
|
if (Prefs.offlineCache.value) {
|
||||||
|
cachingScopes.forEach(function(scope){
|
||||||
|
navigator.serviceWorker.register('/ServiceWorker.js', { scope: `/${scope}/` });
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
navigator.serviceWorker.getRegistrations().then((workers) => {
|
||||||
|
for (var worker of workers) {
|
||||||
|
if (cachingScopes.includes(worker.scope.split('/').slice(-2)[0])) {
|
||||||
|
worker.unregister();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
})();
|
})();
|
||||||
|
@@ -1,16 +1,23 @@
|
|||||||
(function(){
|
(function(){
|
||||||
var bin1Path = 'https://gamingshitposting.github.io/ext-bin-1';
|
|
||||||
var thisElement = document.querySelector(`script[src="${SalaMuseoGames.site.baseurl}/assets/js/software-embed.js"]`);
|
|
||||||
var data = SalaMuseoGames.page.software_data;
|
|
||||||
var platform = data.platform;
|
|
||||||
var core = data.core;
|
|
||||||
var backend = data.backend;
|
|
||||||
var romUrl = (data.rom_url || `${bin1Path}/roms/${data.rom_index}.7z`);
|
|
||||||
var frameUrl = (data.frame_url || `${bin1Path}/${data.frame_index}`);
|
|
||||||
|
|
||||||
function button (name, onclick) { return `<button name="${name.split(' ')[0]}" onclick="(${onclick})(this)">${name}</button>` }
|
var bin1Path = 'https://gamingshitposting.github.io/ext-bin-1';
|
||||||
|
var thisElement = document.querySelector(`script[src="${SalaMuseoGames.site.baseurl}/assets/js/software-embed.js"]`);
|
||||||
|
var data = SalaMuseoGames.page.software_data;
|
||||||
|
var platform = data.platform;
|
||||||
|
var core = data.core;
|
||||||
|
var backend = data.backend;
|
||||||
|
var romUrl = (data.rom_url || `${bin1Path}/roms/${data.rom_index}.7z`);
|
||||||
|
var frameUrl = (data.frame_url || `${bin1Path}/${data.frame_index}`);
|
||||||
|
|
||||||
function diyEmbedHtml (frameUrl) { return (
|
function button (name, onclick) { return `<button name="${name.split(' ')[0]}" onclick="(${onclick})(this)">${name}</button>` }
|
||||||
|
|
||||||
|
var buttonEnlarge = button('Enlarge ↔️', function(){
|
||||||
|
document.body.classList[
|
||||||
|
!document.body.className.split(' ').includes('cinema-view') ? 'add' : 'remove'
|
||||||
|
]('cinema-view');
|
||||||
|
});
|
||||||
|
|
||||||
|
function diyEmbedHtml (frameUrl) { return (
|
||||||
button('Focus 🔳️', function(ctx){
|
button('Focus 🔳️', function(ctx){
|
||||||
ctx.parentElement.scrollIntoView();
|
ctx.parentElement.scrollIntoView();
|
||||||
ctx.parentElement.querySelector('iframe#software-embed-frame').focus();
|
ctx.parentElement.querySelector('iframe#software-embed-frame').focus();
|
||||||
@@ -18,11 +25,7 @@
|
|||||||
button('Fullscreen 🖼️', function(ctx){
|
button('Fullscreen 🖼️', function(ctx){
|
||||||
ctx.parentElement.querySelector('iframe#software-embed-frame').requestFullscreen();
|
ctx.parentElement.querySelector('iframe#software-embed-frame').requestFullscreen();
|
||||||
}) + ' ' +
|
}) + ' ' +
|
||||||
button('Enlarge ↔️', function(ctx){
|
buttonEnlarge + ' ' +
|
||||||
document.body.classList[
|
|
||||||
!document.body.className.split(' ').includes('cinema-view') ? 'add' : 'remove'
|
|
||||||
]('cinema-view');
|
|
||||||
}) + ' ' +
|
|
||||||
button('Reload ♻️', function(ctx){
|
button('Reload ♻️', function(ctx){
|
||||||
var frame = ctx.parentElement.querySelector('iframe#software-embed-frame');
|
var frame = ctx.parentElement.querySelector('iframe#software-embed-frame');
|
||||||
var src = frame.src;
|
var src = frame.src;
|
||||||
@@ -30,13 +33,13 @@
|
|||||||
frame.src = src;
|
frame.src = src;
|
||||||
}) + ' ' +
|
}) + ' ' +
|
||||||
`<iframe id="software-embed-frame" class="software-embed-frame" src="${frameUrl}"></iframe>`
|
`<iframe id="software-embed-frame" class="software-embed-frame" src="${frameUrl}"></iframe>`
|
||||||
) }
|
) }
|
||||||
|
|
||||||
// TODO set any overrides if specified ...
|
// TODO set any overrides if specified ...
|
||||||
|
|
||||||
if (platform === 'web') {
|
if (platform === 'web') {
|
||||||
thisElement.outerHTML = diyEmbedHtml(frameUrl);
|
thisElement.outerHTML = diyEmbedHtml(frameUrl);
|
||||||
} else switch (backend) {
|
} else switch (backend) {
|
||||||
default:
|
default:
|
||||||
case 'cuttingedge':
|
case 'cuttingedge':
|
||||||
case 'emulatorjs':
|
case 'emulatorjs':
|
||||||
@@ -45,13 +48,12 @@
|
|||||||
window.EJS_core = (core || platform);
|
window.EJS_core = (core || platform);
|
||||||
window.EJS_gameUrl = romUrl;
|
window.EJS_gameUrl = romUrl;
|
||||||
window.EJS_screenRecording = { videoBitrate: 150000000 };
|
window.EJS_screenRecording = { videoBitrate: 150000000 };
|
||||||
var frameElement = document.createElement('div');
|
thisElement.parentElement.appendChild(SMG.Util.elementFromHtml(buttonEnlarge));
|
||||||
frameElement.style = 'width: 640px; height: 480px; max-width: 100%;';
|
thisElement.parentElement.appendChild(SMG.Util.makeElement('div', {
|
||||||
frameElement.innerHTML = '<div id="software-embed-frame"></div>';
|
style: 'width: 640px; height: 480px; max-width: 100%;',
|
||||||
thisElement.parentElement.appendChild(frameElement);
|
innerHTML: '<div id="software-embed-frame"></div>',
|
||||||
var scriptElement = document.createElement('script');
|
}));
|
||||||
scriptElement.src = EJS_pathtodata+'loader.js';
|
document.body.appendChild(SMG.Util.makeElement('script', { src: `${EJS_pathtodata}loader.js` }));
|
||||||
document.body.appendChild(scriptElement);
|
|
||||||
break;
|
break;
|
||||||
case 'standalone':
|
case 'standalone':
|
||||||
var frameUrl = '';
|
var frameUrl = '';
|
||||||
@@ -63,5 +65,6 @@
|
|||||||
}
|
}
|
||||||
thisElement.outerHTML = diyEmbedHtml(frameUrl);
|
thisElement.outerHTML = diyEmbedHtml(frameUrl);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
})();
|
})();
|
||||||
|
13
assets/js/util.js
Normal file
13
assets/js/util.js
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
(function(){
|
||||||
|
|
||||||
|
var Util = window.SalaMuseoGames.Util = {};
|
||||||
|
|
||||||
|
Util.makeElement = (function(tag, attrs){
|
||||||
|
return Object.assign(document.createElement('tag'), attrs);
|
||||||
|
});
|
||||||
|
|
||||||
|
Util.elementFromHtml = (function(html){
|
||||||
|
return Util.makeElement('div', { innerHTML: html.trim() }).children[0];
|
||||||
|
});
|
||||||
|
|
||||||
|
})();
|
@@ -20,4 +20,4 @@ All your changes are saved automatically.
|
|||||||
* Try to load games marked unavailable
|
* Try to load games marked unavailable
|
||||||
-->
|
-->
|
||||||
|
|
||||||
<div id="ConfigurationCustomizer"><p>Loading...</p></div>
|
<div id="ConfigurationCustomizer"><p>Loading...</p><script src="{{ site.baseurl }}/assets/js/idb-backup-and-restore.js"></script></div>
|
||||||
|
Reference in New Issue
Block a user