diff --git a/ts/admin.ts b/ts/admin.ts index 4dcf854..202e216 100644 --- a/ts/admin.ts +++ b/ts/admin.ts @@ -152,15 +152,19 @@ let navigated = false; // load tabs const tabs: { id: string; url: string; reloader: () => void; unloader?: () => void }[] = []; [window.invites, accounts, activity, settings].forEach((p: AsTab) => { - let t: { id: string; url: string; reloader: () => void; unloader?: () => void } = { + let t: { id: string; url: string; reloader: (previous?: AsTab) => void; unloader?: () => void } = { id: p.tabName, url: p.pagePath, - reloader: () => { + reloader: (previous: AsTab) => { if (isPageEventBindable(p)) p.bindPageEvents(); if (!navigated && isNavigatable(p) && p.isURL()) { navigated = true; p.navigate(); } else { + if (navigated && previous && isNavigatable(previous)) { + // Clear the query param, as it was likely for a different page + previous.clearURL(); + } p.reload(() => {}); } }, @@ -170,6 +174,7 @@ const tabs: { id: string; url: string; reloader: () => void; unloader?: () => vo window.tabs.addTab( t.id, window.pages.Base + window.pages.Admin + "/" + t.url, + p, null, t.reloader, t.unloader || null, diff --git a/ts/modules/accounts.ts b/ts/modules/accounts.ts index a43868e..b6fa83f 100644 --- a/ts/modules/accounts.ts +++ b/ts/modules/accounts.ts @@ -2516,6 +2516,10 @@ export class accountsList extends PaginatedList implements Navigatable, AsTab { if (details) this.details(details); }); }; + + clearURL() { + this._search.clearURL(); + } } // An alternate view showing accounts in sub-lists grouped by group/label. diff --git a/ts/modules/activity.ts b/ts/modules/activity.ts index 4284239..5bfd9af 100644 --- a/ts/modules/activity.ts +++ b/ts/modules/activity.ts @@ -708,4 +708,8 @@ export class activityList extends PaginatedList implements Navigatable, AsTab { } this._search.navigate(urlParams.toString()); }; + + clearURL() { + this._search.clearURL(); + } } diff --git a/ts/modules/invites.ts b/ts/modules/invites.ts index c9f85d5..017c95a 100644 --- a/ts/modules/invites.ts +++ b/ts/modules/invites.ts @@ -818,6 +818,14 @@ export class DOMInviteList implements InviteList { this.focusInvite(inviteCode, window.lang.notif("errorInviteNotFound")); }; + clearURL() { + const url = new URL(window.location.href); + if (!url.searchParams.has("invite")) return; + url.searchParams.delete("invite"); + console.log("pushing", url.toString()); + window.history.pushState(null, "", url.toString()); + } + constructor() { this._list = document.getElementById("invites") as HTMLDivElement; this.empty = true; diff --git a/ts/modules/search.ts b/ts/modules/search.ts index eb076d7..9d9c7fc 100644 --- a/ts/modules/search.ts +++ b/ts/modules/search.ts @@ -731,6 +731,10 @@ export class Search implements Navigatable { this.setQueryParam(""); }; + clearURL() { + this.clearQueryParam(); + } + // setQueryParam sets the ?search query param to the current searchbox content, // or value if given. If everything is set up correctly, this should trigger a search when it is // set to a new value. diff --git a/ts/modules/tabs.ts b/ts/modules/tabs.ts index efe2b0c..74c67ab 100644 --- a/ts/modules/tabs.ts +++ b/ts/modules/tabs.ts @@ -1,4 +1,4 @@ -import { PageManager } from "../modules/pages.js"; +import { PageManager } from "./pages"; export function isPageEventBindable(object: any): object is PageEventBindable { return "bindPageEvents" in object; @@ -12,7 +12,7 @@ export class TabManager implements TabManager { private _current: string = ""; private _baseOffset = -1; tabs: Map; - pages: PageManager; + pages: Pages; constructor() { this.tabs = new Map(); @@ -26,14 +26,16 @@ export class TabManager implements TabManager { addTab = ( tabID: string, url: string, - preFunc = () => void {}, - postFunc = () => void {}, + contentObject: AsTab | null, + preFunc: (previous?: AsTab) => void = (_?: AsTab) => void {}, + postFunc: (previous?: AsTab) => void = (_?: AsTab) => void {}, unloadFunc = () => void {}, ) => { let tab: Tab = { page: null, tabEl: document.getElementById("tab-" + tabID) as HTMLDivElement, buttonEl: document.getElementById("button-tab-" + tabID) as HTMLButtonElement, + contentObject: contentObject, preFunc: preFunc, postFunc: postFunc, }; @@ -91,14 +93,16 @@ export class TabManager implements TabManager { [t] = this.tabs.values(); } + const prev = this.tabs.get(this.current); + this._current = t.page.name; if (t.preFunc && !noRun) { - t.preFunc(); + t.preFunc(prev?.contentObject); } this.pages.load(tabID); if (t.postFunc && !noRun) { - t.postFunc(); + t.postFunc(prev?.contentObject); } }; } diff --git a/ts/typings/d.ts b/ts/typings/d.ts index 685c155..3eb29a9 100644 --- a/ts/typings/d.ts +++ b/ts/typings/d.ts @@ -75,6 +75,8 @@ declare interface AsTab { declare interface Navigatable { // isURL will return whether the given url (or the current page url if not passed) is a valid link to some resource(s) in the class. isURL(url?: string): boolean; + // clearURL will remove related query params from the current URL. It will likely be called when switching pages. + clearURL(): void; // navigate will load and focus the resource(s) in the class referenced by the given url (or current page url if not passed). navigate(url?: string): void; } @@ -196,14 +198,22 @@ declare interface Tab { page: Page; tabEl: HTMLDivElement; buttonEl: HTMLSpanElement; - preFunc?: () => void; - postFunc?: () => void; + contentObject?: AsTab; + preFunc?: (previous?: AsTab) => void; + postFunc?: (previous?: AsTab) => void; } declare interface Tabs { tabs: Map; pages: Pages; - addTab(tabID: string, url: string, preFunc: () => void, postFunc: () => void, unloadFunc: () => void): void; + addTab( + tabID: string, + url: string, + contentObject: AsTab | null, + preFunc: () => void, + postFunc: () => void, + unloadFunc: () => void, + ): void; current: string; switch(tabID: string, noRun?: boolean): void; }