From 2c482f82db76bc0e5312b26b905d5b3ff73229cd Mon Sep 17 00:00:00 2001 From: zubiden <19638254+zubiden@users.noreply.github.com> Date: Sat, 9 Nov 2024 15:43:32 +0400 Subject: [PATCH] Poll: Fix updates (#5167) --- src/api/gramjs/methods/messages.ts | 7 +++- src/api/gramjs/updates/entityProcessor.ts | 8 ++--- src/api/gramjs/updates/mtpUpdateHandler.ts | 28 ++++++++++++---- src/api/types/updates.ts | 5 +++ src/components/middle/message/Poll.scss | 4 +-- src/global/actions/apiUpdaters/messages.ts | 39 +++++++++++++++++++--- 6 files changed, 72 insertions(+), 19 deletions(-) diff --git a/src/api/gramjs/methods/messages.ts b/src/api/gramjs/methods/messages.ts index 04593a082..b9aef66a2 100644 --- a/src/api/gramjs/methods/messages.ts +++ b/src/api/gramjs/methods/messages.ts @@ -53,7 +53,9 @@ import { buildApiSendAsPeerId, } from '../apiBuilders/chats'; import { buildApiFormattedText } from '../apiBuilders/common'; -import { buildMessageMediaContent, buildMessageTextContent, buildWebPage } from '../apiBuilders/messageContent'; +import { + buildMessageMediaContent, buildMessageTextContent, buildPollFromMedia, buildWebPage, +} from '../apiBuilders/messageContent'; import { buildApiFactCheck, buildApiMessage, @@ -1920,6 +1922,7 @@ function handleLocalMessageUpdate(localMessage: ApiMessage, update: GramJs.TypeU } let newContent: MediaContent | undefined; + let poll: ApiPoll | undefined; if (messageUpdate instanceof GramJs.UpdateShortSentMessage) { if (localMessage.content.text && messageUpdate.entities) { newContent = { @@ -1933,6 +1936,7 @@ function handleLocalMessageUpdate(localMessage: ApiMessage, update: GramJs.TypeU peerId: buildPeer(localMessage.chatId), id: messageUpdate.id, }), }; + poll = buildPollFromMedia(messageUpdate.media); } const mtpMessage = buildMessageFromUpdate(messageUpdate.id, localMessage.chatId, messageUpdate); @@ -1960,6 +1964,7 @@ function handleLocalMessageUpdate(localMessage: ApiMessage, update: GramJs.TypeU sendingState: undefined, ...('date' in messageUpdate && { date: messageUpdate.date }), }, + poll, }); handleGramJsUpdate(update); diff --git a/src/api/gramjs/updates/entityProcessor.ts b/src/api/gramjs/updates/entityProcessor.ts index 550afa031..55dee5823 100644 --- a/src/api/gramjs/updates/entityProcessor.ts +++ b/src/api/gramjs/updates/entityProcessor.ts @@ -26,7 +26,7 @@ export function processAndUpdateEntities(response?: GramJs.AnyRequest['__respons const polls: ApiPoll[] | undefined = []; if ('users' in response && Array.isArray(response.users) && TYPE_USER.has(response.users[0]?.className)) { - const users = response.users.map((user) => { + const users = response.users.map((user: GramJs.TypeUser) => { if (user instanceof GramJs.User) { addUserToLocalDb(user); } @@ -36,7 +36,7 @@ export function processAndUpdateEntities(response?: GramJs.AnyRequest['__respons } if ('chats' in response && Array.isArray(response.chats) && TYPE_CHAT.has(response.chats[0]?.className)) { - const chats = response.chats.map((chat) => { + const chats = response.chats.map((chat: GramJs.TypeChat) => { if ((chat instanceof GramJs.Chat || chat instanceof GramJs.Channel)) { addChatToLocalDb(chat); } @@ -46,7 +46,7 @@ export function processAndUpdateEntities(response?: GramJs.AnyRequest['__respons } if ('messages' in response && Array.isArray(response.messages) && TYPE_MESSAGE.has(response.messages[0]?.className)) { - response.messages.forEach((message) => { + response.messages.forEach((message: GramJs.TypeMessage) => { addMessageToLocalDb(message); const threadInfo = buildApiThreadInfoFromMessage(message); @@ -54,7 +54,7 @@ export function processAndUpdateEntities(response?: GramJs.AnyRequest['__respons threadInfos.push(threadInfo); } - const poll = buildPollFromMedia(message.media); + const poll = 'media' in message && message.media && buildPollFromMedia(message.media); if (poll) { polls.push(poll); } diff --git a/src/api/gramjs/updates/mtpUpdateHandler.ts b/src/api/gramjs/updates/mtpUpdateHandler.ts index a19668dc1..50ff28210 100644 --- a/src/api/gramjs/updates/mtpUpdateHandler.ts +++ b/src/api/gramjs/updates/mtpUpdateHandler.ts @@ -2,7 +2,7 @@ import { Api as GramJs, connection } from '../../../lib/gramjs'; import type { GroupCallConnectionData } from '../../../lib/secret-sauce'; import type { - ApiMessage, ApiStory, ApiStorySkipped, + ApiMessage, ApiPoll, ApiStory, ApiStorySkipped, ApiUpdateConnectionStateType, } from '../../types'; @@ -34,6 +34,7 @@ import { buildApiMessageExtendedMediaPreview, buildBoughtMediaContent, buildPoll, + buildPollFromMedia, buildPollResults, } from '../apiBuilders/messageContent'; import { @@ -125,6 +126,7 @@ export function updater(update: Update) { || update instanceof GramJs.UpdateShortMessage ) { let message: ApiMessage | undefined; + let poll: ApiPoll | undefined; let shouldForceReply: boolean | undefined; if (update instanceof GramJs.UpdateShortChatMessage) { @@ -132,8 +134,9 @@ export function updater(update: Update) { } else if (update instanceof GramJs.UpdateShortMessage) { message = buildApiMessageFromShort(update); } else { + const mtpMessage = update.message; // TODO Remove if proven not reproducing - if (update.message instanceof GramJs.MessageEmpty) { + if (mtpMessage instanceof GramJs.MessageEmpty) { if (DEBUG) { // eslint-disable-next-line no-console console.error('Unexpected update:', update.className, update); @@ -142,9 +145,13 @@ export function updater(update: Update) { return; } - processMessageAndUpdateThreadInfo(update.message); + processMessageAndUpdateThreadInfo(mtpMessage); - message = buildApiMessage(update.message)!; + message = buildApiMessage(mtpMessage)!; + + if (mtpMessage instanceof GramJs.Message) { + poll = mtpMessage.media && buildPollFromMedia(mtpMessage.media); + } shouldForceReply = 'replyMarkup' in update.message && update.message?.replyMarkup instanceof GramJs.ReplyKeyboardForceReply @@ -157,6 +164,7 @@ export function updater(update: Update) { id: message.id, chatId: message.chatId, message, + poll, }); } else { // We don't have preview for action or 'via bot' messages, so `newMessage` update here is required @@ -167,6 +175,7 @@ export function updater(update: Update) { chatId: message.chatId, message, shouldForceReply, + poll, }); } @@ -302,8 +311,9 @@ export function updater(update: Update) { update instanceof GramJs.UpdateEditMessage || update instanceof GramJs.UpdateEditChannelMessage ) { + const mtpMessage = update.message; // TODO Remove if proven not reproducing - if (update.message instanceof GramJs.MessageEmpty) { + if (mtpMessage instanceof GramJs.MessageEmpty) { if (DEBUG) { // eslint-disable-next-line no-console console.error('Unexpected update:', update.className, update); @@ -312,16 +322,20 @@ export function updater(update: Update) { return; } - processMessageAndUpdateThreadInfo(update.message); + processMessageAndUpdateThreadInfo(mtpMessage); // Workaround for a weird server behavior when own message is marked as incoming - const message = omit(buildApiMessage(update.message)!, ['isOutgoing']); + const message = omit(buildApiMessage(mtpMessage)!, ['isOutgoing']); + + const poll = mtpMessage instanceof GramJs.Message && mtpMessage.media + ? buildPollFromMedia(mtpMessage.media) : undefined; sendApiUpdate({ '@type': 'updateMessage', id: message.id, chatId: message.chatId, message, + poll, }); } else if (update instanceof GramJs.UpdateMessageReactions) { sendApiUpdate({ diff --git a/src/api/types/updates.ts b/src/api/types/updates.ts index fe67d1c50..3e9fdd701 100644 --- a/src/api/types/updates.ts +++ b/src/api/types/updates.ts @@ -223,6 +223,7 @@ export type ApiUpdateMessage = { chatId: string; id: number; message: Partial; + poll?: ApiPoll; }; export type ApiUpdateScheduledMessage = { @@ -230,12 +231,14 @@ export type ApiUpdateScheduledMessage = { chatId: string; id: number; message: Partial; + poll?: ApiPoll; }; export type ApiUpdateQuickReplyMessage = { '@type': 'updateQuickReplyMessage'; id: number; message: Partial; + poll?: ApiPoll; }; export type ApiUpdateDeleteQuickReplyMessages = { @@ -271,6 +274,7 @@ export type ApiUpdateScheduledMessageSendSucceeded = { chatId: string; localId: number; message: ApiMessage; + poll?: ApiPoll; }; export type ApiUpdateMessageSendSucceeded = { @@ -278,6 +282,7 @@ export type ApiUpdateMessageSendSucceeded = { chatId: string; localId: number; message: ApiMessage; + poll?: ApiPoll; }; export type ApiUpdateMessageSendFailed = { diff --git a/src/components/middle/message/Poll.scss b/src/components/middle/message/Poll.scss index ca9033c5c..2a53d21c2 100644 --- a/src/components/middle/message/Poll.scss +++ b/src/components/middle/message/Poll.scss @@ -39,10 +39,10 @@ .Checkbox, .Radio { padding-left: 2.25rem; - padding-bottom: 1rem; + margin-bottom: 1.5rem; &:last-child { - margin-bottom: 0; + margin-bottom: 0.75rem; } &:first-child { diff --git a/src/global/actions/apiUpdaters/messages.ts b/src/global/actions/apiUpdaters/messages.ts index 1a56c643e..cb2df236a 100644 --- a/src/global/actions/apiUpdaters/messages.ts +++ b/src/global/actions/apiUpdaters/messages.ts @@ -239,7 +239,9 @@ addActionHandler('apiUpdate', (global, actions, update): ActionReturnType => { } case 'updateMessage': { - const { chatId, id, message } = update; + const { + chatId, id, message, poll, + } = update; const currentMessage = selectChatMessage(global, chatId, id); const chat = selectChat(global, chatId); @@ -258,13 +260,19 @@ addActionHandler('apiUpdate', (global, actions, update): ActionReturnType => { global = clearMessageTranslation(global, chatId, id); } + if (poll) { + global = updatePoll(global, poll.id, poll); + } + setGlobal(global); break; } case 'updateScheduledMessage': { - const { chatId, id, message } = update; + const { + chatId, id, message, poll, + } = update; const currentMessage = selectScheduledMessage(global, chatId, id); if (!currentMessage) { @@ -280,15 +288,24 @@ addActionHandler('apiUpdate', (global, actions, update): ActionReturnType => { const threadScheduledIds = selectScheduledIds(global, chatId, threadId) || []; global = replaceThreadParam(global, chatId, threadId, 'scheduledIds', threadScheduledIds.sort((a, b) => b - a)); } + if (poll) { + global = updatePoll(global, poll.id, poll); + } + setGlobal(global); break; } case 'updateQuickReplyMessage': { - const { id, message } = update; + const { id, message, poll } = update; global = updateQuickReplyMessage(global, id, message); + + if (poll) { + global = updatePoll(global, poll.id, poll); + } + setGlobal(global); break; @@ -319,7 +336,9 @@ addActionHandler('apiUpdate', (global, actions, update): ActionReturnType => { } case 'updateMessageSendSucceeded': { - const { chatId, localId, message } = update; + const { + chatId, localId, message, poll, + } = update; global = updateListedAndViewportIds(global, actions, message as ApiMessage); @@ -338,6 +357,10 @@ addActionHandler('apiUpdate', (global, actions, update): ActionReturnType => { previousLocalId: localId, }); + if (poll) { + global = updatePoll(global, poll.id, poll); + } + global = { ...global, fileUploads: { @@ -389,7 +412,9 @@ addActionHandler('apiUpdate', (global, actions, update): ActionReturnType => { } case 'updateScheduledMessageSendSucceeded': { - const { chatId, localId, message } = update; + const { + chatId, localId, message, poll, + } = update; const scheduledIds = selectScheduledIds(global, chatId, MAIN_THREAD_ID) || []; global = replaceThreadParam(global, chatId, MAIN_THREAD_ID, 'scheduledIds', [...scheduledIds, message.id]); @@ -408,6 +433,10 @@ addActionHandler('apiUpdate', (global, actions, update): ActionReturnType => { previousLocalId: localId, }); + if (poll) { + global = updatePoll(global, poll.id, poll); + } + setGlobal(global); break; }