Introduce a concept of UI features, using it for URL previews at first
Fixes https://github.com/vector-im/element-web/issues/15176 This is effectively the base for all of https://github.com/vector-im/element-web/issues/15185
This commit is contained in:
parent
ab91ce4b2d
commit
f4f30a3274
7 changed files with 108 additions and 6 deletions
|
@ -120,6 +120,18 @@ Call `SettingsStore.getValue()` as you would for any other setting.
|
|||
|
||||
Call `SettingsStore.setValue("feature_name", null, SettingLevel.DEVICE, true)`.
|
||||
|
||||
### A note on UI features
|
||||
|
||||
UI features are a different concept to plain features. Instead of being representative of unstable or
|
||||
unpredicatable behaviour, they are logical chunks of UI which can be disabled by deployments for ease
|
||||
of understanding with users. They are simply represented as boring settings with a convention of being
|
||||
named as `UIFeature.$location` where `$location` is a rough descriptor of what is toggled, such as
|
||||
`URLPreviews` or `Communities`.
|
||||
|
||||
UI features also tend to have their own setting controller (see below) to manipulate settings which might
|
||||
be affected by the UI feature being disabled. For example, if URL previews are disabled as a UI feature
|
||||
then the URL preview options will use the `UIFeatureController` to ensure they remain disabled while the
|
||||
UI feature is disabled.
|
||||
|
||||
## Setting controllers
|
||||
|
||||
|
@ -226,4 +238,3 @@ In practice, handlers which rely on remote changes (account data, room events, e
|
|||
generalized `WatchManager` - a class specifically designed to deduplicate the logic of managing watchers. The handlers
|
||||
which are localized to the local client (device) generally just trigger the `WatchManager` when they manipulate the
|
||||
setting themselves as there's nothing to really 'watch'.
|
||||
|
||||
|
|
|
@ -22,6 +22,8 @@ import * as sdk from "../../../../..";
|
|||
import AccessibleButton from "../../../elements/AccessibleButton";
|
||||
import dis from "../../../../../dispatcher/dispatcher";
|
||||
import MatrixClientContext from "../../../../../contexts/MatrixClientContext";
|
||||
import SettingsStore from "../../../../../settings/SettingsStore";
|
||||
import {UIFeature} from "../../../../../settings/UIFeature";
|
||||
|
||||
export default class GeneralRoomSettingsTab extends React.Component {
|
||||
static propTypes = {
|
||||
|
@ -61,6 +63,16 @@ export default class GeneralRoomSettingsTab extends React.Component {
|
|||
const canChangeGroups = room.currentState.mayClientSendStateEvent("m.room.related_groups", client);
|
||||
const groupsEvent = room.currentState.getStateEvents("m.room.related_groups", "");
|
||||
|
||||
let urlPreviewSettings = <>
|
||||
<span className='mx_SettingsTab_subheading'>{_t("URL Previews")}</span>
|
||||
<div className='mx_SettingsTab_section'>
|
||||
<UrlPreviewSettings room={room} />
|
||||
</div>
|
||||
</>;
|
||||
if (!SettingsStore.getValue(UIFeature.URLPreviews)) {
|
||||
urlPreviewSettings = null;
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="mx_SettingsTab mx_GeneralRoomSettingsTab">
|
||||
<div className="mx_SettingsTab_heading">{_t("General")}</div>
|
||||
|
@ -82,10 +94,7 @@ export default class GeneralRoomSettingsTab extends React.Component {
|
|||
relatedGroupsEvent={groupsEvent} />
|
||||
</div>
|
||||
|
||||
<span className='mx_SettingsTab_subheading'>{_t("URL Previews")}</span>
|
||||
<div className='mx_SettingsTab_section'>
|
||||
<UrlPreviewSettings room={room} />
|
||||
</div>
|
||||
{urlPreviewSettings}
|
||||
|
||||
<span className='mx_SettingsTab_subheading'>{_t("Leave room")}</span>
|
||||
<div className='mx_SettingsTab_section'>
|
||||
|
|
|
@ -23,6 +23,7 @@ import Field from "../../../elements/Field";
|
|||
import * as sdk from "../../../../..";
|
||||
import PlatformPeg from "../../../../../PlatformPeg";
|
||||
import {SettingLevel} from "../../../../../settings/SettingLevel";
|
||||
import {UIFeature} from "../../../../../settings/UIFeature";
|
||||
|
||||
export default class PreferencesUserSettingsTab extends React.Component {
|
||||
static ROOM_LIST_SETTINGS = [
|
||||
|
@ -138,6 +139,10 @@ export default class PreferencesUserSettingsTab extends React.Component {
|
|||
};
|
||||
|
||||
_renderGroup(settingIds) {
|
||||
if (!SettingsStore.getValue(UIFeature.URLPreviews)) {
|
||||
settingIds = settingIds.filter(i => i !== 'urlPreviewsEnabled');
|
||||
}
|
||||
|
||||
const SettingsFlag = sdk.getComponent("views.elements.SettingsFlag");
|
||||
return settingIds.map(i => <SettingsFlag key={i} name={i} level={SettingLevel.ACCOUNT} />);
|
||||
}
|
||||
|
|
|
@ -946,8 +946,8 @@
|
|||
"This room is bridging messages to the following platforms. <a>Learn more.</a>": "This room is bridging messages to the following platforms. <a>Learn more.</a>",
|
||||
"This room isn’t bridging messages to any platforms. <a>Learn more.</a>": "This room isn’t bridging messages to any platforms. <a>Learn more.</a>",
|
||||
"Bridges": "Bridges",
|
||||
"Room Addresses": "Room Addresses",
|
||||
"URL Previews": "URL Previews",
|
||||
"Room Addresses": "Room Addresses",
|
||||
"Uploaded sound": "Uploaded sound",
|
||||
"Sounds": "Sounds",
|
||||
"Notification sound": "Notification sound",
|
||||
|
|
|
@ -32,6 +32,8 @@ import UseSystemFontController from './controllers/UseSystemFontController';
|
|||
import { SettingLevel } from "./SettingLevel";
|
||||
import SettingController from "./controllers/SettingController";
|
||||
import { RightPanelPhases } from "../stores/RightPanelStorePhases";
|
||||
import UIFeatureController from "./controllers/UIFeatureController";
|
||||
import { UIFeature } from "./UIFeature";
|
||||
|
||||
// These are just a bunch of helper arrays to avoid copy/pasting a bunch of times
|
||||
const LEVELS_ROOM_SETTINGS = [
|
||||
|
@ -69,6 +71,10 @@ const LEVELS_DEVICE_ONLY_SETTINGS_WITH_CONFIG = [
|
|||
SettingLevel.DEVICE,
|
||||
SettingLevel.CONFIG,
|
||||
];
|
||||
const LEVELS_UI_FEATURE = [
|
||||
SettingLevel.CONFIG,
|
||||
// in future we might have a .well-known level or something
|
||||
];
|
||||
|
||||
export interface ISetting {
|
||||
// Must be set to true for features. Default is 'false'.
|
||||
|
@ -447,6 +453,7 @@ export const SETTINGS: {[setting: string]: ISetting} = {
|
|||
"room": _td("Enable URL previews by default for participants in this room"),
|
||||
},
|
||||
default: true,
|
||||
controller: new UIFeatureController(UIFeature.URLPreviews),
|
||||
},
|
||||
"urlPreviewsEnabled_e2ee": {
|
||||
supportedLevels: [SettingLevel.ROOM_DEVICE, SettingLevel.ROOM_ACCOUNT],
|
||||
|
@ -454,6 +461,7 @@ export const SETTINGS: {[setting: string]: ISetting} = {
|
|||
"room-account": _td("Enable URL previews for this room (only affects you)"),
|
||||
},
|
||||
default: false,
|
||||
controller: new UIFeatureController(UIFeature.URLPreviews),
|
||||
},
|
||||
"roomColor": {
|
||||
supportedLevels: LEVELS_ROOM_SETTINGS_WITH_ROOM,
|
||||
|
@ -611,4 +619,8 @@ export const SETTINGS: {[setting: string]: ISetting} = {
|
|||
supportedLevels: LEVELS_ROOM_OR_ACCOUNT,
|
||||
default: {},
|
||||
},
|
||||
[UIFeature.URLPreviews]: {
|
||||
supportedLevels: LEVELS_UI_FEATURE,
|
||||
default: true,
|
||||
},
|
||||
};
|
||||
|
|
20
src/settings/UIFeature.ts
Normal file
20
src/settings/UIFeature.ts
Normal file
|
@ -0,0 +1,20 @@
|
|||
/*
|
||||
Copyright 2020 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.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
// see settings.md for documentation on conventions
|
||||
export enum UIFeature {
|
||||
URLPreviews = "UIFeature.URLPreviews",
|
||||
}
|
45
src/settings/controllers/UIFeatureController.ts
Normal file
45
src/settings/controllers/UIFeatureController.ts
Normal file
|
@ -0,0 +1,45 @@
|
|||
/*
|
||||
Copyright 2020 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.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
import SettingController from "./SettingController";
|
||||
import { SettingLevel } from "../SettingLevel";
|
||||
import SettingsStore from "../SettingsStore";
|
||||
|
||||
/**
|
||||
* Enforces that a boolean setting cannot be enabled if the corresponding
|
||||
* UI feature is disabled. If the UI feature is enabled, the setting value
|
||||
* is unchanged.
|
||||
*
|
||||
* Settings using this controller are assumed to return `false` when disabled.
|
||||
*/
|
||||
export default class UIFeatureController extends SettingController {
|
||||
public constructor(private uiFeatureName: string) {
|
||||
super();
|
||||
}
|
||||
|
||||
public getValueOverride(
|
||||
level: SettingLevel,
|
||||
roomId: string,
|
||||
calculatedValue: any,
|
||||
calculatedAtLevel: SettingLevel,
|
||||
): any {
|
||||
if (!SettingsStore.getValue(this.uiFeatureName)) {
|
||||
// per the docs: we force a disabled state when the feature isn't active
|
||||
return false;
|
||||
}
|
||||
return null; // no override
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue