diff --git a/Telegram/ThirdParty/qtlottie b/Telegram/ThirdParty/qtlottie
index 741b80b10..ff75b08c3 160000
--- a/Telegram/ThirdParty/qtlottie
+++ b/Telegram/ThirdParty/qtlottie
@@ -1 +1 @@
-Subproject commit 741b80b10cf8b2a06ed7dfda1bf9d64896ac0249
+Subproject commit ff75b08c3adabaa33f7f879e12119de8ab1c2153
diff --git a/Telegram/ThirdParty/qtlottie_helper/QtBodymovin/private/bmproperty_p.h b/Telegram/ThirdParty/qtlottie_helper/QtBodymovin/private/bmproperty_p.h
index b51a1e244..9455efe0c 100644
--- a/Telegram/ThirdParty/qtlottie_helper/QtBodymovin/private/bmproperty_p.h
+++ b/Telegram/ThirdParty/qtlottie_helper/QtBodymovin/private/bmproperty_p.h
@@ -71,6 +71,13 @@ struct EasingSegment {
     T endValue;
     BezierEasing easing;
     QPainterPath bezier;
+
+    double bezierLength = 0.;
+    struct BezierPoint {
+        QPointF point;
+        double length = 0.;
+    };
+    std::vector<BezierPoint> bezierPoints;
 };
 
 template<typename T>
diff --git a/Telegram/ThirdParty/qtlottie_helper/QtBodymovin/private/bmspatialproperty_p.h b/Telegram/ThirdParty/qtlottie_helper/QtBodymovin/private/bmspatialproperty_p.h
index 1fe0c849b..b87deb729 100644
--- a/Telegram/ThirdParty/qtlottie_helper/QtBodymovin/private/bmspatialproperty_p.h
+++ b/Telegram/ThirdParty/qtlottie_helper/QtBodymovin/private/bmspatialproperty_p.h
@@ -101,6 +101,20 @@ public:
 
         easing.bezier.moveTo(s);
         easing.bezier.cubicTo(c1, c2, e);
+
+        const auto kCount = 150;
+        easing.bezierPoints.reserve(kCount);
+        for (auto k = 0; k < kCount; ++k) {
+            const auto percent = double(k) / (kCount - 1.);
+            auto point = EasingSegment<QPointF>::BezierPoint();
+            point.point = easing.bezier.pointAtPercent(percent);
+            if (k > 0) {
+                const auto delta = (point.point - easing.bezierPoints[k - 1].point);
+                point.length = std::sqrt(QPointF::dotProduct(delta, delta));
+                easing.bezierLength += point.length;
+            }
+            easing.bezierPoints.push_back(point);
+        }
     }
 
     virtual bool update(int frame) override
@@ -110,18 +124,34 @@ public:
 
         int adjustedFrame = qBound(m_startFrame, frame, m_endFrame);
         if (const EasingSegment<QPointF> *easing = getEasingSegment(adjustedFrame)) {
-			if (easing->state == EasingSegmentState::Complete) {
-				int length = (easing->endFrame - easing->startFrame);
-				qreal progress = (length > 0)
-					? ((adjustedFrame - easing->startFrame) * 1.0) / length
-					: 1.;
-				qreal easedValue = easing->easing.valueForProgress(progress);
-				m_value = easing->bezier.pointAtPercent(easedValue);
-			} else {
-				// In case of incomplete easing we should just take the final point.
-				//m_value = m_bezierPath.pointAtPercent(1.);
-				m_value = easing->endValue;
-			}
+            if (easing->state == EasingSegmentState::Complete) {
+                int length = (easing->endFrame - easing->startFrame);
+                qreal progress = (length > 0)
+                    ? ((adjustedFrame - easing->startFrame) * 1.0) / length
+                    : 1.;
+                qreal easedValue = easing->easing.valueForProgress(progress);
+                //m_value = easing->bezier.pointAtPercent(easedValue);
+
+                const auto distance = easedValue * easing->bezierLength;
+                auto segmentPerc = 0.;
+                auto addedLength = 0.;
+                const auto count = easing->bezierPoints.size();
+                for (auto j = 0; j != count; ++j) {
+                    addedLength += easing->bezierPoints[j].length;
+                    if (distance == 0. || easedValue == 0. || j == count - 1) {
+                        m_value = easing->bezierPoints[j].point;
+                        break;
+                    } else if (distance >= addedLength && distance < addedLength + easing->bezierPoints[j + 1].length) {
+                        segmentPerc = (distance - addedLength) / easing->bezierPoints[j + 1].length;
+                        m_value = easing->bezierPoints[j].point + (easing->bezierPoints[j + 1].point - easing->bezierPoints[j].point) * segmentPerc;
+                        break;
+                    }
+                }
+            } else {
+                // In case of incomplete easing we should just take the final point.
+                //m_value = m_bezierPath.pointAtPercent(1.);
+                m_value = easing->endValue;
+            }
         }
 
         return true;