Draft messages
This commit is contained in:
parent
322eed41c5
commit
38780910dd
@ -383,7 +383,7 @@ export default class ChatBubbles {
|
||||
let details = e;
|
||||
|
||||
if(!this.scrolledAllDown) {
|
||||
this.chat.setPeer(this.peerId, 0);
|
||||
this.chat.setMessageId(0);
|
||||
} else {
|
||||
this.renderNewMessagesByIds([details.messageId], true);
|
||||
}
|
||||
@ -729,11 +729,11 @@ export default class ChatBubbles {
|
||||
this.chat.appImManager.setInnerPeer(replyToPeerId, replyToMid, this.chat.type, this.chat.threadId);
|
||||
|
||||
/* if(this.chat.type === 'discussion') {
|
||||
this.chat.appImManager.setPeer(this.peerId, originalMessageId);
|
||||
this.chat.appImManager.setMessageId(, originalMessageId);
|
||||
} else {
|
||||
this.chat.appImManager.setInnerPeer(this.peerId, originalMessageId);
|
||||
} */
|
||||
//this.chat.setPeer(this.peerId, originalMessageId);
|
||||
//this.chat.setMessageId(, originalMessageId);
|
||||
}
|
||||
} else if(target.tagName == 'IMG' && target.parentElement.tagName == "AVATAR-ELEMENT") {
|
||||
let peerId = +target.parentElement.getAttribute('peer');
|
||||
@ -769,9 +769,9 @@ export default class ChatBubbles {
|
||||
this.replyFollowHistory.sort((a, b) => b - a);
|
||||
|
||||
const mid = this.replyFollowHistory.pop();
|
||||
this.chat.setPeer(this.peerId, mid);
|
||||
this.chat.setMessageId(mid);
|
||||
} else {
|
||||
this.chat.setPeer(this.peerId/* , dialog.top_message */);
|
||||
this.chat.setMessageId(/* , dialog.top_message */);
|
||||
// const dialog = this.appMessagesManager.getDialogByPeerId(this.peerId)[0];
|
||||
|
||||
// if(dialog) {
|
||||
@ -1076,7 +1076,7 @@ export default class ChatBubbles {
|
||||
} else {
|
||||
str = months[date.getMonth()] + ' ' + date.getDate();
|
||||
|
||||
if(date.getFullYear() != today.getFullYear()) {
|
||||
if(date.getFullYear() !== today.getFullYear()) {
|
||||
str += ', ' + date.getFullYear();
|
||||
}
|
||||
}
|
||||
@ -1156,9 +1156,7 @@ export default class ChatBubbles {
|
||||
this.bubbleGroups.cleanup();
|
||||
this.unreadOut.clear();
|
||||
this.needUpdate.length = 0;
|
||||
//this.lazyLoadQueue.clear();
|
||||
|
||||
//this.chatInputC.replyElements.cancelBtn.click();
|
||||
this.lazyLoadQueue.clear();
|
||||
|
||||
// clear messages
|
||||
if(bubblesToo) {
|
||||
@ -1194,13 +1192,13 @@ export default class ChatBubbles {
|
||||
//console.time('appImManager setPeer');
|
||||
//console.time('appImManager setPeer pre promise');
|
||||
////console.time('appImManager: pre render start');
|
||||
if(peerId == 0) {
|
||||
if(!peerId) {
|
||||
this.cleanup(true);
|
||||
this.peerId = 0;
|
||||
return null;
|
||||
}
|
||||
|
||||
const samePeer = this.peerId == peerId;
|
||||
const samePeer = this.peerId === peerId;
|
||||
|
||||
const historyStorage = this.appMessagesManager.getHistoryStorage(peerId, this.chat.threadId);
|
||||
let topMessage = this.chat.type === 'pinned' ? this.appMessagesManager.pinnedMessages[peerId].maxId : historyStorage.maxId ?? 0;
|
||||
@ -1248,7 +1246,9 @@ export default class ChatBubbles {
|
||||
this.replyFollowHistory.length = 0;
|
||||
}
|
||||
|
||||
if(DEBUG) {
|
||||
this.log('setPeer peerId:', this.peerId, historyStorage, lastMsgId, topMessage);
|
||||
}
|
||||
|
||||
// add last message, bc in getHistory will load < max_id
|
||||
const additionMsgId = isJump || this.chat.type === 'scheduled' ? 0 : topMessage;
|
||||
@ -1261,7 +1261,7 @@ export default class ChatBubbles {
|
||||
|
||||
let maxBubbleId = 0;
|
||||
if(samePeer) {
|
||||
let el = getElementByPoint(this.chat.bubbles.scrollable.container, 'bottom');
|
||||
let el = getElementByPoint(this.chat.bubbles.scrollable.container, 'bottom'); // ! this may not work if being called when chat is hidden
|
||||
//this.chat.log('[PM]: setCorrectIndex: get last element perf:', performance.now() - perf, el);
|
||||
if(el) {
|
||||
el = findUpClassName(el, 'bubble');
|
||||
@ -1281,10 +1281,6 @@ export default class ChatBubbles {
|
||||
this.chatInner.className = oldChatInner.className;
|
||||
this.chatInner.classList.add('disable-hover', 'is-scrolling');
|
||||
|
||||
if(!samePeer) {
|
||||
this.lazyLoadQueue.clear();
|
||||
}
|
||||
|
||||
this.lazyLoadQueue.lock();
|
||||
|
||||
const {promise, cached} = this.getHistory(lastMsgId, true, isJump, additionMsgId);
|
||||
@ -1321,8 +1317,6 @@ export default class ChatBubbles {
|
||||
this.scrollable.container.append(this.chatInner);
|
||||
animationIntersector.unlockGroup(CHAT_ANIMATION_GROUP);
|
||||
animationIntersector.checkAnimations(false, CHAT_ANIMATION_GROUP/* , true */);
|
||||
//this.scrollable.attachSentinels();
|
||||
//this.scrollable.container.insertBefore(this.chatInner, this.scrollable.container.lastElementChild);
|
||||
|
||||
this.lazyLoadQueue.unlock();
|
||||
|
||||
@ -1457,7 +1451,6 @@ export default class ChatBubbles {
|
||||
|
||||
this.messagesQueuePromise = new Promise((resolve, reject) => {
|
||||
setTimeout(() => {
|
||||
const chatInner = this.chatInner;
|
||||
const queue = this.messagesQueue.slice();
|
||||
this.messagesQueue.length = 0;
|
||||
|
||||
@ -1468,10 +1461,10 @@ export default class ChatBubbles {
|
||||
// promises.push(getHeavyAnimationPromise());
|
||||
|
||||
//this.log('promises to call', promises, queue);
|
||||
const middleware = this.getMiddleware();
|
||||
Promise.all(promises).then(() => {
|
||||
if(this.chatInner != chatInner) {
|
||||
//this.log.warn('chatInner changed!', this.chatInner, chatInner);
|
||||
return reject('chatInner changed!');
|
||||
if(!middleware()) {
|
||||
return Promise.reject('setMessagesQueuePromise: peer changed!');
|
||||
}
|
||||
|
||||
if(this.messagesQueueOnRender) {
|
||||
@ -1490,7 +1483,7 @@ export default class ChatBubbles {
|
||||
if(this.messagesQueue.length) {
|
||||
this.setMessagesQueuePromise();
|
||||
}
|
||||
}, reject);
|
||||
}).catch(reject);
|
||||
}, 0);
|
||||
});
|
||||
}
|
||||
@ -2333,6 +2326,7 @@ export default class ChatBubbles {
|
||||
//const realLength = this.scrollable.container.childElementCount;
|
||||
let previousScrollHeightMinusTop: number/* , previousScrollHeight: number */;
|
||||
//if(realLength > 0/* && (reverse || isSafari) */) { // for safari need set when scrolling bottom too
|
||||
//if(!this.scrollable.isHeavyScrolling) {
|
||||
this.messagesQueueOnRender = () => {
|
||||
const {scrollTop, scrollHeight} = this.scrollable;
|
||||
|
||||
@ -2351,6 +2345,7 @@ export default class ChatBubbles {
|
||||
this.messagesQueueOnRender = undefined;
|
||||
};
|
||||
//}
|
||||
//}
|
||||
|
||||
while(history.length) {
|
||||
let message = this.chat.getMessage(method());
|
||||
@ -2412,7 +2407,7 @@ export default class ChatBubbles {
|
||||
return;
|
||||
}
|
||||
|
||||
this.chat.setPeer(this.peerId, (history.messages[0] as MyMessage).mid);
|
||||
this.chat.setMessageId((history.messages[0] as MyMessage).mid);
|
||||
//console.log('got history date:', history);
|
||||
});
|
||||
};
|
||||
@ -2540,18 +2535,18 @@ export default class ChatBubbles {
|
||||
const promise = result.then((result) => {
|
||||
//this.log('getHistory not cached result by maxId:', maxId, reverse, isBackLimit, result, peerId, justLoad);
|
||||
|
||||
if(reverse ? this.getHistoryTopPromise !== promise : this.getHistoryBottomPromise !== promise) {
|
||||
this.log.warn('getHistory: peer changed');
|
||||
////console.timeEnd('render history total');
|
||||
return Promise.reject();
|
||||
}
|
||||
|
||||
if(justLoad) {
|
||||
this.scrollable.onScroll(); // нужно делать из-за ранней прогрузки
|
||||
return true;
|
||||
}
|
||||
//console.timeEnd('appImManager call getHistory');
|
||||
|
||||
if(this.peerId != peerId || (this.getHistoryTopPromise != promise && this.getHistoryBottomPromise != promise)) {
|
||||
this.log.warn('peer changed');
|
||||
////console.timeEnd('render history total');
|
||||
return Promise.reject();
|
||||
}
|
||||
|
||||
processResult(result);
|
||||
|
||||
////console.timeEnd('render history total');
|
||||
@ -2561,7 +2556,7 @@ export default class ChatBubbles {
|
||||
});
|
||||
}, (err) => {
|
||||
this.log.error('getHistory error:', err);
|
||||
return false;
|
||||
throw err;
|
||||
});
|
||||
|
||||
return promise;
|
||||
@ -2626,7 +2621,7 @@ export default class ChatBubbles {
|
||||
}
|
||||
|
||||
(reverse ? this.getHistoryTopPromise = waitPromise : this.getHistoryBottomPromise = waitPromise);
|
||||
waitPromise.finally(() => {
|
||||
waitPromise.then(() => {
|
||||
(reverse ? this.getHistoryTopPromise = undefined : this.getHistoryBottomPromise = undefined);
|
||||
});
|
||||
|
||||
|
@ -11,6 +11,8 @@ import type { AppStickersManager } from "../../lib/appManagers/appStickersManage
|
||||
import type { AppUsersManager } from "../../lib/appManagers/appUsersManager";
|
||||
import type { AppWebPagesManager } from "../../lib/appManagers/appWebPagesManager";
|
||||
import type { ApiManagerProxy } from "../../lib/mtproto/mtprotoworker";
|
||||
import type { AppDraftsManager } from "../../lib/appManagers/appDraftsManager";
|
||||
import type { ServerTimeManager } from "../../lib/mtproto/serverTimeManager";
|
||||
import EventListenerBase from "../../helpers/eventListenerBase";
|
||||
import { logger, LogLevels } from "../../lib/logger";
|
||||
import rootScope from "../../lib/rootScope";
|
||||
@ -36,6 +38,7 @@ export default class Chat extends EventListenerBase<{
|
||||
public selection: ChatSelection;
|
||||
public contextMenu: ChatContextMenu;
|
||||
|
||||
public initPeerId = 0;
|
||||
public peerId = 0;
|
||||
public threadId: number;
|
||||
public setPeerPromise: Promise<void>;
|
||||
@ -45,7 +48,7 @@ export default class Chat extends EventListenerBase<{
|
||||
|
||||
public type: ChatType = 'chat';
|
||||
|
||||
constructor(public appImManager: AppImManager, public appChatsManager: AppChatsManager, public appDocsManager: AppDocsManager, public appInlineBotsManager: AppInlineBotsManager, public appMessagesManager: AppMessagesManager, public appPeersManager: AppPeersManager, public appPhotosManager: AppPhotosManager, public appProfileManager: AppProfileManager, public appStickersManager: AppStickersManager, public appUsersManager: AppUsersManager, public appWebPagesManager: AppWebPagesManager, public appPollsManager: AppPollsManager, public apiManager: ApiManagerProxy) {
|
||||
constructor(public appImManager: AppImManager, public appChatsManager: AppChatsManager, public appDocsManager: AppDocsManager, public appInlineBotsManager: AppInlineBotsManager, public appMessagesManager: AppMessagesManager, public appPeersManager: AppPeersManager, public appPhotosManager: AppPhotosManager, public appProfileManager: AppProfileManager, public appStickersManager: AppStickersManager, public appUsersManager: AppUsersManager, public appWebPagesManager: AppWebPagesManager, public appPollsManager: AppPollsManager, public apiManager: ApiManagerProxy, public appDraftsManager: AppDraftsManager, public serverTimeManager: ServerTimeManager) {
|
||||
super();
|
||||
|
||||
this.container = document.createElement('div');
|
||||
@ -72,10 +75,12 @@ export default class Chat extends EventListenerBase<{
|
||||
}
|
||||
}
|
||||
|
||||
public init() {
|
||||
public init(peerId: number) {
|
||||
this.initPeerId = peerId;
|
||||
|
||||
this.topbar = new ChatTopbar(this, appSidebarRight, this.appMessagesManager, this.appPeersManager, this.appChatsManager);
|
||||
this.bubbles = new ChatBubbles(this, this.appMessagesManager, this.appStickersManager, this.appUsersManager, this.appInlineBotsManager, this.appPhotosManager, this.appDocsManager, this.appPeersManager, this.appChatsManager);
|
||||
this.input = new ChatInput(this, this.appMessagesManager, this.appDocsManager, this.appChatsManager, this.appPeersManager, this.appWebPagesManager, this.appImManager);
|
||||
this.input = new ChatInput(this, this.appMessagesManager, this.appDocsManager, this.appChatsManager, this.appPeersManager, this.appWebPagesManager, this.appImManager, this.appDraftsManager, this.serverTimeManager);
|
||||
this.selection = new ChatSelection(this, this.bubbles, this.input, this.appMessagesManager);
|
||||
this.contextMenu = new ChatContextMenu(this.bubbles.bubblesContainer, this, this.appMessagesManager, this.appChatsManager, this.appPeersManager, this.appPollsManager);
|
||||
|
||||
@ -131,22 +136,25 @@ export default class Chat extends EventListenerBase<{
|
||||
public cleanup() {
|
||||
this.input.cleanup();
|
||||
this.selection.cleanup();
|
||||
|
||||
this.peerChanged = false;
|
||||
}
|
||||
|
||||
public setPeer(peerId: number, lastMsgId?: number) {
|
||||
if(this.init) {
|
||||
this.init();
|
||||
this.init(peerId);
|
||||
this.init = null;
|
||||
}
|
||||
|
||||
const samePeer = this.peerId === peerId;
|
||||
if(!samePeer) {
|
||||
rootScope.broadcast('peer_changing', this);
|
||||
this.peerId = peerId;
|
||||
}
|
||||
|
||||
//console.time('appImManager setPeer');
|
||||
//console.time('appImManager setPeer pre promise');
|
||||
////console.time('appImManager: pre render start');
|
||||
if(peerId == 0) {
|
||||
if(!peerId) {
|
||||
appSidebarRight.toggleSidebar(false);
|
||||
this.peerId = peerId;
|
||||
this.cleanup();
|
||||
this.topbar.setPeer(peerId);
|
||||
this.bubbles.setPeer(peerId);
|
||||
@ -155,21 +163,17 @@ export default class Chat extends EventListenerBase<{
|
||||
return;
|
||||
}
|
||||
|
||||
const samePeer = this.peerId == peerId;
|
||||
|
||||
// set new
|
||||
if(!samePeer) {
|
||||
if(appSidebarRight.historyTabIds[appSidebarRight.historyTabIds.length - 1] == AppSidebarRight.SLIDERITEMSIDS.search) {
|
||||
if(appSidebarRight.historyTabIds[appSidebarRight.historyTabIds.length - 1] === AppSidebarRight.SLIDERITEMSIDS.search) {
|
||||
appSidebarRight.closeTab(AppSidebarRight.SLIDERITEMSIDS.search);
|
||||
}
|
||||
|
||||
this.peerId = peerId;
|
||||
appSidebarRight.sharedMediaTab.setPeer(peerId, this.threadId);
|
||||
this.cleanup();
|
||||
} else {
|
||||
this.peerChanged = true;
|
||||
}
|
||||
|
||||
this.peerChanged = samePeer;
|
||||
|
||||
const result = this.bubbles.setPeer(peerId, lastMsgId);
|
||||
if(!result) {
|
||||
return;
|
||||
@ -179,8 +183,8 @@ export default class Chat extends EventListenerBase<{
|
||||
|
||||
//console.timeEnd('appImManager setPeer pre promise');
|
||||
|
||||
this.setPeerPromise = promise.finally(() => {
|
||||
if(this.peerId == peerId) {
|
||||
const setPeerPromise = this.setPeerPromise = promise.finally(() => {
|
||||
if(this.setPeerPromise === setPeerPromise) {
|
||||
this.setPeerPromise = null;
|
||||
}
|
||||
});
|
||||
@ -194,12 +198,18 @@ export default class Chat extends EventListenerBase<{
|
||||
return result;
|
||||
}
|
||||
|
||||
public setMessageId(messageId?: number) {
|
||||
return this.setPeer(this.peerId, messageId);
|
||||
}
|
||||
|
||||
public finishPeerChange(isTarget: boolean, isJump: boolean, lastMsgId: number) {
|
||||
if(this.peerChanged) return;
|
||||
|
||||
let peerId = this.peerId;
|
||||
this.peerChanged = true;
|
||||
|
||||
this.cleanup();
|
||||
|
||||
this.topbar.setPeer(peerId);
|
||||
this.topbar.finishPeerChange(isTarget, isJump, lastMsgId);
|
||||
this.bubbles.finishPeerChange();
|
||||
|
@ -4,6 +4,8 @@ import type { AppMessagesManager } from "../../lib/appManagers/appMessagesManage
|
||||
import type { AppPeersManager } from '../../lib/appManagers/appPeersManager';
|
||||
import type { AppWebPagesManager } from "../../lib/appManagers/appWebPagesManager";
|
||||
import type { AppImManager } from '../../lib/appManagers/appImManager';
|
||||
import type { AppDraftsManager, MyDraftMessage } from '../../lib/appManagers/appDraftsManager';
|
||||
import type { ServerTimeManager } from '../../lib/mtproto/serverTimeManager';
|
||||
import type Chat from './chat';
|
||||
import Recorder from '../../../public/recorder.min';
|
||||
import { isTouchSupported } from "../../helpers/touchSupport";
|
||||
@ -21,7 +23,7 @@ import Scrollable from "../scrollable";
|
||||
import { toast } from "../toast";
|
||||
import { wrapReply } from "../wrappers";
|
||||
import InputField from '../inputField';
|
||||
import { MessageEntity } from '../../layer';
|
||||
import { MessageEntity, DraftMessage } from '../../layer';
|
||||
import StickersHelper from './stickersHelper';
|
||||
import ButtonIcon from '../buttonIcon';
|
||||
import DivAndCaption from '../divAndCaption';
|
||||
@ -32,7 +34,8 @@ import PopupSchedule from '../popups/schedule';
|
||||
import SendMenu from './sendContextMenu';
|
||||
import rootScope from '../../lib/rootScope';
|
||||
import PopupPinMessage from '../popups/unpinMessage';
|
||||
import { isApple } from '../../helpers/userAgent';
|
||||
import { debounce } from '../../helpers/schedulers';
|
||||
import { tsNow } from '../../helpers/date';
|
||||
|
||||
const RECORD_MIN_TIME = 500;
|
||||
const POSTING_MEDIA_NOT_ALLOWED = 'Posting media content isn\'t allowed in this group.';
|
||||
@ -109,9 +112,11 @@ export default class ChatInput {
|
||||
|
||||
public goDownBtn: HTMLButtonElement;
|
||||
public goDownUnreadBadge: HTMLElement;
|
||||
btnScheduled: HTMLButtonElement;
|
||||
public btnScheduled: HTMLButtonElement;
|
||||
|
||||
constructor(private chat: Chat, private appMessagesManager: AppMessagesManager, private appDocsManager: AppDocsManager, private appChatsManager: AppChatsManager, private appPeersManager: AppPeersManager, private appWebPagesManager: AppWebPagesManager, private appImManager: AppImManager) {
|
||||
public saveDraftDebounced: () => void;
|
||||
|
||||
constructor(private chat: Chat, private appMessagesManager: AppMessagesManager, private appDocsManager: AppDocsManager, private appChatsManager: AppChatsManager, private appPeersManager: AppPeersManager, private appWebPagesManager: AppWebPagesManager, private appImManager: AppImManager, private appDraftsManager: AppDraftsManager, private serverTimeManager: ServerTimeManager) {
|
||||
this.listenerSetter = new ListenerSetter();
|
||||
}
|
||||
|
||||
@ -311,6 +316,18 @@ export default class ChatInput {
|
||||
}
|
||||
});
|
||||
|
||||
this.listenerSetter.add(rootScope, 'draft_updated', (e) => {
|
||||
const {peerId, threadId, draft} = e;
|
||||
if(this.chat.threadId !== threadId || this.chat.peerId !== peerId) return;
|
||||
this.setDraft(draft);
|
||||
});
|
||||
|
||||
this.listenerSetter.add(rootScope, 'peer_changing', (chat) => {
|
||||
if(this.chat === chat) {
|
||||
this.saveDraft();
|
||||
}
|
||||
});
|
||||
|
||||
try {
|
||||
this.recorder = new Recorder({
|
||||
//encoderBitRate: 32,
|
||||
@ -388,7 +405,8 @@ export default class ChatInput {
|
||||
waveform: result.waveform,
|
||||
objectURL: result.url,
|
||||
replyToMsgId: this.replyToMsgId,
|
||||
threadId: this.chat.threadId
|
||||
threadId: this.chat.threadId,
|
||||
clearDraft: true
|
||||
});
|
||||
|
||||
this.onMessageSent(false, true);
|
||||
@ -398,6 +416,8 @@ export default class ChatInput {
|
||||
|
||||
attachClickEvent(this.replyElements.cancelBtn, this.onHelperCancel, {listenerSetter: this.listenerSetter});
|
||||
attachClickEvent(this.replyElements.container, this.onHelperClick, {listenerSetter: this.listenerSetter});
|
||||
|
||||
this.saveDraftDebounced = debounce(() => this.saveDraft(), 2500, false, true);
|
||||
}
|
||||
|
||||
public constructPinnedHelpers() {
|
||||
@ -470,6 +490,29 @@ export default class ChatInput {
|
||||
this.goDownUnreadBadge.classList.toggle('badge-gray', this.appMessagesManager.isPeerMuted(this.chat.peerId));
|
||||
}
|
||||
|
||||
public saveDraft() {
|
||||
if(!this.chat.peerId) return;
|
||||
|
||||
const entities: MessageEntity[] = [];
|
||||
const str = getRichValue(this.messageInputField.input, entities);
|
||||
|
||||
let draft: DraftMessage.draftMessage;
|
||||
if(str.length) {
|
||||
draft = {
|
||||
_: 'draftMessage',
|
||||
date: tsNow(true) + this.serverTimeManager.serverTimeOffset,
|
||||
message: str,
|
||||
entities: entities.length ? entities : undefined,
|
||||
pFlags: {
|
||||
no_webpage: this.noWebPage
|
||||
},
|
||||
reply_to_msg_id: this.replyToMsgId
|
||||
};
|
||||
}
|
||||
|
||||
this.appDraftsManager.syncDraft(this.chat.peerId, this.chat.threadId, draft);
|
||||
}
|
||||
|
||||
public destroy() {
|
||||
//this.chat.log.error('Input destroying');
|
||||
|
||||
@ -493,6 +536,20 @@ export default class ChatInput {
|
||||
}
|
||||
}
|
||||
|
||||
public setDraft(draft?: MyDraftMessage, fromUpdate = true) {
|
||||
if(!isInputEmpty(this.messageInput)) return;
|
||||
|
||||
if(!draft) {
|
||||
draft = this.appDraftsManager.getDraft(this.chat.peerId, this.chat.threadId);
|
||||
|
||||
if(!draft) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
this.setInputValue(draft.rMessage, fromUpdate, fromUpdate);
|
||||
}
|
||||
|
||||
public finishPeerChange() {
|
||||
const peerId = this.chat.peerId;
|
||||
|
||||
@ -541,6 +598,7 @@ export default class ChatInput {
|
||||
this.messageInput.removeAttribute('contenteditable');
|
||||
} else {
|
||||
this.messageInput.setAttribute('contenteditable', 'true');
|
||||
this.setDraft(undefined, false);
|
||||
}
|
||||
|
||||
this.attachMenu.toggleAttribute('disabled', !visible.length);
|
||||
@ -801,7 +859,7 @@ export default class ChatInput {
|
||||
alert('not single');
|
||||
} */
|
||||
|
||||
//console.log('messageInput input', this.messageInput.innerText, this.serializeNodes(Array.from(this.messageInput.childNodes)));
|
||||
//console.log('messageInput input', this.messageInput.innerText);
|
||||
//const value = this.messageInput.innerText;
|
||||
const markdownEntities: MessageEntity[] = [];
|
||||
const richValue = getRichValue(this.messageInputField.input, markdownEntities);
|
||||
@ -896,6 +954,8 @@ export default class ChatInput {
|
||||
}
|
||||
}
|
||||
|
||||
this.saveDraftDebounced();
|
||||
|
||||
this.updateSendBtn();
|
||||
};
|
||||
|
||||
@ -1039,9 +1099,9 @@ export default class ChatInput {
|
||||
}
|
||||
});
|
||||
} else if(this.helperType == 'reply') {
|
||||
this.chat.setPeer(this.chat.peerId, this.replyToMsgId);
|
||||
this.chat.setMessageId(this.replyToMsgId);
|
||||
} else if(this.helperType == 'edit') {
|
||||
this.chat.setPeer(this.chat.peerId, this.editMsgId);
|
||||
this.chat.setMessageId(this.editMsgId);
|
||||
}
|
||||
};
|
||||
|
||||
@ -1125,7 +1185,8 @@ export default class ChatInput {
|
||||
noWebPage: this.noWebPage,
|
||||
webPage: this.willSendWebPage,
|
||||
scheduleDate: this.scheduleDate,
|
||||
silent: this.sendSilent
|
||||
silent: this.sendSilent,
|
||||
clearDraft: true
|
||||
});
|
||||
}
|
||||
|
||||
@ -1269,6 +1330,16 @@ export default class ChatInput {
|
||||
this.chat.container.classList.remove('is-helper-active');
|
||||
}
|
||||
|
||||
public setInputValue(value: string, clear = true, focus = true) {
|
||||
clear && this.clearInput();
|
||||
this.messageInput.innerHTML = value || '';
|
||||
this.onMessageInput();
|
||||
window.requestAnimationFrame(() => {
|
||||
focus && placeCaretAtEnd(this.messageInput);
|
||||
this.inputScroll.scrollTop = this.inputScroll.scrollHeight;
|
||||
});
|
||||
}
|
||||
|
||||
public setTopInfo(type: ChatInputHelperType, callerFunc: () => void, title = '', subtitle = '', input?: string, message?: any) {
|
||||
if(type != 'webpage') {
|
||||
this.clearHelper(type);
|
||||
@ -1288,13 +1359,7 @@ export default class ChatInput {
|
||||
} */
|
||||
|
||||
if(input !== undefined) {
|
||||
this.clearInput();
|
||||
this.messageInput.innerHTML = input || '';
|
||||
this.onMessageInput();
|
||||
window.requestAnimationFrame(() => {
|
||||
placeCaretAtEnd(this.messageInput);
|
||||
this.inputScroll.scrollTop = this.inputScroll.scrollHeight;
|
||||
});
|
||||
this.setInputValue(input);
|
||||
}
|
||||
|
||||
setTimeout(() => {
|
||||
|
@ -542,7 +542,7 @@ export default class ChatPinnedMessage {
|
||||
public async followPinnedMessage(mid: number) {
|
||||
const message = this.chat.getMessage(mid);
|
||||
if(message && !message.deleted) {
|
||||
this.chat.setPeer(this.topbar.peerId, mid);
|
||||
this.chat.setMessageId(mid);
|
||||
(this.chat.setPeerPromise || Promise.resolve()).then(() => { // * debounce fast clicker
|
||||
this.handleFollowingPinnedMessage();
|
||||
this.testMid(this.pinnedIndex >= (this.count - 1) ? this.pinnedMaxMid : mid - 1);
|
||||
|
@ -208,7 +208,7 @@ export default class ChatTopbar {
|
||||
public constructPeerHelpers() {
|
||||
this.avatarElement = new AvatarElement();
|
||||
this.avatarElement.setAttribute('dialog', '1');
|
||||
this.avatarElement.setAttribute('clickable', '');
|
||||
//this.avatarElement.setAttribute('clickable', '');
|
||||
this.avatarElement.classList.add('avatar-40', 'person-avatar');
|
||||
|
||||
this.subtitle = document.createElement('div');
|
||||
|
@ -168,7 +168,8 @@ export default class PopupNewMedia extends PopupElement {
|
||||
threadId: this.chat.threadId,
|
||||
isMedia: willAttach.isMedia,
|
||||
silent,
|
||||
scheduleDate
|
||||
scheduleDate,
|
||||
clearDraft: true as true
|
||||
}, w));
|
||||
|
||||
caption = undefined;
|
||||
@ -181,7 +182,8 @@ export default class PopupNewMedia extends PopupElement {
|
||||
replyToMsgId: input.replyToMsgId,
|
||||
threadId: this.chat.threadId,
|
||||
silent,
|
||||
scheduleDate
|
||||
scheduleDate,
|
||||
clearDraft: true
|
||||
});
|
||||
caption = '';
|
||||
//input.replyToMsgId = undefined;
|
||||
@ -196,7 +198,8 @@ export default class PopupNewMedia extends PopupElement {
|
||||
replyToMsgId: input.replyToMsgId,
|
||||
threadId: this.chat.threadId,
|
||||
silent,
|
||||
scheduleDate
|
||||
scheduleDate,
|
||||
clearDraft: true as true
|
||||
}, params));
|
||||
|
||||
caption = '';
|
||||
|
@ -1,7 +1,6 @@
|
||||
import { CancellablePromise } from "../helpers/cancellablePromise";
|
||||
import { isTouchSupported } from "../helpers/touchSupport";
|
||||
import { logger, LogLevels } from "../lib/logger";
|
||||
import fastSmoothScroll from "../helpers/fastSmoothScroll";
|
||||
import fastSmoothScroll, { FocusDirection } from "../helpers/fastSmoothScroll";
|
||||
import useHeavyAnimationCheck from "../hooks/useHeavyAnimationCheck";
|
||||
/*
|
||||
var el = $0;
|
||||
@ -52,7 +51,8 @@ export class ScrollableBase {
|
||||
public onScrollMeasure: number = 0;
|
||||
protected onScroll: () => void;
|
||||
|
||||
public isHeavyAnimationInProgress: boolean;
|
||||
public isHeavyAnimationInProgress = false;
|
||||
public isHeavyScrolling = false;
|
||||
|
||||
constructor(public el: HTMLElement, logPrefix = '', public container: HTMLElement = document.createElement('div')) {
|
||||
this.container.classList.add('scrollable');
|
||||
@ -87,7 +87,21 @@ export class ScrollableBase {
|
||||
this.container.append(element);
|
||||
}
|
||||
|
||||
public scrollIntoViewNew = fastSmoothScroll.bind(this, this.container);
|
||||
public scrollIntoViewNew(
|
||||
element: HTMLElement,
|
||||
position: ScrollLogicalPosition,
|
||||
margin?: number,
|
||||
maxDistance?: number,
|
||||
forceDirection?: FocusDirection,
|
||||
forceDuration?: number,
|
||||
axis?: 'x' | 'y'
|
||||
) {
|
||||
this.isHeavyScrolling = true;
|
||||
return fastSmoothScroll(this.container, element, position, margin, maxDistance, forceDirection, forceDuration, axis)
|
||||
.finally(() => {
|
||||
this.isHeavyScrolling = false;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
export type SliceSides = 'top' | 'bottom';
|
||||
|
@ -104,6 +104,8 @@ function scrollWithJs(
|
||||
const elementRect = element.getBoundingClientRect();
|
||||
const containerRect = container.getBoundingClientRect();
|
||||
|
||||
//const transformable = container.firstElementChild as HTMLElement;
|
||||
|
||||
const elementPosition = elementRect[rectStartKey] - containerRect[rectStartKey];
|
||||
const elementSize = element[scrollSizeKey]; // margin is exclusive in DOMRect
|
||||
|
||||
@ -153,6 +155,13 @@ function scrollWithJs(
|
||||
|
||||
// console.log('scrollWithJs: will scroll path:', path, element);
|
||||
|
||||
/* let existsTransform = 0;
|
||||
const currentTransform = transformable.style.transform;
|
||||
if(currentTransform) {
|
||||
existsTransform = parseInt(currentTransform.match(/\((.+?), (.+?), .+\)/)[2]);
|
||||
//path += existsTransform;
|
||||
} */
|
||||
|
||||
if(path < 0) {
|
||||
const remainingPath = -scrollPosition;
|
||||
path = Math.max(path, remainingPath);
|
||||
@ -167,6 +176,46 @@ function scrollWithJs(
|
||||
);
|
||||
const startAt = Date.now();
|
||||
|
||||
/* transformable.classList.add('no-transition');
|
||||
|
||||
const tickTransform = () => {
|
||||
const t = duration ? Math.min((Date.now() - startAt) / duration, 1) : 1;
|
||||
const currentPath = path * transition(t);
|
||||
|
||||
transformable.style.transform = `translate3d(0, ${-currentPath}px, 0)`;
|
||||
container.dataset.translate = '' + -currentPath;
|
||||
|
||||
const willContinue = t < 1;
|
||||
if(!willContinue) {
|
||||
fastRaf(() => {
|
||||
delete container.dataset.transform;
|
||||
container.dataset.transform = '';
|
||||
transformable.style.transform = '';
|
||||
void transformable.offsetLeft; // reflow
|
||||
transformable.classList.remove('no-transition');
|
||||
void transformable.offsetLeft; // reflow
|
||||
container[scrollPositionKey] = Math.round(target);
|
||||
});
|
||||
}
|
||||
|
||||
return willContinue;
|
||||
};
|
||||
|
||||
return animateSingle(tickTransform, container); */
|
||||
|
||||
/* return new Promise((resolve) => {
|
||||
fastRaf(() => {
|
||||
transformable.style.transform = '';
|
||||
transformable.style.transition = '';
|
||||
|
||||
setTimeout(resolve, duration);
|
||||
});
|
||||
});
|
||||
|
||||
const transformableHeight = transformable.scrollHeight;
|
||||
//transformable.style.minHeight = `${transformableHeight}px`;
|
||||
*/
|
||||
|
||||
const tick = () => {
|
||||
const t = duration ? Math.min((Date.now() - startAt) / duration, 1) : 1;
|
||||
|
||||
@ -182,6 +231,24 @@ function scrollWithJs(
|
||||
return Promise.resolve();
|
||||
}
|
||||
|
||||
/* return new Promise((resolve) => {
|
||||
setTimeout(resolve, duration);
|
||||
}).then(() => {
|
||||
transformable.classList.add('no-transition');
|
||||
void transformable.offsetLeft; // reflow
|
||||
transformable.style.transform = '';
|
||||
transformable.style.transition = '';
|
||||
void transformable.offsetLeft; // reflow
|
||||
transformable.classList.remove('no-transition');
|
||||
void transformable.offsetLeft; // reflow
|
||||
fastRaf(() => {
|
||||
|
||||
container[scrollPositionKey] = Math.round(target);
|
||||
//transformable.style.minHeight = ``;
|
||||
});
|
||||
|
||||
}); */
|
||||
|
||||
return animateSingle(tick, container);
|
||||
}
|
||||
|
||||
|
10
src/layer.d.ts
vendored
10
src/layer.d.ts
vendored
@ -831,7 +831,8 @@ export namespace Message {
|
||||
deleted?: boolean,
|
||||
peerId?: number,
|
||||
fromId?: number,
|
||||
canBeEdited?: boolean
|
||||
canBeEdited?: boolean,
|
||||
rReply?: string
|
||||
};
|
||||
|
||||
export type messageService = {
|
||||
@ -856,7 +857,8 @@ export namespace Message {
|
||||
deleted?: boolean,
|
||||
peerId?: number,
|
||||
fromId?: number,
|
||||
canBeEdited?: boolean
|
||||
canBeEdited?: boolean,
|
||||
rReply?: string
|
||||
};
|
||||
}
|
||||
|
||||
@ -4777,7 +4779,9 @@ export namespace DraftMessage {
|
||||
reply_to_msg_id?: number,
|
||||
message: string,
|
||||
entities?: Array<MessageEntity>,
|
||||
date: number
|
||||
date: number,
|
||||
rReply?: string,
|
||||
rMessage?: string
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -137,12 +137,15 @@ export class ApiUpdatesManager {
|
||||
}
|
||||
}
|
||||
|
||||
processUpdateMessage = (updateMessage: any) => {
|
||||
processUpdateMessage = (updateMessage: any, options: Partial<{
|
||||
ignoreSyncLoading: boolean
|
||||
}> = {}) => {
|
||||
// return forceGetDifference()
|
||||
var processOpts = {
|
||||
const processOpts = {
|
||||
date: updateMessage.date,
|
||||
seq: updateMessage.seq,
|
||||
seqStart: updateMessage.seq_start
|
||||
seqStart: updateMessage.seq_start,
|
||||
ignoreSyncLoading: options.ignoreSyncLoading
|
||||
};
|
||||
|
||||
switch(updateMessage._) {
|
||||
@ -389,7 +392,12 @@ export class ApiUpdatesManager {
|
||||
return this.channelStates[channelId];
|
||||
}
|
||||
|
||||
public processUpdate(update: any, options: any = {}) {
|
||||
public processUpdate(update: any, options: Partial<{
|
||||
date: number,
|
||||
seq: number,
|
||||
seqStart: number,
|
||||
ignoreSyncLoading: boolean
|
||||
}> = {}) {
|
||||
let channelId = 0;
|
||||
switch(update._) {
|
||||
case 'updateNewChannelMessage':
|
||||
@ -411,7 +419,7 @@ export class ApiUpdatesManager {
|
||||
|
||||
// this.log.log('process', channelId, curState.pts, update)
|
||||
|
||||
if(curState.syncLoading) {
|
||||
if(curState.syncLoading && !options.ignoreSyncLoading) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -557,10 +565,10 @@ export class ApiUpdatesManager {
|
||||
this.updatesState.seq = stateResult.seq;
|
||||
this.updatesState.pts = stateResult.pts;
|
||||
this.updatesState.date = stateResult.date;
|
||||
setTimeout(() => {
|
||||
//setTimeout(() => {
|
||||
this.updatesState.syncLoading = false;
|
||||
//rootScope.broadcast('state_synchronized');
|
||||
}, 1000);
|
||||
//}, 1000);
|
||||
|
||||
// ! for testing
|
||||
// updatesState.seq = 1
|
||||
|
@ -24,6 +24,7 @@ import Button from "../../components/button";
|
||||
import SetTransition from "../../components/singleTransition";
|
||||
import AppStorage from '../storage';
|
||||
import apiUpdatesManager from "./apiUpdatesManager";
|
||||
import appDraftsManager, { MyDraftMessage } from "./appDraftsManager";
|
||||
|
||||
type DialogDom = {
|
||||
avatarEl: AvatarElement,
|
||||
@ -335,6 +336,13 @@ export class AppDialogsManager {
|
||||
}
|
||||
});
|
||||
|
||||
rootScope.on('dialog_draft', (e) => {
|
||||
const dialog = appMessagesManager.getDialogByPeerId(e.peerId)[0];
|
||||
if(dialog) {
|
||||
this.updateDialog(dialog);
|
||||
}
|
||||
});
|
||||
|
||||
rootScope.on('peer_changed', (e) => {
|
||||
const peerId = e;
|
||||
|
||||
@ -458,6 +466,11 @@ export class AppDialogsManager {
|
||||
}
|
||||
});
|
||||
|
||||
if(state.dialogs?.length) {
|
||||
appDraftsManager.getAllDrafts();
|
||||
appDraftsManager.addMissedDialogs();
|
||||
}
|
||||
|
||||
return this.loadDialogs();
|
||||
}).then(() => {
|
||||
appMessagesManager.getConversationsAll('', 0).finally(() => {
|
||||
@ -903,7 +916,7 @@ export class AppDialogsManager {
|
||||
});
|
||||
}
|
||||
|
||||
public setLastMessage(dialog: any, lastMessage?: any, dom?: DialogDom, highlightWord?: string) {
|
||||
public setLastMessage(dialog: Dialog, lastMessage?: any, dom?: DialogDom, highlightWord?: string) {
|
||||
///////console.log('setlastMessage:', lastMessage);
|
||||
if(!dom) {
|
||||
dom = this.getDialogDom(dialog.peerId);
|
||||
@ -914,7 +927,12 @@ export class AppDialogsManager {
|
||||
}
|
||||
}
|
||||
|
||||
let draftMessage: MyDraftMessage;
|
||||
if(!lastMessage) {
|
||||
if(dialog.draft && dialog.draft._ === 'draftMessage') {
|
||||
draftMessage = dialog.draft;
|
||||
}
|
||||
|
||||
lastMessage = appMessagesManager.getMessageByPeer(dialog.peerId, dialog.top_message);
|
||||
}
|
||||
|
||||
@ -959,6 +977,8 @@ export class AppDialogsManager {
|
||||
});
|
||||
|
||||
dom.lastMessageSpan.innerHTML = lastMessageText + messageWrapped;
|
||||
} else if(draftMessage) {
|
||||
dom.lastMessageSpan.innerHTML = draftMessage.rReply;
|
||||
} else if(!lastMessage.deleted) {
|
||||
dom.lastMessageSpan.innerHTML = lastMessage.rReply;
|
||||
} else {
|
||||
@ -966,7 +986,12 @@ export class AppDialogsManager {
|
||||
}
|
||||
|
||||
/* if(lastMessage.from_id == auth.id) { // You: */
|
||||
if(peer._ != 'peerUser' && peerId != lastMessage.fromId && !lastMessage.action) {
|
||||
if(draftMessage) {
|
||||
const bold = document.createElement('b');
|
||||
bold.classList.add('danger');
|
||||
bold.innerHTML = 'Draft: ';
|
||||
dom.lastMessageSpan.prepend(bold);
|
||||
} else if(peer._ !== 'peerUser' && peerId !== lastMessage.fromId && !lastMessage.action) {
|
||||
const sender = appPeersManager.getPeer(lastMessage.fromId);
|
||||
if(sender && sender.id) {
|
||||
const senderBold = document.createElement('b');
|
||||
@ -987,8 +1012,9 @@ export class AppDialogsManager {
|
||||
}
|
||||
}
|
||||
|
||||
if(!lastMessage.deleted) {
|
||||
dom.lastTimeSpan.innerHTML = formatDateAccordingToToday(new Date(lastMessage.date * 1000));
|
||||
if(!lastMessage.deleted || draftMessage/* && lastMessage._ !== 'draftMessage' */) {
|
||||
const date = draftMessage ? Math.max(draftMessage.date, lastMessage.date || 0) : lastMessage.date;
|
||||
dom.lastTimeSpan.innerHTML = formatDateAccordingToToday(new Date(date * 1000));
|
||||
} else dom.lastTimeSpan.innerHTML = '';
|
||||
|
||||
if(this.doms[peerId] == dom) {
|
||||
@ -1024,7 +1050,9 @@ export class AppDialogsManager {
|
||||
dom.listEl.classList.toggle('is-muted', isMuted);
|
||||
}
|
||||
|
||||
const lastMessage = appMessagesManager.getMessageByPeer(dialog.peerId, dialog.top_message);
|
||||
const lastMessage = dialog.draft && dialog.draft._ === 'draftMessage' ?
|
||||
dialog.draft :
|
||||
appMessagesManager.getMessageByPeer(dialog.peerId, dialog.top_message);
|
||||
if(lastMessage._ != 'messageEmpty' && !lastMessage.deleted &&
|
||||
lastMessage.fromId == rootScope.myId && lastMessage.peerId != rootScope.myId/* &&
|
||||
dialog.read_outbox_max_id */) { // maybe comment, 06.20.2020
|
||||
|
187
src/lib/appManagers/appDraftsManager.ts
Normal file
187
src/lib/appManagers/appDraftsManager.ts
Normal file
@ -0,0 +1,187 @@
|
||||
import { MOUNT_CLASS_TO } from "../mtproto/mtproto_config";
|
||||
import rootScope from "../rootScope";
|
||||
import appPeersManager from "./appPeersManager";
|
||||
import appMessagesManager from "./appMessagesManager";
|
||||
import apiUpdatesManager from "./apiUpdatesManager";
|
||||
import RichTextProcessor from "../richtextprocessor";
|
||||
import serverTimeManager from "../mtproto/serverTimeManager";
|
||||
import { MessageEntity, DraftMessage, MessagesSaveDraft } from "../../layer";
|
||||
import apiManager from "../mtproto/mtprotoworker";
|
||||
import { tsNow } from "../../helpers/date";
|
||||
import { deepEqual } from "../../helpers/object";
|
||||
import appStateManager from "./appStateManager";
|
||||
|
||||
export type MyDraftMessage = DraftMessage.draftMessage;
|
||||
|
||||
export class AppDraftsManager {
|
||||
private drafts: {[peerIdAndThreadId: string]: MyDraftMessage} = {};
|
||||
private getAllDraftPromise: Promise<void> = null;
|
||||
|
||||
constructor() {
|
||||
appStateManager.getState().then(state => {
|
||||
this.drafts = state.drafts;
|
||||
});
|
||||
|
||||
appStateManager.addListener('save', async() => {
|
||||
appStateManager.pushToState('drafts', this.drafts);
|
||||
});
|
||||
|
||||
rootScope.on('apiUpdate', (update) => {
|
||||
if(update._ !== 'updateDraftMessage') {
|
||||
return
|
||||
}
|
||||
|
||||
const peerID = appPeersManager.getPeerId(update.peer);
|
||||
this.saveDraft(peerID, (update as any).threadId, update.draft, {notify: true});
|
||||
});
|
||||
}
|
||||
|
||||
private getKey(peerId: number, threadId?: number) {
|
||||
return '' + peerId + (threadId ? '_' + threadId : '');
|
||||
}
|
||||
|
||||
public getDraft(peerId: number, threadId?: number) {
|
||||
return this.drafts[this.getKey(peerId, threadId)];
|
||||
}
|
||||
|
||||
public addMissedDialogs() {
|
||||
return this.getAllDrafts().then(() => {
|
||||
for(const key in this.drafts) {
|
||||
if(key.indexOf('_') !== -1) { // exclude threads
|
||||
continue;
|
||||
}
|
||||
|
||||
const peerId = +key;
|
||||
const dialog = appMessagesManager.getDialogByPeerId(peerId)[0];
|
||||
if(!dialog) {
|
||||
appMessagesManager.reloadConversation(peerId);
|
||||
/* const dialog = appMessagesManager.generateDialog(peerId);
|
||||
dialog.draft = this.drafts[key];
|
||||
appMessagesManager.saveConversation(dialog);
|
||||
appMessagesManager.newDialogsToHandle[peerId] = dialog;
|
||||
appMessagesManager.scheduleHandleNewDialogs(); */
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public getAllDrafts() {
|
||||
return this.getAllDraftPromise || (this.getAllDraftPromise = new Promise((resolve) => {
|
||||
apiManager.invokeApi('messages.getAllDrafts').then((updates) => {
|
||||
apiUpdatesManager.processUpdateMessage(updates, {ignoreSyncLoading: true});
|
||||
resolve();
|
||||
});
|
||||
}));
|
||||
}
|
||||
|
||||
public saveDraft(peerId: number, threadId: number, apiDraft: DraftMessage, options: Partial<{
|
||||
notify: boolean
|
||||
}> = {}) {
|
||||
const draft = this.processApiDraft(apiDraft);
|
||||
|
||||
const key = this.getKey(peerId, threadId);
|
||||
if(draft) {
|
||||
this.drafts[key] = draft;
|
||||
} else {
|
||||
delete this.drafts[key];
|
||||
}
|
||||
|
||||
if(options.notify) {
|
||||
// console.warn(dT(), 'save draft', peerId, apiDraft, options)
|
||||
rootScope.broadcast('draft_updated', {
|
||||
peerId,
|
||||
threadId,
|
||||
draft
|
||||
});
|
||||
}
|
||||
|
||||
return draft;
|
||||
}
|
||||
|
||||
public draftsAreEqual(draft1: DraftMessage, draft2: DraftMessage) {
|
||||
return deepEqual(draft1, draft2);
|
||||
}
|
||||
|
||||
public isEmptyDraft(draft: DraftMessage) {
|
||||
if(!draft || draft._ === 'draftMessageEmpty') {
|
||||
return true;
|
||||
}
|
||||
|
||||
if(draft.reply_to_msg_id > 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if(!draft.message.length) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public processApiDraft(draft: DraftMessage): MyDraftMessage {
|
||||
if(!draft || draft._ !== 'draftMessage') {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
const myEntities = RichTextProcessor.parseEntities(draft.message);
|
||||
const apiEntities = draft.entities || [];
|
||||
const totalEntities = RichTextProcessor.mergeEntities(apiEntities, myEntities); // ! only in this order, otherwise bold and emoji formatting won't work
|
||||
|
||||
draft.rMessage = RichTextProcessor.wrapDraftText(draft.message, {entities: totalEntities});
|
||||
draft.rReply = appMessagesManager.getRichReplyText(draft);
|
||||
if(draft.reply_to_msg_id) {
|
||||
draft.reply_to_msg_id = appMessagesManager.generateMessageId(draft.reply_to_msg_id);
|
||||
}
|
||||
|
||||
return draft;
|
||||
}
|
||||
|
||||
public syncDraft(peerId: number, threadId: number, localDraft?: MyDraftMessage, saveOnServer = true) {
|
||||
// console.warn(dT(), 'sync draft', peerID)
|
||||
const serverDraft = this.getDraft(peerId, threadId);
|
||||
if(this.draftsAreEqual(serverDraft, localDraft)) {
|
||||
// console.warn(dT(), 'equal drafts', localDraft, serverDraft)
|
||||
return;
|
||||
}
|
||||
|
||||
// console.warn(dT(), 'changed draft', localDraft, serverDraft)
|
||||
let params: MessagesSaveDraft = {
|
||||
peer: appPeersManager.getInputPeerById(peerId),
|
||||
message: ''
|
||||
};
|
||||
|
||||
let draftObj: DraftMessage;
|
||||
if(this.isEmptyDraft(localDraft)) {
|
||||
draftObj = {_: 'draftMessageEmpty'};
|
||||
} else {
|
||||
draftObj = {_: 'draftMessage'} as any as DraftMessage.draftMessage;
|
||||
let message = localDraft.message;
|
||||
let entities: MessageEntity[] = [];
|
||||
//message = RichTextProcessor.parseEmojis(message);
|
||||
//message = RichTextProcessor.parseMarkdown(message, entities, true);
|
||||
|
||||
if(localDraft.reply_to_msg_id) {
|
||||
params.reply_to_msg_id = draftObj.reply_to_msg_id = localDraft.reply_to_msg_id;
|
||||
}
|
||||
|
||||
if(entities.length) {
|
||||
params.entities = draftObj.entities = entities;
|
||||
}
|
||||
|
||||
params.message = draftObj.message = message;
|
||||
}
|
||||
|
||||
draftObj.date = tsNow(true) + serverTimeManager.serverTimeOffset;
|
||||
this.saveDraft(peerId, threadId, draftObj, {notify: true});
|
||||
|
||||
if(saveOnServer && !threadId) {
|
||||
apiManager.invokeApi('messages.saveDraft', params).then(() => {
|
||||
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const appDraftsManager = new AppDraftsManager();
|
||||
MOUNT_CLASS_TO && (MOUNT_CLASS_TO.appDraftsManager = appDraftsManager);
|
||||
export default appDraftsManager;
|
@ -30,6 +30,8 @@ import ChatDragAndDrop from '../../components/chat/dragAndDrop';
|
||||
import { debounce } from '../../helpers/schedulers';
|
||||
import lottieLoader from '../lottieLoader';
|
||||
import useHeavyAnimationCheck from '../../hooks/useHeavyAnimationCheck';
|
||||
import appDraftsManager from './appDraftsManager';
|
||||
import serverTimeManager from '../mtproto/serverTimeManager';
|
||||
|
||||
//console.log('appImManager included33!');
|
||||
|
||||
@ -450,7 +452,7 @@ export class AppImManager {
|
||||
}
|
||||
|
||||
private createNewChat() {
|
||||
const chat = new Chat(this, appChatsManager, appDocsManager, appInlineBotsManager, appMessagesManager, appPeersManager, appPhotosManager, appProfileManager, appStickersManager, appUsersManager, appWebPagesManager, appPollsManager, apiManager);
|
||||
const chat = new Chat(this, appChatsManager, appDocsManager, appInlineBotsManager, appMessagesManager, appPeersManager, appPhotosManager, appProfileManager, appStickersManager, appUsersManager, appWebPagesManager, appPollsManager, apiManager, appDraftsManager, serverTimeManager);
|
||||
|
||||
this.chats.push(chat);
|
||||
}
|
||||
@ -458,6 +460,10 @@ export class AppImManager {
|
||||
private spliceChats(fromIndex: number, justReturn = true) {
|
||||
if(fromIndex >= this.chats.length) return;
|
||||
|
||||
if(this.chats.length > 1 && justReturn) {
|
||||
rootScope.broadcast('peer_changing', this.chat);
|
||||
}
|
||||
|
||||
const spliced = this.chats.splice(fromIndex, this.chats.length - fromIndex);
|
||||
|
||||
// * fix middle chat z-index on animation
|
||||
@ -561,7 +567,7 @@ export class AppImManager {
|
||||
|
||||
public setInnerPeer(peerId: number, lastMsgId?: number, type: ChatType = 'chat', threadId?: number) {
|
||||
// * prevent opening already opened peer
|
||||
const existingIndex = this.chats.findIndex(chat => chat.peerId == peerId && chat.type == type);
|
||||
const existingIndex = this.chats.findIndex(chat => chat.peerId === peerId && chat.type === type);
|
||||
if(existingIndex !== -1) {
|
||||
this.spliceChats(existingIndex + 1);
|
||||
return this.setPeer(peerId, lastMsgId);
|
||||
|
@ -24,7 +24,7 @@ import DialogsStorage from "../storages/dialogs";
|
||||
import FiltersStorage from "../storages/filters";
|
||||
//import { telegramMeWebService } from "../mtproto/mtproto";
|
||||
import apiUpdatesManager from "./apiUpdatesManager";
|
||||
import appChatsManager from "./appChatsManager";
|
||||
import appChatsManager, { Channel } from "./appChatsManager";
|
||||
import appDocsManager, { MyDocument } from "./appDocsManager";
|
||||
import appDownloadManager from "./appDownloadManager";
|
||||
import appPeersManager from "./appPeersManager";
|
||||
@ -33,6 +33,7 @@ import appPollsManager from "./appPollsManager";
|
||||
import appStateManager from "./appStateManager";
|
||||
import appUsersManager from "./appUsersManager";
|
||||
import appWebPagesManager from "./appWebPagesManager";
|
||||
import appDraftsManager from "./appDraftsManager";
|
||||
|
||||
//console.trace('include');
|
||||
// TODO: если удалить сообщение в непрогруженном диалоге, то при обновлении, из-за стейта, последнего сообщения в чатлисте не будет
|
||||
@ -201,41 +202,26 @@ export class AppMessagesManager {
|
||||
});
|
||||
});
|
||||
|
||||
/* rootScope.$on('draft_updated', (e) => {
|
||||
let eventData = e;;
|
||||
var peerId = eventData.peerId;
|
||||
var draft = eventData.draft;
|
||||
rootScope.on('draft_updated', (e) => {
|
||||
const {peerId, threadId, draft} = e;
|
||||
|
||||
var dialog = this.getDialogByPeerID(peerId)[0];
|
||||
if(dialog) {
|
||||
var topDate;
|
||||
if(draft && draft.date) {
|
||||
topDate = draft.date;
|
||||
} else {
|
||||
var channelId = appPeersManager.isChannel(peerId) ? -peerId : 0
|
||||
var topDate = this.getMessage(dialog.top_message).date;
|
||||
|
||||
if(channelId) {
|
||||
var channel = appChatsManager.getChat(channelId);
|
||||
if(!topDate || channel.date && channel.date > topDate) {
|
||||
topDate = channel.date;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(!dialog.pFlags.pinned) {
|
||||
dialog.index = this.dialogsStorage.generateDialogIndex(topDate);
|
||||
}
|
||||
if(threadId) return;
|
||||
|
||||
const dialog = this.getDialogByPeerId(peerId)[0];
|
||||
if(dialog && !threadId) {
|
||||
dialog.draft = draft;
|
||||
this.dialogsStorage.generateIndexForDialog(dialog);
|
||||
this.dialogsStorage.pushDialog(dialog);
|
||||
|
||||
rootScope.$broadcast('dialog_draft', {
|
||||
rootScope.broadcast('dialog_draft', {
|
||||
peerId,
|
||||
draft,
|
||||
index: dialog.index
|
||||
});
|
||||
} else {
|
||||
this.reloadConversation(peerId);
|
||||
}
|
||||
}); */
|
||||
});
|
||||
|
||||
function timedChunk(items: any[], process: (...args: any[]) => any, context: any, callback: (...args: any[]) => void) {
|
||||
if(!items.length) return callback(items);
|
||||
@ -278,7 +264,7 @@ export class AppMessagesManager {
|
||||
}
|
||||
|
||||
dialog.top_message = message.mid;
|
||||
this.setDialogIndexByMessage(dialog, message);
|
||||
this.dialogsStorage.generateIndexForDialog(dialog, false, message);
|
||||
|
||||
break;
|
||||
} else if(message.pFlags && message.pFlags.unread) {
|
||||
@ -602,7 +588,11 @@ export class AppMessagesManager {
|
||||
this.pendingAfterMsgs[peerId] = sentRequestOptions;
|
||||
}
|
||||
|
||||
this.beforeMessageSending(message, {isScheduled: !!options.scheduleDate || undefined, threadId: options.threadId});
|
||||
this.beforeMessageSending(message, {
|
||||
isScheduled: !!options.scheduleDate || undefined,
|
||||
threadId: options.threadId,
|
||||
clearDraft: options.clearDraft
|
||||
});
|
||||
}
|
||||
|
||||
public sendFile(peerId: number, file: File | Blob | MyDocument, options: Partial<{
|
||||
@ -623,6 +613,7 @@ export class AppMessagesManager {
|
||||
duration: number,
|
||||
background: true,
|
||||
silent: true,
|
||||
clearDraft: true,
|
||||
scheduleDate: number,
|
||||
|
||||
waveform: Uint8Array
|
||||
@ -957,7 +948,12 @@ export class AppMessagesManager {
|
||||
return sentDeferred;
|
||||
};
|
||||
|
||||
this.beforeMessageSending(message, {isGroupedItem: options.isGroupedItem, isScheduled: !!options.scheduleDate || undefined, threadId: options.threadId});
|
||||
this.beforeMessageSending(message, {
|
||||
isGroupedItem: options.isGroupedItem,
|
||||
isScheduled: !!options.scheduleDate || undefined,
|
||||
threadId: options.threadId,
|
||||
clearDraft: options.clearDraft
|
||||
});
|
||||
|
||||
if(!options.isGroupedItem) {
|
||||
sentDeferred.then(inputMedia => {
|
||||
@ -972,7 +968,8 @@ export class AppMessagesManager {
|
||||
reply_to_msg_id: replyToMsgId,
|
||||
schedule_date: options.scheduleDate,
|
||||
silent: options.silent,
|
||||
entities
|
||||
entities,
|
||||
clear_draft: options.clearDraft
|
||||
}).then((updates) => {
|
||||
apiUpdatesManager.processUpdateMessage(updates);
|
||||
}, (error) => {
|
||||
@ -1009,6 +1006,7 @@ export class AppMessagesManager {
|
||||
thumbURL: string
|
||||
}>[],
|
||||
silent: true,
|
||||
clearDraft: true,
|
||||
scheduleDate: number
|
||||
}> = {}) {
|
||||
//this.checkSendOptions(options);
|
||||
@ -1066,6 +1064,10 @@ export class AppMessagesManager {
|
||||
this.setDialogTopMessage(message);
|
||||
}
|
||||
|
||||
if(options.clearDraft) {
|
||||
appDraftsManager.syncDraft(peerId, options.threadId);
|
||||
}
|
||||
|
||||
// * test pending
|
||||
//return;
|
||||
|
||||
@ -1090,7 +1092,8 @@ export class AppMessagesManager {
|
||||
multi_media: multiMedia,
|
||||
reply_to_msg_id: replyToMsgId,
|
||||
schedule_date: options.scheduleDate,
|
||||
silent: options.silent
|
||||
silent: options.silent,
|
||||
clear_draft: options.clearDraft
|
||||
}).then((updates) => {
|
||||
apiUpdatesManager.processUpdateMessage(updates);
|
||||
}, (error) => {
|
||||
@ -1332,7 +1335,11 @@ export class AppMessagesManager {
|
||||
this.pendingAfterMsgs[peerId] = sentRequestOptions;
|
||||
}
|
||||
|
||||
this.beforeMessageSending(message, {isScheduled: !!options.scheduleDate || undefined, threadId: options.threadId});
|
||||
this.beforeMessageSending(message, {
|
||||
isScheduled: !!options.scheduleDate || undefined,
|
||||
threadId: options.threadId,
|
||||
clearDraft: options.clearDraft
|
||||
});
|
||||
}
|
||||
|
||||
/* private checkSendOptions(options: Partial<{
|
||||
@ -1346,7 +1353,12 @@ export class AppMessagesManager {
|
||||
}
|
||||
} */
|
||||
|
||||
private beforeMessageSending(message: any, options: Partial<{isGroupedItem: true, isScheduled: true, threadId: number}> = {}) {
|
||||
private beforeMessageSending(message: any, options: Partial<{
|
||||
isGroupedItem: true,
|
||||
isScheduled: true,
|
||||
threadId: number,
|
||||
clearDraft: true
|
||||
}> = {}) {
|
||||
const messageId = message.id;
|
||||
const peerId = this.getMessagePeer(message);
|
||||
const storage = options.isScheduled ? this.getScheduledMessagesStorage(peerId) : this.getMessagesStorage(peerId);
|
||||
@ -1376,6 +1388,10 @@ export class AppMessagesManager {
|
||||
}
|
||||
}
|
||||
|
||||
if(!options.isGroupedItem && options.clearDraft && !options.threadId) {
|
||||
appDraftsManager.syncDraft(peerId, options.threadId);
|
||||
}
|
||||
|
||||
this.pendingByRandomId[message.random_id] = {peerId, tempId: messageId, storage};
|
||||
|
||||
if(!options.isGroupedItem) {
|
||||
@ -1427,12 +1443,6 @@ export class AppMessagesManager {
|
||||
return pFlags;
|
||||
}
|
||||
|
||||
private setDialogIndexByMessage(dialog: MTDialog.dialog, message: MyMessage) {
|
||||
if(!dialog.pFlags.pinned || !dialog.index) {
|
||||
dialog.index = this.dialogsStorage.generateDialogIndex(message.date);
|
||||
}
|
||||
}
|
||||
|
||||
public setDialogTopMessage(message: MyMessage, dialog: MTDialog.dialog = this.getDialogByPeerId(message.peerId)[0]) {
|
||||
if(dialog) {
|
||||
dialog.top_message = message.mid;
|
||||
@ -1440,7 +1450,7 @@ export class AppMessagesManager {
|
||||
const historyStorage = this.getHistoryStorage(message.peerId);
|
||||
historyStorage.maxId = message.mid;
|
||||
|
||||
this.setDialogIndexByMessage(dialog, message);
|
||||
this.dialogsStorage.generateIndexForDialog(dialog, false, message);
|
||||
|
||||
this.newDialogsToHandle[message.peerId] = dialog;
|
||||
this.scheduleHandleNewDialogs();
|
||||
@ -1587,28 +1597,16 @@ export class AppMessagesManager {
|
||||
let offsetDate = 0;
|
||||
let offsetPeerId = 0;
|
||||
let offsetIndex = 0;
|
||||
let flags = 0;
|
||||
|
||||
if(this.dialogsStorage.dialogsOffsetDate[folderId]) {
|
||||
offsetDate = this.dialogsStorage.dialogsOffsetDate[folderId] + serverTimeManager.serverTimeOffset;
|
||||
offsetIndex = this.dialogsStorage.dialogsOffsetDate[folderId] * 0x10000;
|
||||
//flags |= 1; // means pinned already loaded
|
||||
}
|
||||
|
||||
/* if(this.dialogsStorage.dialogsOffsetDate[0]) {
|
||||
flags |= 1; // means pinned already loaded
|
||||
} */
|
||||
|
||||
//if(folderId > 0) {
|
||||
//flags |= 1;
|
||||
flags |= 2;
|
||||
//}
|
||||
|
||||
// ! ВНИМАНИЕ: ОЧЕНЬ СЛОЖНАЯ ЛОГИКА:
|
||||
// ! если делать запрос сначала по папке 0, потом по папке 1, по индексу 0 в массиве будет один и тот же диалог, с dialog.pFlags.pinned, ЛОЛ???
|
||||
// ! т.е., с запросом folder_id: 1, и exclude_pinned: 0, в результате будут ещё и закреплённые с папки 0
|
||||
return apiManager.invokeApi('messages.getDialogs', {
|
||||
flags,
|
||||
folder_id: folderId,
|
||||
offset_date: offsetDate,
|
||||
offset_id: offsetId,
|
||||
@ -1621,7 +1619,9 @@ export class AppMessagesManager {
|
||||
}).then((dialogsResult) => {
|
||||
if(dialogsResult._ == 'messages.dialogsNotModified') return null;
|
||||
|
||||
//this.log.error('messages.getDialogs result:', dialogsResult.dialogs, {...dialogsResult.dialogs[0]});
|
||||
if(DEBUG) {
|
||||
this.log('messages.getDialogs result:', dialogsResult.dialogs, {...dialogsResult.dialogs[0]});
|
||||
}
|
||||
|
||||
/* if(!offsetDate) {
|
||||
telegramMeWebService.setAuthorized(true);
|
||||
@ -2659,7 +2659,7 @@ export class AppMessagesManager {
|
||||
appChatsManager.saveApiChats(dialogsResult.chats);
|
||||
this.saveMessages(dialogsResult.messages);
|
||||
|
||||
//this.log('applyConversation', dialogsResult);
|
||||
this.log('applyConversation', dialogsResult);
|
||||
|
||||
const updatedDialogs: {[peerId: number]: Dialog} = {};
|
||||
(dialogsResult.dialogs as Dialog[]).forEach((dialog) => {
|
||||
@ -2679,7 +2679,7 @@ export class AppMessagesManager {
|
||||
this.log.error('applyConversation lun', dialog, d);
|
||||
} */
|
||||
|
||||
if(topMessage) {
|
||||
if(topMessage || (dialog.draft && dialog.draft._ === 'draftMessage')) {
|
||||
//const wasDialogBefore = this.getDialogByPeerID(peerId)[0];
|
||||
|
||||
// here need to just replace, not FULL replace dialog! WARNING
|
||||
@ -2720,6 +2720,24 @@ export class AppMessagesManager {
|
||||
}
|
||||
}
|
||||
|
||||
public generateDialog(peerId: number) {
|
||||
const dialog: Dialog = {
|
||||
_: 'dialog',
|
||||
pFlags: {},
|
||||
peer: appPeersManager.getOutputPeer(peerId),
|
||||
top_message: 0,
|
||||
read_inbox_max_id: 0,
|
||||
read_outbox_max_id: 0,
|
||||
unread_count: 0,
|
||||
unread_mentions_count: 0,
|
||||
notify_settings: {
|
||||
_: 'peerNotifySettings',
|
||||
},
|
||||
};
|
||||
|
||||
return dialog;
|
||||
}
|
||||
|
||||
public saveConversation(dialog: Dialog, folderId = 0) {
|
||||
const peerId = appPeersManager.getPeerId(dialog.peer);
|
||||
if(!peerId) {
|
||||
@ -2743,7 +2761,7 @@ export class AppMessagesManager {
|
||||
message = {
|
||||
_: 'message',
|
||||
id: mid,
|
||||
mid: mid,
|
||||
mid,
|
||||
from_id: appPeersManager.getOutputPeer(appUsersManager.getSelf().id),
|
||||
peer_id: appPeersManager.getOutputPeer(peerId),
|
||||
deleted: true,
|
||||
@ -2783,6 +2801,7 @@ export class AppMessagesManager {
|
||||
} */
|
||||
}
|
||||
|
||||
dialog.draft = appDraftsManager.saveDraft(peerId, 0, dialog.draft);
|
||||
dialog.peerId = peerId;
|
||||
|
||||
// Because we saved message without dialog present
|
||||
@ -4717,9 +4736,9 @@ export class AppMessagesManager {
|
||||
}
|
||||
|
||||
public setTyping(peerId: number, _action: any): Promise<boolean> {
|
||||
if(!rootScope.myId || !peerId || !this.canWriteToPeer(peerId)) return Promise.resolve(false);
|
||||
if(!rootScope.myId || !peerId || !this.canWriteToPeer(peerId) || peerId === rootScope.myId) return Promise.resolve(false);
|
||||
|
||||
const action: SendMessageAction = typeof(_action) == 'string' ? {_: _action} : _action;
|
||||
const action: SendMessageAction = typeof(_action) === 'string' ? {_: _action} : _action;
|
||||
return apiManager.invokeApi('messages.setTyping', {
|
||||
peer: appPeersManager.getInputPeerById(peerId),
|
||||
action
|
||||
|
@ -11,6 +11,7 @@ import type { AuthState } from '../../types';
|
||||
import type FiltersStorage from '../storages/filters';
|
||||
import type DialogsStorage from '../storages/dialogs';
|
||||
import { copy, setDeepProperty, isObject, validateInitObject } from '../../helpers/object';
|
||||
import { AppDraftsManager } from './appDraftsManager';
|
||||
|
||||
const REFRESH_EVERY = 24 * 60 * 60 * 1000; // 1 day
|
||||
const STATE_VERSION = App.version;
|
||||
@ -55,7 +56,8 @@ export type State = Partial<{
|
||||
suggest: boolean,
|
||||
loop: boolean
|
||||
}
|
||||
}
|
||||
},
|
||||
drafts: AppDraftsManager['drafts']
|
||||
}>;
|
||||
|
||||
const STATE_INIT: State = {
|
||||
@ -96,7 +98,8 @@ const STATE_INIT: State = {
|
||||
suggest: true,
|
||||
loop: true
|
||||
}
|
||||
}
|
||||
},
|
||||
drafts: {}
|
||||
};
|
||||
|
||||
const ALL_KEYS = Object.keys(STATE_INIT) as any as Array<keyof State>;
|
||||
|
@ -9,7 +9,7 @@ export const langPack: {[actionType: string]: string} = {
|
||||
"messageActionChatAddUsers": "invited {} users",
|
||||
"messageActionChatLeave": "left the group",
|
||||
"messageActionChatDeleteUser": "removed user {}",
|
||||
"messageActionChatJoinedByLink": "joined the group",
|
||||
"messageActionChatJoinedByLink": "joined the group via invite link",
|
||||
"messageActionPinMessage": "pinned message",
|
||||
"messageActionContactSignUp": "joined Telegram",
|
||||
"messageActionChannelCreate": "Channel created",
|
||||
|
@ -56,8 +56,8 @@ export const isWebpSupported = () => {
|
||||
return webpSupported;
|
||||
};
|
||||
|
||||
networkerFactory.setUpdatesProcessor((obj, bool) => {
|
||||
respond({update: {obj, bool}});
|
||||
networkerFactory.setUpdatesProcessor((obj) => {
|
||||
respond({update: obj});
|
||||
});
|
||||
|
||||
networkerFactory.onConnectionStatusChange = (status) => {
|
||||
|
@ -46,7 +46,7 @@ export class ApiManagerProxy extends CryptoWorkerMethods {
|
||||
} = {} as any;
|
||||
private pending: Array<Task> = [];
|
||||
|
||||
public updatesProcessor: (obj: any, bool: boolean) => void = null;
|
||||
public updatesProcessor: (obj: any) => void = null;
|
||||
|
||||
private log = logger('API-PROXY');
|
||||
|
||||
@ -134,7 +134,7 @@ export class ApiManagerProxy extends CryptoWorkerMethods {
|
||||
|
||||
if(task.update) {
|
||||
if(this.updatesProcessor) {
|
||||
this.updatesProcessor(task.update.obj, task.update.bool);
|
||||
this.updatesProcessor(task.update);
|
||||
}
|
||||
} else if(task.progress) {
|
||||
rootScope.broadcast('download_progress', task.progress);
|
||||
@ -218,7 +218,7 @@ export class ApiManagerProxy extends CryptoWorkerMethods {
|
||||
}
|
||||
}
|
||||
|
||||
public setUpdatesProcessor(callback: (obj: any, bool: boolean) => void) {
|
||||
public setUpdatesProcessor(callback: (obj: any) => void) {
|
||||
this.updatesProcessor = callback;
|
||||
}
|
||||
|
||||
|
@ -1262,7 +1262,7 @@ export default class MTPNetworker {
|
||||
|
||||
AppStorage.get<number>('dc').then((baseDcId: number) => {
|
||||
if(baseDcId == this.dcId && !this.isFileNetworker && NetworkerFactory.updatesProcessor) {
|
||||
NetworkerFactory.updatesProcessor(message, true);
|
||||
NetworkerFactory.updatesProcessor(message);
|
||||
}
|
||||
});
|
||||
break;
|
||||
@ -1360,7 +1360,7 @@ export default class MTPNetworker {
|
||||
this.log.debug('Update', message);
|
||||
|
||||
if(NetworkerFactory.updatesProcessor !== null) {
|
||||
NetworkerFactory.updatesProcessor(message, true);
|
||||
NetworkerFactory.updatesProcessor(message);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
@ -3,10 +3,10 @@ import { ConnectionStatusChange, InvokeApiOptions } from "../../types";
|
||||
import MTTransport from "./transports/transport";
|
||||
|
||||
export class NetworkerFactory {
|
||||
public updatesProcessor: (obj: any, bool: boolean) => void = null;
|
||||
public updatesProcessor: (obj: any) => void = null;
|
||||
public onConnectionStatusChange: (info: ConnectionStatusChange) => void = null;
|
||||
|
||||
public setUpdatesProcessor(callback: (obj: any, bool: boolean) => void) {
|
||||
public setUpdatesProcessor(callback: (obj: any) => void) {
|
||||
this.updatesProcessor = callback;
|
||||
}
|
||||
|
||||
|
@ -5,14 +5,17 @@ import type { Poll, PollResults } from "./appManagers/appPollsManager";
|
||||
import type { MyDialogFilter } from "./storages/filters";
|
||||
import type { ConnectionStatusChange } from "../types";
|
||||
import type { UserTyping } from "./appManagers/appChatsManager";
|
||||
import type Chat from "../components/chat/chat";
|
||||
import { DEBUG, MOUNT_CLASS_TO, UserAuth } from "./mtproto/mtproto_config";
|
||||
import { State } from "./appManagers/appStateManager";
|
||||
import EventListenerBase from "../helpers/eventListenerBase";
|
||||
import { MyDraftMessage } from "./appManagers/appDraftsManager";
|
||||
|
||||
type BroadcastEvents = {
|
||||
'user_update': number,
|
||||
'user_auth': UserAuth,
|
||||
'peer_changed': number,
|
||||
'peer_changing': Chat,
|
||||
'peer_pinned_messages': {peerId: number, mids?: number[], pinned?: boolean, unpinAll?: true},
|
||||
'peer_pinned_hidden': {peerId: number, maxId: number},
|
||||
'peer_typings': {peerId: number, typings: UserTyping[]},
|
||||
@ -21,7 +24,7 @@ type BroadcastEvents = {
|
||||
'filter_update': MyDialogFilter,
|
||||
'filter_order': number[],
|
||||
|
||||
'dialog_draft': {peerId: number, draft: any, index: number},
|
||||
'dialog_draft': {peerId: number, draft: MyDraftMessage | undefined, index: number},
|
||||
'dialog_unread': {peerId: number},
|
||||
'dialog_flush': {peerId: number},
|
||||
'dialog_drop': {peerId: number, dialog?: Dialog},
|
||||
@ -76,7 +79,7 @@ type BroadcastEvents = {
|
||||
'download_progress': any,
|
||||
'connection_status_change': ConnectionStatusChange,
|
||||
'settings_updated': {key: string, value: any},
|
||||
//'draft_updated': any,
|
||||
'draft_updated': {peerId: number, threadId: number, draft: MyDraftMessage | undefined},
|
||||
|
||||
'event-heavy-animation-start': void,
|
||||
'event-heavy-animation-end': void
|
||||
|
@ -1,7 +1,7 @@
|
||||
import { tsNow } from "../../helpers/date";
|
||||
import type { Message } from "../../layer";
|
||||
import type { AppChatsManager } from "../appManagers/appChatsManager";
|
||||
import type { AppMessagesManager, Dialog } from "../appManagers/appMessagesManager";
|
||||
import type { AppMessagesManager, Dialog, MyMessage } from "../appManagers/appMessagesManager";
|
||||
import type { AppPeersManager } from "../appManagers/appPeersManager";
|
||||
import type { ServerTimeManager } from "../mtproto/serverTimeManager";
|
||||
|
||||
@ -89,27 +89,32 @@ export default class DialogsStorage {
|
||||
return (date * 0x10000) + ((++this.dialogsNum) & 0xFFFF);
|
||||
}
|
||||
|
||||
public generateIndexForDialog(dialog: Dialog, justReturn = false) {
|
||||
public generateIndexForDialog(dialog: Dialog, justReturn = false, message?: MyMessage) {
|
||||
const channelId = this.appPeersManager.isChannel(dialog.peerId) ? -dialog.peerId : 0;
|
||||
const mid = dialog.top_message;
|
||||
const message = this.appMessagesManager.getMessageByPeer(dialog.peerId, mid);
|
||||
|
||||
let topDate = (message as Message.message).date || Date.now() / 1000;
|
||||
let topDate = 0;
|
||||
if(dialog.pFlags.pinned && !justReturn) {
|
||||
topDate = this.generateDialogPinnedDate(dialog);
|
||||
} else {
|
||||
if(!message) {
|
||||
message = this.appMessagesManager.getMessageByPeer(dialog.peerId, dialog.top_message);
|
||||
}
|
||||
|
||||
topDate = (message as Message.message).date || topDate;
|
||||
if(channelId) {
|
||||
const channel = this.appChatsManager.getChat(channelId);
|
||||
if(!topDate || channel.date && channel.date > topDate) {
|
||||
if(!topDate || (channel.date && channel.date > topDate)) {
|
||||
topDate = channel.date;
|
||||
}
|
||||
}
|
||||
|
||||
const savedDraft: any = {};// DraftsManager.saveDraft(peerId, dialog.draft); // warning
|
||||
if(savedDraft && savedDraft.date > topDate) {
|
||||
topDate = savedDraft.date;
|
||||
if(dialog.draft && dialog.draft._ === 'draftMessage' && dialog.draft.date > topDate) {
|
||||
topDate = dialog.draft.date;
|
||||
}
|
||||
}
|
||||
|
||||
if(dialog.pFlags.pinned && !justReturn) {
|
||||
topDate = this.generateDialogPinnedDate(dialog);
|
||||
//this.log('topDate', peerId, topDate);
|
||||
if(!topDate) {
|
||||
topDate = Date.now() / 1000;
|
||||
}
|
||||
|
||||
const index = this.generateDialogIndex(topDate);
|
||||
|
@ -255,4 +255,6 @@ for(const method in methodsMap) {
|
||||
out += `}\n\n`;
|
||||
|
||||
const path = process.argv[2];
|
||||
require('fs').writeFileSync((path || __dirname + '/out/') + 'layer.d.ts', out);
|
||||
const writePathTo = (path || __dirname + '/out/') + 'layer.d.ts';
|
||||
console.log('Writing layer to:', writePathTo);
|
||||
require('fs').writeFileSync(writePathTo, out);
|
@ -70,7 +70,8 @@
|
||||
{"name": "fromId", "type": "number"},
|
||||
{"name": "grouped_id", "type": "string"},
|
||||
{"name": "canBeEdited", "type": "boolean"},
|
||||
{"name": "unread", "type": "true"}
|
||||
{"name": "unread", "type": "true"},
|
||||
{"name": "rReply", "type": "string"}
|
||||
]
|
||||
}, {
|
||||
"predicate": "messageService",
|
||||
@ -80,7 +81,8 @@
|
||||
{"name": "peerId", "type": "number"},
|
||||
{"name": "fromId", "type": "number"},
|
||||
{"name": "canBeEdited", "type": "boolean"},
|
||||
{"name": "unread", "type": "true"}
|
||||
{"name": "unread", "type": "true"},
|
||||
{"name": "rReply", "type": "string"}
|
||||
]
|
||||
}, {
|
||||
"predicate": "messageEmpty",
|
||||
@ -228,4 +230,10 @@
|
||||
"params": [
|
||||
{"name": "phone_number", "type": "string"}
|
||||
]
|
||||
}, {
|
||||
"predicate": "draftMessage",
|
||||
"params": [
|
||||
{"name": "rReply", "type": "string"},
|
||||
{"name": "rMessage", "type": "string"}
|
||||
]
|
||||
}]
|
Loading…
x
Reference in New Issue
Block a user