mirror of
https://github.com/Novaloop-AG/healthchat-web.git
synced 2026-11-04 01:19:41 +00:00
Merge pull request #4 from Novaloop-AG/feature/user-directory-angular
Feature/user directory angular
This commit is contained in:
@@ -0,0 +1,11 @@
|
|||||||
|
{
|
||||||
|
"permissions": {
|
||||||
|
"allow": [
|
||||||
|
"Bash(ls:*)",
|
||||||
|
"Bash(test:*)",
|
||||||
|
"Bash(yarn test:*)",
|
||||||
|
"Bash(npx tsc:*)",
|
||||||
|
"Bash(yarn lint:types:*)"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -103,6 +103,7 @@ $event-highlight-bg-color: var(--timeline-highlights-color);
|
|||||||
|
|
||||||
/* redirect some variables away from their hardcoded values in the light theme */
|
/* redirect some variables away from their hardcoded values in the light theme */
|
||||||
$settings-grey-fg-color: $primary-content;
|
$settings-grey-fg-color: $primary-content;
|
||||||
|
$tab-label-active-fg-color: $primary-content;
|
||||||
|
|
||||||
/* --eventbubble colors */
|
/* --eventbubble colors */
|
||||||
$eventbubble-self-bg: var(--eventbubble-self-bg, $eventbubble-self-bg);
|
$eventbubble-self-bg: var(--eventbubble-self-bg, $eventbubble-self-bg);
|
||||||
|
|||||||
@@ -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 BlockIcon from "@vector-im/compound-design-tokens/assets/web/icons/block";
|
||||||
|
|
||||||
import TabbedView, { Tab, useActiveTabWithDefault } from "../../structures/TabbedView";
|
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 AccountUserSettingsTab from "../settings/tabs/user/AccountUserSettingsTab";
|
||||||
|
import { useModuleSettingsTabs } from "../../../modules/ExtrasApi";
|
||||||
|
import { ModuleApi } from "../../../modules/Api";
|
||||||
import AppearanceUserSettingsTab from "../settings/tabs/user/AppearanceUserSettingsTab";
|
import AppearanceUserSettingsTab from "../settings/tabs/user/AppearanceUserSettingsTab";
|
||||||
import SecurityUserSettingsTab from "../settings/tabs/user/SecurityUserSettingsTab";
|
import SecurityUserSettingsTab from "../settings/tabs/user/SecurityUserSettingsTab";
|
||||||
import NotificationUserSettingsTab from "../settings/tabs/user/NotificationUserSettingsTab";
|
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);
|
return _t("settings|labs_mjolnir|dialog_title", undefined, subs);
|
||||||
case UserTab.Help:
|
case UserTab.Help:
|
||||||
return _t("setting|help_about|dialog_title", undefined, subs);
|
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 {
|
export default function UserSettingsDialog(props: IProps): JSX.Element {
|
||||||
const voipEnabled = useSettingValue(UIFeature.Voip);
|
const voipEnabled = useSettingValue(UIFeature.Voip);
|
||||||
const mjolnirEnabled = useSettingValue("feature_mjolnir");
|
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
|
// store these props in state as changing tabs back and forth should clear them
|
||||||
const [showMsc4108QrCode, setShowMsc4108QrCode] = useState(props.showMsc4108QrCode);
|
const [showMsc4108QrCode, setShowMsc4108QrCode] = useState(props.showMsc4108QrCode);
|
||||||
const [initialEncryptionState, setInitialEncryptionState] = useState(props.initialEncryptionState);
|
const [initialEncryptionState, setInitialEncryptionState] = useState(props.initialEncryptionState);
|
||||||
@@ -120,7 +129,20 @@ export default function UserSettingsDialog(props: IProps): JSX.Element {
|
|||||||
const getTabs = (): NonEmptyArray<Tab<UserTab>> => {
|
const getTabs = (): NonEmptyArray<Tab<UserTab>> => {
|
||||||
const tabs: Tab<UserTab>[] = [];
|
const tabs: Tab<UserTab>[] = [];
|
||||||
|
|
||||||
tabs.push(
|
// 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(),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// JP: Disabled Account tab for HealthChat (replaced by module "Profil" tab)
|
||||||
|
/*tabs.push(
|
||||||
new Tab(
|
new Tab(
|
||||||
UserTab.Account,
|
UserTab.Account,
|
||||||
_td("settings|account|title"),
|
_td("settings|account|title"),
|
||||||
@@ -128,7 +150,7 @@ export default function UserSettingsDialog(props: IProps): JSX.Element {
|
|||||||
<AccountUserSettingsTab closeSettingsFn={props.onFinished} />,
|
<AccountUserSettingsTab closeSettingsFn={props.onFinished} />,
|
||||||
"UserSettingsGeneral",
|
"UserSettingsGeneral",
|
||||||
),
|
),
|
||||||
);
|
);*/
|
||||||
tabs.push(
|
tabs.push(
|
||||||
new Tab(
|
new Tab(
|
||||||
UserTab.SessionManager,
|
UserTab.SessionManager,
|
||||||
@@ -249,7 +271,8 @@ export default function UserSettingsDialog(props: IProps): JSX.Element {
|
|||||||
return tabs as NonEmptyArray<Tab<UserTab>>;
|
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 => {
|
const setActiveTabId = (tabId: UserTab): void => {
|
||||||
_setActiveTabId(tabId);
|
_setActiveTabId(tabId);
|
||||||
// Clear these so switching away from the tab and back to it will not show the QR code again
|
// Clear these so switching away from the tab and back to it will not show the QR code again
|
||||||
|
|||||||
@@ -5,7 +5,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.
|
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 } from "@element-hq/element-web-module-api";
|
import { type SpacePanelItemProps, type ExtrasApi } from "@element-hq/element-web-module-api";
|
||||||
import { TypedEventEmitter } from "matrix-js-sdk/src/matrix";
|
import { TypedEventEmitter } from "matrix-js-sdk/src/matrix";
|
||||||
|
|
||||||
@@ -15,17 +15,27 @@ export interface ModuleSpacePanelItem extends SpacePanelItemProps {
|
|||||||
spaceKey: string;
|
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 {
|
enum ExtrasApiEvent {
|
||||||
SpacePanelItemsChanged = "SpacePanelItemsChanged",
|
SpacePanelItemsChanged = "SpacePanelItemsChanged",
|
||||||
|
SettingsTabsChanged = "SettingsTabsChanged",
|
||||||
}
|
}
|
||||||
|
|
||||||
interface EmittedEvents {
|
interface EmittedEvents {
|
||||||
[ExtrasApiEvent.SpacePanelItemsChanged]: () => void;
|
[ExtrasApiEvent.SpacePanelItemsChanged]: () => void;
|
||||||
|
[ExtrasApiEvent.SettingsTabsChanged]: () => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
export class ElementWebExtrasApi extends TypedEventEmitter<keyof EmittedEvents, EmittedEvents> implements ExtrasApi {
|
export class ElementWebExtrasApi extends TypedEventEmitter<keyof EmittedEvents, EmittedEvents> implements ExtrasApi {
|
||||||
public spacePanelItems = new Map<string, SpacePanelItemProps>();
|
public spacePanelItems = new Map<string, SpacePanelItemProps>();
|
||||||
public visibleRoomBySpaceKey = new Map<string, () => string[]>();
|
public visibleRoomBySpaceKey = new Map<string, () => string[]>();
|
||||||
|
public settingsTabs = new Map<string, ModuleSettingsTab>();
|
||||||
|
|
||||||
public setSpacePanelItem(spacekey: string, item: SpacePanelItemProps): void {
|
public setSpacePanelItem(spacekey: string, item: SpacePanelItemProps): void {
|
||||||
this.spacePanelItems.set(spacekey, item);
|
this.spacePanelItems.set(spacekey, item);
|
||||||
@@ -35,6 +45,11 @@ export class ElementWebExtrasApi extends TypedEventEmitter<keyof EmittedEvents,
|
|||||||
public getVisibleRoomBySpaceKey(spaceKey: string, cb: () => string[]): void {
|
public getVisibleRoomBySpaceKey(spaceKey: string, cb: () => string[]): void {
|
||||||
this.visibleRoomBySpaceKey.set(spaceKey, cb);
|
this.visibleRoomBySpaceKey.set(spaceKey, cb);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public registerSettingsTab(key: string, tab: ModuleSettingsTab): void {
|
||||||
|
this.settingsTabs.set(key, tab);
|
||||||
|
this.emit(ExtrasApiEvent.SettingsTabsChanged);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export function useModuleSpacePanelItems(api: ElementWebExtrasApi): ModuleSpacePanelItem[] {
|
export function useModuleSpacePanelItems(api: ElementWebExtrasApi): ModuleSpacePanelItem[] {
|
||||||
@@ -53,3 +68,24 @@ export function useModuleSpacePanelItems(api: ElementWebExtrasApi): ModuleSpaceP
|
|||||||
|
|
||||||
return items;
|
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