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