Improved display of top bar suggestion in non-main chats lists.

This commit is contained in:
23rd 2025-04-12 16:08:50 +03:00 committed by John Preston
parent 2eab7044ba
commit b4a9e45214
4 changed files with 71 additions and 20 deletions

View file

@ -56,13 +56,22 @@ constexpr auto kSugSetUserpic = "USERPIC_SETUP"_cs;
rpl::producer<Ui::SlideWrap<Ui::RpWidget>*> TopBarSuggestionValue(
not_null<Ui::RpWidget*> parent,
not_null<Main::Session*> session) {
return [=](auto consumer) {
not_null<Main::Session*> session,
rpl::producer<bool> 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<Ui::RpWidget> *wrap = nullptr;
rpl::variable<Toggle> desiredWrapToggle;
rpl::variable<bool> outerWrapToggle;
rpl::lifetime birthdayLifetime;
rpl::lifetime premiumLifetime;
rpl::lifetime userpicLifetime;
@ -70,6 +79,7 @@ rpl::producer<Ui::SlideWrap<Ui::RpWidget>*> TopBarSuggestionValue(
};
const auto state = lifetime.make_state<State>();
state->outerWrapToggle = rpl::duplicate(outerWrapToggleValue);
const auto ensureWrap = [=] {
if (!state->content) {
state->content = Ui::CreateChild<TopBarSuggestionContent>(
@ -85,7 +95,8 @@ rpl::producer<Ui::SlideWrap<Ui::RpWidget>*> TopBarSuggestionValue(
state->wrap = Ui::CreateChild<Ui::SlideWrap<Ui::RpWidget>>(
parent,
object_ptr<Ui::RpWidget>::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<Ui::SlideWrap<Ui::RpWidget>*> 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<Ui::SlideWrap<Ui::RpWidget>*> 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<Ui::SlideWrap<Ui::RpWidget>*> 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<Ui::SlideWrap<Ui::RpWidget>*> 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<Ui::SlideWrap<Ui::RpWidget>*> 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);

View file

@ -24,7 +24,8 @@ namespace Dialogs {
[[nodiscard]] auto TopBarSuggestionValue(
not_null<Ui::RpWidget*> parent,
not_null<Main::Session*>)
not_null<Main::Session*>,
rpl::producer<bool> outerWrapToggleValue)
-> rpl::producer<Ui::SlideWrap<Ui::RpWidget>*>;
} // namespace Dialogs

View file

@ -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<Ui::VerticalLayout*> dialogs) {
? rpl::single<Data::Folder*>(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<Ui::RpWidget> *raw) {
if (raw) {
_topBarSuggestion = dialogs->insert(
0,
object_ptr<Ui::SlideWrap<Ui::RpWidget>>::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);
}
}

View file

@ -330,6 +330,8 @@ private:
base::unique_qptr<Ui::RpWidget> _chatFilters;
Ui::SlideWrap<Ui::RpWidget> *_topBarSuggestion = nullptr;
rpl::event_stream<int> _topBarSuggestionHeightChanged;
rpl::event_stream<bool> _openedFolderOrForumChanges;
object_ptr<Ui::ElasticScroll> _scroll;
QPointer<InnerWidget> _inner;