/* 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 "base/flags.h" #include "dialogs/dialogs_key.h" class MainWidget; class HistoryMessage; class HistoryService; namespace Media { namespace Player { class RoundController; } // namespace Player } // namespace Media namespace Window { class LayerWidget; class MainWindow; class SectionMemento; enum class GifPauseReason { Any = 0, InlineResults = (1 << 0), SavedGifs = (1 << 1), Layer = (1 << 2), RoundPlaying = (1 << 3), MediaPreview = (1 << 4), }; using GifPauseReasons = base::flags; inline constexpr bool is_flag_type(GifPauseReason) { return true; }; class DateClickHandler : public ClickHandler { public: DateClickHandler(Dialogs::Key chat, QDate date); void setDate(QDate date); void onClick(Qt::MouseButton) const override; private: Dialogs::Key _chat; QDate _date; }; struct SectionShow { enum class Way { Forward, Backward, ClearStack, }; SectionShow( Way way = Way::Forward, anim::type animated = anim::type::normal, anim::activation activation = anim::activation::normal) : way(way) , animated(animated) , activation(activation) { } SectionShow( anim::type animated, anim::activation activation = anim::activation::normal) : animated(animated) , activation(activation) { } SectionShow withWay(Way newWay) const { return SectionShow(newWay, animated, activation); } SectionShow withThirdColumn() const { auto copy = *this; copy.thirdColumn = true; return copy; } Way way = Way::Forward; anim::type animated = anim::type::normal; anim::activation activation = anim::activation::normal; bool thirdColumn = false; }; class Controller; class Navigation { public: virtual void showSection( SectionMemento &&memento, const SectionShow ¶ms = SectionShow()) = 0; virtual void showBackFromStack( const SectionShow ¶ms = SectionShow()) = 0; virtual not_null parentController() = 0; void showPeerInfo( PeerId peerId, const SectionShow ¶ms = SectionShow()); void showPeerInfo( not_null peer, const SectionShow ¶ms = SectionShow()); void showPeerInfo( not_null history, const SectionShow ¶ms = SectionShow()); virtual ~Navigation() = default; }; class Controller : public Navigation { public: Controller(not_null window); not_null window() const { return _window; } // This is needed for History TopBar updating when searchInChat // is changed in the DialogsWidget of the current window. rpl::variable searchInChat; void setActiveChatEntry(Dialogs::RowDescriptor row); void setActiveChatEntry(Dialogs::Key key); Dialogs::RowDescriptor activeChatEntryCurrent() const; Dialogs::Key activeChatCurrent() const; rpl::producer activeChatEntryChanges() const; rpl::producer activeChatChanges() const; rpl::producer activeChatEntryValue() const; rpl::producer activeChatValue() const; void enableGifPauseReason(GifPauseReason reason); void disableGifPauseReason(GifPauseReason reason); base::Observable &gifPauseLevelChanged() { return _gifPauseLevelChanged; } bool isGifPausedAtLeastFor(GifPauseReason reason) const; base::Observable &floatPlayerAreaUpdated() { return _floatPlayerAreaUpdated; } struct ColumnLayout { int bodyWidth; int dialogsWidth; int chatWidth; int thirdWidth; Adaptive::WindowLayout windowLayout; }; ColumnLayout computeColumnLayout() const; int dialogsSmallColumnWidth() const; bool forceWideDialogs() const; void updateColumnLayout(); bool canShowThirdSection() const; bool canShowThirdSectionWithoutResize() const; bool takeThirdSectionFromLayer(); void resizeForThirdSection(); void closeThirdSection(); void showSection( SectionMemento &&memento, const SectionShow ¶ms = SectionShow()) override; void showBackFromStack( const SectionShow ¶ms = SectionShow()) override; void showPeerHistory( PeerId peerId, const SectionShow ¶ms = SectionShow::Way::ClearStack, MsgId msgId = ShowAtUnreadMsgId); void showPeerHistory( not_null peer, const SectionShow ¶ms = SectionShow::Way::ClearStack, MsgId msgId = ShowAtUnreadMsgId); void showPeerHistory( not_null history, const SectionShow ¶ms = SectionShow::Way::ClearStack, MsgId msgId = ShowAtUnreadMsgId); void clearSectionStack( const SectionShow ¶ms = SectionShow::Way::ClearStack) { showPeerHistory( PeerId(0), params, ShowAtUnreadMsgId); } void showSpecialLayer( object_ptr &&layer, anim::type animated = anim::type::normal); void hideSpecialLayer( anim::type animated = anim::type::normal) { showSpecialLayer(nullptr, animated); } void showJumpToDate( Dialogs::Key chat, QDate requestedDate); base::Variable &dialogsListFocused() { return _dialogsListFocused; } const base::Variable &dialogsListFocused() const { return _dialogsListFocused; } base::Variable &dialogsListDisplayForced() { return _dialogsListDisplayForced; } const base::Variable &dialogsListDisplayForced() const { return _dialogsListDisplayForced; } not_null parentController() override { return this; } using RoundController = Media::Player::RoundController; bool startRoundVideo(not_null context); RoundController *currentRoundVideo() const; RoundController *roundVideo(not_null context) const; RoundController *roundVideo(FullMsgId contextId) const; void roundVideoFinished(not_null video); rpl::lifetime &lifetime() { return _lifetime; } ~Controller(); private: int minimalThreeColumnWidth() const; not_null chats() const; int countDialogsWidthFromRatio(int bodyWidth) const; int countThirdColumnWidthFromRatio(int bodyWidth) const; struct ShrinkResult { int dialogsWidth; int thirdWidth; }; ShrinkResult shrinkDialogsAndThirdColumns( int dialogsWidth, int thirdWidth, int bodyWidth) const; not_null _window; GifPauseReasons _gifPauseReasons = 0; base::Observable _gifPauseLevelChanged; base::Observable _floatPlayerAreaUpdated; rpl::variable _activeChatEntry; base::Variable _dialogsListFocused = { false }; base::Variable _dialogsListDisplayForced = { false }; std::unique_ptr _roundVideo; rpl::lifetime _lifetime; }; } // namespace Window