diff --git a/app/src/main/java/com/pixelized/biblib/repository/book/BookUtils.kt b/app/src/main/java/com/pixelized/biblib/repository/book/BookUtils.kt new file mode 100644 index 0000000..a152189 --- /dev/null +++ b/app/src/main/java/com/pixelized/biblib/repository/book/BookUtils.kt @@ -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 +} \ No newline at end of file diff --git a/app/src/main/java/com/pixelized/biblib/ui/composable/Search.kt b/app/src/main/java/com/pixelized/biblib/ui/composable/Search.kt index 94c26b7..b350ec0 100644 --- a/app/src/main/java/com/pixelized/biblib/ui/composable/Search.kt +++ b/app/src/main/java/com/pixelized/biblib/ui/composable/Search.kt @@ -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, diff --git a/app/src/main/java/com/pixelized/biblib/ui/scaffold/SearchScaffold.kt b/app/src/main/java/com/pixelized/biblib/ui/scaffold/SearchScaffold.kt index c8f384c..51ca4d1 100644 --- a/app/src/main/java/com/pixelized/biblib/ui/scaffold/SearchScaffold.kt +++ b/app/src/main/java/com/pixelized/biblib/ui/scaffold/SearchScaffold.kt @@ -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 = Saver( - save = { it.expended }, - restore = { SearchScaffoldState(it) }, + val Saver: Saver> = Saver( + save = { it.expended to it.content.ordinal }, + restore = { SearchScaffoldState(it.first, ContentState.values()[it.second]) }, ) } diff --git a/app/src/main/java/com/pixelized/biblib/ui/screen/authentication/viewModel/AuthenticationViewModel.kt b/app/src/main/java/com/pixelized/biblib/ui/screen/authentication/viewModel/AuthenticationViewModel.kt index 534d5e4..a9a330d 100644 --- a/app/src/main/java/com/pixelized/biblib/ui/screen/authentication/viewModel/AuthenticationViewModel.kt +++ b/app/src/main/java/com/pixelized/biblib/ui/screen/authentication/viewModel/AuthenticationViewModel.kt @@ -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? = 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 diff --git a/app/src/main/java/com/pixelized/biblib/ui/screen/launch/LauncherViewModel.kt b/app/src/main/java/com/pixelized/biblib/ui/screen/launch/LauncherViewModel.kt index ad2fd3b..089d570 100644 --- a/app/src/main/java/com/pixelized/biblib/ui/screen/launch/LauncherViewModel.kt +++ b/app/src/main/java/com/pixelized/biblib/ui/screen/launch/LauncherViewModel.kt @@ -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, + ) } \ No newline at end of file