diff --git a/.idea/misc.xml b/.idea/misc.xml index 72c05e7..2c29f05 100644 --- a/.idea/misc.xml +++ b/.idea/misc.xml @@ -88,6 +88,8 @@ + + diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index af5b706..a2bb010 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -3,21 +3,24 @@ package="com.pixelized.biblib"> + + - diff --git a/app/src/main/java/com/pixelized/biblib/BibLibApplication.kt b/app/src/main/java/com/pixelized/biblib/BibLibApplication.kt new file mode 100644 index 0000000..fc1db66 --- /dev/null +++ b/app/src/main/java/com/pixelized/biblib/BibLibApplication.kt @@ -0,0 +1,22 @@ +package com.pixelized.biblib + +import android.app.Application +import com.google.gson.Gson +import com.google.gson.GsonBuilder +import com.pixelized.biblib.injection.Bob +import com.pixelized.biblib.network.client.BibLibClient +import com.pixelized.biblib.network.client.IBibLibClient +import com.pixelized.biblib.utils.BitmapCache + +class BibLibApplication : Application() { + + override fun onCreate() { + super.onCreate() + + Bob[BitmapCache::class] = BitmapCache(this) + + Bob[Gson::class] = GsonBuilder().create() + + Bob[IBibLibClient::class] = BibLibClient() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/pixelized/biblib/data/network/query/AuthLoginQuery.kt b/app/src/main/java/com/pixelized/biblib/data/network/query/AuthLoginQuery.kt new file mode 100644 index 0000000..5cdca94 --- /dev/null +++ b/app/src/main/java/com/pixelized/biblib/data/network/query/AuthLoginQuery.kt @@ -0,0 +1,10 @@ +package com.pixelized.biblib.data.network.query + +import com.google.gson.annotations.SerializedName + +data class AuthLoginQuery( + @SerializedName("username") + val username: String?, + @SerializedName("password") + val password: String?, +) \ No newline at end of file diff --git a/app/src/main/java/com/pixelized/biblib/data/network/response/AuthLoginResponse.kt b/app/src/main/java/com/pixelized/biblib/data/network/response/AuthLoginResponse.kt new file mode 100644 index 0000000..c54b0e6 --- /dev/null +++ b/app/src/main/java/com/pixelized/biblib/data/network/response/AuthLoginResponse.kt @@ -0,0 +1,8 @@ +package com.pixelized.biblib.data.network.response + +import com.google.gson.annotations.SerializedName + +data class AuthLoginResponse( + @SerializedName("id_token") + val token: String? = null, +) : ErrorResponse() \ No newline at end of file diff --git a/app/src/main/java/com/pixelized/biblib/data/network/response/ErrorResponse.kt b/app/src/main/java/com/pixelized/biblib/data/network/response/ErrorResponse.kt new file mode 100644 index 0000000..daf1121 --- /dev/null +++ b/app/src/main/java/com/pixelized/biblib/data/network/response/ErrorResponse.kt @@ -0,0 +1,25 @@ +package com.pixelized.biblib.data.network.response + +import com.google.gson.annotations.SerializedName + +open class ErrorResponse( + @SerializedName("error") + val error: Error? = null, + @SerializedName("message") + val message: String? = null, +) { + val isError: Boolean get() = error != null + + class Error( + @SerializedName("expose") + val expose: Boolean? = null, + @SerializedName("statusCode") + val statusCode: Int? = null, + @SerializedName("status") + val status: Int? = null, + @SerializedName("body") + val body: String? = null, + @SerializedName("type") + val type: String? = null, + ) +} diff --git a/app/src/main/java/com/pixelized/biblib/data/ui/BookThumbnailUio.kt b/app/src/main/java/com/pixelized/biblib/data/ui/BookThumbnailUio.kt index 17bffe4..a255ad0 100644 --- a/app/src/main/java/com/pixelized/biblib/data/ui/BookThumbnailUio.kt +++ b/app/src/main/java/com/pixelized/biblib/data/ui/BookThumbnailUio.kt @@ -1,6 +1,6 @@ package com.pixelized.biblib.data.ui -import com.pixelized.biblib.utils.Constant.THUMBNAIL_URL +import com.pixelized.biblib.network.client.IBibLibClient.Companion.THUMBNAIL_URL import java.net.URL data class BookThumbnailUio( diff --git a/app/src/main/java/com/pixelized/biblib/data/ui/BookUio.kt b/app/src/main/java/com/pixelized/biblib/data/ui/BookUio.kt index ea24150..a4562d1 100644 --- a/app/src/main/java/com/pixelized/biblib/data/ui/BookUio.kt +++ b/app/src/main/java/com/pixelized/biblib/data/ui/BookUio.kt @@ -1,6 +1,6 @@ package com.pixelized.biblib.data.ui -import com.pixelized.biblib.utils.Constant +import com.pixelized.biblib.network.client.IBibLibClient.Companion.COVER_URL import java.net.URL data class BookUio( @@ -14,5 +14,5 @@ data class BookUio( val series: String?, val description: String, ) { - val cover: URL = URL("${Constant.COVER_URL}/$id.jpg") + val cover: URL = URL("${COVER_URL}/$id.jpg") } diff --git a/app/src/main/java/com/pixelized/biblib/injection/Bob.kt b/app/src/main/java/com/pixelized/biblib/injection/Bob.kt new file mode 100644 index 0000000..994951b --- /dev/null +++ b/app/src/main/java/com/pixelized/biblib/injection/Bob.kt @@ -0,0 +1,21 @@ +package com.pixelized.biblib.injection + +import com.pixelized.biblib.utils.exception.InjectionException +import kotlin.reflect.KClass + +@Suppress("UNCHECKED_CAST") +object Bob { + private val components = hashMapOf, Any>() + + operator fun set(clazz: KClass, component: O) { + components[clazz] = component + } + + operator fun get(clazz: KClass<*>): T { + return components[clazz] as? T ?: throw InjectionException(clazz) + } +} + +inline fun get(): T = Bob[T::class] + +inline fun inject(): Lazy = lazy { Bob[T::class] } \ No newline at end of file diff --git a/app/src/main/java/com/pixelized/biblib/network/client/BearerInterceptor.kt b/app/src/main/java/com/pixelized/biblib/network/client/BearerInterceptor.kt new file mode 100644 index 0000000..cafa7b6 --- /dev/null +++ b/app/src/main/java/com/pixelized/biblib/network/client/BearerInterceptor.kt @@ -0,0 +1,23 @@ +package com.pixelized.biblib.network.client + +import okhttp3.Interceptor +import okhttp3.Response + +class BearerInterceptor : Interceptor { + private val bearer get() = "$BEARER $token" + var token: String? = null + + override fun intercept(chain: Interceptor.Chain): Response { + var request = chain.request() + if (request.header(NO_AUTHORIZATION) == null && token.isNullOrEmpty().not()) { + request = request.newBuilder().addHeader(AUTHORIZATION, bearer).build() + } + return chain.proceed(request) + } + + companion object { + private const val NO_AUTHORIZATION = "No-Authentication" + private const val AUTHORIZATION = "Authorization" + private const val BEARER = "Bearer" + } +} \ No newline at end of file diff --git a/app/src/main/java/com/pixelized/biblib/network/client/BibLibClient.kt b/app/src/main/java/com/pixelized/biblib/network/client/BibLibClient.kt new file mode 100644 index 0000000..574a662 --- /dev/null +++ b/app/src/main/java/com/pixelized/biblib/network/client/BibLibClient.kt @@ -0,0 +1,30 @@ +package com.pixelized.biblib.network.client + +import com.google.gson.Gson +import com.pixelized.biblib.injection.inject +import com.pixelized.biblib.network.client.IBibLibClient.Companion.BASE_URL +import okhttp3.OkHttpClient +import retrofit2.Retrofit +import retrofit2.converter.gson.GsonConverterFactory + +class BibLibClient : IBibLibClient { + private val gson by inject() + private val interceptor = BearerInterceptor() + private val retrofit: Retrofit = Retrofit.Builder() + .addConverterFactory(GsonConverterFactory.create(gson)) + .client(OkHttpClient.Builder().addInterceptor(interceptor).build()) + .baseUrl(BASE_URL) + .build() + + override val service: IBibLibWebServiceAPI = retrofit.create(IBibLibWebServiceAPI::class.java) + + // endregion + /////////////////////////////////// + // region BibLib webservice Auth + + override fun updateBearerToken(token: String?) { + interceptor.token = token + } + + // endregion +} \ No newline at end of file diff --git a/app/src/main/java/com/pixelized/biblib/network/client/IBibLibClient.kt b/app/src/main/java/com/pixelized/biblib/network/client/IBibLibClient.kt new file mode 100644 index 0000000..7fdc9fa --- /dev/null +++ b/app/src/main/java/com/pixelized/biblib/network/client/IBibLibClient.kt @@ -0,0 +1,15 @@ +package com.pixelized.biblib.network.client + +interface IBibLibClient { + + val service: IBibLibWebServiceAPI + + fun updateBearerToken(token: String?) + + companion object { + const val BASE_URL = "https://bib.bibulle.fr" + const val THUMBNAIL_URL = "$BASE_URL/api/book/thumbnail" + const val COVER_URL = "$BASE_URL/api/book/cover" + const val REGISTER_URL = "$BASE_URL/signup" + } +} \ No newline at end of file diff --git a/app/src/main/java/com/pixelized/biblib/network/client/IBibLibWebServiceAPI.kt b/app/src/main/java/com/pixelized/biblib/network/client/IBibLibWebServiceAPI.kt new file mode 100644 index 0000000..f3fbb54 --- /dev/null +++ b/app/src/main/java/com/pixelized/biblib/network/client/IBibLibWebServiceAPI.kt @@ -0,0 +1,43 @@ +package com.pixelized.biblib.network.client + +import com.pixelized.biblib.data.network.query.AuthLoginQuery +import com.pixelized.biblib.data.network.response.AuthLoginResponse +import retrofit2.http.Body +import retrofit2.http.GET +import retrofit2.http.POST +import retrofit2.http.Query + +interface IBibLibWebServiceAPI { + @POST("/authent/login") + suspend fun login(@Body query: AuthLoginQuery): AuthLoginResponse + + @GET("/authent/google-id-token") + suspend fun loginWithGoogle(@Query("id_token") token: String): AuthLoginResponse + +// @GET("/authent/user") +// suspend fun user(): UserResponse +// +// @GET("/api/book/new") +// suspend fun new(): BookListResponse +// +// @GET("/api/book") +// suspend fun list(): BookListResponse +// +// @GET("/api/book/{id}") +// suspend fun detail(@Path("id") bookId: Int): BookDetailResponse +// +// @GET("/api/book/{id}/send/kindle") +// suspend fun send(@Path("id") bookId: Int, @Query("mail") mail: String): LinkedTreeMap +// +// @GET("/api/book/{id}/epub/url") +// suspend fun epub(@Path("id") bookId: Int): TokenResponse +// +// @GET("/api/book/{id}/mobi/url") +// suspend fun mobi(@Path("id") bookId: Int): TokenResponse +// +// @GET("/api/book/{id}/epub") +// fun downloadEpub(@Path("id") bookId: Int, @Query("token") token: String): Call +// +// @GET("/api/book/{id}/mobi") +// fun downloadMobi(@Path("id") bookId: Int, @Query("token") token: String): Call +} \ No newline at end of file diff --git a/app/src/main/java/com/pixelized/biblib/ui/MainActivity.kt b/app/src/main/java/com/pixelized/biblib/ui/MainActivity.kt index 58de05a..4521eba 100644 --- a/app/src/main/java/com/pixelized/biblib/ui/MainActivity.kt +++ b/app/src/main/java/com/pixelized/biblib/ui/MainActivity.kt @@ -5,28 +5,37 @@ import androidx.activity.ComponentActivity import androidx.activity.compose.setContent import androidx.activity.viewModels import androidx.compose.animation.Crossfade -import androidx.compose.animation.core.tween import androidx.compose.runtime.Composable import androidx.compose.runtime.getValue import androidx.compose.runtime.livedata.observeAsState import androidx.lifecycle.viewmodel.compose.viewModel +import com.google.android.gms.auth.api.signin.GoogleSignIn +import com.google.android.gms.auth.api.signin.GoogleSignInOptions +import com.pixelized.biblib.R import com.pixelized.biblib.ui.composable.screen.LoginScreenComposable import com.pixelized.biblib.ui.composable.screen.MainScreenComposable import com.pixelized.biblib.ui.composable.screen.SplashScreenComposable import com.pixelized.biblib.ui.theme.BibLibTheme -import com.pixelized.biblib.ui.viewmodel.AuthenticationViewModel import com.pixelized.biblib.ui.viewmodel.NavigationViewModel import com.pixelized.biblib.ui.viewmodel.NavigationViewModel.Screen -import com.pixelized.biblib.utils.BitmapCache class MainActivity : ComponentActivity() { private val navigationViewModel: NavigationViewModel by viewModels() + private val googleSignInOption by lazy { + GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_SIGN_IN) + .requestIdToken(getString(R.string.biblib_server_id)) + .requestEmail() + .build() + } + + val googleSignIn by lazy { + GoogleSignIn.getClient(this, googleSignInOption) + } + override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) - BitmapCache.init(this) - setContent { BibLibTheme { ContentComposable() diff --git a/app/src/main/java/com/pixelized/biblib/ui/composable/screen/LoginScreenComposable.kt b/app/src/main/java/com/pixelized/biblib/ui/composable/screen/LoginScreenComposable.kt index 64a2ccc..92c64c9 100644 --- a/app/src/main/java/com/pixelized/biblib/ui/composable/screen/LoginScreenComposable.kt +++ b/app/src/main/java/com/pixelized/biblib/ui/composable/screen/LoginScreenComposable.kt @@ -1,5 +1,10 @@ package com.pixelized.biblib.ui.composable.screen +import android.util.Log +import android.widget.Toast +import androidx.activity.ComponentActivity +import androidx.activity.compose.rememberLauncherForActivityResult +import androidx.activity.result.contract.ActivityResultContracts import androidx.compose.foundation.Image import androidx.compose.foundation.clickable import androidx.compose.foundation.layout.* @@ -19,6 +24,7 @@ import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.focus.FocusRequester import androidx.compose.ui.focus.focusRequester +import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.platform.LocalFocusManager import androidx.compose.ui.res.painterResource import androidx.compose.ui.res.stringResource @@ -28,7 +34,11 @@ import androidx.compose.ui.text.input.VisualTransformation import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp import androidx.lifecycle.viewmodel.compose.viewModel +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.pixelized.biblib.R +import com.pixelized.biblib.ui.MainActivity import com.pixelized.biblib.ui.theme.BibLibTheme import com.pixelized.biblib.ui.viewmodel.AuthenticationViewModel import com.pixelized.biblib.ui.viewmodel.NavigationViewModel @@ -43,10 +53,35 @@ fun LoginScreenComposablePreview() { @Composable fun LoginScreenComposable( - + navigationViewModel: NavigationViewModel = viewModel(), + authenticationViewModel: AuthenticationViewModel = viewModel(), ) { - val navigationViewModel = viewModel() - val authenticationViewModel = viewModel() + // TODO : c'est de la merde ça + val activity = LocalContext.current as MainActivity + val result = remember { mutableStateOf(null) } + val launcher = + rememberLauncherForActivityResult(ActivityResultContracts.StartActivityForResult()) { + try { + val task = GoogleSignIn.getSignedInAccountFromIntent(it.data) + val account: GoogleSignInAccount? = task.getResult(ApiException::class.java) + + val idToken = account?.idToken +// if (idToken != null) { +// viewModel.loginWithGoogle(idToken).observeLogin() +// } else { +// Toast.makeText(requireActivity(), "GoogleSignIn missing Token", Toast.LENGTH_SHORT).show() +// } + Log.e("AuthLoginFragment", "idToken: $idToken") + } catch (exception: Exception) { +// Toast.makeText(requireActivity(), "GoogleSignIn exception: ${exception.message}", Toast.LENGTH_SHORT).show() + Log.e("AuthLoginFragment", exception.message, exception) + } +// // Here we just update the state, but you could imagine +// // pre-processing the result, or updating a MutableSharedFlow that +// // your composable collects +// result.value = it + } + val typography = MaterialTheme.typography Column( @@ -102,14 +137,12 @@ fun LoginScreenComposable( modifier = Modifier.padding(end = 8.dp), colors = outlinedButtonColors(), onClick = { - // TODO: - navigationViewModel.navigateTo(NavigationViewModel.Screen.MainScreen) + authenticationViewModel.register() }) { Text(text = stringResource(id = R.string.action_register)) } Button(onClick = { - // TODO: - navigationViewModel.navigateTo(NavigationViewModel.Screen.MainScreen) + authenticationViewModel.login() }) { Text(text = stringResource(id = R.string.action_login)) } @@ -121,8 +154,7 @@ fun LoginScreenComposable( modifier = Modifier.fillMaxWidth(), colors = outlinedButtonColors(), onClick = { - // TODO: - navigationViewModel.navigateTo(NavigationViewModel.Screen.MainScreen) + launcher.launch(activity.googleSignIn.signInIntent) }) { Image( modifier = Modifier.padding(end = 8.dp), @@ -189,7 +221,7 @@ private fun PasswordField( private fun CredentialRemember(viewModel: AuthenticationViewModel, modifier: Modifier = Modifier) { val credential = viewModel.rememberCredential.observeAsState() Row(modifier = modifier.clickable { - viewModel.updateRememberCredential(credential = credential.value?.not() ?: false) + viewModel.updateRememberCredential(rememberCredential = credential.value?.not() ?: false) }) { Checkbox( modifier = Modifier.align(Alignment.CenterVertically), diff --git a/app/src/main/java/com/pixelized/biblib/ui/viewmodel/AuthenticationViewModel.kt b/app/src/main/java/com/pixelized/biblib/ui/viewmodel/AuthenticationViewModel.kt index 1c2b63d..2c1ce03 100644 --- a/app/src/main/java/com/pixelized/biblib/ui/viewmodel/AuthenticationViewModel.kt +++ b/app/src/main/java/com/pixelized/biblib/ui/viewmodel/AuthenticationViewModel.kt @@ -1,10 +1,24 @@ package com.pixelized.biblib.ui.viewmodel +import android.app.Application +import android.content.Context +import android.content.SharedPreferences +import android.util.Log +import androidx.core.content.edit +import androidx.lifecycle.AndroidViewModel import androidx.lifecycle.LiveData import androidx.lifecycle.MutableLiveData -import androidx.lifecycle.ViewModel +import androidx.lifecycle.viewModelScope +import androidx.lifecycle.viewmodel.compose.viewModel +import com.pixelized.biblib.data.network.query.AuthLoginQuery +import com.pixelized.biblib.injection.inject +import com.pixelized.biblib.network.client.IBibLibClient +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.launch -class AuthenticationViewModel: ViewModel() { +class AuthenticationViewModel(application: Application) : AndroidViewModel(application) { + private val preferences = application.getSharedPreferences(SHARED_PREF, Context.MODE_PRIVATE) + private val client: IBibLibClient by inject() private val _login = MutableLiveData() val login: LiveData get() = _login @@ -12,9 +26,17 @@ class AuthenticationViewModel: ViewModel() { private val _password = MutableLiveData() val password: LiveData get() = _password - private val _rememberCredential = MutableLiveData(false) + private val _rememberCredential = MutableLiveData() val rememberCredential: LiveData get() = _rememberCredential + init { + viewModelScope.launch(Dispatchers.Main) { + _login.value = preferences.login + _password.value = preferences.password + _rememberCredential.value = preferences.rememberCredential + } + } + fun updateLogin(login: String) { _login.postValue(login) } @@ -23,7 +45,54 @@ class AuthenticationViewModel: ViewModel() { _password.postValue(password) } - fun updateRememberCredential(credential: Boolean) { - _rememberCredential.postValue(credential) + fun updateRememberCredential(rememberCredential: Boolean) { + _rememberCredential.postValue(rememberCredential) + viewModelScope.launch { + preferences.rememberCredential = rememberCredential + if (rememberCredential.not()) { + preferences.login = null + preferences.password = null + } + } + } + + fun register() { + + } + + fun login() { + viewModelScope.launch(Dispatchers.IO) { + if (rememberCredential.value == true) { + preferences.login = login.value + preferences.password = password.value + } + // TODO : validation ! + val query = AuthLoginQuery( + username = login.value, + password = password.value + ) + // TODO : Repository (token management & co) + val response = client.service.login(query) + Log.e("pouet", response.toString()) + } + } + + private var SharedPreferences.login: String? + get() = getString(REMEMBER_USER, null) + set(value) = edit { putString(REMEMBER_USER, value) } + + private var SharedPreferences.password: String? + get() = getString(REMEMBER_PASSWORD, null) + set(value) = edit { putString(REMEMBER_PASSWORD, value) } + + private var SharedPreferences.rememberCredential: Boolean + get() = getBoolean(REMEMBER_CREDENTIAL, false) + set(value) = edit { putBoolean(REMEMBER_CREDENTIAL, value) } + + companion object { + const val SHARED_PREF = "BIB_LIB_SHARED_PREF" + const val REMEMBER_CREDENTIAL = "REMEMBER_CREDENTIAL" + const val REMEMBER_USER = "REMEMBER_USER" + const val REMEMBER_PASSWORD = "REMEMBER_PASSWORD" } } \ No newline at end of file diff --git a/app/src/main/java/com/pixelized/biblib/utils/BitmapCache.kt b/app/src/main/java/com/pixelized/biblib/utils/BitmapCache.kt index eca63f5..84f2255 100644 --- a/app/src/main/java/com/pixelized/biblib/utils/BitmapCache.kt +++ b/app/src/main/java/com/pixelized/biblib/utils/BitmapCache.kt @@ -1,6 +1,6 @@ package com.pixelized.biblib.utils -import android.content.Context +import android.app.Application import android.graphics.Bitmap import android.graphics.BitmapFactory import android.util.Log @@ -12,12 +12,11 @@ import java.io.File import java.io.IOException import java.net.URL -object BitmapCache { - private val scope = CoroutineScope(Dispatchers.IO) +class BitmapCache(application: Application) { private var cache: File? = null - fun init(context: Context) { - cache = context.cacheDir + init { + cache = application.cacheDir } fun writeToDisk(url: URL, bitmap: Bitmap) { diff --git a/app/src/main/java/com/pixelized/biblib/utils/exception/InjectionException.kt b/app/src/main/java/com/pixelized/biblib/utils/exception/InjectionException.kt new file mode 100644 index 0000000..3379876 --- /dev/null +++ b/app/src/main/java/com/pixelized/biblib/utils/exception/InjectionException.kt @@ -0,0 +1,5 @@ +package com.pixelized.biblib.utils.exception + +import kotlin.reflect.KClass + +class InjectionException(clazz: KClass<*>) : RuntimeException("InjectionException occur for class:${clazz}") \ No newline at end of file diff --git a/app/src/main/java/com/pixelized/biblib/utils/exception/NoBearerException.kt b/app/src/main/java/com/pixelized/biblib/utils/exception/NoBearerException.kt new file mode 100644 index 0000000..238368a --- /dev/null +++ b/app/src/main/java/com/pixelized/biblib/utils/exception/NoBearerException.kt @@ -0,0 +1,3 @@ +package com.pixelized.biblib.utils.exception + +class NoBearerException : RuntimeException("Bearer token is null") \ No newline at end of file diff --git a/app/src/main/java/com/pixelized/biblib/utils/extention/UrlEx.kt b/app/src/main/java/com/pixelized/biblib/utils/extention/UrlEx.kt index 2116e4c..43af27f 100644 --- a/app/src/main/java/com/pixelized/biblib/utils/extention/UrlEx.kt +++ b/app/src/main/java/com/pixelized/biblib/utils/extention/UrlEx.kt @@ -5,18 +5,19 @@ import androidx.compose.runtime.mutableStateOf import androidx.compose.ui.graphics.asImageBitmap import androidx.compose.ui.graphics.painter.BitmapPainter import androidx.compose.ui.graphics.painter.Painter +import com.pixelized.biblib.injection.get import com.pixelized.biblib.utils.BitmapCache import java.net.URL - fun URL.toImage(placeHolder: Painter): State { - val cached = BitmapCache.readFromDisk(this)?.let { BitmapPainter(it.asImageBitmap()) } - val state = mutableStateOf(cached ?: placeHolder) + val cache: BitmapCache = get() + val resource = cache.readFromDisk(this)?.let { BitmapPainter(it.asImageBitmap()) } + val state = mutableStateOf(resource ?: placeHolder) - if (cached == null) { - BitmapCache.download(url = this) { downloaded -> + if (resource == null) { + cache.download(url = this) { downloaded -> if (downloaded != null) { - BitmapCache.writeToDisk(this, downloaded) + cache.writeToDisk(this, downloaded) state.value = BitmapPainter(downloaded.asImageBitmap()) } } diff --git a/app/src/main/res/values/biblib_server.xml b/app/src/main/res/values/biblib_server.xml new file mode 100644 index 0000000..f4d220f --- /dev/null +++ b/app/src/main/res/values/biblib_server.xml @@ -0,0 +1,4 @@ + + + 725701605591-rr2dqeabon4kjpfevoruru65eo3rukmv.apps.googleusercontent.com + \ No newline at end of file