Browse Source

Fix saving scroll once again

Fix detecting pinned messages position
master
Eduard Kuzmenko 2 years ago
parent
commit
045199cccc
  1. 6
      src/components/chat/bubbleGroups.ts
  2. 6
      src/components/chat/bubbles.ts
  3. 2
      src/components/chat/chat.ts
  4. 10
      src/components/chat/input.ts
  5. 37
      src/components/chat/pinnedMessage.ts
  6. 18
      src/components/chat/topbar.ts
  7. 88
      src/helpers/scrollSaver.ts

6
src/components/chat/bubbleGroups.ts

@ -80,6 +80,10 @@ class BubbleGroup { @@ -80,6 +80,10 @@ class BubbleGroup {
return this.firstItem.timestamp;
}
get firstMid() {
return this.firstItem.mid;
}
get firstItem() {
return this.items[this.items.length - 1];
}
@ -145,7 +149,7 @@ class BubbleGroup { @@ -145,7 +149,7 @@ class BubbleGroup {
}
if(items.length === 1) {
insertInDescendSortedArray(this.groups.groups, this, 'firstTimestamp');
insertInDescendSortedArray(this.groups.groups, this, 'firstMid');
}
}

6
src/components/chat/bubbles.ts

@ -944,7 +944,7 @@ export default class ChatBubbles { @@ -944,7 +944,7 @@ export default class ChatBubbles {
}
private createScrollSaver(reverse = true) {
const scrollSaver = new ScrollSaver(this.scrollable, '.bubbles-group .bubble', reverse);
const scrollSaver = new ScrollSaver(this.scrollable, '.bubble:not(.is-date)', reverse);
return scrollSaver;
}
@ -2745,6 +2745,10 @@ export default class ChatBubbles { @@ -2745,6 +2745,10 @@ export default class ChatBubbles {
this.attachPlaceholderOnRender();
}
if(!isTarget && this.chat.type === 'chat') {
this.chat.topbar.pinnedMessage.setCorrectIndex(0);
}
this.container.classList.toggle('has-groups', !!Object.keys(this.dateMessages).length);
log.warn('mounted chat', this.chatInner === chatInner, this.chatInner.parentElement, performance.now() - perf);

2
src/components/chat/chat.ts

@ -422,7 +422,7 @@ export default class Chat extends EventListenerBase<{ @@ -422,7 +422,7 @@ export default class Chat extends EventListenerBase<{
this.selection.cleanup(); // TODO: REFACTOR !!!!!!
}
public async setPeer(peerId: PeerId, lastMsgId?: number, startParam?: string) {
public setPeer(peerId: PeerId, lastMsgId?: number, startParam?: string) {
if(!peerId) {
this.inited = undefined;
} else if(!this.inited) {

10
src/components/chat/input.ts

@ -1386,6 +1386,7 @@ export default class ChatInput { @@ -1386,6 +1386,7 @@ export default class ChatInput {
}
private filterAttachMenuButtons() {
if(!this.attachMenuButtons) return;
const {peerId, threadId} = this.chat;
return filterAsync(this.attachMenuButtons, (button) => {
return button.verify(peerId, threadId);
@ -1406,7 +1407,7 @@ export default class ChatInput { @@ -1406,7 +1407,7 @@ export default class ChatInput {
this.updateMessageInputPlaceholder(placeholderKey);
this.attachMenuButtons.forEach((button) => {
this.attachMenuButtons && this.attachMenuButtons.forEach((button) => {
button.element.classList.toggle('hide', !visible.includes(button));
});
@ -1421,8 +1422,11 @@ export default class ChatInput { @@ -1421,8 +1422,11 @@ export default class ChatInput {
}
}
attachMenu.toggleAttribute('disabled', !visible.length);
attachMenu.classList.toggle('btn-disabled', !visible.length);
if(attachMenu) {
attachMenu.toggleAttribute('disabled', !visible.length);
attachMenu.classList.toggle('btn-disabled', !visible.length);
}
this.updateSendBtn();
}

37
src/components/chat/pinnedMessage.ts

@ -4,8 +4,6 @@ @@ -4,8 +4,6 @@
* https://github.com/morethanwords/tweb/blob/master/LICENSE
*/
import type { AppMessagesManager } from "../../lib/appManagers/appMessagesManager";
import type { AppPeersManager } from "../../lib/appManagers/appPeersManager";
import type ChatTopbar from "./topbar";
import PopupPinMessage from "../popups/unpinMessage";
import PinnedContainer from "./pinnedContainer";
@ -24,6 +22,7 @@ import debounce from "../../helpers/schedulers/debounce"; @@ -24,6 +22,7 @@ import debounce from "../../helpers/schedulers/debounce";
import throttle from "../../helpers/schedulers/throttle";
import { AppManagers } from "../../lib/appManagers/managers";
import { Message } from "../../layer";
import { logger } from "../../lib/logger";
class AnimatedSuper {
static DURATION = 200;
@ -253,14 +252,19 @@ export default class ChatPinnedMessage { @@ -253,14 +252,19 @@ export default class ChatPinnedMessage {
private setPinnedMessage: () => void;
private isStatic = false;
private isStatic: boolean;
private debug = false;
private debug: boolean;
public setCorrectIndexThrottled: (lastScrollDirection?: number) => void;
private log: ReturnType<typeof logger>;
constructor(private topbar: ChatTopbar, private chat: Chat, private managers: AppManagers) {
this.listenerSetter = new ListenerSetter();
this.log = logger('PM');
this.debug = true;
this.isStatic = false;
const dAC = new ReplyContainer('pinned-message');
this.pinnedMessageContainer = new PinnedContainer({
@ -361,14 +365,14 @@ export default class ChatPinnedMessage { @@ -361,14 +365,14 @@ export default class ChatPinnedMessage {
//const perf = performance.now();
let el = this.chat.bubbles.getBubbleByPoint('bottom');
//this.chat.log('[PM]: setCorrectIndex: get last element perf:', performance.now() - perf, el);
//this.log('setCorrectIndex: get last element perf:', performance.now() - perf, el);
if(!el) return;
//return;
const mid = el.dataset.mid;
if(el && mid !== undefined) {
//this.chat.log('[PM]: setCorrectIndex will test mid:', mid);
//this.log('setCorrectIndex will test mid:', mid);
this.testMid(+mid, lastScrollDirection);
}
}
@ -379,7 +383,7 @@ export default class ChatPinnedMessage { @@ -379,7 +383,7 @@ export default class ChatPinnedMessage {
//if(lastScrollDirection !== undefined) return;
if(this.hidden) return;
//this.chat.log('[PM]: testMid', mid);
//this.log('testMid', mid);
let currentIndex: number = this.mids.findIndex((_mid) => _mid <= mid);
if(currentIndex !== -1 && !this.isNeededMore(currentIndex)) {
@ -401,7 +405,7 @@ export default class ChatPinnedMessage { @@ -401,7 +405,7 @@ export default class ChatPinnedMessage {
currentIndex = 0;
} */
//this.chat.log('[PM]: testMid: pinned currentIndex', currentIndex, mid);
//this.log('testMid: pinned currentIndex', currentIndex, mid);
const changed = this.pinnedIndex !== currentIndex;
if(changed) {
@ -431,6 +435,9 @@ export default class ChatPinnedMessage { @@ -431,6 +435,9 @@ export default class ChatPinnedMessage {
this.loading = true;
try {
const log = this.debug ? this.log.bindPrefix('getCurrentIndex') : undefined;
log && log('start', mid, correctAfter);
let gotRest = false;
const promises = [
this.managers.appMessagesManager.getSearch({
@ -484,9 +491,9 @@ export default class ChatPinnedMessage { @@ -484,9 +491,9 @@ export default class ChatPinnedMessage {
this.loadedTop = (this.offsetIndex + this.mids.length) === this.count;
this.loadedBottom = !this.offsetIndex;
this.debug && this.chat.log('[PM]: getCurrentIndex result:', mid, result, backLimited, this.offsetIndex, this.loadedTop, this.loadedBottom);
log && log('result', mid, result, backLimited, this.offsetIndex, this.loadedTop, this.loadedBottom);
} catch(err) {
this.chat.log.error('[PM]: getCurrentIndex error', err);
this.log.error('getCurrentIndex error', err);
}
this.loading = false;
@ -528,7 +535,7 @@ export default class ChatPinnedMessage { @@ -528,7 +535,7 @@ export default class ChatPinnedMessage {
public async handleFollowingPinnedMessage() {
this.locked = true;
this.debug && this.chat.log('[PM]: handleFollowingPinnedMessage');
this.debug && this.log('handleFollowingPinnedMessage');
try {
this.setScrollDownListener();
@ -544,16 +551,16 @@ export default class ChatPinnedMessage { @@ -544,16 +551,16 @@ export default class ChatPinnedMessage {
await this.getCurrentIndexPromise;
}
this.debug && this.chat.log('[PM]: handleFollowingPinnedMessage: unlock');
this.debug && this.log('handleFollowingPinnedMessage: unlock');
this.locked = false;
/* // подождём, пока скролл остановится
setTimeout(() => {
this.chat.log('[PM]: handleFollowingPinnedMessage: unlock');
this.log('handleFollowingPinnedMessage: unlock');
this.locked = false;
}, 50); */
} catch(err) {
this.chat.log.error('[PM]: handleFollowingPinnedMessage error:', err);
this.log.error('handleFollowingPinnedMessage error:', err);
this.locked = false;
this.waitForScrollBottom = false;
@ -603,7 +610,7 @@ export default class ChatPinnedMessage { @@ -603,7 +610,7 @@ export default class ChatPinnedMessage {
const fromTop = pinnedIndex > this.wasPinnedIndex;
this.debug && this.chat.log('[PM]: setPinnedMessage: fromTop', fromTop, pinnedIndex, this.wasPinnedIndex);
this.debug && this.log('setPinnedMessage: fromTop', fromTop, pinnedIndex, this.wasPinnedIndex);
const writeTo = this.animatedSubtitle.getRow(pinnedIndex);
const writeMediaTo = this.animatedMedia.getRow(pinnedIndex);

18
src/components/chat/topbar.ts

@ -697,13 +697,14 @@ export default class ChatTopbar { @@ -697,13 +697,14 @@ export default class ChatTopbar {
newAvatar = this.constructAvatar();
}
const [isBroadcast, isAnyChat, chat, _, setTitleCallback, setStatusCallback] = await Promise.all([
const [isBroadcast, isAnyChat, chat, _, setTitleCallback, setStatusCallback, state] = await Promise.all([
this.managers.appPeersManager.isBroadcast(peerId),
this.managers.appPeersManager.isAnyChat(peerId),
peerId.isAnyChat() ? this.managers.appChatsManager.getChat(peerId.toChatId()) : undefined,
newAvatar ? newAvatar.updateWithOptions({peerId}) : undefined,
this.setTitleManual(),
this.setPeerStatusManual(true),
apiManagerProxy.getState()
]);
return () => {
@ -726,7 +727,6 @@ export default class ChatTopbar { @@ -726,7 +727,6 @@ export default class ChatTopbar {
this.verifyButtons();
const middleware = this.chat.bubbles.getMiddleware();
if(this.pinnedMessage) { // * replace with new one
if(this.chat.type === 'chat') {
if(this.chat.wasAlreadyUsed) { // * change
@ -737,15 +737,7 @@ export default class ChatTopbar { @@ -737,15 +737,7 @@ export default class ChatTopbar {
this.pinnedMessage = newPinnedMessage;
}
apiManagerProxy.getState().then((state) => {
if(!middleware()) return;
this.pinnedMessage.hidden = !!state.hiddenPinnedMessages[peerId];
if(!isTarget) {
this.pinnedMessage.setCorrectIndex(0);
}
});
this.pinnedMessage.hidden = !!state.hiddenPinnedMessages[peerId];
} else if(this.chat.type === 'discussion') {
this.pinnedMessage.pinnedMid = this.chat.threadId;
this.pinnedMessage.count = 1;
@ -756,9 +748,7 @@ export default class ChatTopbar { @@ -756,9 +748,7 @@ export default class ChatTopbar {
setTitleCallback();
setStatusCallback && setStatusCallback();
fastRaf(() => {
this.setMutedState();
});
this.setMutedState();
this.container.classList.remove('hide');
};

88
src/helpers/scrollSaver.ts

@ -12,7 +12,7 @@ import reflowScrollableElement from "./dom/reflowScrollableElement"; @@ -12,7 +12,7 @@ import reflowScrollableElement from "./dom/reflowScrollableElement";
export default class ScrollSaver {
private scrollHeight: number;
// private scrollHeightMinusTop: number;
private scrollHeightMinusTop: number;
private scrollTop: number;
private clientHeight: number;
private anchor: HTMLElement;
@ -60,6 +60,14 @@ export default class ScrollSaver { @@ -60,6 +60,14 @@ export default class ScrollSaver {
}
}
if(!rect) {
const bubble = bubbles[0];
if(bubble) {
rect = bubble.getBoundingClientRect();
anchor = bubble;
}
}
return {rect, anchor};
}
@ -83,7 +91,7 @@ export default class ScrollSaver { @@ -83,7 +91,7 @@ export default class ScrollSaver {
this.scrollHeight = scrollHeight;
this.scrollTop = scrollTop;
this.clientHeight = clientHeight;
// this.scrollHeightMinusTop = this.reverse ? scrollHeight - scrollTop : scrollTop;
this.scrollHeightMinusTop = this.reverse ? scrollHeight - scrollTop : scrollTop;
//this.chatInner.style.paddingTop = padding + 'px';
/* if(reverse) {
@ -113,13 +121,13 @@ export default class ScrollSaver { @@ -113,13 +121,13 @@ export default class ScrollSaver {
const {scrollTop, scrollHeight} = this.scrollable;
this.scrollHeight = scrollHeight;
// if(!this.anchor.parentElement) { // fallback to old method if element has disappeared (e.g. edited)
// this._restore(useReflow);
// return;
// }
if(!this.anchor.parentElement) { // try to find new anchor
if(!this.anchor?.parentElement) { // try to find new anchor
this.findAndSetAnchor();
if(!this.anchor) { // fallback to old method if smth is really strange
this._restore(useReflow);
return;
}
}
const rect = this.rect;
@ -129,47 +137,47 @@ export default class ScrollSaver { @@ -129,47 +137,47 @@ export default class ScrollSaver {
// console.warn('scroll restore', rect, diff, newRect);
}
// public _restore(useReflow?: boolean) {
// const {scrollHeightMinusTop: previousScrollHeightMinusTop, scrollable} = this;
// // if(previousScrollHeightMinusTop === undefined) {
// // throw new Error('scroll was not saved');
// // }
public _restore(useReflow?: boolean) {
const {scrollHeightMinusTop: previousScrollHeightMinusTop, scrollable} = this;
// if(previousScrollHeightMinusTop === undefined) {
// throw new Error('scroll was not saved');
// }
// // const scrollHeight = container.scrollHeight;
// const scrollHeight = this.scrollHeight;
// // if(scrollHeight === this.scrollHeight) {
// // return;
// // }
// const scrollHeight = container.scrollHeight;
const scrollHeight = this.scrollHeight;
// if(scrollHeight === this.scrollHeight) {
// return;
// }
// // this.scrollHeight = scrollHeight;
// this.scrollHeight = scrollHeight;
// /* const scrollHeight = container.scrollHeight;
// const addedHeight = scrollHeight - previousScrollHeight;
/* const scrollHeight = container.scrollHeight;
const addedHeight = scrollHeight - previousScrollHeight;
// this.chatInner.style.paddingTop = (10000 - addedHeight) + 'px'; */
// /* const scrollHeight = scrollHeight;
// const addedHeight = scrollHeight - previousScrollHeight;
this.chatInner.style.paddingTop = (10000 - addedHeight) + 'px'; */
/* const scrollHeight = scrollHeight;
const addedHeight = scrollHeight - previousScrollHeight;
// this.chatInner.style.paddingTop = (padding - addedHeight) + 'px';
this.chatInner.style.paddingTop = (padding - addedHeight) + 'px';
// //const newScrollTop = reverse ? scrollHeight - previousScrollHeightMinusTop : previousScrollHeightMinusTop;
// const newScrollTop = reverse ? scrollHeight - addedHeight - previousScrollHeightMinusTop : previousScrollHeightMinusTop;
// this.log('performHistoryResult: will set scrollTop',
// previousScrollHeightMinusTop, scrollHeight,
// newScrollTop, container.container.clientHeight); */
// //const newScrollTop = reverse ? scrollHeight - previousScrollHeightMinusTop : previousScrollHeightMinusTop;
// const newScrollTop = this.reverse ? scrollHeight - previousScrollHeightMinusTop : previousScrollHeightMinusTop;
//const newScrollTop = reverse ? scrollHeight - previousScrollHeightMinusTop : previousScrollHeightMinusTop;
const newScrollTop = reverse ? scrollHeight - addedHeight - previousScrollHeightMinusTop : previousScrollHeightMinusTop;
this.log('performHistoryResult: will set scrollTop',
previousScrollHeightMinusTop, scrollHeight,
newScrollTop, container.container.clientHeight); */
//const newScrollTop = reverse ? scrollHeight - previousScrollHeightMinusTop : previousScrollHeightMinusTop;
const newScrollTop = this.reverse ? scrollHeight - previousScrollHeightMinusTop : previousScrollHeightMinusTop;
// /* if(DEBUG) {
// this.log('performHistoryResult: will set up scrollTop:', newScrollTop, this.isHeavyAnimationInProgress);
// } */
/* if(DEBUG) {
this.log('performHistoryResult: will set up scrollTop:', newScrollTop, this.isHeavyAnimationInProgress);
} */
// this.setScrollTop(newScrollTop, useReflow);
this.setScrollTop(newScrollTop, useReflow);
// /* if(DEBUG) {
// this.log('performHistoryResult: have set up scrollTop:', newScrollTop, container.scrollTop, container.scrollHeight, this.isHeavyAnimationInProgress);
// } */
// }
/* if(DEBUG) {
this.log('performHistoryResult: have set up scrollTop:', newScrollTop, container.scrollTop, container.scrollHeight, this.isHeavyAnimationInProgress);
} */
}
}
MOUNT_CLASS_TO && (MOUNT_CLASS_TO.ScrollSaver = ScrollSaver);

Loading…
Cancel
Save