Browse Source

Refactor message ids

Refactor message storage
Handle scheduled messages updates
master
Eduard Kuzmenko 4 years ago
parent
commit
8330fd2774
  1. 17
      src/components/appMediaPlaybackController.ts
  2. 12
      src/components/appMediaViewer.ts
  3. 5
      src/components/appSearch.ts
  4. 15
      src/components/audio.ts
  5. 4
      src/components/avatar.ts
  6. 4
      src/components/chat/audio.ts
  7. 129
      src/components/chat/bubbles.ts
  8. 31
      src/components/chat/chat.ts
  9. 34
      src/components/chat/contextMenu.ts
  10. 37
      src/components/chat/input.ts
  11. 4
      src/components/chat/pinnedMessage.ts
  12. 12
      src/components/chat/selection.ts
  13. 14
      src/components/chat/topbar.ts
  14. 8
      src/components/poll.ts
  15. 7
      src/components/popupDeleteMessages.ts
  16. 4
      src/components/popupForward.ts
  17. 2
      src/components/popupNewMedia.ts
  18. 2
      src/components/sidebarRight/tabs/forward.ts
  19. 8
      src/components/sidebarRight/tabs/pollResults.ts
  20. 8
      src/components/sidebarRight/tabs/sharedMedia.ts
  21. 31
      src/components/wrappers.ts
  22. 9
      src/lib/appManagers/AppInlineBotsManager.ts
  23. 4
      src/lib/appManagers/appDialogsManager.ts
  24. 13
      src/lib/appManagers/appImManager.ts
  25. 85
      src/lib/appManagers/appMessagesIDsManager.ts
  26. 433
      src/lib/appManagers/appMessagesManager.ts
  27. 32
      src/lib/appManagers/appPollsManager.ts
  28. 6
      src/lib/appManagers/appStateManager.ts
  29. 3
      src/lib/mtproto/referenceDatabase.ts
  30. 7
      src/lib/rootScope.ts
  31. 7
      src/lib/storages/dialogs.ts
  32. 2
      src/scss/partials/_chatBubble.scss
  33. 1
      src/scss/partials/_rightSidebar.scss

17
src/components/appMediaPlaybackController.ts

@ -34,7 +34,7 @@ class AppMediaPlaybackController { @@ -34,7 +34,7 @@ class AppMediaPlaybackController {
document.body.append(this.container);
}
public addMedia(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 media = document.createElement(doc.type == 'round' ? 'video' : 'audio');
@ -61,12 +61,12 @@ class AppMediaPlaybackController { @@ -61,12 +61,12 @@ class AppMediaPlaybackController {
}
this.playingMedia = media;
this.loadSiblingsMedia(doc.type as MediaType, mid);
this.loadSiblingsMedia(peerId, doc.type as MediaType, mid);
}
// audio_pause не успеет сработать без таймаута
setTimeout(() => {
rootScope.broadcast('audio_play', {doc, mid});
rootScope.broadcast('audio_play', {peerId, doc, mid});
}, 0);
});
@ -75,7 +75,7 @@ class AppMediaPlaybackController { @@ -75,7 +75,7 @@ class AppMediaPlaybackController {
const onError = (e: Event) => {
if(this.nextMid == mid) {
this.loadSiblingsMedia(doc.type as MediaType, mid).then(() => {
this.loadSiblingsMedia(peerId, doc.type as MediaType, mid).then(() => {
if(this.nextMid && this.media[this.nextMid]) {
this.media[this.nextMid].play();
}
@ -181,12 +181,11 @@ class AppMediaPlaybackController { @@ -181,12 +181,11 @@ class AppMediaPlaybackController {
}
};
private loadSiblingsMedia(type: MediaType, mid: number) {
private loadSiblingsMedia(peerId: number, type: MediaType, mid: number) {
const media = this.playingMedia;
const message = appMessagesManager.getMessage(mid);
this.prevMid = this.nextMid = 0;
return appMessagesManager.getSearch(message.peerId, '', {
return appMessagesManager.getSearch(peerId, '', {
//_: type == 'audio' ? 'inputMessagesFilterMusic' : (type == 'round' ? 'inputMessagesFilterRoundVideo' : 'inputMessagesFilterVoice')
_: type == 'audio' ? 'inputMessagesFilterMusic' : 'inputMessagesFilterRoundVoice'
}, mid, 3, 0, 2).then(value => {
@ -204,8 +203,8 @@ class AppMediaPlaybackController { @@ -204,8 +203,8 @@ class AppMediaPlaybackController {
}
[this.prevMid, this.nextMid].filter(Boolean).forEach(mid => {
const message = appMessagesManager.getMessage(mid);
this.addMedia(message.media.document, mid, false);
const message = appMessagesManager.getMessageByPeer(peerId, mid);
this.addMedia(peerId, message.media.document, mid, false);
});
//console.log('loadSiblingsAudio', audio, type, mid, value, this.prevMid, this.nextMid);

12
src/components/appMediaViewer.ts

@ -1165,18 +1165,18 @@ export default class AppMediaViewer extends AppMediaViewerBase<'caption', 'delet @@ -1165,18 +1165,18 @@ export default class AppMediaViewer extends AppMediaViewerBase<'caption', 'delet
onPrevClick = (target: AppMediaViewerTargetType) => {
this.nextTargets.unshift({element: this.lastTarget, mid: this.currentMessageId});
this.openMedia(appMessagesManager.getMessage(target.mid), target.element);
this.openMedia(appMessagesManager.getMessageByPeer(this.peerId, target.mid), target.element);
};
onNextClick = (target: AppMediaViewerTargetType) => {
this.prevTargets.push({element: this.lastTarget, mid: this.currentMessageId});
this.openMedia(appMessagesManager.getMessage(target.mid), target.element);
this.openMedia(appMessagesManager.getMessageByPeer(this.peerId, target.mid), target.element);
};
onForwardClick = () => {
if(this.currentMessageId) {
//appSidebarRight.forwardTab.open([this.currentMessageId]);
new PopupForward([this.currentMessageId], () => {
new PopupForward(this.peerId, [this.currentMessageId], () => {
return this.close();
});
}
@ -1192,14 +1192,14 @@ export default class AppMediaViewer extends AppMediaViewerBase<'caption', 'delet @@ -1192,14 +1192,14 @@ export default class AppMediaViewer extends AppMediaViewerBase<'caption', 'delet
appSidebarRight.sharedMediaTab.closeBtn.click();
}
const message = appMessagesManager.getMessage(mid);
const message = appMessagesManager.getMessageByPeer(this.peerId, mid);
appImManager.setPeer(message.peerId, mid);
});
}
};
onDownloadClick = () => {
const message = appMessagesManager.getMessage(this.currentMessageId);
const message = appMessagesManager.getMessageByPeer(this.peerId, this.currentMessageId);
if(message.media.photo) {
appPhotosManager.savePhotoFile(message.media.photo, appImManager.chat.bubbles.lazyLoadQueue.queueId);
} else {
@ -1262,7 +1262,7 @@ export default class AppMediaViewer extends AppMediaViewerBase<'caption', 'delet @@ -1262,7 +1262,7 @@ export default class AppMediaViewer extends AppMediaViewerBase<'caption', 'delet
const method = older ? value.history.forEach : value.history.forEachReverse;
method.call(value.history, mid => {
const message = appMessagesManager.getMessage(mid);
const message = appMessagesManager.getMessageByPeer(this.peerId, mid);
const media = this.getMediaFromMessage(message);
if(!media) return;

5
src/components/appSearch.ts

@ -1,6 +1,5 @@ @@ -1,6 +1,5 @@
import appDialogsManager from "../lib/appManagers/appDialogsManager";
import Scrollable from "./scrollable";
import appMessagesIdsManager from "../lib/appManagers/appMessagesIdsManager";
import appUsersManager from "../lib/appManagers/appUsersManager";
import appPeersManager from '../lib/appManagers/appPeersManager';
import appMessagesManager from "../lib/appManagers/appMessagesManager";
@ -157,7 +156,7 @@ export default class AppSearch { @@ -157,7 +156,7 @@ export default class AppSearch {
return Promise.resolve();
}
const maxId = appMessagesIdsManager.getMessageIdInfo(this.minMsgId)[0] || 0;
const maxId = this.minMsgId || 0;
if(!this.peerId && !maxId && !this.loadedContacts) {
const renderedPeerIds: Set<number> = new Set();
@ -259,7 +258,7 @@ export default class AppSearch { @@ -259,7 +258,7 @@ export default class AppSearch {
const searchGroup = this.searchGroups.messages;
history.forEach((msgId: number) => {
const message = appMessagesManager.getMessage(msgId);
const message = appMessagesManager.getMessageByPeer(this.peerId, msgId);
const {dialog, dom} = appDialogsManager.addDialogNew({
dialog: message.peerId,

15
src/components/audio.ts

@ -14,10 +14,10 @@ import './middleEllipsis'; @@ -14,10 +14,10 @@ import './middleEllipsis';
import { attachClickEvent, cancelEvent, detachClickEvent } from "../helpers/dom";
rootScope.on('messages_media_read', e => {
const mids = e.detail;
const {mids, peerId} = e.detail;
mids.forEach(mid => {
(Array.from(document.querySelectorAll('audio-element[message-id="' + mid + '"]')) as AudioElement[]).forEach(elem => {
(Array.from(document.querySelectorAll('audio-element[message-id="' + mid + '"][peer-id="' + peerId + '"]')) as AudioElement[]).forEach(elem => {
//console.log('updating avatar:', elem);
elem.classList.remove('is-unread');
});
@ -61,10 +61,10 @@ export function decodeWaveform(waveform: Uint8Array | number[]) { @@ -61,10 +61,10 @@ export function decodeWaveform(waveform: Uint8Array | number[]) {
return result;
}
function wrapVoiceMessage(doc: MyDocument, audioEl: AudioElement, mid: number) {
function wrapVoiceMessage(peerId: number, doc: MyDocument, audioEl: AudioElement, mid: number) {
audioEl.classList.add('is-voice');
const message = appMessagesManager.getMessage(mid);
const message = appMessagesManager.getMessageByPeer(peerId, mid);
const isOut = message.fromId == rootScope.myId && message.peerId != rootScope.myId;
let isUnread = message && message.pFlags.media_unread;
if(isUnread) {
@ -171,7 +171,7 @@ function wrapVoiceMessage(doc: MyDocument, audioEl: AudioElement, mid: number) { @@ -171,7 +171,7 @@ function wrapVoiceMessage(doc: MyDocument, audioEl: AudioElement, mid: number) {
audioEl.addAudioListener('playing', () => {
if(isUnread && !isOut && audioEl.classList.contains('is-unread')) {
audioEl.classList.remove('is-unread');
appMessagesManager.readMessages([mid]);
appMessagesManager.readMessages(peerId, [mid]);
isUnread = false;
}
@ -329,6 +329,7 @@ export default class AudioElement extends HTMLElement { @@ -329,6 +329,7 @@ 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);
@ -351,13 +352,13 @@ export default class AudioElement extends HTMLElement { @@ -351,13 +352,13 @@ export default class AudioElement extends HTMLElement {
this.append(downloadDiv);
}
const onTypeLoad = doc.type == 'voice' ? wrapVoiceMessage(doc, this, mid) : wrapAudio(doc, this);
const onTypeLoad = doc.type == 'voice' ? wrapVoiceMessage(peerId, doc, this, mid) : wrapAudio(doc, this);
const audioTimeDiv = this.querySelector('.audio-time') as HTMLDivElement;
audioTimeDiv.innerHTML = durationStr;
const onLoad = (autoload = true) => {
const audio = this.audio = appMediaPlaybackController.addMedia(doc, mid, autoload);
const audio = this.audio = appMediaPlaybackController.addMedia(peerId, doc, mid, autoload);
this.onTypeDisconnect = onTypeLoad();

4
src/components/avatar.ts

@ -57,7 +57,7 @@ export default class AvatarElement extends HTMLElement { @@ -57,7 +57,7 @@ export default class AvatarElement extends HTMLElement {
if(mid) {
// ! гений в деле, костылируем (но это гениально)
let message = appMessagesManager.getMessage(mid);
let message = appMessagesManager.getMessageByPeer(peerId, mid);
const messagePhoto = message.action.photo;
if(messagePhoto.id != photo.id) {
message = {
@ -72,7 +72,7 @@ export default class AvatarElement extends HTMLElement { @@ -72,7 +72,7 @@ export default class AvatarElement extends HTMLElement {
fromId: peerId
};
appMessagesManager.messagesStorage[maxId] = message;
appMessagesManager.getMessagesStorage(peerId)[maxId] = message;
}
const good = Array.from(this.querySelectorAll('img')).find(img => !img.classList.contains('emoji'));

4
src/components/chat/audio.ts

@ -35,10 +35,10 @@ export default class ChatAudio extends PinnedContainer { @@ -35,10 +35,10 @@ export default class ChatAudio extends PinnedContainer {
this.wrapper.prepend(this.toggleEl);
this.topbar.listenerSetter.add(rootScope, 'audio_play', (e) => {
const {doc, mid} = e.detail;
const {doc, mid, peerId} = e.detail;
let title: string, subtitle: string;
const message = appMessagesManager.getMessage(mid);
const message = appMessagesManager.getMessageByPeer(peerId, mid);
if(doc.type == 'voice' || doc.type == 'round') {
title = appPeersManager.getPeerTitle(message.fromId, false, true);
//subtitle = 'Voice message';

129
src/components/chat/bubbles.ts

@ -35,7 +35,6 @@ import LazyLoadQueue from "../lazyLoadQueue"; @@ -35,7 +35,6 @@ import LazyLoadQueue from "../lazyLoadQueue";
import { AppChatsManager } from "../../lib/appManagers/appChatsManager";
import Chat from "./chat";
import ListenerSetter from "../../helpers/listenerSetter";
import { pause } from "../../helpers/schedulers";
const IGNORE_ACTIONS = ['messageActionHistoryClear'];
@ -148,7 +147,7 @@ export default class ChatBubbles { @@ -148,7 +147,7 @@ export default class ChatBubbles {
let bubble = this.bubbles[mid];
if(!bubble) return;
let message = appMessagesManager.getMessage(mid);
let message = this.chat.getMessage(mid);
//this.log('history_update', this.bubbles[mid], mid, message);
let dateMessage = this.getDateContainerByMessage(message, false);
@ -196,7 +195,7 @@ export default class ChatBubbles { @@ -196,7 +195,7 @@ export default class ChatBubbles {
this.log('message_sent', e.detail);
const message = this.appMessagesManager.getMessage(mid);
const message = this.chat.getMessage(mid);
appSidebarRight.sharedMediaTab.renderNewMessages(message.peerId, [mid]);
@ -282,7 +281,7 @@ export default class ChatBubbles { @@ -282,7 +281,7 @@ export default class ChatBubbles {
if(!this.bubbles[maxId]) return;
const renderMaxId = getObjectKeysAndSort(appMessagesManager.groupedMessagesStorage[groupId], 'asc').pop();
this.renderMessage(appMessagesManager.getMessage(renderMaxId), true, false, this.bubbles[maxId], false);
this.renderMessage(this.chat.getMessage(renderMaxId), true, false, this.bubbles[maxId], false);
});
this.listenerSetter.add(rootScope, 'messages_downloaded', (e) => {
@ -301,9 +300,9 @@ export default class ChatBubbles { @@ -301,9 +300,9 @@ export default class ChatBubbles {
const bubble = this.bubbles[mid];
if(!bubble) return;
const message = appMessagesManager.getMessage(mid);
const message = this.chat.getMessage(mid);
const repliedMessage = appMessagesManager.getMessage(replyMid);
const repliedMessage = this.chat.getMessage(replyMid);
if(repliedMessage.deleted) { // чтобы не пыталось бесконечно загрузить удалённое сообщение
delete message.reply_to_mid; // WARNING!
}
@ -321,10 +320,14 @@ export default class ChatBubbles { @@ -321,10 +320,14 @@ export default class ChatBubbles {
}
});
this.listenerSetter.add(this.bubblesContainer, 'click', this.onBubblesClick/* , {capture: true, passive: false} */);
}
public constructPeerHelpers() {
this.listenerSetter.add(rootScope, 'dialog_unread', (e) => {
const info = e.detail;
const dialog = appMessagesManager.getDialogByPeerId(info.peerId)[0];
const dialog = this.appMessagesManager.getDialogByPeerId(info.peerId)[0];
if(dialog?.peerId == this.peerId) {
this.chat.input.setUnreadCount();
this.updateUnreadByDialog(dialog);
@ -347,8 +350,6 @@ export default class ChatBubbles { @@ -347,8 +350,6 @@ export default class ChatBubbles {
}
});
this.listenerSetter.add(this.bubblesContainer, 'click', this.onBubblesClick/* , {capture: true, passive: false} */);
this.stickyIntersector = new StickyIntersector(this.scrollable.container, (stuck, target) => {
for(const timestamp in this.dateMessages) {
const dateMessage = this.dateMessages[timestamp];
@ -395,9 +396,9 @@ export default class ChatBubbles { @@ -395,9 +396,9 @@ export default class ChatBubbles {
} */
//appMessagesManager.readMessages(readed);
/* false && */ appMessagesManager.readHistory(this.peerId, max).catch((err: any) => {
/* false && */ this.appMessagesManager.readHistory(this.peerId, max).catch((err: any) => {
this.log.error('readHistory err:', err);
appMessagesManager.readHistory(this.peerId, max);
this.appMessagesManager.readHistory(this.peerId, max);
});
}
});
@ -406,7 +407,6 @@ export default class ChatBubbles { @@ -406,7 +407,6 @@ export default class ChatBubbles {
public constructPinnedHelpers() {
this.listenerSetter.add(rootScope, 'peer_pinned_messages', (e) => {
const {peerId, mids, pinned} = e.detail;
if(peerId !== this.peerId) return;
if(mids) {
@ -417,6 +417,15 @@ export default class ChatBubbles { @@ -417,6 +417,15 @@ export default class ChatBubbles {
});
}
public constructScheduledHelpers() {
this.listenerSetter.add(rootScope, 'scheduled_delete', (e) => {
const {peerId, mids} = e.detail;
if(peerId !== this.peerId) return;
this.deleteMessagesByIds(mids);
});
}
public onBubblesClick = (e: Event) => {
let target = e.target as HTMLElement;
let bubble: HTMLElement = null;
@ -479,7 +488,7 @@ export default class ChatBubbles { @@ -479,7 +488,7 @@ export default class ChatBubbles {
if(bubble.classList.contains('sticker') && target.parentElement.classList.contains('attachment')) {
const messageId = +bubble.dataset.mid;
const message = this.appMessagesManager.getMessage(messageId);
const message = this.chat.getMessage(messageId);
const doc = message.media?.document;
@ -495,7 +504,7 @@ export default class ChatBubbles { @@ -495,7 +504,7 @@ export default class ChatBubbles {
|| isVideoComponentElement
|| (target.tagName == 'VIDEO' && !bubble.classList.contains('round'))) {
let messageId = +findUpClassName(target, 'album-item')?.dataset.mid || +bubble.dataset.mid;
let message = this.appMessagesManager.getMessage(messageId);
let message = this.chat.getMessage(messageId);
if(!message) {
this.log.warn('no message by messageId:', messageId);
return;
@ -505,7 +514,7 @@ export default class ChatBubbles { @@ -505,7 +514,7 @@ export default class ChatBubbles {
let ids = Object.keys(this.bubbles).map(k => +k).filter(id => {
//if(!this.scrollable.visibleElements.find(e => e.element == this.bubbles[id])) return false;
let message = this.appMessagesManager.getMessage(id);
let message = this.chat.getMessage(id);
return message.media && (message.media.photo || (message.media.document && (message.media.document.type == 'video' || message.media.document.type == 'gif')) || (message.media.webpage && (message.media.webpage.document || message.media.webpage.photo)));
}).sort((a, b) => a - b);
@ -548,9 +557,9 @@ export default class ChatBubbles { @@ -548,9 +557,9 @@ export default class ChatBubbles {
return;
}
if(['IMG', 'DIV', "AVATAR-ELEMENT", 'A'].indexOf(target.tagName) === -1) target = findUpTag(target, 'DIV');
if(['IMG', 'DIV', "AVATAR-ELEMENT"/* , 'A' */].indexOf(target.tagName) === -1) target = findUpTag(target, 'DIV');
if(target.tagName == 'DIV' || target.tagName == "AVATAR-ELEMENT" || target.tagName == 'A') {
if(target.tagName == 'DIV' || target.tagName == "AVATAR-ELEMENT"/* || target.tagName == 'A' */) {
if(target.classList.contains('goto-original')) {
const savedFrom = bubble.dataset.savedFrom;
const splitted = savedFrom.split('_');
@ -561,25 +570,10 @@ export default class ChatBubbles { @@ -561,25 +570,10 @@ export default class ChatBubbles {
return;
} else if(target.classList.contains('forward')) {
const mid = +bubble.dataset.mid;
new PopupForward([mid]);
new PopupForward(this.peerId, [mid]);
//appSidebarRight.forwardTab.open([mid]);
return;
}/* else if(target.classList.contains('follow')) {
cancelEvent(e);
const savedFrom = target.dataset.follow;
const splitted = savedFrom.split('_');
this.chat.appImManager.setInnerPeer(+splitted[0], splitted.length > 1 ? +splitted[1] : undefined);
return;
} else if(target.classList.contains('mention')) {
cancelEvent(e);
const username = target.innerText;
this.appUsersManager.resolveUsername(username.slice(1)).then(peer => {
this.chat.appImManager.setInnerPeer(peer._ == 'user' ? peer.id : -peer.id);
});
return;
} */ else if(target.classList.contains('name')) {
} else if(target.classList.contains('name')) {
const peerId = +target.dataset.peerId;
if(peerId) {
@ -628,7 +622,7 @@ export default class ChatBubbles { @@ -628,7 +622,7 @@ export default class ChatBubbles {
const rect = bubble.getBoundingClientRect();
bad = (this.appPhotosManager.windowH / 2) > rect.top;
} else {
const message = this.appMessagesManager.getMessage(mid);
const message = this.chat.getMessage(mid);
if(!message.deleted) {
bad = false;
}
@ -661,7 +655,7 @@ export default class ChatBubbles { @@ -661,7 +655,7 @@ export default class ChatBubbles {
if(this.bubbles[mid]) {
return {
bubble: this.bubbles[mid],
message: this.appMessagesManager.getMessage(+mid)
message: this.chat.getMessage(+mid)
};
}
}
@ -674,7 +668,7 @@ export default class ChatBubbles { @@ -674,7 +668,7 @@ export default class ChatBubbles {
}
public getMountedBubble(mid: number) {
const message = this.appMessagesManager.getMessage(mid);
const message = this.chat.getMessage(mid);
if(message.grouped_id && this.appMessagesManager.getMidsByAlbum(message.grouped_id).length > 1) {
const a = this.getGroupedBubble(message.grouped_id);
@ -837,7 +831,9 @@ export default class ChatBubbles { @@ -837,7 +831,9 @@ export default class ChatBubbles {
}
this.bubbleGroups.removeBubble(bubble, mid);
if(this.unreadedObserver) {
this.unreadedObserver.unobserve(bubble);
}
//this.unreaded.findAndSplice(mid => mid == id);
bubble.remove();
//bubble.remove();
@ -854,7 +850,7 @@ export default class ChatBubbles { @@ -854,7 +850,7 @@ export default class ChatBubbles {
}
msgIds.forEach((msgId: number) => {
let message = this.appMessagesManager.getMessage(msgId);
let message = this.chat.getMessage(msgId);
/////////this.log('got new message to append:', message);
@ -937,8 +933,10 @@ export default class ChatBubbles { @@ -937,8 +933,10 @@ export default class ChatBubbles {
this.chatInner.append(container);
}
if(this.stickyIntersector) {
this.stickyIntersector.observeStickyHeaderChanges(container);
}
}
return this.dateMessages[dateTimestamp];
}
@ -951,12 +949,12 @@ export default class ChatBubbles { @@ -951,12 +949,12 @@ export default class ChatBubbles {
this.listenerSetter.removeAll();
this.lazyLoadQueue.clear();
this.unreadedObserver.disconnect();
this.stickyIntersector.disconnect();
this.unreadedObserver && this.unreadedObserver.disconnect();
this.stickyIntersector && this.stickyIntersector.disconnect();
delete this.lazyLoadQueue;
delete this.unreadedObserver;
delete this.stickyIntersector;
this.unreadedObserver && delete this.unreadedObserver;
this.stickyIntersector && delete this.stickyIntersector;
}
public cleanup(bubblesToo = false) {
@ -990,10 +988,14 @@ export default class ChatBubbles { @@ -990,10 +988,14 @@ export default class ChatBubbles {
this.getHistoryTopPromise = this.getHistoryBottomPromise = undefined;
if(this.stickyIntersector) {
this.stickyIntersector.disconnect();
}
if(this.unreadedObserver) {
this.unreadedObserver.disconnect();
this.unreaded.length = 0;
}
this.loadedTopTimes = this.loadedBottomTimes = 0;
@ -1350,7 +1352,7 @@ export default class ChatBubbles { @@ -1350,7 +1352,7 @@ export default class ChatBubbles {
if(!our && !message.pFlags.out) {
//this.log('not our message', message, message.pFlags.unread);
if(message.pFlags.unread) {
if(message.pFlags.unread && this.unreadedObserver) {
this.unreadedObserver.observe(bubble);
if(!this.unreaded.indexOf(message.mid)) {
this.unreaded.push(message.mid);
@ -1539,7 +1541,7 @@ export default class ChatBubbles { @@ -1539,7 +1541,7 @@ export default class ChatBubbles {
}
const button = row.buttons[column];
this.appInlineBotsManager.callbackButtonClick(message.mid, button);
this.appInlineBotsManager.callbackButtonClick(this.peerId, message.mid, button);
});
const offset = rows.length * 45 + 'px';
@ -1585,7 +1587,8 @@ export default class ChatBubbles { @@ -1585,7 +1587,8 @@ export default class ChatBubbles {
groupId: '' + message.id,
attachmentDiv,
uploading: true,
isOut: true
isOut: true,
chat: this.chat
});
break;
@ -1645,7 +1648,8 @@ export default class ChatBubbles { @@ -1645,7 +1648,8 @@ export default class ChatBubbles {
albumMustBeRenderedFull,
message,
bubble,
messageDiv
messageDiv,
chat: this.chat
});
if(newNameContainer) {
@ -1681,7 +1685,8 @@ export default class ChatBubbles { @@ -1681,7 +1685,8 @@ export default class ChatBubbles {
attachmentDiv,
middleware: this.getMiddleware(),
isOut: our,
lazyLoadQueue: this.lazyLoadQueue
lazyLoadQueue: this.lazyLoadQueue,
chat: this.chat
});
break;
@ -1748,7 +1753,7 @@ export default class ChatBubbles { @@ -1748,7 +1753,7 @@ export default class ChatBubbles {
});
//}
} else {
const docDiv = wrapDocument(doc, false, false, message.mid);
const docDiv = wrapDocument(this.peerId, doc, false, false, message.mid);
preview.append(docDiv);
preview.classList.add('preview-with-document');
//messageDiv.classList.add((webpage.type || 'document') + '-message');
@ -1865,7 +1870,8 @@ export default class ChatBubbles { @@ -1865,7 +1870,8 @@ export default class ChatBubbles {
attachmentDiv,
middleware: this.getMiddleware(),
isOut: our,
lazyLoadQueue: this.lazyLoadQueue
lazyLoadQueue: this.lazyLoadQueue,
chat: this.chat
});
} else {
const withTail = !isAndroid && !isApple && doc.type != 'round' && !message.message;
@ -1890,7 +1896,8 @@ export default class ChatBubbles { @@ -1890,7 +1896,8 @@ export default class ChatBubbles {
albumMustBeRenderedFull,
message,
bubble,
messageDiv
messageDiv,
chat: this.chat
});
if(newNameContainer) {
@ -1943,7 +1950,7 @@ export default class ChatBubbles { @@ -1943,7 +1950,7 @@ export default class ChatBubbles {
case 'messageMediaPoll': {
bubble.classList.remove('is-message-empty');
const pollElement = wrapPoll(message.media.poll.id, message.mid);
const pollElement = wrapPoll(this.peerId, message.media.poll.id, message.mid);
messageDiv.prepend(pollElement);
messageDiv.classList.add('poll-message');
@ -2015,7 +2022,7 @@ export default class ChatBubbles { @@ -2015,7 +2022,7 @@ export default class ChatBubbles {
}
} else {
if(message.reply_to_mid) {
let originalMessage = this.appMessagesManager.getMessage(message.reply_to_mid);
let originalMessage = this.chat.getMessage(message.reply_to_mid);
let originalPeerTitle = this.appPeersManager.getPeerTitle(originalMessage.fromId || originalMessage.fwdFromId, true) || '';
/////////this.log('message to render reply', originalMessage, originalPeerTitle, bubble, message);
@ -2023,7 +2030,7 @@ export default class ChatBubbles { @@ -2023,7 +2030,7 @@ export default class ChatBubbles {
// need to download separately
if(originalMessage._ == 'messageEmpty') {
//////////this.log('message to render reply empty, need download', message, message.reply_to_mid);
this.appMessagesManager.wrapSingleMessage(message.reply_to_mid);
this.appMessagesManager.wrapSingleMessage(this.peerId, message.reply_to_mid);
this.needUpdate.push({replyMid: message.reply_to_mid, mid: message.mid});
originalPeerTitle = 'Loading...';
@ -2071,7 +2078,7 @@ export default class ChatBubbles { @@ -2071,7 +2078,7 @@ export default class ChatBubbles {
bubble.classList.add('hide-name');
}
if(this.chat.type == 'pinned') {
if(this.chat.type === 'pinned') {
savedFrom = `${this.chat.peerId}_${message.mid}`;
}
@ -2163,7 +2170,7 @@ export default class ChatBubbles { @@ -2163,7 +2170,7 @@ export default class ChatBubbles {
}
while(history.length) {
let message = this.appMessagesManager.getMessage(method());
let message = this.chat.getMessage(method());
this.renderMessage(message, reverse, true);
}
@ -2223,9 +2230,9 @@ export default class ChatBubbles { @@ -2223,9 +2230,9 @@ export default class ChatBubbles {
public requestHistory(maxId: number, loadCount: number, backLimit: number) {
//const middleware = this.getMiddleware();
if(this.chat.type == 'chat') {
if(this.chat.type === 'chat') {
return this.appMessagesManager.getHistory(this.peerId, maxId, loadCount, backLimit);
} else if(this.chat.type == 'pinned') {
} else if(this.chat.type === 'pinned') {
const promise = this.appMessagesManager.getSearch(this.peerId, '', {_: 'inputMessagesFilterPinned'}, maxId, loadCount, 0, backLimit);
/* if(maxId) {
@ -2238,6 +2245,8 @@ export default class ChatBubbles { @@ -2238,6 +2245,8 @@ export default class ChatBubbles {
} */
return promise;
} else if(this.chat.type === 'scheduled') {
return this.appMessagesManager.getScheduledMessages(this.peerId).then(mids => ({history: mids}));
}
}
@ -2293,7 +2302,7 @@ export default class ChatBubbles { @@ -2293,7 +2302,7 @@ export default class ChatBubbles {
// * filter last album, because we don't know is this the last item
for(let i = additionMsgIds.length - 1; i >= 0; --i) {
const message = this.appMessagesManager.getMessage(additionMsgIds[i]);
const message = this.chat.getMessage(additionMsgIds[i]);
if(message.grouped_id) additionMsgIds.splice(i, 1);
else break;
}
@ -2438,7 +2447,7 @@ export default class ChatBubbles { @@ -2438,7 +2447,7 @@ export default class ChatBubbles {
// preload more
//if(!isFirstMessageRender) {
if(this.chat.type == 'chat') {
if(this.chat.type === 'chat') {
const storage = this.appMessagesManager.historiesStorage[peerId];
const isMaxIdInHistory = storage.history.indexOf(maxId) !== -1;
if(isMaxIdInHistory) { // * otherwise it is a search or jump
@ -2490,7 +2499,9 @@ export default class ChatBubbles { @@ -2490,7 +2499,9 @@ export default class ChatBubbles {
if(dateMessage.container.childElementCount == 2) { // only date div + sentinel div
dateMessage.container.remove();
if(this.stickyIntersector) {
this.stickyIntersector.unobserve(dateMessage.container, dateMessage.div);
}
delete this.dateMessages[i];
}
}

31
src/components/chat/chat.ts

@ -21,7 +21,7 @@ import ChatInput from "./input"; @@ -21,7 +21,7 @@ import ChatInput from "./input";
import ChatSelection from "./selection";
import ChatTopbar from "./topbar";
export type ChatType = 'chat' | 'pinned' | 'replies' | 'discussion';
export type ChatType = 'chat' | 'pinned' | 'replies' | 'discussion' | 'scheduled';
export default class Chat extends EventListenerBase<{
setPeer: (mid: number, isTopMessage: boolean) => void
@ -61,6 +61,14 @@ export default class Chat extends EventListenerBase<{ @@ -61,6 +61,14 @@ export default class Chat extends EventListenerBase<{
this.appImManager.chatsContainer.append(this.container);
}
public setType(type: ChatType) {
this.type = type;
if(this.type === 'scheduled') {
this.getMessage = (mid) => this.appMessagesManager.getMessageFromStorage(this.appMessagesManager.getScheduledMessagesStorage(this.peerId), mid);
}
}
private init() {
this.topbar = new ChatTopbar(this, appSidebarRight, this.appMessagesManager, this.appPeersManager, this.appChatsManager);
this.bubbles = new ChatBubbles(this, this.appMessagesManager, this.appSidebarRight, this.appStickersManager, this.appUsersManager, this.appInlineBotsManager, this.appPhotosManager, this.appDocsManager, this.appPeersManager, this.appChatsManager);
@ -68,20 +76,23 @@ export default class Chat extends EventListenerBase<{ @@ -68,20 +76,23 @@ export default class Chat extends EventListenerBase<{
this.selection = new ChatSelection(this.bubbles, this.input, this.appMessagesManager);
this.contextMenu = new ChatContextMenu(this.bubbles.bubblesContainer, this, this.appMessagesManager, this.appChatsManager, this.appPeersManager, this.appPollsManager);
if(this.type == 'chat') {
if(this.type === 'chat') {
this.topbar.constructPeerHelpers();
} else if(this.type == 'pinned') {
} else if(this.type === 'pinned') {
this.topbar.constructPinnedHelpers();
}
this.topbar.construct();
this.input.construct();
if(this.type == 'chat') { // * гений в деле, разный порядок из-за разной последовательности действий
if(this.type === 'chat') { // * гений в деле, разный порядок из-за разной последовательности действий
this.bubbles.constructPeerHelpers();
this.input.constructPeerHelpers();
} else if(this.type == 'pinned') {
this.input.constructPinnedHelpers();
} else if(this.type === 'pinned') {
this.bubbles.constructPinnedHelpers();
this.input.constructPinnedHelpers();
} else if(this.type === 'scheduled') {
this.bubbles.constructScheduledHelpers();
}
this.container.classList.add('type-' + this.type);
@ -187,4 +198,12 @@ export default class Chat extends EventListenerBase<{ @@ -187,4 +198,12 @@ export default class Chat extends EventListenerBase<{
rootScope.broadcast('peer_changed', peerId);
}
public getMessage(mid: number) {
return this.appMessagesManager.getMessageByPeer(this.peerId, mid);
}
public getMidsByMid(mid: number) {
return this.appMessagesManager.getMidsByMid(this.peerId, mid);
}
}

34
src/components/chat/contextMenu.ts

@ -50,7 +50,7 @@ export default class ChatContextMenu { @@ -50,7 +50,7 @@ export default class ChatContextMenu {
// * если открыть контекстное меню для альбома не по бабблу, и последний элемент не выбран, чтобы показать остальные пункты
if(chat.selection.isSelecting && !bubbleContainer) {
const mids = appMessagesManager.getMidsByMid(mid);
const mids = this.chat.getMidsByMid(mid);
if(mids.length > 1) {
const selectedMid = chat.selection.selectedMids.has(mid) ? mid : mids.find(mid => chat.selection.selectedMids.has(mid));
if(selectedMid) {
@ -147,17 +147,17 @@ export default class ChatContextMenu { @@ -147,17 +147,17 @@ export default class ChatContextMenu {
icon: 'edit',
text: 'Edit',
onClick: this.onEditClick,
verify: () => this.appMessagesManager.canEditMessage(this.mid, 'text') && !!this.chat.input.messageInput
verify: () => this.appMessagesManager.canEditMessage(this.peerId, this.mid, 'text') && !!this.chat.input.messageInput
}, {
icon: 'copy',
text: 'Copy',
onClick: this.onCopyClick,
verify: () => !!this.appMessagesManager.getMessage(this.mid).message
verify: () => !!this.chat.getMessage(this.mid).message
}, {
icon: 'copy',
text: 'Copy selected',
onClick: this.onCopyClick,
verify: () => this.chat.selection.selectedMids.has(this.mid) && !![...this.chat.selection.selectedMids].find(mid => !!this.appMessagesManager.getMessage(mid).message),
verify: () => this.chat.selection.selectedMids.has(this.mid) && !![...this.chat.selection.selectedMids].find(mid => !!this.chat.getMessage(mid).message),
notDirect: () => true,
withSelection: true
}, {
@ -165,7 +165,7 @@ export default class ChatContextMenu { @@ -165,7 +165,7 @@ export default class ChatContextMenu {
text: 'Pin',
onClick: this.onPinClick,
verify: () => {
const message = this.appMessagesManager.getMessage(this.mid);
const message = this.chat.getMessage(this.mid);
return this.mid > 0 && message._ != 'messageService' && !message.pFlags.pinned && this.appPeersManager.canPinMessage(this.peerId);
}
}, {
@ -173,7 +173,7 @@ export default class ChatContextMenu { @@ -173,7 +173,7 @@ export default class ChatContextMenu {
text: 'Unpin',
onClick: this.onUnpinClick,
verify: () => {
const message = this.appMessagesManager.getMessage(this.mid);
const message = this.chat.getMessage(this.mid);
return message.pFlags.pinned && this.appPeersManager.canPinMessage(this.peerId);
}
}, {
@ -181,7 +181,7 @@ export default class ChatContextMenu { @@ -181,7 +181,7 @@ export default class ChatContextMenu {
text: 'Revote',
onClick: this.onRetractVote,
verify: () => {
const message = this.appMessagesManager.getMessage(this.mid);
const message = this.chat.getMessage(this.mid);
const poll = message.media?.poll as Poll;
return poll && poll.chosenIndexes.length && !poll.pFlags.closed && !poll.pFlags.quiz;
}/* ,
@ -191,9 +191,9 @@ export default class ChatContextMenu { @@ -191,9 +191,9 @@ export default class ChatContextMenu {
text: 'Stop poll',
onClick: this.onStopPoll,
verify: () => {
const message = this.appMessagesManager.getMessage(this.mid);
const message = this.chat.getMessage(this.mid);
const poll = message.media?.poll;
return this.appMessagesManager.canEditMessage(this.mid, 'poll') && poll && !poll.pFlags.closed && this.mid > 0;
return this.appMessagesManager.canEditMessage(this.peerId, this.mid, 'poll') && poll && !poll.pFlags.closed && this.mid > 0;
}/* ,
cancelEvent: true */
}, {
@ -213,7 +213,7 @@ export default class ChatContextMenu { @@ -213,7 +213,7 @@ export default class ChatContextMenu {
text: 'Select',
onClick: this.onSelectClick,
verify: () => {
const message = this.appMessagesManager.getMessage(this.mid);
const message = this.chat.getMessage(this.mid);
return !message.action && !this.chat.selection.selectedMids.has(this.mid);
},
notDirect: () => true,
@ -229,7 +229,7 @@ export default class ChatContextMenu { @@ -229,7 +229,7 @@ export default class ChatContextMenu {
icon: 'delete danger',
text: 'Delete',
onClick: this.onDeleteClick,
verify: () => this.appMessagesManager.canDeleteMessage(this.mid)
verify: () => this.appMessagesManager.canDeleteMessage(this.peerId, this.mid)
}, {
icon: 'delete danger',
text: 'Delete selected',
@ -245,7 +245,7 @@ export default class ChatContextMenu { @@ -245,7 +245,7 @@ export default class ChatContextMenu {
};
private onReplyClick = () => {
const message = this.appMessagesManager.getMessage(this.mid);
const message = this.chat.getMessage(this.mid);
const chatInputC = this.chat.input;
const f = () => {
chatInputC.setTopInfo('reply', f, this.appPeersManager.getPeerTitle(message.fromId, true), message.message, undefined, message);
@ -261,7 +261,7 @@ export default class ChatContextMenu { @@ -261,7 +261,7 @@ export default class ChatContextMenu {
private onCopyClick = () => {
const mids = this.chat.selection.isSelecting ? [...this.chat.selection.selectedMids] : [this.mid];
const str = mids.reduce((acc, mid) => {
const message = this.appMessagesManager.getMessage(mid);
const message = this.chat.getMessage(mid);
return acc + (message?.message ? message.message + '\n' : '');
}, '').trim();
@ -277,18 +277,18 @@ export default class ChatContextMenu { @@ -277,18 +277,18 @@ export default class ChatContextMenu {
};
private onRetractVote = () => {
this.appPollsManager.sendVote(this.mid, []);
this.appPollsManager.sendVote(this.peerId, this.mid, []);
};
private onStopPoll = () => {
this.appPollsManager.stopPoll(this.mid);
this.appPollsManager.stopPoll(this.peerId, this.mid);
};
private onForwardClick = () => {
if(this.chat.selection.isSelecting) {
this.chat.selection.selectionForwardBtn.click();
} else {
new PopupForward(this.isTargetAGroupedItem ? [this.mid] : this.appMessagesManager.getMidsByMid(this.mid));
new PopupForward(this.peerId, this.isTargetAGroupedItem ? [this.mid] : this.chat.getMidsByMid(this.mid));
}
};
@ -304,7 +304,7 @@ export default class ChatContextMenu { @@ -304,7 +304,7 @@ export default class ChatContextMenu {
if(this.chat.selection.isSelecting) {
this.chat.selection.selectionDeleteBtn.click();
} else {
new PopupDeleteMessages(this.isTargetAGroupedItem ? [this.mid] : this.appMessagesManager.getMidsByMid(this.mid));
new PopupDeleteMessages(this.peerId, this.isTargetAGroupedItem ? [this.mid] : this.chat.getMidsByMid(this.mid));
}
};
}

37
src/components/chat/input.ts

@ -68,6 +68,7 @@ export default class ChatInput { @@ -68,6 +68,7 @@ export default class ChatInput {
public willSendWebPage: any = null;
public forwardingMids: number[] = [];
public forwardingFromPeerId: number = 0;
public replyToMsgId = 0;
public editMsgId = 0;
public noWebPage: true;
@ -102,6 +103,7 @@ export default class ChatInput { @@ -102,6 +103,7 @@ export default class ChatInput {
public goDownBtn: HTMLButtonElement;
public goDownUnreadBadge: HTMLElement;
btnScheduled: HTMLButtonElement;
constructor(private chat: Chat, private appMessagesManager: AppMessagesManager, private appDocsManager: AppDocsManager, private appChatsManager: AppChatsManager, private appPeersManager: AppPeersManager, private appWebPagesManager: AppWebPagesManager, private appImManager: AppImManager) {
this.listenerSetter = new ListenerSetter();
@ -158,6 +160,9 @@ export default class ChatInput { @@ -158,6 +160,9 @@ export default class ChatInput {
this.inputScroll = new Scrollable(this.inputMessageContainer);
this.btnScheduled = ButtonIcon('schedule', {noRipple: true});
this.btnScheduled.classList.add('btn-scheduled', 'hide');
this.attachMenuButtons = [{
icon: 'photo',
text: 'Photo or Video',
@ -219,7 +224,7 @@ export default class ChatInput { @@ -219,7 +224,7 @@ export default class ChatInput {
this.fileInput.multiple = true;
this.fileInput.style.display = 'none';
this.newMessageWrapper.append(this.btnToggleEmoticons, this.inputMessageContainer, this.attachMenu, this.recordTimeEl, this.fileInput);
this.newMessageWrapper.append(this.btnToggleEmoticons, this.inputMessageContainer, this.btnScheduled, this.attachMenu, this.recordTimeEl, this.fileInput);
this.rowsWrapper.append(this.replyElements.container, this.newMessageWrapper);
@ -311,6 +316,10 @@ export default class ChatInput { @@ -311,6 +316,10 @@ export default class ChatInput {
}); */
attachClickEvent(this.btnSend, this.onBtnSendClick, {listenerSetter: this.listenerSetter});
attachClickEvent(this.btnScheduled, (e) => {
this.appImManager.setInnerPeer(this.chat.peerId, 0, 'scheduled');
}, {listenerSetter: this.listenerSetter});
if(this.recorder) {
const onCancelRecordClick = (e: Event) => {
cancelEvent(e);
@ -450,6 +459,13 @@ export default class ChatInput { @@ -450,6 +459,13 @@ export default class ChatInput {
if(this.chat.type == 'pinned') {
this.chatInput.classList.toggle('can-pin', this.appPeersManager.canPinMessage(peerId));
} else if(this.chat.type == 'chat') {
this.btnScheduled.classList.add('hide');
const middleware = this.chat.bubbles.getMiddleware();
this.appMessagesManager.getScheduledMessages(peerId).then(mids => {
if(!middleware()) return;
this.btnScheduled.classList.toggle('hide', !mids.length);
});
}
if(this.messageInput) {
@ -953,11 +969,12 @@ export default class ChatInput { @@ -953,11 +969,12 @@ export default class ChatInput {
if(this.helperWaitingForward) return;
this.helperWaitingForward = true;
const fromId = this.forwardingFromPeerId;
const mids = this.forwardingMids.slice();
const helperFunc = this.helperFunc;
this.clearHelper();
let selected = false;
new PopupForward(mids, () => {
new PopupForward(fromId, mids, () => {
selected = true;
}, () => {
this.helperWaitingForward = false;
@ -1032,7 +1049,7 @@ export default class ChatInput { @@ -1032,7 +1049,7 @@ export default class ChatInput {
//return;
if(this.editMsgId) {
this.appMessagesManager.editMessage(this.editMsgId, str, {
this.appMessagesManager.editMessage(this.chat.peerId, this.editMsgId, str, {
noWebPage: this.noWebPage
});
} else {
@ -1046,8 +1063,10 @@ export default class ChatInput { @@ -1046,8 +1063,10 @@ export default class ChatInput {
// * wait for sendText set messageId for invokeAfterMsg
if(this.forwardingMids.length) {
const mids = this.forwardingMids.slice();
const fromPeerId = this.forwardingFromPeerId;
const peerId = this.chat.peerId;
setTimeout(() => {
this.appMessagesManager.forwardMessages(this.chat.peerId, mids);
this.appMessagesManager.forwardMessages(peerId, fromPeerId, mids);
}, 0);
}
@ -1071,7 +1090,7 @@ export default class ChatInput { @@ -1071,7 +1090,7 @@ export default class ChatInput {
}
public initMessageEditing(mid: number) {
const message = this.appMessagesManager.getMessage(mid);
const message = this.chat.getMessage(mid);
let input = RichTextProcessor.wrapDraftText(message.message, {entities: message.totalEntities});
const f = () => {
@ -1082,11 +1101,11 @@ export default class ChatInput { @@ -1082,11 +1101,11 @@ export default class ChatInput {
f();
}
public initMessagesForward(mids: number[]) {
public initMessagesForward(fromPeerId: number, mids: number[]) {
const f = () => {
//const peerTitles: string[]
const smth: Set<string | number> = new Set(mids.map(mid => {
const message = this.appMessagesManager.getMessage(mid);
const message = this.appMessagesManager.getMessageByPeer(fromPeerId, mid);
if(message.fwd_from && message.fwd_from.from_name && !message.fromId && !message.fwdFromId) {
return message.fwd_from.from_name;
} else {
@ -1103,13 +1122,14 @@ export default class ChatInput { @@ -1103,13 +1122,14 @@ export default class ChatInput {
const title = peerTitles.length < 3 ? peerTitles.join(' and ') : peerTitles[0] + ' and ' + (peerTitles.length - 1) + ' others';
if(mids.length == 1) {
const message = this.appMessagesManager.getMessage(mids[0]);
const message = this.appMessagesManager.getMessageByPeer(fromPeerId, mids[0]);
this.setTopInfo('forward', f, title, message.message, undefined, message);
} else {
this.setTopInfo('forward', f, title, mids.length + ' forwarded messages');
}
this.forwardingMids = mids.slice();
this.forwardingFromPeerId = fromPeerId;
};
f();
@ -1128,6 +1148,7 @@ export default class ChatInput { @@ -1128,6 +1148,7 @@ export default class ChatInput {
this.replyToMsgId = 0;
this.forwardingMids.length = 0;
this.forwardingFromPeerId = 0;
this.editMsgId = 0;
this.helperType = this.helperFunc = undefined;
this.chat.container.classList.remove('is-helper-active');

4
src/components/chat/pinnedMessage.ts

@ -524,7 +524,7 @@ export default class ChatPinnedMessage { @@ -524,7 +524,7 @@ export default class ChatPinnedMessage {
}
public async followPinnedMessage(mid: number) {
const message = this.appMessagesManager.getMessage(mid);
const message = this.chat.getMessage(mid);
if(message && !message.deleted) {
this.chat.setPeer(this.topbar.peerId, mid);
(this.chat.setPeerPromise || Promise.resolve()).then(() => { // * debounce fast clicker
@ -550,7 +550,7 @@ export default class ChatPinnedMessage { @@ -550,7 +550,7 @@ export default class ChatPinnedMessage {
const count = this.count;
if(count) {
const pinnedIndex = this.pinnedIndex;
const message = this.appMessagesManager.getMessage(this.pinnedMid);
const message = this.chat.getMessage(this.pinnedMid);
//this.animatedCounter.prepareNumber(count);

12
src/components/chat/selection.ts

@ -207,7 +207,7 @@ export default class ChatSelection { @@ -207,7 +207,7 @@ export default class ChatSelection {
let cantForward = !this.selectedMids.size, cantDelete = !this.selectedMids.size;
for(const mid of this.selectedMids.values()) {
const message = this.appMessagesManager.getMessage(mid);
const message = this.appMessagesManager.getMessageByPeer(this.bubbles.peerId, mid);
if(!cantForward) {
if(message.action) {
cantForward = true;
@ -216,7 +216,7 @@ export default class ChatSelection { @@ -216,7 +216,7 @@ export default class ChatSelection {
if(!cantDelete) {
const canDelete = this.appMessagesManager.canDeleteMessage(mid);
const canDelete = this.appMessagesManager.canDeleteMessage(this.bubbles.peerId, mid);
if(!canDelete) {
cantDelete = true;
}
@ -295,7 +295,7 @@ export default class ChatSelection { @@ -295,7 +295,7 @@ export default class ChatSelection {
this.selectionForwardBtn = Button('btn-primary btn-transparent selection-container-forward', {icon: 'forward'});
this.selectionForwardBtn.append('Forward');
this.listenerSetter.add(this.selectionForwardBtn, 'click', () => {
new PopupForward([...this.selectedMids], () => {
new PopupForward(this.bubbles.peerId, [...this.selectedMids], () => {
this.cancelSelection();
});
});
@ -303,7 +303,7 @@ export default class ChatSelection { @@ -303,7 +303,7 @@ export default class ChatSelection {
this.selectionDeleteBtn = Button('btn-primary btn-transparent danger selection-container-delete', {icon: 'delete'});
this.selectionDeleteBtn.append('Delete');
this.listenerSetter.add(this.selectionDeleteBtn, 'click', () => {
new PopupDeleteMessages([...this.selectedMids], () => {
new PopupDeleteMessages(this.bubbles.peerId, [...this.selectedMids], () => {
this.cancelSelection();
});
});
@ -365,7 +365,7 @@ export default class ChatSelection { @@ -365,7 +365,7 @@ export default class ChatSelection {
}
public isGroupedMidsSelected(mid: number) {
const mids = this.appMessagesManager.getMidsByMid(mid);
const mids = this.appMessagesManager.getMidsByMid(this.bubbles.peerId, mid);
const selectedMids = mids.filter(mid => this.selectedMids.has(mid));
return mids.length == selectedMids.length;
}
@ -376,7 +376,7 @@ export default class ChatSelection { @@ -376,7 +376,7 @@ export default class ChatSelection {
const isGrouped = bubble.classList.contains('is-grouped');
if(isGrouped) {
if(!this.isGroupedBubbleSelected(bubble)) {
const mids = this.appMessagesManager.getMidsByMid(mid);
const mids = this.appMessagesManager.getMidsByMid(this.bubbles.peerId, mid);
mids.forEach(mid => this.selectedMids.delete(mid));
}

14
src/components/chat/topbar.ts

@ -125,7 +125,7 @@ export default class ChatTopbar { @@ -125,7 +125,7 @@ export default class ChatTopbar {
this.pinnedMessage.followPinnedMessage(mid);
//}
} else {
const message = this.appMessagesManager.getMessage(mid);
const message = this.appMessagesManager.getMessageByPeer(this.peerId, mid);
this.chat.appImManager.setInnerPeer(message.peerId, mid);
}
@ -373,7 +373,7 @@ export default class ChatTopbar { @@ -373,7 +373,7 @@ export default class ChatTopbar {
public setTitle(count?: number) {
let title = '';
if(this.chat.type == 'pinned') {
if(this.chat.type === 'pinned') {
title = count === -1 ? 'Pinned Messages' : (count === 1 ? 'Pinned Message' : (count + ' Pinned Messages'));
if(count === undefined) {
@ -393,7 +393,15 @@ export default class ChatTopbar { @@ -393,7 +393,15 @@ export default class ChatTopbar {
}
});
}
} else {
} else if(this.chat.type === 'scheduled') {
title = count === -1 ? 'Scheduled Messages' : (count === 1 ? 'Scheduled Message' : (count + ' Scheduled Messages'));
if(count === undefined) {
this.appMessagesManager.getScheduledMessages(this.peerId).then(mids => {
this.setTitle(mids.length);
});
}
} else if(this.chat.type === 'chat') {
if(this.peerId == rootScope.myId) title = 'Saved Messages';
else title = this.appPeersManager.getPeerTitle(this.peerId);
}

8
src/components/poll.ts

@ -152,6 +152,7 @@ export default class PollElement extends HTMLElement { @@ -152,6 +152,7 @@ export default class PollElement extends HTMLElement {
private chosenIndexes: number[] = [];
private percents: number[];
private peerId: number;
private pollId: string;
private mid: number;
@ -178,6 +179,7 @@ export default class PollElement extends HTMLElement { @@ -178,6 +179,7 @@ export default class PollElement extends HTMLElement {
//console.log('line total length:', lineTotalLength);
}
this.peerId = +this.getAttribute('peer-id');
this.pollId = this.getAttribute('poll-id');
this.mid = +this.getAttribute('message-id');
const {poll, results} = appPollsManager.getPoll(this.pollId);
@ -307,7 +309,7 @@ export default class PollElement extends HTMLElement { @@ -307,7 +309,7 @@ export default class PollElement extends HTMLElement {
setTimeout(() => {
// нужно запросить апдейт чтобы опрос обновился
appPollsManager.getResults(this.mid);
appPollsManager.getResults(this.peerId, this.mid);
}, 3e3);
}
}, 1e3);
@ -324,7 +326,7 @@ export default class PollElement extends HTMLElement { @@ -324,7 +326,7 @@ export default class PollElement extends HTMLElement {
this.viewResults.addEventListener('click', (e) => {
cancelEvent(e);
appSidebarRight.pollResultsTab.init(this.pollId, this.mid);
appSidebarRight.pollResultsTab.init(this.peerId, this.pollId, this.mid);
});
ripple(this.viewResults);
@ -464,7 +466,7 @@ export default class PollElement extends HTMLElement { @@ -464,7 +466,7 @@ export default class PollElement extends HTMLElement {
this.classList.add('disable-hover');
this.sentVote = true;
return this.sendVotePromise = appPollsManager.sendVote(this.mid, indexes).then(() => {
return this.sendVotePromise = appPollsManager.sendVote(this.peerId, this.mid, indexes).then(() => {
targets.forEach(target => {
target.classList.remove('is-voting');
});

7
src/components/popupDeleteMessages.ts

@ -6,14 +6,13 @@ import { PopupButton } from "./popup"; @@ -6,14 +6,13 @@ import { PopupButton } from "./popup";
import PopupPeer from "./popupPeer";
export default class PopupDeleteMessages {
constructor(mids: number[], onConfirm?: () => void) {
const peerId = appMessagesManager.getMessage(mids[0]).peerId;
constructor(peerId: number, mids: number[], onConfirm?: () => void) {
const firstName = appPeersManager.getPeerTitle(peerId, false, true);
mids = mids.slice();
const callback = (revoke: boolean) => {
onConfirm && onConfirm();
appMessagesManager.deleteMessages(mids, revoke);
appMessagesManager.deleteMessages(peerId, mids, revoke);
};
let title: string, description: string, buttons: PopupButton[];
@ -45,7 +44,7 @@ export default class PopupDeleteMessages { @@ -45,7 +44,7 @@ export default class PopupDeleteMessages {
const hasRights = appChatsManager.hasRights(-peerId, 'deleteRevoke');
if(chat._ == 'chat') {
const canRevoke = hasRights ? mids.slice() : mids.filter(mid => {
const message = appMessagesManager.getMessage(mid);
const message = appMessagesManager.getMessageByPeer(peerId, mid);
return message.fromId == rootScope.myId;
});

4
src/components/popupForward.ts

@ -7,7 +7,7 @@ export default class PopupForward extends PopupElement { @@ -7,7 +7,7 @@ export default class PopupForward extends PopupElement {
private selector: AppSelectPeers;
//private scrollable: Scrollable;
constructor(mids: number[], onSelect?: () => Promise<void> | void, onClose?: () => void) {
constructor(fromPeerId: number, mids: number[], onSelect?: () => Promise<void> | void, onClose?: () => void) {
super('popup-forward', null, {closable: true, overlayClosable: true, body: true});
if(onClose) this.onClose = onClose;
@ -21,7 +21,7 @@ export default class PopupForward extends PopupElement { @@ -21,7 +21,7 @@ export default class PopupForward extends PopupElement {
await (onSelect ? onSelect() || Promise.resolve() : Promise.resolve());
appImManager.setInnerPeer(peerId);
appImManager.chat.input.initMessagesForward(mids.slice());
appImManager.chat.input.initMessagesForward(fromPeerId, mids.slice());
}, ['dialogs', 'contacts'], () => {
this.show();
this.selector.checkForTriggers(); // ! due to zero height before mounting

2
src/components/popupNewMedia.ts

@ -224,7 +224,7 @@ export default class PopupNewMedia extends PopupElement { @@ -224,7 +224,7 @@ export default class PopupNewMedia extends PopupElement {
params.objectURL = URL.createObjectURL(file);
}
const docDiv = wrapDocument({
const docDiv = wrapDocument(0, {
file: file,
file_name: file.name || '',
size: file.size,

2
src/components/sidebarRight/tabs/forward.ts

@ -45,7 +45,7 @@ export default class AppForwardTab implements SliderTab { @@ -45,7 +45,7 @@ export default class AppForwardTab implements SliderTab {
let s = () => {
let promises = peerIds.splice(0, 3).map(peerId => {
return appMessagesManager.forwardMessages(peerId, this.mids);
return appMessagesManager.forwardMessages(peerId, 0, this.mids);
});
Promise.all(promises).then(() => {

8
src/components/sidebarRight/tabs/pollResults.ts

@ -14,6 +14,7 @@ export default class AppPollResultsTab implements SliderTab { @@ -14,6 +14,7 @@ export default class AppPollResultsTab implements SliderTab {
private resultsDiv = this.contentDiv.firstElementChild as HTMLDivElement;
private scrollable: Scrollable;
private peerId: number;
private pollId: string;
private mid: number;
@ -31,11 +32,12 @@ export default class AppPollResultsTab implements SliderTab { @@ -31,11 +32,12 @@ export default class AppPollResultsTab implements SliderTab {
this.cleanup();
}
public init(pollId: string, mid: number) {
if(this.pollId == pollId && this.mid == mid) return;
public init(peerId: number, pollId: string, mid: number) {
if(this.peerId == peerId && this.pollId == pollId && this.mid == mid) return;
this.cleanup();
this.peerId = peerId;
this.pollId = pollId;
this.mid = mid;
@ -86,7 +88,7 @@ export default class AppPollResultsTab implements SliderTab { @@ -86,7 +88,7 @@ export default class AppPollResultsTab implements SliderTab {
if(loading) return;
loading = true;
appPollsManager.getVotes(mid, answer.option, offset, limit).then(votesList => {
appPollsManager.getVotes(peerId, mid, answer.option, offset, limit).then(votesList => {
votesList.votes.forEach(vote => {
const {dom} = appDialogsManager.addDialogNew({
dialog: vote.user_id,

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

@ -179,7 +179,7 @@ export default class AppSharedMediaTab implements SliderTab { @@ -179,7 +179,7 @@ export default class AppSharedMediaTab implements SliderTab {
return;
}
const message = appMessagesManager.getMessage(messageId);
const message = appMessagesManager.getMessageByPeer(this.peerId, messageId);
const ids = Object.keys(this.mediaDivsByIds).map(k => +k).sort((a, b) => a - b);
const idx = ids.findIndex(i => i == messageId);
@ -331,11 +331,11 @@ export default class AppSharedMediaTab implements SliderTab { @@ -331,11 +331,11 @@ export default class AppSharedMediaTab implements SliderTab {
if(type != 'inputMessagesFilterUrl') {
for(let mid of ids) {
let message = appMessagesManager.getMessage(mid);
let message = appMessagesManager.getMessageByPeer(this.peerId, mid);
if(message.media) messages.push(message);
}
} else {
messages = ids.slice().map(mid => appMessagesManager.getMessage(mid));
messages = ids.slice().map(mid => appMessagesManager.getMessageByPeer(this.peerId, mid));
}
let filtered: any[] = [];
@ -528,7 +528,7 @@ export default class AppSharedMediaTab implements SliderTab { @@ -528,7 +528,7 @@ export default class AppSharedMediaTab implements SliderTab {
case 'inputMessagesFilterMusic':
case 'inputMessagesFilterDocument': {
for(const message of messages) {
const div = wrapDocument(message.media.document, true, false, message.mid, 400);
const div = wrapDocument(this.peerId, message.media.document, true, false, message.mid, 400);
div.dataset.mid = '' + message.mid;
elemsToAppend.push(div);
}

31
src/components/wrappers.ts

@ -27,6 +27,7 @@ import './middleEllipsis'; @@ -27,6 +27,7 @@ import './middleEllipsis';
import { nextRandomInt } from '../helpers/random';
import RichTextProcessor from '../lib/richtextprocessor';
import appImManager from '../lib/appManagers/appImManager';
import Chat from './chat/chat';
const MAX_VIDEO_AUTOPLAY_SIZE = 50 * 1024 * 1024; // 50 MB
@ -93,7 +94,7 @@ export function wrapVideo({doc, container, message, boxWidth, boxHeight, withTai @@ -93,7 +94,7 @@ export function wrapVideo({doc, container, message, boxWidth, boxHeight, withTai
video.setAttribute('playsinline', 'true');
if(doc.type == 'round') {
//video.muted = true;
const globalVideo = appMediaPlaybackController.addMedia(doc, message.mid);
const globalVideo = appMediaPlaybackController.addMedia(message.peerId, doc, message.mid);
video.addEventListener('canplay', () => {
if(globalVideo.currentTime > 0) {
@ -342,9 +343,9 @@ export const formatDate = (timestamp: number, monthShort = false, withYear = tru @@ -342,9 +343,9 @@ export const formatDate = (timestamp: number, monthShort = false, withYear = tru
return str + ' at ' + date.getHours() + ':' + ('0' + date.getMinutes()).slice(-2);
};
export function wrapDocument(doc: MyDocument, withTime = false, uploading = false, mid?: number, fontWeight = 500): HTMLElement {
export function wrapDocument(peerId: number, doc: MyDocument, withTime = false, uploading = false, mid?: number, fontWeight = 500): HTMLElement {
if(doc.type == 'audio' || doc.type == 'voice') {
const audioElement = wrapAudio(doc, withTime, mid);
const audioElement = wrapAudio(peerId, doc, withTime, mid);
audioElement.dataset.fontWeight = '' + fontWeight;
return audioElement;
}
@ -437,8 +438,9 @@ export function wrapDocument(doc: MyDocument, withTime = false, uploading = fals @@ -437,8 +438,9 @@ export function wrapDocument(doc: MyDocument, withTime = false, uploading = fals
return docDiv;
}
export function wrapAudio(doc: MyDocument, withTime = false, mid?: number): HTMLElement {
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);
@ -898,20 +900,21 @@ export function prepareAlbum(options: { @@ -898,20 +900,21 @@ export function prepareAlbum(options: {
} */
}
export function wrapAlbum({groupId, attachmentDiv, middleware, uploading, lazyLoadQueue, isOut}: {
export function wrapAlbum({groupId, attachmentDiv, middleware, uploading, lazyLoadQueue, isOut, chat}: {
groupId: string,
attachmentDiv: HTMLElement,
middleware?: () => boolean,
lazyLoadQueue?: LazyLoadQueue,
uploading?: boolean,
isOut: boolean
isOut: boolean,
chat: Chat
}) {
const items: {size: PhotoSize.photoSize, media: any, message: any}[] = [];
// !lowest msgID will be the FIRST in album
const storage = appMessagesManager.getMidsByAlbum(groupId);
for(const mid of storage) {
const m = appMessagesManager.getMessage(mid);
const m = chat.getMessage(mid);
const media = m.media.photo || m.media.document;
const size: any = media._ == 'photo' ? appPhotosManager.choosePhotoSize(media, 480, 480) : {w: media.w, h: media.h};
@ -966,24 +969,25 @@ export function wrapAlbum({groupId, attachmentDiv, middleware, uploading, lazyLo @@ -966,24 +969,25 @@ export function wrapAlbum({groupId, attachmentDiv, middleware, uploading, lazyLo
});
}
export function wrapGroupedDocuments({albumMustBeRenderedFull, message, bubble, messageDiv}: {
export function wrapGroupedDocuments({albumMustBeRenderedFull, message, bubble, messageDiv, chat}: {
albumMustBeRenderedFull: boolean,
message: any,
messageDiv: HTMLElement,
bubble: HTMLElement,
uploading?: boolean
uploading?: boolean,
chat: Chat
}) {
let nameContainer: HTMLDivElement;
const mids = albumMustBeRenderedFull ? appMessagesManager.getMidsByMid(message.mid) : [message.mid];
const mids = albumMustBeRenderedFull ? chat.getMidsByMid(message.mid) : [message.mid];
const isPending = message.mid < 0;
if(isPending) {
mids.reverse();
}
mids.forEach((mid, idx) => {
const message = appMessagesManager.getMessage(mid);
const message = chat.getMessage(mid);
const doc = message.media.document;
const div = wrapDocument(doc, false, isPending, mid);
const div = wrapDocument(chat.peerId, doc, false, isPending, mid);
const container = document.createElement('div');
container.classList.add('document-container');
@ -1037,8 +1041,9 @@ export function wrapGroupedDocuments({albumMustBeRenderedFull, message, bubble, @@ -1037,8 +1041,9 @@ export function wrapGroupedDocuments({albumMustBeRenderedFull, message, bubble,
return nameContainer;
}
export function wrapPoll(pollId: string, mid: number) {
export function wrapPoll(peerId: number, pollId: string, mid: number) {
const elem = new PollElement();
elem.setAttribute('peer-id', '' + peerId);
elem.setAttribute('poll-id', pollId);
elem.setAttribute('message-id', '' + mid);
return elem;

9
src/lib/appManagers/AppInlineBotsManager.ts

@ -4,8 +4,6 @@ import appPeersManager from "./appPeersManager"; @@ -4,8 +4,6 @@ import appPeersManager from "./appPeersManager";
import apiManagerProxy from "../mtproto/mtprotoworker";
import { RichTextProcessor } from "../richtextprocessor";
import appDocsManager from "./appDocsManager";
import appMessagesIdsManager from "./appMessagesIdsManager";
import appMessagesManager from "./appMessagesManager";
import appPhotosManager from "./appPhotosManager";
import appUsersManager from "./appUsersManager";
@ -270,13 +268,10 @@ export class AppInlineBotsManager { @@ -270,13 +268,10 @@ export class AppInlineBotsManager {
})
} */
public callbackButtonClick(mid: number, button: any) {
let message = appMessagesManager.getMessage(mid);
let peerId = appMessagesManager.getMessagePeer(message);
public callbackButtonClick(peerId: number, mid: number, button: any) {
return apiManagerProxy.invokeApi('messages.getBotCallbackAnswer', {
peer: appPeersManager.getInputPeerById(peerId),
msg_id: appMessagesIdsManager.getMessageLocalId(mid),
msg_id: mid,
data: button.data
}, {timeout: 1, stopTime: -1, noErrorBox: true}).then((callbackAnswer) => {
if(typeof callbackAnswer.message === 'string' && callbackAnswer.message.length) {

4
src/lib/appManagers/appDialogsManager.ts

@ -939,7 +939,7 @@ export class AppDialogsManager { @@ -939,7 +939,7 @@ export class AppDialogsManager {
}
if(!lastMessage) {
lastMessage = appMessagesManager.getMessage(dialog.top_message);
lastMessage = appMessagesManager.getMessageByPeer(dialog.peerId, dialog.top_message);
}
if(lastMessage._ == 'messageEmpty' || (lastMessage._ == 'messageService' && !lastMessage.rReply)) {
@ -1048,7 +1048,7 @@ export class AppDialogsManager { @@ -1048,7 +1048,7 @@ export class AppDialogsManager {
dom.listEl.classList.toggle('is-muted', isMuted);
}
const lastMessage = appMessagesManager.getMessage(dialog.top_message);
const lastMessage = appMessagesManager.getMessageByPeer(dialog.peerId, dialog.top_message);
if(lastMessage._ != 'messageEmpty' && !lastMessage.deleted &&
lastMessage.fromId == rootScope.myId && lastMessage.peerId != rootScope.myId/* &&
dialog.read_outbox_max_id */) { // maybe comment, 06.20.2020

13
src/lib/appManagers/appImManager.ts

@ -20,7 +20,7 @@ import appPhotosManager from './appPhotosManager'; @@ -20,7 +20,7 @@ import appPhotosManager from './appPhotosManager';
import appProfileManager from './appProfileManager';
import appStickersManager from './appStickersManager';
import appWebPagesManager from './appWebPagesManager';
import { cancelEvent, findUpClassName, generatePathData, getFilesFromEvent, placeCaretAtEnd } from '../../helpers/dom';
import { cancelEvent, getFilesFromEvent, placeCaretAtEnd } from '../../helpers/dom';
import PopupNewMedia from '../../components/popupNewMedia';
import { TransitionSlider } from '../../components/transition';
import { numberWithCommas } from '../../helpers/number';
@ -28,9 +28,7 @@ import MarkupTooltip from '../../components/chat/markupTooltip'; @@ -28,9 +28,7 @@ import MarkupTooltip from '../../components/chat/markupTooltip';
import { isTouchSupported } from '../../helpers/touchSupport';
import appPollsManager from './appPollsManager';
import SetTransition from '../../components/singleTransition';
import { isSafari } from '../../helpers/userAgent';
import ChatDragAndDrop from '../../components/chat/dragAndDrop';
import appMessagesIdsManager from './appMessagesIdsManager';
//console.log('appImManager included33!');
@ -154,9 +152,6 @@ export class AppImManager { @@ -154,9 +152,6 @@ export class AppImManager {
appUsersManager.resolveUsername(p).then(peer => {
const isUser = peer._ == 'user';
const peerId = isUser ? peer.id : -peer.id;
if(postId) {
postId = appMessagesIdsManager.getFullMessageId(postId, -peerId);
}
this.setInnerPeer(peerId, postId);
});
@ -212,11 +207,11 @@ export class AppImManager { @@ -212,11 +207,11 @@ export class AppImManager {
if(history?.history) {
let goodMid: number;
for(const mid of history.history) {
const message = appMessagesManager.getMessage(mid);
const message = appMessagesManager.getMessageByPeer(chat.peerId, mid);
const good = this.myId == chat.peerId ? message.fromId == this.myId : message.pFlags.out;
if(good) {
if(appMessagesManager.canEditMessage(mid, 'text')) {
if(appMessagesManager.canEditMessage(this.chat.peerId, mid, 'text')) {
goodMid = mid;
}
@ -508,7 +503,7 @@ export class AppImManager { @@ -508,7 +503,7 @@ export class AppImManager {
this.createNewChat();
if(type) {
this.chat.type = type;
this.chat.setType(type);
}
this.chatsSelectTab(this.chat.container);

85
src/lib/appManagers/appMessagesIDsManager.ts

@ -1,85 +0,0 @@ @@ -1,85 +0,0 @@
import { MOUNT_CLASS_TO } from "../mtproto/mtproto_config";
import appStateManager from "./appStateManager";
export class AppMessagesIdsManager {
public channelLocals: {[channelId: string]: number} = {};
public channelsByLocals: {[localStart: string]: number} = {};
public channelCurLocal = 0;
public fullMsgIdModulus = 4294967296;
constructor() {
appStateManager.getState().then(state => {
const cached = state.messagesIdsLocals;
if(cached) {
this.channelLocals = cached.channelLocals;
this.channelsByLocals = cached.channelsByLocals;
this.channelCurLocal = cached.channelCurLocal;
}
});
appStateManager.addListener('save', () => {
appStateManager.pushToState('messagesIdsLocals', {
channelLocals: this.channelLocals,
channelsByLocals: this.channelsByLocals,
channelCurLocal: this.channelCurLocal
});
});
}
public getFullMessageId(msgId: number, channelId: number): number {
if(!channelId || msgId <= 0) {
return msgId;
}
msgId = this.getMessageLocalId(msgId);
let localStart = this.channelLocals[channelId];
if(!localStart) {
localStart = (++this.channelCurLocal) * this.fullMsgIdModulus;
this.channelsByLocals[localStart] = channelId;
this.channelLocals[channelId] = localStart;
}
return localStart + msgId;
}
public getMessageIdInfo(fullMsgId: number) {
if(fullMsgId < this.fullMsgIdModulus) {
return [fullMsgId, 0];
}
const msgId = fullMsgId % this.fullMsgIdModulus;
const channelId = this.channelsByLocals[fullMsgId - msgId];
return [msgId, channelId];
}
public getMessageLocalId(fullMsgId: number) {
return fullMsgId ? fullMsgId % this.fullMsgIdModulus : 0;
}
public splitMessageIdsByChannels(mids: number[]) {
const msgIdsByChannels: {[channelId: number]: number[]} = {};
const midsByChannels: {[channelId: number]: number[]} = {};
for(const mid of mids) {
const msgChannel = this.getMessageIdInfo(mid);
const channelId = msgChannel[1];
if(msgIdsByChannels[channelId] === undefined) {
msgIdsByChannels[channelId] = [];
midsByChannels[channelId] = [];
}
msgIdsByChannels[channelId].push(msgChannel[0]);
midsByChannels[channelId].push(mid);
}
return {
msgIds: msgIdsByChannels,
mids: midsByChannels
};
}
}
const appMessagesIdsManager = new AppMessagesIdsManager();
MOUNT_CLASS_TO && (MOUNT_CLASS_TO.appMessagesIdsManager = appMessagesIdsManager);
export default appMessagesIdsManager;

433
src/lib/appManagers/appMessagesManager.ts

File diff suppressed because it is too large Load Diff

32
src/lib/appManagers/appPollsManager.ts

@ -159,21 +159,20 @@ export class AppPollsManager { @@ -159,21 +159,20 @@ export class AppPollsManager {
};
}
public sendVote(mid: number, optionIds: number[]): Promise<void> {
const message = appMessagesManager.getMessage(mid);
public sendVote(peerId: number, messageId: number, optionIds: number[]): Promise<void> {
const message = appMessagesManager.getMessageByPeer(peerId, messageId);
const poll: Poll = message.media.poll;
const options: Uint8Array[] = optionIds.map(index => {
return poll.answers[index].option;
});
const inputPeer = appPeersManager.getInputPeerById(message.peerId);
const messageId = message.id;
const inputPeer = appPeersManager.getInputPeerById(peerId);
if(mid < 0) {
return appMessagesManager.invokeAfterMessageIsSent(mid, 'sendVote', (mid) => {
if(messageId < 0) {
return appMessagesManager.invokeAfterMessageIsSent(messageId, 'sendVote', (mid) => {
this.log('invoke sendVote callback');
return this.sendVote(mid, optionIds);
return this.sendVote(peerId, mid, optionIds);
});
}
@ -187,10 +186,9 @@ export class AppPollsManager { @@ -187,10 +186,9 @@ export class AppPollsManager {
});
}
public getResults(mid: number) {
const message = appMessagesManager.getMessage(mid);
public getResults(peerId: number, messageId: number) {
const message = appMessagesManager.getMessageByPeer(peerId, messageId);
const inputPeer = appPeersManager.getInputPeerById(message.peerId);
const messageId = message.id;
return apiManager.invokeApi('messages.getPollResults', {
peer: inputPeer,
@ -201,11 +199,7 @@ export class AppPollsManager { @@ -201,11 +199,7 @@ export class AppPollsManager {
});
}
public getVotes(mid: number, option?: Uint8Array, offset?: string, limit = 20) {
const message = appMessagesManager.getMessage(mid);
const inputPeer = appPeersManager.getInputPeerById(message.peerId);
const messageId = message.id;
public getVotes(peerId: number, messageId: number, option?: Uint8Array, offset?: string, limit = 20) {
let flags = 0;
if(option) {
flags |= 1 << 0;
@ -217,7 +211,7 @@ export class AppPollsManager { @@ -217,7 +211,7 @@ export class AppPollsManager {
return apiManager.invokeApi('messages.getPollVotes', {
flags,
peer: inputPeer,
peer: appPeersManager.getInputPeerById(peerId),
id: messageId,
option,
offset,
@ -231,15 +225,15 @@ export class AppPollsManager { @@ -231,15 +225,15 @@ export class AppPollsManager {
});
}
public stopPoll(mid: number) {
const message = appMessagesManager.getMessage(mid);
public stopPoll(peerId: number, messageId: number) {
const message = appMessagesManager.getMessageByPeer(peerId, messageId);
const poll: Poll = message.media.poll;
if(poll.pFlags.closed) return Promise.resolve();
const newPoll = copy(poll);
newPoll.pFlags.closed = true;
return appMessagesManager.editMessage(mid, undefined, {
return appMessagesManager.editMessage(peerId, messageId, undefined, {
newMedia: this.getInputMediaPoll(newPoll)
}).then(() => {
//console.log('stopped poll');

6
src/lib/appManagers/appStateManager.ts

@ -8,7 +8,6 @@ import { logger } from '../logger'; @@ -8,7 +8,6 @@ import { logger } from '../logger';
import type { AppUsersManager } from './appUsersManager';
import type { AppChatsManager } from './appChatsManager';
import type { AuthState } from '../../types';
import type { AppMessagesIdsManager } from './appMessagesIdsManager';
import type FiltersStorage from '../storages/filters';
import type DialogsStorage from '../storages/dialogs';
@ -33,11 +32,6 @@ type State = Partial<{ @@ -33,11 +32,6 @@ type State = Partial<{
stickerSets: AppStickersManager['stickerSets'],
version: typeof STATE_VERSION,
authState: AuthState,
messagesIdsLocals: {
channelLocals: AppMessagesIdsManager['channelLocals'],
channelsByLocals: AppMessagesIdsManager['channelsByLocals'],
channelCurLocal: AppMessagesIdsManager['channelCurLocal'],
},
hiddenPinnedMessages: {[peerId: string]: number}
}>;

3
src/lib/mtproto/referenceDatabase.ts

@ -13,6 +13,7 @@ export namespace ReferenceContext { @@ -13,6 +13,7 @@ export namespace ReferenceContext {
export type referenceContextMessage = {
type: 'message',
peerId: number,
messageId: number
};
}
@ -80,7 +81,7 @@ class ReferenceDatabase { @@ -80,7 +81,7 @@ class ReferenceDatabase {
[context, reference] = this.getContext(reference);
switch(context?.type) {
case 'message': {
return appMessagesManager.wrapSingleMessage(context.messageId, true);
return appMessagesManager.wrapSingleMessage(context.peerId, context.messageId, true);
// .then(() => {
// console.log('FILE_REFERENCE_EXPIRED: got message', context, appMessagesManager.getMessage((context as ReferenceContext.referenceContextMessage).messageId).media, reference);
// });

7
src/lib/rootScope.ts

@ -44,14 +44,17 @@ type BroadcastEvents = { @@ -44,14 +44,17 @@ type BroadcastEvents = {
'messages_pending': void,
'messages_read': void,
'messages_downloaded': number[],
'messages_media_read': number[],
'messages_media_read': {peerId: number, mids: number[]},
'scheduled_new': {peerId: number, mid: number},
'scheduled_delete': {peerId: number, mids: number[]},
'album_edit': {peerId: number, groupId: string, deletedMids: number[]},
'stickers_installed': StickerSet.stickerSet,
'stickers_deleted': StickerSet.stickerSet,
'audio_play': {doc: MyDocument, mid: number},
'audio_play': {doc: MyDocument, mid: number, peerId: number},
'audio_pause': void,
'state_synchronized': number,

7
src/lib/storages/dialogs.ts

@ -1,7 +1,6 @@ @@ -1,7 +1,6 @@
import { tsNow } from "../../helpers/date";
import type { Message } from "../../layer";
import type { AppChatsManager } from "../appManagers/appChatsManager";
import type { AppMessagesIdsManager } from "../appManagers/appMessagesIdsManager";
import type { AppMessagesManager, Dialog } from "../appManagers/appMessagesManager";
import type { AppPeersManager } from "../appManagers/appPeersManager";
import type { ServerTimeManager } from "../mtproto/serverTimeManager";
@ -18,7 +17,7 @@ export default class DialogsStorage { @@ -18,7 +17,7 @@ export default class DialogsStorage {
};
public dialogsNum = 0;
constructor(private appMessagesManager: AppMessagesManager, private appMessagesIdsManager: AppMessagesIdsManager, private appChatsManager: AppChatsManager, private appPeersManager: AppPeersManager, private serverTimeManager: ServerTimeManager) {
constructor(private appMessagesManager: AppMessagesManager, private appChatsManager: AppChatsManager, private appPeersManager: AppPeersManager, private serverTimeManager: ServerTimeManager) {
}
@ -92,8 +91,8 @@ export default class DialogsStorage { @@ -92,8 +91,8 @@ export default class DialogsStorage {
public generateIndexForDialog(dialog: Dialog, justReturn = false) {
const channelId = this.appPeersManager.isChannel(dialog.peerId) ? -dialog.peerId : 0;
const mid = this.appMessagesIdsManager.getFullMessageId(dialog.top_message, channelId);
const message = this.appMessagesManager.getMessage(mid);
const mid = dialog.top_message;
const message = this.appMessagesManager.getMessageByPeer(dialog.peerId, mid);
let topDate = (message as Message.message).date || Date.now() / 1000;
if(channelId) {

2
src/scss/partials/_chatBubble.scss

@ -189,7 +189,7 @@ $bubble-margin: .25rem; @@ -189,7 +189,7 @@ $bubble-margin: .25rem;
} */
}
.chat:not(.type-pinned) & .bubble__container {
.chat.type-chat & .bubble__container {
cursor: pointer;
pointer-events: all;
}

1
src/scss/partials/_rightSidebar.scss

@ -199,6 +199,7 @@ @@ -199,6 +199,7 @@
text-overflow: ellipsis;
overflow: hidden;
word-break: break-word;
white-space: pre-wrap;
}
&-bio {

Loading…
Cancel
Save