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 (
+
+ );
+ }
+
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.",