Ondrej Stanek
01/05/2024, 3:26 PMclass ClassroomNode(
buildContext: BuildContext,
private val backStack: BackStack<ClassroomNavTarget> = BackStack(
model = BackStackModel(
initialTarget = ClassroomNavTarget.Classroom,
savedStateMap = buildContext.savedStateMap,
),
visualisation = { BackStackFader(it) }
)
) : ParentNode<ClassroomNavTarget>(
buildContext = buildContext,
appyxComponent = backStack
) {
...
override fun resolve(interactionTarget: ClassroomNavTarget, buildContext: BuildContext): Node =
when (interactionTarget) {
...
is ClassroomNavTarget.Lesson ->
// I feel like I need to pass the spotlight model here
// something like pseudo code below
// val lessonCards = classroomRepository.getLessonCards(interactionTarget.id) // but it is async
// val spotlight = Spotlight(model = SpotlightModel(initialItems = lessonCards))
// LessonNode(buildContext, popBackStack = { backStack.pop() }, spotlight)
LessonNode(buildContext, popBackStack = { backStack.pop() })
...
}
}
class LessonNode(
buildContext: BuildContext,
private val popBackStack: () -> Unit,
private val spotlight: Spotlight<StudyCards> = Spotlight(
model = SpotlightModel(
items = initialItems,
savedStateMap = null
),
visualisation = { SpotlightStack3D(it) },
gestureFactory = {
SpotlightSlider.Gestures(
transitionBounds = it,
orientation = Orientation.Vertical,
reverseOrientation = true,
)
},
)
) : ParentNode<StudyCards>(
buildContext = buildContext,
appyxComponent = spotlight
) {Zsolt
01/05/2024, 5:43 PMresolve, just return a Node instance. If you have many dependencies you can benefit from having a Builder class with a dedicated build method. But this is secondary now.
For your case, it already feels like your lesson cards fetching belongs as a responsibility to LessonNode rather than to ClassroomNode. Plus, you don’t even need to have all the items upfront.
Instead, you could create LessonNode without async, and start the async operation inside of it. Then, when it completes you would trigger an Update operation on your spotlight instance: https://bumble-tech.github.io/appyx/components/spotlight/#update-elements
Meanwhile you could show a loading spinner, and if you like, you can also customise the transitions for the incoming elements.Ondrej Stanek
01/05/2024, 6:02 PM// Navigator.kt
fun goToLesson(lessonId: String) {
lifecycleScope.launch {
rootNode
.goToMain()
.goToClassroom()
.goToLesson(lessonId)
}
}
// ClassroomNode.kt
suspend fun goToLesson(lessonId: String): LessonNode {
val lessonCards = classroomRepository
.getLessonCards(lessonId)
.getOrElse {
println("Error I should handle error state: $it")
emptyList()
}
.map {lessonCardModel ->
val (front, back) = lessonCardModel.text.split(QaCardDelimiter)
StudyCards.ReverseCard(
StudyCards.SimpleCard(front),
StudyCards.SimpleCard(front),
)
}
return attachChild {
backStack.push(ClassroomNavTarget.Lesson(lessonId, lessonCards))
}
}Zsolt
01/05/2024, 6:10 PMZsolt
01/05/2024, 6:11 PMfront twice, and back 0 times in your reverse card)Ondrej Stanek
01/05/2024, 6:12 PM