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