Improve performance across screens (#4071)

* Keep screens loaded while they're hidden and rebuild the library faster

* Count chapters in SQL for the migration list

* Show the extension list sooner and check trust against loaded stores

* Cancel the previous tracker search when searching again

* Write reader progress less often and keep its work off the main thread

* Stop rebuilding the settings search index on every key

* Watch updates for widgets only while one is placed

The query re-ran on every chapter or manga write even with no widget on
the home screen.

* Observe download pages and limit how often their progress updates

* Throttle the library update notification and write fetch data together
This commit is contained in:
AntsyLich
2026-10-11 04:28:52 +00:00
committed by GitHub
parent b15af71b94
commit 260e31cd2c
33 changed files with 458 additions and 136 deletions
@@ -6,17 +6,18 @@ import app.cash.sqldelight.coroutines.mapToList
import app.cash.sqldelight.coroutines.mapToOne
import app.cash.sqldelight.coroutines.mapToOneOrNull
import kotlinx.coroutines.flow.Flow
import tachiyomi.core.common.util.lang.pausedWhileUnsubscribed
import kotlin.coroutines.CoroutineContext
import kotlin.coroutines.EmptyCoroutineContext
fun <T : Any> Query<T>.subscribeToList(
context: CoroutineContext = EmptyCoroutineContext,
): Flow<List<T>> = asFlow().mapToList(context)
): Flow<List<T>> = asFlow().pausedWhileUnsubscribed().mapToList(context)
fun <T : Any> Query<T>.subscribeToOne(
context: CoroutineContext = EmptyCoroutineContext,
): Flow<T> = asFlow().mapToOne(context)
): Flow<T> = asFlow().pausedWhileUnsubscribed().mapToOne(context)
fun <T : Any> Query<T>.subscribeToOneOrNull(
context: CoroutineContext = EmptyCoroutineContext,
): Flow<T?> = asFlow().mapToOneOrNull(context)
): Flow<T?> = asFlow().pausedWhileUnsubscribed().mapToOneOrNull(context)
@@ -14,6 +14,7 @@ import tachiyomi.data.Database
import tachiyomi.data.subscribeToList
import tachiyomi.domain.chapter.model.Chapter
import tachiyomi.domain.chapter.model.ChapterRemoteUpdate
import tachiyomi.domain.chapter.model.ChapterSummary
import tachiyomi.domain.chapter.model.ChapterUpdate
import tachiyomi.domain.chapter.repository.ChapterRepository
import kotlin.time.Instant
@@ -112,6 +113,14 @@ class ChapterRepositoryImpl(
.awaitAsList()
}
override suspend fun getChapterSummaryByMangaId(mangaId: Long): ChapterSummary {
return database.chapterQueries
.getChapterSummaryByMangaId(mangaId) { total, latestChapterNumber ->
ChapterSummary(chapterCount = total, latestChapterNumber = latestChapterNumber)
}
.awaitAsOne()
}
override suspend fun getScanlatorsByMangaId(mangaId: Long): List<String> {
return database.chapterQueries
.getScanlatorsByMangaId(mangaId) { it.orEmpty() }
@@ -48,6 +48,11 @@ AND (
OR ES.scanlator IS NULL
);
getChapterSummaryByMangaId:
SELECT count(*) AS total, max(remote_chapter_number) AS latestChapterNumber
FROM chapter
WHERE manga_id = :mangaId;
getScanlatorsByMangaId:
SELECT DISTINCT remote_scanlator
FROM chapter