diff --git a/client/components/Chat.vue b/client/components/Chat.vue index daae13bf..8ff709a5 100644 --- a/client/components/Chat.vue +++ b/client/components/Chat.vue @@ -69,7 +69,9 @@ Show older messages - + 30) { - return; - } - - this.$nextTick(() => { - el.scrollTop = el.scrollHeight; - }); + this.keepScrollPosition(); }, }, created() { @@ -141,7 +131,7 @@ export default { } if (window.IntersectionObserver) { - this.historyObserver = new window.IntersectionObserver(loadMoreHistory, { + this.historyObserver = new window.IntersectionObserver(this.onLoadButtonObserved, { root: this.$refs.chat, }); } @@ -173,16 +163,38 @@ export default { lastId: lastMessage, }); }, + onLoadButtonObserved(entries) { + entries.forEach((entry) => { + if (!entry.isIntersecting) { + return; + } + + entry.target.click(); + }); + }, + keepScrollPosition() { + // If we are already waiting for the next tick to force scroll position, + // we have no reason to perform more checks and set it again in the next tick + if (this.isWaitingForNextTick) { + return; + } + + const el = this.$refs.chat; + + if (!el) { + return; + } + + if (el.scrollHeight - el.scrollTop - el.offsetHeight > 30) { + return; + } + + this.isWaitingForNextTick = true; + this.$nextTick(() => { + this.isWaitingForNextTick = false; + el.scrollTop = el.scrollHeight; + }); + }, }, }; - -function loadMoreHistory(entries) { - entries.forEach((entry) => { - if (!entry.isIntersecting) { - return; - } - - entry.target.click(); - }); -} diff --git a/client/components/LinkPreview.vue b/client/components/LinkPreview.vue index c468679d..2a65a0dc 100644 --- a/client/components/LinkPreview.vue +++ b/client/components/LinkPreview.vue @@ -138,6 +138,9 @@ export default { const options = require("../js/options"); this.$set(this.link, "canDisplay", this.link.type !== "loading" && options.shouldOpenMessagePreview(this.link.type)); + // parent 1 - message - parent 2 - messagelist + this.$parent.$parent.$emit("keepScrollPosition"); + if (this.link.type !== "link") { return; } @@ -152,7 +155,8 @@ export default { }, methods: { onPreviewReady() { - + // TODO: Instead of forcing scroll position, wait for image to load before showing it + this.$parent.$parent.$emit("keepScrollPosition"); }, onMoreClick() { this.isContentShown = !this.isContentShown;