@@ -4,15 +4,15 @@ package com.squareup.workflow1.internal
4
4
5
5
import androidx.compose.runtime.Composable
6
6
import androidx.compose.runtime.Composition
7
+ import androidx.compose.runtime.CompositionLocalContext
7
8
import androidx.compose.runtime.CompositionLocalProvider
8
9
import androidx.compose.runtime.MonotonicFrameClock
9
10
import androidx.compose.runtime.Recomposer
10
11
import androidx.compose.runtime.currentCompositeKeyHash
12
+ import androidx.compose.runtime.currentCompositionLocalContext
11
13
import androidx.compose.runtime.currentRecomposeScope
12
- import androidx.compose.runtime.key
13
14
import androidx.compose.runtime.mutableStateOf
14
15
import androidx.compose.runtime.remember
15
- import androidx.compose.runtime.rememberCompositionContext
16
16
import androidx.compose.runtime.rememberCoroutineScope
17
17
import androidx.compose.runtime.saveable.LocalSaveableStateRegistry
18
18
import androidx.compose.runtime.saveable.SaveableStateRegistry
@@ -176,6 +176,7 @@ internal class SubtreeManager<PropsT, StateT, OutputT>(
176
176
val recomposer = Recomposer (coroutineContext)
177
177
val composition = Composition (UnitApplier , recomposer)
178
178
val saveableStateRegistry: SaveableStateRegistry // TODO
179
+ val localsContext: CompositionLocalContext ? // TODO
179
180
180
181
// TODO I think we need more than a simple UNDISPATCHED start to make this work – we have to
181
182
// pump the dispatcher until the composition is finished.
@@ -188,7 +189,7 @@ internal class SubtreeManager<PropsT, StateT, OutputT>(
188
189
}
189
190
190
191
val rendering = mutableStateOf<ChildRenderingT ?>(null )
191
- composition.setContent {
192
+ val wrappedContent = @Composable {
192
193
CompositionLocalProvider (
193
194
LocalWorkflowCompositionHost provides this ,
194
195
LocalSaveableStateRegistry provides saveableStateRegistry,
@@ -197,6 +198,19 @@ internal class SubtreeManager<PropsT, StateT, OutputT>(
197
198
}
198
199
}
199
200
201
+ composition.setContent {
202
+ // Must provide the locals from the parent composition first so we can override the ones we
203
+ // need. If it's null then there's no parent, but the CompositionLocalProvider API has no nice
204
+ // way to pass nothing in this overload. I believe it's safe to actually call content through
205
+ // two different code paths because whether there's a parent composition cannot change for an
206
+ // existing workflow session – they can't move.
207
+ if (localsContext == null ) {
208
+ wrappedContent()
209
+ } else {
210
+ CompositionLocalProvider (localsContext, wrappedContent)
211
+ }
212
+ }
213
+
200
214
// TODO prime the first frame to generate the initial rendering
201
215
202
216
@Suppress(" UNCHECKED_CAST" )
@@ -218,14 +232,14 @@ internal class SubtreeManager<PropsT, StateT, OutputT>(
218
232
219
233
val key = currentCompositeKeyHash
220
234
val coroutineScope = rememberCoroutineScope()
221
- val compositionContext = rememberCompositionContext()
235
+ val localsContext = currentCompositionLocalContext
222
236
val recomposeScope = currentRecomposeScope
223
237
val child = remember {
224
- ComposedWorkflowChild (
225
- key,
226
- coroutineScope,
227
- compositionContext ,
228
- recomposeScope
238
+ ComposedWorkflowChild < ChildOutputT , PropsT , OutputT , Unit / * TODO * / > (
239
+ compositeHashKey = key,
240
+ coroutineScope = coroutineScope ,
241
+ recomposeScope = recomposeScope ,
242
+ localsContext = localsContext,
229
243
)
230
244
}
231
245
child.onOutput = onOutput
@@ -236,7 +250,7 @@ internal class SubtreeManager<PropsT, StateT, OutputT>(
236
250
// tracking. After the composition frame is finished, we can update the WorkflowNode state as
237
251
// required.
238
252
// TODO don't call render, it's not powerful enough for what we need.
239
- render(
253
+ return render(
240
254
child = workflow,
241
255
props = props,
242
256
key = child.workflowKey,
0 commit comments