/* 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 #include "ui/rp_widget.h" #include "info/info_wrap_widget.h" namespace Dialogs::Stories { struct Content; } // namespace Dialogs::Stories namespace Storage { enum class SharedMediaType : signed char; } // namespace Storage namespace Ui { class RoundRect; class ScrollArea; class InputField; struct ScrollToRequest; template class PaddingWrap; } // namespace Ui namespace Info::Settings { struct Tag; } // namespace Info::Settings namespace Info::Downloads { struct Tag; } // namespace Info::Downloads namespace Info::Stories { struct Tag; enum class Tab; } // namespace Info::Stories namespace Info { class ContentMemento; class Controller; class ContentWidget : public Ui::RpWidget { public: ContentWidget( QWidget *parent, not_null controller); virtual bool showInternal( not_null memento) = 0; std::shared_ptr createMemento(); virtual void setIsStackBottom(bool isStackBottom); [[nodiscard]] bool isStackBottom() const; rpl::producer scrollHeightValue() const; rpl::producer desiredHeightValue() const override; virtual rpl::producer desiredShadowVisibility() const; bool hasTopBarShadow() const; virtual void setInnerFocus(); virtual void showFinished() { } virtual void enableBackButton() { } // When resizing the widget with top edge moved up or down and we // want to add this top movement to the scroll position, so inner // content will not move. void setGeometryWithTopMoved( const QRect &newGeometry, int topDelta); void applyAdditionalScroll(int additionalScroll); int scrollTillBottom(int forHeight) const; [[nodiscard]] rpl::producer scrollTillBottomChanges() const; [[nodiscard]] virtual const Ui::RoundRect *bottomSkipRounding() const { return nullptr; } // Float player interface. bool floatPlayerHandleWheelEvent(QEvent *e); QRect floatPlayerAvailableRect() const; virtual rpl::producer selectedListValue() const; virtual void selectionAction(SelectionAction action) { } [[nodiscard]] virtual rpl::producer title() = 0; [[nodiscard]] virtual auto titleStories() -> rpl::producer; virtual void saveChanges(FnMut done); [[nodiscard]] int scrollBottomSkip() const; [[nodiscard]] rpl::producer scrollBottomSkipValue() const; [[nodiscard]] rpl::producer desiredBottomShadowVisibility() const; protected: template Widget *setInnerWidget(object_ptr inner) { return static_cast( doSetInnerWidget(std::move(inner))); } not_null controller() const { return _controller; } void resizeEvent(QResizeEvent *e) override; void paintEvent(QPaintEvent *e) override; void setScrollTopSkip(int scrollTopSkip); void setScrollBottomSkip(int scrollBottomSkip); int scrollTopSave() const; void scrollTopRestore(int scrollTop); void scrollTo(const Ui::ScrollToRequest &request); [[nodiscard]] rpl::producer scrollTopValue() const; void setPaintPadding(const style::margins &padding); void setViewport(rpl::producer> &&events) const; private: RpWidget *doSetInnerWidget(object_ptr inner); void updateControlsGeometry(); void refreshSearchField(bool shown); virtual std::shared_ptr doCreateMemento() = 0; const not_null _controller; style::color _bg; rpl::variable _scrollTopSkip = -1; rpl::variable _scrollBottomSkip = 0; rpl::event_stream _scrollTillBottomChanges; object_ptr _scroll; Ui::PaddingWrap *_innerWrap = nullptr; base::unique_qptr _searchWrap = nullptr; QPointer _searchField; int _innerDesiredHeight = 0; bool _isStackBottom = false; // Saving here topDelta in setGeometryWithTopMoved() to get it passed to resizeEvent(). int _topDelta = 0; // To paint round edges from content. style::margins _paintPadding; }; class ContentMemento { public: ContentMemento( not_null peer, Data::ForumTopic *topic, PeerId migratedPeerId); explicit ContentMemento(Settings::Tag settings); explicit ContentMemento(Downloads::Tag downloads); explicit ContentMemento(Stories::Tag stories); ContentMemento(not_null poll, FullMsgId contextId) : _poll(poll) , _pollContextId(contextId) { } virtual object_ptr createWidget( QWidget *parent, not_null controller, const QRect &geometry) = 0; PeerData *peer() const { return _peer; } PeerId migratedPeerId() const { return _migratedPeerId; } Data::ForumTopic *topic() const { return _topic; } UserData *settingsSelf() const { return _settingsSelf; } PeerData *storiesPeer() const { return _storiesPeer; } Stories::Tab storiesTab() const { return _storiesTab; } PollData *poll() const { return _poll; } FullMsgId pollContextId() const { return _pollContextId; } Key key() const; virtual Section section() const = 0; virtual ~ContentMemento() = default; void setScrollTop(int scrollTop) { _scrollTop = scrollTop; } int scrollTop() const { return _scrollTop; } void setSearchFieldQuery(const QString &query) { _searchFieldQuery = query; } QString searchFieldQuery() const { return _searchFieldQuery; } void setSearchEnabledByContent(bool enabled) { _searchEnabledByContent = enabled; } bool searchEnabledByContent() const { return _searchEnabledByContent; } void setSearchStartsFocused(bool focused) { _searchStartsFocused = focused; } bool searchStartsFocused() const { return _searchStartsFocused; } private: PeerData * const _peer = nullptr; const PeerId _migratedPeerId = 0; Data::ForumTopic *_topic = nullptr; UserData * const _settingsSelf = nullptr; PeerData * const _storiesPeer = nullptr; Stories::Tab _storiesTab = {}; PollData * const _poll = nullptr; const FullMsgId _pollContextId; int _scrollTop = 0; QString _searchFieldQuery; bool _searchEnabledByContent = false; bool _searchStartsFocused = false; rpl::lifetime _lifetime; }; } // namespace Info