diff --git a/Telegram/SourceFiles/inline_bots/bot_attach_web_view.cpp b/Telegram/SourceFiles/inline_bots/bot_attach_web_view.cpp index 876dadf87..122a95b4e 100644 --- a/Telegram/SourceFiles/inline_bots/bot_attach_web_view.cpp +++ b/Telegram/SourceFiles/inline_bots/bot_attach_web_view.cpp @@ -904,23 +904,28 @@ void AttachWebView::requestBots() { }).send(); } -bool AttachWebView::showingDisclaimer(const AttachWebViewBot &bot) const { - return bot.disclaimerRequired - && !_disclaimerAccepted.contains(bot.user); +bool AttachWebView::disclaimerAccepted(const AttachWebViewBot &bot) const { + return _disclaimerAccepted.contains(bot.user); +} + +bool AttachWebView::showMainMenuNewBadge( + const AttachWebViewBot &bot) const { + return bot.inMainMenu + && bot.disclaimerRequired + && !disclaimerAccepted(bot); } void AttachWebView::requestAddToMenu( not_null bot, - std::optional startCommand) { - requestAddToMenu(bot, startCommand, nullptr, std::nullopt, PeerTypes()); + AddToMenuOpen open) { + requestAddToMenu(bot, open, nullptr, std::nullopt); } void AttachWebView::requestAddToMenu( not_null bot, - std::optional startCommand, + AddToMenuOpen open, Window::SessionController *controller, - std::optional action, - PeerTypes chooseTypes) { + std::optional action) { Expects(controller != nullptr || _context != nullptr); if (!bot->isBot() || !bot->botInfo->supportsAttachMenu) { @@ -929,8 +934,7 @@ void AttachWebView::requestAddToMenu( } const auto wasController = (controller != nullptr); _addToMenuChooseController = base::make_weak(controller); - _addToMenuStartCommand = startCommand; - _addToMenuChooseTypes = chooseTypes; + _addToMenuOpen = open; if (!controller) { _addToMenuContext = base::take(_context); } else if (action) { @@ -950,17 +954,30 @@ void AttachWebView::requestAddToMenu( _addToMenuId = 0; const auto bot = base::take(_addToMenuBot); const auto context = std::shared_ptr(base::take(_addToMenuContext)); - const auto chooseTypes = base::take(_addToMenuChooseTypes); - const auto startCommand = base::take(_addToMenuStartCommand); + const auto open = base::take(_addToMenuOpen); const auto chooseController = base::take(_addToMenuChooseController); - const auto open = [=](PeerTypes types) { + const auto launch = [=](PeerTypes types) { + const auto openAttach = v::is(open) + ? v::get(open) + : AddToMenuOpenAttach(); + const auto chooseTypes = openAttach.chooseTypes; const auto strong = chooseController.get(); - if (!strong) { - if (wasController || !startCommand) { + if (v::is(open)) { + if (!context) { + return false; + } + const auto &openApp = v::get(open); + _app = openApp.app; + _startCommand = openApp.startCommand; + _context = std::make_unique(*context); + requestAppView(true); + return true; + } else if (!strong) { + if (wasController || !v::is(open)) { // Just ignore the click if controller was destroyed. return true; } - } else if (!startCommand) { + } else if (v::is(open)) { _bot = bot; requestSimple(strong, bot, { .fromMainMenu = true }); return true; @@ -969,7 +986,7 @@ void AttachWebView::requestAddToMenu( strong->showThread(thread); requestWithOptionalConfirm( bot, - { .startCommand = *startCommand }, + { .startCommand = openAttach.startCommand }, LookupContext(strong, Api::SendAction(thread))); }; ShowChooseBox(strong, useTypes, done); @@ -980,7 +997,7 @@ void AttachWebView::requestAddToMenu( } requestWithOptionalConfirm( bot, - { .startCommand = *startCommand }, + { .startCommand = openAttach.startCommand }, *context); return true; }; @@ -999,11 +1016,11 @@ void AttachWebView::requestAddToMenu( const auto types = parsed->types; if (parsed->inactive) { confirmAddToMenu(*parsed, [=] { - open(types); + launch(types); }); } else { requestBots(); - if (!open(types)) { + if (!launch(types)) { showToast( tr::lng_bot_menu_already_added(tr::now)); } @@ -1014,9 +1031,20 @@ void AttachWebView::requestAddToMenu( }).fail([=] { _addToMenuId = 0; _addToMenuBot = nullptr; - _addToMenuContext = nullptr; - _addToMenuStartCommand = std::nullopt; - showToast(tr::lng_bot_menu_not_supported(tr::now)); + auto context = base::take(_addToMenuContext); + const auto open = base::take(_addToMenuOpen); + if (const auto openApp = std::get_if(&open)) { + _app = openApp->app; + _startCommand = openApp->startCommand; + _context = std::move(context); + if (_appConfirmationRequired) { + confirmAppOpen(_appRequestWriteAccess); + } else { + requestAppView(false); + } + } else { + showToast(tr::lng_bot_menu_not_supported(tr::now)); + } }).send(); } @@ -1046,7 +1074,9 @@ void AttachWebView::resolve() { showToast(tr::lng_bot_menu_not_supported(tr::now)); return; } - requestAddToMenu(_bot, _startCommand); + requestAddToMenu(_bot, AddToMenuOpenAttach{ + .startCommand = _startCommand, + }); }); } @@ -1209,12 +1239,14 @@ void AttachWebView::requestApp( showToast(tr::lng_username_app_not_found(tr::now)); return; } - const auto confirm = firstTime || forceConfirmation; - if (confirm) { - confirmAppOpen(result.data().is_request_write_access()); - } else { - requestAppView(false); - } + // Check if this app can be added to main menu. + // On fail it'll still be opened. + _appConfirmationRequired = firstTime || forceConfirmation; + _appRequestWriteAccess = result.data().is_request_write_access(); + requestAddToMenu(_bot, AddToMenuOpenApp{ + .app = _app, + .startCommand = _startCommand, + }); }).fail([=] { showToast(tr::lng_username_app_not_found(tr::now)); cancel(); @@ -1331,9 +1363,9 @@ void AttachWebView::acceptDisclaimer( _attachBotsUpdates.fire({}); return; } else if (i->inactive) { - requestAddToMenu(_bot, {}, controller, {}, {}); + requestAddToMenu(_bot, AddToMenuOpenMenu(), controller, {}); return; - } else if (!showingDisclaimer(*i)) { + } else if (!i->disclaimerRequired || disclaimerAccepted(*i)) { done(); return; } @@ -1478,7 +1510,7 @@ void AttachWebView::confirmAddToMenu( }); close(); }; - const auto disclaimer = showingDisclaimer(bot); + const auto disclaimer = !disclaimerAccepted(bot); if (disclaimer) { FillDisclaimerBox(box, [=] { _disclaimerAccepted.emplace(bot.user); diff --git a/Telegram/SourceFiles/inline_bots/bot_attach_web_view.h b/Telegram/SourceFiles/inline_bots/bot_attach_web_view.h index 665000755..c0216b943 100644 --- a/Telegram/SourceFiles/inline_bots/bot_attach_web_view.h +++ b/Telegram/SourceFiles/inline_bots/bot_attach_web_view.h @@ -70,6 +70,21 @@ struct AttachWebViewBot { bool requestWriteAccess : 1 = false; }; +struct AddToMenuOpenAttach { + QString startCommand; + PeerTypes chooseTypes; +}; +struct AddToMenuOpenMenu { +}; +struct AddToMenuOpenApp { + not_null app; + QString startCommand; +}; +using AddToMenuOpen = std::variant< + AddToMenuOpenAttach, + AddToMenuOpenMenu, + AddToMenuOpenApp>; + class AttachWebView final : public base::has_weak_ptr , public Ui::BotWebView::Delegate { @@ -119,17 +134,19 @@ public: [[nodiscard]] rpl::producer<> attachBotsUpdates() const { return _attachBotsUpdates.events(); } - [[nodiscard]] bool showingDisclaimer(const AttachWebViewBot &bot) const; + [[nodiscard]] bool disclaimerAccepted( + const AttachWebViewBot &bot) const; + [[nodiscard]] bool showMainMenuNewBadge( + const AttachWebViewBot &bot) const; void requestAddToMenu( not_null bot, - std::optional startCommand); + AddToMenuOpen open); void requestAddToMenu( not_null bot, - std::optional startCommand, + AddToMenuOpen open, Window::SessionController *controller, - std::optional action, - PeerTypes chooseTypes); + std::optional action); void removeFromMenu(not_null bot); [[nodiscard]] std::optional lookupLastAction( @@ -140,6 +157,7 @@ public: private: struct Context; + Webview::ThemeParams botThemeParams() override; bool botHandleLocalUri(QString uri) override; void botHandleInvoice(QString slug) override; @@ -224,6 +242,8 @@ private: QString _startCommand; BotAppData *_app = nullptr; QPointer _confirmAddBox; + bool _appConfirmationRequired = false; + bool _appRequestWriteAccess = false; mtpRequestId _requestId = 0; mtpRequestId _prolongId = 0; @@ -234,9 +254,8 @@ private: std::unique_ptr _addToMenuContext; UserData *_addToMenuBot = nullptr; mtpRequestId _addToMenuId = 0; - std::optional _addToMenuStartCommand; + AddToMenuOpen _addToMenuOpen; base::weak_ptr _addToMenuChooseController; - PeerTypes _addToMenuChooseTypes; std::vector _attachBots; rpl::event_stream<> _attachBotsUpdates; diff --git a/Telegram/SourceFiles/window/window_main_menu.cpp b/Telegram/SourceFiles/window/window_main_menu.cpp index 7974b64a4..b4300cf70 100644 --- a/Telegram/SourceFiles/window/window_main_menu.cpp +++ b/Telegram/SourceFiles/window/window_main_menu.cpp @@ -254,7 +254,7 @@ void SetupMenuBots( } }, button->lifetime()); - const auto badge = bots->showingDisclaimer(bot) + const auto badge = bots->showMainMenuNewBadge(bot) ? Ui::CreateChild>( button.get(), object_ptr( diff --git a/Telegram/SourceFiles/window/window_session_controller.cpp b/Telegram/SourceFiles/window/window_session_controller.cpp index 3e5a1f85e..98d74822a 100644 --- a/Telegram/SourceFiles/window/window_session_controller.cpp +++ b/Telegram/SourceFiles/window/window_session_controller.cpp @@ -589,20 +589,21 @@ void SessionNavigation::showPeerByLinkResolved( : nullptr; bot->session().attachWebView().requestAddToMenu( bot, - *info.attachBotToggleCommand, + InlineBots::AddToMenuOpenAttach{ + .startCommand = *info.attachBotToggleCommand, + .chooseTypes = info.attachBotChooseTypes, + }, parentController(), (contextUser ? Api::SendAction( contextUser->owner().history(contextUser)) - : std::optional()), - info.attachBotChooseTypes); + : std::optional())); } else if (bot && info.attachBotMenuOpen) { bot->session().attachWebView().requestAddToMenu( bot, - std::nullopt, + InlineBots::AddToMenuOpenMenu(), parentController(), - std::optional(), - {}); + std::optional()); } else { crl::on_main(this, [=] { showPeerHistory(peer, params, msgId);