@@ -4,15 +4,15 @@ package com.squareup.workflow1.internal
44
55import androidx.compose.runtime.Composable
66import androidx.compose.runtime.Composition
7+ import androidx.compose.runtime.CompositionLocalContext
78import androidx.compose.runtime.CompositionLocalProvider
89import androidx.compose.runtime.MonotonicFrameClock
910import androidx.compose.runtime.Recomposer
1011import androidx.compose.runtime.currentCompositeKeyHash
12+ import androidx.compose.runtime.currentCompositionLocalContext
1113import androidx.compose.runtime.currentRecomposeScope
12- import androidx.compose.runtime.key
1314import androidx.compose.runtime.mutableStateOf
1415import androidx.compose.runtime.remember
15- import androidx.compose.runtime.rememberCompositionContext
1616import androidx.compose.runtime.rememberCoroutineScope
1717import androidx.compose.runtime.saveable.LocalSaveableStateRegistry
1818import androidx.compose.runtime.saveable.SaveableStateRegistry
@@ -176,6 +176,7 @@ internal class SubtreeManager<PropsT, StateT, OutputT>(
176176 val recomposer = Recomposer (coroutineContext)
177177 val composition = Composition (UnitApplier , recomposer)
178178 val saveableStateRegistry: SaveableStateRegistry // TODO
179+ val localsContext: CompositionLocalContext ? // TODO
179180
180181 // TODO I think we need more than a simple UNDISPATCHED start to make this work – we have to
181182 // pump the dispatcher until the composition is finished.
@@ -188,7 +189,7 @@ internal class SubtreeManager<PropsT, StateT, OutputT>(
188189 }
189190
190191 val rendering = mutableStateOf<ChildRenderingT ?>(null )
191- composition.setContent {
192+ val wrappedContent = @Composable {
192193 CompositionLocalProvider (
193194 LocalWorkflowCompositionHost provides this ,
194195 LocalSaveableStateRegistry provides saveableStateRegistry,
@@ -197,6 +198,19 @@ internal class SubtreeManager<PropsT, StateT, OutputT>(
197198 }
198199 }
199200
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+
200214 // TODO prime the first frame to generate the initial rendering
201215
202216 @Suppress(" UNCHECKED_CAST" )
@@ -218,14 +232,14 @@ internal class SubtreeManager<PropsT, StateT, OutputT>(
218232
219233 val key = currentCompositeKeyHash
220234 val coroutineScope = rememberCoroutineScope()
221- val compositionContext = rememberCompositionContext()
235+ val localsContext = currentCompositionLocalContext
222236 val recomposeScope = currentRecomposeScope
223237 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,
229243 )
230244 }
231245 child.onOutput = onOutput
@@ -236,7 +250,7 @@ internal class SubtreeManager<PropsT, StateT, OutputT>(
236250 // tracking. After the composition frame is finished, we can update the WorkflowNode state as
237251 // required.
238252 // TODO don't call render, it's not powerful enough for what we need.
239- render(
253+ return render(
240254 child = workflow,
241255 props = props,
242256 key = child.workflowKey,
0 commit comments