Merge pull request #5571 from SimonBrandner/improve-layout-handling

Use a more generic layout setting - useIRCLayout → layout
This commit is contained in:
J. Ryan Stinnett 2021-02-17 11:02:26 +00:00 committed by GitHub
commit 53c4a1ada5
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
12 changed files with 110 additions and 104 deletions

View file

@ -27,6 +27,7 @@ import dis from "../../dispatcher/dispatcher";
import {MatrixClientPeg} from '../../MatrixClientPeg'; import {MatrixClientPeg} from '../../MatrixClientPeg';
import SettingsStore from '../../settings/SettingsStore'; import SettingsStore from '../../settings/SettingsStore';
import {Layout, LayoutPropType} from "../../settings/Layout";
import {_t} from "../../languageHandler"; import {_t} from "../../languageHandler";
import {haveTileForEvent} from "../views/rooms/EventTile"; import {haveTileForEvent} from "../views/rooms/EventTile";
import {textForEvent} from "../../TextForEvent"; import {textForEvent} from "../../TextForEvent";
@ -136,14 +137,13 @@ export default class MessagePanel extends React.Component {
// whether to show reactions for an event // whether to show reactions for an event
showReactions: PropTypes.bool, showReactions: PropTypes.bool,
// whether to use the irc layout // which layout to use
useIRCLayout: PropTypes.bool, layout: LayoutPropType,
// whether or not to show flair at all // whether or not to show flair at all
enableFlair: PropTypes.bool, enableFlair: PropTypes.bool,
}; };
// Force props to be loaded for useIRCLayout
constructor(props) { constructor(props) {
super(props); super(props);
@ -623,7 +623,7 @@ export default class MessagePanel extends React.Component {
isSelectedEvent={highlight} isSelectedEvent={highlight}
getRelationsForEvent={this.props.getRelationsForEvent} getRelationsForEvent={this.props.getRelationsForEvent}
showReactions={this.props.showReactions} showReactions={this.props.showReactions}
useIRCLayout={this.props.useIRCLayout} layout={this.props.layout}
enableFlair={this.props.enableFlair} enableFlair={this.props.enableFlair}
/> />
</TileErrorBoundary> </TileErrorBoundary>
@ -821,7 +821,7 @@ export default class MessagePanel extends React.Component {
} }
let ircResizer = null; let ircResizer = null;
if (this.props.useIRCLayout) { if (this.props.layout == Layout.IRC) {
ircResizer = <IRCTimelineProfileResizer ircResizer = <IRCTimelineProfileResizer
minWidth={20} minWidth={20}
maxWidth={600} maxWidth={600}

View file

@ -48,6 +48,7 @@ import RoomViewStore from '../../stores/RoomViewStore';
import RoomScrollStateStore from '../../stores/RoomScrollStateStore'; import RoomScrollStateStore from '../../stores/RoomScrollStateStore';
import WidgetEchoStore from '../../stores/WidgetEchoStore'; import WidgetEchoStore from '../../stores/WidgetEchoStore';
import SettingsStore from "../../settings/SettingsStore"; import SettingsStore from "../../settings/SettingsStore";
import {Layout} from "../../settings/Layout";
import AccessibleButton from "../views/elements/AccessibleButton"; import AccessibleButton from "../views/elements/AccessibleButton";
import RightPanelStore from "../../stores/RightPanelStore"; import RightPanelStore from "../../stores/RightPanelStore";
import { haveTileForEvent } from "../views/rooms/EventTile"; import { haveTileForEvent } from "../views/rooms/EventTile";
@ -181,7 +182,7 @@ export interface IState {
}; };
canReact: boolean; canReact: boolean;
canReply: boolean; canReply: boolean;
useIRCLayout: boolean; layout: Layout;
matrixClientIsReady: boolean; matrixClientIsReady: boolean;
showUrlPreview?: boolean; showUrlPreview?: boolean;
e2eStatus?: E2EStatus; e2eStatus?: E2EStatus;
@ -236,7 +237,7 @@ export default class RoomView extends React.Component<IProps, IState> {
statusBarVisible: false, statusBarVisible: false,
canReact: false, canReact: false,
canReply: false, canReply: false,
useIRCLayout: SettingsStore.getValue("useIRCLayout"), layout: SettingsStore.getValue("layout"),
matrixClientIsReady: this.context && this.context.isInitialSyncComplete(), matrixClientIsReady: this.context && this.context.isInitialSyncComplete(),
}; };
@ -264,7 +265,7 @@ export default class RoomView extends React.Component<IProps, IState> {
this.showReadReceiptsWatchRef = SettingsStore.watchSetting("showReadReceipts", null, this.showReadReceiptsWatchRef = SettingsStore.watchSetting("showReadReceipts", null,
this.onReadReceiptsChange); this.onReadReceiptsChange);
this.layoutWatcherRef = SettingsStore.watchSetting("useIRCLayout", null, this.onLayoutChange); this.layoutWatcherRef = SettingsStore.watchSetting("layout", null, this.onLayoutChange);
} }
private onWidgetStoreUpdate = () => { private onWidgetStoreUpdate = () => {
@ -638,7 +639,7 @@ export default class RoomView extends React.Component<IProps, IState> {
private onLayoutChange = () => { private onLayoutChange = () => {
this.setState({ this.setState({
useIRCLayout: SettingsStore.getValue("useIRCLayout"), layout: SettingsStore.getValue("layout"),
}); });
}; };
@ -1945,8 +1946,8 @@ export default class RoomView extends React.Component<IProps, IState> {
const messagePanelClassNames = classNames( const messagePanelClassNames = classNames(
"mx_RoomView_messagePanel", "mx_RoomView_messagePanel",
{ {
"mx_IRCLayout": this.state.useIRCLayout, "mx_IRCLayout": this.state.layout == Layout.IRC,
"mx_GroupLayout": !this.state.useIRCLayout, "mx_GroupLayout": this.state.layout == Layout.Group,
}); });
// console.info("ShowUrlPreview for %s is %s", this.state.room.roomId, this.state.showUrlPreview); // console.info("ShowUrlPreview for %s is %s", this.state.room.roomId, this.state.showUrlPreview);
@ -1969,7 +1970,7 @@ export default class RoomView extends React.Component<IProps, IState> {
permalinkCreator={this.getPermalinkCreatorForRoom(this.state.room)} permalinkCreator={this.getPermalinkCreatorForRoom(this.state.room)}
resizeNotifier={this.props.resizeNotifier} resizeNotifier={this.props.resizeNotifier}
showReactions={true} showReactions={true}
useIRCLayout={this.state.useIRCLayout} layout={this.state.layout}
/>); />);
let topUnreadMessagesBar = null; let topUnreadMessagesBar = null;

View file

@ -18,6 +18,7 @@ limitations under the License.
*/ */
import SettingsStore from "../../settings/SettingsStore"; import SettingsStore from "../../settings/SettingsStore";
import {LayoutPropType} from "../../settings/Layout";
import React, {createRef} from 'react'; import React, {createRef} from 'react';
import ReactDOM from "react-dom"; import ReactDOM from "react-dom";
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
@ -111,8 +112,8 @@ class TimelinePanel extends React.Component {
// whether to show reactions for an event // whether to show reactions for an event
showReactions: PropTypes.bool, showReactions: PropTypes.bool,
// whether to use the irc layout // which layout to use
useIRCLayout: PropTypes.bool, layout: LayoutPropType,
} }
// a map from room id to read marker event timestamp // a map from room id to read marker event timestamp
@ -1442,7 +1443,7 @@ class TimelinePanel extends React.Component {
getRelationsForEvent={this.getRelationsForEvent} getRelationsForEvent={this.getRelationsForEvent}
editState={this.state.editState} editState={this.state.editState}
showReactions={this.props.showReactions} showReactions={this.props.showReactions}
useIRCLayout={this.props.useIRCLayout} layout={this.props.layout}
enableFlair={SettingsStore.getValue(UIFeature.Flair)} enableFlair={SettingsStore.getValue(UIFeature.Flair)}
/> />
); );

View file

@ -22,6 +22,7 @@ import * as Avatar from '../../../Avatar';
import { MatrixClientPeg } from '../../../MatrixClientPeg'; import { MatrixClientPeg } from '../../../MatrixClientPeg';
import EventTile from '../rooms/EventTile'; import EventTile from '../rooms/EventTile';
import SettingsStore from "../../../settings/SettingsStore"; import SettingsStore from "../../../settings/SettingsStore";
import {Layout} from "../../../settings/Layout";
import {UIFeature} from "../../../settings/UIFeature"; import {UIFeature} from "../../../settings/UIFeature";
interface IProps { interface IProps {
@ -33,7 +34,7 @@ interface IProps {
/** /**
* Whether to use the irc layout or not * Whether to use the irc layout or not
*/ */
useIRCLayout: boolean; layout: Layout;
/** /**
* classnames to apply to the wrapper of the preview * classnames to apply to the wrapper of the preview
@ -121,14 +122,14 @@ export default class EventTilePreview extends React.Component<IProps, IState> {
const event = this.fakeEvent(this.state); const event = this.fakeEvent(this.state);
const className = classnames(this.props.className, { const className = classnames(this.props.className, {
"mx_IRCLayout": this.props.useIRCLayout, "mx_IRCLayout": this.props.layout == Layout.IRC,
"mx_GroupLayout": !this.props.useIRCLayout, "mx_GroupLayout": this.props.layout == Layout.Group,
}); });
return <div className={className}> return <div className={className}>
<EventTile <EventTile
mxEvent={event} mxEvent={event}
useIRCLayout={this.props.useIRCLayout} layout={this.props.layout}
enableFlair={SettingsStore.getValue(UIFeature.Flair)} enableFlair={SettingsStore.getValue(UIFeature.Flair)}
/> />
</div>; </div>;

View file

@ -24,6 +24,7 @@ import {wantsDateSeparator} from '../../../DateUtils';
import {MatrixEvent} from 'matrix-js-sdk'; import {MatrixEvent} from 'matrix-js-sdk';
import {makeUserPermalink, RoomPermalinkCreator} from "../../../utils/permalinks/Permalinks"; import {makeUserPermalink, RoomPermalinkCreator} from "../../../utils/permalinks/Permalinks";
import SettingsStore from "../../../settings/SettingsStore"; import SettingsStore from "../../../settings/SettingsStore";
import {LayoutPropType} from "../../../settings/Layout";
import escapeHtml from "escape-html"; import escapeHtml from "escape-html";
import MatrixClientContext from "../../../contexts/MatrixClientContext"; import MatrixClientContext from "../../../contexts/MatrixClientContext";
import {Action} from "../../../dispatcher/actions"; import {Action} from "../../../dispatcher/actions";
@ -42,7 +43,7 @@ export default class ReplyThread extends React.Component {
onHeightChanged: PropTypes.func.isRequired, onHeightChanged: PropTypes.func.isRequired,
permalinkCreator: PropTypes.instanceOf(RoomPermalinkCreator).isRequired, permalinkCreator: PropTypes.instanceOf(RoomPermalinkCreator).isRequired,
// Specifies which layout to use. // Specifies which layout to use.
useIRCLayout: PropTypes.bool, layout: LayoutPropType,
}; };
static contextType = MatrixClientContext; static contextType = MatrixClientContext;
@ -209,7 +210,7 @@ export default class ReplyThread extends React.Component {
}; };
} }
static makeThread(parentEv, onHeightChanged, permalinkCreator, ref, useIRCLayout) { static makeThread(parentEv, onHeightChanged, permalinkCreator, ref, layout) {
if (!ReplyThread.getParentEventId(parentEv)) { if (!ReplyThread.getParentEventId(parentEv)) {
return <div className="mx_ReplyThread_wrapper_empty" />; return <div className="mx_ReplyThread_wrapper_empty" />;
} }
@ -218,7 +219,7 @@ export default class ReplyThread extends React.Component {
onHeightChanged={onHeightChanged} onHeightChanged={onHeightChanged}
ref={ref} ref={ref}
permalinkCreator={permalinkCreator} permalinkCreator={permalinkCreator}
useIRCLayout={useIRCLayout} layout={layout}
/>; />;
} }
@ -386,7 +387,7 @@ export default class ReplyThread extends React.Component {
permalinkCreator={this.props.permalinkCreator} permalinkCreator={this.props.permalinkCreator}
isRedacted={ev.isRedacted()} isRedacted={ev.isRedacted()}
isTwelveHour={SettingsStore.getValue("showTwelveHourTimestamps")} isTwelveHour={SettingsStore.getValue("showTwelveHourTimestamps")}
useIRCLayout={this.props.useIRCLayout} layout={this.props.layout}
enableFlair={SettingsStore.getValue(UIFeature.Flair)} enableFlair={SettingsStore.getValue(UIFeature.Flair)}
replacingEventId={ev.replacingEventId()} replacingEventId={ev.replacingEventId()}
/> />

View file

@ -27,6 +27,7 @@ import * as TextForEvent from "../../../TextForEvent";
import * as sdk from "../../../index"; import * as sdk from "../../../index";
import dis from '../../../dispatcher/dispatcher'; import dis from '../../../dispatcher/dispatcher';
import SettingsStore from "../../../settings/SettingsStore"; import SettingsStore from "../../../settings/SettingsStore";
import {Layout, LayoutPropType} from "../../../settings/Layout";
import {EventStatus} from 'matrix-js-sdk'; import {EventStatus} from 'matrix-js-sdk';
import {formatTime} from "../../../DateUtils"; import {formatTime} from "../../../DateUtils";
import {MatrixClientPeg} from '../../../MatrixClientPeg'; import {MatrixClientPeg} from '../../../MatrixClientPeg';
@ -227,8 +228,8 @@ export default class EventTile extends React.Component {
// whether to show reactions for this event // whether to show reactions for this event
showReactions: PropTypes.bool, showReactions: PropTypes.bool,
// whether to use the irc layout // which layout to use
useIRCLayout: PropTypes.bool, layout: LayoutPropType,
// whether or not to show flair at all // whether or not to show flair at all
enableFlair: PropTypes.bool, enableFlair: PropTypes.bool,
@ -734,7 +735,7 @@ export default class EventTile extends React.Component {
// joins/parts/etc // joins/parts/etc
avatarSize = 14; avatarSize = 14;
needsSenderProfile = false; needsSenderProfile = false;
} else if (this.props.useIRCLayout) { } else if (this.props.layout == Layout.IRC) {
avatarSize = 14; avatarSize = 14;
needsSenderProfile = true; needsSenderProfile = true;
} else if (this.props.continuation && this.props.tileShape !== "file_grid") { } else if (this.props.continuation && this.props.tileShape !== "file_grid") {
@ -845,10 +846,11 @@ export default class EventTile extends React.Component {
{ timestamp } { timestamp }
</a>; </a>;
const groupTimestamp = !this.props.useIRCLayout ? linkedTimestamp : null; const useIRCLayout = this.props.layout == Layout.IRC;
const ircTimestamp = this.props.useIRCLayout ? linkedTimestamp : null; const groupTimestamp = !useIRCLayout ? linkedTimestamp : null;
const groupPadlock = !this.props.useIRCLayout && !isBubbleMessage && this._renderE2EPadlock(); const ircTimestamp = useIRCLayout ? linkedTimestamp : null;
const ircPadlock = this.props.useIRCLayout && !isBubbleMessage && this._renderE2EPadlock(); const groupPadlock = !useIRCLayout && !isBubbleMessage && this._renderE2EPadlock();
const ircPadlock = useIRCLayout && !isBubbleMessage && this._renderE2EPadlock();
switch (this.props.tileShape) { switch (this.props.tileShape) {
case 'notif': { case 'notif': {
@ -943,7 +945,7 @@ export default class EventTile extends React.Component {
this.props.onHeightChanged, this.props.onHeightChanged,
this.props.permalinkCreator, this.props.permalinkCreator,
this._replyThread, this._replyThread,
this.props.useIRCLayout, this.props.layout,
); );
// tab-index=-1 to allow it to be focusable but do not add tab stop for it, primarily for screen readers // tab-index=-1 to allow it to be focusable but do not add tab stop for it, primarily for screen readers

View file

@ -28,15 +28,14 @@ import { FontWatcher } from "../../../../../settings/watchers/FontWatcher";
import { RecheckThemePayload } from '../../../../../dispatcher/payloads/RecheckThemePayload'; import { RecheckThemePayload } from '../../../../../dispatcher/payloads/RecheckThemePayload';
import { Action } from '../../../../../dispatcher/actions'; import { Action } from '../../../../../dispatcher/actions';
import { IValidationResult, IFieldState } from '../../../elements/Validation'; import { IValidationResult, IFieldState } from '../../../elements/Validation';
import StyledRadioButton from '../../../elements/StyledRadioButton';
import StyledCheckbox from '../../../elements/StyledCheckbox'; import StyledCheckbox from '../../../elements/StyledCheckbox';
import SettingsFlag from '../../../elements/SettingsFlag'; import SettingsFlag from '../../../elements/SettingsFlag';
import Field from '../../../elements/Field'; import Field from '../../../elements/Field';
import EventTilePreview from '../../../elements/EventTilePreview'; import EventTilePreview from '../../../elements/EventTilePreview';
import StyledRadioGroup from "../../../elements/StyledRadioGroup"; import StyledRadioGroup from "../../../elements/StyledRadioGroup";
import classNames from 'classnames';
import { SettingLevel } from "../../../../../settings/SettingLevel"; import { SettingLevel } from "../../../../../settings/SettingLevel";
import {UIFeature} from "../../../../../settings/UIFeature"; import {UIFeature} from "../../../../../settings/UIFeature";
import {Layout} from "../../../../../settings/Layout";
interface IProps { interface IProps {
} }
@ -62,7 +61,7 @@ interface IState extends IThemeState {
useSystemFont: boolean; useSystemFont: boolean;
systemFont: string; systemFont: string;
showAdvanced: boolean; showAdvanced: boolean;
useIRCLayout: boolean; layout: Layout;
} }
@ -83,7 +82,7 @@ export default class AppearanceUserSettingsTab extends React.Component<IProps, I
useSystemFont: SettingsStore.getValue("useSystemFont"), useSystemFont: SettingsStore.getValue("useSystemFont"),
systemFont: SettingsStore.getValue("systemFont"), systemFont: SettingsStore.getValue("systemFont"),
showAdvanced: false, showAdvanced: false,
useIRCLayout: SettingsStore.getValue("useIRCLayout"), layout: SettingsStore.getValue("layout"),
}; };
} }
@ -213,15 +212,15 @@ export default class AppearanceUserSettingsTab extends React.Component<IProps, I
this.setState({customThemeUrl: e.target.value}); this.setState({customThemeUrl: e.target.value});
}; };
private onLayoutChange = (e: React.ChangeEvent<HTMLInputElement>): void => { private onIRCLayoutChange = (enabled: boolean) => {
const val = e.target.value === "true"; if (enabled) {
this.setState({layout: Layout.IRC});
this.setState({ SettingsStore.setValue("layout", null, SettingLevel.DEVICE, Layout.IRC);
useIRCLayout: val, } else {
}); this.setState({layout: Layout.Group});
SettingsStore.setValue("layout", null, SettingLevel.DEVICE, Layout.Group);
SettingsStore.setValue("useIRCLayout", null, SettingLevel.DEVICE, val); }
}; }
private renderThemeSection() { private renderThemeSection() {
const themeWatcher = new ThemeWatcher(); const themeWatcher = new ThemeWatcher();
@ -306,7 +305,7 @@ export default class AppearanceUserSettingsTab extends React.Component<IProps, I
<EventTilePreview <EventTilePreview
className="mx_AppearanceUserSettingsTab_fontSlider_preview" className="mx_AppearanceUserSettingsTab_fontSlider_preview"
message={this.MESSAGE_PREVIEW_TEXT} message={this.MESSAGE_PREVIEW_TEXT}
useIRCLayout={this.state.useIRCLayout} layout={this.state.layout}
/> />
<div className="mx_AppearanceUserSettingsTab_fontSlider"> <div className="mx_AppearanceUserSettingsTab_fontSlider">
<div className="mx_AppearanceUserSettingsTab_fontSlider_smallText">Aa</div> <div className="mx_AppearanceUserSettingsTab_fontSlider_smallText">Aa</div>
@ -342,50 +341,6 @@ export default class AppearanceUserSettingsTab extends React.Component<IProps, I
</div>; </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.useIRCLayout,
})}>
<EventTilePreview
className="mx_AppearanceUserSettingsTab_Layout_RadioButton_preview"
message={this.MESSAGE_PREVIEW_TEXT}
useIRCLayout={true}
/>
<StyledRadioButton
name="layout"
value="true"
checked={this.state.useIRCLayout}
onChange={this.onLayoutChange}
>
{_t("Compact")}
</StyledRadioButton>
</div>
<div className="mx_AppearanceUserSettingsTab_spacer" />
<div className={classNames("mx_AppearanceUserSettingsTab_Layout_RadioButton", {
mx_AppearanceUserSettingsTab_Layout_RadioButton_selected: !this.state.useIRCLayout,
})}>
<EventTilePreview
className="mx_AppearanceUserSettingsTab_Layout_RadioButton_preview"
message={this.MESSAGE_PREVIEW_TEXT}
useIRCLayout={false}
/>
<StyledRadioButton
name="layout"
value="false"
checked={!this.state.useIRCLayout}
onChange={this.onLayoutChange}
>
{_t("Modern")}
</StyledRadioButton>
</div>
</div>
</div>;
};
private renderAdvancedSection() { private renderAdvancedSection() {
if (!SettingsStore.getValue(UIFeature.AdvancedSettings)) return null; if (!SettingsStore.getValue(UIFeature.AdvancedSettings)) return null;
@ -409,14 +364,15 @@ export default class AppearanceUserSettingsTab extends React.Component<IProps, I
name="useCompactLayout" name="useCompactLayout"
level={SettingLevel.DEVICE} level={SettingLevel.DEVICE}
useCheckbox={true} useCheckbox={true}
disabled={this.state.useIRCLayout} disabled={this.state.layout == Layout.IRC}
/>
<SettingsFlag
name="useIRCLayout"
level={SettingLevel.DEVICE}
useCheckbox={true}
onChange={(checked) => this.setState({useIRCLayout: checked})}
/> />
<StyledCheckbox
checked={this.state.layout == Layout.IRC}
onChange={(ev) => this.onIRCLayoutChange(ev.target.checked)}
>
{_t("Enable experimental, compact IRC style layout")}
</StyledCheckbox>
<SettingsFlag <SettingsFlag
name="useSystemFont" name="useSystemFont"
level={SettingLevel.DEVICE} level={SettingLevel.DEVICE}

View file

@ -17,6 +17,7 @@ limitations under the License.
import { createContext } from "react"; import { createContext } from "react";
import {IState} from "../components/structures/RoomView"; import {IState} from "../components/structures/RoomView";
import {Layout} from "../settings/Layout";
const RoomContext = createContext<IState>({ const RoomContext = createContext<IState>({
roomLoading: true, roomLoading: true,
@ -40,7 +41,7 @@ const RoomContext = createContext<IState>({
statusBarVisible: false, statusBarVisible: false,
canReact: false, canReact: false,
canReply: false, canReply: false,
useIRCLayout: false, layout: Layout.Group,
matrixClientIsReady: false, matrixClientIsReady: false,
}); });
RoomContext.displayName = "RoomContext"; RoomContext.displayName = "RoomContext";

View file

@ -844,7 +844,6 @@
"How fast should messages be downloaded.": "How fast should messages be downloaded.", "How fast should messages be downloaded.": "How fast should messages be downloaded.",
"Manually verify all remote sessions": "Manually verify all remote sessions", "Manually verify all remote sessions": "Manually verify all remote sessions",
"IRC display name width": "IRC display name width", "IRC display name width": "IRC display name width",
"Enable experimental, compact IRC style layout": "Enable experimental, compact IRC style layout",
"Show chat effects": "Show chat effects", "Show chat effects": "Show chat effects",
"Collecting app version information": "Collecting app version information", "Collecting app version information": "Collecting app version information",
"Collecting logs": "Collecting logs", "Collecting logs": "Collecting logs",
@ -1164,12 +1163,10 @@
"Custom theme URL": "Custom theme URL", "Custom theme URL": "Custom theme URL",
"Add theme": "Add theme", "Add theme": "Add theme",
"Theme": "Theme", "Theme": "Theme",
"Message layout": "Message layout",
"Compact": "Compact",
"Modern": "Modern",
"Hide advanced": "Hide advanced", "Hide advanced": "Hide advanced",
"Show advanced": "Show advanced", "Show advanced": "Show advanced",
"Set the name of a font installed on your system & %(brand)s will attempt to use it.": "Set the name of a font installed on your system & %(brand)s will attempt to use it.", "Set the name of a font installed on your system & %(brand)s will attempt to use it.": "Set the name of a font installed on your system & %(brand)s will attempt to use it.",
"Enable experimental, compact IRC style layout": "Enable experimental, compact IRC style layout",
"Customise your appearance": "Customise your appearance", "Customise your appearance": "Customise your appearance",
"Appearance Settings only affect this %(brand)s session.": "Appearance Settings only affect this %(brand)s session.", "Appearance Settings only affect this %(brand)s session.": "Appearance Settings only affect this %(brand)s session.",
"Flair": "Flair", "Flair": "Flair",

26
src/settings/Layout.ts Normal file
View file

@ -0,0 +1,26 @@
/*
Copyright 2021 Šimon Brandner <simon.bra.ag@gmail.com>
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 PropTypes from 'prop-types';
/* TODO: This should be later reworked into something more generic */
export enum Layout {
IRC = "irc",
Group = "group"
}
/* We need this because multiple components are still using JavaScript */
export const LayoutPropType = PropTypes.oneOf(Object.values(Layout));

View file

@ -36,6 +36,7 @@ import { isMac } from '../Keyboard';
import UIFeatureController from "./controllers/UIFeatureController"; import UIFeatureController from "./controllers/UIFeatureController";
import { UIFeature } from "./UIFeature"; import { UIFeature } from "./UIFeature";
import { OrderedMultiController } from "./controllers/OrderedMultiController"; import { OrderedMultiController } from "./controllers/OrderedMultiController";
import {Layout} from "./Layout";
// These are just a bunch of helper arrays to avoid copy/pasting a bunch of times // These are just a bunch of helper arrays to avoid copy/pasting a bunch of times
const LEVELS_ROOM_SETTINGS = [ const LEVELS_ROOM_SETTINGS = [
@ -643,10 +644,9 @@ export const SETTINGS: {[setting: string]: ISetting} = {
displayName: _td("IRC display name width"), displayName: _td("IRC display name width"),
default: 80, default: 80,
}, },
"useIRCLayout": { "layout": {
supportedLevels: LEVELS_ACCOUNT_SETTINGS, supportedLevels: LEVELS_ACCOUNT_SETTINGS,
displayName: _td("Enable experimental, compact IRC style layout"), default: Layout.Group,
default: false,
}, },
"showChatEffects": { "showChatEffects": {
supportedLevels: LEVELS_ACCOUNT_SETTINGS, supportedLevels: LEVELS_ACCOUNT_SETTINGS,

View file

@ -20,6 +20,7 @@ import SettingsHandler from "./SettingsHandler";
import {MatrixClientPeg} from "../../MatrixClientPeg"; import {MatrixClientPeg} from "../../MatrixClientPeg";
import {SettingLevel} from "../SettingLevel"; import {SettingLevel} from "../SettingLevel";
import { CallbackFn, WatchManager } from "../WatchManager"; import { CallbackFn, WatchManager } from "../WatchManager";
import { Layout } from "../Layout";
/** /**
* Gets and sets settings at the "device" level for the current device. * Gets and sets settings at the "device" level for the current device.
@ -67,6 +68,13 @@ export default class DeviceSettingsHandler extends SettingsHandler {
return val['value']; return val['value'];
} }
// Special case for old useIRCLayout setting
if (settingName === "layout") {
const settings = this.getSettings() || {};
if (settings["useIRCLayout"]) return Layout.IRC;
return settings[settingName];
}
const settings = this.getSettings() || {}; const settings = this.getSettings() || {};
return settings[settingName]; return settings[settingName];
} }
@ -106,6 +114,18 @@ export default class DeviceSettingsHandler extends SettingsHandler {
return Promise.resolve(); return Promise.resolve();
} }
// Special case for old useIRCLayout setting
if (settingName === "layout") {
const settings = this.getSettings() || {};
delete settings["useIRCLayout"];
settings["layout"] = newValue;
localStorage.setItem("mx_local_settings", JSON.stringify(settings));
this.watchers.notifyUpdate(settingName, null, SettingLevel.DEVICE, newValue);
return Promise.resolve();
}
const settings = this.getSettings() || {}; const settings = this.getSettings() || {};
settings[settingName] = newValue; settings[settingName] = newValue;
localStorage.setItem("mx_local_settings", JSON.stringify(settings)); localStorage.setItem("mx_local_settings", JSON.stringify(settings));