diff --git a/src/components/chat/bubbles.ts b/src/components/chat/bubbles.ts index 8a6da5ca..f6e0e9af 100644 --- a/src/components/chat/bubbles.ts +++ b/src/components/chat/bubbles.ts @@ -207,6 +207,8 @@ export default class ChatBubbles { private hoverBubble: HTMLElement; private hoverReaction: HTMLElement; + private onUpdateScrollSaver: ScrollSaver; + // private reactions: Map; constructor( @@ -428,10 +430,8 @@ export default class ChatBubbles { const updatePosition = this.chat.type === 'scheduled'; - const scrollSaver = new ScrollSaver(this.scrollable, true); - scrollSaver.save(); + this.saveOnUpdateScroll(); this.safeRenderMessage(mounted.message, true, false, mounted.bubble, updatePosition); - scrollSaver.restore(); if(updatePosition) { (this.messagesQueuePromise || Promise.resolve()).then(() => { @@ -465,13 +465,12 @@ export default class ChatBubbles { return; } - const scrollSaver = new ScrollSaver(this.scrollable, true); const bubble = this.getBubbleByMessage(message); if(!bubble) { return; } - scrollSaver.save(); + this.saveOnUpdateScroll(); const key = message.peerId + '_' + message.mid; const set = REACTIONS_ELEMENTS.get(key); @@ -482,8 +481,6 @@ export default class ChatBubbles { } else { rootScope.dispatchEvent('missed_reactions_element', {message, changedResults}); } - - scrollSaver.restore(); }); } @@ -775,6 +772,7 @@ export default class ChatBubbles { let different = false; postViewsElements.forEach(postViews => { if(different || postViews.innerHTML !== str) { + this.saveOnUpdateScroll(); different = true; postViews.innerHTML = str; } @@ -922,6 +920,18 @@ export default class ChatBubbles { } } + private saveOnUpdateScroll() { + if(!this.onUpdateScrollSaver) { + this.onUpdateScrollSaver = new ScrollSaver(this.scrollable, true); + setTimeout(() => { + this.onUpdateScrollSaver.restore(); + this.onUpdateScrollSaver = undefined; + }, 0); + + this.onUpdateScrollSaver.save(); + } + } + private onBubblesMouseMove = (e: MouseEvent) => { const content = findUpClassName(e.target, 'bubble-content'); if(content && !this.chat.selection.isSelecting) { @@ -3904,7 +3914,7 @@ export default class ChatBubbles { } if(scrollSaver) { - scrollSaver.restore(); + scrollSaver.restore(history.length === 1 && !reverse ? false : true); } return true; diff --git a/src/helpers/scrollSaver.ts b/src/helpers/scrollSaver.ts index a502262b..f7d500ad 100644 --- a/src/helpers/scrollSaver.ts +++ b/src/helpers/scrollSaver.ts @@ -9,6 +9,7 @@ import { IS_SAFARI } from "../environment/userAgent"; import reflowScrollableElement from "./dom/reflowScrollableElement"; export default class ScrollSaver { + private previousScrollHeight: number; private previousScrollHeightMinusTop: number/* , previousScrollHeight: number */; /** @@ -16,7 +17,10 @@ export default class ScrollSaver { * @param scrollable to reset scroll position and direction * @param reverse true means top */ - constructor(private scrollable: Scrollable, private reverse: boolean) { + constructor( + private scrollable: Scrollable, + private reverse: boolean + ) { } @@ -29,6 +33,7 @@ export default class ScrollSaver { //previousScrollHeight = scrollHeight; //previousScrollHeight = scrollHeight + padding; + this.previousScrollHeight = scrollHeight; this.previousScrollHeightMinusTop = this.reverse ? scrollHeight - scrollTop : scrollTop; //this.chatInner.style.paddingTop = padding + 'px'; @@ -43,14 +48,19 @@ export default class ScrollSaver { } */ } - public restore() { + public restore(useReflow?: boolean) { const {container, previousScrollHeightMinusTop, scrollable} = this; if(previousScrollHeightMinusTop !== undefined) { + const scrollHeight = container.scrollHeight; + if(scrollHeight === this.previousScrollHeight) { + return; + } + /* const scrollHeight = container.scrollHeight; const addedHeight = scrollHeight - previousScrollHeight; this.chatInner.style.paddingTop = (10000 - addedHeight) + 'px'; */ - /* const scrollHeight = container.scrollHeight; + /* const scrollHeight = scrollHeight; const addedHeight = scrollHeight - previousScrollHeight; this.chatInner.style.paddingTop = (padding - addedHeight) + 'px'; @@ -58,10 +68,10 @@ export default class ScrollSaver { //const newScrollTop = reverse ? scrollHeight - previousScrollHeightMinusTop : previousScrollHeightMinusTop; const newScrollTop = reverse ? scrollHeight - addedHeight - previousScrollHeightMinusTop : previousScrollHeightMinusTop; this.log('performHistoryResult: will set scrollTop', - previousScrollHeightMinusTop, container.scrollHeight, + previousScrollHeightMinusTop, scrollHeight, newScrollTop, container.container.clientHeight); */ //const newScrollTop = reverse ? scrollHeight - previousScrollHeightMinusTop : previousScrollHeightMinusTop; - const newScrollTop = this.reverse ? container.scrollHeight - previousScrollHeightMinusTop : previousScrollHeightMinusTop; + const newScrollTop = this.reverse ? scrollHeight - previousScrollHeightMinusTop : previousScrollHeightMinusTop; /* if(DEBUG) { this.log('performHistoryResult: will set up scrollTop:', newScrollTop, this.isHeavyAnimationInProgress); @@ -70,13 +80,13 @@ export default class ScrollSaver { // touchSupport for safari iOS //isTouchSupported && isApple && (container.container.style.overflow = 'hidden'); container.scrollTop = newScrollTop; - //container.scrollTop = container.scrollHeight; + //container.scrollTop = scrollHeight; //isTouchSupported && isApple && (container.container.style.overflow = ''); scrollable.lastScrollPosition = newScrollTop; // scrollable.lastScrollDirection = 0; - if(IS_SAFARI/* && !isAppleMobile */) { // * fix blinking and jumping + if(IS_SAFARI && useReflow/* && !isAppleMobile */) { // * fix blinking and jumping reflowScrollableElement(container); }