diff --git a/js/ui/dm/ConversationList.js b/js/ui/dm/ConversationList.js index 5aec1cd4..fc6f7545 100644 --- a/js/ui/dm/ConversationList.js +++ b/js/ui/dm/ConversationList.js @@ -1,5 +1,7 @@ import { ContactRow } from "./ContactRow.js"; +let hasPeekAnimationPlayed = false; + function createElement(doc, tag, className, text) { const element = doc.createElement(tag); if (className) { @@ -93,12 +95,13 @@ export function ConversationList({ }); // Peek animation - if (conversations.length > 0) { + if (conversations.length > 0 && !hasPeekAnimationPlayed) { if (typeof IntersectionObserver !== "undefined") { const observer = new IntersectionObserver((entries) => { const entry = entries[0]; if (entry.isIntersecting) { observer.disconnect(); + hasPeekAnimationPlayed = true; setTimeout(() => { if (list.scrollHeight > list.clientHeight) { list.scrollTo({ top: 40, behavior: "smooth" }); @@ -112,6 +115,7 @@ export function ConversationList({ observer.observe(list); } else { // Fallback for no IntersectionObserver (e.g. some tests or very old browsers) + hasPeekAnimationPlayed = true; setTimeout(() => { if (list.scrollHeight > list.clientHeight) { list.scrollTo({ top: 40, behavior: "smooth" }); diff --git a/js/ui/dm/MessageThread.js b/js/ui/dm/MessageThread.js index de405db2..e03f734d 100644 --- a/js/ui/dm/MessageThread.js +++ b/js/ui/dm/MessageThread.js @@ -1,6 +1,8 @@ import { DayDivider } from "./DayDivider.js"; import { MessageBubble } from "./MessageBubble.js"; +let hasPeekAnimationPlayed = false; + function createElement(doc, tag, className, text) { const element = doc.createElement(tag); if (className) { @@ -142,10 +144,13 @@ export function MessageThread({ // Scroll to bottom and peek if (messages.length > 0) { - const animate = () => { - timeline.scrollTop = timeline.scrollHeight; + const performPeek = () => { + if (hasPeekAnimationPlayed) { + return; + } if (timeline.scrollHeight > timeline.clientHeight) { + hasPeekAnimationPlayed = true; setTimeout(() => { const targetScroll = Math.max(0, timeline.scrollTop - 40); timeline.scrollTo({ top: targetScroll, behavior: "smooth" }); @@ -160,6 +165,11 @@ export function MessageThread({ } }; + const initializeScroll = () => { + timeline.scrollTop = timeline.scrollHeight; + performPeek(); + }; + if (typeof IntersectionObserver !== "undefined") { const observer = new IntersectionObserver((entries) => { const entry = entries[0]; @@ -167,15 +177,12 @@ export function MessageThread({ observer.disconnect(); // First ensure we are at bottom timeline.scrollTop = timeline.scrollHeight; - setTimeout(animate, 300); + setTimeout(initializeScroll, 300); } }, { threshold: 0.1 }); observer.observe(timeline); } else { - setTimeout(() => { - timeline.scrollTop = timeline.scrollHeight; - animate(); - }, 0); + setTimeout(initializeScroll, 0); } }