Loading favicons and theirs colors is now parallelized during initial sync

This commit is contained in:
Shinokuni 2025-01-18 16:46:28 +01:00
parent 213d01d667
commit a25542b78a

View File

@ -20,7 +20,12 @@ import com.readrops.app.util.FeedColors
import com.readrops.db.Database
import com.readrops.db.entities.Feed
import com.readrops.db.entities.account.Account
import kotlinx.coroutines.CoroutineDispatcher
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.async
import kotlinx.coroutines.awaitAll
import kotlinx.coroutines.flow.first
import kotlinx.coroutines.withContext
import org.koin.core.component.KoinComponent
import org.koin.core.component.get
import org.koin.core.parameter.parametersOf
@ -36,6 +41,7 @@ class Synchronizer(
private val database: Database,
private val context: Context,
private val encryptedPreferences: SharedPreferences,
private val dispatcher: CoroutineDispatcher = Dispatchers.IO
) : KoinComponent {
suspend fun synchronizeAccounts(
@ -147,34 +153,44 @@ class Synchronizer(
private suspend fun fetchFeedColors(
syncResult: SyncResult,
notificationBuilder: Builder
) = with(syncResult) {
) = withContext(dispatcher) {
notificationBuilder.setContentTitle(context.getString(R.string.get_feeds_colors))
for ((index, feed) in feeds.withIndex()) {
notificationBuilder.setContentText(feed.name)
.setStyle(NotificationCompat.BigTextStyle().bigText(feed.name))
.setProgress(feeds.size, index + 1, false)
var index = 0
syncResult.feeds.chunked(MAX_PARALLEL_REQUESTS)
.map {
it.map { feed ->
async {
notificationBuilder.setProgress(syncResult.feeds.size, ++index, false)
if (notificationManager.areNotificationsEnabled()) {
notificationManager.notify(SYNC_NOTIFICATION_ID, notificationBuilder.build())
}
if (notificationManager.areNotificationsEnabled()) {
notificationManager.notify(
SYNC_NOTIFICATION_ID,
notificationBuilder.build()
)
}
try {
if (feed.iconUrl != null) {
val color = FeedColors.getFeedColor(feed.iconUrl!!)
database.feedDao().updateFeedColor(feed.id, color)
try {
if (feed.iconUrl != null) {
val color = FeedColors.getFeedColor(feed.iconUrl!!)
database.feedDao().updateFeedColor(feed.id, color)
}
Unit
} catch (e: Exception) {
Log.e(TAG, "${feed.name}: ${e.message}")
}
}
}
} catch (e: Exception) {
Log.e(TAG, "${feed.name}: ${e.message}")
.awaitAll()
}
}
}
private suspend fun loadFeverFavicons(
favicons: Map<Feed, Favicon>,
account: Account,
notificationBuilder: Builder
) {
) = withContext(dispatcher) {
if (notificationManager.areNotificationsEnabled()) {
// can't make detailed progress as the favicon might already exist in cache
notificationBuilder.setContentTitle("Loading icons and colors")
@ -184,38 +200,46 @@ class Synchronizer(
val diskCache = context.imageLoader.diskCache!!
for ((feed, favicon) in favicons) {
val key = "account_${account.id}_feed_${feed.name!!.replace(" ", "_")}"
val snapshot = diskCache.openSnapshot(key)
favicons.entries.chunked(MAX_PARALLEL_REQUESTS)
.map {
it.map { (feed, favicon) ->
async {
val key = "account_${account.id}_feed_${feed.name!!.replace(" ", "_")}"
val snapshot = diskCache.openSnapshot(key)
if (snapshot == null) {
try {
diskCache.openEditor(key)!!.apply {
diskCache.fileSystem.write(data) {
write(favicon.data)
if (snapshot == null) {
try {
diskCache.openEditor(key)!!.apply {
diskCache.fileSystem.write(data) {
write(favicon.data)
}
commit()
}
database.feedDao().updateFeedIconUrl(feed.id, key)
val bitmap =
BitmapFactory.decodeByteArray(favicon.data, 0, favicon.data.size)
if (bitmap != null) {
val color = FeedColors.getFeedColor(bitmap)
database.feedDao().updateFeedColor(feed.id, color)
}
} catch (e: Exception) {
Log.e(TAG, "${feed.name}: ${e.message}")
}
}
commit()
snapshot?.close()
}
database.feedDao().updateFeedIconUrl(feed.id, key)
val bitmap =
BitmapFactory.decodeByteArray(favicon.data, 0, favicon.data.size)
if (bitmap != null) {
val color = FeedColors.getFeedColor(bitmap)
database.feedDao().updateFeedColor(feed.id, color)
}
} catch (e: Exception) {
Log.e(TAG, "${feed.name}: ${e.message}")
}
.awaitAll()
}
snapshot?.close()
}
}
companion object {
private val TAG = Synchronizer::class.java.simpleName
private const val MAX_PARALLEL_REQUESTS = 30
}
}