diff --git a/Telegram/SourceFiles/core/application.cpp b/Telegram/SourceFiles/core/application.cpp index a8852f037..22c863aff 100644 --- a/Telegram/SourceFiles/core/application.cpp +++ b/Telegram/SourceFiles/core/application.cpp @@ -1032,11 +1032,15 @@ void Application::preventOrInvoke(Fn &&callback) { } void Application::lockByPasscode() { + enumerateWindows([&](not_null w) { + _passcodeLock = true; + w->setupPasscodeLock(); + }); +} + +void Application::maybeLockByPasscode() { preventOrInvoke([=] { - enumerateWindows([&](not_null w) { - _passcodeLock = true; - w->setupPasscodeLock(); - }); + lockByPasscode(); }); } @@ -1427,7 +1431,7 @@ void Application::startShortcuts() { }); request->check(Command::Lock) && request->handle([=] { if (!passcodeLocked() && _domain->local().hasLocalPasscode()) { - lockByPasscode(); + maybeLockByPasscode(); return true; } return false; diff --git a/Telegram/SourceFiles/core/application.h b/Telegram/SourceFiles/core/application.h index 6958cf222..d05906372 100644 --- a/Telegram/SourceFiles/core/application.h +++ b/Telegram/SourceFiles/core/application.h @@ -263,6 +263,7 @@ public: [[nodiscard]] bool downloadPreventsQuit(); void checkLocalTime(); void lockByPasscode(); + void maybeLockByPasscode(); void unlockPasscode(); [[nodiscard]] bool passcodeLocked() const; rpl::producer passcodeLockChanges() const; diff --git a/Telegram/SourceFiles/data/data_forum.cpp b/Telegram/SourceFiles/data/data_forum.cpp index 7e184988f..ab39ca9b2 100644 --- a/Telegram/SourceFiles/data/data_forum.cpp +++ b/Telegram/SourceFiles/data/data_forum.cpp @@ -67,6 +67,18 @@ not_null Forum::topicsList() { return &_topicsList; } +rpl::producer<> Forum::destroyed() const { + return channel()->flagsValue( + ) | rpl::filter([=](const ChannelData::Flags::Change &update) { + using Flag = ChannelData::Flag; + return (update.diff & Flag::Forum) && !(update.value & Flag::Forum); + }) | rpl::take(1) | rpl::to_empty; +} + +rpl::producer> Forum::topicDestroyed() const { + return _topicDestroyed.events(); +} + void Forum::requestTopics() { if (_allLoaded || _requestId) { return; diff --git a/Telegram/SourceFiles/data/data_forum.h b/Telegram/SourceFiles/data/data_forum.h index 354f15e6b..117ad8b4a 100644 --- a/Telegram/SourceFiles/data/data_forum.h +++ b/Telegram/SourceFiles/data/data_forum.h @@ -34,6 +34,9 @@ public: [[nodiscard]] not_null history() const; [[nodiscard]] not_null channel() const; [[nodiscard]] not_null topicsList(); + [[nodiscard]] rpl::producer<> destroyed() const; + [[nodiscard]] auto topicDestroyed() const + -> rpl::producer>; void requestTopics(); [[nodiscard]] rpl::producer<> chatsListChanges() const; @@ -75,6 +78,7 @@ private: const not_null _history; base::flat_map> _topics; + rpl::event_stream> _topicDestroyed; Dialogs::MainList _topicsList; base::flat_map _topicRequests; diff --git a/Telegram/SourceFiles/data/data_forum_topic.cpp b/Telegram/SourceFiles/data/data_forum_topic.cpp index 3a40af836..069505c48 100644 --- a/Telegram/SourceFiles/data/data_forum_topic.cpp +++ b/Telegram/SourceFiles/data/data_forum_topic.cpp @@ -138,8 +138,8 @@ QImage ForumTopicIconFrame( ForumTopic::ForumTopic(not_null history, MsgId rootId) : Entry(&history->owner(), Type::ForumTopic) -, _history(history) -, _list(forum()->topicsList()) +, _forum(history->peer->forum()) +, _list(_forum->topicsList()) , _replies(std::make_shared(history, rootId)) , _rootId(rootId) { _replies->unreadCountValue( @@ -165,15 +165,22 @@ std::shared_ptr ForumTopic::replies() const { } not_null ForumTopic::channel() const { - return _history->peer->asChannel(); + return _forum->channel(); } not_null ForumTopic::history() const { - return _history; + return _forum->history(); } not_null ForumTopic::forum() const { - return channel()->forum(); + return _forum; +} + +rpl::producer<> ForumTopic::destroyed() const { + using namespace rpl::mappers; + return rpl::merge( + _forum->destroyed(), + _forum->topicDestroyed() | rpl::filter(_1 == this) | rpl::to_empty); } MsgId ForumTopic::rootId() const { @@ -183,7 +190,7 @@ MsgId ForumTopic::rootId() const { void ForumTopic::setRealRootId(MsgId realId) { if (_rootId != realId) { _rootId = realId; - _replies = std::make_shared(_history, _rootId); + _replies = std::make_shared(history(), _rootId); } } @@ -252,7 +259,7 @@ int ForumTopic::chatListNameVersion() const { void ForumTopic::applyTopicTopMessage(MsgId topMessageId) { if (topMessageId) { - const auto itemId = FullMsgId(_history->peer->id, topMessageId); + const auto itemId = FullMsgId(channel()->id, topMessageId); if (const auto item = owner().message(itemId)) { setLastServerMessage(item); @@ -428,7 +435,7 @@ void ForumTopic::applyIconId(DocumentId iconId) { if (_iconId != iconId) { _iconId = iconId; _icon = iconId - ? _history->owner().customEmojiManager().create( + ? owner().customEmojiManager().create( _iconId, [=] { updateChatListEntry(); }, Data::CustomEmojiManager::SizeTag::Normal) @@ -524,7 +531,7 @@ Dialogs::UnreadState ForumTopic::unreadStateFor( bool known) const { auto result = Dialogs::UnreadState(); const auto mark = !count && unreadMark(); - const auto muted = _history->mute(); + const auto muted = history()->mute(); result.messages = count; result.messagesMuted = muted ? count : 0; result.chats = count ? 1 : 0; diff --git a/Telegram/SourceFiles/data/data_forum_topic.h b/Telegram/SourceFiles/data/data_forum_topic.h index deeef3fec..61c0bdc16 100644 --- a/Telegram/SourceFiles/data/data_forum_topic.h +++ b/Telegram/SourceFiles/data/data_forum_topic.h @@ -55,6 +55,7 @@ public: [[nodiscard]] not_null channel() const; [[nodiscard]] not_null history() const; [[nodiscard]] not_null forum() const; + [[nodiscard]] rpl::producer<> destroyed() const; [[nodiscard]] MsgId rootId() const; [[nodiscard]] bool isGeneral() const { return (_rootId == kGeneralId); @@ -131,7 +132,7 @@ private: int count, bool known) const; - const not_null _history; + const not_null _forum; const not_null _list; std::shared_ptr _replies; MsgId _rootId = 0; diff --git a/Telegram/SourceFiles/data/data_peer.cpp b/Telegram/SourceFiles/data/data_peer.cpp index b1674700b..03292e0b5 100644 --- a/Telegram/SourceFiles/data/data_peer.cpp +++ b/Telegram/SourceFiles/data/data_peer.cpp @@ -13,6 +13,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "data/data_changes.h" #include "data/data_photo.h" #include "data/data_folder.h" +#include "data/data_forum.h" #include "data/data_session.h" #include "data/data_file_origin.h" #include "data/data_histories.h" @@ -889,6 +890,22 @@ Data::Forum *PeerData::forum() const { return nullptr; } +Data::ForumTopic *PeerData::forumTopicFor( + not_null item) const { + if (const auto forum = this->forum()) { + return forum->topicFor(item); + } + return nullptr; +} + +Data::ForumTopic *PeerData::forumTopicFor(MsgId rootId) const { + if (const auto forum = this->forum()) { + return forum->topicFor(rootId); + } + return nullptr; +} + + bool PeerData::canWrite() const { if (const auto user = asUser()) { return user->canWrite(); diff --git a/Telegram/SourceFiles/data/data_peer.h b/Telegram/SourceFiles/data/data_peer.h index f480095fe..f6af6bfc2 100644 --- a/Telegram/SourceFiles/data/data_peer.h +++ b/Telegram/SourceFiles/data/data_peer.h @@ -33,6 +33,7 @@ class Session; namespace Data { class Forum; +class ForumTopic; class Session; class GroupCall; class CloudImageView; @@ -197,6 +198,9 @@ public: } [[nodiscard]] Data::Forum *forum() const; + [[nodiscard]] Data::ForumTopic *forumTopicFor( + not_null item) const; + [[nodiscard]] Data::ForumTopic *forumTopicFor(MsgId rootId) const; [[nodiscard]] std::optional notifyMuteUntil() const { return _notify.muteUntil(); diff --git a/Telegram/SourceFiles/dialogs/dialogs_widget.cpp b/Telegram/SourceFiles/dialogs/dialogs_widget.cpp index f4b2d6972..56549bc3a 100644 --- a/Telegram/SourceFiles/dialogs/dialogs_widget.cpp +++ b/Telegram/SourceFiles/dialogs/dialogs_widget.cpp @@ -328,7 +328,7 @@ Widget::Widget( }, lifetime()); _lockUnlock->setClickedCallback([this] { _lockUnlock->setIconOverride(&st::dialogsUnlockIcon, &st::dialogsUnlockIconOver); - Core::App().lockByPasscode(); + Core::App().maybeLockByPasscode(); _lockUnlock->setIconOverride(nullptr); }); diff --git a/Telegram/SourceFiles/history/view/history_view_replies_section.cpp b/Telegram/SourceFiles/history/view/history_view_replies_section.cpp index 33ca0eb3e..865381415 100644 --- a/Telegram/SourceFiles/history/view/history_view_replies_section.cpp +++ b/Telegram/SourceFiles/history/view/history_view_replies_section.cpp @@ -487,6 +487,13 @@ void RepliesWidget::subscribeToTopic() { _cornerButtons.updateUnreadThingsVisibility(); }, _topicLifetime); + _topic->destroyed( + ) | rpl::start_with_next([=] { + controller()->showBackFromStack(Window::SectionShow( + anim::type::normal, + anim::activation::background)); + }, _topicLifetime); + _cornerButtons.updateUnreadThingsVisibility(); } diff --git a/Telegram/SourceFiles/info/common_groups/info_common_groups_widget.cpp b/Telegram/SourceFiles/info/common_groups/info_common_groups_widget.cpp index 134e89f28..392bee43c 100644 --- a/Telegram/SourceFiles/info/common_groups/info_common_groups_widget.cpp +++ b/Telegram/SourceFiles/info/common_groups/info_common_groups_widget.cpp @@ -22,7 +22,7 @@ namespace Info { namespace CommonGroups { Memento::Memento(not_null user) -: ContentMemento(user, 0) { +: ContentMemento(user, nullptr, PeerId()) { } Section Memento::section() const { diff --git a/Telegram/SourceFiles/info/info_content_widget.cpp b/Telegram/SourceFiles/info/info_content_widget.cpp index 46a66f31a..fcd405a5e 100644 --- a/Telegram/SourceFiles/info/info_content_widget.cpp +++ b/Telegram/SourceFiles/info/info_content_widget.cpp @@ -337,16 +337,23 @@ Key ContentMemento::key() const { } } -ContentMemento::ContentMemento(not_null topic) -: _peer(topic->channel()) -, _migratedPeerId(_peer->migrateFrom() ? _peer->migrateFrom()->id : 0) +ContentMemento::ContentMemento( + not_null peer, + Data::ForumTopic *topic, + PeerId migratedPeerId) +: _peer(peer) +, _migratedPeerId((!topic && peer->migrateFrom()) + ? peer->migrateFrom()->id + : 0) , _topic(topic) { - _peer->owner().itemIdChanged( - ) | rpl::start_with_next([=](const Data::Session::IdChange &change) { - if (_topic->rootId() == change.oldId) { - _topic = _topic->forum()->topicFor(change.newId.msg); - } - }, _lifetime); + if (_topic) { + _peer->owner().itemIdChanged( + ) | rpl::start_with_next([=](const Data::Session::IdChange &change) { + if (_topic->rootId() == change.oldId) { + _topic = _topic->forum()->topicFor(change.newId.msg); + } + }, _lifetime); + } } ContentMemento::ContentMemento(Settings::Tag settings) diff --git a/Telegram/SourceFiles/info/info_content_widget.h b/Telegram/SourceFiles/info/info_content_widget.h index b1f9d636a..44f4e2d8c 100644 --- a/Telegram/SourceFiles/info/info_content_widget.h +++ b/Telegram/SourceFiles/info/info_content_widget.h @@ -144,11 +144,10 @@ private: class ContentMemento { public: - ContentMemento(not_null peer, PeerId migratedPeerId) - : _peer(peer) - , _migratedPeerId(migratedPeerId) { - } - explicit ContentMemento(not_null topic); + ContentMemento( + not_null peer, + Data::ForumTopic *topic, + PeerId migratedPeerId); explicit ContentMemento(Settings::Tag settings); explicit ContentMemento(Downloads::Tag downloads); ContentMemento(not_null poll, FullMsgId contextId) diff --git a/Telegram/SourceFiles/info/info_controller.cpp b/Telegram/SourceFiles/info/info_controller.cpp index 33212df25..d33098b7d 100644 --- a/Telegram/SourceFiles/info/info_controller.cpp +++ b/Telegram/SourceFiles/info/info_controller.cpp @@ -192,7 +192,10 @@ Controller::Controller( void Controller::setupMigrationViewer() { const auto peer = _key.peer(); - if (!peer || (!peer->isChat() && !peer->isChannel()) || _migrated) { + if (_key.topic() + || !peer + || (!peer->isChat() && !peer->isChannel()) + || _migrated) { return; } peer->session().changes().peerFlagsValue( @@ -335,6 +338,7 @@ auto Controller::produceSearchQuery( auto result = SearchQuery(); result.type = _section.mediaType(); result.peerId = _key.peer()->id; + result.topicRootId = _key.topic() ? _key.topic()->rootId() : 0; result.query = query; result.migratedPeerId = _migrated ? _migrated->id : PeerId(0); return result; diff --git a/Telegram/SourceFiles/info/info_memento.cpp b/Telegram/SourceFiles/info/info_memento.cpp index 07c77c474..2dba25b5d 100644 --- a/Telegram/SourceFiles/info/info_memento.cpp +++ b/Telegram/SourceFiles/info/info_memento.cpp @@ -20,6 +20,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "boxes/peer_list_box.h" #include "data/data_channel.h" #include "data/data_chat.h" +#include "data/data_forum_topic.h" #include "data/data_session.h" #include "main/main_session.h" @@ -51,6 +52,27 @@ Memento::Memento(not_null poll, FullMsgId contextId) Memento::Memento(std::vector> stack) : _stack(std::move(stack)) { + auto topics = base::flat_set>(); + for (auto &entry : _stack) { + if (const auto topic = entry->topic()) { + topics.emplace(topic); + } + } + for (const auto &topic : topics) { + topic->destroyed( + ) | rpl::start_with_next([=] { + for (auto i = begin(_stack); i != end(_stack);) { + if (i->get()->topic() == topic) { + i = _stack.erase(i); + } else { + ++i; + } + } + if (_stack.empty()) { + _removeRequests.fire({}); + } + }, _lifetime); + } } std::vector> Memento::DefaultStack( diff --git a/Telegram/SourceFiles/info/info_memento.h b/Telegram/SourceFiles/info/info_memento.h index 8c3ca2148..3d18296cb 100644 --- a/Telegram/SourceFiles/info/info_memento.h +++ b/Telegram/SourceFiles/info/info_memento.h @@ -58,6 +58,10 @@ public: not_null controller, const QRect &geometry) override; + rpl::producer<> removeRequests() const override { + return _removeRequests.events(); + } + int stackSize() const { return int(_stack.size()); } @@ -96,6 +100,8 @@ private: Section section); std::vector> _stack; + rpl::event_stream<> _removeRequests; + rpl::lifetime _lifetime; }; diff --git a/Telegram/SourceFiles/info/info_section_widget.cpp b/Telegram/SourceFiles/info/info_section_widget.cpp index c8d6fd3fd..084b2f223 100644 --- a/Telegram/SourceFiles/info/info_section_widget.cpp +++ b/Telegram/SourceFiles/info/info_section_widget.cpp @@ -124,6 +124,10 @@ object_ptr SectionWidget::moveContentToLayer( bodyGeometry); } +rpl::producer<> SectionWidget::removeRequests() const { + return _content->removeRequests(); +} + bool SectionWidget::floatPlayerHandleWheelEvent(QEvent *e) { return _content->floatPlayerHandleWheelEvent(e); } diff --git a/Telegram/SourceFiles/info/info_section_widget.h b/Telegram/SourceFiles/info/info_section_widget.h index f93281e3e..8ff1dbcfa 100644 --- a/Telegram/SourceFiles/info/info_section_widget.h +++ b/Telegram/SourceFiles/info/info_section_widget.h @@ -53,6 +53,8 @@ public: object_ptr moveContentToLayer( QRect bodyGeometry) override; + rpl::producer<> removeRequests() const override; + // Float player interface. bool floatPlayerHandleWheelEvent(QEvent *e) override; QRect floatPlayerAvailableRect() override; diff --git a/Telegram/SourceFiles/info/info_wrap_widget.cpp b/Telegram/SourceFiles/info/info_wrap_widget.cpp index 5e9414c68..42cd1066c 100644 --- a/Telegram/SourceFiles/info/info_wrap_widget.cpp +++ b/Telegram/SourceFiles/info/info_wrap_widget.cpp @@ -40,6 +40,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "data/data_session.h" #include "data/data_changes.h" #include "data/data_user.h" +#include "data/data_forum_topic.h" #include "mainwidget.h" #include "lang/lang_keys.h" #include "styles/style_chat.h" // popupMenuExpandedSeparator @@ -104,6 +105,22 @@ WrapWidget::WrapWidget( }); }, lifetime()); restoreHistoryStack(memento->takeStack()); + + if (const auto topic = _controller->topic()) { + topic->destroyed( + ) | rpl::start_with_next([=] { + if (_wrap.current() == Wrap::Layer) { + _controller->parentController()->hideSpecialLayer(); + } else if (_wrap.current() == Wrap::Narrow) { + _controller->parentController()->showBackFromStack( + Window::SectionShow( + anim::type::normal, + anim::activation::background)); + } else { + _removeRequests.fire({}); + } + }, lifetime()); + } } void WrapWidget::setupShortcuts() { @@ -233,129 +250,16 @@ Dialogs::RowDescriptor WrapWidget::activeChat() const { Unexpected("Owner in WrapWidget::activeChat()."); } -// This was done for tabs support. -// -//void WrapWidget::createTabs() { -// _topTabs.create(this, st::infoTabs); -// auto sections = QStringList(); -// sections.push_back(tr::lng_profile_info_section(tr::now).toUpper()); -// sections.push_back(tr::lng_info_tab_media(tr::now).toUpper()); -// _topTabs->setSections(sections); -// _topTabs->setActiveSection(static_cast(_tab)); -// _topTabs->finishAnimating(); -// -// _topTabs->sectionActivated( -// ) | rpl::map([](int index) { -// return static_cast(index); -// }) | rpl::start_with_next( -// [this](Tab tab) { showTab(tab); }, -// lifetime()); -// -// _topTabs->move(0, 0); -// _topTabs->resizeToWidth(width()); -// _topTabs->show(); -// -// _topTabsBackground.create(this, st::profileBg); -// _topTabsBackground->setAttribute(Qt::WA_OpaquePaintEvent); -// -// _topTabsBackground->move(0, 0); -// _topTabsBackground->resize( -// width(), -// _topTabs->height() - st::lineWidth); -// _topTabsBackground->show(); -//} - void WrapWidget::forceContentRepaint() { // WA_OpaquePaintEvent on TopBar creates render glitches when // animating the LayerWidget's height :( Fixing by repainting. - - // This was done for tabs support. - // - //if (_topTabs) { - // _topTabsBackground->update(); - //} - if (_topBar) { _topBar->update(); } _content->update(); } -// This was done for tabs support. -// -//void WrapWidget::showTab(Tab tab) { -// if (_tab == tab) { -// return; -// } -// Expects(_content != nullptr); -// auto direction = (tab > _tab) -// ? SlideDirection::FromRight -// : SlideDirection::FromLeft; -// auto newAnotherMemento = _content->createMemento(); -// if (!_anotherTabMemento) { -// _anotherTabMemento = createTabMemento(tab); -// } -// auto newController = createController( -// _controller->parentController(), -// _anotherTabMemento.get()); -// auto newContent = createContent( -// _anotherTabMemento.get(), -// newController.get()); -// auto animationParams = SectionSlideParams(); -//// animationParams.withFade = (wrap() == Wrap::Layer); -// animationParams.withTabs = true; -// animationParams.withTopBarShadow = hasTopBarShadow() -// && newContent->hasTopBarShadow(); -// animationParams.oldContentCache = grabForShowAnimation( -// animationParams); -// -// _controller = std::move(newController); -// showContent(std::move(newContent)); -// -// showAnimated(direction, animationParams); -// -// _anotherTabMemento = std::move(newAnotherMemento); -// _tab = tab; -//} -// -//void WrapWidget::setupTabbedTop() { -// auto section = _controller->section(); -// switch (section.type()) { -// case Section::Type::Profile: -// setupTabs(Tab::Profile); -// break; -// case Section::Type::Media: -// switch (section.mediaType()) { -// case Section::MediaType::Photo: -// case Section::MediaType::Video: -// case Section::MediaType::File: -// setupTabs(Tab::Media); -// break; -// default: -// setupTabs(Tab::None); -// break; -// } -// break; -// case Section::Type::CommonGroups: -// case Section::Type::Members: -// setupTabs(Tab::None); -// break; -// } -//} - void WrapWidget::setupTop() { - // This was done for tabs support. - // - //if (wrap() == Wrap::Side && !hasStackHistory()) { - // setupTabbedTop(); - //} else { - // setupTabs(Tab::None); - //} - //if (_topTabs) { - // _topBar.destroy(); - //} else { - // createTopBar(); - //} if (HasCustomTopBar(_controller.get())) { _topBar.destroy(); return; @@ -602,11 +506,6 @@ bool WrapWidget::requireTopBarSearch() const { } else if (hasStackHistory()) { return true; } - // This was for top-level tabs support. - // - //auto section = _controller->section(); - //return (section.type() != Section::Type::Media) - // || !Media::TypeToTabIndex(section.mediaType()).has_value(); return false; } @@ -618,7 +517,6 @@ bool WrapWidget::showBackFromStackInternal( showNewContent( last.section.get(), params.withWay(Window::SectionShow::Way::Backward)); - //_anotherTabMemento = std::move(last.anotherTab); return true; } return (wrap() == Wrap::Layer); @@ -645,11 +543,6 @@ void WrapWidget::removeFromStack(const std::vector
§ions) { } not_null WrapWidget::topWidget() const { - // This was done for tabs support. - // - //if (_topTabs) { - // return _topTabsBackground; - //} return _topBar; } @@ -670,7 +563,6 @@ void WrapWidget::showContent(object_ptr content) { } _additionalScroll = 0; _content->show(); - //_anotherTabMemento = nullptr; finishShowContent(); } @@ -696,23 +588,9 @@ void WrapWidget::finishShowContent() { ) | rpl::start_with_next([=] { updateContentGeometry(); }, _content->lifetime()); - - // This was done for tabs support. - // - //if (_topTabs) { - // _topTabs->raise(); - //} } rpl::producer WrapWidget::topShadowToggledValue() const { - // Allows always showing shadow for specific wrap value. - // Was done for top level tabs support. - // - //using namespace rpl::mappers; - //return rpl::combine( - // _controller->wrapValue(), - // _desiredShadowVisibilities.events() | rpl::flatten_latest(), - // (_1 == Wrap::Side) || _2); return _desiredShadowVisibilities.events() | rpl::flatten_latest( ) | rpl::map([=](bool v) { return v && (_topBar != nullptr); }); @@ -730,22 +608,6 @@ rpl::producer WrapWidget::selectedListValue() const { return _selectedLists.events() | rpl::flatten_latest(); } -// Was done for top level tabs support. -// -//std::shared_ptr WrapWidget::createTabMemento( -// Tab tab) { -// switch (tab) { -// case Tab::Profile: return std::make_shared( -// _controller->peerId(), -// _controller->migratedPeerId()); -// case Tab::Media: return std::make_shared( -// _controller->peerId(), -// _controller->migratedPeerId(), -// Media::Type::Photo); -// } -// Unexpected("Tab value in Info::WrapWidget::createInner()"); -//} - object_ptr WrapWidget::createContent( not_null memento, not_null controller) { @@ -755,43 +617,11 @@ object_ptr WrapWidget::createContent( contentGeometry()); } -// Was done for top level tabs support. -// -//void WrapWidget::convertProfileFromStackToTab() { -// if (!hasStackHistory()) { -// return; -// } -// auto &entry = _historyStack[0]; -// if (entry.section->section().type() != Section::Type::Profile) { -// return; -// } -// auto convertInsideStack = (_historyStack.size() > 1); -// auto checkSection = convertInsideStack -// ? _historyStack[1].section->section() -// : _controller->section(); -// auto &anotherMemento = convertInsideStack -// ? _historyStack[1].anotherTab -// : _anotherTabMemento; -// if (checkSection.type() != Section::Type::Media) { -// return; -// } -// if (!Info::Media::TypeToTabIndex(checkSection.mediaType())) { -// return; -// } -// anotherMemento = std::move(entry.section); -// _historyStack.erase(_historyStack.begin()); -//} - rpl::producer WrapWidget::wrapValue() const { return _wrap.value(); } void WrapWidget::setWrap(Wrap wrap) { - // Was done for top level tabs support. - // - //if (_wrap.current() != Wrap::Side && wrap == Wrap::Side) { - // convertProfileFromStackToTab(); - //} _wrap = wrap; } @@ -810,9 +640,6 @@ QPixmap WrapWidget::grabForShowAnimation( } else { _topShadow->setVisible(_topShadow->toggled()); } - //if (params.withTabs && _topTabs) { - // _topTabs->hide(); - //} const auto expanding = _expanding; if (expanding) { _grabbingForExpanding = true; @@ -824,18 +651,11 @@ QPixmap WrapWidget::grabForShowAnimation( if (params.withTopBarShadow) { _topShadow->setVisible(true); } - //if (params.withTabs && _topTabs) { - // _topTabs->show(); - //} return result; } void WrapWidget::showAnimatedHook( const Window::SectionSlideParams ¶ms) { - //if (params.withTabs && _topTabs) { - // _topTabs->show(); - // _topTabsBackground->show(); - //} if (params.withTopBarShadow) { _topShadow->setVisible(true); } @@ -870,25 +690,6 @@ bool WrapWidget::showInternal( if (!skipInternal && _content->showInternal(content)) { highlightTopBar(); return true; - - // This was done for tabs support. - // - //} else if (_topTabs) { - // // If we open the profile being in the media tab. - // // Just switch back to the profile tab. - // auto type = content->section().type(); - // if (type == Section::Type::Profile - // && _tab != Tab::Profile) { - // _anotherTabMemento = std::move(infoMemento->takeStack().back()); - // _topTabs->setActiveSection(static_cast(Tab::Profile)); - // return true; - // } else if (type == Section::Type::Media - // && _tab != Tab::Media - // && Media::TypeToTabIndex(content->section().mediaType()).has_value()) { - // _anotherTabMemento = std::move(infoMemento->takeStack().back()); - // _topTabs->setActiveSection(static_cast(Tab::Media)); - // return true; - // } } } @@ -899,9 +700,7 @@ bool WrapWidget::showInternal( return true; } - showNewContent( - content, - params); + showNewContent(content, params); return true; } return false; @@ -997,9 +796,6 @@ void WrapWidget::showNewContent( if (saveToStack) { auto item = StackItem(); item.section = _content->createMemento(); - //if (_anotherTabMemento) { - // item.anotherTab = std::move(_anotherTabMemento); - //} _historyStack.push_back(std::move(item)); } else if (params.way == Window::SectionShow::Way::ClearStack) { _historyStack.clear(); @@ -1041,29 +837,7 @@ void WrapWidget::showNewContent(not_null memento) { showContent(createContent(memento, _controller.get())); } -// This was done for tabs support. -// -//void WrapWidget::setupTabs(Tab tab) { -// _tab = tab; -// if (_tab == Tab::None) { -// _topTabs.destroy(); -// _topTabsBackground.destroy(); -// } else if (!_topTabs) { -// createTabs(); -// } else { -// _topTabs->setActiveSection(static_cast(tab)); -// } -//} - void WrapWidget::resizeEvent(QResizeEvent *e) { - // This was done for tabs support. - // - //if (_topTabs) { - // _topTabs->resizeToWidth(width()); - // _topTabsBackground->resize( - // width(), - // _topTabs->height() - st::lineWidth); - //} if (_topBar) { _topBar->resizeToWidth(width()); } diff --git a/Telegram/SourceFiles/info/info_wrap_widget.h b/Telegram/SourceFiles/info/info_wrap_widget.h index b3d22e5e0..edf303b1b 100644 --- a/Telegram/SourceFiles/info/info_wrap_widget.h +++ b/Telegram/SourceFiles/info/info_wrap_widget.h @@ -132,6 +132,10 @@ public: [[nodiscard]] rpl::producer grabbingForExpanding() const; [[nodiscard]] const Ui::RoundRect *bottomSkipRounding() const; + [[nodiscard]] rpl::producer<> removeRequests() const { + return _removeRequests.events(); + } + ~WrapWidget(); protected: @@ -147,11 +151,6 @@ protected: private: using SlideDirection = Window::SlideDirection; using SectionSlideParams = Window::SectionSlideParams; - //enum class Tab { - // Profile, - // Media, - // None, - //}; struct StackItem; void startInjectingActivePeerProfiles(); @@ -173,9 +172,6 @@ private: not_null memento, const Window::SectionShow ¶ms); void setupTop(); - //void setupTabbedTop(); - //void setupTabs(Tab tab); - //void createTabs(); void createTopBar(); void highlightTopBar(); void setupShortcuts(); @@ -190,16 +186,13 @@ private: rpl::producer topShadowToggledValue() const; void updateContentGeometry(); - //void showTab(Tab tab); void showContent(object_ptr content); - //std::shared_ptr createTabMemento(Tab tab); object_ptr createContent( not_null memento, not_null controller); std::unique_ptr createController( not_null window, not_null memento); - //void convertProfileFromStackToTab(); rpl::producer selectedListValue() const; bool requireTopBarSearch() const; @@ -215,8 +208,6 @@ private: int _additionalScroll = 0; bool _expanding = false; rpl::variable _grabbingForExpanding = false; - //object_ptr _topTabsBackground = { nullptr }; - //object_ptr _topTabs = { nullptr }; object_ptr _topBar = { nullptr }; object_ptr _topBarSurrogate = { nullptr }; Ui::Animations::Simple _topBarOverrideAnimation; @@ -227,9 +218,8 @@ private: base::unique_qptr _topBarMenuToggle; base::unique_qptr _topBarMenu; -// Tab _tab = Tab::Profile; -// std::shared_ptr _anotherTabMemento; std::vector _historyStack; + rpl::event_stream<> _removeRequests; rpl::event_stream> _desiredHeights; rpl::event_stream> _desiredShadowVisibilities; diff --git a/Telegram/SourceFiles/info/media/info_media_buttons.h b/Telegram/SourceFiles/info/media/info_media_buttons.h index cf4e7dedc..ea00814aa 100644 --- a/Telegram/SourceFiles/info/media/info_media_buttons.h +++ b/Telegram/SourceFiles/info/media/info_media_buttons.h @@ -93,8 +93,15 @@ inline auto AddButton( MediaText(type), tracker)->entity(); result->addClickHandler([=] { - navigation->showSection( - std::make_shared(peer, Section(type))); + const auto topic = topicRootId + ? peer->forumTopicFor(topicRootId) + : nullptr; + if (topicRootId && !topic) { + return; + } + navigation->showSection(topicRootId + ? std::make_shared(topic, Section(type)) + : std::make_shared(peer, Section(type))); }); return result; }; diff --git a/Telegram/SourceFiles/info/media/info_media_inner_widget.cpp b/Telegram/SourceFiles/info/media/info_media_inner_widget.cpp index 8c9e045c5..dce97363c 100644 --- a/Telegram/SourceFiles/info/media/info_media_inner_widget.cpp +++ b/Telegram/SourceFiles/info/media/info_media_inner_widget.cpp @@ -41,8 +41,7 @@ InnerWidget::InnerWidget( } // Allows showing additional shared media links and tabs. -// Was done for top level tabs support. -// Now used for shared media in Saved Messages. +// Used for shared media in Saved Messages. void InnerWidget::setupOtherTypes() { if (_controller->key().peer()->isSelf() && _isStackBottom) { createOtherTypes(); @@ -50,26 +49,14 @@ void InnerWidget::setupOtherTypes() { _otherTypes.destroy(); refreshHeight(); } - //rpl::combine( - // _controller->wrapValue(), - // _controller->searchEnabledByContent() - //) | rpl::start_with_next([this](Wrap wrap, bool enabled) { - // _searchEnabled = enabled; - // refreshSearchField(); - //}, lifetime()); } void InnerWidget::createOtherTypes() { - //_otherTabsShadow.create(this); - //_otherTabsShadow->show(); - - //_otherTabs = nullptr; _otherTypes.create(this); _otherTypes->show(); createTypeButtons(); _otherTypes->add(object_ptr(_otherTypes)); - //createTabs(); _otherTypes->resizeToWidth(width()); _otherTypes->heightValue( @@ -111,19 +98,6 @@ void InnerWidget::createTypeButtons() { icon, st::infoSharedMediaButtonIconPosition)->show(); }; - //auto addCommonGroupsButton = [&]( - // not_null user, - // const style::icon &icon) { - // auto result = AddCommonGroupsButton( - // content, - // _controller, - // user, - // tracker); - // object_ptr( - // result, - // icon, - // st::infoSharedMediaButtonIconPosition)->show(); - //}; addMediaButton(Type::Photo, st::infoIconMediaPhoto); addMediaButton(Type::Video, st::infoIconMediaVideo); @@ -132,9 +106,6 @@ void InnerWidget::createTypeButtons() { addMediaButton(Type::Link, st::infoIconMediaLink); addMediaButton(Type::RoundVoiceFile, st::infoIconMediaVoice); addMediaButton(Type::GIF, st::infoIconMediaGif); -// if (auto user = _controller->key().peer()->asUser()) { -// addCommonGroupsButton(user, st::infoIconMediaGroup); -// } content->add(object_ptr( content, @@ -143,33 +114,6 @@ void InnerWidget::createTypeButtons() { wrap->finishAnimating(); } -//void InnerWidget::createTabs() { -// _otherTabs = _otherTypes->add(object_ptr( -// this, -// st::infoTabs)); -// auto sections = QStringList(); -// sections.push_back(tr::lng_media_type_photos(tr::now).toUpper()); -// sections.push_back(tr::lng_media_type_videos(tr::now).toUpper()); -// sections.push_back(tr::lng_media_type_files(tr::now).toUpper()); -// _otherTabs->setSections(sections); -// _otherTabs->setActiveSection(*TypeToTabIndex(type())); -// _otherTabs->finishAnimating(); -// -// _otherTabs->sectionActivated( -// ) | rpl::map([](int index) { -// return TabIndexToType(index); -// }) | rpl::start_with_next( -// [this](Type newType) { -// if (type() != newType) { -// switchToTab(Memento( -// _controller->peerId(), -// _controller->migratedPeerId(), -// newType)); -// } -// }, -// _otherTabs->lifetime()); -//} - Type InnerWidget::type() const { return _controller->section().mediaType(); } @@ -188,63 +132,10 @@ bool InnerWidget::showInternal(not_null memento) { if (mementoType == type()) { restoreState(memento); return true; - - // Allows showing additional shared media links and tabs. - // Was done for top level tabs support. - // - //} else if (_otherTypes) { - // if (TypeToTabIndex(mementoType)) { - // switchToTab(std::move(*memento)); - // return true; - // } - } return false; } -// Allows showing additional shared media links and tabs. -// Was done for top level tabs support. -// -//void InnerWidget::switchToTab(Memento &&memento) { -// // Save state of the tab before setSection() call. -// _controller->setSection(&memento); -// _list = setupList(); -// restoreState(&memento); -// _list->show(); -// _list->resizeToWidth(width()); -// refreshHeight(); -// if (_otherTypes) { -// _otherTabsShadow->raise(); -// _otherTypes->raise(); -// _otherTabs->setActiveSection(*TypeToTabIndex(type())); -// } -//} -// -//void InnerWidget::refreshSearchField() { -// auto search = _controller->searchFieldController(); -// if (search && _otherTabs && _searchEnabled) { -// _searchField = search->createRowView( -// this, -// st::infoMediaSearch); -// _searchField->resizeToWidth(width()); -// _searchField->show(); -// search->queryChanges( -// ) | rpl::start_with_next([this] { -// scrollToSearchField(); -// }, _searchField->lifetime()); -// } else { -// _searchField = nullptr; -// } -//} -// -//void InnerWidget::scrollToSearchField() { -// Expects(_searchField != nullptr); -// -// auto top = _searchField->y(); -// auto bottom = top + _searchField->height(); -// _scrollToRequests.fire({ top, bottom }); -//} - object_ptr InnerWidget::setupList() { auto result = object_ptr( this, @@ -299,11 +190,7 @@ int InnerWidget::resizeGetHeight(int newWidth) { if (_otherTypes) { _otherTypes->resizeToWidth(newWidth); - //_otherTabsShadow->resizeToWidth(newWidth); } - //if (_searchField) { - // _searchField->resizeToWidth(newWidth); - //} _list->resizeToWidth(newWidth); _empty->resizeToWidth(newWidth); return recountHeight(); @@ -321,12 +208,7 @@ int InnerWidget::recountHeight() { if (_otherTypes) { _otherTypes->moveToLeft(0, top); top += _otherTypes->heightNoMargins() - st::lineWidth; -// _otherTabsShadow->moveToLeft(0, top); } - //if (_searchField) { - // _searchField->moveToLeft(0, top); - // top += _searchField->heightNoMargins() - st::lineWidth; - //} auto listHeight = 0; if (_list) { _list->moveToLeft(0, top); diff --git a/Telegram/SourceFiles/info/media/info_media_inner_widget.h b/Telegram/SourceFiles/info/media/info_media_inner_widget.h index 1b4d55276..a7a2ce61d 100644 --- a/Telegram/SourceFiles/info/media/info_media_inner_widget.h +++ b/Telegram/SourceFiles/info/media/info_media_inner_widget.h @@ -62,18 +62,10 @@ private: int recountHeight(); void refreshHeight(); // Allows showing additional shared media links and tabs. - // Was done for top level tabs support. - // Now used for shared media in Saved Messages. + // Used for shared media in Saved Messages. void setupOtherTypes(); void createOtherTypes(); void createTypeButtons(); - // Allows showing additional shared media links and tabs. - // Was done for top level tabs support. - // - //void createTabs(); - //void switchToTab(Memento &&memento); - //void refreshSearchField(); - //void scrollToSearchField(); Type type() const; @@ -81,13 +73,9 @@ private: const not_null _controller; - //Ui::SettingsSlider *_otherTabs = nullptr; object_ptr _otherTypes = { nullptr }; - //object_ptr _otherTabsShadow = { nullptr }; - //base::unique_qptr _searchField = nullptr; object_ptr _list = { nullptr }; object_ptr _empty; - //bool _searchEnabled = false; bool _inResize = false; bool _isStackBottom = false; diff --git a/Telegram/SourceFiles/info/media/info_media_widget.cpp b/Telegram/SourceFiles/info/media/info_media_widget.cpp index 55325fb49..a02453a0e 100644 --- a/Telegram/SourceFiles/info/media/info_media_widget.cpp +++ b/Telegram/SourceFiles/info/media/info_media_widget.cpp @@ -15,6 +15,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "ui/ui_utility.h" #include "data/data_peer.h" #include "data/data_user.h" +#include "data/data_channel.h" +#include "data/data_forum_topic.h" #include "lang/lang_keys.h" #include "styles/style_info.h" @@ -43,6 +45,7 @@ Memento::Memento(not_null controller) (controller->peer() ? controller->peer() : controller->parentController()->session().user()), + controller->topic(), controller->migratedPeerId(), (controller->section().type() == Section::Type::Downloads ? Type::File @@ -50,23 +53,25 @@ Memento::Memento(not_null controller) } Memento::Memento(not_null peer, PeerId migratedPeerId, Type type) -: ContentMemento(peer, migratedPeerId) -, _type(type) { - _searchState.query.type = type; - _searchState.query.peerId = peer->id; - _searchState.query.migratedPeerId = migratedPeerId; - if (migratedPeerId) { - _searchState.migratedList = Storage::SparseIdsList(); - } +: Memento(peer, nullptr, migratedPeerId, type) { } Memento::Memento(not_null topic, Type type) -: ContentMemento(topic) +: Memento(topic->channel(), topic, PeerId(), type) { +} + +Memento::Memento( + not_null peer, + Data::ForumTopic *topic, + PeerId migratedPeerId, + Type type) +: ContentMemento(peer, topic, migratedPeerId) , _type(type) { - _searchState.query.type = type; // #TODO forum search - _searchState.query.peerId = peer()->id; - _searchState.query.migratedPeerId = migratedPeerId(); - if (migratedPeerId()) { + _searchState.query.type = type; + _searchState.query.peerId = peer->id; + _searchState.query.topicRootId = topic ? topic->rootId() : 0; + _searchState.query.migratedPeerId = migratedPeerId; + if (migratedPeerId) { _searchState.migratedList = Storage::SparseIdsList(); } } diff --git a/Telegram/SourceFiles/info/media/info_media_widget.h b/Telegram/SourceFiles/info/media/info_media_widget.h index 1b9438aff..693d01aee 100644 --- a/Telegram/SourceFiles/info/media/info_media_widget.h +++ b/Telegram/SourceFiles/info/media/info_media_widget.h @@ -83,6 +83,12 @@ public: } private: + Memento( + not_null peer, + Data::ForumTopic *topic, + PeerId migratedPeerId, + Type type); + Type _type = Type::Photo; FullMsgId _aroundId; int _idsLimit = 0; diff --git a/Telegram/SourceFiles/info/members/info_members_widget.cpp b/Telegram/SourceFiles/info/members/info_members_widget.cpp index 5ddea3ec7..0a00a7344 100644 --- a/Telegram/SourceFiles/info/members/info_members_widget.cpp +++ b/Telegram/SourceFiles/info/members/info_members_widget.cpp @@ -26,7 +26,7 @@ Memento::Memento(not_null controller) } Memento::Memento(not_null peer, PeerId migratedPeerId) -: ContentMemento(peer, migratedPeerId) { +: ContentMemento(peer, nullptr, migratedPeerId) { } Section Memento::section() const { diff --git a/Telegram/SourceFiles/info/profile/info_profile_inner_widget.cpp b/Telegram/SourceFiles/info/profile/info_profile_inner_widget.cpp index eb13f977f..e885c9a6a 100644 --- a/Telegram/SourceFiles/info/profile/info_profile_inner_widget.cpp +++ b/Telegram/SourceFiles/info/profile/info_profile_inner_widget.cpp @@ -73,8 +73,9 @@ object_ptr InnerWidget::setupContent( _topic ? TitleValue(_topic) : NameValue(_peer))); _cover->showSection( ) | rpl::start_with_next([=](Section section) { - _controller->showSection( - std::make_shared(_peer, section)); + _controller->showSection(_topic + ? std::make_shared(_topic, section) + : std::make_shared(_peer, section)); }, _cover->lifetime()); _cover->setOnlineCount(rpl::single(0)); if (_topic) { @@ -166,34 +167,6 @@ object_ptr InnerWidget::setupSharedMedia( object_ptr(parent) ); - // Allows removing shared media links in third column. - // Was done for tabs support. - // - //using ToggledData = std::tuple; - //rpl::combine( - // tracker.atLeastOneShownValue(), - // _controller->wrapValue(), - // _isStackBottom.value() - //) | rpl::combine_previous( - // ToggledData() - //) | rpl::start_with_next([wrap = result.data()]( - // const ToggledData &was, - // const ToggledData &now) { - // bool wasOneShown, wasStackBottom, nowOneShown, nowStackBottom; - // Wrap wasWrap, nowWrap; - // std::tie(wasOneShown, wasWrap, wasStackBottom) = was; - // std::tie(nowOneShown, nowWrap, nowStackBottom) = now; - // // MSVC Internal Compiler Error - // //auto [wasOneShown, wasWrap, wasStackBottom] = was; - // //auto [nowOneShown, nowWrap, nowStackBottom] = now; - // wrap->toggle( - // nowOneShown && (nowWrap != Wrap::Side || !nowStackBottom), - // (wasStackBottom == nowStackBottom && wasWrap == nowWrap) - // ? anim::type::normal - // : anim::type::instant); - //}, result->lifetime()); - // - // Using that instead result->setDuration( st::infoSlideDuration )->toggleOn( diff --git a/Telegram/SourceFiles/info/profile/info_profile_widget.cpp b/Telegram/SourceFiles/info/profile/info_profile_widget.cpp index 22d836c31..39bf8491e 100644 --- a/Telegram/SourceFiles/info/profile/info_profile_widget.cpp +++ b/Telegram/SourceFiles/info/profile/info_profile_widget.cpp @@ -13,6 +13,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "ui/ui_utility.h" #include "data/data_peer.h" #include "data/data_channel.h" +#include "data/data_forum_topic.h" #include "data/data_user.h" #include "lang/lang_keys.h" #include "info/info_controller.h" @@ -22,15 +23,23 @@ namespace Info::Profile { Memento::Memento(not_null controller) : Memento( controller->peer(), + controller->topic(), controller->migratedPeerId()) { } Memento::Memento(not_null peer, PeerId migratedPeerId) -: ContentMemento(peer, migratedPeerId) { +: Memento(peer, nullptr, migratedPeerId) { +} + +Memento::Memento( + not_null peer, + Data::ForumTopic *topic, + PeerId migratedPeerId) +: ContentMemento(peer, topic, migratedPeerId) { } Memento::Memento(not_null topic) -: ContentMemento(topic) { +: ContentMemento(topic->channel(), topic, 0) { } Section Memento::section() const { diff --git a/Telegram/SourceFiles/info/profile/info_profile_widget.h b/Telegram/SourceFiles/info/profile/info_profile_widget.h index 0781a7082..51e9f0b06 100644 --- a/Telegram/SourceFiles/info/profile/info_profile_widget.h +++ b/Telegram/SourceFiles/info/profile/info_profile_widget.h @@ -37,6 +37,11 @@ public: ~Memento(); private: + Memento( + not_null peer, + Data::ForumTopic *topic, + PeerId migratedPeerId); + std::unique_ptr _membersState; }; diff --git a/Telegram/SourceFiles/mainwidget.cpp b/Telegram/SourceFiles/mainwidget.cpp index 227e1758d..090759dec 100644 --- a/Telegram/SourceFiles/mainwidget.cpp +++ b/Telegram/SourceFiles/mainwidget.cpp @@ -123,27 +123,33 @@ enum StackItemType { class StackItem { public: - StackItem(PeerData *peer) : _peer(peer) { + explicit StackItem(PeerData *peer) : _peer(peer) { } - PeerData *peer() const { + [[nodiscard]] PeerData *peer() const { return _peer; } void setThirdSectionMemento( std::shared_ptr memento); - std::shared_ptr takeThirdSectionMemento() { + [[nodiscard]] auto takeThirdSectionMemento() + -> std::shared_ptr { return std::move(_thirdSectionMemento); } void setThirdSectionWeak(QPointer section) { _thirdSectionWeak = section; } - QPointer thirdSectionWeak() const { + [[nodiscard]] QPointer thirdSectionWeak() const { return _thirdSectionWeak; } - virtual StackItemType type() const = 0; + [[nodiscard]] rpl::lifetime &lifetime() { + return _lifetime; + } + + [[nodiscard]] virtual StackItemType type() const = 0; + [[nodiscard]] virtual rpl::producer<> removeRequests() const = 0; virtual ~StackItem() = default; private: @@ -151,9 +157,11 @@ private: QPointer _thirdSectionWeak; std::shared_ptr _thirdSectionMemento; + rpl::lifetime _lifetime; + }; -class StackItemHistory : public StackItem { +class StackItemHistory final : public StackItem { public: StackItemHistory( not_null history, @@ -168,6 +176,9 @@ public: StackItemType type() const override { return HistoryStackItem; } + rpl::producer<> removeRequests() const override { + return rpl::never<>(); + } not_null history; MsgId msgId; @@ -183,6 +194,9 @@ public: StackItemType type() const override { return SectionStackItem; } + rpl::producer<> removeRequests() const override { + return _memento->removeRequests(); + } std::shared_ptr takeMemento() { return std::move(_memento); } @@ -1499,15 +1513,28 @@ void MainWidget::saveSectionInStack() { if (auto memento = _mainSection->createMemento()) { _stack.push_back(std::make_unique( std::move(memento))); - _stack.back()->setThirdSectionWeak(_thirdSection.data()); + } else { + return; } } else if (const auto history = _history->history()) { _stack.push_back(std::make_unique( history, _history->msgId(), _history->replyReturns())); - _stack.back()->setThirdSectionWeak(_thirdSection.data()); + } else { + return; } + const auto raw = _stack.back().get(); + raw->setThirdSectionWeak(_thirdSection.data()); + raw->removeRequests( + ) | rpl::start_with_next([=] { + for (auto i = begin(_stack); i != end(_stack); ++i) { + if (i->get() == raw) { + _stack.erase(i); + return; + } + } + }, raw->lifetime()); } void MainWidget::showSection( @@ -1715,6 +1742,12 @@ void MainWidget::showNewSection( : _mainSection; if (newThirdSection) { _thirdSection = std::move(newThirdSection); + _thirdSection->removeRequests( + ) | rpl::start_with_next([=] { + _thirdSection.destroy(); + _thirdShadow.destroy(); + updateControlsGeometry(); + }, _thirdSection->lifetime()); if (!_thirdShadow) { _thirdShadow.create(this); _thirdShadow->show(); @@ -1821,9 +1854,9 @@ bool MainWidget::preventsCloseSection(Fn callback) const { bool MainWidget::preventsCloseSection( Fn callback, const SectionShow ¶ms) const { - return params.thirdColumn - ? false - : preventsCloseSection(std::move(callback)); + return !params.thirdColumn + && (params.activation != anim::activation::background) + && preventsCloseSection(std::move(callback)); } void MainWidget::showBackFromStack( diff --git a/Telegram/SourceFiles/media/view/media_view_overlay_widget.cpp b/Telegram/SourceFiles/media/view/media_view_overlay_widget.cpp index 868236797..f20f0bf7e 100644 --- a/Telegram/SourceFiles/media/view/media_view_overlay_widget.cpp +++ b/Telegram/SourceFiles/media/view/media_view_overlay_widget.cpp @@ -1902,9 +1902,19 @@ void OverlayWidget::showMediaOverview() { close(); if (SharedMediaOverviewType(*overviewType)) { if (const auto window = findWindow()) { - window->showSection(std::make_shared( - _history->peer, - Info::Section(*overviewType))); + const auto topic = _topicRootId + ? _history->peer->forumTopicFor(_topicRootId) + : nullptr; + if (_topicRootId && !topic) { + return; + } + window->showSection(_topicRootId + ? std::make_shared( + topic, + Info::Section(*overviewType)) + : std::make_shared( + _history->peer, + Info::Section(*overviewType))); } } } diff --git a/Telegram/SourceFiles/ui/chat/chat.style b/Telegram/SourceFiles/ui/chat/chat.style index 2f87b2c2c..c37d3b7e4 100644 --- a/Telegram/SourceFiles/ui/chat/chat.style +++ b/Telegram/SourceFiles/ui/chat/chat.style @@ -1225,11 +1225,11 @@ reactionPremiumLocked: icon{ { "chat/reactions_premium_star", historyPeerUserpicFg }, }; reactionExpandPanel: icon{ - { "chat/reactions_round_big", windowSubTextFg }, + { "chat/reactions_round_big", windowBgRipple }, { "chat/reactions_expand_panel", windowBg }, }; reactionsExpandDropdown: icon{ - { "chat/reactions_round_small", windowSubTextFg }, + { "chat/reactions_round_small", windowBgRipple }, { "chat/reactions_expand_panel", windowBg }, }; diff --git a/Telegram/SourceFiles/window/section_memento.h b/Telegram/SourceFiles/window/section_memento.h index 628c27c64..605663bd5 100644 --- a/Telegram/SourceFiles/window/section_memento.h +++ b/Telegram/SourceFiles/window/section_memento.h @@ -19,21 +19,25 @@ enum class Column; class SectionMemento { public: - virtual object_ptr createWidget( + [[nodiscard]] virtual object_ptr createWidget( QWidget *parent, not_null controller, Column column, const QRect &geometry) = 0; - virtual object_ptr createLayer( + [[nodiscard]] virtual object_ptr createLayer( not_null controller, const QRect &geometry) { return nullptr; } - virtual bool instant() const { + [[nodiscard]] virtual bool instant() const { return false; } + [[nodiscard]] virtual rpl::producer<> removeRequests() const { + return rpl::never<>(); + } + virtual ~SectionMemento() = default; }; diff --git a/Telegram/SourceFiles/window/section_widget.h b/Telegram/SourceFiles/window/section_widget.h index 81cc3b12e..dec35d6df 100644 --- a/Telegram/SourceFiles/window/section_widget.h +++ b/Telegram/SourceFiles/window/section_widget.h @@ -139,7 +139,8 @@ public: return false; } - virtual bool preventsClose(Fn &&continueCallback) const { + [[nodiscard]] virtual bool preventsClose( + Fn &&continueCallback) const { return false; } @@ -157,10 +158,13 @@ public: doSetInnerFocus(); } - virtual rpl::producer desiredHeight() const; + [[nodiscard]] virtual rpl::producer desiredHeight() const; + [[nodiscard]] virtual rpl::producer<> removeRequests() const { + return rpl::never<>(); + } // Some sections convert to layers on some geometry sizes. - virtual object_ptr moveContentToLayer( + [[nodiscard]] virtual object_ptr moveContentToLayer( QRect bodyGeometry) { return nullptr; } diff --git a/Telegram/SourceFiles/window/window_session_controller.cpp b/Telegram/SourceFiles/window/window_session_controller.cpp index 57e65ab78..7f05f1041 100644 --- a/Telegram/SourceFiles/window/window_session_controller.cpp +++ b/Telegram/SourceFiles/window/window_session_controller.cpp @@ -893,12 +893,8 @@ void SessionController::openForum( closeFolder(); _openedForum = forum.get(); if (_openedForum.current() == forum) { - forum->flagsValue( - ) | rpl::filter([=](const ChannelData::Flags::Change &update) { - using Flag = ChannelData::Flag; - return (update.diff & Flag::Forum) - && !(update.value & Flag::Forum); - }) | rpl::start_with_next([=] { + forum->forum()->destroyed( + ) | rpl::start_with_next([=] { closeForum(); showPeerHistory( forum,