mirror of
https://github.com/hrfee/jfa-go.git
synced 2024-12-22 09:00:10 +00:00
ts: move "page" stuff to module
not the happiest with it, but it works alright. PageManager is instantiated, you pass is Page{} objects, which have a (code)name, page title, and url, and a show, hide, and shouldSkip function, each returning a bool. The first two are self explanatory, the last tells you if the page is disabled for some reason (like on setup some are disabled if messages are). You can then call load(<(code)name>), or prev/next(<name>).
This commit is contained in:
parent
b5dea7755b
commit
d2e5209832
106
ts/modules/pages.ts
Normal file
106
ts/modules/pages.ts
Normal file
@ -0,0 +1,106 @@
|
|||||||
|
export interface Page {
|
||||||
|
name: string;
|
||||||
|
title: string;
|
||||||
|
url: string;
|
||||||
|
show: () => boolean;
|
||||||
|
hide: () => boolean;
|
||||||
|
shouldSkip: () => boolean;
|
||||||
|
index?: number;
|
||||||
|
};
|
||||||
|
|
||||||
|
export interface PageConfig {
|
||||||
|
hideOthersOnPageShow: boolean;
|
||||||
|
defaultName: string;
|
||||||
|
defaultTitle: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export class PageManager {
|
||||||
|
pages: Map<string, Page>;
|
||||||
|
pageList: string[];
|
||||||
|
hideOthers: boolean;
|
||||||
|
defaultName: string = "";
|
||||||
|
defaultTitle: string = "";
|
||||||
|
|
||||||
|
private _overridePushState = () => {
|
||||||
|
const pushState = window.history.pushState;
|
||||||
|
window.history.pushState = function (data: any, __: string, _: string | URL) {
|
||||||
|
pushState.apply(window.history, arguments);
|
||||||
|
let ev = { state: data as string } as PopStateEvent;
|
||||||
|
window.onpopstate(ev);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
private _onpopstate = (event: PopStateEvent) => {
|
||||||
|
let name = event.state;
|
||||||
|
if (!(event.state in this.pages)) {
|
||||||
|
name = this.pageList[0]
|
||||||
|
}
|
||||||
|
let success = this.pages[name].show();
|
||||||
|
if (!success) {
|
||||||
|
console.log("failed");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!(this.hideOthers)) {
|
||||||
|
console.log("shoudln't hide others");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
for (let k of this.pageList) {
|
||||||
|
if (name != k) {
|
||||||
|
this.pages[k].hide();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
console.log("loop ended", this);
|
||||||
|
}
|
||||||
|
|
||||||
|
constructor(c: PageConfig) {
|
||||||
|
this.pages = new Map<string, Page>;
|
||||||
|
this.pageList = [];
|
||||||
|
this.hideOthers = c.hideOthersOnPageShow;
|
||||||
|
this.defaultName = c.defaultName;
|
||||||
|
this.defaultTitle = c.defaultTitle;
|
||||||
|
|
||||||
|
this._overridePushState();
|
||||||
|
window.onpopstate = this._onpopstate;
|
||||||
|
}
|
||||||
|
|
||||||
|
setPage(p: Page) {
|
||||||
|
p.index = this.pageList.length;
|
||||||
|
this.pages[p.name] = p;
|
||||||
|
this.pageList.push(p.name);
|
||||||
|
}
|
||||||
|
|
||||||
|
load(name: string = "") {
|
||||||
|
if (!(name in this.pages)) return window.history.pushState(name || this.defaultName, this.defaultTitle, "")
|
||||||
|
const p = this.pages[name];
|
||||||
|
this.loadPage(p);
|
||||||
|
}
|
||||||
|
|
||||||
|
loadPage (p: Page) {
|
||||||
|
window.history.pushState(p.name || this.defaultName, p.title, p.url);
|
||||||
|
}
|
||||||
|
|
||||||
|
prev(name: string = "") {
|
||||||
|
if (!(name in this.pages)) return console.error(`previous page ${name} not found`);
|
||||||
|
let p = this.pages[name];
|
||||||
|
let shouldSkip = true;
|
||||||
|
while (shouldSkip && p.index > 0) {
|
||||||
|
p = this.pages[this.pageList[p.index-1]];
|
||||||
|
shouldSkip = p.shouldSkip();
|
||||||
|
}
|
||||||
|
this.loadPage(p);
|
||||||
|
}
|
||||||
|
|
||||||
|
next(name: string = "") {
|
||||||
|
if (!(name in this.pages)) return console.error(`previous page ${name} not found`);
|
||||||
|
let p = this.pages[name];
|
||||||
|
console.log("next", name, p);
|
||||||
|
console.log("pages", this.pages, this.pageList);
|
||||||
|
let shouldSkip = true;
|
||||||
|
while (shouldSkip && p.index < this.pageList.length) {
|
||||||
|
p = this.pages[this.pageList[p.index+1]];
|
||||||
|
shouldSkip = p.shouldSkip();
|
||||||
|
}
|
||||||
|
console.log("next ended with", p);
|
||||||
|
this.loadPage(p);
|
||||||
|
}
|
||||||
|
};
|
108
ts/setup.ts
108
ts/setup.ts
@ -1,6 +1,7 @@
|
|||||||
import { _get, _post, toggleLoader, notificationBox } from "./modules/common.js";
|
import { _get, _post, toggleLoader, notificationBox } from "./modules/common.js";
|
||||||
import { lang, LangFile, loadLangSelector } from "./modules/lang.js";
|
import { lang, LangFile, loadLangSelector } from "./modules/lang.js";
|
||||||
import { ThemeManager } from "./modules/theme.js";
|
import { ThemeManager } from "./modules/theme.js";
|
||||||
|
import { PageManager } from "./modules/pages.js";
|
||||||
|
|
||||||
interface sWindow extends Window {
|
interface sWindow extends Window {
|
||||||
messages: {};
|
messages: {};
|
||||||
@ -18,6 +19,8 @@ const get = (id: string): HTMLElement => document.getElementById(id);
|
|||||||
const text = (id: string, val: string) => { document.getElementById(id).textContent = val; };
|
const text = (id: string, val: string) => { document.getElementById(id).textContent = val; };
|
||||||
const html = (id: string, val: string) => { document.getElementById(id).innerHTML = val; };
|
const html = (id: string, val: string) => { document.getElementById(id).innerHTML = val; };
|
||||||
|
|
||||||
|
|
||||||
|
// FIXME: Reuse setting types from ts/modules/settings.ts
|
||||||
interface boolEvent extends Event {
|
interface boolEvent extends Event {
|
||||||
detail: boolean;
|
detail: boolean;
|
||||||
}
|
}
|
||||||
@ -513,61 +516,15 @@ for (let section in settings) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const pageNames: string[][] = [];
|
let pages = new PageManager({
|
||||||
|
hideOthersOnPageShow: true,
|
||||||
(() => {
|
defaultName: "welcome",
|
||||||
const pushState = window.history.pushState;
|
defaultTitle: "Setup - jfa-go",
|
||||||
window.history.pushState = function (data: any, __: string, _: string | URL) {
|
});
|
||||||
pushState.apply(window.history, arguments);
|
|
||||||
let ev = { state: data as string } as PopStateEvent;
|
|
||||||
window.onpopstate(ev);
|
|
||||||
};
|
|
||||||
})();
|
|
||||||
|
|
||||||
window.onpopstate = (event: PopStateEvent) => {
|
|
||||||
if (event.state === "welcome") {
|
|
||||||
cards[0].classList.remove("unfocused");
|
|
||||||
for (let i = 1; i < cards.length; i++) { cards[i].classList.add("unfocused"); }
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
for (let i = 0; i < cards.length; i++) {
|
|
||||||
if (event.state === pageNames[i][0]) {
|
|
||||||
cards[i].classList.remove("unfocused");
|
|
||||||
} else {
|
|
||||||
cards[i].classList.add("unfocused");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const cards = Array.from(document.getElementsByClassName("page-container")[0].querySelectorAll(".card.sectioned")) as Array<HTMLDivElement>;
|
const cards = Array.from(document.getElementsByClassName("page-container")[0].querySelectorAll(".card.sectioned")) as Array<HTMLDivElement>;
|
||||||
(window as any).cards = cards;
|
(window as any).cards = cards;
|
||||||
|
|
||||||
const changePageToIndex = (title: string, pageTitle: string, i: number) => {
|
|
||||||
cards[i].classList.remove("unfocused");
|
|
||||||
const urlParams = new URLSearchParams(window.location.search);
|
|
||||||
const lang = urlParams.get("lang");
|
|
||||||
let page = "/#" + title;
|
|
||||||
if (lang) { page += "?lang=" + lang; }
|
|
||||||
console.log("pushing", title, pageTitle, page);
|
|
||||||
window.history.pushState(title || "welcome", pageTitle, page);
|
|
||||||
};
|
|
||||||
|
|
||||||
const changePage = (title: string, pageTitle: string) => {
|
|
||||||
let found = false;
|
|
||||||
for (let i = 0; i < cards.length; i++) {
|
|
||||||
if (!found && pageNames[i][0] == title && !(cards[i].classList.contains("hidden"))) {
|
|
||||||
found = true;
|
|
||||||
changePageToIndex(title, pageTitle, i);
|
|
||||||
} else {
|
|
||||||
cards[i].classList.add("unfocused");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!found) {
|
|
||||||
changePageToIndex(title, pageTitle, 0);
|
|
||||||
}
|
|
||||||
window.scrollTo(0, 0);
|
|
||||||
};
|
|
||||||
|
|
||||||
(() => {
|
(() => {
|
||||||
for (let i = 0; i < cards.length; i++) {
|
for (let i = 0; i < cards.length; i++) {
|
||||||
const card = cards[i];
|
const card = cards[i];
|
||||||
@ -578,37 +535,30 @@ const changePage = (title: string, pageTitle: string) => {
|
|||||||
if (titleEl.classList.contains("welcome")) {
|
if (titleEl.classList.contains("welcome")) {
|
||||||
title = "";
|
title = "";
|
||||||
}
|
}
|
||||||
let pageTitle = titleEl.textContent + " - jfa-go";
|
pages.setPage({
|
||||||
pageNames.push([title, pageTitle]);
|
name: title,
|
||||||
if (back) { back.addEventListener("click", () => {
|
title: titleEl.textContent + " - jfa-go",
|
||||||
for (let ind = cards.length - 1; ind >= 0; ind--) {
|
url: "/#" + title,
|
||||||
if (ind < i && !(cards[ind].classList.contains("hidden"))) {
|
show: () => {
|
||||||
changePage(pageNames[ind][0], pageNames[ind][1]);
|
cards[i].classList.remove("unfocused");
|
||||||
break;
|
return true;
|
||||||
}
|
},
|
||||||
}
|
hide: () => {
|
||||||
}); }
|
cards[i].classList.add("unfocused");
|
||||||
if (next) {
|
return true;
|
||||||
const func = () => {
|
},
|
||||||
|
shouldSkip: () => {
|
||||||
|
return cards[i].classList.contains("hidden");
|
||||||
|
},
|
||||||
|
});
|
||||||
|
if (back) back.addEventListener("click", () => pages.prev(title));
|
||||||
|
if (next) next.addEventListener("click", () => {
|
||||||
if (next.hasAttribute("disabled")) return;
|
if (next.hasAttribute("disabled")) return;
|
||||||
for (let ind = 0; ind < cards.length; ind++) {
|
pages.next(title);
|
||||||
if (ind > i && !(cards[ind].classList.contains("hidden"))) {
|
});
|
||||||
changePage(pageNames[ind][0], pageNames[ind][1]);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
next.addEventListener("click", func)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
})();
|
})();
|
||||||
|
|
||||||
(() => {
|
|
||||||
let initialLocation = window.location.hash.replace("#", "") || "welcome";
|
|
||||||
changePage(initialLocation, "Setup - jfa-go");
|
|
||||||
})();
|
|
||||||
// window.history.replaceState("welcome", "Setup - jfa-go",);
|
|
||||||
|
|
||||||
(() => {
|
(() => {
|
||||||
const button = document.getElementById("jellyfin-test-connection") as HTMLSpanElement;
|
const button = document.getElementById("jellyfin-test-connection") as HTMLSpanElement;
|
||||||
const ogText = button.textContent;
|
const ogText = button.textContent;
|
||||||
@ -665,3 +615,5 @@ const changePage = (title: string, pageTitle: string) => {
|
|||||||
})();
|
})();
|
||||||
|
|
||||||
loadLangSelector("setup");
|
loadLangSelector("setup");
|
||||||
|
|
||||||
|
pages.load(window.location.hash.replace("#", ""));
|
||||||
|
72
ts/user.ts
72
ts/user.ts
@ -5,6 +5,7 @@ import { _get, _post, _delete, notificationBox, whichAnimationEvent, toDateStrin
|
|||||||
import { Login } from "./modules/login.js";
|
import { Login } from "./modules/login.js";
|
||||||
import { Discord, Telegram, Matrix, ServiceConfiguration, MatrixConfiguration } from "./modules/account-linking.js";
|
import { Discord, Telegram, Matrix, ServiceConfiguration, MatrixConfiguration } from "./modules/account-linking.js";
|
||||||
import { Validator, ValidatorConf, ValidatorRespDTO } from "./modules/validator.js";
|
import { Validator, ValidatorConf, ValidatorRespDTO } from "./modules/validator.js";
|
||||||
|
import { PageManager } from "./modules/pages.js";
|
||||||
|
|
||||||
interface userWindow extends Window {
|
interface userWindow extends Window {
|
||||||
jellyfinID: string;
|
jellyfinID: string;
|
||||||
@ -21,6 +22,8 @@ interface userWindow extends Window {
|
|||||||
referralsEnabled: boolean;
|
referralsEnabled: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const basePath = window.location.pathname.replace("/password/reset", "");
|
||||||
|
|
||||||
declare var window: userWindow;
|
declare var window: userWindow;
|
||||||
|
|
||||||
const theme = new ThemeManager(document.getElementById("button-theme"));
|
const theme = new ThemeManager(document.getElementById("button-theme"));
|
||||||
@ -35,6 +38,27 @@ window.token = "";
|
|||||||
|
|
||||||
window.modals = {} as Modals;
|
window.modals = {} as Modals;
|
||||||
|
|
||||||
|
let pages = new PageManager({
|
||||||
|
hideOthersOnPageShow: true,
|
||||||
|
defaultName: "",
|
||||||
|
defaultTitle: document.title,
|
||||||
|
});
|
||||||
|
|
||||||
|
pages.setPage({
|
||||||
|
name: "",
|
||||||
|
title: document.title,
|
||||||
|
url: basePath,
|
||||||
|
show: () => {
|
||||||
|
if (!login.loggedIn) login.login("", "");
|
||||||
|
return true;
|
||||||
|
},
|
||||||
|
hide: () => {
|
||||||
|
window.modals.login.close();
|
||||||
|
return true;
|
||||||
|
},
|
||||||
|
shouldSkip: () => false,
|
||||||
|
});
|
||||||
|
|
||||||
(() => {
|
(() => {
|
||||||
window.modals.login = new Modal(document.getElementById("modal-login"), true);
|
window.modals.login = new Modal(document.getElementById("modal-login"), true);
|
||||||
window.modals.email = new Modal(document.getElementById("modal-email"), false);
|
window.modals.email = new Modal(document.getElementById("modal-email"), false);
|
||||||
@ -49,36 +73,32 @@ window.modals = {} as Modals;
|
|||||||
}
|
}
|
||||||
if (window.pwrEnabled) {
|
if (window.pwrEnabled) {
|
||||||
window.modals.pwr = new Modal(document.getElementById("modal-pwr"), false);
|
window.modals.pwr = new Modal(document.getElementById("modal-pwr"), false);
|
||||||
window.modals.pwr.onclose = () => {
|
pages.setPage({
|
||||||
window.history.pushState("", "", window.location.pathname.replace("/password/reset", ""));
|
name: "reset",
|
||||||
};
|
title: document.title,
|
||||||
const resetButton = document.getElementById("modal-login-pwr");
|
url: basePath+"/password/reset",
|
||||||
resetButton.onclick = () => {
|
show: () => {
|
||||||
window.history.pushState("reset", "", window.location.pathname+"/password/reset");
|
|
||||||
}
|
|
||||||
|
|
||||||
window.onpopstate = (event: PopStateEvent) => {
|
|
||||||
if ((event.state == "reset" || window.location.pathname.includes("/password/reset")) && window.pwrEnabled) {
|
|
||||||
const usernameInput = document.getElementById("login-user") as HTMLInputElement;
|
const usernameInput = document.getElementById("login-user") as HTMLInputElement;
|
||||||
const input = document.getElementById("pwr-address") as HTMLInputElement;
|
const input = document.getElementById("pwr-address") as HTMLInputElement;
|
||||||
input.value = usernameInput.value;
|
input.value = usernameInput.value;
|
||||||
window.modals.login.close();
|
|
||||||
window.modals.pwr.show();
|
window.modals.pwr.show();
|
||||||
} else {
|
return true;
|
||||||
|
},
|
||||||
|
hide: () => {
|
||||||
|
// Don't recursively run this through the onclose event
|
||||||
window.modals.pwr.close(null, true);
|
window.modals.pwr.close(null, true);
|
||||||
if (!login.loggedIn) login.login("", "");
|
return true;
|
||||||
}
|
},
|
||||||
|
shouldSkip: () => false,
|
||||||
|
});
|
||||||
|
window.modals.pwr.onclose = () => {
|
||||||
|
pages.load("");
|
||||||
};
|
};
|
||||||
|
const resetButton = document.getElementById("modal-login-pwr");
|
||||||
|
resetButton.onclick = () => {
|
||||||
|
pages.load("reset");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
})();
|
|
||||||
|
|
||||||
(() => {
|
|
||||||
const pushState = window.history.pushState;
|
|
||||||
window.history.pushState = function (data: any, __: string, _: string | URL) {
|
|
||||||
pushState.apply(window.history, arguments);
|
|
||||||
let ev = { state: data as string } as PopStateEvent;
|
|
||||||
window.onpopstate(ev);
|
|
||||||
};
|
|
||||||
})();
|
})();
|
||||||
|
|
||||||
window.notifications = new notificationBox(document.getElementById('notification-box') as HTMLDivElement, 5);
|
window.notifications = new notificationBox(document.getElementById('notification-box') as HTMLDivElement, 5);
|
||||||
@ -798,8 +818,4 @@ const generatePermutations = (xs: number[]): [number[], number[]][] => {
|
|||||||
|
|
||||||
login.bindLogout(document.getElementById("logout-button"));
|
login.bindLogout(document.getElementById("logout-button"));
|
||||||
|
|
||||||
(() => {
|
pages.load(window.location.pathname.endsWith("/password/reset") ? "reset" : "");
|
||||||
let data = "";
|
|
||||||
if (window.location.pathname.endsWith("/password/reset")) data = "reset";
|
|
||||||
window.history.pushState(data, "", window.location.pathname);
|
|
||||||
})();
|
|
||||||
|
Loading…
Reference in New Issue
Block a user