Fix restoring scroll position on edited message
This commit is contained in:
parent
5c1691f84b
commit
a7fd334eaa
@ -503,7 +503,7 @@ export default class BubbleGroups {
|
||||
prepareForGrouping(bubble: HTMLElement, message: MyMessage) {
|
||||
const foundItem = this.getItemByBubble(bubble);
|
||||
if(foundItem) { // should happen only on edit
|
||||
debugger;
|
||||
// debugger;
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -248,7 +248,7 @@ export default class ChatBubbles {
|
||||
private attachPlaceholderOnRender: () => void;
|
||||
|
||||
private bubblesToEject: Set<HTMLElement> = new Set();
|
||||
private bubblesToReplace: Set<HTMLElement> = new Set();
|
||||
private bubblesToReplace: Map<HTMLElement, HTMLElement> = new Map(); // TO -> FROM
|
||||
private updatePlaceholderPosition: () => void;
|
||||
private setPeerOptions: {lastMsgId: number; topMessage: number;};
|
||||
|
||||
@ -3153,7 +3153,7 @@ export default class ChatBubbles {
|
||||
|
||||
loadQueue = filterQueue(loadQueue);
|
||||
|
||||
const restoreScroll = this.prepareToSaveScroll(reverse);
|
||||
const {restoreScroll, scrollSaver} = this.prepareToSaveScroll(reverse);
|
||||
// if(this.messagesQueueOnRender) {
|
||||
// this.messagesQueueOnRender();
|
||||
// }
|
||||
@ -3163,7 +3163,9 @@ export default class ChatBubbles {
|
||||
}
|
||||
|
||||
this.ejectBubbles();
|
||||
for(const bubble of this.bubblesToReplace) {
|
||||
for(const [bubble, oldBubble] of this.bubblesToReplace) {
|
||||
scrollSaver.replaceSaved(oldBubble, bubble);
|
||||
|
||||
if(!loadQueue.find((details) => details.bubble === bubble)) {
|
||||
continue;
|
||||
}
|
||||
@ -3317,7 +3319,7 @@ export default class ChatBubbles {
|
||||
|
||||
this.bubblesToEject.add(bubble);
|
||||
this.bubblesToReplace.delete(bubble);
|
||||
this.bubblesToReplace.add(newBubble);
|
||||
this.bubblesToReplace.set(newBubble, bubble);
|
||||
this.bubbleGroups.changeBubbleByBubble(bubble, newBubble);
|
||||
}
|
||||
|
||||
@ -4414,7 +4416,7 @@ export default class ChatBubbles {
|
||||
private prepareToSaveScroll(reverse?: boolean) {
|
||||
const isMounted = !!this.chatInner.parentElement;
|
||||
if(!isMounted) {
|
||||
return;
|
||||
return {};
|
||||
}
|
||||
|
||||
const log = this.log.bindPrefix('prepareToSaveScroll');
|
||||
@ -4431,11 +4433,14 @@ export default class ChatBubbles {
|
||||
// const saved = scrollSaver.getSaved();
|
||||
// const hadScroll = saved.scrollHeight !== saved.clientHeight;
|
||||
|
||||
return () => {
|
||||
log('restore');
|
||||
// scrollSaver.restore(_history.length === 1 && !reverse ? false : true);
|
||||
scrollSaver.restore(reverse);
|
||||
this.onRenderScrollSet(scrollSaver.getSaved());
|
||||
return {
|
||||
restoreScroll: () => {
|
||||
log('restore');
|
||||
// scrollSaver.restore(_history.length === 1 && !reverse ? false : true);
|
||||
scrollSaver.restore(reverse);
|
||||
this.onRenderScrollSet(scrollSaver.getSaved());
|
||||
},
|
||||
scrollSaver
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -15,8 +15,7 @@ export default class ScrollSaver {
|
||||
private scrollHeightMinusTop: number;
|
||||
private scrollTop: number;
|
||||
private clientHeight: number;
|
||||
private anchor: HTMLElement;
|
||||
private rect: DOMRect;
|
||||
private elements: {element: HTMLElement, rect: DOMRect}[];
|
||||
|
||||
/**
|
||||
*
|
||||
@ -43,43 +42,50 @@ export default class ScrollSaver {
|
||||
};
|
||||
}
|
||||
|
||||
public findAnchor() {
|
||||
public findElements() {
|
||||
const {container} = this;
|
||||
const containerRect = container.getBoundingClientRect();
|
||||
const bubbles = Array.from(container.querySelectorAll(this.query)) as HTMLElement[];
|
||||
let rect: DOMRect, anchor: HTMLElement;
|
||||
const elements: ScrollSaver['elements'] = [];
|
||||
for(const bubble of bubbles) {
|
||||
const elementRect = bubble.getBoundingClientRect();
|
||||
const visibleRect = getVisibleRect(bubble, container, undefined, elementRect, containerRect);
|
||||
if(visibleRect) {
|
||||
rect = elementRect;
|
||||
anchor = bubble;
|
||||
elements.push({element: bubble, rect: elementRect});
|
||||
// break; // find first
|
||||
} else if(anchor) { // find last
|
||||
} else if(elements.length) { // find last
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if(!rect) {
|
||||
if(!elements.length) {
|
||||
const bubble = bubbles[0];
|
||||
if(bubble) {
|
||||
rect = bubble.getBoundingClientRect();
|
||||
anchor = bubble;
|
||||
elements.push({element: bubble, rect: bubble.getBoundingClientRect()});
|
||||
}
|
||||
}
|
||||
|
||||
return {rect, anchor};
|
||||
return elements;
|
||||
}
|
||||
|
||||
public findAndSetAnchor() {
|
||||
const {rect, anchor} = this.findAnchor();
|
||||
this.rect = rect;
|
||||
this.anchor = anchor;
|
||||
public replaceSaved(from: HTMLElement, to: HTMLElement) {
|
||||
if(!this.elements) {
|
||||
return;
|
||||
}
|
||||
|
||||
const idx = this.elements.findIndex(({element}) => from === element);
|
||||
if(idx !== -1) {
|
||||
this.elements[idx].element = to;
|
||||
}
|
||||
}
|
||||
|
||||
public findAndSetElements() {
|
||||
this.elements = this.findElements();
|
||||
}
|
||||
|
||||
public save() {
|
||||
this.findAndSetAnchor();
|
||||
// console.warn('scroll save', this.anchor, this.rect);
|
||||
this.findAndSetElements();
|
||||
console.warn('scroll save', this.elements);
|
||||
this._save();
|
||||
}
|
||||
|
||||
@ -121,21 +127,32 @@ export default class ScrollSaver {
|
||||
const {scrollTop, scrollHeight} = this.scrollable;
|
||||
this.scrollHeight = scrollHeight;
|
||||
|
||||
if(!this.anchor?.parentElement) { // try to find new anchor
|
||||
this.findAndSetAnchor();
|
||||
let anchor: ScrollSaver['elements'][0];
|
||||
// for(let i = this.elements.length - 1; i >= 0; --i) {
|
||||
// const _anchor = this.elements[i];
|
||||
// if(_anchor.element.parentElement) {
|
||||
// anchor = _anchor;
|
||||
// break;
|
||||
// }
|
||||
// }
|
||||
anchor = this.elements[this.elements.length - 1];
|
||||
|
||||
if(!anchor?.element?.parentElement) { // try to find new anchor
|
||||
this.findAndSetElements();
|
||||
anchor = this.elements[this.elements.length - 1];
|
||||
|
||||
if(!this.anchor) { // fallback to old method if smth is really strange
|
||||
if(!anchor) { // fallback to old method if smth is really strange
|
||||
this._restore(useReflow);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
const rect = this.rect;
|
||||
const newRect = this.anchor.getBoundingClientRect();
|
||||
const {element, rect} = anchor;
|
||||
const newRect = element.getBoundingClientRect();
|
||||
const diff = newRect.bottom - rect.bottom;
|
||||
this.setScrollTop(scrollTop + diff, useReflow);
|
||||
// if(diff) debugger;
|
||||
// console.warn('scroll restore', rect, diff, newRect);
|
||||
console.warn('scroll restore', rect, diff, newRect);
|
||||
}
|
||||
|
||||
public _restore(useReflow?: boolean) {
|
||||
|
@ -2367,7 +2367,7 @@ $bubble-beside-button-width: 38px;
|
||||
color: var(--monospace-text-color);
|
||||
}
|
||||
|
||||
.reply.is-overriding-color {
|
||||
&:not(.just-media) .reply.is-overriding-color {
|
||||
.reply-border {
|
||||
background-color: rgb(var(--override-color));
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user