From 571c27a64e8452a58a05d85bf40e1d7885d2dd1b Mon Sep 17 00:00:00 2001 From: sijanec Date: Mon, 8 Jun 2020 22:43:11 +0200 Subject: added update mechanism, DO NOT MERGE b4 seeing commit notes! this "update mechanism" only deletes old caches. old means caches that are caches with names other than the name in cache_name.txt. It is important not to cache cache_name.txt and always serve it with HTTP headers that allow no HTTP level caching. Update checking occurs every 300 seconds and if a new cache is released and sw.js is not reinstalled, this timer will clear the cache. the old update method did not work since it relied on sw being reloaded often, which is not the case on iPhone devices, where Safari runs almost the whole uptime of the phone and it's not common for people to shut down their precious little iPhones. it worked on android as android is known for killing apps and chrome is no exception. --- assets/js/app.js.bvr | 115 +++++++++++-------- assets/js/setup-storage.js | 77 +++++++------ assets/pages-src/about.bvr | 248 ++++++++++++++++++++++------------------- assets/root/cache_name.txt.bvr | 2 + assets/root/sw.js.bvr | 235 ++++++++++++++++++++------------------ 5 files changed, 372 insertions(+), 305 deletions(-) create mode 100644 assets/root/cache_name.txt.bvr (limited to 'assets') diff --git a/assets/js/app.js.bvr b/assets/js/app.js.bvr index d19c1d6..0a91078 100644 --- a/assets/js/app.js.bvr +++ b/assets/js/app.js.bvr @@ -1,20 +1,20 @@ <@?i global@> const app_version = "<@?g app_version@>"; const previous_commit = "<@?g latest_commit@>"; - +const BEZIAPP_UPDATE_INTERVAL = 300; // update vsakih 300 sekund if ("serviceWorker" in navigator) { - navigator.serviceWorker.register("/sw.js") - .then(() => { }) - .catch((err) => console.log("Service worker registration failed", err)); + navigator.serviceWorker.register("/sw.js") + .then(() => { }) + .catch((err) => console.log("Service worker registration failed", err)); } // Listen to messages from service workers. if (navigator.serviceWorker) { - navigator.serviceWorker.addEventListener('message', (event) => { - if (event.data.msg === "install") { - window.location.replace("/index.html"); - } - }); + navigator.serviceWorker.addEventListener('message', (event) => { + if (event.data.msg === "install") { + window.location.replace("/index.html"); + } + }); } /** @@ -24,12 +24,12 @@ if (navigator.serviceWorker) { * @param {string} devmsg Developer-friendly message */ async function UIAlert(usermsg, devmsg) { - if (true) { // če bo kakšen dev switch? - M.toast( { html: usermsg } ); - console.log(`[BežiApp UIAlert] ${usermsg} ${devmsg}`); - } else { - M.toast( { html: `${usermsg} ${devmsg}` } ); - } + if (true) { // če bo kakšen dev switch? + M.toast({ html: usermsg }); + console.log(`[BežiApp UIAlert] ${usermsg} ${devmsg}`); + } else { + M.toast({ html: `${usermsg} ${devmsg}` }); + } } /** @@ -37,44 +37,69 @@ async function UIAlert(usermsg, devmsg) { * @param {Object} err GSEC error object */ function gsecErrorHandlerUI(err) { - console.log(`gsecErrorHanderUI: handling ${err}`); - if(err == GSEC_ERR_NET || err == GSEC_ERR_NET_POSTBACK_GET || - err == GSEC_ERR_NET_POSTBACK_POST) { + console.log(`gsecErrorHanderUI: handling ${err}`); + if (err == GSEC_ERR_NET || err == GSEC_ERR_NET_POSTBACK_GET || + err == GSEC_ERR_NET_POSTBACK_POST) { - UIAlert( D("gsecErrNet") ); - } else if(err == GSEC_ERR_LOGIN) { - UIAlert( D("gsecErrLogin") ); - localforage.setItem("logged_in", false).then( () => { - window.location.replace("/index.html"); - }); - } else { - UIAlert( D("gsecErrOther") ); - } + UIAlert(D("gsecErrNet")); + } else if (err == GSEC_ERR_LOGIN) { + UIAlert(D("gsecErrLogin")); + localforage.setItem("logged_in", false).then(() => { + window.location.replace("/index.html"); + }); + } else { + UIAlert(D("gsecErrOther")); + } } +var update_app_function = async function () { + $.get("/cache_name.txt", (data, status) => { + var cache_name = data.split("///")[1].split("|||")[0]; + var data_to_send = { + action: "checkversion", + valid_cache_name: cache_name + } + navigator.serviceWorker.controller.postMessage(JSON.stringify(data_to_send)); + }); +} var error_report_function = async function (msg, url, lineNo, columnNo, error) { - localforage.getItem("errorReporting").then(async function(value) { - let selectedE = value; - if(value == null || value.length < 1) { - selectedE = "on"; - } - if(selectedE == "on") { - var data = {}; - data.error = {"msg": msg, "url": url, "line": lineNo, "column": columnNo, "obj": error}; - data.client = {"ua": navigator.userAgent, "app_version": app_version, "previous_commit": previous_commit, "username": null}; + // catching everything here so no looping error shit. that's the last thing we want + try { + localforage.getItem("errorReporting").then(async function (value) { + let selectedE = value; + if (value == null || value.length < 1) { + selectedE = "on"; + } + if (selectedE == "on") { + var data = {}; + data.error = { "msg": msg, "url": url, "line": lineNo, "column": columnNo, "obj": error }; + data.client = { "ua": navigator.userAgent, "app_version": app_version, "previous_commit": previous_commit, "username": null }; - // Load required data - data.client.username = await localforage.getItem("username"); + // Load required data + data.client.username = await localforage.getItem("username"); - data.type = "error"; - $.post("https://beziapp-report.gimb.tk/", data); - } else { - console.log("error not reported as reporting is disabled!"); - } - }).catch(() => {}); - return false; + data.type = "error"; + $.post("https://beziapp-report.gimb.tk/", data); + } else { + console.log("error not reported as reporting is disabled!"); + } + }).catch(() => { }); + return false; + } catch (e) { + console.log("error_erport_function: !!! ERROR! (caught) - probably some network error."); + } } window.onerror = error_report_function; window.onunhandledrejection = error_report_function; + + +document.addEventListener("DOMContentLoaded", () => { + localforage.getItem("lastUpdate").then((data) => { + if(Math.floor(Date.now() / 1000) > data + BEZIAPP_UPDATE_INTERVAL) { + // trigger an update + update_app_function(); + } + }); +}); \ No newline at end of file diff --git a/assets/js/setup-storage.js b/assets/js/setup-storage.js index c862d5f..b29c959 100644 --- a/assets/js/setup-storage.js +++ b/assets/js/setup-storage.js @@ -1,44 +1,43 @@ async function setupStorage(force = false) { - let logged_in; - promises_check_if_already_installed = [ - localforage.getItem("logged_in").then( function(val) { - console.log("[setupStorage] logged in status: " + val); - logged_in = val; - }) - ]; - await Promise.all(promises_check_if_already_installed); + let logged_in; + promises_check_if_already_installed = [ + localforage.getItem("logged_in").then(function (val) { + console.log("[setupStorage] logged in status: " + val); + logged_in = val; + }) + ]; + await Promise.all(promises_check_if_already_installed); - let promises_update = [ - localforage.setItem("profile", {}), - localforage.setItem("timetable", []), - localforage.setItem("teachers", []), - localforage.setItem("gradings", []), - localforage.setItem("grades", []), - localforage.setItem("absences", {}), - localforage.setItem("messages", [[], [], []]), // see messages.js:129, commit 8eb9ca9caca30fbbe023243657535ab4088be377 - localforage.setItem("directory", {}), //\\ well I could remember my own code but I didn't. - localforage.setItem("meals", {}), - localforage.setItem("chosenLang", "en"), - localforage.setItem("theme", "light"), - localforage.setItem("errorReporting", "on"), - localforage.setItem("triggerWarningAccepted", false) - ]; + let promises_update = [ + localforage.setItem("profile", {}), + localforage.setItem("timetable", []), + localforage.setItem("teachers", []), + localforage.setItem("gradings", []), + localforage.setItem("grades", []), + localforage.setItem("absences", {}), + localforage.setItem("messages", [[], [], []]), // see messages.js:129, commit 8eb9ca9caca30fbbe023243657535ab4088be377 + localforage.setItem("directory", {}), //\\ well I could remember my own code but I didn't. + localforage.setItem("meals", {}), + localforage.setItem("chosenLang", "en"), + localforage.setItem("theme", "light"), + localforage.setItem("errorReporting", "on"), + localforage.setItem("lastUpdate", 0), + localforage.setItem("triggerWarningAccepted", false) + ]; - if (logged_in && force == false) { // torej, če je že bila prijava narejena, ne posodobi backwards-compatible vrednosti (username, password,...) - await Promise.all(promises_update); - console.log("[setupStorage] user logged in: only updated"); - } else { + if (logged_in && force == false) { // torej, če je že bila prijava narejena, ne posodobi backwards-compatible vrednosti (username, password,...) + await Promise.all(promises_update); + console.log("[setupStorage] user logged in: only updated"); + } else { - let promises_first_install = [ - localforage.setItem("logged_in", false), - localforage.setItem("username", ""), - localforage.setItem("password", ""), - localforage.setItem("chosenLang", "en"), - localforage.setItem("theme", "light"), - localforage.setItem("triggerWarningAccepted", false) - ]; - await localforage.clear(); - await Promise.all(promises_first_install); - console.log("[setupStorage] user not logged in: set up whole database"); - } + let promises_first_install = [ + localforage.setItem("logged_in", false), + localforage.setItem("username", ""), + localforage.setItem("password", ""), + ]; + await localforage.clear(); + await Promise.all(promises_first_install); + await Promise.all(promises_update); + console.log("[setupStorage] user not logged in: set up whole database"); + } } diff --git a/assets/pages-src/about.bvr b/assets/pages-src/about.bvr index 26b5957..7c0ddb3 100644 --- a/assets/pages-src/about.bvr +++ b/assets/pages-src/about.bvr @@ -1,133 +1,151 @@ <@?i global@> - - - - - - - - About « BežiApp + + - - - - - + + + + + + About « BežiApp - - + + + + + - - + + - - - - - + + - - - - - + + + + + - - + + + + + + + + <@?i navigation@> -
-
-
-

- BežiApp -

- -# I agree, will make a script -
version <@?g app_version@>
-
-
-
-
- +
+
+
+
+
    +
  • +
    + translatorsForThisLanguage - miscTranslationLanguage +
    +
  • +
  • + + miscTranslationAuthors + +
  • +
+
+
+

^HEAD <@?g latest_commit@> - +

-
- + + - + \ No newline at end of file diff --git a/assets/root/cache_name.txt.bvr b/assets/root/cache_name.txt.bvr new file mode 100644 index 0000000..e3a1ee3 --- /dev/null +++ b/assets/root/cache_name.txt.bvr @@ -0,0 +1,2 @@ +<@?i global@> +///site-static-<@?g app_version@>-<@?u 0 7 ?g latest_commit@>||| diff --git a/assets/root/sw.js.bvr b/assets/root/sw.js.bvr index a44a6fc..1a823d4 100644 --- a/assets/root/sw.js.bvr +++ b/assets/root/sw.js.bvr @@ -6,79 +6,79 @@ const static_cache_name = "site-static-<@?g app_version@>-<@?u 0 7 ?g latest_com // sw.js NE SME BITI CACHAN, ker vsebuje verzijo! const assets = [ - "/css/materialize.min.css", - "/css/fontawesome.min.css", - "/css/materialicons.css", - "/css/styles.css", - "/css/fullcalendar/custom.css", - "/css/fullcalendar/daygrid/main.min.css", - "/css/fullcalendar/core/main.min.css", - "/css/fullcalendar/timegrid/main.min.css", + "/css/materialize.min.css", + "/css/fontawesome.min.css", + "/css/materialicons.css", + "/css/styles.css", + "/css/fullcalendar/custom.css", + "/css/fullcalendar/daygrid/main.min.css", + "/css/fullcalendar/core/main.min.css", + "/css/fullcalendar/timegrid/main.min.css", - "/fonts/fa-solid-900.eot", - "/fonts/fa-solid-900.woff2", - "/fonts/fa-brands-400.woff2", - "/fonts/fa-regular-400.eot", - "/fonts/fa-regular-400.woff2", - "/fonts/fa-brands-400.eot", - "/fonts/materialicons.woff2", + "/fonts/fa-solid-900.eot", + "/fonts/fa-solid-900.woff2", + "/fonts/fa-brands-400.woff2", + "/fonts/fa-regular-400.eot", + "/fonts/fa-regular-400.woff2", + "/fonts/fa-brands-400.eot", + "/fonts/materialicons.woff2", - "/img/avatars/asijanec.png", - "/img/avatars/rstular.png", - "/img/icons/icon_384.png", - "/img/icons/icon_192.png", - "/img/icons/icon_72.png", - "/img/icons/icon_144.png", - "/img/icons/icon_512.png", - "/img/icons/icon_96.png", - "/img/icons/icon_48.png", + "/img/avatars/asijanec.png", + "/img/avatars/rstular.png", + "/img/icons/icon_384.png", + "/img/icons/icon_192.png", + "/img/icons/icon_72.png", + "/img/icons/icon_144.png", + "/img/icons/icon_512.png", + "/img/icons/icon_96.png", + "/img/icons/icon_48.png", - "/js/timetable.js", - "/js/gradings.js", - "/js/messaging.js", - "/js/privacypolicy.js", - "/js/teachers.js", - "/js/tos.js", - "/js/login.js", - "/js/app.js", - "/js/meals.js", - "/js/settings.js", + "/js/timetable.js", + "/js/gradings.js", + "/js/messaging.js", + "/js/privacypolicy.js", + "/js/teachers.js", + "/js/tos.js", + "/js/login.js", + "/js/app.js", + "/js/meals.js", + "/js/settings.js", "/js/lang/bundle.js", "/js/setup-storage.js", - "/js/lib/materialize.min.js", - "/js/lib/jquery.min.js", - "/js/lib/localforage.min.js", - "/js/lib/xss.js", - "/js/lib/mergedeep.js", + "/js/lib/materialize.min.js", + "/js/lib/jquery.min.js", + "/js/lib/localforage.min.js", + "/js/lib/xss.js", + "/js/lib/mergedeep.js", - "/js/lib/fullcalendar/daygrid/main.min.js", - "/js/lib/fullcalendar/core/main.min.js", - "/js/lib/fullcalendar/timegrid/main.min.js", - "/js/grades.js", - "/js/about.js", - "/js/logout.js", - "/js/initialize.js", - "/js/absences.js", - "/js/changelog.js", + "/js/lib/fullcalendar/daygrid/main.min.js", + "/js/lib/fullcalendar/core/main.min.js", + "/js/lib/fullcalendar/timegrid/main.min.js", + "/js/grades.js", + "/js/about.js", + "/js/logout.js", + "/js/initialize.js", + "/js/absences.js", + "/js/changelog.js", - "/pages/timetable.html", - "/pages/teachers.html", - "/pages/absences.html", - "/pages/about.html", - "/pages/changelog.html", - "/pages/messaging.html", - "/pages/gradings.html", - "/pages/grades.html", - "/pages/privacypolicy.html", - "/pages/tos.html", - "/pages/meals.html", - "/pages/settings.html", + "/pages/timetable.html", + "/pages/teachers.html", + "/pages/absences.html", + "/pages/about.html", + "/pages/changelog.html", + "/pages/messaging.html", + "/pages/gradings.html", + "/pages/grades.html", + "/pages/privacypolicy.html", + "/pages/tos.html", + "/pages/meals.html", + "/pages/settings.html", - "/manifest.json", - "/index.html", - "/login.html", - "/logout.html", + "/manifest.json", + "/index.html", + "/login.html", + "/logout.html", "/favicon.png", "/pages/jitsi.html", "/js/jitsi.js", @@ -93,58 +93,81 @@ const assets = [ importScripts("/js/lib/localforage.min.js"); importScripts("/js/setup-storage.js"); self.addEventListener("install", (evt) => { - // Add localforage.clear() if storage purge is required - evt.waitUntil( - // localforage.clear() - setupStorage() - ); + // Add localforage.clear() if storage purge is required + evt.waitUntil( + // localforage.clear() + setupStorage() + ); - evt.waitUntil( - caches.open(static_cache_name).then((cache) => { - cache.addAll(assets); - }) - ); + evt.waitUntil( + caches.open(static_cache_name).then((cache) => { + cache.addAll(assets); + }) + ); }); // Delete old caches self.addEventListener("activate", evt => { - evt.waitUntil( - caches.keys().then((keys) => { - return Promise.all(keys - .filter(key => key !== static_cache_name) - .map(key => caches.delete(key)) - ); - }) - ); + evt.waitUntil( + caches.keys().then((keys) => { + return Promise.all(keys + .filter(key => key !== static_cache_name) + .map(key => caches.delete(key)) + ); + }) + ); }); self.addEventListener("message", event => { - if (event.data) { - let data = JSON.parse(event.data); // parse the message back to JSON - if (data.action == "addtocache") { // check the action - event.waitUntil( - caches.open(static_cache_name).then(function (cache) { - try { - return cache.add([data.url]); - } - catch (error) { - console.error("[sw.js] error: " + error); - } - }) - ); - } else if (data.action == "deletecaches") { - caches.keys().then(function (names) { - for (let name of names) - console.log("[sw.js] deleting cache named " + name); - caches.delete(name); - }); - } - } + if (event.data) { + let data = JSON.parse(event.data); // parse the message back to JSON + if (data.action == "addtocache") { // check the action + event.waitUntil( + caches.open(static_cache_name).then(function (cache) { + try { + return cache.add([data.url]); + } + catch (error) { + console.error("[sw.js] error: " + error); + } + }) + ); + } else if (data.action == "deletecaches") { + caches.keys().then(function (names) { + for (let name of names) { + console.log("[sw.js] deleting cache named " + name); + caches.delete(name); + } + }); + } else if (data.action.startsWith("checkversion")) { + try { + var names = await caches.keys(); + console.log("[sw.js] checkversion: ***** checkversion v0 for BežiApp ***** hello, world!"); + if(!(data.valid_cache_name == undefined || data.valid_cache_name == null || data.valid_cache_name == "")) { + var valid_cache_name = data.valid_cache_name; + console.log("[sw.js] checkversion: requested version (cachename) " + valid_cache_name); + } else { + var valid_cache_name = static_cache_name; + console.log("[sw.js] checkversion: no version to keep specified, using current "+valid_cache_name+", but that makes no sense to me."); + } + console.log("[sw.js] checkversion: deleting caches that don't match that cache name ..."); + for (let name of names) { + if(valid_cache_name != name) { + caches.delete(name); + console.log("[sw.js] checkversion: done requesting delete of cache " + name); + } + } + console.log("[sw.js] checkversion: done, exiting!"); + } catch (e) { + console.log("[sw.js] checkversion: !!! ERRORS! (caught)"); + } + } + } }); self.addEventListener("fetch", (evt) => { - evt.respondWith(caches.match(evt.request).then((cache_res) => { - return cache_res || fetch(evt.request); - })) + evt.respondWith(caches.match(evt.request).then((cache_res) => { + return cache_res || fetch(evt.request); + })) }); -- cgit v1.2.3