Merge pull request #6566 from SimonBrandner/task/export-layout
commit
3153e11761
|
@ -240,6 +240,7 @@
|
||||||
@import "./views/settings/_E2eAdvancedPanel.scss";
|
@import "./views/settings/_E2eAdvancedPanel.scss";
|
||||||
@import "./views/settings/_EmailAddresses.scss";
|
@import "./views/settings/_EmailAddresses.scss";
|
||||||
@import "./views/settings/_IntegrationManager.scss";
|
@import "./views/settings/_IntegrationManager.scss";
|
||||||
|
@import "./views/settings/_LayoutSwitcher.scss";
|
||||||
@import "./views/settings/_Notifications.scss";
|
@import "./views/settings/_Notifications.scss";
|
||||||
@import "./views/settings/_PhoneNumbers.scss";
|
@import "./views/settings/_PhoneNumbers.scss";
|
||||||
@import "./views/settings/_ProfileSettings.scss";
|
@import "./views/settings/_ProfileSettings.scss";
|
||||||
|
|
|
@ -0,0 +1,91 @@
|
||||||
|
/*
|
||||||
|
Copyright 2020 - 2021 The Matrix.org Foundation C.I.C.
|
||||||
|
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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
.mx_LayoutSwitcher {
|
||||||
|
.mx_LayoutSwitcher_RadioButtons {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
gap: 24px;
|
||||||
|
|
||||||
|
color: $primary-fg-color;
|
||||||
|
|
||||||
|
> .mx_LayoutSwitcher_RadioButton {
|
||||||
|
flex-grow: 0;
|
||||||
|
flex-shrink: 1;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
|
||||||
|
width: 300px;
|
||||||
|
|
||||||
|
border: 1px solid $appearance-tab-border-color;
|
||||||
|
border-radius: 10px;
|
||||||
|
|
||||||
|
.mx_EventTile_msgOption,
|
||||||
|
.mx_MessageActionBar {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mx_LayoutSwitcher_RadioButton_preview {
|
||||||
|
flex-grow: 1;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
padding: 10px;
|
||||||
|
pointer-events: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mx_RadioButton {
|
||||||
|
flex-grow: 0;
|
||||||
|
padding: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mx_EventTile_content {
|
||||||
|
margin-right: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.mx_LayoutSwitcher_RadioButton_selected {
|
||||||
|
border-color: $accent-color;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.mx_RadioButton {
|
||||||
|
border-top: 1px solid $appearance-tab-border-color;
|
||||||
|
|
||||||
|
> input + div {
|
||||||
|
border-color: rgba($muted-fg-color, 0.2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.mx_RadioButton_checked {
|
||||||
|
background-color: rgba($accent-color, 0.08);
|
||||||
|
}
|
||||||
|
|
||||||
|
.mx_EventTile {
|
||||||
|
margin: 0;
|
||||||
|
&[data-layout=bubble] {
|
||||||
|
margin-right: 40px;
|
||||||
|
}
|
||||||
|
&[data-layout=irc] {
|
||||||
|
> a {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.mx_EventTile_line {
|
||||||
|
max-width: 90%;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
Copyright 2020 The Matrix.org Foundation C.I.C.
|
Copyright 2020 - 2021 The Matrix.org Foundation C.I.C.
|
||||||
|
|
||||||
Licensed under the Apache License, Version 2.0 (the "License");
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
you may not use this file except in compliance with the License.
|
you may not use this file except in compliance with the License.
|
||||||
|
@ -155,79 +155,6 @@ limitations under the License.
|
||||||
margin-left: calc($font-16px + 10px);
|
margin-left: calc($font-16px + 10px);
|
||||||
}
|
}
|
||||||
|
|
||||||
.mx_AppearanceUserSettingsTab_Layout_RadioButtons {
|
|
||||||
display: flex;
|
|
||||||
flex-direction: row;
|
|
||||||
gap: 24px;
|
|
||||||
|
|
||||||
color: $primary-fg-color;
|
|
||||||
|
|
||||||
> .mx_AppearanceUserSettingsTab_Layout_RadioButton {
|
|
||||||
flex-grow: 0;
|
|
||||||
flex-shrink: 1;
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
|
|
||||||
width: 300px;
|
|
||||||
|
|
||||||
border: 1px solid $appearance-tab-border-color;
|
|
||||||
border-radius: 10px;
|
|
||||||
|
|
||||||
.mx_EventTile_msgOption,
|
|
||||||
.mx_MessageActionBar {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
.mx_AppearanceUserSettingsTab_Layout_RadioButton_preview {
|
|
||||||
flex-grow: 1;
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
padding: 10px;
|
|
||||||
pointer-events: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
.mx_RadioButton {
|
|
||||||
flex-grow: 0;
|
|
||||||
padding: 10px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.mx_EventTile_content {
|
|
||||||
margin-right: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
&.mx_AppearanceUserSettingsTab_Layout_RadioButton_selected {
|
|
||||||
border-color: $accent-color;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.mx_RadioButton {
|
|
||||||
border-top: 1px solid $appearance-tab-border-color;
|
|
||||||
|
|
||||||
> input + div {
|
|
||||||
border-color: rgba($muted-fg-color, 0.2);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.mx_RadioButton_checked {
|
|
||||||
background-color: rgba($accent-color, 0.08);
|
|
||||||
}
|
|
||||||
|
|
||||||
.mx_EventTile {
|
|
||||||
margin: 0;
|
|
||||||
&[data-layout=bubble] {
|
|
||||||
margin-right: 40px;
|
|
||||||
}
|
|
||||||
&[data-layout=irc] {
|
|
||||||
> a {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.mx_EventTile_line {
|
|
||||||
max-width: 90%;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.mx_AppearanceUserSettingsTab_Advanced {
|
.mx_AppearanceUserSettingsTab_Advanced {
|
||||||
color: $primary-fg-color;
|
color: $primary-fg-color;
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,133 @@
|
||||||
|
/*
|
||||||
|
Copyright 2019 New Vector Ltd
|
||||||
|
Copyright 2019 - 2021 The Matrix.org Foundation C.I.C.
|
||||||
|
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 React from "react";
|
||||||
|
import classNames from "classnames";
|
||||||
|
import SettingsStore from "../../../settings/SettingsStore";
|
||||||
|
import EventTilePreview from "../elements/EventTilePreview";
|
||||||
|
import StyledRadioButton from "../elements/StyledRadioButton";
|
||||||
|
import { _t } from "../../../languageHandler";
|
||||||
|
import { Layout } from "../../../settings/Layout";
|
||||||
|
import { SettingLevel } from "../../../settings/SettingLevel";
|
||||||
|
|
||||||
|
interface IProps {
|
||||||
|
userId: string;
|
||||||
|
displayName: string;
|
||||||
|
avatarUrl: string;
|
||||||
|
messagePreviewText: string;
|
||||||
|
onLayoutChanged?: (layout: Layout) => void;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface IState {
|
||||||
|
layout: Layout;
|
||||||
|
}
|
||||||
|
|
||||||
|
export default class LayoutSwitcher extends React.Component<IProps, IState> {
|
||||||
|
constructor(props: IProps) {
|
||||||
|
super(props);
|
||||||
|
|
||||||
|
this.state = {
|
||||||
|
layout: SettingsStore.getValue("layout"),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
private onLayoutChange = (e: React.ChangeEvent<HTMLInputElement>): void => {
|
||||||
|
const layout = e.target.value as Layout;
|
||||||
|
|
||||||
|
this.setState({ layout: layout });
|
||||||
|
SettingsStore.setValue("layout", null, SettingLevel.DEVICE, layout);
|
||||||
|
this.props.onLayoutChanged(layout);
|
||||||
|
};
|
||||||
|
|
||||||
|
public render(): JSX.Element {
|
||||||
|
const ircClasses = classNames("mx_LayoutSwitcher_RadioButton", {
|
||||||
|
mx_LayoutSwitcher_RadioButton_selected: this.state.layout == Layout.IRC,
|
||||||
|
});
|
||||||
|
const groupClasses = classNames("mx_LayoutSwitcher_RadioButton", {
|
||||||
|
mx_LayoutSwitcher_RadioButton_selected: this.state.layout == Layout.Group,
|
||||||
|
});
|
||||||
|
const bubbleClasses = classNames("mx_LayoutSwitcher_RadioButton", {
|
||||||
|
mx_LayoutSwitcher_RadioButton_selected: this.state.layout === Layout.Bubble,
|
||||||
|
});
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="mx_SettingsTab_section mx_LayoutSwitcher">
|
||||||
|
<span className="mx_SettingsTab_subheading">
|
||||||
|
{ _t("Message layout") }
|
||||||
|
</span>
|
||||||
|
|
||||||
|
<div className="mx_LayoutSwitcher_RadioButtons">
|
||||||
|
<label className={ircClasses}>
|
||||||
|
<EventTilePreview
|
||||||
|
className="mx_LayoutSwitcher_RadioButton_preview"
|
||||||
|
message={this.props.messagePreviewText}
|
||||||
|
layout={Layout.IRC}
|
||||||
|
userId={this.props.userId}
|
||||||
|
displayName={this.props.displayName}
|
||||||
|
avatarUrl={this.props.avatarUrl}
|
||||||
|
/>
|
||||||
|
<StyledRadioButton
|
||||||
|
name="layout"
|
||||||
|
value={Layout.IRC}
|
||||||
|
checked={this.state.layout === Layout.IRC}
|
||||||
|
onChange={this.onLayoutChange}
|
||||||
|
>
|
||||||
|
{ _t("IRC") }
|
||||||
|
</StyledRadioButton>
|
||||||
|
</label>
|
||||||
|
<label className={groupClasses}>
|
||||||
|
<EventTilePreview
|
||||||
|
className="mx_LayoutSwitcher_RadioButton_preview"
|
||||||
|
message={this.props.messagePreviewText}
|
||||||
|
layout={Layout.Group}
|
||||||
|
userId={this.props.userId}
|
||||||
|
displayName={this.props.displayName}
|
||||||
|
avatarUrl={this.props.avatarUrl}
|
||||||
|
/>
|
||||||
|
<StyledRadioButton
|
||||||
|
name="layout"
|
||||||
|
value={Layout.Group}
|
||||||
|
checked={this.state.layout == Layout.Group}
|
||||||
|
onChange={this.onLayoutChange}
|
||||||
|
>
|
||||||
|
{ _t("Modern") }
|
||||||
|
</StyledRadioButton>
|
||||||
|
</label>
|
||||||
|
<label className={bubbleClasses}>
|
||||||
|
<EventTilePreview
|
||||||
|
className="mx_LayoutSwitcher_RadioButton_preview"
|
||||||
|
message={this.props.messagePreviewText}
|
||||||
|
layout={Layout.Bubble}
|
||||||
|
userId={this.props.userId}
|
||||||
|
displayName={this.props.displayName}
|
||||||
|
avatarUrl={this.props.avatarUrl}
|
||||||
|
/>
|
||||||
|
<StyledRadioButton
|
||||||
|
name="layout"
|
||||||
|
value={Layout.Bubble}
|
||||||
|
checked={this.state.layout == Layout.Bubble}
|
||||||
|
onChange={this.onLayoutChange}
|
||||||
|
>
|
||||||
|
{ _t("Message bubbles") }
|
||||||
|
</StyledRadioButton>
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,6 +1,6 @@
|
||||||
/*
|
/*
|
||||||
Copyright 2019 New Vector Ltd
|
Copyright 2019 New Vector Ltd
|
||||||
Copyright 2019, 2020 The Matrix.org Foundation C.I.C.
|
Copyright 2019 - 2021 The Matrix.org Foundation C.I.C.
|
||||||
|
|
||||||
Licensed under the Apache License, Version 2.0 (the "License");
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
you may not use this file except in compliance with the License.
|
you may not use this file except in compliance with the License.
|
||||||
|
@ -37,10 +37,9 @@ import StyledRadioGroup from "../../../elements/StyledRadioGroup";
|
||||||
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";
|
import { Layout } from "../../../../../settings/Layout";
|
||||||
import classNames from 'classnames';
|
|
||||||
import StyledRadioButton from '../../../elements/StyledRadioButton';
|
|
||||||
import { replaceableComponent } from "../../../../../utils/replaceableComponent";
|
import { replaceableComponent } from "../../../../../utils/replaceableComponent";
|
||||||
import { compare } from "../../../../../utils/strings";
|
import { compare } from "../../../../../utils/strings";
|
||||||
|
import LayoutSwitcher from "../../LayoutSwitcher";
|
||||||
|
|
||||||
interface IProps {
|
interface IProps {
|
||||||
}
|
}
|
||||||
|
@ -243,17 +242,8 @@ 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 onLayoutChanged = (layout: Layout): 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 });
|
this.setState({ layout: layout });
|
||||||
|
|
||||||
SettingsStore.setValue("layout", null, SettingLevel.DEVICE, layout);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
private onIRCLayoutChange = (enabled: boolean) => {
|
private onIRCLayoutChange = (enabled: boolean) => {
|
||||||
|
@ -391,75 +381,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">
|
|
||||||
<label 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}
|
|
||||||
>
|
|
||||||
{ _t("IRC") }
|
|
||||||
</StyledRadioButton>
|
|
||||||
</label>
|
|
||||||
<label 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>
|
|
||||||
</label>
|
|
||||||
<label 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>
|
|
||||||
</label>
|
|
||||||
</div>
|
|
||||||
</div>;
|
|
||||||
};
|
|
||||||
|
|
||||||
private renderAdvancedSection() {
|
private renderAdvancedSection() {
|
||||||
if (!SettingsStore.getValue(UIFeature.AdvancedSettings)) return null;
|
if (!SettingsStore.getValue(UIFeature.AdvancedSettings)) return null;
|
||||||
|
|
||||||
|
@ -527,6 +448,19 @@ export default class AppearanceUserSettingsTab extends React.Component<IProps, I
|
||||||
render() {
|
render() {
|
||||||
const brand = SdkConfig.get().brand;
|
const brand = SdkConfig.get().brand;
|
||||||
|
|
||||||
|
let layoutSection;
|
||||||
|
if (SettingsStore.getValue("feature_new_layout_switcher")) {
|
||||||
|
layoutSection = (
|
||||||
|
<LayoutSwitcher
|
||||||
|
userId={this.state.userId}
|
||||||
|
displayName={this.state.displayName}
|
||||||
|
avatarUrl={this.state.avatarUrl}
|
||||||
|
messagePreviewText={this.MESSAGE_PREVIEW_TEXT}
|
||||||
|
onLayoutChanged={this.onLayoutChanged}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="mx_SettingsTab mx_AppearanceUserSettingsTab">
|
<div className="mx_SettingsTab mx_AppearanceUserSettingsTab">
|
||||||
<div className="mx_SettingsTab_heading">{ _t("Customise your appearance") }</div>
|
<div className="mx_SettingsTab_heading">{ _t("Customise your appearance") }</div>
|
||||||
|
@ -534,7 +468,7 @@ export default class AppearanceUserSettingsTab extends React.Component<IProps, I
|
||||||
{ _t("Appearance Settings only affect this %(brand)s session.", { brand }) }
|
{ _t("Appearance Settings only affect this %(brand)s session.", { brand }) }
|
||||||
</div>
|
</div>
|
||||||
{ this.renderThemeSection() }
|
{ this.renderThemeSection() }
|
||||||
{ SettingsStore.getValue("feature_new_layout_switcher") ? this.renderLayoutSection() : null }
|
{ layoutSection }
|
||||||
{ this.renderFontSection() }
|
{ this.renderFontSection() }
|
||||||
{ this.renderAdvancedSection() }
|
{ this.renderAdvancedSection() }
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -1140,6 +1140,10 @@
|
||||||
"Connecting to integration manager...": "Connecting to integration manager...",
|
"Connecting to integration manager...": "Connecting to integration manager...",
|
||||||
"Cannot connect to integration manager": "Cannot connect to integration manager",
|
"Cannot connect to integration manager": "Cannot connect to integration manager",
|
||||||
"The integration manager is offline or it cannot reach your homeserver.": "The integration manager is offline or it cannot reach your homeserver.",
|
"The integration manager is offline or it cannot reach your homeserver.": "The integration manager is offline or it cannot reach your homeserver.",
|
||||||
|
"Message layout": "Message layout",
|
||||||
|
"IRC": "IRC",
|
||||||
|
"Modern": "Modern",
|
||||||
|
"Message bubbles": "Message bubbles",
|
||||||
"Messages containing keywords": "Messages containing keywords",
|
"Messages containing keywords": "Messages containing keywords",
|
||||||
"Error saving notification preferences": "Error saving notification preferences",
|
"Error saving notification preferences": "Error saving notification preferences",
|
||||||
"An error occurred whilst saving your notification preferences.": "An error occurred whilst saving your notification preferences.",
|
"An error occurred whilst saving your notification preferences.": "An error occurred whilst saving your notification preferences.",
|
||||||
|
@ -1252,10 +1256,6 @@
|
||||||
"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",
|
|
||||||
"IRC": "IRC",
|
|
||||||
"Modern": "Modern",
|
|
||||||
"Message bubbles": "Message bubbles",
|
|
||||||
"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",
|
"Enable experimental, compact IRC style layout": "Enable experimental, compact IRC style layout",
|
||||||
"Customise your appearance": "Customise your appearance",
|
"Customise your appearance": "Customise your appearance",
|
||||||
|
|
Loading…
Reference in New Issue