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

Propagate composition locals to layers in the (re)composition phase #1233

Merged

Conversation

m-sasha
Copy link
Member

@m-sasha m-sasha commented Apr 3, 2024

When the value of a composition local that is provided outside a Popup changes, typically, the order of events is:

  1. The value changes, triggering a recomposition of the function with CompositionLocalProvider.
  2. The function with CompositionLocalProvider is recomposed, modifying the composition local context, which triggers rememberComposeSceneLayer to recompose, as it reads currentCompositionLocalContext.
  3. rememberComposeSceneLayer is recomposed.
  4. The SideEffect in rememberComposeSceneLayer is executed, changing the compositionLocalContext of the layer, which triggers recomposition of the layer (popup) content.
  5. The layer content is recomposed and it sees the updated composition local value.

However, if the layer content is recomposed (for unrelated reasons) in the same frame as rememberComposeSceneLayer, it will read an old value of the composition local.

The question then is why doesn't the layer content recompose again when the SideEffect updates compositionLocalContext. The answer is that MultiLayerComposeScene.compositionLocalContext is not a Compose state.

Proposed Changes

Apply compositionLocalContext, density and layoutDirection to layer immediately in rememberComposeSceneLayer.

Testing

Test: Added a unit test

This PR should be verified by QA.

Issues Fixed

Fixes: JetBrains/compose-multiplatform#4558

@m-sasha m-sasha requested review from MatkovIvan and igordmn April 3, 2024 12:06
Copy link
Collaborator

@igordmn igordmn left a comment

Choose a reason for hiding this comment

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

Lgtm.

Let's wait for Ivan, maybe there were issues with setting these in the composition instead of SideEffect.

Copy link
Collaborator

@igordmn igordmn left a comment

Choose a reason for hiding this comment

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

1924208

After last commit, it is need to be discussed

Mistakenly read the diff

@@ -581,7 +587,14 @@ private class MultiLayerComposeSceneImpl(
composition?.dispose()
composition = owner.setContent(
parent = this@AttachedComposeSceneLayer.compositionContext,
{ this@AttachedComposeSceneLayer.compositionLocalContext }
{
Copy link
Collaborator

Choose a reason for hiding this comment

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

Better to remove this lambda completely (it has the same default value), otherwise it is difficult to read without IDE support. The comment itself can be placed above setContent

DisposableEffect(Unit) {
onDispose {
layer.close()
}
}
SideEffect {
Copy link
Member

Choose a reason for hiding this comment

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

It looks like SideEffect was required because of rememberUpdatedState. The current state works fine

Copy link
Member

Choose a reason for hiding this comment

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

SideEffect was introduced in #562

@m-sasha m-sasha merged commit b3621de into jb-main Apr 4, 2024
6 checks passed
@m-sasha m-sasha deleted the m-sasha/pass-composition-locals-to-layer-immediately branch April 4, 2024 10:07
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Popup content sees previous value of staticCompositionLocal
3 participants