send_files_box.h 8.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310
  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/flags.h"
  9. #include "ui/layers/box_content.h"
  10. #include "ui/chat/attach/attach_prepare.h"
  11. #include "ui/chat/attach/attach_send_files_way.h"
  12. namespace style {
  13. struct ComposeControls;
  14. } // namespace style
  15. namespace Window {
  16. class SessionController;
  17. } // namespace Window
  18. namespace Api {
  19. struct SendOptions;
  20. enum class SendType;
  21. } // namespace Api
  22. namespace ChatHelpers {
  23. class TabbedPanel;
  24. class Show;
  25. class FieldAutocomplete;
  26. } // namespace ChatHelpers
  27. namespace Ui {
  28. class Checkbox;
  29. class RoundButton;
  30. class InputField;
  31. struct GroupMediaLayout;
  32. class EmojiButton;
  33. class AlbumPreview;
  34. class VerticalLayout;
  35. class FlatLabel;
  36. class PopupMenu;
  37. } // namespace Ui
  38. namespace Window {
  39. class SessionController;
  40. } // namespace Window
  41. namespace SendMenu {
  42. struct Details;
  43. struct Action;
  44. } // namespace SendMenu
  45. namespace HistoryView::Controls {
  46. class CharactersLimitLabel;
  47. } // namespace HistoryView::Controls
  48. enum class SendFilesAllow {
  49. OnlyOne = (1 << 0),
  50. Photos = (1 << 1),
  51. Videos = (1 << 2),
  52. Music = (1 << 3),
  53. Files = (1 << 4),
  54. Stickers = (1 << 5),
  55. Gifs = (1 << 6),
  56. EmojiWithoutPremium = (1 << 7),
  57. Texts = (1 << 8),
  58. };
  59. inline constexpr bool is_flag_type(SendFilesAllow) { return true; }
  60. using SendFilesLimits = base::flags<SendFilesAllow>;
  61. using SendFilesCheck = Fn<bool(
  62. const Ui::PreparedFile &file,
  63. bool compress,
  64. bool silent)>;
  65. [[nodiscard]] SendFilesLimits DefaultLimitsForPeer(not_null<PeerData*> peer);
  66. [[nodiscard]] SendFilesCheck DefaultCheckForPeer(
  67. not_null<Window::SessionController*> controller,
  68. not_null<PeerData*> peer);
  69. [[nodiscard]] SendFilesCheck DefaultCheckForPeer(
  70. std::shared_ptr<ChatHelpers::Show> show,
  71. not_null<PeerData*> peer);
  72. using SendFilesConfirmed = Fn<void(
  73. Ui::PreparedList &&list,
  74. Ui::SendFilesWay way,
  75. TextWithTags &&caption,
  76. Api::SendOptions options,
  77. bool ctrlShiftEnter)>;
  78. struct SendFilesBoxDescriptor {
  79. std::shared_ptr<ChatHelpers::Show> show;
  80. Ui::PreparedList list;
  81. TextWithTags caption;
  82. PeerData *captionToPeer = nullptr;
  83. SendFilesLimits limits = {};
  84. SendFilesCheck check;
  85. Api::SendType sendType = {};
  86. Fn<SendMenu::Details()> sendMenuDetails = nullptr;
  87. const style::ComposeControls *stOverride = nullptr;
  88. SendFilesConfirmed confirmed;
  89. Fn<void()> cancelled;
  90. };
  91. class SendFilesBox : public Ui::BoxContent {
  92. public:
  93. enum class SendLimit {
  94. One,
  95. Many
  96. };
  97. SendFilesBox(
  98. QWidget*,
  99. not_null<Window::SessionController*> controller,
  100. Ui::PreparedList &&list,
  101. const TextWithTags &caption,
  102. not_null<PeerData*> toPeer,
  103. Api::SendType sendType,
  104. SendMenu::Details sendMenuDetails);
  105. SendFilesBox(QWidget*, SendFilesBoxDescriptor &&descriptor);
  106. void setConfirmedCallback(SendFilesConfirmed callback) {
  107. _confirmedCallback = std::move(callback);
  108. }
  109. void setCancelledCallback(Fn<void()> callback) {
  110. _cancelledCallback = std::move(callback);
  111. }
  112. void showFinished() override;
  113. ~SendFilesBox();
  114. protected:
  115. void prepare() override;
  116. void setInnerFocus() override;
  117. void keyPressEvent(QKeyEvent *e) override;
  118. void paintEvent(QPaintEvent *e) override;
  119. void resizeEvent(QResizeEvent *e) override;
  120. private:
  121. using MenuAction = SendMenu::Action;
  122. using MenuDetails = SendMenu::Details;
  123. class Block final {
  124. public:
  125. Block(
  126. not_null<QWidget*> parent,
  127. const style::ComposeControls &st,
  128. not_null<std::vector<Ui::PreparedFile>*> items,
  129. int from,
  130. int till,
  131. Fn<bool()> gifPaused,
  132. Ui::SendFilesWay way,
  133. Fn<bool(
  134. const Ui::PreparedFile &,
  135. Ui::AttachActionType)> actionAllowed);
  136. Block(Block &&other) = default;
  137. Block &operator=(Block &&other) = default;
  138. [[nodiscard]] int fromIndex() const;
  139. [[nodiscard]] int tillIndex() const;
  140. [[nodiscard]] object_ptr<Ui::RpWidget> takeWidget();
  141. [[nodiscard]] rpl::producer<int> itemDeleteRequest() const;
  142. [[nodiscard]] rpl::producer<int> itemReplaceRequest() const;
  143. [[nodiscard]] rpl::producer<int> itemModifyRequest() const;
  144. [[nodiscard]] rpl::producer<int> itemEditCoverRequest() const;
  145. [[nodiscard]] rpl::producer<int> itemClearCoverRequest() const;
  146. [[nodiscard]] rpl::producer<> orderUpdated() const;
  147. void setSendWay(Ui::SendFilesWay way);
  148. void toggleSpoilers(bool enabled);
  149. void applyChanges();
  150. [[nodiscard]] QImage generatePriceTagBackground() const;
  151. private:
  152. base::unique_qptr<Ui::RpWidget> _preview;
  153. not_null<std::vector<Ui::PreparedFile>*> _items;
  154. int _from = 0;
  155. int _till = 0;
  156. bool _isAlbum = false;
  157. bool _isSingleMedia = false;
  158. };
  159. void initSendWay();
  160. void initPreview();
  161. [[nodiscard]] bool hasSendMenu(const MenuDetails &details) const;
  162. [[nodiscard]] bool hasSpoilerMenu() const;
  163. [[nodiscard]] bool allWithSpoilers();
  164. [[nodiscard]] bool checkWithWay(
  165. Ui::SendFilesWay way,
  166. bool silent = false) const;
  167. [[nodiscard]] bool checkWith(
  168. const Ui::PreparedList &added,
  169. Ui::SendFilesWay way,
  170. bool silent = false) const;
  171. void addMenuButton();
  172. void applyBlockChanges();
  173. void toggleSpoilers(bool enabled);
  174. void changePrice();
  175. [[nodiscard]] bool canChangePrice() const;
  176. [[nodiscard]] bool hasPrice() const;
  177. void refreshPriceTag();
  178. [[nodiscard]] QImage preparePriceTagBg(QSize size) const;
  179. bool validateLength(const QString &text) const;
  180. void refreshButtons();
  181. void refreshControls(bool initial = false);
  182. void setupSendWayControls();
  183. void setupCaption();
  184. void setupCaptionAutocomplete();
  185. void setupEmojiPanel();
  186. void updateSendWayControls();
  187. void updateEmojiPanelGeometry();
  188. void emojiFilterForGeometry(not_null<QEvent*> event);
  189. void preparePreview();
  190. void generatePreviewFrom(int fromBlock);
  191. void send(Api::SendOptions options, bool ctrlShiftEnter = false);
  192. [[nodiscard]] Fn<void(Api::SendOptions)> sendCallback();
  193. void captionResized();
  194. void saveSendWaySettings();
  195. void setupDragArea();
  196. void refreshTitleText();
  197. void updateBoxSize();
  198. void updateControlsGeometry();
  199. void updateCaptionPlaceholder();
  200. bool addFiles(not_null<const QMimeData*> data);
  201. bool addFiles(Ui::PreparedList list);
  202. void addFile(Ui::PreparedFile &&file);
  203. void pushBlock(int from, int till);
  204. void openDialogToAddFileToAlbum();
  205. void refreshAllAfterChanges(int fromItem, Fn<void()> perform = nullptr);
  206. void enqueueNextPrepare();
  207. void addPreparedAsyncFile(Ui::PreparedFile &&file);
  208. void checkCharsLimitation();
  209. void refreshMessagesCount();
  210. [[nodiscard]] Fn<MenuDetails()> prepareSendMenuDetails(
  211. const SendFilesBoxDescriptor &descriptor);
  212. [[nodiscard]] auto prepareSendMenuCallback()
  213. -> Fn<void(MenuAction, MenuDetails)>;
  214. const std::shared_ptr<ChatHelpers::Show> _show;
  215. const style::ComposeControls &_st;
  216. const Api::SendType _sendType = Api::SendType();
  217. QString _titleText;
  218. rpl::variable<int> _titleHeight = 0;
  219. Ui::PreparedList _list;
  220. std::optional<int> _removingIndex;
  221. rpl::variable<int> _messagesCount;
  222. SendFilesLimits _limits = {};
  223. Fn<MenuDetails()> _sendMenuDetails;
  224. Fn<void(MenuAction, MenuDetails)> _sendMenuCallback;
  225. PeerData *_captionToPeer = nullptr;
  226. SendFilesCheck _check;
  227. SendFilesConfirmed _confirmedCallback;
  228. Fn<void()> _cancelledCallback;
  229. rpl::variable<uint64> _price = 0;
  230. std::unique_ptr<Ui::RpWidget> _priceTag;
  231. QImage _priceTagBg;
  232. bool _confirmed = false;
  233. bool _invertCaption = false;
  234. object_ptr<Ui::InputField> _caption = { nullptr };
  235. std::unique_ptr<ChatHelpers::FieldAutocomplete> _autocomplete;
  236. TextWithTags _prefilledCaptionText;
  237. object_ptr<Ui::EmojiButton> _emojiToggle = { nullptr };
  238. base::unique_qptr<ChatHelpers::TabbedPanel> _emojiPanel;
  239. base::unique_qptr<QObject> _emojiFilter;
  240. using CharactersLimitLabel = HistoryView::Controls::CharactersLimitLabel;
  241. base::unique_qptr<CharactersLimitLabel> _charsLimitation;
  242. object_ptr<Ui::Checkbox> _groupFiles = { nullptr };
  243. object_ptr<Ui::Checkbox> _sendImagesAsPhotos = { nullptr };
  244. object_ptr<Ui::Checkbox> _wayRemember = { nullptr };
  245. object_ptr<Ui::FlatLabel> _hintLabel = { nullptr };
  246. rpl::variable<Ui::SendFilesWay> _sendWay = Ui::SendFilesWay();
  247. rpl::variable<int> _footerHeight = 0;
  248. rpl::lifetime _dimensionsLifetime;
  249. object_ptr<Ui::ScrollArea> _scroll;
  250. QPointer<Ui::VerticalLayout> _inner;
  251. std::vector<Block> _blocks;
  252. Fn<void()> _whenReadySend;
  253. bool _preparing = false;
  254. base::unique_qptr<Ui::PopupMenu> _menu;
  255. QPointer<Ui::RoundButton> _send;
  256. QPointer<Ui::RoundButton> _addFile;
  257. };