Browse Source

Refactored message ids again

master
Eduard Kuzmenko 4 years ago
parent
commit
3047285307
  1. 40
      src/components/appMediaPlaybackController.ts
  2. 31
      src/components/audio.ts
  3. 51
      src/components/chat/bubbleGroups.ts
  4. 85
      src/components/chat/bubbles.ts
  5. 25
      src/components/popups/newMedia.ts
  6. 6
      src/components/sidebarRight/tabs/sharedMedia.ts
  7. 39
      src/components/wrappers.ts
  8. 6
      src/lib/appManagers/appImManager.ts
  9. 226
      src/lib/appManagers/appMessagesManager.ts
  10. 2
      src/lib/appManagers/appPollsManager.ts
  11. 3
      src/lib/mtproto/apiFileManager.ts
  12. 2
      src/lib/richtextprocessor.ts

40
src/components/appMediaPlaybackController.ts

@ -17,13 +17,22 @@ type MediaType = 'voice' | 'audio' | 'round'; @@ -17,13 +17,22 @@ type MediaType = 'voice' | 'audio' | 'round';
class AppMediaPlaybackController {
private container: HTMLElement;
private media: {[mid: string]: HTMLMediaElement} = {};
private media: {
[peerId: string]: {
[mid: string]: HTMLMediaElement
}
} = {};
private playingMedia: HTMLMediaElement;
private waitingMediaForLoad: {[mid: string]: CancellablePromise<void>} = {};
private waitingMediaForLoad: {
[peerId: string]: {
[mid: string]: CancellablePromise<void>
}
} = {};
public willBePlayedMedia: HTMLMediaElement;
private currentPeerId: number;
private prevMid: number;
private nextMid: number;
@ -35,7 +44,8 @@ class AppMediaPlaybackController { @@ -35,7 +44,8 @@ class AppMediaPlaybackController {
}
public addMedia(peerId: number, doc: MyDocument, mid: number, autoload = true): HTMLMediaElement {
if(this.media[mid]) return this.media[mid];
const storage = this.media[peerId] ?? (this.media[peerId] = {});
if(storage[mid]) return storage[mid];
const media = document.createElement(doc.type == 'round' ? 'video' : 'audio');
//const source = document.createElement('source');
@ -55,6 +65,8 @@ class AppMediaPlaybackController { @@ -55,6 +65,8 @@ class AppMediaPlaybackController {
this.container.append(media);
media.addEventListener('playing', () => {
this.currentPeerId = peerId;
if(this.playingMedia != media) {
if(this.playingMedia && !this.playingMedia.paused) {
this.playingMedia.pause();
@ -76,8 +88,8 @@ class AppMediaPlaybackController { @@ -76,8 +88,8 @@ class AppMediaPlaybackController {
const onError = (e: Event) => {
if(this.nextMid == mid) {
this.loadSiblingsMedia(peerId, doc.type as MediaType, mid).then(() => {
if(this.nextMid && this.media[this.nextMid]) {
this.media[this.nextMid].play();
if(this.nextMid && storage[this.nextMid]) {
storage[this.nextMid].play();
}
});
}
@ -89,7 +101,8 @@ class AppMediaPlaybackController { @@ -89,7 +101,8 @@ class AppMediaPlaybackController {
if(autoload) {
deferred.resolve();
} else {
this.waitingMediaForLoad[mid] = deferred;
const waitingStorage = this.waitingMediaForLoad[peerId] ?? (this.waitingMediaForLoad[peerId] = {});
waitingStorage[mid] = deferred;
}
// если что - загрузит voice или round заранее, так правильнее
@ -105,7 +118,7 @@ class AppMediaPlaybackController { @@ -105,7 +118,7 @@ class AppMediaPlaybackController {
media.src = doc.url;
}, onError);
return this.media[mid] = media;
return storage[mid] = media;
}
// safari подгрузит последний чанк и песня включится,
@ -136,11 +149,12 @@ class AppMediaPlaybackController { @@ -136,11 +149,12 @@ class AppMediaPlaybackController {
}/* , {once: true} */);
}
public resolveWaitingForLoadMedia(mid: number) {
const promise = this.waitingMediaForLoad[mid];
public resolveWaitingForLoadMedia(peerId: number, mid: number) {
const storage = this.waitingMediaForLoad[peerId] ?? (this.waitingMediaForLoad[peerId] = {});
const promise = storage[mid];
if(promise) {
promise.resolve();
delete this.waitingMediaForLoad[mid];
delete storage[mid];
}
}
@ -167,13 +181,13 @@ class AppMediaPlaybackController { @@ -167,13 +181,13 @@ class AppMediaPlaybackController {
//console.log('on media end');
if(this.nextMid) {
const media = this.media[this.nextMid];
const media = this.media[this.currentPeerId][this.nextMid];
/* if(isSafari) {
media.autoplay = true;
} */
this.resolveWaitingForLoadMedia(this.nextMid);
this.resolveWaitingForLoadMedia(this.currentPeerId, this.nextMid);
setTimeout(() => {
media.play()//.catch(() => {});
@ -189,7 +203,7 @@ class AppMediaPlaybackController { @@ -189,7 +203,7 @@ class AppMediaPlaybackController {
//_: type == 'audio' ? 'inputMessagesFilterMusic' : (type == 'round' ? 'inputMessagesFilterRoundVideo' : 'inputMessagesFilterVoice')
_: type == 'audio' ? 'inputMessagesFilterMusic' : 'inputMessagesFilterRoundVoice'
}, mid, 3, 0, 2).then(value => {
if(this.playingMedia != media) {
if(this.playingMedia !== media) {
return;
}

31
src/components/audio.ts

@ -61,10 +61,11 @@ export function decodeWaveform(waveform: Uint8Array | number[]) { @@ -61,10 +61,11 @@ export function decodeWaveform(waveform: Uint8Array | number[]) {
return result;
}
function wrapVoiceMessage(peerId: number, doc: MyDocument, audioEl: AudioElement, mid: number) {
function wrapVoiceMessage(audioEl: AudioElement) {
audioEl.classList.add('is-voice');
const message = appMessagesManager.getMessageByPeer(peerId, mid);
const message = audioEl.message;
const doc = message.media.document as MyDocument;
const isOut = message.fromId == rootScope.myId && message.peerId != rootScope.myId;
let isUnread = message && message.pFlags.media_unread;
if(isUnread) {
@ -171,7 +172,7 @@ function wrapVoiceMessage(peerId: number, doc: MyDocument, audioEl: AudioElement @@ -171,7 +172,7 @@ function wrapVoiceMessage(peerId: number, doc: MyDocument, audioEl: AudioElement
audioEl.addAudioListener('playing', () => {
if(isUnread && !isOut && audioEl.classList.contains('is-unread')) {
audioEl.classList.remove('is-unread');
appMessagesManager.readMessages(peerId, [mid]);
appMessagesManager.readMessages(audioEl.message.peerId, [audioEl.message.mid]);
isUnread = false;
}
@ -249,9 +250,10 @@ function wrapVoiceMessage(peerId: number, doc: MyDocument, audioEl: AudioElement @@ -249,9 +250,10 @@ function wrapVoiceMessage(peerId: number, doc: MyDocument, audioEl: AudioElement
return onLoad;
}
function wrapAudio(doc: MyDocument, audioEl: AudioElement) {
const withTime = !!+audioEl.getAttribute('with-time');
function wrapAudio(audioEl: AudioElement) {
const withTime = audioEl.withTime;
const doc = audioEl.message.media.document;
const title = doc.audioTitle || doc.file_name;
let subtitle = doc.audioPerformer ? RichTextProcessor.wrapPlainText(doc.audioPerformer) : '';
@ -314,6 +316,8 @@ function wrapAudio(doc: MyDocument, audioEl: AudioElement) { @@ -314,6 +316,8 @@ function wrapAudio(doc: MyDocument, audioEl: AudioElement) {
export default class AudioElement extends HTMLElement {
public audio: HTMLAudioElement;
public preloader: ProgressivePreloader;
public message: any;
public withTime = false;
private attachedHandlers: {[name: string]: any[]} = {};
private onTypeDisconnect: () => void;
@ -329,11 +333,8 @@ export default class AudioElement extends HTMLElement { @@ -329,11 +333,8 @@ export default class AudioElement extends HTMLElement {
this.classList.add('audio');
const peerId = +this.getAttribute('peer-id');
const mid = +this.getAttribute('message-id');
const docId = this.getAttribute('doc-id');
const doc = appDocsManager.getDoc(docId);
const uploading = +doc.id < 0;
const doc = this.message.media.document;
const uploading = this.message.pFlags.is_outgoing;
const durationStr = String(doc.duration | 0).toHHMMSS(true);
@ -352,13 +353,13 @@ export default class AudioElement extends HTMLElement { @@ -352,13 +353,13 @@ export default class AudioElement extends HTMLElement {
this.append(downloadDiv);
}
const onTypeLoad = doc.type == 'voice' ? wrapVoiceMessage(peerId, doc, this, mid) : wrapAudio(doc, this);
const onTypeLoad = doc.type == 'voice' ? wrapVoiceMessage(this) : wrapAudio(this);
const audioTimeDiv = this.querySelector('.audio-time') as HTMLDivElement;
audioTimeDiv.innerHTML = durationStr;
const onLoad = (autoload = true) => {
const audio = this.audio = appMediaPlaybackController.addMedia(peerId, doc, mid, autoload);
const audio = this.audio = appMediaPlaybackController.addMedia(this.message.peerId, this.message.media.document, this.message.mid, autoload);
this.onTypeDisconnect = onTypeLoad();
@ -449,7 +450,7 @@ export default class AudioElement extends HTMLElement { @@ -449,7 +450,7 @@ export default class AudioElement extends HTMLElement {
const r = (e: Event) => {
//onLoad();
//cancelEvent(e);
appMediaPlaybackController.resolveWaitingForLoadMedia(mid);
appMediaPlaybackController.resolveWaitingForLoadMedia(this.message.peerId, this.message.mid);
appMediaPlaybackController.willBePlayed(this.audio); // prepare for loading audio
@ -465,7 +466,7 @@ export default class AudioElement extends HTMLElement { @@ -465,7 +466,7 @@ export default class AudioElement extends HTMLElement {
preloader.attach(downloadDiv);
this.append(downloadDiv);
new Promise((resolve) => {
new Promise<void>((resolve) => {
if(this.audio.readyState >= 2) resolve();
else this.addAudioListener('canplay', resolve);
}).then(() => {
@ -473,7 +474,7 @@ export default class AudioElement extends HTMLElement { @@ -473,7 +474,7 @@ export default class AudioElement extends HTMLElement {
//setTimeout(() => {
// release loaded audio
if(appMediaPlaybackController.willBePlayedMedia == this.audio) {
if(appMediaPlaybackController.willBePlayedMedia === this.audio) {
this.audio.play();
appMediaPlaybackController.willBePlayedMedia = null;
}

51
src/components/chat/bubbleGroups.ts

@ -1,6 +1,7 @@ @@ -1,6 +1,7 @@
import rootScope from "../../lib/rootScope";
import { generatePathData } from "../../helpers/dom";
import { MyMessage } from "../../lib/appManagers/appMessagesManager";
import Chat from "./chat";
type Group = {bubble: HTMLDivElement, mid: number, timestamp: number}[];
type BubbleGroup = {timestamp: number, fromId: number, mid: number, group: Group};
@ -10,6 +11,10 @@ export default class BubbleGroups { @@ -10,6 +11,10 @@ export default class BubbleGroups {
//updateRAFs: Map<HTMLDivElement[], number> = new Map();
private newGroupDiff = 121; // * 121 in scheduled messages
constructor(private chat: Chat) {
}
removeBubble(bubble: HTMLDivElement, mid: number) {
const details = this.bubbles.findAndSplice(g => g.mid === mid);
if(details && details.group.length) {
@ -38,10 +43,37 @@ export default class BubbleGroups { @@ -38,10 +43,37 @@ export default class BubbleGroups {
const insertObject = {bubble, mid, timestamp};
if(this.bubbles.length) {
const foundBubble = this.bubbles.find(bubble => {
let foundBubble: BubbleGroup;
let foundAtIndex = -1;
for(let i = 0; i < this.bubbles.length; ++i) {
const bubble = this.bubbles[i];
const diff = Math.abs(bubble.timestamp - timestamp);
const good = bubble.fromId === fromId && diff <= this.newGroupDiff;
if(good) {
foundAtIndex = i;
if(this.chat.type === 'scheduled') {
break;
}
} else {
foundAtIndex = -1;
}
if(this.chat.type !== 'scheduled') {
if(mid > bubble.mid) {
break;
}
}
}
if(foundAtIndex !== -1) {
foundBubble = this.bubbles[foundAtIndex];
}
/* const foundBubble = this.bubbles.find(bubble => {
const diff = Math.abs(bubble.timestamp - timestamp);
return bubble.fromId === fromId && diff <= this.newGroupDiff;
});
}); */
if(!foundBubble) this.groups.push(group = [insertObject]);
else {
@ -70,8 +102,21 @@ export default class BubbleGroups { @@ -70,8 +102,21 @@ export default class BubbleGroups {
}
//console.log('[BUBBLE]: addBubble', bubble, message.mid, fromId, reverse, group);
if(mid > 0) {
let insertIndex = 0;
for(; insertIndex < this.bubbles.length; ++insertIndex) {
if(this.bubbles[insertIndex].mid < mid) {
break;
}
}
this.bubbles.splice(insertIndex, 0, {timestamp, fromId, mid: message.mid, group});
} else {
this.bubbles.unshift({timestamp, fromId, mid: message.mid, group});
}
this.bubbles.push({timestamp, fromId, mid: message.mid, group});
//this.bubbles.push({timestamp, fromId, mid: message.mid, group});
this.updateGroup(group);
}

85
src/components/chat/bubbles.ts

@ -36,6 +36,7 @@ import { AppChatsManager } from "../../lib/appManagers/appChatsManager"; @@ -36,6 +36,7 @@ import { AppChatsManager } from "../../lib/appManagers/appChatsManager";
import Chat from "./chat";
import ListenerSetter from "../../helpers/listenerSetter";
import PollElement from "../poll";
import AudioElement from "../audio";
const IGNORE_ACTIONS = ['messageActionHistoryClear'];
@ -120,7 +121,7 @@ export default class ChatBubbles { @@ -120,7 +121,7 @@ export default class ChatBubbles {
// * constructor end
this.log = this.chat.log;
this.bubbleGroups = new BubbleGroups();
this.bubbleGroups = new BubbleGroups(this.chat);
this.preloader = new ProgressivePreloader(null, false);
this.lazyLoadQueue = new LazyLoadQueue();
this.lazyLoadQueue.queueId = ++queueId;
@ -165,7 +166,7 @@ export default class ChatBubbles { @@ -165,7 +166,7 @@ export default class ChatBubbles {
this.log('message_sent', e.detail);
const mounted = this.getMountedBubble(tempId) || this.getMountedBubble(mid);
const mounted = this.getMountedBubble(tempId, tempMessage) || this.getMountedBubble(mid);
if(mounted) {
const message = this.chat.getMessage(mid);
const bubble = mounted.bubble;
@ -175,7 +176,7 @@ export default class ChatBubbles { @@ -175,7 +176,7 @@ export default class ChatBubbles {
// set new mids to album items for mediaViewer
if(message.grouped_id) {
const item = bubble.querySelector(`.grouped-item[data-mid="${tempId}"]`) as HTMLElement;
const item = (bubble.querySelector(`.grouped-item[data-mid="${tempId}"]`) as HTMLElement) || bubble; // * it can be .document-container
item.dataset.mid = '' + mid;
}
@ -190,9 +191,10 @@ export default class ChatBubbles { @@ -190,9 +191,10 @@ export default class ChatBubbles {
}
if(['audio', 'voice'].includes(message.media?.document?.type)) {
const audio = bubble.querySelector(`audio-element[message-id="${tempId}"]`);
const audio = bubble.querySelector(`audio-element[message-id="${tempId}"]`) as AudioElement;
audio.setAttribute('doc-id', message.media.document.id);
audio.setAttribute('message-id', '' + mid);
audio.message = message;
}
/* bubble.classList.remove('is-sending');
@ -219,7 +221,7 @@ export default class ChatBubbles { @@ -219,7 +221,7 @@ export default class ChatBubbles {
delete this.bubbles[tempId];
bubble.classList.remove('is-sending');
bubble.classList.add('is-sent');
bubble.classList.add(this.peerId === rootScope.myId && this.chat.type !== 'scheduled' ? 'is-read' : 'is-sent');
bubble.dataset.mid = '' + mid;
this.bubbleGroups.removeBubble(bubble, tempId);
@ -695,9 +697,7 @@ export default class ChatBubbles { @@ -695,9 +697,7 @@ export default class ChatBubbles {
return Array.from(bubble.querySelectorAll('.grouped-item')) as HTMLElement[];
}
public getMountedBubble(mid: number) {
const message = this.chat.getMessage(mid);
public getMountedBubble(mid: number, message = this.chat.getMessage(mid)) {
if(message.grouped_id && this.appMessagesManager.getMidsByAlbum(message.grouped_id).length > 1) {
const a = this.getGroupedBubble(message.grouped_id);
if(a) {
@ -1350,40 +1350,40 @@ export default class ChatBubbles { @@ -1350,40 +1350,40 @@ export default class ChatBubbles {
public setBubblePosition(bubble: HTMLElement, message: any, reverse: boolean) {
const dateMessage = this.getDateContainerByMessage(message, reverse);
let children = Array.from(dateMessage.container.children).slice(1) as HTMLElement[];
let i = 0, foundMidOnSameTimestamp = 0;
for(; i < children.length; ++i) {
const t = children[i];
const timestamp = +t.dataset.timestamp;
if(message.date < timestamp) {
break;
} else if(message.date === timestamp) {
foundMidOnSameTimestamp = +t.dataset.mid;
if(this.chat.type === 'scheduled' || this.chat.type === 'pinned') {
let children = Array.from(dateMessage.container.children).slice(2) as HTMLElement[];
let i = 0, foundMidOnSameTimestamp = 0;
for(; i < children.length; ++i) {
const t = children[i];
const timestamp = +t.dataset.timestamp;
if(message.date < timestamp) {
break;
} else if(message.date === timestamp) {
foundMidOnSameTimestamp = +t.dataset.mid;
}
if(foundMidOnSameTimestamp && message.mid < foundMidOnSameTimestamp) {
break;
}
}
if(foundMidOnSameTimestamp && message.mid < foundMidOnSameTimestamp) {
break;
// * 1 for date, 1 for date sentinel
let index = 2 + i;
if(bubble.parentElement) { // * if already mounted
const currentIndex = whichChild(bubble);
if(index > currentIndex) {
index -= 1; // * minus for already mounted
}
}
}
// * 1 for date
let index = 1 + i;
if(bubble.parentElement) { // * if already mounted
const currentIndex = whichChild(bubble);
if(index > currentIndex) {
index -= 1; // * minus for already mounted
positionElementByIndex(bubble, dateMessage.container, index);
} else {
if(reverse) {
dateMessage.container.insertBefore(bubble, dateMessage.container.children[1].nextSibling);
} else {
dateMessage.container.append(bubble);
}
}
positionElementByIndex(bubble, dateMessage.container, index);
//this.bubbleGroups.updateGroupByMessageId(message.mid);
/* if(reverse) {
dateMessage.container.insertBefore(bubble, dateMessage.div.nextSibling);
} else {
dateMessage.container.append(bubble);
} */
}
// * will change .cleaned in cleanup() and new instance will be created
@ -1637,10 +1637,11 @@ export default class ChatBubbles { @@ -1637,10 +1637,11 @@ export default class ChatBubbles {
bubbleContainer.prepend(containerDiv);
}
const isOutgoing = message.pFlags.is_outgoing/* && this.peerId != rootScope.myId */;
if(our) {
if(message.pFlags.unread || message.mid < 0) this.unreadOut.add(message.mid); // message.mid < 0 added 11.02.2020
if(message.pFlags.unread || isOutgoing) this.unreadOut.add(message.mid);
let status = '';
if(message.mid < 0) status = 'is-sending';
if(isOutgoing) status = 'is-sending';
else status = message.pFlags.unread ? 'is-sent' : 'is-read';
bubble.classList.add(status);
}
@ -1839,7 +1840,9 @@ export default class ChatBubbles { @@ -1839,7 +1840,9 @@ export default class ChatBubbles {
});
//}
} else {
const docDiv = wrapDocument(this.peerId, doc, false, false, message.mid);
const docDiv = wrapDocument({
message
});
preview.append(docDiv);
preview.classList.add('preview-with-document');
//messageDiv.classList.add((webpage.type || 'document') + '-message');

25
src/components/popups/newMedia.ts

@ -256,13 +256,24 @@ export default class PopupNewMedia extends PopupElement { @@ -256,13 +256,24 @@ export default class PopupNewMedia extends PopupElement {
params.objectURL = URL.createObjectURL(file);
}
const docDiv = wrapDocument(0, {
file: file,
file_name: file.name || '',
size: file.size,
type: isPhoto ? 'photo' : 'doc',
url: params.objectURL
} as any, false, true);
const docDiv = wrapDocument({
message: {
_: 'message',
mid: 0,
peerId: 0,
media: {
_: 'messageMediaDocument',
document: {
_: 'document',
file: file,
file_name: file.name || '',
size: file.size,
type: isPhoto ? 'photo' : 'doc',
url: params.objectURL
}
}
} as any
});
const finish = () => {
itemDiv.append(docDiv);

6
src/components/sidebarRight/tabs/sharedMedia.ts

@ -528,7 +528,11 @@ export default class AppSharedMediaTab implements SliderTab { @@ -528,7 +528,11 @@ export default class AppSharedMediaTab implements SliderTab {
case 'inputMessagesFilterMusic':
case 'inputMessagesFilterDocument': {
for(const message of messages) {
const div = wrapDocument(this.peerId, message.media.document, true, false, message.mid, 400);
const div = wrapDocument({
message,
withTime: true,
fontWeight: 400
});
div.dataset.mid = '' + message.mid;
elemsToAppend.push(div);
}

39
src/components/wrappers.ts

@ -343,9 +343,21 @@ export const formatDate = (timestamp: number, monthShort = false, withYear = tru @@ -343,9 +343,21 @@ export const formatDate = (timestamp: number, monthShort = false, withYear = tru
return str + ' at ' + date.getHours() + ':' + ('0' + date.getMinutes()).slice(-2);
};
export function wrapDocument(peerId: number, doc: MyDocument, withTime = false, uploading = false, mid?: number, fontWeight = 500): HTMLElement {
export function wrapDocument({message, withTime, uploading, fontWeight}: {
message: any,
withTime?: boolean,
uploading?: boolean,
fontWeight?: number
}): HTMLElement {
if(!fontWeight) fontWeight = 500;
const doc = message.media.document;
if(doc.type == 'audio' || doc.type == 'voice') {
const audioElement = wrapAudio(peerId, doc, withTime, mid);
const audioElement = new AudioElement();
audioElement.setAttribute('message-id', '' + message.mid);
audioElement.setAttribute('peer-id', '' + message.peerId);
audioElement.withTime = withTime;
audioElement.message = message;
audioElement.dataset.fontWeight = '' + fontWeight;
return audioElement;
}
@ -438,15 +450,6 @@ export function wrapDocument(peerId: number, doc: MyDocument, withTime = false, @@ -438,15 +450,6 @@ export function wrapDocument(peerId: number, doc: MyDocument, withTime = false,
return docDiv;
}
export function wrapAudio(peerId: number, doc: MyDocument, withTime = false, mid?: number): HTMLElement {
let elem = new AudioElement();
elem.setAttribute('peer-id', '' + peerId);
elem.setAttribute('doc-id', doc.id);
elem.setAttribute('with-time', '' + +withTime);
elem.setAttribute('message-id', '' + mid);
return elem;
}
function wrapMediaWithTail(photo: MyPhoto | MyDocument, message: {mid: number, message: string}, container: HTMLElement, boxWidth: number, boxHeight: number, isOut: boolean) {
const svg = document.createElementNS("http://www.w3.org/2000/svg", "svg");
svg.classList.add('bubble__media-container', isOut ? 'is-out' : 'is-in');
@ -921,10 +924,10 @@ export function wrapAlbum({groupId, attachmentDiv, middleware, uploading, lazyLo @@ -921,10 +924,10 @@ export function wrapAlbum({groupId, attachmentDiv, middleware, uploading, lazyLo
items.push({size, media, message: m});
}
// * pending
/* // * pending
if(storage[0] < 0) {
items.reverse();
}
} */
prepareAlbum({
container: attachmentDiv,
@ -979,15 +982,17 @@ export function wrapGroupedDocuments({albumMustBeRenderedFull, message, bubble, @@ -979,15 +982,17 @@ export function wrapGroupedDocuments({albumMustBeRenderedFull, message, bubble,
}) {
let nameContainer: HTMLDivElement;
const mids = albumMustBeRenderedFull ? chat.getMidsByMid(message.mid) : [message.mid];
const isPending = message.mid < 0;
if(isPending) {
const isPending = message.pFlags.is_outgoing;
/* if(isPending) {
mids.reverse();
}
} */
mids.forEach((mid, idx) => {
const message = chat.getMessage(mid);
const doc = message.media.document;
const div = wrapDocument(chat.peerId, doc, false, isPending, mid);
const div = wrapDocument({
message
});
const container = document.createElement('div');
container.classList.add('document-container');

6
src/lib/appManagers/appImManager.ts

@ -137,6 +137,10 @@ export class AppImManager { @@ -137,6 +137,10 @@ export class AppImManager {
const hash = location.hash;
const splitted = hash.split('?');
if(!splitted[1]) {
return;
}
const params: any = {};
splitted[1].split('&').forEach(item => {
params[item.split('=')[0]] = decodeURIComponent(item.split('=')[1]);
@ -148,7 +152,7 @@ export class AppImManager { @@ -148,7 +152,7 @@ export class AppImManager {
case '#/im': {
const p = params.p;
if(p[0] === '@') {
let postId = params.post !== undefined ? +params.post : undefined;
let postId = params.post !== undefined ? appMessagesManager.generateMessageId(+params.post) : undefined;
appUsersManager.resolveUsername(p).then(peer => {
const isUser = peer._ == 'user';
const peerId = isUser ? peer.id : -peer.id;

226
src/lib/appManagers/appMessagesManager.ts

@ -78,7 +78,10 @@ export type PinnedStorage = Partial<{ @@ -78,7 +78,10 @@ export type PinnedStorage = Partial<{
count: number,
maxId: number
}>;
export type MessagesStorage = {[mid: string]: any};
export type MessagesStorage = {
//generateIndex: (message: any) => void
[mid: string]: any
};
export class AppMessagesManager {
public messagesStorageByPeerId: {[peerId: string]: MessagesStorage} = {};
public groupedMessagesStorage: {[groupId: string]: MessagesStorage} = {}; // will be used for albums
@ -107,7 +110,7 @@ export class AppMessagesManager { @@ -107,7 +110,7 @@ export class AppMessagesManager {
public pendingAfterMsgs: any = {};
public pendingTopMsgs: {[peerId: string]: number} = {};
public sendFilePromise: CancellablePromise<void> = Promise.resolve();
public tempId = -1;
public tempNum = 0;
public tempFinalizeCallbacks: {
[tempId: string]: {
[callbackName: string]: Partial<{
@ -231,7 +234,7 @@ export class AppMessagesManager { @@ -231,7 +234,7 @@ export class AppMessagesManager {
let removeUnread = 0;
for(const mid of history) {
const message = this.getMessageByPeer(dialog.peerId, mid);
if(/* message._ != 'messageEmpty' && */message.id > 0) {
if(/* message._ != 'messageEmpty' && */!message.pFlags.is_outgoing) {
messages.push(message);
if(message.fromId != dialog.peerId) {
@ -239,6 +242,7 @@ export class AppMessagesManager { @@ -239,6 +242,7 @@ export class AppMessagesManager {
}
dialog.top_message = message.mid;
this.setDialogIndexByMessage(dialog, message);
break;
} else if(message.pFlags && message.pFlags.unread) {
@ -341,7 +345,7 @@ export class AppMessagesManager { @@ -341,7 +345,7 @@ export class AppMessagesManager {
const {mid, peerId} = message;
if(mid < 0) {
if(message.pFlags.is_outgoing) {
return this.invokeAfterMessageIsSent(mid, 'edit', (message) => {
this.log('invoke editMessage callback', message);
return this.editMessage(message, text, options);
@ -357,7 +361,7 @@ export class AppMessagesManager { @@ -357,7 +361,7 @@ export class AppMessagesManager {
const schedule_date = options.scheduleDate || (message.pFlags.is_scheduled ? message.date : undefined);
return apiManager.invokeApi('messages.editMessage', {
peer: appPeersManager.getInputPeerById(peerId),
id: mid,
id: message.id,
message: text,
media: options.newMedia,
entities: entities ? this.getInputEntities(entities) : undefined,
@ -426,10 +430,10 @@ export class AppMessagesManager { @@ -426,10 +430,10 @@ export class AppMessagesManager {
sendEntites = undefined;
}
var messageId = this.tempId--;
var messageId = this.generateTempMessageId(peerId);
var randomIdS = randomLong();
var pFlags: any = {};
var replyToMsgId = options.replyToMsgId;
var replyToMsgId = options.replyToMsgId ? this.getLocalMessageId(options.replyToMsgId) : undefined;
var isChannel = appPeersManager.isChannel(peerId);
var isMegagroup = isChannel && appPeersManager.isMegagroup(peerId);
var asChannel = isChannel && !isMegagroup ? true : false;
@ -589,10 +593,10 @@ export class AppMessagesManager { @@ -589,10 +593,10 @@ export class AppMessagesManager {
}> = {}) {
peerId = appPeersManager.getPeerMigratedTo(peerId) || peerId;
//this.checkSendOptions(options);
const messageId = this.tempId--;
const messageId = this.generateTempMessageId(peerId);
const randomIdS = randomLong();
const pFlags: any = {};
const replyToMsgId = options.replyToMsgId;
const replyToMsgId = options.replyToMsgId ? this.getLocalMessageId(options.replyToMsgId) : undefined;
const isChannel = appPeersManager.isChannel(peerId);
const isMegagroup = isChannel && appPeersManager.isMegagroup(peerId);
const asChannel = !!(isChannel && !isMegagroup);
@ -936,7 +940,7 @@ export class AppMessagesManager { @@ -936,7 +940,7 @@ export class AppMessagesManager {
}
peerId = appPeersManager.getPeerMigratedTo(peerId) || peerId;
const replyToMsgId = options.replyToMsgId;
const replyToMsgId = options.replyToMsgId ? this.getLocalMessageId(options.replyToMsgId) : undefined;
let caption = options.caption || '';
let entities: MessageEntity[];
@ -966,20 +970,24 @@ export class AppMessagesManager { @@ -966,20 +970,24 @@ export class AppMessagesManager {
return this.sendFile(peerId, file, o).message;
});
const groupId = messages[0].id;
const message = messages[messages.length - 1];
const groupId = message.id;
messages.forEach(message => {
message.grouped_id = groupId;
});
const storage = options.scheduleDate ? this.getScheduledMessagesStorage(peerId) : this.getMessagesStorage(peerId);
if(options.scheduleDate) {
this.saveMessages(messages, {storage, isScheduled: true});
this.saveMessages(messages, {storage, isScheduled: true, isOutgoing: true});
rootScope.broadcast('scheduled_new', {peerId, mid: groupId});
} else {
this.saveMessages(messages, {storage});
this.saveMessages(messages, {storage, isOutgoing: true});
rootScope.broadcast('history_append', {peerId, messageId: groupId, my: true});
this.setDialogTopMessage(message);
}
// * test pending
//return;
const toggleError = (message: any, on: boolean) => {
@ -1061,9 +1069,9 @@ export class AppMessagesManager { @@ -1061,9 +1069,9 @@ export class AppMessagesManager {
peerId = appPeersManager.getPeerMigratedTo(peerId) || peerId;
//this.checkSendOptions(options);
const messageId = this.tempId--;
const messageId = this.generateTempMessageId(peerId);
const randomIdS = randomLong();
const replyToMsgId = options.replyToMsgId;
const replyToMsgId = options.replyToMsgId ? this.getLocalMessageId(options.replyToMsgId) : undefined;
const isChannel = appPeersManager.isChannel(peerId);
const isMegagroup = isChannel && appPeersManager.isMegagroup(peerId);
const asChannel = isChannel && !isMegagroup ? true : false;
@ -1266,16 +1274,19 @@ export class AppMessagesManager { @@ -1266,16 +1274,19 @@ export class AppMessagesManager {
if(options.isScheduled) {
if(!options.isGroupedItem) {
this.saveMessages([message], {storage, isScheduled: true});
this.saveMessages([message], {storage, isScheduled: true, isOutgoing: true});
rootScope.broadcast('scheduled_new', {peerId, mid: messageId});
}
} else {
const historyStorage = this.getHistoryStorage(peerId);
historyStorage.pending.unshift(messageId);
//historyStorage.pending.unshift(messageId);
historyStorage.history.unshift(messageId);
if(!options.isGroupedItem) {
this.saveMessages([message], {storage});
this.saveMessages([message], {storage, isOutgoing: true});
rootScope.broadcast('history_append', {peerId, messageId, my: true});
this.setDialogTopMessage(message);
}
}
@ -1284,6 +1295,25 @@ export class AppMessagesManager { @@ -1284,6 +1295,25 @@ export class AppMessagesManager {
if(!options.isGroupedItem) {
setTimeout(message.send, 0);
//setTimeout(message.send, 4000);
//setTimeout(message.send, 7000);
}
}
private setDialogIndexByMessage(dialog: MTDialog.dialog, message: MyMessage) {
if(!dialog.pFlags.pinned || !dialog.index) {
dialog.index = this.dialogsStorage.generateDialogIndex(message.date);
}
}
public setDialogTopMessage(message: MyMessage) {
const dialog = this.getDialogByPeerId(message.peerId)[0];
if(dialog) {
dialog.top_message = message.mid;
this.setDialogIndexByMessage(dialog, message);
this.newDialogsToHandle[message.peerId] = dialog;
this.scheduleHandleNewDialogs();
}
}
@ -1526,7 +1556,7 @@ export class AppMessagesManager { @@ -1526,7 +1556,7 @@ export class AppMessagesManager {
scheduleDate: number
}> = {}) {
peerId = appPeersManager.getPeerMigratedTo(peerId) || peerId;
msgIds = msgIds.slice().sort((a, b) => a - b);
msgIds = msgIds.slice().sort((a, b) => a - b).map(mid => this.getLocalMessageId(mid));
const randomIds: string[] = msgIds.map(() => randomLong());
@ -1564,8 +1594,30 @@ export class AppMessagesManager { @@ -1564,8 +1594,30 @@ export class AppMessagesManager {
};
}
private createMessageStorage() {
const storage: MessagesStorage = {} as any;
/* let num = 0;
Object.defineProperty(storage, 'num', {
get: () => ++num,
set: (_num: number) => num = _num,
enumerable: false
});
Object.defineProperty(storage, 'generateIndex', {
value: (message: any) => {
if(message.index === undefined) {
message.index = (message.date * 0x10000) + (storage.num & 0xFFFF);
}
},
enumerable: false
}); */
return storage;
}
public getMessagesStorage(peerId: number) {
return this.messagesStorageByPeerId[peerId] ?? (this.messagesStorageByPeerId[peerId] = {});
return this.messagesStorageByPeerId[peerId] ?? (this.messagesStorageByPeerId[peerId] = this.createMessageStorage());
}
public getMessageById(messageId: number) {
@ -1712,13 +1764,13 @@ export class AppMessagesManager { @@ -1712,13 +1764,13 @@ export class AppMessagesManager {
});
}
public updatePinnedMessage(peerId: number, mid: number, unpin?: true, silent?: true, oneSide?: true) {
public updatePinnedMessage(peerId: number, id: number, unpin?: true, silent?: true, oneSide?: true) {
return apiManager.invokeApi('messages.updatePinnedMessage', {
peer: appPeersManager.getInputPeerById(peerId),
unpin,
silent,
pm_oneside: oneSide,
id: mid
id
}).then(updates => {
this.log('pinned updates:', updates);
apiUpdatesManager.processUpdateMessage(updates);
@ -1789,9 +1841,47 @@ export class AppMessagesManager { @@ -1789,9 +1841,47 @@ export class AppMessagesManager {
else return [message.mid];
}
public generateTempMessageId(peerId: number) {
const dialog = this.getDialogByPeerId(peerId)[0];
return this.generateMessageId(dialog?.top_message || 0, true);
}
public generateMessageId(messageId: number, temp = false) {
const q = 0xFFFFFFFF;
const num = temp ? ++this.tempNum : 0;
if(messageId > q) {
if(temp) {
return messageId + (num & 0xFFFF);
}
return messageId;
}
return q + (messageId * 0x10000 + (num & 0xFFFF));
}
/**
* * will ignore outgoing offset
*/
public getLocalMessageId(messageId: number) {
const q = 0xFFFFFFFF;
if(messageId < q) {
return messageId;
}
const l = 0xFFFF;
const used = messageId & l;
if(used !== l) {
messageId -= used + 1;
}
return (messageId - q) / 0x10000;
}
public saveMessages(messages: any[], options: Partial<{
storage: MessagesStorage,
isScheduled: true
isScheduled: true,
isOutgoing: true
}> = {}) {
let groups: Map<number, string>;
messages.forEach((message) => {
@ -1807,15 +1897,20 @@ export class AppMessagesManager { @@ -1807,15 +1897,20 @@ export class AppMessagesManager {
// defineNotNumerableProperties(message, ['rReply', 'mid', 'savedFrom', 'fwdFromId', 'fromId', 'peerId', 'reply_to_mid', 'viaBotId']);
const peerId = this.getMessagePeer(message);
const storage = options.storage || this.getMessagesStorage(peerId);
const isChannel = message.peer_id._ == 'peerChannel';
const channelId = isChannel ? -peerId : 0;
const isBroadcast = isChannel && appChatsManager.isBroadcast(channelId);
const mid = message.id;
if(options.isScheduled) {
message.pFlags.is_scheduled = true;
}
if(options.isOutgoing) {
message.pFlags.is_outgoing = true;
}
const mid = this.generateMessageId(message.id);
message.mid = mid;
if(message.grouped_id) {
@ -1834,14 +1929,16 @@ export class AppMessagesManager { @@ -1834,14 +1929,16 @@ export class AppMessagesManager {
// this.log(dT(), 'msg unread', mid, apiMessage.pFlags.out, dialog && dialog[apiMessage.pFlags.out ? 'read_outbox_max_id' : 'read_inbox_max_id'])
if(message.reply_to && message.reply_to.reply_to_msg_id) {
message.reply_to_mid = message.reply_to.reply_to_msg_id;
//message.reply_to_mid = message.reply_to.reply_to_msg_id;
message.reply_to_mid = this.generateMessageId(message.reply_to.reply_to_msg_id);
}
const overwriting = !!message.peerId;
if(!overwriting) {
message.date -= serverTimeManager.serverTimeOffset;
}
//storage.generateIndex(message);
const myId = appUsersManager.getSelf().id;
message.peerId = peerId;
@ -1856,7 +1953,8 @@ export class AppMessagesManager { @@ -1856,7 +1953,8 @@ export class AppMessagesManager {
//if(peerId == myID) {
if(fwdHeader.saved_from_peer && fwdHeader.saved_from_msg_id) {
const savedFromPeerId = appPeersManager.getPeerId(fwdHeader.saved_from_peer);
const savedFromMid = fwdHeader.saved_from_msg_id;
//const savedFromMid = fwdHeader.saved_from_msg_id;
const savedFromMid = this.generateMessageId(fwdHeader.saved_from_msg_id);
message.savedFrom = savedFromPeerId + '_' + savedFromMid;
}
@ -2019,10 +2117,9 @@ export class AppMessagesManager { @@ -2019,10 +2117,9 @@ export class AppMessagesManager {
if(message.message && message.message.length && !message.totalEntities) {
const myEntities = RichTextProcessor.parseEntities(message.message);
const apiEntities = message.entities || [];
message.totalEntities = RichTextProcessor.mergeEntities(apiEntities, myEntities, !message.pending); // ! only in this order, otherwise bold and emoji formatting won't work
message.totalEntities = RichTextProcessor.mergeEntities(apiEntities, myEntities); // ! only in this order, otherwise bold and emoji formatting won't work
}
const storage = options.storage || this.getMessagesStorage(peerId);
storage[mid] = message;
});
@ -2417,10 +2514,10 @@ export class AppMessagesManager { @@ -2417,10 +2514,10 @@ export class AppMessagesManager {
let mid: number, message;
if(dialog.top_message) {
mid = dialog.top_message;
mid = this.generateMessageId(dialog.top_message);//dialog.top_message;
message = this.getMessageByPeer(peerId, mid);
} else {
mid = this.tempId--;
mid = this.generateTempMessageId(peerId);
message = {
_: 'message',
id: mid,
@ -2432,7 +2529,7 @@ export class AppMessagesManager { @@ -2432,7 +2529,7 @@ export class AppMessagesManager {
date: 0,
message: ''
};
this.saveMessages([message]);
this.saveMessages([message], {isOutgoing: true});
}
if(!message?.pFlags) {
@ -2450,6 +2547,8 @@ export class AppMessagesManager { @@ -2450,6 +2547,8 @@ export class AppMessagesManager {
}
dialog.top_message = mid;
dialog.read_inbox_max_id = this.generateMessageId(dialog.read_inbox_max_id);
dialog.read_outbox_max_id = this.generateMessageId(dialog.read_outbox_max_id);
if(!dialog.hasOwnProperty('folder_id')) {
if(dialog._ == 'dialog') {
@ -2536,7 +2635,7 @@ export class AppMessagesManager { @@ -2536,7 +2635,7 @@ export class AppMessagesManager {
if(lastReplyMarkup) {
if(lastReplyMarkup.pFlags.single_use &&
!lastReplyMarkup.pFlags.hidden &&
(message.mid > lastReplyMarkup.mid || message.mid < 0) &&
(message.mid > lastReplyMarkup.mid || message.pFlags.is_outgoing) &&
message.message) {
lastReplyMarkup.pFlags.hidden = true;
// this.log('set', historyStorage.reply_markup)
@ -2757,7 +2856,7 @@ export class AppMessagesManager { @@ -2757,7 +2856,7 @@ export class AppMessagesManager {
min_date: 0,
max_date: 0,
limit,
offset_id: maxId || 0,
offset_id: this.getLocalMessageId(maxId) || 0,
add_offset: backLimit ? -backLimit : 0,
max_id: 0,
min_id: 0,
@ -2873,17 +2972,19 @@ export class AppMessagesManager { @@ -2873,17 +2972,19 @@ export class AppMessagesManager {
}
}
public deleteMessages(peerId: number, msgIds: number[], revoke: boolean) {
public deleteMessages(peerId: number, mids: number[], revoke: boolean) {
let promise: Promise<any>;
mids = mids.map(mid => this.getLocalMessageId(mid));
if(peerId < 0 && appPeersManager.isChannel(-peerId)) {
const channelId = -peerId;
const channel = appChatsManager.getChat(channelId);
if(!channel.pFlags.creator && !(channel.pFlags.editor && channel.pFlags.megagroup)) {
const goodMsgIds: number[] = [];
if (channel.pFlags.editor || channel.pFlags.megagroup) {
msgIds.forEach((msgId, i) => {
const message = this.getMessageByPeer(peerId, msgIds[i]);
mids.forEach((msgId, i) => {
const message = this.getMessageByPeer(peerId, mids[i]);
if(message.pFlags.out) {
goodMsgIds.push(msgId);
}
@ -2894,19 +2995,19 @@ export class AppMessagesManager { @@ -2894,19 +2995,19 @@ export class AppMessagesManager {
return;
}
msgIds = goodMsgIds;
mids = goodMsgIds;
}
promise = apiManager.invokeApi('channels.deleteMessages', {
channel: appChatsManager.getChannelInput(channelId),
id: msgIds
id: mids
}).then((affectedMessages) => {
apiUpdatesManager.processUpdateMessage({
_: 'updateShort',
update: {
_: 'updateDeleteChannelMessages',
channel_id: channelId,
messages: msgIds,
messages: mids,
pts: affectedMessages.pts,
pts_count: affectedMessages.pts_count
}
@ -2915,13 +3016,13 @@ export class AppMessagesManager { @@ -2915,13 +3016,13 @@ export class AppMessagesManager {
} else {
promise = apiManager.invokeApi('messages.deleteMessages', {
revoke: revoke || undefined,
id: msgIds
id: mids
}).then((affectedMessages) => {
apiUpdatesManager.processUpdateMessage({
_: 'updateShort',
update: {
_: 'updateDeleteMessages',
messages: msgIds,
messages: mids,
pts: affectedMessages.pts,
pts_count: affectedMessages.pts_count
}
@ -3064,7 +3165,8 @@ export class AppMessagesManager { @@ -3064,7 +3165,8 @@ export class AppMessagesManager {
//this.log('AMM updateMessageID:', update, pendingData);
if(pendingData) {
const {peerId, tempId, storage} = pendingData;
const mid = update.id;
//const mid = update.id;
const mid = this.generateMessageId(update.id);
const message = this.getMessageFromStorage(storage, mid);
if(!message.deleted) {
const historyStorage = this.getHistoryStorage(peerId);
@ -3150,16 +3252,10 @@ export class AppMessagesManager { @@ -3150,16 +3252,10 @@ export class AppMessagesManager {
}
const inboxUnread = !message.pFlags.out && message.pFlags.unread;
dialog.top_message = message.mid;
this.setDialogTopMessage(message);
if(inboxUnread) {
dialog.unread_count++;
}
if(!dialog.pFlags.pinned || !dialog.index) {
dialog.index = this.dialogsStorage.generateDialogIndex(message.date);
}
this.newDialogsToHandle[peerId] = dialog;
this.scheduleHandleNewDialogs();
break;
}
@ -3331,7 +3427,8 @@ export class AppMessagesManager { @@ -3331,7 +3427,8 @@ export class AppMessagesManager {
case 'updateEditChannelMessage': {
const message = update.message as MyMessage;
const peerId = this.getMessagePeer(message);
const mid = message.id;
//const mid = message.id;
const mid = this.generateMessageId(message.id);
const storage = this.getMessagesStorage(peerId);
if(storage[mid] === undefined) {
break;
@ -3388,7 +3485,8 @@ export class AppMessagesManager { @@ -3388,7 +3485,8 @@ export class AppMessagesManager {
case 'updateReadChannelInbox':
case 'updateReadChannelOutbox': {
const channelId: number = (update as Update.updateReadChannelInbox).channel_id;
const maxId = update.max_id;
//const maxId = update.max_id;
const maxId = this.generateMessageId(update.max_id);
const peerId = channelId ? -channelId : appPeersManager.getPeerId((update as Update.updateReadHistoryInbox).peer);
const isOut = update._ == 'updateReadHistoryOutbox' || update._ == 'updateReadChannelOutbox' ? true : undefined;
const foundDialog = this.getDialogByPeerId(peerId)[0];
@ -3470,7 +3568,7 @@ export class AppMessagesManager { @@ -3470,7 +3568,7 @@ export class AppMessagesManager {
}
}
rootScope.broadcast('messages_media_read', {peerId, mids: messages});
rootScope.broadcast('messages_media_read', {peerId, mids: messages.map(id => this.generateMessageId(id))});
break;
}
@ -3493,7 +3591,8 @@ export class AppMessagesManager { @@ -3493,7 +3591,8 @@ export class AppMessagesManager {
case 'updateDeleteMessages':
case 'updateDeleteChannelMessages': {
const channelId: number = (update as Update.updateDeleteChannelMessages).channel_id;
const messages = (update as any as Update.updateDeleteChannelMessages).messages;
//const messages = (update as any as Update.updateDeleteChannelMessages).messages;
const messages = (update as any as Update.updateDeleteChannelMessages).messages.map(id => this.generateMessageId(id));
const peerId = channelId ? -channelId : this.getMessageById(messages[0]).peerId;
if(!peerId) {
@ -3588,7 +3687,8 @@ export class AppMessagesManager { @@ -3588,7 +3687,8 @@ export class AppMessagesManager {
case 'updateChannelMessageViews': {
const views = update.views;
const mid = update.id;
//const mid = update.id;
const mid = this.generateMessageId(update.id);
const message = this.getMessageByPeer(-update.channel_id, mid);
if(!message.deleted && message.views && message.views < views) {
message.views = views;
@ -3601,7 +3701,7 @@ export class AppMessagesManager { @@ -3601,7 +3701,7 @@ export class AppMessagesManager {
this.log('updateServiceNotification', update);
const fromId = 777000;
const peerId = fromId;
const messageId = this.tempId--;
const messageId = this.generateTempMessageId(peerId);
const message: any = {
_: 'message',
id: messageId,
@ -3623,7 +3723,7 @@ export class AppMessagesManager { @@ -3623,7 +3723,7 @@ export class AppMessagesManager {
phone: '42777'
}]);
}
this.saveMessages([message]);
this.saveMessages([message], {isOutgoing: true});
if(update.inbox_date) {
this.pendingTopMsgs[peerId] = messageId;
@ -3710,7 +3810,7 @@ export class AppMessagesManager { @@ -3710,7 +3810,7 @@ export class AppMessagesManager {
const storage = this.scheduledMessagesStorage[peerId];
if(storage) {
const mid = message.id;
const mid = this.generateMessageId(message.id);
const oldMessage = this.getMessageFromStorage(storage, mid);
this.saveMessages([message], {storage, isScheduled: true});
@ -3735,9 +3835,10 @@ export class AppMessagesManager { @@ -3735,9 +3835,10 @@ export class AppMessagesManager {
const storage = this.scheduledMessagesStorage[peerId];
if(storage) {
this.handleDeletedMessages(peerId, storage, update.messages);
const mids = update.messages.map(id => this.generateMessageId(id));
this.handleDeletedMessages(peerId, storage, mids);
rootScope.broadcast('scheduled_delete', {peerId, mids: update.messages});
rootScope.broadcast('scheduled_delete', {peerId, mids});
}
break;
@ -3836,6 +3937,7 @@ export class AppMessagesManager { @@ -3836,6 +3937,7 @@ export class AppMessagesManager {
const message = this.getMessageFromStorage(storage, tempId);
if(!message.deleted) {
delete message.pFlags.is_outgoing;
delete message.pending;
delete message.error;
delete message.random_id;
@ -3913,7 +4015,7 @@ export class AppMessagesManager { @@ -3913,7 +4015,7 @@ export class AppMessagesManager {
}
public getScheduledMessagesStorage(peerId: number) {
return this.scheduledMessagesStorage[peerId] ?? (this.scheduledMessagesStorage[peerId] = {});
return this.scheduledMessagesStorage[peerId] ?? (this.scheduledMessagesStorage[peerId] = this.createMessageStorage());
}
public getScheduledMessages(peerId: number): Promise<number[]> {
@ -4158,7 +4260,7 @@ export class AppMessagesManager { @@ -4158,7 +4260,7 @@ export class AppMessagesManager {
const promise = apiManager.invokeApi('messages.getHistory', {
peer: appPeersManager.getInputPeerById(peerId),
offset_id: maxId || 0,
offset_id: this.getLocalMessageId(maxId) || 0,
offset_date: offsetDate,
add_offset: offset,
limit: limit,

2
src/lib/appManagers/appPollsManager.ts

@ -170,7 +170,7 @@ export class AppPollsManager { @@ -170,7 +170,7 @@ export class AppPollsManager {
const peerId = message.peerId;
const inputPeer = appPeersManager.getInputPeerById(peerId);
if(messageId < 0) {
if(message.pFlags.is_outgoing) {
return appMessagesManager.invokeAfterMessageIsSent(messageId, 'sendVote', (message) => {
this.log('invoke sendVote callback');
return this.sendVote(message, optionIds);

3
src/lib/mtproto/apiFileManager.ts

@ -513,7 +513,8 @@ export class ApiFileManager { @@ -513,7 +513,8 @@ export class ApiFileManager {
(r.value as Promise<void>).then(process);
};
const maxRequests = Infinity;
//const maxRequests = Infinity;
const maxRequests = 10;
/* for(let i = 0; i < 10; ++i) {
process();
} */

2
src/lib/richtextprocessor.ts

@ -364,7 +364,7 @@ namespace RichTextProcessor { @@ -364,7 +364,7 @@ namespace RichTextProcessor {
return totalEntities;
} */
export function mergeEntities(currentEntities: MessageEntity[], newEntities: MessageEntity[], fromApi?: boolean) {
export function mergeEntities(currentEntities: MessageEntity[], newEntities: MessageEntity[]) {
currentEntities = currentEntities.slice();
const filtered = newEntities.filter(e => !currentEntities.find(_e => e._ == _e._ && e.offset == _e.offset && e.length == _e.length));
currentEntities.push(...filtered);

Loading…
Cancel
Save