diff --git a/src/components/Chat.vue b/src/components/Chat.vue
index f06302d..3563d7c 100644
--- a/src/components/Chat.vue
+++ b/src/components/Chat.vue
@@ -149,7 +149,7 @@
@@ -166,8 +166,9 @@
-
-
-
+
@@ -264,7 +269,12 @@
-
+
{
+ self.events = self.timelineWindow.getEvents();
if (success) {
- self.events = self.timelineWindow.getEvents();
return _getMoreIfNeeded.call(self);
} else {
return Promise.reject("Failed to paginate");
@@ -587,6 +599,7 @@ export default {
this.onRoomJoined(null);
} else {
// Error. Done loading.
+ this.events = this.timelineWindow.getEvents();
this.initialLoadDone = true;
}
})
@@ -700,6 +713,9 @@ export default {
case "m.room.avatar":
return RoomAvatarChanged;
+
+ case "m.room.history_visibility":
+ return RoomHistoryVisibility;
}
return DebugEvent;
},
@@ -1039,7 +1055,7 @@ export default {
/** Stop Read Receipt timer */
stopRRTimer() {
if (this.rrTimer) {
- clearInterval(this.rrTimer);
+ clearTimeout(this.rrTimer);
this.rrTimer = null;
}
},
@@ -1049,32 +1065,48 @@ export default {
*/
restartRRTimer() {
this.stopRRTimer();
- this.rrTimer = setInterval(this.rrTimerElapsed, READ_RECEIPT_TIMEOUT);
+ this.rrTimer = setTimeout(this.rrTimerElapsed, READ_RECEIPT_TIMEOUT);
},
rrTimerElapsed() {
- const container = this.$refs.chatContainer;
- const el = util.getLastVisibleElement(container);
- if (el) {
- const eventId = el.getAttribute("eventId");
- if (eventId && this.room) {
- const event = this.room.findEventById(eventId);
- if (event && (!this.lastRR || event.getTs() > this.lastRR.getTs())) {
- // Disable timer while we are sending
- clearInterval(this.rrTimer);
- this.rrTimer = null;
+ this.rrTimer = null;
- // Send read receipt
+ const container = this.$refs.chatContainer;
+ const elFirst = util.getFirstVisibleElement(container);
+ const elLast = util.getLastVisibleElement(container);
+ if (elFirst && elLast) {
+ const eventIdFirst = elFirst.getAttribute("eventId");
+ const eventIdLast = elLast.getAttribute("eventId");
+ if (eventIdLast && this.room) {
+ var event = this.room.findEventById(eventIdLast);
+ const index = this.events.indexOf(event);
+
+ // Walk backwards through visible events to the first one that is incoming
+ //
+ var lastTimestamp = 0;
+ if (this.lastRR) {
+ lastTimestamp = this.lastRR.getTs();
+ }
+
+ for (var i = index; i >= 0; i--) {
+ event = this.events[i];
+ if (event == this.lastRR || event.getTs() <= lastTimestamp) {
+ // Already sent this or too old...
+ break;
+ }
+ // Is it an incoming event?
+ if (event.getSender() !== this.$matrix.currentUserId) {
+ // Send read receipt
this.$matrix.matrixClient
.sendReadReceipt(event)
.then(() => {
this.$matrix.matrixClient.setRoomReadMarkers(
this.room.roomId,
- eventId
+ event.getId()
);
})
.then(() => {
- console.log("RR sent for event: " + eventId);
+ console.log("RR sent for event: " + event.getId());
this.lastRR = event;
})
.catch((err) => {
@@ -1083,9 +1115,17 @@ export default {
.finally(() => {
this.restartRRTimer();
});
+ return; // Bail out here
+ }
+
+ // Stop iterating at first visible
+ if (event.getId() == eventIdFirst) {
+ break;
+ }
}
}
}
+ this.restartRRTimer();
},
showDayMarkerBeforeEvent(event) {
diff --git a/src/components/messages/RoomHistoryVisibility.vue b/src/components/messages/RoomHistoryVisibility.vue
new file mode 100644
index 0000000..b3cfc26
--- /dev/null
+++ b/src/components/messages/RoomHistoryVisibility.vue
@@ -0,0 +1,34 @@
+
+
+
+ {{ stateEventDisplayName(event) }} made room history {{ history(event) }}
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/plugins/utils.js b/src/plugins/utils.js
index 5439ba4..65e9f61 100644
--- a/src/plugins/utils.js
+++ b/src/plugins/utils.js
@@ -348,9 +348,17 @@ class Util {
return null;
}
+ getFirstVisibleElement(parentNode) {
+ const y = parentNode.scrollTop;
+ return this.getElementAtY(parentNode, y);
+ }
+
getLastVisibleElement(parentNode) {
const y = parentNode.scrollTop + parentNode.clientHeight;
+ return this.getElementAtY(parentNode, y);
+ }
+ getElementAtY(parentNode, y) {
let start = 0;
let end = parentNode.children.length - 1;