mirror of
				https://github.com/vector-im/element-web.git
				synced 2025-11-04 02:02:14 +01:00 
			
		
		
		
	Add new layout switcher UI
Co-authored-by: Quirin Götz <codeworks@supercable.onl>
This commit is contained in:
		
							parent
							
								
									97e6599780
								
							
						
					
					
						commit
						ae5cd9d7ac
					
				@ -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<IProps, I
 | 
			
		||||
        this.setState({customThemeUrl: e.target.value});
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    private onLayoutChange = (e: React.ChangeEvent<HTMLInputElement>): 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<IProps, I
 | 
			
		||||
        </div>;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private renderLayoutSection = () => {
 | 
			
		||||
        return <div className="mx_SettingsTab_section mx_AppearanceUserSettingsTab_Layout">
 | 
			
		||||
            <span className="mx_SettingsTab_subheading">{ _t("Message layout") }</span>
 | 
			
		||||
 | 
			
		||||
            <div className="mx_AppearanceUserSettingsTab_Layout_RadioButtons">
 | 
			
		||||
                <div className={classNames("mx_AppearanceUserSettingsTab_Layout_RadioButton", {
 | 
			
		||||
                    mx_AppearanceUserSettingsTab_Layout_RadioButton_selected: this.state.layout == Layout.IRC,
 | 
			
		||||
                })}>
 | 
			
		||||
                    <EventTilePreview
 | 
			
		||||
                        className="mx_AppearanceUserSettingsTab_Layout_RadioButton_preview"
 | 
			
		||||
                        message={this.MESSAGE_PREVIEW_TEXT}
 | 
			
		||||
                        layout={Layout.IRC}
 | 
			
		||||
                        userId={this.state.userId}
 | 
			
		||||
                        displayName={this.state.displayName}
 | 
			
		||||
                        avatarUrl={this.state.avatarUrl}
 | 
			
		||||
                    />
 | 
			
		||||
                    <StyledRadioButton
 | 
			
		||||
                        name="layout"
 | 
			
		||||
                        value="irc"
 | 
			
		||||
                        checked={this.state.layout == Layout.IRC}
 | 
			
		||||
                        onChange={this.onLayoutChange}
 | 
			
		||||
                    >
 | 
			
		||||
                        { "IRC" }
 | 
			
		||||
                    </StyledRadioButton>
 | 
			
		||||
                </div>
 | 
			
		||||
                <div className="mx_AppearanceUserSettingsTab_spacer" />
 | 
			
		||||
                <div className={classNames("mx_AppearanceUserSettingsTab_Layout_RadioButton", {
 | 
			
		||||
                    mx_AppearanceUserSettingsTab_Layout_RadioButton_selected: this.state.layout == Layout.Group,
 | 
			
		||||
                })}>
 | 
			
		||||
                    <EventTilePreview
 | 
			
		||||
                        className="mx_AppearanceUserSettingsTab_Layout_RadioButton_preview"
 | 
			
		||||
                        message={this.MESSAGE_PREVIEW_TEXT}
 | 
			
		||||
                        layout={Layout.Group}
 | 
			
		||||
                        userId={this.state.userId}
 | 
			
		||||
                        displayName={this.state.displayName}
 | 
			
		||||
                        avatarUrl={this.state.avatarUrl}
 | 
			
		||||
                    />
 | 
			
		||||
                    <StyledRadioButton
 | 
			
		||||
                        name="layout"
 | 
			
		||||
                        value="group"
 | 
			
		||||
                        checked={this.state.layout == Layout.Group}
 | 
			
		||||
                        onChange={this.onLayoutChange}
 | 
			
		||||
                    >
 | 
			
		||||
                        {_t("Modern")}
 | 
			
		||||
                    </StyledRadioButton>
 | 
			
		||||
                </div>
 | 
			
		||||
                <div className="mx_AppearanceUserSettingsTab_spacer" />
 | 
			
		||||
                <div className={classNames("mx_AppearanceUserSettingsTab_Layout_RadioButton", {
 | 
			
		||||
                    mx_AppearanceUserSettingsTab_Layout_RadioButton_selected: this.state.layout == Layout.Bubble,
 | 
			
		||||
                })}>
 | 
			
		||||
                    <EventTilePreview
 | 
			
		||||
                        className="mx_AppearanceUserSettingsTab_Layout_RadioButton_preview"
 | 
			
		||||
                        message={this.MESSAGE_PREVIEW_TEXT}
 | 
			
		||||
                        layout={Layout.Bubble}
 | 
			
		||||
                        userId={this.state.userId}
 | 
			
		||||
                        displayName={this.state.displayName}
 | 
			
		||||
                        avatarUrl={this.state.avatarUrl}
 | 
			
		||||
                    />
 | 
			
		||||
                    <StyledRadioButton
 | 
			
		||||
                        name="layout"
 | 
			
		||||
                        value="bubble"
 | 
			
		||||
                        checked={this.state.layout == Layout.Bubble}
 | 
			
		||||
                        onChange={this.onLayoutChange}
 | 
			
		||||
                    >
 | 
			
		||||
                        {_t("Message bubbles")}
 | 
			
		||||
                    </StyledRadioButton>
 | 
			
		||||
                </div>
 | 
			
		||||
            </div>
 | 
			
		||||
        </div>;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private renderAdvancedSection() {
 | 
			
		||||
        if (!SettingsStore.getValue(UIFeature.AdvancedSettings)) return null;
 | 
			
		||||
 | 
			
		||||
@ -390,14 +476,17 @@ export default class AppearanceUserSettingsTab extends React.Component<IProps, I
 | 
			
		||||
                    name="useCompactLayout"
 | 
			
		||||
                    level={SettingLevel.DEVICE}
 | 
			
		||||
                    useCheckbox={true}
 | 
			
		||||
                    disabled={this.state.layout == Layout.IRC}
 | 
			
		||||
                    disabled={this.state.layout !== Layout.Group}
 | 
			
		||||
                />
 | 
			
		||||
 | 
			
		||||
                { !SettingsStore.getValue("feature_new_layout_switcher") ?
 | 
			
		||||
                    <StyledCheckbox
 | 
			
		||||
                        checked={this.state.layout == Layout.IRC}
 | 
			
		||||
                        onChange={(ev) => this.onIRCLayoutChange(ev.target.checked)}
 | 
			
		||||
                    >
 | 
			
		||||
                        {_t("Enable experimental, compact IRC style layout")}
 | 
			
		||||
                </StyledCheckbox>
 | 
			
		||||
                    </StyledCheckbox> : null
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                <SettingsFlag
 | 
			
		||||
                    name="useSystemFont"
 | 
			
		||||
@ -438,6 +527,7 @@ export default class AppearanceUserSettingsTab extends React.Component<IProps, I
 | 
			
		||||
                    {_t("Appearance Settings only affect this %(brand)s session.", { brand })}
 | 
			
		||||
                </div>
 | 
			
		||||
                { this.renderThemeSection() }
 | 
			
		||||
                { SettingsStore.getValue("feature_new_layout_switcher") ? this.renderLayoutSection() : null }
 | 
			
		||||
                { this.renderFontSection() }
 | 
			
		||||
                { this.renderAdvancedSection() }
 | 
			
		||||
            </div>
 | 
			
		||||
 | 
			
		||||
@ -1,5 +1,6 @@
 | 
			
		||||
/*
 | 
			
		||||
Copyright 2021 Šimon Brandner <simon.bra.ag@gmail.com>
 | 
			
		||||
Copyright 2021 Quirin Götz <codeworks@supercable.onl>
 | 
			
		||||
 | 
			
		||||
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 */
 | 
			
		||||
 | 
			
		||||
@ -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,
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										26
									
								
								src/settings/controllers/NewLayoutSwitcherController.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										26
									
								
								src/settings/controllers/NewLayoutSwitcherController.ts
									
									
									
									
									
										Normal file
									
								
							@ -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);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user