diff --git a/src/assets/css/chat.scss b/src/assets/css/chat.scss
index 1edd287..0150e87 100644
--- a/src/assets/css/chat.scss
+++ b/src/assets/css/chat.scss
@@ -109,6 +109,7 @@ $admin-fg: white;
}
.input-area-outer {
+ position: relative;
background-color: #ffffff;
margin: 0;
padding-left: 2 * $chat-standard-padding-s;
@@ -149,6 +150,12 @@ $admin-fg: white;
}
}
+ .scroll-to-end {
+ position:absolute;
+ top:-64px;
+ right:16px;
+ }
+
.op-button {
position: relative;
display: inline-block;
diff --git a/src/components/Chat.vue b/src/components/Chat.vue
index 868a7d3..82d564d 100644
--- a/src/components/Chat.vue
+++ b/src/components/Chat.vue
@@ -9,19 +9,19 @@
@click.prevent="closeContextMenuIfOpen"
>
-
-
+
+
-
@@ -76,8 +87,23 @@
+
+
+ arrow_downward
+
+
- REPLYING TO EVENT: {{ replyToEvent.getContent().body }}
+
+ REPLYING TO EVENT: {{ replyToEvent.getContent().body }}
+
@@ -87,7 +113,13 @@
-
-
+
+
cancel
-
- {{ editedEvent ? 'save' : 'arrow_upward' }}
+
+ {{
+ editedEvent ? "save" : "arrow_upward"
+ }}
@@ -169,19 +223,21 @@
-
-
- You are logged in as a guest
-
- Unfortunately guests are not allowed to upload files.
-
-
-
-
- Ok
-
-
-
+
+
+ You are logged in as a guest
+
+ Unfortunately guests are not allowed to upload files.
+
+
+
+
+ Ok
+
+
+
@@ -281,6 +337,12 @@ export default {
*/
chatContainerSize: 0,
+ /**
+ * True if we should show the "scroll to end" marker in the chat. For now at least, we use a simple
+ * method here, basically just "if we can scroll, show it".
+ */
+ showScrollToEnd: false,
+
/** Shows a dialog with info about an operation being disallowed for guests */
showNotAllowedForGuests: false,
@@ -333,17 +395,24 @@ export default {
// If we have sent a RR, use that as read marker (so we don't have to wait for server round trip)
return this.lastRR.getId();
}
- return this.fullyReadMarker || this.room.getEventReadUpTo(this.$matrix.currentUserId, false);
+ return (
+ this.fullyReadMarker ||
+ this.room.getEventReadUpTo(this.$matrix.currentUserId, false)
+ );
},
fullyReadMarker() {
- const readEvent = this.room.getAccountData('m.fully_read');
+ const readEvent = this.room.getAccountData("m.fully_read");
if (readEvent) {
return readEvent.getContent().event_id;
}
return null;
},
attachButtonDisabled() {
- return this.editedEvent != null || this.replyToEvent != null || this.currentInput.length > 0;
+ return (
+ this.editedEvent != null ||
+ this.replyToEvent != null ||
+ this.currentInput.length > 0
+ );
},
sendButtonDisabled() {
return this.currentInput.length == 0;
@@ -373,8 +442,7 @@ export default {
}
}
return "top:" + top + "px;left:" + left + "px";
- }
-
+ },
},
watch: {
@@ -384,7 +452,9 @@ export default {
if (value && value == oldValue) {
return; // No change.
}
- console.log("Chat: Current room changed to " + (value ? value : "null"));
+ console.log(
+ "Chat: Current room changed to " + (value ? value : "null")
+ );
// Clear old events
this.events = [];
@@ -398,76 +468,84 @@ export default {
if (!this.room) {
// Public room?
- if (this.roomId && this.roomId.startsWith('#')) {
+ if (this.roomId && this.roomId.startsWith("#")) {
this.onRoomNotJoined();
}
return; // no room
}
- // Joined?
- if (this.room.hasMembershipState(this.currentUser.user_id, "join")) {
- // Yes, load everything
- this.onRoomJoined();
- } else {
- this.onRoomNotJoined();
- }
- }
+ // Joined?
+ if (this.room.hasMembershipState(this.currentUser.user_id, "join")) {
+ // Yes, load everything
+ this.onRoomJoined();
+ } else {
+ this.onRoomNotJoined();
+ }
+ },
},
},
methods: {
onRoomJoined() {
-
var initialEventId = this.readMarker;
console.log("Read up to " + initialEventId);
//initialEventId = null;
-
+
this.timelineWindow = new TimelineWindow(
- this.$matrix.matrixClient,
- this.room.getUnfilteredTimelineSet(),
- {}
+ this.$matrix.matrixClient,
+ this.room.getUnfilteredTimelineSet(),
+ {}
);
const self = this;
this.timelineWindow.load(initialEventId, 20).then(() => {
console.log("This is", self);
- self.events = self.timelineWindow.getEvents();
+ self.events = self.timelineWindow.getEvents();
- const getMoreIfNeeded = function _getMoreIfNeeded() {
- const container = self.$refs.chatContainer;
- if (container.scrollHeight <= container.clientHeight &&
- self.timelineWindow &&
- self.timelineWindow.canPaginate(EventTimeline.BACKWARDS)) {
- return self.timelineWindow.paginate(EventTimeline.BACKWARDS, 10, true)
- .then(success => {
- if (success) {
- self.events = self.timelineWindow.getEvents();
- return _getMoreIfNeeded.call(self);
- } else {
- return Promise.reject("Failed to paginate");
- }
- });
- } else {
- return Promise.resolve("Done");
- }
- }.bind(self);
+ const getMoreIfNeeded = function _getMoreIfNeeded() {
+ const container = self.$refs.chatContainer;
+ if (
+ container.scrollHeight <= container.clientHeight &&
+ self.timelineWindow &&
+ self.timelineWindow.canPaginate(EventTimeline.BACKWARDS)
+ ) {
+ return self.timelineWindow
+ .paginate(EventTimeline.BACKWARDS, 10, true)
+ .then((success) => {
+ if (success) {
+ self.events = self.timelineWindow.getEvents();
+ return _getMoreIfNeeded.call(self);
+ } else {
+ return Promise.reject("Failed to paginate");
+ }
+ });
+ } else {
+ return Promise.resolve("Done");
+ }
+ }.bind(self);
- getMoreIfNeeded()
- .catch(err => {
+ getMoreIfNeeded()
+ .catch((err) => {
console.log("ERROR " + err);
})
.finally(() => {
self.initialLoadDone = true;
- if (initialEventId) {
- self.scrollToEvent(initialEventId);
- }
- self.restartRRTimer();
+ if (initialEventId) {
+ self.scrollToEvent(initialEventId);
+ }
+ self.restartRRTimer();
});
- });
+ });
},
onRoomNotJoined() {
- this.$navigation.push({ name: "Join", params: { roomId: util.sanitizeRoomId(this.roomAliasOrId) }}, 0);
+ this.$navigation.push(
+ {
+ name: "Join",
+ params: { roomId: util.sanitizeRoomId(this.roomAliasOrId) },
+ },
+ 0
+ );
},
touchX(event) {
@@ -594,6 +672,10 @@ export default {
) {
this.handleScrolledToBottom(false);
}
+ this.showScrollToEnd =
+ container.scrollHeight - container.scrollTop.toFixed(0) >
+ container.clientHeight;
+
this.restartRRTimer();
},
onEvent(event) {
@@ -631,7 +713,7 @@ export default {
} else {
const index = this.typingMembers.indexOf(member);
if (index > -1) {
- this.typingMembers.splice(index, 1);
+ this.typingMembers.splice(index, 1);
}
}
console.log("Typing: ", this.typingMembers);
@@ -669,7 +751,7 @@ export default {
// this.showNotAllowedForGuests = true;
// return;
// }
- this.$refs.attachment.click()
+ this.$refs.attachment.click();
},
/**
@@ -776,8 +858,8 @@ export default {
},
/**
- * Scroll so that the given event is at the middle of the chat view (if more events) or else at the bottom.
- */
+ * Scroll so that the given event is at the middle of the chat view (if more events) or else at the bottom.
+ */
scrollToEvent(eventId) {
const container = this.$refs.chatContainer;
const ref = this.$refs[eventId];
@@ -825,13 +907,14 @@ export default {
},
redact(event) {
- this.$matrix.matrixClient.redactEvent(event.getRoomId(), event.getId())
- .then(() => {
- console.log("Message redacted");
- })
- .catch(err => {
- console.log("Redaction failed: ", err);
- })
+ this.$matrix.matrixClient
+ .redactEvent(event.getRoomId(), event.getId())
+ .then(() => {
+ console.log("Message redacted");
+ })
+ .catch((err) => {
+ console.log("Redaction failed: ", err);
+ });
},
download(event) {
@@ -906,10 +989,10 @@ export default {
this.rrTimer = null;
}
},
-
+
/**
- * Start/restart the timer to Read Receipts.
- */
+ * Start/restart the timer to Read Receipts.
+ */
restartRRTimer() {
this.stopRRTimer();
this.rrTimer = setInterval(this.rrTimerElapsed, READ_RECEIPT_TIMEOUT);
@@ -919,30 +1002,33 @@ export default {
const container = this.$refs.chatContainer;
const el = util.getLastVisibleElement(container);
if (el) {
- const eventId = el.getAttribute('eventId');
+ 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;
// Send read receipt
- this.$matrix.matrixClient.sendReadReceipt(event)
- .then(() => {
- this.$matrix.matrixClient.setRoomReadMarkers(this.room.roomId, eventId)
- })
- .then(() => {
- console.log("RR sent for event: " + eventId);
- this.lastRR = event;
- })
- .catch(err => {
- console.log("Failed to update read marker: ", err);
- })
- .finally(() => {
- this.restartRRTimer();
- });
+ this.$matrix.matrixClient
+ .sendReadReceipt(event)
+ .then(() => {
+ this.$matrix.matrixClient.setRoomReadMarkers(
+ this.room.roomId,
+ eventId
+ );
+ })
+ .then(() => {
+ console.log("RR sent for event: " + eventId);
+ this.lastRR = event;
+ })
+ .catch((err) => {
+ console.log("Failed to update read marker: ", err);
+ })
+ .finally(() => {
+ this.restartRRTimer();
+ });
}
}
}
@@ -959,7 +1045,7 @@ export default {
dayForEvent(event) {
return util.formatDay(event.getTs());
- }
+ },
},
};