Convert UserSettings to functional component (#12474)
* Convert UserSettings to functional component * Put comment back * Fix test * Unused imports
This commit is contained in:
parent
bb4f57583f
commit
906c9dd948
2 changed files with 35 additions and 62 deletions
|
@ -1,6 +1,6 @@
|
||||||
/*
|
/*
|
||||||
Copyright 2019 New Vector Ltd
|
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");
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
you may not use this file except in compliance with 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 TabbedView, { Tab } from "../../structures/TabbedView";
|
||||||
import { _t, _td } from "../../../languageHandler";
|
import { _t, _td } from "../../../languageHandler";
|
||||||
import GeneralUserSettingsTab from "../settings/tabs/user/GeneralUserSettingsTab";
|
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 LabsUserSettingsTab, { showLabsFlags } from "../settings/tabs/user/LabsUserSettingsTab";
|
||||||
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";
|
||||||
|
@ -37,6 +37,7 @@ import SessionManagerTab from "../settings/tabs/user/SessionManagerTab";
|
||||||
import { UserTab } from "./UserTab";
|
import { UserTab } from "./UserTab";
|
||||||
import { NonEmptyArray } from "../../../@types/common";
|
import { NonEmptyArray } from "../../../@types/common";
|
||||||
import { SDKContext, SdkContextClass } from "../../../contexts/SDKContext";
|
import { SDKContext, SdkContextClass } from "../../../contexts/SDKContext";
|
||||||
|
import { useSettingValue } from "../../../hooks/useSettings";
|
||||||
|
|
||||||
interface IProps {
|
interface IProps {
|
||||||
initialTabId?: UserTab;
|
initialTabId?: UserTab;
|
||||||
|
@ -44,35 +45,11 @@ interface IProps {
|
||||||
onFinished(): void;
|
onFinished(): void;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface IState {
|
export default function UserSettingsDialog(props: IProps): JSX.Element {
|
||||||
mjolnirEnabled: boolean;
|
const voipEnabled = useSettingValue<boolean>(UIFeature.Voip);
|
||||||
}
|
const mjolnirEnabled = useSettingValue<boolean>("feature_mjolnir");
|
||||||
|
|
||||||
export default class UserSettingsDialog extends React.Component<IProps, IState> {
|
const getTabs = (): NonEmptyArray<Tab<UserTab>> => {
|
||||||
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));
|
|
||||||
}
|
|
||||||
|
|
||||||
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<Tab<UserTab>> {
|
|
||||||
const tabs: Tab<UserTab>[] = [];
|
const tabs: Tab<UserTab>[] = [];
|
||||||
|
|
||||||
tabs.push(
|
tabs.push(
|
||||||
|
@ -80,7 +57,7 @@ export default class UserSettingsDialog extends React.Component<IProps, IState>
|
||||||
UserTab.General,
|
UserTab.General,
|
||||||
_td("common|general"),
|
_td("common|general"),
|
||||||
"mx_UserSettingsDialog_settingsIcon",
|
"mx_UserSettingsDialog_settingsIcon",
|
||||||
<GeneralUserSettingsTab closeSettingsFn={this.props.onFinished} />,
|
<GeneralUserSettingsTab closeSettingsFn={props.onFinished} />,
|
||||||
"UserSettingsGeneral",
|
"UserSettingsGeneral",
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
@ -90,7 +67,6 @@ export default class UserSettingsDialog extends React.Component<IProps, IState>
|
||||||
_td("settings|sessions|title"),
|
_td("settings|sessions|title"),
|
||||||
"mx_UserSettingsDialog_sessionsIcon",
|
"mx_UserSettingsDialog_sessionsIcon",
|
||||||
<SessionManagerTab />,
|
<SessionManagerTab />,
|
||||||
// don't track with posthog while under construction
|
|
||||||
undefined,
|
undefined,
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
@ -117,7 +93,7 @@ export default class UserSettingsDialog extends React.Component<IProps, IState>
|
||||||
UserTab.Preferences,
|
UserTab.Preferences,
|
||||||
_td("common|preferences"),
|
_td("common|preferences"),
|
||||||
"mx_UserSettingsDialog_preferencesIcon",
|
"mx_UserSettingsDialog_preferencesIcon",
|
||||||
<PreferencesUserSettingsTab closeSettingsFn={this.props.onFinished} />,
|
<PreferencesUserSettingsTab closeSettingsFn={props.onFinished} />,
|
||||||
"UserSettingsPreferences",
|
"UserSettingsPreferences",
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
@ -140,7 +116,7 @@ export default class UserSettingsDialog extends React.Component<IProps, IState>
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|
||||||
if (SettingsStore.getValue(UIFeature.Voip)) {
|
if (voipEnabled) {
|
||||||
tabs.push(
|
tabs.push(
|
||||||
new Tab(
|
new Tab(
|
||||||
UserTab.Voice,
|
UserTab.Voice,
|
||||||
|
@ -157,11 +133,11 @@ export default class UserSettingsDialog extends React.Component<IProps, IState>
|
||||||
UserTab.Security,
|
UserTab.Security,
|
||||||
_td("room_settings|security|title"),
|
_td("room_settings|security|title"),
|
||||||
"mx_UserSettingsDialog_securityIcon",
|
"mx_UserSettingsDialog_securityIcon",
|
||||||
<SecurityUserSettingsTab closeSettingsFn={this.props.onFinished} />,
|
<SecurityUserSettingsTab closeSettingsFn={props.onFinished} />,
|
||||||
"UserSettingsSecurityPrivacy",
|
"UserSettingsSecurityPrivacy",
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
// Show the Labs tab if enabled or if there are any active betas
|
|
||||||
if (showLabsFlags() || SettingsStore.getFeatureSettingNames().some((k) => SettingsStore.getBetaInfo(k))) {
|
if (showLabsFlags() || SettingsStore.getFeatureSettingNames().some((k) => SettingsStore.getBetaInfo(k))) {
|
||||||
tabs.push(
|
tabs.push(
|
||||||
new Tab(
|
new Tab(
|
||||||
|
@ -173,7 +149,7 @@ export default class UserSettingsDialog extends React.Component<IProps, IState>
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
if (this.state.mjolnirEnabled) {
|
if (mjolnirEnabled) {
|
||||||
tabs.push(
|
tabs.push(
|
||||||
new Tab(
|
new Tab(
|
||||||
UserTab.Mjolnir,
|
UserTab.Mjolnir,
|
||||||
|
@ -195,29 +171,23 @@ export default class UserSettingsDialog extends React.Component<IProps, IState>
|
||||||
);
|
);
|
||||||
|
|
||||||
return tabs as NonEmptyArray<Tab<UserTab>>;
|
return tabs as NonEmptyArray<Tab<UserTab>>;
|
||||||
}
|
};
|
||||||
|
|
||||||
public render(): React.ReactNode {
|
return (
|
||||||
return (
|
// XXX: SDKContext is provided within the LoggedInView subtree.
|
||||||
// XXX: SDKContext is provided within the LoggedInView subtree.
|
// Modals function outside the MatrixChat React tree, so sdkContext is reprovided here to simulate that.
|
||||||
// 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.
|
||||||
// The longer term solution is to move our ModalManager into the React tree to inherit contexts properly.
|
<SDKContext.Provider value={props.sdkContext}>
|
||||||
<SDKContext.Provider value={this.props.sdkContext}>
|
<BaseDialog
|
||||||
<BaseDialog
|
className="mx_UserSettingsDialog"
|
||||||
className="mx_UserSettingsDialog"
|
hasCancel={true}
|
||||||
hasCancel={true}
|
onFinished={props.onFinished}
|
||||||
onFinished={this.props.onFinished}
|
title={_t("common|settings")}
|
||||||
title={_t("common|settings")}
|
>
|
||||||
>
|
<div className="mx_SettingsDialog_content">
|
||||||
<div className="mx_SettingsDialog_content">
|
<TabbedView tabs={getTabs()} initialTabId={props.initialTabId} screenName="UserSettings" />
|
||||||
<TabbedView
|
</div>
|
||||||
tabs={this.getTabs()}
|
</BaseDialog>
|
||||||
initialTabId={this.props.initialTabId}
|
</SDKContext.Provider>
|
||||||
screenName="UserSettings"
|
);
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</BaseDialog>
|
|
||||||
</SDKContext.Provider>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -152,14 +152,17 @@ describe("<UserSettingsDialog />", () => {
|
||||||
watchSettingCallbacks[settingName] = callback;
|
watchSettingCallbacks[settingName] = callback;
|
||||||
return `mock-watcher-id-${settingName}`;
|
return `mock-watcher-id-${settingName}`;
|
||||||
});
|
});
|
||||||
|
mockSettingsStore.getValue.mockReturnValue(false);
|
||||||
|
|
||||||
const { queryByTestId, unmount } = render(getComponent());
|
const { queryByTestId, unmount } = render(getComponent());
|
||||||
expect(queryByTestId(`settings-tab-${UserTab.Mjolnir}`)).toBeFalsy();
|
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
|
// call the watch setting callback
|
||||||
|
mockSettingsStore.getValue.mockReturnValue(true);
|
||||||
watchSettingCallbacks["feature_mjolnir"]("feature_mjolnir", "", SettingLevel.ACCOUNT, true, true);
|
watchSettingCallbacks["feature_mjolnir"]("feature_mjolnir", "", SettingLevel.ACCOUNT, true, true);
|
||||||
|
|
||||||
// tab is rendered now
|
// tab is rendered now
|
||||||
expect(queryByTestId(`settings-tab-${UserTab.Mjolnir}`)).toBeTruthy();
|
expect(queryByTestId(`settings-tab-${UserTab.Mjolnir}`)).toBeTruthy();
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue