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" text = "Rechercher sur BibLib"
) )
}, },
value = if (state.isCollapsed()) "" else search, value = if (state.content == SearchScaffoldState.ContentState.SEARCH) search else "",
singleLine = true, singleLine = true,
enabled = state.content == SearchScaffoldState.ContentState.SEARCH, enabled = state.content == SearchScaffoldState.ContentState.SEARCH,
readOnly = state.content != SearchScaffoldState.ContentState.SEARCH, readOnly = state.content != SearchScaffoldState.ContentState.SEARCH,

View file

@ -24,7 +24,7 @@ fun SearchScaffold(
search: @Composable () -> Unit, search: @Composable () -> Unit,
content: @Composable () -> Unit, content: @Composable () -> Unit,
) { ) {
var initialCardBoxHeight by remember { mutableStateOf(0) } var initialCardBoxHeight by rememberSaveable { mutableStateOf(0) }
Layout( Layout(
modifier = modifier, modifier = modifier,
content = { content = {
@ -95,11 +95,12 @@ fun rememberSearchScaffoldState(
@Stable @Stable
class SearchScaffoldState( class SearchScaffoldState(
expended: Boolean expended: Boolean,
state: ContentState = ContentState.INITIAL,
) { ) {
private var expended: Boolean by mutableStateOf(expended) private var expended: Boolean by mutableStateOf(expended)
var content: ContentState by mutableStateOf(ContentState.INITIAL) var content: ContentState by mutableStateOf(state)
private set private set
fun isCollapsed(): Boolean = expended.not() fun isCollapsed(): Boolean = expended.not()
@ -115,9 +116,9 @@ class SearchScaffoldState(
} }
companion object { companion object {
val Saver: Saver<SearchScaffoldState, Boolean> = Saver( val Saver: Saver<SearchScaffoldState, Pair<Boolean, Int>> = Saver(
save = { it.expended }, save = { it.expended to it.content.ordinal },
restore = { SearchScaffoldState(it) }, 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.google.android.gms.common.api.ApiException
import com.pixelized.biblib.network.client.IBibLibClient import com.pixelized.biblib.network.client.IBibLibClient
import com.pixelized.biblib.network.data.query.AuthLoginQuery 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.CredentialRepository_Factory
import com.pixelized.biblib.repository.credential.ICredentialRepository import com.pixelized.biblib.repository.credential.ICredentialRepository
import com.pixelized.biblib.repository.googleSignIn.IGoogleSingInRepository import com.pixelized.biblib.repository.googleSignIn.IGoogleSingInRepository
@ -31,6 +36,8 @@ class AuthenticationViewModel @Inject constructor(
private val credentialRepository: ICredentialRepository, private val credentialRepository: ICredentialRepository,
private val googleSignIn: IGoogleSingInRepository, private val googleSignIn: IGoogleSingInRepository,
private val client: IBibLibClient, private val client: IBibLibClient,
private val bookRepository: IBookRepository,
private val apiCache: IAPICacheRepository,
) : ViewModel() { ) : ViewModel() {
private var launcher: ActivityResultLauncher<Intent>? = null private var launcher: ActivityResultLauncher<Intent>? = null
@ -51,6 +58,8 @@ class AuthenticationViewModel @Inject constructor(
val idToken = response.token ?: throw MissingTokenException() val idToken = response.token ?: throw MissingTokenException()
client.token = idToken client.token = idToken
credentialRepository.bearer = response.token credentialRepository.bearer = response.token
// update book if needed
updateBooks()
_authenticationProcess.value = StateUio.Success(Unit) _authenticationProcess.value = StateUio.Success(Unit)
} catch (exception: Exception) { } catch (exception: Exception) {
Log.e("AuthenticationViewModel", exception.message, exception) Log.e("AuthenticationViewModel", exception.message, exception)
@ -77,6 +86,8 @@ class AuthenticationViewModel @Inject constructor(
val response = client.service.loginWithGoogle(token = googleToken) val response = client.service.loginWithGoogle(token = googleToken)
val token = response.token ?: throw MissingTokenException() val token = response.token ?: throw MissingTokenException()
client.token = token client.token = token
// update book if needed
updateBooks()
_authenticationProcess.value = StateUio.Success(Unit) _authenticationProcess.value = StateUio.Success(Unit)
} catch (exception: Exception) { } catch (exception: Exception) {
Log.e("AuthenticationViewModel", exception.message, exception) Log.e("AuthenticationViewModel", exception.message, exception)
@ -91,6 +102,16 @@ class AuthenticationViewModel @Inject constructor(
launcher?.launch(googleSignIn.client.signInIntent) launcher?.launch(googleSignIn.client.signInIntent)
} }
// endregion
//////////////////////////////////////
// region: Books update
private suspend fun updateBooks(): Boolean = updateBooks(
client = client,
cache = apiCache,
repository = bookRepository,
)
// endregion // endregion
////////////////////////////////////// //////////////////////////////////////
// region: Dialog // 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.network.factory.BookFactory
import com.pixelized.biblib.repository.apiCache.IAPICacheRepository import com.pixelized.biblib.repository.apiCache.IAPICacheRepository
import com.pixelized.biblib.repository.book.IBookRepository 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.credential.ICredentialRepository
import com.pixelized.biblib.repository.googleSignIn.IGoogleSingInRepository import com.pixelized.biblib.repository.googleSignIn.IGoogleSingInRepository
import com.pixelized.biblib.ui.navigation.screen.Screen import com.pixelized.biblib.ui.navigation.screen.Screen
import dagger.hilt.android.lifecycle.HiltViewModel import dagger.hilt.android.lifecycle.HiltViewModel
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import javax.inject.Inject import javax.inject.Inject
@ -38,12 +40,11 @@ class LauncherViewModel @Inject constructor(
// Try to Authenticate // Try to Authenticate
if (autoLoginWithGoogle() || autologinWithCredential()) { if (autoLoginWithGoogle() || autologinWithCredential()) {
// Update book // Update book
if (loadNewBooks()) { updateBooks()
loadAllBooks()
}
// Change the start destination // Change the start destination
startDestination = Screen.Home startDestination = Screen.Home
} }
delay(1000)
// Update loading state. // Update loading state.
isLoadingDone = true isLoadingDone = true
} }
@ -99,28 +100,9 @@ class LauncherViewModel @Inject constructor(
////////////////////////////////////// //////////////////////////////////////
// region: Books update // region: Books update
private suspend fun loadNewBooks(): Boolean { private suspend fun updateBooks(): Boolean = updateBooks(
val cached = apiCache.new client = client,
val updated = client.service.new() cache = apiCache,
return if (cached != updated) { repository = bookRepository,
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
}
} }