Implement fever favicon (#496)
This commit is contained in:
parent
ed893c3810
commit
4d5d9ef3da
@ -92,10 +92,9 @@ class FeverRssService @Inject constructor(
|
|||||||
* obtained is 0 or their quantity exceeds 250, at which point the pulling process stops.
|
* obtained is 0 or their quantity exceeds 250, at which point the pulling process stops.
|
||||||
*
|
*
|
||||||
* 1. Fetch the Fever groups
|
* 1. Fetch the Fever groups
|
||||||
* 2. Fetch the Fever feeds
|
* 2. Fetch the Fever feeds (including favicons)
|
||||||
* 3. Fetch the Fever articles
|
* 3. Fetch the Fever articles
|
||||||
* 4. Synchronize read/unread and starred/un-starred items
|
* 4. Synchronize read/unread and starred/un-starred items
|
||||||
* 5. TODO: Fetch the Fever favicons
|
|
||||||
*/
|
*/
|
||||||
override suspend fun sync(coroutineWorker: CoroutineWorker): ListenableWorker.Result = supervisorScope {
|
override suspend fun sync(coroutineWorker: CoroutineWorker): ListenableWorker.Result = supervisorScope {
|
||||||
coroutineWorker.setProgress(SyncWorker.setIsSyncing(true))
|
coroutineWorker.setProgress(SyncWorker.setIsSyncing(true))
|
||||||
@ -127,6 +126,9 @@ class FeverRssService @Inject constructor(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Fetch the Fever favicons
|
||||||
|
val faviconsById = feverAPI.getFavicons().favicons?.associateBy { it.id } ?: emptyMap()
|
||||||
feedDao.insertOrUpdate(
|
feedDao.insertOrUpdate(
|
||||||
feedsBody.feeds?.map {
|
feedsBody.feeds?.map {
|
||||||
Feed(
|
Feed(
|
||||||
@ -135,6 +137,7 @@ class FeverRssService @Inject constructor(
|
|||||||
url = it.url!!,
|
url = it.url!!,
|
||||||
groupId = accountId.spacerDollar(feedsGroupsMap[it.id.toString()]!!),
|
groupId = accountId.spacerDollar(feedsGroupsMap[it.id.toString()]!!),
|
||||||
accountId = accountId,
|
accountId = accountId,
|
||||||
|
icon = faviconsById[it.favicon_id]?.data
|
||||||
)
|
)
|
||||||
} ?: emptyList()
|
} ?: emptyList()
|
||||||
)
|
)
|
||||||
@ -191,7 +194,6 @@ class FeverRssService @Inject constructor(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: 5. Fetch the Fever favicons
|
|
||||||
|
|
||||||
Log.i("RLog", "onCompletion: ${System.currentTimeMillis() - preTime}")
|
Log.i("RLog", "onCompletion: ${System.currentTimeMillis() - preTime}")
|
||||||
accountDao.update(account.apply {
|
accountDao.update(account.apply {
|
||||||
|
@ -101,12 +101,12 @@ object FeverDTO {
|
|||||||
val api_version: Int?,
|
val api_version: Int?,
|
||||||
val auth: Int?,
|
val auth: Int?,
|
||||||
val last_refreshed_on_time: Long?,
|
val last_refreshed_on_time: Long?,
|
||||||
val favicons: Map<String, Favicon>,
|
val favicons: List<Favicon>?,
|
||||||
)
|
)
|
||||||
|
|
||||||
data class Favicon(
|
data class Favicon(
|
||||||
val mime_type: String,
|
val id: Int,
|
||||||
val data: String,
|
val data: String?,
|
||||||
)
|
)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -15,6 +15,7 @@ import androidx.compose.ui.tooling.preview.Preview
|
|||||||
import androidx.compose.ui.unit.Dp
|
import androidx.compose.ui.unit.Dp
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import androidx.compose.ui.unit.sp
|
import androidx.compose.ui.unit.sp
|
||||||
|
import me.ash.reader.ui.component.base.Base64Image
|
||||||
import me.ash.reader.ui.component.base.RYAsyncImage
|
import me.ash.reader.ui.component.base.RYAsyncImage
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
@ -26,7 +27,7 @@ fun FeedIcon(
|
|||||||
if (iconUrl == null) {
|
if (iconUrl == null) {
|
||||||
Box(
|
Box(
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.size(20.dp)
|
.size(size)
|
||||||
.clip(CircleShape)
|
.clip(CircleShape)
|
||||||
.background(MaterialTheme.colorScheme.primary),
|
.background(MaterialTheme.colorScheme.primary),
|
||||||
contentAlignment = Alignment.Center,
|
contentAlignment = Alignment.Center,
|
||||||
@ -38,6 +39,14 @@ fun FeedIcon(
|
|||||||
fontSize = 10.sp,
|
fontSize = 10.sp,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
// e.g. image/gif;base64,R0lGODlh...
|
||||||
|
else if ("^image/.*;base64,.*".toRegex().matches(iconUrl)) {
|
||||||
|
Base64Image(
|
||||||
|
modifier = Modifier
|
||||||
|
.size(size)
|
||||||
|
.clip(CircleShape),
|
||||||
|
base64Uri = iconUrl)
|
||||||
} else {
|
} else {
|
||||||
RYAsyncImage(
|
RYAsyncImage(
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
|
@ -0,0 +1,30 @@
|
|||||||
|
package me.ash.reader.ui.component.base
|
||||||
|
|
||||||
|
import android.graphics.Bitmap
|
||||||
|
import android.graphics.BitmapFactory
|
||||||
|
import android.util.Base64
|
||||||
|
import androidx.compose.foundation.Image
|
||||||
|
import androidx.compose.runtime.Composable
|
||||||
|
import androidx.compose.ui.Modifier
|
||||||
|
import androidx.compose.ui.graphics.asImageBitmap
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
fun Base64Image(
|
||||||
|
modifier: Modifier = Modifier,
|
||||||
|
base64Uri: String
|
||||||
|
) {
|
||||||
|
val bitmap = base64ToBitmap(base64Uri)
|
||||||
|
val imageBitmap = bitmap.asImageBitmap()
|
||||||
|
|
||||||
|
Image(
|
||||||
|
bitmap = imageBitmap,
|
||||||
|
modifier = modifier,
|
||||||
|
contentDescription = null
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun base64ToBitmap(base64String: String): Bitmap {
|
||||||
|
val base64Data = base64String.substringAfter("base64,")
|
||||||
|
val imageBytes = Base64.decode(base64Data, Base64.DEFAULT)
|
||||||
|
return BitmapFactory.decodeByteArray(imageBytes, 0, imageBytes.size)
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user