Profile refresh mechanism when trying to send a book with no associated emails.
This commit is contained in:
parent
29a427ac5a
commit
80bcb9a686
11 changed files with 117 additions and 60 deletions
|
|
@ -1,8 +1,9 @@
|
|||
# 0.1.4
|
||||
> Not yet
|
||||
* Fix SignIn and EditProfile Url.
|
||||
* Fix SignIn and EditProfile Urls.
|
||||
* Fix Search IME padding.
|
||||
* Clear search filter after validation.
|
||||
* Clear search filter after validation.
|
||||
* Profile refresh mechanism when trying to send a book with no associated emails.
|
||||
|
||||
# 0.1.3
|
||||
> Published 25 October 2022
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@ import com.bumptech.glide.load.engine.DiskCacheStrategy
|
|||
import com.bumptech.glide.request.RequestOptions
|
||||
import com.pixelized.biblib.ui.navigation.ScreenNavHost
|
||||
import com.pixelized.biblib.ui.screen.launch.LauncherViewModel
|
||||
import com.pixelized.biblib.utils.extention.bibLib
|
||||
import com.skydoves.landscapist.glide.LocalGlideRequestOptions
|
||||
|
||||
val LocalSnackHostState = staticCompositionLocalOf<SnackbarHostState> {
|
||||
|
|
@ -40,6 +41,7 @@ fun MainContent(
|
|||
) { snackBarData ->
|
||||
Snackbar(
|
||||
snackbarData = snackBarData,
|
||||
shape = MaterialTheme.shapes.medium,
|
||||
backgroundColor = MaterialTheme.colors.error,
|
||||
contentColor = MaterialTheme.colors.onError,
|
||||
actionColor = MaterialTheme.colors.onError,
|
||||
|
|
|
|||
|
|
@ -1,23 +1,15 @@
|
|||
package com.pixelized.biblib.ui.screen.home.detail
|
||||
|
||||
import android.util.Log
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.compose.runtime.setValue
|
||||
import androidx.lifecycle.ViewModel
|
||||
import androidx.lifecycle.viewModelScope
|
||||
import com.pixelized.biblib.network.client.IBibLibClient
|
||||
import com.pixelized.biblib.network.factory.UserFactory
|
||||
import com.pixelized.biblib.utils.extention.capitalize
|
||||
import dagger.hilt.android.lifecycle.HiltViewModel
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.launch
|
||||
import javax.inject.Inject
|
||||
|
||||
@HiltViewModel
|
||||
class BookOptionViewModel @Inject constructor(
|
||||
private val client: IBibLibClient,
|
||||
) : ViewModel() {
|
||||
class BookOptionViewModel @Inject constructor() : ViewModel() {
|
||||
|
||||
var emails by mutableStateOf(listOf<OptionUio>())
|
||||
private set
|
||||
|
|
@ -25,19 +17,9 @@ class BookOptionViewModel @Inject constructor(
|
|||
var formats by mutableStateOf(initialFormat())
|
||||
private set
|
||||
|
||||
init {
|
||||
viewModelScope.launch(Dispatchers.IO) {
|
||||
try {
|
||||
val factory = UserFactory()
|
||||
val response = client.service.user()
|
||||
val data = factory.fromUserResponseToUser(response)
|
||||
|
||||
emails = data.amazonEmails.mapIndexed { index, mail ->
|
||||
OptionUio(value = mail, selected = index == 0)
|
||||
}
|
||||
} catch (exception: Exception) {
|
||||
Log.e("AccountViewModel", exception.message, exception)
|
||||
}
|
||||
fun updateEmails(amazonEmails: List<String>) {
|
||||
emails = amazonEmails.mapIndexed { index, mail ->
|
||||
OptionUio(value = mail, selected = index == 0)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
package com.pixelized.biblib.ui.screen.home.detail
|
||||
|
||||
import android.content.Context
|
||||
import androidx.activity.compose.BackHandler
|
||||
import androidx.annotation.StringRes
|
||||
import androidx.compose.animation.animateContentSize
|
||||
import androidx.compose.foundation.layout.*
|
||||
import androidx.compose.foundation.rememberScrollState
|
||||
import androidx.compose.foundation.verticalScroll
|
||||
|
|
@ -20,6 +20,7 @@ import com.pixelized.biblib.ui.screen.home.page.profile.ProfileViewModel
|
|||
import com.pixelized.biblib.ui.screen.home.page.profile.UserUio
|
||||
import com.pixelized.biblib.ui.theme.color.ShadowPalette
|
||||
import com.pixelized.biblib.utils.extention.bibLib
|
||||
import kotlinx.coroutines.cancel
|
||||
import kotlinx.coroutines.launch
|
||||
|
||||
@Stable
|
||||
|
|
@ -77,6 +78,7 @@ fun DetailScreen(
|
|||
modifier = Modifier
|
||||
.navigationBarsPadding()
|
||||
.padding(bottom = MaterialTheme.bibLib.dimen.dp16),
|
||||
emails = profileViewModel.mails,
|
||||
onHelp = { uri ->
|
||||
uriHandler.openUri(uri)
|
||||
},
|
||||
|
|
@ -96,17 +98,13 @@ fun DetailScreen(
|
|||
.systemBarsPadding(),
|
||||
book = detail,
|
||||
onSend = {
|
||||
scope.launch {
|
||||
val user = profileViewModel.user as? StateUio.Success<UserUio>
|
||||
if (user?.value?.amazonEmails?.isEmpty() == true) {
|
||||
snackBarHost.showSnackbar(
|
||||
message = context.getString(R.string.error_no_amazon_email),
|
||||
duration = SnackbarDuration.Long,
|
||||
)
|
||||
} else {
|
||||
emailSheetState.show()
|
||||
}
|
||||
}
|
||||
onSend(
|
||||
context = context,
|
||||
profileViewModel = profileViewModel,
|
||||
snackBarHost = snackBarHost,
|
||||
emailSheetState = emailSheetState,
|
||||
userState = profileViewModel.user
|
||||
)
|
||||
}
|
||||
)
|
||||
DetailScreenSendLoader(
|
||||
|
|
@ -159,6 +157,35 @@ fun DetailScreen(
|
|||
}
|
||||
}
|
||||
|
||||
@OptIn(ExperimentalMaterialApi::class)
|
||||
private suspend fun onSend(
|
||||
context: Context,
|
||||
profileViewModel: ProfileViewModel,
|
||||
snackBarHost: SnackbarHostState,
|
||||
emailSheetState: ModalBottomSheetState,
|
||||
userState: StateUio<UserUio>,
|
||||
) {
|
||||
val user = userState as? StateUio.Success<UserUio>
|
||||
if (user?.value?.amazonEmails?.isEmpty() == true) {
|
||||
val result = snackBarHost.showSnackbar(
|
||||
message = context.getString(R.string.error_send_no_amazon_email_message),
|
||||
actionLabel = context.getString(R.string.error_send_no_amazon_email_action),
|
||||
duration = SnackbarDuration.Indefinite,
|
||||
)
|
||||
if (result == SnackbarResult.ActionPerformed) {
|
||||
onSend(
|
||||
context = context,
|
||||
profileViewModel = profileViewModel,
|
||||
snackBarHost = snackBarHost,
|
||||
emailSheetState = emailSheetState,
|
||||
userState = profileViewModel.updateUser()
|
||||
)
|
||||
}
|
||||
} else {
|
||||
emailSheetState.show()
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun EmptyDetail(
|
||||
modifier: Modifier = Modifier,
|
||||
|
|
|
|||
|
|
@ -15,6 +15,7 @@ import androidx.compose.material.icons.filled.Send
|
|||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.Immutable
|
||||
import androidx.compose.runtime.Stable
|
||||
import androidx.compose.runtime.rememberCoroutineScope
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.layout.ContentScale
|
||||
|
|
@ -37,6 +38,7 @@ import com.pixelized.biblib.utils.extention.bibLib
|
|||
import com.pixelized.biblib.utils.extention.default
|
||||
import com.skydoves.landscapist.CircularReveal
|
||||
import com.skydoves.landscapist.glide.GlideImage
|
||||
import kotlinx.coroutines.launch
|
||||
import java.io.Serializable
|
||||
|
||||
@Stable
|
||||
|
|
@ -75,8 +77,10 @@ fun DetailScreenContent(
|
|||
book: BookDetailUio,
|
||||
onMobi: () -> Unit = default(),
|
||||
onEpub: () -> Unit = default(),
|
||||
onSend: () -> Unit = default(),
|
||||
onSend: suspend () -> Unit = { },
|
||||
) {
|
||||
val scope = rememberCoroutineScope()
|
||||
|
||||
AnimatedDelayer(
|
||||
targetState = book.id,
|
||||
) {
|
||||
|
|
@ -130,7 +134,7 @@ fun DetailScreenContent(
|
|||
) {
|
||||
Button(
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
onClick = onSend,
|
||||
onClick = { scope.launch { onSend() } },
|
||||
) {
|
||||
Icon(imageVector = Icons.Default.Send, contentDescription = "")
|
||||
Spacer(modifier = Modifier.width(MaterialTheme.bibLib.dimen.dp4))
|
||||
|
|
|
|||
|
|
@ -15,6 +15,7 @@ import androidx.compose.material.RadioButton
|
|||
import androidx.compose.material.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.Immutable
|
||||
import androidx.compose.runtime.LaunchedEffect
|
||||
import androidx.compose.runtime.Stable
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
|
|
@ -26,6 +27,7 @@ import androidx.compose.ui.text.style.TextOverflow
|
|||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import androidx.hilt.navigation.compose.hiltViewModel
|
||||
import com.pixelized.biblib.R
|
||||
import com.pixelized.biblib.ui.screen.home.page.profile.UserUio
|
||||
import com.pixelized.biblib.ui.theme.BibLibTheme
|
||||
import com.pixelized.biblib.utils.extention.*
|
||||
|
||||
|
|
@ -49,9 +51,13 @@ annotation class Format {
|
|||
fun DetailScreenSendOption(
|
||||
modifier: Modifier = Modifier,
|
||||
optionViewModel: BookOptionViewModel = hiltViewModel(),
|
||||
emails: List<String>,
|
||||
onHelp: (url: String) -> Unit = default<String>(),
|
||||
onSend: (email: String, format: String) -> Unit = { _, _ -> },
|
||||
) {
|
||||
LaunchedEffect(key1 = emails) {
|
||||
optionViewModel.updateEmails(amazonEmails = emails)
|
||||
}
|
||||
DetailScreenSendOption(
|
||||
modifier = modifier,
|
||||
emails = optionViewModel.emails,
|
||||
|
|
@ -138,7 +144,7 @@ fun DetailScreenSendOption(
|
|||
.padding(horizontal = MaterialTheme.bibLib.dimen.dp16),
|
||||
color = MaterialTheme.bibLib.colors.typography.easy,
|
||||
style = MaterialTheme.typography.caption,
|
||||
text = stringResource(id = R.string.detail_option_mail),
|
||||
text = stringResource(id = R.string.detail_option_format),
|
||||
)
|
||||
}
|
||||
items(items = formats) { format ->
|
||||
|
|
|
|||
|
|
@ -5,6 +5,8 @@ import android.content.res.Configuration.UI_MODE_NIGHT_NO
|
|||
import android.content.res.Configuration.UI_MODE_NIGHT_YES
|
||||
import android.net.Uri
|
||||
import androidx.compose.foundation.layout.*
|
||||
import androidx.compose.foundation.lazy.LazyColumn
|
||||
import androidx.compose.foundation.lazy.items
|
||||
import androidx.compose.material.*
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.filled.Edit
|
||||
|
|
@ -12,8 +14,10 @@ import androidx.compose.runtime.Composable
|
|||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.platform.LocalContext
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import androidx.hilt.navigation.compose.hiltViewModel
|
||||
import com.pixelized.biblib.R
|
||||
import com.pixelized.biblib.network.client.IBibLibClient
|
||||
import com.pixelized.biblib.ui.composable.StateUio
|
||||
import com.pixelized.biblib.ui.navigation.LocalScreenNavHostController
|
||||
|
|
@ -62,8 +66,9 @@ private fun ProfileScreenContent(
|
|||
Text(
|
||||
style = MaterialTheme.typography.body1,
|
||||
color = MaterialTheme.colors.onSurface,
|
||||
text = "Welcome"
|
||||
text = stringResource(id = R.string.profile_title)
|
||||
)
|
||||
|
||||
Text(
|
||||
style = MaterialTheme.typography.h6,
|
||||
color = MaterialTheme.colors.primary,
|
||||
|
|
@ -94,14 +99,28 @@ private fun ProfileScreenContent(
|
|||
modifier = Modifier.padding(top = MaterialTheme.bibLib.dimen.dp16),
|
||||
style = MaterialTheme.typography.body1,
|
||||
color = MaterialTheme.colors.onSurface,
|
||||
text = "Linked emails:"
|
||||
text = stringResource(id = R.string.profile_emails)
|
||||
)
|
||||
user.amazonEmails.forEach {
|
||||
Text(
|
||||
style = MaterialTheme.typography.caption,
|
||||
color = MaterialTheme.colors.onSurface,
|
||||
text = it,
|
||||
)
|
||||
LazyColumn {
|
||||
if (user.amazonEmails.isEmpty()) {
|
||||
item {
|
||||
Text(
|
||||
style = MaterialTheme.typography.caption,
|
||||
color = MaterialTheme.colors.error,
|
||||
text = stringResource(id = R.string.profile_emails_empty),
|
||||
)
|
||||
}
|
||||
} else {
|
||||
items(
|
||||
items = user.amazonEmails
|
||||
) {
|
||||
Text(
|
||||
style = MaterialTheme.typography.caption,
|
||||
color = MaterialTheme.colors.onSurface,
|
||||
text = it,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Button(
|
||||
|
|
@ -117,19 +136,18 @@ private fun ProfileScreenContent(
|
|||
)
|
||||
Text(
|
||||
modifier = Modifier.padding(start = MaterialTheme.bibLib.dimen.dp8),
|
||||
text = "Edit profile"
|
||||
text = stringResource(id = R.string.profile_edit_action)
|
||||
)
|
||||
}
|
||||
|
||||
Button(
|
||||
modifier = Modifier
|
||||
|
||||
.align(Alignment.End),
|
||||
colors = ButtonDefaults.outlinedButtonColors(),
|
||||
onClick = onLogoutClick,
|
||||
) {
|
||||
Text(
|
||||
text = "Logout"
|
||||
text = stringResource(id = R.string.profile_logout_action)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
package com.pixelized.biblib.ui.screen.home.page.profile
|
||||
|
||||
import android.util.Log
|
||||
import androidx.compose.runtime.derivedStateOf
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.compose.runtime.setValue
|
||||
|
|
@ -15,6 +16,7 @@ import com.pixelized.biblib.ui.composable.StateUio
|
|||
import dagger.hilt.android.lifecycle.HiltViewModel
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.withContext
|
||||
import javax.inject.Inject
|
||||
|
||||
@HiltViewModel
|
||||
|
|
@ -27,13 +29,19 @@ class ProfileViewModel @Inject constructor(
|
|||
var user by mutableStateOf<StateUio<UserUio>>(StateUio.Progress())
|
||||
private set
|
||||
|
||||
init {
|
||||
updateUser()
|
||||
val mails: List<String> by derivedStateOf {
|
||||
(user as? StateUio.Success<UserUio>)?.value?.amazonEmails ?: emptyList()
|
||||
}
|
||||
|
||||
private fun updateUser() {
|
||||
init {
|
||||
viewModelScope.launch(Dispatchers.IO) {
|
||||
user = try {
|
||||
updateUser()
|
||||
}
|
||||
}
|
||||
|
||||
suspend fun updateUser(): StateUio<UserUio> {
|
||||
return withContext(Dispatchers.IO) {
|
||||
try {
|
||||
val factory = UserFactory()
|
||||
val response = client.service.user()
|
||||
val data = factory.fromUserResponseToUser(response)
|
||||
|
|
@ -41,6 +49,8 @@ class ProfileViewModel @Inject constructor(
|
|||
} catch (exception: Exception) {
|
||||
Log.e("AccountViewModel", exception.message, exception)
|
||||
StateUio.Failure(exception)
|
||||
}.also {
|
||||
user = it
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -21,6 +21,7 @@
|
|||
<string name="error_book_update_message">La mise à jour de la librarie à échouée.</string>
|
||||
<string name="error_get_book_detail_message">La récupération des détails a échouée.</string>
|
||||
<string name="error_send_book_message">L\'envoi de l\'eBook a échoué.</string>
|
||||
<string name="error_send_no_amazon_email_message">Vous n\'avez aucun mail lié à votre compte. Merci de vous rendre sur https://bib.bibulle.fr/profile pour en ajouter un.</string>
|
||||
|
||||
<!-- Dialogs -->
|
||||
|
||||
|
|
@ -28,7 +29,6 @@
|
|||
<string name="error_authentication">Oups, la connection a échoué !</string>
|
||||
<string name="error_book">Oups! le téléchargement de la librairy à échoué !</string>
|
||||
<string name="error_offline">Vous êtes hors ligne.</string>
|
||||
<string name="error_no_amazon_email">Vous n\'avez aucun mail lié à votre compte. Merci de vous rendre sur https://bib.bibulle.fr/ et d\'éditez voter profile pour en ajouter un.</string>
|
||||
<string name="loading_authentication">Ouverture de BibLibrary.</string>
|
||||
<string name="loading_book">Téléchargement de BibLibrary.</string>
|
||||
|
||||
|
|
@ -70,6 +70,10 @@
|
|||
|
||||
<string name="search_sort_by">Trié par : %1$s</string>
|
||||
|
||||
<string name="profile_title">Profile</string>
|
||||
<string name="profile_title">Bonjour</string>
|
||||
<string name="profile_emails">Amails associés :</string>
|
||||
<string name="profile_emails_empty">Aucun email associé</string>
|
||||
<string name="profile_edit_action">Édition du profile</string>
|
||||
<string name="profile_logout_action">Déconnexion</string>
|
||||
|
||||
</resources>
|
||||
|
|
@ -32,6 +32,8 @@
|
|||
<string name="error_get_book_detail_action" translatable="false">@string/error_action_retry</string>
|
||||
<string name="error_send_book_message">Failed to send the book to your kindle.</string>
|
||||
<string name="error_send_book_action" translatable="false">@string/error_action_retry</string>
|
||||
<string name="error_send_no_amazon_email_message">You have no email linked to your account. Please go to https://bib.bibulle.fr/profile to add one.</string>
|
||||
<string name="error_send_no_amazon_email_action" translatable="false">@string/error_action_retry</string>
|
||||
|
||||
<!-- Dialogs -->
|
||||
|
||||
|
|
@ -39,7 +41,6 @@
|
|||
<string name="error_authentication">Oops, connection failed!</string>
|
||||
<string name="error_book">Oops! library download failed!</string>
|
||||
<string name="error_offline">You are offline.</string>
|
||||
<string name="error_no_amazon_email">You have no email linked to your account. Please go to https://bib.bibulle.fr/ and edit your profile to add one.</string>
|
||||
|
||||
<string name="loading_authentication">Opening the BibLibrary.</string>
|
||||
<string name="loading_book">Downloading the BibLibrary.</string>
|
||||
|
|
@ -82,6 +83,10 @@
|
|||
|
||||
<string name="search_sort_by">Sort by: %1$s</string>
|
||||
|
||||
<string name="profile_title">Profil</string>
|
||||
<string name="profile_title">Welcome</string>
|
||||
<string name="profile_emails">Linked emails:</string>
|
||||
<string name="profile_emails_empty">no associated email</string>
|
||||
<string name="profile_edit_action">Edit profile</string>
|
||||
<string name="profile_logout_action">Logout</string>
|
||||
|
||||
</resources>
|
||||
Loading…
Add table
Add a link
Reference in a new issue