mirror of https://github.com/vector-im/riot-web
Merge pull request #2494 from matrix-org/travis/usettings/tab/notifications
Implement the "Notifications" tab of new user settingspull/21833/head
commit
479b354d97
|
@ -23,6 +23,7 @@ import GeneralSettingsTab from "../settings/tabs/GeneralSettingsTab";
|
||||||
import dis from '../../../dispatcher';
|
import dis from '../../../dispatcher';
|
||||||
import SettingsStore from "../../../settings/SettingsStore";
|
import SettingsStore from "../../../settings/SettingsStore";
|
||||||
import LabsSettingsTab from "../settings/tabs/LabsSettingsTab";
|
import LabsSettingsTab from "../settings/tabs/LabsSettingsTab";
|
||||||
|
import NotificationSettingsTab from "../settings/tabs/NotificationSettingsTab";
|
||||||
|
|
||||||
// TODO: Ditch this whole component
|
// TODO: Ditch this whole component
|
||||||
export class TempTab extends React.Component {
|
export class TempTab extends React.Component {
|
||||||
|
@ -56,7 +57,7 @@ export default class UserSettingsDialog extends React.Component {
|
||||||
tabs.push(new Tab(
|
tabs.push(new Tab(
|
||||||
_td("Notifications"),
|
_td("Notifications"),
|
||||||
"mx_UserSettingsDialog_bellIcon",
|
"mx_UserSettingsDialog_bellIcon",
|
||||||
<div>Notifications Test</div>,
|
<NotificationSettingsTab />,
|
||||||
));
|
));
|
||||||
tabs.push(new Tab(
|
tabs.push(new Tab(
|
||||||
_td("Preferences"),
|
_td("Preferences"),
|
||||||
|
|
|
@ -0,0 +1,42 @@
|
||||||
|
/*
|
||||||
|
Copyright 2019 New Vector Ltd
|
||||||
|
|
||||||
|
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 PropTypes from "prop-types";
|
||||||
|
import ToggleSwitch from "./ToggleSwitch";
|
||||||
|
|
||||||
|
export default class LabelledToggleSwitch extends React.Component {
|
||||||
|
static propTypes = {
|
||||||
|
// The value for the toggle switch
|
||||||
|
value: PropTypes.bool.isRequired,
|
||||||
|
|
||||||
|
// The function to call when the value changes
|
||||||
|
onChange: PropTypes.func.isRequired,
|
||||||
|
|
||||||
|
// The translated label for the switch
|
||||||
|
label: PropTypes.string.isRequired,
|
||||||
|
};
|
||||||
|
|
||||||
|
render() {
|
||||||
|
// This is a minimal version of a SettingsFlag
|
||||||
|
return (
|
||||||
|
<div className="mx_SettingsFlag">
|
||||||
|
<span className="mx_SettingsFlag_label">{this.props.label}</span>
|
||||||
|
<ToggleSwitch checked={this.props.value} onChange={this.props.onChange} />
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
|
@ -28,6 +28,8 @@ import {
|
||||||
PushRuleVectorState,
|
PushRuleVectorState,
|
||||||
ContentRules,
|
ContentRules,
|
||||||
} from '../../../notifications';
|
} from '../../../notifications';
|
||||||
|
import * as SdkConfig from "../../../SdkConfig";
|
||||||
|
import LabelledToggleSwitch from "../elements/LabelledToggleSwitch";
|
||||||
|
|
||||||
// TODO: this "view" component still has far too much application logic in it,
|
// TODO: this "view" component still has far too much application logic in it,
|
||||||
// which should be factored out to other files.
|
// which should be factored out to other files.
|
||||||
|
@ -70,19 +72,6 @@ module.exports = React.createClass({
|
||||||
ERROR: "ERROR", // There was an error
|
ERROR: "ERROR", // There was an error
|
||||||
},
|
},
|
||||||
|
|
||||||
propTypes: {
|
|
||||||
// The array of threepids from the JS SDK (required for email notifications)
|
|
||||||
threepids: React.PropTypes.array.isRequired,
|
|
||||||
// The brand string set when creating an email pusher
|
|
||||||
brand: React.PropTypes.string,
|
|
||||||
},
|
|
||||||
|
|
||||||
getDefaultProps: function() {
|
|
||||||
return {
|
|
||||||
threepids: [],
|
|
||||||
};
|
|
||||||
},
|
|
||||||
|
|
||||||
getInitialState: function() {
|
getInitialState: function() {
|
||||||
return {
|
return {
|
||||||
phase: this.phases.LOADING,
|
phase: this.phases.LOADING,
|
||||||
|
@ -94,6 +83,7 @@ module.exports = React.createClass({
|
||||||
},
|
},
|
||||||
externalPushRules: [], // Push rules (except content rule) that have been defined outside Vector UI
|
externalPushRules: [], // Push rules (except content rule) that have been defined outside Vector UI
|
||||||
externalContentRules: [], // Keyword push rules that have been defined outside Vector UI
|
externalContentRules: [], // Keyword push rules that have been defined outside Vector UI
|
||||||
|
threepids: [], // used for email notifications
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -101,42 +91,42 @@ module.exports = React.createClass({
|
||||||
this._refreshFromServer();
|
this._refreshFromServer();
|
||||||
},
|
},
|
||||||
|
|
||||||
onEnableNotificationsChange: function(event) {
|
onEnableNotificationsChange: function(checked) {
|
||||||
const self = this;
|
const self = this;
|
||||||
this.setState({
|
this.setState({
|
||||||
phase: this.phases.LOADING,
|
phase: this.phases.LOADING,
|
||||||
});
|
});
|
||||||
|
|
||||||
MatrixClientPeg.get().setPushRuleEnabled('global', self.state.masterPushRule.kind, self.state.masterPushRule.rule_id, !event.target.checked).done(function() {
|
MatrixClientPeg.get().setPushRuleEnabled('global', self.state.masterPushRule.kind, self.state.masterPushRule.rule_id, !checked).done(function() {
|
||||||
self._refreshFromServer();
|
self._refreshFromServer();
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
onEnableDesktopNotificationsChange: function(event) {
|
onEnableDesktopNotificationsChange: function(checked) {
|
||||||
SettingsStore.setValue(
|
SettingsStore.setValue(
|
||||||
"notificationsEnabled", null,
|
"notificationsEnabled", null,
|
||||||
SettingLevel.DEVICE,
|
SettingLevel.DEVICE,
|
||||||
event.target.checked,
|
checked,
|
||||||
).finally(() => {
|
).finally(() => {
|
||||||
this.forceUpdate();
|
this.forceUpdate();
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
onEnableDesktopNotificationBodyChange: function(event) {
|
onEnableDesktopNotificationBodyChange: function(checked) {
|
||||||
SettingsStore.setValue(
|
SettingsStore.setValue(
|
||||||
"notificationBodyEnabled", null,
|
"notificationBodyEnabled", null,
|
||||||
SettingLevel.DEVICE,
|
SettingLevel.DEVICE,
|
||||||
event.target.checked,
|
checked,
|
||||||
).finally(() => {
|
).finally(() => {
|
||||||
this.forceUpdate();
|
this.forceUpdate();
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
onEnableAudioNotificationsChange: function(event) {
|
onEnableAudioNotificationsChange: function(checked) {
|
||||||
SettingsStore.setValue(
|
SettingsStore.setValue(
|
||||||
"audioNotificationsEnabled", null,
|
"audioNotificationsEnabled", null,
|
||||||
SettingLevel.DEVICE,
|
SettingLevel.DEVICE,
|
||||||
event.target.checked,
|
checked,
|
||||||
).finally(() => {
|
).finally(() => {
|
||||||
this.forceUpdate();
|
this.forceUpdate();
|
||||||
});
|
});
|
||||||
|
@ -146,7 +136,7 @@ module.exports = React.createClass({
|
||||||
let emailPusherPromise;
|
let emailPusherPromise;
|
||||||
if (event.target.checked) {
|
if (event.target.checked) {
|
||||||
const data = {};
|
const data = {};
|
||||||
data['brand'] = this.props.brand || 'Riot';
|
data['brand'] = SdkConfig.get().brand || 'Riot';
|
||||||
emailPusherPromise = UserSettingsStore.addEmailPusher(address, data);
|
emailPusherPromise = UserSettingsStore.addEmailPusher(address, data);
|
||||||
} else {
|
} else {
|
||||||
const emailPusher = UserSettingsStore.getEmailPusher(this.state.pushers, address);
|
const emailPusher = UserSettingsStore.getEmailPusher(this.state.pushers, address);
|
||||||
|
@ -434,7 +424,6 @@ module.exports = React.createClass({
|
||||||
// Check if any legacy im.vector rules need to be ported to the new API
|
// Check if any legacy im.vector rules need to be ported to the new API
|
||||||
// for overriding the actions of default rules.
|
// for overriding the actions of default rules.
|
||||||
_portRulesToNewAPI: function(rulesets) {
|
_portRulesToNewAPI: function(rulesets) {
|
||||||
const self = this;
|
|
||||||
const needsUpdate = [];
|
const needsUpdate = [];
|
||||||
const cli = MatrixClientPeg.get();
|
const cli = MatrixClientPeg.get();
|
||||||
|
|
||||||
|
@ -633,6 +622,8 @@ module.exports = React.createClass({
|
||||||
externalPushRules: self.state.externalPushRules,
|
externalPushRules: self.state.externalPushRules,
|
||||||
});
|
});
|
||||||
}).done();
|
}).done();
|
||||||
|
|
||||||
|
MatrixClientPeg.get().getThreePids().then((r) => this.setState({threepids: r.threepids}));
|
||||||
},
|
},
|
||||||
|
|
||||||
_updatePushRuleActions: function(rule, actions, enabled) {
|
_updatePushRuleActions: function(rule, actions, enabled) {
|
||||||
|
@ -691,27 +682,25 @@ module.exports = React.createClass({
|
||||||
return rows;
|
return rows;
|
||||||
},
|
},
|
||||||
|
|
||||||
|
hasEmailPusher: function(pushers, address) {
|
||||||
|
if (pushers === undefined) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
for (let i = 0; i < pushers.length; ++i) {
|
||||||
|
if (pushers[i].kind === 'email' && pushers[i].pushkey === address) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
},
|
||||||
|
|
||||||
emailNotificationsRow: function(address, label) {
|
emailNotificationsRow: function(address, label) {
|
||||||
return (<div className="mx_UserNotifSettings_tableRow">
|
return <LabelledToggleSwitch value={this.hasEmailPusher(this.state.pushers, address)}
|
||||||
<div className="mx_UserNotifSettings_inputCell">
|
onChange={this.onEnableEmailNotificationsChange.bind(this, address)}
|
||||||
<input id="enableEmailNotifications_{address}"
|
label={label} />;
|
||||||
ref="enableEmailNotifications_{address}"
|
|
||||||
type="checkbox"
|
|
||||||
checked={ UserSettingsStore.hasEmailPusher(this.state.pushers, address) }
|
|
||||||
onChange={ this.onEnableEmailNotificationsChange.bind(this, address) }
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
<div className="mx_UserNotifSettings_labelCell">
|
|
||||||
<label htmlFor="enableEmailNotifications_{address}">
|
|
||||||
{label}
|
|
||||||
</label>
|
|
||||||
</div>
|
|
||||||
</div>);
|
|
||||||
},
|
},
|
||||||
|
|
||||||
render: function() {
|
render: function() {
|
||||||
const self = this;
|
|
||||||
|
|
||||||
let spinner;
|
let spinner;
|
||||||
if (this.state.phase === this.phases.LOADING) {
|
if (this.state.phase === this.phases.LOADING) {
|
||||||
const Loader = sdk.getComponent("elements.Spinner");
|
const Loader = sdk.getComponent("elements.Spinner");
|
||||||
|
@ -720,23 +709,9 @@ module.exports = React.createClass({
|
||||||
|
|
||||||
let masterPushRuleDiv;
|
let masterPushRuleDiv;
|
||||||
if (this.state.masterPushRule) {
|
if (this.state.masterPushRule) {
|
||||||
masterPushRuleDiv = (
|
masterPushRuleDiv = <LabelledToggleSwitch value={!this.state.masterPushRule.enabled}
|
||||||
<div className="mx_UserNotifSettings_tableRow">
|
onChange={this.onEnableNotificationsChange}
|
||||||
<div className="mx_UserNotifSettings_inputCell">
|
label={_t('Enable notifications for this account')}/>;
|
||||||
<input id="enableNotifications"
|
|
||||||
ref="enableNotifications"
|
|
||||||
type="checkbox"
|
|
||||||
checked={ !this.state.masterPushRule.enabled }
|
|
||||||
onChange={ this.onEnableNotificationsChange }
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
<div className="mx_UserNotifSettings_labelCell">
|
|
||||||
<label htmlFor="enableNotifications">
|
|
||||||
{ _t('Enable notifications for this account') }
|
|
||||||
</label>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// When enabled, the master rule inhibits all existing rules
|
// When enabled, the master rule inhibits all existing rules
|
||||||
|
@ -747,17 +722,17 @@ module.exports = React.createClass({
|
||||||
{masterPushRuleDiv}
|
{masterPushRuleDiv}
|
||||||
|
|
||||||
<div className="mx_UserSettings_notifTable">
|
<div className="mx_UserSettings_notifTable">
|
||||||
{ _t('All notifications are currently disabled for all targets.') }.
|
{ _t('All notifications are currently disabled for all targets.') }
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
const emailThreepids = this.props.threepids.filter((tp) => tp.medium === "email");
|
const emailThreepids = this.state.threepids.filter((tp) => tp.medium === "email");
|
||||||
let emailNotificationsRow;
|
let emailNotificationsRow;
|
||||||
if (emailThreepids.length === 0) {
|
if (emailThreepids.length === 0) {
|
||||||
emailNotificationsRow = <div>
|
emailNotificationsRow = <div>
|
||||||
{ _t('Add an email address above to configure email notifications') }
|
{ _t('Add an email address to configure email notifications') }
|
||||||
</div>;
|
</div>;
|
||||||
} else {
|
} else {
|
||||||
// This only supports the first email address in your profile for now
|
// This only supports the first email address in your profile for now
|
||||||
|
@ -788,7 +763,7 @@ module.exports = React.createClass({
|
||||||
let devicesSection;
|
let devicesSection;
|
||||||
if (this.state.pushers === undefined) {
|
if (this.state.pushers === undefined) {
|
||||||
devicesSection = <div className="error">{ _t('Unable to fetch notification target list') }</div>;
|
devicesSection = <div className="error">{ _t('Unable to fetch notification target list') }</div>;
|
||||||
} else if (this.state.pushers.length == 0) {
|
} else if (this.state.pushers.length === 0) {
|
||||||
devicesSection = null;
|
devicesSection = null;
|
||||||
} else {
|
} else {
|
||||||
// TODO: It would be great to be able to delete pushers from here too,
|
// TODO: It would be great to be able to delete pushers from here too,
|
||||||
|
@ -836,50 +811,17 @@ module.exports = React.createClass({
|
||||||
|
|
||||||
{ spinner }
|
{ spinner }
|
||||||
|
|
||||||
<div className="mx_UserNotifSettings_tableRow">
|
<LabelledToggleSwitch value={SettingsStore.getValue("notificationsEnabled")}
|
||||||
<div className="mx_UserNotifSettings_inputCell">
|
onChange={this.onEnableDesktopNotificationsChange}
|
||||||
<input id="enableDesktopNotifications"
|
label={_t('Enable desktop notifications')} />
|
||||||
ref="enableDesktopNotifications"
|
|
||||||
type="checkbox"
|
|
||||||
checked={ SettingsStore.getValue("notificationsEnabled") }
|
|
||||||
onChange={ this.onEnableDesktopNotificationsChange } />
|
|
||||||
</div>
|
|
||||||
<div className="mx_UserNotifSettings_labelCell">
|
|
||||||
<label htmlFor="enableDesktopNotifications">
|
|
||||||
{ _t('Enable desktop notifications') }
|
|
||||||
</label>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div className="mx_UserNotifSettings_tableRow">
|
<LabelledToggleSwitch value={SettingsStore.getValue("notificationBodyEnabled")}
|
||||||
<div className="mx_UserNotifSettings_inputCell">
|
onChange={this.onEnableDesktopNotificationBodyChange}
|
||||||
<input id="enableDesktopNotificationBody"
|
label={_t('Show message in desktop notification')} />
|
||||||
ref="enableDesktopNotificationBody"
|
|
||||||
type="checkbox"
|
|
||||||
checked={ SettingsStore.getValue("notificationBodyEnabled") }
|
|
||||||
onChange={ this.onEnableDesktopNotificationBodyChange } />
|
|
||||||
</div>
|
|
||||||
<div className="mx_UserNotifSettings_labelCell">
|
|
||||||
<label htmlFor="enableDesktopNotificationBody">
|
|
||||||
{ _t('Show message in desktop notification') }
|
|
||||||
</label>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div className="mx_UserNotifSettings_tableRow">
|
<LabelledToggleSwitch value={SettingsStore.getValue("audioNotificationsEnabled")}
|
||||||
<div className="mx_UserNotifSettings_inputCell">
|
onChange={this.onEnableAudioNotificationsChange}
|
||||||
<input id="enableDesktopAudioNotifications"
|
label={_t('Enable audible notifications in web client')} />
|
||||||
ref="enableDesktopAudioNotifications"
|
|
||||||
type="checkbox"
|
|
||||||
checked={ SettingsStore.getValue("audioNotificationsEnabled") }
|
|
||||||
onChange={ this.onEnableAudioNotificationsChange } />
|
|
||||||
</div>
|
|
||||||
<div className="mx_UserNotifSettings_labelCell">
|
|
||||||
<label htmlFor="enableDesktopAudioNotifications">
|
|
||||||
{ _t('Enable audible notifications in web client') }
|
|
||||||
</label>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{ emailNotificationsRow }
|
{ emailNotificationsRow }
|
||||||
|
|
||||||
|
|
|
@ -18,8 +18,8 @@ import React from 'react';
|
||||||
import {_t} from "../../../../languageHandler";
|
import {_t} from "../../../../languageHandler";
|
||||||
import PropTypes from "prop-types";
|
import PropTypes from "prop-types";
|
||||||
import SettingsStore from "../../../../settings/SettingsStore";
|
import SettingsStore from "../../../../settings/SettingsStore";
|
||||||
import ToggleSwitch from "../../elements/ToggleSwitch";
|
|
||||||
import MatrixClientPeg from "../../../../MatrixClientPeg";
|
import MatrixClientPeg from "../../../../MatrixClientPeg";
|
||||||
|
import LabelledToggleSwitch from "../../elements/LabelledToggleSwitch";
|
||||||
const Modal = require("../../../../Modal");
|
const Modal = require("../../../../Modal");
|
||||||
const sdk = require("../../../../index");
|
const sdk = require("../../../../index");
|
||||||
|
|
||||||
|
@ -65,15 +65,9 @@ export class LabsSettingToggle extends React.Component {
|
||||||
};
|
};
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
// This is a minimal version of a SettingsFlag
|
|
||||||
const label = _t(SettingsStore.getDisplayName(this.props.featureId));
|
const label = _t(SettingsStore.getDisplayName(this.props.featureId));
|
||||||
const value = SettingsStore.isFeatureEnabled(this.props.featureId);
|
const value = SettingsStore.isFeatureEnabled(this.props.featureId);
|
||||||
return (
|
return <LabelledToggleSwitch value={value} label={label} onChange={this._onChange} />;
|
||||||
<div className="mx_SettingsFlag">
|
|
||||||
<span className="mx_SettingsFlag_label">{label}</span>
|
|
||||||
<ToggleSwitch checked={value} onChange={this._onChange} />
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,37 @@
|
||||||
|
/*
|
||||||
|
Copyright 2019 New Vector Ltd
|
||||||
|
|
||||||
|
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 {_t} from "../../../../languageHandler";
|
||||||
|
const sdk = require("../../../../index");
|
||||||
|
|
||||||
|
export default class NotificationSettingsTab extends React.Component {
|
||||||
|
constructor() {
|
||||||
|
super();
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
const Notifications = sdk.getComponent("views.settings.Notifications");
|
||||||
|
return (
|
||||||
|
<div className="mx_SettingsTab">
|
||||||
|
<div className="mx_SettingsTab_heading">{_t("Notifications")}</div>
|
||||||
|
<div className="mx_SettingsTab_section">
|
||||||
|
<Notifications />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
|
@ -399,7 +399,7 @@
|
||||||
"Notify me for anything else": "Notify me for anything else",
|
"Notify me for anything else": "Notify me for anything else",
|
||||||
"Enable notifications for this account": "Enable notifications for this account",
|
"Enable notifications for this account": "Enable notifications for this account",
|
||||||
"All notifications are currently disabled for all targets.": "All notifications are currently disabled for all targets.",
|
"All notifications are currently disabled for all targets.": "All notifications are currently disabled for all targets.",
|
||||||
"Add an email address above to configure email notifications": "Add an email address above to configure email notifications",
|
"Add an email address to configure email notifications": "Add an email address to configure email notifications",
|
||||||
"Enable email notifications": "Enable email notifications",
|
"Enable email notifications": "Enable email notifications",
|
||||||
"Notifications on the following keywords follow rules which can’t be displayed here:": "Notifications on the following keywords follow rules which can’t be displayed here:",
|
"Notifications on the following keywords follow rules which can’t be displayed here:": "Notifications on the following keywords follow rules which can’t be displayed here:",
|
||||||
"Unable to fetch notification target list": "Unable to fetch notification target list",
|
"Unable to fetch notification target list": "Unable to fetch notification target list",
|
||||||
|
@ -442,6 +442,7 @@
|
||||||
"Lazy loading members not supported": "Lazy loading members not supported",
|
"Lazy loading members not supported": "Lazy loading members not supported",
|
||||||
"Lazy loading is not supported by your current homeserver.": "Lazy loading is not supported by your current homeserver.",
|
"Lazy loading is not supported by your current homeserver.": "Lazy loading is not supported by your current homeserver.",
|
||||||
"Labs": "Labs",
|
"Labs": "Labs",
|
||||||
|
"Notifications": "Notifications",
|
||||||
"Cannot add any more widgets": "Cannot add any more widgets",
|
"Cannot add any more widgets": "Cannot add any more widgets",
|
||||||
"The maximum permitted number of widgets have already been added to this room.": "The maximum permitted number of widgets have already been added to this room.",
|
"The maximum permitted number of widgets have already been added to this room.": "The maximum permitted number of widgets have already been added to this room.",
|
||||||
"Add a widget": "Add a widget",
|
"Add a widget": "Add a widget",
|
||||||
|
@ -720,7 +721,6 @@
|
||||||
"When someone puts a URL in their message, a URL preview can be shown to give more information about that link such as the title, description, and an image from the website.": "When someone puts a URL in their message, a URL preview can be shown to give more information about that link such as the title, description, and an image from the website.",
|
"When someone puts a URL in their message, a URL preview can be shown to give more information about that link such as the title, description, and an image from the website.": "When someone puts a URL in their message, a URL preview can be shown to give more information about that link such as the title, description, and an image from the website.",
|
||||||
"Members": "Members",
|
"Members": "Members",
|
||||||
"Files": "Files",
|
"Files": "Files",
|
||||||
"Notifications": "Notifications",
|
|
||||||
"Sunday": "Sunday",
|
"Sunday": "Sunday",
|
||||||
"Monday": "Monday",
|
"Monday": "Monday",
|
||||||
"Tuesday": "Tuesday",
|
"Tuesday": "Tuesday",
|
||||||
|
|
Loading…
Reference in New Issue