Shivam Kanodia
06/26/2023, 6:40 AM@Composable
internal fun RootContent(component: RootComponent) {
Children(
stack = component.childStack,
animation = stackAnimation(fade()),
) {
println("child stack ===== ${component.childStack.value}")
when (val child = it.instance) {
is RootComponent.Child.EnterMobileNumber -> LoginComponent(child.component)
is RootComponent.Child.EnterOtp -> OtpComponent(child.component)
is RootComponent.Child.ProjectListing -> ProjectListingMainScreen(child.component)
is RootComponent.Child.ProjectDetails -> ProjectDetailsScreen(child.component)
is RootComponent.Child.Notifications -> NotificationScreen(child.component)
is RootComponent.Child.ImagePreviewFullScreen -> ImagePreviewFullScreen(child.component)
}
}
}
THis is my root content . Now inside ProjectDetails Component i have a BootomNaviagtion containing 5 options "A,B,C,D,E" all of which are different and clicking on "A" loads Component A , Component A can have its own childers which can be one or many , now please help me how should i define ProjectDetails Componet and what should be the structure of this component i.e when inside ProjectDetails, i want this component to act as root component for its 5 childen (A,B,C,D,E), am i thinking in right approach or how should i proceed from here!! @Arkadii Ivanov Please help!!Arkadii Ivanov
06/26/2023, 10:20 PMnavigation.bringToFront(...)
.Shivam Kanodia
06/27/2023, 5:39 AMShivam Kanodia
06/28/2023, 7:03 AMShivam Kanodia
06/28/2023, 7:03 AMclass RootComponent internal constructor(
componentContext: ComponentContext,
private val enterMobileNumber: (ComponentContext, (EnterMobileNumberComponent.Output) -> Unit) -> EnterMobileNumberComponent,
private val enterOtp: (ComponentContext, mobileNumber: String, verificationId: String, (EnterOtpComponent.Output) -> Unit) -> EnterOtpComponent,
private val projectListing: (ComponentContext, (ProjectListingComponent.Output) -> Unit) -> ProjectListingComponent,
private val projectDetails: (ComponentContext, projectId: String, (ProjectDetailsComponent.Output) -> Unit) -> ProjectDetailsComponent,
private val imagePreviewFullScreen: (ComponentContext, imagesList: List<PreviewFile>, initialImageIndex: Int, (ImagePreviewFullScreenComponent.Output) -> Unit) -> ImagePreviewFullScreenComponent,
private val notifications: (ComponentContext, (NotificationsComponent.Output) -> Unit) -> NotificationsComponent,
) : ComponentContext by componentContext {
constructor(
componentContext: ComponentContext,
storeFactory: StoreFactory,
) : this(componentContext = componentContext, enterMobileNumber = { childContext, output ->
EnterMobileNumberComponent(
componentContext = childContext, storeFactory = storeFactory, output = output
)
}, enterOtp = { childContext, mobileNum, verificationId, output ->
EnterOtpComponent(
componentContext = childContext,
mobileNumber = mobileNum,
verificationId = verificationId,
storeFactory = storeFactory,
output = output
)
}, projectListing = { childContext, output ->
ProjectListingComponent(
componentContext = childContext, storeFactory = storeFactory, output = output
)
}, projectDetails = { childContext, projectId, output ->
ProjectDetailsComponent(
componentContext = childContext,
projectId = projectId,
storeFactory = storeFactory,
output = output
)
}, notifications = { childContext, output ->
NotificationsComponent(
componentContext = childContext, storeFactory = storeFactory, output = output
)
}, imagePreviewFullScreen = { childContext, imagesList, initialImageIndex, output ->
ImagePreviewFullScreenComponent(
componentContext = childContext,
imagesList = imagesList,
initialImageIndex = initialImageIndex,
output = output
)
})
private val navigation = StackNavigation<Configuration>()
private val stack = childStack(
source = navigation,
initialConfiguration = getInitConfig(),
handleBackButton = false,
childFactory = ::createChild
)
private fun getInitConfig() = if (pref.getString(RdashConstants.AUTH_TOKEN).isNullOrEmpty()
.not()
) Configuration.ProjectListing
else Configuration.EnterMobileNumber
val childStack: Value<ChildStack<*, Child>> = stack
private fun createChild(
configuration: Configuration, componentContext: ComponentContext
): Child = when (configuration) {
is Configuration.EnterMobileNumber -> Child.EnterMobileNumber(
enterMobileNumber(
componentContext, ::onEnterMobileNumberOutput
)
)
is Configuration.EnterOtp -> Child.EnterOtp(
enterOtp(
componentContext,
configuration.mobile,
configuration.verificationId,
::onEnterOtpOutput
)
)
is Configuration.ProjectListing -> Child.ProjectListing(
projectListing(componentContext, ::onProjectListingOutput)
)
is Configuration.ProjectDetails -> Child.ProjectDetails(
projectDetails(
componentContext, configuration.projectId, ::onProjectDetailsOutput
)
)
is Configuration.ImagePreviewFullScreen -> Child.ImagePreviewFullScreen(
imagePreviewFullScreen(
componentContext,
configuration.imagesList,
configuration.initialImageIndex,
::onImagePreviewOutput
)
)
is Configuration.Notification -> Child.Notifications(
notifications(
componentContext, ::onNotificationsOutput
)
)
}
private fun onEnterMobileNumberOutput(output: EnterMobileNumberComponent.Output): Unit =
when (output) {
is EnterMobileNumberComponent.Output.NavigateBack -> navigation.pop()
is EnterMobileNumberComponent.Output.NavigateToEnterOTP -> navigation.push(
Configuration.EnterOtp(
output.mobileNum, output.verificationId
)
)
}
private fun onEnterOtpOutput(output: EnterOtpComponent.Output): Unit = when (output) {
is EnterOtpComponent.Output.NavigateBack -> navigation.pop()
is EnterOtpComponent.Output.NavigateToProjectList -> {
println("NavigateToProjectList")
navigation.replaceAll(Configuration.ProjectListing)
}
}
private fun onProjectListingOutput(output: ProjectListingComponent.Output): Unit =
when (output) {
is ProjectListingComponent.Output.NavigateBack -> navigation.pop()
is ProjectListingComponent.Output.NavigateToProjectDetails -> {
navigation.push(Configuration.ProjectDetails(projectId = output.projectId))
}
is ProjectListingComponent.Output.Logout -> {
navigation.replaceAll(Configuration.EnterMobileNumber)
}
is ProjectListingComponent.Output.NavigateToNotification -> {
navigation.push(Configuration.Notification)
}
}
private fun onProjectDetailsOutput(output: ProjectDetailsComponent.Output): Unit =
when (output) {
is ProjectDetailsComponent.Output.NavigateBack -> navigation.pop()
is ProjectDetailsComponent.Output.OpenFullScreenComponent -> navigation.push(
Configuration.ImagePreviewFullScreen(
imagesList = output.imagesList, initialImageIndex = output.initialImageIndex
)
)
else -> {}
}
private fun onNotificationsOutput(output: NotificationsComponent.Output): Unit = when (output) {
is NotificationsComponent.Output.NavigateBack -> navigation.pop()
}
private fun onImagePreviewOutput(output: ImagePreviewFullScreenComponent.Output): Unit =
when (output) {
is ImagePreviewFullScreenComponent.Output.NavigateBack -> navigation.pop()/*is ImagePreviewFullScreenComponent.Output.NavigateToImagePreviewFullScreen -> navigation.push(
Configuration.ImagePreviewFullScreen(
imagesList = output.imagesList,
initialImageIndex = output.initialImageIndex
)
)*/
else -> {}
}
private sealed class Configuration : Parcelable {
@Parcelize
object EnterMobileNumber : Configuration()
@Parcelize
data class EnterOtp(var mobile: String, val verificationId: String) : Configuration()
@Parcelize
object ProjectListing : Configuration()
@Parcelize
data class ProjectDetails(val projectId: String) : Configuration()
@Parcelize
data class ImagePreviewFullScreen(
val imagesList: List<PreviewFile>, val initialImageIndex: Int = 0
) : Configuration()
@Parcelize
object Notification : Configuration()
}
sealed class Child {
data class EnterMobileNumber(val component: EnterMobileNumberComponent) : Child()
data class EnterOtp(val component: EnterOtpComponent) : Child()
data class ProjectListing(val component: ProjectListingComponent) : Child()
data class ProjectDetails(val component: ProjectDetailsComponent) : Child()
data class ImagePreviewFullScreen(val component: ImagePreviewFullScreenComponent) : Child()
data class Notifications(val component: NotificationsComponent) : Child()
}
}
This is root componentShivam Kanodia
06/28/2023, 7:04 AM@Composable
internal fun RootContent(component: RootComponent) {
Children(
stack = component.childStack,
animation = stackAnimation(fade()),
) {
println("child stack ===== ${component.childStack.value}")
when (val child = it.instance) {
is RootComponent.Child.EnterMobileNumber -> LoginComponent(child.component)
is RootComponent.Child.EnterOtp -> OtpComponent(child.component)
is RootComponent.Child.ProjectListing -> ProjectListingMainScreen(child.component)
is RootComponent.Child.ProjectDetails -> ProjectDetailsScreen(child.component)
is RootComponent.Child.Notifications -> NotificationScreen(child.component)
is RootComponent.Child.ImagePreviewFullScreen -> ImagePreviewFullScreen(child.component)
}
}
}
This is RootContentShivam Kanodia
06/28/2023, 7:05 AMShivam Kanodia
06/28/2023, 7:06 AMclass ProjectDetailsComponent(
componentContext: ComponentContext,
projectId: String,
storeFactory: StoreFactory,
private val output: (Output) -> Unit
) : ComponentContext by componentContext {
private val projectStore = instanceKeeper.getStore {
ProjectStoreFactory(
storeFactory = storeFactory
).create()
}
@OptIn(ExperimentalCoroutinesApi::class)
val state: StateFlow<ProjectStore.State> = projectStore.stateFlow
val projectId: String = projectId
fun onEvent(event: ProjectStore.Intent) {
projectStore.accept(event)
}
fun onOutput(output: Output) {
output(output)
}
sealed class Output {
object NavigateBack : Output()
data class OpenFullScreenComponent(
val imagesList: List<PreviewFile>,
val initialImageIndex: Int,
) : Output()
object Logout : Output()
}
}
This is my ProjectDetailsComponent which i want to changeArkadii Ivanov
06/28/2023, 9:24 AMProjectDetailsContent
should also use Children
function, and show a bottom bar with the currently selected tab depending on the currently active child.
class ProjectDetailsComponent(
componentContext: ComponentContext,
// ...
) : ComponentContext by componentContext {
private val navigation = StackNavigation<Config>()
private val _stack: Value<ChildStack<Config, Child>> =
childStack(
source = navigation,
childFactory = ::createChild,
)
val stack: Value<ChildStack<*, Child>> = _stack
private fun createChild(config: Config, componentContext: ComponentContext): Child =
when (config) {
is Config.A -> Child.A(AComponent(componentContext))
is Config.B -> Child.B(BComponent(componentContext))
// ...
}
private sealed class Config : Parcelable {
@Parcelize
object A : Config()
@Parcelize
object B : Config()
// ...
}
sealed class Child {
class A(val component: AComponent) : Child()
class B(val component: BComponent) : Child()
// ...
}
}
Shivam Kanodia
06/28/2023, 10:26 AMArkadii Ivanov
06/28/2023, 10:35 AMProjectDetailsContent
should be similar to the RootContent in the example. It should display BottomNavigation
below Children
.Shivam Kanodia
06/28/2023, 11:13 AMShivam Kanodia
07/03/2023, 10:16 AMArkadii Ivanov
07/03/2023, 11:03 AMBottomSheet should be shown above BottomNav not behind BottomNav.Could you elaborate?
Shivam Kanodia
07/03/2023, 1:01 PMArkadii Ivanov
07/03/2023, 1:20 PMArkadii Ivanov
07/03/2023, 4:59 PM