UI in settings for toggling features

This commit is contained in:
Bruno Windels 2023-02-10 09:27:18 +01:00
parent bb477b6aad
commit da1b7d4108
6 changed files with 157 additions and 0 deletions

View File

@ -0,0 +1,70 @@
/*
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 {ViewModel} from "../../ViewModel";
import type {Options as BaseOptions} from "../../ViewModel";
import {FeatureFlag, FeatureSet} from "../../../features";
import type {SegmentType} from "../../navigation/index";
export class FeaturesViewModel extends ViewModel {
public readonly featureViewModels: ReadonlyArray<FeatureViewModel>;
constructor(options) {
super(options);
this.featureViewModels = [
new FeatureViewModel(this.childOptions({
name: this.i18n`Audio/video calls (experimental)`,
description: this.i18n`Allows starting and participating in A/V calls compatible with Element Call (MSC3401). Look for the start call option in the room menu ((...) in the right corner) to start a call.`,
feature: FeatureFlag.Calls
})),
];
}
}
type FeatureOptions = BaseOptions & {
feature: FeatureFlag,
description: string,
name: string
};
export class FeatureViewModel extends ViewModel<SegmentType, FeatureOptions> {
get enabled(): boolean {
return this.features.isFeatureEnabled(this.getOption("feature"));
}
async enableFeature(enabled: boolean): Promise<void> {
let newFeatures;
if (enabled) {
newFeatures = this.features.withFeature(this.getOption("feature"));
} else {
newFeatures = this.features.withoutFeature(this.getOption("feature"));
}
await newFeatures.store(this.platform.settingsStorage);
this.platform.restart();
}
get id(): string {
return `${this.getOption("feature")}`;
}
get name(): string {
return this.getOption("name");
}
get description(): string {
return this.getOption("description");
}
}

View File

@ -16,6 +16,7 @@ limitations under the License.
import {ViewModel} from "../../ViewModel";
import {KeyBackupViewModel} from "./KeyBackupViewModel.js";
import {FeaturesViewModel} from "./FeaturesViewModel";
import {submitLogsFromSessionToDefaultServer} from "../../../domain/rageshake";
class PushNotificationStatus {
@ -53,6 +54,7 @@ export class SettingsViewModel extends ViewModel {
this.pushNotifications = new PushNotificationStatus();
this._activeTheme = undefined;
this._logsFeedbackMessage = undefined;
this._featuresViewModel = new FeaturesViewModel(this.childOptions());
}
get _session() {
@ -125,6 +127,10 @@ export class SettingsViewModel extends ViewModel {
return this._keyBackupViewModel;
}
get featuresViewModel() {
return this._featuresViewModel;
}
get storageQuota() {
return this._formatBytes(this._estimate?.quota);
}

View File

@ -283,6 +283,10 @@ export class Platform {
}
}
restart() {
document.location.reload();
}
openFile(mimeType = null) {
const input = document.createElement("input");
input.setAttribute("type", "file");

View File

@ -751,6 +751,24 @@ a {
margin-bottom: 0;
}
.FeatureView {
display: flex;
gap: 8px;
}
.FeaturesView ul {
list-style: none;
padding: 8px 16px;
}
.FeaturesView input[type="checkbox"] {
align-self: start;
}
.FeatureView h4 {
margin: 0;
}
.error {
color: var(--error-color);
font-weight: 600;

View File

@ -0,0 +1,52 @@
/*
Copyright 2023 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 {TemplateView, TemplateBuilder} from "../../general/TemplateView";
import {ViewNode} from "../../general/types";
import {disableTargetCallback} from "../../general/utils";
import type {FeaturesViewModel, FeatureViewModel} from "../../../../../domain/session/settings/FeaturesViewModel";
export class FeaturesView extends TemplateView<FeaturesViewModel> {
render(t, vm: FeaturesViewModel): ViewNode {
return t.div({
className: "FeaturesView",
}, [
t.p("Enable experimental features here that are still in development. These are not yet ready for primetime, so expect bugs."),
// we don't use a binding/ListView because this is a static list
t.ul(vm.featureViewModels.map(vm => {
return t.li(t.view(new FeatureView(vm)));
}))
]);
}
}
class FeatureView extends TemplateView<FeatureViewModel> {
render(t, vm): ViewNode {
let id = `feature_${vm.id}`;
return t.div({className: "FeatureView"}, [
t.input({
type: "checkbox",
id,
checked: vm => vm.enabled,
onChange: evt => vm.enableFeature(evt.target.checked)
}),
t.div({class: "FeatureView_container"}, [
t.h4(t.label({for: id}, vm.name)),
t.p(vm.description)
])
]);
}
}

View File

@ -17,6 +17,7 @@ limitations under the License.
import {TemplateView} from "../../general/TemplateView";
import {disableTargetCallback} from "../../general/utils";
import {KeyBackupSettingsView} from "./KeyBackupSettingsView.js"
import {FeaturesView} from "./FeaturesView"
export class SettingsView extends TemplateView {
render(t, vm) {
@ -110,6 +111,12 @@ export class SettingsView extends TemplateView {
logButtons.push(t.button({onClick: disableTargetCallback(() => vm.sendLogsToServer())}, `Submit logs to ${vm.logsServer}`));
}
logButtons.push(t.button({onClick: () => vm.exportLogs()}, "Download logs"));
settingNodes.push(
t.h3("Experimental features"),
t.view(new FeaturesView(vm.featuresViewModel))
);
settingNodes.push(
t.h3("Application"),
row(t, vm.i18n`Version`, version),