mirror of
https://github.com/SchildiChat/element-web.git
synced 2024-10-01 01:26:12 -04:00
Merge pull request #332 from vector-im/kegan/syncing
Implement connection lost bar + resend all
This commit is contained in:
commit
c3385d597a
24
src/Resend.js
Normal file
24
src/Resend.js
Normal 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
|
||||||
|
});
|
||||||
|
},
|
||||||
|
};
|
@ -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() {
|
||||||
|
@ -78,7 +78,7 @@ limitations under the License.
|
|||||||
}
|
}
|
||||||
|
|
||||||
.mx_EventTile_notSent {
|
.mx_EventTile_notSent {
|
||||||
color: #f11;
|
color: #ddd;
|
||||||
}
|
}
|
||||||
|
|
||||||
.mx_EventTile_highlight {
|
.mx_EventTile_highlight {
|
||||||
|
@ -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;
|
||||||
|
BIN
src/skins/vector/img/warning2.png
Normal file
BIN
src/skins/vector/img/warning2.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.4 KiB |
@ -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();
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -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=""/>
|
||||||
|
Loading…
Reference in New Issue
Block a user