diff --git a/src/components/views/dialogs/UserSettingsDialog.tsx b/src/components/views/dialogs/UserSettingsDialog.tsx index 820617ae962..a6c82d50c2c 100644 --- a/src/components/views/dialogs/UserSettingsDialog.tsx +++ b/src/components/views/dialogs/UserSettingsDialog.tsx @@ -1,6 +1,6 @@ /* Copyright 2019 New Vector Ltd -Copyright 2019 The Matrix.org Foundation C.I.C. +Copyright 2019, 2024 The Matrix.org Foundation C.I.C. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -20,7 +20,7 @@ import React from "react"; import TabbedView, { Tab } from "../../structures/TabbedView"; import { _t, _td } from "../../../languageHandler"; import GeneralUserSettingsTab from "../settings/tabs/user/GeneralUserSettingsTab"; -import SettingsStore, { CallbackFn } from "../../../settings/SettingsStore"; +import SettingsStore from "../../../settings/SettingsStore"; import LabsUserSettingsTab, { showLabsFlags } from "../settings/tabs/user/LabsUserSettingsTab"; import AppearanceUserSettingsTab from "../settings/tabs/user/AppearanceUserSettingsTab"; import SecurityUserSettingsTab from "../settings/tabs/user/SecurityUserSettingsTab"; @@ -37,6 +37,7 @@ import SessionManagerTab from "../settings/tabs/user/SessionManagerTab"; import { UserTab } from "./UserTab"; import { NonEmptyArray } from "../../../@types/common"; import { SDKContext, SdkContextClass } from "../../../contexts/SDKContext"; +import { useSettingValue } from "../../../hooks/useSettings"; interface IProps { initialTabId?: UserTab; @@ -44,35 +45,11 @@ interface IProps { onFinished(): void; } -interface IState { - mjolnirEnabled: boolean; -} - -export default class UserSettingsDialog extends React.Component { - private settingsWatchers: string[] = []; - - public constructor(props: IProps) { - super(props); - - this.state = { - mjolnirEnabled: SettingsStore.getValue("feature_mjolnir"), - }; - } - - public componentDidMount(): void { - this.settingsWatchers = [SettingsStore.watchSetting("feature_mjolnir", null, this.mjolnirChanged)]; - } - - public componentWillUnmount(): void { - this.settingsWatchers.forEach((watcherRef) => SettingsStore.unwatchSetting(watcherRef)); - } +export default function UserSettingsDialog(props: IProps): JSX.Element { + const voipEnabled = useSettingValue(UIFeature.Voip); + const mjolnirEnabled = useSettingValue("feature_mjolnir"); - private mjolnirChanged: CallbackFn = (settingName, roomId, atLevel, newValue) => { - // We can cheat because we know what levels a feature is tracked at, and how it is tracked - this.setState({ mjolnirEnabled: newValue }); - }; - - private getTabs(): NonEmptyArray> { + const getTabs = (): NonEmptyArray> => { const tabs: Tab[] = []; tabs.push( @@ -80,7 +57,7 @@ export default class UserSettingsDialog extends React.Component UserTab.General, _td("common|general"), "mx_UserSettingsDialog_settingsIcon", - , + , "UserSettingsGeneral", ), ); @@ -90,7 +67,6 @@ export default class UserSettingsDialog extends React.Component _td("settings|sessions|title"), "mx_UserSettingsDialog_sessionsIcon", , - // don't track with posthog while under construction undefined, ), ); @@ -117,7 +93,7 @@ export default class UserSettingsDialog extends React.Component UserTab.Preferences, _td("common|preferences"), "mx_UserSettingsDialog_preferencesIcon", - , + , "UserSettingsPreferences", ), ); @@ -140,7 +116,7 @@ export default class UserSettingsDialog extends React.Component ), ); - if (SettingsStore.getValue(UIFeature.Voip)) { + if (voipEnabled) { tabs.push( new Tab( UserTab.Voice, @@ -157,11 +133,11 @@ export default class UserSettingsDialog extends React.Component UserTab.Security, _td("room_settings|security|title"), "mx_UserSettingsDialog_securityIcon", - , + , "UserSettingsSecurityPrivacy", ), ); - // Show the Labs tab if enabled or if there are any active betas + if (showLabsFlags() || SettingsStore.getFeatureSettingNames().some((k) => SettingsStore.getBetaInfo(k))) { tabs.push( new Tab( @@ -173,7 +149,7 @@ export default class UserSettingsDialog extends React.Component ), ); } - if (this.state.mjolnirEnabled) { + if (mjolnirEnabled) { tabs.push( new Tab( UserTab.Mjolnir, @@ -195,29 +171,23 @@ export default class UserSettingsDialog extends React.Component ); return tabs as NonEmptyArray>; - } + }; - public render(): React.ReactNode { - return ( - // XXX: SDKContext is provided within the LoggedInView subtree. - // Modals function outside the MatrixChat React tree, so sdkContext is reprovided here to simulate that. - // The longer term solution is to move our ModalManager into the React tree to inherit contexts properly. - - -
- -
-
-
- ); - } + return ( + // XXX: SDKContext is provided within the LoggedInView subtree. + // Modals function outside the MatrixChat React tree, so sdkContext is reprovided here to simulate that. + // The longer term solution is to move our ModalManager into the React tree to inherit contexts properly. + + +
+ +
+
+
+ ); } diff --git a/test/components/views/dialogs/UserSettingsDialog-test.tsx b/test/components/views/dialogs/UserSettingsDialog-test.tsx index a2cd034ba36..7524f1469fd 100644 --- a/test/components/views/dialogs/UserSettingsDialog-test.tsx +++ b/test/components/views/dialogs/UserSettingsDialog-test.tsx @@ -152,14 +152,17 @@ describe("", () => { watchSettingCallbacks[settingName] = callback; return `mock-watcher-id-${settingName}`; }); + mockSettingsStore.getValue.mockReturnValue(false); const { queryByTestId, unmount } = render(getComponent()); expect(queryByTestId(`settings-tab-${UserTab.Mjolnir}`)).toBeFalsy(); - expect(mockSettingsStore.watchSetting.mock.calls[0][0]).toEqual("feature_mjolnir"); + expect(mockSettingsStore.watchSetting).toHaveBeenCalledWith("feature_mjolnir", null, expect.anything()); // call the watch setting callback + mockSettingsStore.getValue.mockReturnValue(true); watchSettingCallbacks["feature_mjolnir"]("feature_mjolnir", "", SettingLevel.ACCOUNT, true, true); + // tab is rendered now expect(queryByTestId(`settings-tab-${UserTab.Mjolnir}`)).toBeTruthy();