diff --git a/src/Resend.js b/src/Resend.js new file mode 100644 index 0000000000..52b7c93654 --- /dev/null +++ b/src/Resend.js @@ -0,0 +1,24 @@ +var MatrixClientPeg = require('matrix-react-sdk/lib/MatrixClientPeg'); +var dis = require('matrix-react-sdk/lib/dispatcher'); + +module.exports = { + resend: function(event) { + MatrixClientPeg.get().resendEvent( + event, MatrixClientPeg.get().getRoom(event.getRoomId()) + ).done(function() { + dis.dispatch({ + action: 'message_sent', + event: event + }); + }, function() { + dis.dispatch({ + action: 'message_send_failed', + event: event + }); + }); + dis.dispatch({ + action: 'message_resend_started', + event: event + }); + }, +}; \ No newline at end of file diff --git a/src/controllers/organisms/RoomView.js b/src/controllers/organisms/RoomView.js index 15d67b1555..1324e21ffd 100644 --- a/src/controllers/organisms/RoomView.js +++ b/src/controllers/organisms/RoomView.js @@ -24,6 +24,7 @@ var Modal = require("matrix-react-sdk/lib/Modal"); var sdk = require('matrix-react-sdk/lib/index'); var CallHandler = require('matrix-react-sdk/lib/CallHandler'); var VectorConferenceHandler = require('../../modules/VectorConferenceHandler'); +var Resend = require("../../Resend"); var dis = require("matrix-react-sdk/lib/dispatcher"); @@ -32,8 +33,9 @@ var INITIAL_SIZE = 20; module.exports = { getInitialState: function() { + var room = this.props.roomId ? MatrixClientPeg.get().getRoom(this.props.roomId) : null; return { - room: this.props.roomId ? MatrixClientPeg.get().getRoom(this.props.roomId) : null, + room: room, messageCap: INITIAL_SIZE, editingRoomSettings: false, uploadingRoomSettings: false, @@ -41,7 +43,8 @@ module.exports = { draggingFile: false, searching: false, searchResults: null, - syncState: MatrixClientPeg.get().getSyncState() + syncState: MatrixClientPeg.get().getSyncState(), + hasUnsentMessages: this._hasUnsentMessages(room) } }, @@ -77,6 +80,9 @@ module.exports = { switch (payload.action) { case 'message_send_failed': case 'message_sent': + this.setState({ + hasUnsentMessages: this._hasUnsentMessages(this.state.room) + }); case 'message_resend_started': this.setState({ room: MatrixClientPeg.get().getRoom(this.props.roomId) @@ -182,6 +188,19 @@ module.exports = { this._updateConfCallNotification(); }, + _hasUnsentMessages: function(room) { + return this._getUnsentMessages(room).length > 0; + }, + + _getUnsentMessages: function(room) { + if (!room) { return []; } + // TODO: It would be nice if the JS SDK provided nicer constant-time + // constructs rather than O(N) (N=num msgs) on this. + return room.timeline.filter(function(ev) { + return ev.status === Matrix.EventStatus.NOT_SENT; + }); + }, + _updateConfCallNotification: function() { var room = MatrixClientPeg.get().getRoom(this.props.roomId); if (!room) return; @@ -274,6 +293,13 @@ module.exports = { return false; }, + onResendAllClick: function() { + var eventsToResend = this._getUnsentMessages(this.state.room); + eventsToResend.forEach(function(event) { + Resend.resend(event); + }); + }, + onJoinButtonClicked: function(ev) { var self = this; MatrixClientPeg.get().joinRoom(this.props.roomId).then(function() { diff --git a/src/skins/vector/css/organisms/RoomView.css b/src/skins/vector/css/organisms/RoomView.css index 961a79453a..0379a2aaef 100644 --- a/src/skins/vector/css/organisms/RoomView.css +++ b/src/skins/vector/css/organisms/RoomView.css @@ -209,6 +209,10 @@ limitations under the License. font-size: 12px; } +.mx_RoomView_resend_link { + cursor: pointer; +} + .mx_RoomView_typingBar { margin-top: 10px; margin-left: 54px; diff --git a/src/skins/vector/views/molecules/MessageContextMenu.js b/src/skins/vector/views/molecules/MessageContextMenu.js index 995c2c4b51..b36d4ccbbf 100644 --- a/src/skins/vector/views/molecules/MessageContextMenu.js +++ b/src/skins/vector/views/molecules/MessageContextMenu.js @@ -22,25 +22,13 @@ var MatrixClientPeg = require('matrix-react-sdk/lib/MatrixClientPeg'); var dis = require('matrix-react-sdk/lib/dispatcher'); var sdk = require('matrix-react-sdk') var Modal = require('matrix-react-sdk/lib/Modal'); +var Resend = require("../../../../Resend"); module.exports = React.createClass({ displayName: 'MessageContextMenu', onResendClick: function() { - MatrixClientPeg.get().resendEvent( - this.props.mxEvent, MatrixClientPeg.get().getRoom( - this.props.mxEvent.getRoomId() - ) - ).done(function() { - dis.dispatch({ - action: 'message_sent' - }); - }, function() { - dis.dispatch({ - action: 'message_send_failed' - }); - }); - dis.dispatch({action: 'message_resend_started'}); + Resend.resend(this.props.mxEvent); if (this.props.onFinished) this.props.onFinished(); }, diff --git a/src/skins/vector/views/organisms/RoomView.js b/src/skins/vector/views/organisms/RoomView.js index 86b200cf25..1eda7b7ffd 100644 --- a/src/skins/vector/views/organisms/RoomView.js +++ b/src/skins/vector/views/organisms/RoomView.js @@ -199,6 +199,8 @@ module.exports = React.createClass({ var unreadMsgs = this.getUnreadMessagesString(); // no conn bar trumps unread count since you can't get unread messages // without a connection! (technically may already have some but meh) + // It also trumps the "some not sent" msg since you can't resend without + // a connection! if (this.state.syncState === "ERROR") { statusBar = (