diff --git a/packages/vkui/src/components/View/View.test.tsx b/packages/vkui/src/components/View/View.test.tsx
index e279d5ffcd..5ad9b598d8 100644
--- a/packages/vkui/src/components/View/View.test.tsx
+++ b/packages/vkui/src/components/View/View.test.tsx
@@ -249,7 +249,8 @@ describe('View', () => {
expect(document.getElementById('p1')).toBeTruthy();
expect(document.getElementById('p2')).toBeNull();
});
- it('restores scroll after swipeBack', () => {
+
+ it('restores scroll after cancelled swipeBack (mouse up during the move)', () => {
let y = 101;
scrollsCache['scroll']['p1'] = 22;
const [MockScroll, scrollTo] = mockScrollContext(() => y);
@@ -262,7 +263,21 @@ describe('View', () => {
});
fireEvent.mouseUp(view);
rerender();
- expect(scrollTo).toBeCalledWith(0, 22);
+ expect(scrollTo).toHaveBeenCalledWith(0, 22);
+ });
+
+ it('restores scroll when swipeBack cancelled because user moves panel back to starting point', () => {
+ const currentScrollPosition = 22;
+ const startPosition = { clientX: 0, clientY: 100 };
+ const [MockScroll, scrollTo] = mockScrollContext(() => currentScrollPosition);
+ const { view, rerender, SwipeBack } = setupSwipeBack({ Wrapper: MockScroll });
+ fireEvent.mouseDown(view, startPosition);
+ fireEvent.mouseMove(view, { clientX: SWIPE_BACK_SHIFT_THRESHOLD, clientY: 100 });
+ fireEvent.mouseMove(view, startPosition);
+ fireEvent.mouseUp(view);
+
+ rerender();
+ expect(scrollTo).toHaveBeenCalledWith(0, currentScrollPosition);
});
describe('horizontal scrollable elements', () => {
diff --git a/packages/vkui/src/components/View/View.tsx b/packages/vkui/src/components/View/View.tsx
index 2ee5b871f0..37b644c266 100644
--- a/packages/vkui/src/components/View/View.tsx
+++ b/packages/vkui/src/components/View/View.tsx
@@ -113,6 +113,7 @@ export const View = ({
const prevSwipingBack = usePrevious(swipingBack);
const prevBrowserSwipe = usePrevious(browserSwipe);
const prevSwipeBackResult = usePrevious(swipeBackResult);
+ const prevSwipeBackShift = usePrevious(swipeBackShift);
const prevSwipeBackPrevPanel = usePrevious(swipeBackPrevPanel);
const prevOnTransition = usePrevious(onTransition);
@@ -439,11 +440,6 @@ export const View = ({
);
}
- // Если свайп назад отменился (когда пользователь недостаточно сильно свайпнул)
- if (prevSwipeBackResult === 'fail' && !swipeBackResult && activePanel !== null) {
- scroll?.scrollTo(0, scrolls.current[activePanel]);
- }
-
// Закончился Safari свайп
if (prevActivePanel !== activePanelProp && browserSwipe) {
setBrowserSwipe(false);
@@ -476,6 +472,33 @@ export const View = ({
waitTransitionFinish,
]);
+ React.useEffect(
+ function restoreScrollPositionWhenSwipeBackIsCancelled() {
+ // Если свайп назад отменился (когда пользователь недостаточно сильно свайпнул)
+ const swipeBackCancelledInTheMiddleOfAction =
+ prevSwipeBackResult === 'fail' && !swipeBackResult;
+ const swipeBackCancelledByMovingPanelBackToInitialPoint =
+ prevSwipingBack && !swipingBack && prevSwipeBackShift === 0;
+
+ if (
+ (swipeBackCancelledInTheMiddleOfAction ||
+ swipeBackCancelledByMovingPanelBackToInitialPoint) &&
+ activePanel !== null
+ ) {
+ scroll?.scrollTo(0, scrolls.current[activePanel]);
+ }
+ },
+ [
+ prevSwipeBackResult,
+ swipeBackResult,
+ prevSwipingBack,
+ swipingBack,
+ prevSwipeBackShift,
+ activePanel,
+ scroll,
+ ],
+ );
+
return (