mirror of
https://github.com/Novaloop-AG/healthchat-web.git
synced 2026-10-31 08:15:07 +00:00
feat(settings): prepend module tabs in UserSettingsDialog
This commit is contained in:
@@ -23,8 +23,10 @@ import LockIcon from "@vector-im/compound-design-tokens/assets/web/icons/lock";
|
||||
import BlockIcon from "@vector-im/compound-design-tokens/assets/web/icons/block";
|
||||
|
||||
import TabbedView, { Tab, useActiveTabWithDefault } from "../../structures/TabbedView";
|
||||
import { _t, _td } from "../../../languageHandler";
|
||||
import { _t, _td, type TranslationKey } from "../../../languageHandler";
|
||||
import AccountUserSettingsTab from "../settings/tabs/user/AccountUserSettingsTab";
|
||||
import { useModuleSettingsTabs } from "../../../modules/ExtrasApi";
|
||||
import { ModuleApi } from "../../../modules/Api";
|
||||
import AppearanceUserSettingsTab from "../settings/tabs/user/AppearanceUserSettingsTab";
|
||||
import SecurityUserSettingsTab from "../settings/tabs/user/SecurityUserSettingsTab";
|
||||
import NotificationUserSettingsTab from "../settings/tabs/user/NotificationUserSettingsTab";
|
||||
@@ -87,12 +89,19 @@ function titleForTabID(tabId: UserTab): React.ReactNode {
|
||||
return _t("settings|labs_mjolnir|dialog_title", undefined, subs);
|
||||
case UserTab.Help:
|
||||
return _t("setting|help_about|dialog_title", undefined, subs);
|
||||
default: {
|
||||
// Module-registered tab — look up the label from the extras API
|
||||
const moduleTab = ModuleApi.instance.extras.settingsTabs.get(tabId);
|
||||
if (moduleTab) return moduleTab.label;
|
||||
return tabId;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export default function UserSettingsDialog(props: IProps): JSX.Element {
|
||||
const voipEnabled = useSettingValue(UIFeature.Voip);
|
||||
const mjolnirEnabled = useSettingValue("feature_mjolnir");
|
||||
const moduleSettingsTabs = useModuleSettingsTabs(ModuleApi.instance.extras);
|
||||
// store these props in state as changing tabs back and forth should clear them
|
||||
const [showMsc4108QrCode, setShowMsc4108QrCode] = useState(props.showMsc4108QrCode);
|
||||
const [initialEncryptionState, setInitialEncryptionState] = useState(props.initialEncryptionState);
|
||||
@@ -120,6 +129,18 @@ export default function UserSettingsDialog(props: IProps): JSX.Element {
|
||||
const getTabs = (): NonEmptyArray<Tab<UserTab>> => {
|
||||
const tabs: Tab<UserTab>[] = [];
|
||||
|
||||
// Prepend module-registered settings tabs (e.g. HealthChat "Profil")
|
||||
for (const moduleTab of moduleSettingsTabs) {
|
||||
tabs.push(
|
||||
new Tab(
|
||||
moduleTab.key as UserTab,
|
||||
moduleTab.label as TranslationKey,
|
||||
moduleTab.icon,
|
||||
moduleTab.body(),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
tabs.push(
|
||||
new Tab(
|
||||
UserTab.Account,
|
||||
@@ -249,7 +270,8 @@ export default function UserSettingsDialog(props: IProps): JSX.Element {
|
||||
return tabs as NonEmptyArray<Tab<UserTab>>;
|
||||
};
|
||||
|
||||
const [activeTabId, _setActiveTabId] = useActiveTabWithDefault(getTabs(), UserTab.Account, props.initialTabId);
|
||||
const defaultTab = moduleSettingsTabs.length > 0 ? (moduleSettingsTabs[0].key as UserTab) : UserTab.Account;
|
||||
const [activeTabId, _setActiveTabId] = useActiveTabWithDefault(getTabs(), defaultTab, props.initialTabId);
|
||||
const setActiveTabId = (tabId: UserTab): void => {
|
||||
_setActiveTabId(tabId);
|
||||
// Clear these so switching away from the tab and back to it will not show the QR code again
|
||||
|
||||
@@ -6,7 +6,7 @@ SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only OR LicenseRef-Element-Com
|
||||
Please see LICENSE files in the repository root for full details.
|
||||
*/
|
||||
|
||||
import { useState } from "react";
|
||||
import { type JSX, useState } from "react";
|
||||
import {
|
||||
type SpacePanelItemProps,
|
||||
type ExtrasApi,
|
||||
@@ -20,18 +20,28 @@ export interface ModuleSpacePanelItem extends SpacePanelItemProps {
|
||||
spaceKey: string;
|
||||
}
|
||||
|
||||
/** Shape of a settings tab registered by a module plugin. */
|
||||
export interface ModuleSettingsTab {
|
||||
label: string;
|
||||
icon: JSX.Element | string | null;
|
||||
body: () => JSX.Element;
|
||||
}
|
||||
|
||||
enum ExtrasApiEvent {
|
||||
SpacePanelItemsChanged = "SpacePanelItemsChanged",
|
||||
SettingsTabsChanged = "SettingsTabsChanged",
|
||||
}
|
||||
|
||||
interface EmittedEvents {
|
||||
[ExtrasApiEvent.SpacePanelItemsChanged]: () => void;
|
||||
[ExtrasApiEvent.SettingsTabsChanged]: () => void;
|
||||
}
|
||||
|
||||
export class ElementWebExtrasApi extends TypedEventEmitter<keyof EmittedEvents, EmittedEvents> implements ExtrasApi {
|
||||
public spacePanelItems = new Map<string, SpacePanelItemProps>();
|
||||
public visibleRoomBySpaceKey = new Map<string, () => string[]>();
|
||||
public roomHeaderButtonsCallbacks: RoomHeaderButtonsCallback[] = [];
|
||||
public settingsTabs = new Map<string, ModuleSettingsTab>();
|
||||
|
||||
public setSpacePanelItem(spacekey: string, item: SpacePanelItemProps): void {
|
||||
this.spacePanelItems.set(spacekey, item);
|
||||
@@ -45,6 +55,11 @@ export class ElementWebExtrasApi extends TypedEventEmitter<keyof EmittedEvents,
|
||||
public addRoomHeaderButtonCallback(cb: RoomHeaderButtonsCallback): void {
|
||||
this.roomHeaderButtonsCallbacks.push(cb);
|
||||
}
|
||||
|
||||
public registerSettingsTab(key: string, tab: ModuleSettingsTab): void {
|
||||
this.settingsTabs.set(key, tab);
|
||||
this.emit(ExtrasApiEvent.SettingsTabsChanged);
|
||||
}
|
||||
}
|
||||
|
||||
export function useModuleSpacePanelItems(api: ElementWebExtrasApi): ModuleSpacePanelItem[] {
|
||||
@@ -63,3 +78,24 @@ export function useModuleSpacePanelItems(api: ElementWebExtrasApi): ModuleSpaceP
|
||||
|
||||
return items;
|
||||
}
|
||||
|
||||
export interface ModuleSettingsTabEntry extends ModuleSettingsTab {
|
||||
key: string;
|
||||
}
|
||||
|
||||
export function useModuleSettingsTabs(api: ElementWebExtrasApi): ModuleSettingsTabEntry[] {
|
||||
const getTabs = (): ModuleSettingsTabEntry[] => {
|
||||
return Array.from(api.settingsTabs.entries()).map(([key, tab]) => ({
|
||||
key,
|
||||
...tab,
|
||||
}));
|
||||
};
|
||||
|
||||
const [tabs, setTabs] = useState<ModuleSettingsTabEntry[]>(getTabs);
|
||||
|
||||
useTypedEventEmitter(api, ExtrasApiEvent.SettingsTabsChanged, () => {
|
||||
setTabs(getTabs());
|
||||
});
|
||||
|
||||
return tabs;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user