attach_bot_webview.h 7.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252
  1. /*
  2. This file is part of Telegram Desktop,
  3. the official desktop application for the Telegram messaging service.
  4. For license and copyright information please follow this link:
  5. https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
  6. */
  7. #pragma once
  8. #include "base/expected.h"
  9. #include "base/object_ptr.h"
  10. #include "base/weak_ptr.h"
  11. #include "base/flags.h"
  12. #include "ui/rect_part.h"
  13. #include "ui/round_rect.h"
  14. #include "webview/webview_common.h"
  15. class QJsonObject;
  16. class QJsonValue;
  17. namespace Ui {
  18. class FlatLabel;
  19. class BoxContent;
  20. class RpWidget;
  21. class SeparatePanel;
  22. class IconButton;
  23. enum class LayerOption;
  24. using LayerOptions = base::flags<LayerOption>;
  25. } // namespace Ui
  26. namespace Webview {
  27. struct Available;
  28. } // namespace Webview
  29. namespace Ui::BotWebView {
  30. struct DownloadsProgress;
  31. struct DownloadsEntry;
  32. enum class DownloadsAction;
  33. [[nodiscard]] TextWithEntities ErrorText(const Webview::Available &info);
  34. enum class MenuButton {
  35. None = 0x00,
  36. OpenBot = 0x01,
  37. RemoveFromMenu = 0x02,
  38. RemoveFromMainMenu = 0x04,
  39. ShareGame = 0x08,
  40. };
  41. inline constexpr bool is_flag_type(MenuButton) { return true; }
  42. using MenuButtons = base::flags<MenuButton>;
  43. using CustomMethodResult = base::expected<QByteArray, QString>;
  44. struct CustomMethodRequest {
  45. QString method;
  46. QByteArray params;
  47. Fn<void(CustomMethodResult)> callback;
  48. };
  49. struct SetEmojiStatusRequest {
  50. uint64 customEmojiId = 0;
  51. TimeId duration = 0;
  52. Fn<void(QString)> callback;
  53. };
  54. struct DownloadFileRequest {
  55. QString url;
  56. QString name;
  57. Fn<void(bool)> callback;
  58. };
  59. struct SendPreparedMessageRequest {
  60. QString id = 0;
  61. Fn<void(QString)> callback;
  62. };
  63. class Delegate {
  64. public:
  65. [[nodiscard]] virtual Webview::ThemeParams botThemeParams() = 0;
  66. [[nodiscard]] virtual auto botDownloads(bool forceCheck = false)
  67. -> const std::vector<DownloadsEntry> & = 0;
  68. virtual void botDownloadsAction(uint32 id, DownloadsAction type) = 0;
  69. virtual bool botHandleLocalUri(QString uri, bool keepOpen) = 0;
  70. virtual void botHandleInvoice(QString slug) = 0;
  71. virtual void botHandleMenuButton(MenuButton button) = 0;
  72. virtual bool botValidateExternalLink(QString uri) = 0;
  73. virtual void botOpenIvLink(QString uri) = 0;
  74. virtual void botSendData(QByteArray data) = 0;
  75. virtual void botSwitchInlineQuery(
  76. std::vector<QString> chatTypes,
  77. QString query) = 0;
  78. virtual void botCheckWriteAccess(Fn<void(bool allowed)> callback) = 0;
  79. virtual void botAllowWriteAccess(Fn<void(bool allowed)> callback) = 0;
  80. virtual void botRequestEmojiStatusAccess(
  81. Fn<void(bool allowed)> callback) = 0;
  82. virtual void botSharePhone(Fn<void(bool shared)> callback) = 0;
  83. virtual void botInvokeCustomMethod(CustomMethodRequest request) = 0;
  84. virtual void botSetEmojiStatus(SetEmojiStatusRequest request) = 0;
  85. virtual void botDownloadFile(DownloadFileRequest request) = 0;
  86. virtual void botSendPreparedMessage(
  87. SendPreparedMessageRequest request) = 0;
  88. virtual void botOpenPrivacyPolicy() = 0;
  89. virtual void botClose() = 0;
  90. };
  91. struct Args {
  92. QString url;
  93. Webview::StorageId storageId;
  94. rpl::producer<QString> title;
  95. object_ptr<Ui::RpWidget> titleBadge = { nullptr };
  96. rpl::producer<QString> bottom;
  97. not_null<Delegate*> delegate;
  98. MenuButtons menuButtons;
  99. bool fullscreen = false;
  100. bool allowClipboardRead = false;
  101. rpl::producer<DownloadsProgress> downloadsProgress;
  102. };
  103. class Panel final : public base::has_weak_ptr {
  104. public:
  105. explicit Panel(Args &&args);
  106. ~Panel();
  107. void requestActivate();
  108. void toggleProgress(bool shown);
  109. void showBox(object_ptr<BoxContent> box);
  110. void showBox(
  111. object_ptr<BoxContent> box,
  112. LayerOptions options,
  113. anim::type animated);
  114. void hideLayer(anim::type animated);
  115. void showToast(TextWithEntities &&text);
  116. not_null<QWidget*> toastParent() const;
  117. void showCriticalError(const TextWithEntities &text);
  118. void showWebviewError(
  119. const QString &text,
  120. const Webview::Available &information);
  121. void updateThemeParams(const Webview::ThemeParams &params);
  122. void hideForPayment();
  123. void invoiceClosed(const QString &slug, const QString &status);
  124. [[nodiscard]] rpl::lifetime &lifetime();
  125. private:
  126. class Button;
  127. struct Progress;
  128. struct WebviewWithLifetime;
  129. bool showWebview(Args &&args, const Webview::ThemeParams &params);
  130. bool createWebview(const Webview::ThemeParams &params);
  131. void createWebviewBottom();
  132. void showWebviewProgress();
  133. void hideWebviewProgress();
  134. void setupDownloadsProgress(
  135. not_null<RpWidget*> button,
  136. rpl::producer<DownloadsProgress> progress,
  137. bool fullscreen);
  138. void setTitle(rpl::producer<QString> title);
  139. void sendDataMessage(const QJsonObject &args);
  140. void switchInlineQueryMessage(const QJsonObject &args);
  141. void processSendMessageRequest(const QJsonObject &args);
  142. void processEmojiStatusRequest(const QJsonObject &args);
  143. void processEmojiStatusAccessRequest();
  144. void processButtonMessage(
  145. std::unique_ptr<Button> &button,
  146. const QJsonObject &args);
  147. void processBackButtonMessage(const QJsonObject &args);
  148. void processSettingsButtonMessage(const QJsonObject &args);
  149. void processHeaderColor(const QJsonObject &args);
  150. void processBackgroundColor(const QJsonObject &args);
  151. void processBottomBarColor(const QJsonObject &args);
  152. void processDownloadRequest(const QJsonObject &args);
  153. void openTgLink(const QJsonObject &args);
  154. void openExternalLink(const QJsonObject &args);
  155. void openInvoice(const QJsonObject &args);
  156. void openPopup(const QJsonObject &args);
  157. void openScanQrPopup(const QJsonObject &args);
  158. void openShareStory(const QJsonObject &args);
  159. void requestWriteAccess();
  160. void replyRequestWriteAccess(bool allowed);
  161. void requestPhone();
  162. void replyRequestPhone(bool shared);
  163. void invokeCustomMethod(const QJsonObject &args);
  164. void replyCustomMethod(QJsonValue requestId, QJsonObject response);
  165. void requestClipboardText(const QJsonObject &args);
  166. void setupClosingBehaviour(const QJsonObject &args);
  167. void createButton(std::unique_ptr<Button> &button);
  168. void scheduleCloseWithConfirmation();
  169. void closeWithConfirmation();
  170. void sendViewport();
  171. void sendSafeArea();
  172. void sendContentSafeArea();
  173. void sendFullScreen();
  174. void updateColorOverrides(const Webview::ThemeParams &params);
  175. void overrideBodyColor(std::optional<QColor> color);
  176. using EventData = std::variant<QString, QJsonObject>;
  177. void postEvent(const QString &event);
  178. void postEvent(const QString &event, EventData data);
  179. [[nodiscard]] bool allowOpenLink() const;
  180. [[nodiscard]] bool allowClipboardQuery() const;
  181. [[nodiscard]] bool progressWithBackground() const;
  182. [[nodiscard]] QRect progressRect() const;
  183. void setupProgressGeometry();
  184. void layoutButtons();
  185. Webview::StorageId _storageId;
  186. const not_null<Delegate*> _delegate;
  187. bool _closeNeedConfirmation = false;
  188. bool _hasSettingsButton = false;
  189. MenuButtons _menuButtons = {};
  190. std::unique_ptr<SeparatePanel> _widget;
  191. std::unique_ptr<WebviewWithLifetime> _webview;
  192. std::unique_ptr<RpWidget> _webviewBottom;
  193. QPointer<FlatLabel> _webviewBottomLabel;
  194. rpl::variable<QString> _bottomText;
  195. QPointer<RpWidget> _webviewParent;
  196. std::unique_ptr<RpWidget> _bottomButtonsBg;
  197. std::unique_ptr<Button> _mainButton;
  198. std::unique_ptr<Button> _secondaryButton;
  199. RectPart _secondaryPosition = RectPart::Left;
  200. rpl::variable<int> _footerHeight = 0;
  201. std::unique_ptr<Progress> _progress;
  202. rpl::event_stream<> _themeUpdateForced;
  203. std::optional<QColor> _bottomBarColor;
  204. rpl::lifetime _headerColorLifetime;
  205. rpl::lifetime _bodyColorLifetime;
  206. rpl::lifetime _bottomBarColorLifetime;
  207. rpl::event_stream<> _downloadsUpdated;
  208. rpl::variable<bool> _fullscreen = false;
  209. bool _layerShown : 1 = false;
  210. bool _webviewProgress : 1 = false;
  211. bool _themeUpdateScheduled : 1 = false;
  212. bool _hiddenForPayment : 1 = false;
  213. bool _closeWithConfirmationScheduled : 1 = false;
  214. bool _allowClipboardRead : 1 = false;
  215. bool _inBlockingRequest : 1 = false;
  216. bool _headerColorReceived : 1 = false;
  217. bool _bodyColorReceived : 1 = false;
  218. bool _bottomColorReceived : 1 = false;
  219. };
  220. [[nodiscard]] std::unique_ptr<Panel> Show(Args &&args);
  221. } // namespace Ui::BotWebView