From f0c8e48403e42af1d3bddb61cbb682880acf50e3 Mon Sep 17 00:00:00 2001 From: 23rd <23rd@vivaldi.net> Date: Wed, 19 Feb 2025 22:29:09 +0300 Subject: [PATCH] Added ability to keep ratio of swipe within range. --- .../SourceFiles/ui/controls/swipe_handler.cpp | 46 ++++++++++++++++--- .../SourceFiles/ui/controls/swipe_handler.h | 1 + 2 files changed, 41 insertions(+), 6 deletions(-) diff --git a/Telegram/SourceFiles/ui/controls/swipe_handler.cpp b/Telegram/SourceFiles/ui/controls/swipe_handler.cpp index e21f07f53e..654399fc53 100644 --- a/Telegram/SourceFiles/ui/controls/swipe_handler.cpp +++ b/Telegram/SourceFiles/ui/controls/swipe_handler.cpp @@ -30,6 +30,33 @@ constexpr auto kSwipeSlow = 0.2; constexpr auto kMsgBareIdSwipeBack = std::numeric_limits::max() - 77; constexpr auto kSwipedBackSpeedRatio = 0.35; +float64 InterpolationRatio(float64 from, float64 to, float64 result) { + return (result - from) / (to - from); +}; + +class RatioRange final { +public: + [[nodiscard]] float64 calcRatio(float64 value) { + if (value < _min) { + const auto shift = _min - value; + _min -= shift; + _max -= shift; + _max = _min + 1; + } else if (value > _max) { + const auto shift = value - _max; + _min += shift; + _max += shift; + _max = _min + 1; + } + return InterpolationRatio(_min, _max, value); + } + +private: + float64 _min = 0; + float64 _max = 1; + +}; + } // namespace void SetupSwipeHandler( @@ -55,6 +82,7 @@ void SetupSwipeHandler( std::optional orientation; std::optional direction; float64 threshold = style::ConvertFloatScale(kThresholdWidth); + RatioRange ratioRange; int directionInt = 1.; QPointF startAt; QPointF delta; @@ -103,10 +131,13 @@ void SetupSwipeHandler( }; const auto processEnd = [=](std::optional delta = {}) { if (state->orientation == Qt::Horizontal) { + const auto rawRatio = delta.value_or(state->delta).x() + / state->threshold + * state->directionInt; const auto ratio = std::clamp( - delta.value_or(state->delta).x() - / state->threshold - * state->directionInt, + state->finishByTopData.keepRatioWithinRange + ? state->ratioRange.calcRatio(rawRatio) + : rawRatio, 0., kMaxRatio); if ((ratio >= 1) && state->finishByTopData.callback) { @@ -183,9 +214,11 @@ void SetupSwipeHandler( } } else if (*state->orientation == Qt::Horizontal) { state->delta = args.delta; - const auto ratio = args.delta.x() - * state->directionInt - / state->threshold; + const auto rawRatio = 0 + + args.delta.x() * state->directionInt / state->threshold; + const auto ratio = state->finishByTopData.keepRatioWithinRange + ? state->ratioRange.calcRatio(rawRatio) + : rawRatio; updateRatio(ratio); constexpr auto kResetReachedOn = 0.95; constexpr auto kBounceDuration = crl::time(500); @@ -435,6 +468,7 @@ SwipeHandlerFinishData DefaultSwipeBackHandlerFinishData( .callback = std::move(callback), .msgBareId = kMsgBareIdSwipeBack, .speedRatio = kSwipedBackSpeedRatio, + .keepRatioWithinRange = true, }; } diff --git a/Telegram/SourceFiles/ui/controls/swipe_handler.h b/Telegram/SourceFiles/ui/controls/swipe_handler.h index ac3f5f014b..7c5e3ff20f 100644 --- a/Telegram/SourceFiles/ui/controls/swipe_handler.h +++ b/Telegram/SourceFiles/ui/controls/swipe_handler.h @@ -22,6 +22,7 @@ struct SwipeHandlerFinishData { Fn callback; int64 msgBareId = 0; float64 speedRatio = 1.0; + bool keepRatioWithinRange = false; }; using Scroll = std::variant<