Add book update after login.

This commit is contained in:
Thomas Andres Gomez 2022-07-05 12:34:40 +02:00
parent eacc395195
commit 3b5f1dae97
5 changed files with 87 additions and 34 deletions

View file

@ -0,0 +1,49 @@
package com.pixelized.biblib.repository.book
import com.pixelized.biblib.network.client.IBibLibClient
import com.pixelized.biblib.network.factory.BookFactory
import com.pixelized.biblib.repository.apiCache.IAPICacheRepository
suspend fun updateBooks(
client: IBibLibClient,
cache: IAPICacheRepository,
repository: IBookRepository,
): Boolean {
return loadNewBooks(client, cache) || loadAllBooks(client, cache, repository)
}
suspend fun loadNewBooks(
client: IBibLibClient,
cache: IAPICacheRepository,
): Boolean {
val cached = cache.new
val updated = client.service.new()
return if (cached != updated) {
cache.new = updated
true
} else {
false
}
}
suspend fun loadAllBooks(
client: IBibLibClient,
cache: IAPICacheRepository,
repository: IBookRepository,
): Boolean {
client.service.list().let { response ->
val newIds = cache.new?.data?.map { it.book_id } ?: listOf()
val factory = BookFactory()
val books = response.data?.mapNotNull { dto ->
val isNew = newIds.contains(dto.book_id)
val index = newIds.indexOf(dto.book_id)
try {
factory.fromListResponseToBook(dto, isNew, index)
} catch (exception: Exception) {
null
}
}
books?.let { data -> repository.update(data) }
}
return true
}

View file

@ -73,7 +73,7 @@ fun Search(
text = "Rechercher sur BibLib"
)
},
value = if (state.isCollapsed()) "" else search,
value = if (state.content == SearchScaffoldState.ContentState.SEARCH) search else "",
singleLine = true,
enabled = state.content == SearchScaffoldState.ContentState.SEARCH,
readOnly = state.content != SearchScaffoldState.ContentState.SEARCH,

View file

@ -24,7 +24,7 @@ fun SearchScaffold(
search: @Composable () -> Unit,
content: @Composable () -> Unit,
) {
var initialCardBoxHeight by remember { mutableStateOf(0) }
var initialCardBoxHeight by rememberSaveable { mutableStateOf(0) }
Layout(
modifier = modifier,
content = {
@ -95,11 +95,12 @@ fun rememberSearchScaffoldState(
@Stable
class SearchScaffoldState(
expended: Boolean
expended: Boolean,
state: ContentState = ContentState.INITIAL,
) {
private var expended: Boolean by mutableStateOf(expended)
var content: ContentState by mutableStateOf(ContentState.INITIAL)
var content: ContentState by mutableStateOf(state)
private set
fun isCollapsed(): Boolean = expended.not()
@ -115,9 +116,9 @@ class SearchScaffoldState(
}
companion object {
val Saver: Saver<SearchScaffoldState, Boolean> = Saver(
save = { it.expended },
restore = { SearchScaffoldState(it) },
val Saver: Saver<SearchScaffoldState, Pair<Boolean, Int>> = Saver(
save = { it.expended to it.content.ordinal },
restore = { SearchScaffoldState(it.first, ContentState.values()[it.second]) },
)
}

View file

@ -14,6 +14,11 @@ import com.google.android.gms.auth.api.signin.GoogleSignIn
import com.google.android.gms.common.api.ApiException
import com.pixelized.biblib.network.client.IBibLibClient
import com.pixelized.biblib.network.data.query.AuthLoginQuery
import com.pixelized.biblib.network.data.response.BookListResponse
import com.pixelized.biblib.network.factory.BookFactory
import com.pixelized.biblib.repository.apiCache.IAPICacheRepository
import com.pixelized.biblib.repository.book.IBookRepository
import com.pixelized.biblib.repository.book.updateBooks
import com.pixelized.biblib.repository.credential.CredentialRepository_Factory
import com.pixelized.biblib.repository.credential.ICredentialRepository
import com.pixelized.biblib.repository.googleSignIn.IGoogleSingInRepository
@ -31,6 +36,8 @@ class AuthenticationViewModel @Inject constructor(
private val credentialRepository: ICredentialRepository,
private val googleSignIn: IGoogleSingInRepository,
private val client: IBibLibClient,
private val bookRepository: IBookRepository,
private val apiCache: IAPICacheRepository,
) : ViewModel() {
private var launcher: ActivityResultLauncher<Intent>? = null
@ -51,6 +58,8 @@ class AuthenticationViewModel @Inject constructor(
val idToken = response.token ?: throw MissingTokenException()
client.token = idToken
credentialRepository.bearer = response.token
// update book if needed
updateBooks()
_authenticationProcess.value = StateUio.Success(Unit)
} catch (exception: Exception) {
Log.e("AuthenticationViewModel", exception.message, exception)
@ -77,6 +86,8 @@ class AuthenticationViewModel @Inject constructor(
val response = client.service.loginWithGoogle(token = googleToken)
val token = response.token ?: throw MissingTokenException()
client.token = token
// update book if needed
updateBooks()
_authenticationProcess.value = StateUio.Success(Unit)
} catch (exception: Exception) {
Log.e("AuthenticationViewModel", exception.message, exception)
@ -91,6 +102,16 @@ class AuthenticationViewModel @Inject constructor(
launcher?.launch(googleSignIn.client.signInIntent)
}
// endregion
//////////////////////////////////////
// region: Books update
private suspend fun updateBooks(): Boolean = updateBooks(
client = client,
cache = apiCache,
repository = bookRepository,
)
// endregion
//////////////////////////////////////
// region: Dialog

View file

@ -10,11 +10,13 @@ import com.pixelized.biblib.network.data.query.AuthLoginQuery
import com.pixelized.biblib.network.factory.BookFactory
import com.pixelized.biblib.repository.apiCache.IAPICacheRepository
import com.pixelized.biblib.repository.book.IBookRepository
import com.pixelized.biblib.repository.book.updateBooks
import com.pixelized.biblib.repository.credential.ICredentialRepository
import com.pixelized.biblib.repository.googleSignIn.IGoogleSingInRepository
import com.pixelized.biblib.ui.navigation.screen.Screen
import dagger.hilt.android.lifecycle.HiltViewModel
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
import javax.inject.Inject
@ -38,12 +40,11 @@ class LauncherViewModel @Inject constructor(
// Try to Authenticate
if (autoLoginWithGoogle() || autologinWithCredential()) {
// Update book
if (loadNewBooks()) {
loadAllBooks()
}
updateBooks()
// Change the start destination
startDestination = Screen.Home
}
delay(1000)
// Update loading state.
isLoadingDone = true
}
@ -99,28 +100,9 @@ class LauncherViewModel @Inject constructor(
//////////////////////////////////////
// region: Books update
private suspend fun loadNewBooks(): Boolean {
val cached = apiCache.new
val updated = client.service.new()
return if (cached != updated) {
apiCache.new = updated
true
} else {
false
}
}
private suspend fun loadAllBooks(): Boolean {
client.service.list().let { response ->
val newIds = apiCache.new?.data?.map { it.book_id } ?: listOf()
val factory = BookFactory()
val books = response.data?.map { dto ->
val isNew = newIds.contains(dto.book_id)
val index = newIds.indexOf(dto.book_id)
factory.fromListResponseToBook(dto, isNew, index)
}
books?.let { data -> bookRepository.update(data) }
}
return true
}
private suspend fun updateBooks(): Boolean = updateBooks(
client = client,
cache = apiCache,
repository = bookRepository,
)
}