Fixes for "scroll to latest"

This commit is contained in:
N-Pex 2025-06-19 10:47:16 +02:00
parent e3f7f1758f
commit f0382afd83
2 changed files with 54 additions and 35 deletions

View file

@ -369,10 +369,16 @@ body {
position: absolute;
bottom: 102px;
right: 16px;
opacity: 1;
transition: opacity 0.3s linear;
&.reversed {
top: 120px;
transform: rotate(180deg);
}
&.hidden {
pointer-events: none;
opacity: 0;
}
}
.op-button {

View file

@ -120,7 +120,7 @@
</div>
<!-- "Scroll to end"-button -->
<v-btn v-if="!useVoiceMode" icon="arrow_downward" :class="{'scroll-to-end': true, 'reversed': reverseOrder}" v-show="showScrollToEnd" theme="dark" size="x-small" elevation="0" color="black"
<v-btn v-if="!useVoiceMode" icon="arrow_downward" :class="{'scroll-to-end': true, 'reversed': reverseOrder, 'hidden': !showScrollToEnd}" theme="dark" size="x-small" elevation="0" color="black"
@click.stop="scrollToEndOfTimeline">
</v-btn>
@ -410,6 +410,7 @@ export default {
timelineWindowPaginating: false,
scrollPosition: null,
scrollUpdateTimer: null,
uploadBatch: undefined,
showEmojiPicker: false,
selectedEvent: null,
@ -1210,13 +1211,7 @@ export default {
this.handleScrolledToLatest(false);
}
}
this.showScrollToEnd =
container.scrollHeight === container.clientHeight
? false
: (this.reverseOrder ? (container.scrollTop.toFixed(0) > 0) : (container.scrollHeight - container.scrollTop.toFixed(0) > container.clientHeight)) ||
(this.timelineWindow && this.timelineWindow.canPaginate(EventTimeline.FORWARDS));
this.delayedUpdateOfScrollToBottom();
this.restartRRTimer();
},
@ -1284,6 +1279,24 @@ export default {
}
},
delayedUpdateOfScrollToBottom() {
if (this.scrollUpdateTimer) {
clearTimeout(this.scrollUpdateTimer);
}
this.scrollUpdateTimer = setTimeout(() => {
this.scrollUpdateTimer = null;
const container = this.chatContainer;
if (!container) {
return;
}
this.showScrollToEnd =
container.scrollHeight === container.clientHeight
? false
: (this.reverseOrder ? (container.scrollTop.toFixed(0) > 0) : (container.scrollHeight - container.scrollTop.toFixed(0) > container.clientHeight)) ||
(this.timelineWindow && this.timelineWindow.canPaginate(EventTimeline.FORWARDS));
}, 1000);
},
onEvent(event) {
//console.log("OnEvent", JSON.stringify(event));
if (event.getRoomId() !== this.roomId) {
@ -1307,16 +1320,7 @@ export default {
if (loadingDone && event.forwardLooking && (!event.isRelation() || event.isMxThread || event.threadRootId || event.parentThread)) {
// If we are at bottom, scroll to see new events...
var scrollToSeeNew = !event.isRedaction() && event.getSender() == this.$matrix.currentUserId; // When we sent, scroll
const container = this.chatContainer;
if (container) {
if (this.reverseOrder && container.scrollTop.toFixed(0) == 0) {
scrollToSeeNew = true;
}
else if (!this.reverseOrder && container.scrollHeight - container.scrollTop.toFixed(0) == container.clientHeight) {
scrollToSeeNew = true;
}
}
this.handleScrolledToLatest(scrollToSeeNew);
this.handleScrolledToLatest(scrollToSeeNew || !this.showScrollToEnd);
// If kick or ban event, redirect to "goodbye"...
if (event.getType() === "m.room.member" &&
@ -1516,32 +1520,41 @@ export default {
},
smoothScrollToLatest() {
this.$nextTick(function () {
this.$nextTick(() => {
// TODO - fix this. We need to wait until the "lastChild" below has been
// laid out correctly. If we do it "too early" it will have zero height and
// thus not correctly scrolled into the viewport. So we wait a few ticks...
window.requestAnimationFrame(() => {
window.requestAnimationFrame(() => {
window.requestAnimationFrame(() => {
window.requestAnimationFrame(() => {
const container = this.chatContainer;
if (container && container.children.length > 0) {
if (this.reverseOrder) {
const firstChild = container.children[0];
console.log("Scroll into view", firstChild);
window.requestAnimationFrame(() => {
firstChild.scrollIntoView({
behavior: "smooth",
block: "end",
inline: "nearest",
window.requestAnimationFrame(() => {
firstChild.scrollIntoView({
behavior: "smooth",
block: "end",
inline: "nearest",
});
});
});
} else {
const lastChild = container.children[container.children.length - 1];
console.log("Scroll into view", lastChild);
window.requestAnimationFrame(() => {
lastChild.scrollIntoView({
behavior: "smooth",
block: "start",
inline: "nearest",
const lastChild = container.children[container.children.length - 1];
window.requestAnimationFrame(() => {
lastChild.scrollIntoView({
behavior: "smooth",
block: "start",
inline: "nearest",
});
});
});
}
}
}
});
})
})
})
})
},
showMoreMessageOperations(e) {