diff --git a/src/components/views/settings/tabs/user/AppearanceUserSettingsTab.tsx b/src/components/views/settings/tabs/user/AppearanceUserSettingsTab.tsx index 9e27ed968e..bc31f750c3 100644 --- a/src/components/views/settings/tabs/user/AppearanceUserSettingsTab.tsx +++ b/src/components/views/settings/tabs/user/AppearanceUserSettingsTab.tsx @@ -37,6 +37,8 @@ import StyledRadioGroup from "../../../elements/StyledRadioGroup"; import { SettingLevel } from "../../../../../settings/SettingLevel"; import { UIFeature } from "../../../../../settings/UIFeature"; import { Layout } from "../../../../../settings/Layout"; +import classNames from 'classnames'; +import StyledRadioButton from '../../../elements/StyledRadioButton'; import { replaceableComponent } from "../../../../../utils/replaceableComponent"; import { compare } from "../../../../../utils/strings"; @@ -235,6 +237,19 @@ export default class AppearanceUserSettingsTab extends React.Component): void => { + let layout; + switch (e.target.value) { + case "irc": layout = Layout.IRC; break; + case "group": layout = Layout.Group; break; + case "bubble": layout = Layout.Bubble; break; + } + + this.setState({ layout: layout }); + + SettingsStore.setValue("layout", null, SettingLevel.DEVICE, layout); + }; + private onIRCLayoutChange = (enabled: boolean) => { if (enabled) { this.setState({layout: Layout.IRC}); @@ -367,6 +382,77 @@ export default class AppearanceUserSettingsTab extends React.Component; } + private renderLayoutSection = () => { + return
+ { _t("Message layout") } + +
+
+ + + { "IRC" } + +
+
+
+ + + {_t("Modern")} + +
+
+
+ + + {_t("Message bubbles")} + +
+
+
; + } + private renderAdvancedSection() { if (!SettingsStore.getValue(UIFeature.AdvancedSettings)) return null; @@ -390,14 +476,17 @@ export default class AppearanceUserSettingsTab extends React.Component - this.onIRCLayoutChange(ev.target.checked)} - > - {_t("Enable experimental, compact IRC style layout")} - + + { !SettingsStore.getValue("feature_new_layout_switcher") ? + this.onIRCLayoutChange(ev.target.checked)} + > + {_t("Enable experimental, compact IRC style layout")} + : null + } {_t("Appearance Settings only affect this %(brand)s session.", { brand })}
- {this.renderThemeSection()} - {this.renderFontSection()} - {this.renderAdvancedSection()} + { this.renderThemeSection() } + { SettingsStore.getValue("feature_new_layout_switcher") ? this.renderLayoutSection() : null } + { this.renderFontSection() } + { this.renderAdvancedSection() }
); } diff --git a/src/settings/Layout.ts b/src/settings/Layout.ts index 3a42b2b510..d4e1f06c0a 100644 --- a/src/settings/Layout.ts +++ b/src/settings/Layout.ts @@ -1,5 +1,6 @@ /* Copyright 2021 Šimon Brandner +Copyright 2021 Quirin Götz Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -19,7 +20,8 @@ import PropTypes from 'prop-types'; /* TODO: This should be later reworked into something more generic */ export enum Layout { IRC = "irc", - Group = "group" + Group = "group", + Bubble = "bubble", } /* We need this because multiple components are still using JavaScript */ diff --git a/src/settings/Settings.tsx b/src/settings/Settings.tsx index 155d039572..87edf886e0 100644 --- a/src/settings/Settings.tsx +++ b/src/settings/Settings.tsx @@ -41,6 +41,7 @@ import { Layout } from "./Layout"; import ReducedMotionController from './controllers/ReducedMotionController'; import IncompatibleController from "./controllers/IncompatibleController"; import SdkConfig from "../SdkConfig"; +import NewLayoutSwitcherController from './controllers/NewLayoutSwitcherController'; // These are just a bunch of helper arrays to avoid copy/pasting a bunch of times const LEVELS_ROOM_SETTINGS = [ @@ -285,6 +286,13 @@ export const SETTINGS: {[setting: string]: ISetting} = { displayName: _td("Show info about bridges in room settings"), default: false, }, + "feature_new_layout_switcher": { + isFeature: true, + supportedLevels: LEVELS_FEATURE, + displayName: _td("Explore new ways switching layouts (including a new bubble layout)"), + default: false, + controller: new NewLayoutSwitcherController(), + }, "RoomList.backgroundImage": { supportedLevels: LEVELS_ACCOUNT_SETTINGS, default: null, diff --git a/src/settings/controllers/NewLayoutSwitcherController.ts b/src/settings/controllers/NewLayoutSwitcherController.ts new file mode 100644 index 0000000000..b1d6cac55e --- /dev/null +++ b/src/settings/controllers/NewLayoutSwitcherController.ts @@ -0,0 +1,26 @@ +/* +Copyright 2021 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"; +import { Layout } from "../Layout"; + +export default class NewLayoutSwitcherController extends SettingController { + public onChange(level: SettingLevel, roomId: string, newValue: any) { + // On disabling switch back to Layout.Group if Layout.Bubble + if (!newValue && SettingsStore.getValue("layout") == Layout.Bubble) { + SettingsStore.setValue("layout", null, SettingLevel.DEVICE, Layout.Group); + } + } +}