/* 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 "boxes/abstract_box.h" #include "ui/chat/attach/attach_prepare.h" #include "ui/chat/attach/attach_send_files_way.h" #include "ui/widgets/popup_menu.h" #include "storage/localimageloader.h" #include "storage/storage_media_prepare.h" namespace style { struct ComposeControls; } // namespace style namespace Window { class SessionController; } // namespace Window namespace Api { struct SendOptions; enum class SendType; } // namespace Api namespace ChatHelpers { class TabbedPanel; class Show; } // namespace ChatHelpers namespace Ui { class Checkbox; class RoundButton; class InputField; struct GroupMediaLayout; class EmojiButton; class AlbumPreview; class VerticalLayout; class FlatLabel; class PopupMenu; } // namespace Ui namespace Window { class SessionController; } // namespace Window namespace SendMenu { enum class Type; } // namespace SendMenu enum class SendFilesAllow { OnlyOne = (1 << 0), Photos = (1 << 1), Videos = (1 << 2), Music = (1 << 3), Files = (1 << 4), Stickers = (1 << 5), Gifs = (1 << 6), EmojiWithoutPremium = (1 << 7), Texts = (1 << 8), }; inline constexpr bool is_flag_type(SendFilesAllow) { return true; } using SendFilesLimits = base::flags; using SendFilesCheck = Fn; [[nodiscard]] SendFilesLimits DefaultLimitsForPeer(not_null peer); [[nodiscard]] SendFilesCheck DefaultCheckForPeer( not_null controller, not_null peer); [[nodiscard]] SendFilesCheck DefaultCheckForPeer( std::shared_ptr show, not_null peer); using SendFilesConfirmed = Fn; struct SendFilesBoxDescriptor { std::shared_ptr show; Ui::PreparedList list; TextWithTags caption; SendFilesLimits limits = {}; SendFilesCheck check; Api::SendType sendType = {}; SendMenu::Type sendMenuType = {}; const style::ComposeControls *stOverride = nullptr; SendFilesConfirmed confirmed; Fn cancelled; }; class SendFilesBox : public Ui::BoxContent { public: enum class SendLimit { One, Many }; SendFilesBox( QWidget*, not_null controller, Ui::PreparedList &&list, const TextWithTags &caption, SendFilesLimits limits, SendFilesCheck check, Api::SendType sendType, SendMenu::Type sendMenuType); SendFilesBox(QWidget*, SendFilesBoxDescriptor &&descriptor); void setConfirmedCallback(SendFilesConfirmed callback) { _confirmedCallback = std::move(callback); } void setCancelledCallback(Fn callback) { _cancelledCallback = std::move(callback); } ~SendFilesBox(); protected: void prepare() override; void setInnerFocus() override; void keyPressEvent(QKeyEvent *e) override; void paintEvent(QPaintEvent *e) override; void resizeEvent(QResizeEvent *e) override; private: class Block final { public: Block( not_null parent, const style::ComposeControls &st, not_null*> items, int from, int till, Fn gifPaused, Ui::SendFilesWay way); Block(Block &&other) = default; Block &operator=(Block &&other) = default; [[nodiscard]] int fromIndex() const; [[nodiscard]] int tillIndex() const; [[nodiscard]] object_ptr takeWidget(); [[nodiscard]] rpl::producer itemDeleteRequest() const; [[nodiscard]] rpl::producer itemReplaceRequest() const; [[nodiscard]] rpl::producer itemModifyRequest() const; void setSendWay(Ui::SendFilesWay way); void toggleSpoilers(bool enabled); void applyChanges(); private: base::unique_qptr _preview; not_null*> _items; int _from = 0; int _till = 0; bool _isAlbum = false; bool _isSingleMedia = false; }; void initSendWay(); void initPreview(); [[nodiscard]] bool hasSendMenu() const; [[nodiscard]] bool hasSpoilerMenu() const; [[nodiscard]] bool allWithSpoilers(); [[nodiscard]] bool checkWithWay( Ui::SendFilesWay way, bool silent = false) const; [[nodiscard]] bool checkWith( const Ui::PreparedList &added, Ui::SendFilesWay way, bool silent = false) const; void addMenuButton(); void applyBlockChanges(); void toggleSpoilers(bool enabled); bool validateLength(const QString &text) const; void refreshButtons(); void refreshControls(bool initial = false); void setupSendWayControls(); void setupCaption(); void setupEmojiPanel(); void updateSendWayControls(); void updateEmojiPanelGeometry(); void emojiFilterForGeometry(not_null event); void preparePreview(); void generatePreviewFrom(int fromBlock); void send(Api::SendOptions options, bool ctrlShiftEnter = false); void sendSilent(); void sendScheduled(); void sendWhenOnline(); void captionResized(); void saveSendWaySettings(); void setupDragArea(); void refreshTitleText(); void updateBoxSize(); void updateControlsGeometry(); void updateCaptionPlaceholder(); bool addFiles(not_null data); bool addFiles(Ui::PreparedList list); void addFile(Ui::PreparedFile &&file); void pushBlock(int from, int till); void openDialogToAddFileToAlbum(); void refreshAllAfterChanges(int fromItem, Fn perform = nullptr); void enqueueNextPrepare(); void addPreparedAsyncFile(Ui::PreparedFile &&file); const std::shared_ptr _show; const style::ComposeControls &_st; const Api::SendType _sendType = Api::SendType(); QString _titleText; rpl::variable _titleHeight = 0; Ui::PreparedList _list; std::optional _removingIndex; SendFilesLimits _limits = {}; SendMenu::Type _sendMenuType = {}; SendFilesCheck _check; SendFilesConfirmed _confirmedCallback; Fn _cancelledCallback; bool _confirmed = false; object_ptr _caption = { nullptr }; TextWithTags _prefilledCaptionText; object_ptr _emojiToggle = { nullptr }; base::unique_qptr _emojiPanel; base::unique_qptr _emojiFilter; object_ptr _groupFiles = { nullptr }; object_ptr _sendImagesAsPhotos = { nullptr }; object_ptr _wayRemember = { nullptr }; object_ptr _hintLabel = { nullptr }; rpl::variable _sendWay = Ui::SendFilesWay(); rpl::variable _footerHeight = 0; rpl::lifetime _dimensionsLifetime; object_ptr _scroll; QPointer _inner; std::vector _blocks; Fn _whenReadySend; bool _preparing = false; base::unique_qptr _menu; QPointer _send; QPointer _addFile; };