/* 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 "base/observer.h" #include "dialogs/dialogs_key.h" class AuthSession; class MainWidget; class HistoryMessage; class HistoryService; namespace Settings { enum class Type; } // namespace Settings namespace Media { namespace Player { class FloatController; class FloatDelegate; } // namespace Player } // namespace Media namespace Passport { struct FormRequest; class FormController; } // namespace Passport 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(ClickContext context) 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 SessionController; class SessionNavigation { public: explicit SessionNavigation(not_null session); AuthSession &session() const; 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()); void showSettings( Settings::Type type, const SectionShow ¶ms = SectionShow()); void showSettings(const SectionShow ¶ms = SectionShow()); virtual ~SessionNavigation() = default; private: const not_null _session; }; class SessionController : public SessionNavigation , private base::Subscriber { public: SessionController( not_null session, not_null window); not_null window() const { return _window; } // This is needed for History TopBar updating when searchInChat // is changed in the Dialogs::Widget of the current window. rpl::variable searchInChat; bool uniqueChatsInSearchResults() const; void openFolder(not_null folder); void closeFolder(); const rpl::variable &openedFolder() const; 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; bool jumpToChatListEntry(Dialogs::RowDescriptor row); void showEditPeerBox(PeerData *peer); 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 removeLayerBlackout(); void showJumpToDate( Dialogs::Key chat, QDate requestedDate); void showPassportForm(const Passport::FormRequest &request); void clearPassportForm(); 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; } void setDefaultFloatPlayerDelegate( not_null delegate); void replaceFloatPlayerDelegate( not_null replacement); void restoreFloatPlayerDelegate( not_null replacement); rpl::producer floatPlayerClosed() const; rpl::lifetime &lifetime() { return _lifetime; } ~SessionController(); private: void init(); void initSupportMode(); 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; void pushToChatEntryHistory(Dialogs::RowDescriptor row); bool chatEntryHistoryMove(int steps); const not_null _window; std::unique_ptr _passportForm; GifPauseReasons _gifPauseReasons = 0; base::Observable _gifPauseLevelChanged; base::Observable _floatPlayerAreaUpdated; rpl::variable _activeChatEntry; base::Variable _dialogsListFocused = { false }; base::Variable _dialogsListDisplayForced = { false }; std::deque _chatEntryHistory; int _chatEntryHistoryPosition = -1; std::unique_ptr _floatPlayers; Media::Player::FloatDelegate *_defaultFloatPlayerDelegate = nullptr; Media::Player::FloatDelegate *_replacementFloatPlayerDelegate = nullptr; PeerData *_showEditPeer = nullptr; rpl::variable _openedFolder; rpl::lifetime _lifetime; }; } // namespace Window