From b4a9e4521439d9c84bb9a8120d2090699fb05741 Mon Sep 17 00:00:00 2001 From: 23rd <23rd@vivaldi.net> Date: Sat, 12 Apr 2025 16:08:50 +0300 Subject: [PATCH] Improved display of top bar suggestion in non-main chats lists. --- .../dialogs/dialogs_top_bar_suggestion.cpp | 53 ++++++++++++++++--- .../dialogs/dialogs_top_bar_suggestion.h | 3 +- .../SourceFiles/dialogs/dialogs_widget.cpp | 33 ++++++++---- Telegram/SourceFiles/dialogs/dialogs_widget.h | 2 + 4 files changed, 71 insertions(+), 20 deletions(-) diff --git a/Telegram/SourceFiles/dialogs/dialogs_top_bar_suggestion.cpp b/Telegram/SourceFiles/dialogs/dialogs_top_bar_suggestion.cpp index a62402fd8e..9b5f448e68 100644 --- a/Telegram/SourceFiles/dialogs/dialogs_top_bar_suggestion.cpp +++ b/Telegram/SourceFiles/dialogs/dialogs_top_bar_suggestion.cpp @@ -56,13 +56,22 @@ constexpr auto kSugSetUserpic = "USERPIC_SETUP"_cs; rpl::producer*> TopBarSuggestionValue( not_null parent, - not_null session) { - return [=](auto consumer) { + not_null session, + rpl::producer outerWrapToggleValue) { + return [=, outerWrapToggleValue = rpl::duplicate(outerWrapToggleValue)]( + auto consumer) { auto lifetime = rpl::lifetime(); + struct Toggle { + bool value = false; + anim::type type; + }; + struct State { TopBarSuggestionContent *content = nullptr; Ui::SlideWrap *wrap = nullptr; + rpl::variable desiredWrapToggle; + rpl::variable outerWrapToggle; rpl::lifetime birthdayLifetime; rpl::lifetime premiumLifetime; rpl::lifetime userpicLifetime; @@ -70,6 +79,7 @@ rpl::producer*> TopBarSuggestionValue( }; const auto state = lifetime.make_state(); + state->outerWrapToggle = rpl::duplicate(outerWrapToggleValue); const auto ensureWrap = [=] { if (!state->content) { state->content = Ui::CreateChild( @@ -85,7 +95,8 @@ rpl::producer*> TopBarSuggestionValue( state->wrap = Ui::CreateChild>( parent, object_ptr::fromRaw(state->content)); - state->wrap->toggle(false, anim::type::instant); + state->desiredWrapToggle.force_assign( + Toggle{ false, anim::type::instant }); } }; @@ -225,7 +236,8 @@ rpl::producer*> TopBarSuggestionValue( content->setLeftPadding(fake->width() + leftPadding); } - wrap->toggle(true, anim::type::normal); + state->desiredWrapToggle.force_assign( + Toggle{ true, anim::type::normal }); }), state->giftsLifetime); return; } else if (config->suggestionCurrent(kSugSetBirthday.utf8()) @@ -263,7 +275,8 @@ rpl::producer*> TopBarSuggestionValue( tr::lng_dialogs_suggestions_birthday_about( tr::now, TextWithEntities::Simple)); - wrap->toggle(true, anim::type::normal); + state->desiredWrapToggle.force_assign( + Toggle{ true, anim::type::normal }); return; } else if (session->premiumPossible() && !session->premium()) { const auto isPremiumAnnual = config->suggestionCurrent( @@ -305,7 +318,8 @@ rpl::producer*> TopBarSuggestionValue( : kSugPremiumUpgrade.utf8()); repeat(repeat); }); - wrap->toggle(true, anim::type::normal); + state->desiredWrapToggle.force_assign( + Toggle{ true, anim::type::normal }); }; if (isPremiumAnnual || isPremiumRestore || isPremiumUpgrade) { content->setRightIcon(RightIcon::Arrow); @@ -391,10 +405,12 @@ rpl::producer*> TopBarSuggestionValue( tr::lng_dialogs_suggestions_userpics_about( tr::now, TextWithEntities::Simple)); - wrap->toggle(true, anim::type::normal); + state->desiredWrapToggle.force_assign( + Toggle{ true, anim::type::normal }); return; } - wrap->toggle(false, anim::type::normal); + state->desiredWrapToggle.force_assign( + Toggle{ false, anim::type::normal }); base::call_delayed(st::slideWrapDuration * 2, wrap, [=] { state->content = nullptr; state->wrap = nullptr; @@ -402,6 +418,27 @@ rpl::producer*> TopBarSuggestionValue( }); }; + state->desiredWrapToggle.value() | rpl::combine_previous( + ) | rpl::filter([=] { + return state->wrap != nullptr; + }) | rpl::start_with_next([=](Toggle was, Toggle now) { + state->wrap->toggle( + state->outerWrapToggle.current() && now.value, + (was.value == now.value) + ? anim::type::instant + : now.type); + }, lifetime); + + state->outerWrapToggle.value() | rpl::combine_previous( + ) | rpl::filter([=] { + return state->wrap != nullptr; + }) | rpl::start_with_next([=](bool was, bool now) { + const auto toggle = state->desiredWrapToggle.current(); + state->wrap->toggle( + toggle.value && now, + (was == now) ? toggle.type : anim::type::instant); + }, lifetime); + session->appConfig().value() | rpl::start_with_next([=] { const auto was = state->wrap; processCurrentSuggestion(processCurrentSuggestion); diff --git a/Telegram/SourceFiles/dialogs/dialogs_top_bar_suggestion.h b/Telegram/SourceFiles/dialogs/dialogs_top_bar_suggestion.h index 4ff01525c6..613299988b 100644 --- a/Telegram/SourceFiles/dialogs/dialogs_top_bar_suggestion.h +++ b/Telegram/SourceFiles/dialogs/dialogs_top_bar_suggestion.h @@ -24,7 +24,8 @@ namespace Dialogs { [[nodiscard]] auto TopBarSuggestionValue( not_null parent, - not_null) + not_null, + rpl::producer outerWrapToggleValue) -> rpl::producer*>; } // namespace Dialogs diff --git a/Telegram/SourceFiles/dialogs/dialogs_widget.cpp b/Telegram/SourceFiles/dialogs/dialogs_widget.cpp index 6ee40e1a69..b76b82de89 100644 --- a/Telegram/SourceFiles/dialogs/dialogs_widget.cpp +++ b/Telegram/SourceFiles/dialogs/dialogs_widget.cpp @@ -386,10 +386,12 @@ Widget::Widget( _childListPeerId.value(), _childListShown.value(), makeChildListShown))); - _scroll->heightValue() | rpl::start_with_next([=](int height) { + rpl::combine( + _scroll->heightValue(), + _topBarSuggestionHeightChanged.events_starting_with(0) + ) | rpl::start_with_next([=](int height, int topBarHeight) { innerList->setMinimumHeight(height); - _inner->setMinimumHeight(height - - (_topBarSuggestion ? _topBarSuggestion->height() : 0)); + _inner->setMinimumHeight(height - topBarHeight); _inner->refresh(); }, innerList->lifetime()); _scroll->widthValue() | rpl::start_with_next([=](int width) { @@ -1028,13 +1030,28 @@ void Widget::setupTopBarSuggestions(not_null dialogs) { ? rpl::single(nullptr) : session->data().chatsListLoadedEvents() ) | rpl::filter(_1 == nullptr) | rpl::map([=] { - return TopBarSuggestionValue(dialogs, session); + auto on = rpl::combine( + controller()->activeChatsFilter(), + _openedFolderOrForumChanges.events_starting_with(false), + widthValue() | rpl::map( + _1 >= st::columnMinimalWidthLeft + ) | rpl::distinct_until_changed() + ) | rpl::map([=](FilterId id, bool folderOrForum, bool wide) { + return !folderOrForum + && wide + && (id == session->data().chatsFilters().defaultId()); + }); + return TopBarSuggestionValue(dialogs, session, std::move(on)); }) | rpl::flatten_latest() | rpl::start_with_next([=]( Ui::SlideWrap *raw) { if (raw) { _topBarSuggestion = dialogs->insert( 0, object_ptr>::fromRaw(raw)); + _topBarSuggestion->heightValue( + ) | rpl::start_to_stream( + _topBarSuggestionHeightChanged, + _topBarSuggestion->entity()->lifetime()); rpl::combine( _topBarSuggestion->entity()->desiredHeightValue(), _childListShown.value() @@ -1075,13 +1092,7 @@ void Widget::updateFrozenAccountBar() { void Widget::updateTopBarSuggestions() { if (_topBarSuggestion) { - if ((_layout == Layout::Child) - || _openedForum - || _openedFolder) { - _topBarSuggestion->toggle(false, anim::type::instant); - } else { - _topBarSuggestion->toggle(true, anim::type::instant); - } + _openedFolderOrForumChanges.fire(_openedForum || _openedFolder); } } diff --git a/Telegram/SourceFiles/dialogs/dialogs_widget.h b/Telegram/SourceFiles/dialogs/dialogs_widget.h index fb502850fc..2ed8f98cb8 100644 --- a/Telegram/SourceFiles/dialogs/dialogs_widget.h +++ b/Telegram/SourceFiles/dialogs/dialogs_widget.h @@ -330,6 +330,8 @@ private: base::unique_qptr _chatFilters; Ui::SlideWrap *_topBarSuggestion = nullptr; + rpl::event_stream _topBarSuggestionHeightChanged; + rpl::event_stream _openedFolderOrForumChanges; object_ptr _scroll; QPointer _inner;