Skip to content

Commit f5f460d

Browse files
23rdjohn-preston
authored andcommitted
Added slide animation for chats filter switching.
1 parent 5d431ea commit f5f460d

5 files changed

Lines changed: 111 additions & 13 deletions

File tree

Telegram/SourceFiles/dialogs/dialogs.style

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -212,6 +212,7 @@ dialogsSpeakingDenominator: 8.;
212212
dialogsImportantBarHeight: 37px;
213213

214214
dialogsWidthDuration: universalDuration;
215+
dialogsFilterSwipeSlideDuration: 140;
215216
dialogsTextWidthMin: 150px;
216217

217218
dialogsTextPalette: TextPalette(defaultTextPalette) {

Telegram/SourceFiles/dialogs/dialogs_inner_widget.cpp

Lines changed: 7 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -579,11 +579,6 @@ InnerWidget::InnerWidget(
579579
update(next);
580580
}, lifetime());
581581

582-
_controller->activeChatsFilter(
583-
) | rpl::on_next([=](FilterId filterId) {
584-
switchToFilter(filterId);
585-
}, lifetime());
586-
587582
_controller->window().widget()->globalForceClicks(
588583
) | rpl::on_next([=](QPoint globalPosition) {
589584
processGlobalForceClick(globalPosition);
@@ -5596,8 +5591,8 @@ void InnerWidget::switchToFilter(FilterId filterId) {
55965591
const auto skip = found
55975592
// Don't save a scroll state for very flexible chat filters.
55985593
&& (filterIt->flags() & (Data::ChatFilter::Flag::NoRead));
5599-
if (!skip) {
5600-
restoreChatsFilterScrollState(filterId);
5594+
if (skip || !restoreChatsFilterScrollState(filterId)) {
5595+
jumpToTop();
56015596
}
56025597
}
56035598
}
@@ -5610,11 +5605,13 @@ void InnerWidget::saveChatsFilterScrollState(FilterId filterId) {
56105605
_chatsFilterScrollStates[filterId] = -y();
56115606
}
56125607

5613-
void InnerWidget::restoreChatsFilterScrollState(FilterId filterId) {
5608+
bool InnerWidget::restoreChatsFilterScrollState(FilterId filterId) {
56145609
const auto it = _chatsFilterScrollStates.find(filterId);
5615-
if (it != end(_chatsFilterScrollStates)) {
5616-
_mustScrollTo.fire({ std::max(it->second, 0), -1 });
5610+
if (it == end(_chatsFilterScrollStates)) {
5611+
return false;
56175612
}
5613+
_mustScrollTo.fire({ std::max(it->second, 0), -1 });
5614+
return true;
56185615
}
56195616

56205617
QImage *InnerWidget::cacheChatsFilterTag(

Telegram/SourceFiles/dialogs/dialogs_inner_widget.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -147,6 +147,7 @@ class InnerWidget final : public Ui::RpWidget {
147147
void peerSearchReceived(Api::PeerSearchResult result);
148148

149149
[[nodiscard]] FilterId filterId() const;
150+
void switchToFilter(FilterId filterId);
150151

151152
void clearSelection();
152153

@@ -340,7 +341,6 @@ class InnerWidget final : public Ui::RpWidget {
340341
void refreshWithCollapsedRows(bool toTop = false);
341342
bool needCollapsedRowsRefresh() const;
342343
bool chooseCollapsedRow(Qt::KeyboardModifiers modifiers);
343-
void switchToFilter(FilterId filterId);
344344
bool chooseHashtag();
345345
ChosenRow computeChosenRow() const;
346346
bool isRowActive(not_null<Row*> row, const RowDescriptor &entry) const;
@@ -609,7 +609,7 @@ class InnerWidget final : public Ui::RpWidget {
609609
[[nodiscard]] bool hasChatTypeFilter() const;
610610

611611
void saveChatsFilterScrollState(FilterId filterId);
612-
void restoreChatsFilterScrollState(FilterId filterId);
612+
bool restoreChatsFilterScrollState(FilterId filterId);
613613

614614
[[nodiscard]] not_null<Ui::QuickActionContext*> ensureQuickAction(
615615
int64 key);

Telegram/SourceFiles/dialogs/dialogs_widget.cpp

Lines changed: 92 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ For license and copyright information please follow this link:
4141
#include "ui/wrap/vertical_layout.h"
4242
#include "ui/effects/radial_animation.h"
4343
#include "ui/effects/ripple_animation.h"
44+
#include "ui/effects/slide_animation.h"
4445
#include "ui/chat/requests_bar.h"
4546
#include "ui/chat/group_call_bar.h"
4647
#include "ui/chat/more_chats_bar.h"
@@ -447,6 +448,10 @@ Widget::Widget(
447448
_childListPeerId.value(),
448449
_childListShown.value(),
449450
makeChildListShown)));
451+
controller->activeChatsFilter(
452+
) | rpl::on_next([=](FilterId id) {
453+
switchToChatsFilter(id);
454+
}, lifetime());
450455
rpl::combine(
451456
_scroll->heightValue(),
452457
_topBarSuggestionHeightChanged.events_starting_with(0)
@@ -953,7 +958,9 @@ void Widget::setupSwipeBack() {
953958
if (CheckAndJumpToNearChatsFilter(controller(), next, false)) {
954959
return Ui::Controls::DefaultSwipeBackHandlerFinishData([=] {
955960
_swipeBackData = {};
961+
_chatsFilterSwipeSwitch = true;
956962
CheckAndJumpToNearChatsFilter(controller(), next, true);
963+
_chatsFilterSwipeSwitch = false;
957964
});
958965
}
959966
}
@@ -2052,9 +2059,10 @@ void Widget::toggleFiltersMenu(bool enabled) {
20522059
_chatFilters.get(),
20532060
&session(),
20542061
[this](FilterId id) {
2055-
_scroll->scrollToY(0);
20562062
if (controller()->activeChatsFilterCurrent() != id) {
20572063
controller()->setActiveChatsFilter(id);
2064+
} else {
2065+
_scroll->scrollToY(0);
20582066
}
20592067
},
20602068
Window::GifPauseReason::Any,
@@ -2246,6 +2254,7 @@ void Widget::changeOpenedSubsection(
22462254
if (isHidden()) {
22472255
animated = anim::type::instant;
22482256
}
2257+
_chatsFilterSlideCanvas = nullptr;
22492258
auto oldContentCache = QPixmap();
22502259
const auto showDirection = fromRight
22512260
? Window::SlideDirection::FromRight
@@ -2519,6 +2528,84 @@ void Widget::showSearchInTopBar(anim::type animated) {
25192528
updateForceDisplayWide();
25202529
}
25212530

2531+
void Widget::switchToChatsFilter(FilterId id) {
2532+
const auto was = _inner->filterId();
2533+
const auto animated = (was != id)
2534+
&& !isHidden()
2535+
&& !_showAnimation
2536+
&& (_chatsFilterSwipeSwitch
2537+
|| (_chatFilters && !_chatFilters->isHidden()));
2538+
if (!animated) {
2539+
_inner->switchToFilter(id);
2540+
return;
2541+
}
2542+
const auto &list = session().data().chatsFilters().list();
2543+
const auto indexOf = [&](FilterId filterId) {
2544+
return int(ranges::find(list, filterId, &Data::ChatFilter::id)
2545+
- begin(list));
2546+
};
2547+
const auto slideLeft = (indexOf(id) < indexOf(was));
2548+
const auto duration = _chatsFilterSwipeSwitch
2549+
? st::dialogsFilterSwipeSlideDuration
2550+
: st::slideDuration;
2551+
_chatsFilterSlideCanvas = nullptr;
2552+
auto wasCache = grabForChatsFilterSlide();
2553+
_inner->switchToFilter(id);
2554+
if (_inner->filterId() == was) {
2555+
return;
2556+
}
2557+
startChatsFilterSlide(
2558+
std::move(wasCache),
2559+
grabForChatsFilterSlide(),
2560+
slideLeft,
2561+
duration);
2562+
}
2563+
2564+
QPixmap Widget::grabForChatsFilterSlide() {
2565+
const auto hidden = _scrollToTop->isHidden();
2566+
if (!hidden) {
2567+
_scrollToTop->hide();
2568+
}
2569+
auto result = Ui::GrabOpaque(
2570+
_scroll.data(),
2571+
_scroll->rect(),
2572+
st::dialogsBg->c);
2573+
if (!hidden) {
2574+
_scrollToTop->show();
2575+
}
2576+
return result;
2577+
}
2578+
2579+
void Widget::startChatsFilterSlide(
2580+
QPixmap wasCache,
2581+
QPixmap nowCache,
2582+
bool slideLeft,
2583+
crl::time duration) {
2584+
_chatsFilterSlideCanvas = std::make_unique<Ui::RpWidget>(this);
2585+
const auto canvas = _chatsFilterSlideCanvas.get();
2586+
canvas->setAttribute(Qt::WA_TransparentForMouseEvents);
2587+
canvas->setAttribute(Qt::WA_OpaquePaintEvent);
2588+
canvas->setGeometry(_scroll->geometry());
2589+
const auto animation
2590+
= canvas->lifetime().make_state<Ui::SlideAnimation>();
2591+
animation->setSnapshots(std::move(wasCache), std::move(nowCache));
2592+
canvas->paintOn([=](QPainter &p) {
2593+
p.fillRect(canvas->rect(), st::dialogsBg);
2594+
animation->paintFrame(p, 0, 0, canvas->width());
2595+
});
2596+
canvas->show();
2597+
if (_connecting) {
2598+
_connecting->raise();
2599+
}
2600+
animation->start(slideLeft, [=] {
2601+
if (animation->animating()) {
2602+
canvas->update();
2603+
} else {
2604+
_chatsFilterSlideCanvas = nullptr;
2605+
}
2606+
}, duration);
2607+
}
2608+
25222609
QPixmap Widget::grabForFolderSlideAnimation() {
25232610
const auto hidden = _scrollToTop->isHidden();
25242611
if (!hidden) {
@@ -2832,6 +2919,7 @@ void Widget::showAnimated(
28322919
Window::SlideDirection direction,
28332920
const Window::SectionSlideParams &params) {
28342921
_showAnimation = nullptr;
2922+
_chatsFilterSlideCanvas = nullptr;
28352923

28362924
auto oldContentCache = params.oldContentCache;
28372925
showFast();
@@ -4607,6 +4695,9 @@ void Widget::updateControlsGeometry() {
46074695
const auto scrollHeight = height() - scrollTop - bottomSkip;
46084696
const auto wasScrollHeight = _scroll->height();
46094697
_scroll->setGeometry(0, scrollTop, scrollWidth, scrollHeight);
4698+
if (_chatsFilterSlideCanvas) {
4699+
_chatsFilterSlideCanvas->setGeometry(_scroll->geometry());
4700+
}
46104701
if (scrollHeight != wasScrollHeight) {
46114702
controller()->floatPlayerAreaUpdated();
46124703
}

Telegram/SourceFiles/dialogs/dialogs_widget.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -212,6 +212,13 @@ class Widget final : public Window::AbstractSectionWidget {
212212
void setupConnectingWidget();
213213
void setupMainMenuToggle();
214214
void setupMoreChatsBar();
215+
void switchToChatsFilter(FilterId id);
216+
[[nodiscard]] QPixmap grabForChatsFilterSlide();
217+
void startChatsFilterSlide(
218+
QPixmap wasCache,
219+
QPixmap nowCache,
220+
bool slideLeft,
221+
crl::time duration);
215222
void setupDownloadBar();
216223
void setupShortcuts();
217224
void setupStories();
@@ -428,6 +435,7 @@ class Widget final : public Window::AbstractSectionWidget {
428435
bool _searchQueryFromArchive = true;
429436

430437
Ui::Controls::SwipeBackResult _swipeBackData;
438+
bool _chatsFilterSwipeSwitch = false;
431439
bool _swipeBackMirrored = false;
432440
bool _swipeBackIconMirrored = false;
433441

@@ -448,6 +456,7 @@ class Widget final : public Window::AbstractSectionWidget {
448456
rpl::variable<float64> _childListShown;
449457
rpl::variable<PeerId> _childListPeerId;
450458
std::unique_ptr<Ui::RpWidget> _hideChildListCanvas;
459+
std::unique_ptr<Ui::RpWidget> _chatsFilterSlideCanvas;
451460

452461
};
453462

0 commit comments

Comments
 (0)