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