Merge pull request #332 from vector-im/kegan/syncing

Implement connection lost bar + resend all
This commit is contained in:
Kegsay 2015-11-09 15:35:38 +00:00
commit c3385d597a
7 changed files with 132 additions and 19 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,6 +43,8 @@ module.exports = {
draggingFile: false, draggingFile: false,
searching: false, searching: false,
searchResults: null, searchResults: null,
syncState: MatrixClientPeg.get().getSyncState(),
hasUnsentMessages: this._hasUnsentMessages(room)
} }
}, },
@ -50,6 +54,7 @@ module.exports = {
MatrixClientPeg.get().on("Room.name", this.onRoomName); MatrixClientPeg.get().on("Room.name", this.onRoomName);
MatrixClientPeg.get().on("RoomMember.typing", this.onRoomMemberTyping); MatrixClientPeg.get().on("RoomMember.typing", this.onRoomMemberTyping);
MatrixClientPeg.get().on("RoomState.members", this.onRoomStateMember); MatrixClientPeg.get().on("RoomState.members", this.onRoomStateMember);
MatrixClientPeg.get().on("sync", this.onSyncStateChange);
this.atBottom = true; this.atBottom = true;
}, },
@ -67,6 +72,7 @@ module.exports = {
MatrixClientPeg.get().removeListener("Room.name", this.onRoomName); MatrixClientPeg.get().removeListener("Room.name", this.onRoomName);
MatrixClientPeg.get().removeListener("RoomMember.typing", this.onRoomMemberTyping); MatrixClientPeg.get().removeListener("RoomMember.typing", this.onRoomMemberTyping);
MatrixClientPeg.get().removeListener("RoomState.members", this.onRoomStateMember); MatrixClientPeg.get().removeListener("RoomState.members", this.onRoomStateMember);
MatrixClientPeg.get().removeListener("sync", this.onSyncStateChange);
} }
}, },
@ -74,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)
@ -102,6 +111,12 @@ module.exports = {
} }
}, },
onSyncStateChange: function(state) {
this.setState({
syncState: state
});
},
// MatrixRoom still showing the messages from the old room? // MatrixRoom still showing the messages from the old room?
// Set the key to the room_id. Sadly you can no longer get at // Set the key to the room_id. Sadly you can no longer get at
// the key from inside the component, or we'd check this in code. // the key from inside the component, or we'd check this in code.
@ -173,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;
@ -265,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

@ -78,7 +78,7 @@ limitations under the License.
} }
.mx_EventTile_notSent { .mx_EventTile_notSent {
color: #f11; color: #ddd;
} }
.mx_EventTile_highlight { .mx_EventTile_highlight {

View File

@ -158,13 +158,14 @@ limitations under the License.
order: 4; order: 4;
width: 100%; width: 100%;
-webkit-flex: 0 0 36px; -webkit-flex: 0 0 auto;
flex: 0 0 36px; flex: 0 0 auto;
} }
.mx_RoomView_statusAreaBox { .mx_RoomView_statusAreaBox {
max-width: 960px; max-width: 960px;
margin: auto; margin: auto;
min-height: 36px;
} }
.mx_RoomView_statusAreaBox_line { .mx_RoomView_statusAreaBox_line {
@ -185,6 +186,34 @@ limitations under the License.
vertical-align: middle; vertical-align: middle;
} }
.mx_RoomView_connectionLostBar {
margin-top: 19px;
height: 58px;
}
.mx_RoomView_connectionLostBar img {
padding-left: 10px;
padding-right: 22px;
vertical-align: middle;
float: left;
}
.mx_RoomView_connectionLostBar_title {
color: #ff0064;
}
.mx_RoomView_connectionLostBar_desc {
color: #454545;
font-size: 14px;
opacity: 0.5;
}
.mx_RoomView_resend_link {
color: #454545 ! important;
text-decoration: underline ! important;
cursor: pointer;
}
.mx_RoomView_typingBar { .mx_RoomView_typingBar {
margin-top: 10px; margin-top: 10px;
margin-left: 54px; margin-left: 54px;

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

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

@ -197,9 +197,46 @@ module.exports = React.createClass({
} else { } else {
var typingString = this.getWhoIsTypingString(); var typingString = this.getWhoIsTypingString();
var unreadMsgs = this.getUnreadMessagesString(); 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 = (
<div className="mx_RoomView_connectionLostBar">
<img src="img/warning2.png" width="30" height="30" alt="/!\"/>
<div className="mx_RoomView_connectionLostBar_textArea">
<div className="mx_RoomView_connectionLostBar_title">
Connectivity to the server has been lost.
</div>
<div className="mx_RoomView_connectionLostBar_desc">
Sent messages will be stored until your connection has returned.
</div>
</div>
</div>
);
}
else if (this.state.hasUnsentMessages) {
statusBar = (
<div className="mx_RoomView_connectionLostBar">
<img src="img/warning2.png" width="30" height="30" alt="/!\"/>
<div className="mx_RoomView_connectionLostBar_textArea">
<div className="mx_RoomView_connectionLostBar_title">
Some of your messages have not been sent.
</div>
<div className="mx_RoomView_connectionLostBar_desc">
<a className="mx_RoomView_resend_link"
onClick={ this.onResendAllClick }>
Resend all now
</a> 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
if (unreadMsgs) { else if (unreadMsgs) {
statusBar = ( statusBar = (
<div className="mx_RoomView_unreadMessagesBar" onClick={ this.scrollToBottom }> <div className="mx_RoomView_unreadMessagesBar" onClick={ this.scrollToBottom }>
<img src="img/newmessages.png" width="24" height="24" alt=""/> <img src="img/newmessages.png" width="24" height="24" alt=""/>