Refactored message ids again
This commit is contained in:
parent
f387ef8a27
commit
3047285307
@ -17,13 +17,22 @@ type MediaType = 'voice' | 'audio' | 'round';
|
|||||||
|
|
||||||
class AppMediaPlaybackController {
|
class AppMediaPlaybackController {
|
||||||
private container: HTMLElement;
|
private container: HTMLElement;
|
||||||
private media: {[mid: string]: HTMLMediaElement} = {};
|
private media: {
|
||||||
|
[peerId: string]: {
|
||||||
|
[mid: string]: HTMLMediaElement
|
||||||
|
}
|
||||||
|
} = {};
|
||||||
private playingMedia: HTMLMediaElement;
|
private playingMedia: HTMLMediaElement;
|
||||||
|
|
||||||
private waitingMediaForLoad: {[mid: string]: CancellablePromise<void>} = {};
|
private waitingMediaForLoad: {
|
||||||
|
[peerId: string]: {
|
||||||
|
[mid: string]: CancellablePromise<void>
|
||||||
|
}
|
||||||
|
} = {};
|
||||||
|
|
||||||
public willBePlayedMedia: HTMLMediaElement;
|
public willBePlayedMedia: HTMLMediaElement;
|
||||||
|
|
||||||
|
private currentPeerId: number;
|
||||||
private prevMid: number;
|
private prevMid: number;
|
||||||
private nextMid: number;
|
private nextMid: number;
|
||||||
|
|
||||||
@ -35,7 +44,8 @@ class AppMediaPlaybackController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public addMedia(peerId: number, doc: MyDocument, mid: number, autoload = true): HTMLMediaElement {
|
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 media = document.createElement(doc.type == 'round' ? 'video' : 'audio');
|
||||||
//const source = document.createElement('source');
|
//const source = document.createElement('source');
|
||||||
@ -55,6 +65,8 @@ class AppMediaPlaybackController {
|
|||||||
this.container.append(media);
|
this.container.append(media);
|
||||||
|
|
||||||
media.addEventListener('playing', () => {
|
media.addEventListener('playing', () => {
|
||||||
|
this.currentPeerId = peerId;
|
||||||
|
|
||||||
if(this.playingMedia != media) {
|
if(this.playingMedia != media) {
|
||||||
if(this.playingMedia && !this.playingMedia.paused) {
|
if(this.playingMedia && !this.playingMedia.paused) {
|
||||||
this.playingMedia.pause();
|
this.playingMedia.pause();
|
||||||
@ -76,8 +88,8 @@ class AppMediaPlaybackController {
|
|||||||
const onError = (e: Event) => {
|
const onError = (e: Event) => {
|
||||||
if(this.nextMid == mid) {
|
if(this.nextMid == mid) {
|
||||||
this.loadSiblingsMedia(peerId, doc.type as MediaType, mid).then(() => {
|
this.loadSiblingsMedia(peerId, doc.type as MediaType, mid).then(() => {
|
||||||
if(this.nextMid && this.media[this.nextMid]) {
|
if(this.nextMid && storage[this.nextMid]) {
|
||||||
this.media[this.nextMid].play();
|
storage[this.nextMid].play();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -89,7 +101,8 @@ class AppMediaPlaybackController {
|
|||||||
if(autoload) {
|
if(autoload) {
|
||||||
deferred.resolve();
|
deferred.resolve();
|
||||||
} else {
|
} else {
|
||||||
this.waitingMediaForLoad[mid] = deferred;
|
const waitingStorage = this.waitingMediaForLoad[peerId] ?? (this.waitingMediaForLoad[peerId] = {});
|
||||||
|
waitingStorage[mid] = deferred;
|
||||||
}
|
}
|
||||||
|
|
||||||
// если что - загрузит voice или round заранее, так правильнее
|
// если что - загрузит voice или round заранее, так правильнее
|
||||||
@ -105,7 +118,7 @@ class AppMediaPlaybackController {
|
|||||||
media.src = doc.url;
|
media.src = doc.url;
|
||||||
}, onError);
|
}, onError);
|
||||||
|
|
||||||
return this.media[mid] = media;
|
return storage[mid] = media;
|
||||||
}
|
}
|
||||||
|
|
||||||
// safari подгрузит последний чанк и песня включится,
|
// safari подгрузит последний чанк и песня включится,
|
||||||
@ -136,11 +149,12 @@ class AppMediaPlaybackController {
|
|||||||
}/* , {once: true} */);
|
}/* , {once: true} */);
|
||||||
}
|
}
|
||||||
|
|
||||||
public resolveWaitingForLoadMedia(mid: number) {
|
public resolveWaitingForLoadMedia(peerId: number, mid: number) {
|
||||||
const promise = this.waitingMediaForLoad[mid];
|
const storage = this.waitingMediaForLoad[peerId] ?? (this.waitingMediaForLoad[peerId] = {});
|
||||||
|
const promise = storage[mid];
|
||||||
if(promise) {
|
if(promise) {
|
||||||
promise.resolve();
|
promise.resolve();
|
||||||
delete this.waitingMediaForLoad[mid];
|
delete storage[mid];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -167,13 +181,13 @@ class AppMediaPlaybackController {
|
|||||||
//console.log('on media end');
|
//console.log('on media end');
|
||||||
|
|
||||||
if(this.nextMid) {
|
if(this.nextMid) {
|
||||||
const media = this.media[this.nextMid];
|
const media = this.media[this.currentPeerId][this.nextMid];
|
||||||
|
|
||||||
/* if(isSafari) {
|
/* if(isSafari) {
|
||||||
media.autoplay = true;
|
media.autoplay = true;
|
||||||
} */
|
} */
|
||||||
|
|
||||||
this.resolveWaitingForLoadMedia(this.nextMid);
|
this.resolveWaitingForLoadMedia(this.currentPeerId, this.nextMid);
|
||||||
|
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
media.play()//.catch(() => {});
|
media.play()//.catch(() => {});
|
||||||
@ -189,7 +203,7 @@ class AppMediaPlaybackController {
|
|||||||
//_: type == 'audio' ? 'inputMessagesFilterMusic' : (type == 'round' ? 'inputMessagesFilterRoundVideo' : 'inputMessagesFilterVoice')
|
//_: type == 'audio' ? 'inputMessagesFilterMusic' : (type == 'round' ? 'inputMessagesFilterRoundVideo' : 'inputMessagesFilterVoice')
|
||||||
_: type == 'audio' ? 'inputMessagesFilterMusic' : 'inputMessagesFilterRoundVoice'
|
_: type == 'audio' ? 'inputMessagesFilterMusic' : 'inputMessagesFilterRoundVoice'
|
||||||
}, mid, 3, 0, 2).then(value => {
|
}, mid, 3, 0, 2).then(value => {
|
||||||
if(this.playingMedia != media) {
|
if(this.playingMedia !== media) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -61,10 +61,11 @@ export function decodeWaveform(waveform: Uint8Array | number[]) {
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
function wrapVoiceMessage(peerId: number, doc: MyDocument, audioEl: AudioElement, mid: number) {
|
function wrapVoiceMessage(audioEl: AudioElement) {
|
||||||
audioEl.classList.add('is-voice');
|
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;
|
const isOut = message.fromId == rootScope.myId && message.peerId != rootScope.myId;
|
||||||
let isUnread = message && message.pFlags.media_unread;
|
let isUnread = message && message.pFlags.media_unread;
|
||||||
if(isUnread) {
|
if(isUnread) {
|
||||||
@ -171,7 +172,7 @@ function wrapVoiceMessage(peerId: number, doc: MyDocument, audioEl: AudioElement
|
|||||||
audioEl.addAudioListener('playing', () => {
|
audioEl.addAudioListener('playing', () => {
|
||||||
if(isUnread && !isOut && audioEl.classList.contains('is-unread')) {
|
if(isUnread && !isOut && audioEl.classList.contains('is-unread')) {
|
||||||
audioEl.classList.remove('is-unread');
|
audioEl.classList.remove('is-unread');
|
||||||
appMessagesManager.readMessages(peerId, [mid]);
|
appMessagesManager.readMessages(audioEl.message.peerId, [audioEl.message.mid]);
|
||||||
isUnread = false;
|
isUnread = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -249,9 +250,10 @@ function wrapVoiceMessage(peerId: number, doc: MyDocument, audioEl: AudioElement
|
|||||||
return onLoad;
|
return onLoad;
|
||||||
}
|
}
|
||||||
|
|
||||||
function wrapAudio(doc: MyDocument, audioEl: AudioElement) {
|
function wrapAudio(audioEl: AudioElement) {
|
||||||
const withTime = !!+audioEl.getAttribute('with-time');
|
const withTime = audioEl.withTime;
|
||||||
|
|
||||||
|
const doc = audioEl.message.media.document;
|
||||||
const title = doc.audioTitle || doc.file_name;
|
const title = doc.audioTitle || doc.file_name;
|
||||||
let subtitle = doc.audioPerformer ? RichTextProcessor.wrapPlainText(doc.audioPerformer) : '';
|
let subtitle = doc.audioPerformer ? RichTextProcessor.wrapPlainText(doc.audioPerformer) : '';
|
||||||
|
|
||||||
@ -314,6 +316,8 @@ function wrapAudio(doc: MyDocument, audioEl: AudioElement) {
|
|||||||
export default class AudioElement extends HTMLElement {
|
export default class AudioElement extends HTMLElement {
|
||||||
public audio: HTMLAudioElement;
|
public audio: HTMLAudioElement;
|
||||||
public preloader: ProgressivePreloader;
|
public preloader: ProgressivePreloader;
|
||||||
|
public message: any;
|
||||||
|
public withTime = false;
|
||||||
|
|
||||||
private attachedHandlers: {[name: string]: any[]} = {};
|
private attachedHandlers: {[name: string]: any[]} = {};
|
||||||
private onTypeDisconnect: () => void;
|
private onTypeDisconnect: () => void;
|
||||||
@ -329,11 +333,8 @@ export default class AudioElement extends HTMLElement {
|
|||||||
|
|
||||||
this.classList.add('audio');
|
this.classList.add('audio');
|
||||||
|
|
||||||
const peerId = +this.getAttribute('peer-id');
|
const doc = this.message.media.document;
|
||||||
const mid = +this.getAttribute('message-id');
|
const uploading = this.message.pFlags.is_outgoing;
|
||||||
const docId = this.getAttribute('doc-id');
|
|
||||||
const doc = appDocsManager.getDoc(docId);
|
|
||||||
const uploading = +doc.id < 0;
|
|
||||||
|
|
||||||
const durationStr = String(doc.duration | 0).toHHMMSS(true);
|
const durationStr = String(doc.duration | 0).toHHMMSS(true);
|
||||||
|
|
||||||
@ -352,13 +353,13 @@ export default class AudioElement extends HTMLElement {
|
|||||||
this.append(downloadDiv);
|
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;
|
const audioTimeDiv = this.querySelector('.audio-time') as HTMLDivElement;
|
||||||
audioTimeDiv.innerHTML = durationStr;
|
audioTimeDiv.innerHTML = durationStr;
|
||||||
|
|
||||||
const onLoad = (autoload = true) => {
|
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();
|
this.onTypeDisconnect = onTypeLoad();
|
||||||
|
|
||||||
@ -449,7 +450,7 @@ export default class AudioElement extends HTMLElement {
|
|||||||
const r = (e: Event) => {
|
const r = (e: Event) => {
|
||||||
//onLoad();
|
//onLoad();
|
||||||
//cancelEvent(e);
|
//cancelEvent(e);
|
||||||
appMediaPlaybackController.resolveWaitingForLoadMedia(mid);
|
appMediaPlaybackController.resolveWaitingForLoadMedia(this.message.peerId, this.message.mid);
|
||||||
|
|
||||||
appMediaPlaybackController.willBePlayed(this.audio); // prepare for loading audio
|
appMediaPlaybackController.willBePlayed(this.audio); // prepare for loading audio
|
||||||
|
|
||||||
@ -465,7 +466,7 @@ export default class AudioElement extends HTMLElement {
|
|||||||
preloader.attach(downloadDiv);
|
preloader.attach(downloadDiv);
|
||||||
this.append(downloadDiv);
|
this.append(downloadDiv);
|
||||||
|
|
||||||
new Promise((resolve) => {
|
new Promise<void>((resolve) => {
|
||||||
if(this.audio.readyState >= 2) resolve();
|
if(this.audio.readyState >= 2) resolve();
|
||||||
else this.addAudioListener('canplay', resolve);
|
else this.addAudioListener('canplay', resolve);
|
||||||
}).then(() => {
|
}).then(() => {
|
||||||
@ -473,7 +474,7 @@ export default class AudioElement extends HTMLElement {
|
|||||||
|
|
||||||
//setTimeout(() => {
|
//setTimeout(() => {
|
||||||
// release loaded audio
|
// release loaded audio
|
||||||
if(appMediaPlaybackController.willBePlayedMedia == this.audio) {
|
if(appMediaPlaybackController.willBePlayedMedia === this.audio) {
|
||||||
this.audio.play();
|
this.audio.play();
|
||||||
appMediaPlaybackController.willBePlayedMedia = null;
|
appMediaPlaybackController.willBePlayedMedia = null;
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
import rootScope from "../../lib/rootScope";
|
import rootScope from "../../lib/rootScope";
|
||||||
import { generatePathData } from "../../helpers/dom";
|
import { generatePathData } from "../../helpers/dom";
|
||||||
import { MyMessage } from "../../lib/appManagers/appMessagesManager";
|
import { MyMessage } from "../../lib/appManagers/appMessagesManager";
|
||||||
|
import Chat from "./chat";
|
||||||
|
|
||||||
type Group = {bubble: HTMLDivElement, mid: number, timestamp: number}[];
|
type Group = {bubble: HTMLDivElement, mid: number, timestamp: number}[];
|
||||||
type BubbleGroup = {timestamp: number, fromId: number, mid: number, group: Group};
|
type BubbleGroup = {timestamp: number, fromId: number, mid: number, group: Group};
|
||||||
@ -10,6 +11,10 @@ export default class BubbleGroups {
|
|||||||
//updateRAFs: Map<HTMLDivElement[], number> = new Map();
|
//updateRAFs: Map<HTMLDivElement[], number> = new Map();
|
||||||
private newGroupDiff = 121; // * 121 in scheduled messages
|
private newGroupDiff = 121; // * 121 in scheduled messages
|
||||||
|
|
||||||
|
constructor(private chat: Chat) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
removeBubble(bubble: HTMLDivElement, mid: number) {
|
removeBubble(bubble: HTMLDivElement, mid: number) {
|
||||||
const details = this.bubbles.findAndSplice(g => g.mid === mid);
|
const details = this.bubbles.findAndSplice(g => g.mid === mid);
|
||||||
if(details && details.group.length) {
|
if(details && details.group.length) {
|
||||||
@ -38,10 +43,37 @@ export default class BubbleGroups {
|
|||||||
|
|
||||||
const insertObject = {bubble, mid, timestamp};
|
const insertObject = {bubble, mid, timestamp};
|
||||||
if(this.bubbles.length) {
|
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);
|
const diff = Math.abs(bubble.timestamp - timestamp);
|
||||||
return bubble.fromId === fromId && diff <= this.newGroupDiff;
|
return bubble.fromId === fromId && diff <= this.newGroupDiff;
|
||||||
});
|
}); */
|
||||||
|
|
||||||
if(!foundBubble) this.groups.push(group = [insertObject]);
|
if(!foundBubble) this.groups.push(group = [insertObject]);
|
||||||
else {
|
else {
|
||||||
@ -71,7 +103,20 @@ export default class BubbleGroups {
|
|||||||
|
|
||||||
//console.log('[BUBBLE]: addBubble', bubble, message.mid, fromId, reverse, group);
|
//console.log('[BUBBLE]: addBubble', bubble, message.mid, fromId, reverse, group);
|
||||||
|
|
||||||
this.bubbles.push({timestamp, fromId, mid: message.mid, 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.updateGroup(group);
|
this.updateGroup(group);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -36,6 +36,7 @@ import { AppChatsManager } from "../../lib/appManagers/appChatsManager";
|
|||||||
import Chat from "./chat";
|
import Chat from "./chat";
|
||||||
import ListenerSetter from "../../helpers/listenerSetter";
|
import ListenerSetter from "../../helpers/listenerSetter";
|
||||||
import PollElement from "../poll";
|
import PollElement from "../poll";
|
||||||
|
import AudioElement from "../audio";
|
||||||
|
|
||||||
const IGNORE_ACTIONS = ['messageActionHistoryClear'];
|
const IGNORE_ACTIONS = ['messageActionHistoryClear'];
|
||||||
|
|
||||||
@ -120,7 +121,7 @@ export default class ChatBubbles {
|
|||||||
// * constructor end
|
// * constructor end
|
||||||
|
|
||||||
this.log = this.chat.log;
|
this.log = this.chat.log;
|
||||||
this.bubbleGroups = new BubbleGroups();
|
this.bubbleGroups = new BubbleGroups(this.chat);
|
||||||
this.preloader = new ProgressivePreloader(null, false);
|
this.preloader = new ProgressivePreloader(null, false);
|
||||||
this.lazyLoadQueue = new LazyLoadQueue();
|
this.lazyLoadQueue = new LazyLoadQueue();
|
||||||
this.lazyLoadQueue.queueId = ++queueId;
|
this.lazyLoadQueue.queueId = ++queueId;
|
||||||
@ -165,7 +166,7 @@ export default class ChatBubbles {
|
|||||||
|
|
||||||
this.log('message_sent', e.detail);
|
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) {
|
if(mounted) {
|
||||||
const message = this.chat.getMessage(mid);
|
const message = this.chat.getMessage(mid);
|
||||||
const bubble = mounted.bubble;
|
const bubble = mounted.bubble;
|
||||||
@ -175,7 +176,7 @@ export default class ChatBubbles {
|
|||||||
|
|
||||||
// set new mids to album items for mediaViewer
|
// set new mids to album items for mediaViewer
|
||||||
if(message.grouped_id) {
|
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;
|
item.dataset.mid = '' + mid;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -190,9 +191,10 @@ export default class ChatBubbles {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if(['audio', 'voice'].includes(message.media?.document?.type)) {
|
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('doc-id', message.media.document.id);
|
||||||
audio.setAttribute('message-id', '' + mid);
|
audio.setAttribute('message-id', '' + mid);
|
||||||
|
audio.message = message;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* bubble.classList.remove('is-sending');
|
/* bubble.classList.remove('is-sending');
|
||||||
@ -219,7 +221,7 @@ export default class ChatBubbles {
|
|||||||
delete this.bubbles[tempId];
|
delete this.bubbles[tempId];
|
||||||
|
|
||||||
bubble.classList.remove('is-sending');
|
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;
|
bubble.dataset.mid = '' + mid;
|
||||||
|
|
||||||
this.bubbleGroups.removeBubble(bubble, tempId);
|
this.bubbleGroups.removeBubble(bubble, tempId);
|
||||||
@ -695,9 +697,7 @@ export default class ChatBubbles {
|
|||||||
return Array.from(bubble.querySelectorAll('.grouped-item')) as HTMLElement[];
|
return Array.from(bubble.querySelectorAll('.grouped-item')) as HTMLElement[];
|
||||||
}
|
}
|
||||||
|
|
||||||
public getMountedBubble(mid: number) {
|
public getMountedBubble(mid: number, message = this.chat.getMessage(mid)) {
|
||||||
const message = this.chat.getMessage(mid);
|
|
||||||
|
|
||||||
if(message.grouped_id && this.appMessagesManager.getMidsByAlbum(message.grouped_id).length > 1) {
|
if(message.grouped_id && this.appMessagesManager.getMidsByAlbum(message.grouped_id).length > 1) {
|
||||||
const a = this.getGroupedBubble(message.grouped_id);
|
const a = this.getGroupedBubble(message.grouped_id);
|
||||||
if(a) {
|
if(a) {
|
||||||
@ -1350,40 +1350,40 @@ export default class ChatBubbles {
|
|||||||
|
|
||||||
public setBubblePosition(bubble: HTMLElement, message: any, reverse: boolean) {
|
public setBubblePosition(bubble: HTMLElement, message: any, reverse: boolean) {
|
||||||
const dateMessage = this.getDateContainerByMessage(message, reverse);
|
const dateMessage = this.getDateContainerByMessage(message, reverse);
|
||||||
let children = Array.from(dateMessage.container.children).slice(1) as HTMLElement[];
|
if(this.chat.type === 'scheduled' || this.chat.type === 'pinned') {
|
||||||
let i = 0, foundMidOnSameTimestamp = 0;
|
let children = Array.from(dateMessage.container.children).slice(2) as HTMLElement[];
|
||||||
for(; i < children.length; ++i) {
|
let i = 0, foundMidOnSameTimestamp = 0;
|
||||||
const t = children[i];
|
for(; i < children.length; ++i) {
|
||||||
const timestamp = +t.dataset.timestamp;
|
const t = children[i];
|
||||||
if(message.date < timestamp) {
|
const timestamp = +t.dataset.timestamp;
|
||||||
break;
|
if(message.date < timestamp) {
|
||||||
} else if(message.date === timestamp) {
|
break;
|
||||||
foundMidOnSameTimestamp = +t.dataset.mid;
|
} else if(message.date === timestamp) {
|
||||||
|
foundMidOnSameTimestamp = +t.dataset.mid;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(foundMidOnSameTimestamp && message.mid < foundMidOnSameTimestamp) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(foundMidOnSameTimestamp && message.mid < foundMidOnSameTimestamp) {
|
// * 1 for date, 1 for date sentinel
|
||||||
break;
|
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
|
positionElementByIndex(bubble, dateMessage.container, index);
|
||||||
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);
|
|
||||||
|
|
||||||
//this.bubbleGroups.updateGroupByMessageId(message.mid);
|
|
||||||
|
|
||||||
/* if(reverse) {
|
|
||||||
dateMessage.container.insertBefore(bubble, dateMessage.div.nextSibling);
|
|
||||||
} else {
|
} else {
|
||||||
dateMessage.container.append(bubble);
|
if(reverse) {
|
||||||
} */
|
dateMessage.container.insertBefore(bubble, dateMessage.container.children[1].nextSibling);
|
||||||
|
} else {
|
||||||
|
dateMessage.container.append(bubble);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// * will change .cleaned in cleanup() and new instance will be created
|
// * will change .cleaned in cleanup() and new instance will be created
|
||||||
@ -1637,10 +1637,11 @@ export default class ChatBubbles {
|
|||||||
bubbleContainer.prepend(containerDiv);
|
bubbleContainer.prepend(containerDiv);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const isOutgoing = message.pFlags.is_outgoing/* && this.peerId != rootScope.myId */;
|
||||||
if(our) {
|
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 = '';
|
let status = '';
|
||||||
if(message.mid < 0) status = 'is-sending';
|
if(isOutgoing) status = 'is-sending';
|
||||||
else status = message.pFlags.unread ? 'is-sent' : 'is-read';
|
else status = message.pFlags.unread ? 'is-sent' : 'is-read';
|
||||||
bubble.classList.add(status);
|
bubble.classList.add(status);
|
||||||
}
|
}
|
||||||
@ -1839,7 +1840,9 @@ export default class ChatBubbles {
|
|||||||
});
|
});
|
||||||
//}
|
//}
|
||||||
} else {
|
} else {
|
||||||
const docDiv = wrapDocument(this.peerId, doc, false, false, message.mid);
|
const docDiv = wrapDocument({
|
||||||
|
message
|
||||||
|
});
|
||||||
preview.append(docDiv);
|
preview.append(docDiv);
|
||||||
preview.classList.add('preview-with-document');
|
preview.classList.add('preview-with-document');
|
||||||
//messageDiv.classList.add((webpage.type || 'document') + '-message');
|
//messageDiv.classList.add((webpage.type || 'document') + '-message');
|
||||||
|
@ -256,13 +256,24 @@ export default class PopupNewMedia extends PopupElement {
|
|||||||
params.objectURL = URL.createObjectURL(file);
|
params.objectURL = URL.createObjectURL(file);
|
||||||
}
|
}
|
||||||
|
|
||||||
const docDiv = wrapDocument(0, {
|
const docDiv = wrapDocument({
|
||||||
file: file,
|
message: {
|
||||||
file_name: file.name || '',
|
_: 'message',
|
||||||
size: file.size,
|
mid: 0,
|
||||||
type: isPhoto ? 'photo' : 'doc',
|
peerId: 0,
|
||||||
url: params.objectURL
|
media: {
|
||||||
} as any, false, true);
|
_: 'messageMediaDocument',
|
||||||
|
document: {
|
||||||
|
_: 'document',
|
||||||
|
file: file,
|
||||||
|
file_name: file.name || '',
|
||||||
|
size: file.size,
|
||||||
|
type: isPhoto ? 'photo' : 'doc',
|
||||||
|
url: params.objectURL
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} as any
|
||||||
|
});
|
||||||
|
|
||||||
const finish = () => {
|
const finish = () => {
|
||||||
itemDiv.append(docDiv);
|
itemDiv.append(docDiv);
|
||||||
|
@ -528,7 +528,11 @@ export default class AppSharedMediaTab implements SliderTab {
|
|||||||
case 'inputMessagesFilterMusic':
|
case 'inputMessagesFilterMusic':
|
||||||
case 'inputMessagesFilterDocument': {
|
case 'inputMessagesFilterDocument': {
|
||||||
for(const message of messages) {
|
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;
|
div.dataset.mid = '' + message.mid;
|
||||||
elemsToAppend.push(div);
|
elemsToAppend.push(div);
|
||||||
}
|
}
|
||||||
|
@ -343,9 +343,21 @@ export const formatDate = (timestamp: number, monthShort = false, withYear = tru
|
|||||||
return str + ' at ' + date.getHours() + ':' + ('0' + date.getMinutes()).slice(-2);
|
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') {
|
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;
|
audioElement.dataset.fontWeight = '' + fontWeight;
|
||||||
return audioElement;
|
return audioElement;
|
||||||
}
|
}
|
||||||
@ -438,15 +450,6 @@ export function wrapDocument(peerId: number, doc: MyDocument, withTime = false,
|
|||||||
return docDiv;
|
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) {
|
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");
|
const svg = document.createElementNS("http://www.w3.org/2000/svg", "svg");
|
||||||
svg.classList.add('bubble__media-container', isOut ? 'is-out' : 'is-in');
|
svg.classList.add('bubble__media-container', isOut ? 'is-out' : 'is-in');
|
||||||
@ -921,10 +924,10 @@ export function wrapAlbum({groupId, attachmentDiv, middleware, uploading, lazyLo
|
|||||||
items.push({size, media, message: m});
|
items.push({size, media, message: m});
|
||||||
}
|
}
|
||||||
|
|
||||||
// * pending
|
/* // * pending
|
||||||
if(storage[0] < 0) {
|
if(storage[0] < 0) {
|
||||||
items.reverse();
|
items.reverse();
|
||||||
}
|
} */
|
||||||
|
|
||||||
prepareAlbum({
|
prepareAlbum({
|
||||||
container: attachmentDiv,
|
container: attachmentDiv,
|
||||||
@ -979,15 +982,17 @@ export function wrapGroupedDocuments({albumMustBeRenderedFull, message, bubble,
|
|||||||
}) {
|
}) {
|
||||||
let nameContainer: HTMLDivElement;
|
let nameContainer: HTMLDivElement;
|
||||||
const mids = albumMustBeRenderedFull ? chat.getMidsByMid(message.mid) : [message.mid];
|
const mids = albumMustBeRenderedFull ? chat.getMidsByMid(message.mid) : [message.mid];
|
||||||
const isPending = message.mid < 0;
|
const isPending = message.pFlags.is_outgoing;
|
||||||
if(isPending) {
|
/* if(isPending) {
|
||||||
mids.reverse();
|
mids.reverse();
|
||||||
}
|
} */
|
||||||
|
|
||||||
mids.forEach((mid, idx) => {
|
mids.forEach((mid, idx) => {
|
||||||
const message = chat.getMessage(mid);
|
const message = chat.getMessage(mid);
|
||||||
const doc = message.media.document;
|
const doc = message.media.document;
|
||||||
const div = wrapDocument(chat.peerId, doc, false, isPending, mid);
|
const div = wrapDocument({
|
||||||
|
message
|
||||||
|
});
|
||||||
|
|
||||||
const container = document.createElement('div');
|
const container = document.createElement('div');
|
||||||
container.classList.add('document-container');
|
container.classList.add('document-container');
|
||||||
|
@ -137,6 +137,10 @@ export class AppImManager {
|
|||||||
const hash = location.hash;
|
const hash = location.hash;
|
||||||
const splitted = hash.split('?');
|
const splitted = hash.split('?');
|
||||||
|
|
||||||
|
if(!splitted[1]) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
const params: any = {};
|
const params: any = {};
|
||||||
splitted[1].split('&').forEach(item => {
|
splitted[1].split('&').forEach(item => {
|
||||||
params[item.split('=')[0]] = decodeURIComponent(item.split('=')[1]);
|
params[item.split('=')[0]] = decodeURIComponent(item.split('=')[1]);
|
||||||
@ -148,7 +152,7 @@ export class AppImManager {
|
|||||||
case '#/im': {
|
case '#/im': {
|
||||||
const p = params.p;
|
const p = params.p;
|
||||||
if(p[0] === '@') {
|
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 => {
|
appUsersManager.resolveUsername(p).then(peer => {
|
||||||
const isUser = peer._ == 'user';
|
const isUser = peer._ == 'user';
|
||||||
const peerId = isUser ? peer.id : -peer.id;
|
const peerId = isUser ? peer.id : -peer.id;
|
||||||
|
@ -78,7 +78,10 @@ export type PinnedStorage = Partial<{
|
|||||||
count: number,
|
count: number,
|
||||||
maxId: number
|
maxId: number
|
||||||
}>;
|
}>;
|
||||||
export type MessagesStorage = {[mid: string]: any};
|
export type MessagesStorage = {
|
||||||
|
//generateIndex: (message: any) => void
|
||||||
|
[mid: string]: any
|
||||||
|
};
|
||||||
export class AppMessagesManager {
|
export class AppMessagesManager {
|
||||||
public messagesStorageByPeerId: {[peerId: string]: MessagesStorage} = {};
|
public messagesStorageByPeerId: {[peerId: string]: MessagesStorage} = {};
|
||||||
public groupedMessagesStorage: {[groupId: string]: MessagesStorage} = {}; // will be used for albums
|
public groupedMessagesStorage: {[groupId: string]: MessagesStorage} = {}; // will be used for albums
|
||||||
@ -107,7 +110,7 @@ export class AppMessagesManager {
|
|||||||
public pendingAfterMsgs: any = {};
|
public pendingAfterMsgs: any = {};
|
||||||
public pendingTopMsgs: {[peerId: string]: number} = {};
|
public pendingTopMsgs: {[peerId: string]: number} = {};
|
||||||
public sendFilePromise: CancellablePromise<void> = Promise.resolve();
|
public sendFilePromise: CancellablePromise<void> = Promise.resolve();
|
||||||
public tempId = -1;
|
public tempNum = 0;
|
||||||
public tempFinalizeCallbacks: {
|
public tempFinalizeCallbacks: {
|
||||||
[tempId: string]: {
|
[tempId: string]: {
|
||||||
[callbackName: string]: Partial<{
|
[callbackName: string]: Partial<{
|
||||||
@ -231,7 +234,7 @@ export class AppMessagesManager {
|
|||||||
let removeUnread = 0;
|
let removeUnread = 0;
|
||||||
for(const mid of history) {
|
for(const mid of history) {
|
||||||
const message = this.getMessageByPeer(dialog.peerId, mid);
|
const message = this.getMessageByPeer(dialog.peerId, mid);
|
||||||
if(/* message._ != 'messageEmpty' && */message.id > 0) {
|
if(/* message._ != 'messageEmpty' && */!message.pFlags.is_outgoing) {
|
||||||
messages.push(message);
|
messages.push(message);
|
||||||
|
|
||||||
if(message.fromId != dialog.peerId) {
|
if(message.fromId != dialog.peerId) {
|
||||||
@ -239,6 +242,7 @@ export class AppMessagesManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
dialog.top_message = message.mid;
|
dialog.top_message = message.mid;
|
||||||
|
this.setDialogIndexByMessage(dialog, message);
|
||||||
|
|
||||||
break;
|
break;
|
||||||
} else if(message.pFlags && message.pFlags.unread) {
|
} else if(message.pFlags && message.pFlags.unread) {
|
||||||
@ -341,7 +345,7 @@ export class AppMessagesManager {
|
|||||||
|
|
||||||
const {mid, peerId} = message;
|
const {mid, peerId} = message;
|
||||||
|
|
||||||
if(mid < 0) {
|
if(message.pFlags.is_outgoing) {
|
||||||
return this.invokeAfterMessageIsSent(mid, 'edit', (message) => {
|
return this.invokeAfterMessageIsSent(mid, 'edit', (message) => {
|
||||||
this.log('invoke editMessage callback', message);
|
this.log('invoke editMessage callback', message);
|
||||||
return this.editMessage(message, text, options);
|
return this.editMessage(message, text, options);
|
||||||
@ -357,7 +361,7 @@ export class AppMessagesManager {
|
|||||||
const schedule_date = options.scheduleDate || (message.pFlags.is_scheduled ? message.date : undefined);
|
const schedule_date = options.scheduleDate || (message.pFlags.is_scheduled ? message.date : undefined);
|
||||||
return apiManager.invokeApi('messages.editMessage', {
|
return apiManager.invokeApi('messages.editMessage', {
|
||||||
peer: appPeersManager.getInputPeerById(peerId),
|
peer: appPeersManager.getInputPeerById(peerId),
|
||||||
id: mid,
|
id: message.id,
|
||||||
message: text,
|
message: text,
|
||||||
media: options.newMedia,
|
media: options.newMedia,
|
||||||
entities: entities ? this.getInputEntities(entities) : undefined,
|
entities: entities ? this.getInputEntities(entities) : undefined,
|
||||||
@ -426,10 +430,10 @@ export class AppMessagesManager {
|
|||||||
sendEntites = undefined;
|
sendEntites = undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
var messageId = this.tempId--;
|
var messageId = this.generateTempMessageId(peerId);
|
||||||
var randomIdS = randomLong();
|
var randomIdS = randomLong();
|
||||||
var pFlags: any = {};
|
var pFlags: any = {};
|
||||||
var replyToMsgId = options.replyToMsgId;
|
var replyToMsgId = options.replyToMsgId ? this.getLocalMessageId(options.replyToMsgId) : undefined;
|
||||||
var isChannel = appPeersManager.isChannel(peerId);
|
var isChannel = appPeersManager.isChannel(peerId);
|
||||||
var isMegagroup = isChannel && appPeersManager.isMegagroup(peerId);
|
var isMegagroup = isChannel && appPeersManager.isMegagroup(peerId);
|
||||||
var asChannel = isChannel && !isMegagroup ? true : false;
|
var asChannel = isChannel && !isMegagroup ? true : false;
|
||||||
@ -589,10 +593,10 @@ export class AppMessagesManager {
|
|||||||
}> = {}) {
|
}> = {}) {
|
||||||
peerId = appPeersManager.getPeerMigratedTo(peerId) || peerId;
|
peerId = appPeersManager.getPeerMigratedTo(peerId) || peerId;
|
||||||
//this.checkSendOptions(options);
|
//this.checkSendOptions(options);
|
||||||
const messageId = this.tempId--;
|
const messageId = this.generateTempMessageId(peerId);
|
||||||
const randomIdS = randomLong();
|
const randomIdS = randomLong();
|
||||||
const pFlags: any = {};
|
const pFlags: any = {};
|
||||||
const replyToMsgId = options.replyToMsgId;
|
const replyToMsgId = options.replyToMsgId ? this.getLocalMessageId(options.replyToMsgId) : undefined;
|
||||||
const isChannel = appPeersManager.isChannel(peerId);
|
const isChannel = appPeersManager.isChannel(peerId);
|
||||||
const isMegagroup = isChannel && appPeersManager.isMegagroup(peerId);
|
const isMegagroup = isChannel && appPeersManager.isMegagroup(peerId);
|
||||||
const asChannel = !!(isChannel && !isMegagroup);
|
const asChannel = !!(isChannel && !isMegagroup);
|
||||||
@ -936,7 +940,7 @@ export class AppMessagesManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
peerId = appPeersManager.getPeerMigratedTo(peerId) || peerId;
|
peerId = appPeersManager.getPeerMigratedTo(peerId) || peerId;
|
||||||
const replyToMsgId = options.replyToMsgId;
|
const replyToMsgId = options.replyToMsgId ? this.getLocalMessageId(options.replyToMsgId) : undefined;
|
||||||
|
|
||||||
let caption = options.caption || '';
|
let caption = options.caption || '';
|
||||||
let entities: MessageEntity[];
|
let entities: MessageEntity[];
|
||||||
@ -966,20 +970,24 @@ export class AppMessagesManager {
|
|||||||
return this.sendFile(peerId, file, o).message;
|
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 => {
|
messages.forEach(message => {
|
||||||
message.grouped_id = groupId;
|
message.grouped_id = groupId;
|
||||||
});
|
});
|
||||||
|
|
||||||
const storage = options.scheduleDate ? this.getScheduledMessagesStorage(peerId) : this.getMessagesStorage(peerId);
|
const storage = options.scheduleDate ? this.getScheduledMessagesStorage(peerId) : this.getMessagesStorage(peerId);
|
||||||
if(options.scheduleDate) {
|
if(options.scheduleDate) {
|
||||||
this.saveMessages(messages, {storage, isScheduled: true});
|
this.saveMessages(messages, {storage, isScheduled: true, isOutgoing: true});
|
||||||
rootScope.broadcast('scheduled_new', {peerId, mid: groupId});
|
rootScope.broadcast('scheduled_new', {peerId, mid: groupId});
|
||||||
} else {
|
} else {
|
||||||
this.saveMessages(messages, {storage});
|
this.saveMessages(messages, {storage, isOutgoing: true});
|
||||||
rootScope.broadcast('history_append', {peerId, messageId: groupId, my: true});
|
rootScope.broadcast('history_append', {peerId, messageId: groupId, my: true});
|
||||||
|
|
||||||
|
this.setDialogTopMessage(message);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// * test pending
|
||||||
//return;
|
//return;
|
||||||
|
|
||||||
const toggleError = (message: any, on: boolean) => {
|
const toggleError = (message: any, on: boolean) => {
|
||||||
@ -1061,9 +1069,9 @@ export class AppMessagesManager {
|
|||||||
peerId = appPeersManager.getPeerMigratedTo(peerId) || peerId;
|
peerId = appPeersManager.getPeerMigratedTo(peerId) || peerId;
|
||||||
|
|
||||||
//this.checkSendOptions(options);
|
//this.checkSendOptions(options);
|
||||||
const messageId = this.tempId--;
|
const messageId = this.generateTempMessageId(peerId);
|
||||||
const randomIdS = randomLong();
|
const randomIdS = randomLong();
|
||||||
const replyToMsgId = options.replyToMsgId;
|
const replyToMsgId = options.replyToMsgId ? this.getLocalMessageId(options.replyToMsgId) : undefined;
|
||||||
const isChannel = appPeersManager.isChannel(peerId);
|
const isChannel = appPeersManager.isChannel(peerId);
|
||||||
const isMegagroup = isChannel && appPeersManager.isMegagroup(peerId);
|
const isMegagroup = isChannel && appPeersManager.isMegagroup(peerId);
|
||||||
const asChannel = isChannel && !isMegagroup ? true : false;
|
const asChannel = isChannel && !isMegagroup ? true : false;
|
||||||
@ -1266,16 +1274,19 @@ export class AppMessagesManager {
|
|||||||
|
|
||||||
if(options.isScheduled) {
|
if(options.isScheduled) {
|
||||||
if(!options.isGroupedItem) {
|
if(!options.isGroupedItem) {
|
||||||
this.saveMessages([message], {storage, isScheduled: true});
|
this.saveMessages([message], {storage, isScheduled: true, isOutgoing: true});
|
||||||
rootScope.broadcast('scheduled_new', {peerId, mid: messageId});
|
rootScope.broadcast('scheduled_new', {peerId, mid: messageId});
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
const historyStorage = this.getHistoryStorage(peerId);
|
const historyStorage = this.getHistoryStorage(peerId);
|
||||||
historyStorage.pending.unshift(messageId);
|
//historyStorage.pending.unshift(messageId);
|
||||||
|
historyStorage.history.unshift(messageId);
|
||||||
|
|
||||||
if(!options.isGroupedItem) {
|
if(!options.isGroupedItem) {
|
||||||
this.saveMessages([message], {storage});
|
this.saveMessages([message], {storage, isOutgoing: true});
|
||||||
rootScope.broadcast('history_append', {peerId, messageId, my: true});
|
rootScope.broadcast('history_append', {peerId, messageId, my: true});
|
||||||
|
|
||||||
|
this.setDialogTopMessage(message);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1284,6 +1295,25 @@ export class AppMessagesManager {
|
|||||||
if(!options.isGroupedItem) {
|
if(!options.isGroupedItem) {
|
||||||
setTimeout(message.send, 0);
|
setTimeout(message.send, 0);
|
||||||
//setTimeout(message.send, 4000);
|
//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 {
|
|||||||
scheduleDate: number
|
scheduleDate: number
|
||||||
}> = {}) {
|
}> = {}) {
|
||||||
peerId = appPeersManager.getPeerMigratedTo(peerId) || peerId;
|
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());
|
const randomIds: string[] = msgIds.map(() => randomLong());
|
||||||
|
|
||||||
@ -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) {
|
public getMessagesStorage(peerId: number) {
|
||||||
return this.messagesStorageByPeerId[peerId] ?? (this.messagesStorageByPeerId[peerId] = {});
|
return this.messagesStorageByPeerId[peerId] ?? (this.messagesStorageByPeerId[peerId] = this.createMessageStorage());
|
||||||
}
|
}
|
||||||
|
|
||||||
public getMessageById(messageId: number) {
|
public getMessageById(messageId: number) {
|
||||||
@ -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', {
|
return apiManager.invokeApi('messages.updatePinnedMessage', {
|
||||||
peer: appPeersManager.getInputPeerById(peerId),
|
peer: appPeersManager.getInputPeerById(peerId),
|
||||||
unpin,
|
unpin,
|
||||||
silent,
|
silent,
|
||||||
pm_oneside: oneSide,
|
pm_oneside: oneSide,
|
||||||
id: mid
|
id
|
||||||
}).then(updates => {
|
}).then(updates => {
|
||||||
this.log('pinned updates:', updates);
|
this.log('pinned updates:', updates);
|
||||||
apiUpdatesManager.processUpdateMessage(updates);
|
apiUpdatesManager.processUpdateMessage(updates);
|
||||||
@ -1789,9 +1841,47 @@ export class AppMessagesManager {
|
|||||||
else return [message.mid];
|
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<{
|
public saveMessages(messages: any[], options: Partial<{
|
||||||
storage: MessagesStorage,
|
storage: MessagesStorage,
|
||||||
isScheduled: true
|
isScheduled: true,
|
||||||
|
isOutgoing: true
|
||||||
}> = {}) {
|
}> = {}) {
|
||||||
let groups: Map<number, string>;
|
let groups: Map<number, string>;
|
||||||
messages.forEach((message) => {
|
messages.forEach((message) => {
|
||||||
@ -1807,15 +1897,20 @@ export class AppMessagesManager {
|
|||||||
// defineNotNumerableProperties(message, ['rReply', 'mid', 'savedFrom', 'fwdFromId', 'fromId', 'peerId', 'reply_to_mid', 'viaBotId']);
|
// defineNotNumerableProperties(message, ['rReply', 'mid', 'savedFrom', 'fwdFromId', 'fromId', 'peerId', 'reply_to_mid', 'viaBotId']);
|
||||||
|
|
||||||
const peerId = this.getMessagePeer(message);
|
const peerId = this.getMessagePeer(message);
|
||||||
|
const storage = options.storage || this.getMessagesStorage(peerId);
|
||||||
const isChannel = message.peer_id._ == 'peerChannel';
|
const isChannel = message.peer_id._ == 'peerChannel';
|
||||||
const channelId = isChannel ? -peerId : 0;
|
const channelId = isChannel ? -peerId : 0;
|
||||||
const isBroadcast = isChannel && appChatsManager.isBroadcast(channelId);
|
const isBroadcast = isChannel && appChatsManager.isBroadcast(channelId);
|
||||||
|
|
||||||
const mid = message.id;
|
|
||||||
if(options.isScheduled) {
|
if(options.isScheduled) {
|
||||||
message.pFlags.is_scheduled = true;
|
message.pFlags.is_scheduled = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(options.isOutgoing) {
|
||||||
|
message.pFlags.is_outgoing = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
const mid = this.generateMessageId(message.id);
|
||||||
message.mid = mid;
|
message.mid = mid;
|
||||||
|
|
||||||
if(message.grouped_id) {
|
if(message.grouped_id) {
|
||||||
@ -1834,7 +1929,8 @@ 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'])
|
// 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) {
|
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;
|
const overwriting = !!message.peerId;
|
||||||
@ -1842,6 +1938,7 @@ export class AppMessagesManager {
|
|||||||
message.date -= serverTimeManager.serverTimeOffset;
|
message.date -= serverTimeManager.serverTimeOffset;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//storage.generateIndex(message);
|
||||||
const myId = appUsersManager.getSelf().id;
|
const myId = appUsersManager.getSelf().id;
|
||||||
|
|
||||||
message.peerId = peerId;
|
message.peerId = peerId;
|
||||||
@ -1856,7 +1953,8 @@ export class AppMessagesManager {
|
|||||||
//if(peerId == myID) {
|
//if(peerId == myID) {
|
||||||
if(fwdHeader.saved_from_peer && fwdHeader.saved_from_msg_id) {
|
if(fwdHeader.saved_from_peer && fwdHeader.saved_from_msg_id) {
|
||||||
const savedFromPeerId = appPeersManager.getPeerId(fwdHeader.saved_from_peer);
|
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;
|
message.savedFrom = savedFromPeerId + '_' + savedFromMid;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2019,10 +2117,9 @@ export class AppMessagesManager {
|
|||||||
if(message.message && message.message.length && !message.totalEntities) {
|
if(message.message && message.message.length && !message.totalEntities) {
|
||||||
const myEntities = RichTextProcessor.parseEntities(message.message);
|
const myEntities = RichTextProcessor.parseEntities(message.message);
|
||||||
const apiEntities = message.entities || [];
|
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;
|
storage[mid] = message;
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -2417,10 +2514,10 @@ export class AppMessagesManager {
|
|||||||
|
|
||||||
let mid: number, message;
|
let mid: number, message;
|
||||||
if(dialog.top_message) {
|
if(dialog.top_message) {
|
||||||
mid = dialog.top_message;
|
mid = this.generateMessageId(dialog.top_message);//dialog.top_message;
|
||||||
message = this.getMessageByPeer(peerId, mid);
|
message = this.getMessageByPeer(peerId, mid);
|
||||||
} else {
|
} else {
|
||||||
mid = this.tempId--;
|
mid = this.generateTempMessageId(peerId);
|
||||||
message = {
|
message = {
|
||||||
_: 'message',
|
_: 'message',
|
||||||
id: mid,
|
id: mid,
|
||||||
@ -2432,7 +2529,7 @@ export class AppMessagesManager {
|
|||||||
date: 0,
|
date: 0,
|
||||||
message: ''
|
message: ''
|
||||||
};
|
};
|
||||||
this.saveMessages([message]);
|
this.saveMessages([message], {isOutgoing: true});
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!message?.pFlags) {
|
if(!message?.pFlags) {
|
||||||
@ -2450,6 +2547,8 @@ export class AppMessagesManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
dialog.top_message = mid;
|
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.hasOwnProperty('folder_id')) {
|
||||||
if(dialog._ == 'dialog') {
|
if(dialog._ == 'dialog') {
|
||||||
@ -2536,7 +2635,7 @@ export class AppMessagesManager {
|
|||||||
if(lastReplyMarkup) {
|
if(lastReplyMarkup) {
|
||||||
if(lastReplyMarkup.pFlags.single_use &&
|
if(lastReplyMarkup.pFlags.single_use &&
|
||||||
!lastReplyMarkup.pFlags.hidden &&
|
!lastReplyMarkup.pFlags.hidden &&
|
||||||
(message.mid > lastReplyMarkup.mid || message.mid < 0) &&
|
(message.mid > lastReplyMarkup.mid || message.pFlags.is_outgoing) &&
|
||||||
message.message) {
|
message.message) {
|
||||||
lastReplyMarkup.pFlags.hidden = true;
|
lastReplyMarkup.pFlags.hidden = true;
|
||||||
// this.log('set', historyStorage.reply_markup)
|
// this.log('set', historyStorage.reply_markup)
|
||||||
@ -2757,7 +2856,7 @@ export class AppMessagesManager {
|
|||||||
min_date: 0,
|
min_date: 0,
|
||||||
max_date: 0,
|
max_date: 0,
|
||||||
limit,
|
limit,
|
||||||
offset_id: maxId || 0,
|
offset_id: this.getLocalMessageId(maxId) || 0,
|
||||||
add_offset: backLimit ? -backLimit : 0,
|
add_offset: backLimit ? -backLimit : 0,
|
||||||
max_id: 0,
|
max_id: 0,
|
||||||
min_id: 0,
|
min_id: 0,
|
||||||
@ -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>;
|
let promise: Promise<any>;
|
||||||
|
|
||||||
|
mids = mids.map(mid => this.getLocalMessageId(mid));
|
||||||
|
|
||||||
if(peerId < 0 && appPeersManager.isChannel(-peerId)) {
|
if(peerId < 0 && appPeersManager.isChannel(-peerId)) {
|
||||||
const channelId = -peerId;
|
const channelId = -peerId;
|
||||||
const channel = appChatsManager.getChat(channelId);
|
const channel = appChatsManager.getChat(channelId);
|
||||||
if(!channel.pFlags.creator && !(channel.pFlags.editor && channel.pFlags.megagroup)) {
|
if(!channel.pFlags.creator && !(channel.pFlags.editor && channel.pFlags.megagroup)) {
|
||||||
const goodMsgIds: number[] = [];
|
const goodMsgIds: number[] = [];
|
||||||
if (channel.pFlags.editor || channel.pFlags.megagroup) {
|
if (channel.pFlags.editor || channel.pFlags.megagroup) {
|
||||||
msgIds.forEach((msgId, i) => {
|
mids.forEach((msgId, i) => {
|
||||||
const message = this.getMessageByPeer(peerId, msgIds[i]);
|
const message = this.getMessageByPeer(peerId, mids[i]);
|
||||||
if(message.pFlags.out) {
|
if(message.pFlags.out) {
|
||||||
goodMsgIds.push(msgId);
|
goodMsgIds.push(msgId);
|
||||||
}
|
}
|
||||||
@ -2894,19 +2995,19 @@ export class AppMessagesManager {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
msgIds = goodMsgIds;
|
mids = goodMsgIds;
|
||||||
}
|
}
|
||||||
|
|
||||||
promise = apiManager.invokeApi('channels.deleteMessages', {
|
promise = apiManager.invokeApi('channels.deleteMessages', {
|
||||||
channel: appChatsManager.getChannelInput(channelId),
|
channel: appChatsManager.getChannelInput(channelId),
|
||||||
id: msgIds
|
id: mids
|
||||||
}).then((affectedMessages) => {
|
}).then((affectedMessages) => {
|
||||||
apiUpdatesManager.processUpdateMessage({
|
apiUpdatesManager.processUpdateMessage({
|
||||||
_: 'updateShort',
|
_: 'updateShort',
|
||||||
update: {
|
update: {
|
||||||
_: 'updateDeleteChannelMessages',
|
_: 'updateDeleteChannelMessages',
|
||||||
channel_id: channelId,
|
channel_id: channelId,
|
||||||
messages: msgIds,
|
messages: mids,
|
||||||
pts: affectedMessages.pts,
|
pts: affectedMessages.pts,
|
||||||
pts_count: affectedMessages.pts_count
|
pts_count: affectedMessages.pts_count
|
||||||
}
|
}
|
||||||
@ -2915,13 +3016,13 @@ export class AppMessagesManager {
|
|||||||
} else {
|
} else {
|
||||||
promise = apiManager.invokeApi('messages.deleteMessages', {
|
promise = apiManager.invokeApi('messages.deleteMessages', {
|
||||||
revoke: revoke || undefined,
|
revoke: revoke || undefined,
|
||||||
id: msgIds
|
id: mids
|
||||||
}).then((affectedMessages) => {
|
}).then((affectedMessages) => {
|
||||||
apiUpdatesManager.processUpdateMessage({
|
apiUpdatesManager.processUpdateMessage({
|
||||||
_: 'updateShort',
|
_: 'updateShort',
|
||||||
update: {
|
update: {
|
||||||
_: 'updateDeleteMessages',
|
_: 'updateDeleteMessages',
|
||||||
messages: msgIds,
|
messages: mids,
|
||||||
pts: affectedMessages.pts,
|
pts: affectedMessages.pts,
|
||||||
pts_count: affectedMessages.pts_count
|
pts_count: affectedMessages.pts_count
|
||||||
}
|
}
|
||||||
@ -3064,7 +3165,8 @@ export class AppMessagesManager {
|
|||||||
//this.log('AMM updateMessageID:', update, pendingData);
|
//this.log('AMM updateMessageID:', update, pendingData);
|
||||||
if(pendingData) {
|
if(pendingData) {
|
||||||
const {peerId, tempId, storage} = 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);
|
const message = this.getMessageFromStorage(storage, mid);
|
||||||
if(!message.deleted) {
|
if(!message.deleted) {
|
||||||
const historyStorage = this.getHistoryStorage(peerId);
|
const historyStorage = this.getHistoryStorage(peerId);
|
||||||
@ -3150,16 +3252,10 @@ export class AppMessagesManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const inboxUnread = !message.pFlags.out && message.pFlags.unread;
|
const inboxUnread = !message.pFlags.out && message.pFlags.unread;
|
||||||
dialog.top_message = message.mid;
|
this.setDialogTopMessage(message);
|
||||||
if(inboxUnread) {
|
if(inboxUnread) {
|
||||||
dialog.unread_count++;
|
dialog.unread_count++;
|
||||||
}
|
}
|
||||||
if(!dialog.pFlags.pinned || !dialog.index) {
|
|
||||||
dialog.index = this.dialogsStorage.generateDialogIndex(message.date);
|
|
||||||
}
|
|
||||||
|
|
||||||
this.newDialogsToHandle[peerId] = dialog;
|
|
||||||
this.scheduleHandleNewDialogs();
|
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -3331,7 +3427,8 @@ export class AppMessagesManager {
|
|||||||
case 'updateEditChannelMessage': {
|
case 'updateEditChannelMessage': {
|
||||||
const message = update.message as MyMessage;
|
const message = update.message as MyMessage;
|
||||||
const peerId = this.getMessagePeer(message);
|
const peerId = this.getMessagePeer(message);
|
||||||
const mid = message.id;
|
//const mid = message.id;
|
||||||
|
const mid = this.generateMessageId(message.id);
|
||||||
const storage = this.getMessagesStorage(peerId);
|
const storage = this.getMessagesStorage(peerId);
|
||||||
if(storage[mid] === undefined) {
|
if(storage[mid] === undefined) {
|
||||||
break;
|
break;
|
||||||
@ -3388,7 +3485,8 @@ export class AppMessagesManager {
|
|||||||
case 'updateReadChannelInbox':
|
case 'updateReadChannelInbox':
|
||||||
case 'updateReadChannelOutbox': {
|
case 'updateReadChannelOutbox': {
|
||||||
const channelId: number = (update as Update.updateReadChannelInbox).channel_id;
|
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 peerId = channelId ? -channelId : appPeersManager.getPeerId((update as Update.updateReadHistoryInbox).peer);
|
||||||
const isOut = update._ == 'updateReadHistoryOutbox' || update._ == 'updateReadChannelOutbox' ? true : undefined;
|
const isOut = update._ == 'updateReadHistoryOutbox' || update._ == 'updateReadChannelOutbox' ? true : undefined;
|
||||||
const foundDialog = this.getDialogByPeerId(peerId)[0];
|
const foundDialog = this.getDialogByPeerId(peerId)[0];
|
||||||
@ -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;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3493,7 +3591,8 @@ export class AppMessagesManager {
|
|||||||
case 'updateDeleteMessages':
|
case 'updateDeleteMessages':
|
||||||
case 'updateDeleteChannelMessages': {
|
case 'updateDeleteChannelMessages': {
|
||||||
const channelId: number = (update as Update.updateDeleteChannelMessages).channel_id;
|
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;
|
const peerId = channelId ? -channelId : this.getMessageById(messages[0]).peerId;
|
||||||
|
|
||||||
if(!peerId) {
|
if(!peerId) {
|
||||||
@ -3588,7 +3687,8 @@ export class AppMessagesManager {
|
|||||||
|
|
||||||
case 'updateChannelMessageViews': {
|
case 'updateChannelMessageViews': {
|
||||||
const views = update.views;
|
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);
|
const message = this.getMessageByPeer(-update.channel_id, mid);
|
||||||
if(!message.deleted && message.views && message.views < views) {
|
if(!message.deleted && message.views && message.views < views) {
|
||||||
message.views = views;
|
message.views = views;
|
||||||
@ -3601,7 +3701,7 @@ export class AppMessagesManager {
|
|||||||
this.log('updateServiceNotification', update);
|
this.log('updateServiceNotification', update);
|
||||||
const fromId = 777000;
|
const fromId = 777000;
|
||||||
const peerId = fromId;
|
const peerId = fromId;
|
||||||
const messageId = this.tempId--;
|
const messageId = this.generateTempMessageId(peerId);
|
||||||
const message: any = {
|
const message: any = {
|
||||||
_: 'message',
|
_: 'message',
|
||||||
id: messageId,
|
id: messageId,
|
||||||
@ -3623,7 +3723,7 @@ export class AppMessagesManager {
|
|||||||
phone: '42777'
|
phone: '42777'
|
||||||
}]);
|
}]);
|
||||||
}
|
}
|
||||||
this.saveMessages([message]);
|
this.saveMessages([message], {isOutgoing: true});
|
||||||
|
|
||||||
if(update.inbox_date) {
|
if(update.inbox_date) {
|
||||||
this.pendingTopMsgs[peerId] = messageId;
|
this.pendingTopMsgs[peerId] = messageId;
|
||||||
@ -3710,7 +3810,7 @@ export class AppMessagesManager {
|
|||||||
|
|
||||||
const storage = this.scheduledMessagesStorage[peerId];
|
const storage = this.scheduledMessagesStorage[peerId];
|
||||||
if(storage) {
|
if(storage) {
|
||||||
const mid = message.id;
|
const mid = this.generateMessageId(message.id);
|
||||||
|
|
||||||
const oldMessage = this.getMessageFromStorage(storage, mid);
|
const oldMessage = this.getMessageFromStorage(storage, mid);
|
||||||
this.saveMessages([message], {storage, isScheduled: true});
|
this.saveMessages([message], {storage, isScheduled: true});
|
||||||
@ -3735,9 +3835,10 @@ export class AppMessagesManager {
|
|||||||
|
|
||||||
const storage = this.scheduledMessagesStorage[peerId];
|
const storage = this.scheduledMessagesStorage[peerId];
|
||||||
if(storage) {
|
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;
|
break;
|
||||||
@ -3836,6 +3937,7 @@ export class AppMessagesManager {
|
|||||||
|
|
||||||
const message = this.getMessageFromStorage(storage, tempId);
|
const message = this.getMessageFromStorage(storage, tempId);
|
||||||
if(!message.deleted) {
|
if(!message.deleted) {
|
||||||
|
delete message.pFlags.is_outgoing;
|
||||||
delete message.pending;
|
delete message.pending;
|
||||||
delete message.error;
|
delete message.error;
|
||||||
delete message.random_id;
|
delete message.random_id;
|
||||||
@ -3913,7 +4015,7 @@ export class AppMessagesManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public getScheduledMessagesStorage(peerId: number) {
|
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[]> {
|
public getScheduledMessages(peerId: number): Promise<number[]> {
|
||||||
@ -4158,7 +4260,7 @@ export class AppMessagesManager {
|
|||||||
|
|
||||||
const promise = apiManager.invokeApi('messages.getHistory', {
|
const promise = apiManager.invokeApi('messages.getHistory', {
|
||||||
peer: appPeersManager.getInputPeerById(peerId),
|
peer: appPeersManager.getInputPeerById(peerId),
|
||||||
offset_id: maxId || 0,
|
offset_id: this.getLocalMessageId(maxId) || 0,
|
||||||
offset_date: offsetDate,
|
offset_date: offsetDate,
|
||||||
add_offset: offset,
|
add_offset: offset,
|
||||||
limit: limit,
|
limit: limit,
|
||||||
|
@ -170,7 +170,7 @@ export class AppPollsManager {
|
|||||||
const peerId = message.peerId;
|
const peerId = message.peerId;
|
||||||
const inputPeer = appPeersManager.getInputPeerById(peerId);
|
const inputPeer = appPeersManager.getInputPeerById(peerId);
|
||||||
|
|
||||||
if(messageId < 0) {
|
if(message.pFlags.is_outgoing) {
|
||||||
return appMessagesManager.invokeAfterMessageIsSent(messageId, 'sendVote', (message) => {
|
return appMessagesManager.invokeAfterMessageIsSent(messageId, 'sendVote', (message) => {
|
||||||
this.log('invoke sendVote callback');
|
this.log('invoke sendVote callback');
|
||||||
return this.sendVote(message, optionIds);
|
return this.sendVote(message, optionIds);
|
||||||
|
@ -513,7 +513,8 @@ export class ApiFileManager {
|
|||||||
(r.value as Promise<void>).then(process);
|
(r.value as Promise<void>).then(process);
|
||||||
};
|
};
|
||||||
|
|
||||||
const maxRequests = Infinity;
|
//const maxRequests = Infinity;
|
||||||
|
const maxRequests = 10;
|
||||||
/* for(let i = 0; i < 10; ++i) {
|
/* for(let i = 0; i < 10; ++i) {
|
||||||
process();
|
process();
|
||||||
} */
|
} */
|
||||||
|
@ -364,7 +364,7 @@ namespace RichTextProcessor {
|
|||||||
return totalEntities;
|
return totalEntities;
|
||||||
} */
|
} */
|
||||||
|
|
||||||
export function mergeEntities(currentEntities: MessageEntity[], newEntities: MessageEntity[], fromApi?: boolean) {
|
export function mergeEntities(currentEntities: MessageEntity[], newEntities: MessageEntity[]) {
|
||||||
currentEntities = currentEntities.slice();
|
currentEntities = currentEntities.slice();
|
||||||
const filtered = newEntities.filter(e => !currentEntities.find(_e => e._ == _e._ && e.offset == _e.offset && e.length == _e.length));
|
const filtered = newEntities.filter(e => !currentEntities.find(_e => e._ == _e._ && e.offset == _e.offset && e.length == _e.length));
|
||||||
currentEntities.push(...filtered);
|
currentEntities.push(...filtered);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user