-
Notifications
You must be signed in to change notification settings - Fork 185
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat(View): increase swipe back zone #5725
feat(View): increase swipe back zone #5725
Conversation
This pull request is automatically built and testable in CodeSandbox. To see build info of the built libraries, click here or the icon next to each commit SHA. Latest deployment of this branch, based on commit 03ad12c:
|
size-limit report 📦
|
e2e tests |
👀 Docs deployed
Commit 03ad12c |
Codecov ReportPatch coverage:
Additional details and impacted files@@ Coverage Diff @@
## master #5725 +/- ##
==========================================
+ Coverage 81.99% 82.20% +0.21%
==========================================
Files 298 298
Lines 9839 9865 +26
Branches 3115 3118 +3
==========================================
+ Hits 8067 8110 +43
+ Misses 1772 1755 -17
Flags with carried forward coverage won't be shown. Click here to find out more.
☔ View full report in Codecov by Sentry. |
Круто! @inomdzhon А с горизонтальными скроллбарами проверил?
|
1562253
to
78d920a
Compare
Ой .... только сейчас заметил коммент 😰 Угу, как раз перевёл в драфт, чтобы поправить горизотныльный скролл и Gallery) Спасибо за замечание 🙏 |
31c78f6
to
d81d5a1
Compare
d81d5a1
to
b38f3b2
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Отличная работа! 🥇
Тесты хороши 👍
Увеличил зону срабатывания свайпа назад, тем самым приблизив поведение к нативным приложениям. В частности, как в приложении ВКонтакте на iOS.
b38f3b2
to
03ad12c
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
✨
Увеличил зону срабатывания свайпа назад, тем самым приблизив поведение к нативным приложениям. В частности, как в приложении ВКонтакте на iOS. > **Note** > > Для `ViewInfitnite` повторил всё, что для `View`. h.2 Побочные изменения > Спасибо @shevchux и @mendrew за замечания ❤️ Иначе пропустил бы эти кейсы) Во-первых, немного пошатал тесты. Во-вторых, оптимизировал код: убрал из зависимостей `useEffect` лишнее; состояние `swipeBackPrevented` теперь храню в `useRef` вместо `useState`. Во-третьих, поправил следующие кейсы: h.3 Кейс 1. Элементы с горизонтальным скроллом. Добавил обнаружение смещения горизонтального скролла (в частности необходимо для `HorizontallScroll`), чтобы предотвращать свайп бек если пользователей взаимодействует с элементами, у которых есть горизонтальный скролл. Свайп бек включается: - либо если положение скролла находится в начале, иначе свайп бэк игнорируется. Если мы проскролили к началу, то нам необходимо отжать палец и заново синицировать свайп бэк, чтобы он сработал; - либо если потянули за край экрана слева (спасибо, @shevchux за предложение). > Вдохновился поведением у приложения ВКонтакте на iOS. > Использую состояние `swipeBackPrevented`, чтобы вызывать функцию обнаружения только один раз во время начала жеста. Чтобы получить родителей со скроллом, применяю утилиту [getOverflowAncestors()](https://github.com/floating-ui/floating-ui/blob/%40floating-ui/react-dom%402.0.2/packages/utils/test/getOverflowAncestors.test.ts) из бибилотеки Floating UI. h.3 Кейс 2. Компонент [Gallery](https://vkcom.github.io/VKUI/5.7.2/#/Gallery). Добавил `stopPropagation()` на `onDragStart` для `Gallery`, чтобы предотвращать свайп бэк.
Мы очень хитро восстанавливаем позицию скролла, надеясь на то, что это всегда будет работать в useEffect, который сработает перед обработкой события transition (перед завершением анимации), где окончательно сбросятся все состояния. Но в случае, если пользователь вернул панель назад, мы просто сбрасываем состояние компонента, отвечающее, за свайп. Логика, отвечающая за восстановление скролла не срабатывает, потому что это не считается как `failure`. Вот тут мы решаем `swipeBack` был успешным (`success`), был отменён (`fail`), то есть свайп не закончен, либо это вообще не считается свайпом, потому что панель по завершении жеста осталась на той же позиции. https://github.com/VKCOM/VKUI/blob/a4719b49f887c2584eec6655d72e373e62409c59/packages/vkui/src/components/View/View.tsx#L301-L316 Если это не свайп вовсе (пользователь вернул панель на место), то мы просто сбрасываем состояние свайпа с помощью функции `onSwipeBackCancel`. Но в такой ситуации не сработает условие для восстановления скролла при отмене свайпа. https://github.com/VKCOM/VKUI/blob/8dbb1de9855af8c772abcb719848175654e39a8a/src/components/View/View.tsx#L494-L500 - caused by #5725 -- Изменения Вынес логику по восстановлению скролла при отмене свайпа в отдельный useEffect, потому что изначальный слишком большой. Смотрю на переменные `prevSwipingBack`, `swipingBack`, чтобы понять был ли всё же свайп, потому что `swipeBackResult` нам ни о чем не скажет, даже если бы мы его устанавливали, то он не был бы тут же очищен в том же рендере из-за вызова `onSwipeBackCancel`. Также проверяю `prevSwipeBackShift`, который равен нулю, то есть смещения после жеста у панели нет, что значит, что пользователь жестом свайпа вернул панель туда откуда взял.
Cherry-picked из v6. Мы очень хитро восстанавливаем позицию скролла, надеясь на то, что это всегда будет работать в useEffect, который сработает перед обработкой события transition (перед завершением анимации), где окончательно сбросятся все состояния. Но в случае, если пользователь вернул панель назад, мы просто сбрасываем состояние компонента, отвечающее, за свайп. Логика, отвечающая за восстановление скролла не срабатывает, потому что это не считается как `failure`. Вот тут мы решаем `swipeBack` был успешным (`success`), был отменён (`fail`), то есть свайп не закончен, либо это вообще не считается свайпом, потому что панель по завершении жеста осталась на той же позиции. https://github.com/VKCOM/VKUI/blob/a4719b49f887c2584eec6655d72e373e62409c59/packages/vkui/src/components/View/View.tsx#L301-L316 Если это не свайп вовсе (пользователь вернул панель на место), то мы просто сбрасываем состояние свайпа с помощью функции `onSwipeBackCancel`. Но в такой ситуации не сработает условие для восстановления скролла при отмене свайпа. https://github.com/VKCOM/VKUI/blob/8dbb1de9855af8c772abcb719848175654e39a8a/src/components/View/View.tsx#L494-L500 - caused by #5725 -- Изменения Вынес логику по восстановлению скролла при отмене свайпа в отдельный useEffect, потому что изначальный слишком большой. Смотрю на переменные `prevSwipingBack`, `swipingBack`, чтобы понять был ли всё же свайп, потому что `swipeBackResult` нам ни о чем не скажет, даже если бы мы его устанавливали, то он не был бы тут же очищен в том же рендере из-за вызова `onSwipeBackCancel`. Также проверяю `prevSwipeBackShift`, который равен нулю, то есть смещения после жеста у панели нет, что значит, что пользователь жестом свайпа вернул панель туда откуда взял.
Cherry-picked из v6. Мы очень хитро восстанавливаем позицию скролла, надеясь на то, что это всегда будет работать в useEffect, который сработает перед обработкой события transition (перед завершением анимации), где окончательно сбросятся все состояния. Но в случае, если пользователь вернул панель назад, мы просто сбрасываем состояние компонента, отвечающее, за свайп. Логика, отвечающая за восстановление скролла не срабатывает, потому что это не считается как `failure`. Вот тут мы решаем `swipeBack` был успешным (`success`), был отменён (`fail`), то есть свайп не закончен, либо это вообще не считается свайпом, потому что панель по завершении жеста осталась на той же позиции. https://github.com/VKCOM/VKUI/blob/a4719b49f887c2584eec6655d72e373e62409c59/packages/vkui/src/components/View/View.tsx#L301-L316 Если это не свайп вовсе (пользователь вернул панель на место), то мы просто сбрасываем состояние свайпа с помощью функции `onSwipeBackCancel`. Но в такой ситуации не сработает условие для восстановления скролла при отмене свайпа. https://github.com/VKCOM/VKUI/blob/8dbb1de9855af8c772abcb719848175654e39a8a/src/components/View/View.tsx#L494-L500 - caused by #5725 -- Изменения Вынес логику по восстановлению скролла при отмене свайпа в отдельный useEffect, потому что изначальный слишком большой. Смотрю на переменные `prevSwipingBack`, `swipingBack`, чтобы понять был ли всё же свайп, потому что `swipeBackResult` нам ни о чем не скажет, даже если бы мы его устанавливали, то он не был бы тут же очищен в том же рендере из-за вызова `onSwipeBackCancel`. Также проверяю `prevSwipeBackShift`, который равен нулю, то есть смещения после жеста у панели нет, что значит, что пользователь жестом свайпа вернул панель туда откуда взял.
Cherry-picked из v6. Мы очень хитро восстанавливаем позицию скролла, надеясь на то, что это всегда будет работать в useEffect, который сработает перед обработкой события transition (перед завершением анимации), где окончательно сбросятся все состояния. Но в случае, если пользователь вернул панель назад, мы просто сбрасываем состояние компонента, отвечающее, за свайп. Логика, отвечающая за восстановление скролла не срабатывает, потому что это не считается как `failure`. Вот тут мы решаем `swipeBack` был успешным (`success`), был отменён (`fail`), то есть свайп не закончен, либо это вообще не считается свайпом, потому что панель по завершении жеста осталась на той же позиции. https://github.com/VKCOM/VKUI/blob/a4719b49f887c2584eec6655d72e373e62409c59/packages/vkui/src/components/View/View.tsx#L301-L316 Если это не свайп вовсе (пользователь вернул панель на место), то мы просто сбрасываем состояние свайпа с помощью функции `onSwipeBackCancel`. Но в такой ситуации не сработает условие для восстановления скролла при отмене свайпа. https://github.com/VKCOM/VKUI/blob/8dbb1de9855af8c772abcb719848175654e39a8a/src/components/View/View.tsx#L494-L500 - caused by #5725 -- Изменения Вынес логику по восстановлению скролла при отмене свайпа в отдельный useEffect, потому что изначальный слишком большой. Смотрю на переменные `prevSwipingBack`, `swipingBack`, чтобы понять был ли всё же свайп, потому что `swipeBackResult` нам ни о чем не скажет, даже если бы мы его устанавливали, то он не был бы тут же очищен в том же рендере из-за вызова `onSwipeBackCancel`. Также проверяю `prevSwipeBackShift`, который равен нулю, то есть смещения после жеста у панели нет, что значит, что пользователь жестом свайпа вернул панель туда откуда взял.
Увеличил зону срабатывания свайпа назад, тем самым приблизив поведение к нативным приложениям. В частности, как в приложении ВКонтакте на iOS.
Пример
view-example.mov
Побочные изменения
Во-первых, немного пошатал тесты.
Во-вторых, оптимизировал код: убрал из зависимостей
useEffect
лишнее; состояниеswipeBackPrevented
теперь храню вuseRef
вместоuseState
.Во-третьих, поправил следующие кейсы:
Кейс 1. Элементы с горизонтальным скроллом.
Добавил обнаружение смещения горизонтального скролла (в частности необходимо для
HorizontallScroll
), чтобы предотвращать свайп бек если пользователей взаимодействует с элементами, у которых есть горизонтальный скролл.Свайп бек включается:
Пример
view-horizontall-scroll-example.mov
Кейс 2. Компонент Gallery.
Добавил
stopPropagation()
наonDragStart
дляGallery
, чтобы предотвращать свайп бэк.Пример
view-gallery-example.mov
UPD
Добавил в доки
View
(стайлгайд и сторибук) примеры с кейсами 1 и 2.По замечанию @shevchux, в доке у
CellButton
'ов выставилstopPropagation={false}
, чтобы не путало пользователей. Иначе свайп бэк блокируется.UPD