Fix broken profile & shared media
This commit is contained in:
parent
c805347e83
commit
7b0ab07255
@ -32,11 +32,11 @@ import ListenerSetter from "../../helpers/listenerSetter";
|
||||
import PollElement from "../poll";
|
||||
import AudioElement from "../audio";
|
||||
import { ChatInvite, Document, Message, MessageEntity, MessageMedia, MessageReplyHeader, Photo, PhotoSize, ReactionCount, ReplyMarkup, SponsoredMessage, Update, User, WebPage } from "../../layer";
|
||||
import { NULL_PEER_ID, REPLIES_PEER_ID } from "../../lib/mtproto/mtproto_config";
|
||||
import { BOT_START_PARAM, NULL_PEER_ID, REPLIES_PEER_ID } from "../../lib/mtproto/mtproto_config";
|
||||
import { FocusDirection, ScrollStartCallbackDimensions } from "../../helpers/fastSmoothScroll";
|
||||
import useHeavyAnimationCheck, { getHeavyAnimationPromise, dispatchHeavyAnimationEvent, interruptHeavyAnimation } from "../../hooks/useHeavyAnimationCheck";
|
||||
import { fastRaf, fastRafPromise } from "../../helpers/schedulers";
|
||||
import deferredPromise from "../../helpers/cancellablePromise";
|
||||
import deferredPromise, { CancellablePromise } from "../../helpers/cancellablePromise";
|
||||
import RepliesElement from "./replies";
|
||||
import DEBUG from "../../config/debug";
|
||||
import { SliceEnd } from "../../helpers/slicedArray";
|
||||
@ -251,6 +251,8 @@ export default class ChatBubbles {
|
||||
private updatePlaceholderPosition: () => void;
|
||||
private setPeerOptions: {lastMsgId: number; topMessage: number;};
|
||||
|
||||
private setPeerTempId: number = 0;
|
||||
|
||||
// private reactions: Map<number, ReactionsElement>;
|
||||
|
||||
constructor(
|
||||
@ -2522,6 +2524,8 @@ export default class ChatBubbles {
|
||||
}
|
||||
|
||||
public async setPeer(samePeer: boolean, peerId: PeerId, lastMsgId?: number, startParam?: string): Promise<{cached?: boolean, promise: Chat['setPeerPromise']}> {
|
||||
const tempId = ++this.setPeerTempId;
|
||||
|
||||
if(!peerId) {
|
||||
this.cleanup(true);
|
||||
this.preloader.detach();
|
||||
@ -2532,6 +2536,16 @@ export default class ChatBubbles {
|
||||
const log = this.log.bindPrefix('setPeer');
|
||||
log.warn('start');
|
||||
|
||||
const middleware = () => {
|
||||
return this.setPeerTempId === tempId;
|
||||
};
|
||||
|
||||
const m = middlewarePromise(middleware, PEER_CHANGED_ERROR);
|
||||
|
||||
if(!samePeer) {
|
||||
await m(this.chat.onChangePeer(m));
|
||||
}
|
||||
|
||||
/* if(samePeer && this.chat.setPeerPromise) {
|
||||
return {cached: true, promise: this.chat.setPeerPromise};
|
||||
} */
|
||||
@ -2542,8 +2556,8 @@ export default class ChatBubbles {
|
||||
lastMsgId = 0;
|
||||
}
|
||||
|
||||
const historyStorage = await this.chat.getHistoryStorage();
|
||||
let topMessage = chatType === 'pinned' ? await this.managers.appMessagesManager.getPinnedMessagesMaxId(peerId) : historyStorage.maxId ?? 0;
|
||||
const historyStorage = await m(this.chat.getHistoryStorage());
|
||||
let topMessage = chatType === 'pinned' ? await m(this.managers.appMessagesManager.getPinnedMessagesMaxId(peerId)) : historyStorage.maxId ?? 0;
|
||||
const isTarget = lastMsgId !== undefined;
|
||||
|
||||
// * this one will fix topMessage for null message in history (e.g. channel comments with only 1 comment and it is a topMessage)
|
||||
@ -2561,8 +2575,8 @@ export default class ChatBubbles {
|
||||
if(savedPosition) {
|
||||
|
||||
} else if(topMessage) {
|
||||
readMaxId = await this.managers.appMessagesManager.getReadMaxIdIfUnread(peerId, this.chat.threadId);
|
||||
const dialog = await this.managers.appMessagesManager.getDialogOnly(peerId);
|
||||
readMaxId = await m(this.managers.appMessagesManager.getReadMaxIdIfUnread(peerId, this.chat.threadId));
|
||||
const dialog = await m(this.managers.appMessagesManager.getDialogOnly(peerId));
|
||||
if(/* dialog.unread_count */readMaxId && !samePeer && (!dialog || dialog.unread_count !== 1)) {
|
||||
const foundSlice = historyStorage.history.findSliceOffset(readMaxId);
|
||||
if(foundSlice && foundSlice.slice.isEnd(SliceEnd.Bottom)) {
|
||||
@ -2580,8 +2594,12 @@ export default class ChatBubbles {
|
||||
|
||||
const isJump = lastMsgId !== topMessage/* && overrideAdditionMsgId === undefined */;
|
||||
|
||||
if(startParam === undefined && await m(this.chat.isStartButtonNeeded())) {
|
||||
startParam = BOT_START_PARAM;
|
||||
}
|
||||
|
||||
if(samePeer) {
|
||||
const mounted = await this.getMountedBubble(lastMsgId);
|
||||
const mounted = await m(this.getMountedBubble(lastMsgId));
|
||||
if(mounted) {
|
||||
if(isTarget) {
|
||||
this.scrollToBubble(mounted.bubble, 'center');
|
||||
@ -2609,7 +2627,7 @@ export default class ChatBubbles {
|
||||
this.replyFollowHistory.length = 0;
|
||||
|
||||
this.passEntities = {
|
||||
messageEntityBotCommand: await this.managers.appPeersManager.isAnyGroup(peerId) || await this.managers.appUsersManager.isBot(peerId)
|
||||
messageEntityBotCommand: await m(this.managers.appPeersManager.isAnyGroup(peerId)) || await m(this.managers.appUsersManager.isBot(peerId))
|
||||
};
|
||||
}
|
||||
|
||||
@ -2636,13 +2654,9 @@ export default class ChatBubbles {
|
||||
this.destroyResizeObserver();
|
||||
}
|
||||
|
||||
// const oldContainer = this.container;
|
||||
const oldChatInner = this.chatInner;
|
||||
const oldPlaceholderBubble = this.emptyPlaceholderBubble;
|
||||
this.cleanup();
|
||||
// this.constructBubbles();
|
||||
// const container = this.container;
|
||||
// const chatInner = this.chatInner;/* = document.createElement('div'); */
|
||||
const chatInner = this.chatInner = document.createElement('div');
|
||||
if(samePeer) {
|
||||
chatInner.className = oldChatInner.className;
|
||||
@ -2667,7 +2681,7 @@ export default class ChatBubbles {
|
||||
|
||||
let result: Awaited<ReturnType<ChatBubbles['getHistory']>>;
|
||||
if(!savedPosition) {
|
||||
result = await this.getHistory1(lastMsgId, true, isJump, additionMsgId);
|
||||
result = await m(this.getHistory1(lastMsgId, true, isJump, additionMsgId));
|
||||
} else {
|
||||
result = {
|
||||
promise: getHeavyAnimationPromise().then(() => {
|
||||
@ -2684,10 +2698,8 @@ export default class ChatBubbles {
|
||||
|
||||
const {promise, cached} = result;
|
||||
|
||||
const middleware = this.getMiddleware();
|
||||
if(!cached && !samePeer) {
|
||||
await this.chat.finishPeerChange(isTarget, isJump, lastMsgId, startParam);
|
||||
if(!middleware()) throw PEER_CHANGED_ERROR;
|
||||
await m(this.chat.finishPeerChange(isTarget, isJump, lastMsgId, startParam));
|
||||
this.scrollable.container.textContent = '';
|
||||
// oldContainer.textContent = '';
|
||||
//oldChatInner.remove();
|
||||
@ -2698,14 +2710,13 @@ export default class ChatBubbles {
|
||||
this.ladderDeferred = deferredPromise<void>(); */
|
||||
|
||||
animationIntersector.lockGroup(CHAT_ANIMATION_GROUP);
|
||||
const setPeerPromise = promise.then(async() => {
|
||||
const setPeerPromise = m(promise).then(async() => {
|
||||
log.warn('promise fulfilled');
|
||||
|
||||
let mountedByLastMsgId = haveToScrollToBubble ? await (lastMsgId ? this.getMountedBubble(lastMsgId) : {bubble: this.getLastBubble()}) : undefined;
|
||||
let mountedByLastMsgId = haveToScrollToBubble ? await m(lastMsgId ? this.getMountedBubble(lastMsgId) : {bubble: this.getLastBubble()}) : undefined;
|
||||
if(cached && !samePeer) {
|
||||
log.warn('finishing peer change');
|
||||
await this.chat.finishPeerChange(isTarget, isJump, lastMsgId, startParam); // * костыль
|
||||
if(!middleware()) throw PEER_CHANGED_ERROR;
|
||||
await m(this.chat.finishPeerChange(isTarget, isJump, lastMsgId, startParam)); // * костыль
|
||||
log.warn('finished peer change');
|
||||
}
|
||||
|
||||
@ -2838,7 +2849,7 @@ export default class ChatBubbles {
|
||||
}
|
||||
|
||||
if(chatType === 'chat') {
|
||||
const dialog = await this.managers.appMessagesManager.getDialogOnly(peerId);
|
||||
const dialog = await m(this.managers.appMessagesManager.getDialogOnly(peerId));
|
||||
if(dialog?.pFlags.unread_mark) {
|
||||
this.managers.appMessagesManager.markDialogUnread(peerId, true);
|
||||
}
|
||||
|
@ -16,7 +16,7 @@ import ChatContextMenu from "./contextMenu";
|
||||
import ChatInput from "./input";
|
||||
import ChatSelection from "./selection";
|
||||
import ChatTopbar from "./topbar";
|
||||
import { BOT_START_PARAM, NULL_PEER_ID, REPLIES_PEER_ID } from "../../lib/mtproto/mtproto_config";
|
||||
import { NULL_PEER_ID, REPLIES_PEER_ID } from "../../lib/mtproto/mtproto_config";
|
||||
import SetTransition from "../singleTransition";
|
||||
import AppPrivateSearchTab from "../sidebarRight/tabs/search";
|
||||
import renderImageFromUrl from "../../helpers/dom/renderImageFromUrl";
|
||||
@ -32,6 +32,8 @@ import SlicedArray from "../../helpers/slicedArray";
|
||||
import themeController from "../../helpers/themeController";
|
||||
import AppSharedMediaTab from "../sidebarRight/tabs/sharedMedia";
|
||||
import noop from "../../helpers/noop";
|
||||
import middlewarePromise from "../../helpers/middlewarePromise";
|
||||
import indexOfAndSplice from "../../helpers/array/indexOfAndSplice";
|
||||
|
||||
export type ChatType = 'chat' | 'pinned' | 'replies' | 'discussion' | 'scheduled';
|
||||
|
||||
@ -74,6 +76,7 @@ export default class Chat extends EventListenerBase<{
|
||||
public backgroundTempId: number;
|
||||
public setBackgroundPromise: Promise<void>;
|
||||
public sharedMediaTab: AppSharedMediaTab;
|
||||
public sharedMediaTabs: AppSharedMediaTab[];
|
||||
// public renderDarkPattern: () => Promise<void>;
|
||||
|
||||
public isAnyGroup: boolean;
|
||||
@ -103,6 +106,7 @@ export default class Chat extends EventListenerBase<{
|
||||
this.appImManager.chatsContainer.append(this.container);
|
||||
|
||||
this.backgroundTempId = 0;
|
||||
this.sharedMediaTabs = [];
|
||||
}
|
||||
|
||||
public setBackground(url: string, skipAnimation?: boolean): Promise<void> {
|
||||
@ -388,6 +392,35 @@ export default class Chat extends EventListenerBase<{
|
||||
this.topbar.cleanup();
|
||||
this.selection.cleanup();
|
||||
}
|
||||
|
||||
public async onChangePeer(m: ReturnType<typeof middlewarePromise>) {
|
||||
const {peerId} = this;
|
||||
|
||||
const searchTab = appSidebarRight.getTab(AppPrivateSearchTab);
|
||||
if(searchTab) {
|
||||
searchTab.close();
|
||||
}
|
||||
|
||||
const [noForwards, isRestricted, isAnyGroup] = await m(Promise.all([
|
||||
this.managers.appPeersManager.noForwards(peerId),
|
||||
this.managers.appPeersManager.isRestricted(peerId),
|
||||
this._isAnyGroup(peerId),
|
||||
this.setAutoDownloadMedia()
|
||||
]));
|
||||
|
||||
this.noForwards = noForwards;
|
||||
this.isRestricted = isRestricted;
|
||||
this.isAnyGroup = isAnyGroup;
|
||||
|
||||
this.container.classList.toggle('no-forwards', this.noForwards);
|
||||
|
||||
this.sharedMediaTab = appSidebarRight.createSharedMediaTab();
|
||||
this.sharedMediaTabs.push(this.sharedMediaTab);
|
||||
|
||||
this.sharedMediaTab.setPeer(peerId, this.threadId);
|
||||
this.input.clearHelper(); // костыль
|
||||
this.selection.cleanup(); // TODO: REFACTOR !!!!!!
|
||||
}
|
||||
|
||||
public async setPeer(peerId: PeerId, lastMsgId?: number, startParam?: string) {
|
||||
if(!peerId) {
|
||||
@ -418,59 +451,11 @@ export default class Chat extends EventListenerBase<{
|
||||
return;
|
||||
}
|
||||
|
||||
let sharedMediaTabs: AppSharedMediaTab[], sharedMediaTab = this.sharedMediaTab;
|
||||
// set new
|
||||
if(!samePeer) {
|
||||
const searchTab = appSidebarRight.getTab(AppPrivateSearchTab);
|
||||
if(searchTab) {
|
||||
searchTab.close();
|
||||
}
|
||||
|
||||
const [noForwards, isRestricted, isAnyGroup] = await Promise.all([
|
||||
this.managers.appPeersManager.noForwards(peerId),
|
||||
this.managers.appPeersManager.isRestricted(peerId),
|
||||
this._isAnyGroup(peerId),
|
||||
this.setAutoDownloadMedia()
|
||||
]);
|
||||
|
||||
this.noForwards = noForwards;
|
||||
this.isRestricted = isRestricted;
|
||||
this.isAnyGroup = isAnyGroup;
|
||||
|
||||
this.container.classList.toggle('no-forwards', this.noForwards);
|
||||
|
||||
sharedMediaTabs = [
|
||||
sharedMediaTab,
|
||||
sharedMediaTab = this.sharedMediaTab = appSidebarRight.createSharedMediaTab()
|
||||
];
|
||||
|
||||
sharedMediaTab.setPeer(peerId, this.threadId);
|
||||
this.input.clearHelper(); // костыль
|
||||
this.selection.cleanup(); // TODO: REFACTOR !!!!!!
|
||||
}
|
||||
|
||||
this.peerChanged = samePeer;
|
||||
|
||||
if(startParam === undefined && await this.isStartButtonNeeded()) {
|
||||
startParam = BOT_START_PARAM;
|
||||
}
|
||||
|
||||
const bubblesSetPeerPromise = this.bubbles.setPeer(samePeer, peerId, lastMsgId, startParam);
|
||||
const setPeerPromise = this.setPeerPromise = bubblesSetPeerPromise.then((result) => {
|
||||
if(!result) {
|
||||
return;
|
||||
}
|
||||
|
||||
if(!samePeer) {
|
||||
sharedMediaTab.setLoadMutex(setPeerPromise);
|
||||
sharedMediaTab.loadSidebarMedia(true);
|
||||
}
|
||||
|
||||
return result.promise.catch(noop).finally(() => {
|
||||
if(sharedMediaTabs) {
|
||||
sharedMediaTabs.filter((tab) => tab && this.sharedMediaTab !== tab).forEach((tab) => this.destroySharedMediaTab(tab));
|
||||
}
|
||||
});
|
||||
return result.promise;
|
||||
}).catch(noop).finally(() => {
|
||||
if(this.setPeerPromise === setPeerPromise) {
|
||||
this.setPeerPromise = null;
|
||||
@ -481,6 +466,7 @@ export default class Chat extends EventListenerBase<{
|
||||
}
|
||||
|
||||
public destroySharedMediaTab(tab = this.sharedMediaTab) {
|
||||
indexOfAndSplice(this.sharedMediaTabs, tab);
|
||||
tab.destroy();
|
||||
}
|
||||
|
||||
@ -504,6 +490,7 @@ export default class Chat extends EventListenerBase<{
|
||||
this.cleanup(false);
|
||||
|
||||
const sharedMediaTab = this.sharedMediaTab;
|
||||
sharedMediaTab.loadSidebarMedia(true);
|
||||
|
||||
const callbacksPromise = Promise.all([
|
||||
this.topbar.finishPeerChange(isTarget),
|
||||
@ -526,6 +513,8 @@ export default class Chat extends EventListenerBase<{
|
||||
|
||||
appSidebarRight.replaceSharedMediaTab(sharedMediaTab);
|
||||
|
||||
this.sharedMediaTabs.filter((tab) => tab !== sharedMediaTab).forEach((tab) => this.destroySharedMediaTab(tab));
|
||||
|
||||
this.log.setPrefix('CHAT-' + peerId + '-' + this.type);
|
||||
|
||||
this.appImManager.dispatchEvent('peer_changed', peerId);
|
||||
|
@ -6,6 +6,14 @@
|
||||
|
||||
export default function middlewarePromise(middleware: () => boolean, throwWhat: any = '') {
|
||||
return <T>(promise: T): T => {
|
||||
if(!(promise instanceof Promise)) {
|
||||
if(promise instanceof Error) {
|
||||
throw promise;
|
||||
} else {
|
||||
return promise;
|
||||
}
|
||||
}
|
||||
|
||||
return (promise as any as Promise<any>).then((result) => {
|
||||
if(!middleware()) {
|
||||
throw throwWhat;
|
||||
|
Loading…
x
Reference in New Issue
Block a user