From 918e614e53319190c4c15a07e01c8cce10ffa753 Mon Sep 17 00:00:00 2001 From: Eduard Kuzmenko Date: Tue, 22 Dec 2020 10:18:42 +0200 Subject: [PATCH] Inject discussion message on chat history load --- src/components/chat/bubbles.ts | 37 +++++++- src/lib/appManagers/appMessagesManager.ts | 111 ++++++++++------------ src/scss/partials/_chatBubble.scss | 10 ++ 3 files changed, 94 insertions(+), 64 deletions(-) diff --git a/src/components/chat/bubbles.ts b/src/components/chat/bubbles.ts index 425ac998..19e0e76e 100644 --- a/src/components/chat/bubbles.ts +++ b/src/components/chat/bubbles.ts @@ -2241,6 +2241,10 @@ export default class ChatBubbles { savedFrom = `${this.chat.peerId}_${message.mid}`; } + if(message.mid === this.chat.threadId) { + bubble.classList.add('is-thread-starter'); + } + if(savedFrom) { const goto = document.createElement('div'); goto.classList.add('bubble-beside-button', 'goto-original', 'tgico-arrow-next'); @@ -2275,6 +2279,12 @@ export default class ChatBubbles { if(!history/* .filter((id: number) => id > 0) */.length) { if(!isBackLimit) { this.scrolledAll = true; + + /* if(this.chat.type === 'discussion') { + const serviceStartMessageId = this.appMessagesManager.threadsServiceMessagesIdsStorage[this.peerId + '_' + this.chat.threadId]; + if(serviceStartMessageId) history.push(serviceStartMessageId); + history.push(this.chat.threadId); + } */ } else { this.scrolledAllDown = true; } @@ -2393,8 +2403,33 @@ export default class ChatBubbles { public requestHistory(maxId: number, loadCount: number, backLimit: number) { //const middleware = this.getMiddleware(); - if(this.chat.type === 'chat' || this.chat.type === 'discussion') { + if(this.chat.type === 'chat') { return this.appMessagesManager.getHistory(this.peerId, maxId, loadCount, backLimit, this.chat.threadId); + } else if(this.chat.type === 'discussion') { + const result = this.appMessagesManager.getHistory(this.peerId, maxId, loadCount, backLimit, this.chat.threadId); + const checkForStart = (historyResult: HistoryResult) => { + const topLoadCount = loadCount; + const isTopEnd = historyResult.offsetIdOffset >= (historyResult.count - topLoadCount); + this.log('discussion got history', loadCount, backLimit, historyResult, isTopEnd); + + // * inject discussion start + if(isTopEnd) { + const serviceStartMessageId = this.appMessagesManager.threadsServiceMessagesIdsStorage[this.peerId + '_' + this.chat.threadId]; + if(serviceStartMessageId) historyResult.history.push(serviceStartMessageId); + historyResult.history.push(this.chat.threadId); + this.scrolledAll = true; + } + }; + + if(result instanceof Promise) { + return result.then(result => { + checkForStart(result); + return result; + }); + } + + checkForStart(result); + return result; } else if(this.chat.type === 'pinned') { const promise = this.appMessagesManager.getSearch(this.peerId, '', {_: 'inputMessagesFilterPinned'}, maxId, loadCount, 0, backLimit) .then(value => ({history: value.history.map(m => m.mid)})); diff --git a/src/lib/appManagers/appMessagesManager.ts b/src/lib/appManagers/appMessagesManager.ts index de73bff0..80ed6bfe 100644 --- a/src/lib/appManagers/appMessagesManager.ts +++ b/src/lib/appManagers/appMessagesManager.ts @@ -55,8 +55,7 @@ export type HistoryStorage = { export type HistoryResult = { count: number, history: number[], - unreadOffset: number, - unreadSkip: boolean + offsetIdOffset?: number }; export type Dialog = MTDialog.dialog; @@ -110,6 +109,7 @@ export class AppMessagesManager { } = {}; public pinnedMessages: {[peerId: string]: PinnedStorage} = {}; + public threadsServiceMessagesIdsStorage: {[peerId_threadId: string]: number} = {}; public threadsToReplies: { [peerId_threadId: string]: string; } = {}; @@ -3047,12 +3047,34 @@ export class AppMessagesManager { this.saveMessages(result.messages); const message = result.messages[0] as MyMessage; + const threadKey = message.peerId + '_' + message.mid; + + if(!this.threadsServiceMessagesIdsStorage[threadKey]) { + (result.messages as Message.message[]).forEach(message => { + const serviceStartMessage: Message.messageService = { + _: 'messageService', + id: this.generateMessageId(message.id, true), + date: message.date, + from_id: message.from_id, + peer_id: message.peer_id, + action: { + _: 'messageActionCustomAction', + message: 'Discussion started' + }, + reply_to: this.generateReplyHeader(message.id) + }; + + this.saveMessages([serviceStartMessage], {isOutgoing: true}); + this.threadsServiceMessagesIdsStorage[threadKey] = serviceStartMessage.mid; + }); + } + const historyStorage = this.getHistoryStorage(message.peerId, message.mid); result.max_id = historyStorage.maxId = this.generateMessageId(result.max_id) || 0; result.read_inbox_max_id = historyStorage.readMaxId = this.generateMessageId(result.read_inbox_max_id) || 0; result.read_outbox_max_id = historyStorage.readOutboxMaxId = this.generateMessageId(result.read_outbox_max_id) || 0; - this.threadsToReplies[message.peerId + '_' + message.mid] = peerId + '_' + mid; + this.threadsToReplies[threadKey] = peerId + '_' + mid; return result; }); @@ -4214,14 +4236,12 @@ export class AppMessagesManager { }); } - public getHistory(peerId: number, maxId = 0, limit: number, backLimit?: number, threadId?: number) { + public getHistory(peerId: number, maxId = 0, limit: number, backLimit?: number, threadId?: number): Promise | HistoryResult { if(this.migratedFromTo[peerId]) { peerId = this.migratedFromTo[peerId]; } const historyStorage = this.getHistoryStorage(peerId, threadId); - const unreadOffset = 0; - const unreadSkip = false; let offset = 0; let offsetNotFound = false; @@ -4230,12 +4250,9 @@ export class AppMessagesManager { let reqPeerId = peerId; if(this.migratedToFrom[peerId]) { isMigrated = true; - /* if(maxId && maxId < appMessagesIdsManager.fullMsgIdModulus) { - reqPeerId = this.migratedToFrom[peerId]; - } */ } - if(maxId > 0) { + if(maxId) { offsetNotFound = true; for(; offset < historyStorage.history.length; offset++) { if(maxId > historyStorage.history[offset]) { @@ -4257,23 +4274,18 @@ export class AppMessagesManager { limit = limit; } - let history = historyStorage.history.slice(offset, offset + limit); - if(!maxId && historyStorage.pending.length) { - history = historyStorage.pending.slice().concat(history); - } - - return this.wrapHistoryResult(peerId, { + const history = historyStorage.history.slice(offset, offset + limit); + return { count: historyStorage.count, history: history, - unreadOffset: unreadOffset, - unreadSkip: unreadSkip - }); + offsetIdOffset: offset + }; } if(offsetNotFound) { offset = 0; } - if((backLimit || unreadSkip || maxId) && historyStorage.history.indexOf(maxId) == -1) { + if((backLimit || maxId) && historyStorage.history.indexOf(maxId) === -1) { if(backLimit) { offset = -backLimit; limit += backLimit; @@ -4285,45 +4297,31 @@ export class AppMessagesManager { historyStorage.count++; } - let history: number[] = []; - historyResult.messages.forEach((message: any) => { - history.push(message.mid); - }); - - if(!maxId && historyStorage.pending.length) { - history = historyStorage.pending.slice().concat(history); - } - - return this.wrapHistoryResult(peerId, { + const history = (historyResult.messages as MyMessage[]).map(message => message.mid); + return { count: historyStorage.count, - history: history, - unreadOffset: unreadOffset, - unreadSkip: unreadSkip - }); + history, + offsetIdOffset: (historyResult as MessagesMessages.messagesMessagesSlice).offset_id_offset || 0 + }; }); } return this.fillHistoryStorage(peerId, maxId, limit, historyStorage, threadId).then(() => { - offset = 0; - if(maxId > 0) { - for(offset = 0; offset < historyStorage.history.length; offset++) { + let offset = 0; + if(maxId) { + for(; offset < historyStorage.history.length; offset++) { if(maxId > historyStorage.history[offset]) { break; } } } - let history = historyStorage.history.slice(backLimit ? Math.max(offset - backLimit, 0) : offset, offset + limit); - if(!maxId && historyStorage.pending.length) { - history = historyStorage.pending.slice().concat(history); - } - - return this.wrapHistoryResult(peerId, { + const history = historyStorage.history.slice(backLimit ? Math.max(offset - backLimit, 0) : offset, offset + limit); + return { count: historyStorage.count, - history: history, - unreadOffset: unreadOffset, - unreadSkip: unreadSkip - }); + history, + offsetIdOffset: offset + }; }); } @@ -4338,7 +4336,7 @@ export class AppMessagesManager { } let offset = 0; - if(maxId > 0) { + if(maxId) { for(; offset < historyStorage.history.length; offset++) { if(maxId > historyStorage.history[offset]) { break; @@ -4391,19 +4389,6 @@ export class AppMessagesManager { }); } - public wrapHistoryResult(peerId: number, result: HistoryResult) { - if(result.unreadOffset) { - for(let i = result.history.length - 1; i >= 0; i--) { - const message = this.getMessageByPeer(peerId, result.history[i]); - if(!message.deleted && !message.pFlags.out && message.pFlags.unread) { - result.unreadOffset = i + 1; - break; - } - } - } - return result; - } - public requestHistory(peerId: number, maxId: number, limit = 0, offset = 0, offsetDate = 0, threadId = 0): Promise> { const isChannel = appPeersManager.isChannel(peerId); @@ -4417,7 +4402,7 @@ export class AppMessagesManager { offset_id: this.getLocalMessageId(maxId) || 0, offset_date: offsetDate, add_offset: offset, - limit: limit, + limit, max_id: 0, min_id: 0, hash: 0 @@ -4456,7 +4441,7 @@ export class AppMessagesManager { }); } - return historyResult as any; + return historyResult; }, (error) => { switch (error.type) { case 'CHANNEL_PRIVATE': diff --git a/src/scss/partials/_chatBubble.scss b/src/scss/partials/_chatBubble.scss index 767ac027..585c1c11 100644 --- a/src/scss/partials/_chatBubble.scss +++ b/src/scss/partials/_chatBubble.scss @@ -1512,6 +1512,16 @@ $bubble-margin: .25rem; } } } + + &.is-thread-starter { + .user-avatar { + display: none; + } + + &.is-in .bubble__container { + margin-left: 0; + } + } } // * fix scroll with only 1 bubble