Fix displaying forwarded messages
Fix order of forward's caption
This commit is contained in:
parent
916b77e567
commit
66850dd735
@ -36,7 +36,7 @@ import { BOT_START_PARAM, NULL_PEER_ID, REPLIES_PEER_ID } from "../../lib/mtprot
|
||||
import { FocusDirection, ScrollStartCallbackDimensions } from "../../helpers/fastSmoothScroll";
|
||||
import useHeavyAnimationCheck, { getHeavyAnimationPromise, dispatchHeavyAnimationEvent, interruptHeavyAnimation } from "../../hooks/useHeavyAnimationCheck";
|
||||
import { fastRaf, fastRafPromise } from "../../helpers/schedulers";
|
||||
import deferredPromise, { CancellablePromise } from "../../helpers/cancellablePromise";
|
||||
import deferredPromise from "../../helpers/cancellablePromise";
|
||||
import RepliesElement from "./replies";
|
||||
import DEBUG from "../../config/debug";
|
||||
import { SliceEnd } from "../../helpers/slicedArray";
|
||||
@ -49,7 +49,6 @@ import { getMiddleware } from "../../helpers/middleware";
|
||||
import cancelEvent from "../../helpers/dom/cancelEvent";
|
||||
import { attachClickEvent, simulateClickEvent } from "../../helpers/dom/clickEvent";
|
||||
import htmlToDocumentFragment from "../../helpers/dom/htmlToDocumentFragment";
|
||||
import positionElementByIndex from "../../helpers/dom/positionElementByIndex";
|
||||
import reflowScrollableElement from "../../helpers/dom/reflowScrollableElement";
|
||||
import replaceContent from "../../helpers/dom/replaceContent";
|
||||
import setInnerHTML from "../../helpers/dom/setInnerHTML";
|
||||
@ -98,7 +97,6 @@ import getPeerId from "../../lib/appManagers/utils/peers/getPeerId";
|
||||
import getServerMessageId from "../../lib/appManagers/utils/messageId/getServerMessageId";
|
||||
import generateMessageId from "../../lib/appManagers/utils/messageId/generateMessageId";
|
||||
import { AppManagers } from "../../lib/appManagers/managers";
|
||||
import filterAsync from "../../helpers/array/filterAsync";
|
||||
import { Awaited } from "../../types";
|
||||
import idleController from "../../helpers/idleController";
|
||||
import overlayCounter from "../../helpers/overlayCounter";
|
||||
@ -106,10 +104,10 @@ import { cancelContextMenuOpening } from "../../helpers/dom/attachContextMenuLis
|
||||
import contextMenuController from "../../helpers/contextMenuController";
|
||||
import { AckedResult } from "../../lib/mtproto/superMessagePort";
|
||||
import middlewarePromise from "../../helpers/middlewarePromise";
|
||||
import findAndSplice from "../../helpers/array/findAndSplice";
|
||||
import { EmoticonsDropdown } from "../emoticonsDropdown";
|
||||
import indexOfAndSplice from "../../helpers/array/indexOfAndSplice";
|
||||
import noop from "../../helpers/noop";
|
||||
import getAlbumText from "../../lib/appManagers/utils/messages/getAlbumText";
|
||||
|
||||
const USE_MEDIA_TAILS = false;
|
||||
const IGNORE_ACTIONS: Set<Message.messageService['action']['_']> = new Set([
|
||||
@ -283,11 +281,12 @@ export default class ChatBubbles {
|
||||
// * events
|
||||
|
||||
// will call when sent for update pos
|
||||
this.listenerSetter.add(rootScope)('history_update', async({storageKey, mid, message}) => {
|
||||
this.listenerSetter.add(rootScope)('history_update', async({storageKey, sequential, message}) => {
|
||||
if(this.chat.messagesStorageKey !== storageKey || this.chat.type === 'scheduled') {
|
||||
return;
|
||||
}
|
||||
|
||||
const {mid} = message;
|
||||
const log = false ? this.log.bindPrefix('history_update-' + mid) : undefined;
|
||||
log && log('start');
|
||||
|
||||
@ -317,16 +316,22 @@ export default class ChatBubbles {
|
||||
return;
|
||||
}
|
||||
|
||||
const group = item.group;
|
||||
const newItem = this.bubbleGroups.createItem(bubble, message);
|
||||
// newItem.mid = item.mid;
|
||||
const _items = this.bubbleGroups.itemsArr.slice();
|
||||
indexOfAndSplice(_items, item);
|
||||
const foundItem = this.bubbleGroups.findGroupSiblingByItem(newItem, _items);
|
||||
if(group === foundItem?.group || (group === this.bubbleGroups.getLastGroup() && group.items.length === 1)/* && false */) {
|
||||
log && log('item has correct position', item);
|
||||
this.bubbleGroups.changeBubbleMid(bubble, mid);
|
||||
return;
|
||||
if(sequential) {
|
||||
const group = item.group;
|
||||
const newItem = this.bubbleGroups.createItem(bubble, message);
|
||||
// newItem.mid = item.mid;
|
||||
const _items = this.bubbleGroups.itemsArr.slice();
|
||||
indexOfAndSplice(_items, item);
|
||||
const foundItem = this.bubbleGroups.findGroupSiblingByItem(newItem, _items);
|
||||
if(
|
||||
group === foundItem?.group
|
||||
|| (group === this.bubbleGroups.getLastGroup() && group.items.length === 1 && newItem.dateTimestamp === item.dateTimestamp)
|
||||
|| (this.peerId === rootScope.myId && sequential && newItem.dateTimestamp === item.dateTimestamp)
|
||||
) {
|
||||
log && log('item has correct position', item);
|
||||
this.bubbleGroups.changeBubbleMid(bubble, mid);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// return;
|
||||
@ -436,12 +441,12 @@ export default class ChatBubbles {
|
||||
let messages: (Message.message | Message.messageService)[], tempIds: number[];
|
||||
const groupedId = (message as Message.message).grouped_id;
|
||||
if(groupedId) {
|
||||
const mids = await this.managers.appMessagesManager.getMidsByMessage(message);
|
||||
messages = await this.managers.appMessagesManager.getMessagesByAlbum(groupedId);
|
||||
const mids = messages.map(({mid}) => mid);
|
||||
if(!mids.length || getMainMidForGrouped(mids) !== mid || bubbles[mid] !== _bubble) {
|
||||
return;
|
||||
}
|
||||
|
||||
messages = await Promise.all(mids.map((mid) => this.chat.getMessage(mid)));
|
||||
if(bubbles[mid] !== _bubble) {
|
||||
return;
|
||||
}
|
||||
@ -835,13 +840,13 @@ export default class ChatBubbles {
|
||||
|
||||
public constructPeerHelpers() {
|
||||
// will call when message is sent (only 1)
|
||||
this.listenerSetter.add(rootScope)('history_append', async({storageKey, mid}) => {
|
||||
this.listenerSetter.add(rootScope)('history_append', async({storageKey, message}) => {
|
||||
if(storageKey !== this.chat.messagesStorageKey) return;
|
||||
|
||||
if(!this.scrollable.loadedAll.bottom) {
|
||||
this.chat.setMessageId();
|
||||
} else {
|
||||
this.renderNewMessagesByIds([mid], true);
|
||||
this.renderNewMessage(message, true);
|
||||
}
|
||||
|
||||
if(rootScope.settings.animationsEnabled) {
|
||||
@ -852,10 +857,9 @@ export default class ChatBubbles {
|
||||
}
|
||||
});
|
||||
|
||||
this.listenerSetter.add(rootScope)('history_multiappend', (msgIdsByPeer) => {
|
||||
if(!(this.peerId in msgIdsByPeer)) return;
|
||||
const msgIds = Array.from(msgIdsByPeer[this.peerId]).slice().sort((a, b) => b - a);
|
||||
this.renderNewMessagesByIds(msgIds);
|
||||
this.listenerSetter.add(rootScope)('history_multiappend', (message) => {
|
||||
if(this.peerId !== message.peerId) return;
|
||||
this.renderNewMessage(message);
|
||||
});
|
||||
|
||||
this.listenerSetter.add(rootScope)('history_delete', ({peerId, msgs}) => {
|
||||
@ -1377,10 +1381,10 @@ export default class ChatBubbles {
|
||||
this.chat.topbar.setTitle((await this.managers.appMessagesManager.getScheduledMessagesStorage(this.peerId)).size);
|
||||
};
|
||||
|
||||
this.listenerSetter.add(rootScope)('scheduled_new', ({peerId, mid}) => {
|
||||
if(peerId !== this.peerId) return;
|
||||
this.listenerSetter.add(rootScope)('scheduled_new', (message) => {
|
||||
if(message.peerId !== this.peerId) return;
|
||||
|
||||
this.renderNewMessagesByIds([mid]);
|
||||
this.renderNewMessage(message);
|
||||
onUpdate();
|
||||
});
|
||||
|
||||
@ -2162,8 +2166,8 @@ export default class ChatBubbles {
|
||||
};
|
||||
}
|
||||
|
||||
private renderNewMessagesByIds(mids: number[], scrolledDown?: boolean) {
|
||||
const promise = this._renderNewMessagesByIds(mids, scrolledDown);
|
||||
private renderNewMessage(message: MyMessage, scrolledDown?: boolean) {
|
||||
const promise = this._renderNewMessage(message, scrolledDown);
|
||||
this.renderNewPromises.add(promise);
|
||||
promise.catch(noop).finally(() => {
|
||||
this.renderNewPromises.delete(promise);
|
||||
@ -2171,15 +2175,17 @@ export default class ChatBubbles {
|
||||
return promise;
|
||||
}
|
||||
|
||||
private async _renderNewMessagesByIds(mids: number[], scrolledDown?: boolean) {
|
||||
private async _renderNewMessage(message: MyMessage, scrolledDown?: boolean) {
|
||||
if(!this.scrollable.loadedAll.bottom) { // seems search active or sliced
|
||||
//this.log('renderNewMessagesByIds: seems search is active, skipping render:', mids);
|
||||
const setPeerPromise = this.chat.setPeerPromise;
|
||||
if(setPeerPromise) {
|
||||
const middleware = this.getMiddleware();
|
||||
setPeerPromise.then(() => {
|
||||
setPeerPromise.then(async() => {
|
||||
if(!middleware()) return;
|
||||
this.renderNewMessagesByIds(mids);
|
||||
const newMessage = await this.chat.getMessage(message.mid);
|
||||
if(!middleware()) return;
|
||||
this.renderNewMessage(newMessage);
|
||||
});
|
||||
}
|
||||
|
||||
@ -2187,14 +2193,15 @@ export default class ChatBubbles {
|
||||
}
|
||||
|
||||
if(this.chat.threadId) {
|
||||
mids = await filterAsync(mids, async(mid) => {
|
||||
const message = await this.chat.getMessage(mid);
|
||||
const replyTo = message?.reply_to as MessageReplyHeader;
|
||||
return replyTo && (replyTo.reply_to_top_id || replyTo.reply_to_msg_id) === this.chat.threadId;
|
||||
});
|
||||
const replyTo = message?.reply_to as MessageReplyHeader;
|
||||
if(!(replyTo && (replyTo.reply_to_top_id || replyTo.reply_to_msg_id) === this.chat.threadId)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
mids = mids.filter((mid) => !this.bubbles[mid]);
|
||||
if(this.bubbles[message.mid]) {
|
||||
return;
|
||||
}
|
||||
// ! should scroll even without new messages
|
||||
/* if(!mids.length) {
|
||||
return;
|
||||
@ -2211,7 +2218,7 @@ export default class ChatBubbles {
|
||||
const middleware = this.getMiddleware();
|
||||
const {isPaddingNeeded, unsetPadding} = this.setTopPadding(middleware);
|
||||
|
||||
const promise = this.performHistoryResult({history: mids}, false);
|
||||
const promise = this.performHistoryResult({history: [message]}, false);
|
||||
if(scrolledDown) {
|
||||
promise.then(() => {
|
||||
if(!middleware()) return;
|
||||
@ -2221,7 +2228,7 @@ export default class ChatBubbles {
|
||||
|
||||
let bubble: HTMLElement;
|
||||
if(this.chat.type === 'scheduled') {
|
||||
bubble = this.bubbles[Math.max(...mids)];
|
||||
bubble = this.bubbles[message.mid];
|
||||
}
|
||||
|
||||
const promise = bubble ? this.scrollToBubbleEnd(bubble) : this.scrollToEnd();
|
||||
@ -3373,10 +3380,12 @@ export default class ChatBubbles {
|
||||
const isMessage = message._ === 'message';
|
||||
const groupedId = isMessage && message.grouped_id;
|
||||
let albumMids: number[], reactionsMessage: Message.message;
|
||||
const albumMessages = groupedId ? await this.managers.appMessagesManager.getMessagesByAlbum(groupedId) : undefined;
|
||||
|
||||
const albumMustBeRenderedFull = this.chat.type !== 'pinned';
|
||||
|
||||
if(groupedId && albumMustBeRenderedFull) { // will render only last album's message
|
||||
albumMids = await this.managers.appMessagesManager.getMidsByAlbum(groupedId);
|
||||
albumMids = albumMessages.map((message) => message.mid);
|
||||
const mainMid = getMainMidForGrouped(albumMids);
|
||||
if(message.mid !== mainMid) {
|
||||
return;
|
||||
@ -3384,7 +3393,7 @@ export default class ChatBubbles {
|
||||
}
|
||||
|
||||
if(isMessage) {
|
||||
reactionsMessage = groupedId ? await this.managers.appMessagesManager.getGroupsFirstMessage(message) : message;
|
||||
reactionsMessage = groupedId ? albumMessages[0] : message;
|
||||
}
|
||||
|
||||
// * can't use 'message.pFlags.out' here because this check will be used to define side of message (left-right)
|
||||
@ -3470,7 +3479,7 @@ export default class ChatBubbles {
|
||||
!['video', 'gif'].includes(((messageMedia as MessageMedia.messageMediaDocument).document as MyDocument).type)) {
|
||||
// * just filter these cases for documents caption
|
||||
} else if(groupedId && albumMustBeRenderedFull) {
|
||||
const t = await this.managers.appMessagesManager.getAlbumText(groupedId);
|
||||
const t = getAlbumText(albumMessages);
|
||||
messageMessage = t.message;
|
||||
//totalEntities = t.entities;
|
||||
totalEntities = t.totalEntities;
|
||||
@ -3745,8 +3754,8 @@ export default class ChatBubbles {
|
||||
|
||||
if(albumMustBeRenderedFull && groupedId && albumMids.length !== 1) {
|
||||
bubble.classList.add('is-album', 'is-grouped');
|
||||
const promise = wrapAlbum({
|
||||
groupId: groupedId,
|
||||
wrapAlbum({
|
||||
messages: albumMessages,
|
||||
attachmentDiv,
|
||||
middleware: this.getMiddleware(),
|
||||
isOut: our,
|
||||
@ -3756,8 +3765,6 @@ export default class ChatBubbles {
|
||||
autoDownload: this.chat.autoDownload,
|
||||
});
|
||||
|
||||
loadPromises.push(promise);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
@ -4001,8 +4008,8 @@ export default class ChatBubbles {
|
||||
if(albumMustBeRenderedFull && groupedId && albumMids.length !== 1) {
|
||||
bubble.classList.add('is-album', 'is-grouped');
|
||||
|
||||
await wrapAlbum({
|
||||
groupId: groupedId,
|
||||
wrapAlbum({
|
||||
messages: albumMessages,
|
||||
attachmentDiv,
|
||||
middleware: this.getMiddleware(),
|
||||
isOut: our,
|
||||
|
@ -2395,7 +2395,7 @@ export default class ChatInput {
|
||||
// * wait for sendText set messageId for invokeAfterMsg
|
||||
if(this.forwarding) {
|
||||
const forwarding = copy(this.forwarding);
|
||||
setTimeout(() => {
|
||||
// setTimeout(() => {
|
||||
for(const fromPeerId in forwarding) {
|
||||
this.managers.appMessagesManager.forwardMessages(peerId, fromPeerId.toPeerId(), forwarding[fromPeerId], {
|
||||
...sendingParams,
|
||||
@ -2407,7 +2407,7 @@ export default class ChatInput {
|
||||
if(!value) {
|
||||
this.onMessageSent();
|
||||
}
|
||||
}, 0);
|
||||
// }, 0);
|
||||
}
|
||||
|
||||
// this.onMessageSent();
|
||||
|
@ -21,6 +21,7 @@ import PopupPeer, { PopupPeerButtonCallbackCheckboxes, PopupPeerCheckboxOptions
|
||||
import ButtonCorner from "../../buttonCorner";
|
||||
import { attachClickEvent } from "../../../helpers/dom/clickEvent";
|
||||
import PeerProfile from "../../peerProfile";
|
||||
import { Message } from "../../../layer";
|
||||
|
||||
const historiesStorage: {
|
||||
[peerId: PeerId]: Partial<{
|
||||
@ -156,10 +157,8 @@ export default class AppSharedMediaTab extends SliderSuperTab {
|
||||
}
|
||||
});
|
||||
|
||||
this.listenerSetter.add(rootScope)('history_multiappend', (msgIdsByPeer) => {
|
||||
for(const peerId in msgIdsByPeer) {
|
||||
this.renderNewMessages(peerId.toPeerId(), Array.from(msgIdsByPeer[peerId]));
|
||||
}
|
||||
this.listenerSetter.add(rootScope)('history_multiappend', (message) => {
|
||||
this.renderNewMessages(message);
|
||||
});
|
||||
|
||||
this.listenerSetter.add(rootScope)('history_delete', ({peerId, msgs}) => {
|
||||
@ -168,7 +167,7 @@ export default class AppSharedMediaTab extends SliderSuperTab {
|
||||
|
||||
// Calls when message successfully sent and we have an id
|
||||
this.listenerSetter.add(rootScope)('message_sent', ({message}) => {
|
||||
this.renderNewMessages(message.peerId, [message.mid]);
|
||||
this.renderNewMessages(message);
|
||||
});
|
||||
|
||||
//this.container.prepend(this.closeBtn.parentElement);
|
||||
@ -321,14 +320,12 @@ export default class AppSharedMediaTab extends SliderSuperTab {
|
||||
//console.log('construct shared media time:', performance.now() - perf);
|
||||
}
|
||||
|
||||
public async renderNewMessages(peerId: PeerId, mids: number[]) {
|
||||
public async renderNewMessages(message: Message.message | Message.messageService) {
|
||||
if(this.init) return; // * not inited yet
|
||||
|
||||
const {peerId} = message;
|
||||
if(!historiesStorage[peerId]) return;
|
||||
|
||||
const messages = await Promise.all(mids.map((mid) => this.managers.appMessagesManager.getMessageByPeer(peerId, mid)));
|
||||
|
||||
mids = mids.slice().reverse(); // ! because it will be ascend sorted array
|
||||
for(const mediaTab of this.searchSuper.mediaTabs) {
|
||||
const inputFilter = mediaTab.inputFilter;
|
||||
const history = historiesStorage[peerId][inputFilter];
|
||||
@ -336,7 +333,7 @@ export default class AppSharedMediaTab extends SliderSuperTab {
|
||||
continue;
|
||||
}
|
||||
|
||||
const filtered = this.searchSuper.filterMessagesByType(messages, inputFilter).filter((message) => !history.find((m) => m.mid === message.mid && m.peerId === message.peerId));
|
||||
const filtered = this.searchSuper.filterMessagesByType([message], inputFilter).filter((message) => !history.find((m) => m.mid === message.mid && m.peerId === message.peerId));
|
||||
if(filtered.length) {
|
||||
history.unshift(...filtered.map((message) => ({mid: message.mid, peerId: message.peerId})));
|
||||
|
||||
|
@ -6,7 +6,7 @@
|
||||
|
||||
import { ChatAutoDownloadSettings } from "../../helpers/autoDownload";
|
||||
import mediaSizes from "../../helpers/mediaSizes";
|
||||
import { PhotoSize } from "../../layer";
|
||||
import { Message, PhotoSize } from "../../layer";
|
||||
import { AppManagers } from "../../lib/appManagers/managers";
|
||||
import getMediaFromMessage from "../../lib/appManagers/utils/messages/getMediaFromMessage";
|
||||
import choosePhotoSize from "../../lib/appManagers/utils/photos/choosePhotoSize";
|
||||
@ -17,8 +17,8 @@ import prepareAlbum from "../prepareAlbum";
|
||||
import wrapPhoto from "./photo";
|
||||
import wrapVideo from "./video";
|
||||
|
||||
export default async function wrapAlbum({groupId, attachmentDiv, middleware, uploading, lazyLoadQueue, isOut, chat, loadPromises, autoDownload, managers = rootScope.managers}: {
|
||||
groupId: string,
|
||||
export default function wrapAlbum({messages, attachmentDiv, middleware, uploading, lazyLoadQueue, isOut, chat, loadPromises, autoDownload, managers = rootScope.managers}: {
|
||||
messages: Message.message[],
|
||||
attachmentDiv: HTMLElement,
|
||||
middleware?: () => boolean,
|
||||
lazyLoadQueue?: LazyLoadQueue,
|
||||
@ -32,8 +32,6 @@ export default async function wrapAlbum({groupId, attachmentDiv, middleware, upl
|
||||
const items: {size: PhotoSize.photoSize, media: any, message: any}[] = [];
|
||||
|
||||
// !lowest msgID will be the FIRST in album
|
||||
const storage = await managers.appMessagesManager.getMidsByAlbum(groupId);
|
||||
const messages = await Promise.all(storage.map((mid) => chat.getMessage(mid)));
|
||||
for(const message of messages) {
|
||||
const media = getMediaFromMessage(message);
|
||||
|
||||
@ -63,8 +61,9 @@ export default async function wrapAlbum({groupId, attachmentDiv, middleware, upl
|
||||
div.dataset.peerId = '' + message.peerId;
|
||||
const mediaDiv = div.firstElementChild as HTMLElement;
|
||||
const isPhoto = media._ === 'photo';
|
||||
let thumbPromise: Promise<any>;
|
||||
if(isPhoto) {
|
||||
wrapPhoto({
|
||||
thumbPromise = wrapPhoto({
|
||||
photo: media,
|
||||
message,
|
||||
container: mediaDiv,
|
||||
@ -79,7 +78,7 @@ export default async function wrapAlbum({groupId, attachmentDiv, middleware, upl
|
||||
managers
|
||||
});
|
||||
} else {
|
||||
wrapVideo({
|
||||
thumbPromise = wrapVideo({
|
||||
doc: message.media.document,
|
||||
container: mediaDiv,
|
||||
message,
|
||||
@ -94,5 +93,9 @@ export default async function wrapAlbum({groupId, attachmentDiv, middleware, upl
|
||||
managers
|
||||
});
|
||||
}
|
||||
|
||||
if(thumbPromise && loadPromises) {
|
||||
loadPromises.push(thumbPromise);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
export default function getObjectKeysAndSort(object: {[key: string]: any}, sort: 'asc' | 'desc' = 'asc') {
|
||||
export default function getObjectKeysAndSort(object: {[key: string]: any} | Map<number, any>, sort: 'asc' | 'desc' = 'asc') {
|
||||
if(!object) return [];
|
||||
const ids = object instanceof Map ? [...object.keys()] : Object.keys(object).map((i) => +i);
|
||||
if(sort === 'asc') return ids.sort((a, b) => a - b);
|
||||
|
@ -114,9 +114,7 @@ export default class SearchListLoader<Item extends {mid: number, peerId: PeerId}
|
||||
}
|
||||
};
|
||||
|
||||
protected onHistoryMultiappend = async(obj: {
|
||||
[peerId: string]: Set<number>;
|
||||
}) => {
|
||||
protected onHistoryMultiappend = async(message: Message.message | Message.messageService) => {
|
||||
if(this.searchContext.folderId !== undefined) {
|
||||
return;
|
||||
}
|
||||
@ -126,13 +124,11 @@ export default class SearchListLoader<Item extends {mid: number, peerId: PeerId}
|
||||
return;
|
||||
}
|
||||
|
||||
const mids = obj[this.searchContext.peerId];
|
||||
if(!mids) {
|
||||
if(message.peerId !== this.searchContext.peerId) {
|
||||
return;
|
||||
}
|
||||
|
||||
const sorted = Array.from(mids).sort((a, b) => a - b);
|
||||
const filtered = await this.filterMids(sorted);
|
||||
const filtered = await this.filterMids([message.mid]);
|
||||
const targets = (await Promise.all(filtered.map((message) => this.processItem(message)))).filter(Boolean);
|
||||
if(targets.length) {
|
||||
/* const {previous, current, next} = this;
|
||||
@ -159,9 +155,7 @@ export default class SearchListLoader<Item extends {mid: number, peerId: PeerId}
|
||||
};
|
||||
|
||||
protected onMessageSent = ({message}: {message: MyMessage}) => {
|
||||
this.onHistoryMultiappend({
|
||||
[message.peerId]: new Set([message.mid])
|
||||
});
|
||||
this.onHistoryMultiappend(message);
|
||||
};
|
||||
|
||||
public setSearchContext(context: SearchSuperContext) {
|
||||
|
@ -58,6 +58,8 @@ import type { Progress } from "./appDownloadManager";
|
||||
import noop from "../../helpers/noop";
|
||||
import appTabsManager from "./appTabsManager";
|
||||
import MTProtoMessagePort from "../mtproto/mtprotoMessagePort";
|
||||
import getAlbumText from "./utils/messages/getAlbumText";
|
||||
import pause from "../../helpers/schedulers/pause";
|
||||
|
||||
//console.trace('include');
|
||||
// TODO: если удалить диалог находясь в папке, то он не удалится из папки и будет виден в настройках
|
||||
@ -134,6 +136,11 @@ type PendingMessageDetails = {
|
||||
sequential?: boolean
|
||||
};
|
||||
|
||||
const processAfter = (cb: () => void) => {
|
||||
// setTimeout(cb, 0);
|
||||
cb();
|
||||
};
|
||||
|
||||
export class AppMessagesManager extends AppManager {
|
||||
private messagesStorageByPeerId: {[peerId: string]: MessagesStorage};
|
||||
private groupedMessagesStorage: {[groupId: string]: MessagesStorage}; // will be used for albums
|
||||
@ -186,8 +193,6 @@ export class AppMessagesManager extends AppManager {
|
||||
public migratedFromTo: {[peerId: PeerId]: PeerId} = {};
|
||||
public migratedToFrom: {[peerId: PeerId]: PeerId} = {};
|
||||
|
||||
private newMessagesHandleTimeout = 0;
|
||||
private newMessagesToHandle: {[peerId: PeerId]: Set<number>} = {};
|
||||
private newDialogsHandlePromise: Promise<any>;
|
||||
private newDialogsToHandle: {[peerId: PeerId]: Dialog} = {};
|
||||
public newUpdatesAfterReloadToHandle: {[peerId: PeerId]: Set<Update>} = {};
|
||||
@ -474,37 +479,31 @@ export class AppMessagesManager extends AppManager {
|
||||
scheduleDate: number,
|
||||
silent: true,
|
||||
sendAsPeerId: PeerId,
|
||||
}> = {}) {
|
||||
}> = {}): Promise<void> {
|
||||
if(!text.trim()) {
|
||||
return;
|
||||
}
|
||||
|
||||
options.entities ??= [];
|
||||
|
||||
//this.checkSendOptions(options);
|
||||
|
||||
if(options.threadId && !options.replyToMsgId) {
|
||||
options.replyToMsgId = options.threadId;
|
||||
}
|
||||
|
||||
|
||||
const config = await this.apiManager.getConfig();
|
||||
const MAX_LENGTH = config.message_length_max;
|
||||
if(text.length > MAX_LENGTH) {
|
||||
const splitted = splitStringByLength(text, MAX_LENGTH);
|
||||
text = splitted[0];
|
||||
|
||||
if(splitted.length > 1) {
|
||||
const splitted = splitStringByLength(text, MAX_LENGTH);
|
||||
text = splitted[0];
|
||||
if(splitted.length > 1) {
|
||||
if(options.webPage?._ === 'webPage' && !text.includes(options.webPage.url)) {
|
||||
delete options.webPage;
|
||||
}
|
||||
|
||||
for(let i = 1; i < splitted.length; ++i) {
|
||||
setTimeout(() => {
|
||||
this.sendText(peerId, splitted[i], options);
|
||||
}, i);
|
||||
}
|
||||
}
|
||||
|
||||
peerId = this.appPeersManager.getPeerMigratedTo(peerId) || peerId;
|
||||
|
||||
let entities = options.entities || [];
|
||||
|
||||
let entities = options.entities;
|
||||
if(!options.viaBotId) {
|
||||
text = parseMarkdown(text, entities);
|
||||
//entities = mergeEntities(entities, parseEntities(text));
|
||||
@ -653,7 +652,12 @@ export class AppMessagesManager extends AppManager {
|
||||
sequential: true
|
||||
});
|
||||
|
||||
return message.promise;
|
||||
const promises: ReturnType<AppMessagesManager['sendText']>[] = [message.promise];
|
||||
for(let i = 1; i < splitted.length; ++i) {
|
||||
promises.push(this.sendText(peerId, splitted[i], options));
|
||||
}
|
||||
|
||||
return Promise.all(promises).then(noop);
|
||||
}
|
||||
|
||||
public sendFile(peerId: PeerId, file: File | Blob | MyDocument, options: Partial<{
|
||||
@ -684,6 +688,9 @@ export class AppMessagesManager extends AppManager {
|
||||
noSound: boolean,
|
||||
|
||||
waveform: Uint8Array,
|
||||
|
||||
// ! only for internal use
|
||||
processAfter?: typeof processAfter
|
||||
}> = {}) {
|
||||
peerId = this.appPeersManager.getPeerMigratedTo(peerId) || peerId;
|
||||
|
||||
@ -1033,7 +1040,8 @@ export class AppMessagesManager extends AppManager {
|
||||
isGroupedItem: options.isGroupedItem,
|
||||
isScheduled: !!options.scheduleDate || undefined,
|
||||
threadId: options.threadId,
|
||||
clearDraft: options.clearDraft
|
||||
clearDraft: options.clearDraft,
|
||||
processAfter: options.processAfter
|
||||
});
|
||||
|
||||
if(!options.isGroupedItem) {
|
||||
@ -1128,6 +1136,11 @@ export class AppMessagesManager extends AppManager {
|
||||
|
||||
const groupId = '' + ++this.groupedTempId;
|
||||
|
||||
const callbacks: Array<() => void> = [];
|
||||
const processAfter = (cb: () => void) => {
|
||||
callbacks.push(cb);
|
||||
};
|
||||
|
||||
const messages = files.map((file, idx) => {
|
||||
const details = options.sendFileDetails[idx];
|
||||
const o: Parameters<AppMessagesManager['sendFile']>[2] = {
|
||||
@ -1139,6 +1152,7 @@ export class AppMessagesManager extends AppManager {
|
||||
threadId: options.threadId,
|
||||
sendAsPeerId: options.sendAsPeerId,
|
||||
groupId,
|
||||
processAfter,
|
||||
...details
|
||||
};
|
||||
|
||||
@ -1152,11 +1166,15 @@ export class AppMessagesManager extends AppManager {
|
||||
});
|
||||
|
||||
if(options.clearDraft) {
|
||||
setTimeout(() => {
|
||||
callbacks.push(() => {
|
||||
this.appDraftsManager.clearDraft(peerId, options.threadId);
|
||||
}, 0);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
callbacks.forEach((callback) => {
|
||||
callback();
|
||||
});
|
||||
|
||||
// * test pending
|
||||
//return;
|
||||
|
||||
@ -1451,18 +1469,19 @@ export class AppMessagesManager extends AppManager {
|
||||
isScheduled: true,
|
||||
threadId: number,
|
||||
clearDraft: true,
|
||||
sequential: boolean
|
||||
sequential: boolean,
|
||||
processAfter?: (cb: () => void) => void
|
||||
}> = {}) {
|
||||
const messageId = message.id;
|
||||
const peerId = this.getMessagePeer(message);
|
||||
const storage = options.isScheduled ? this.getScheduledMessagesStorage(peerId) : this.getHistoryMessagesStorage(peerId);
|
||||
|
||||
let callbacks: Array<() => void> = [];
|
||||
if(options.isScheduled) {
|
||||
//if(!options.isGroupedItem) {
|
||||
this.saveMessages([message], {storage, isScheduled: true, isOutgoing: true});
|
||||
setTimeout(() => {
|
||||
this.rootScope.dispatchEvent('scheduled_new', {peerId, mid: messageId});
|
||||
}, 0);
|
||||
callbacks.push(() => {
|
||||
this.rootScope.dispatchEvent('scheduled_new', message);
|
||||
});
|
||||
} else {
|
||||
/* if(options.threadId && this.threadsStorage[peerId]) {
|
||||
delete this.threadsStorage[peerId][options.threadId];
|
||||
@ -1478,12 +1497,11 @@ export class AppMessagesManager extends AppManager {
|
||||
}
|
||||
}
|
||||
|
||||
//if(!options.isGroupedItem) {
|
||||
this.saveMessages([message], {storage, isOutgoing: true});
|
||||
this.setDialogTopMessage(message);
|
||||
setTimeout(() => {
|
||||
this.rootScope.dispatchEvent('history_append', {storageKey: storage.key, peerId, mid: messageId});
|
||||
}, 0);
|
||||
callbacks.push(() => {
|
||||
this.rootScope.dispatchEvent('history_append', {storageKey: storage.key, message});
|
||||
});
|
||||
}
|
||||
|
||||
const pending: PendingMessageDetails = this.pendingByRandomId[message.random_id] = {
|
||||
@ -1495,13 +1513,21 @@ export class AppMessagesManager extends AppManager {
|
||||
};
|
||||
|
||||
if(!options.isGroupedItem && message.send) {
|
||||
setTimeout(() => {
|
||||
callbacks.push(() => {
|
||||
if(options.clearDraft) {
|
||||
this.appDraftsManager.clearDraft(peerId, options.threadId);
|
||||
}
|
||||
|
||||
message.send();
|
||||
}, 0/* 3000 */);
|
||||
});
|
||||
}
|
||||
|
||||
if(callbacks.length) {
|
||||
(options.processAfter || processAfter)(() => {
|
||||
for(const callback of callbacks) {
|
||||
callback();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
return pending;
|
||||
@ -2280,51 +2306,47 @@ export class AppMessagesManager extends AppManager {
|
||||
return promise || this.reloadConversationsPromise;
|
||||
}
|
||||
|
||||
this.reloadConversationsPromise = new Promise((resolve, reject) => {
|
||||
setTimeout(() => {
|
||||
const inputDialogPeers: InputDialogPeer[] = [];
|
||||
const promises: {[peerId: string]: typeof promise} = {};
|
||||
for(const [peerId, {inputDialogPeer, promise}] of this.reloadConversationsPeers) {
|
||||
inputDialogPeers.push(inputDialogPeer);
|
||||
promises[peerId] = promise;
|
||||
this.reloadConversationsPromise = pause(0).then(() => {
|
||||
const inputDialogPeers: InputDialogPeer[] = [];
|
||||
const promises: {[peerId: string]: typeof promise} = {};
|
||||
for(const [peerId, {inputDialogPeer, promise}] of this.reloadConversationsPeers) {
|
||||
inputDialogPeers.push(inputDialogPeer);
|
||||
promises[peerId] = promise;
|
||||
}
|
||||
|
||||
this.reloadConversationsPeers.clear();
|
||||
|
||||
const fullfillLeft = () => {
|
||||
for(const peerId in promises) {
|
||||
promises[peerId].resolve(undefined);
|
||||
}
|
||||
};
|
||||
|
||||
this.reloadConversationsPeers.clear();
|
||||
return this.apiManager.invokeApi('messages.getPeerDialogs', {peers: inputDialogPeers}).then((result) => {
|
||||
this.dialogsStorage.applyDialogs(result);
|
||||
|
||||
const fullfillLeft = () => {
|
||||
for(const peerId in promises) {
|
||||
promises[peerId].resolve(undefined);
|
||||
}
|
||||
};
|
||||
|
||||
this.apiManager.invokeApi('messages.getPeerDialogs', {peers: inputDialogPeers}).then((result) => {
|
||||
this.dialogsStorage.applyDialogs(result);
|
||||
|
||||
result.dialogs.forEach((dialog) => {
|
||||
const peerId = dialog.peerId;
|
||||
if(peerId) {
|
||||
promises[peerId].resolve(dialog as Dialog);
|
||||
delete promises[peerId];
|
||||
}
|
||||
});
|
||||
|
||||
// fullfillLeft();
|
||||
// resolve();
|
||||
}, (err) => {
|
||||
// fullfillLeft();
|
||||
// resolve();
|
||||
// reject(err);
|
||||
}).finally(() => {
|
||||
fullfillLeft();
|
||||
resolve();
|
||||
|
||||
this.reloadConversationsPromise = null;
|
||||
|
||||
if(this.reloadConversationsPeers.size) {
|
||||
this.reloadConversation();
|
||||
result.dialogs.forEach((dialog) => {
|
||||
const peerId = dialog.peerId;
|
||||
if(peerId) {
|
||||
promises[peerId].resolve(dialog as Dialog);
|
||||
delete promises[peerId];
|
||||
}
|
||||
});
|
||||
}, 0);
|
||||
|
||||
// fullfillLeft();
|
||||
// resolve();
|
||||
}, (err) => {
|
||||
// fullfillLeft();
|
||||
// resolve();
|
||||
// reject(err);
|
||||
}).then(() => {
|
||||
fullfillLeft();
|
||||
|
||||
this.reloadConversationsPromise = null;
|
||||
if(this.reloadConversationsPeers.size) {
|
||||
this.reloadConversation();
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
return promise || this.reloadConversationsPromise;
|
||||
@ -2506,24 +2528,7 @@ export class AppMessagesManager extends AppManager {
|
||||
|
||||
public getAlbumText(grouped_id: string) {
|
||||
const group = this.groupedMessagesStorage[grouped_id];
|
||||
let foundMessages = 0, message: string, totalEntities: MessageEntity[], entities: MessageEntity[];
|
||||
for(const [mid, m] of group) {
|
||||
assumeType<Message.message>(m);
|
||||
if(m.message) {
|
||||
if(++foundMessages > 1) break;
|
||||
message = m.message;
|
||||
totalEntities = m.totalEntities;
|
||||
entities = m.entities;
|
||||
}
|
||||
}
|
||||
|
||||
if(foundMessages > 1) {
|
||||
message = undefined;
|
||||
totalEntities = undefined;
|
||||
entities = undefined;
|
||||
}
|
||||
|
||||
return {message, entities, totalEntities};
|
||||
return getAlbumText(Array.from(group.values()) as Message.message[]);
|
||||
}
|
||||
|
||||
public getGroupsFirstMessage(message: Message.message) {
|
||||
@ -2537,11 +2542,17 @@ export class AppMessagesManager extends AppManager {
|
||||
}
|
||||
}
|
||||
|
||||
return storage.get(minMid) as Message.message;
|
||||
return this.getMessageFromStorage(storage, minMid) as Message.message;
|
||||
}
|
||||
|
||||
public getMidsByAlbum(grouped_id: string, sort: 'asc' | 'desc' = 'asc') {
|
||||
return getObjectKeysAndSort(this.groupedMessagesStorage[grouped_id], sort);
|
||||
public getMidsByAlbum(groupedId: string, sort: 'asc' | 'desc' = 'asc') {
|
||||
return getObjectKeysAndSort(this.groupedMessagesStorage[groupedId], sort);
|
||||
}
|
||||
|
||||
public getMessagesByAlbum(groupedId: string) {
|
||||
const mids = this.getMidsByAlbum(groupedId, 'asc');
|
||||
const storage = this.groupedMessagesStorage[groupedId];
|
||||
return mids.map((mid) => this.getMessageFromStorage(storage, mid) as Message.message);
|
||||
}
|
||||
|
||||
public getMidsByMessage(message: Message) {
|
||||
@ -3541,22 +3552,10 @@ export class AppMessagesManager extends AppManager {
|
||||
});
|
||||
}
|
||||
|
||||
private handleNewMessage(peerId: PeerId, mid: number) {
|
||||
(this.newMessagesToHandle[peerId] ??= new Set()).add(mid);
|
||||
// if(!this.newMessagesHandleTimeout) {
|
||||
// this.newMessagesHandleTimeout = ctx.setTimeout(this.handleNewMessages, 0);
|
||||
// }
|
||||
this.handleNewMessages();
|
||||
private handleNewMessage(message: MyMessage) {
|
||||
this.rootScope.dispatchEvent('history_multiappend', message);
|
||||
}
|
||||
|
||||
private handleNewMessages = () => {
|
||||
clearTimeout(this.newMessagesHandleTimeout);
|
||||
this.newMessagesHandleTimeout = 0;
|
||||
|
||||
this.rootScope.dispatchEvent('history_multiappend', this.newMessagesToHandle);
|
||||
this.newMessagesToHandle = {};
|
||||
};
|
||||
|
||||
private handleNewDialogs = () => {
|
||||
let newMaxSeenId = 0;
|
||||
const obj = this.newDialogsToHandle;
|
||||
@ -3589,12 +3588,9 @@ export class AppMessagesManager extends AppManager {
|
||||
}
|
||||
|
||||
if(this.newDialogsHandlePromise) return this.newDialogsHandlePromise;
|
||||
return this.newDialogsHandlePromise = new Promise<void>((resolve) => {
|
||||
setTimeout(() => {
|
||||
resolve();
|
||||
this.newDialogsHandlePromise = undefined;
|
||||
this.handleNewDialogs();
|
||||
}, 0);
|
||||
return this.newDialogsHandlePromise = pause(0).then(() => {
|
||||
this.newDialogsHandlePromise = undefined;
|
||||
this.handleNewDialogs();
|
||||
});
|
||||
}
|
||||
|
||||
@ -4144,7 +4140,7 @@ export class AppMessagesManager extends AppManager {
|
||||
|
||||
// commented to render the message if it's been sent faster than history_append came to main thread
|
||||
// if(!pendingMessage) {
|
||||
this.handleNewMessage(peerId, message.mid);
|
||||
this.handleNewMessage(message);
|
||||
// }
|
||||
|
||||
if(isLocalThreadUpdate) {
|
||||
@ -4749,7 +4745,7 @@ export class AppMessagesManager extends AppManager {
|
||||
} else {
|
||||
const pendingMessage = this.checkPendingMessage(message);
|
||||
if(!pendingMessage) {
|
||||
this.rootScope.dispatchEvent('scheduled_new', {peerId, mid: message.mid});
|
||||
this.rootScope.dispatchEvent('scheduled_new', message as Message.message);
|
||||
}
|
||||
}
|
||||
};
|
||||
@ -4826,7 +4822,7 @@ export class AppMessagesManager extends AppManager {
|
||||
if(randomId) {
|
||||
const pendingData = this.pendingByRandomId[randomId];
|
||||
if(pendingMessage = this.finalizePendingMessage(randomId, message)) {
|
||||
this.rootScope.dispatchEvent('history_update', {storageKey: pendingData.storage.key, peerId: message.peerId, mid: message.mid, message, sequential: pendingData.sequential});
|
||||
this.rootScope.dispatchEvent('history_update', {storageKey: pendingData.storage.key, message, sequential: pendingData.sequential});
|
||||
}
|
||||
|
||||
delete this.pendingByMessageId[message.mid];
|
||||
@ -5175,7 +5171,7 @@ export class AppMessagesManager extends AppManager {
|
||||
}
|
||||
|
||||
public getMessageWithReplies(message: Message.message) {
|
||||
return this.filterMessages(message, message => !!(message as Message.message).replies)[0] as any;
|
||||
return this.filterMessages(message, (message) => !!(message as Message.message).replies)[0] as any;
|
||||
}
|
||||
|
||||
public getMessageWithCommentReplies(message: Message.message) {
|
||||
@ -5211,7 +5207,7 @@ export class AppMessagesManager extends AppManager {
|
||||
// if there is no id - then request by first id because cannot request by id 0 with backLimit
|
||||
const historyResult = await this.getHistory(peerId, slice[0] ?? 1, 0, 50, threadId);
|
||||
for(let i = 0, length = historyResult.history.length; i < length; ++i) {
|
||||
this.handleNewMessage(peerId, historyResult.history[i]);
|
||||
this.handleNewMessage(this.getMessageByPeer(peerId, historyResult.history[i]));
|
||||
}
|
||||
|
||||
return {isBottomEnd: historyStorage.history.slice.isEnd(SliceEnd.Bottom)};
|
||||
@ -5531,70 +5527,67 @@ export class AppMessagesManager extends AppManager {
|
||||
return this.fetchSingleMessagesPromise;
|
||||
}
|
||||
|
||||
return this.fetchSingleMessagesPromise = new Promise((resolve) => {
|
||||
setTimeout(() => {
|
||||
const requestPromises: Promise<void>[] = [];
|
||||
|
||||
for(const [peerId, map] of this.needSingleMessages) {
|
||||
const mids = [...map.keys()];
|
||||
const msgIds: InputMessage[] = mids.map((mid) => {
|
||||
return {
|
||||
_: 'inputMessageID',
|
||||
id: getServerMessageId(mid)
|
||||
};
|
||||
return this.fetchSingleMessagesPromise = pause(0).then(() => {
|
||||
const requestPromises: Promise<void>[] = [];
|
||||
|
||||
for(const [peerId, map] of this.needSingleMessages) {
|
||||
const mids = [...map.keys()];
|
||||
const msgIds: InputMessage[] = mids.map((mid) => {
|
||||
return {
|
||||
_: 'inputMessageID',
|
||||
id: getServerMessageId(mid)
|
||||
};
|
||||
});
|
||||
|
||||
let promise: Promise<MethodDeclMap['channels.getMessages']['res'] | MethodDeclMap['messages.getMessages']['res']>;
|
||||
if(peerId.isAnyChat() && this.appPeersManager.isChannel(peerId)) {
|
||||
promise = this.apiManager.invokeApiSingle('channels.getMessages', {
|
||||
channel: this.appChatsManager.getChannelInput(peerId.toChatId()),
|
||||
id: msgIds
|
||||
});
|
||||
|
||||
let promise: Promise<MethodDeclMap['channels.getMessages']['res'] | MethodDeclMap['messages.getMessages']['res']>;
|
||||
if(peerId.isAnyChat() && this.appPeersManager.isChannel(peerId)) {
|
||||
promise = this.apiManager.invokeApiSingle('channels.getMessages', {
|
||||
channel: this.appChatsManager.getChannelInput(peerId.toChatId()),
|
||||
id: msgIds
|
||||
});
|
||||
} else {
|
||||
promise = this.apiManager.invokeApiSingle('messages.getMessages', {
|
||||
id: msgIds
|
||||
});
|
||||
}
|
||||
|
||||
const after = promise.then((getMessagesResult) => {
|
||||
assumeType<Exclude<MessagesMessages.messagesMessages, MessagesMessages.messagesMessagesNotModified>>(getMessagesResult);
|
||||
|
||||
this.appUsersManager.saveApiUsers(getMessagesResult.users);
|
||||
this.appChatsManager.saveApiChats(getMessagesResult.chats);
|
||||
const messages = this.saveMessages(getMessagesResult.messages);
|
||||
|
||||
for(let i = 0; i < messages.length; ++i) {
|
||||
const message = messages[i];
|
||||
if(!message) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const mid = generateMessageId(message.id);
|
||||
const promise = map.get(mid);
|
||||
promise.resolve(message);
|
||||
map.delete(mid);
|
||||
}
|
||||
|
||||
if(map.size) {
|
||||
for(const [mid, promise] of map) {
|
||||
promise.resolve(this.generateEmptyMessage(mid));
|
||||
}
|
||||
}
|
||||
}).finally(() => {
|
||||
this.rootScope.dispatchEvent('messages_downloaded', {peerId, mids});
|
||||
} else {
|
||||
promise = this.apiManager.invokeApiSingle('messages.getMessages', {
|
||||
id: msgIds
|
||||
});
|
||||
|
||||
requestPromises.push(after);
|
||||
}
|
||||
|
||||
this.needSingleMessages.clear();
|
||||
const after = promise.then((getMessagesResult) => {
|
||||
assumeType<Exclude<MessagesMessages.messagesMessages, MessagesMessages.messagesMessagesNotModified>>(getMessagesResult);
|
||||
|
||||
Promise.all(requestPromises).finally(() => {
|
||||
this.fetchSingleMessagesPromise = null;
|
||||
if(this.needSingleMessages.size) this.fetchSingleMessages();
|
||||
resolve();
|
||||
this.appUsersManager.saveApiUsers(getMessagesResult.users);
|
||||
this.appChatsManager.saveApiChats(getMessagesResult.chats);
|
||||
const messages = this.saveMessages(getMessagesResult.messages);
|
||||
|
||||
for(let i = 0; i < messages.length; ++i) {
|
||||
const message = messages[i];
|
||||
if(!message) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const mid = generateMessageId(message.id);
|
||||
const promise = map.get(mid);
|
||||
promise.resolve(message);
|
||||
map.delete(mid);
|
||||
}
|
||||
|
||||
if(map.size) {
|
||||
for(const [mid, promise] of map) {
|
||||
promise.resolve(this.generateEmptyMessage(mid));
|
||||
}
|
||||
}
|
||||
}).finally(() => {
|
||||
this.rootScope.dispatchEvent('messages_downloaded', {peerId, mids});
|
||||
});
|
||||
}, 0);
|
||||
|
||||
requestPromises.push(after);
|
||||
}
|
||||
|
||||
this.needSingleMessages.clear();
|
||||
|
||||
return Promise.all(requestPromises).then(noop, noop).then(() => {
|
||||
this.fetchSingleMessagesPromise = null;
|
||||
if(this.needSingleMessages.size) this.fetchSingleMessages();
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
@ -5745,11 +5738,6 @@ export class AppMessagesManager extends AppManager {
|
||||
}
|
||||
|
||||
storage.delete(mid);
|
||||
|
||||
const peerMessagesToHandle = this.newMessagesToHandle[peerId];
|
||||
if(peerMessagesToHandle && peerMessagesToHandle.has(mid)) {
|
||||
peerMessagesToHandle.delete(mid);
|
||||
}
|
||||
}
|
||||
|
||||
if(history.albums) {
|
||||
|
23
src/lib/appManagers/utils/messages/getAlbumText.ts
Normal file
23
src/lib/appManagers/utils/messages/getAlbumText.ts
Normal file
@ -0,0 +1,23 @@
|
||||
import assumeType from "../../../../helpers/assumeType";
|
||||
import { Message, MessageEntity } from "../../../../layer";
|
||||
|
||||
export default function getAlbumText(messages: Message.message[]) {
|
||||
let foundMessages = 0, message: string, totalEntities: MessageEntity[], entities: MessageEntity[];
|
||||
for(const m of messages) {
|
||||
assumeType<Message.message>(m);
|
||||
if(m.message) {
|
||||
if(++foundMessages > 1) break;
|
||||
message = m.message;
|
||||
totalEntities = m.totalEntities;
|
||||
entities = m.entities;
|
||||
}
|
||||
}
|
||||
|
||||
if(foundMessages > 1) {
|
||||
message = undefined;
|
||||
totalEntities = undefined;
|
||||
entities = undefined;
|
||||
}
|
||||
|
||||
return {message, entities, totalEntities};
|
||||
}
|
@ -15,12 +15,12 @@ import type { GroupCallId } from "./appManagers/appGroupCallsManager";
|
||||
import type { AppManagers } from "./appManagers/managers";
|
||||
import type { State } from "../config/state";
|
||||
import type { Progress } from "./appManagers/appDownloadManager";
|
||||
import type { CallId } from "./appManagers/appCallsManager";
|
||||
import { NULL_PEER_ID, UserAuth } from "./mtproto/mtproto_config";
|
||||
import EventListenerBase from "../helpers/eventListenerBase";
|
||||
import { MOUNT_CLASS_TO } from "../config/debug";
|
||||
import MTProtoMessagePort from "./mtproto/mtprotoMessagePort";
|
||||
import { IS_WORKER } from "../helpers/context";
|
||||
import { CallId } from "./appManagers/appCallsManager";
|
||||
|
||||
export type BroadcastEvents = {
|
||||
'chat_full_update': ChatId,
|
||||
@ -58,10 +58,10 @@ export type BroadcastEvents = {
|
||||
// 'dialog_order': {dialog: Dialog, pos: number},
|
||||
'dialogs_multiupdate': {[peerId: PeerId]: Dialog},
|
||||
|
||||
'history_append': {storageKey: MessagesStorageKey, peerId: PeerId, mid: number},
|
||||
'history_update': {storageKey: MessagesStorageKey, peerId: PeerId, mid: number, message: MyMessage, sequential?: boolean},
|
||||
'history_append': {storageKey: MessagesStorageKey, message: Message.message},
|
||||
'history_update': {storageKey: MessagesStorageKey, message: MyMessage, sequential?: boolean},
|
||||
'history_reply_markup': {peerId: PeerId},
|
||||
'history_multiappend': AppMessagesManager['newMessagesToHandle'],
|
||||
'history_multiappend': MyMessage,
|
||||
'history_delete': {peerId: PeerId, msgs: Set<number>},
|
||||
'history_forbidden': PeerId,
|
||||
'history_reload': PeerId,
|
||||
@ -78,7 +78,7 @@ export type BroadcastEvents = {
|
||||
|
||||
'replies_updated': Message.message,
|
||||
|
||||
'scheduled_new': {peerId: PeerId, mid: number},
|
||||
'scheduled_new': Message.message,
|
||||
'scheduled_delete': {peerId: PeerId, mids: number[]},
|
||||
|
||||
'album_edit': {peerId: PeerId, groupId: string, deletedMids: number[], messages: Message.message[]},
|
||||
|
63
src/tests/splitString.test.ts
Normal file
63
src/tests/splitString.test.ts
Normal file
@ -0,0 +1,63 @@
|
||||
import pause from "../helpers/schedulers/pause";
|
||||
import splitStringByLength from "../helpers/string/splitStringByLength";
|
||||
import { MessageEntity } from "../layer";
|
||||
|
||||
const text = 'abc def ghi jkl mno pqr stu vwx yz';
|
||||
// const text = 'abcdefghijklmnopqrstuvwxyz';
|
||||
const entities: MessageEntity[] = [];
|
||||
const maxLength = 3;
|
||||
const parts = ['abc def ghi', 'jkl mno pqr', 'stu vwx yz'];
|
||||
|
||||
async function split(str: string, maxLength: number, entities: MessageEntity[]) {
|
||||
if(str.length <= maxLength) return [str];
|
||||
|
||||
const delimiter = ' ';
|
||||
const out: {part: string, entities: MessageEntity[]}[] = [];
|
||||
|
||||
let offset = 0;
|
||||
while(str.length) {
|
||||
const isEnd = (offset + maxLength) >= str.length;
|
||||
const sliced = str.slice(offset, offset + maxLength);
|
||||
if(!sliced.length) {
|
||||
break;
|
||||
}
|
||||
|
||||
const delimiterIndex = !isEnd ? sliced.lastIndexOf(delimiter) : -1;
|
||||
console.log(`sliced='${sliced}'`);
|
||||
let good: string;
|
||||
if(delimiterIndex !== -1) {
|
||||
offset += delimiter.length;
|
||||
good = sliced.slice(0, delimiterIndex);
|
||||
} else {
|
||||
good = sliced;
|
||||
}
|
||||
|
||||
if(!good.length) {
|
||||
continue;
|
||||
}
|
||||
|
||||
offset += good.length;
|
||||
out.push({part: good, entities: []});
|
||||
console.log(`'${good}'`);
|
||||
|
||||
// await pause(1000);
|
||||
}
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
describe('Split string', () => {
|
||||
const splitted = split(text, maxLength, []);
|
||||
|
||||
// console.log(parts, splitted);
|
||||
|
||||
test('parts', () => {
|
||||
expect(1).toEqual(1);
|
||||
});
|
||||
|
||||
test('a', async() => {
|
||||
console.log(await splitted);
|
||||
});
|
||||
|
||||
// test('')
|
||||
});
|
Loading…
Reference in New Issue
Block a user