From 3b0028164b23af92e296834f11b65ec2310f779d Mon Sep 17 00:00:00 2001 From: aminecmi Date: Sat, 17 Dec 2022 22:25:23 +0100 Subject: [PATCH] Glide update + trying requests. --- androidApp/build.gradle.kts | 4 +- .../readerforselfossv2/android/ACRAUtils.kt | 2 +- .../android/adapters/ItemsAdapter.kt | 4 +- .../android/fragments/ArticleFragment.kt | 5 +- .../android/fragments/ImageFragment.kt | 2 +- .../readerforselfossv2/model/ResultModel.kt | 27 ------- .../apps/readerforselfossv2/rest/RestUtils.kt | 79 +++++++++++++++++++ .../readerforselfossv2/rest/SelfossApi.kt | 47 +++++------ 8 files changed, 109 insertions(+), 61 deletions(-) create mode 100644 shared/src/commonMain/kotlin/bou/amine/apps/readerforselfossv2/rest/RestUtils.kt diff --git a/androidApp/build.gradle.kts b/androidApp/build.gradle.kts index 87c566f..d2a572b 100644 --- a/androidApp/build.gradle.kts +++ b/androidApp/build.gradle.kts @@ -146,8 +146,8 @@ dependencies { implementation("com.amulyakhare:com.amulyakhare.textdrawable:1.0.1") // glide - kapt("com.github.bumptech.glide:compiler:4.11.0") - implementation("com.github.bumptech.glide:okhttp3-integration:4.1.1") + kapt("com.github.bumptech.glide:compiler:4.14.2") + implementation("com.github.bumptech.glide:okhttp3-integration:4.14.2") // Themes implementation("com.github.rubensousa:floatingtoolbar:1.5.1") diff --git a/androidApp/src/main/java/bou/amine/apps/readerforselfossv2/android/ACRAUtils.kt b/androidApp/src/main/java/bou/amine/apps/readerforselfossv2/android/ACRAUtils.kt index 9bfb152..1a93b6a 100644 --- a/androidApp/src/main/java/bou/amine/apps/readerforselfossv2/android/ACRAUtils.kt +++ b/androidApp/src/main/java/bou/amine/apps/readerforselfossv2/android/ACRAUtils.kt @@ -4,6 +4,6 @@ import org.acra.ACRA import org.acra.ktx.sendSilentlyWithAcra fun Throwable.sendSilentlyWithAcraWithName(name: String) { - ACRA.errorReporter.putCustomData("error_source", name) + ACRA.errorReporter.putCustomData("error_source", name) this.sendSilentlyWithAcra() } \ No newline at end of file diff --git a/androidApp/src/main/java/bou/amine/apps/readerforselfossv2/android/adapters/ItemsAdapter.kt b/androidApp/src/main/java/bou/amine/apps/readerforselfossv2/android/adapters/ItemsAdapter.kt index bca124b..944bd35 100644 --- a/androidApp/src/main/java/bou/amine/apps/readerforselfossv2/android/adapters/ItemsAdapter.kt +++ b/androidApp/src/main/java/bou/amine/apps/readerforselfossv2/android/adapters/ItemsAdapter.kt @@ -36,9 +36,7 @@ abstract class ItemsAdapter : RecyclerView.Adapte Snackbar.LENGTH_LONG ) .setAction(R.string.undo_string) { - CoroutineScope(Dispatchers.IO).launch { - unreadItemAtIndex(item, position, false) - } + unreadItemAtIndex(item, position, false) } val view = s.view diff --git a/androidApp/src/main/java/bou/amine/apps/readerforselfossv2/android/fragments/ArticleFragment.kt b/androidApp/src/main/java/bou/amine/apps/readerforselfossv2/android/fragments/ArticleFragment.kt index 68ff69f..037e20d 100644 --- a/androidApp/src/main/java/bou/amine/apps/readerforselfossv2/android/fragments/ArticleFragment.kt +++ b/androidApp/src/main/java/bou/amine/apps/readerforselfossv2/android/fragments/ArticleFragment.kt @@ -16,7 +16,6 @@ import android.webkit.WebView import android.webkit.WebViewClient import android.widget.Toast import androidx.appcompat.app.AlertDialog -import androidx.core.content.res.ResourcesCompat import androidx.core.widget.NestedScrollView import androidx.fragment.app.Fragment import bou.amine.apps.readerforselfossv2.android.ImageActivity @@ -45,8 +44,6 @@ import com.google.android.material.floatingactionbutton.FloatingActionButton import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.launch -import org.acra.ktx.sendSilentlyWithAcra -import org.acra.ktx.sendWithAcra import org.kodein.di.DI import org.kodein.di.DIAware import org.kodein.di.android.x.closestDI @@ -343,7 +340,7 @@ class ArticleFragment : Fragment(), DIAware { } @Deprecated("Deprecated in Java") - override fun shouldInterceptRequest(view: WebView?, url: String): WebResourceResponse? { + override fun shouldInterceptRequest(view: WebView, url: String): WebResourceResponse? { val glideOptions = RequestOptions.diskCacheStrategyOf(DiskCacheStrategy.ALL) if (url.lowercase(Locale.US).contains(".jpg") || url.lowercase(Locale.US).contains(".jpeg")) { try { diff --git a/androidApp/src/main/java/bou/amine/apps/readerforselfossv2/android/fragments/ImageFragment.kt b/androidApp/src/main/java/bou/amine/apps/readerforselfossv2/android/fragments/ImageFragment.kt index 129f883..7b46b8c 100644 --- a/androidApp/src/main/java/bou/amine/apps/readerforselfossv2/android/fragments/ImageFragment.kt +++ b/androidApp/src/main/java/bou/amine/apps/readerforselfossv2/android/fragments/ImageFragment.kt @@ -28,7 +28,7 @@ class ImageFragment : Fragment() { val view = binding?.root binding!!.photoView.visibility = View.VISIBLE - Glide.with(activity) + Glide.with(requireActivity()) .asBitmap() .apply(glideOptions) .load(imageUrl) diff --git a/shared/src/commonMain/kotlin/bou/amine/apps/readerforselfossv2/model/ResultModel.kt b/shared/src/commonMain/kotlin/bou/amine/apps/readerforselfossv2/model/ResultModel.kt index 7c56467..e067389 100644 --- a/shared/src/commonMain/kotlin/bou/amine/apps/readerforselfossv2/model/ResultModel.kt +++ b/shared/src/commonMain/kotlin/bou/amine/apps/readerforselfossv2/model/ResultModel.kt @@ -1,8 +1,5 @@ package bou.amine.apps.readerforselfossv2.model -import io.ktor.client.call.* -import io.ktor.client.statement.* -import io.ktor.http.* import kotlinx.serialization.Serializable @Serializable @@ -21,28 +18,4 @@ class StatusAndData(val success: Boolean, val data: T? = null) { return StatusAndData(false) } } -} - -suspend fun responseOrSuccessIf404(r: HttpResponse): SuccessResponse { - return if (r.status === HttpStatusCode.NotFound) { - SuccessResponse(true) - } else { - maybeResponse(r) - } -} - -suspend fun maybeResponse(r: HttpResponse): SuccessResponse { - return if (r.status.isSuccess()) { - r.body() - } else { - SuccessResponse(false) - } -} - -suspend inline fun bodyOrFailure(r: HttpResponse): StatusAndData { - return if (r.status.isSuccess()) { - StatusAndData.succes(r.body()) - } else { - StatusAndData.error() - } } \ No newline at end of file diff --git a/shared/src/commonMain/kotlin/bou/amine/apps/readerforselfossv2/rest/RestUtils.kt b/shared/src/commonMain/kotlin/bou/amine/apps/readerforselfossv2/rest/RestUtils.kt new file mode 100644 index 0000000..4fc3fbc --- /dev/null +++ b/shared/src/commonMain/kotlin/bou/amine/apps/readerforselfossv2/rest/RestUtils.kt @@ -0,0 +1,79 @@ +package bou.amine.apps.readerforselfossv2.rest + +import bou.amine.apps.readerforselfossv2.model.StatusAndData +import bou.amine.apps.readerforselfossv2.model.SuccessResponse +import io.github.aakira.napier.Napier +import io.ktor.client.* +import io.ktor.client.call.* +import io.ktor.client.request.* +import io.ktor.client.request.forms.* +import io.ktor.client.statement.* +import io.ktor.http.* + + +suspend fun responseOrSuccessIf404(r: HttpResponse?): SuccessResponse { + return if (r != null && r.status === HttpStatusCode.NotFound) { + SuccessResponse(true) + } else { + maybeResponse(r) + } +} + +suspend fun maybeResponse(r: HttpResponse?): SuccessResponse { + return if (r != null && r.status.isSuccess()) { + r.body() + } else { + SuccessResponse(false) + } +} + +suspend inline fun bodyOrFailure(r: HttpResponse?): StatusAndData { + return if (r != null && r.status.isSuccess()) { + StatusAndData.succes(r.body()) + } else { + StatusAndData.error() + } +} + +inline fun tryToRequest( + requestType: String, + fn: () -> HttpResponse +): HttpResponse? { + var response: HttpResponse? = null + try { + response = fn() + } catch (ex: Exception) { + Napier.e("Couldn't execute $requestType request", ex, "tryTo$requestType") + } + return response +} + +suspend inline fun HttpClient.tryToGet( + urlString: String, + crossinline block: HttpRequestBuilder.() -> Unit = {} +): HttpResponse? = tryToRequest("Get") { return this.get { url(urlString); block() } } + + +suspend inline fun HttpClient.tryToPost( + urlString: String, + block: HttpRequestBuilder.() -> Unit = {} +): HttpResponse? = tryToRequest("Post") { return this.post { url(urlString); block() } } + +suspend inline fun HttpClient.tryToDelete( + urlString: String, + block: HttpRequestBuilder.() -> Unit = {} +): HttpResponse? = tryToRequest("Delete") { return this.delete { url(urlString); block() } } + + +suspend fun HttpClient.tryToSubmitForm( + url: String, + formParameters: Parameters = Parameters.Empty, + encodeInQuery: Boolean = false, + block: HttpRequestBuilder.() -> Unit = {} +): HttpResponse? = + tryToRequest("SubmitForm") { + return this.submitForm(formParameters, encodeInQuery) { + url(url) + block() + } + } \ No newline at end of file diff --git a/shared/src/commonMain/kotlin/bou/amine/apps/readerforselfossv2/rest/SelfossApi.kt b/shared/src/commonMain/kotlin/bou/amine/apps/readerforselfossv2/rest/SelfossApi.kt index b2a8cd2..bba630c 100644 --- a/shared/src/commonMain/kotlin/bou/amine/apps/readerforselfossv2/rest/SelfossApi.kt +++ b/shared/src/commonMain/kotlin/bou/amine/apps/readerforselfossv2/rest/SelfossApi.kt @@ -1,6 +1,8 @@ package bou.amine.apps.readerforselfossv2.rest -import bou.amine.apps.readerforselfossv2.model.* +import bou.amine.apps.readerforselfossv2.model.SelfossModel +import bou.amine.apps.readerforselfossv2.model.StatusAndData +import bou.amine.apps.readerforselfossv2.model.SuccessResponse import bou.amine.apps.readerforselfossv2.service.AppSettingsService import io.github.aakira.napier.Napier import io.ktor.client.* @@ -10,7 +12,6 @@ import io.ktor.client.plugins.contentnegotiation.* import io.ktor.client.plugins.cookies.* import io.ktor.client.plugins.logging.* import io.ktor.client.request.* -import io.ktor.client.request.forms.* import io.ktor.client.statement.* import io.ktor.http.* import io.ktor.serialization.kotlinx.json.* @@ -50,7 +51,7 @@ class SelfossApi(private val appSettingsService: AppSettingsService) { retryIf { _, response -> response.status == HttpStatusCode.Forbidden && shouldHavePostLogin() && hasLoginInfo() } - modifyRequest { _ -> + modifyRequest { Napier.i("Will modify", tag = "HttpSend") CoroutineScope(Dispatchers.Main).launch { Napier.i("Will login", tag = "HttpSend") @@ -75,7 +76,7 @@ class SelfossApi(private val appSettingsService: AppSettingsService) { // Api version was introduces after the POST login, so when there is a version, it should be available private fun shouldHavePostLogin() = appSettingsService.getApiVersion() != -1 - private fun hasLoginInfo() = appSettingsService.getUserName() != null && appSettingsService.getPassword() != null + private fun hasLoginInfo() = appSettingsService.getUserName().isNotEmpty() && appSettingsService.getPassword().isNotEmpty() suspend fun login(): SuccessResponse = if (appSettingsService.getUserName().isNotEmpty() && appSettingsService.getPassword().isNotEmpty()) { @@ -88,12 +89,12 @@ class SelfossApi(private val appSettingsService: AppSettingsService) { SuccessResponse(true) } - private suspend fun getLogin() = maybeResponse(client.get(url("/login")) { + private suspend fun getLogin() = maybeResponse(client.tryToGet(url("/login")) { parameter("username", appSettingsService.getUserName()) parameter("password", appSettingsService.getPassword()) }) - private suspend fun postLogin() = maybeResponse(client.post(url("/login")) { + private suspend fun postLogin() = maybeResponse(client.tryToPost(url("/login")) { parameter("username", appSettingsService.getUserName()) parameter("password", appSettingsService.getPassword()) }) @@ -106,9 +107,9 @@ class SelfossApi(private val appSettingsService: AppSettingsService) { maybeLogoutIfAvailable() } - private suspend fun maybeLogoutIfAvailable() = responseOrSuccessIf404(client.get(url("/logout"))) + private suspend fun maybeLogoutIfAvailable() = responseOrSuccessIf404(client.tryToGet(url("/logout"))) - private suspend fun doLogout() = maybeResponse(client.delete(url("/api/session/current"))) + private suspend fun doLogout() = maybeResponse(client.tryToDelete(url("/api/session/current"))) suspend fun getItems( type: String, @@ -119,7 +120,7 @@ class SelfossApi(private val appSettingsService: AppSettingsService) { updatedSince: String?, items: Int? = null ): StatusAndData> = - bodyOrFailure(client.get(url("/items")) { + bodyOrFailure(client.tryToGet(url("/items")) { if (!shouldHavePostLogin()) { parameter("username", appSettingsService.getUserName()) parameter("password", appSettingsService.getPassword()) @@ -134,7 +135,7 @@ class SelfossApi(private val appSettingsService: AppSettingsService) { }) suspend fun stats(): StatusAndData = - bodyOrFailure(client.get(url("/stats")) { + bodyOrFailure(client.tryToGet(url("/stats")) { if (!shouldHavePostLogin()) { parameter("username", appSettingsService.getUserName()) parameter("password", appSettingsService.getPassword()) @@ -142,7 +143,7 @@ class SelfossApi(private val appSettingsService: AppSettingsService) { }) suspend fun tags(): StatusAndData> = - bodyOrFailure(client.get(url("/tags")) { + bodyOrFailure(client.tryToGet(url("/tags")) { if (!shouldHavePostLogin()) { parameter("username", appSettingsService.getUserName()) parameter("password", appSettingsService.getPassword()) @@ -150,7 +151,7 @@ class SelfossApi(private val appSettingsService: AppSettingsService) { }) suspend fun update(): StatusAndData = - bodyOrFailure(client.get(url("/update")) { + bodyOrFailure(client.tryToGet(url("/update")) { if (!shouldHavePostLogin()) { parameter("username", appSettingsService.getUserName()) parameter("password", appSettingsService.getPassword()) @@ -158,7 +159,7 @@ class SelfossApi(private val appSettingsService: AppSettingsService) { }) suspend fun spouts(): StatusAndData> = - bodyOrFailure(client.get(url("/sources/spouts")) { + bodyOrFailure(client.tryToGet(url("/sources/spouts")) { if (!shouldHavePostLogin()) { parameter("username", appSettingsService.getUserName()) parameter("password", appSettingsService.getPassword()) @@ -166,7 +167,7 @@ class SelfossApi(private val appSettingsService: AppSettingsService) { }) suspend fun sources(): StatusAndData> = - bodyOrFailure(client.get(url("/sources/list")) { + bodyOrFailure(client.tryToGet(url("/sources/list")) { if (!shouldHavePostLogin()) { parameter("username", appSettingsService.getUserName()) parameter("password", appSettingsService.getPassword()) @@ -174,10 +175,10 @@ class SelfossApi(private val appSettingsService: AppSettingsService) { }) suspend fun version(): StatusAndData = - bodyOrFailure(client.get(url("/api/about"))) + bodyOrFailure(client.tryToGet(url("/api/about"))) suspend fun markAsRead(id: String): SuccessResponse = - maybeResponse(client.post(url("/mark/$id")) { + maybeResponse(client.tryToPost(url("/mark/$id")) { if (!shouldHavePostLogin()) { parameter("username", appSettingsService.getUserName()) parameter("password", appSettingsService.getPassword()) @@ -185,7 +186,7 @@ class SelfossApi(private val appSettingsService: AppSettingsService) { }) suspend fun unmarkAsRead(id: String): SuccessResponse = - maybeResponse(client.post(url("/unmark/$id")) { + maybeResponse(client.tryToPost(url("/unmark/$id")) { if (!shouldHavePostLogin()) { parameter("username", appSettingsService.getUserName()) parameter("password", appSettingsService.getPassword()) @@ -193,7 +194,7 @@ class SelfossApi(private val appSettingsService: AppSettingsService) { }) suspend fun starr(id: String): SuccessResponse = - maybeResponse(client.post(url("/starr/$id")) { + maybeResponse(client.tryToPost(url("/starr/$id")) { if (!shouldHavePostLogin()) { parameter("username", appSettingsService.getUserName()) parameter("password", appSettingsService.getPassword()) @@ -201,7 +202,7 @@ class SelfossApi(private val appSettingsService: AppSettingsService) { }) suspend fun unstarr(id: String): SuccessResponse = - maybeResponse(client.post(url("/unstarr/$id")) { + maybeResponse(client.tryToPost(url("/unstarr/$id")) { if (!shouldHavePostLogin()) { parameter("username", appSettingsService.getUserName()) parameter("password", appSettingsService.getPassword()) @@ -209,7 +210,7 @@ class SelfossApi(private val appSettingsService: AppSettingsService) { }) suspend fun markAllAsRead(ids: List): SuccessResponse = - maybeResponse(client.submitForm( + maybeResponse(client.tryToSubmitForm( url = url("/mark"), formParameters = Parameters.build { if (!shouldHavePostLogin()) { @@ -242,8 +243,8 @@ class SelfossApi(private val appSettingsService: AppSettingsService) { spout: String, tags: String, filter: String - ): HttpResponse = - client.submitForm( + ): HttpResponse? = + client.tryToSubmitForm( url = url("/source"), formParameters = Parameters.build { if (!shouldHavePostLogin()) { @@ -259,7 +260,7 @@ class SelfossApi(private val appSettingsService: AppSettingsService) { ) suspend fun deleteSource(id: Int): SuccessResponse = - maybeResponse(client.delete(url("/source/$id")) { + maybeResponse(client.tryToDelete(url("/source/$id")) { if (!shouldHavePostLogin()) { parameter("username", appSettingsService.getUserName()) parameter("password", appSettingsService.getPassword())