From e120ae6ae6bf526e21125d8fd86f09589c49a65e Mon Sep 17 00:00:00 2001 From: John Preston Date: Fri, 10 May 2024 15:00:30 +0400 Subject: [PATCH] Pass effect to API for sending. --- Telegram/SourceFiles/api/api_polls.cpp | 3 + Telegram/SourceFiles/api/api_sending.cpp | 9 + Telegram/SourceFiles/apiwrap.cpp | 13 +- .../media/stories/media_stories_share.cpp | 15 +- Telegram/SourceFiles/menu/menu_send.cpp | 165 +++++++++++++++++- 5 files changed, 194 insertions(+), 11 deletions(-) diff --git a/Telegram/SourceFiles/api/api_polls.cpp b/Telegram/SourceFiles/api/api_polls.cpp index b2422af25e..52a5f6d6fd 100644 --- a/Telegram/SourceFiles/api/api_polls.cpp +++ b/Telegram/SourceFiles/api/api_polls.cpp @@ -68,6 +68,9 @@ void Polls::create( if (action.options.shortcutId) { sendFlags |= MTPmessages_SendMedia::Flag::f_quick_reply_shortcut; } + if (action.options.effectId) { + sendFlags |= MTPmessages_SendMedia::Flag::f_effect; + } const auto sendAs = action.options.sendAs; if (sendAs) { sendFlags |= MTPmessages_SendMedia::Flag::f_send_as; diff --git a/Telegram/SourceFiles/api/api_sending.cpp b/Telegram/SourceFiles/api/api_sending.cpp index 9528ae446f..cbe617b750 100644 --- a/Telegram/SourceFiles/api/api_sending.cpp +++ b/Telegram/SourceFiles/api/api_sending.cpp @@ -133,6 +133,9 @@ void SendExistingMedia( flags |= MessageFlag::ShortcutMessage; sendFlags |= MTPmessages_SendMedia::Flag::f_quick_reply_shortcut; } + if (action.options.effectId) { + sendFlags |= MTPmessages_SendMedia::Flag::f_effect; + } session->data().registerMessageRandomId(randomId, newId); @@ -144,6 +147,7 @@ void SendExistingMedia( .date = HistoryItem::NewMessageDate(action.options), .shortcutId = action.options.shortcutId, .postAuthor = messagePostAuthor, + .effectId = action.options.effectId, }, media, caption); const auto performRequest = [=](const auto &repeatRequest) -> void { @@ -307,6 +311,9 @@ bool SendDice(MessageToSend &message) { flags |= MessageFlag::ShortcutMessage; sendFlags |= MTPmessages_SendMedia::Flag::f_quick_reply_shortcut; } + if (action.options.effectId) { + sendFlags |= MTPmessages_SendMedia::Flag::f_effect; + } session->data().registerMessageRandomId(randomId, newId); @@ -318,6 +325,7 @@ bool SendDice(MessageToSend &message) { .date = HistoryItem::NewMessageDate(action.options), .shortcutId = action.options.shortcutId, .postAuthor = messagePostAuthor, + .effectId = action.options.effectId, }, TextWithEntities(), MTP_messageMediaDice( MTP_int(0), MTP_string(emoji))); @@ -512,6 +520,7 @@ void SendConfirmedFile( .shortcutId = file->to.options.shortcutId, .postAuthor = messagePostAuthor, .groupedId = groupId, + .effectId = file->to.options.effectId, }, caption, media); } diff --git a/Telegram/SourceFiles/apiwrap.cpp b/Telegram/SourceFiles/apiwrap.cpp index c16926c73c..0e96bcec10 100644 --- a/Telegram/SourceFiles/apiwrap.cpp +++ b/Telegram/SourceFiles/apiwrap.cpp @@ -3383,6 +3383,7 @@ void ApiWrap::forwardMessages( .date = HistoryItem::NewMessageDate(action.options), .shortcutId = action.options.shortcutId, .postAuthor = messagePostAuthor, + .effectId = action.options.effectId, }, item); _session->data().registerMessageRandomId(randomId, newId); if (!localIds) { @@ -3483,6 +3484,7 @@ void ApiWrap::sendSharedContact( .date = HistoryItem::NewMessageDate(action.options), .shortcutId = action.options.shortcutId, .postAuthor = messagePostAuthor, + .effectId = action.options.effectId, }, TextWithEntities(), MTP_messageMediaContact( MTP_string(phone), MTP_string(firstName), @@ -3816,6 +3818,10 @@ void ApiWrap::sendMessage(MessageToSend &&message) { sendFlags |= MTPmessages_SendMessage::Flag::f_quick_reply_shortcut; mediaFlags |= MTPmessages_SendMedia::Flag::f_quick_reply_shortcut; } + if (action.options.effectId) { + sendFlags |= MTPmessages_SendMessage::Flag::f_effect; + mediaFlags |= MTPmessages_SendMedia::Flag::f_effect; + } lastMessage = history->addNewLocalMessage({ .id = newId.msg, .flags = flags, @@ -3824,6 +3830,7 @@ void ApiWrap::sendMessage(MessageToSend &&message) { .date = HistoryItem::NewMessageDate(action.options), .shortcutId = action.options.shortcutId, .postAuthor = messagePostAuthor, + .effectId = action.options.effectId, }, sending, media); const auto done = [=]( const MTPUpdates &result, @@ -4162,7 +4169,8 @@ void ApiWrap::sendMediaWithRandomId( | (!sentEntities.v.isEmpty() ? Flag::f_entities : Flag(0)) | (options.scheduled ? Flag::f_schedule_date : Flag(0)) | (options.sendAs ? Flag::f_send_as : Flag(0)) - | (options.shortcutId ? Flag::f_quick_reply_shortcut : Flag(0)); + | (options.shortcutId ? Flag::f_quick_reply_shortcut : Flag(0)) + | (options.effectId ? Flag::f_effect : Flag(0)); auto &histories = history->owner().histories(); const auto peer = history->peer; @@ -4271,7 +4279,8 @@ void ApiWrap::sendAlbumIfReady(not_null album) { | (sendAs ? Flag::f_send_as : Flag(0)) | (album->options.shortcutId ? Flag::f_quick_reply_shortcut - : Flag(0)); + : Flag(0)) + | (album->options.effectId ? Flag::f_effect : Flag(0)); auto &histories = history->owner().histories(); const auto peer = history->peer; histories.sendPreparedMessage( diff --git a/Telegram/SourceFiles/media/stories/media_stories_share.cpp b/Telegram/SourceFiles/media/stories/media_stories_share.cpp index bfd0e5c003..9d32a126a5 100644 --- a/Telegram/SourceFiles/media/stories/media_stories_share.cpp +++ b/Telegram/SourceFiles/media/stories/media_stories_share.cpp @@ -128,9 +128,7 @@ namespace Media::Stories { if (action.replyTo) { sendFlags |= MTPmessages_SendMedia::Flag::f_reply_to; } - const auto silentPost = ShouldSendSilent( - threadPeer, - action.options); + const auto silentPost = ShouldSendSilent(threadPeer, options); if (silentPost) { sendFlags |= MTPmessages_SendMedia::Flag::f_silent; } @@ -140,6 +138,9 @@ namespace Media::Stories { if (options.shortcutId) { sendFlags |= MTPmessages_SendMedia::Flag::f_quick_reply_shortcut; } + if (options.effectId) { + sendFlags |= MTPmessages_SendMedia::Flag::f_effect; + } const auto done = [=] { if (!--state->requests) { if (show->valid()) { @@ -161,12 +162,10 @@ namespace Media::Stories { MTP_long(randomId), MTPReplyMarkup(), MTPVector(), - MTP_int(action.options.scheduled), + MTP_int(options.scheduled), MTP_inputPeerEmpty(), - Data::ShortcutIdToMTP( - session, - action.options.shortcutId), - MTP_long(action.options.effectId) + Data::ShortcutIdToMTP(session, options.shortcutId), + MTP_long(options.effectId) ), [=]( const MTPUpdates &result, const MTP::Response &response) { diff --git a/Telegram/SourceFiles/menu/menu_send.cpp b/Telegram/SourceFiles/menu/menu_send.cpp index 1f216122be..6b39559150 100644 --- a/Telegram/SourceFiles/menu/menu_send.cpp +++ b/Telegram/SourceFiles/menu/menu_send.cpp @@ -12,9 +12,13 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "boxes/abstract_box.h" #include "chat_helpers/compose/compose_show.h" #include "core/shortcuts.h" +#include "history/view/media/history_view_sticker.h" #include "history/view/reactions/history_view_reactions_selector.h" #include "history/view/history_view_schedule_box.h" #include "lang/lang_keys.h" +#include "ui/chat/chat_style.h" +#include "ui/chat/chat_theme.h" +#include "ui/widgets/buttons.h" #include "ui/widgets/popup_menu.h" #include "data/data_peer.h" #include "data/data_forum.h" @@ -25,6 +29,9 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "history/history.h" #include "history/history_unread_things.h" #include "apiwrap.h" +#include "window/themes/window_theme.h" +#include "window/section_widget.h" +#include "styles/style_chat.h" #include "styles/style_chat_helpers.h" #include "styles/style_menu_icons.h" @@ -33,6 +40,33 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL namespace SendMenu { namespace { +class EffectPreview final : public Ui::RpWidget { +public: + EffectPreview( + not_null parent, + std::shared_ptr show, + Details details, + QPoint position, + const Data::Reaction &effect, + Fn action); +private: + void paintEvent(QPaintEvent *e) override; + void mousePressEvent(QMouseEvent *e) override; + + void setupGeometry(QPoint position); + void setupBackground(); + void setupSend(Details details); + + const std::shared_ptr _show; + const std::shared_ptr _theme; + const std::unique_ptr _chatStyle; + const std::unique_ptr _send; + const Fn _actionWithEffect; + QRect _inner; + QImage _bg; + +}; + [[nodiscard]] Data::PossibleItemReactionsRef LookupPossibleEffects( not_null session) { auto result = Data::PossibleItemReactionsRef(); @@ -51,6 +85,124 @@ namespace { return result; } +void ShowEffectPreview( + not_null parent, + std::shared_ptr show, + Details details, + QPoint position, + const Data::Reaction &effect, + Fn action) { + const auto widget = Ui::CreateChild( + parent, + show, + details, + position, + effect, + action); + widget->raise(); + widget->show(); +} + +[[nodiscard]] Fn ComposeActionWithEffect( + Fn sendAction, + EffectId id) { + if (!id) { + return sendAction; + } + return [=](Action action, Details details) { + if (const auto options = std::get_if(&action)) { + options->effectId = id; + } + sendAction(action, details); + }; +} + +EffectPreview::EffectPreview( + not_null parent, + std::shared_ptr show, + Details details, + QPoint position, + const Data::Reaction &effect, + Fn action) +: RpWidget(parent) +, _show(show) +, _theme(Window::Theme::DefaultChatThemeOn(lifetime())) +, _chatStyle( + std::make_unique( + _show->session().colorIndicesValue())) +, _send( + std::make_unique( + this, + u"Send with Effect"_q,AssertIsDebug() + st::previewMarkRead)) +, _actionWithEffect(ComposeActionWithEffect(action, effect.id.custom())) { + setupGeometry(position); + setupBackground(); + setupSend(details); +} + +void EffectPreview::paintEvent(QPaintEvent *e) { + auto p = QPainter(this); + p.drawImage(0, 0, _bg); +} + +void EffectPreview::mousePressEvent(QMouseEvent *e) { + delete this; +} + +void EffectPreview::setupGeometry(QPoint position) { + const auto parent = parentWidget(); + const auto innerSize = HistoryView::Sticker::MessageEffectSize(); + const auto shadow = st::previewMenu.shadow; + const auto extend = shadow.extend; + _inner = QRect(QPoint(extend.left(), extend.top()), innerSize); + const auto size = _inner.marginsAdded(extend).size(); + const auto left = std::max( + std::min( + position.x() - size.width() / 2, + parent->width() - size.width()), + 0); + const auto topMin = std::min((parent->height() - size.height()) / 2, 0); + const auto top = std::max( + std::min( + position.y() - size.height() / 2, + parent->height() - size.height()), + topMin); + setGeometry(left, top, size.width(), size.height() + _send->height()); + _send->setGeometry(0, size.height(), size.width(), _send->height()); +} + +void EffectPreview::setupBackground() { + const auto ratio = style::DevicePixelRatio(); + _bg = QImage( + _inner.size() * ratio, + QImage::Format_ARGB32_Premultiplied); + + const auto paint = [=] { + auto p = QPainter(&_bg); + Window::SectionWidget::PaintBackground( + p, + _theme.get(), + QSize(width(), height() * 5), + QRect(QPoint(), size())); + }; + paint(); + _theme->repaintBackgroundRequests() | rpl::start_with_next([=] { + paint(); + update(); + }, lifetime()); +} + +void EffectPreview::setupSend(Details details) { + _send->setClickedCallback([=] { + _actionWithEffect(Api::SendOptions(), details); + }); + const auto type = details.type; + SetupMenuAndShortcuts(_send.get(), _show, [=] { + return Details{ .type = type }; + }, _actionWithEffect); +} + } // namespace Fn DefaultCallback( @@ -131,7 +283,18 @@ FillMenuResult FillSendMenu( (*selector)->chosen( ) | rpl::start_with_next([=](ChosenReaction chosen) { - + const auto &reactions = showForEffect->session().data().reactions(); + const auto &effects = reactions.list(Data::Reactions::Type::Effects); + const auto i = ranges::find(effects, chosen.id, &Data::Reaction::id); + if (i != end(effects)) { + ShowEffectPreview( + menu, + showForEffect, + details, + menu->mapFromGlobal(chosen.globalGeometry.center()), + *i, + action); + } }, menu->lifetime()); return FillMenuResult::Prepared;