mirror of
https://github.com/Suwayomi/TachideskJUI.git
synced 2026-02-02 00:44:05 +01:00
Remove repeat requests when failures happen
This commit is contained in:
@@ -17,6 +17,8 @@ import ca.gosyer.util.lang.withIOContext
|
||||
import io.ktor.client.request.HttpRequestBuilder
|
||||
import io.ktor.client.request.forms.formData
|
||||
import io.ktor.client.request.forms.submitFormWithBinaryData
|
||||
import io.ktor.client.request.get
|
||||
import io.ktor.client.request.post
|
||||
import io.ktor.client.statement.HttpResponse
|
||||
import io.ktor.http.ContentType
|
||||
import io.ktor.http.Headers
|
||||
@@ -47,7 +49,7 @@ class BackupInteractionHandler @Inject constructor(
|
||||
}
|
||||
|
||||
suspend fun importBackup(backup: Backup, block: HttpRequestBuilder.() -> Unit = {}) = withIOContext {
|
||||
client.postRepeat<HttpResponse>(
|
||||
client.post<HttpResponse>(
|
||||
serverUrl + backupImportRequest()
|
||||
) {
|
||||
contentType(ContentType.Application.Json)
|
||||
@@ -57,14 +59,14 @@ class BackupInteractionHandler @Inject constructor(
|
||||
}
|
||||
|
||||
suspend fun exportBackupFile(block: HttpRequestBuilder.() -> Unit = {}) = withIOContext {
|
||||
client.getRepeat<HttpResponse>(
|
||||
client.get<HttpResponse>(
|
||||
serverUrl + backupFileExportRequest(),
|
||||
block
|
||||
)
|
||||
}
|
||||
|
||||
suspend fun exportBackup(block: HttpRequestBuilder.() -> Unit = {}) = withIOContext {
|
||||
client.getRepeat<Backup>(
|
||||
client.get<Backup>(
|
||||
serverUrl + backupExportRequest(),
|
||||
block
|
||||
)
|
||||
|
||||
@@ -6,17 +6,8 @@
|
||||
|
||||
package ca.gosyer.data.server.interactions
|
||||
|
||||
import androidx.compose.ui.graphics.ImageBitmap
|
||||
import ca.gosyer.data.server.Http
|
||||
import ca.gosyer.data.server.ServerPreferences
|
||||
import ca.gosyer.util.lang.throwIfCancellation
|
||||
import io.ktor.client.request.HttpRequestBuilder
|
||||
import io.ktor.client.request.delete
|
||||
import io.ktor.client.request.forms.submitForm
|
||||
import io.ktor.client.request.get
|
||||
import io.ktor.client.request.patch
|
||||
import io.ktor.client.request.post
|
||||
import io.ktor.http.Parameters
|
||||
|
||||
open class BaseInteractionHandler(
|
||||
protected val client: Http,
|
||||
@@ -24,72 +15,4 @@ open class BaseInteractionHandler(
|
||||
) {
|
||||
private val _serverUrl = serverPreferences.serverUrl()
|
||||
val serverUrl get() = _serverUrl.get()
|
||||
|
||||
protected inline fun <T> repeat(block: () -> T): T {
|
||||
var attempt = 1
|
||||
var lastException: Exception
|
||||
do {
|
||||
try {
|
||||
return block()
|
||||
} catch (e: Exception) {
|
||||
e.throwIfCancellation()
|
||||
lastException = e
|
||||
}
|
||||
attempt++
|
||||
} while (attempt <= 3)
|
||||
throw lastException
|
||||
}
|
||||
|
||||
protected suspend inline fun <reified T> Http.getRepeat(
|
||||
urlString: String,
|
||||
noinline block: HttpRequestBuilder.() -> Unit = {}
|
||||
): T {
|
||||
return repeat {
|
||||
get(urlString, block)
|
||||
}
|
||||
}
|
||||
|
||||
protected suspend inline fun <reified T> Http.deleteRepeat(
|
||||
urlString: String,
|
||||
noinline block: HttpRequestBuilder.() -> Unit = {}
|
||||
): T {
|
||||
return repeat {
|
||||
delete(urlString, block)
|
||||
}
|
||||
}
|
||||
|
||||
protected suspend inline fun <reified T> Http.patchRepeat(
|
||||
urlString: String,
|
||||
noinline block: HttpRequestBuilder.() -> Unit = {}
|
||||
): T {
|
||||
return repeat {
|
||||
patch(urlString, block)
|
||||
}
|
||||
}
|
||||
|
||||
protected suspend inline fun <reified T> Http.postRepeat(
|
||||
urlString: String,
|
||||
noinline block: HttpRequestBuilder.() -> Unit = {}
|
||||
): T {
|
||||
return repeat {
|
||||
post(urlString, block)
|
||||
}
|
||||
}
|
||||
|
||||
protected suspend inline fun <reified T> Http.submitFormRepeat(
|
||||
urlString: String,
|
||||
formParameters: Parameters = Parameters.Empty,
|
||||
encodeInQuery: Boolean = false,
|
||||
block: HttpRequestBuilder.() -> Unit = {}
|
||||
): T {
|
||||
return repeat {
|
||||
submitForm(urlString, formParameters, encodeInQuery, block)
|
||||
}
|
||||
}
|
||||
|
||||
suspend fun imageFromUrl(client: Http, imageUrl: String, block: HttpRequestBuilder.() -> Unit): ImageBitmap {
|
||||
return repeat {
|
||||
ca.gosyer.util.compose.imageFromUrl(client, imageUrl, block)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,6 +20,9 @@ import ca.gosyer.data.server.requests.getMangaCategoriesQuery
|
||||
import ca.gosyer.data.server.requests.getMangaInCategoryQuery
|
||||
import ca.gosyer.data.server.requests.removeMangaFromCategoryRequest
|
||||
import ca.gosyer.util.lang.withIOContext
|
||||
import io.ktor.client.request.delete
|
||||
import io.ktor.client.request.forms.submitForm
|
||||
import io.ktor.client.request.get
|
||||
import io.ktor.client.statement.HttpResponse
|
||||
import io.ktor.http.HttpMethod
|
||||
import io.ktor.http.Parameters
|
||||
@@ -31,7 +34,7 @@ class CategoryInteractionHandler @Inject constructor(
|
||||
) : BaseInteractionHandler(client, serverPreferences) {
|
||||
|
||||
suspend fun getMangaCategories(mangaId: Long) = withIOContext {
|
||||
client.getRepeat<List<Category>>(
|
||||
client.get<List<Category>>(
|
||||
serverUrl + getMangaCategoriesQuery(mangaId)
|
||||
)
|
||||
}
|
||||
@@ -39,7 +42,7 @@ class CategoryInteractionHandler @Inject constructor(
|
||||
suspend fun getMangaCategories(manga: Manga) = getMangaCategories(manga.id)
|
||||
|
||||
suspend fun addMangaToCategory(mangaId: Long, categoryId: Long) = withIOContext {
|
||||
client.getRepeat<HttpResponse>(
|
||||
client.get<HttpResponse>(
|
||||
serverUrl + addMangaToCategoryQuery(mangaId, categoryId)
|
||||
)
|
||||
}
|
||||
@@ -48,7 +51,7 @@ class CategoryInteractionHandler @Inject constructor(
|
||||
suspend fun addMangaToCategory(mangaId: Long, category: Category) = addMangaToCategory(mangaId, category.id)
|
||||
|
||||
suspend fun removeMangaFromCategory(mangaId: Long, categoryId: Long) = withIOContext {
|
||||
client.deleteRepeat<HttpResponse>(
|
||||
client.delete<HttpResponse>(
|
||||
serverUrl + removeMangaFromCategoryRequest(mangaId, categoryId)
|
||||
)
|
||||
}
|
||||
@@ -57,13 +60,13 @@ class CategoryInteractionHandler @Inject constructor(
|
||||
suspend fun removeMangaFromCategory(mangaId: Long, category: Category) = removeMangaFromCategory(mangaId, category.id)
|
||||
|
||||
suspend fun getCategories() = withIOContext {
|
||||
client.getRepeat<List<Category>>(
|
||||
client.get<List<Category>>(
|
||||
serverUrl + getCategoriesQuery()
|
||||
)
|
||||
}
|
||||
|
||||
suspend fun createCategory(name: String) = withIOContext {
|
||||
client.submitFormRepeat<HttpResponse>(
|
||||
client.submitForm<HttpResponse>(
|
||||
serverUrl + createCategoryRequest(),
|
||||
formParameters = Parameters.build {
|
||||
append("name", name)
|
||||
@@ -72,7 +75,7 @@ class CategoryInteractionHandler @Inject constructor(
|
||||
}
|
||||
|
||||
suspend fun modifyCategory(categoryId: Long, name: String? = null, isLanding: Boolean? = null) = withIOContext {
|
||||
client.submitFormRepeat<HttpResponse>(
|
||||
client.submitForm<HttpResponse>(
|
||||
serverUrl + categoryModifyRequest(categoryId),
|
||||
formParameters = Parameters.build {
|
||||
if (name != null) {
|
||||
@@ -89,7 +92,7 @@ class CategoryInteractionHandler @Inject constructor(
|
||||
suspend fun modifyCategory(category: Category, name: String? = null, isLanding: Boolean? = null) = modifyCategory(category.id, name, isLanding)
|
||||
|
||||
suspend fun reorderCategory(categoryId: Long, to: Int, from: Int) = withIOContext {
|
||||
client.submitFormRepeat<HttpResponse>(
|
||||
client.submitForm<HttpResponse>(
|
||||
serverUrl + categoryReorderRequest(categoryId),
|
||||
formParameters = Parameters.build {
|
||||
append("to", to.toString())
|
||||
@@ -102,14 +105,14 @@ class CategoryInteractionHandler @Inject constructor(
|
||||
suspend fun reorderCategory(category: Category, to: Int, from: Int) = reorderCategory(category.id, to, from)
|
||||
|
||||
suspend fun deleteCategory(categoryId: Long) = withIOContext {
|
||||
client.deleteRepeat<HttpResponse>(
|
||||
client.delete<HttpResponse>(
|
||||
serverUrl + categoryDeleteRequest(categoryId)
|
||||
)
|
||||
}
|
||||
suspend fun deleteCategory(category: Category) = deleteCategory(category.id)
|
||||
|
||||
suspend fun getMangaFromCategory(categoryId: Long) = withIOContext {
|
||||
client.getRepeat<List<Manga>>(
|
||||
client.get<List<Manga>>(
|
||||
serverUrl + getMangaInCategoryQuery(categoryId)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -17,8 +17,12 @@ import ca.gosyer.data.server.requests.getPageQuery
|
||||
import ca.gosyer.data.server.requests.queueDownloadChapterRequest
|
||||
import ca.gosyer.data.server.requests.updateChapterMetaRequest
|
||||
import ca.gosyer.data.server.requests.updateChapterRequest
|
||||
import ca.gosyer.util.compose.imageFromUrl
|
||||
import ca.gosyer.util.lang.withIOContext
|
||||
import io.ktor.client.request.HttpRequestBuilder
|
||||
import io.ktor.client.request.delete
|
||||
import io.ktor.client.request.forms.submitForm
|
||||
import io.ktor.client.request.get
|
||||
import io.ktor.client.request.parameter
|
||||
import io.ktor.client.statement.HttpResponse
|
||||
import io.ktor.http.HttpMethod
|
||||
@@ -31,7 +35,7 @@ class ChapterInteractionHandler @Inject constructor(
|
||||
) : BaseInteractionHandler(client, serverPreferences) {
|
||||
|
||||
suspend fun getChapters(mangaId: Long, refresh: Boolean = false) = withIOContext {
|
||||
client.getRepeat<List<Chapter>>(
|
||||
client.get<List<Chapter>>(
|
||||
serverUrl + getMangaChaptersQuery(mangaId)
|
||||
) {
|
||||
url {
|
||||
@@ -45,7 +49,7 @@ class ChapterInteractionHandler @Inject constructor(
|
||||
suspend fun getChapters(manga: Manga, refresh: Boolean = false) = getChapters(manga.id, refresh)
|
||||
|
||||
suspend fun getChapter(mangaId: Long, chapterIndex: Int) = withIOContext {
|
||||
client.getRepeat<Chapter>(
|
||||
client.get<Chapter>(
|
||||
serverUrl + getChapterQuery(mangaId, chapterIndex)
|
||||
)
|
||||
}
|
||||
@@ -64,7 +68,7 @@ class ChapterInteractionHandler @Inject constructor(
|
||||
lastPageRead: Int? = null,
|
||||
markPreviousRead: Boolean? = null
|
||||
) = withIOContext {
|
||||
client.submitFormRepeat<HttpResponse>(
|
||||
client.submitForm<HttpResponse>(
|
||||
serverUrl + updateChapterRequest(mangaId, chapterIndex),
|
||||
formParameters = Parameters.build {
|
||||
if (read != null) {
|
||||
@@ -132,7 +136,7 @@ class ChapterInteractionHandler @Inject constructor(
|
||||
suspend fun getPage(manga: Manga, chapter: Chapter, pageNum: Int, block: HttpRequestBuilder.() -> Unit) = getPage(manga.id, chapter.index, pageNum, block)
|
||||
|
||||
suspend fun queueChapterDownload(mangaId: Long, chapterIndex: Int) = withIOContext {
|
||||
client.getRepeat<HttpResponse>(
|
||||
client.get<HttpResponse>(
|
||||
serverUrl + queueDownloadChapterRequest(mangaId, chapterIndex)
|
||||
)
|
||||
}
|
||||
@@ -144,7 +148,7 @@ class ChapterInteractionHandler @Inject constructor(
|
||||
suspend fun queueChapterDownload(manga: Manga, chapter: Chapter) = queueChapterDownload(manga.id, chapter.index)
|
||||
|
||||
suspend fun deleteChapterDownload(mangaId: Long, chapterIndex: Int) = withIOContext {
|
||||
client.deleteRepeat<HttpResponse>(
|
||||
client.delete<HttpResponse>(
|
||||
serverUrl + deleteDownloadChapterRequest(mangaId, chapterIndex)
|
||||
)
|
||||
}
|
||||
@@ -156,7 +160,7 @@ class ChapterInteractionHandler @Inject constructor(
|
||||
suspend fun deleteChapterDownload(manga: Manga, chapter: Chapter) = deleteChapterDownload(manga.id, chapter.index)
|
||||
|
||||
suspend fun updateChapterMeta(mangaId: Long, chapterIndex: Int, key: String, value: String) = withIOContext {
|
||||
client.submitFormRepeat<HttpResponse>(
|
||||
client.submitForm<HttpResponse>(
|
||||
serverUrl + updateChapterMetaRequest(mangaId, chapterIndex),
|
||||
formParameters = Parameters.build {
|
||||
append("key", key)
|
||||
|
||||
@@ -12,6 +12,7 @@ import ca.gosyer.data.server.requests.downloadsClearRequest
|
||||
import ca.gosyer.data.server.requests.downloadsStartRequest
|
||||
import ca.gosyer.data.server.requests.downloadsStopRequest
|
||||
import ca.gosyer.util.lang.withIOContext
|
||||
import io.ktor.client.request.get
|
||||
import io.ktor.client.statement.HttpResponse
|
||||
import javax.inject.Inject
|
||||
|
||||
@@ -21,19 +22,19 @@ class DownloadInteractionHandler @Inject constructor(
|
||||
) : BaseInteractionHandler(client, serverPreferences) {
|
||||
|
||||
suspend fun startDownloading() = withIOContext {
|
||||
client.getRepeat<HttpResponse>(
|
||||
client.get<HttpResponse>(
|
||||
serverUrl + downloadsStartRequest()
|
||||
)
|
||||
}
|
||||
|
||||
suspend fun stopDownloading() = withIOContext {
|
||||
client.getRepeat<HttpResponse>(
|
||||
client.get<HttpResponse>(
|
||||
serverUrl + downloadsStopRequest()
|
||||
)
|
||||
}
|
||||
|
||||
suspend fun clearDownloadQueue() = withIOContext {
|
||||
client.getRepeat<HttpResponse>(
|
||||
client.get<HttpResponse>(
|
||||
serverUrl + downloadsClearRequest()
|
||||
)
|
||||
}
|
||||
|
||||
@@ -14,8 +14,10 @@ import ca.gosyer.data.server.requests.apkInstallQuery
|
||||
import ca.gosyer.data.server.requests.apkUninstallQuery
|
||||
import ca.gosyer.data.server.requests.apkUpdateQuery
|
||||
import ca.gosyer.data.server.requests.extensionListQuery
|
||||
import ca.gosyer.util.compose.imageFromUrl
|
||||
import ca.gosyer.util.lang.withIOContext
|
||||
import io.ktor.client.request.HttpRequestBuilder
|
||||
import io.ktor.client.request.get
|
||||
import io.ktor.client.statement.HttpResponse
|
||||
import javax.inject.Inject
|
||||
|
||||
@@ -25,25 +27,25 @@ class ExtensionInteractionHandler @Inject constructor(
|
||||
) : BaseInteractionHandler(client, serverPreferences) {
|
||||
|
||||
suspend fun getExtensionList() = withIOContext {
|
||||
client.getRepeat<List<Extension>>(
|
||||
client.get<List<Extension>>(
|
||||
serverUrl + extensionListQuery()
|
||||
)
|
||||
}
|
||||
|
||||
suspend fun installExtension(extension: Extension) = withIOContext {
|
||||
client.getRepeat<HttpResponse>(
|
||||
client.get<HttpResponse>(
|
||||
serverUrl + apkInstallQuery(extension.pkgName)
|
||||
)
|
||||
}
|
||||
|
||||
suspend fun updateExtension(extension: Extension) = withIOContext {
|
||||
client.getRepeat<HttpResponse>(
|
||||
client.get<HttpResponse>(
|
||||
serverUrl + apkUpdateQuery(extension.pkgName)
|
||||
)
|
||||
}
|
||||
|
||||
suspend fun uninstallExtension(extension: Extension) = withIOContext {
|
||||
client.getRepeat<HttpResponse>(
|
||||
client.get<HttpResponse>(
|
||||
serverUrl + apkUninstallQuery(extension.pkgName)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -13,6 +13,8 @@ import ca.gosyer.data.server.requests.addMangaToLibraryQuery
|
||||
import ca.gosyer.data.server.requests.getLibraryQuery
|
||||
import ca.gosyer.data.server.requests.removeMangaFromLibraryRequest
|
||||
import ca.gosyer.util.lang.withIOContext
|
||||
import io.ktor.client.request.delete
|
||||
import io.ktor.client.request.get
|
||||
import io.ktor.client.statement.HttpResponse
|
||||
import javax.inject.Inject
|
||||
|
||||
@@ -22,13 +24,13 @@ class LibraryInteractionHandler @Inject constructor(
|
||||
) : BaseInteractionHandler(client, serverPreferences) {
|
||||
|
||||
suspend fun getLibraryManga() = withIOContext {
|
||||
client.getRepeat<List<Manga>>(
|
||||
client.get<List<Manga>>(
|
||||
serverUrl + getLibraryQuery()
|
||||
)
|
||||
}
|
||||
|
||||
suspend fun addMangaToLibrary(mangaId: Long) = withIOContext {
|
||||
client.getRepeat<HttpResponse>(
|
||||
client.get<HttpResponse>(
|
||||
serverUrl + addMangaToLibraryQuery(mangaId)
|
||||
)
|
||||
}
|
||||
@@ -36,7 +38,7 @@ class LibraryInteractionHandler @Inject constructor(
|
||||
suspend fun addMangaToLibrary(manga: Manga) = addMangaToLibrary(manga.id)
|
||||
|
||||
suspend fun removeMangaFromLibrary(mangaId: Long) = withIOContext {
|
||||
client.deleteRepeat<HttpResponse>(
|
||||
client.delete<HttpResponse>(
|
||||
serverUrl + removeMangaFromLibraryRequest(mangaId)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -12,8 +12,11 @@ import ca.gosyer.data.server.ServerPreferences
|
||||
import ca.gosyer.data.server.requests.mangaQuery
|
||||
import ca.gosyer.data.server.requests.mangaThumbnailQuery
|
||||
import ca.gosyer.data.server.requests.updateMangaMetaRequest
|
||||
import ca.gosyer.util.compose.imageFromUrl
|
||||
import ca.gosyer.util.lang.withIOContext
|
||||
import io.ktor.client.request.HttpRequestBuilder
|
||||
import io.ktor.client.request.forms.submitForm
|
||||
import io.ktor.client.request.get
|
||||
import io.ktor.client.request.parameter
|
||||
import io.ktor.client.statement.HttpResponse
|
||||
import io.ktor.http.HttpMethod
|
||||
@@ -26,7 +29,7 @@ class MangaInteractionHandler @Inject constructor(
|
||||
) : BaseInteractionHandler(client, serverPreferences) {
|
||||
|
||||
suspend fun getManga(mangaId: Long, refresh: Boolean = false) = withIOContext {
|
||||
client.getRepeat<Manga>(
|
||||
client.get<Manga>(
|
||||
serverUrl + mangaQuery(mangaId)
|
||||
) {
|
||||
url {
|
||||
@@ -48,7 +51,7 @@ class MangaInteractionHandler @Inject constructor(
|
||||
}
|
||||
|
||||
suspend fun updateMangaMeta(mangaId: Long, key: String, value: String) = withIOContext {
|
||||
client.submitFormRepeat<HttpResponse>(
|
||||
client.submitForm<HttpResponse>(
|
||||
serverUrl + updateMangaMetaRequest(mangaId),
|
||||
formParameters = Parameters.build {
|
||||
append("key", key)
|
||||
|
||||
@@ -18,6 +18,7 @@ import ca.gosyer.data.server.requests.sourceListQuery
|
||||
import ca.gosyer.data.server.requests.sourcePopularQuery
|
||||
import ca.gosyer.data.server.requests.sourceSearchQuery
|
||||
import ca.gosyer.util.lang.withIOContext
|
||||
import io.ktor.client.request.get
|
||||
import io.ktor.client.statement.HttpResponse
|
||||
import javax.inject.Inject
|
||||
|
||||
@@ -27,13 +28,13 @@ class SourceInteractionHandler @Inject constructor(
|
||||
) : BaseInteractionHandler(client, serverPreferences) {
|
||||
|
||||
suspend fun getSourceList() = withIOContext {
|
||||
client.getRepeat<List<Source>>(
|
||||
client.get<List<Source>>(
|
||||
serverUrl + sourceListQuery()
|
||||
)
|
||||
}
|
||||
|
||||
suspend fun getSourceInfo(sourceId: Long) = withIOContext {
|
||||
client.getRepeat<Source>(
|
||||
client.get<Source>(
|
||||
serverUrl + sourceInfoQuery(sourceId)
|
||||
)
|
||||
}
|
||||
@@ -41,7 +42,7 @@ class SourceInteractionHandler @Inject constructor(
|
||||
suspend fun getSourceInfo(source: Source) = getSourceInfo(source.id)
|
||||
|
||||
suspend fun getPopularManga(sourceId: Long, pageNum: Int) = withIOContext {
|
||||
client.getRepeat<MangaPage>(
|
||||
client.get<MangaPage>(
|
||||
serverUrl + sourcePopularQuery(sourceId, pageNum)
|
||||
)
|
||||
}
|
||||
@@ -52,7 +53,7 @@ class SourceInteractionHandler @Inject constructor(
|
||||
)
|
||||
|
||||
suspend fun getLatestManga(sourceId: Long, pageNum: Int) = withIOContext {
|
||||
client.getRepeat<MangaPage>(
|
||||
client.get<MangaPage>(
|
||||
serverUrl + sourceLatestQuery(sourceId, pageNum)
|
||||
)
|
||||
}
|
||||
@@ -64,13 +65,13 @@ class SourceInteractionHandler @Inject constructor(
|
||||
|
||||
// TODO: 2021-03-14
|
||||
suspend fun getGlobalSearchResults(searchTerm: String) = withIOContext {
|
||||
client.getRepeat<HttpResponse>(
|
||||
client.get<HttpResponse>(
|
||||
serverUrl + globalSearchQuery(searchTerm)
|
||||
)
|
||||
}
|
||||
|
||||
suspend fun getSearchResults(sourceId: Long, searchTerm: String, pageNum: Int) = withIOContext {
|
||||
client.getRepeat<MangaPage>(
|
||||
client.get<MangaPage>(
|
||||
serverUrl + sourceSearchQuery(sourceId, searchTerm, pageNum)
|
||||
)
|
||||
}
|
||||
@@ -83,7 +84,7 @@ class SourceInteractionHandler @Inject constructor(
|
||||
|
||||
// TODO: 2021-03-14
|
||||
suspend fun getFilterList(sourceId: Long) = withIOContext {
|
||||
client.getRepeat<HttpResponse>(
|
||||
client.get<HttpResponse>(
|
||||
serverUrl + getFilterListQuery(sourceId)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -11,7 +11,6 @@ import androidx.compose.foundation.layout.BoxWithConstraints
|
||||
import androidx.compose.foundation.layout.fillMaxSize
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.DisposableEffect
|
||||
import androidx.compose.runtime.MutableState
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.ui.Alignment
|
||||
@@ -23,14 +22,15 @@ import androidx.compose.ui.layout.ContentScale
|
||||
import ca.gosyer.common.di.AppScope
|
||||
import ca.gosyer.data.server.Http
|
||||
import ca.gosyer.util.compose.imageFromUrl
|
||||
import ca.gosyer.util.lang.throwIfCancellation
|
||||
import ca.gosyer.util.system.kLogger
|
||||
import io.ktor.client.features.onDownload
|
||||
import io.ktor.client.request.HttpRequestBuilder
|
||||
import kotlinx.coroutines.CoroutineExceptionHandler
|
||||
import kotlinx.coroutines.DelicateCoroutinesApi
|
||||
import kotlinx.coroutines.GlobalScope
|
||||
import kotlinx.coroutines.launch
|
||||
|
||||
val logger = kLogger {}
|
||||
|
||||
@OptIn(DelicateCoroutinesApi::class)
|
||||
@Composable
|
||||
fun KtorImage(
|
||||
@@ -42,22 +42,22 @@ fun KtorImage(
|
||||
contentScale: ContentScale = ContentScale.Fit,
|
||||
alpha: Float = DefaultAlpha,
|
||||
colorFilter: ColorFilter? = null,
|
||||
retries: Int = 3,
|
||||
client: Http = remember { AppScope.getInstance() }
|
||||
) {
|
||||
BoxWithConstraints {
|
||||
val drawable: MutableState<ImageBitmap?> = remember { mutableStateOf(null) }
|
||||
val loading: MutableState<Boolean> = remember { mutableStateOf(true) }
|
||||
val progress: MutableState<Float> = remember { mutableStateOf(0.0F) }
|
||||
val error: MutableState<String?> = remember { mutableStateOf(null) }
|
||||
val drawable = remember { mutableStateOf<ImageBitmap?>(null) }
|
||||
val loading = remember { mutableStateOf(true) }
|
||||
val progress = remember { mutableStateOf(0.0F) }
|
||||
val error = remember { mutableStateOf<String?>(null) }
|
||||
DisposableEffect(imageUrl) {
|
||||
val handler = CoroutineExceptionHandler { _, throwable ->
|
||||
logger.error(throwable) { "Error loading image $imageUrl" }
|
||||
loading.value = false
|
||||
error.value = throwable.message
|
||||
}
|
||||
val job = GlobalScope.launch(handler) {
|
||||
if (drawable.value == null) {
|
||||
drawable.value = getImage(client, imageUrl, retries) {
|
||||
drawable.value = imageFromUrl(client, imageUrl) {
|
||||
onDownload { bytesSentTotal, contentLength ->
|
||||
progress.value = (bytesSentTotal.toFloat() / contentLength).coerceAtMost(1.0F)
|
||||
}
|
||||
@@ -88,18 +88,3 @@ fun KtorImage(
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private suspend fun getImage(client: Http, imageUrl: String, retries: Int = 3, block: HttpRequestBuilder.() -> Unit): ImageBitmap {
|
||||
var attempt = 1
|
||||
var lastException: Exception
|
||||
do {
|
||||
try {
|
||||
return imageFromUrl(client, imageUrl, block)
|
||||
} catch (e: Exception) {
|
||||
e.throwIfCancellation()
|
||||
lastException = e
|
||||
}
|
||||
attempt++
|
||||
} while (attempt <= retries)
|
||||
throw lastException
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user