diff --git a/Telegram/SourceFiles/api/api_editing.cpp b/Telegram/SourceFiles/api/api_editing.cpp index 126223bee..a1e168adf 100644 --- a/Telegram/SourceFiles/api/api_editing.cpp +++ b/Telegram/SourceFiles/api/api_editing.cpp @@ -11,6 +11,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "api/api_media.h" #include "api/api_text_entities.h" #include "ui/boxes/confirm_box.h" +#include "data/business/data_shortcut_messages.h" #include "data/data_histories.h" #include "data/data_scheduled_messages.h" #include "data/data_session.h" @@ -92,6 +93,8 @@ mtpRequestId EditMessage( const auto id = item->isScheduled() ? session->data().scheduledMessages().lookupId(item) + : item->isBusinessShortcut() + ? session->data().shortcutMessages().lookupId(item) : item->id; return api->request(MTPmessages_EditMessage( MTP_flags(flags), diff --git a/Telegram/SourceFiles/api/api_sending.cpp b/Telegram/SourceFiles/api/api_sending.cpp index 96bdf4a4a..982992ce3 100644 --- a/Telegram/SourceFiles/api/api_sending.cpp +++ b/Telegram/SourceFiles/api/api_sending.cpp @@ -85,20 +85,21 @@ void SendExistingMedia( ? (*localMessageId) : session->data().nextLocalMessageId()); const auto randomId = base::RandomValue(); + const auto &action = message.action; auto flags = NewMessageFlags(peer); auto sendFlags = MTPmessages_SendMedia::Flags(0); - if (message.action.replyTo) { + if (action.replyTo) { flags |= MessageFlag::HasReplyInfo; sendFlags |= MTPmessages_SendMedia::Flag::f_reply_to; } const auto anonymousPost = peer->amAnonymous(); - const auto silentPost = ShouldSendSilent(peer, message.action.options); - InnerFillMessagePostFlags(message.action.options, peer, flags); + const auto silentPost = ShouldSendSilent(peer, action.options); + InnerFillMessagePostFlags(action.options, peer, flags); if (silentPost) { sendFlags |= MTPmessages_SendMedia::Flag::f_silent; } - const auto sendAs = message.action.options.sendAs; + const auto sendAs = action.options.sendAs; const auto messageFromId = sendAs ? sendAs->id : anonymousPost @@ -125,33 +126,30 @@ void SendExistingMedia( } const auto captionText = caption.text; - if (message.action.options.scheduled) { + if (action.options.scheduled) { flags |= MessageFlag::IsOrWasScheduled; sendFlags |= MTPmessages_SendMedia::Flag::f_schedule_date; } - if (message.action.options.shortcutId) { + if (action.options.shortcutId) { + flags |= MessageFlag::ShortcutMessage; sendFlags |= MTPmessages_SendMedia::Flag::f_quick_reply_shortcut; } session->data().registerMessageRandomId(randomId, newId); - const auto viaBotId = UserId(); - history->addNewLocalMessage( - newId.msg, - flags, - viaBotId, - message.action.replyTo, - HistoryItem::NewMessageDate(message.action.options.scheduled), - messageFromId, - messagePostAuthor, - media, - caption, - HistoryMessageMarkupData()); + history->addNewLocalMessage({ + .id = newId.msg, + .flags = flags, + .from = messageFromId, + .replyTo = action.replyTo, + .date = HistoryItem::NewMessageDate(action.options), + .shortcutId = action.options.shortcutId, + .postAuthor = messagePostAuthor, + }, media, caption); const auto performRequest = [=](const auto &repeatRequest) -> void { auto &histories = history->owner().histories(); const auto session = &history->session(); - const auto &action = message.action; const auto usedFileReference = media->fileReference(); histories.sendPreparedMessage( history, @@ -187,7 +185,7 @@ void SendExistingMedia( }; performRequest(performRequest); - api->finishForwarding(message.action); + api->finishForwarding(action); } } // namespace @@ -307,23 +305,23 @@ bool SendDice(MessageToSend &message) { sendFlags |= MTPmessages_SendMedia::Flag::f_schedule_date; } if (action.options.shortcutId) { + flags |= MessageFlag::ShortcutMessage; sendFlags |= MTPmessages_SendMedia::Flag::f_quick_reply_shortcut; } session->data().registerMessageRandomId(randomId, newId); - const auto viaBotId = UserId(); - history->addNewLocalMessage( - newId.msg, - flags, - viaBotId, - action.replyTo, - HistoryItem::NewMessageDate(action.options.scheduled), - messageFromId, - messagePostAuthor, - TextWithEntities(), - MTP_messageMediaDice(MTP_int(0), MTP_string(emoji)), - HistoryMessageMarkupData()); + history->addNewLocalMessage({ + .id = newId.msg, + .flags = flags, + .from = messageFromId, + .replyTo = action.replyTo, + .date = HistoryItem::NewMessageDate(action.options), + .shortcutId = action.options.shortcutId, + .postAuthor = messagePostAuthor, + }, TextWithEntities(), MTP_messageMediaDice( + MTP_int(0), + MTP_string(emoji))); histories.sendPreparedMessage( history, action.replyTo, @@ -420,7 +418,13 @@ void SendConfirmedFile( if (file->to.options.scheduled) { flags |= MessageFlag::IsOrWasScheduled; - // Scheduled messages have no the 'edited' badge. + // Scheduled messages have no 'edited' badge. + flags |= MessageFlag::HideEdited; + } + if (file->to.options.shortcutId) { + flags |= MessageFlag::ShortcutMessage; + + // Shortcut messages have no 'edited' badge. flags |= MessageFlag::HideEdited; } if (file->type == SendMediaType::Audio) { @@ -429,8 +433,7 @@ void SendConfirmedFile( } } - const auto messageFromId = - file->to.options.sendAs + const auto messageFromId = file->to.options.sendAs ? file->to.options.sendAs->id : anonymousPost ? PeerId() @@ -500,19 +503,15 @@ void SendConfirmedFile( edition.savePreviousMedia = true; itemToEdit->applyEdition(std::move(edition)); } else { - const auto viaBotId = UserId(); - history->addNewLocalMessage( - newId.msg, - flags, - viaBotId, - file->to.replyTo, - HistoryItem::NewMessageDate(file->to.options.scheduled), - messageFromId, - messagePostAuthor, - caption, - media, - HistoryMessageMarkupData(), - groupId); + history->addNewLocalMessage({ + .id = newId.msg, + .flags = flags, + .from = messageFromId, + .replyTo = file->to.replyTo, + .date = HistoryItem::NewMessageDate(file->to.options), + .shortcutId = file->to.options.shortcutId, + .postAuthor = messagePostAuthor, + }, caption, media); } if (isEditing) { diff --git a/Telegram/SourceFiles/api/api_updates.cpp b/Telegram/SourceFiles/api/api_updates.cpp index 679faa063..57db15d92 100644 --- a/Telegram/SourceFiles/api/api_updates.cpp +++ b/Telegram/SourceFiles/api/api_updates.cpp @@ -20,6 +20,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "mtproto/mtp_instance.h" #include "mtproto/mtproto_config.h" #include "mtproto/mtproto_dc_options.h" +#include "data/business/data_shortcut_messages.h" #include "data/notify/data_notify_settings.h" #include "data/stickers/data_stickers.h" #include "data/data_saved_messages.h" @@ -1774,6 +1775,31 @@ void Updates::feedUpdate(const MTPUpdate &update) { session().data().scheduledMessages().apply(d); } break; + case mtpc_updateQuickReplies: { + const auto &d = update.c_updateQuickReplies(); + session().data().shortcutMessages().apply(d); + } break; + + case mtpc_updateNewQuickReply: { + const auto &d = update.c_updateNewQuickReply(); + session().data().shortcutMessages().apply(d); + } break; + + case mtpc_updateDeleteQuickReply: { + const auto &d = update.c_updateDeleteQuickReply(); + session().data().shortcutMessages().apply(d); + } break; + + case mtpc_updateQuickReplyMessage: { + const auto &d = update.c_updateQuickReplyMessage(); + session().data().shortcutMessages().apply(d); + } break; + + case mtpc_updateDeleteQuickReplyMessages: { + const auto &d = update.c_updateDeleteQuickReplyMessages(); + session().data().shortcutMessages().apply(d); + } break; + case mtpc_updateWebPage: { auto &d = update.c_updateWebPage(); diff --git a/Telegram/SourceFiles/apiwrap.cpp b/Telegram/SourceFiles/apiwrap.cpp index bca32c3da..4676c5a50 100644 --- a/Telegram/SourceFiles/apiwrap.cpp +++ b/Telegram/SourceFiles/apiwrap.cpp @@ -2449,6 +2449,14 @@ void ApiWrap::refreshFileReference( request(MTPmessages_GetScheduledMessages( item->history()->peer->input, MTP_vector(1, MTP_int(realId)))); + } else if (item->isBusinessShortcut()) { + const auto &shortcuts = _session->data().shortcutMessages(); + const auto realId = shortcuts.lookupId(item); + request(MTPmessages_GetQuickReplyMessages( + MTP_flags(MTPmessages_GetQuickReplyMessages::Flag::f_id), + MTP_int(item->shortcutId()), + MTP_vector(1, MTP_int(realId)), + MTP_long(0))); } else if (const auto channel = item->history()->peer->asChannel()) { request(MTPchannels_GetMessages( channel->inputChannel, @@ -3232,6 +3240,7 @@ void ApiWrap::forwardMessages( sendFlags |= SendFlag::f_schedule_date; } if (action.options.shortcutId) { + flags |= MessageFlag::ShortcutMessage; sendFlags |= SendFlag::f_quick_reply_shortcut; } if (draft.options != Data::ForwardOptions::PreserveInfo) { @@ -3317,14 +3326,15 @@ void ApiWrap::forwardMessages( const auto messagePostAuthor = peer->isBroadcast() ? self->name() : QString(); - history->addNewLocalMessage( - newId.msg, - flags, - HistoryItem::NewMessageDate(action.options.scheduled), - messageFromId, - messagePostAuthor, - item, - topMsgId); + history->addNewLocalMessage({ + .id = newId.msg, + .flags = flags, + .from = messageFromId, + .replyTo = { .topicRootId = topMsgId }, + .date = HistoryItem::NewMessageDate(action.options), + .shortcutId = action.options.shortcutId, + .postAuthor = messagePostAuthor, + }, item); _session->data().registerMessageRandomId(randomId, newId); if (!localIds) { localIds = std::make_shared>(); @@ -3405,6 +3415,9 @@ void ApiWrap::sendSharedContact( if (action.options.scheduled) { flags |= MessageFlag::IsOrWasScheduled; } + if (action.options.shortcutId) { + flags |= MessageFlag::ShortcutMessage; + } const auto messageFromId = action.options.sendAs ? action.options.sendAs->id : anonymousPost @@ -3413,23 +3426,20 @@ void ApiWrap::sendSharedContact( const auto messagePostAuthor = peer->isBroadcast() ? _session->user()->name() : QString(); - const auto viaBotId = UserId(); - const auto item = history->addNewLocalMessage( - newId.msg, - flags, - viaBotId, - action.replyTo, - HistoryItem::NewMessageDate(action.options.scheduled), - messageFromId, - messagePostAuthor, - TextWithEntities(), - MTP_messageMediaContact( - MTP_string(phone), - MTP_string(firstName), - MTP_string(lastName), - MTP_string(), // vcard - MTP_long(userId.bare)), - HistoryMessageMarkupData()); + const auto item = history->addNewLocalMessage({ + .id = newId.msg, + .flags = flags, + .from = messageFromId, + .replyTo = action.replyTo, + .date = HistoryItem::NewMessageDate(action.options), + .shortcutId = action.options.shortcutId, + .postAuthor = messagePostAuthor, + }, TextWithEntities(), MTP_messageMediaContact( + MTP_string(phone), + MTP_string(firstName), + MTP_string(lastName), + MTP_string(), // vcard + MTP_long(userId.bare))); const auto media = MTP_inputMediaContact( MTP_string(phone), @@ -3737,21 +3747,19 @@ void ApiWrap::sendMessage(MessageToSend &&message) { mediaFlags |= MTPmessages_SendMedia::Flag::f_schedule_date; } if (action.options.shortcutId) { + flags |= MessageFlag::ShortcutMessage; sendFlags |= MTPmessages_SendMessage::Flag::f_quick_reply_shortcut; mediaFlags |= MTPmessages_SendMedia::Flag::f_quick_reply_shortcut; } - const auto viaBotId = UserId(); - lastMessage = history->addNewLocalMessage( - newId.msg, - flags, - viaBotId, - action.replyTo, - HistoryItem::NewMessageDate(action.options.scheduled), - messageFromId, - messagePostAuthor, - sending, - media, - HistoryMessageMarkupData()); + lastMessage = history->addNewLocalMessage({ + .id = newId.msg, + .flags = flags, + .from = messageFromId, + .replyTo = action.replyTo, + .date = HistoryItem::NewMessageDate(action.options), + .shortcutId = action.options.shortcutId, + .postAuthor = messagePostAuthor, + }, sending, media); const auto done = [=]( const MTPUpdates &result, const MTP::Response &response) { @@ -3903,6 +3911,7 @@ void ApiWrap::sendInlineResult( sendFlags |= SendFlag::f_schedule_date; } if (action.options.shortcutId) { + flags |= MessageFlag::ShortcutMessage; sendFlags |= SendFlag::f_quick_reply_shortcut; } if (action.options.hideViaBot) { @@ -3923,15 +3932,18 @@ void ApiWrap::sendInlineResult( _session->data().registerMessageRandomId(randomId, newId); - data->addToHistory( - history, - flags, - newId.msg, - messageFromId, - HistoryItem::NewMessageDate(action.options.scheduled), - (bot && !action.options.hideViaBot) ? peerToUser(bot->id) : 0, - action.replyTo, - messagePostAuthor); + data->addToHistory(history, { + .id = newId.msg, + .flags = flags, + .from = messageFromId, + .replyTo = action.replyTo, + .date = HistoryItem::NewMessageDate(action.options), + .shortcutId = action.options.shortcutId, + .viaBotId = ((bot && !action.options.hideViaBot) + ? peerToUser(bot->id) + : UserId()), + .postAuthor = messagePostAuthor, + }); history->clearCloudDraft(topicRootId); history->startSavingCloudDraft(topicRootId); diff --git a/Telegram/SourceFiles/boxes/background_preview_box.cpp b/Telegram/SourceFiles/boxes/background_preview_box.cpp index 8406657e6..048362638 100644 --- a/Telegram/SourceFiles/boxes/background_preview_box.cpp +++ b/Telegram/SourceFiles/boxes/background_preview_box.cpp @@ -81,11 +81,11 @@ constexpr auto kMaxWallPaperSlugLength = 255; const auto flags = MessageFlag::FakeHistoryItem | MessageFlag::HasFromId | (out ? MessageFlag::Outgoing : MessageFlag(0)); - const auto item = history->makeMessage( - history->owner().nextLocalMessageId(), - flags, - base::unixtime::now(), - PreparedServiceText{ { text } }); + const auto item = history->makeMessage({ + .id = history->owner().nextLocalMessageId(), + .flags = flags, + .date = base::unixtime::now(), + }, PreparedServiceText{ { text } }); return AdminLog::OwnedItem(delegate, item); } @@ -96,24 +96,16 @@ constexpr auto kMaxWallPaperSlugLength = 255; bool out) { Expects(history->peer->isUser()); - const auto flags = MessageFlag::FakeHistoryItem - | MessageFlag::HasFromId - | (out ? MessageFlag::Outgoing : MessageFlag(0)); - const auto replyTo = FullReplyTo(); - const auto viaBotId = UserId(); - const auto groupedId = uint64(); - const auto item = history->makeMessage( - history->nextNonHistoryEntryId(), - flags, - replyTo, - viaBotId, - base::unixtime::now(), - out ? history->session().userId() : peerToUser(history->peer->id), - QString(), - TextWithEntities{ text }, - MTP_messageMediaEmpty(), - HistoryMessageMarkupData(), - groupedId); + const auto item = history->makeMessage({ + .id = history->nextNonHistoryEntryId(), + .flags = (MessageFlag::FakeHistoryItem + | MessageFlag::HasFromId + | (out ? MessageFlag::Outgoing : MessageFlag(0))), + .from = (out + ? history->session().userId() + : peerToUser(history->peer->id)), + .date = base::unixtime::now(), + }, TextWithEntities{ text }, MTP_messageMediaEmpty()); return AdminLog::OwnedItem(delegate, item); } diff --git a/Telegram/SourceFiles/boxes/peers/edit_peer_color_box.cpp b/Telegram/SourceFiles/boxes/peers/edit_peer_color_box.cpp index 3f01fe269..2e24d2804 100644 --- a/Telegram/SourceFiles/boxes/peers/edit_peer_color_box.cpp +++ b/Telegram/SourceFiles/boxes/peers/edit_peer_color_box.cpp @@ -319,47 +319,36 @@ PreviewWrap::PreviewWrap( , _delegate(std::make_unique(box, _style.get(), [=] { update(); })) -, _replyToItem(_history->addNewLocalMessage( - _history->nextNonHistoryEntryId(), - (MessageFlag::FakeHistoryItem +, _replyToItem(_history->addNewLocalMessage({ + .id = _history->nextNonHistoryEntryId(), + .flags = (MessageFlag::FakeHistoryItem | MessageFlag::HasFromId | MessageFlag::Post), - UserId(), // via - FullReplyTo(), - base::unixtime::now(), // date - _fake->id, - QString(), // postAuthor - TextWithEntities{ _peer->isSelf() - ? tr::lng_settings_color_reply(tr::now) - : tr::lng_settings_color_reply_channel(tr::now), - }, - MTP_messageMediaEmpty(), - HistoryMessageMarkupData(), - uint64(0))) -, _replyItem(_history->addNewLocalMessage( - _history->nextNonHistoryEntryId(), - (MessageFlag::FakeHistoryItem + .from = _fake->id, + .date = base::unixtime::now(), +}, TextWithEntities{ _peer->isSelf() + ? tr::lng_settings_color_reply(tr::now) + : tr::lng_settings_color_reply_channel(tr::now), +}, MTP_messageMediaEmpty())) +, _replyItem(_history->addNewLocalMessage({ + .id = _history->nextNonHistoryEntryId(), + .flags = (MessageFlag::FakeHistoryItem | MessageFlag::HasFromId | MessageFlag::HasReplyInfo | MessageFlag::Post), - UserId(), // via - FullReplyTo{ .messageId = _replyToItem->fullId() }, - base::unixtime::now(), // date - _fake->id, - QString(), // postAuthor - TextWithEntities{ _peer->isSelf() - ? tr::lng_settings_color_text(tr::now) - : tr::lng_settings_color_text_channel(tr::now), - }, - MTP_messageMediaWebPage( + .from = _fake->id, + .replyTo = FullReplyTo{.messageId = _replyToItem->fullId() }, + .date = base::unixtime::now(), +}, TextWithEntities{ _peer->isSelf() + ? tr::lng_settings_color_text(tr::now) + : tr::lng_settings_color_text_channel(tr::now), +}, MTP_messageMediaWebPage( + MTP_flags(0), + MTP_webPagePending( MTP_flags(0), - MTP_webPagePending( - MTP_flags(0), - MTP_long(_webpage->id), - MTPstring(), - MTP_int(0))), - HistoryMessageMarkupData(), - uint64(0))) + MTP_long(_webpage->id), + MTPstring(), + MTP_int(0))))) , _element(_replyItem->createView(_delegate.get())) , _position(0, st::msgMargin.bottom()) { _style->apply(_theme.get()); diff --git a/Telegram/SourceFiles/boxes/reactions_settings_box.cpp b/Telegram/SourceFiles/boxes/reactions_settings_box.cpp index 4de09e882..e33624403 100644 --- a/Telegram/SourceFiles/boxes/reactions_settings_box.cpp +++ b/Telegram/SourceFiles/boxes/reactions_settings_box.cpp @@ -77,20 +77,15 @@ AdminLog::OwnedItem GenerateItem( const QString &text) { Expects(history->peer->isUser()); - const auto item = history->addNewLocalMessage( - history->nextNonHistoryEntryId(), - (MessageFlag::FakeHistoryItem + const auto item = history->addNewLocalMessage({ + .id = history->nextNonHistoryEntryId(), + .flags = (MessageFlag::FakeHistoryItem | MessageFlag::HasFromId | MessageFlag::HasReplyInfo), - UserId(), // via - FullReplyTo{ .messageId = replyTo }, - base::unixtime::now(), // date - from, - QString(), // postAuthor - TextWithEntities{ .text = text }, - MTP_messageMediaEmpty(), - HistoryMessageMarkupData(), - uint64(0)); // groupedId + .from = from, + .replyTo = FullReplyTo{ .messageId = replyTo }, + .date = base::unixtime::now(), + }, TextWithEntities{ .text = text }, MTP_messageMediaEmpty()); return AdminLog::OwnedItem(delegate, item); } diff --git a/Telegram/SourceFiles/data/business/data_shortcut_messages.cpp b/Telegram/SourceFiles/data/business/data_shortcut_messages.cpp index 1013c05bc..026e6a99e 100644 --- a/Telegram/SourceFiles/data/business/data_shortcut_messages.cpp +++ b/Telegram/SourceFiles/data/business/data_shortcut_messages.cpp @@ -27,13 +27,13 @@ constexpr auto kRequestTimeLimit = 60 * crl::time(1000); [[nodiscard]] MsgId RemoteToLocalMsgId(MsgId id) { Expects(IsServerMsgId(id)); - return ServerMaxMsgId + id + 1; + return ScheduledMaxMsgId + id + 1; } [[nodiscard]] MsgId LocalToRemoteMsgId(MsgId id) { Expects(IsShortcutMsgId(id)); - return (id - ServerMaxMsgId - 1); + return (id - ScheduledMaxMsgId - 1); } [[nodiscard]] bool TooEarlyForRequest(crl::time received) { @@ -145,6 +145,14 @@ int ShortcutMessages::count(BusinessShortcutId shortcutId) const { return (i != end(_data)) ? i->second.items.size() : 0; } +void ShortcutMessages::apply(const MTPDupdateQuickReplies &update) { + +} + +void ShortcutMessages::apply(const MTPDupdateNewQuickReply &update) { + +} + void ShortcutMessages::apply(const MTPDupdateQuickReplyMessage &update) { const auto &message = update.vmessage(); const auto shortcutId = BusinessShortcutIdFromMessage(message); diff --git a/Telegram/SourceFiles/data/business/data_shortcut_messages.h b/Telegram/SourceFiles/data/business/data_shortcut_messages.h index 2028f2ece..57997e7e0 100644 --- a/Telegram/SourceFiles/data/business/data_shortcut_messages.h +++ b/Telegram/SourceFiles/data/business/data_shortcut_messages.h @@ -50,6 +50,8 @@ public: [[nodiscard]] int count(BusinessShortcutId shortcutId) const; [[nodiscard]] MsgId localMessageId(MsgId remoteId) const; + void apply(const MTPDupdateQuickReplies &update); + void apply(const MTPDupdateNewQuickReply &update); void apply(const MTPDupdateQuickReplyMessage &update); void apply(const MTPDupdateDeleteQuickReplyMessages &update); void apply(const MTPDupdateDeleteQuickReply &update); diff --git a/Telegram/SourceFiles/data/data_download_manager.cpp b/Telegram/SourceFiles/data/data_download_manager.cpp index cd736e9e7..95c78092d 100644 --- a/Telegram/SourceFiles/data/data_download_manager.cpp +++ b/Telegram/SourceFiles/data/data_download_manager.cpp @@ -879,29 +879,20 @@ not_null DownloadManager::generateItem( const auto session = document ? &document->session() : &photo->session(); - const auto fromId = previousItem - ? previousItem->from()->id - : session->userPeerId(); const auto history = previousItem ? previousItem->history() : session->data().history(session->user()); - const auto flags = MessageFlag::FakeHistoryItem; - const auto replyTo = FullReplyTo(); - const auto viaBotId = UserId(); - const auto date = base::unixtime::now(); + ; const auto caption = TextWithEntities(); const auto make = [&](const auto media) { - return history->makeMessage( - history->nextNonHistoryEntryId(), - flags, - replyTo, - viaBotId, - date, - fromId, - QString(), - media, - caption, - HistoryMessageMarkupData()); + return history->makeMessage({ + .id = history->nextNonHistoryEntryId(), + .flags = MessageFlag::FakeHistoryItem, + .from = (previousItem + ? previousItem->from()->id + : session->userPeerId()), + .date = base::unixtime::now(), + }, media, caption); }; const auto result = document ? make(document) : make(photo); _generated.emplace(result); diff --git a/Telegram/SourceFiles/data/data_histories.cpp b/Telegram/SourceFiles/data/data_histories.cpp index 0dde157ad..a43b2f680 100644 --- a/Telegram/SourceFiles/data/data_histories.cpp +++ b/Telegram/SourceFiles/data/data_histories.cpp @@ -8,6 +8,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "data/data_histories.h" #include "api/api_text_entities.h" +#include "data/business/data_shortcut_messages.h" #include "data/data_session.h" #include "data/data_channel.h" #include "data/data_chat.h" @@ -821,6 +822,7 @@ void Histories::deleteMessages(const MessageIdsList &ids, bool revoke) { remove.reserve(ids.size()); base::flat_map, QVector> idsByPeer; base::flat_map, QVector> scheduledIdsByPeer; + base::flat_map> quickIdsByShortcut; for (const auto &itemId : ids) { if (const auto item = _owner->message(itemId)) { const auto history = item->history(); @@ -834,6 +836,16 @@ void Histories::deleteMessages(const MessageIdsList &ids, bool revoke) { _owner->scheduledMessages().removeSending(item); } continue; + } else if (item->isBusinessShortcut()) { + const auto wasOnServer = !item->isSending() + && !item->hasFailed(); + if (wasOnServer) { + quickIdsByShortcut[item->shortcutId()].push_back(MTP_int( + _owner->shortcutMessages().lookupId(item))); + } else { + _owner->shortcutMessages().removeSending(item); + } + continue; } remove.push_back(item); if (item->isRegular()) { @@ -853,6 +865,15 @@ void Histories::deleteMessages(const MessageIdsList &ids, bool revoke) { peer->session().api().applyUpdates(result); }).send(); } + for (const auto &[shortcutId, ids] : quickIdsByShortcut) { + const auto api = &_owner->session().api(); + api->request(MTPmessages_DeleteQuickReplyMessages( + MTP_int(shortcutId), + MTP_vector(ids) + )).done([=](const MTPUpdates &result) { + api->applyUpdates(result); + }).send(); + } for (const auto item : remove) { const auto history = item->history(); diff --git a/Telegram/SourceFiles/data/data_replies_list.cpp b/Telegram/SourceFiles/data/data_replies_list.cpp index 733a0ae05..5c1700093 100644 --- a/Telegram/SourceFiles/data/data_replies_list.cpp +++ b/Telegram/SourceFiles/data/data_replies_list.cpp @@ -34,11 +34,11 @@ constexpr auto kMaxMessagesToDeleteMyTopic = 10; not_null history, TimeId date, const QString &text) { - return history->makeMessage( - history->nextNonHistoryEntryId(), - MessageFlag::FakeHistoryItem, - date, - PreparedServiceText{ { .text = text } }); + return history->makeMessage({ + .id = history->nextNonHistoryEntryId(), + .flags = MessageFlag::FakeHistoryItem, + .date = date, + }, PreparedServiceText{ { .text = text } }); } [[nodiscard]] bool IsCreating(not_null history, MsgId rootId) { diff --git a/Telegram/SourceFiles/data/data_sponsored_messages.cpp b/Telegram/SourceFiles/data/data_sponsored_messages.cpp index 556bee6ce..fb6f03308 100644 --- a/Telegram/SourceFiles/data/data_sponsored_messages.cpp +++ b/Telegram/SourceFiles/data/data_sponsored_messages.cpp @@ -80,7 +80,7 @@ bool SponsoredMessages::append(not_null history) { entryIt->itemFullId = FullMsgId( history->peer->id, _session->data().nextLocalMessageId()); - entryIt->item.reset(history->addNewLocalMessage( + entryIt->item.reset(history->addSponsoredMessage( entryIt->itemFullId.msg, entryIt->sponsored.from, entryIt->sponsored.textWithEntities)); diff --git a/Telegram/SourceFiles/data/data_stories.cpp b/Telegram/SourceFiles/data/data_stories.cpp index a35279be4..0090ba369 100644 --- a/Telegram/SourceFiles/data/data_stories.cpp +++ b/Telegram/SourceFiles/data/data_stories.cpp @@ -970,7 +970,7 @@ std::shared_ptr Stories::resolveItem(not_null story) { } const auto history = _owner->history(story->peer()); auto result = std::shared_ptr( - history->makeMessage(story).get(), + history->makeMessage(StoryIdToMsgId(story->id()), story).get(), HistoryItem::Destroyer()); i->second = result; return result; diff --git a/Telegram/SourceFiles/data/data_types.h b/Telegram/SourceFiles/data/data_types.h index 176a13f74..ca11c8969 100644 --- a/Telegram/SourceFiles/data/data_types.h +++ b/Telegram/SourceFiles/data/data_types.h @@ -318,6 +318,8 @@ enum class MessageFlag : uint64 { Sponsored = (1ULL << 42), ReactionsAreTags = (1ULL << 43), + + ShortcutMessage = (1ULL << 44), }; inline constexpr bool is_flag_type(MessageFlag) { return true; } using MessageFlags = base::flags; diff --git a/Telegram/SourceFiles/history/admin_log/history_admin_log_item.cpp b/Telegram/SourceFiles/history/admin_log/history_admin_log_item.cpp index b71b0cd82..c54093dc3 100644 --- a/Telegram/SourceFiles/history/admin_log/history_admin_log_item.cpp +++ b/Telegram/SourceFiles/history/admin_log/history_admin_log_item.cpp @@ -801,13 +801,12 @@ void GenerateItems( auto message = PreparedServiceText{ text }; message.links.push_back(fromLink); addPart( - history->makeMessage( - history->nextNonHistoryEntryId(), - MessageFlag::AdminLogEntry, - date, - std::move(message), - peerToUser(from->id), - photo), + history->makeMessage({ + .id = history->nextNonHistoryEntryId(), + .flags = MessageFlag::AdminLogEntry, + .from = from->id, + .date = date, + }, std::move(message), photo), 0, realId); }; @@ -826,23 +825,11 @@ void GenerateItems( }; const auto makeSimpleTextMessage = [&](TextWithEntities &&text) { - const auto bodyFlags = MessageFlag::HasFromId - | MessageFlag::AdminLogEntry; - const auto bodyReplyTo = FullReplyTo(); - const auto bodyViaBotId = UserId(); - const auto bodyGroupedId = uint64(); - return history->makeMessage( - history->nextNonHistoryEntryId(), - bodyFlags, - bodyReplyTo, - bodyViaBotId, - date, - peerToUser(from->id), - QString(), - std::move(text), - MTP_messageMediaEmpty(), - HistoryMessageMarkupData(), - bodyGroupedId); + return history->makeMessage({ + .id = history->nextNonHistoryEntryId(), + .flags = MessageFlag::HasFromId | MessageFlag::AdminLogEntry, + .from = from->id, + }, std::move(text), MTP_messageMediaEmpty()); }; const auto addSimpleTextMessage = [&](TextWithEntities &&text) { @@ -1145,12 +1132,12 @@ void GenerateItems( auto message = PreparedServiceText{ text }; message.links.push_back(fromLink); message.links.push_back(setLink); - addPart(history->makeMessage( - history->nextNonHistoryEntryId(), - MessageFlag::AdminLogEntry, - date, - std::move(message), - peerToUser(from->id))); + addPart(history->makeMessage({ + .id = history->nextNonHistoryEntryId(), + .flags = MessageFlag::AdminLogEntry, + .from = from->id, + .date = date, + }, std::move(message))); } }; @@ -1189,12 +1176,12 @@ void GenerateItems( auto message = PreparedServiceText{ text }; message.links.push_back(fromLink); message.links.push_back(setLink); - addPart(history->makeMessage( - history->nextNonHistoryEntryId(), - MessageFlag::AdminLogEntry, - date, - std::move(message), - peerToUser(from->id))); + addPart(history->makeMessage({ + .id = history->nextNonHistoryEntryId(), + .flags = MessageFlag::AdminLogEntry, + .from = from->id, + .date = date, + }, std::move(message))); } }; @@ -1270,12 +1257,12 @@ void GenerateItems( auto message = PreparedServiceText{ text }; message.links.push_back(fromLink); message.links.push_back(chatLink); - addPart(history->makeMessage( - history->nextNonHistoryEntryId(), - MessageFlag::AdminLogEntry, - date, - std::move(message), - peerToUser(from->id))); + addPart(history->makeMessage({ + .id = history->nextNonHistoryEntryId(), + .flags = MessageFlag::AdminLogEntry, + .from = from->id, + .date = date, + }, std::move(message))); } }; @@ -1366,12 +1353,12 @@ void GenerateItems( auto message = PreparedServiceText{ text }; message.links.push_back(fromLink); message.links.push_back(link); - addPart(history->makeMessage( - history->nextNonHistoryEntryId(), - MessageFlag::AdminLogEntry, - date, - std::move(message), - peerToUser(from->id))); + addPart(history->makeMessage({ + .id = history->nextNonHistoryEntryId(), + .flags = MessageFlag::AdminLogEntry, + .from = from->id, + .date = date, + }, std::move(message))); }; const auto createParticipantMute = [&](const LogMute &data) { @@ -1441,13 +1428,12 @@ void GenerateItems( if (additional) { message.links.push_back(std::move(additional)); } - addPart(history->makeMessage( - history->nextNonHistoryEntryId(), - MessageFlag::AdminLogEntry, - date, - std::move(message), - peerToUser(from->id), - nullptr)); + addPart(history->makeMessage({ + .id = history->nextNonHistoryEntryId(), + .flags = MessageFlag::AdminLogEntry, + .from = from->id, + .date = date, + }, std::move(message))); }; const auto createParticipantJoinByInvite = [&]( diff --git a/Telegram/SourceFiles/history/history.cpp b/Telegram/SourceFiles/history/history.cpp index f5a9765c0..499bf7cea 100644 --- a/Telegram/SourceFiles/history/history.cpp +++ b/Telegram/SourceFiles/history/history.cpp @@ -18,6 +18,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "history/history_translation.h" #include "history/history_unread_things.h" #include "dialogs/ui/dialogs_layout.h" +#include "data/business/data_shortcut_messages.h" #include "data/notify/data_notify_settings.h" #include "data/stickers/data_stickers.h" #include "data/data_drafts.h" @@ -71,6 +72,12 @@ constexpr auto kSkipCloudDraftsFor = TimeId(2); using UpdateFlag = Data::HistoryUpdate::Flag; +[[nodiscard]] HistoryItemCommonFields WithLocalFlag( + HistoryItemCommonFields fields) { + fields.flags |= MessageFlag::Local; + return fields; +} + } // namespace History::History(not_null owner, PeerId peerId) @@ -446,17 +453,17 @@ std::vector> History::createItems( not_null History::addNewMessage( MsgId id, - const MTPMessage &msg, + const MTPMessage &message, MessageFlags localFlags, NewMessageType type) { - const auto detachExistingItem = (type == NewMessageType::Unread); - const auto item = createItem(id, msg, localFlags, detachExistingItem); + const auto detachExisting = (type == NewMessageType::Unread); + const auto item = createItem(id, message, localFlags, detachExisting); if (type == NewMessageType::Existing || item->mainView()) { return item; } const auto unread = (type == NewMessageType::Unread); if (unread && item->isHistoryEntry()) { - applyMessageChanges(item, msg); + applyMessageChanges(item, message); } return addNewItem(item, unread); } @@ -585,6 +592,9 @@ not_null History::addNewItem( if (item->isScheduled()) { owner().scheduledMessages().appendSending(item); return item; + } else if (item->isBusinessShortcut()) { + owner().shortcutMessages().appendSending(item); + return item; } else if (!item->isHistoryEntry()) { return item; } @@ -635,139 +645,54 @@ void History::checkForLoadedAtTop(not_null added) { } not_null History::addNewLocalMessage( - MsgId id, - MessageFlags flags, - UserId viaBotId, - FullReplyTo replyTo, - TimeId date, - PeerId from, - const QString &postAuthor, + HistoryItemCommonFields &&fields, const TextWithEntities &text, - const MTPMessageMedia &media, - HistoryMessageMarkupData &&markup, - uint64 groupedId) { + const MTPMessageMedia &media) { return addNewItem( - makeMessage( - id, - flags | MessageFlag::Local, - replyTo, - viaBotId, - date, - from, - postAuthor, - text, - media, - std::move(markup), - groupedId), + makeMessage(WithLocalFlag(std::move(fields)), text, media), true); } not_null History::addNewLocalMessage( - MsgId id, - MessageFlags flags, - TimeId date, - PeerId from, - const QString &postAuthor, - not_null forwardOriginal, - MsgId topicRootId) { + HistoryItemCommonFields &&fields, + not_null forwardOriginal) { return addNewItem( - makeMessage( - id, - flags | MessageFlag::Local, - date, - from, - postAuthor, - forwardOriginal, - topicRootId), + makeMessage(WithLocalFlag(std::move(fields)), forwardOriginal), true); } not_null History::addNewLocalMessage( - MsgId id, - MessageFlags flags, - UserId viaBotId, - FullReplyTo replyTo, - TimeId date, - PeerId from, - const QString &postAuthor, + HistoryItemCommonFields &&fields, not_null document, - const TextWithEntities &caption, - HistoryMessageMarkupData &&markup) { + const TextWithEntities &caption) { return addNewItem( - makeMessage( - id, - flags | MessageFlag::Local, - replyTo, - viaBotId, - date, - from, - postAuthor, - document, - caption, - std::move(markup)), + makeMessage(WithLocalFlag(std::move(fields)), document, caption), true); } not_null History::addNewLocalMessage( - MsgId id, - MessageFlags flags, - UserId viaBotId, - FullReplyTo replyTo, - TimeId date, - PeerId from, - const QString &postAuthor, + HistoryItemCommonFields &&fields, not_null photo, - const TextWithEntities &caption, - HistoryMessageMarkupData &&markup) { + const TextWithEntities &caption) { return addNewItem( - makeMessage( - id, - flags | MessageFlag::Local, - replyTo, - viaBotId, - date, - from, - postAuthor, - photo, - caption, - std::move(markup)), + makeMessage(WithLocalFlag(std::move(fields)), photo, caption), true); } not_null History::addNewLocalMessage( - MsgId id, - MessageFlags flags, - UserId viaBotId, - FullReplyTo replyTo, - TimeId date, - PeerId from, - const QString &postAuthor, - not_null game, - HistoryMessageMarkupData &&markup) { + HistoryItemCommonFields &&fields, + not_null game) { return addNewItem( - makeMessage( - id, - flags | MessageFlag::Local, - replyTo, - viaBotId, - date, - from, - postAuthor, - game, - std::move(markup)), + makeMessage(WithLocalFlag(std::move(fields)), game), true); } -not_null History::addNewLocalMessage( +not_null History::addSponsoredMessage( MsgId id, Data::SponsoredFrom from, const TextWithEntities &textWithEntities) { return addNewItem( - makeMessage( - id, - from, - textWithEntities, - nullptr), + makeMessage(id, from, textWithEntities, nullptr), true); } diff --git a/Telegram/SourceFiles/history/history.h b/Telegram/SourceFiles/history/history.h index adeb63fc2..29620dc2e 100644 --- a/Telegram/SourceFiles/history/history.h +++ b/Telegram/SourceFiles/history/history.h @@ -20,6 +20,7 @@ class History; class HistoryBlock; class HistoryTranslation; class HistoryItem; +struct HistoryItemCommonFields; struct HistoryMessageMarkupData; class HistoryMainElementDelegateMixin; struct LanguageId; @@ -127,11 +128,23 @@ public: void applyGroupAdminChanges(const base::flat_set &changes); template - not_null makeMessage(Args &&...args) { + not_null makeMessage(MsgId id, Args &&...args) { return static_cast( insertItem( std::make_unique( this, + id, + std::forward(args)...)).get()); + } + template + not_null makeMessage( + HistoryItemCommonFields &&fields, + Args &&...args) { + return static_cast( + insertItem( + std::make_unique( + this, + std::move(fields), std::forward(args)...)).get()); } @@ -143,62 +156,30 @@ public: not_null addNewMessage( MsgId id, - const MTPMessage &msg, + const MTPMessage &message, MessageFlags localFlags, NewMessageType type); + not_null addNewLocalMessage( - MsgId id, - MessageFlags flags, - UserId viaBotId, - FullReplyTo replyTo, - TimeId date, - PeerId from, - const QString &postAuthor, + HistoryItemCommonFields &&fields, const TextWithEntities &text, - const MTPMessageMedia &media, - HistoryMessageMarkupData &&markup, - uint64 groupedId = 0); + const MTPMessageMedia &media); not_null addNewLocalMessage( - MsgId id, - MessageFlags flags, - TimeId date, - PeerId from, - const QString &postAuthor, - not_null forwardOriginal, - MsgId topicRootId); + HistoryItemCommonFields &&fields, + not_null forwardOriginal); not_null addNewLocalMessage( - MsgId id, - MessageFlags flags, - UserId viaBotId, - FullReplyTo replyTo, - TimeId date, - PeerId from, - const QString &postAuthor, + HistoryItemCommonFields &&fields, not_null document, - const TextWithEntities &caption, - HistoryMessageMarkupData &&markup); + const TextWithEntities &caption); not_null addNewLocalMessage( - MsgId id, - MessageFlags flags, - UserId viaBotId, - FullReplyTo replyTo, - TimeId date, - PeerId from, - const QString &postAuthor, + HistoryItemCommonFields &&fields, not_null photo, - const TextWithEntities &caption, - HistoryMessageMarkupData &&markup); - not_null addNewLocalMessage( - MsgId id, - MessageFlags flags, - UserId viaBotId, - FullReplyTo replyTo, - TimeId date, - PeerId from, - const QString &postAuthor, - not_null game, - HistoryMessageMarkupData &&markup); + const TextWithEntities &caption); not_null addNewLocalMessage( + HistoryItemCommonFields &&fields, + not_null game); + + not_null addSponsoredMessage( MsgId id, Data::SponsoredFrom from, const TextWithEntities &textWithEntities); // sponsored diff --git a/Telegram/SourceFiles/history/history_item.cpp b/Telegram/SourceFiles/history/history_item.cpp index aa815ccc9..1f75a47d8 100644 --- a/Telegram/SourceFiles/history/history_item.cpp +++ b/Telegram/SourceFiles/history/history_item.cpp @@ -125,6 +125,14 @@ template return false; } +[[nodiscard]] HistoryItemCommonFields ForwardedFields( + HistoryItemCommonFields fields, + not_null history, + not_null original) { + fields.flags |= NewForwardedFlags(history->peer, fields.from, original); + return fields; +} + } // namespace void HistoryItem::HistoryItem::Destroyer::operator()(HistoryItem *value) { @@ -347,12 +355,13 @@ HistoryItem::HistoryItem( MsgId id, const MTPDmessage &data, MessageFlags localFlags) -: HistoryItem( - history, - id, - FlagsFromMTP(id, data.vflags().v, localFlags), - data.vdate().v, - data.vfrom_id() ? peerFromMTP(*data.vfrom_id()) : PeerId(0)) { +: HistoryItem(history, { + .id = id, + .flags = FlagsFromMTP(id, data.vflags().v, localFlags), + .from = data.vfrom_id() ? peerFromMTP(*data.vfrom_id()) : PeerId(0), + .date = data.vdate().v, + .shortcutId = data.vquick_reply_shortcut_id().value_or_empty(), +}) { _boostsApplied = data.vfrom_boosts_applied().value_or_empty(); const auto media = data.vmedia(); @@ -406,12 +415,12 @@ HistoryItem::HistoryItem( MsgId id, const MTPDmessageService &data, MessageFlags localFlags) -: HistoryItem( - history, - id, - FlagsFromMTP(id, data.vflags().v, localFlags), - data.vdate().v, - data.vfrom_id() ? peerFromMTP(*data.vfrom_id()) : PeerId(0)) { +: HistoryItem(history, { + .id = id, + .flags = FlagsFromMTP(id, data.vflags().v, localFlags), + .from = data.vfrom_id() ? peerFromMTP(*data.vfrom_id()) : PeerId(0), + .date = data.vdate().v, +}) { if (data.vaction().type() != mtpc_messageActionPhoneCall) { createServiceFromMtp(data); } else { @@ -431,9 +440,7 @@ HistoryItem::HistoryItem( MessageFlags localFlags) : HistoryItem( history, - id, - localFlags, - TimeId(0), + { .id = id, .flags = localFlags }, PreparedServiceText{ tr::lng_message_empty( tr::now, Ui::Text::WithEntities) }) { @@ -441,13 +448,10 @@ HistoryItem::HistoryItem( HistoryItem::HistoryItem( not_null history, - MsgId id, - MessageFlags flags, - TimeId date, + HistoryItemCommonFields &&fields, PreparedServiceText &&message, - PeerId from, PhotoData *photo) -: HistoryItem(history, id, flags, date, from) { +: HistoryItem(history, fields) { setServiceText(std::move(message)); if (photo) { _media = std::make_unique( @@ -459,25 +463,16 @@ HistoryItem::HistoryItem( HistoryItem::HistoryItem( not_null history, - MsgId id, - MessageFlags flags, - TimeId date, - PeerId from, - const QString &postAuthor, - not_null original, - MsgId topicRootId) -: HistoryItem( - history, - id, - (NewForwardedFlags(history->peer, from, original) | flags), - date, - from) { + HistoryItemCommonFields &&fields, + not_null original) +: HistoryItem(history, ForwardedFields(fields, history, original)) { const auto peer = history->peer; auto config = CreateConfig(); const auto originalMedia = original->media(); const auto dropForwardInfo = original->computeDropForwardedInfo(); + const auto topicRootId = fields.replyTo.topicRootId; config.reply.messageId = config.reply.topMessageId = topicRootId; config.reply.topicPost = (topicRootId != 0) ? 1 : 0; if (const auto originalReply = original->Get()) { @@ -520,8 +515,8 @@ HistoryItem::HistoryItem( ? original->author()->id : PeerId(); } - if (flags & MessageFlag::HasPostAuthor) { - config.postAuthor = postAuthor; + if (_flags & MessageFlag::HasPostAuthor) { + config.postAuthor = fields.postAuthor; } if (const auto fwdViaBot = original->viaBot()) { config.viaBotId = peerToUser(fwdViaBot->id); @@ -571,63 +566,28 @@ HistoryItem::HistoryItem( HistoryItem::HistoryItem( not_null history, - MsgId id, - MessageFlags flags, - FullReplyTo replyTo, - UserId viaBotId, - TimeId date, - PeerId from, - const QString &postAuthor, + HistoryItemCommonFields &&fields, const TextWithEntities &textWithEntities, - const MTPMessageMedia &media, - HistoryMessageMarkupData &&markup, - uint64 groupedId) -: HistoryItem( - history, - id, - flags, - date, - (flags & MessageFlag::HasFromId) ? from : 0) { - createComponentsHelper( - flags, - replyTo, - viaBotId, - postAuthor, - std::move(markup)); + const MTPMessageMedia &media) +: HistoryItem(history, fields) { + createComponentsHelper(std::move(fields)); setMedia(media); setText(textWithEntities); - if (groupedId) { + if (fields.groupedId) { setGroupId(MessageGroupId::FromRaw( history->peer->id, - groupedId, - flags & MessageFlag::IsOrWasScheduled)); + fields.groupedId, + _flags & MessageFlag::IsOrWasScheduled)); } } HistoryItem::HistoryItem( not_null history, - MsgId id, - MessageFlags flags, - FullReplyTo replyTo, - UserId viaBotId, - TimeId date, - PeerId from, - const QString &postAuthor, + HistoryItemCommonFields &&fields, not_null document, - const TextWithEntities &caption, - HistoryMessageMarkupData &&markup) -: HistoryItem( - history, - id, - flags, - date, - (flags & MessageFlag::HasFromId) ? from : 0) { - createComponentsHelper( - flags, - replyTo, - viaBotId, - postAuthor, - std::move(markup)); + const TextWithEntities &caption) +: HistoryItem(history, fields) { + createComponentsHelper(std::move(fields)); const auto skipPremiumEffect = !history->session().premium(); const auto spoiler = false; @@ -642,28 +602,11 @@ HistoryItem::HistoryItem( HistoryItem::HistoryItem( not_null history, - MsgId id, - MessageFlags flags, - FullReplyTo replyTo, - UserId viaBotId, - TimeId date, - PeerId from, - const QString &postAuthor, + HistoryItemCommonFields &&fields, not_null photo, - const TextWithEntities &caption, - HistoryMessageMarkupData &&markup) -: HistoryItem( - history, - id, - flags, - date, - (flags & MessageFlag::HasFromId) ? from : 0) { - createComponentsHelper( - flags, - replyTo, - viaBotId, - postAuthor, - std::move(markup)); + const TextWithEntities &caption) +: HistoryItem(history, fields) { + createComponentsHelper(std::move(fields)); const auto spoiler = false; _media = std::make_unique(this, photo, spoiler); @@ -672,27 +615,10 @@ HistoryItem::HistoryItem( HistoryItem::HistoryItem( not_null history, - MsgId id, - MessageFlags flags, - FullReplyTo replyTo, - UserId viaBotId, - TimeId date, - PeerId from, - const QString &postAuthor, - not_null game, - HistoryMessageMarkupData &&markup) -: HistoryItem( - history, - id, - flags, - date, - (flags & MessageFlag::HasFromId) ? from : 0) { - createComponentsHelper( - flags, - replyTo, - viaBotId, - postAuthor, - std::move(markup)); + HistoryItemCommonFields &&fields, + not_null game) +: HistoryItem(history, fields) { + createComponentsHelper(std::move(fields)); _media = std::make_unique(this, game); setTextValue({}); @@ -704,18 +630,15 @@ HistoryItem::HistoryItem( Data::SponsoredFrom from, const TextWithEntities &textWithEntities, HistoryItem *injectedAfter) -: HistoryItem( - history, - id, - ((history->peer->isChannel() ? MessageFlag::Post : MessageFlag(0)) - //| (from.peer ? MessageFlag::HasFromId : MessageFlag(0)) - | MessageFlag::Local), - HistoryItem::NewMessageDate(injectedAfter - ? injectedAfter->date() - : 0), - /*from.peer ? from.peer->id : */PeerId(0)) { - _flags |= MessageFlag::Sponsored; - +: HistoryItem(history, { + .id = id, + .flags = (MessageFlag::Local + | MessageFlag::Sponsored + | (history->peer->isChannel() ? MessageFlag::Post : MessageFlag(0))), + .date = HistoryItem::NewMessageDate(injectedAfter + ? injectedAfter->date() + : 0), +}) { const auto webPageType = !from.externalLink.isEmpty() ? WebPageType::None : from.isExactPost @@ -758,15 +681,15 @@ HistoryItem::HistoryItem( HistoryItem::HistoryItem( not_null history, - MsgId id, - MessageFlags flags, - TimeId date, - PeerId from) -: id(id) + const HistoryItemCommonFields &fields) +: id(fields.id) , _history(history) -, _from(from ? history->owner().peer(from) : history->peer) -, _flags(FinalizeMessageFlags(history, flags)) -, _date(date) { +, _from((fields.flags & MessageFlag::HasFromId && fields.from) + ? history->owner().peer(fields.from) + : history->peer) +, _flags(FinalizeMessageFlags(history, fields.flags)) +, _date(fields.date) +, _shortcutId(fields.shortcutId) { if (isHistoryEntry() && IsClientMsgId(id)) { _history->registerClientSideMessage(this); } @@ -774,15 +697,18 @@ HistoryItem::HistoryItem( HistoryItem::HistoryItem( not_null history, + MsgId id, not_null story) -: id(StoryIdToMsgId(story->id())) -, _history(history) -, _from(history->peer) -, _flags(MessageFlag::Local - | MessageFlag::Outgoing - | MessageFlag::FakeHistoryItem - | MessageFlag::StoryItem) -, _date(story->date()) { +: HistoryItem(history, { + .id = id, + .flags = (MessageFlag::Local + | MessageFlag::Outgoing + | MessageFlag::HasFromId + | MessageFlag::FakeHistoryItem + | MessageFlag::StoryItem), + .from = history->peer->id, + .date = story->date(), +}) { setStoryFields(story); } @@ -807,6 +733,11 @@ TimeId HistoryItem::NewMessageDate(TimeId scheduled) { return scheduled ? scheduled : base::unixtime::now(); } +TimeId HistoryItem::NewMessageDate( + const Api::SendOptions &options) { + return options.shortcutId ? TimeId() : NewMessageDate(options.scheduled); +} + HistoryServiceDependentData *HistoryItem::GetServiceDependentData() { if (const auto pinned = Get()) { return pinned; @@ -1603,6 +1534,14 @@ bool HistoryItem::isUserpicSuggestion() const { return (_flags & MessageFlag::IsUserpicSuggestion); } +BusinessShortcutId HistoryItem::shortcutId() const { + return _shortcutId; +} + +bool HistoryItem::isBusinessShortcut() const { + return _shortcutId != 0; +} + void HistoryItem::destroy() { _history->destroyMessage(this); } @@ -3520,15 +3459,11 @@ TextWithEntities HistoryItem::withLocalEntities( return textWithEntities; } -void HistoryItem::createComponentsHelper( - MessageFlags flags, - FullReplyTo replyTo, - UserId viaBotId, - const QString &postAuthor, - HistoryMessageMarkupData &&markup) { +void HistoryItem::createComponentsHelper(HistoryItemCommonFields &&fields) { + const auto &replyTo = fields.replyTo; auto config = CreateConfig(); - config.viaBotId = viaBotId; - if (flags & MessageFlag::HasReplyInfo) { + config.viaBotId = fields.viaBotId; + if (fields.flags & MessageFlag::HasReplyInfo) { config.reply.messageId = replyTo.messageId.msg; config.reply.storyId = replyTo.storyId.story; config.reply.externalPeerId = replyTo.storyId @@ -3567,9 +3502,13 @@ void HistoryItem::createComponentsHelper( config.reply.quoteOffset = replyTo.quoteOffset; config.reply.quote = std::move(replyTo.quote); } - config.markup = std::move(markup); - if (flags & MessageFlag::HasPostAuthor) config.postAuthor = postAuthor; - if (flags & MessageFlag::HasViews) config.viewsCount = 1; + config.markup = std::move(fields.markup); + if (fields.flags & MessageFlag::HasPostAuthor) { + config.postAuthor = fields.postAuthor; + } + if (fields.flags & MessageFlag::HasViews) { + config.viewsCount = 1; + } createComponents(std::move(config)); } diff --git a/Telegram/SourceFiles/history/history_item.h b/Telegram/SourceFiles/history/history_item.h index febc8d67c..f287bb039 100644 --- a/Telegram/SourceFiles/history/history_item.h +++ b/Telegram/SourceFiles/history/history_item.h @@ -15,6 +15,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL class HiddenSenderInfo; class History; + struct HistoryMessageReply; struct HistoryMessageViews; struct HistoryMessageMarkupData; @@ -28,6 +29,10 @@ struct PreparedServiceText; class ReplyKeyboard; struct LanguageId; +namespace Api { +struct SendOptions; +} // namespace Api + namespace base { template class enum_mask; @@ -86,6 +91,19 @@ class Service; class ServiceMessagePainter; } // namespace HistoryView +struct HistoryItemCommonFields { + MsgId id = 0; + MessageFlags flags = 0; + PeerId from = 0; + FullReplyTo replyTo; + TimeId date = 0; + BusinessShortcutId shortcutId = 0; + UserId viaBotId = 0; + QString postAuthor; + uint64 groupedId = 0; + HistoryMessageMarkupData markup; +}; + class HistoryItem final : public RuntimeComposer { public: [[nodiscard]] static std::unique_ptr CreateMedia( @@ -114,73 +132,39 @@ public: Data::SponsoredFrom from, const TextWithEntities &textWithEntities, HistoryItem *injectedAfter); + HistoryItem( // Story wrap. + not_null history, + MsgId id, + not_null story); HistoryItem( // Local message. not_null history, - MsgId id, - MessageFlags flags, - FullReplyTo replyTo, - UserId viaBotId, - TimeId date, - PeerId from, - const QString &postAuthor, + HistoryItemCommonFields &&fields, const TextWithEntities &textWithEntities, - const MTPMessageMedia &media, - HistoryMessageMarkupData &&markup, - uint64 groupedId); + const MTPMessageMedia &media); HistoryItem( // Local service message. not_null history, - MsgId id, - MessageFlags flags, - TimeId date, + HistoryItemCommonFields &&fields, PreparedServiceText &&message, - PeerId from = 0, PhotoData *photo = nullptr); HistoryItem( // Local forwarded. not_null history, - MsgId id, - MessageFlags flags, - TimeId date, - PeerId from, - const QString &postAuthor, - not_null original, - MsgId topicRootId); + HistoryItemCommonFields &&fields, + not_null original); HistoryItem( // Local photo. not_null history, - MsgId id, - MessageFlags flags, - FullReplyTo replyTo, - UserId viaBotId, - TimeId date, - PeerId from, - const QString &postAuthor, + HistoryItemCommonFields &&fields, not_null photo, - const TextWithEntities &caption, - HistoryMessageMarkupData &&markup); + const TextWithEntities &caption); HistoryItem( // Local document. not_null history, - MsgId id, - MessageFlags flags, - FullReplyTo replyTo, - UserId viaBotId, - TimeId date, - PeerId from, - const QString &postAuthor, + HistoryItemCommonFields &&fields, not_null document, - const TextWithEntities &caption, - HistoryMessageMarkupData &&markup); + const TextWithEntities &caption); HistoryItem( // Local game. not_null history, - MsgId id, - MessageFlags flags, - FullReplyTo replyTo, - UserId viaBotId, - TimeId date, - PeerId from, - const QString &postAuthor, - not_null game, - HistoryMessageMarkupData &&markup); - HistoryItem(not_null history, not_null story); + HistoryItemCommonFields &&fields, + not_null game); ~HistoryItem(); struct Destroyer { @@ -210,12 +194,8 @@ public: [[nodiscard]] bool isSponsored() const; [[nodiscard]] bool skipNotification() const; [[nodiscard]] bool isUserpicSuggestion() const; - [[nodiscard]] BusinessShortcutId shortcutId() const { - return _shortcutId; - } - [[nodiscard]] bool isBusinessShortcut() const { - return _shortcutId != 0; - } + [[nodiscard]] BusinessShortcutId shortcutId() const; + [[nodiscard]] bool isBusinessShortcut() const; void addLogEntryOriginal( WebPageId localId, @@ -473,6 +453,8 @@ public: [[nodiscard]] TimeId date() const; [[nodiscard]] static TimeId NewMessageDate(TimeId scheduled); + [[nodiscard]] static TimeId NewMessageDate( + const Api::SendOptions &options); [[nodiscard]] Data::Media *media() const { return _media.get(); @@ -554,17 +536,9 @@ private: HistoryItem( not_null history, - MsgId id, - MessageFlags flags, - TimeId date, - PeerId from); + const HistoryItemCommonFields &fields); - void createComponentsHelper( - MessageFlags flags, - FullReplyTo replyTo, - UserId viaBotId, - const QString &postAuthor, - HistoryMessageMarkupData &&markup); + void createComponentsHelper(HistoryItemCommonFields &&fields); void createComponents(CreateConfig &&config); void setupForwardedComponent(const CreateConfig &config); diff --git a/Telegram/SourceFiles/history/history_item_components.cpp b/Telegram/SourceFiles/history/history_item_components.cpp index ae6d3dc3a..ee5d1d21f 100644 --- a/Telegram/SourceFiles/history/history_item_components.cpp +++ b/Telegram/SourceFiles/history/history_item_components.cpp @@ -301,6 +301,7 @@ ReplyFields ReplyFieldsFromMTP( if (const auto id = data.vreply_to_msg_id().value_or_empty()) { result.messageId = data.is_reply_to_scheduled() ? owner->scheduledMessages().localMessageId(id) + AssertIsDebug() : id; result.topMessageId = data.vreply_to_top_id().value_or(id); diff --git a/Telegram/SourceFiles/history/history_item_helpers.cpp b/Telegram/SourceFiles/history/history_item_helpers.cpp index 752560a7f..65153bf86 100644 --- a/Telegram/SourceFiles/history/history_item_helpers.cpp +++ b/Telegram/SourceFiles/history/history_item_helpers.cpp @@ -386,6 +386,9 @@ MessageFlags FlagsFromMTP( | ((flags & MTP::f_from_id) ? Flag::HasFromId : Flag()) | ((flags & MTP::f_reply_to) ? Flag::HasReplyInfo : Flag()) | ((flags & MTP::f_reply_markup) ? Flag::HasReplyMarkup : Flag()) + | ((flags & MTP::f_quick_reply_shortcut_id) + ? Flag::ShortcutMessage + : Flag()) | ((flags & MTP::f_from_scheduled) ? Flag::IsOrWasScheduled : Flag()) @@ -598,11 +601,11 @@ not_null GenerateJoinedMessage( TimeId inviteDate, not_null inviter, bool viaRequest) { - return history->makeMessage( - history->owner().nextLocalMessageId(), - MessageFlag::Local | MessageFlag::ShowSimilarChannels, - inviteDate, - GenerateJoinedText(history, inviter, viaRequest)); + return history->makeMessage({ + .id = history->owner().nextLocalMessageId(), + .flags = MessageFlag::Local | MessageFlag::ShowSimilarChannels, + .date = inviteDate, + }, GenerateJoinedText(history, inviter, viaRequest)); } std::optional PeerHasThisCall( @@ -657,6 +660,7 @@ std::optional PeerHasThisCall( MessageFlags flags) { if (!(flags & MessageFlag::FakeHistoryItem) && !(flags & MessageFlag::IsOrWasScheduled) + && !(flags & MessageFlag::ShortcutMessage) && !(flags & MessageFlag::AdminLogEntry)) { flags |= MessageFlag::HistoryEntry; if (history->peer->isSelf()) { diff --git a/Telegram/SourceFiles/history/view/controls/history_view_draft_options.cpp b/Telegram/SourceFiles/history/view/controls/history_view_draft_options.cpp index 5ba81cd1e..a0d3d6066 100644 --- a/Telegram/SourceFiles/history/view/controls/history_view_draft_options.cpp +++ b/Telegram/SourceFiles/history/view/controls/history_view_draft_options.cpp @@ -257,38 +257,32 @@ rpl::producer PreviewWrap::showLinkSelector( was->destroy(); } using Flag = MTPDmessageMediaWebPage::Flag; - _draftItem = _history->addNewLocalMessage( - _history->nextNonHistoryEntryId(), - (MessageFlag::FakeHistoryItem + _draftItem = _history->addNewLocalMessage({ + .id = _history->nextNonHistoryEntryId(), + .flags = (MessageFlag::FakeHistoryItem | MessageFlag::Outgoing | MessageFlag::HasFromId | (webpage.invert ? MessageFlag::InvertMedia : MessageFlag())), - UserId(), // via - FullReplyTo(), - base::unixtime::now(), // date - _history->session().userPeerId(), - QString(), // postAuthor - HighlightParsedLinks({ - message.text, - TextUtilities::ConvertTextTagsToEntities(message.tags), - }, links), - MTP_messageMediaWebPage( - MTP_flags(Flag() - | (webpage.forceLargeMedia - ? Flag::f_force_large_media - : Flag()) - | (webpage.forceSmallMedia - ? Flag::f_force_small_media - : Flag())), - MTP_webPagePending( - MTP_flags(webpage.url.isEmpty() - ? MTPDwebPagePending::Flag() - : MTPDwebPagePending::Flag::f_url), - MTP_long(webpage.id), - MTP_string(webpage.url), - MTP_int(0))), - HistoryMessageMarkupData(), - uint64(0)); // groupedId + .from = _history->session().userPeerId(), + .date = base::unixtime::now(), + }, HighlightParsedLinks({ + message.text, + TextUtilities::ConvertTextTagsToEntities(message.tags), + }, links), MTP_messageMediaWebPage( + MTP_flags(Flag() + | (webpage.forceLargeMedia + ? Flag::f_force_large_media + : Flag()) + | (webpage.forceSmallMedia + ? Flag::f_force_small_media + : Flag())), + MTP_webPagePending( + MTP_flags(webpage.url.isEmpty() + ? MTPDwebPagePending::Flag() + : MTPDwebPagePending::Flag::f_url), + MTP_long(webpage.id), + MTP_string(webpage.url), + MTP_int(0)))); _element = _draftItem->createView(_delegate.get()); _selectType = TextSelectType::Letters; _symbol = _selectionStartSymbol = 0; diff --git a/Telegram/SourceFiles/history/view/history_view_about_view.cpp b/Telegram/SourceFiles/history/view/history_view_about_view.cpp index 51ae055f3..c017d8842 100644 --- a/Telegram/SourceFiles/history/view/history_view_about_view.cpp +++ b/Telegram/SourceFiles/history/view/history_view_about_view.cpp @@ -188,54 +188,39 @@ bool AboutView::refresh() { } AdminLog::OwnedItem AboutView::makeAboutBot(not_null info) { - const auto flags = MessageFlag::FakeAboutView - | MessageFlag::FakeHistoryItem - | MessageFlag::Local; - const auto postAuthor = QString(); - const auto date = TimeId(0); - const auto replyTo = FullReplyTo(); - const auto viaBotId = UserId(0); - const auto groupedId = uint64(0); const auto textWithEntities = TextUtilities::ParseEntities( info->description, Ui::ItemTextBotNoMonoOptions().flags); - const auto make = [&](auto &&a, auto &&b, auto &&...other) { - return _history->makeMessage( - _history->nextNonHistoryEntryId(), - flags, - replyTo, - viaBotId, - date, - _history->peer->id, - postAuthor, - std::forward(a), - std::forward(b), - HistoryMessageMarkupData(), - std::forward(other)...); + const auto make = [&](auto &&...args) { + return _history->makeMessage({ + .id = _history->nextNonHistoryEntryId(), + .flags = (MessageFlag::FakeAboutView + | MessageFlag::FakeHistoryItem + | MessageFlag::Local), + .from = _history->peer->id, + }, std::forward(args)...); }; const auto item = info->document ? make(info->document, textWithEntities) : info->photo ? make(info->photo, textWithEntities) - : make(textWithEntities, MTP_messageMediaEmpty(), groupedId); + : make(textWithEntities, MTP_messageMediaEmpty()); return AdminLog::OwnedItem(_delegate, item); } AdminLog::OwnedItem AboutView::makePremiumRequired() { - const auto flags = MessageFlag::FakeAboutView - | MessageFlag::FakeHistoryItem - | MessageFlag::Local; - const auto date = TimeId(0); - const auto item = _history->makeMessage( - _history->nextNonHistoryEntryId(), - flags, - date, - PreparedServiceText{ tr::lng_send_non_premium_text( - tr::now, - lt_user, - Ui::Text::Bold(_history->peer->shortName()), - Ui::Text::RichLangValue) }, - peerToUser(_history->peer->id)); + const auto item = _history->makeMessage({ + .id = _history->nextNonHistoryEntryId(), + .flags = (MessageFlag::FakeAboutView + | MessageFlag::FakeHistoryItem + | MessageFlag::Local), + .from = _history->peer->id, + }, PreparedServiceText{ tr::lng_send_non_premium_text( + tr::now, + lt_user, + Ui::Text::Bold(_history->peer->shortName()), + Ui::Text::RichLangValue), + }); auto result = AdminLog::OwnedItem(_delegate, item); result->overrideMedia(std::make_unique( result.get(), diff --git a/Telegram/SourceFiles/history/view/history_view_element.h b/Telegram/SourceFiles/history/view/history_view_element.h index 0f15a0fef..5a6ea07d6 100644 --- a/Telegram/SourceFiles/history/view/history_view_element.h +++ b/Telegram/SourceFiles/history/view/history_view_element.h @@ -59,6 +59,7 @@ enum class Context : char { ContactPreview, SavedSublist, TTLViewer, + ShortcutMessages, }; enum class OnlyEmojiAndSpaces : char { diff --git a/Telegram/SourceFiles/history/view/history_view_list_widget.cpp b/Telegram/SourceFiles/history/view/history_view_list_widget.cpp index 393284d32..3c09635a1 100644 --- a/Telegram/SourceFiles/history/view/history_view_list_widget.cpp +++ b/Telegram/SourceFiles/history/view/history_view_list_widget.cpp @@ -1792,7 +1792,7 @@ void ListWidget::updateItemsGeometry() { if (view->isHidden()) { view->setDisplayDate(false); } else { - view->setDisplayDate(true); + view->setDisplayDate(_context != Context::ShortcutMessages); view->setAttachToPrevious(false); return i; } @@ -2048,7 +2048,8 @@ void ListWidget::checkActivation() { } void ListWidget::paintEvent(QPaintEvent *e) { - if (_controller->contentOverlapped(this, e)) { + if ((_context != Context::ShortcutMessages) + && _controller->contentOverlapped(this, e)) { return; } @@ -3737,7 +3738,8 @@ void ListWidget::refreshAttachmentsFromTill(int from, int till) { } else { const auto viewDate = view->dateTime(); const auto nextDate = next->dateTime(); - next->setDisplayDate(nextDate.date() != viewDate.date()); + next->setDisplayDate(_context != Context::ShortcutMessages + && nextDate.date() != viewDate.date()); auto attached = next->computeIsAttachToPrevious(view); next->setAttachToPrevious(attached, view); view->setAttachToNext(attached, next); diff --git a/Telegram/SourceFiles/history/view/history_view_list_widget.h b/Telegram/SourceFiles/history/view/history_view_list_widget.h index ebba2f578..2e2fdbae7 100644 --- a/Telegram/SourceFiles/history/view/history_view_list_widget.h +++ b/Telegram/SourceFiles/history/view/history_view_list_widget.h @@ -631,11 +631,11 @@ private: const not_null _delegate; const not_null _controller; const std::unique_ptr _emojiInteractions; + const Context _context; Data::MessagePosition _aroundPosition; Data::MessagePosition _shownAtPosition; Data::MessagePosition _initialAroundPosition; - Context _context; int _aroundIndex = -1; int _idsLimit = kMinimalIdsLimit; Data::MessagesSlice _slice; diff --git a/Telegram/SourceFiles/history/view/history_view_message.cpp b/Telegram/SourceFiles/history/view/history_view_message.cpp index 4eafd53e5..f08ed8414 100644 --- a/Telegram/SourceFiles/history/view/history_view_message.cpp +++ b/Telegram/SourceFiles/history/view/history_view_message.cpp @@ -2061,6 +2061,7 @@ bool Message::hasFromPhoto() const { return !item->out() && !item->history()->peer->isUser(); } break; case Context::ContactPreview: + case Context::ShortcutMessages: return false; } Unexpected("Context in Message::hasFromPhoto."); @@ -3268,6 +3269,7 @@ bool Message::hasFromName() const { return false; } break; case Context::ContactPreview: + case Context::ShortcutMessages: return false; } Unexpected("Context in Message::hasFromName."); @@ -3306,6 +3308,9 @@ bool Message::hasOutLayout() const { const auto item = data(); if (item->history()->peer->isSelf()) { if (const auto forwarded = item->Get()) { + if (context() == Context::ShortcutMessages) { + return true; + } return (context() == Context::SavedSublist) && (!forwarded->forwardOfForward() ? (forwarded->originalSender diff --git a/Telegram/SourceFiles/inline_bots/inline_bot_result.cpp b/Telegram/SourceFiles/inline_bots/inline_bot_result.cpp index 339b40eaf..5931c22c4 100644 --- a/Telegram/SourceFiles/inline_bots/inline_bot_result.cpp +++ b/Telegram/SourceFiles/inline_bots/inline_bot_result.cpp @@ -17,6 +17,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "data/data_photo_media.h" #include "data/data_document_media.h" #include "history/history.h" +#include "history/history_item.h" #include "history/history_item_reply_markup.h" #include "inline_bots/inline_bot_layout_item.h" #include "inline_bots/inline_bot_send_data.h" @@ -376,30 +377,15 @@ bool Result::hasThumbDisplay() const { void Result::addToHistory( not_null history, - MessageFlags flags, - MsgId msgId, - PeerId fromId, - TimeId date, - UserId viaBotId, - FullReplyTo replyTo, - const QString &postAuthor) const { - flags |= MessageFlag::FromInlineBot; - - auto markup = _replyMarkup ? *_replyMarkup : HistoryMessageMarkupData(); - if (!markup.isNull()) { - flags |= MessageFlag::HasReplyMarkup; + HistoryItemCommonFields &&fields) const { + fields.flags |= MessageFlag::FromInlineBot; + if (_replyMarkup) { + fields.markup = *_replyMarkup; + if (!fields.markup.isNull()) { + fields.flags |= MessageFlag::HasReplyMarkup; + } } - sendData->addToHistory( - this, - history, - flags, - msgId, - fromId, - date, - viaBotId, - replyTo, - postAuthor, - std::move(markup)); + sendData->addToHistory(this, history, std::move(fields)); } QString Result::getErrorOnSend(not_null history) const { diff --git a/Telegram/SourceFiles/inline_bots/inline_bot_result.h b/Telegram/SourceFiles/inline_bots/inline_bot_result.h index 296deb613..cc7e090ee 100644 --- a/Telegram/SourceFiles/inline_bots/inline_bot_result.h +++ b/Telegram/SourceFiles/inline_bots/inline_bot_result.h @@ -16,6 +16,7 @@ class FileLoader; class History; class UserData; struct HistoryMessageMarkupData; +struct HistoryItemCommonFields; namespace Data { class LocationPoint; @@ -64,13 +65,7 @@ public: void addToHistory( not_null history, - MessageFlags flags, - MsgId msgId, - PeerId fromId, - TimeId date, - UserId viaBotId, - FullReplyTo replyTo, - const QString &postAuthor) const; + HistoryItemCommonFields &&fields) const; QString getErrorOnSend(not_null history) const; // interface for Layout:: usage diff --git a/Telegram/SourceFiles/inline_bots/inline_bot_send_data.cpp b/Telegram/SourceFiles/inline_bots/inline_bot_send_data.cpp index a8135979b..0b8e9d8b7 100644 --- a/Telegram/SourceFiles/inline_bots/inline_bot_send_data.cpp +++ b/Telegram/SourceFiles/inline_bots/inline_bot_send_data.cpp @@ -31,29 +31,15 @@ QString SendData::getLayoutDescription(const Result *owner) const { void SendDataCommon::addToHistory( const Result *owner, not_null history, - MessageFlags flags, - MsgId msgId, - PeerId fromId, - TimeId date, - UserId viaBotId, - FullReplyTo replyTo, - const QString &postAuthor, - HistoryMessageMarkupData &&markup) const { - auto fields = getSentMessageFields(); - if (replyTo) { - flags |= MessageFlag::HasReplyInfo; + HistoryItemCommonFields &&fields) const { + auto distinct = getSentMessageFields(); + if (fields.replyTo) { + fields.flags |= MessageFlag::HasReplyInfo; } history->addNewLocalMessage( - msgId, - flags, - viaBotId, - replyTo, - date, - fromId, - postAuthor, - std::move(fields.text), - std::move(fields.media), - std::move(markup)); + std::move(fields), + std::move(distinct.text), + std::move(distinct.media)); } QString SendDataCommon::getErrorOnSend( @@ -113,25 +99,11 @@ QString SendContact::getLayoutDescription(const Result *owner) const { void SendPhoto::addToHistory( const Result *owner, not_null history, - MessageFlags flags, - MsgId msgId, - PeerId fromId, - TimeId date, - UserId viaBotId, - FullReplyTo replyTo, - const QString &postAuthor, - HistoryMessageMarkupData &&markup) const { + HistoryItemCommonFields &&fields) const { history->addNewLocalMessage( - msgId, - flags, - viaBotId, - replyTo, - date, - fromId, - postAuthor, + std::move(fields), _photo, - { _message, _entities }, - std::move(markup)); + { _message, _entities }); } QString SendPhoto::getErrorOnSend( @@ -144,25 +116,11 @@ QString SendPhoto::getErrorOnSend( void SendFile::addToHistory( const Result *owner, not_null history, - MessageFlags flags, - MsgId msgId, - PeerId fromId, - TimeId date, - UserId viaBotId, - FullReplyTo replyTo, - const QString &postAuthor, - HistoryMessageMarkupData &&markup) const { + HistoryItemCommonFields &&fields) const { history->addNewLocalMessage( - msgId, - flags, - viaBotId, - replyTo, - date, - fromId, - postAuthor, + std::move(fields), _document, - { _message, _entities }, - std::move(markup)); + { _message, _entities }); } QString SendFile::getErrorOnSend( @@ -175,24 +133,8 @@ QString SendFile::getErrorOnSend( void SendGame::addToHistory( const Result *owner, not_null history, - MessageFlags flags, - MsgId msgId, - PeerId fromId, - TimeId date, - UserId viaBotId, - FullReplyTo replyTo, - const QString &postAuthor, - HistoryMessageMarkupData &&markup) const { - history->addNewLocalMessage( - msgId, - flags, - viaBotId, - replyTo, - date, - fromId, - postAuthor, - _game, - std::move(markup)); + HistoryItemCommonFields &&fields) const { + history->addNewLocalMessage(std::move(fields), _game); } QString SendGame::getErrorOnSend( diff --git a/Telegram/SourceFiles/inline_bots/inline_bot_send_data.h b/Telegram/SourceFiles/inline_bots/inline_bot_send_data.h index 84c25624f..502cc006e 100644 --- a/Telegram/SourceFiles/inline_bots/inline_bot_send_data.h +++ b/Telegram/SourceFiles/inline_bots/inline_bot_send_data.h @@ -9,7 +9,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "history/history_location_manager.h" -struct HistoryMessageMarkupData; +struct HistoryItemCommonFields; namespace Main { class Session; @@ -43,14 +43,7 @@ public: virtual void addToHistory( const Result *owner, not_null history, - MessageFlags flags, - MsgId msgId, - PeerId fromId, - TimeId date, - UserId viaBotId, - FullReplyTo replyTo, - const QString &postAuthor, - HistoryMessageMarkupData &&markup) const = 0; + HistoryItemCommonFields &&fields) const = 0; virtual QString getErrorOnSend( const Result *owner, not_null history) const = 0; @@ -85,14 +78,7 @@ public: void addToHistory( const Result *owner, not_null history, - MessageFlags flags, - MsgId msgId, - PeerId fromId, - TimeId date, - UserId viaBotId, - FullReplyTo replyTo, - const QString &postAuthor, - HistoryMessageMarkupData &&markup) const override; + HistoryItemCommonFields &&fields) const override; QString getErrorOnSend( const Result *owner, @@ -253,14 +239,7 @@ public: void addToHistory( const Result *owner, not_null history, - MessageFlags flags, - MsgId msgId, - PeerId fromId, - TimeId date, - UserId viaBotId, - FullReplyTo replyTo, - const QString &postAuthor, - HistoryMessageMarkupData &&markup) const override; + HistoryItemCommonFields &&fields) const override; QString getErrorOnSend( const Result *owner, @@ -294,14 +273,7 @@ public: void addToHistory( const Result *owner, not_null history, - MessageFlags flags, - MsgId msgId, - PeerId fromId, - TimeId date, - UserId viaBotId, - FullReplyTo replyTo, - const QString &postAuthor, - HistoryMessageMarkupData &&markup) const override; + HistoryItemCommonFields &&fields) const override; QString getErrorOnSend( const Result *owner, @@ -329,14 +301,7 @@ public: void addToHistory( const Result *owner, not_null history, - MessageFlags flags, - MsgId msgId, - PeerId fromId, - TimeId date, - UserId viaBotId, - FullReplyTo replyTo, - const QString &postAuthor, - HistoryMessageMarkupData &&markup) const override; + HistoryItemCommonFields &&fields) const override; QString getErrorOnSend( const Result *owner, diff --git a/Telegram/SourceFiles/media/stories/media_stories_reactions.cpp b/Telegram/SourceFiles/media/stories/media_stories_reactions.cpp index f401f6b37..da07a1516 100644 --- a/Telegram/SourceFiles/media/stories/media_stories_reactions.cpp +++ b/Telegram/SourceFiles/media/stories/media_stories_reactions.cpp @@ -131,23 +131,12 @@ private: not_null history) { Expects(history->peer->isUser()); - const auto flags = MessageFlag::FakeHistoryItem - | MessageFlag::HasFromId; - const auto replyTo = FullReplyTo(); - const auto viaBotId = UserId(); - const auto groupedId = uint64(); - const auto item = history->makeMessage( - history->nextNonHistoryEntryId(), - flags, - replyTo, - viaBotId, - base::unixtime::now(), - peerToUser(history->peer->id), - QString(), - TextWithEntities(), - MTP_messageMediaEmpty(), - HistoryMessageMarkupData(), - groupedId); + const auto item = history->makeMessage({ + .id = history->nextNonHistoryEntryId(), + .flags = MessageFlag::FakeHistoryItem | MessageFlag::HasFromId, + .from = history->peer->id, + .date = base::unixtime::now(), + }, TextWithEntities(), MTP_messageMediaEmpty()); return AdminLog::OwnedItem(delegate, item); } diff --git a/Telegram/SourceFiles/settings/business/settings_shortcut_messages.cpp b/Telegram/SourceFiles/settings/business/settings_shortcut_messages.cpp index 290aa222c..8a1053da5 100644 --- a/Telegram/SourceFiles/settings/business/settings_shortcut_messages.cpp +++ b/Telegram/SourceFiles/settings/business/settings_shortcut_messages.cpp @@ -17,6 +17,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "chat_helpers/tabbed_selector.h" #include "core/file_utilities.h" #include "core/mime_type.h" +#include "data/business/data_shortcut_messages.h" #include "data/data_message_reaction_id.h" #include "data/data_premium_limits.h" #include "data/data_session.h" @@ -75,6 +76,8 @@ public: } [[nodiscard]] rpl::producer title() override; + [[nodiscard]] rpl::producer<> sectionShowBack() override; + void setInnerFocus() override; bool paintOuter( not_null outer, @@ -82,6 +85,8 @@ public: QRect clip) override; private: + void outerResized(QSize outer); + // ListDelegate interface. Context listContext() override; bool listScrollTo(int top, bool syntetic = true) override; @@ -154,7 +159,11 @@ private: QPointer createPinnedToBottom( not_null parent) override; void setupComposeControls(); + void processScroll(); + void updateInnerVisibleArea(); + void pushReplyReturn(not_null item); + void checkReplyReturns(); void uploadFile(const QByteArray &fileContent, SendMediaType type); bool confirmSendingFiles( @@ -234,6 +243,7 @@ private: QPointer _inner; std::unique_ptr _controlsWrap; std::unique_ptr _composeControls; + rpl::event_stream<> _showBackRequests; bool _skipScrollEvent = false; std::unique_ptr _stickerToast; @@ -294,10 +304,17 @@ ShortcutMessages::ShortcutMessages( this, controller, static_cast(this)); - //_scroll->scrolls( - //) | rpl::start_with_next([=] { - // onScroll(); - //}, lifetime()); + + _scroll->sizeValue() | rpl::filter([](QSize size) { + return !size.isEmpty(); + }) | rpl::start_with_next([=](QSize size) { + outerResized(size); + }, lifetime()); + + _scroll->scrolls( + ) | rpl::start_with_next([=] { + processScroll(); + }, lifetime()); _inner->editMessageRequested( ) | rpl::start_with_next([=](auto fullId) { @@ -312,10 +329,10 @@ ShortcutMessages::ShortcutMessages( { auto emptyInfo = base::make_unique_q( _inner, - controller->chatStyle(), + _style.get(), st::msgServicePadding); const auto emptyText = Ui::Text::Semibold( - tr::lng_scheduled_messages_empty(tr::now)); + u"give me your money.."_q); emptyInfo->setText(emptyText); _inner->setEmptyInfoWidget(std::move(emptyInfo)); } @@ -335,6 +352,31 @@ rpl::producer ShortcutMessages::title() { return rpl::single(u"Editing messages list"_q); } +void ShortcutMessages::processScroll() { + if (_skipScrollEvent) { + return; + } + updateInnerVisibleArea(); +} + +void ShortcutMessages::updateInnerVisibleArea() { + if (!_inner->animatedScrolling()) { + checkReplyReturns(); + } + const auto scrollTop = _scroll->scrollTop(); + _inner->setVisibleTopBottom(scrollTop, scrollTop + _scroll->height()); + _cornerButtons.updateJumpDownVisibility(); + _cornerButtons.updateUnreadThingsVisibility(); +} + +rpl::producer<> ShortcutMessages::sectionShowBack() { + return _showBackRequests.events(); +} + +void ShortcutMessages::setInnerFocus() { + _composeControls->focus(); +} + bool ShortcutMessages::paintOuter( not_null outer, int maxVisibleHeight, @@ -349,6 +391,29 @@ bool ShortcutMessages::paintOuter( return true; } +void ShortcutMessages::outerResized(QSize outer) { + const auto contentWidth = outer.width(); + + const auto newScrollTop = _scroll->isHidden() + ? std::nullopt + : _scroll->scrollTop() + ? base::make_optional(_scroll->scrollTop()) + : 0; + _skipScrollEvent = true; + _inner->resizeToWidth(contentWidth, _scroll->height()); + resize(width(), _inner->height()); + _skipScrollEvent = false; + + if (!_scroll->isHidden()) { + if (newScrollTop) { + _scroll->scrollToY(*newScrollTop); + } + updateInnerVisibleArea(); + } + _composeControls->setAutocompleteBoundingRect(_scroll->geometry()); + _cornerButtons.updatePositions(); +} + void ShortcutMessages::setupComposeControls() { _composeControls->setHistory({ .history = _history.get(), @@ -446,10 +511,10 @@ void ShortcutMessages::setupComposeControls() { if (action == Ui::InputField::MimeAction::Check) { return Core::CanSendFiles(data); } else if (action == Ui::InputField::MimeAction::Insert) { - //return confirmSendingFiles( - // data, - // std::nullopt, - // Core::ReadMimeText(data));#TODO + return confirmSendingFiles( + data, + std::nullopt, + Core::ReadMimeText(data)); } Unexpected("action in MimeData hook."); }); @@ -480,22 +545,24 @@ QPointer ShortcutMessages::createPinnedToBottom( _controlsWrap.get(), _controller, [=](not_null emoji) { listShowPremiumToast(emoji); }, - ComposeControls::Mode::Scheduled, + ComposeControls::Mode::Normal, SendMenu::Type::Disabled); setupComposeControls(); + showAtEnd(); + return _controlsWrap.get(); } Context ShortcutMessages::listContext() { - return Context::History; + return Context::ShortcutMessages; } bool ShortcutMessages::listScrollTo(int top, bool syntetic) { top = std::clamp(top, 0, _scroll->scrollTopMax()); if (_scroll->scrollTop() == top) { - //updateInnerVisibleArea(); + updateInnerVisibleArea(); return false; } _scroll->scrollToY(top); @@ -509,7 +576,7 @@ void ShortcutMessages::listCancelRequest() { } else if (_composeControls->handleCancelRequest()) { return; } - _controller->showBackFromStack(); + _showBackRequests.fire({}); } void ShortcutMessages::listDeleteRequest() { @@ -525,13 +592,11 @@ rpl::producer ShortcutMessages::listSource( int limitBefore, int limitAfter) { const auto data = &_controller->session().data(); - //return rpl::single(rpl::empty) | rpl::then( - // data->scheduledMessages().updates(_history) - //) | rpl::map([=] { - // return data->scheduledMessages().list(_history); - //}) | rpl::after_next([=](const Data::MessagesSlice &slice) { - // highlightSingleNewMessage(slice); - //}); + return rpl::single(rpl::empty) | rpl::then( + data->shortcutMessages().updates(_shortcutId) + ) | rpl::map([=] { + return data->shortcutMessages().list(_shortcutId); + }); return rpl::never(); } @@ -698,12 +763,12 @@ std::optional ShortcutMessages::cornerButtonsDownShown() { || _composeControls->isTTLButtonShown()) { return false; } - //const auto top = _scroll->scrollTop() + st::historyToDownShownAfter; - //if (top < _scroll->scrollTopMax() || _cornerButtons.replyReturn()) { - // return true; - //} else if (_inner->loadedAtBottomKnown()) { - // return !_inner->loadedAtBottom(); - //} + const auto top = _scroll->scrollTop() + st::historyToDownShownAfter; + if (top < _scroll->scrollTopMax() || _cornerButtons.replyReturn()) { + return true; + } else if (_inner->loadedAtBottomKnown()) { + return !_inner->loadedAtBottom(); + } return std::nullopt; } @@ -717,10 +782,31 @@ bool ShortcutMessages::cornerButtonsHas(CornerButtonType type) { return (type == CornerButtonType::Down); } +void ShortcutMessages::pushReplyReturn(not_null item) { + if (item->shortcutId() == _shortcutId) { + _cornerButtons.pushReplyReturn(item); + } +} + +void ShortcutMessages::checkReplyReturns() { + const auto currentTop = _scroll->scrollTop(); + while (const auto replyReturn = _cornerButtons.replyReturn()) { + const auto position = replyReturn->position(); + const auto scrollTop = _inner->scrollTopForPosition(position); + const auto below = scrollTop + ? (currentTop >= std::min(*scrollTop, _scroll->scrollTopMax())) + : _inner->isBelowPosition(position); + if (below) { + _cornerButtons.calculateNextReplyReturn(); + } else { + break; + } + } +} + void ShortcutMessages::uploadFile( const QByteArray &fileContent, SendMediaType type) { - // #TODO replies schedule _session->api().sendFile(fileContent, type, prepareSendAction({})); } @@ -773,11 +859,6 @@ void ShortcutMessages::send() { return; } send({}); - // #TODO replies schedule - //const auto callback = [=](Api::SendOptions options) { send(options); }; - //Ui::show( - // PrepareScheduleBox(this, sendMenuType(), callback), - // Ui::LayerOption::KeepOther); } void ShortcutMessages::sendVoice(ComposeControls::VoiceToSend &&data) { @@ -933,7 +1014,7 @@ bool ShortcutMessages::confirmSendingFiles( _composeControls->getTextWithAppliedMarkdown(), _history->peer, Api::SendType::Normal, - SendMenu::Type::SilentOnly); // #TODO replies schedule + SendMenu::Type::Disabled); box->setConfirmedCallback(crl::guard(this, [=]( Ui::PreparedList &&list, diff --git a/Telegram/SourceFiles/support/support_autocomplete.cpp b/Telegram/SourceFiles/support/support_autocomplete.cpp index 75d42760d..45ad83edd 100644 --- a/Telegram/SourceFiles/support/support_autocomplete.cpp +++ b/Telegram/SourceFiles/support/support_autocomplete.cpp @@ -273,24 +273,14 @@ AdminLog::OwnedItem GenerateCommentItem( if (data.comment.isEmpty()) { return nullptr; } - const auto flags = MessageFlag::HasFromId - | MessageFlag::Outgoing - | MessageFlag::FakeHistoryItem; - const auto replyTo = FullReplyTo(); - const auto viaBotId = UserId(); - const auto groupedId = uint64(); - const auto item = history->makeMessage( - history->nextNonHistoryEntryId(), - flags, - replyTo, - viaBotId, - base::unixtime::now(), - history->session().userId(), - QString(), - TextWithEntities{ data.comment }, - MTP_messageMediaEmpty(), - HistoryMessageMarkupData(), - groupedId); + const auto item = history->makeMessage({ + .id = history->nextNonHistoryEntryId(), + .flags = (MessageFlag::HasFromId + | MessageFlag::Outgoing + | MessageFlag::FakeHistoryItem), + .from = history->session().userPeerId(), + .date = base::unixtime::now(), + }, TextWithEntities{ data.comment }, MTP_messageMediaEmpty()); return AdminLog::OwnedItem(delegate, item); } @@ -298,29 +288,19 @@ AdminLog::OwnedItem GenerateContactItem( not_null delegate, not_null history, const Contact &data) { - const auto replyTo = FullReplyTo(); - const auto viaBotId = UserId(); - const auto postAuthor = QString(); - const auto groupedId = uint64(); - const auto item = history->makeMessage( - history->nextNonHistoryEntryId(), - (MessageFlag::HasFromId + const auto item = history->makeMessage({ + .id = history->nextNonHistoryEntryId(), + .flags = (MessageFlag::HasFromId | MessageFlag::Outgoing | MessageFlag::FakeHistoryItem), - replyTo, - viaBotId, - base::unixtime::now(), - history->session().userPeerId(), - postAuthor, - TextWithEntities(), - MTP_messageMediaContact( - MTP_string(data.phone), - MTP_string(data.firstName), - MTP_string(data.lastName), - MTP_string(), // vcard - MTP_long(0)), // user_id - HistoryMessageMarkupData(), - groupedId); + .from = history->session().userPeerId(), + .date = base::unixtime::now(), + }, TextWithEntities(), MTP_messageMediaContact( + MTP_string(data.phone), + MTP_string(data.firstName), + MTP_string(data.lastName), + MTP_string(), // vcard + MTP_long(0))); // user_id return AdminLog::OwnedItem(delegate, item); }