// noinspection JSUnresolvedVariable async function fetchPlus(resource, options = {}) { const { timeout = 8000 } = options; const controller = new AbortController(); const id = setTimeout(() => controller.abort(), timeout); const response = await fetch(resource, { ...options, signal: controller.signal }); clearTimeout(id); return response; } window.connected = false; let valuesToGet = { "pluralkit-cloudburst-members": { url: "/api/data?f=ynmuc/members.json", limited: false, name: "Members at Cloudburst...", }, "pluralkit-cloudburst-fronters": { url: "/api/data?f=ynmuc/fronters.json", limited: false, name: "Fronters at Cloudburst...", }, "pluralkit-cloudburst-switches": { url: "/api/data?f=ynmuc/switches.json", limited: false, name: "Switches at Cloudburst...", }, "pluralkit-raindrops-members": { url: "/api/data?f=gdapd/members.json", limited: false, name: "Members at Raindrops...", }, "pluralkit-raindrops-fronters": { url: "/api/data?f=gdapd/fronters.json", limited: false, name: "Fronters at Raindrops...", }, "pluralkit-raindrops-switches": { url: "/api/data?f=gdapd/switches.json", limited: false, name: "Switches at Raindrops...", }, "actions": { url: "/api/data?f=actions.json", limited: false, name: "Actions...", }, "rules": { url: "/api/data?f=rules.json", limited: false, name: "Systems rules...", }, "nicknames": { url: "/api/data?f=nicknames.json", limited: false, name: "Relations nicknames...", }, "peh-cloudburst-data": { url: "/api/cloudburst-data", limited: false, name: "Cloudburst data...", }, "peh-raindrops-data": { url: "/api/raindrops-data", limited: false, name: "Raindrops data...", }, "peh-cloudburst-scored": { url: "/api/cloudburst-scored", limited: false, name: "Cloudburst ordered members...", }, "peh-raindrops-scored": { url: "/api/raindrops-scored", limited: false, name: "Raindrops ordered members...", }, "peh-cloudburst-banners": { url: "/api/cloudburst-banners", limited: false, name: "Cloudburst banner data...", }, "peh-raindrops-banners": { url: "/api/raindrops-banners", limited: false, name: "Raindrops banner data...", }, "identity": { url: "/api/me", limited: false, name: "Identity...", }, "images": { url: "/api/app-images", limited: false, name: "Images...", condition: async () => { let known = await localforage.getItem("images-refresh"); let currentKnown; try { currentKnown = btoa(Object.keys(JSON.parse(await localforage.getItem("peh-cloudburst-data")).members).join("") + Object.keys(JSON.parse(await localforage.getItem("peh-raindrops-data")).members).join("") + new Date().toDateString()); } catch (e) { return true; } localforage.setItem("images-refresh", currentKnown); if (known) { return known !== currentKnown; } else { return true; } } }, "image-me": { url: "/api/me-picture", limited: false, name: "Identity avatar...", }, "bits-transactions": { url: "/bits/Application/TransactionsList/index.php", limited: false, name: "Bits transactions...", }, "bits-goal": { url: "/bits/Application/GetGoal/index.php", limited: false, name: "Bits goal...", }, "bits-expenses": { url: "/bits/Application/GetExpenses/index.php", limited: false, name: "Bits expenses...", }, "bits-username": { url: "/bits/Authentication/Username/index.php", limited: false, name: "Bits user info...", } } let keys = Object.keys(valuesToGet); let index = 2; window.onerror = (event, source, lineno, colno, error) => { console.log(event, source, lineno, colno, error); document.getElementById("loader-message").classList.add("text-danger"); document.getElementById("loader-message").innerText = "An error occurred."; } window.onunhandledrejection = (handler, event) => { console.log(handler, event); document.getElementById("loader-message").classList.add("text-danger"); document.getElementById("loader-message").innerText = "An error occurred."; } async function getNewValue() { if (!keys[0]) { await postLoad(); return; } try { if (valuesToGet[keys[0]].condition && !(await valuesToGet[keys[0]].condition())) { keys.shift(); if (!keys[0]) { await localforage.setItem("refresh", new Date().toISOString()); await postLoad(); return; } document.getElementById("progress-inner").style.width = ((index / Object.keys(valuesToGet).length) * 100) + "%"; index++; await getNewValue(); return; } document.getElementById("loader-message").innerText = valuesToGet[keys[0]].name; await localforage.setItem(keys[0], (await (await fetchPlus(valuesToGet[keys[0]]["url"], { timeout: 3000 })).text())); keys.shift(); if (!keys[0]) { await localforage.setItem("refresh", new Date().toISOString()); await postLoad(); return; } setTimeout(async () => { document.getElementById("progress-inner").style.width = ((index / Object.keys(valuesToGet).length) * 100) + "%"; index++; await getNewValue(); }, valuesToGet[keys[0]]["limited"] ? 550 : 0); } catch (e) { console.log("Error while fetching", keys[0]); console.error(e); for (let key of Object.keys(valuesToGet)) { if (await localforage.getItem(key) === null) { throw new Error("App requested key '" + key + "' but it can't be retrieved at the moment"); } } await postLoad(); } } async function load() { await localforage.setItem("values-to-get", JSON.stringify(valuesToGet)); try { let online = (await (await fetchPlus("/api/test", { timeout: 3000 })).text()); if (online === "SUCCESS") window.connected = true; } catch (e) {} await getNewValue(); } async function postLoad() { for (let key of await localforage.keys()) { if (key !== "images") localStorage.setItem(key, await localforage.getItem(key)) } window.images = JSON.parse(await localforage.getItem("images")); localStorage.setItem("pluralkit-0", localStorage.getItem("pluralkit-raindrops-members")); localStorage.setItem("pluralkit-1", localStorage.getItem("pluralkit-cloudburst-members")); window.data = {}; for (let value of Object.keys(valuesToGet)) { try { window.data[value] = JSON.parse(localStorage.getItem(value)); } catch (e) { window.data[value] = localStorage.getItem(value); } } window.currentFronter = window.data['pluralkit-' + window.data['identity'].id + '-fronters'].members[0] try { let member = window.currentFronter; await (await window.fetch("/bits/Application/SetCurrentIdentity/index.php?Name=" + btoa(member['display_name'] ?? member['name']).replaceAll("+", "-").replaceAll("/", "_") + "&Picture=" + btoa(member['avatar_url'] ?? "./assets/default.png").replaceAll("+", "-").replaceAll("/", "_"))).text(); } catch (e) { try { await (await window.fetch("/bits/Application/SetCurrentIdentity/index.php?Name=" + btoa(window.data['pluralkit-' + window.data['identity'].id + '-members'].filter(i => i.name === "unknown")[0]['display_name']).replaceAll("+", "-").replaceAll("/", "_") + "&Picture=" + btoa(window.data['pluralkit-' + window.data['identity'].id + '-members'].filter(i => i.name === "unknown")[0]['avatar_url']).replaceAll("+", "-").replaceAll("/", "_"))).text(); } catch (e) {} } try { document.getElementById("home-name").innerText = getMiniName(window.currentFronter['display_name'] ?? window.currentFronter['name']); document.getElementById("home-avatar").src = window.data['image-me']; switch (new Date().getHours()) { case 0: case 1: case 2: case 3: case 4: case 5: document.getElementById("home-greeting").innerText = "Good night"; break; case 6: case 7: case 8: case 9: case 10: case 11: document.getElementById("home-greeting").innerText = "Good morning"; break; case 12: case 13: case 14: case 15: case 16: case 17: document.getElementById("home-greeting").innerText = "Good afternoon"; break; case 18: case 19: case 20: case 21: case 22: case 23: document.getElementById("home-greeting").innerText = "Good evening"; break; } } catch (e) { document.getElementById("home-front").style.display = "none"; } window.otherSystem = window.data.identity.id === "raindrops" ? "cloudburst" : "raindrops"; window.otherFronters = window.data["pluralkit-" + otherSystem + "-fronters"]; document.getElementById("home-other-system").innerText = otherSystem === "raindrops" ? "Raindrops System" : "Cloudburst System"; if (window.otherFronters.members[0]) document.getElementById("home-other-name").innerText = window.otherFronters.members[0].display_name ?? window.otherFronters.members[0].name; if (window.otherFronters.members[0]) document.getElementById("home-other-img").src = window.images.profile[otherSystem === "raindrops" ? "gdapd" : "ynmuc"][window.otherFronters.members[0].id]; if (!window.otherFronters.members[0]) document.getElementById("home-other").style.display = "none"; if (!window.connected) { document.getElementById("home-app-planner").classList.add("disabled"); document.getElementById("home-app-emergency").classList.add("disabled"); } if (window.serviceWorkerRegistration) { if (window.serviceWorkerRegistration.sync) { window.serviceWorkerRegistration.sync.register('data-sync') .catch(function(err) { return err; }) .then(() => { console.log("Scheduled background sync for the next time connection is available"); }) } else { console.log("Background sync not possible on this platform"); } } document.getElementById("copyright-year").innerText = new Date().getFullYear().toString(); document.getElementById("update-date").innerText = timeAgo(await localforage.getItem("refresh")); setInterval(async () => { Array.from(document.getElementsByClassName("relative-time")).forEach((el) => { el.innerText = timeAgo(parseInt(el.getAttribute("data-relative-timestamp")) * 1000); }) }, 1000) document.getElementById("loader").style.display = "none"; }