mirror of
https://github.com/AyuGram/AyuGramDesktop.git
synced 2026-08-06 11:52:58 +00:00
[thanos] Stabilized collapse animation for bulk deletions.
This commit is contained in:
@@ -4306,6 +4306,15 @@ bool HistoryInner::focusNextPrevChild(bool next) {
|
||||
}
|
||||
|
||||
void HistoryInner::adjustCurrent(int32 y) const {
|
||||
auto gapShift = 0;
|
||||
for (const auto &gap : _collapseGaps) {
|
||||
if (y < gap.absY + gapShift) {
|
||||
break;
|
||||
}
|
||||
gapShift += gap.height;
|
||||
}
|
||||
y -= gapShift;
|
||||
|
||||
int32 htop = historyTop(), hdrawtop = historyDrawTop(), mtop = migratedTop();
|
||||
_curHistory = nullptr;
|
||||
if (mtop >= 0) {
|
||||
|
||||
@@ -2870,6 +2870,15 @@ TextSelection ListWidget::getSelectedTextRange(
|
||||
int ListWidget::findItemIndexByY(int y) const {
|
||||
Expects(!_items.empty());
|
||||
|
||||
auto gapShift = 0;
|
||||
for (const auto &gap : _collapseGaps) {
|
||||
if (y < gap.absY + gapShift) {
|
||||
break;
|
||||
}
|
||||
gapShift += gap.height;
|
||||
}
|
||||
y -= gapShift;
|
||||
|
||||
if (y < _itemsTop) {
|
||||
return 0;
|
||||
}
|
||||
@@ -2891,7 +2900,11 @@ Element *ListWidget::strictFindItemByY(int y) const {
|
||||
if (_items.empty()) {
|
||||
return nullptr;
|
||||
}
|
||||
return (y >= _itemsTop && y < _itemsTop + _itemsHeight)
|
||||
auto gapTotal = 0;
|
||||
for (const auto &gap : _collapseGaps) {
|
||||
gapTotal += gap.height;
|
||||
}
|
||||
return (y >= _itemsTop && y < _itemsTop + _itemsHeight + gapTotal)
|
||||
? findItemByY(y).get()
|
||||
: nullptr;
|
||||
}
|
||||
|
||||
@@ -21,8 +21,8 @@ namespace Ui {
|
||||
namespace {
|
||||
|
||||
constexpr auto kBaseMs = 400;
|
||||
constexpr auto kPerPixelMs = 0.5;
|
||||
constexpr auto kMaxMs = 1200;
|
||||
constexpr auto kPerPixelMs = 0.15;
|
||||
constexpr auto kMaxMs = 600;
|
||||
|
||||
} // namespace
|
||||
|
||||
@@ -36,6 +36,15 @@ ThanosEffectController::ThanosEffectController(
|
||||
) | rpl::on_next([=](const auto &items) {
|
||||
captureItemsBatch(items);
|
||||
}, lifetime);
|
||||
|
||||
_session->data().historyChanged(
|
||||
) | rpl::on_next([=](not_null<History*> history) {
|
||||
if (_restoreScrollPending && history == _capturedHistory) {
|
||||
_restoreScrollPending = false;
|
||||
_capturedHistory = nullptr;
|
||||
_delegate.scrollToY(_savedScrollTop);
|
||||
}
|
||||
}, lifetime);
|
||||
}
|
||||
|
||||
ThanosEffectController::~ThanosEffectController() = default;
|
||||
@@ -45,10 +54,21 @@ void ThanosEffectController::captureItemsBatch(
|
||||
if (!ThanosEffect::Supported()) {
|
||||
return;
|
||||
}
|
||||
_suppressCollapseAnimation = true;
|
||||
const auto guard = gsl::finally([&] {
|
||||
_suppressCollapseAnimation = false;
|
||||
});
|
||||
auto firstHistory = (History*)nullptr;
|
||||
for (const auto &item : items) {
|
||||
if (_delegate.viewForItem(item)) {
|
||||
firstHistory = item->history();
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!firstHistory) {
|
||||
return;
|
||||
}
|
||||
if (!_restoreScrollPending) {
|
||||
_capturedHistory = firstHistory;
|
||||
_savedScrollTop = _delegate.scrollArea()->scrollTop();
|
||||
_restoreScrollPending = true;
|
||||
}
|
||||
for (const auto &item : items) {
|
||||
if (const auto view = _delegate.viewForItem(item)) {
|
||||
const auto top = _delegate.itemTop(view);
|
||||
@@ -226,12 +246,6 @@ void ThanosEffectController::startCollapseAnimation(
|
||||
|
||||
syncCollapseGapsToHost();
|
||||
|
||||
const auto aboveViewport = std::max(0, scrollTop - itemTop);
|
||||
const auto scrollAdjust = std::min(height, aboveViewport);
|
||||
if (scrollAdjust > 0) {
|
||||
_delegate.scrollToY(scrollTop + scrollAdjust);
|
||||
}
|
||||
|
||||
auto totalHeight = 0;
|
||||
for (const auto &gap : _collapseGaps) {
|
||||
totalHeight += gap.currentHeight;
|
||||
@@ -246,7 +260,7 @@ void ThanosEffectController::startCollapseAnimation(
|
||||
0.,
|
||||
1.,
|
||||
duration,
|
||||
anim::easeOutCirc);
|
||||
anim::halfSine);
|
||||
}
|
||||
|
||||
void ThanosEffectController::collapseAnimationCallback() {
|
||||
|
||||
@@ -24,6 +24,7 @@ namespace HistoryView {
|
||||
class Element;
|
||||
} // namespace HistoryView
|
||||
|
||||
class History;
|
||||
class HistoryItem;
|
||||
|
||||
namespace Ui {
|
||||
@@ -93,11 +94,14 @@ private:
|
||||
base::flat_map<
|
||||
not_null<const HistoryView::Element*>,
|
||||
PreCapturedView> _preCaptured;
|
||||
bool _suppressCollapseAnimation = false;
|
||||
std::vector<CollapseGap> _renderGaps;
|
||||
|
||||
std::vector<CollapseGapState> _collapseGaps;
|
||||
Animations::Simple _collapseAnimation;
|
||||
|
||||
History *_capturedHistory = nullptr;
|
||||
int _savedScrollTop = 0;
|
||||
bool _restoreScrollPending = false;
|
||||
};
|
||||
|
||||
} // namespace Ui
|
||||
|
||||
Reference in New Issue
Block a user