Fix dumb mistake with google sign in.
This commit is contained in:
parent
1e58752008
commit
4b5893cf43
7 changed files with 67 additions and 43 deletions
|
|
@ -102,6 +102,8 @@ dependencies {
|
||||||
implementation 'com.squareup.retrofit2:retrofit:2.9.0'
|
implementation 'com.squareup.retrofit2:retrofit:2.9.0'
|
||||||
implementation 'com.squareup.retrofit2:converter-gson:2.9.0'
|
implementation 'com.squareup.retrofit2:converter-gson:2.9.0'
|
||||||
implementation 'com.google.code.gson:gson:2.8.6'
|
implementation 'com.google.code.gson:gson:2.8.6'
|
||||||
|
//Logging Network Calls
|
||||||
|
implementation 'com.squareup.okhttp3:logging-interceptor:4.8.1'
|
||||||
|
|
||||||
// Room
|
// Room
|
||||||
implementation "androidx.room:room-runtime:2.3.0"
|
implementation "androidx.room:room-runtime:2.3.0"
|
||||||
|
|
|
||||||
|
|
@ -1,26 +1,38 @@
|
||||||
package com.pixelized.biblib.network.client
|
package com.pixelized.biblib.network.client
|
||||||
|
|
||||||
import com.google.gson.Gson
|
import com.google.gson.Gson
|
||||||
import com.pixelized.biblib.utils.injection.inject
|
|
||||||
import com.pixelized.biblib.network.client.IBibLibClient.Companion.BASE_URL
|
import com.pixelized.biblib.network.client.IBibLibClient.Companion.BASE_URL
|
||||||
|
import com.pixelized.biblib.utils.injection.inject
|
||||||
import okhttp3.OkHttpClient
|
import okhttp3.OkHttpClient
|
||||||
|
import okhttp3.logging.HttpLoggingInterceptor
|
||||||
import retrofit2.Retrofit
|
import retrofit2.Retrofit
|
||||||
import retrofit2.converter.gson.GsonConverterFactory
|
import retrofit2.converter.gson.GsonConverterFactory
|
||||||
|
|
||||||
|
|
||||||
class BibLibClient : IBibLibClient {
|
class BibLibClient : IBibLibClient {
|
||||||
private val gson by inject<Gson>()
|
private val gson by inject<Gson>()
|
||||||
private val interceptor = BearerInterceptor()
|
private val bearerInterceptor = BearerInterceptor()
|
||||||
|
private val httpInterceptor = HttpLoggingInterceptor().apply {
|
||||||
|
this.level = HttpLoggingInterceptor.Level.BODY
|
||||||
|
}
|
||||||
private val retrofit: Retrofit = Retrofit.Builder()
|
private val retrofit: Retrofit = Retrofit.Builder()
|
||||||
.addConverterFactory(GsonConverterFactory.create(gson))
|
.addConverterFactory(GsonConverterFactory.create(gson))
|
||||||
.client(OkHttpClient.Builder().addInterceptor(interceptor).build())
|
.client(
|
||||||
|
OkHttpClient.Builder()
|
||||||
|
.addInterceptor(bearerInterceptor)
|
||||||
|
.addInterceptor(httpInterceptor)
|
||||||
|
.build()
|
||||||
|
)
|
||||||
.baseUrl(BASE_URL)
|
.baseUrl(BASE_URL)
|
||||||
.build()
|
.build()
|
||||||
|
|
||||||
override val service: IBibLibWebServiceAPI = retrofit.create(IBibLibWebServiceAPI::class.java)
|
override val service: IBibLibWebServiceAPI = retrofit.create(IBibLibWebServiceAPI::class.java)
|
||||||
|
|
||||||
override var token: String?
|
override var token: String?
|
||||||
get() = interceptor.token
|
get() = bearerInterceptor.token
|
||||||
set(value) { interceptor.token = value }
|
set(value) {
|
||||||
|
bearerInterceptor.token = value
|
||||||
|
}
|
||||||
|
|
||||||
// endregion
|
// endregion
|
||||||
}
|
}
|
||||||
|
|
@ -21,7 +21,6 @@ class BookRepository : IBookRepository {
|
||||||
database.bookDao().getBook().map { it.toBook() }
|
database.bookDao().getBook().map { it.toBook() }
|
||||||
|
|
||||||
override suspend fun update(data: List<Book>) {
|
override suspend fun update(data: List<Book>) {
|
||||||
Log.d("pouet", "BookRepository#update(): $data")
|
|
||||||
val authors = mutableSetOf<AuthorDbo>()
|
val authors = mutableSetOf<AuthorDbo>()
|
||||||
val genres = mutableSetOf<GenreDbo>()
|
val genres = mutableSetOf<GenreDbo>()
|
||||||
val series = mutableSetOf<SeriesDbo>()
|
val series = mutableSetOf<SeriesDbo>()
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,7 @@ package com.pixelized.biblib.ui.composable.screen
|
||||||
|
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
import android.net.Uri
|
import android.net.Uri
|
||||||
|
import android.util.Log
|
||||||
import androidx.compose.animation.AnimatedVisibility
|
import androidx.compose.animation.AnimatedVisibility
|
||||||
import androidx.compose.animation.ExperimentalAnimationApi
|
import androidx.compose.animation.ExperimentalAnimationApi
|
||||||
import androidx.compose.animation.expandVertically
|
import androidx.compose.animation.expandVertically
|
||||||
|
|
@ -51,6 +52,7 @@ import com.pixelized.biblib.ui.viewmodel.credential.CredentialViewModel
|
||||||
import com.pixelized.biblib.ui.viewmodel.credential.ICredentialViewModel
|
import com.pixelized.biblib.ui.viewmodel.credential.ICredentialViewModel
|
||||||
import com.pixelized.biblib.ui.viewmodel.navigation.INavigationViewModel
|
import com.pixelized.biblib.ui.viewmodel.navigation.INavigationViewModel
|
||||||
import com.pixelized.biblib.ui.viewmodel.navigation.NavigationViewModel
|
import com.pixelized.biblib.ui.viewmodel.navigation.NavigationViewModel
|
||||||
|
import kotlinx.coroutines.delay
|
||||||
|
|
||||||
|
|
||||||
private const val LE_LOAD_BOOK = "LE_LOAD_BOOK"
|
private const val LE_LOAD_BOOK = "LE_LOAD_BOOK"
|
||||||
|
|
@ -62,6 +64,10 @@ fun LoginScreenComposable(
|
||||||
authenticationViewModel: IAuthenticationViewModel = viewModel<AuthenticationViewModel>(),
|
authenticationViewModel: IAuthenticationViewModel = viewModel<AuthenticationViewModel>(),
|
||||||
bookViewModel: IBooksViewModel = viewModel<BooksViewModel>()
|
bookViewModel: IBooksViewModel = viewModel<BooksViewModel>()
|
||||||
) {
|
) {
|
||||||
|
LaunchedEffect("merde") {
|
||||||
|
authenticationViewModel.clearState()
|
||||||
|
}
|
||||||
|
|
||||||
Box(
|
Box(
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.fillMaxWidth()
|
.fillMaxWidth()
|
||||||
|
|
@ -105,11 +111,11 @@ private fun LoginScreenDialogComposable(
|
||||||
authenticationViewModel: IAuthenticationViewModel,
|
authenticationViewModel: IAuthenticationViewModel,
|
||||||
booksViewModel: IBooksViewModel,
|
booksViewModel: IBooksViewModel,
|
||||||
) {
|
) {
|
||||||
val authState = authenticationViewModel.state.observeAsState()
|
val authState by authenticationViewModel.state.observeAsState()
|
||||||
val bookState = booksViewModel.state.observeAsState()
|
val bookState by booksViewModel.state.observeAsState()
|
||||||
|
|
||||||
val visible = authState.value is IAuthenticationViewModel.State.Error
|
val visible = authState !is IAuthenticationViewModel.State.Initial
|
||||||
|| bookState.value is IBooksViewModel.State.Error
|
|| bookState !is IBooksViewModel.State.Initial
|
||||||
|
|
||||||
CrossFadeOverlay(
|
CrossFadeOverlay(
|
||||||
modifier = Modifier.clickable {
|
modifier = Modifier.clickable {
|
||||||
|
|
@ -121,19 +127,19 @@ private fun LoginScreenDialogComposable(
|
||||||
) {
|
) {
|
||||||
AnimatedVisibility(
|
AnimatedVisibility(
|
||||||
modifier = Modifier.align(Alignment.Center),
|
modifier = Modifier.align(Alignment.Center),
|
||||||
visible = authState.value is IAuthenticationViewModel.State.Error,
|
visible = authState is IAuthenticationViewModel.State.Error,
|
||||||
initiallyVisible = false,
|
initiallyVisible = false,
|
||||||
enter = expandVertically(Alignment.CenterVertically),
|
enter = expandVertically(Alignment.CenterVertically),
|
||||||
exit = shrinkVertically(Alignment.CenterVertically),
|
exit = shrinkVertically(Alignment.CenterVertically),
|
||||||
) {
|
) {
|
||||||
ErrorCard(
|
ErrorCard(
|
||||||
message = stringResource(id = R.string.error_authentication),
|
message = stringResource(id = R.string.error_authentication),
|
||||||
exception = (authState.value as? IAuthenticationViewModel.State.Error)?.exception
|
exception = (authState as? IAuthenticationViewModel.State.Error)?.exception
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
AnimatedVisibility(
|
AnimatedVisibility(
|
||||||
modifier = Modifier.align(Alignment.Center),
|
modifier = Modifier.align(Alignment.Center),
|
||||||
visible = authState.value is IAuthenticationViewModel.State.Loading,
|
visible = authState is IAuthenticationViewModel.State.Loading,
|
||||||
initiallyVisible = false,
|
initiallyVisible = false,
|
||||||
enter = expandVertically(Alignment.CenterVertically),
|
enter = expandVertically(Alignment.CenterVertically),
|
||||||
exit = shrinkVertically(Alignment.CenterVertically),
|
exit = shrinkVertically(Alignment.CenterVertically),
|
||||||
|
|
@ -144,7 +150,7 @@ private fun LoginScreenDialogComposable(
|
||||||
}
|
}
|
||||||
AnimatedVisibility(
|
AnimatedVisibility(
|
||||||
modifier = Modifier.align(Alignment.Center),
|
modifier = Modifier.align(Alignment.Center),
|
||||||
visible = (authState.value as? IAuthenticationViewModel.State.Finished)?.logged
|
visible = (authState as? IAuthenticationViewModel.State.Finished)?.logged
|
||||||
?: false,
|
?: false,
|
||||||
initiallyVisible = false,
|
initiallyVisible = false,
|
||||||
enter = expandVertically(Alignment.CenterVertically),
|
enter = expandVertically(Alignment.CenterVertically),
|
||||||
|
|
@ -156,19 +162,19 @@ private fun LoginScreenDialogComposable(
|
||||||
}
|
}
|
||||||
AnimatedVisibility(
|
AnimatedVisibility(
|
||||||
modifier = Modifier.align(Alignment.Center),
|
modifier = Modifier.align(Alignment.Center),
|
||||||
visible = bookState.value is IBooksViewModel.State.Error,
|
visible = bookState is IBooksViewModel.State.Error,
|
||||||
initiallyVisible = false,
|
initiallyVisible = false,
|
||||||
enter = expandVertically(Alignment.CenterVertically),
|
enter = expandVertically(Alignment.CenterVertically),
|
||||||
exit = shrinkVertically(Alignment.CenterVertically),
|
exit = shrinkVertically(Alignment.CenterVertically),
|
||||||
) {
|
) {
|
||||||
ErrorCard(
|
ErrorCard(
|
||||||
message = stringResource(id = R.string.error_book),
|
message = stringResource(id = R.string.error_book),
|
||||||
exception = (bookState.value as? IBooksViewModel.State.Error)?.exception
|
exception = (bookState as? IBooksViewModel.State.Error)?.exception
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
AnimatedVisibility(
|
AnimatedVisibility(
|
||||||
modifier = Modifier.align(Alignment.Center),
|
modifier = Modifier.align(Alignment.Center),
|
||||||
visible = bookState.value is IBooksViewModel.State.Loading,
|
visible = bookState is IBooksViewModel.State.Loading,
|
||||||
initiallyVisible = false,
|
initiallyVisible = false,
|
||||||
enter = expandVertically(Alignment.CenterVertically),
|
enter = expandVertically(Alignment.CenterVertically),
|
||||||
exit = shrinkVertically(Alignment.CenterVertically),
|
exit = shrinkVertically(Alignment.CenterVertically),
|
||||||
|
|
@ -179,7 +185,7 @@ private fun LoginScreenDialogComposable(
|
||||||
}
|
}
|
||||||
AnimatedVisibility(
|
AnimatedVisibility(
|
||||||
modifier = Modifier.align(Alignment.Center),
|
modifier = Modifier.align(Alignment.Center),
|
||||||
visible = bookState.value is IBooksViewModel.State.Finished,
|
visible = bookState is IBooksViewModel.State.Finished,
|
||||||
initiallyVisible = false,
|
initiallyVisible = false,
|
||||||
enter = expandVertically(Alignment.CenterVertically),
|
enter = expandVertically(Alignment.CenterVertically),
|
||||||
exit = shrinkVertically(Alignment.CenterVertically),
|
exit = shrinkVertically(Alignment.CenterVertically),
|
||||||
|
|
@ -197,18 +203,20 @@ private fun LoginScreenNavigationComposable(
|
||||||
authenticationViewModel: IAuthenticationViewModel,
|
authenticationViewModel: IAuthenticationViewModel,
|
||||||
bookViewModel: IBooksViewModel,
|
bookViewModel: IBooksViewModel,
|
||||||
) {
|
) {
|
||||||
val authenticationState = authenticationViewModel.state.observeAsState()
|
val authenticationState by authenticationViewModel.state.observeAsState()
|
||||||
(authenticationState.value as? IAuthenticationViewModel.State.Finished)?.let {
|
(authenticationState as? IAuthenticationViewModel.State.Finished)?.let {
|
||||||
if (it.logged) {
|
if (it.logged) {
|
||||||
LaunchedEffect(LE_LOAD_BOOK) {
|
LaunchedEffect(LE_LOAD_BOOK) {
|
||||||
|
delay(1000)
|
||||||
bookViewModel.updateBooks()
|
bookViewModel.updateBooks()
|
||||||
}
|
}
|
||||||
val bookLoadingState = bookViewModel.state.observeAsState()
|
|
||||||
if (bookLoadingState.value is IBooksViewModel.State.Finished) {
|
|
||||||
navigationViewModel.navigateTo(INavigationViewModel.Screen.MainScreen)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
val bookLoadingState by bookViewModel.state.observeAsState()
|
||||||
|
if (bookLoadingState is IBooksViewModel.State.Finished) {
|
||||||
|
navigationViewModel.navigateTo(INavigationViewModel.Screen.MainScreen)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
|
|
@ -379,15 +387,11 @@ private fun CredentialRemember(
|
||||||
@Composable
|
@Composable
|
||||||
fun LoginScreenComposablePreview() {
|
fun LoginScreenComposablePreview() {
|
||||||
BibLibTheme {
|
BibLibTheme {
|
||||||
val navigationViewModel = INavigationViewModel.Mock()
|
|
||||||
val credentialViewModel = ICredentialViewModel.Mock()
|
|
||||||
val authenticationViewModel = IAuthenticationViewModel.Mock()
|
|
||||||
val bookViewModel = IBooksViewModel.Mock()
|
|
||||||
LoginScreenComposable(
|
LoginScreenComposable(
|
||||||
navigationViewModel,
|
navigationViewModel = INavigationViewModel.Mock(),
|
||||||
credentialViewModel,
|
credentialViewModel = ICredentialViewModel.Mock(),
|
||||||
authenticationViewModel,
|
authenticationViewModel = IAuthenticationViewModel.Mock(),
|
||||||
bookViewModel,
|
bookViewModel = IBooksViewModel.Mock(),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -11,13 +11,13 @@ import androidx.lifecycle.MutableLiveData
|
||||||
import androidx.lifecycle.ViewModel
|
import androidx.lifecycle.ViewModel
|
||||||
import androidx.lifecycle.viewModelScope
|
import androidx.lifecycle.viewModelScope
|
||||||
import com.google.android.gms.auth.api.signin.GoogleSignIn
|
import com.google.android.gms.auth.api.signin.GoogleSignIn
|
||||||
import com.google.android.gms.auth.api.signin.GoogleSignInAccount
|
|
||||||
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.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.viewmodel.authentication.IAuthenticationViewModel.State
|
import com.pixelized.biblib.ui.viewmodel.authentication.IAuthenticationViewModel.State
|
||||||
|
import com.pixelized.biblib.utils.exception.MissingGoogleTokenException
|
||||||
import com.pixelized.biblib.utils.exception.MissingTokenException
|
import com.pixelized.biblib.utils.exception.MissingTokenException
|
||||||
import com.pixelized.biblib.utils.injection.inject
|
import com.pixelized.biblib.utils.injection.inject
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
|
|
@ -77,15 +77,19 @@ class AuthenticationViewModel : ViewModel(), IAuthenticationViewModel {
|
||||||
launcher = rememberLauncherForActivityResult(
|
launcher = rememberLauncherForActivityResult(
|
||||||
ActivityResultContracts.StartActivityForResult()
|
ActivityResultContracts.StartActivityForResult()
|
||||||
) {
|
) {
|
||||||
try {
|
viewModelScope.launch(Dispatchers.IO) {
|
||||||
val task = GoogleSignIn.getSignedInAccountFromIntent(it.data)
|
try {
|
||||||
val account: GoogleSignInAccount? = task.getResult(ApiException::class.java)
|
val task = GoogleSignIn.getSignedInAccountFromIntent(it.data)
|
||||||
val idToken = account?.idToken ?: throw MissingTokenException()
|
val account = task.getResult(ApiException::class.java)
|
||||||
client.token = idToken
|
val googleToken = account?.idToken ?: throw MissingGoogleTokenException()
|
||||||
_state.postValue(State.Finished(true))
|
val response = client.service.loginWithGoogle(googleToken)
|
||||||
} catch (exception: Exception) {
|
val token = response.token ?: throw MissingTokenException()
|
||||||
Log.e("AuthenticationViewModel", exception.message, exception)
|
client.token = token
|
||||||
_state.postValue(State.Error(exception))
|
_state.postValue(State.Finished(true))
|
||||||
|
} catch (exception: Exception) {
|
||||||
|
Log.e("AuthenticationViewModel", exception.message, exception)
|
||||||
|
_state.postValue(State.Error(exception))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -24,7 +24,7 @@ class BooksViewModel : ViewModel(), IBooksViewModel {
|
||||||
private val client: IBibLibClient by inject()
|
private val client: IBibLibClient by inject()
|
||||||
private val apiCache: IAPICacheRepository by inject()
|
private val apiCache: IAPICacheRepository by inject()
|
||||||
|
|
||||||
private val _state = MutableLiveData<IBooksViewModel.State>()
|
private val _state = MutableLiveData<IBooksViewModel.State>(IBooksViewModel.State.Initial)
|
||||||
override val state: LiveData<IBooksViewModel.State> get() = _state
|
override val state: LiveData<IBooksViewModel.State> get() = _state
|
||||||
|
|
||||||
private val source
|
private val source
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,3 @@
|
||||||
|
package com.pixelized.biblib.utils.exception
|
||||||
|
|
||||||
|
class MissingGoogleTokenException: RuntimeException("Google login response miss token data.")
|
||||||
Loading…
Add table
Add a link
Reference in a new issue