/* 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 "window/section_widget.h" #include "window/section_memento.h" #include "history/view/history_view_corner_buttons.h" #include "history/view/history_view_list_widget.h" #include "data/data_messages.h" #include "base/timer.h" class History; enum class SendMediaType; struct SendingAlbum; namespace SendMenu { enum class Type; } // namespace SendMenu namespace Api { struct SendOptions; struct SendAction; } // namespace Api namespace Storage { } // namespace Storage namespace Ui { class ScrollArea; class PlainShadow; class FlatButton; class PinnedBar; struct PreparedList; class SendFilesWay; } // namespace Ui namespace Profile { class BackButton; } // namespace Profile namespace InlineBots { class Result; } // namespace InlineBots namespace Data { class RepliesList; class ForumTopic; } // namespace Data namespace HistoryView { namespace Controls { struct VoiceToSend; } // namespace Controls class Element; class TopBarWidget; class RepliesMemento; class ComposeControls; class SendActionPainter; class StickerToast; class TopicReopenBar; class EmptyPainter; class PinnedTracker; class TranslateBar; class RepliesWidget final : public Window::SectionWidget , private ListDelegate , private CornerButtonsDelegate { public: RepliesWidget( QWidget *parent, not_null controller, not_null history, MsgId rootId); ~RepliesWidget(); [[nodiscard]] not_null history() const; Dialogs::RowDescriptor activeChat() const override; bool preventsClose(Fn &&continueCallback) const override; bool hasTopBarShadow() const override { return true; } QPixmap grabForShowAnimation( const Window::SectionSlideParams ¶ms) override; bool showInternal( not_null memento, const Window::SectionShow ¶ms) override; std::shared_ptr createMemento() override; bool showMessage( PeerId peerId, const Window::SectionShow ¶ms, MsgId messageId) override; Window::SectionActionResult sendBotCommand( Bot::SendCommandRequest request) override; bool confirmSendingFiles(const QStringList &files) override; bool confirmSendingFiles(not_null data) override; void setInternalState( const QRect &geometry, not_null memento); // Tabbed selector management. bool pushTabbedSelectorToThirdSection( not_null thread, const Window::SectionShow ¶ms) override; bool returnTabbedSelector() override; // Float player interface. bool floatPlayerHandleWheelEvent(QEvent *e) override; QRect floatPlayerAvailableRect() override; // ListDelegate interface. Context listContext() override; bool listScrollTo(int top, bool syntetic = true) override; void listCancelRequest() override; void listDeleteRequest() override; void listTryProcessKeyInput(not_null e) override; rpl::producer listSource( Data::MessagePosition aroundId, int limitBefore, int limitAfter) override; bool listAllowsMultiSelect() override; bool listIsItemGoodForSelection(not_null item) override; bool listIsLessInOrder( not_null first, not_null second) override; void listSelectionChanged(SelectedItems &&items) override; void listMarkReadTill(not_null item) override; void listMarkContentsRead( const base::flat_set> &items) override; MessagesBarData listMessagesBar( const std::vector> &elements) override; void listContentRefreshed() override; void listUpdateDateLink( ClickHandlerPtr &link, not_null view) override; bool listElementHideReply(not_null view) override; bool listElementShownUnread(not_null view) override; bool listIsGoodForAroundPosition(not_null view) override; void listSendBotCommand( const QString &command, const FullMsgId &context) override; void listHandleViaClick(not_null bot) override; not_null listChatTheme() override; CopyRestrictionType listCopyRestrictionType(HistoryItem *item) override; CopyRestrictionType listCopyMediaRestrictionType( not_null item) override; CopyRestrictionType listSelectRestrictionType() override; auto listAllowedReactionsValue() ->rpl::producer override; void listShowPremiumToast(not_null document) override; void listOpenPhoto( not_null photo, FullMsgId context) override; void listOpenDocument( not_null document, FullMsgId context, bool showInMediaView) override; void listPaintEmpty( Painter &p, const Ui::ChatPaintContext &context) override; QString listElementAuthorRank(not_null view) override; History *listTranslateHistory() override; void listAddTranslatedItems( not_null tracker) override; // CornerButtonsDelegate delegate. void cornerButtonsShowAtPosition( Data::MessagePosition position) override; Data::Thread *cornerButtonsThread() override; FullMsgId cornerButtonsCurrentId() override; bool cornerButtonsIgnoreVisibility() override; std::optional cornerButtonsDownShown() override; bool cornerButtonsUnreadMayBeShown() override; bool cornerButtonsHas(CornerButtonType type) override; private: void resizeEvent(QResizeEvent *e) override; void paintEvent(QPaintEvent *e) override; void showAnimatedHook( const Window::SectionSlideParams ¶ms) override; void showFinishedHook() override; void checkActivation() override; void doSetInnerFocus() override; void onScroll(); void updateInnerVisibleArea(); void updateControlsGeometry(); void updateAdaptiveLayout(); void saveState(not_null memento); void restoreState(not_null memento); void setReplies(std::shared_ptr replies); void refreshReplies(); void showAtStart(); void showAtEnd(); void showAtPosition( Data::MessagePosition position, FullMsgId originItemId = {}); void showAtPosition( Data::MessagePosition position, FullMsgId originItemId, const Window::SectionShow ¶ms); void finishSending(); void setupComposeControls(); void setupRoot(); void setupRootView(); void setupTopicViewer(); void subscribeToTopic(); void subscribeToPinnedMessages(); void setTopic(Data::ForumTopic *topic); void setupDragArea(); void setupShortcuts(); void setupTranslateBar(); void searchInTopic(); void updatePinnedVisibility(); void confirmDeleteSelected(); void confirmForwardSelected(); void clearSelected(); void setPinnedVisibility(bool shown); [[nodiscard]] Api::SendAction prepareSendAction( Api::SendOptions options) const; void send(); void send(Api::SendOptions options); void sendVoice(Controls::VoiceToSend &&data); void edit( not_null item, Api::SendOptions options, mtpRequestId *const saveEditMsgRequestId); void chooseAttach(std::optional overrideSendImagesAsPhotos); [[nodiscard]] SendMenu::Type sendMenuType() const; [[nodiscard]] FullReplyTo replyTo() const; [[nodiscard]] HistoryItem *lookupRoot() const; [[nodiscard]] Data::ForumTopic *lookupTopic(); [[nodiscard]] bool computeAreComments() const; void orderWidgets(); void pushReplyReturn(not_null item); void checkReplyReturns(); void recountChatWidth(); void replyToMessage(FullReplyTo id); void refreshTopBarActiveChat(); void refreshUnreadCountBadge(std::optional count); void hidePinnedMessage(); void updatePinnedViewer(); void setupPinnedTracker(); void checkPinnedBarState(); void clearHidingPinnedBar(); void refreshPinnedBarButton(bool many, HistoryItem *item); void checkLastPinnedClickedIdReset( int wasScrollTop, int nowScrollTop); void uploadFile(const QByteArray &fileContent, SendMediaType type); bool confirmSendingFiles( QImage &&image, QByteArray &&content, std::optional overrideSendImagesAsPhotos = std::nullopt, const QString &insertTextOnCancel = QString()); bool confirmSendingFiles( const QStringList &files, const QString &insertTextOnCancel); bool confirmSendingFiles( Ui::PreparedList &&list, const QString &insertTextOnCancel = QString()); bool confirmSendingFiles( not_null data, std::optional overrideSendImagesAsPhotos, const QString &insertTextOnCancel = QString()); bool showSendingFilesError(const Ui::PreparedList &list) const; bool showSendingFilesError( const Ui::PreparedList &list, std::optional compress) const; void sendingFilesConfirmed( Ui::PreparedList &&list, Ui::SendFilesWay way, TextWithTags &&caption, Api::SendOptions options, bool ctrlShiftEnter); void sendExistingDocument(not_null document); bool sendExistingDocument( not_null document, Api::SendOptions options, std::optional localId); void sendExistingPhoto(not_null photo); bool sendExistingPhoto( not_null photo, Api::SendOptions options); void sendInlineResult( not_null result, not_null bot); void sendInlineResult( not_null result, not_null bot, Api::SendOptions options, std::optional localMessageId); void setupEmptyPainter(); void refreshJoinGroupButton(); [[nodiscard]] bool emptyShown() const; [[nodiscard]] bool showSlowmodeError(); const not_null _history; MsgId _rootId = 0; std::shared_ptr _theme; HistoryItem *_root = nullptr; Data::ForumTopic *_topic = nullptr; mutable bool _newTopicDiscarded = false; std::shared_ptr _replies; rpl::lifetime _repliesLifetime; rpl::variable _areComments = false; std::shared_ptr _sendAction; QPointer _inner; object_ptr _topBar; object_ptr _topBarShadow; std::unique_ptr _composeControls; std::unique_ptr _joinGroup; std::unique_ptr _topicReopenBar; std::unique_ptr _emptyPainter; bool _skipScrollEvent = false; bool _synteticScrollEvent = false; std::unique_ptr _translateBar; int _translateBarHeight = 0; std::unique_ptr _pinnedTracker; std::unique_ptr _pinnedBar; std::unique_ptr _hidingPinnedBar; int _pinnedBarHeight = 0; FullMsgId _pinnedClickedId; std::optional _minPinnedId; HistoryItem *_shownPinnedItem = nullptr; std::unique_ptr _rootView; int _rootViewHeight = 0; bool _rootViewInited = false; bool _rootViewInitScheduled = false; rpl::variable _rootVisible = false; std::unique_ptr _scroll; std::unique_ptr _stickerToast; FullMsgId _lastShownAt; HistoryView::CornerButtons _cornerButtons; rpl::lifetime _topicLifetime; int _lastScrollTop = 0; int _topicReopenBarHeight = 0; int _scrollTopDelta = 0; bool _choosingAttach = false; bool _loaded = false; }; class RepliesMemento final : public Window::SectionMemento { public: RepliesMemento( not_null history, MsgId rootId, MsgId highlightId = 0, const TextWithEntities &highlightPart = {}); explicit RepliesMemento( not_null commentsItem, MsgId commentId = 0); void setReadInformation( MsgId inboxReadTillId, int unreadCount, MsgId outboxReadTillId); object_ptr createWidget( QWidget *parent, not_null controller, Window::Column column, const QRect &geometry) override; [[nodiscard]] not_null getHistory() const { return _history; } [[nodiscard]] MsgId getRootId() const { return _rootId; } void setReplies(std::shared_ptr replies) { _replies = std::move(replies); } [[nodiscard]] std::shared_ptr getReplies() const { return _replies; } void setFromTopic(not_null topic); void setReplyReturns(const QVector &list) { _replyReturns = list; } const QVector &replyReturns() const { return _replyReturns; } Data::ForumTopic *topicForRemoveRequests() const override; [[nodiscard]] not_null list() { return &_list; } [[nodiscard]] MsgId highlightId() const { return _highlightId; } [[nodiscard]] const TextWithEntities &highlightPart() const { return _highlightPart; } private: void setupTopicViewer(); const not_null _history; MsgId _rootId = 0; const MsgId _highlightId = 0; const TextWithEntities _highlightPart; ListMemento _list; std::shared_ptr _replies; QVector _replyReturns; rpl::lifetime _lifetime; }; } // namespace HistoryView