From 51878ab38e4724b715cf92563875fe591fcb613e Mon Sep 17 00:00:00 2001 From: John Preston Date: Tue, 6 May 2025 21:22:36 +0400 Subject: [PATCH] Allow opening monoforums. --- Telegram/SourceFiles/data/data_channel.cpp | 10 +- .../SourceFiles/data/data_saved_messages.cpp | 24 ++++ .../SourceFiles/data/data_saved_messages.h | 8 ++ .../dialogs/dialogs_inner_widget.cpp | 41 ++++++ .../dialogs/dialogs_inner_widget.h | 1 + .../SourceFiles/dialogs/dialogs_main_list.cpp | 2 +- .../SourceFiles/dialogs/dialogs_widget.cpp | 130 ++++++++++++++++-- Telegram/SourceFiles/dialogs/dialogs_widget.h | 16 ++- .../view/history_view_top_bar_widget.cpp | 4 + .../info/profile/info_profile_actions.cpp | 17 +++ Telegram/SourceFiles/mainwidget.cpp | 12 ++ Telegram/SourceFiles/mainwidget.h | 4 + .../window/window_session_controller.cpp | 59 +++++++- .../window/window_session_controller.h | 9 ++ 14 files changed, 317 insertions(+), 20 deletions(-) diff --git a/Telegram/SourceFiles/data/data_channel.cpp b/Telegram/SourceFiles/data/data_channel.cpp index 817e59fb97..0159fcca80 100644 --- a/Telegram/SourceFiles/data/data_channel.cpp +++ b/Telegram/SourceFiles/data/data_channel.cpp @@ -199,12 +199,18 @@ void ChannelData::setFlags(ChannelDataFlags which) { // Let Data::Forum live till the end of _flags.set. // That way the data can be used in changes handler. // Example: render frame for forum auto-closing animation. - const auto taken = ((diff & Flag::Forum) && !(which & Flag::Forum)) + const auto takenForum = ((diff & Flag::Forum) && !(which & Flag::Forum)) ? mgInfo->takeForumData() : nullptr; + const auto takenMonoforum = ((diff & Flag::Monoforum) + && !(which & Flag::Monoforum)) + ? mgInfo->takeMonoforumData() + : nullptr; const auto wasIn = amIn(); if ((diff & Flag::Forum) && (which & Flag::Forum)) { mgInfo->ensureForum(this); + } else if ((diff & Flag::Monoforum) && (which & Flag::Monoforum)) { + mgInfo->ensureMonoforum(this); } _flags.set(which); if (diff & (Flag::Left | Flag::Forbidden)) { @@ -252,7 +258,7 @@ void ChannelData::setFlags(ChannelDataFlags which) { } } } - if (const auto raw = taken.get()) { + if (const auto raw = takenForum.get()) { owner().forumIcons().clearUserpicsReset(raw); } } diff --git a/Telegram/SourceFiles/data/data_saved_messages.cpp b/Telegram/SourceFiles/data/data_saved_messages.cpp index 6a401afd17..74a597b287 100644 --- a/Telegram/SourceFiles/data/data_saved_messages.cpp +++ b/Telegram/SourceFiles/data/data_saved_messages.cpp @@ -74,6 +74,10 @@ rpl::producer<> SavedMessages::chatsListChanges() const { return _chatsListChanges.events(); } +rpl::producer<> SavedMessages::chatsListLoadedEvents() const { + return _chatsListLoadedEvents.events(); +} + void SavedMessages::loadMore() { _loadMoreScheduled = true; _loadMore.call(); @@ -104,6 +108,9 @@ void SavedMessages::sendLoadMore() { ).done([=](const MTPmessages_SavedDialogs &result) { apply(result, false); _chatsListChanges.fire({}); + if (_chatsList.loaded()) { + _chatsListLoadedEvents.fire({}); + } }).fail([=](const MTP::Error &error) { if (error.type() == u"SAVED_DIALOGS_UNSUPPORTED"_q) { _unsupported = true; @@ -321,6 +328,23 @@ void SavedMessages::apply(const MTPDupdateSavedDialogPinned &update) { }); } +rpl::producer<> SavedMessages::destroyed() const { + if (!_parentChat) { + return rpl::never<>(); + } + return _parentChat->flagsValue( + ) | rpl::filter([=](const ChannelData::Flags::Change &update) { + using Flag = ChannelData::Flag; + return (update.diff & Flag::Monoforum) + && !(update.value & Flag::Monoforum); + }) | rpl::take(1) | rpl::to_empty; +} + +auto SavedMessages::sublistDestroyed() const +-> rpl::producer> { + return _sublistDestroyed.events(); +} + rpl::lifetime &SavedMessages::lifetime() { return _lifetime; } diff --git a/Telegram/SourceFiles/data/data_saved_messages.h b/Telegram/SourceFiles/data/data_saved_messages.h index 3ef9aae9c0..6d6bbe3236 100644 --- a/Telegram/SourceFiles/data/data_saved_messages.h +++ b/Telegram/SourceFiles/data/data_saved_messages.h @@ -35,6 +35,11 @@ public: [[nodiscard]] not_null sublist(not_null peer); [[nodiscard]] rpl::producer<> chatsListChanges() const; + [[nodiscard]] rpl::producer<> chatsListLoadedEvents() const; + + [[nodiscard]] rpl::producer<> destroyed() const; + [[nodiscard]] auto sublistDestroyed() const + -> rpl::producer>; void loadMore(); void loadMore(not_null sublist); @@ -55,6 +60,8 @@ private: const not_null _owner; ChannelData *_parentChat = nullptr; + rpl::event_stream> _sublistDestroyed; + Dialogs::MainList _chatsList; base::flat_map< not_null, @@ -73,6 +80,7 @@ private: bool _loadMoreScheduled = false; rpl::event_stream<> _chatsListChanges; + rpl::event_stream<> _chatsListLoadedEvents; bool _pinnedLoaded = false; bool _unsupported = false; diff --git a/Telegram/SourceFiles/dialogs/dialogs_inner_widget.cpp b/Telegram/SourceFiles/dialogs/dialogs_inner_widget.cpp index 4b21f5c6e9..79996bd7b6 100644 --- a/Telegram/SourceFiles/dialogs/dialogs_inner_widget.cpp +++ b/Telegram/SourceFiles/dialogs/dialogs_inner_widget.cpp @@ -781,6 +781,47 @@ void InnerWidget::changeOpenedForum(Data::Forum *forum) { } } +void InnerWidget::changeOpenedMonoforum(Data::SavedMessages *monoforum) { + if (_savedSublists == monoforum) { + return; + } + stopReorderPinned(); + clearSelection(); + + if (monoforum) { + saveChatsFilterScrollState(_filterId); + } + _filterId = monoforum + ? 0 + : _controller->activeChatsFilterCurrent(); + if (_openedForum) { + // If we close it inside forum destruction we should not schedule. + session().data().forumIcons().scheduleUserpicsReset(_openedForum); + } + _savedSublists = monoforum; + _st = &st::defaultDialogRow; + refreshShownList(); + + _openedForumLifetime.destroy(); + if (monoforum) { + rpl::merge( + monoforum->chatsListChanges(), + monoforum->chatsListLoadedEvents() + ) | rpl::start_with_next([=] { + refresh(); + }, _openedForumLifetime); + } + + refreshWithCollapsedRows(true); + if (_loadMoreCallback) { + _loadMoreCallback(); + } + + if (!monoforum) { + restoreChatsFilterScrollState(_filterId); + } +} + void InnerWidget::showSavedSublists(ChannelData *parentChat) { Expects(!parentChat || parentChat->monoforum()); Expects(!_geometryInited); diff --git a/Telegram/SourceFiles/dialogs/dialogs_inner_widget.h b/Telegram/SourceFiles/dialogs/dialogs_inner_widget.h index bc6b54e832..f840a99b43 100644 --- a/Telegram/SourceFiles/dialogs/dialogs_inner_widget.h +++ b/Telegram/SourceFiles/dialogs/dialogs_inner_widget.h @@ -141,6 +141,7 @@ public: void changeOpenedFolder(Data::Folder *folder); void changeOpenedForum(Data::Forum *forum); + void changeOpenedMonoforum(Data::SavedMessages *monoforum); void showSavedSublists(ChannelData *parentChat); void selectSkip(int32 direction); void selectSkipPage(int32 pixels, int32 direction); diff --git a/Telegram/SourceFiles/dialogs/dialogs_main_list.cpp b/Telegram/SourceFiles/dialogs/dialogs_main_list.cpp index 9c9ad67bae..5e525b5a2c 100644 --- a/Telegram/SourceFiles/dialogs/dialogs_main_list.cpp +++ b/Telegram/SourceFiles/dialogs/dialogs_main_list.cpp @@ -28,7 +28,7 @@ MainList::MainList( std::move( pinnedLimit ) | rpl::start_with_next([=](int limit) { - _pinned.setLimit(limit); + _pinned.setLimit(std::max(limit, 1)); }, _lifetime); session->changes().realtimeNameUpdates( diff --git a/Telegram/SourceFiles/dialogs/dialogs_widget.cpp b/Telegram/SourceFiles/dialogs/dialogs_widget.cpp index 4223f86538..cc817e3011 100644 --- a/Telegram/SourceFiles/dialogs/dialogs_widget.cpp +++ b/Telegram/SourceFiles/dialogs/dialogs_widget.cpp @@ -25,6 +25,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "history/view/history_view_contact_status.h" #include "history/view/history_view_requests_bar.h" #include "history/view/history_view_group_call_bar.h" +#include "history/view/history_view_sublist_section.h" #include "boxes/peers/edit_peer_requests_box.h" #include "ui/text/text_utilities.h" #include "ui/widgets/buttons.h" @@ -78,6 +79,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "data/data_changes.h" #include "data/data_download_manager.h" #include "data/data_chat_filters.h" +#include "data/data_saved_messages.h" #include "data/data_saved_sublist.h" #include "data/data_stories.h" #include "info/downloads/info_downloads_widget.h" @@ -418,6 +420,8 @@ Widget::Widget( ) | rpl::filter([=](const Data::HistoryUpdate &update) { if (_openedForum) { return (update.history == _openedForum->history()); + } else if (_openedMonoforum) { + return (update.history->peer == _openedMonoforum->parentChat()); } else if (_openedFolder) { return (update.history->folder() == _openedFolder) && !update.history->isPinnedDialog(FilterId()); @@ -596,6 +600,7 @@ Widget::Widget( _search->setFocusFast(); if (_childList) { controller->closeForum(); + controller->closeMonoforum(); } }); @@ -618,6 +623,8 @@ Widget::Widget( searchMore(); } else if (_openedForum && state == WidgetState::Default) { _openedForum->requestTopics(); + } else if (_openedMonoforum && state == WidgetState::Default) { + _openedMonoforum->loadMore(); } else { const auto folder = _inner->shownFolder(); if (!folder || !folder->chatsList()->loaded()) { @@ -666,7 +673,16 @@ Widget::Widget( ) | rpl::filter(!rpl::mappers::_1) | rpl::start_with_next([=] { if (_openedForum) { changeOpenedForum(nullptr, anim::type::normal); - } else if (_childList) { + } else if (_childList && !_childList->openedMonoforum()) { + closeChildList(anim::type::normal); + } + }, lifetime()); + + controller->shownMonoforum().changes( + ) | rpl::filter(!rpl::mappers::_1) | rpl::start_with_next([=] { + if (_openedMonoforum) { + changeOpenedMonoforum(nullptr, anim::type::normal); + } else if (_childList && !_childList->openedForum()) { closeChildList(anim::type::normal); } }, lifetime()); @@ -795,7 +811,7 @@ void Widget::setupSwipeBack() { } }); } - if (controller()->shownForum().current()) { + if (controller()->shownForum().current()) { // #TODO monoforum if (!isRightToLeft) { return Ui::Controls::SwipeHandlerFinishData(); } @@ -924,6 +940,26 @@ void Widget::chosenRow(const ChosenRow &row) { } } return; + } else if (history + && history->isMonoforum() + && !row.message.fullId + && !controller()->adaptive().isOneColumn()) { + const auto monoforum = history->peer->monoforum(); + if (controller()->shownMonoforum().current() == monoforum) { + controller()->closeMonoforum(); + //} else if (row.newWindow) { // #TODO monoforum + // controller()->showInNewWindow( + // Window::SeparateId(Window::SeparateType::Forum, history)); + } else { + controller()->showMonoforum( + monoforum, + Window::SectionShow().withChildColumn()); + controller()->showThread( + history, + ShowAtUnreadMsgId, + Window::SectionShow::Way::ClearStack); + } + return; } else if (history) { const auto peer = history->peer; const auto showAtMsgId = controller()->uniqueChatsInSearchResults() @@ -958,6 +994,13 @@ void Widget::chosenRow(const ChosenRow &row) { } controller()->openFolder(folder); hideChildList(); + } else if (const auto sublist = row.key.sublist()) { + using namespace Window; + auto params = SectionShow(SectionShow::Way::Forward); + params.dropSameFromStack = true; + controller()->showSection( + std::make_shared(sublist), + params); } if (row.filteredRow && !session().supportMode()) { if (_subsectionTopBar) { @@ -1032,7 +1075,8 @@ void Widget::setupTopBarSuggestions(not_null dialogs) { ) | rpl::filter(_1 == nullptr) | rpl::map([=] { auto on = rpl::combine( controller()->activeChatsFilter(), - _openedFolderOrForumChanges.events_starting_with(false), + _openedFolderOrForumOrMonoforumChanges.events_starting_with( + false), widthValue() | rpl::map( _1 >= st::columnMinimalWidthLeft ) | rpl::distinct_until_changed(), @@ -1041,11 +1085,11 @@ void Widget::setupTopBarSuggestions(not_null dialogs) { _jumpToDate->toggledValue() ) | rpl::map([=]( FilterId id, - bool folderOrForum, + bool folderOrForumOrMonoforum, bool wide, bool search, bool searchInPeer) { - return !folderOrForum + return !folderOrForumOrMonoforum && wide && !search && !searchInPeer @@ -1102,7 +1146,8 @@ void Widget::updateFrozenAccountBar() { void Widget::updateTopBarSuggestions() { if (_topBarSuggestion) { - _openedFolderOrForumChanges.fire(_openedForum || _openedFolder); + _openedFolderOrForumOrMonoforumChanges.fire( + _openedFolder || _openedForum || _openedMonoforum); } } @@ -1540,7 +1585,7 @@ void Widget::updateControlsVisibility(bool fast) { if (_chatFilters) { _chatFilters->setVisible(!_openedForum); } - if (_openedFolder || _openedForum) { + if (_openedFolder || _openedForum || _openedMonoforum) { _subsectionTopBar->show(); if (_forumTopShadow) { _forumTopShadow->show(); @@ -1919,6 +1964,29 @@ void Widget::changeOpenedForum(Data::Forum *forum, anim::type animated) { }, (forum != nullptr), animated); } +void Widget::changeOpenedMonoforum( + Data::SavedMessages *monoforum, + anim::type animated) { + if (_openedMonoforum == monoforum) { + return; + } + changeOpenedSubsection([&] { + cancelSearch({ .forceFullCancel = true }); + closeChildList(anim::type::instant); + _openedMonoforum = monoforum; + _searchState.tab = monoforum + ? ChatSearchTab::ThisPeer + : ChatSearchTab::MyMessages; + _searchWithPostsPreview = computeSearchWithPostsPreview(); + _api.request(base::take(_topicSearchRequest)).cancel(); + _inner->changeOpenedMonoforum(monoforum); + storiesToggleExplicitExpand(false); + updateFrozenAccountBar(); + updateTopBarSuggestions(); + updateStoriesVisibility(); + }, (monoforum != nullptr), animated); +} + void Widget::hideChildList() { if (_childList) { controller()->closeForum(); @@ -1926,7 +1994,7 @@ void Widget::hideChildList() { } void Widget::refreshTopBars() { - if (_openedFolder || _openedForum) { + if (_openedFolder || _openedForum || _openedMonoforum) { if (!_subsectionTopBar) { _subsectionTopBar.create(this, controller()); if (_stories) { @@ -1956,10 +2024,12 @@ void Widget::refreshTopBars() { } const auto history = _openedForum ? _openedForum->history().get() + : _openedMonoforum + ? session().data().history(_openedMonoforum->parentChat()).get() : nullptr; _subsectionTopBar->setActiveChat( HistoryView::TopBarWidget::ActiveChat{ - .key = (_openedForum + .key = ((_openedForum || _openedMonoforum) ? Dialogs::Key(history) : Dialogs::Key(_openedFolder)), .section = Dialogs::EntryState::Section::ChatsList, @@ -2121,6 +2191,14 @@ bool Widget::searchHasFocus() const { return _searchHasFocus; } +Data::Forum *Widget::openedForum() const { + return _openedForum; +} + +Data::SavedMessages *Widget::openedMonoforum() const { + return _openedMonoforum; +} + void Widget::jumpToTop(bool belowPinned) { if (session().supportMode()) { return; @@ -3283,12 +3361,33 @@ void Widget::showForum( return; } cancelSearch({ .forceFullCancel = true }); - openChildList(forum, params); + openChildList(forum, nullptr, params); +} + +void Widget::showMonoforum( + not_null monoforum, + const Window::SectionShow ¶ms) { + if (_openedMonoforum == monoforum) { + return; + } + const auto nochat = !controller()->mainSectionShown(); + if (!params.childColumn + || (Core::App().settings().dialogsWidthRatio(nochat) == 0.) + || (_layout != Layout::Main) + || OptionForumHideChatsList.value()) { + changeOpenedMonoforum(monoforum, params.animated); + return; + } + cancelSearch({ .forceFullCancel = true }); + openChildList(nullptr, monoforum, params); } void Widget::openChildList( - not_null forum, + Data::Forum *forum, + Data::SavedMessages *monoforum, const Window::SectionShow ¶ms) { + Expects(forum || monoforum); + auto slide = Window::SectionSlideParams(); const auto animated = !_childList && (params.animated == anim::type::normal); @@ -3309,8 +3408,13 @@ void Widget::openChildList( this, controller(), Layout::Child); - _childList->showForum(forum, copy); - _childListPeerId = forum->channel()->id; + if (forum) { + _childList->showForum(forum, copy); + _childListPeerId = forum->channel()->id; + } else { + _childList->showMonoforum(monoforum, copy); + _childListPeerId = monoforum->parentChat()->id; + } } _childListShadow = std::make_unique(this); diff --git a/Telegram/SourceFiles/dialogs/dialogs_widget.h b/Telegram/SourceFiles/dialogs/dialogs_widget.h index a38ce878f8..b2584462f2 100644 --- a/Telegram/SourceFiles/dialogs/dialogs_widget.h +++ b/Telegram/SourceFiles/dialogs/dialogs_widget.h @@ -23,6 +23,7 @@ class Error; namespace Data { class Forum; +class SavedMessages; enum class StorySourcesList : uchar; struct ReactionId; } // namespace Data @@ -108,9 +109,15 @@ public: void showForum( not_null forum, const Window::SectionShow ¶ms); + void showMonoforum( + not_null monoforum, + const Window::SectionShow ¶ms); void setInnerFocus(bool unfocusSearch = false); [[nodiscard]] bool searchHasFocus() const; + [[nodiscard]] Data::Forum *openedForum() const; + [[nodiscard]] Data::SavedMessages *openedMonoforum() const; + void jumpToTop(bool belowPinned = false); void raiseWithTooltip(); @@ -247,6 +254,9 @@ private: anim::type animated); void changeOpenedFolder(Data::Folder *folder, anim::type animated); void changeOpenedForum(Data::Forum *forum, anim::type animated); + void changeOpenedMonoforum( + Data::SavedMessages *monoforum, + anim::type animated); void hideChildList(); void destroyChildListCanvas(); [[nodiscard]] QPixmap grabForFolderSlideAnimation(); @@ -256,7 +266,8 @@ private: Window::SlideDirection direction); void openChildList( - not_null forum, + Data::Forum *forum, + Data::SavedMessages *monoforum, const Window::SectionShow ¶ms); void closeChildList(anim::type animated); @@ -332,7 +343,7 @@ private: Ui::SlideWrap *_topBarSuggestion = nullptr; rpl::event_stream _topBarSuggestionHeightChanged; rpl::event_stream _searchStateForTopBarSuggestion; - rpl::event_stream _openedFolderOrForumChanges; + rpl::event_stream _openedFolderOrForumOrMonoforumChanges; object_ptr _scroll; QPointer _inner; @@ -358,6 +369,7 @@ private: Data::Folder *_openedFolder = nullptr; Data::Forum *_openedForum = nullptr; + Data::SavedMessages *_openedMonoforum = nullptr; SearchState _searchState; History *_searchInMigrated = nullptr; rpl::lifetime _searchTagsLifetime; diff --git a/Telegram/SourceFiles/history/view/history_view_top_bar_widget.cpp b/Telegram/SourceFiles/history/view/history_view_top_bar_widget.cpp index c4548ee4bf..c5c3a6187a 100644 --- a/Telegram/SourceFiles/history/view/history_view_top_bar_widget.cpp +++ b/Telegram/SourceFiles/history/view/history_view_top_bar_widget.cpp @@ -762,6 +762,10 @@ void TopBarWidget::backClicked() { && _activeChat.key.history() && _activeChat.key.history()->isForum()) { _controller->closeForum(); + } else if (_activeChat.section == Section::ChatsList + && _activeChat.key.history() + && _activeChat.key.history()->isMonoforum()) { + _controller->closeMonoforum(); } else { _controller->showBackFromStack(); } diff --git a/Telegram/SourceFiles/info/profile/info_profile_actions.cpp b/Telegram/SourceFiles/info/profile/info_profile_actions.cpp index e38d772d83..bc7de9ef5c 100644 --- a/Telegram/SourceFiles/info/profile/info_profile_actions.cpp +++ b/Telegram/SourceFiles/info/profile/info_profile_actions.cpp @@ -2183,6 +2183,23 @@ Ui::MultiSlideTracker DetailsFiller::fillChannelButtons( std::move(viewChannel), tracker); + auto viewDirectVisible = channel->flagsValue() | rpl::map([=] { + return channel->monoforumLink() != nullptr; + }) | rpl::distinct_until_changed(); + auto viewDirect = [=] { + if (const auto linked = channel->monoforumLink()) { + if (const auto monoforum = linked->monoforum()) { + window->showMonoforum(monoforum); + } + } + }; + AddMainButton( // #TODO monoforum + _wrap, + rpl::single(u"View Direct Messages"_q), + std::move(viewDirectVisible), + std::move(viewDirect), + tracker); + return tracker; } diff --git a/Telegram/SourceFiles/mainwidget.cpp b/Telegram/SourceFiles/mainwidget.cpp index 2a458c24e9..d3cbed09a0 100644 --- a/Telegram/SourceFiles/mainwidget.cpp +++ b/Telegram/SourceFiles/mainwidget.cpp @@ -1565,6 +1565,18 @@ void MainWidget::showForum( } } +void MainWidget::showMonoforum( + not_null monoforum, + const SectionShow ¶ms) { + Expects(_dialogs != nullptr); + + _dialogs->showMonoforum(monoforum, params); + + if (params.activation != anim::activation::background) { + _controller->window().hideSettingsAndLayer(); + } +} + PeerData *MainWidget::peer() const { return _history->peer(); } diff --git a/Telegram/SourceFiles/mainwidget.h b/Telegram/SourceFiles/mainwidget.h index 48ec64735b..54bb67513c 100644 --- a/Telegram/SourceFiles/mainwidget.h +++ b/Telegram/SourceFiles/mainwidget.h @@ -32,6 +32,7 @@ class Thread; class WallPaper; struct ForwardDraft; class Forum; +class SavedMessages; struct ReportInput; } // namespace Data @@ -198,6 +199,9 @@ public: not_null item, const SectionShow ¶ms); void showForum(not_null forum, const SectionShow ¶ms); + void showMonoforum( + not_null monoforum, + const SectionShow ¶ms); bool notify_switchInlineBotButtonReceived(const QString &query, UserData *samePeerBot, MsgId samePeerReplyTo); diff --git a/Telegram/SourceFiles/window/window_session_controller.cpp b/Telegram/SourceFiles/window/window_session_controller.cpp index 6edfaf3da0..2d9af18ff0 100644 --- a/Telegram/SourceFiles/window/window_session_controller.cpp +++ b/Telegram/SourceFiles/window/window_session_controller.cpp @@ -603,10 +603,15 @@ void SessionNavigation::showPeerByLinkResolved( showPeerInfo(peer, params); } else if (resolveType == ResolveType::HashtagSearch) { searchMessages(info.text, peer->owner().history(peer)); - } else if (peer->isForum() && resolveType != ResolveType::Boost) { + } else if ((peer->isForum() || peer->isMonoforum()) + && resolveType != ResolveType::Boost) { const auto itemId = info.messageId; if (!itemId) { - parentController()->showForum(peer->forum(), params); + if (peer->isForum()) { + parentController()->showForum(peer->forum(), params); + } else { + parentController()->showMonoforum(peer->monoforum(), params); + } } else if (const auto item = peer->owner().message(peer, itemId)) { showMessageByLinkResolved(item, info); } else { @@ -1924,6 +1929,56 @@ const rpl::variable &SessionController::shownForum() const { return _shownForum; } +void SessionController::showMonoforum( + not_null monoforum, + const SectionShow ¶ms) { + // if (showForumInDifferentWindow(forum, params)) { + // return; + // } + _shownMonoforumLifetime.destroy(); + if (_shownMonoforum.current() != monoforum) { + resetFakeUnreadWhileOpened(); + } + if (monoforum + && _activeChatEntry.current().key.peer() + && adaptive().isOneColumn()) { + clearSectionStack(params); + } + _shownMonoforum = monoforum.get(); + if (_shownMonoforum.current() != monoforum) { + return; + } + monoforum->destroyed( + ) | rpl::start_with_next([=] { + closeMonoforum(); + }, _shownMonoforumLifetime); + content()->showMonoforum(monoforum, params); +} + +void SessionController::closeMonoforum() { + if (const auto monoforum = _shownMonoforum.current()) { + const auto id = windowId(); + if (id.type == SeparateType::SavedSublist) { + const auto initial = id.parentChat; + if (!initial + || !initial->monoforum() + || initial == monoforum->parentChat()) { + Core::App().closeWindow(_window); + } else { + showMonoforum(initial->monoforum()); + } + return; + } + } + _shownMonoforumLifetime.destroy(); + _shownMonoforum = nullptr; +} + +auto SessionController::shownMonoforum() const +-> const rpl::variable & { + return _shownMonoforum; +} + void SessionController::setActiveChatEntry(Dialogs::RowDescriptor row) { if (windowId().type == SeparateType::SharedMedia) { return; diff --git a/Telegram/SourceFiles/window/window_session_controller.h b/Telegram/SourceFiles/window/window_session_controller.h index 040739589d..7eea85827a 100644 --- a/Telegram/SourceFiles/window/window_session_controller.h +++ b/Telegram/SourceFiles/window/window_session_controller.h @@ -26,6 +26,7 @@ enum class WindowLayout; namespace Data { struct StoriesContext; +class SavedMessages; enum class StorySourcesList : uchar; } // namespace Data @@ -405,6 +406,12 @@ public: void closeForum(); const rpl::variable &shownForum() const; + void showMonoforum( + not_null monoforum, + const SectionShow ¶ms = SectionShow::Way::ClearStack); + void closeMonoforum(); + const rpl::variable &shownMonoforum() const; + void setActiveChatEntry(Dialogs::RowDescriptor row); void setActiveChatEntry(Dialogs::Key key); Dialogs::RowDescriptor activeChatEntryCurrent() const; @@ -746,6 +753,8 @@ private: rpl::variable _openedFolder; rpl::variable _shownForum; rpl::lifetime _shownForumLifetime; + rpl::variable _shownMonoforum; + rpl::lifetime _shownMonoforumLifetime; rpl::event_stream<> _filtersMenuChanged;