diff --git a/src/components/views/elements/ManageIntegsButton.js b/src/components/views/elements/ManageIntegsButton.js new file mode 100644 index 0000000000..a5f6eb7982 --- /dev/null +++ b/src/components/views/elements/ManageIntegsButton.js @@ -0,0 +1,117 @@ +/* +Copyright 2017 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 sdk from '../../../index'; +import SdkConfig from '../../../SdkConfig'; +import ScalarAuthClient from '../../../ScalarAuthClient'; +import ScalarMessaging from '../../../ScalarMessaging'; +import Modal from "../../../Modal"; +import { _t } from '../../../languageHandler'; +import AccessibleButton from './AccessibleButton'; +import TintableSvg from './TintableSvg'; + +export default class ManageIntegsButton extends React.Component { + constructor(props) { + super(props); + + this.state = { + scalarError: null, + showIntegrationsError: false, + }; + + this.onManageIntegrations = this.onManageIntegrations.bind(this); + this.onShowIntegrationsError = this.onShowIntegrationsError.bind(this); + } + + componentWillMount() { + ScalarMessaging.startListening(); + this.scalarClient = null; + + if (SdkConfig.get().integrations_ui_url && SdkConfig.get().integrations_rest_url) { + this.scalarClient = new ScalarAuthClient(); + this.scalarClient.connect().done(() => { + this.forceUpdate(); + }, (err) => { + this.setState({ scalarError: err}); + console.error(err); + }); + } + } + + componentWillUnmount() { + ScalarMessaging.stopListening(); + } + + onManageIntegrations(ev) { + ev.preventDefault(); + const IntegrationsManager = sdk.getComponent("views.settings.IntegrationsManager"); + Modal.createDialog(IntegrationsManager, { + src: (this.scalarClient !== null && this.scalarClient.hasCredentials()) ? + this.scalarClient.getScalarInterfaceUrlForRoom(this.props.roomId) : + null, + }, "mx_IntegrationsManager"); + } + + onShowIntegrationsError(ev) { + ev.preventDefault(); + this.setState({ + showIntegrationsError: !this.state.showIntegrationsError, + }); + } + + render() { + let integrationsButton; + let integrationsError; + if (this.scalarClient !== null) { + if (this.state.showIntegrationsError && this.state.scalarError) { + integrationsError = ( + + { _t('Could not connect to the integration server') } + + ); + } + + if (this.scalarClient.hasCredentials()) { + integrationsButton = ( + + + + ); + } else if (this.state.scalarError) { + integrationsButton = ( +
+ + { integrationsError } +
+ ); + } else { + integrationsButton = ( + + + + ); + } + } + + return integrationsButton; + } +} + +ManageIntegsButton.propTypes = { + roomId: PropTypes.string.isRequired, +}; diff --git a/src/components/views/rooms/AppsDrawer.js b/src/components/views/rooms/AppsDrawer.js index 42a680bab6..3a3ec06c5c 100644 --- a/src/components/views/rooms/AppsDrawer.js +++ b/src/components/views/rooms/AppsDrawer.js @@ -28,6 +28,8 @@ import ScalarMessaging from '../../../ScalarMessaging'; import { _t } from '../../../languageHandler'; import WidgetUtils from '../../../WidgetUtils'; +// The maximum number of widgets that can be added in a room +const MAX_WIDGETS = 2; module.exports = React.createClass({ displayName: 'AppsDrawer', @@ -184,6 +186,18 @@ module.exports = React.createClass({ onClickAddWidget: function(e) { e.preventDefault(); + // Display a warning dialog if the max number of widgets have already been added to the room + const apps = this._getApps(); + if (apps && apps.length >= MAX_WIDGETS) { + const ErrorDialog = sdk.getComponent("dialogs.ErrorDialog"); + const errorMsg = `The maximum number of ${MAX_WIDGETS} widgets have already been added to this room.`; + console.error(errorMsg); + Modal.createDialog(ErrorDialog, { + title: _t("Cannot add any more widgets"), + description: _t("The maximum permitted number of widgets have already been added to this room."), + }); + return; + } this._launchManageIntegrations(); }, @@ -206,8 +220,6 @@ module.exports = React.createClass({ let addWidget; if (this.props.showApps && - this.state.apps && - this.state.apps.length < 2 && this._canUserModify() ) { addWidget =
{apps}
- {addWidget} + {this._canUserModify() && addWidget} ); }, diff --git a/src/components/views/rooms/MessageComposer.js b/src/components/views/rooms/MessageComposer.js index 51b595eab0..fd8c73eb80 100644 --- a/src/components/views/rooms/MessageComposer.js +++ b/src/components/views/rooms/MessageComposer.js @@ -289,12 +289,12 @@ export default class MessageComposer extends React.Component { if (this.props.showApps) { hideAppsButton =
- +
; } else { showAppsButton =
- +
; } } diff --git a/src/components/views/rooms/RoomHeader.js b/src/components/views/rooms/RoomHeader.js index edd89e4a35..499fdf21cc 100644 --- a/src/components/views/rooms/RoomHeader.js +++ b/src/components/views/rooms/RoomHeader.js @@ -29,6 +29,7 @@ import * as linkify from 'linkifyjs'; import linkifyElement from 'linkifyjs/element'; import linkifyMatrix from '../../../linkify-matrix'; import AccessibleButton from '../elements/AccessibleButton'; +import ManageIntegsButton from '../elements/ManageIntegsButton'; import {CancelButton} from './SimpleRoomHeader'; linkifyMatrix(linkify); @@ -47,6 +48,7 @@ module.exports = React.createClass({ onSaveClick: React.PropTypes.func, onSearchClick: React.PropTypes.func, onLeaveClick: React.PropTypes.func, + onCancelClick: React.PropTypes.func, }, getDefaultProps: function() { @@ -54,6 +56,7 @@ module.exports = React.createClass({ editing: false, inRoom: false, onSaveClick: function() {}, + onCancelClick: function() {}, }; }, @@ -320,10 +323,18 @@ module.exports = React.createClass({ } let rightRow; + let manageIntegsButton; + if(this.props.room && this.props.room.roomId) { + manageIntegsButton = ; + } + if (!this.props.editing) { rightRow =
{ settingsButton } + { manageIntegsButton } { forgetButton } { searchButton } { rightPanelButtons } diff --git a/src/components/views/rooms/RoomSettings.js b/src/components/views/rooms/RoomSettings.js index 85301ab54e..0fea50d2fa 100644 --- a/src/components/views/rooms/RoomSettings.js +++ b/src/components/views/rooms/RoomSettings.js @@ -24,8 +24,6 @@ import sdk from '../../../index'; import Modal from '../../../Modal'; import ObjectUtils from '../../../ObjectUtils'; import dis from '../../../dispatcher'; -import ScalarAuthClient from '../../../ScalarAuthClient'; -import ScalarMessaging from '../../../ScalarMessaging'; import UserSettingsStore from '../../../UserSettingsStore'; import AccessibleButton from '../elements/AccessibleButton'; @@ -92,7 +90,6 @@ module.exports = React.createClass({ propTypes: { room: React.PropTypes.object.isRequired, onSaveClick: React.PropTypes.func, - onCancelClick: React.PropTypes.func, }, getInitialState: function() { @@ -118,14 +115,10 @@ module.exports = React.createClass({ // Default to false if it's undefined, otherwise react complains about changing // components from uncontrolled to controlled isRoomPublished: this._originalIsRoomPublished || false, - scalar_error: null, - showIntegrationsError: false, }; }, componentWillMount: function() { - ScalarMessaging.startListening(); - MatrixClientPeg.get().on("RoomMember.membership", this._onRoomMemberMembership); MatrixClientPeg.get().getRoomDirectoryVisibility( @@ -137,18 +130,6 @@ module.exports = React.createClass({ console.error("Failed to get room visibility: " + err); }); - this.scalarClient = null; - if (SdkConfig.get().integrations_ui_url && SdkConfig.get().integrations_rest_url) { - this.scalarClient = new ScalarAuthClient(); - this.scalarClient.connect().done(() => { - this.forceUpdate(); - }, (err) => { - this.setState({ - scalar_error: err - }); - }); - } - dis.dispatch({ action: 'ui_opacity', sideOpacity: 0.3, @@ -157,8 +138,6 @@ module.exports = React.createClass({ }, componentWillUnmount: function() { - ScalarMessaging.stopListening(); - const cli = MatrixClientPeg.get(); if (cli) { cli.removeListener("RoomMember.membership", this._onRoomMemberMembership); @@ -513,28 +492,6 @@ module.exports = React.createClass({ roomState.mayClientSendStateEvent("m.room.guest_access", cli)); }, - onManageIntegrations(ev) { - ev.preventDefault(); - var IntegrationsManager = sdk.getComponent("views.settings.IntegrationsManager"); - Modal.createTrackedDialog('Integrations Manager', 'onManageIntegrations', IntegrationsManager, { - src: (this.scalarClient !== null && this.scalarClient.hasCredentials()) ? - this.scalarClient.getScalarInterfaceUrlForRoom(this.props.room.roomId) : - null, - onFinished: ()=>{ - if (this._calcSavePromises().length === 0) { - this.props.onCancelClick(ev); - } - }, - }, "mx_IntegrationsManager"); - }, - - onShowIntegrationsError(ev) { - ev.preventDefault(); - this.setState({ - showIntegrationsError: !this.state.showIntegrationsError, - }); - }, - onLeaveClick() { dis.dispatch({ action: 'leave_room', @@ -796,46 +753,10 @@ module.exports = React.createClass({
; } - let integrationsButton; - let integrationsError; - - if (this.scalarClient !== null) { - if (this.state.showIntegrationsError && this.state.scalar_error) { - console.error(this.state.scalar_error); - integrationsError = ( - - { _t('Could not connect to the integration server') } - - ); - } - - if (this.scalarClient.hasCredentials()) { - integrationsButton = ( -
- { _t('Manage Integrations') } -
- ); - } else if (this.state.scalar_error) { - integrationsButton = ( -
- Integrations Error - { integrationsError } -
- ); - } else { - integrationsButton = ( -
- { _t('Manage Integrations') } -
- ); - } - } - return (
{ leaveButton } - { integrationsButton } { tagsSection } diff --git a/src/i18n/strings/en_EN.json b/src/i18n/strings/en_EN.json index d175984e50..aa4f71fcb3 100644 --- a/src/i18n/strings/en_EN.json +++ b/src/i18n/strings/en_EN.json @@ -190,6 +190,7 @@ "Can't connect to homeserver - please check your connectivity, ensure your homeserver's SSL certificate is trusted, and that a browser extension is not blocking requests.": "Can't connect to homeserver - please check your connectivity, ensure your homeserver's SSL certificate is trusted, and that a browser extension is not blocking requests.", "Can't connect to homeserver via HTTP when an HTTPS URL is in your browser bar. Either use HTTPS or enable unsafe scripts.": "Can't connect to homeserver via HTTP when an HTTPS URL is in your browser bar. Either use HTTPS or enable unsafe scripts.", "Can't load user settings": "Can't load user settings", + "Cannot add any more widgets": "Cannot add any more widgets", "Change Password": "Change Password", "%(senderName)s changed their display name from %(oldDisplayName)s to %(displayName)s.": "%(senderName)s changed their display name from %(oldDisplayName)s to %(displayName)s.", "%(senderName)s changed their profile picture.": "%(senderName)s changed their profile picture.", @@ -547,6 +548,7 @@ "Tagged as: ": "Tagged as: ", "The default role for new room members is": "The default role for new room members is", "The main address for this room is": "The main address for this room is", + "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 phone number entered looks invalid": "The phone number entered looks invalid", "The signing key you provided matches the signing key you received from %(userId)s's device %(deviceId)s. Device marked as verified.": "The signing key you provided matches the signing key you received from %(userId)s's device %(deviceId)s. Device marked as verified.", "This action cannot be performed by a guest user. Please register to be able to do this.": "This action cannot be performed by a guest user. Please register to be able to do this.",