mirror of
https://github.com/element-hq/element-web
synced 2024-11-28 12:28:50 +03:00
Merge pull request #2494 from matrix-org/travis/usettings/tab/notifications
Implement the "Notifications" tab of new user settings
This commit is contained in:
commit
479b354d97
6 changed files with 130 additions and 114 deletions
|
@ -23,6 +23,7 @@ import GeneralSettingsTab from "../settings/tabs/GeneralSettingsTab";
|
|||
import dis from '../../../dispatcher';
|
||||
import SettingsStore from "../../../settings/SettingsStore";
|
||||
import LabsSettingsTab from "../settings/tabs/LabsSettingsTab";
|
||||
import NotificationSettingsTab from "../settings/tabs/NotificationSettingsTab";
|
||||
|
||||
// TODO: Ditch this whole component
|
||||
export class TempTab extends React.Component {
|
||||
|
@ -56,7 +57,7 @@ export default class UserSettingsDialog extends React.Component {
|
|||
tabs.push(new Tab(
|
||||
_td("Notifications"),
|
||||
"mx_UserSettingsDialog_bellIcon",
|
||||
<div>Notifications Test</div>,
|
||||
<NotificationSettingsTab />,
|
||||
));
|
||||
tabs.push(new Tab(
|
||||
_td("Preferences"),
|
||||
|
|
42
src/components/views/elements/LabelledToggleSwitch.js
Normal file
42
src/components/views/elements/LabelledToggleSwitch.js
Normal file
|
@ -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,
|
||||
ContentRules,
|
||||
} 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,
|
||||
// which should be factored out to other files.
|
||||
|
@ -70,19 +72,6 @@ module.exports = React.createClass({
|
|||
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() {
|
||||
return {
|
||||
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
|
||||
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();
|
||||
},
|
||||
|
||||
onEnableNotificationsChange: function(event) {
|
||||
onEnableNotificationsChange: function(checked) {
|
||||
const self = this;
|
||||
this.setState({
|
||||
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();
|
||||
});
|
||||
},
|
||||
|
||||
onEnableDesktopNotificationsChange: function(event) {
|
||||
onEnableDesktopNotificationsChange: function(checked) {
|
||||
SettingsStore.setValue(
|
||||
"notificationsEnabled", null,
|
||||
SettingLevel.DEVICE,
|
||||
event.target.checked,
|
||||
checked,
|
||||
).finally(() => {
|
||||
this.forceUpdate();
|
||||
});
|
||||
},
|
||||
|
||||
onEnableDesktopNotificationBodyChange: function(event) {
|
||||
onEnableDesktopNotificationBodyChange: function(checked) {
|
||||
SettingsStore.setValue(
|
||||
"notificationBodyEnabled", null,
|
||||
SettingLevel.DEVICE,
|
||||
event.target.checked,
|
||||
checked,
|
||||
).finally(() => {
|
||||
this.forceUpdate();
|
||||
});
|
||||
},
|
||||
|
||||
onEnableAudioNotificationsChange: function(event) {
|
||||
onEnableAudioNotificationsChange: function(checked) {
|
||||
SettingsStore.setValue(
|
||||
"audioNotificationsEnabled", null,
|
||||
SettingLevel.DEVICE,
|
||||
event.target.checked,
|
||||
checked,
|
||||
).finally(() => {
|
||||
this.forceUpdate();
|
||||
});
|
||||
|
@ -146,7 +136,7 @@ module.exports = React.createClass({
|
|||
let emailPusherPromise;
|
||||
if (event.target.checked) {
|
||||
const data = {};
|
||||
data['brand'] = this.props.brand || 'Riot';
|
||||
data['brand'] = SdkConfig.get().brand || 'Riot';
|
||||
emailPusherPromise = UserSettingsStore.addEmailPusher(address, data);
|
||||
} else {
|
||||
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
|
||||
// for overriding the actions of default rules.
|
||||
_portRulesToNewAPI: function(rulesets) {
|
||||
const self = this;
|
||||
const needsUpdate = [];
|
||||
const cli = MatrixClientPeg.get();
|
||||
|
||||
|
@ -633,6 +622,8 @@ module.exports = React.createClass({
|
|||
externalPushRules: self.state.externalPushRules,
|
||||
});
|
||||
}).done();
|
||||
|
||||
MatrixClientPeg.get().getThreePids().then((r) => this.setState({threepids: r.threepids}));
|
||||
},
|
||||
|
||||
_updatePushRuleActions: function(rule, actions, enabled) {
|
||||
|
@ -691,27 +682,25 @@ module.exports = React.createClass({
|
|||
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) {
|
||||
return (<div className="mx_UserNotifSettings_tableRow">
|
||||
<div className="mx_UserNotifSettings_inputCell">
|
||||
<input id="enableEmailNotifications_{address}"
|
||||
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>);
|
||||
return <LabelledToggleSwitch value={this.hasEmailPusher(this.state.pushers, address)}
|
||||
onChange={this.onEnableEmailNotificationsChange.bind(this, address)}
|
||||
label={label} />;
|
||||
},
|
||||
|
||||
render: function() {
|
||||
const self = this;
|
||||
|
||||
let spinner;
|
||||
if (this.state.phase === this.phases.LOADING) {
|
||||
const Loader = sdk.getComponent("elements.Spinner");
|
||||
|
@ -720,23 +709,9 @@ module.exports = React.createClass({
|
|||
|
||||
let masterPushRuleDiv;
|
||||
if (this.state.masterPushRule) {
|
||||
masterPushRuleDiv = (
|
||||
<div className="mx_UserNotifSettings_tableRow">
|
||||
<div className="mx_UserNotifSettings_inputCell">
|
||||
<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>
|
||||
);
|
||||
masterPushRuleDiv = <LabelledToggleSwitch value={!this.state.masterPushRule.enabled}
|
||||
onChange={this.onEnableNotificationsChange}
|
||||
label={_t('Enable notifications for this account')}/>;
|
||||
}
|
||||
|
||||
// When enabled, the master rule inhibits all existing rules
|
||||
|
@ -747,17 +722,17 @@ module.exports = React.createClass({
|
|||
{masterPushRuleDiv}
|
||||
|
||||
<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>
|
||||
);
|
||||
}
|
||||
|
||||
const emailThreepids = this.props.threepids.filter((tp) => tp.medium === "email");
|
||||
const emailThreepids = this.state.threepids.filter((tp) => tp.medium === "email");
|
||||
let emailNotificationsRow;
|
||||
if (emailThreepids.length === 0) {
|
||||
emailNotificationsRow = <div>
|
||||
{ _t('Add an email address above to configure email notifications') }
|
||||
{ _t('Add an email address to configure email notifications') }
|
||||
</div>;
|
||||
} else {
|
||||
// This only supports the first email address in your profile for now
|
||||
|
@ -788,7 +763,7 @@ module.exports = React.createClass({
|
|||
let devicesSection;
|
||||
if (this.state.pushers === undefined) {
|
||||
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;
|
||||
} else {
|
||||
// TODO: It would be great to be able to delete pushers from here too,
|
||||
|
@ -836,50 +811,17 @@ module.exports = React.createClass({
|
|||
|
||||
{ spinner }
|
||||
|
||||
<div className="mx_UserNotifSettings_tableRow">
|
||||
<div className="mx_UserNotifSettings_inputCell">
|
||||
<input id="enableDesktopNotifications"
|
||||
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>
|
||||
<LabelledToggleSwitch value={SettingsStore.getValue("notificationsEnabled")}
|
||||
onChange={this.onEnableDesktopNotificationsChange}
|
||||
label={_t('Enable desktop notifications')} />
|
||||
|
||||
<div className="mx_UserNotifSettings_tableRow">
|
||||
<div className="mx_UserNotifSettings_inputCell">
|
||||
<input id="enableDesktopNotificationBody"
|
||||
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>
|
||||
<LabelledToggleSwitch value={SettingsStore.getValue("notificationBodyEnabled")}
|
||||
onChange={this.onEnableDesktopNotificationBodyChange}
|
||||
label={_t('Show message in desktop notification')} />
|
||||
|
||||
<div className="mx_UserNotifSettings_tableRow">
|
||||
<div className="mx_UserNotifSettings_inputCell">
|
||||
<input id="enableDesktopAudioNotifications"
|
||||
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>
|
||||
<LabelledToggleSwitch value={SettingsStore.getValue("audioNotificationsEnabled")}
|
||||
onChange={this.onEnableAudioNotificationsChange}
|
||||
label={_t('Enable audible notifications in web client')} />
|
||||
|
||||
{ emailNotificationsRow }
|
||||
|
||||
|
|
|
@ -18,8 +18,8 @@ import React from 'react';
|
|||
import {_t} from "../../../../languageHandler";
|
||||
import PropTypes from "prop-types";
|
||||
import SettingsStore from "../../../../settings/SettingsStore";
|
||||
import ToggleSwitch from "../../elements/ToggleSwitch";
|
||||
import MatrixClientPeg from "../../../../MatrixClientPeg";
|
||||
import LabelledToggleSwitch from "../../elements/LabelledToggleSwitch";
|
||||
const Modal = require("../../../../Modal");
|
||||
const sdk = require("../../../../index");
|
||||
|
||||
|
@ -65,15 +65,9 @@ export class LabsSettingToggle extends React.Component {
|
|||
};
|
||||
|
||||
render() {
|
||||
// This is a minimal version of a SettingsFlag
|
||||
const label = _t(SettingsStore.getDisplayName(this.props.featureId));
|
||||
const value = SettingsStore.isFeatureEnabled(this.props.featureId);
|
||||
return (
|
||||
<div className="mx_SettingsFlag">
|
||||
<span className="mx_SettingsFlag_label">{label}</span>
|
||||
<ToggleSwitch checked={value} onChange={this._onChange} />
|
||||
</div>
|
||||
);
|
||||
return <LabelledToggleSwitch value={value} label={label} onChange={this._onChange} />;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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",
|
||||
"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.",
|
||||
"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",
|
||||
"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",
|
||||
|
@ -442,6 +442,7 @@
|
|||
"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.",
|
||||
"Labs": "Labs",
|
||||
"Notifications": "Notifications",
|
||||
"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.",
|
||||
"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.",
|
||||
"Members": "Members",
|
||||
"Files": "Files",
|
||||
"Notifications": "Notifications",
|
||||
"Sunday": "Sunday",
|
||||
"Monday": "Monday",
|
||||
"Tuesday": "Tuesday",
|
||||
|
|
Loading…
Reference in a new issue