diff --git a/src/components/structures/RoomStatusBar.js b/src/components/structures/RoomStatusBar.js index 3a2ab33db8..cad55351d1 100644 --- a/src/components/structures/RoomStatusBar.js +++ b/src/components/structures/RoomStatusBar.js @@ -43,6 +43,10 @@ module.exports = React.createClass({ // the end of the live timeline. atEndOfLiveTimeline: React.PropTypes.bool, + // This is true when the user is alone in the room, but has also sent a message. + // Used to suggest to the user to invite someone + sentMessageAndIsAlone: React.PropTypes.bool, + // true if there is an active call in this room (means we show // the 'Active Call' text in the status bar if there is nothing // more interesting) @@ -60,6 +64,14 @@ module.exports = React.createClass({ // 'unsent messages' bar onCancelAllClick: React.PropTypes.func, + // callback for when the user clicks on the 'invite others' button in the + // 'you are alone' bar + onInviteClick: React.PropTypes.func, + + // callback for when the user clicks on the 'stop warning me' button in the + // 'you are alone' bar + onStopWarningClick: React.PropTypes.func, + // callback for when the user clicks on the 'scroll to bottom' button onScrollToBottomClick: React.PropTypes.func, @@ -140,7 +152,8 @@ module.exports = React.createClass({ (this.state.usersTyping.length > 0) || this.props.numUnreadMessages || !this.props.atEndOfLiveTimeline || - this.props.hasActiveCall + this.props.hasActiveCall || + this.props.sentMessageAndIsAlone ) { return STATUS_BAR_EXPANDED; } else if (this.props.unsentMessageError) { @@ -305,6 +318,21 @@ module.exports = React.createClass({ ); } + // If you're alone in the room, and have sent a message, suggest to invite someone + if (this.props.sentMessageAndIsAlone) { + return ( +
+ { _tJsx("There's no one else here! Would you like to invite others or stop warning about the empty room?", + [/(.*?)<\/a>/, /(.*?)<\/a>/], + [ + (sub) => { sub }, + (sub) => { sub }, + ], + ) } +
+ ); + } + return null; }, diff --git a/src/components/structures/RoomView.js b/src/components/structures/RoomView.js index 3d3537e067..db40380636 100644 --- a/src/components/structures/RoomView.js +++ b/src/components/structures/RoomView.js @@ -117,6 +117,7 @@ module.exports = React.createClass({ guestsCanJoin: false, canPeek: false, showApps: false, + isAlone: false, isPeeking: false, // error object, as from the matrix client/server API @@ -461,6 +462,8 @@ module.exports = React.createClass({ switch (payload.action) { case 'message_send_failed': case 'message_sent': + this._checkIfAlone(this.state.room); + // no break; to intentionally fall through case 'message_send_cancelled': this.setState({ unsentMessageError: this._getUnsentMessageError(this.state.room), @@ -740,6 +743,20 @@ module.exports = React.createClass({ } }, 500), + _checkIfAlone: function(room) { + let warnedAboutLonelyRoom = false; + if (localStorage) { + warnedAboutLonelyRoom = localStorage.getItem('mx_user_alone_warned_' + this.state.room.roomId); + } + if (warnedAboutLonelyRoom) { + if (this.state.isAlone) this.setState({isAlone: false}); + return; + } + + const joinedMembers = room.currentState.getMembers().filter(m => m.membership === "join" || m.membership === "invite"); + this.setState({isAlone: joinedMembers.length === 1}); + }, + _getUnsentMessageError: function(room) { const unsentMessages = this._getUnsentMessages(room); if (!unsentMessages.length) return ""; @@ -821,6 +838,22 @@ module.exports = React.createClass({ Resend.cancelUnsentEvents(this.state.room); }, + onInviteButtonClick: function() { + // call AddressPickerDialog + dis.dispatch({ + action: 'view_invite', + roomId: this.state.room.roomId, + }); + this.setState({isAlone: false}); // there's a good chance they'll invite someone + }, + + onStopAloneWarningClick: function() { + if (localStorage) { + localStorage.setItem('mx_user_alone_warned_' + this.state.room.roomId, true); + } + this.setState({isAlone: false}); + }, + onJoinButtonClicked: function(ev) { const cli = MatrixClientPeg.get(); @@ -1581,9 +1614,12 @@ module.exports = React.createClass({ numUnreadMessages={this.state.numUnreadMessages} unsentMessageError={this.state.unsentMessageError} atEndOfLiveTimeline={this.state.atEndOfLiveTimeline} + sentMessageAndIsAlone={this.state.isAlone} hasActiveCall={inCall} onResendAllClick={this.onResendAllClick} onCancelAllClick={this.onCancelAllClick} + onInviteClick={this.onInviteButtonClick} + onStopWarningClick={this.onStopAloneWarningClick} onScrollToBottomClick={this.jumpToLiveTimeline} onResize={this.onChildResize} onVisible={this.onStatusBarVisible} diff --git a/src/i18n/strings/en_EN.json b/src/i18n/strings/en_EN.json index a167381152..c8c4b8f14d 100644 --- a/src/i18n/strings/en_EN.json +++ b/src/i18n/strings/en_EN.json @@ -610,6 +610,7 @@ "Room": "Room", "Copied!": "Copied!", "Failed to copy": "Failed to copy", + "There's no one else here! Would you like to invite others or stop warning about the empty room?": "There's no one else here! Would you like to invite others or stop warning about the empty room?", "Connectivity to the server has been lost.": "Connectivity to the server has been lost.", "Sent messages will be stored until your connection has returned.": "Sent messages will be stored until your connection has returned.", "Resend all or cancel all now. You can also select individual messages to resend or cancel.": "Resend all or cancel all now. You can also select individual messages to resend or cancel.",