Add resending bar (and resend all option)

Factor out resend logic which was in the context menu into a separate
Resend file (it shouldn't be in the skin, but it also isn't really
suitable for a controller given 2 different views invoke it..)
pull/332/head
Kegan Dougal 2015-11-05 15:59:03 +00:00
parent 804af341ac
commit 3a8c263e8e
5 changed files with 78 additions and 16 deletions

24
src/Resend.js Normal file
View File

@ -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
});
},
};

View File

@ -24,6 +24,7 @@ var Modal = require("matrix-react-sdk/lib/Modal");
var sdk = require('matrix-react-sdk/lib/index'); var sdk = require('matrix-react-sdk/lib/index');
var CallHandler = require('matrix-react-sdk/lib/CallHandler'); var CallHandler = require('matrix-react-sdk/lib/CallHandler');
var VectorConferenceHandler = require('../../modules/VectorConferenceHandler'); var VectorConferenceHandler = require('../../modules/VectorConferenceHandler');
var Resend = require("../../Resend");
var dis = require("matrix-react-sdk/lib/dispatcher"); var dis = require("matrix-react-sdk/lib/dispatcher");
@ -32,8 +33,9 @@ var INITIAL_SIZE = 20;
module.exports = { module.exports = {
getInitialState: function() { getInitialState: function() {
var room = this.props.roomId ? MatrixClientPeg.get().getRoom(this.props.roomId) : null;
return { return {
room: this.props.roomId ? MatrixClientPeg.get().getRoom(this.props.roomId) : null, room: room,
messageCap: INITIAL_SIZE, messageCap: INITIAL_SIZE,
editingRoomSettings: false, editingRoomSettings: false,
uploadingRoomSettings: false, uploadingRoomSettings: false,
@ -41,7 +43,8 @@ module.exports = {
draggingFile: false, draggingFile: false,
searching: false, searching: false,
searchResults: null, searchResults: null,
syncState: MatrixClientPeg.get().getSyncState() syncState: MatrixClientPeg.get().getSyncState(),
hasUnsentMessages: this._hasUnsentMessages(room)
} }
}, },
@ -77,6 +80,9 @@ module.exports = {
switch (payload.action) { switch (payload.action) {
case 'message_send_failed': case 'message_send_failed':
case 'message_sent': case 'message_sent':
this.setState({
hasUnsentMessages: this._hasUnsentMessages(this.state.room)
});
case 'message_resend_started': case 'message_resend_started':
this.setState({ this.setState({
room: MatrixClientPeg.get().getRoom(this.props.roomId) room: MatrixClientPeg.get().getRoom(this.props.roomId)
@ -182,6 +188,19 @@ module.exports = {
this._updateConfCallNotification(); 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() { _updateConfCallNotification: function() {
var room = MatrixClientPeg.get().getRoom(this.props.roomId); var room = MatrixClientPeg.get().getRoom(this.props.roomId);
if (!room) return; if (!room) return;
@ -274,6 +293,13 @@ module.exports = {
return false; return false;
}, },
onResendAllClick: function() {
var eventsToResend = this._getUnsentMessages(this.state.room);
eventsToResend.forEach(function(event) {
Resend.resend(event);
});
},
onJoinButtonClicked: function(ev) { onJoinButtonClicked: function(ev) {
var self = this; var self = this;
MatrixClientPeg.get().joinRoom(this.props.roomId).then(function() { MatrixClientPeg.get().joinRoom(this.props.roomId).then(function() {

View File

@ -209,6 +209,10 @@ limitations under the License.
font-size: 12px; font-size: 12px;
} }
.mx_RoomView_resend_link {
cursor: pointer;
}
.mx_RoomView_typingBar { .mx_RoomView_typingBar {
margin-top: 10px; margin-top: 10px;
margin-left: 54px; margin-left: 54px;

View File

@ -22,25 +22,13 @@ var MatrixClientPeg = require('matrix-react-sdk/lib/MatrixClientPeg');
var dis = require('matrix-react-sdk/lib/dispatcher'); var dis = require('matrix-react-sdk/lib/dispatcher');
var sdk = require('matrix-react-sdk') var sdk = require('matrix-react-sdk')
var Modal = require('matrix-react-sdk/lib/Modal'); var Modal = require('matrix-react-sdk/lib/Modal');
var Resend = require("../../../../Resend");
module.exports = React.createClass({ module.exports = React.createClass({
displayName: 'MessageContextMenu', displayName: 'MessageContextMenu',
onResendClick: function() { onResendClick: function() {
MatrixClientPeg.get().resendEvent( Resend.resend(this.props.mxEvent);
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'});
if (this.props.onFinished) this.props.onFinished(); if (this.props.onFinished) this.props.onFinished();
}, },

View File

@ -199,6 +199,8 @@ module.exports = React.createClass({
var unreadMsgs = this.getUnreadMessagesString(); var unreadMsgs = this.getUnreadMessagesString();
// no conn bar trumps unread count since you can't get unread messages // no conn bar trumps unread count since you can't get unread messages
// without a connection! (technically may already have some but meh) // 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") { if (this.state.syncState === "ERROR") {
statusBar = ( statusBar = (
<div className="mx_RoomView_connectionLostBar"> <div className="mx_RoomView_connectionLostBar">
@ -214,6 +216,24 @@ module.exports = React.createClass({
</div> </div>
); );
} }
else if (this.state.hasUnsentMessages) {
statusBar = (
<div className="mx_RoomView_connectionLostBar">
<img src="img/cancel.png" width="10" height="12" alt=""/>
<div className="mx_RoomView_connectionLostBar_textArea">
<span className="mx_RoomView_connectionLostBar_title">
Some of your messages have not been sent.
</span>
<div className="mx_RoomView_connectionLostBar_desc">
<span className="mx_RoomView_resend_link"
onClick={ this.onResendAllClick } >
Resend all now
</span> or select individual messages to re-send.
</div>
</div>
</div>
);
}
// unread count trumps who is typing since the unread count is only // unread count trumps who is typing since the unread count is only
// set when you've scrolled up // set when you've scrolled up
else if (unreadMsgs) { else if (unreadMsgs) {