mirror of
https://github.com/vector-im/hydrogen-web.git
synced 2024-12-23 03:25:12 +01:00
UI in settings for toggling features
This commit is contained in:
parent
bb477b6aad
commit
da1b7d4108
70
src/domain/session/settings/FeaturesViewModel.ts
Normal file
70
src/domain/session/settings/FeaturesViewModel.ts
Normal 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");
|
||||
}
|
||||
}
|
@ -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);
|
||||
}
|
||||
|
@ -283,6 +283,10 @@ export class Platform {
|
||||
}
|
||||
}
|
||||
|
||||
restart() {
|
||||
document.location.reload();
|
||||
}
|
||||
|
||||
openFile(mimeType = null) {
|
||||
const input = document.createElement("input");
|
||||
input.setAttribute("type", "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;
|
||||
|
52
src/platform/web/ui/session/settings/FeaturesView.ts
Normal file
52
src/platform/web/ui/session/settings/FeaturesView.ts
Normal 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)
|
||||
])
|
||||
]);
|
||||
}
|
||||
}
|
@ -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),
|
||||
|
Loading…
Reference in New Issue
Block a user