Update dependencies

pull/539/head
Koitharu 3 years ago
parent 4bd7656681
commit 590120433c
Signed by: Koitharu
GPG Key ID: 676DEE768C17A9D7

@ -16,11 +16,12 @@ android {
applicationId 'org.koitharu.kotatsu' applicationId 'org.koitharu.kotatsu'
minSdk = 21 minSdk = 21
targetSdk = 34 targetSdk = 34
versionCode = 589 versionCode = 590
versionName = '6.2.2' versionName = '6.2.3'
generatedDensities = [] generatedDensities = []
testInstrumentationRunner "org.koitharu.kotatsu.HiltTestRunner" testInstrumentationRunner "org.koitharu.kotatsu.HiltTestRunner"
ksp { ksp {
// arg("room.generateKotlin", "true") TODO: enable later
arg("room.schemaLocation", "$projectDir/schemas") arg("room.schemaLocation", "$projectDir/schemas")
} }
androidResources { androidResources {
@ -81,7 +82,7 @@ afterEvaluate {
} }
dependencies { dependencies {
//noinspection GradleDependency //noinspection GradleDependency
implementation('com.github.KotatsuApp:kotatsu-parsers:0054d06e6e') { implementation('com.github.KotatsuApp:kotatsu-parsers:6bf0ae92e4') {
exclude group: 'org.json', module: 'json' exclude group: 'org.json', module: 'json'
} }
@ -98,7 +99,7 @@ dependencies {
implementation 'androidx.lifecycle:lifecycle-process:2.6.2' implementation 'androidx.lifecycle:lifecycle-process:2.6.2'
implementation 'androidx.constraintlayout:constraintlayout:2.1.4' implementation 'androidx.constraintlayout:constraintlayout:2.1.4'
implementation 'androidx.swiperefreshlayout:swiperefreshlayout:1.1.0' implementation 'androidx.swiperefreshlayout:swiperefreshlayout:1.1.0'
implementation 'androidx.recyclerview:recyclerview:1.3.1' implementation 'androidx.recyclerview:recyclerview:1.3.2'
implementation 'androidx.viewpager2:viewpager2:1.1.0-beta02' implementation 'androidx.viewpager2:viewpager2:1.1.0-beta02'
implementation 'androidx.preference:preference-ktx:1.2.1' implementation 'androidx.preference:preference-ktx:1.2.1'
implementation 'androidx.biometric:biometric-ktx:1.2.0-alpha05' implementation 'androidx.biometric:biometric-ktx:1.2.0-alpha05'
@ -114,9 +115,9 @@ dependencies {
exclude group: 'com.google.j2objc', module: 'j2objc-annotations' exclude group: 'com.google.j2objc', module: 'j2objc-annotations'
} }
implementation 'androidx.room:room-runtime:2.5.2' implementation 'androidx.room:room-runtime:2.6.0'
implementation 'androidx.room:room-ktx:2.5.2' implementation 'androidx.room:room-ktx:2.6.0'
ksp 'androidx.room:room-compiler:2.5.2' ksp 'androidx.room:room-compiler:2.6.0'
implementation 'com.squareup.okhttp3:okhttp:4.11.0' implementation 'com.squareup.okhttp3:okhttp:4.11.0'
implementation 'com.squareup.okhttp3:okhttp-dnsoverhttps:4.11.0' implementation 'com.squareup.okhttp3:okhttp-dnsoverhttps:4.11.0'
@ -152,7 +153,7 @@ dependencies {
androidTestImplementation 'org.jetbrains.kotlinx:kotlinx-coroutines-test:1.7.3' androidTestImplementation 'org.jetbrains.kotlinx:kotlinx-coroutines-test:1.7.3'
androidTestImplementation 'androidx.room:room-testing:2.5.2' androidTestImplementation 'androidx.room:room-testing:2.6.0'
androidTestImplementation 'com.squareup.moshi:moshi-kotlin:1.15.0' androidTestImplementation 'com.squareup.moshi:moshi-kotlin:1.15.0'
androidTestImplementation 'com.google.dagger:hilt-android-testing:2.48.1' androidTestImplementation 'com.google.dagger:hilt-android-testing:2.48.1'

@ -82,7 +82,7 @@ class AppBackupAgentTest {
assertEquals(history, historyRepository.getOne(SampleData.manga)) assertEquals(history, historyRepository.getOne(SampleData.manga))
assertEquals(listOf(SampleData.manga), favouritesRepository.getManga(category.id)) assertEquals(listOf(SampleData.manga), favouritesRepository.getManga(category.id))
val allTags = database.tagsDao.findTags(SampleData.tag.source.name).toMangaTags() val allTags = database.getTagsDao().findTags(SampleData.tag.source.name).toMangaTags()
assertTrue(SampleData.tag in allTags) assertTrue(SampleData.tag in allTags)
} }

@ -25,15 +25,15 @@ class BookmarksRepository @Inject constructor(
) { ) {
fun observeBookmark(manga: Manga, chapterId: Long, page: Int): Flow<Bookmark?> { fun observeBookmark(manga: Manga, chapterId: Long, page: Int): Flow<Bookmark?> {
return db.bookmarksDao.observe(manga.id, chapterId, page).map { it?.toBookmark(manga) } return db.getBookmarksDao().observe(manga.id, chapterId, page).map { it?.toBookmark(manga) }
} }
fun observeBookmarks(manga: Manga): Flow<List<Bookmark>> { fun observeBookmarks(manga: Manga): Flow<List<Bookmark>> {
return db.bookmarksDao.observe(manga.id).mapItems { it.toBookmark(manga) } return db.getBookmarksDao().observe(manga.id).mapItems { it.toBookmark(manga) }
} }
fun observeBookmarks(): Flow<Map<Manga, List<Bookmark>>> { fun observeBookmarks(): Flow<Map<Manga, List<Bookmark>>> {
return db.bookmarksDao.observe().map { map -> return db.getBookmarksDao().observe().map { map ->
val res = LinkedHashMap<Manga, List<Bookmark>>(map.size) val res = LinkedHashMap<Manga, List<Bookmark>>(map.size)
for ((k, v) in map) { for ((k, v) in map) {
val manga = k.toManga() val manga = k.toManga()
@ -46,9 +46,9 @@ class BookmarksRepository @Inject constructor(
suspend fun addBookmark(bookmark: Bookmark) { suspend fun addBookmark(bookmark: Bookmark) {
db.withTransaction { db.withTransaction {
val tags = bookmark.manga.tags.toEntities() val tags = bookmark.manga.tags.toEntities()
db.tagsDao.upsert(tags) db.getTagsDao().upsert(tags)
db.mangaDao.upsert(bookmark.manga.toEntity(), tags) db.getMangaDao().upsert(bookmark.manga.toEntity(), tags)
db.bookmarksDao.insert(bookmark.toEntity()) db.getBookmarksDao().insert(bookmark.toEntity())
} }
} }
@ -56,11 +56,11 @@ class BookmarksRepository @Inject constructor(
val entity = bookmark.toEntity().copy( val entity = bookmark.toEntity().copy(
imageUrl = imageUrl, imageUrl = imageUrl,
) )
db.bookmarksDao.upsert(listOf(entity)) db.getBookmarksDao().upsert(listOf(entity))
} }
suspend fun removeBookmark(mangaId: Long, chapterId: Long, page: Int) { suspend fun removeBookmark(mangaId: Long, chapterId: Long, page: Int) {
check(db.bookmarksDao.delete(mangaId, chapterId, page) != 0) { check(db.getBookmarksDao().delete(mangaId, chapterId, page) != 0) {
"Bookmark not found" "Bookmark not found"
} }
} }
@ -72,7 +72,7 @@ class BookmarksRepository @Inject constructor(
suspend fun removeBookmarks(ids: Set<Long>): ReversibleHandle { suspend fun removeBookmarks(ids: Set<Long>): ReversibleHandle {
val entities = ArrayList<BookmarkEntity>(ids.size) val entities = ArrayList<BookmarkEntity>(ids.size)
db.withTransaction { db.withTransaction {
val dao = db.bookmarksDao val dao = db.getBookmarksDao()
for (pageId in ids) { for (pageId in ids) {
val e = dao.find(pageId) val e = dao.find(pageId)
if (e != null) { if (e != null) {
@ -92,7 +92,7 @@ class BookmarksRepository @Inject constructor(
db.withTransaction { db.withTransaction {
for (e in entities) { for (e in entities) {
try { try {
db.bookmarksDao.insert(e) db.getBookmarksDao().insert(e)
} catch (e: SQLException) { } catch (e: SQLException) {
e.printStackTraceDebug() e.printStackTraceDebug()
} }

@ -22,7 +22,7 @@ class BackupRepository @Inject constructor(
var offset = 0 var offset = 0
val entry = BackupEntry(BackupEntry.HISTORY, JSONArray()) val entry = BackupEntry(BackupEntry.HISTORY, JSONArray())
while (true) { while (true) {
val history = db.historyDao.findAll(offset, PAGE_SIZE) val history = db.getHistoryDao().findAll(offset, PAGE_SIZE)
if (history.isEmpty()) { if (history.isEmpty()) {
break break
} }
@ -42,7 +42,7 @@ class BackupRepository @Inject constructor(
suspend fun dumpCategories(): BackupEntry { suspend fun dumpCategories(): BackupEntry {
val entry = BackupEntry(BackupEntry.CATEGORIES, JSONArray()) val entry = BackupEntry(BackupEntry.CATEGORIES, JSONArray())
val categories = db.favouriteCategoriesDao.findAll() val categories = db.getFavouriteCategoriesDao().findAll()
for (item in categories) { for (item in categories) {
entry.data.put(JsonSerializer(item).toJson()) entry.data.put(JsonSerializer(item).toJson())
} }
@ -53,7 +53,7 @@ class BackupRepository @Inject constructor(
var offset = 0 var offset = 0
val entry = BackupEntry(BackupEntry.FAVOURITES, JSONArray()) val entry = BackupEntry(BackupEntry.FAVOURITES, JSONArray())
while (true) { while (true) {
val favourites = db.favouritesDao.findAll(offset, PAGE_SIZE) val favourites = db.getFavouritesDao().findAll(offset, PAGE_SIZE)
if (favourites.isEmpty()) { if (favourites.isEmpty()) {
break break
} }
@ -73,7 +73,7 @@ class BackupRepository @Inject constructor(
suspend fun dumpBookmarks(): BackupEntry { suspend fun dumpBookmarks(): BackupEntry {
val entry = BackupEntry(BackupEntry.BOOKMARKS, JSONArray()) val entry = BackupEntry(BackupEntry.BOOKMARKS, JSONArray())
val all = db.bookmarksDao.findAll() val all = db.getBookmarksDao().findAll()
for ((m, b) in all) { for ((m, b) in all) {
val json = JSONObject() val json = JSONObject()
val manga = JsonSerializer(m.manga).toJson() val manga = JsonSerializer(m.manga).toJson()
@ -122,9 +122,9 @@ class BackupRepository @Inject constructor(
val history = JsonDeserializer(item).toHistoryEntity() val history = JsonDeserializer(item).toHistoryEntity()
result += runCatchingCancellable { result += runCatchingCancellable {
db.withTransaction { db.withTransaction {
db.tagsDao.upsert(tags) db.getTagsDao().upsert(tags)
db.mangaDao.upsert(manga, tags) db.getMangaDao().upsert(manga, tags)
db.historyDao.upsert(history) db.getHistoryDao().upsert(history)
} }
} }
} }
@ -136,7 +136,7 @@ class BackupRepository @Inject constructor(
for (item in entry.data.JSONIterator()) { for (item in entry.data.JSONIterator()) {
val category = JsonDeserializer(item).toFavouriteCategoryEntity() val category = JsonDeserializer(item).toFavouriteCategoryEntity()
result += runCatchingCancellable { result += runCatchingCancellable {
db.favouriteCategoriesDao.upsert(category) db.getFavouriteCategoriesDao().upsert(category)
} }
} }
return result return result
@ -153,9 +153,9 @@ class BackupRepository @Inject constructor(
val favourite = JsonDeserializer(item).toFavouriteEntity() val favourite = JsonDeserializer(item).toFavouriteEntity()
result += runCatchingCancellable { result += runCatchingCancellable {
db.withTransaction { db.withTransaction {
db.tagsDao.upsert(tags) db.getTagsDao().upsert(tags)
db.mangaDao.upsert(manga, tags) db.getMangaDao().upsert(manga, tags)
db.favouritesDao.upsert(favourite) db.getFavouritesDao().upsert(favourite)
} }
} }
} }
@ -175,9 +175,9 @@ class BackupRepository @Inject constructor(
} }
result += runCatchingCancellable { result += runCatchingCancellable {
db.withTransaction { db.withTransaction {
db.tagsDao.upsert(tags) db.getTagsDao().upsert(tags)
db.mangaDao.upsert(manga, tags) db.getMangaDao().upsert(manga, tags)
db.bookmarksDao.upsert(bookmarks) db.getBookmarksDao().upsert(bookmarks)
} }
} }
} }

@ -66,29 +66,29 @@ const val DATABASE_VERSION = 17
) )
abstract class MangaDatabase : RoomDatabase() { abstract class MangaDatabase : RoomDatabase() {
abstract val historyDao: HistoryDao abstract fun getHistoryDao(): HistoryDao
abstract val tagsDao: TagsDao abstract fun getTagsDao(): TagsDao
abstract val mangaDao: MangaDao abstract fun getMangaDao(): MangaDao
abstract val favouritesDao: FavouritesDao abstract fun getFavouritesDao(): FavouritesDao
abstract val preferencesDao: PreferencesDao abstract fun getPreferencesDao(): PreferencesDao
abstract val favouriteCategoriesDao: FavouriteCategoriesDao abstract fun getFavouriteCategoriesDao(): FavouriteCategoriesDao
abstract val tracksDao: TracksDao abstract fun getTracksDao(): TracksDao
abstract val trackLogsDao: TrackLogsDao abstract fun getTrackLogsDao(): TrackLogsDao
abstract val suggestionDao: SuggestionDao abstract fun getSuggestionDao(): SuggestionDao
abstract val bookmarksDao: BookmarksDao abstract fun getBookmarksDao(): BookmarksDao
abstract val scrobblingDao: ScrobblingDao abstract fun getScrobblingDao(): ScrobblingDao
abstract val sourcesDao: MangaSourcesDao abstract fun getSourcesDao(): MangaSourcesDao
} }
fun getDatabaseMigrations(context: Context): Array<Migration> = arrayOf( fun getDatabaseMigrations(context: Context): Array<Migration> = arrayOf(

@ -28,16 +28,16 @@ class MangaDataRepository @Inject constructor(
suspend fun saveReaderMode(manga: Manga, mode: ReaderMode) { suspend fun saveReaderMode(manga: Manga, mode: ReaderMode) {
db.withTransaction { db.withTransaction {
storeManga(manga) storeManga(manga)
val entity = db.preferencesDao.find(manga.id) ?: newEntity(manga.id) val entity = db.getPreferencesDao().find(manga.id) ?: newEntity(manga.id)
db.preferencesDao.upsert(entity.copy(mode = mode.id)) db.getPreferencesDao().upsert(entity.copy(mode = mode.id))
} }
} }
suspend fun saveColorFilter(manga: Manga, colorFilter: ReaderColorFilter?) { suspend fun saveColorFilter(manga: Manga, colorFilter: ReaderColorFilter?) {
db.withTransaction { db.withTransaction {
storeManga(manga) storeManga(manga)
val entity = db.preferencesDao.find(manga.id) ?: newEntity(manga.id) val entity = db.getPreferencesDao().find(manga.id) ?: newEntity(manga.id)
db.preferencesDao.upsert( db.getPreferencesDao().upsert(
entity.copy( entity.copy(
cfBrightness = colorFilter?.brightness ?: 0f, cfBrightness = colorFilter?.brightness ?: 0f,
cfContrast = colorFilter?.contrast ?: 0f, cfContrast = colorFilter?.contrast ?: 0f,
@ -48,25 +48,25 @@ class MangaDataRepository @Inject constructor(
} }
suspend fun getReaderMode(mangaId: Long): ReaderMode? { suspend fun getReaderMode(mangaId: Long): ReaderMode? {
return db.preferencesDao.find(mangaId)?.let { ReaderMode.valueOf(it.mode) } return db.getPreferencesDao().find(mangaId)?.let { ReaderMode.valueOf(it.mode) }
} }
suspend fun getColorFilter(mangaId: Long): ReaderColorFilter? { suspend fun getColorFilter(mangaId: Long): ReaderColorFilter? {
return db.preferencesDao.find(mangaId)?.getColorFilterOrNull() return db.getPreferencesDao().find(mangaId)?.getColorFilterOrNull()
} }
fun observeColorFilter(mangaId: Long): Flow<ReaderColorFilter?> { fun observeColorFilter(mangaId: Long): Flow<ReaderColorFilter?> {
return db.preferencesDao.observe(mangaId) return db.getPreferencesDao().observe(mangaId)
.map { it?.getColorFilterOrNull() } .map { it?.getColorFilterOrNull() }
.distinctUntilChanged() .distinctUntilChanged()
} }
suspend fun findMangaById(mangaId: Long): Manga? { suspend fun findMangaById(mangaId: Long): Manga? {
return db.mangaDao.find(mangaId)?.toManga() return db.getMangaDao().find(mangaId)?.toManga()
} }
suspend fun findMangaByPublicUrl(publicUrl: String): Manga? { suspend fun findMangaByPublicUrl(publicUrl: String): Manga? {
return db.mangaDao.findByPublicUrl(publicUrl)?.toManga() return db.getMangaDao().findByPublicUrl(publicUrl)?.toManga()
} }
suspend fun resolveIntent(intent: MangaIntent): Manga? = when { suspend fun resolveIntent(intent: MangaIntent): Manga? = when {
@ -79,13 +79,13 @@ class MangaDataRepository @Inject constructor(
suspend fun storeManga(manga: Manga) { suspend fun storeManga(manga: Manga) {
val tags = manga.tags.toEntities() val tags = manga.tags.toEntities()
db.withTransaction { db.withTransaction {
db.tagsDao.upsert(tags) db.getTagsDao().upsert(tags)
db.mangaDao.upsert(manga.toEntity(), tags) db.getMangaDao().upsert(manga.toEntity(), tags)
} }
} }
suspend fun findTags(source: MangaSource): Set<MangaTag> { suspend fun findTags(source: MangaSource): Set<MangaTag> {
return db.tagsDao.findTags(source.name).toMangaTags() return db.getTagsDao().findTags(source.name).toMangaTags()
} }
private fun MangaPrefsEntity.getColorFilterOrNull(): ReaderColorFilter? { private fun MangaPrefsEntity.getColorFilterOrNull(): ReaderColorFilter? {

@ -16,7 +16,7 @@ class ProgressUpdateUseCase @Inject constructor(
) { ) {
suspend operator fun invoke(manga: Manga): Float { suspend operator fun invoke(manga: Manga): Float {
val history = database.historyDao.find(manga.id) ?: return PROGRESS_NONE val history = database.getHistoryDao().find(manga.id) ?: return PROGRESS_NONE
val seed = if (manga.isLocal) { val seed = if (manga.isLocal) {
localMangaRepository.getRemoteManga(manga) ?: manga localMangaRepository.getRemoteManga(manga) ?: manga
} else { } else {
@ -43,7 +43,7 @@ class ProgressUpdateUseCase @Inject constructor(
val ppc = 1f / chaptersCount val ppc = 1f / chaptersCount
val result = ppc * chapterIndex + ppc * pagePercent val result = ppc * chapterIndex + ppc * pagePercent
if (result != history.percent) { if (result != history.percent) {
database.historyDao.update( database.getHistoryDao().update(
history.copy( history.copy(
chapterId = chapter.id, chapterId = chapter.id,
percent = result, percent = result,

@ -30,7 +30,7 @@ class MangaSourcesRepository @Inject constructor(
) { ) {
private val dao: MangaSourcesDao private val dao: MangaSourcesDao
get() = db.sourcesDao get() = db.getSourcesDao()
private val remoteSources = EnumSet.allOf(MangaSource::class.java).apply { private val remoteSources = EnumSet.allOf(MangaSource::class.java).apply {
remove(MangaSource.LOCAL) remove(MangaSource.LOCAL)

@ -31,27 +31,27 @@ class FavouritesRepository @Inject constructor(
) { ) {
suspend fun getAllManga(): List<Manga> { suspend fun getAllManga(): List<Manga> {
val entities = db.favouritesDao.findAll() val entities = db.getFavouritesDao().findAll()
return entities.toMangaList() return entities.toMangaList()
} }
suspend fun getLastManga(limit: Int): List<Manga> { suspend fun getLastManga(limit: Int): List<Manga> {
val entities = db.favouritesDao.findLast(limit) val entities = db.getFavouritesDao().findLast(limit)
return entities.toMangaList() return entities.toMangaList()
} }
fun observeAll(order: ListSortOrder): Flow<List<Manga>> { fun observeAll(order: ListSortOrder): Flow<List<Manga>> {
return db.favouritesDao.observeAll(order) return db.getFavouritesDao().observeAll(order)
.mapItems { it.toManga() } .mapItems { it.toManga() }
} }
suspend fun getManga(categoryId: Long): List<Manga> { suspend fun getManga(categoryId: Long): List<Manga> {
val entities = db.favouritesDao.findAll(categoryId) val entities = db.getFavouritesDao().findAll(categoryId)
return entities.toMangaList() return entities.toMangaList()
} }
fun observeAll(categoryId: Long, order: ListSortOrder): Flow<List<Manga>> { fun observeAll(categoryId: Long, order: ListSortOrder): Flow<List<Manga>> {
return db.favouritesDao.observeAll(categoryId, order) return db.getFavouritesDao().observeAll(categoryId, order)
.mapItems { it.toManga() } .mapItems { it.toManga() }
} }
@ -61,25 +61,25 @@ class FavouritesRepository @Inject constructor(
} }
fun observeCategories(): Flow<List<FavouriteCategory>> { fun observeCategories(): Flow<List<FavouriteCategory>> {
return db.favouriteCategoriesDao.observeAll().mapItems { return db.getFavouriteCategoriesDao().observeAll().mapItems {
it.toFavouriteCategory() it.toFavouriteCategory()
}.distinctUntilChanged() }.distinctUntilChanged()
} }
fun observeCategoriesForLibrary(): Flow<List<FavouriteCategory>> { fun observeCategoriesForLibrary(): Flow<List<FavouriteCategory>> {
return db.favouriteCategoriesDao.observeAllForLibrary().mapItems { return db.getFavouriteCategoriesDao().observeAllForLibrary().mapItems {
it.toFavouriteCategory() it.toFavouriteCategory()
}.distinctUntilChanged() }.distinctUntilChanged()
} }
fun observeCategoriesWithCovers(): Flow<Map<FavouriteCategory, List<Cover>>> { fun observeCategoriesWithCovers(): Flow<Map<FavouriteCategory, List<Cover>>> {
return db.favouriteCategoriesDao.observeAll() return db.getFavouriteCategoriesDao().observeAll()
.map { .map {
db.withTransaction { db.withTransaction {
val res = LinkedHashMap<FavouriteCategory, List<Cover>>() val res = LinkedHashMap<FavouriteCategory, List<Cover>>()
for (entity in it) { for (entity in it) {
val cat = entity.toFavouriteCategory() val cat = entity.toFavouriteCategory()
res[cat] = db.favouritesDao.findCovers( res[cat] = db.getFavouritesDao().findCovers(
categoryId = cat.id, categoryId = cat.id,
order = cat.order, order = cat.order,
) )
@ -90,16 +90,16 @@ class FavouritesRepository @Inject constructor(
} }
fun observeCategory(id: Long): Flow<FavouriteCategory?> { fun observeCategory(id: Long): Flow<FavouriteCategory?> {
return db.favouriteCategoriesDao.observe(id) return db.getFavouriteCategoriesDao().observe(id)
.map { it?.toFavouriteCategory() } .map { it?.toFavouriteCategory() }
} }
fun observeCategoriesIds(mangaId: Long): Flow<Set<Long>> { fun observeCategoriesIds(mangaId: Long): Flow<Set<Long>> {
return db.favouritesDao.observeIds(mangaId).map { it.toSet() } return db.getFavouritesDao().observeIds(mangaId).map { it.toSet() }
} }
suspend fun getCategory(id: Long): FavouriteCategory { suspend fun getCategory(id: Long): FavouriteCategory {
return db.favouriteCategoriesDao.find(id.toInt()).toFavouriteCategory() return db.getFavouriteCategoriesDao().find(id.toInt()).toFavouriteCategory()
} }
suspend fun createCategory( suspend fun createCategory(
@ -111,14 +111,14 @@ class FavouritesRepository @Inject constructor(
val entity = FavouriteCategoryEntity( val entity = FavouriteCategoryEntity(
title = title, title = title,
createdAt = System.currentTimeMillis(), createdAt = System.currentTimeMillis(),
sortKey = db.favouriteCategoriesDao.getNextSortKey(), sortKey = db.getFavouriteCategoriesDao().getNextSortKey(),
categoryId = 0, categoryId = 0,
order = sortOrder.name, order = sortOrder.name,
track = isTrackerEnabled, track = isTrackerEnabled,
deletedAt = 0L, deletedAt = 0L,
isVisibleInLibrary = isVisibleOnShelf, isVisibleInLibrary = isVisibleOnShelf,
) )
val id = db.favouriteCategoriesDao.insert(entity) val id = db.getFavouriteCategoriesDao().insert(entity)
val category = entity.toFavouriteCategory(id) val category = entity.toFavouriteCategory(id)
channels.createChannel(category) channels.createChannel(category)
return category return category
@ -131,22 +131,22 @@ class FavouritesRepository @Inject constructor(
isTrackerEnabled: Boolean, isTrackerEnabled: Boolean,
isVisibleOnShelf: Boolean, isVisibleOnShelf: Boolean,
) { ) {
db.favouriteCategoriesDao.update(id, title, sortOrder.name, isTrackerEnabled, isVisibleOnShelf) db.getFavouriteCategoriesDao().update(id, title, sortOrder.name, isTrackerEnabled, isVisibleOnShelf)
} }
suspend fun updateCategory(id: Long, isVisibleInLibrary: Boolean) { suspend fun updateCategory(id: Long, isVisibleInLibrary: Boolean) {
db.favouriteCategoriesDao.updateLibVisibility(id, isVisibleInLibrary) db.getFavouriteCategoriesDao().updateLibVisibility(id, isVisibleInLibrary)
} }
suspend fun updateCategoryTracking(id: Long, isTrackingEnabled: Boolean) { suspend fun updateCategoryTracking(id: Long, isTrackingEnabled: Boolean) {
db.favouriteCategoriesDao.updateTracking(id, isTrackingEnabled) db.getFavouriteCategoriesDao().updateTracking(id, isTrackingEnabled)
} }
suspend fun removeCategories(ids: Collection<Long>) { suspend fun removeCategories(ids: Collection<Long>) {
db.withTransaction { db.withTransaction {
for (id in ids) { for (id in ids) {
db.favouritesDao.deleteAll(id) db.getFavouritesDao().deleteAll(id)
db.favouriteCategoriesDao.delete(id) db.getFavouriteCategoriesDao().delete(id)
} }
} }
// run after transaction success // run after transaction success
@ -156,11 +156,11 @@ class FavouritesRepository @Inject constructor(
} }
suspend fun setCategoryOrder(id: Long, order: ListSortOrder) { suspend fun setCategoryOrder(id: Long, order: ListSortOrder) {
db.favouriteCategoriesDao.updateOrder(id, order.name) db.getFavouriteCategoriesDao().updateOrder(id, order.name)
} }
suspend fun reorderCategories(orderedIds: List<Long>) { suspend fun reorderCategories(orderedIds: List<Long>) {
val dao = db.favouriteCategoriesDao val dao = db.getFavouriteCategoriesDao()
db.withTransaction { db.withTransaction {
for ((i, id) in orderedIds.withIndex()) { for ((i, id) in orderedIds.withIndex()) {
dao.updateSortKey(id, i) dao.updateSortKey(id, i)
@ -172,8 +172,8 @@ class FavouritesRepository @Inject constructor(
db.withTransaction { db.withTransaction {
for (manga in mangas) { for (manga in mangas) {
val tags = manga.tags.toEntities() val tags = manga.tags.toEntities()
db.tagsDao.upsert(tags) db.getTagsDao().upsert(tags)
db.mangaDao.upsert(manga.toEntity(), tags) db.getMangaDao().upsert(manga.toEntity(), tags)
val entity = FavouriteEntity( val entity = FavouriteEntity(
mangaId = manga.id, mangaId = manga.id,
categoryId = categoryId, categoryId = categoryId,
@ -181,7 +181,7 @@ class FavouritesRepository @Inject constructor(
sortKey = 0, sortKey = 0,
deletedAt = 0L, deletedAt = 0L,
) )
db.favouritesDao.insert(entity) db.getFavouritesDao().insert(entity)
} }
} }
} }
@ -189,7 +189,7 @@ class FavouritesRepository @Inject constructor(
suspend fun removeFromFavourites(ids: Collection<Long>): ReversibleHandle { suspend fun removeFromFavourites(ids: Collection<Long>): ReversibleHandle {
db.withTransaction { db.withTransaction {
for (id in ids) { for (id in ids) {
db.favouritesDao.delete(mangaId = id) db.getFavouritesDao().delete(mangaId = id)
} }
} }
return ReversibleHandle { recoverToFavourites(ids) } return ReversibleHandle { recoverToFavourites(ids) }
@ -198,14 +198,14 @@ class FavouritesRepository @Inject constructor(
suspend fun removeFromCategory(categoryId: Long, ids: Collection<Long>): ReversibleHandle { suspend fun removeFromCategory(categoryId: Long, ids: Collection<Long>): ReversibleHandle {
db.withTransaction { db.withTransaction {
for (id in ids) { for (id in ids) {
db.favouritesDao.delete(categoryId = categoryId, mangaId = id) db.getFavouritesDao().delete(categoryId = categoryId, mangaId = id)
} }
} }
return ReversibleHandle { recoverToCategory(categoryId, ids) } return ReversibleHandle { recoverToCategory(categoryId, ids) }
} }
private fun observeOrder(categoryId: Long): Flow<ListSortOrder> { private fun observeOrder(categoryId: Long): Flow<ListSortOrder> {
return db.favouriteCategoriesDao.observe(categoryId) return db.getFavouriteCategoriesDao().observe(categoryId)
.filterNotNull() .filterNotNull()
.map { x -> ListSortOrder(x.order, ListSortOrder.NEWEST) } .map { x -> ListSortOrder(x.order, ListSortOrder.NEWEST) }
.distinctUntilChanged() .distinctUntilChanged()
@ -214,7 +214,7 @@ class FavouritesRepository @Inject constructor(
private suspend fun recoverToFavourites(ids: Collection<Long>) { private suspend fun recoverToFavourites(ids: Collection<Long>) {
db.withTransaction { db.withTransaction {
for (id in ids) { for (id in ids) {
db.favouritesDao.recover(mangaId = id) db.getFavouritesDao().recover(mangaId = id)
} }
} }
} }
@ -222,7 +222,7 @@ class FavouritesRepository @Inject constructor(
private suspend fun recoverToCategory(categoryId: Long, ids: Collection<Long>) { private suspend fun recoverToCategory(categoryId: Long, ids: Collection<Long>) {
db.withTransaction { db.withTransaction {
for (id in ids) { for (id in ids) {
db.favouritesDao.recover(mangaId = id, categoryId = categoryId) db.getFavouritesDao().recover(mangaId = id, categoryId = categoryId)
} }
} }
} }

@ -23,7 +23,7 @@ abstract class HistoryDao {
@Transaction @Transaction
@Query("SELECT * FROM history WHERE deleted_at = 0 AND manga_id IN (:ids)") @Query("SELECT * FROM history WHERE deleted_at = 0 AND manga_id IN (:ids)")
abstract suspend fun findAll(ids: Collection<Long>): List<HistoryEntity?> abstract suspend fun findAll(ids: Collection<Long>): List<HistoryEntity>
@Transaction @Transaction
@Query("SELECT * FROM history WHERE deleted_at = 0 ORDER BY updated_at DESC") @Query("SELECT * FROM history WHERE deleted_at = 0 ORDER BY updated_at DESC")

@ -38,36 +38,36 @@ class HistoryRepository @Inject constructor(
) { ) {
suspend fun getList(offset: Int, limit: Int): List<Manga> { suspend fun getList(offset: Int, limit: Int): List<Manga> {
val entities = db.historyDao.findAll(offset, limit) val entities = db.getHistoryDao().findAll(offset, limit)
return entities.map { it.manga.toManga(it.tags.toMangaTags()) } return entities.map { it.manga.toManga(it.tags.toMangaTags()) }
} }
suspend fun getLastOrNull(): Manga? { suspend fun getLastOrNull(): Manga? {
val entity = db.historyDao.findAll(0, 1).firstOrNull() ?: return null val entity = db.getHistoryDao().findAll(0, 1).firstOrNull() ?: return null
return entity.manga.toManga(entity.tags.toMangaTags()) return entity.manga.toManga(entity.tags.toMangaTags())
} }
fun observeLast(): Flow<Manga?> { fun observeLast(): Flow<Manga?> {
return db.historyDao.observeAll(1).map { return db.getHistoryDao().observeAll(1).map {
val first = it.firstOrNull() val first = it.firstOrNull()
first?.manga?.toManga(first.tags.toMangaTags()) first?.manga?.toManga(first.tags.toMangaTags())
} }
} }
fun observeAll(): Flow<List<Manga>> { fun observeAll(): Flow<List<Manga>> {
return db.historyDao.observeAll().mapItems { return db.getHistoryDao().observeAll().mapItems {
it.manga.toManga(it.tags.toMangaTags()) it.manga.toManga(it.tags.toMangaTags())
} }
} }
fun observeAll(limit: Int): Flow<List<Manga>> { fun observeAll(limit: Int): Flow<List<Manga>> {
return db.historyDao.observeAll(limit).mapItems { return db.getHistoryDao().observeAll(limit).mapItems {
it.manga.toManga(it.tags.toMangaTags()) it.manga.toManga(it.tags.toMangaTags())
} }
} }
fun observeAllWithHistory(order: ListSortOrder): Flow<List<MangaWithHistory>> { fun observeAllWithHistory(order: ListSortOrder): Flow<List<MangaWithHistory>> {
return db.historyDao.observeAll(order).mapItems { return db.getHistoryDao().observeAll(order).mapItems {
MangaWithHistory( MangaWithHistory(
it.manga.toManga(it.tags.toMangaTags()), it.manga.toManga(it.tags.toMangaTags()),
it.history.toMangaHistory(), it.history.toMangaHistory(),
@ -76,13 +76,13 @@ class HistoryRepository @Inject constructor(
} }
fun observeOne(id: Long): Flow<MangaHistory?> { fun observeOne(id: Long): Flow<MangaHistory?> {
return db.historyDao.observe(id).map { return db.getHistoryDao().observe(id).map {
it?.toMangaHistory() it?.toMangaHistory()
} }
} }
fun observeHasItems(): Flow<Boolean> { fun observeHasItems(): Flow<Boolean> {
return db.historyDao.observeCount() return db.getHistoryDao().observeCount()
.map { it > 0 } .map { it > 0 }
.distinctUntilChanged() .distinctUntilChanged()
} }
@ -93,12 +93,12 @@ class HistoryRepository @Inject constructor(
} }
val tags = manga.tags.toEntities() val tags = manga.tags.toEntities()
db.withTransaction { db.withTransaction {
val existing = db.mangaDao.find(manga.id)?.manga val existing = db.getMangaDao().find(manga.id)?.manga
if (existing == null || existing.source == manga.source.name) { if (existing == null || existing.source == manga.source.name) {
db.tagsDao.upsert(tags) db.getTagsDao().upsert(tags)
db.mangaDao.upsert(manga.toEntity(), tags) db.getMangaDao().upsert(manga.toEntity(), tags)
} }
db.historyDao.upsert( db.getHistoryDao().upsert(
HistoryEntity( HistoryEntity(
mangaId = manga.id, mangaId = manga.id,
createdAt = System.currentTimeMillis(), createdAt = System.currentTimeMillis(),
@ -119,29 +119,29 @@ class HistoryRepository @Inject constructor(
} }
suspend fun getOne(manga: Manga): MangaHistory? { suspend fun getOne(manga: Manga): MangaHistory? {
return db.historyDao.find(manga.id)?.recoverIfNeeded(manga)?.toMangaHistory() return db.getHistoryDao().find(manga.id)?.recoverIfNeeded(manga)?.toMangaHistory()
} }
suspend fun getProgress(mangaId: Long): Float { suspend fun getProgress(mangaId: Long): Float {
return db.historyDao.findProgress(mangaId) ?: PROGRESS_NONE return db.getHistoryDao().findProgress(mangaId) ?: PROGRESS_NONE
} }
suspend fun clear() { suspend fun clear() {
db.historyDao.clear() db.getHistoryDao().clear()
} }
suspend fun delete(manga: Manga) { suspend fun delete(manga: Manga) {
db.historyDao.delete(manga.id) db.getHistoryDao().delete(manga.id)
} }
suspend fun deleteAfter(minDate: Long) { suspend fun deleteAfter(minDate: Long) {
db.historyDao.deleteAfter(minDate) db.getHistoryDao().deleteAfter(minDate)
} }
suspend fun delete(ids: Collection<Long>): ReversibleHandle { suspend fun delete(ids: Collection<Long>): ReversibleHandle {
db.withTransaction { db.withTransaction {
for (id in ids) { for (id in ids) {
db.historyDao.delete(id) db.getHistoryDao().delete(id)
} }
} }
return ReversibleHandle { return ReversibleHandle {
@ -154,13 +154,13 @@ class HistoryRepository @Inject constructor(
* Useful for replacing saved manga on deleting it with remote source * Useful for replacing saved manga on deleting it with remote source
*/ */
suspend fun deleteOrSwap(manga: Manga, alternative: Manga?) { suspend fun deleteOrSwap(manga: Manga, alternative: Manga?) {
if (alternative == null || db.mangaDao.update(alternative.toEntity()) <= 0) { if (alternative == null || db.getMangaDao().update(alternative.toEntity()) <= 0) {
db.historyDao.delete(manga.id) db.getHistoryDao().delete(manga.id)
} }
} }
suspend fun getPopularTags(limit: Int): List<MangaTag> { suspend fun getPopularTags(limit: Int): List<MangaTag> {
return db.historyDao.findPopularTags(limit).map { x -> x.toMangaTag() } return db.getHistoryDao().findPopularTags(limit).map { x -> x.toMangaTag() }
} }
fun shouldSkip(manga: Manga): Boolean { fun shouldSkip(manga: Manga): Boolean {
@ -178,7 +178,7 @@ class HistoryRepository @Inject constructor(
private suspend fun recover(ids: Collection<Long>) { private suspend fun recover(ids: Collection<Long>) {
db.withTransaction { db.withTransaction {
for (id in ids) { for (id in ids) {
db.historyDao.recover(id) db.getHistoryDao().recover(id)
} }
} }
} }
@ -192,7 +192,7 @@ class HistoryRepository @Inject constructor(
(chapters.size * percent).toInt(), (chapters.size * percent).toInt(),
)?.id ?: return this )?.id ?: return this
val newEntity = copy(chapterId = newChapterId) val newEntity = copy(chapterId = newChapterId)
db.historyDao.update(newEntity) db.getHistoryDao().update(newEntity)
return newEntity return newEntity
} }
} }

@ -106,7 +106,7 @@ class AniListRepository @Inject constructor(
} }
override suspend fun unregister(mangaId: Long) { override suspend fun unregister(mangaId: Long) {
return db.scrobblingDao.delete(ScrobblerService.ANILIST.id, mangaId) return db.getScrobblingDao().delete(ScrobblerService.ANILIST.id, mangaId)
} }
override fun logout() { override fun logout() {
@ -223,7 +223,7 @@ class AniListRepository @Inject constructor(
comment = json.getString("notes"), comment = json.getString("notes"),
rating = scoreFormat.normalize(json.getDouble("score").toFloat()), rating = scoreFormat.normalize(json.getDouble("score").toFloat()),
) )
db.scrobblingDao.upsert(entity) db.getScrobblingDao().upsert(entity)
} }
private fun ScrobblerManga(json: JSONObject): ScrobblerManga { private fun ScrobblerManga(json: JSONObject): ScrobblerManga {

@ -29,7 +29,7 @@ class AniListScrobbler @Inject constructor(
status: ScrobblingStatus?, status: ScrobblingStatus?,
comment: String?, comment: String?,
) { ) {
val entity = db.scrobblingDao.find(scrobblerService.id, mangaId) val entity = db.getScrobblingDao().find(scrobblerService.id, mangaId)
requireNotNull(entity) { "Scrobbling info for manga $mangaId not found" } requireNotNull(entity) { "Scrobbling info for manga $mangaId not found" }
repository.updateRate( repository.updateRate(
rateId = entity.id, rateId = entity.id,

@ -67,24 +67,24 @@ abstract class Scrobbler(
} }
suspend fun scrobble(mangaId: Long, chapter: MangaChapter) { suspend fun scrobble(mangaId: Long, chapter: MangaChapter) {
val entity = db.scrobblingDao.find(scrobblerService.id, mangaId) ?: return val entity = db.getScrobblingDao().find(scrobblerService.id, mangaId) ?: return
repository.updateRate(entity.id, entity.mangaId, chapter) repository.updateRate(entity.id, entity.mangaId, chapter)
} }
suspend fun getScrobblingInfoOrNull(mangaId: Long): ScrobblingInfo? { suspend fun getScrobblingInfoOrNull(mangaId: Long): ScrobblingInfo? {
val entity = db.scrobblingDao.find(scrobblerService.id, mangaId) ?: return null val entity = db.getScrobblingDao().find(scrobblerService.id, mangaId) ?: return null
return entity.toScrobblingInfo() return entity.toScrobblingInfo()
} }
abstract suspend fun updateScrobblingInfo(mangaId: Long, rating: Float, status: ScrobblingStatus?, comment: String?) abstract suspend fun updateScrobblingInfo(mangaId: Long, rating: Float, status: ScrobblingStatus?, comment: String?)
fun observeScrobblingInfo(mangaId: Long): Flow<ScrobblingInfo?> { fun observeScrobblingInfo(mangaId: Long): Flow<ScrobblingInfo?> {
return db.scrobblingDao.observe(scrobblerService.id, mangaId) return db.getScrobblingDao().observe(scrobblerService.id, mangaId)
.map { it?.toScrobblingInfo() } .map { it?.toScrobblingInfo() }
} }
fun observeAllScrobblingInfo(): Flow<List<ScrobblingInfo>> { fun observeAllScrobblingInfo(): Flow<List<ScrobblingInfo>> {
return db.scrobblingDao.observe(scrobblerService.id) return db.getScrobblingDao().observe(scrobblerService.id)
.map { entities -> .map { entities ->
coroutineScope { coroutineScope {
entities.map { entities.map {

@ -85,7 +85,7 @@ class MALRepository @Inject constructor(
} }
override suspend fun unregister(mangaId: Long) { override suspend fun unregister(mangaId: Long) {
return db.scrobblingDao.delete(ScrobblerService.MAL.id, mangaId) return db.getScrobblingDao().delete(ScrobblerService.MAL.id, mangaId)
} }
override suspend fun findManga(query: String, offset: Int): List<ScrobblerManga> { override suspend fun findManga(query: String, offset: Int): List<ScrobblerManga> {
@ -176,7 +176,7 @@ class MALRepository @Inject constructor(
comment = json.getString("comments"), comment = json.getString("comments"),
rating = (json.getDouble("score").toFloat() / 10f).coerceIn(0f, 1f), rating = (json.getDouble("score").toFloat() / 10f).coerceIn(0f, 1f),
) )
db.scrobblingDao.upsert(entity) db.getScrobblingDao().upsert(entity)
} }
override fun logout() { override fun logout() {

@ -30,7 +30,7 @@ class MALScrobbler @Inject constructor(
status: ScrobblingStatus?, status: ScrobblingStatus?,
comment: String?, comment: String?,
) { ) {
val entity = db.scrobblingDao.find(scrobblerService.id, mangaId) val entity = db.getScrobblingDao().find(scrobblerService.id, mangaId)
requireNotNull(entity) { "Scrobbling info for manga $mangaId not found" } requireNotNull(entity) { "Scrobbling info for manga $mangaId not found" }
repository.updateRate( repository.updateRate(
rateId = entity.id, rateId = entity.id,

@ -84,7 +84,7 @@ class ShikimoriRepository @Inject constructor(
} }
override suspend fun unregister(mangaId: Long) { override suspend fun unregister(mangaId: Long) {
return db.scrobblingDao.delete(ScrobblerService.SHIKIMORI.id, mangaId) return db.getScrobblingDao().delete(ScrobblerService.SHIKIMORI.id, mangaId)
} }
override fun logout() { override fun logout() {
@ -192,7 +192,7 @@ class ShikimoriRepository @Inject constructor(
comment = json.getString("text"), comment = json.getString("text"),
rating = (json.getDouble("score").toFloat() / 10f).coerceIn(0f, 1f), rating = (json.getDouble("score").toFloat() / 10f).coerceIn(0f, 1f),
) )
db.scrobblingDao.upsert(entity) db.getScrobblingDao().upsert(entity)
} }
private fun ScrobblerManga(json: JSONObject) = ScrobblerManga( private fun ScrobblerManga(json: JSONObject) = ScrobblerManga(

@ -31,7 +31,7 @@ class ShikimoriScrobbler @Inject constructor(
status: ScrobblingStatus?, status: ScrobblingStatus?,
comment: String?, comment: String?,
) { ) {
val entity = db.scrobblingDao.find(scrobblerService.id, mangaId) val entity = db.getScrobblingDao().find(scrobblerService.id, mangaId)
requireNotNull(entity) { "Scrobbling info for manga $mangaId not found" } requireNotNull(entity) { "Scrobbling info for manga $mangaId not found" }
repository.updateRate( repository.updateRate(
rateId = entity.id, rateId = entity.id,

@ -40,9 +40,9 @@ class MangaSearchRepository @Inject constructor(
} }
val skipNsfw = settings.isNsfwContentDisabled val skipNsfw = settings.isNsfwContentDisabled
return if (source != null) { return if (source != null) {
db.mangaDao.searchByTitle("%$query%", source.name, limit) db.getMangaDao().searchByTitle("%$query%", source.name, limit)
} else { } else {
db.mangaDao.searchByTitle("%$query%", limit) db.getMangaDao().searchByTitle("%$query%", limit)
}.let { }.let {
if (skipNsfw) it.filterNot { x -> x.manga.isNsfw } else it if (skipNsfw) it.filterNot { x -> x.manga.isNsfw } else it
} }
@ -83,7 +83,7 @@ class MangaSearchRepository @Inject constructor(
if (query.isEmpty()) { if (query.isEmpty()) {
return emptyList() return emptyList()
} }
val titles = db.suggestionDao.getTitles("$query%") val titles = db.getSuggestionDao().getTitles("$query%")
if (titles.isEmpty()) { if (titles.isEmpty()) {
return emptyList() return emptyList()
} }
@ -92,19 +92,20 @@ class MangaSearchRepository @Inject constructor(
suspend fun getTagsSuggestion(query: String, limit: Int, source: MangaSource?): List<MangaTag> { suspend fun getTagsSuggestion(query: String, limit: Int, source: MangaSource?): List<MangaTag> {
return when { return when {
query.isNotEmpty() && source != null -> db.tagsDao.findTags(source.name, "%$query%", limit) query.isNotEmpty() && source != null -> db.getTagsDao()
query.isNotEmpty() -> db.tagsDao.findTags("%$query%", limit) .findTags(source.name, "%$query%", limit)
source != null -> db.tagsDao.findPopularTags(source.name, limit) query.isNotEmpty() -> db.getTagsDao().findTags("%$query%", limit)
else -> db.tagsDao.findPopularTags(limit) source != null -> db.getTagsDao().findPopularTags(source.name, limit)
else -> db.getTagsDao().findPopularTags(limit)
}.toMangaTagsList() }.toMangaTagsList()
} }
suspend fun getTagsSuggestion(tags: Set<MangaTag>): List<MangaTag> { suspend fun getTagsSuggestion(tags: Set<MangaTag>): List<MangaTag> {
val ids = tags.mapToSet { it.toEntity().id } val ids = tags.mapToSet { it.toEntity().id }
return if (ids.size == 1) { return if (ids.size == 1) {
db.tagsDao.findRelatedTags(ids.first()) db.getTagsDao().findRelatedTags(ids.first())
} else { } else {
db.tagsDao.findRelatedTags(ids) db.getTagsDao().findRelatedTags(ids)
}.mapNotNull { x -> }.mapNotNull { x ->
if (x.id in ids) null else x.toMangaTag() if (x.id in ids) null else x.toMangaTag()
} }

@ -11,7 +11,7 @@ class TagsAutoCompleteProvider @Inject constructor(
if (query.isEmpty()) { if (query.isEmpty()) {
return emptyList() return emptyList()
} }
val tags = db.tagsDao.findTags(query = "$query%", limit = 6) val tags = db.getTagsDao().findTags(query = "$query%", limit = 6)
val set = HashSet<String>() val set = HashSet<String>()
val result = ArrayList<String>(tags.size) val result = ArrayList<String>(tags.size)
for (tag in tags) { for (tag in tags) {

@ -17,39 +17,39 @@ class SuggestionRepository @Inject constructor(
) { ) {
fun observeAll(): Flow<List<Manga>> { fun observeAll(): Flow<List<Manga>> {
return db.suggestionDao.observeAll().mapItems { return db.getSuggestionDao().observeAll().mapItems {
it.manga.toManga(it.tags.toMangaTags()) it.manga.toManga(it.tags.toMangaTags())
} }
} }
fun observeAll(limit: Int): Flow<List<Manga>> { fun observeAll(limit: Int): Flow<List<Manga>> {
return db.suggestionDao.observeAll(limit).mapItems { return db.getSuggestionDao().observeAll(limit).mapItems {
it.manga.toManga(it.tags.toMangaTags()) it.manga.toManga(it.tags.toMangaTags())
} }
} }
suspend fun getRandom(): Manga? { suspend fun getRandom(): Manga? {
return db.suggestionDao.getRandom()?.let { return db.getSuggestionDao().getRandom()?.let {
it.manga.toManga(it.tags.toMangaTags()) it.manga.toManga(it.tags.toMangaTags())
} }
} }
suspend fun clear() { suspend fun clear() {
db.suggestionDao.deleteAll() db.getSuggestionDao().deleteAll()
} }
suspend fun isEmpty(): Boolean { suspend fun isEmpty(): Boolean {
return db.suggestionDao.count() == 0 return db.getSuggestionDao().count() == 0
} }
suspend fun replace(suggestions: Iterable<MangaSuggestion>) { suspend fun replace(suggestions: Iterable<MangaSuggestion>) {
db.withTransaction { db.withTransaction {
db.suggestionDao.deleteAll() db.getSuggestionDao().deleteAll()
suggestions.forEach { (manga, relevance) -> suggestions.forEach { (manga, relevance) ->
val tags = manga.tags.toEntities() val tags = manga.tags.toEntities()
db.tagsDao.upsert(tags) db.getTagsDao().upsert(tags)
db.mangaDao.upsert(manga.toEntity(), tags) db.getMangaDao().upsert(manga.toEntity(), tags)
db.suggestionDao.upsert( db.getSuggestionDao().upsert(
SuggestionEntity( SuggestionEntity(
mangaId = manga.id, mangaId = manga.id,
relevance = relevance, relevance = relevance,

@ -120,11 +120,11 @@ class SyncController @Inject constructor(
private suspend fun MangaDatabase.gc(favourites: Boolean, history: Boolean) = withTransaction { private suspend fun MangaDatabase.gc(favourites: Boolean, history: Boolean) = withTransaction {
val deletedAt = System.currentTimeMillis() - defaultGcPeriod val deletedAt = System.currentTimeMillis() - defaultGcPeriod
if (history) { if (history) {
historyDao.gc(deletedAt) getHistoryDao().gc(deletedAt)
} }
if (favourites) { if (favourites) {
favouritesDao.gc(deletedAt) getFavouritesDao().gc(deletedAt)
favouriteCategoriesDao.gc(deletedAt) getFavouriteCategoriesDao().gc(deletedAt)
} }
} }

@ -20,11 +20,11 @@ import org.koitharu.kotatsu.core.db.entity.MangaEntity
class TrackEntity( class TrackEntity(
@PrimaryKey(autoGenerate = false) @PrimaryKey(autoGenerate = false)
@ColumnInfo(name = "manga_id") val mangaId: Long, @ColumnInfo(name = "manga_id") val mangaId: Long,
@get:Deprecated(message = "Should not be used", level = DeprecationLevel.ERROR) @get:Deprecated(message = "Should not be used", level = DeprecationLevel.WARNING)
@ColumnInfo(name = "chapters_total") val totalChapters: Int, @ColumnInfo(name = "chapters_total") val totalChapters: Int,
@ColumnInfo(name = "last_chapter_id") val lastChapterId: Long, @ColumnInfo(name = "last_chapter_id") val lastChapterId: Long,
@ColumnInfo(name = "chapters_new") val newChapters: Int, @ColumnInfo(name = "chapters_new") val newChapters: Int,
@ColumnInfo(name = "last_check") val lastCheck: Long, @ColumnInfo(name = "last_check") val lastCheck: Long,
@get:Deprecated(message = "Should not be used", level = DeprecationLevel.ERROR) @get:Deprecated(message = "Should not be used", level = DeprecationLevel.WARNING)
@ColumnInfo(name = "last_notified_id") val lastNotifiedChapterId: Long @ColumnInfo(name = "last_notified_id") val lastNotifiedChapterId: Long
) )

@ -41,23 +41,23 @@ class TrackingRepository @Inject constructor(
private var isGcCalled = AtomicBoolean(false) private var isGcCalled = AtomicBoolean(false)
suspend fun getNewChaptersCount(mangaId: Long): Int { suspend fun getNewChaptersCount(mangaId: Long): Int {
return db.tracksDao.findNewChapters(mangaId) ?: 0 return db.getTracksDao().findNewChapters(mangaId) ?: 0
} }
fun observeNewChaptersCount(mangaId: Long): Flow<Int> { fun observeNewChaptersCount(mangaId: Long): Flow<Int> {
return db.tracksDao.observeNewChapters(mangaId).map { it ?: 0 } return db.getTracksDao().observeNewChapters(mangaId).map { it ?: 0 }
} }
fun observeUpdatedMangaCount(): Flow<Int> { fun observeUpdatedMangaCount(): Flow<Int> {
return db.tracksDao.observeNewChapters().map { list -> list.count { it > 0 } } return db.getTracksDao().observeNewChapters().map { list -> list.count { it > 0 } }
.onStart { gcIfNotCalled() } .onStart { gcIfNotCalled() }
} }
fun observeUpdatedManga(limit: Int = 0): Flow<List<Manga>> { fun observeUpdatedManga(limit: Int = 0): Flow<List<Manga>> {
return if (limit == 0) { return if (limit == 0) {
db.tracksDao.observeUpdatedManga() db.getTracksDao().observeUpdatedManga()
} else { } else {
db.tracksDao.observeUpdatedManga(limit) db.getTracksDao().observeUpdatedManga(limit)
}.mapItems { it.toManga() } }.mapItems { it.toManga() }
.distinctUntilChanged() .distinctUntilChanged()
.onStart { gcIfNotCalled() } .onStart { gcIfNotCalled() }
@ -65,7 +65,7 @@ class TrackingRepository @Inject constructor(
suspend fun getTracks(mangaList: Collection<Manga>): List<MangaTracking> { suspend fun getTracks(mangaList: Collection<Manga>): List<MangaTracking> {
val ids = mangaList.mapToSet { it.id } val ids = mangaList.mapToSet { it.id }
val tracks = db.tracksDao.findAll(ids).groupBy { it.mangaId } val tracks = db.getTracksDao().findAll(ids).groupBy { it.mangaId }
val idSet = HashSet<Long>() val idSet = HashSet<Long>()
val result = ArrayList<MangaTracking>(mangaList.size) val result = ArrayList<MangaTracking>(mangaList.size)
for (item in mangaList) { for (item in mangaList) {
@ -89,7 +89,7 @@ class TrackingRepository @Inject constructor(
@VisibleForTesting @VisibleForTesting
suspend fun getTrack(manga: Manga): MangaTracking { suspend fun getTrack(manga: Manga): MangaTracking {
val track = db.tracksDao.find(manga.id) val track = db.getTracksDao().find(manga.id)
return MangaTracking( return MangaTracking(
manga = manga, manga = manga,
lastChapterId = track?.lastChapterId ?: NO_ID, lastChapterId = track?.lastChapterId ?: NO_ID,
@ -99,14 +99,14 @@ class TrackingRepository @Inject constructor(
@VisibleForTesting @VisibleForTesting
suspend fun deleteTrack(mangaId: Long) { suspend fun deleteTrack(mangaId: Long) {
db.tracksDao.delete(mangaId) db.getTracksDao().delete(mangaId)
} }
fun observeTrackingLog(limit: Flow<Int>): Flow<List<TrackingLogItem>> { fun observeTrackingLog(limit: Flow<Int>): Flow<List<TrackingLogItem>> {
return limit.flatMapLatest { limitValue -> return limit.flatMapLatest { limitValue ->
combine( combine(
db.tracksDao.observeNewChaptersMap(), db.getTracksDao().observeNewChaptersMap(),
db.trackLogsDao.observeAll(limitValue), db.getTrackLogsDao().observeAll(limitValue),
) { counters, entities -> ) { counters, entities ->
val countersMap = counters.toMutableMap() val countersMap = counters.toMutableMap()
entities.map { x -> x.toTrackingLogItem(countersMap) } entities.map { x -> x.toTrackingLogItem(countersMap) }
@ -116,21 +116,21 @@ class TrackingRepository @Inject constructor(
} }
} }
suspend fun getLogsCount() = db.trackLogsDao.count() suspend fun getLogsCount() = db.getTrackLogsDao().count()
suspend fun clearLogs() = db.trackLogsDao.clear() suspend fun clearLogs() = db.getTrackLogsDao().clear()
suspend fun clearCounters() = db.tracksDao.clearCounters() suspend fun clearCounters() = db.getTracksDao().clearCounters()
suspend fun gc() { suspend fun gc() {
db.tracksDao.gc() db.getTracksDao().gc()
db.trackLogsDao.gc() db.getTrackLogsDao().gc()
} }
suspend fun saveUpdates(updates: MangaUpdates.Success) { suspend fun saveUpdates(updates: MangaUpdates.Success) {
db.withTransaction { db.withTransaction {
val track = getOrCreateTrack(updates.manga.id).mergeWith(updates) val track = getOrCreateTrack(updates.manga.id).mergeWith(updates)
db.tracksDao.upsert(track) db.getTracksDao().upsert(track)
if (updates.isValid && updates.newChapters.isNotEmpty()) { if (updates.isValid && updates.newChapters.isNotEmpty()) {
updatePercent(updates) updatePercent(updates)
val logEntity = TrackLogEntity( val logEntity = TrackLogEntity(
@ -138,7 +138,7 @@ class TrackingRepository @Inject constructor(
chapters = updates.newChapters.joinToString("\n") { x -> x.name }, chapters = updates.newChapters.joinToString("\n") { x -> x.name },
createdAt = System.currentTimeMillis(), createdAt = System.currentTimeMillis(),
) )
db.trackLogsDao.insert(logEntity) db.getTrackLogsDao().insert(logEntity)
} }
} }
} }
@ -146,10 +146,10 @@ class TrackingRepository @Inject constructor(
suspend fun clearUpdates(ids: Collection<Long>) { suspend fun clearUpdates(ids: Collection<Long>) {
when { when {
ids.isEmpty() -> return ids.isEmpty() -> return
ids.size == 1 -> db.tracksDao.clearCounter(ids.single()) ids.size == 1 -> db.getTracksDao().clearCounter(ids.single())
else -> db.withTransaction { else -> db.withTransaction {
for (id in ids) { for (id in ids) {
db.tracksDao.clearCounter(id) db.getTracksDao().clearCounter(id)
} }
} }
} }
@ -174,11 +174,11 @@ class TrackingRepository @Inject constructor(
lastCheck = System.currentTimeMillis(), lastCheck = System.currentTimeMillis(),
lastNotifiedChapterId = lastChapterId, lastNotifiedChapterId = lastChapterId,
) )
db.tracksDao.upsert(entity) db.getTracksDao().upsert(entity)
} }
suspend fun getCategoriesCount(): IntArray { suspend fun getCategoriesCount(): IntArray {
val categories = db.favouriteCategoriesDao.findAll() val categories = db.getFavouriteCategoriesDao().findAll()
return intArrayOf( return intArrayOf(
categories.count { it.track }, categories.count { it.track },
categories.size, categories.size,
@ -186,19 +186,19 @@ class TrackingRepository @Inject constructor(
} }
suspend fun getAllFavouritesManga(): Map<FavouriteCategory, List<Manga>> { suspend fun getAllFavouritesManga(): Map<FavouriteCategory, List<Manga>> {
val categories = db.favouriteCategoriesDao.findAll() val categories = db.getFavouriteCategoriesDao().findAll()
return categories.associateTo(LinkedHashMap(categories.size)) { categoryEntity -> return categories.associateTo(LinkedHashMap(categories.size)) { categoryEntity ->
categoryEntity.toFavouriteCategory() to categoryEntity.toFavouriteCategory() to
db.favouritesDao.findAllManga(categoryEntity.categoryId).toMangaList() db.getFavouritesDao().findAllManga(categoryEntity.categoryId).toMangaList()
} }
} }
suspend fun getAllHistoryManga(): List<Manga> { suspend fun getAllHistoryManga(): List<Manga> {
return db.historyDao.findAllManga().toMangaList() return db.getHistoryDao().findAllManga().toMangaList()
} }
private suspend fun getOrCreateTrack(mangaId: Long): TrackEntity { private suspend fun getOrCreateTrack(mangaId: Long): TrackEntity {
return db.tracksDao.find(mangaId) ?: TrackEntity( return db.getTracksDao().find(mangaId) ?: TrackEntity(
mangaId = mangaId, mangaId = mangaId,
totalChapters = 0, totalChapters = 0,
lastChapterId = 0L, lastChapterId = 0L,
@ -209,7 +209,7 @@ class TrackingRepository @Inject constructor(
} }
private suspend fun updatePercent(updates: MangaUpdates.Success) { private suspend fun updatePercent(updates: MangaUpdates.Success) {
val history = db.historyDao.find(updates.manga.id) ?: return val history = db.getHistoryDao().find(updates.manga.id) ?: return
val chapters = updates.manga.chapters val chapters = updates.manga.chapters
if (chapters.isNullOrEmpty()) { if (chapters.isNullOrEmpty()) {
return return
@ -220,7 +220,7 @@ class TrackingRepository @Inject constructor(
} }
val position = (chapters.size - updates.newChapters.size) * history.percent val position = (chapters.size - updates.newChapters.size) * history.percent
val newPercent = position / chapters.size.toFloat() val newPercent = position / chapters.size.toFloat()
db.historyDao.update(history.copy(percent = newPercent)) db.getHistoryDao().update(history.copy(percent = newPercent))
} }
private fun TrackEntity.mergeWith(updates: MangaUpdates.Success): TrackEntity { private fun TrackEntity.mergeWith(updates: MangaUpdates.Success): TrackEntity {

Loading…
Cancel
Save