Use bookRepository at application start.
This commit is contained in:
parent
b94eaba31b
commit
45f5e9023e
9 changed files with 256 additions and 145 deletions
|
|
@ -52,7 +52,7 @@ fun LoadingCard(
|
|||
private fun LoadingCardLightPreview() {
|
||||
BibLibTheme(darkTheme = false) {
|
||||
LoadingCard(
|
||||
message = stringResource(id = R.string.loading)
|
||||
message = stringResource(id = R.string.loading_authentication)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -62,7 +62,7 @@ private fun LoadingCardLightPreview() {
|
|||
private fun LoadingCardDarkPreview() {
|
||||
BibLibTheme(darkTheme = true) {
|
||||
LoadingCard(
|
||||
message = stringResource(id = R.string.loading)
|
||||
message = stringResource(id = R.string.loading_book)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -60,7 +60,7 @@ fun SuccessCard(
|
|||
@Composable
|
||||
private fun SuccessLightPreview() {
|
||||
BibLibTheme(darkTheme = false) {
|
||||
SuccessCard(message = stringResource(id = R.string.authentication_success))
|
||||
SuccessCard(message = stringResource(id = R.string.success_authentication))
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -68,6 +68,6 @@ private fun SuccessLightPreview() {
|
|||
@Composable
|
||||
private fun SuccessDarkPreview() {
|
||||
BibLibTheme(darkTheme = true) {
|
||||
SuccessCard(message = stringResource(id = R.string.authentication_success))
|
||||
SuccessCard(message = stringResource(id = R.string.success_authentication))
|
||||
}
|
||||
}
|
||||
|
|
@ -45,15 +45,19 @@ import com.pixelized.biblib.ui.composable.items.dialog.SuccessCard
|
|||
import com.pixelized.biblib.ui.theme.BibLibTheme
|
||||
import com.pixelized.biblib.ui.viewmodel.authentication.AuthenticationViewModel
|
||||
import com.pixelized.biblib.ui.viewmodel.authentication.IAuthentication
|
||||
import com.pixelized.biblib.ui.viewmodel.initialisation.IInitialisation
|
||||
import com.pixelized.biblib.ui.viewmodel.initialisation.InitialisationViewModel
|
||||
import com.pixelized.biblib.ui.viewmodel.navigation.INavigation
|
||||
import com.pixelized.biblib.ui.viewmodel.navigation.NavigationViewModel
|
||||
import kotlinx.coroutines.delay
|
||||
|
||||
|
||||
private const val LE_LOAD_BOOK = "LE_LOAD_BOOK"
|
||||
|
||||
@Composable
|
||||
fun LoginScreenComposable(
|
||||
navigation: INavigation = viewModel<NavigationViewModel>(),
|
||||
authentication: IAuthentication = viewModel<AuthenticationViewModel>(),
|
||||
initialisation: IInitialisation = viewModel<InitialisationViewModel>()
|
||||
) {
|
||||
Box(
|
||||
modifier = Modifier
|
||||
|
|
@ -61,10 +65,10 @@ fun LoginScreenComposable(
|
|||
.fillMaxHeight()
|
||||
) {
|
||||
authentication.PrepareLoginWithGoogle()
|
||||
LoginScreenNavigationComposable(navigation, authentication)
|
||||
LoginScreenNavigationComposable(navigation, authentication, initialisation)
|
||||
|
||||
LoginScreenContentComposable(authentication)
|
||||
LoginScreenDialogComposable(authentication)
|
||||
LoginScreenDialogComposable(authentication, initialisation)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -91,49 +95,87 @@ private fun LoginScreenContentComposable(
|
|||
@OptIn(ExperimentalAnimationApi::class)
|
||||
@Composable
|
||||
private fun LoginScreenDialogComposable(
|
||||
authentication: IAuthentication
|
||||
authentication: IAuthentication,
|
||||
initialisation: IInitialisation,
|
||||
) {
|
||||
val state = authentication.state.observeAsState()
|
||||
val authenticationState = authentication.state.observeAsState()
|
||||
val bookLoadingState = initialisation.state.observeAsState()
|
||||
|
||||
CrossFadeOverlay(
|
||||
modifier = Modifier.clickable {
|
||||
if (state.value is IAuthentication.State.Error) {
|
||||
if (authenticationState.value is IAuthentication.State.Error) {
|
||||
authentication.clearState()
|
||||
}
|
||||
},
|
||||
visible = (state.value is IAuthentication.State.Initial).not()
|
||||
visible = (authenticationState.value is IAuthentication.State.Initial
|
||||
&& bookLoadingState.value is IInitialisation.State.Initial).not()
|
||||
) {
|
||||
AnimatedVisibility(
|
||||
modifier = Modifier.align(Alignment.Center),
|
||||
visible = state.value is IAuthentication.State.Error,
|
||||
visible = authenticationState.value is IAuthentication.State.Error,
|
||||
initiallyVisible = false,
|
||||
enter = expandVertically(Alignment.CenterVertically),
|
||||
exit = shrinkVertically(Alignment.CenterVertically),
|
||||
) {
|
||||
ErrorCard(
|
||||
message = stringResource(id = R.string.error_generic),
|
||||
exception = (state.value as? IAuthentication.State.Error)?.exception
|
||||
exception = (authenticationState.value as? IAuthentication.State.Error)?.exception
|
||||
)
|
||||
}
|
||||
AnimatedVisibility(
|
||||
modifier = Modifier.align(Alignment.Center),
|
||||
visible = state.value is IAuthentication.State.Loading,
|
||||
visible = authenticationState.value is IAuthentication.State.Loading,
|
||||
initiallyVisible = false,
|
||||
enter = expandVertically(Alignment.CenterVertically),
|
||||
exit = shrinkVertically(Alignment.CenterVertically),
|
||||
) {
|
||||
LoadingCard(
|
||||
message = stringResource(id = R.string.loading)
|
||||
message = stringResource(id = R.string.loading_authentication)
|
||||
)
|
||||
}
|
||||
AnimatedVisibility(
|
||||
modifier = Modifier.align(Alignment.Center),
|
||||
visible = state.value is IAuthentication.State.Connect,
|
||||
visible = authenticationState.value is IAuthentication.State.Connect,
|
||||
initiallyVisible = false,
|
||||
enter = expandVertically(Alignment.CenterVertically),
|
||||
exit = shrinkVertically(Alignment.CenterVertically),
|
||||
) {
|
||||
SuccessCard(
|
||||
message = stringResource(id = R.string.authentication_success)
|
||||
message = stringResource(id = R.string.success_authentication)
|
||||
)
|
||||
}
|
||||
AnimatedVisibility(
|
||||
modifier = Modifier.align(Alignment.Center),
|
||||
visible = bookLoadingState.value is IInitialisation.State.Error,
|
||||
initiallyVisible = false,
|
||||
enter = expandVertically(Alignment.CenterVertically),
|
||||
exit = shrinkVertically(Alignment.CenterVertically),
|
||||
) {
|
||||
ErrorCard(
|
||||
message = stringResource(id = R.string.error_generic),
|
||||
exception = (bookLoadingState.value as? IInitialisation.State.Error)?.exception
|
||||
)
|
||||
}
|
||||
AnimatedVisibility(
|
||||
modifier = Modifier.align(Alignment.Center),
|
||||
visible = bookLoadingState.value is IInitialisation.State.Loading,
|
||||
initiallyVisible = false,
|
||||
enter = expandVertically(Alignment.CenterVertically),
|
||||
exit = shrinkVertically(Alignment.CenterVertically),
|
||||
) {
|
||||
LoadingCard(
|
||||
message = stringResource(id = R.string.loading_book)
|
||||
)
|
||||
}
|
||||
AnimatedVisibility(
|
||||
modifier = Modifier.align(Alignment.Center),
|
||||
visible = bookLoadingState.value is IInitialisation.State.Finished,
|
||||
initiallyVisible = false,
|
||||
enter = expandVertically(Alignment.CenterVertically),
|
||||
exit = shrinkVertically(Alignment.CenterVertically),
|
||||
) {
|
||||
SuccessCard(
|
||||
message = stringResource(id = R.string.success_book)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -142,15 +184,21 @@ private fun LoginScreenDialogComposable(
|
|||
@Composable
|
||||
private fun LoginScreenNavigationComposable(
|
||||
navigation: INavigation,
|
||||
authentication: IAuthentication
|
||||
authentication: IAuthentication,
|
||||
initialisation: IInitialisation,
|
||||
) {
|
||||
val state = authentication.state.observeAsState()
|
||||
if (state.value == IAuthentication.State.Connect) {
|
||||
LaunchedEffect(key1 = "navigateTo(MainScreen)") {
|
||||
delay(1000)
|
||||
navigation.navigateTo(INavigation.Screen.MainScreen)
|
||||
val authenticationState = authentication.state.observeAsState()
|
||||
val bookLoadingState = initialisation.state.observeAsState()
|
||||
|
||||
if (authenticationState.value == IAuthentication.State.Connect) {
|
||||
LaunchedEffect(LE_LOAD_BOOK) {
|
||||
initialisation.loadBook()
|
||||
}
|
||||
}
|
||||
|
||||
if (bookLoadingState.value is IInitialisation.State.Finished) {
|
||||
navigation.navigateTo(INavigation.Screen.MainScreen)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
|
|
@ -317,6 +365,7 @@ fun LoginScreenComposablePreview() {
|
|||
BibLibTheme {
|
||||
val navigationViewModel = INavigation.Mock()
|
||||
val authenticationViewModel = IAuthentication.Mock()
|
||||
LoginScreenComposable(navigationViewModel, authenticationViewModel)
|
||||
val initialisation = IInitialisation.Mock()
|
||||
LoginScreenComposable(navigationViewModel, authenticationViewModel, initialisation)
|
||||
}
|
||||
}
|
||||
|
|
@ -2,11 +2,14 @@ package com.pixelized.biblib.ui.composable.screen
|
|||
|
||||
import androidx.compose.animation.*
|
||||
import androidx.compose.animation.core.tween
|
||||
import androidx.compose.foundation.clickable
|
||||
import androidx.compose.foundation.layout.*
|
||||
import androidx.compose.material.MaterialTheme
|
||||
import androidx.compose.material.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.LaunchedEffect
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.livedata.observeAsState
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.res.stringResource
|
||||
|
|
@ -15,6 +18,8 @@ import androidx.compose.ui.unit.dp
|
|||
import androidx.lifecycle.viewmodel.compose.viewModel
|
||||
import com.pixelized.biblib.BuildConfig
|
||||
import com.pixelized.biblib.R
|
||||
import com.pixelized.biblib.ui.composable.items.dialog.CrossFadeOverlay
|
||||
import com.pixelized.biblib.ui.composable.items.dialog.ErrorCard
|
||||
import com.pixelized.biblib.ui.theme.BibLibTheme
|
||||
import com.pixelized.biblib.ui.viewmodel.initialisation.IInitialisation
|
||||
import com.pixelized.biblib.ui.viewmodel.initialisation.InitialisationViewModel
|
||||
|
|
@ -23,12 +28,16 @@ import com.pixelized.biblib.ui.viewmodel.navigation.NavigationViewModel
|
|||
import kotlinx.coroutines.delay
|
||||
import java.util.*
|
||||
|
||||
private const val ANIMATION_DURATION = 1000
|
||||
private const val LAUNCH_EFFECT_LOAD_APPLICATION = "LoadApplication"
|
||||
|
||||
@Preview
|
||||
@Composable
|
||||
fun SplashScreenComposablePreview() {
|
||||
BibLibTheme {
|
||||
SplashScreenComposable(IInitialisation.Mock(), INavigation.Mock())
|
||||
val initialisation = IInitialisation.Mock(IInitialisation.State.Loading)
|
||||
val navigation = INavigation.Mock()
|
||||
SplashScreenComposable(initialisation, navigation, true)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -36,92 +45,138 @@ fun SplashScreenComposablePreview() {
|
|||
@Composable
|
||||
fun SplashScreenComposable(
|
||||
initialisation: IInitialisation = viewModel<InitialisationViewModel>(),
|
||||
navigation: INavigation = viewModel<NavigationViewModel>()
|
||||
navigation: INavigation = viewModel<NavigationViewModel>(),
|
||||
initiallyVisible: Boolean = false,
|
||||
) {
|
||||
val state by initialisation.state.observeAsState()
|
||||
|
||||
LaunchedEffect(LAUNCH_EFFECT_LOAD_APPLICATION) {
|
||||
initialisation.loadApplication()
|
||||
}
|
||||
|
||||
ContentComposable(state = state, initiallyVisible = initiallyVisible)
|
||||
DialogComposable(state = state)
|
||||
NavigationComposable(navigation = navigation, state = state)
|
||||
}
|
||||
|
||||
@OptIn(ExperimentalAnimationApi::class)
|
||||
@Composable
|
||||
private fun ContentComposable(
|
||||
state: IInitialisation.State?,
|
||||
duration: Int = ANIMATION_DURATION,
|
||||
initiallyVisible: Boolean = false,
|
||||
) {
|
||||
val duration = 1000
|
||||
val typography = MaterialTheme.typography
|
||||
initialisation.LoadApplication {
|
||||
val visible = it !is IInitialisation.State.Finished
|
||||
val visible = state !is IInitialisation.State.Finished
|
||||
|
||||
Box(
|
||||
Box(
|
||||
modifier = Modifier
|
||||
.fillMaxHeight()
|
||||
.fillMaxWidth()
|
||||
.padding(16.dp),
|
||||
) {
|
||||
Column(
|
||||
modifier = Modifier
|
||||
.fillMaxHeight()
|
||||
.fillMaxWidth()
|
||||
.padding(16.dp),
|
||||
.width(240.dp)
|
||||
.align(Alignment.Center)
|
||||
) {
|
||||
Column(
|
||||
modifier = Modifier
|
||||
.width(240.dp)
|
||||
.align(Alignment.Center)
|
||||
) {
|
||||
AnimatedVisibility(
|
||||
visible = visible,
|
||||
initiallyVisible = false,
|
||||
enter = fadeIn(animationSpec = tween(duration))
|
||||
+ slideInVertically(
|
||||
initialOffsetY = { height -> -height },
|
||||
animationSpec = tween(duration)
|
||||
),
|
||||
exit = fadeOut(animationSpec = tween(duration))
|
||||
+ slideOutVertically(
|
||||
targetOffsetY = { height -> -height },
|
||||
animationSpec = tween(duration)
|
||||
),
|
||||
) {
|
||||
Text(
|
||||
style = typography.h4,
|
||||
text = "Welcome to"
|
||||
)
|
||||
}
|
||||
AnimatedVisibility(
|
||||
modifier = Modifier.align(Alignment.End),
|
||||
visible = visible,
|
||||
initiallyVisible = false,
|
||||
enter = fadeIn(animationSpec = tween(duration))
|
||||
+ slideInVertically(
|
||||
initialOffsetY = { height -> height },
|
||||
animationSpec = tween(duration)
|
||||
),
|
||||
exit = fadeOut(animationSpec = tween(duration))
|
||||
+ slideOutVertically(
|
||||
targetOffsetY = { height -> height },
|
||||
animationSpec = tween(duration)
|
||||
),
|
||||
) {
|
||||
Text(
|
||||
style = typography.h4,
|
||||
text = stringResource(id = R.string.app_name)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
AnimatedVisibility(
|
||||
modifier = Modifier.align(Alignment.BottomEnd),
|
||||
visible = visible,
|
||||
enter = fadeIn(animationSpec = tween(duration)),
|
||||
exit = fadeOut(animationSpec = tween(duration)),
|
||||
initiallyVisible = initiallyVisible,
|
||||
enter = fadeIn(animationSpec = tween(duration))
|
||||
+ slideInVertically(
|
||||
initialOffsetY = { height -> -height },
|
||||
animationSpec = tween(duration)
|
||||
),
|
||||
exit = fadeOut(animationSpec = tween(duration))
|
||||
+ slideOutVertically(
|
||||
targetOffsetY = { height -> -height },
|
||||
animationSpec = tween(duration)
|
||||
),
|
||||
) {
|
||||
Text(
|
||||
style = typography.caption,
|
||||
text = stringResource(
|
||||
R.string.app_version,
|
||||
BuildConfig.BUILD_TYPE.toUpperCase(Locale.getDefault()),
|
||||
BuildConfig.VERSION_NAME,
|
||||
BuildConfig.VERSION_CODE
|
||||
)
|
||||
style = typography.h4,
|
||||
text = "Welcome to"
|
||||
)
|
||||
}
|
||||
AnimatedVisibility(
|
||||
modifier = Modifier.align(Alignment.End),
|
||||
visible = visible,
|
||||
initiallyVisible = initiallyVisible,
|
||||
enter = fadeIn(animationSpec = tween(duration))
|
||||
+ slideInVertically(
|
||||
initialOffsetY = { height -> height },
|
||||
animationSpec = tween(duration)
|
||||
),
|
||||
exit = fadeOut(animationSpec = tween(duration))
|
||||
+ slideOutVertically(
|
||||
targetOffsetY = { height -> height },
|
||||
animationSpec = tween(duration)
|
||||
),
|
||||
) {
|
||||
Text(
|
||||
style = typography.h4,
|
||||
text = stringResource(id = R.string.app_name)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
if (it is IInitialisation.State.Finished) {
|
||||
LaunchedEffect(key1 = "SplashScreen.navigateTo()") {
|
||||
delay(1000)
|
||||
if (it.needLogin) {
|
||||
navigation.navigateTo(INavigation.Screen.LoginScreen)
|
||||
} else {
|
||||
navigation.navigateTo(INavigation.Screen.MainScreen)
|
||||
}
|
||||
}
|
||||
AnimatedVisibility(
|
||||
modifier = Modifier.align(Alignment.BottomEnd),
|
||||
visible = visible,
|
||||
initiallyVisible = initiallyVisible,
|
||||
enter = fadeIn(animationSpec = tween(duration)),
|
||||
exit = fadeOut(animationSpec = tween(duration)),
|
||||
) {
|
||||
Text(
|
||||
style = typography.caption,
|
||||
text = stringResource(
|
||||
R.string.app_version,
|
||||
BuildConfig.BUILD_TYPE.toUpperCase(Locale.getDefault()),
|
||||
BuildConfig.VERSION_NAME,
|
||||
BuildConfig.VERSION_CODE
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@OptIn(ExperimentalAnimationApi::class)
|
||||
@Composable
|
||||
private fun DialogComposable(state: IInitialisation.State?) {
|
||||
CrossFadeOverlay(
|
||||
modifier = Modifier.clickable {},
|
||||
visible = state is IInitialisation.State.Error
|
||||
) {
|
||||
AnimatedVisibility(
|
||||
modifier = Modifier.align(Alignment.Center),
|
||||
visible = true,
|
||||
initiallyVisible = false,
|
||||
enter = expandVertically(Alignment.CenterVertically),
|
||||
exit = shrinkVertically(Alignment.CenterVertically),
|
||||
) {
|
||||
ErrorCard(
|
||||
message = stringResource(id = R.string.error_generic),
|
||||
exception = (state as? IInitialisation.State.Error)?.exception
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun NavigationComposable(
|
||||
navigation: INavigation,
|
||||
state: IInitialisation.State?,
|
||||
duration: Int = ANIMATION_DURATION,
|
||||
) {
|
||||
if (state is IInitialisation.State.Finished) {
|
||||
LaunchedEffect(key1 = "SplashScreen.navigateTo()") {
|
||||
delay(duration.toLong())
|
||||
if (state.needLogin) {
|
||||
navigation.navigateTo(INavigation.Screen.LoginScreen)
|
||||
} else {
|
||||
navigation.navigateTo(INavigation.Screen.MainScreen)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue