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. 141
      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. 607
      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 {
document.body.append(this.container); 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]; if(this.media[mid]) return this.media[mid];
const media = document.createElement(doc.type == 'round' ? 'video' : 'audio'); const media = document.createElement(doc.type == 'round' ? 'video' : 'audio');
@ -61,12 +61,12 @@ class AppMediaPlaybackController {
} }
this.playingMedia = media; this.playingMedia = media;
this.loadSiblingsMedia(doc.type as MediaType, mid); this.loadSiblingsMedia(peerId, doc.type as MediaType, mid);
} }
// audio_pause не успеет сработать без таймаута // audio_pause не успеет сработать без таймаута
setTimeout(() => { setTimeout(() => {
rootScope.broadcast('audio_play', {doc, mid}); rootScope.broadcast('audio_play', {peerId, doc, mid});
}, 0); }, 0);
}); });
@ -75,7 +75,7 @@ class AppMediaPlaybackController {
const onError = (e: Event) => { const onError = (e: Event) => {
if(this.nextMid == mid) { 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]) { if(this.nextMid && this.media[this.nextMid]) {
this.media[this.nextMid].play(); this.media[this.nextMid].play();
} }
@ -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 media = this.playingMedia;
const message = appMessagesManager.getMessage(mid);
this.prevMid = this.nextMid = 0; this.prevMid = this.nextMid = 0;
return appMessagesManager.getSearch(message.peerId, '', { return appMessagesManager.getSearch(peerId, '', {
//_: 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 => {
@ -204,8 +203,8 @@ class AppMediaPlaybackController {
} }
[this.prevMid, this.nextMid].filter(Boolean).forEach(mid => { [this.prevMid, this.nextMid].filter(Boolean).forEach(mid => {
const message = appMessagesManager.getMessage(mid); const message = appMessagesManager.getMessageByPeer(peerId, mid);
this.addMedia(message.media.document, mid, false); this.addMedia(peerId, message.media.document, mid, false);
}); });
//console.log('loadSiblingsAudio', audio, type, mid, value, this.prevMid, this.nextMid); //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
onPrevClick = (target: AppMediaViewerTargetType) => { onPrevClick = (target: AppMediaViewerTargetType) => {
this.nextTargets.unshift({element: this.lastTarget, mid: this.currentMessageId}); 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) => { onNextClick = (target: AppMediaViewerTargetType) => {
this.prevTargets.push({element: this.lastTarget, mid: this.currentMessageId}); 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 = () => { onForwardClick = () => {
if(this.currentMessageId) { if(this.currentMessageId) {
//appSidebarRight.forwardTab.open([this.currentMessageId]); //appSidebarRight.forwardTab.open([this.currentMessageId]);
new PopupForward([this.currentMessageId], () => { new PopupForward(this.peerId, [this.currentMessageId], () => {
return this.close(); return this.close();
}); });
} }
@ -1192,14 +1192,14 @@ export default class AppMediaViewer extends AppMediaViewerBase<'caption', 'delet
appSidebarRight.sharedMediaTab.closeBtn.click(); appSidebarRight.sharedMediaTab.closeBtn.click();
} }
const message = appMessagesManager.getMessage(mid); const message = appMessagesManager.getMessageByPeer(this.peerId, mid);
appImManager.setPeer(message.peerId, mid); appImManager.setPeer(message.peerId, mid);
}); });
} }
}; };
onDownloadClick = () => { onDownloadClick = () => {
const message = appMessagesManager.getMessage(this.currentMessageId); const message = appMessagesManager.getMessageByPeer(this.peerId, this.currentMessageId);
if(message.media.photo) { if(message.media.photo) {
appPhotosManager.savePhotoFile(message.media.photo, appImManager.chat.bubbles.lazyLoadQueue.queueId); appPhotosManager.savePhotoFile(message.media.photo, appImManager.chat.bubbles.lazyLoadQueue.queueId);
} else { } else {
@ -1262,7 +1262,7 @@ export default class AppMediaViewer extends AppMediaViewerBase<'caption', 'delet
const method = older ? value.history.forEach : value.history.forEachReverse; const method = older ? value.history.forEach : value.history.forEachReverse;
method.call(value.history, mid => { method.call(value.history, mid => {
const message = appMessagesManager.getMessage(mid); const message = appMessagesManager.getMessageByPeer(this.peerId, mid);
const media = this.getMediaFromMessage(message); const media = this.getMediaFromMessage(message);
if(!media) return; if(!media) return;

5
src/components/appSearch.ts

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

15
src/components/audio.ts

@ -14,10 +14,10 @@ import './middleEllipsis';
import { attachClickEvent, cancelEvent, detachClickEvent } from "../helpers/dom"; import { attachClickEvent, cancelEvent, detachClickEvent } from "../helpers/dom";
rootScope.on('messages_media_read', e => { rootScope.on('messages_media_read', e => {
const mids = e.detail; const {mids, peerId} = e.detail;
mids.forEach(mid => { 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); //console.log('updating avatar:', elem);
elem.classList.remove('is-unread'); elem.classList.remove('is-unread');
}); });
@ -61,10 +61,10 @@ export function decodeWaveform(waveform: Uint8Array | number[]) {
return result; 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'); 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; 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 +171,7 @@ function wrapVoiceMessage(doc: MyDocument, audioEl: AudioElement, mid: number) {
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([mid]); appMessagesManager.readMessages(peerId, [mid]);
isUnread = false; isUnread = false;
} }
@ -329,6 +329,7 @@ export default class AudioElement extends HTMLElement {
this.classList.add('audio'); this.classList.add('audio');
const peerId = +this.getAttribute('peer-id');
const mid = +this.getAttribute('message-id'); const mid = +this.getAttribute('message-id');
const docId = this.getAttribute('doc-id'); const docId = this.getAttribute('doc-id');
const doc = appDocsManager.getDoc(docId); const doc = appDocsManager.getDoc(docId);
@ -351,13 +352,13 @@ export default class AudioElement extends HTMLElement {
this.append(downloadDiv); 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; 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(doc, mid, autoload); const audio = this.audio = appMediaPlaybackController.addMedia(peerId, doc, mid, autoload);
this.onTypeDisconnect = onTypeLoad(); this.onTypeDisconnect = onTypeLoad();

4
src/components/avatar.ts

@ -57,7 +57,7 @@ export default class AvatarElement extends HTMLElement {
if(mid) { if(mid) {
// ! гений в деле, костылируем (но это гениально) // ! гений в деле, костылируем (но это гениально)
let message = appMessagesManager.getMessage(mid); let message = appMessagesManager.getMessageByPeer(peerId, mid);
const messagePhoto = message.action.photo; const messagePhoto = message.action.photo;
if(messagePhoto.id != photo.id) { if(messagePhoto.id != photo.id) {
message = { message = {
@ -72,7 +72,7 @@ export default class AvatarElement extends HTMLElement {
fromId: peerId fromId: peerId
}; };
appMessagesManager.messagesStorage[maxId] = message; appMessagesManager.getMessagesStorage(peerId)[maxId] = message;
} }
const good = Array.from(this.querySelectorAll('img')).find(img => !img.classList.contains('emoji')); 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 {
this.wrapper.prepend(this.toggleEl); this.wrapper.prepend(this.toggleEl);
this.topbar.listenerSetter.add(rootScope, 'audio_play', (e) => { this.topbar.listenerSetter.add(rootScope, 'audio_play', (e) => {
const {doc, mid} = e.detail; const {doc, mid, peerId} = e.detail;
let title: string, subtitle: string; let title: string, subtitle: string;
const message = appMessagesManager.getMessage(mid); const message = appMessagesManager.getMessageByPeer(peerId, mid);
if(doc.type == 'voice' || doc.type == 'round') { if(doc.type == 'voice' || doc.type == 'round') {
title = appPeersManager.getPeerTitle(message.fromId, false, true); title = appPeersManager.getPeerTitle(message.fromId, false, true);
//subtitle = 'Voice message'; //subtitle = 'Voice message';

141
src/components/chat/bubbles.ts

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

31
src/components/chat/chat.ts

@ -21,7 +21,7 @@ import ChatInput from "./input";
import ChatSelection from "./selection"; import ChatSelection from "./selection";
import ChatTopbar from "./topbar"; 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<{ export default class Chat extends EventListenerBase<{
setPeer: (mid: number, isTopMessage: boolean) => void setPeer: (mid: number, isTopMessage: boolean) => void
@ -61,6 +61,14 @@ export default class Chat extends EventListenerBase<{
this.appImManager.chatsContainer.append(this.container); 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() { private init() {
this.topbar = new ChatTopbar(this, appSidebarRight, this.appMessagesManager, this.appPeersManager, this.appChatsManager); 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); 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<{
this.selection = new ChatSelection(this.bubbles, this.input, this.appMessagesManager); 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); 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(); this.topbar.constructPeerHelpers();
} else if(this.type == 'pinned') { } else if(this.type === 'pinned') {
this.topbar.constructPinnedHelpers(); this.topbar.constructPinnedHelpers();
} }
this.topbar.construct(); this.topbar.construct();
this.input.construct(); this.input.construct();
if(this.type == 'chat') { // * гений в деле, разный порядок из-за разной последовательности действий if(this.type === 'chat') { // * гений в деле, разный порядок из-за разной последовательности действий
this.bubbles.constructPeerHelpers();
this.input.constructPeerHelpers(); this.input.constructPeerHelpers();
} else if(this.type == 'pinned') { } else if(this.type === 'pinned') {
this.input.constructPinnedHelpers();
this.bubbles.constructPinnedHelpers(); this.bubbles.constructPinnedHelpers();
this.input.constructPinnedHelpers();
} else if(this.type === 'scheduled') {
this.bubbles.constructScheduledHelpers();
} }
this.container.classList.add('type-' + this.type); this.container.classList.add('type-' + this.type);
@ -187,4 +198,12 @@ export default class Chat extends EventListenerBase<{
rootScope.broadcast('peer_changed', peerId); 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 {
// * если открыть контекстное меню для альбома не по бабблу, и последний элемент не выбран, чтобы показать остальные пункты // * если открыть контекстное меню для альбома не по бабблу, и последний элемент не выбран, чтобы показать остальные пункты
if(chat.selection.isSelecting && !bubbleContainer) { if(chat.selection.isSelecting && !bubbleContainer) {
const mids = appMessagesManager.getMidsByMid(mid); const mids = this.chat.getMidsByMid(mid);
if(mids.length > 1) { if(mids.length > 1) {
const selectedMid = chat.selection.selectedMids.has(mid) ? mid : mids.find(mid => chat.selection.selectedMids.has(mid)); const selectedMid = chat.selection.selectedMids.has(mid) ? mid : mids.find(mid => chat.selection.selectedMids.has(mid));
if(selectedMid) { if(selectedMid) {
@ -147,17 +147,17 @@ export default class ChatContextMenu {
icon: 'edit', icon: 'edit',
text: 'Edit', text: 'Edit',
onClick: this.onEditClick, 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', icon: 'copy',
text: 'Copy', text: 'Copy',
onClick: this.onCopyClick, onClick: this.onCopyClick,
verify: () => !!this.appMessagesManager.getMessage(this.mid).message verify: () => !!this.chat.getMessage(this.mid).message
}, { }, {
icon: 'copy', icon: 'copy',
text: 'Copy selected', text: 'Copy selected',
onClick: this.onCopyClick, 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, notDirect: () => true,
withSelection: true withSelection: true
}, { }, {
@ -165,7 +165,7 @@ export default class ChatContextMenu {
text: 'Pin', text: 'Pin',
onClick: this.onPinClick, onClick: this.onPinClick,
verify: () => { 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); return this.mid > 0 && message._ != 'messageService' && !message.pFlags.pinned && this.appPeersManager.canPinMessage(this.peerId);
} }
}, { }, {
@ -173,7 +173,7 @@ export default class ChatContextMenu {
text: 'Unpin', text: 'Unpin',
onClick: this.onUnpinClick, onClick: this.onUnpinClick,
verify: () => { verify: () => {
const message = this.appMessagesManager.getMessage(this.mid); const message = this.chat.getMessage(this.mid);
return message.pFlags.pinned && this.appPeersManager.canPinMessage(this.peerId); return message.pFlags.pinned && this.appPeersManager.canPinMessage(this.peerId);
} }
}, { }, {
@ -181,7 +181,7 @@ export default class ChatContextMenu {
text: 'Revote', text: 'Revote',
onClick: this.onRetractVote, onClick: this.onRetractVote,
verify: () => { verify: () => {
const message = this.appMessagesManager.getMessage(this.mid); const message = this.chat.getMessage(this.mid);
const poll = message.media?.poll as Poll; const poll = message.media?.poll as Poll;
return poll && poll.chosenIndexes.length && !poll.pFlags.closed && !poll.pFlags.quiz; return poll && poll.chosenIndexes.length && !poll.pFlags.closed && !poll.pFlags.quiz;
}/* , }/* ,
@ -191,9 +191,9 @@ export default class ChatContextMenu {
text: 'Stop poll', text: 'Stop poll',
onClick: this.onStopPoll, onClick: this.onStopPoll,
verify: () => { verify: () => {
const message = this.appMessagesManager.getMessage(this.mid); const message = this.chat.getMessage(this.mid);
const poll = message.media?.poll; 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 */ cancelEvent: true */
}, { }, {
@ -213,7 +213,7 @@ export default class ChatContextMenu {
text: 'Select', text: 'Select',
onClick: this.onSelectClick, onClick: this.onSelectClick,
verify: () => { 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); return !message.action && !this.chat.selection.selectedMids.has(this.mid);
}, },
notDirect: () => true, notDirect: () => true,
@ -229,7 +229,7 @@ export default class ChatContextMenu {
icon: 'delete danger', icon: 'delete danger',
text: 'Delete', text: 'Delete',
onClick: this.onDeleteClick, onClick: this.onDeleteClick,
verify: () => this.appMessagesManager.canDeleteMessage(this.mid) verify: () => this.appMessagesManager.canDeleteMessage(this.peerId, this.mid)
}, { }, {
icon: 'delete danger', icon: 'delete danger',
text: 'Delete selected', text: 'Delete selected',
@ -245,7 +245,7 @@ export default class ChatContextMenu {
}; };
private onReplyClick = () => { private onReplyClick = () => {
const message = this.appMessagesManager.getMessage(this.mid); const message = this.chat.getMessage(this.mid);
const chatInputC = this.chat.input; const chatInputC = this.chat.input;
const f = () => { const f = () => {
chatInputC.setTopInfo('reply', f, this.appPeersManager.getPeerTitle(message.fromId, true), message.message, undefined, message); chatInputC.setTopInfo('reply', f, this.appPeersManager.getPeerTitle(message.fromId, true), message.message, undefined, message);
@ -261,7 +261,7 @@ export default class ChatContextMenu {
private onCopyClick = () => { private onCopyClick = () => {
const mids = this.chat.selection.isSelecting ? [...this.chat.selection.selectedMids] : [this.mid]; const mids = this.chat.selection.isSelecting ? [...this.chat.selection.selectedMids] : [this.mid];
const str = mids.reduce((acc, 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' : ''); return acc + (message?.message ? message.message + '\n' : '');
}, '').trim(); }, '').trim();
@ -277,18 +277,18 @@ export default class ChatContextMenu {
}; };
private onRetractVote = () => { private onRetractVote = () => {
this.appPollsManager.sendVote(this.mid, []); this.appPollsManager.sendVote(this.peerId, this.mid, []);
}; };
private onStopPoll = () => { private onStopPoll = () => {
this.appPollsManager.stopPoll(this.mid); this.appPollsManager.stopPoll(this.peerId, this.mid);
}; };
private onForwardClick = () => { private onForwardClick = () => {
if(this.chat.selection.isSelecting) { if(this.chat.selection.isSelecting) {
this.chat.selection.selectionForwardBtn.click(); this.chat.selection.selectionForwardBtn.click();
} else { } 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 {
if(this.chat.selection.isSelecting) { if(this.chat.selection.isSelecting) {
this.chat.selection.selectionDeleteBtn.click(); this.chat.selection.selectionDeleteBtn.click();
} else { } 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 {
public willSendWebPage: any = null; public willSendWebPage: any = null;
public forwardingMids: number[] = []; public forwardingMids: number[] = [];
public forwardingFromPeerId: number = 0;
public replyToMsgId = 0; public replyToMsgId = 0;
public editMsgId = 0; public editMsgId = 0;
public noWebPage: true; public noWebPage: true;
@ -102,6 +103,7 @@ export default class ChatInput {
public goDownBtn: HTMLButtonElement; public goDownBtn: HTMLButtonElement;
public goDownUnreadBadge: HTMLElement; 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) { 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(); this.listenerSetter = new ListenerSetter();
@ -158,6 +160,9 @@ export default class ChatInput {
this.inputScroll = new Scrollable(this.inputMessageContainer); this.inputScroll = new Scrollable(this.inputMessageContainer);
this.btnScheduled = ButtonIcon('schedule', {noRipple: true});
this.btnScheduled.classList.add('btn-scheduled', 'hide');
this.attachMenuButtons = [{ this.attachMenuButtons = [{
icon: 'photo', icon: 'photo',
text: 'Photo or Video', text: 'Photo or Video',
@ -219,7 +224,7 @@ export default class ChatInput {
this.fileInput.multiple = true; this.fileInput.multiple = true;
this.fileInput.style.display = 'none'; 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); this.rowsWrapper.append(this.replyElements.container, this.newMessageWrapper);
@ -311,6 +316,10 @@ export default class ChatInput {
}); */ }); */
attachClickEvent(this.btnSend, this.onBtnSendClick, {listenerSetter: this.listenerSetter}); 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) { if(this.recorder) {
const onCancelRecordClick = (e: Event) => { const onCancelRecordClick = (e: Event) => {
cancelEvent(e); cancelEvent(e);
@ -450,6 +459,13 @@ export default class ChatInput {
if(this.chat.type == 'pinned') { if(this.chat.type == 'pinned') {
this.chatInput.classList.toggle('can-pin', this.appPeersManager.canPinMessage(peerId)); 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) { if(this.messageInput) {
@ -953,11 +969,12 @@ export default class ChatInput {
if(this.helperWaitingForward) return; if(this.helperWaitingForward) return;
this.helperWaitingForward = true; this.helperWaitingForward = true;
const fromId = this.forwardingFromPeerId;
const mids = this.forwardingMids.slice(); const mids = this.forwardingMids.slice();
const helperFunc = this.helperFunc; const helperFunc = this.helperFunc;
this.clearHelper(); this.clearHelper();
let selected = false; let selected = false;
new PopupForward(mids, () => { new PopupForward(fromId, mids, () => {
selected = true; selected = true;
}, () => { }, () => {
this.helperWaitingForward = false; this.helperWaitingForward = false;
@ -1032,7 +1049,7 @@ export default class ChatInput {
//return; //return;
if(this.editMsgId) { if(this.editMsgId) {
this.appMessagesManager.editMessage(this.editMsgId, str, { this.appMessagesManager.editMessage(this.chat.peerId, this.editMsgId, str, {
noWebPage: this.noWebPage noWebPage: this.noWebPage
}); });
} else { } else {
@ -1046,8 +1063,10 @@ export default class ChatInput {
// * wait for sendText set messageId for invokeAfterMsg // * wait for sendText set messageId for invokeAfterMsg
if(this.forwardingMids.length) { if(this.forwardingMids.length) {
const mids = this.forwardingMids.slice(); const mids = this.forwardingMids.slice();
const fromPeerId = this.forwardingFromPeerId;
const peerId = this.chat.peerId;
setTimeout(() => { setTimeout(() => {
this.appMessagesManager.forwardMessages(this.chat.peerId, mids); this.appMessagesManager.forwardMessages(peerId, fromPeerId, mids);
}, 0); }, 0);
} }
@ -1071,7 +1090,7 @@ export default class ChatInput {
} }
public initMessageEditing(mid: number) { 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}); let input = RichTextProcessor.wrapDraftText(message.message, {entities: message.totalEntities});
const f = () => { const f = () => {
@ -1082,11 +1101,11 @@ export default class ChatInput {
f(); f();
} }
public initMessagesForward(mids: number[]) { public initMessagesForward(fromPeerId: number, mids: number[]) {
const f = () => { const f = () => {
//const peerTitles: string[] //const peerTitles: string[]
const smth: Set<string | number> = new Set(mids.map(mid => { 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) { if(message.fwd_from && message.fwd_from.from_name && !message.fromId && !message.fwdFromId) {
return message.fwd_from.from_name; return message.fwd_from.from_name;
} else { } else {
@ -1103,13 +1122,14 @@ export default class ChatInput {
const title = peerTitles.length < 3 ? peerTitles.join(' and ') : peerTitles[0] + ' and ' + (peerTitles.length - 1) + ' others'; const title = peerTitles.length < 3 ? peerTitles.join(' and ') : peerTitles[0] + ' and ' + (peerTitles.length - 1) + ' others';
if(mids.length == 1) { 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); this.setTopInfo('forward', f, title, message.message, undefined, message);
} else { } else {
this.setTopInfo('forward', f, title, mids.length + ' forwarded messages'); this.setTopInfo('forward', f, title, mids.length + ' forwarded messages');
} }
this.forwardingMids = mids.slice(); this.forwardingMids = mids.slice();
this.forwardingFromPeerId = fromPeerId;
}; };
f(); f();
@ -1128,6 +1148,7 @@ export default class ChatInput {
this.replyToMsgId = 0; this.replyToMsgId = 0;
this.forwardingMids.length = 0; this.forwardingMids.length = 0;
this.forwardingFromPeerId = 0;
this.editMsgId = 0; this.editMsgId = 0;
this.helperType = this.helperFunc = undefined; this.helperType = this.helperFunc = undefined;
this.chat.container.classList.remove('is-helper-active'); this.chat.container.classList.remove('is-helper-active');

4
src/components/chat/pinnedMessage.ts

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

12
src/components/chat/selection.ts

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

14
src/components/chat/topbar.ts

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

8
src/components/poll.ts

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

7
src/components/popupDeleteMessages.ts

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

4
src/components/popupForward.ts

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

2
src/components/popupNewMedia.ts

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

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

@ -45,7 +45,7 @@ export default class AppForwardTab implements SliderTab {
let s = () => { let s = () => {
let promises = peerIds.splice(0, 3).map(peerId => { 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(() => { Promise.all(promises).then(() => {

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

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

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

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

31
src/components/wrappers.ts

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

9
src/lib/appManagers/AppInlineBotsManager.ts

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

4
src/lib/appManagers/appDialogsManager.ts

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

13
src/lib/appManagers/appImManager.ts

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

85
src/lib/appManagers/appMessagesIDsManager.ts

@ -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;

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

6
src/lib/appManagers/appStateManager.ts

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

3
src/lib/mtproto/referenceDatabase.ts

@ -13,6 +13,7 @@ export namespace ReferenceContext {
export type referenceContextMessage = { export type referenceContextMessage = {
type: 'message', type: 'message',
peerId: number,
messageId: number messageId: number
}; };
} }
@ -80,7 +81,7 @@ class ReferenceDatabase {
[context, reference] = this.getContext(reference); [context, reference] = this.getContext(reference);
switch(context?.type) { switch(context?.type) {
case 'message': { case 'message': {
return appMessagesManager.wrapSingleMessage(context.messageId, true); return appMessagesManager.wrapSingleMessage(context.peerId, context.messageId, true);
// .then(() => { // .then(() => {
// console.log('FILE_REFERENCE_EXPIRED: got message', context, appMessagesManager.getMessage((context as ReferenceContext.referenceContextMessage).messageId).media, reference); // 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 = {
'messages_pending': void, 'messages_pending': void,
'messages_read': void, 'messages_read': void,
'messages_downloaded': number[], '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[]}, 'album_edit': {peerId: number, groupId: string, deletedMids: number[]},
'stickers_installed': StickerSet.stickerSet, 'stickers_installed': StickerSet.stickerSet,
'stickers_deleted': StickerSet.stickerSet, 'stickers_deleted': StickerSet.stickerSet,
'audio_play': {doc: MyDocument, mid: number}, 'audio_play': {doc: MyDocument, mid: number, peerId: number},
'audio_pause': void, 'audio_pause': void,
'state_synchronized': number, 'state_synchronized': number,

7
src/lib/storages/dialogs.ts

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

2
src/scss/partials/_chatBubble.scss

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

1
src/scss/partials/_rightSidebar.scss

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

Loading…
Cancel
Save