Skip to content
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

Fix scrolling when we change LazyListState #769

Merged
merged 2 commits into from
Aug 24, 2023

Conversation

igordmn
Copy link
Collaborator

@igordmn igordmn commented Aug 23, 2023

Fixes JetBrains/compose-multiplatform#3551

When the new state is passed to LazyList, it goes down to Modifier.pointerScrollable as controller: ScrollableState, and wraps to rememberUpdatedState, which is always the same instance. Because it is the same instance, MouseWheelScrollableElement.update is never called.

Passing it is as a value now, as MouseWheelScrollableElement doesn't need a state.

Testing

  • Run SkikoScrollableTest
  • Run the snippet from the issue

Fixes JetBrains/compose-multiplatform#3551

When the new state is passed to LazyList, it goes down to `Modifier.pointerScrollable` as `controller: ScrollableState`, and wraps to `rememberUpdatedState`, which is always the same instance. Because it is the same instance, MouseWheelScrollableElement.update is never called.

Passing it is as a value now, as MouseWheelScrollableElement doesn't need a state.
@igordmn igordmn force-pushed the igor.demin/fix-recreating-list-state-scrolling branch from e2ad8fe to e665cce Compare August 23, 2023 18:04
@igordmn igordmn requested a review from eymar August 23, 2023 18:04
It seems there is test that checks equality of the modifier across compositions. Probably for optimization.

Remembering scrolling logic seems logical here, and shouldn't add overhead.

In 1.6 it was fully rewritten to modifier node:

https://github.com/androidx/androidx/blob/a7e6bdf524be186baca08e9ddf7272b834a14bd2/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/gestures/Scrollable.kt#L276
.nestedScroll(nestedScrollConnection, nestedScrollDispatcher.value)
}

// {} isn't being memoized for us, so extract this to make sure we compare equally on recomposition.
private val NoOpOnDragStarted: suspend CoroutineScope.(startedPosition: Offset) -> Unit = {}

@Composable
private fun rememberScrollingLogic(
Copy link
Collaborator Author

@igordmn igordmn Aug 23, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It seems there is test that checks equality of the modifier across compositions. Probably for optimization. remember fixes the test.

Remembering scrolling logic seems logical here, and shouldn't add overhead.

In 1.6 it was fully rewritten to modifier node:

https://github.com/androidx/androidx/blob/a7e6bdf524be186baca08e9ddf7272b834a14bd2/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/gestures/Scrollable.kt#L276

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

which test was failing before adding rememberScrollingLogic ?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Collaborator

@eymar eymar left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM. The tests passed on my machine too.

@igordmn igordmn merged commit db4f869 into jb-main Aug 24, 2023
3 checks passed
@igordmn igordmn deleted the igor.demin/fix-recreating-list-state-scrolling branch August 24, 2023 11:31
igordmn added a commit that referenced this pull request Aug 24, 2023
* Fix scrolling when we change LazyListState

Fixes JetBrains/compose-multiplatform#3551

When the new state is passed to LazyList, it goes down to `Modifier.pointerScrollable` as `controller: ScrollableState`, and wraps to `rememberUpdatedState`, which is always the same instance. Because it is the same instance, MouseWheelScrollableElement.update is never called.

Passing it is as a value now, as MouseWheelScrollableElement doesn't need a state.

* Remember ScrollingLogic

It seems there is test that checks equality of the modifier across compositions. Probably for optimization.

Remembering scrolling logic seems logical here, and shouldn't add overhead.

In 1.6 it was fully rewritten to modifier node:

https://github.com/androidx/androidx/blob/a7e6bdf524be186baca08e9ddf7272b834a14bd2/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/gestures/Scrollable.kt#L276
igordmn added a commit that referenced this pull request Nov 15, 2023
* Fix scrolling when we change LazyListState

Fixes JetBrains/compose-multiplatform#3551

When the new state is passed to LazyList, it goes down to `Modifier.pointerScrollable` as `controller: ScrollableState`, and wraps to `rememberUpdatedState`, which is always the same instance. Because it is the same instance, MouseWheelScrollableElement.update is never called.

Passing it is as a value now, as MouseWheelScrollableElement doesn't need a state.

* Remember ScrollingLogic

It seems there is test that checks equality of the modifier across compositions. Probably for optimization.

Remembering scrolling logic seems logical here, and shouldn't add overhead.

In 1.6 it was fully rewritten to modifier node:

https://github.com/androidx/androidx/blob/a7e6bdf524be186baca08e9ddf7272b834a14bd2/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/gestures/Scrollable.kt#L276
igordmn pushed a commit that referenced this pull request Nov 16, 2023
* Set scroll progress state on mouse events

* Animate mouse wheel scroll

* Refactor changes

* Add helper inline functions

* Batch offsets

* Filter zero values and apply raw delta only without animation

* Use scrollBy inside animation, fix parameter usage in lambda

* Fix tests

* Add TODOs and comments

* Fix more tests

* Cleanup mouse hover test helper class

* Add test for scroll during animation

* Address feedback (part 1)

* Make smooth scrolling configurable

* Do not animate scroll on events from trackpads

* Fix internal type for tests

* Make animation scrolling speed density dependant

* Fix conditionally applying scroll modifier

* Fix cancel animation condition

* Cache smooth scrolling flag

* Adjust scrolling animation threshold

* Add isScrollInProgress TODO

* Add test for isSmoothScrollingEnabled flag

* Reset flag in finally

* Use strict comparison to detect consuming event

mouse [bugfix, hard] foundation. mouse. Fix missing scrolling events (#527)

* Move awaitPointerEventScope outside the loop

* Add test for multi-event regression

mouse [bugfix, simple] foundation. mouse. Handle scroll cancellation exception (#696)

* Catch scroll cancellation exception

* Fix demo

mouse [feature, hard] foundation. mouse. Fix scrolling when we change LazyListState (#769)

* Fix scrolling when we change LazyListState

Fixes JetBrains/compose-multiplatform#3551

When the new state is passed to LazyList, it goes down to `Modifier.pointerScrollable` as `controller: ScrollableState`, and wraps to `rememberUpdatedState`, which is always the same instance. Because it is the same instance, MouseWheelScrollableElement.update is never called.

Passing it is as a value now, as MouseWheelScrollableElement doesn't need a state.

* Remember ScrollingLogic

It seems there is test that checks equality of the modifier across compositions. Probably for optimization.

Remembering scrolling logic seems logical here, and shouldn't add overhead.

In 1.6 it was fully rewritten to modifier node:

https://github.com/androidx/androidx/blob/a7e6bdf524be186baca08e9ddf7272b834a14bd2/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/gestures/Scrollable.kt#L276

mouse [bugfix, simple] foundation. mouse. Take into account `enabled` in `scrollable` for mouse input (#880)

Fixes JetBrains/compose-multiplatform#3816

## Testing
1. The new test
2. Manual testing of `Modifier.verticalScroll(enabled = false`
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
2 participants