From bd57be08992e20cf5a9571d47dd5d46c0ae167af Mon Sep 17 00:00:00 2001 From: Alexander Ebert Date: Wed, 15 Dec 2021 15:25:15 +0100 Subject: [PATCH] Implicitly close tabs upon navigation This is required to ensure compatibility with the functionality of legacy user panels. --- .../Core/Ui/Page/Menu/Container.ts | 4 +- ts/WoltLabSuite/Core/Ui/Page/Menu/Main.ts | 6 +- ts/WoltLabSuite/Core/Ui/Page/Menu/Provider.ts | 4 +- ts/WoltLabSuite/Core/Ui/Page/Menu/User.ts | 56 +++++++++++++------ .../Core/Ui/Page/Menu/Container.js | 3 +- .../js/WoltLabSuite/Core/Ui/Page/Menu/Main.js | 5 +- .../js/WoltLabSuite/Core/Ui/Page/Menu/User.js | 46 +++++++++------ 7 files changed, 85 insertions(+), 39 deletions(-) diff --git a/ts/WoltLabSuite/Core/Ui/Page/Menu/Container.ts b/ts/WoltLabSuite/Core/Ui/Page/Menu/Container.ts index 776a43f72b..8e368cbd85 100644 --- a/ts/WoltLabSuite/Core/Ui/Page/Menu/Container.ts +++ b/ts/WoltLabSuite/Core/Ui/Page/Menu/Container.ts @@ -37,7 +37,7 @@ export class PageMenuContainer { scrollDisable(); this.container.hidden = false; - this.provider.refresh(); + this.provider.wakeup(); this.getFocusTrap().activate(); } @@ -50,6 +50,8 @@ export class PageMenuContainer { this.container.hidden = true; this.getFocusTrap().deactivate(); + + this.provider.sleep(); } toggle(): void { diff --git a/ts/WoltLabSuite/Core/Ui/Page/Menu/Main.ts b/ts/WoltLabSuite/Core/Ui/Page/Menu/Main.ts index 9e6c7761f3..43c023c30d 100644 --- a/ts/WoltLabSuite/Core/Ui/Page/Menu/Main.ts +++ b/ts/WoltLabSuite/Core/Ui/Page/Menu/Main.ts @@ -113,7 +113,11 @@ export class PageMenuMain implements PageMenuProvider { return this.mainMenu; } - refresh(): void { + sleep(): void { + /* Does nothing */ + } + + wakeup(): void { /* Does nothing */ } diff --git a/ts/WoltLabSuite/Core/Ui/Page/Menu/Provider.ts b/ts/WoltLabSuite/Core/Ui/Page/Menu/Provider.ts index bed52a2feb..5f2bb0ea0c 100644 --- a/ts/WoltLabSuite/Core/Ui/Page/Menu/Provider.ts +++ b/ts/WoltLabSuite/Core/Ui/Page/Menu/Provider.ts @@ -7,5 +7,7 @@ export interface PageMenuProvider { getMenuButton(): HTMLElement; - refresh(): void; + sleep(): void; + + wakeup(): void; } diff --git a/ts/WoltLabSuite/Core/Ui/Page/Menu/User.ts b/ts/WoltLabSuite/Core/Ui/Page/Menu/User.ts index 01f70c6bc6..a0618508cf 100644 --- a/ts/WoltLabSuite/Core/Ui/Page/Menu/User.ts +++ b/ts/WoltLabSuite/Core/Ui/Page/Menu/User.ts @@ -39,6 +39,7 @@ type LegacyUserPanelApi = { }; export class PageMenuUser implements PageMenuProvider { + private activeTab?: Tab = undefined; private readonly callbackOpen: CallbackOpen; private readonly container: PageMenuContainer; private readonly legacyUserPanels = new Map(); @@ -87,15 +88,20 @@ export class PageMenuUser implements PageMenuProvider { return this.userMenu; } - refresh(): void { - const activeTab = this.tabs.find((element) => element.getAttribute("aria-selected") === "true"); - if (activeTab === undefined) { - this.openNotifications(); - } else { + sleep(): void { + if (this.activeTab) { + this.closeTab(this.activeTab); + } + } + + wakeup(): void { + if (this.activeTab) { // The UI elements in the tab panel are shared and can appear in a different // context. The element might have been moved elsewhere while the menu was // closed. - this.attachViewToPanel(activeTab); + this.openTab(this.activeTab); + } else { + this.openNotifications(); } } @@ -109,18 +115,7 @@ export class PageMenuUser implements PageMenuProvider { } private openTab(tab: Tab): void { - if (tab.getAttribute("aria-selected") === "true") { - return; - } - - const activeTab = this.tabs.find((element) => element.getAttribute("aria-selected") === "true"); - if (activeTab) { - activeTab.setAttribute("aria-selected", "false"); - activeTab.tabIndex = -1; - - const activePanel = this.tabPanels.get(activeTab)!; - activePanel.hidden = true; - } + this.closeActiveTab(); tab.setAttribute("aria-selected", "true"); tab.tabIndex = 0; @@ -133,6 +128,31 @@ export class PageMenuUser implements PageMenuProvider { } this.attachViewToPanel(tab); + + this.activeTab = tab; + } + + private closeActiveTab(): void { + if (!this.activeTab) { + return; + } + + this.closeTab(this.activeTab); + + this.activeTab = undefined; + } + + private closeTab(tab: Tab): void { + tab.setAttribute("aria-selected", "false"); + tab.tabIndex = -1; + + const tabPanel = this.tabPanels.get(tab)!; + tabPanel.hidden = true; + + const legacyPanel = this.legacyUserPanels.get(tab); + if (legacyPanel) { + legacyPanel.close(); + } } private attachViewToPanel(tab: Tab): void { diff --git a/wcfsetup/install/files/js/WoltLabSuite/Core/Ui/Page/Menu/Container.js b/wcfsetup/install/files/js/WoltLabSuite/Core/Ui/Page/Menu/Container.js index bfad0f9bb3..2bd8ed3003 100644 --- a/wcfsetup/install/files/js/WoltLabSuite/Core/Ui/Page/Menu/Container.js +++ b/wcfsetup/install/files/js/WoltLabSuite/Core/Ui/Page/Menu/Container.js @@ -28,7 +28,7 @@ define(["require", "exports", "tslib", "focus-trap", "../../Screen", "../../Clos (0, Screen_1.pageOverlayOpen)(); (0, Screen_1.scrollDisable)(); this.container.hidden = false; - this.provider.refresh(); + this.provider.wakeup(); this.getFocusTrap().activate(); } close() { @@ -37,6 +37,7 @@ define(["require", "exports", "tslib", "focus-trap", "../../Screen", "../../Clos (0, Screen_1.scrollEnable)(); this.container.hidden = true; this.getFocusTrap().deactivate(); + this.provider.sleep(); } toggle() { if (this.container.hidden) { diff --git a/wcfsetup/install/files/js/WoltLabSuite/Core/Ui/Page/Menu/Main.js b/wcfsetup/install/files/js/WoltLabSuite/Core/Ui/Page/Menu/Main.js index 28f01c7452..cfbc2d9d94 100644 --- a/wcfsetup/install/files/js/WoltLabSuite/Core/Ui/Page/Menu/Main.js +++ b/wcfsetup/install/files/js/WoltLabSuite/Core/Ui/Page/Menu/Main.js @@ -81,7 +81,10 @@ define(["require", "exports", "tslib", "./Container", "../../../Language", "../. getMenuButton() { return this.mainMenu; } - refresh() { + sleep() { + /* Does nothing */ + } + wakeup() { /* Does nothing */ } buildMainMenu() { diff --git a/wcfsetup/install/files/js/WoltLabSuite/Core/Ui/Page/Menu/User.js b/wcfsetup/install/files/js/WoltLabSuite/Core/Ui/Page/Menu/User.js index 041a1f6909..c00c886f7d 100644 --- a/wcfsetup/install/files/js/WoltLabSuite/Core/Ui/Page/Menu/User.js +++ b/wcfsetup/install/files/js/WoltLabSuite/Core/Ui/Page/Menu/User.js @@ -16,6 +16,7 @@ define(["require", "exports", "tslib", "./Container", "../../../Language", "../. EventHandler = (0, tslib_1.__importStar)(EventHandler); class PageMenuUser { constructor() { + this.activeTab = undefined; this.legacyUserPanels = new Map(); this.userMenuProviders = new Map(); this.tabPanels = new Map(); @@ -49,16 +50,20 @@ define(["require", "exports", "tslib", "./Container", "../../../Language", "../. getMenuButton() { return this.userMenu; } - refresh() { - const activeTab = this.tabs.find((element) => element.getAttribute("aria-selected") === "true"); - if (activeTab === undefined) { - this.openNotifications(); + sleep() { + if (this.activeTab) { + this.closeTab(this.activeTab); } - else { + } + wakeup() { + if (this.activeTab) { // The UI elements in the tab panel are shared and can appear in a different // context. The element might have been moved elsewhere while the menu was // closed. - this.attachViewToPanel(activeTab); + this.openTab(this.activeTab); + } + else { + this.openNotifications(); } } openNotifications() { @@ -69,16 +74,7 @@ define(["require", "exports", "tslib", "./Container", "../../../Language", "../. this.openTab(notifications); } openTab(tab) { - if (tab.getAttribute("aria-selected") === "true") { - return; - } - const activeTab = this.tabs.find((element) => element.getAttribute("aria-selected") === "true"); - if (activeTab) { - activeTab.setAttribute("aria-selected", "false"); - activeTab.tabIndex = -1; - const activePanel = this.tabPanels.get(activeTab); - activePanel.hidden = true; - } + this.closeActiveTab(); tab.setAttribute("aria-selected", "true"); tab.tabIndex = 0; const tabPanel = this.tabPanels.get(tab); @@ -87,6 +83,24 @@ define(["require", "exports", "tslib", "./Container", "../../../Language", "../. tab.focus(); } this.attachViewToPanel(tab); + this.activeTab = tab; + } + closeActiveTab() { + if (!this.activeTab) { + return; + } + this.closeTab(this.activeTab); + this.activeTab = undefined; + } + closeTab(tab) { + tab.setAttribute("aria-selected", "false"); + tab.tabIndex = -1; + const tabPanel = this.tabPanels.get(tab); + tabPanel.hidden = true; + const legacyPanel = this.legacyUserPanels.get(tab); + if (legacyPanel) { + legacyPanel.close(); + } } attachViewToPanel(tab) { const origin = tab.dataset.origin; -- 2.20.1