Use sqldelight in migration (#7331)
* Use sqldelight in migration * Some more changes Co-Authored-By: Ivan Iskandar <12537387+ivaniskandar@users.noreply.github.com> * Review Changes * Review changes 2 * Review Changes 3 * Review Changes 4 Co-authored-by: Ivan Iskandar <12537387+ivaniskandar@users.noreply.github.com> (cherry picked from commit e3b1053c03da17c8c1b66f1914251707134e84a9) # Conflicts: # app/src/main/java/eu/kanade/tachiyomi/ui/browse/migration/search/SearchPresenter.kt # app/src/main/java/eu/kanade/tachiyomi/ui/manga/MangaPresenter.kt
This commit is contained in:
parent
9e63d7fb0b
commit
14a57b7d4d
@ -55,6 +55,12 @@ class CategoryRepositoryImpl(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override suspend fun getCategoriesForManga(mangaId: Long): List<Category> {
|
||||||
|
return handler.awaitList {
|
||||||
|
categoriesQueries.getCategoriesByMangaId(mangaId, categoryMapper)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
override suspend fun checkDuplicateName(name: String): Boolean {
|
override suspend fun checkDuplicateName(name: String): Boolean {
|
||||||
return handler
|
return handler
|
||||||
.awaitList { categoriesQueries.getCategories() }
|
.awaitList { categoriesQueries.getCategories() }
|
||||||
|
@ -41,8 +41,27 @@ class ChapterRepositoryImpl(
|
|||||||
}
|
}
|
||||||
|
|
||||||
override suspend fun update(chapterUpdate: ChapterUpdate) {
|
override suspend fun update(chapterUpdate: ChapterUpdate) {
|
||||||
try {
|
handler.await {
|
||||||
handler.await {
|
chaptersQueries.update(
|
||||||
|
chapterUpdate.mangaId,
|
||||||
|
chapterUpdate.url,
|
||||||
|
chapterUpdate.name,
|
||||||
|
chapterUpdate.scanlator,
|
||||||
|
chapterUpdate.read?.toLong(),
|
||||||
|
chapterUpdate.bookmark?.toLong(),
|
||||||
|
chapterUpdate.lastPageRead,
|
||||||
|
chapterUpdate.chapterNumber?.toDouble(),
|
||||||
|
chapterUpdate.sourceOrder,
|
||||||
|
chapterUpdate.dateFetch,
|
||||||
|
chapterUpdate.dateUpload,
|
||||||
|
chapterId = chapterUpdate.id,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override suspend fun updateAll(chapterUpdates: List<ChapterUpdate>) {
|
||||||
|
handler.await(inTransaction = true) {
|
||||||
|
chapterUpdates.forEach { chapterUpdate ->
|
||||||
chaptersQueries.update(
|
chaptersQueries.update(
|
||||||
chapterUpdate.mangaId,
|
chapterUpdate.mangaId,
|
||||||
chapterUpdate.url,
|
chapterUpdate.url,
|
||||||
@ -58,33 +77,6 @@ class ChapterRepositoryImpl(
|
|||||||
chapterId = chapterUpdate.id,
|
chapterId = chapterUpdate.id,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
} catch (e: Exception) {
|
|
||||||
logcat(LogPriority.ERROR, e)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override suspend fun updateAll(chapterUpdates: List<ChapterUpdate>) {
|
|
||||||
try {
|
|
||||||
handler.await(inTransaction = true) {
|
|
||||||
chapterUpdates.forEach { chapterUpdate ->
|
|
||||||
chaptersQueries.update(
|
|
||||||
chapterUpdate.mangaId,
|
|
||||||
chapterUpdate.url,
|
|
||||||
chapterUpdate.name,
|
|
||||||
chapterUpdate.scanlator,
|
|
||||||
chapterUpdate.read?.toLong(),
|
|
||||||
chapterUpdate.bookmark?.toLong(),
|
|
||||||
chapterUpdate.lastPageRead,
|
|
||||||
chapterUpdate.chapterNumber?.toDouble(),
|
|
||||||
chapterUpdate.sourceOrder,
|
|
||||||
chapterUpdate.dateFetch,
|
|
||||||
chapterUpdate.dateUpload,
|
|
||||||
chapterId = chapterUpdate.id,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} catch (e: Exception) {
|
|
||||||
logcat(LogPriority.ERROR, e)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -42,6 +42,15 @@ class MangaRepositoryImpl(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override suspend fun moveMangaToCategories(mangaId: Long, categoryIds: List<Long>) {
|
||||||
|
handler.await(inTransaction = true) {
|
||||||
|
mangas_categoriesQueries.deleteMangaCategoryByMangaId(mangaId)
|
||||||
|
categoryIds.map { categoryId ->
|
||||||
|
mangas_categoriesQueries.insert(mangaId, categoryId)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
override suspend fun update(update: MangaUpdate): Boolean {
|
override suspend fun update(update: MangaUpdate): Boolean {
|
||||||
return try {
|
return try {
|
||||||
handler.await {
|
handler.await {
|
||||||
|
22
app/src/main/java/eu/kanade/data/track/TrackMapper.kt
Normal file
22
app/src/main/java/eu/kanade/data/track/TrackMapper.kt
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
package eu.kanade.data.track
|
||||||
|
|
||||||
|
import eu.kanade.domain.track.model.Track
|
||||||
|
|
||||||
|
val trackMapper: (Long, Long, Long, Long, Long?, String, Double, Long, Long, Float, String, Long, Long) -> Track =
|
||||||
|
{ id, mangaId, syncId, remoteId, libraryId, title, lastChapterRead, totalChapters, status, score, remoteUrl, startDate, finishDate ->
|
||||||
|
Track(
|
||||||
|
id = id,
|
||||||
|
mangaId = mangaId,
|
||||||
|
syncId = syncId,
|
||||||
|
remoteId = remoteId,
|
||||||
|
libraryId = libraryId,
|
||||||
|
title = title,
|
||||||
|
lastChapterRead = lastChapterRead,
|
||||||
|
totalChapters = totalChapters,
|
||||||
|
status = status,
|
||||||
|
score = score,
|
||||||
|
remoteUrl = remoteUrl,
|
||||||
|
startDate = startDate,
|
||||||
|
finishDate = finishDate,
|
||||||
|
)
|
||||||
|
}
|
@ -0,0 +1,37 @@
|
|||||||
|
package eu.kanade.data.track
|
||||||
|
|
||||||
|
import eu.kanade.data.DatabaseHandler
|
||||||
|
import eu.kanade.domain.track.model.Track
|
||||||
|
import eu.kanade.domain.track.repository.TrackRepository
|
||||||
|
|
||||||
|
class TrackRepositoryImpl(
|
||||||
|
private val handler: DatabaseHandler,
|
||||||
|
) : TrackRepository {
|
||||||
|
|
||||||
|
override suspend fun getTracksByMangaId(mangaId: Long): List<Track> {
|
||||||
|
return handler.awaitList {
|
||||||
|
manga_syncQueries.getTracksByMangaId(mangaId, trackMapper)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override suspend fun insertAll(tracks: List<Track>) {
|
||||||
|
handler.await(inTransaction = true) {
|
||||||
|
tracks.forEach { mangaTrack ->
|
||||||
|
manga_syncQueries.insert(
|
||||||
|
mangaId = mangaTrack.id,
|
||||||
|
syncId = mangaTrack.syncId,
|
||||||
|
remoteId = mangaTrack.remoteId,
|
||||||
|
libraryId = mangaTrack.libraryId,
|
||||||
|
title = mangaTrack.title,
|
||||||
|
lastChapterRead = mangaTrack.lastChapterRead,
|
||||||
|
totalChapters = mangaTrack.totalChapters,
|
||||||
|
status = mangaTrack.status,
|
||||||
|
score = mangaTrack.score,
|
||||||
|
remoteUrl = mangaTrack.remoteUrl,
|
||||||
|
startDate = mangaTrack.startDate,
|
||||||
|
finishDate = mangaTrack.finishDate,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -5,9 +5,11 @@ import eu.kanade.data.chapter.ChapterRepositoryImpl
|
|||||||
import eu.kanade.data.history.HistoryRepositoryImpl
|
import eu.kanade.data.history.HistoryRepositoryImpl
|
||||||
import eu.kanade.data.manga.MangaRepositoryImpl
|
import eu.kanade.data.manga.MangaRepositoryImpl
|
||||||
import eu.kanade.data.source.SourceRepositoryImpl
|
import eu.kanade.data.source.SourceRepositoryImpl
|
||||||
|
import eu.kanade.data.track.TrackRepositoryImpl
|
||||||
import eu.kanade.domain.category.interactor.DeleteCategory
|
import eu.kanade.domain.category.interactor.DeleteCategory
|
||||||
import eu.kanade.domain.category.interactor.GetCategories
|
import eu.kanade.domain.category.interactor.GetCategories
|
||||||
import eu.kanade.domain.category.interactor.InsertCategory
|
import eu.kanade.domain.category.interactor.InsertCategory
|
||||||
|
import eu.kanade.domain.category.interactor.MoveMangaToCategories
|
||||||
import eu.kanade.domain.category.interactor.UpdateCategory
|
import eu.kanade.domain.category.interactor.UpdateCategory
|
||||||
import eu.kanade.domain.category.repository.CategoryRepository
|
import eu.kanade.domain.category.repository.CategoryRepository
|
||||||
import eu.kanade.domain.chapter.interactor.GetChapterByMangaId
|
import eu.kanade.domain.chapter.interactor.GetChapterByMangaId
|
||||||
@ -29,6 +31,7 @@ import eu.kanade.domain.history.repository.HistoryRepository
|
|||||||
import eu.kanade.domain.manga.interactor.GetDuplicateLibraryManga
|
import eu.kanade.domain.manga.interactor.GetDuplicateLibraryManga
|
||||||
import eu.kanade.domain.manga.interactor.GetFavoritesBySourceId
|
import eu.kanade.domain.manga.interactor.GetFavoritesBySourceId
|
||||||
import eu.kanade.domain.manga.interactor.GetMangaById
|
import eu.kanade.domain.manga.interactor.GetMangaById
|
||||||
|
import eu.kanade.domain.manga.interactor.GetMangaWithChapters
|
||||||
import eu.kanade.domain.manga.interactor.ResetViewerFlags
|
import eu.kanade.domain.manga.interactor.ResetViewerFlags
|
||||||
import eu.kanade.domain.manga.interactor.UpdateManga
|
import eu.kanade.domain.manga.interactor.UpdateManga
|
||||||
import eu.kanade.domain.manga.repository.MangaRepository
|
import eu.kanade.domain.manga.repository.MangaRepository
|
||||||
@ -43,6 +46,9 @@ import eu.kanade.domain.source.interactor.ToggleSource
|
|||||||
import eu.kanade.domain.source.interactor.ToggleSourcePin
|
import eu.kanade.domain.source.interactor.ToggleSourcePin
|
||||||
import eu.kanade.domain.source.interactor.UpsertSourceData
|
import eu.kanade.domain.source.interactor.UpsertSourceData
|
||||||
import eu.kanade.domain.source.repository.SourceRepository
|
import eu.kanade.domain.source.repository.SourceRepository
|
||||||
|
import eu.kanade.domain.track.interactor.GetTracks
|
||||||
|
import eu.kanade.domain.track.interactor.InsertTrack
|
||||||
|
import eu.kanade.domain.track.repository.TrackRepository
|
||||||
import uy.kohesive.injekt.api.InjektModule
|
import uy.kohesive.injekt.api.InjektModule
|
||||||
import uy.kohesive.injekt.api.InjektRegistrar
|
import uy.kohesive.injekt.api.InjektRegistrar
|
||||||
import uy.kohesive.injekt.api.addFactory
|
import uy.kohesive.injekt.api.addFactory
|
||||||
@ -61,10 +67,16 @@ class DomainModule : InjektModule {
|
|||||||
addSingletonFactory<MangaRepository> { MangaRepositoryImpl(get()) }
|
addSingletonFactory<MangaRepository> { MangaRepositoryImpl(get()) }
|
||||||
addFactory { GetDuplicateLibraryManga(get()) }
|
addFactory { GetDuplicateLibraryManga(get()) }
|
||||||
addFactory { GetFavoritesBySourceId(get()) }
|
addFactory { GetFavoritesBySourceId(get()) }
|
||||||
|
addFactory { GetMangaWithChapters(get(), get()) }
|
||||||
addFactory { GetMangaById(get()) }
|
addFactory { GetMangaById(get()) }
|
||||||
addFactory { GetNextChapter(get()) }
|
addFactory { GetNextChapter(get()) }
|
||||||
addFactory { ResetViewerFlags(get()) }
|
addFactory { ResetViewerFlags(get()) }
|
||||||
addFactory { UpdateManga(get()) }
|
addFactory { UpdateManga(get()) }
|
||||||
|
addFactory { MoveMangaToCategories(get()) }
|
||||||
|
|
||||||
|
addSingletonFactory<TrackRepository> { TrackRepositoryImpl(get()) }
|
||||||
|
addFactory { GetTracks(get()) }
|
||||||
|
addFactory { InsertTrack(get()) }
|
||||||
|
|
||||||
addSingletonFactory<ChapterRepository> { ChapterRepositoryImpl(get()) }
|
addSingletonFactory<ChapterRepository> { ChapterRepositoryImpl(get()) }
|
||||||
addFactory { GetChapterByMangaId(get()) }
|
addFactory { GetChapterByMangaId(get()) }
|
||||||
|
@ -11,4 +11,8 @@ class GetCategories(
|
|||||||
fun subscribe(): Flow<List<Category>> {
|
fun subscribe(): Flow<List<Category>> {
|
||||||
return categoryRepository.getAll()
|
return categoryRepository.getAll()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
suspend fun await(mangaId: Long): List<Category> {
|
||||||
|
return categoryRepository.getCategoriesForManga(mangaId)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,18 @@
|
|||||||
|
package eu.kanade.domain.category.interactor
|
||||||
|
|
||||||
|
import eu.kanade.domain.manga.repository.MangaRepository
|
||||||
|
import eu.kanade.tachiyomi.util.system.logcat
|
||||||
|
import logcat.LogPriority
|
||||||
|
|
||||||
|
class MoveMangaToCategories(
|
||||||
|
private val mangaRepository: MangaRepository,
|
||||||
|
) {
|
||||||
|
|
||||||
|
suspend fun await(mangaId: Long, categoryIds: List<Long>) {
|
||||||
|
try {
|
||||||
|
mangaRepository.moveMangaToCategories(mangaId, categoryIds)
|
||||||
|
} catch (e: Exception) {
|
||||||
|
logcat(LogPriority.ERROR, e)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -16,6 +16,8 @@ interface CategoryRepository {
|
|||||||
|
|
||||||
suspend fun delete(categoryId: Long)
|
suspend fun delete(categoryId: Long)
|
||||||
|
|
||||||
|
suspend fun getCategoriesForManga(mangaId: Long): List<Category>
|
||||||
|
|
||||||
suspend fun checkDuplicateName(name: String): Boolean
|
suspend fun checkDuplicateName(name: String): Boolean
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3,8 +3,6 @@ package eu.kanade.domain.chapter.interactor
|
|||||||
import eu.kanade.domain.chapter.model.Chapter
|
import eu.kanade.domain.chapter.model.Chapter
|
||||||
import eu.kanade.domain.chapter.repository.ChapterRepository
|
import eu.kanade.domain.chapter.repository.ChapterRepository
|
||||||
import eu.kanade.tachiyomi.util.system.logcat
|
import eu.kanade.tachiyomi.util.system.logcat
|
||||||
import kotlinx.coroutines.flow.Flow
|
|
||||||
import kotlinx.coroutines.flow.flowOf
|
|
||||||
import logcat.LogPriority
|
import logcat.LogPriority
|
||||||
|
|
||||||
class GetChapterByMangaId(
|
class GetChapterByMangaId(
|
||||||
@ -19,13 +17,4 @@ class GetChapterByMangaId(
|
|||||||
emptyList()
|
emptyList()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
suspend fun subscribe(mangaId: Long): Flow<List<Chapter>> {
|
|
||||||
return try {
|
|
||||||
chapterRepository.getChapterByMangaIdAsFlow(mangaId)
|
|
||||||
} catch (e: Exception) {
|
|
||||||
logcat(LogPriority.ERROR, e)
|
|
||||||
flowOf(emptyList())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -26,6 +26,7 @@ class SyncChaptersWithSource(
|
|||||||
private val chapterRepository: ChapterRepository = Injekt.get(),
|
private val chapterRepository: ChapterRepository = Injekt.get(),
|
||||||
private val shouldUpdateDbChapter: ShouldUpdateDbChapter = Injekt.get(),
|
private val shouldUpdateDbChapter: ShouldUpdateDbChapter = Injekt.get(),
|
||||||
private val updateManga: UpdateManga = Injekt.get(),
|
private val updateManga: UpdateManga = Injekt.get(),
|
||||||
|
private val updateChapter: UpdateChapter = Injekt.get(),
|
||||||
private val getChapterByMangaId: GetChapterByMangaId = Injekt.get(),
|
private val getChapterByMangaId: GetChapterByMangaId = Injekt.get(),
|
||||||
) {
|
) {
|
||||||
|
|
||||||
@ -184,7 +185,7 @@ class SyncChaptersWithSource(
|
|||||||
|
|
||||||
if (toChange.isNotEmpty()) {
|
if (toChange.isNotEmpty()) {
|
||||||
val chapterUpdates = toChange.map { it.toChapterUpdate() }
|
val chapterUpdates = toChange.map { it.toChapterUpdate() }
|
||||||
chapterRepository.updateAll(chapterUpdates)
|
updateChapter.awaitAll(chapterUpdates)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set this manga as updated since chapters were changed
|
// Set this manga as updated since chapters were changed
|
||||||
|
@ -2,12 +2,26 @@ package eu.kanade.domain.chapter.interactor
|
|||||||
|
|
||||||
import eu.kanade.domain.chapter.model.ChapterUpdate
|
import eu.kanade.domain.chapter.model.ChapterUpdate
|
||||||
import eu.kanade.domain.chapter.repository.ChapterRepository
|
import eu.kanade.domain.chapter.repository.ChapterRepository
|
||||||
|
import eu.kanade.tachiyomi.util.system.logcat
|
||||||
|
import logcat.LogPriority
|
||||||
|
|
||||||
class UpdateChapter(
|
class UpdateChapter(
|
||||||
private val chapterRepository: ChapterRepository,
|
private val chapterRepository: ChapterRepository,
|
||||||
) {
|
) {
|
||||||
|
|
||||||
suspend fun await(chapterUpdate: ChapterUpdate) {
|
suspend fun await(chapterUpdate: ChapterUpdate) {
|
||||||
chapterRepository.update(chapterUpdate)
|
try {
|
||||||
|
chapterRepository.update(chapterUpdate)
|
||||||
|
} catch (e: Exception) {
|
||||||
|
logcat(LogPriority.ERROR, e)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
suspend fun awaitAll(chapterUpdates: List<ChapterUpdate>) {
|
||||||
|
try {
|
||||||
|
chapterRepository.updateAll(chapterUpdates)
|
||||||
|
} catch (e: Exception) {
|
||||||
|
logcat(LogPriority.ERROR, e)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,23 @@
|
|||||||
|
package eu.kanade.domain.manga.interactor
|
||||||
|
|
||||||
|
import eu.kanade.domain.chapter.model.Chapter
|
||||||
|
import eu.kanade.domain.chapter.repository.ChapterRepository
|
||||||
|
import eu.kanade.domain.manga.model.Manga
|
||||||
|
import eu.kanade.domain.manga.repository.MangaRepository
|
||||||
|
import kotlinx.coroutines.flow.Flow
|
||||||
|
import kotlinx.coroutines.flow.combine
|
||||||
|
|
||||||
|
class GetMangaWithChapters(
|
||||||
|
private val mangaRepository: MangaRepository,
|
||||||
|
private val chapterRepository: ChapterRepository,
|
||||||
|
) {
|
||||||
|
|
||||||
|
suspend fun subscribe(id: Long): Flow<Pair<Manga, List<Chapter>>> {
|
||||||
|
return combine(
|
||||||
|
mangaRepository.subscribeMangaById(id),
|
||||||
|
chapterRepository.getChapterByMangaIdAsFlow(id),
|
||||||
|
) { manga, chapters ->
|
||||||
|
Pair(manga, chapters)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -14,6 +14,10 @@ class UpdateManga(
|
|||||||
private val mangaRepository: MangaRepository,
|
private val mangaRepository: MangaRepository,
|
||||||
) {
|
) {
|
||||||
|
|
||||||
|
suspend fun await(mangaUpdate: MangaUpdate): Boolean {
|
||||||
|
return mangaRepository.update(mangaUpdate)
|
||||||
|
}
|
||||||
|
|
||||||
suspend fun awaitUpdateFromSource(
|
suspend fun awaitUpdateFromSource(
|
||||||
localManga: Manga,
|
localManga: Manga,
|
||||||
remoteManga: MangaInfo,
|
remoteManga: MangaInfo,
|
||||||
|
@ -16,5 +16,7 @@ interface MangaRepository {
|
|||||||
|
|
||||||
suspend fun resetViewerFlags(): Boolean
|
suspend fun resetViewerFlags(): Boolean
|
||||||
|
|
||||||
|
suspend fun moveMangaToCategories(mangaId: Long, categoryIds: List<Long>)
|
||||||
|
|
||||||
suspend fun update(update: MangaUpdate): Boolean
|
suspend fun update(update: MangaUpdate): Boolean
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,20 @@
|
|||||||
|
package eu.kanade.domain.track.interactor
|
||||||
|
|
||||||
|
import eu.kanade.domain.track.model.Track
|
||||||
|
import eu.kanade.domain.track.repository.TrackRepository
|
||||||
|
import eu.kanade.tachiyomi.util.system.logcat
|
||||||
|
import logcat.LogPriority
|
||||||
|
|
||||||
|
class GetTracks(
|
||||||
|
private val trackRepository: TrackRepository,
|
||||||
|
) {
|
||||||
|
|
||||||
|
suspend fun await(mangaId: Long): List<Track> {
|
||||||
|
return try {
|
||||||
|
trackRepository.getTracksByMangaId(mangaId)
|
||||||
|
} catch (e: Exception) {
|
||||||
|
logcat(LogPriority.ERROR, e)
|
||||||
|
emptyList()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,19 @@
|
|||||||
|
package eu.kanade.domain.track.interactor
|
||||||
|
|
||||||
|
import eu.kanade.domain.track.model.Track
|
||||||
|
import eu.kanade.domain.track.repository.TrackRepository
|
||||||
|
import eu.kanade.tachiyomi.util.system.logcat
|
||||||
|
import logcat.LogPriority
|
||||||
|
|
||||||
|
class InsertTrack(
|
||||||
|
private val trackRepository: TrackRepository,
|
||||||
|
) {
|
||||||
|
|
||||||
|
suspend fun awaitAll(tracks: List<Track>) {
|
||||||
|
try {
|
||||||
|
trackRepository.insertAll(tracks)
|
||||||
|
} catch (e: Exception) {
|
||||||
|
logcat(LogPriority.ERROR, e)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
27
app/src/main/java/eu/kanade/domain/track/model/Track.kt
Normal file
27
app/src/main/java/eu/kanade/domain/track/model/Track.kt
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
package eu.kanade.domain.track.model
|
||||||
|
|
||||||
|
data class Track(
|
||||||
|
val id: Long,
|
||||||
|
val mangaId: Long,
|
||||||
|
val syncId: Long,
|
||||||
|
val remoteId: Long,
|
||||||
|
val libraryId: Long?,
|
||||||
|
val title: String,
|
||||||
|
val lastChapterRead: Double,
|
||||||
|
val totalChapters: Long,
|
||||||
|
val status: Long,
|
||||||
|
val score: Float,
|
||||||
|
val remoteUrl: String,
|
||||||
|
val startDate: Long,
|
||||||
|
val finishDate: Long,
|
||||||
|
) {
|
||||||
|
fun copyPersonalFrom(other: Track): Track {
|
||||||
|
return this.copy(
|
||||||
|
lastChapterRead = other.lastChapterRead,
|
||||||
|
score = other.score,
|
||||||
|
status = other.status,
|
||||||
|
startDate = other.startDate,
|
||||||
|
finishDate = other.finishDate,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,10 @@
|
|||||||
|
package eu.kanade.domain.track.repository
|
||||||
|
|
||||||
|
import eu.kanade.domain.track.model.Track
|
||||||
|
|
||||||
|
interface TrackRepository {
|
||||||
|
|
||||||
|
suspend fun getTracksByMangaId(mangaId: Long): List<Track>
|
||||||
|
|
||||||
|
suspend fun insertAll(tracks: List<Track>)
|
||||||
|
}
|
@ -1,9 +1,10 @@
|
|||||||
package eu.kanade.tachiyomi.data.track
|
package eu.kanade.tachiyomi.data.track
|
||||||
|
|
||||||
|
import eu.kanade.domain.track.model.Track
|
||||||
import eu.kanade.tachiyomi.data.database.models.Manga
|
import eu.kanade.tachiyomi.data.database.models.Manga
|
||||||
import eu.kanade.tachiyomi.data.database.models.Track
|
|
||||||
import eu.kanade.tachiyomi.data.track.model.TrackSearch
|
import eu.kanade.tachiyomi.data.track.model.TrackSearch
|
||||||
import eu.kanade.tachiyomi.source.Source
|
import eu.kanade.tachiyomi.source.Source
|
||||||
|
import eu.kanade.domain.manga.model.Manga as DomainManga
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An Enhanced Track Service will never prompt the user to match a manga with the remote.
|
* An Enhanced Track Service will never prompt the user to match a manga with the remote.
|
||||||
@ -30,10 +31,10 @@ interface EnhancedTrackService {
|
|||||||
/**
|
/**
|
||||||
* Checks whether the provided source/track/manga triplet is from this TrackService
|
* Checks whether the provided source/track/manga triplet is from this TrackService
|
||||||
*/
|
*/
|
||||||
fun isTrackFrom(track: Track, manga: Manga, source: Source?): Boolean
|
fun isTrackFrom(track: Track, manga: DomainManga, source: Source?): Boolean
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Migrates the given track for the manga to the newSource, if possible
|
* Migrates the given track for the manga to the newSource, if possible
|
||||||
*/
|
*/
|
||||||
fun migrateTrack(track: Track, manga: Manga, newSource: Source): Track?
|
fun migrateTrack(track: Track, manga: DomainManga, newSource: Source): Track?
|
||||||
}
|
}
|
||||||
|
@ -13,6 +13,8 @@ import eu.kanade.tachiyomi.data.track.model.TrackSearch
|
|||||||
import eu.kanade.tachiyomi.source.Source
|
import eu.kanade.tachiyomi.source.Source
|
||||||
import okhttp3.Dns
|
import okhttp3.Dns
|
||||||
import okhttp3.OkHttpClient
|
import okhttp3.OkHttpClient
|
||||||
|
import eu.kanade.domain.manga.model.Manga as DomainManga
|
||||||
|
import eu.kanade.domain.track.model.Track as DomainTrack
|
||||||
|
|
||||||
class Komga(private val context: Context, id: Int) : TrackService(id), EnhancedTrackService, NoLoginTrackService {
|
class Komga(private val context: Context, id: Int) : TrackService(id), EnhancedTrackService, NoLoginTrackService {
|
||||||
|
|
||||||
@ -105,12 +107,12 @@ class Komga(private val context: Context, id: Int) : TrackService(id), EnhancedT
|
|||||||
null
|
null
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun isTrackFrom(track: Track, manga: Manga, source: Source?): Boolean =
|
override fun isTrackFrom(track: DomainTrack, manga: DomainManga, source: Source?): Boolean =
|
||||||
track.tracking_url == manga.url && source?.let { accept(it) } == true
|
track.remoteUrl == manga.url && source?.let { accept(it) } == true
|
||||||
|
|
||||||
override fun migrateTrack(track: Track, manga: Manga, newSource: Source): Track? =
|
override fun migrateTrack(track: DomainTrack, manga: DomainManga, newSource: Source): DomainTrack? =
|
||||||
if (accept(newSource)) {
|
if (accept(newSource)) {
|
||||||
track.also { track.tracking_url = manga.url }
|
track.copy(remoteUrl = manga.url)
|
||||||
} else {
|
} else {
|
||||||
null
|
null
|
||||||
}
|
}
|
||||||
|
@ -5,11 +5,13 @@ import android.net.Uri
|
|||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import com.jakewharton.rxrelay.PublishRelay
|
import com.jakewharton.rxrelay.PublishRelay
|
||||||
import eu.kanade.domain.category.interactor.GetCategories
|
import eu.kanade.domain.category.interactor.GetCategories
|
||||||
import eu.kanade.domain.chapter.interactor.GetChapterByMangaId
|
|
||||||
import eu.kanade.domain.chapter.interactor.GetMergedChapterByMangaId
|
import eu.kanade.domain.chapter.interactor.GetMergedChapterByMangaId
|
||||||
import eu.kanade.domain.chapter.model.toDbChapter
|
import eu.kanade.domain.chapter.model.toDbChapter
|
||||||
import eu.kanade.domain.manga.interactor.GetDuplicateLibraryManga
|
import eu.kanade.domain.manga.interactor.GetDuplicateLibraryManga
|
||||||
|
import eu.kanade.domain.manga.interactor.GetMangaWithChapters
|
||||||
|
import eu.kanade.domain.manga.interactor.UpdateManga
|
||||||
import eu.kanade.domain.manga.model.toDbManga
|
import eu.kanade.domain.manga.model.toDbManga
|
||||||
|
import eu.kanade.domain.manga.model.toMangaInfo
|
||||||
import eu.kanade.tachiyomi.R
|
import eu.kanade.tachiyomi.R
|
||||||
import eu.kanade.tachiyomi.data.cache.CoverCache
|
import eu.kanade.tachiyomi.data.cache.CoverCache
|
||||||
import eu.kanade.tachiyomi.data.database.DatabaseHelper
|
import eu.kanade.tachiyomi.data.database.DatabaseHelper
|
||||||
@ -31,7 +33,6 @@ import eu.kanade.tachiyomi.source.LocalSource
|
|||||||
import eu.kanade.tachiyomi.source.Source
|
import eu.kanade.tachiyomi.source.Source
|
||||||
import eu.kanade.tachiyomi.source.SourceManager
|
import eu.kanade.tachiyomi.source.SourceManager
|
||||||
import eu.kanade.tachiyomi.source.model.toSChapter
|
import eu.kanade.tachiyomi.source.model.toSChapter
|
||||||
import eu.kanade.tachiyomi.source.model.toSManga
|
|
||||||
import eu.kanade.tachiyomi.source.online.MetadataSource
|
import eu.kanade.tachiyomi.source.online.MetadataSource
|
||||||
import eu.kanade.tachiyomi.source.online.all.MergedSource
|
import eu.kanade.tachiyomi.source.online.all.MergedSource
|
||||||
import eu.kanade.tachiyomi.ui.base.presenter.BasePresenter
|
import eu.kanade.tachiyomi.ui.base.presenter.BasePresenter
|
||||||
@ -45,7 +46,6 @@ import eu.kanade.tachiyomi.util.isLocal
|
|||||||
import eu.kanade.tachiyomi.util.lang.launchIO
|
import eu.kanade.tachiyomi.util.lang.launchIO
|
||||||
import eu.kanade.tachiyomi.util.lang.launchUI
|
import eu.kanade.tachiyomi.util.lang.launchUI
|
||||||
import eu.kanade.tachiyomi.util.lang.withUIContext
|
import eu.kanade.tachiyomi.util.lang.withUIContext
|
||||||
import eu.kanade.tachiyomi.util.prepUpdateCover
|
|
||||||
import eu.kanade.tachiyomi.util.removeCovers
|
import eu.kanade.tachiyomi.util.removeCovers
|
||||||
import eu.kanade.tachiyomi.util.shouldDownloadNewChapters
|
import eu.kanade.tachiyomi.util.shouldDownloadNewChapters
|
||||||
import eu.kanade.tachiyomi.util.system.logcat
|
import eu.kanade.tachiyomi.util.system.logcat
|
||||||
@ -98,12 +98,17 @@ class MangaPresenter(
|
|||||||
private val db: DatabaseHelper = Injekt.get(),
|
private val db: DatabaseHelper = Injekt.get(),
|
||||||
private val trackManager: TrackManager = Injekt.get(),
|
private val trackManager: TrackManager = Injekt.get(),
|
||||||
private val downloadManager: DownloadManager = Injekt.get(),
|
private val downloadManager: DownloadManager = Injekt.get(),
|
||||||
private val coverCache: CoverCache = Injekt.get(),
|
// SY -->
|
||||||
private val sourceManager: SourceManager = Injekt.get(),
|
private val sourceManager: SourceManager = Injekt.get(),
|
||||||
private val getChapterByMangaId: GetChapterByMangaId = Injekt.get(),
|
// SY <--
|
||||||
|
private val coverCache: CoverCache = Injekt.get(),
|
||||||
|
private val getMangaWithChapters: GetMangaWithChapters = Injekt.get(),
|
||||||
|
// SY -->
|
||||||
|
private val getMergedChapterByMangaId: GetMergedChapterByMangaId = Injekt.get(),
|
||||||
|
// SY <--
|
||||||
private val getDuplicateLibraryManga: GetDuplicateLibraryManga = Injekt.get(),
|
private val getDuplicateLibraryManga: GetDuplicateLibraryManga = Injekt.get(),
|
||||||
private val getCategories: GetCategories = Injekt.get(),
|
private val getCategories: GetCategories = Injekt.get(),
|
||||||
private val getMergedChapterByMangaId: GetMergedChapterByMangaId = Injekt.get(),
|
private val updateManga: UpdateManga = Injekt.get(),
|
||||||
) : BasePresenter<MangaController>() {
|
) : BasePresenter<MangaController>() {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -183,7 +188,6 @@ class MangaPresenter(
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Manga info - start
|
// Manga info - start
|
||||||
|
|
||||||
getMangaObservable()
|
getMangaObservable()
|
||||||
.observeOn(AndroidSchedulers.mainThread())
|
.observeOn(AndroidSchedulers.mainThread())
|
||||||
// SY -->
|
// SY -->
|
||||||
@ -232,27 +236,27 @@ class MangaPresenter(
|
|||||||
manga.id?.let { mangaId ->
|
manga.id?.let { mangaId ->
|
||||||
if (source is MergedSource) {
|
if (source is MergedSource) {
|
||||||
getMergedChapterByMangaId.subscribe(mangaId)
|
getMergedChapterByMangaId.subscribe(mangaId)
|
||||||
.map { source.transformMergedChapters(mangaId, it, true, dedupe) }
|
.map { manga to source.transformMergedChapters(mangaId, it, true, dedupe) }
|
||||||
} else {
|
} else {
|
||||||
getChapterByMangaId.subscribe(mangaId)
|
getMangaWithChapters.subscribe(mangaId)
|
||||||
}
|
}
|
||||||
.collectLatest { domainChapters ->
|
.collectLatest { (_, chapters) ->
|
||||||
val chapterItems = domainChapters.map { it.toDbChapter().toModel() }
|
val chapterItems = chapters.map { it.toDbChapter().toModel() }
|
||||||
setDownloadedChapters(chapterItems)
|
setDownloadedChapters(chapterItems)
|
||||||
this@MangaPresenter.allChapters = chapterItems
|
this@MangaPresenter.allChapters = chapterItems
|
||||||
observeDownloads()
|
observeDownloads()
|
||||||
|
|
||||||
// SY -->
|
// SY -->
|
||||||
if (domainChapters.isNotEmpty() && (source.isEhBasedSource()) && DebugToggles.ENABLE_EXH_ROOT_REDIRECT.enabled) {
|
if (chapters.isNotEmpty() && (source.isEhBasedSource()) && DebugToggles.ENABLE_EXH_ROOT_REDIRECT.enabled) {
|
||||||
// Check for gallery in library and accept manga with lowest id
|
// Check for gallery in library and accept manga with lowest id
|
||||||
// Find chapters sharing same root
|
// Find chapters sharing same root
|
||||||
updateHelper.findAcceptedRootAndDiscardOthers(manga.source, domainChapters.map { it.toDbChapter() })
|
updateHelper.findAcceptedRootAndDiscardOthers(manga.source, chapters.map { it.toDbChapter() })
|
||||||
.onEach { (acceptedChain, _) ->
|
.onEach { (acceptedChain, _) ->
|
||||||
// Redirect if we are not the accepted root
|
// Redirect if we are not the accepted root
|
||||||
if (manga.id != acceptedChain.manga.id && acceptedChain.manga.favorite) {
|
if (manga.id != acceptedChain.manga.id && acceptedChain.manga.favorite) {
|
||||||
// Update if any of our chapters are not in accepted manga's chapters
|
// Update if any of our chapters are not in accepted manga's chapters
|
||||||
xLogD("Found accepted manga %s", manga.url)
|
xLogD("Found accepted manga %s", manga.url)
|
||||||
val ourChapterUrls = domainChapters.map { it.url }.toSet()
|
val ourChapterUrls = chapters.map { it.url }.toSet()
|
||||||
val acceptedChapterUrls = acceptedChain.chapters.map { it.url }.toSet()
|
val acceptedChapterUrls = acceptedChain.chapters.map { it.url }.toSet()
|
||||||
val update = (ourChapterUrls - acceptedChapterUrls).isNotEmpty()
|
val update = (ourChapterUrls - acceptedChapterUrls).isNotEmpty()
|
||||||
redirectFlow.emit(
|
redirectFlow.emit(
|
||||||
@ -280,7 +284,6 @@ class MangaPresenter(
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Manga info - start
|
// Manga info - start
|
||||||
|
|
||||||
private fun getMangaObservable(): Observable<Manga> {
|
private fun getMangaObservable(): Observable<Manga> {
|
||||||
return db.getManga(manga.url, manga.source).asRxObservable()
|
return db.getManga(manga.url, manga.source).asRxObservable()
|
||||||
}
|
}
|
||||||
@ -318,16 +321,11 @@ class MangaPresenter(
|
|||||||
if (fetchMangaJob?.isActive == true) return
|
if (fetchMangaJob?.isActive == true) return
|
||||||
fetchMangaJob = presenterScope.launchIO {
|
fetchMangaJob = presenterScope.launchIO {
|
||||||
try {
|
try {
|
||||||
val networkManga = source.getMangaDetails(manga.toMangaInfo())
|
manga.toDomainManga()?.let { domainManga ->
|
||||||
val sManga = networkManga.toSManga()
|
val networkManga = source.getMangaDetails(domainManga.toMangaInfo())
|
||||||
manga.prepUpdateCover(coverCache, sManga, manualFetch)
|
|
||||||
manga.copyFrom(sManga)
|
updateManga.awaitUpdateFromSource(domainManga, networkManga, manualFetch, coverCache)
|
||||||
if (!manga.favorite) {
|
|
||||||
// if the manga isn't a favorite, set its title from source and update in db
|
|
||||||
manga.title = sManga.title
|
|
||||||
}
|
}
|
||||||
manga.initialized = true
|
|
||||||
db.insertManga(manga).executeAsBlocking()
|
|
||||||
|
|
||||||
withUIContext { view?.onFetchMangaInfoDone() }
|
withUIContext { view?.onFetchMangaInfoDone() }
|
||||||
} catch (e: Throwable) {
|
} catch (e: Throwable) {
|
||||||
|
@ -245,9 +245,8 @@ class MangaFullCoverDialog : FullComposeController<MangaFullCoverDialog.MangaFul
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
private const val MANGA_EXTRA = "mangaId"
|
private const val MANGA_EXTRA = "mangaId"
|
||||||
|
|
||||||
@ -257,4 +256,3 @@ class MangaFullCoverDialog : FullComposeController<MangaFullCoverDialog.MangaFul
|
|||||||
private const val REQUEST_IMAGE_OPEN = 101
|
private const val REQUEST_IMAGE_OPEN = 101
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -56,8 +56,10 @@ class MaterialSpinnerView @JvmOverloads constructor(context: Context, attrs: Att
|
|||||||
val title = getString(R.styleable.MaterialSpinnerView_title).orEmpty()
|
val title = getString(R.styleable.MaterialSpinnerView_title).orEmpty()
|
||||||
binding.title.text = title
|
binding.title.text = title
|
||||||
|
|
||||||
val viewEntries = (getTextArray(R.styleable.MaterialSpinnerView_android_entries)
|
val viewEntries = (
|
||||||
?: emptyArray()).map { it.toString() }
|
getTextArray(R.styleable.MaterialSpinnerView_android_entries)
|
||||||
|
?: emptyArray()
|
||||||
|
).map { it.toString() }
|
||||||
entries = viewEntries
|
entries = viewEntries
|
||||||
binding.details.text = viewEntries.firstOrNull().orEmpty()
|
binding.details.text = viewEntries.firstOrNull().orEmpty()
|
||||||
}
|
}
|
||||||
|
@ -23,7 +23,8 @@ SELECT
|
|||||||
C._id AS id,
|
C._id AS id,
|
||||||
C.name,
|
C.name,
|
||||||
C.sort AS `order`,
|
C.sort AS `order`,
|
||||||
C.flags
|
C.flags,
|
||||||
|
C.manga_order AS `mangaOrder`
|
||||||
FROM categories C
|
FROM categories C
|
||||||
JOIN mangas_categories MC
|
JOIN mangas_categories MC
|
||||||
ON C._id = MC.category_id
|
ON C._id = MC.category_id
|
||||||
|
Loading…
x
Reference in New Issue
Block a user