Moves URL Previews into suspend functions

This commit is contained in:
Vitor Pamplona
2023-08-04 10:47:01 -04:00
parent e7defa14b9
commit ba2902b725
4 changed files with 19 additions and 24 deletions
@@ -2,33 +2,35 @@ package com.vitorpamplona.amethyst.model
import android.util.LruCache
import androidx.compose.runtime.Stable
import com.vitorpamplona.amethyst.service.checkNotInMainThread
import com.vitorpamplona.amethyst.service.previews.BahaUrlPreview
import com.vitorpamplona.amethyst.service.previews.IUrlPreviewCallback
import com.vitorpamplona.amethyst.service.previews.UrlInfoItem
import com.vitorpamplona.amethyst.ui.components.UrlPreviewState
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext
@Stable
object UrlCachedPreviewer {
var cache = LruCache<String, UrlPreviewState>(100)
private set
fun previewInfo(url: String, onReady: (UrlPreviewState) -> Unit) {
checkNotInMainThread()
suspend fun previewInfo(
url: String,
onReady: suspend (UrlPreviewState) -> Unit
) = withContext(Dispatchers.IO) {
cache[url]?.let {
onReady(it)
return
return@withContext
}
BahaUrlPreview(
url,
object : IUrlPreviewCallback {
override fun onComplete(urlInfo: UrlInfoItem) {
override suspend fun onComplete(urlInfo: UrlInfoItem) = withContext(Dispatchers.IO) {
cache[url]?.let {
if (it is UrlPreviewState.Loaded || it is UrlPreviewState.Empty) {
onReady(it)
return
return@withContext
}
}
@@ -42,10 +44,10 @@ object UrlCachedPreviewer {
onReady(state)
}
override fun onFailed(throwable: Throwable) {
override suspend fun onFailed(throwable: Throwable) = withContext(Dispatchers.IO) {
cache[url]?.let {
onReady(it)
return
return@withContext
}
val state = UrlPreviewState.Error(throwable.message ?: "Error Loading url preview")
@@ -1,25 +1,21 @@
package com.vitorpamplona.amethyst.service.previews
import android.net.Uri
import com.vitorpamplona.amethyst.service.checkNotInMainThread
import kotlinx.coroutines.*
import java.util.*
class BahaUrlPreview(val url: String, var callback: IUrlPreviewCallback?) {
val scope = CoroutineScope(Job() + Dispatchers.IO)
private val imageExtensionArray = arrayOf(".gif", ".png", ".jpg", ".jpeg", ".bmp", ".webp")
fun fetchUrlPreview(timeOut: Int = 30000) {
val exceptionHandler = CoroutineExceptionHandler { coroutineContext, throwable ->
callback?.onFailed(throwable)
}
scope.launch(exceptionHandler) {
suspend fun fetchUrlPreview(timeOut: Int = 30000) = withContext(Dispatchers.IO) {
try {
fetch(timeOut)
} catch (t: Throwable) {
callback?.onFailed(t)
}
}
private suspend fun fetch(timeOut: Int = 30000) {
checkNotInMainThread()
lateinit var urlInfoItem: UrlInfoItem
if (checkIsImageUrl()) {
urlInfoItem = UrlInfoItem(url = url, image = url)
@@ -43,7 +39,6 @@ class BahaUrlPreview(val url: String, var callback: IUrlPreviewCallback?) {
}
fun cleanUp() {
scope.cancel()
callback = null
}
}
@@ -1,6 +1,6 @@
package com.vitorpamplona.amethyst.service.previews
interface IUrlPreviewCallback {
fun onComplete(urlInfo: UrlInfoItem)
fun onFailed(throwable: Throwable)
suspend fun onComplete(urlInfo: UrlInfoItem)
suspend fun onFailed(throwable: Throwable)
}
@@ -30,7 +30,7 @@ fun UrlPreview(url: String, urlText: String, accountViewModel: AccountViewModel)
} else {
var urlPreviewState by remember(url) {
mutableStateOf(
UrlCachedPreviewer.cache.get(url)?.let { it } ?: UrlPreviewState.Loading
UrlCachedPreviewer.cache.get(url) ?: UrlPreviewState.Loading
)
}
@@ -39,9 +39,7 @@ fun UrlPreview(url: String, urlText: String, accountViewModel: AccountViewModel)
LaunchedEffect(url) {
launch(Dispatchers.IO) {
UrlCachedPreviewer.previewInfo(url) {
launch(Dispatchers.Main) {
urlPreviewState = it
}
urlPreviewState = it
}
}
}