Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions src/components/ChatView.vue
Original file line number Diff line number Diff line change
Expand Up @@ -205,6 +205,7 @@ export default {
},

scrollToBottom() {
this.$router.replace({ hash: '' })
EventBus.emit('scroll-chat-to-bottom', { smooth: false, force: true })
},
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,6 @@

<template>
<div ref="messageMain"
v-element-size="[onResize, { width: 0, height: 22.5 }]"
v-intersection-observer="onIntersectionObserver"
class="message-main">
<!-- System or deleted message body content -->
<div v-if="isSystemMessage || isDeletedMessage"
Expand Down Expand Up @@ -130,7 +128,6 @@
import { showError, showSuccess } from '@nextcloud/dialogs'
import { t } from '@nextcloud/l10n'
import moment from '@nextcloud/moment'
import { vElementSize as ElementSize, vIntersectionObserver as IntersectionObserver } from '@vueuse/components'
import emojiRegex from 'emoji-regex'
import { inject, toRefs } from 'vue'
import NcButton from '@nextcloud/vue/components/NcButton'
Expand Down Expand Up @@ -180,11 +177,6 @@ export default {
ReloadIcon,
},

directives: {
IntersectionObserver,
ElementSize,
},

props: {
message: {
type: Object,
Expand Down Expand Up @@ -235,8 +227,6 @@ export default {
showReloadButton: false,
currentCodeBlock: null,
copyButtonOffset: 0,
isVisible: false,
previousSize: { width: 0, height: 22.5 }, // default height of one-line message body without widgets
}
},

Expand Down Expand Up @@ -484,29 +474,6 @@ export default {
this.isEditing = value
}
},

onIntersectionObserver([{ isIntersecting }]) {
this.isVisible = isIntersecting
},

onResize({ width, height }) {
const oldWidth = this.previousSize?.width
const oldHeight = this.previousSize?.height
this.previousSize = { width, height }

if (!this.isVisible) {
return
}
if (oldWidth && oldWidth !== width) {
// Resizing messages list
return
}
if (height === 0) {
// component is unmounted
return
}
EventBus.emit('message-height-changed', { heightDiff: height - oldHeight })
},
},
}
</script>
Expand Down
31 changes: 22 additions & 9 deletions src/components/MessagesList/MessagesList.vue
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
@scroll="onScroll"
@scrollend="endScroll">
<TransitionWrapper name="fade">
<div class="scroller__loading">
<div ref="scrollerLoader" class="scroller__loading">
<NcLoadingIcon v-if="displayMessagesLoader" class="scroller__loading-element" :size="32" />
</div>
</TransitionWrapper>
Expand Down Expand Up @@ -81,6 +81,7 @@ import { debugTimer } from '../../utils/debugTimer.ts'
import { convertToUnix, ONE_DAY_IN_MS } from '../../utils/formattedTime.ts'

const SCROLL_TOLERANCE = 10
const LOAD_HISTORY_THRESHOLD = 800

export default {
name: 'MessagesList',
Expand Down Expand Up @@ -335,7 +336,6 @@ export default {
EventBus.on('scroll-chat-to-bottom', this.scrollToBottom)
EventBus.on('focus-message', this.focusMessage)
EventBus.on('route-change', this.onRouteChange)
EventBus.on('message-height-changed', this.onMessageHeightChanged)
subscribe('networkOffline', this.handleNetworkOffline)
subscribe('networkOnline', this.handleNetworkOnline)
window.addEventListener('focus', this.onWindowFocus)
Expand All @@ -359,7 +359,6 @@ export default {
EventBus.off('scroll-chat-to-bottom', this.scrollToBottom)
EventBus.off('focus-message', this.focusMessage)
EventBus.off('route-change', this.onRouteChange)
EventBus.off('message-height-changed', this.onMessageHeightChanged)
this.$store.dispatch('cancelPollNewMessages', { requestId: this.chatIdentifier })
this.destroying = true

Expand Down Expand Up @@ -908,7 +907,7 @@ export default {
this.setChatScrolledToBottom(false)
}

if ((scrollHeight > clientHeight && scrollTop < 800 && this.isScrolling === 'up')
if ((scrollHeight > clientHeight && scrollTop < LOAD_HISTORY_THRESHOLD && this.isScrolling === 'up')
|| skipHeightCheck) {
if (this.loadingOldMessages || this.isChatBeginningReached) {
// already loading, don't do it twice
Expand Down Expand Up @@ -1112,6 +1111,14 @@ export default {
newTop = this.$refs.scroller.scrollHeight
this.setChatScrolledToBottom(true)
}

if (options?.smooth && this.$refs.scroller.scrollTop < newTop - 1.5 * window.innerHeight) {
// Imitate scrolling the whole distance to the element
this.$refs.scroller.scrollTo({
top: newTop - 1.5 * window.innerHeight,
behavior: 'instant',
})
}
this.$refs.scroller.scrollTo({
top: newTop,
behavior: options?.smooth ? 'smooth' : 'auto',
Expand Down Expand Up @@ -1151,6 +1158,17 @@ export default {
// FIXME: because scrollToBottom is also triggered and it is wrapped in $nextTick
// We need to trigger this at the same time (nextTick) to avoid focusing and then scrolling to bottom
this.$nextTick(() => {
if (smooth) {
const newTop = scrollElement.getBoundingClientRect().top - this.$refs.scrollerLoader.getBoundingClientRect().top
if (this.$refs.scroller.scrollTop > newTop) {
// Imitate scrolling the whole distance to the element
// If this goes to scrollTop < LOAD_HISTORY_THRESHOLD, might initiate loading of old messages
this.$refs.scroller.scrollTo({
top: Math.max(LOAD_HISTORY_THRESHOLD, newTop),
behavior: 'instant',
})
}
}
scrollElement.scrollIntoView({
behavior: smooth ? 'smooth' : 'auto',
block: 'center',
Expand Down Expand Up @@ -1271,11 +1289,6 @@ export default {
return group.isSystemMessagesGroup ? MessagesSystemGroup : MessagesGroup
},

onMessageHeightChanged({ heightDiff }) {
// scroll down by the height difference
this.$refs.scroller.scrollTop += heightDiff
},

updateTasksCount() {
if (!this.$refs.scroller) {
return
Expand Down
1 change: 0 additions & 1 deletion src/services/EventBus.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,6 @@ export type Events = {
'focus-message': number // TODO: listener method can receive ...[messageId, smooth, highlightAnimation]
'forbidden-route': { error: string }
'joined-conversation': { token: string }
'message-height-changed': { heightDiff: number }
'poll-drafts-open': { selector?: string }
'poll-editor-open': { id: number | null, fromDrafts: boolean, action?: string, selector?: string }
'refresh-peer-list': void
Expand Down
Loading