|
|
|
@ -279,7 +279,6 @@ export default { |
|
|
|
if (oldValue) { |
|
|
|
this.$store.dispatch('cancelLookForNewMessages', { requestId: oldValue }) |
|
|
|
} |
|
|
|
this.$emit('update:is-chat-scrolled-to-bottom', true) |
|
|
|
this.handleStartGettingMessagesPreconditions() |
|
|
|
|
|
|
|
// Remove expired messages when joining a room |
|
|
|
@ -308,6 +307,9 @@ export default { |
|
|
|
} else { |
|
|
|
this.softUpdateByDateGroups(this.messagesGroupedByDateByAuthor, newGroups) |
|
|
|
} |
|
|
|
|
|
|
|
// scroll to bottom if needed |
|
|
|
this.scrollToBottom({ smooth: true }) |
|
|
|
}, |
|
|
|
}, |
|
|
|
}, |
|
|
|
@ -316,10 +318,7 @@ export default { |
|
|
|
this.debounceUpdateReadMarkerPosition = debounce(this.updateReadMarkerPosition, 1000) |
|
|
|
this.debounceHandleScroll = debounce(this.handleScroll, 50) |
|
|
|
|
|
|
|
this.scrollToBottom() |
|
|
|
EventBus.$on('scroll-chat-to-bottom', this.handleScrollChatToBottomEvent) |
|
|
|
EventBus.$on('smooth-scroll-chat-to-bottom', this.smoothScrollToBottom) |
|
|
|
EventBus.$on('scroll-chat-to-bottom-if-sticky', this.scrollToBottomIfSticky) |
|
|
|
EventBus.$on('scroll-chat-to-bottom', this.scrollToBottom) |
|
|
|
EventBus.$on('focus-message', this.focusMessage) |
|
|
|
EventBus.$on('route-change', this.onRouteChange) |
|
|
|
subscribe('networkOffline', this.handleNetworkOffline) |
|
|
|
@ -339,9 +338,7 @@ export default { |
|
|
|
this.debounceHandleScroll.clear?.() |
|
|
|
|
|
|
|
window.removeEventListener('focus', this.onWindowFocus) |
|
|
|
EventBus.$off('scroll-chat-to-bottom', this.handleScrollChatToBottomEvent) |
|
|
|
EventBus.$off('smooth-scroll-chat-to-bottom', this.smoothScrollToBottom) |
|
|
|
EventBus.$on('scroll-chat-to-bottom-if-sticky', this.scrollToBottomIfSticky) |
|
|
|
EventBus.$off('scroll-chat-to-bottom', this.scrollToBottom) |
|
|
|
EventBus.$off('focus-message', this.focusMessage) |
|
|
|
EventBus.$off('route-change', this.onRouteChange) |
|
|
|
|
|
|
|
@ -638,7 +635,7 @@ export default { |
|
|
|
if (!isFocused) { |
|
|
|
// if no anchor was present or the message to focus on did not exist, |
|
|
|
// scroll to bottom |
|
|
|
this.scrollToBottom() |
|
|
|
this.scrollToBottom({ force: true }) |
|
|
|
} |
|
|
|
|
|
|
|
// if no scrollbars, clear read marker directly as scrolling is not possible for the user to clear it |
|
|
|
@ -752,10 +749,7 @@ export default { |
|
|
|
return |
|
|
|
} |
|
|
|
|
|
|
|
const followInNewMessages = this.conversation.lastMessage |
|
|
|
&& this.conversation.lastReadMessage === this.conversation.lastMessage.id |
|
|
|
|
|
|
|
await this.getNewMessages(followInNewMessages) |
|
|
|
await this.getNewMessages() |
|
|
|
}, |
|
|
|
|
|
|
|
async getMessageContext(messageId) { |
|
|
|
@ -815,13 +809,11 @@ export default { |
|
|
|
/** |
|
|
|
* Creates a long polling request for a new message. |
|
|
|
* |
|
|
|
* @param {boolean} scrollToBottom Whether we should try to automatically scroll to the bottom |
|
|
|
*/ |
|
|
|
async getNewMessages(scrollToBottom = true) { |
|
|
|
async getNewMessages() { |
|
|
|
if (this.destroying) { |
|
|
|
return |
|
|
|
} |
|
|
|
|
|
|
|
// Make the request |
|
|
|
try { |
|
|
|
// TODO: move polling logic to the store and also cancel timers on cancel |
|
|
|
@ -831,11 +823,6 @@ export default { |
|
|
|
lastKnownMessageId: this.$store.getters.getLastKnownMessageId(this.token), |
|
|
|
requestId: this.chatIdentifier, |
|
|
|
}) |
|
|
|
|
|
|
|
// Scroll to the last message if sticky |
|
|
|
if (scrollToBottom && this.isSticky) { |
|
|
|
this.smoothScrollToBottom() |
|
|
|
} |
|
|
|
} catch (exception) { |
|
|
|
if (Axios.isCancel(exception)) { |
|
|
|
console.debug('The request has been canceled', exception) |
|
|
|
@ -1106,66 +1093,42 @@ export default { |
|
|
|
}, |
|
|
|
|
|
|
|
/** |
|
|
|
* @param {object} options Event options |
|
|
|
* @param {boolean} options.force Set to true, if the chat should be scrolled to the bottom even when it was not before |
|
|
|
*/ |
|
|
|
handleScrollChatToBottomEvent(options) { |
|
|
|
if ((options && options.force) || this.isChatScrolledToBottom) { |
|
|
|
this.scrollToBottom() |
|
|
|
} |
|
|
|
}, |
|
|
|
|
|
|
|
/** |
|
|
|
* Scrolls to the bottom of the list (to show reaction to the last message). |
|
|
|
*/ |
|
|
|
scrollToBottomIfSticky() { |
|
|
|
if (this.isSticky) { |
|
|
|
this.scrollToBottom() |
|
|
|
} |
|
|
|
}, |
|
|
|
|
|
|
|
/** |
|
|
|
* Scrolls to the bottom of the list smoothly. |
|
|
|
* Scrolls to the bottom of the list. |
|
|
|
* @param {object} options Options for scrolling |
|
|
|
* @param {boolean} [options.smooth] 'smooth' scrolling to the bottom ('auto' by default) |
|
|
|
* @param {boolean} [options.force] force scrolling to the bottom (otherwise check for current position) |
|
|
|
*/ |
|
|
|
smoothScrollToBottom() { |
|
|
|
scrollToBottom(options = {}) { |
|
|
|
this.$nextTick(() => { |
|
|
|
if (!this.$refs.scroller) { |
|
|
|
return |
|
|
|
} |
|
|
|
|
|
|
|
if (this.isWindowVisible && (document.hasFocus() || this.isInCall)) { |
|
|
|
// scrollTo is used when the user is watching |
|
|
|
this.$refs.scroller.scrollTo({ |
|
|
|
top: this.$refs.scroller.scrollHeight, |
|
|
|
behavior: 'smooth', |
|
|
|
}) |
|
|
|
let newTop |
|
|
|
if (options?.force) { |
|
|
|
newTop = this.$refs.scroller.scrollHeight |
|
|
|
this.setChatScrolledToBottom(true) |
|
|
|
} else { |
|
|
|
// Otherwise we jump half a message and stop autoscrolling, so the user can read up |
|
|
|
if (this.$refs.scroller.scrollHeight - this.$refs.scroller.scrollTop - this.$refs.scroller.offsetHeight < 40) { |
|
|
|
// Single new line from the previous author is 35px so scroll half a line |
|
|
|
this.$refs.scroller.scrollTop += 10 |
|
|
|
} else { |
|
|
|
// Single new line from the new author is 75px so scroll half an avatar |
|
|
|
this.$refs.scroller.scrollTop += 40 |
|
|
|
} |
|
|
|
this.setChatScrolledToBottom(false) |
|
|
|
} |
|
|
|
}) |
|
|
|
}, |
|
|
|
/** |
|
|
|
* Scrolls to the bottom of the list. |
|
|
|
*/ |
|
|
|
scrollToBottom() { |
|
|
|
this.$nextTick(() => { |
|
|
|
if (!this.$refs.scroller) { |
|
|
|
} else if (!this.isSticky) { |
|
|
|
// Reading old messages |
|
|
|
return |
|
|
|
} else if (!this.isWindowVisible) { |
|
|
|
const firstUnreadMessageHeight = this.$refs.scroller.scrollHeight - this.$refs.scroller.scrollTop - this.$refs.scroller.offsetHeight |
|
|
|
const scrollBy = firstUnreadMessageHeight < 40 ? 10 : 40 |
|
|
|
// We jump half a message and stop autoscrolling, so the user can read up |
|
|
|
// Single new line from the previous author is 35px so scroll half a line (10px) |
|
|
|
// Single new line from the new author is 75px so scroll half an avatar (40px) |
|
|
|
newTop = this.$refs.scroller.scrollTop + scrollBy |
|
|
|
this.setChatScrolledToBottom(false) |
|
|
|
} else { |
|
|
|
newTop = this.$refs.scroller.scrollHeight |
|
|
|
this.setChatScrolledToBottom(true) |
|
|
|
} |
|
|
|
|
|
|
|
this.$refs.scroller.scrollTop = this.$refs.scroller.scrollHeight |
|
|
|
this.setChatScrolledToBottom(true) |
|
|
|
this.$refs.scroller.scrollTo({ |
|
|
|
top: newTop, |
|
|
|
behavior: options?.smooth ? 'smooth' : 'auto', |
|
|
|
}) |
|
|
|
}) |
|
|
|
|
|
|
|
}, |
|
|
|
|
|
|
|
/** |
|
|
|
|