From 2fed657940f0f226aceee6b498d6a2db12fcd190 Mon Sep 17 00:00:00 2001 From: John Preston Date: Thu, 14 Nov 2024 22:26:41 +0400 Subject: [PATCH] Make nice share message from miniapp. --- .../boxes/peer_list_controllers.cpp | 5 ++ .../SourceFiles/boxes/peer_list_controllers.h | 3 + .../boxes/peers/edit_peer_invite_link.cpp | 86 ++++++++++++++----- .../boxes/peers/edit_peer_invite_link.h | 13 ++- .../inline_bots/bot_attach_web_view.cpp | 62 +++++++++---- .../inline_bot_confirm_prepared.cpp | 59 +++++++++++-- .../inline_bots/inline_bot_confirm_prepared.h | 8 +- 7 files changed, 188 insertions(+), 48 deletions(-) diff --git a/Telegram/SourceFiles/boxes/peer_list_controllers.cpp b/Telegram/SourceFiles/boxes/peer_list_controllers.cpp index 53d56080a..05b8d6d20 100644 --- a/Telegram/SourceFiles/boxes/peer_list_controllers.cpp +++ b/Telegram/SourceFiles/boxes/peer_list_controllers.cpp @@ -1065,6 +1065,11 @@ std::unique_ptr ChooseTopicBoxController::createSearchRow( return nullptr; } +std::unique_ptr ChooseTopicBoxController::MakeRow( + not_null topic) { + return std::make_unique(topic); +} + auto ChooseTopicBoxController::createRow(not_null topic) -> std::unique_ptr { const auto skip = _filter && !_filter(topic); diff --git a/Telegram/SourceFiles/boxes/peer_list_controllers.h b/Telegram/SourceFiles/boxes/peer_list_controllers.h index 20479c2b4..07f71534a 100644 --- a/Telegram/SourceFiles/boxes/peer_list_controllers.h +++ b/Telegram/SourceFiles/boxes/peer_list_controllers.h @@ -335,6 +335,9 @@ public: void loadMoreRows() override; std::unique_ptr createSearchRow(PeerListRowId id) override; + [[nodiscard]] static std::unique_ptr MakeRow( + not_null topic); + private: class Row final : public PeerListRow { public: diff --git a/Telegram/SourceFiles/boxes/peers/edit_peer_invite_link.cpp b/Telegram/SourceFiles/boxes/peers/edit_peer_invite_link.cpp index 4dc7f897b..c8b4f2d48 100644 --- a/Telegram/SourceFiles/boxes/peers/edit_peer_invite_link.cpp +++ b/Telegram/SourceFiles/boxes/peers/edit_peer_invite_link.cpp @@ -12,12 +12,14 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "base/unixtime.h" #include "boxes/gift_premium_box.h" #include "boxes/peer_list_box.h" +#include "boxes/peer_list_controllers.h" #include "boxes/share_box.h" #include "core/application.h" #include "core/ui_integration.h" // Core::MarkedTextContext. #include "data/components/credits.h" #include "data/data_changes.h" #include "data/data_channel.h" +#include "data/data_forum_topic.h" #include "data/data_histories.h" #include "data/data_peer.h" #include "data/data_session.h" @@ -51,6 +53,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "window/window_session_controller.h" #include "styles/style_boxes.h" #include "styles/style_credits.h" +#include "styles/style_dialogs.h" #include "styles/style_giveaway.h" #include "styles/style_info.h" #include "styles/style_layers.h" // st::boxDividerLabel. @@ -264,8 +267,9 @@ private: class SingleRowController final : public PeerListController { public: SingleRowController( - not_null peer, - rpl::producer status); + not_null thread, + rpl::producer status, + Fn clicked); void prepare() override; void loadMoreRows() override; @@ -273,8 +277,10 @@ public: Main::Session &session() const override; private: - const not_null _peer; + const not_null _session; + const base::weak_ptr _thread; rpl::producer _status; + Fn _clicked; rpl::lifetime _lifetime; }; @@ -1144,36 +1150,59 @@ int Controller::descriptionTopSkipMin() const { } SingleRowController::SingleRowController( - not_null peer, - rpl::producer status) -: _peer(peer) -, _status(std::move(status)) { + not_null thread, + rpl::producer status, + Fn clicked) +: _session(&thread->session()) +, _thread(thread) +, _status(std::move(status)) +, _clicked(std::move(clicked)) { } void SingleRowController::prepare() { - auto row = std::make_unique(_peer); - + const auto strong = _thread.get(); + if (!strong) { + return; + } + const auto topic = strong->asTopic(); + auto row = topic + ? ChooseTopicBoxController::MakeRow(topic) + : std::make_unique(strong->peer()); const auto raw = row.get(); - std::move( - _status - ) | rpl::start_with_next([=](const QString &status) { - raw->setCustomStatus(status); - delegate()->peerListUpdateRow(raw); - }, _lifetime); - + if (_status) { + std::move( + _status + ) | rpl::start_with_next([=](const QString &status) { + raw->setCustomStatus(status); + delegate()->peerListUpdateRow(raw); + }, _lifetime); + } delegate()->peerListAppendRow(std::move(row)); delegate()->peerListRefreshRows(); + + if (topic) { + topic->destroyed() | rpl::start_with_next([=] { + while (delegate()->peerListFullRowsCount()) { + delegate()->peerListRemoveRow(delegate()->peerListRowAt(0)); + } + delegate()->peerListRefreshRows(); + }, _lifetime); + } } void SingleRowController::loadMoreRows() { } void SingleRowController::rowClicked(not_null row) { - ShowPeerInfoSync(row->peer()); + if (const auto onstack = _clicked) { + onstack(); + } else { + ShowPeerInfoSync(row->peer()); + } } Main::Session &SingleRowController::session() const { - return _peer->session(); + return *_session; } } // namespace @@ -1186,14 +1215,29 @@ bool IsExpiredLink(const Api::InviteLink &data, TimeId now) { void AddSinglePeerRow( not_null container, not_null peer, - rpl::producer status) { + rpl::producer status, + Fn clicked) { + AddSinglePeerRow( + container, + peer->owner().history(peer), + std::move(status), + std::move(clicked)); +} + +void AddSinglePeerRow( + not_null container, + not_null thread, + rpl::producer status, + Fn clicked) { const auto delegate = container->lifetime().make_state< PeerListContentDelegateSimple >(); const auto controller = container->lifetime().make_state< SingleRowController - >(peer, std::move(status)); - controller->setStyleOverrides(&st::peerListSingleRow); + >(thread, std::move(status), std::move(clicked)); + controller->setStyleOverrides(thread->asTopic() + ? &st::chooseTopicList + : &st::peerListSingleRow); const auto content = container->add(object_ptr( container, controller)); diff --git a/Telegram/SourceFiles/boxes/peers/edit_peer_invite_link.h b/Telegram/SourceFiles/boxes/peers/edit_peer_invite_link.h index e59ffdd5e..45abe3a46 100644 --- a/Telegram/SourceFiles/boxes/peers/edit_peer_invite_link.h +++ b/Telegram/SourceFiles/boxes/peers/edit_peer_invite_link.h @@ -16,6 +16,10 @@ namespace Api { struct InviteLink; } // namespace Api +namespace Data { +class Thread; +} // namespace Data + namespace Main { class Session; } // namespace Main @@ -31,7 +35,14 @@ class BoxContent; void AddSinglePeerRow( not_null container, not_null peer, - rpl::producer status); + rpl::producer status, + Fn clicked = nullptr); + +void AddSinglePeerRow( + not_null container, + not_null thread, + rpl::producer status, + Fn clicked = nullptr); void AddPermanentLinkBlock( std::shared_ptr show, diff --git a/Telegram/SourceFiles/inline_bots/bot_attach_web_view.cpp b/Telegram/SourceFiles/inline_bots/bot_attach_web_view.cpp index 93fa4d389..b2609d3ea 100644 --- a/Telegram/SourceFiles/inline_bots/bot_attach_web_view.cpp +++ b/Telegram/SourceFiles/inline_bots/bot_attach_web_view.cpp @@ -11,6 +11,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "api/api_common.h" #include "api/api_sending.h" #include "apiwrap.h" +#include "base/call_delayed.h" #include "base/qthelp_url.h" #include "base/random.h" #include "base/timer_rpl.h" @@ -60,6 +61,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "ui/effects/ripple_animation.h" #include "ui/painter.h" #include "ui/text/text_utilities.h" +#include "ui/toast/toast.h" #include "ui/vertical_list.h" #include "ui/widgets/checkbox.h" #include "ui/widgets/dropdown_menu.h" @@ -1786,29 +1788,23 @@ void WebViewInstance::botSendPreparedMessage( }); struct State { QPointer preview; + rpl::event_stream> recipient; bool sent = false; }; const auto state = std::make_shared(); - auto box = Box(PreparedPreviewBox, item, [=] { + auto recipient = state->recipient.events(); + auto box = Box(PreparedPreviewBox, item, std::move(recipient), [=] { + if (state->sent) { + return; + } const auto chosen = [=](not_null thread) { - auto action = Api::SendAction(thread); - const auto done = [=](bool success) { - if (success) { - callback(QString()); - } else { - callback(u"MESSAGE_SEND_FAILED"_q); - } - }; - bot->session().api().sendInlineResult( - bot, - parsed.get(), - action, - std::nullopt, - done); - state->sent = true; - if (const auto strong = state->preview.data()) { - strong->closeBox(); + if (!Data::CanSend(thread, ChatRestriction::SendInline)) { + panel->showToast({ + tr::lng_restricted_send_inline_all(tr::now), + }); + return false; } + state->recipient.fire_copy(thread); return true; }; auto box = Window::PrepareChooseRecipientBox( @@ -1818,6 +1814,36 @@ void WebViewInstance::botSendPreparedMessage( nullptr, types); panel->showBox(std::move(box)); + }, [=](not_null thread) { + if (state->sent) { + return; + } + state->sent = true; + const auto weak = state->preview; + const auto done = [=](bool success) { + if (success) { + if (const auto strong = weak.data()) { + strong->showToast({ tr::lng_share_done(tr::now) }); + } + base::call_delayed(Ui::Toast::kDefaultDuration, [weak] { + if (const auto strong = weak.data()) { + strong->closeBox(); + } + }); + callback(QString()); + } else { + if (const auto strong = weak.data()) { + strong->closeBox(); + } + callback(u"MESSAGE_SEND_FAILED"_q); + } + }; + bot->session().api().sendInlineResult( + bot, + parsed.get(), + Api::SendAction(thread), + std::nullopt, + done); }); box->boxClosing() | rpl::start_with_next([=] { if (!state->sent) { diff --git a/Telegram/SourceFiles/inline_bots/inline_bot_confirm_prepared.cpp b/Telegram/SourceFiles/inline_bots/inline_bot_confirm_prepared.cpp index 07aae0515..4b4b434ae 100644 --- a/Telegram/SourceFiles/inline_bots/inline_bot_confirm_prepared.cpp +++ b/Telegram/SourceFiles/inline_bots/inline_bot_confirm_prepared.cpp @@ -7,6 +7,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL */ #include "inline_bots/inline_bot_confirm_prepared.h" +#include "boxes/peers/edit_peer_invite_link.h" +#include "data/data_forum_topic.h" #include "data/data_session.h" #include "data/data_user.h" #include "history/admin_log/history_admin_log_item.h" @@ -19,11 +21,13 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "ui/chat/chat_theme.h" #include "ui/effects/path_shift_gradient.h" #include "ui/layers/generic_box.h" +#include "ui/wrap/slide_wrap.h" #include "ui/painter.h" #include "ui/vertical_list.h" #include "window/themes/window_theme.h" #include "window/section_widget.h" #include "styles/style_chat.h" +#include "styles/style_layers.h" namespace InlineBots { namespace { @@ -168,22 +172,63 @@ void PreviewWrap::paintEvent(QPaintEvent *e) { _item->draw(p, context); } -} // namesace +} // namespace void PreparedPreviewBox( not_null box, not_null item, - Fn share) { + rpl::producer> recipient, + Fn choose, + Fn)> send) { box->setTitle(tr::lng_bot_share_prepared_title()); const auto container = box->verticalLayout(); container->add(object_ptr(container, item)); const auto bot = item->viaBot(); const auto name = bot ? bot->name() : u"Bot"_q; - Ui::AddDividerText( - container, - tr::lng_bot_share_prepared_about(lt_bot, rpl::single(name))), - box->addButton(tr::lng_bot_share_prepared_button(), share); - box->addButton(tr::lng_cancel(), [=] { box->closeBox(); }); + const auto info = container->add( + object_ptr>( + container, + object_ptr( + container, + object_ptr( + container, + tr::lng_bot_share_prepared_about(lt_bot, rpl::single(name)), + st::boxDividerLabel), + st::defaultBoxDividerLabelPadding, + RectPart::Top | RectPart::Bottom))); + const auto row = container->add(object_ptr( + container)); + + const auto reset = [=] { + info->show(anim::type::instant); + while (row->count()) { + delete row->widgetAt(0); + } + box->addButton(tr::lng_bot_share_prepared_button(), choose); + box->addButton(tr::lng_cancel(), [=] { box->closeBox(); }); + }; + reset(); + + const auto lifetime = box->lifetime().make_state(); + std::move( + recipient + ) | rpl::start_with_next([=](not_null thread) { + info->hide(anim::type::instant); + while (row->count()) { + delete row->widgetAt(0); + } + AddSkip(row); + AddSinglePeerRow(row, thread, nullptr, choose); + if (const auto topic = thread->asTopic()) { + *lifetime = topic->destroyed() | rpl::start_with_next(reset); + } else { + *lifetime = rpl::lifetime(); + } + row->resizeToWidth(container->width()); + box->clearButtons(); + box->addButton(tr::lng_send_button(), [=] { send(thread); }); + box->addButton(tr::lng_cancel(), [=] { box->closeBox(); }); + }, info->lifetime()); item->history()->owner().itemRemoved( ) | rpl::start_with_next([=](not_null removed) { diff --git a/Telegram/SourceFiles/inline_bots/inline_bot_confirm_prepared.h b/Telegram/SourceFiles/inline_bots/inline_bot_confirm_prepared.h index 606bc31c2..69af5d11a 100644 --- a/Telegram/SourceFiles/inline_bots/inline_bot_confirm_prepared.h +++ b/Telegram/SourceFiles/inline_bots/inline_bot_confirm_prepared.h @@ -7,6 +7,10 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL */ #pragma once +namespace Data { +class Thread; +} // namespace Data + namespace Ui { class GenericBox; } // namespace Ui @@ -16,6 +20,8 @@ namespace InlineBots { void PreparedPreviewBox( not_null box, not_null item, - Fn share); + rpl::producer> recipient, + Fn choose, + Fn)> sent); } // namespace InlineBots