/* This file is part of Telegram Desktop, the official desktop application for the Telegram messaging service. For license and copyright information please follow this link: https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL */ #pragma once #include "base/flags.h" #include "base/timer.h" #include "base/weak_ptr.h" #include "mtproto/sender.h" #include "ui/chat/attach/attach_bot_webview.h" #include "ui/rp_widget.h" namespace Api { struct SendAction; } // namespace Api namespace Ui { class GenericBox; class DropdownMenu; } // namespace Ui namespace Ui::BotWebView { class Panel; } // namespace Ui::BotWebView namespace Main { class Session; } // namespace Main namespace Window { class SessionController; } // namespace Window namespace Data { class DocumentMedia; } // namespace Data namespace InlineBots { enum class PeerType : uint8 { SameBot = 0x01, Bot = 0x02, User = 0x04, Group = 0x08, Broadcast = 0x10, }; using PeerTypes = base::flags; [[nodiscard]] bool PeerMatchesTypes( not_null peer, not_null bot, PeerTypes types); [[nodiscard]] PeerTypes ParseChooseTypes(QStringView choose); struct AttachWebViewBot { not_null user; DocumentData *icon = nullptr; std::shared_ptr media; QString name; PeerTypes types = 0; bool inactive : 1 = false; bool inMainMenu : 1 = false; bool inAttachMenu : 1 = false; bool disclaimerRequired : 1 = false; bool requestWriteAccess : 1 = false; }; struct AddToMenuOpenAttach { QString startCommand; PeerTypes chooseTypes; }; struct AddToMenuOpenMenu { QString startCommand; }; 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 { public: explicit AttachWebView(not_null session); ~AttachWebView(); struct WebViewButton { QString text; QString startCommand; QByteArray url; bool fromAttachMenu = false; bool fromMainMenu = false; bool fromSwitch = false; }; void request( not_null controller, const Api::SendAction &action, const QString &botUsername, const QString &startCommand); void request( not_null controller, const Api::SendAction &action, not_null bot, const WebViewButton &button); void requestSimple( not_null controller, not_null bot, const WebViewButton &button); void requestMenu( not_null controller, not_null bot); void requestApp( not_null controller, const Api::SendAction &action, not_null bot, const QString &appName, const QString &startParam, bool forceConfirmation); void cancel(); void requestBots(Fn callback = nullptr); [[nodiscard]] const std::vector &attachBots() const { return _attachBots; } [[nodiscard]] rpl::producer<> attachBotsUpdates() const { return _attachBotsUpdates.events(); } void notifyBotIconLoaded() { _attachBotsUpdates.fire({}); } [[nodiscard]] bool disclaimerAccepted( const AttachWebViewBot &bot) const; [[nodiscard]] bool showMainMenuNewBadge( const AttachWebViewBot &bot) const; void requestAddToMenu( not_null bot, AddToMenuOpen open); void requestAddToMenu( not_null bot, AddToMenuOpen open, Window::SessionController *controller, std::optional action); void removeFromMenu(not_null bot); [[nodiscard]] std::optional lookupLastAction( const QString &url) const; static void ClearAll(); private: struct Context; Webview::ThemeParams botThemeParams() override; bool botHandleLocalUri(QString uri, bool keepOpen) override; void botHandleInvoice(QString slug) override; void botHandleMenuButton(Ui::BotWebView::MenuButton button) override; void botSendData(QByteArray data) override; void botSwitchInlineQuery( std::vector chatTypes, QString query) override; void botCheckWriteAccess(Fn callback) override; void botAllowWriteAccess(Fn callback) override; void botSharePhone(Fn callback) override; void botInvokeCustomMethod( Ui::BotWebView::CustomMethodRequest request) override; void botClose() override; [[nodiscard]] static Context LookupContext( not_null controller, const Api::SendAction &action); [[nodiscard]] static bool IsSame( const std::unique_ptr &a, const Context &b); void requestWithOptionalConfirm( not_null bot, const WebViewButton &button, const Context &context, Window::SessionController *controllerForConfirm = nullptr); void resolve(); void request(const WebViewButton &button); void requestSimple(const WebViewButton &button); void resolveUsername( const QString &username, Fn)> done); void confirmOpen( not_null controller, Fn done); void acceptMainMenuDisclaimer( not_null controller, const WebViewButton &button); enum class ToggledState { Removed, Added, AllowedToWrite, }; void toggleInMenu( not_null bot, ToggledState state, Fn callback = nullptr); void show( uint64 queryId, const QString &url, const QString &buttonText = QString(), bool allowClipboardRead = false, const BotAppData *app = nullptr, bool fromMainMenu = false); void confirmAddToMenu( AttachWebViewBot bot, Fn callback = nullptr); void confirmAppOpen(bool requestWriteAccess); void requestAppView(bool allowWrite); void started(uint64 queryId); void showToast( const QString &text, Window::SessionController *controller = nullptr); const not_null _session; base::Timer _refreshTimer; std::unique_ptr _context; std::unique_ptr _lastShownContext; QString _lastShownUrl; uint64 _lastShownQueryId = 0; QString _lastShownButtonText; UserData *_bot = nullptr; QString _botUsername; QString _botAppName; QString _startCommand; BotAppData *_app = nullptr; QPointer _confirmAddBox; bool _appConfirmationRequired = false; bool _appRequestWriteAccess = false; mtpRequestId _requestId = 0; mtpRequestId _prolongId = 0; uint64 _botsHash = 0; mtpRequestId _botsRequestId = 0; std::vector> _botsRequestCallbacks; std::unique_ptr _addToMenuContext; UserData *_addToMenuBot = nullptr; mtpRequestId _addToMenuId = 0; AddToMenuOpen _addToMenuOpen; base::weak_ptr _addToMenuChooseController; std::vector _attachBots; rpl::event_stream<> _attachBotsUpdates; base::flat_set> _disclaimerAccepted; std::unique_ptr _panel; bool _catchingCancelInShowCall = false; }; [[nodiscard]] std::unique_ptr MakeAttachBotsMenu( not_null parent, not_null controller, not_null peer, Fn actionFactory, Fn attach); class MenuBotIcon final : public Ui::RpWidget { public: MenuBotIcon( QWidget *parent, std::shared_ptr media); private: void paintEvent(QPaintEvent *e) override; void validate(); std::shared_ptr _media; QImage _image; QImage _mask; }; } // namespace InlineBots