Simplifies URL Preview call
This commit is contained in:
@@ -1,26 +1,21 @@
|
|||||||
package com.vitorpamplona.amethyst.model
|
package com.vitorpamplona.amethyst.model
|
||||||
|
|
||||||
|
import android.util.LruCache
|
||||||
import com.vitorpamplona.amethyst.service.checkNotInMainThread
|
import com.vitorpamplona.amethyst.service.checkNotInMainThread
|
||||||
import com.vitorpamplona.amethyst.service.previews.BahaUrlPreview
|
import com.vitorpamplona.amethyst.service.previews.BahaUrlPreview
|
||||||
import com.vitorpamplona.amethyst.service.previews.IUrlPreviewCallback
|
import com.vitorpamplona.amethyst.service.previews.IUrlPreviewCallback
|
||||||
import com.vitorpamplona.amethyst.service.previews.UrlInfoItem
|
import com.vitorpamplona.amethyst.service.previews.UrlInfoItem
|
||||||
|
import com.vitorpamplona.amethyst.ui.components.UrlPreviewState
|
||||||
|
|
||||||
object UrlCachedPreviewer {
|
object UrlCachedPreviewer {
|
||||||
var cache = mapOf<String, UrlInfoItem>()
|
var cache = LruCache<String, UrlPreviewState>(100)
|
||||||
private set
|
|
||||||
var failures = mapOf<String, Throwable>()
|
|
||||||
private set
|
private set
|
||||||
|
|
||||||
fun previewInfo(url: String, callback: IUrlPreviewCallback? = null) {
|
fun previewInfo(url: String, onReady: (UrlPreviewState) -> Unit) {
|
||||||
checkNotInMainThread()
|
checkNotInMainThread()
|
||||||
|
|
||||||
cache[url]?.let {
|
cache[url]?.let {
|
||||||
callback?.onComplete(it)
|
onReady(it)
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
failures[url]?.let {
|
|
||||||
callback?.onFailed(it)
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -28,13 +23,32 @@ object UrlCachedPreviewer {
|
|||||||
url,
|
url,
|
||||||
object : IUrlPreviewCallback {
|
object : IUrlPreviewCallback {
|
||||||
override fun onComplete(urlInfo: UrlInfoItem) {
|
override fun onComplete(urlInfo: UrlInfoItem) {
|
||||||
cache = cache + Pair(url, urlInfo)
|
cache[url]?.let {
|
||||||
callback?.onComplete(urlInfo)
|
if (it is UrlPreviewState.Loaded || it is UrlPreviewState.Empty) {
|
||||||
|
onReady(it)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
val state = if (urlInfo.allFetchComplete() && urlInfo.url == url) {
|
||||||
|
UrlPreviewState.Loaded(urlInfo)
|
||||||
|
} else {
|
||||||
|
UrlPreviewState.Empty
|
||||||
|
}
|
||||||
|
|
||||||
|
cache.put(url, state)
|
||||||
|
onReady(state)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onFailed(throwable: Throwable) {
|
override fun onFailed(throwable: Throwable) {
|
||||||
failures = failures + Pair(url, throwable)
|
cache[url]?.let {
|
||||||
callback?.onFailed(throwable)
|
onReady(it)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
val state = UrlPreviewState.Error(throwable.message ?: "Error Loading url preview")
|
||||||
|
cache.put(url, state)
|
||||||
|
onReady(state)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
).fetchUrlPreview()
|
).fetchUrlPreview()
|
||||||
|
|||||||
@@ -8,56 +8,25 @@ import androidx.compose.runtime.getValue
|
|||||||
import androidx.compose.runtime.mutableStateOf
|
import androidx.compose.runtime.mutableStateOf
|
||||||
import androidx.compose.runtime.remember
|
import androidx.compose.runtime.remember
|
||||||
import androidx.compose.runtime.setValue
|
import androidx.compose.runtime.setValue
|
||||||
import androidx.compose.ui.platform.LocalContext
|
|
||||||
import com.vitorpamplona.amethyst.R
|
|
||||||
import com.vitorpamplona.amethyst.model.UrlCachedPreviewer
|
import com.vitorpamplona.amethyst.model.UrlCachedPreviewer
|
||||||
import com.vitorpamplona.amethyst.service.previews.IUrlPreviewCallback
|
|
||||||
import com.vitorpamplona.amethyst.service.previews.UrlInfoItem
|
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun UrlPreview(url: String, urlText: String) {
|
fun UrlPreview(url: String, urlText: String) {
|
||||||
val context = LocalContext.current
|
|
||||||
|
|
||||||
var urlPreviewState by remember(url) {
|
var urlPreviewState by remember(url) {
|
||||||
val default = UrlCachedPreviewer.cache[url]?.let {
|
mutableStateOf(
|
||||||
if (it.allFetchComplete() && it.url == url) {
|
UrlCachedPreviewer.cache.get(url)?.let { it } ?: UrlPreviewState.Loading
|
||||||
UrlPreviewState.Loaded(it)
|
)
|
||||||
} else {
|
|
||||||
UrlPreviewState.Empty
|
|
||||||
}
|
|
||||||
} ?: UrlPreviewState.Loading
|
|
||||||
|
|
||||||
mutableStateOf(default)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Doesn't use a viewModel because of viewModel reusing issues (too many UrlPreview are created).
|
// Doesn't use a viewModel because of viewModel reusing issues (too many UrlPreview are created).
|
||||||
LaunchedEffect(url) {
|
LaunchedEffect(url) {
|
||||||
if (urlPreviewState == UrlPreviewState.Loading) {
|
if (urlPreviewState == UrlPreviewState.Loading) {
|
||||||
launch(Dispatchers.IO) {
|
launch(Dispatchers.IO) {
|
||||||
UrlCachedPreviewer.previewInfo(
|
UrlCachedPreviewer.previewInfo(url) {
|
||||||
url,
|
urlPreviewState = it
|
||||||
object : IUrlPreviewCallback {
|
}
|
||||||
override fun onComplete(urlInfo: UrlInfoItem) {
|
|
||||||
if (urlInfo.allFetchComplete() && urlInfo.url == url) {
|
|
||||||
urlPreviewState = UrlPreviewState.Loaded(urlInfo)
|
|
||||||
} else {
|
|
||||||
urlPreviewState = UrlPreviewState.Empty
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onFailed(throwable: Throwable) {
|
|
||||||
urlPreviewState = UrlPreviewState.Error(
|
|
||||||
context.getString(
|
|
||||||
R.string.error_parsing_preview_for,
|
|
||||||
url,
|
|
||||||
throwable.message
|
|
||||||
)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,8 +5,16 @@ import com.vitorpamplona.amethyst.service.previews.UrlInfoItem
|
|||||||
|
|
||||||
@Immutable
|
@Immutable
|
||||||
sealed class UrlPreviewState {
|
sealed class UrlPreviewState {
|
||||||
|
|
||||||
|
@Immutable
|
||||||
object Loading : UrlPreviewState()
|
object Loading : UrlPreviewState()
|
||||||
|
|
||||||
|
@Immutable
|
||||||
class Loaded(val previewInfo: UrlInfoItem) : UrlPreviewState()
|
class Loaded(val previewInfo: UrlInfoItem) : UrlPreviewState()
|
||||||
|
|
||||||
|
@Immutable
|
||||||
object Empty : UrlPreviewState()
|
object Empty : UrlPreviewState()
|
||||||
|
|
||||||
|
@Immutable
|
||||||
class Error(val errorMessage: String) : UrlPreviewState()
|
class Error(val errorMessage: String) : UrlPreviewState()
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user