From 92813f567b4a284ad292c838afb507cefa899a83 Mon Sep 17 00:00:00 2001 From: Jacob Bosco Date: Sat, 21 Jan 2023 10:17:36 +0530 Subject: [PATCH] WTA #71: Added setup for Project details page. --- .../wakatimeapp/details/ui/DetailsPage.kt | 70 +++++++++++++++++-- .../details/ui/DetailsPageViewModel.kt | 1 + .../details/ui/DetailsPageViewState.kt | 2 +- 3 files changed, 67 insertions(+), 6 deletions(-) diff --git a/details/src/main/java/com/jacob/wakatimeapp/details/ui/DetailsPage.kt b/details/src/main/java/com/jacob/wakatimeapp/details/ui/DetailsPage.kt index 87c97e76..1f1cd7db 100644 --- a/details/src/main/java/com/jacob/wakatimeapp/details/ui/DetailsPage.kt +++ b/details/src/main/java/com/jacob/wakatimeapp/details/ui/DetailsPage.kt @@ -2,22 +2,38 @@ package com.jacob.wakatimeapp.details.ui import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.height +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.statusBarsPadding import androidx.compose.material3.MaterialTheme -import androidx.compose.material3.Text +import androidx.compose.material3.SnackbarDuration.Long +import androidx.compose.material3.SnackbarHostState import androidx.compose.runtime.Composable +import androidx.compose.runtime.LaunchedEffect +import androidx.compose.runtime.collectAsState +import androidx.compose.runtime.getValue +import androidx.compose.runtime.rememberCoroutineScope import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.hilt.navigation.compose.hiltViewModel +import com.jacob.wakatimeapp.core.ui.components.WtaAnimation +import com.jacob.wakatimeapp.core.ui.theme.assets +import com.jacob.wakatimeapp.core.ui.theme.spacing +import com.jacob.wakatimeapp.details.ui.components.DetailsPageHeader import com.ramcosta.composedestinations.annotation.Destination +import kotlinx.coroutines.launch @Composable @Destination(navArgsDelegate = DetailsPageNavArgs::class) fun DetailsPage( navigator: DetailsPageNavigator, + snackbarHostState: SnackbarHostState, modifier: Modifier = Modifier, ) = DetailsPageScreen( navigator = navigator, modifier = modifier, + snackbarHostState = snackbarHostState, viewModel = hiltViewModel(), ) @@ -26,16 +42,60 @@ fun DetailsPage( private fun DetailsPageScreen( navigator: DetailsPageNavigator, viewModel: DetailsPageViewModel, + snackbarHostState: SnackbarHostState, modifier: Modifier = Modifier, ) { + val snackBarCoroutineScope = rememberCoroutineScope() + val viewState by viewModel.viewState.collectAsState() + + LaunchedEffect(viewState) { + if (viewState !is DetailsPageViewState.Error) return@LaunchedEffect + val viewStateError = viewState as DetailsPageViewState.Error + + snackBarCoroutineScope.launch { + snackbarHostState.showSnackbar( + message = viewStateError.error.message, + duration = Long, + ) + } + } + + DetailsPageContent(viewState = viewState, modifier = modifier) +} + +@Composable +private fun DetailsPageContent(viewState: DetailsPageViewState, modifier: Modifier = Modifier) = Column( - modifier = modifier, + modifier = modifier.statusBarsPadding(), horizontalAlignment = Alignment.CenterHorizontally, verticalArrangement = Arrangement.Center, ) { - Text( - text = "Details Page", - style = MaterialTheme.typography.headlineLarge, + when (viewState) { + is DetailsPageViewState.Loading -> DetailsPageLoading() + is DetailsPageViewState.Loaded -> DetailsPageLoaded(viewState) + is DetailsPageViewState.Error -> DetailsPageError(viewState) + } + } + +@Composable +private fun DetailsPageLoaded(viewState: DetailsPageViewState.Loaded) { + Column { + Spacer(modifier = Modifier.height(MaterialTheme.spacing.small)) + DetailsPageHeader( + viewState.projectName, + modifier = Modifier.padding(horizontal = MaterialTheme.spacing.extraSmall), ) } } + +@Composable +private fun DetailsPageError(errorMessage: DetailsPageViewState.Error) = WtaAnimation( + animation = MaterialTheme.assets.animations.randomErrorAnimation, + text = errorMessage.error.message, +) + +@Composable +private fun DetailsPageLoading() = WtaAnimation( + animation = MaterialTheme.assets.animations.randomLoadingAnimation, + text = "Loading..", +) diff --git a/details/src/main/java/com/jacob/wakatimeapp/details/ui/DetailsPageViewModel.kt b/details/src/main/java/com/jacob/wakatimeapp/details/ui/DetailsPageViewModel.kt index 8c555450..36da1e21 100644 --- a/details/src/main/java/com/jacob/wakatimeapp/details/ui/DetailsPageViewModel.kt +++ b/details/src/main/java/com/jacob/wakatimeapp/details/ui/DetailsPageViewModel.kt @@ -25,6 +25,7 @@ internal class DetailsPageViewModel @Inject constructor( viewModelScope.launch { val data = getProjectStatsUC(args.projectName) Timber.w(data.toString()) + _viewState.value = DetailsPageViewState.Loaded(args.projectName) } } } diff --git a/details/src/main/java/com/jacob/wakatimeapp/details/ui/DetailsPageViewState.kt b/details/src/main/java/com/jacob/wakatimeapp/details/ui/DetailsPageViewState.kt index 3148104e..906a6fa4 100644 --- a/details/src/main/java/com/jacob/wakatimeapp/details/ui/DetailsPageViewState.kt +++ b/details/src/main/java/com/jacob/wakatimeapp/details/ui/DetailsPageViewState.kt @@ -3,7 +3,7 @@ package com.jacob.wakatimeapp.details.ui sealed class DetailsPageViewState { object Loading : DetailsPageViewState() - data class Loaded(val detUiDetailsPageViewState: DetailsPageViewState) : DetailsPageViewState() + data class Loaded(val projectName: String) : DetailsPageViewState() data class Error(val error: com.jacob.wakatimeapp.core.models.Error) : DetailsPageViewState() }