diff --git a/src/boot/routes.js b/src/boot/routes.js index 3736036cd..beaa144e8 100644 --- a/src/boot/routes.js +++ b/src/boot/routes.js @@ -72,6 +72,7 @@ export default (store) => { () => import('src/components/chat_view/chat_view.vue'), ), props: true, + meta: { dontScroll: true }, beforeEnter: validateAuthenticatedRoute, }, { name: 'quotes', path: '/notice/:id/quotes', component: QuotesTimeline }, diff --git a/src/components/chat_message/chat_message.js b/src/components/chat_message/chat_message.js index ac950a979..516741a33 100644 --- a/src/components/chat_message/chat_message.js +++ b/src/components/chat_message/chat_message.js @@ -184,11 +184,6 @@ const ChatMessage = { menuOpened: false, } }, - watch: { - focused: function (value) { - this.scrollIfFocused(value) - }, - }, methods: { onHover(bool) { this.$emit('hover', { @@ -224,22 +219,6 @@ const ChatMessage = { this.hovered = false this.menuOpened = false }, - scrollIfFocused(focused) { - if (this.$el.getBoundingClientRect == null) return - if (focused) { - const rect = this.$el.getBoundingClientRect() - if (rect.top < 100) { - // Post is above screen, match its top to screen top - window.scrollBy(0, rect.top - 100) - } else if (rect.height >= window.innerHeight - 50) { - // Post we want to see is taller than screen so match its top to screen top - window.scrollBy(0, rect.top - 100) - } else if (rect.bottom > window.innerHeight - 50) { - // Post is below screen, match its bottom to screen bottom - window.scrollBy(0, rect.bottom - window.innerHeight + 50) - } - } - }, }, } diff --git a/src/components/chat_message/chat_message.vue b/src/components/chat_message/chat_message.vue index f9095a3de..c3deac0a5 100644 --- a/src/components/chat_message/chat_message.vue +++ b/src/components/chat_message/chat_message.vue @@ -3,6 +3,7 @@ v-if="isMessage" class="chat-message-wrapper" :class="[classnames, { 'hovered-message-chain': hoveredMessageChain }]" + :id="`chatmessage-${message.id}`" @mouseover="onHover(true)" @mouseleave="onHover(false)" > diff --git a/src/components/chat_view/chat_view.js b/src/components/chat_view/chat_view.js index de2ed8857..8d45707f3 100644 --- a/src/components/chat_view/chat_view.js +++ b/src/components/chat_view/chat_view.js @@ -86,9 +86,9 @@ const Chat = { created() { if (this.testMode) return this.startFetching() - window.addEventListener('resize', this.handleResize) }, mounted() { + window.addEventListener('resize', this.handleResize) window.addEventListener('scroll', this.handleScroll) if (typeof document.hidden !== 'undefined') { document.addEventListener( @@ -122,14 +122,11 @@ const Chat = { ) }, isConversation() { - return this.conversationId !== null + return this.statusId !== null }, recipient() { return this.chat?.account }, - recipientId() { - return this.$route.params.recipient_id - }, formPlaceholder() { if (this.recipient) { return this.$t('chats.message_user', { @@ -166,7 +163,8 @@ const Chat = { }), }, watch: { - messages() { + messages(old, neu) { + if (old.length === neu.length) return // We don't want to scroll to the bottom on a new message when the user is viewing older messages. // Therefore we need to know whether the scroll position was at the bottom before the DOM update. const bottomedOutBeforeUpdate = isBottomedOut(BOTTOMED_OUT_OFFSET) @@ -180,7 +178,38 @@ const Chat = { await nextTick() // wait for changes to propagate to postStatusForm this.$refs.postStatusForm.update() }, - $route: function () { + $route: async function (newVal) { + if (this.messagesIndex[newVal.params.statusId]) { + const focused = document.getElementById(`chatmessage-${this.$route.params.statusId}`) + if (focused?.getBoundingClientRect == null) return + const bottomBoundary = window.innerHeight - this.$refs.footer.clientHeight + const topBoundary = this.$refs.header.clientHeight + document.getElementById('nav').clientHeight + const margin = Number(window.getComputedStyle(this.$refs.messageList.$el).gap.replace('px','')) + + const rect = focused.getBoundingClientRect() + const scrollAmount = (() => { + if (rect.top < topBoundary) { + // Post is above screen, match its top to screen top + return rect.top - topBoundary - margin + } else if (rect.height >= bottomBoundary) { + // Post we want to see is taller than screen so match its top to screen top + return rect.top - topBoundary - margin + } else if (rect.bottom > bottomBoundary) { + // Post is below screen, match its bottom to screen bottom + return rect.bottom - bottomBoundary + margin + } else { + return 0 + } + })() + + if (scrollAmount !== 0) { + window.scrollBy(0, scrollAmount) + } + + return + } + + this.clear() this.startFetching() }, mastoUserSocketStatus(newValue) { @@ -295,6 +324,9 @@ const Chat = { this.addMessages({ messages }) await nextTick() + if (isFirstFetch) { + this.scrollDown() + } const fetchOlderMessages = !!maxId if (fetchOlderMessages) { diff --git a/src/components/chat_view/chat_view.vue b/src/components/chat_view/chat_view.vue index 254b8712e..5ea2fd2b5 100644 --- a/src/components/chat_view/chat_view.vue +++ b/src/components/chat_view/chat_view.vue @@ -18,7 +18,7 @@ icon="chevron-left" /> -