/* This file is part of jellything (https://codeberg.org/metamuffin/jellything) which is licensed under the GNU Affero General Public License (version 3); see /COPYING. Copyright (C) 2023 metamuffin */ /// import { e } from "./jshelper/src/element.ts"; const duration = 200 globalThis.addEventListener("DOMContentLoaded", () => { patch_page() }) globalThis.addEventListener("popstate", async (_e) => { await transition_to(window.location.href, true) }) let disable_transition = false globalThis.addEventListener("navigationrequiresreload", () => { disable_transition = true }) function patch_page() { document.querySelectorAll("a").forEach(el => { el.addEventListener("click", async ev => { ev.preventDefault() await transition_to(el.href) }) }) } async function transition_to(href: string, back?: boolean) { if (disable_transition) return window.location.href = href const trigger_load = prepare_load(href, back) await fade(false) trigger_load() disable_transition = false; await fade(true) } function show_error(mesg: string) { document.body.append(e("span", { class: "jst-error" }, mesg)) } function prepare_load(href: string, back?: boolean) { const r_promise = fetch(href) return async () => { let rt = "" try { const r = await r_promise if (!r.ok) return show_error("Error response. Try again.") rt = await r.text() } catch (e) { if (e instanceof TypeError) return show_error("Navigation failed. Check your connection.") return show_error("unknown error when fetching page") } const [head, body] = rt.split("")[1].split("") if (!back) window.history.pushState({}, "", href) document.head.innerHTML = head document.body.outerHTML = body globalThis.dispatchEvent(new Event("DOMContentLoaded")) } } function fade(dir: boolean) { const overlay = document.createElement("div") overlay.classList.add("jst-fade") overlay.style.backgroundColor = dir ? "black" : "transparent" overlay.style.animationName = dir ? "jst-fadeout" : "jst-fadein" overlay.style.animationFillMode = "forwards" overlay.style.animationDuration = `${duration}ms` document.body.appendChild(overlay) return new Promise(res => { setTimeout(() => { if (dir) document.body.removeChild(overlay) res() }, duration) }) }