From 06a9ab3a706d3dfdc5e696f44d32bbbb0ff5b1e6 Mon Sep 17 00:00:00 2001 From: Travis Ralston Date: Wed, 23 Jan 2019 20:13:43 -0700 Subject: [PATCH] Styling to match the other tabs a bit closer Introduces a new component to reduce code duplication --- .../views/elements/LabelledToggleSwitch.js | 42 +++++ .../views/settings/Notifications.js | 143 ++++++------------ .../views/settings/tabs/LabsSettingsTab.js | 10 +- .../settings/tabs/NotificationSettingsTab.js | 11 +- 4 files changed, 88 insertions(+), 118 deletions(-) create mode 100644 src/components/views/elements/LabelledToggleSwitch.js diff --git a/src/components/views/elements/LabelledToggleSwitch.js b/src/components/views/elements/LabelledToggleSwitch.js new file mode 100644 index 0000000000..3d3025ad06 --- /dev/null +++ b/src/components/views/elements/LabelledToggleSwitch.js @@ -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 ( +
+ {this.props.label} + +
+ ); + } +} diff --git a/src/components/views/settings/Notifications.js b/src/components/views/settings/Notifications.js index ff843d0e1e..c502ef6bc6 100644 --- a/src/components/views/settings/Notifications.js +++ b/src/components/views/settings/Notifications.js @@ -29,6 +29,7 @@ import { 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. @@ -71,17 +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, - }, - - getDefaultProps: function() { - return { - threepids: [], - }; - }, - getInitialState: function() { return { phase: this.phases.LOADING, @@ -93,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 }; }, @@ -100,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(); }); @@ -433,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(); @@ -632,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) { @@ -690,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 (
-
- -
-
- -
-
); + return ; }, render: function() { - const self = this; - let spinner; if (this.state.phase === this.phases.LOADING) { const Loader = sdk.getComponent("elements.Spinner"); @@ -719,23 +709,9 @@ module.exports = React.createClass({ let masterPushRuleDiv; if (this.state.masterPushRule) { - masterPushRuleDiv = ( -
-
- -
-
- -
-
- ); + masterPushRuleDiv = ; } // When enabled, the master rule inhibits all existing rules @@ -746,17 +722,17 @@ module.exports = React.createClass({ {masterPushRuleDiv}
- { _t('All notifications are currently disabled for all targets.') }. + { _t('All notifications are currently disabled for all targets.') }
); } - 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 =
- { _t('Add an email address above to configure email notifications') } + { _t('Add an email address to configure email notifications') }
; } else { // This only supports the first email address in your profile for now @@ -787,7 +763,7 @@ module.exports = React.createClass({ let devicesSection; if (this.state.pushers === undefined) { devicesSection =
{ _t('Unable to fetch notification target list') }
; - } 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, @@ -835,50 +811,17 @@ module.exports = React.createClass({ { spinner } -
-
- -
-
- -
-
+ -
-
- -
-
- -
-
+ -
-
- -
-
- -
-
+ { emailNotificationsRow } diff --git a/src/components/views/settings/tabs/LabsSettingsTab.js b/src/components/views/settings/tabs/LabsSettingsTab.js index a815ddfdd4..4cdd3c8dab 100644 --- a/src/components/views/settings/tabs/LabsSettingsTab.js +++ b/src/components/views/settings/tabs/LabsSettingsTab.js @@ -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 ( -
- {label} - -
- ); + return } } diff --git a/src/components/views/settings/tabs/NotificationSettingsTab.js b/src/components/views/settings/tabs/NotificationSettingsTab.js index eb7523fdd1..b5dd3cedbd 100644 --- a/src/components/views/settings/tabs/NotificationSettingsTab.js +++ b/src/components/views/settings/tabs/NotificationSettingsTab.js @@ -16,20 +16,11 @@ limitations under the License. import React from 'react'; import {_t} from "../../../../languageHandler"; -import MatrixClientPeg from "../../../../MatrixClientPeg"; const sdk = require("../../../../index"); export default class NotificationSettingsTab extends React.Component { constructor() { super(); - - this.state = { - threepids: [], - }; - } - - async componentWillMount(): void { - MatrixClientPeg.get().getThreePids().then(r => this.setState({threepids: r.threepids})); } render() { @@ -38,7 +29,7 @@ export default class NotificationSettingsTab extends React.Component {
{_t("Notifications")}
- +
);