From 8f448b80fc6c66de2ea8fc72dd51624ba3c452cf Mon Sep 17 00:00:00 2001 From: Kitteh Date: Fri, 14 May 2021 13:38:29 +0100 Subject: [PATCH] Decouple the page routing system from pageState. --- src/PageRouter.ts | 74 +++++++++++++++++++++++++++++++++++++++++ src/elements/NavBar.ts | 12 +++---- src/globalPageRouter.ts | 6 ++++ src/main.ts | 39 ++++++++++++++-------- src/pageUtils.ts | 15 ++------- src/playground.ts | 4 +++ 6 files changed, 117 insertions(+), 33 deletions(-) create mode 100644 src/PageRouter.ts create mode 100644 src/globalPageRouter.ts diff --git a/src/PageRouter.ts b/src/PageRouter.ts new file mode 100644 index 0000000..77b8572 --- /dev/null +++ b/src/PageRouter.ts @@ -0,0 +1,74 @@ +import { Page } from "./types/Page"; +import { getObjectKeys } from "./utils"; + +type pageList = { + [key: string]: Page; +}; + +const PageDoesNotExistError = new Error("Page does not exist."); +const PageHasNotBeenSetError = new Error("Page has not been set."); + +export class PageRouter extends EventTarget { + constructor(pages: pageList, pageContentElement: HTMLElement, pageTitleElement: HTMLElement) { + super(); + this.pages = pages; + this.pageContentElement = pageContentElement; + this.pageTitleElement = pageTitleElement; + } + + private pages: pageList; + private currentPageID: string; + private currentPage: Page; + + public pageContentElement: HTMLElement; + public pageTitleElement: HTMLElement; + + public async getPageIDs(): Promise { + return getObjectKeys(this.pages); + } + + public async getCurrentPageID(): Promise { + return this.currentPageID; + } + + public async changePage(pageID: string): Promise { + if (!(await this.getPageIDs()).includes(pageID)) throw PageDoesNotExistError; + + // Do cleanup on current page. + if (this.currentPage) { + await this.currentPage.cleanup(); + } + + // Set the current page to the new page + this.currentPageID = pageID; + this.currentPage = this.pages[pageID]; + + // Dispatch an event saying the page has been changed. + this.dispatchEvent(new CustomEvent("pageChanged")); + + // Render the page. + await this.renderPage(); + } + + public async renderPage(): Promise { + if (!this.currentPage) throw PageHasNotBeenSetError; + + // Reset back to blank. + this.pageContentElement.innerHTML = ""; + this.pageTitleElement.innerHTML = ""; + + // TODO: Make Page have a getTitle method. + this.pageTitleElement.innerText = this.currentPage.name; + + await this.currentPage.render(); + } + + public async refresh(): Promise { + await this.renderPage(); + } + + public async goBack(): Promise { + if (!this.currentPage) throw PageHasNotBeenSetError; + await this.currentPage.goBack(); + } +} diff --git a/src/elements/NavBar.ts b/src/elements/NavBar.ts index 71497b5..3931990 100644 --- a/src/elements/NavBar.ts +++ b/src/elements/NavBar.ts @@ -1,8 +1,6 @@ import { ListItem } from "./ListItem"; -import { Page } from "../types/Page"; -import { changePage } from "../pageUtils"; import { makeElement } from "../htmlUtils"; -import { pageState } from "../globalPageState"; +import { pageRouter } from "../globalPageRouter"; import i18next from "i18next"; export function NavBar(): HTMLElement { @@ -23,7 +21,7 @@ export function NavBar(): HTMLElement { tag: "a", text: i18next.t("home_btn"), onclick: async () => { - await changePage("HOME"); + await pageRouter.changePage("HOME"); }, }), ), @@ -32,7 +30,7 @@ export function NavBar(): HTMLElement { tag: "a", text: i18next.t("back_btn"), onclick: async () => { - await (pageState.currentPage as Page).goBack(); + await pageRouter.goBack(); }, }), ), @@ -41,7 +39,7 @@ export function NavBar(): HTMLElement { tag: "a", text: i18next.t("refresh_btn"), onclick: async () => { - await changePage(pageState.currentPageString); + await pageRouter.refresh(); }, }), ), @@ -60,7 +58,7 @@ export function NavBar(): HTMLElement { tag: "a", text: i18next.t("me_btn"), onclick: async () => { - await changePage("ME"); + await pageRouter.changePage("ME"); }, }), ), diff --git a/src/globalPageRouter.ts b/src/globalPageRouter.ts new file mode 100644 index 0000000..5ee44ca --- /dev/null +++ b/src/globalPageRouter.ts @@ -0,0 +1,6 @@ +import { PageRouter } from "./PageRouter"; + +export let pageRouter: PageRouter; +export function setPageRouter(router: PageRouter): void { + pageRouter = router; +} diff --git a/src/main.ts b/src/main.ts index f1f4155..a8523f8 100644 --- a/src/main.ts +++ b/src/main.ts @@ -17,15 +17,17 @@ import "prismjs/components/prism-json"; Prism.highlightAll(); /* eslint-enable */ +// Actual Imports + import { NavBar } from "./elements/NavBar"; -import { changePage, renderPage } from "./pageUtils"; +import { PageRouter } from "./PageRouter"; +import { allPages } from "./allPages"; +import { formatDistance } from "./formatDistance"; import { getSealStatus } from "./api/sys/getSealStatus"; import { makeElement } from "./htmlUtils"; import { pageState } from "./globalPageState"; import { playground } from "./playground"; - -// Translations -import { formatDistance } from "./formatDistance"; +import { setPageRouter } from "./globalPageRouter"; import i18next from "i18next"; // @ts-ignore @@ -65,23 +67,34 @@ async function onLoad(): Promise { window.pageContent = document.querySelector("#pageContent"); + const pageRouter = new PageRouter( + allPages, + document.getElementById("pageContent"), + document.getElementById("pageTitle"), + ); + setPageRouter(pageRouter); + + pageRouter.addEventListener("pageChanged", async function (_) { + pageState.currentPage = await pageRouter.getCurrentPageID(); + document.documentElement.dir = pageState.pageDirection; + }); + if (process.env.NODE_ENV == "development") { await playground(); } - await renderPage(); + await pageRouter.changePage(pageState.currentPageString); - setInterval(() => { - if (pageState.currentPageString != "UNSEAL") { + setInterval(async () => { + if ((await pageRouter.getCurrentPageID()) != "UNSEAL") { if (pageState.apiURL.length != 0) { return; } - void getSealStatus().then((sealStatus) => { - if (sealStatus.sealed) { - void changePage("UNSEAL"); - return; - } - }); + const sealStatus = await getSealStatus(); + if (sealStatus.sealed) { + await pageRouter.changePage("UNSEAL"); + return; + } } }, 5000); } diff --git a/src/pageUtils.ts b/src/pageUtils.ts index 7891b04..0c65458 100644 --- a/src/pageUtils.ts +++ b/src/pageUtils.ts @@ -3,6 +3,7 @@ import { PageState } from "./PageState"; import { getSealStatus } from "./api/sys/getSealStatus"; import { lookupSelf } from "./api/sys/lookupSelf"; import { makeElement } from "./htmlUtils"; +import { pageRouter } from "./globalPageRouter"; import { pageState } from "./globalPageState"; import ClipboardJS from "clipboard"; import UIkit from "uikit"; @@ -79,19 +80,7 @@ export function setErrorText(text: string): void { } export async function changePage(page: string): Promise { - if (pageState.currentPage) { - await (pageState.currentPage as Page).cleanup(); - } - pageState.currentPage = page; - await renderPage(); -} - -export async function renderPage(): Promise { - document.documentElement.dir = pageState.pageDirection; - console.log("Rendering Page: ", (pageState.currentPage as Page).name); - document.querySelector("#pageContent").innerHTML = ""; - setPageTitle((pageState.currentPage as Page).name); - await (pageState.currentPage as Page).render(); + await pageRouter.changePage(page); } export function setPageTitle(title: string | HTMLElement): void { diff --git a/src/playground.ts b/src/playground.ts index 6d47103..29ff118 100644 --- a/src/playground.ts +++ b/src/playground.ts @@ -1,4 +1,6 @@ +import { PageRouter } from "./PageRouter"; import { PageState } from "./PageState"; +import { pageRouter } from "./globalPageRouter"; import { pageState } from "./globalPageState"; import i18next from "i18next"; @@ -11,6 +13,7 @@ declare global { interface Window { pageState: PageState; i18next: unknown; + router: PageRouter; } } @@ -19,4 +22,5 @@ export async function playground(): Promise { console.log("Welcome to Playground!"); window.pageState = pageState; window.i18next = i18next; + window.router = pageRouter; }