Added slide animation for chats filter switching.

This commit is contained in:
23rd
2026-09-10 12:24:07 +03:00
committed by John Preston
parent 5d431ead94
commit f5f460da36
5 changed files with 111 additions and 13 deletions

View File

@@ -41,6 +41,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "ui/wrap/vertical_layout.h"
#include "ui/effects/radial_animation.h"
#include "ui/effects/ripple_animation.h"
#include "ui/effects/slide_animation.h"
#include "ui/chat/requests_bar.h"
#include "ui/chat/group_call_bar.h"
#include "ui/chat/more_chats_bar.h"
@@ -447,6 +448,10 @@ Widget::Widget(
_childListPeerId.value(),
_childListShown.value(),
makeChildListShown)));
controller->activeChatsFilter(
) | rpl::on_next([=](FilterId id) {
switchToChatsFilter(id);
}, lifetime());
rpl::combine(
_scroll->heightValue(),
_topBarSuggestionHeightChanged.events_starting_with(0)
@@ -953,7 +958,9 @@ void Widget::setupSwipeBack() {
if (CheckAndJumpToNearChatsFilter(controller(), next, false)) {
return Ui::Controls::DefaultSwipeBackHandlerFinishData([=] {
_swipeBackData = {};
_chatsFilterSwipeSwitch = true;
CheckAndJumpToNearChatsFilter(controller(), next, true);
_chatsFilterSwipeSwitch = false;
});
}
}
@@ -2052,9 +2059,10 @@ void Widget::toggleFiltersMenu(bool enabled) {
_chatFilters.get(),
&session(),
[this](FilterId id) {
_scroll->scrollToY(0);
if (controller()->activeChatsFilterCurrent() != id) {
controller()->setActiveChatsFilter(id);
} else {
_scroll->scrollToY(0);
}
},
Window::GifPauseReason::Any,
@@ -2246,6 +2254,7 @@ void Widget::changeOpenedSubsection(
if (isHidden()) {
animated = anim::type::instant;
}
_chatsFilterSlideCanvas = nullptr;
auto oldContentCache = QPixmap();
const auto showDirection = fromRight
? Window::SlideDirection::FromRight
@@ -2519,6 +2528,84 @@ void Widget::showSearchInTopBar(anim::type animated) {
updateForceDisplayWide();
}
void Widget::switchToChatsFilter(FilterId id) {
const auto was = _inner->filterId();
const auto animated = (was != id)
&& !isHidden()
&& !_showAnimation
&& (_chatsFilterSwipeSwitch
|| (_chatFilters && !_chatFilters->isHidden()));
if (!animated) {
_inner->switchToFilter(id);
return;
}
const auto &list = session().data().chatsFilters().list();
const auto indexOf = [&](FilterId filterId) {
return int(ranges::find(list, filterId, &Data::ChatFilter::id)
- begin(list));
};
const auto slideLeft = (indexOf(id) < indexOf(was));
const auto duration = _chatsFilterSwipeSwitch
? st::dialogsFilterSwipeSlideDuration
: st::slideDuration;
_chatsFilterSlideCanvas = nullptr;
auto wasCache = grabForChatsFilterSlide();
_inner->switchToFilter(id);
if (_inner->filterId() == was) {
return;
}
startChatsFilterSlide(
std::move(wasCache),
grabForChatsFilterSlide(),
slideLeft,
duration);
}
QPixmap Widget::grabForChatsFilterSlide() {
const auto hidden = _scrollToTop->isHidden();
if (!hidden) {
_scrollToTop->hide();
}
auto result = Ui::GrabOpaque(
_scroll.data(),
_scroll->rect(),
st::dialogsBg->c);
if (!hidden) {
_scrollToTop->show();
}
return result;
}
void Widget::startChatsFilterSlide(
QPixmap wasCache,
QPixmap nowCache,
bool slideLeft,
crl::time duration) {
_chatsFilterSlideCanvas = std::make_unique<Ui::RpWidget>(this);
const auto canvas = _chatsFilterSlideCanvas.get();
canvas->setAttribute(Qt::WA_TransparentForMouseEvents);
canvas->setAttribute(Qt::WA_OpaquePaintEvent);
canvas->setGeometry(_scroll->geometry());
const auto animation
= canvas->lifetime().make_state<Ui::SlideAnimation>();
animation->setSnapshots(std::move(wasCache), std::move(nowCache));
canvas->paintOn([=](QPainter &p) {
p.fillRect(canvas->rect(), st::dialogsBg);
animation->paintFrame(p, 0, 0, canvas->width());
});
canvas->show();
if (_connecting) {
_connecting->raise();
}
animation->start(slideLeft, [=] {
if (animation->animating()) {
canvas->update();
} else {
_chatsFilterSlideCanvas = nullptr;
}
}, duration);
}
QPixmap Widget::grabForFolderSlideAnimation() {
const auto hidden = _scrollToTop->isHidden();
if (!hidden) {
@@ -2832,6 +2919,7 @@ void Widget::showAnimated(
Window::SlideDirection direction,
const Window::SectionSlideParams &params) {
_showAnimation = nullptr;
_chatsFilterSlideCanvas = nullptr;
auto oldContentCache = params.oldContentCache;
showFast();
@@ -4607,6 +4695,9 @@ void Widget::updateControlsGeometry() {
const auto scrollHeight = height() - scrollTop - bottomSkip;
const auto wasScrollHeight = _scroll->height();
_scroll->setGeometry(0, scrollTop, scrollWidth, scrollHeight);
if (_chatsFilterSlideCanvas) {
_chatsFilterSlideCanvas->setGeometry(_scroll->geometry());
}
if (scrollHeight != wasScrollHeight) {
controller()->floatPlayerAreaUpdated();
}