mirror of
				https://github.com/mihonapp/mihon.git
				synced 2025-11-04 08:08:55 +01:00 
			
		
		
		
	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>
This commit is contained in:
		@@ -48,6 +48,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 {
 | 
			
		||||
        return handler
 | 
			
		||||
            .awaitList { categoriesQueries.getCategories() }
 | 
			
		||||
 
 | 
			
		||||
@@ -41,8 +41,27 @@ class ChapterRepositoryImpl(
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    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(
 | 
			
		||||
                    chapterUpdate.mangaId,
 | 
			
		||||
                    chapterUpdate.url,
 | 
			
		||||
@@ -58,33 +77,6 @@ class ChapterRepositoryImpl(
 | 
			
		||||
                    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 {
 | 
			
		||||
        return try {
 | 
			
		||||
            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.manga.MangaRepositoryImpl
 | 
			
		||||
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.GetCategories
 | 
			
		||||
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.repository.CategoryRepository
 | 
			
		||||
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.GetFavoritesBySourceId
 | 
			
		||||
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.UpdateManga
 | 
			
		||||
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.UpsertSourceData
 | 
			
		||||
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.InjektRegistrar
 | 
			
		||||
import uy.kohesive.injekt.api.addFactory
 | 
			
		||||
@@ -61,10 +67,16 @@ class DomainModule : InjektModule {
 | 
			
		||||
        addSingletonFactory<MangaRepository> { MangaRepositoryImpl(get()) }
 | 
			
		||||
        addFactory { GetDuplicateLibraryManga(get()) }
 | 
			
		||||
        addFactory { GetFavoritesBySourceId(get()) }
 | 
			
		||||
        addFactory { GetMangaWithChapters(get(), get()) }
 | 
			
		||||
        addFactory { GetMangaById(get()) }
 | 
			
		||||
        addFactory { GetNextChapter(get()) }
 | 
			
		||||
        addFactory { ResetViewerFlags(get()) }
 | 
			
		||||
        addFactory { UpdateManga(get()) }
 | 
			
		||||
        addFactory { MoveMangaToCategories(get()) }
 | 
			
		||||
 | 
			
		||||
        addSingletonFactory<TrackRepository> { TrackRepositoryImpl(get()) }
 | 
			
		||||
        addFactory { GetTracks(get()) }
 | 
			
		||||
        addFactory { InsertTrack(get()) }
 | 
			
		||||
 | 
			
		||||
        addSingletonFactory<ChapterRepository> { ChapterRepositoryImpl(get()) }
 | 
			
		||||
        addFactory { GetChapterByMangaId(get()) }
 | 
			
		||||
 
 | 
			
		||||
@@ -11,4 +11,8 @@ class GetCategories(
 | 
			
		||||
    fun subscribe(): Flow<List<Category>> {
 | 
			
		||||
        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 getCategoriesForManga(mangaId: Long): List<Category>
 | 
			
		||||
 | 
			
		||||
    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.repository.ChapterRepository
 | 
			
		||||
import eu.kanade.tachiyomi.util.system.logcat
 | 
			
		||||
import kotlinx.coroutines.flow.Flow
 | 
			
		||||
import kotlinx.coroutines.flow.flowOf
 | 
			
		||||
import logcat.LogPriority
 | 
			
		||||
 | 
			
		||||
class GetChapterByMangaId(
 | 
			
		||||
@@ -19,13 +17,4 @@ class GetChapterByMangaId(
 | 
			
		||||
            emptyList()
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    suspend fun subscribe(mangaId: Long): Flow<List<Chapter>> {
 | 
			
		||||
        return try {
 | 
			
		||||
            chapterRepository.getChapterByMangaIdAsFlow(mangaId)
 | 
			
		||||
        } catch (e: Exception) {
 | 
			
		||||
            logcat(LogPriority.ERROR, e)
 | 
			
		||||
            flowOf(emptyList())
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -25,6 +25,7 @@ class SyncChaptersWithSource(
 | 
			
		||||
    private val chapterRepository: ChapterRepository = Injekt.get(),
 | 
			
		||||
    private val shouldUpdateDbChapter: ShouldUpdateDbChapter = Injekt.get(),
 | 
			
		||||
    private val updateManga: UpdateManga = Injekt.get(),
 | 
			
		||||
    private val updateChapter: UpdateChapter = Injekt.get(),
 | 
			
		||||
    private val getChapterByMangaId: GetChapterByMangaId = Injekt.get(),
 | 
			
		||||
) {
 | 
			
		||||
 | 
			
		||||
@@ -167,7 +168,7 @@ class SyncChaptersWithSource(
 | 
			
		||||
 | 
			
		||||
        if (toChange.isNotEmpty()) {
 | 
			
		||||
            val chapterUpdates = toChange.map { it.toChapterUpdate() }
 | 
			
		||||
            chapterRepository.updateAll(chapterUpdates)
 | 
			
		||||
            updateChapter.awaitAll(chapterUpdates)
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // 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.repository.ChapterRepository
 | 
			
		||||
import eu.kanade.tachiyomi.util.system.logcat
 | 
			
		||||
import logcat.LogPriority
 | 
			
		||||
 | 
			
		||||
class UpdateChapter(
 | 
			
		||||
    private val chapterRepository: ChapterRepository,
 | 
			
		||||
) {
 | 
			
		||||
 | 
			
		||||
    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,
 | 
			
		||||
) {
 | 
			
		||||
 | 
			
		||||
    suspend fun await(mangaUpdate: MangaUpdate): Boolean {
 | 
			
		||||
        return mangaRepository.update(mangaUpdate)
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    suspend fun awaitUpdateFromSource(
 | 
			
		||||
        localManga: Manga,
 | 
			
		||||
        remoteManga: MangaInfo,
 | 
			
		||||
 
 | 
			
		||||
@@ -16,5 +16,7 @@ interface MangaRepository {
 | 
			
		||||
 | 
			
		||||
    suspend fun resetViewerFlags(): Boolean
 | 
			
		||||
 | 
			
		||||
    suspend fun moveMangaToCategories(mangaId: Long, categoryIds: List<Long>)
 | 
			
		||||
 | 
			
		||||
    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
 | 
			
		||||
 | 
			
		||||
import eu.kanade.domain.track.model.Track
 | 
			
		||||
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.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.
 | 
			
		||||
@@ -30,10 +31,10 @@ interface EnhancedTrackService {
 | 
			
		||||
    /**
 | 
			
		||||
     * 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
 | 
			
		||||
     */
 | 
			
		||||
    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 okhttp3.Dns
 | 
			
		||||
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 {
 | 
			
		||||
 | 
			
		||||
@@ -105,12 +107,12 @@ class Komga(private val context: Context, id: Int) : TrackService(id), EnhancedT
 | 
			
		||||
            null
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
    override fun isTrackFrom(track: Track, manga: Manga, source: Source?): Boolean =
 | 
			
		||||
        track.tracking_url == manga.url && source?.let { accept(it) } == true
 | 
			
		||||
    override fun isTrackFrom(track: DomainTrack, manga: DomainManga, source: Source?): Boolean =
 | 
			
		||||
        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)) {
 | 
			
		||||
            track.also { track.tracking_url = manga.url }
 | 
			
		||||
            track.copy(remoteUrl = manga.url)
 | 
			
		||||
        } else {
 | 
			
		||||
            null
 | 
			
		||||
        }
 | 
			
		||||
 
 | 
			
		||||
@@ -2,9 +2,21 @@ package eu.kanade.tachiyomi.ui.browse.migration.search
 | 
			
		||||
 | 
			
		||||
import android.os.Bundle
 | 
			
		||||
import com.jakewharton.rxrelay.BehaviorRelay
 | 
			
		||||
import eu.kanade.domain.category.interactor.GetCategories
 | 
			
		||||
import eu.kanade.domain.category.interactor.MoveMangaToCategories
 | 
			
		||||
import eu.kanade.domain.chapter.interactor.GetChapterByMangaId
 | 
			
		||||
import eu.kanade.domain.chapter.interactor.SyncChaptersWithSource
 | 
			
		||||
import eu.kanade.domain.chapter.interactor.UpdateChapter
 | 
			
		||||
import eu.kanade.domain.chapter.model.toChapterUpdate
 | 
			
		||||
import eu.kanade.domain.manga.interactor.UpdateManga
 | 
			
		||||
import eu.kanade.domain.manga.model.MangaUpdate
 | 
			
		||||
import eu.kanade.domain.manga.model.hasCustomCover
 | 
			
		||||
import eu.kanade.domain.manga.model.toDbManga
 | 
			
		||||
import eu.kanade.domain.track.interactor.GetTracks
 | 
			
		||||
import eu.kanade.domain.track.interactor.InsertTrack
 | 
			
		||||
import eu.kanade.tachiyomi.data.cache.CoverCache
 | 
			
		||||
import eu.kanade.tachiyomi.data.database.models.Manga
 | 
			
		||||
import eu.kanade.tachiyomi.data.database.models.MangaCategory
 | 
			
		||||
import eu.kanade.tachiyomi.data.database.models.toDomainManga
 | 
			
		||||
import eu.kanade.tachiyomi.data.database.models.toMangaInfo
 | 
			
		||||
import eu.kanade.tachiyomi.data.track.EnhancedTrackService
 | 
			
		||||
import eu.kanade.tachiyomi.data.track.TrackManager
 | 
			
		||||
@@ -17,8 +29,6 @@ import eu.kanade.tachiyomi.ui.browse.migration.MigrationFlags
 | 
			
		||||
import eu.kanade.tachiyomi.ui.browse.source.globalsearch.GlobalSearchCardItem
 | 
			
		||||
import eu.kanade.tachiyomi.ui.browse.source.globalsearch.GlobalSearchItem
 | 
			
		||||
import eu.kanade.tachiyomi.ui.browse.source.globalsearch.GlobalSearchPresenter
 | 
			
		||||
import eu.kanade.tachiyomi.util.chapter.syncChaptersWithSource
 | 
			
		||||
import eu.kanade.tachiyomi.util.hasCustomCover
 | 
			
		||||
import eu.kanade.tachiyomi.util.lang.launchIO
 | 
			
		||||
import eu.kanade.tachiyomi.util.lang.launchUI
 | 
			
		||||
import eu.kanade.tachiyomi.util.lang.withUIContext
 | 
			
		||||
@@ -31,6 +41,14 @@ import java.util.Date
 | 
			
		||||
class SearchPresenter(
 | 
			
		||||
    initialQuery: String? = "",
 | 
			
		||||
    private val manga: Manga,
 | 
			
		||||
    private val syncChaptersWithSource: SyncChaptersWithSource = Injekt.get(),
 | 
			
		||||
    private val getChapterByMangaId: GetChapterByMangaId = Injekt.get(),
 | 
			
		||||
    private val updateChapter: UpdateChapter = Injekt.get(),
 | 
			
		||||
    private val updateManga: UpdateManga = Injekt.get(),
 | 
			
		||||
    private val getCategories: GetCategories = Injekt.get(),
 | 
			
		||||
    private val getTracks: GetTracks = Injekt.get(),
 | 
			
		||||
    private val insertTrack: InsertTrack = Injekt.get(),
 | 
			
		||||
    private val moveMangaToCategories: MoveMangaToCategories = Injekt.get(),
 | 
			
		||||
) : GlobalSearchPresenter(initialQuery) {
 | 
			
		||||
 | 
			
		||||
    private val replacingMangaRelay = BehaviorRelay.create<Pair<Boolean, Manga?>>()
 | 
			
		||||
@@ -94,101 +112,93 @@ class SearchPresenter(
 | 
			
		||||
        replace: Boolean,
 | 
			
		||||
    ) {
 | 
			
		||||
        val flags = preferences.migrateFlags().get()
 | 
			
		||||
        val migrateChapters =
 | 
			
		||||
            MigrationFlags.hasChapters(
 | 
			
		||||
                flags,
 | 
			
		||||
            )
 | 
			
		||||
        val migrateCategories =
 | 
			
		||||
            MigrationFlags.hasCategories(
 | 
			
		||||
                flags,
 | 
			
		||||
            )
 | 
			
		||||
        val migrateTracks =
 | 
			
		||||
            MigrationFlags.hasTracks(
 | 
			
		||||
                flags,
 | 
			
		||||
            )
 | 
			
		||||
        val migrateCustomCover =
 | 
			
		||||
            MigrationFlags.hasCustomCover(
 | 
			
		||||
                flags,
 | 
			
		||||
            )
 | 
			
		||||
 | 
			
		||||
        val migrateChapters = MigrationFlags.hasChapters(flags)
 | 
			
		||||
        val migrateCategories = MigrationFlags.hasCategories(flags)
 | 
			
		||||
        val migrateTracks = MigrationFlags.hasTracks(flags)
 | 
			
		||||
        val migrateCustomCover = MigrationFlags.hasCustomCover(flags)
 | 
			
		||||
 | 
			
		||||
        val prevDomainManga = prevManga.toDomainManga() ?: return
 | 
			
		||||
        val domainManga = manga.toDomainManga() ?: return
 | 
			
		||||
 | 
			
		||||
        try {
 | 
			
		||||
            syncChaptersWithSource(sourceChapters, manga, source)
 | 
			
		||||
            syncChaptersWithSource.await(sourceChapters, domainManga, source)
 | 
			
		||||
        } catch (e: Exception) {
 | 
			
		||||
            // Worst case, chapters won't be synced
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        db.inTransaction {
 | 
			
		||||
            // Update chapters read
 | 
			
		||||
            if (migrateChapters) {
 | 
			
		||||
                val prevMangaChapters = db.getChapters(prevManga).executeAsBlocking()
 | 
			
		||||
                val maxChapterRead = prevMangaChapters
 | 
			
		||||
                    .filter { it.read }
 | 
			
		||||
                    .maxOfOrNull { it.chapter_number } ?: 0f
 | 
			
		||||
                val dbChapters = db.getChapters(manga).executeAsBlocking()
 | 
			
		||||
                for (chapter in dbChapters) {
 | 
			
		||||
                    if (chapter.isRecognizedNumber) {
 | 
			
		||||
                        val prevChapter = prevMangaChapters
 | 
			
		||||
                            .find { it.isRecognizedNumber && it.chapter_number == chapter.chapter_number }
 | 
			
		||||
                        if (prevChapter != null) {
 | 
			
		||||
                            chapter.date_fetch = prevChapter.date_fetch
 | 
			
		||||
                            chapter.bookmark = prevChapter.bookmark
 | 
			
		||||
                        }
 | 
			
		||||
                        if (chapter.chapter_number <= maxChapterRead) {
 | 
			
		||||
                            chapter.read = true
 | 
			
		||||
                        }
 | 
			
		||||
        // Update chapters read, bookmark and dateFetch
 | 
			
		||||
        if (migrateChapters) {
 | 
			
		||||
            val prevMangaChapters = getChapterByMangaId.await(prevDomainManga.id)
 | 
			
		||||
            val mangaChapters = getChapterByMangaId.await(domainManga.id)
 | 
			
		||||
 | 
			
		||||
            val maxChapterRead = prevMangaChapters
 | 
			
		||||
                .filter { it.read }
 | 
			
		||||
                .maxOfOrNull { it.chapterNumber }
 | 
			
		||||
 | 
			
		||||
            val updatedMangaChapters = mangaChapters.map { mangaChapter ->
 | 
			
		||||
                var updatedChapter = mangaChapter
 | 
			
		||||
                if (updatedChapter.isRecognizedNumber) {
 | 
			
		||||
                    val prevChapter = prevMangaChapters
 | 
			
		||||
                        .find { it.isRecognizedNumber && it.chapterNumber == updatedChapter.chapterNumber }
 | 
			
		||||
 | 
			
		||||
                    if (prevChapter != null) {
 | 
			
		||||
                        updatedChapter = updatedChapter.copy(
 | 
			
		||||
                            dateFetch = prevChapter.dateFetch,
 | 
			
		||||
                            bookmark = prevChapter.bookmark,
 | 
			
		||||
                        )
 | 
			
		||||
                    }
 | 
			
		||||
 | 
			
		||||
                    if (maxChapterRead != null && updatedChapter.chapterNumber <= maxChapterRead) {
 | 
			
		||||
                        updatedChapter = updatedChapter.copy(read = true)
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
                db.insertChapters(dbChapters).executeAsBlocking()
 | 
			
		||||
 | 
			
		||||
                updatedChapter
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            // Update categories
 | 
			
		||||
            if (migrateCategories) {
 | 
			
		||||
                val categories = db.getCategoriesForManga(prevManga).executeAsBlocking()
 | 
			
		||||
                val mangaCategories = categories.map { MangaCategory.create(manga, it) }
 | 
			
		||||
                db.setMangaCategories(mangaCategories, listOf(manga))
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            // Update track
 | 
			
		||||
            if (migrateTracks) {
 | 
			
		||||
                val tracksToUpdate = db.getTracks(prevManga.id).executeAsBlocking().mapNotNull { track ->
 | 
			
		||||
                    track.id = null
 | 
			
		||||
                    track.manga_id = manga.id!!
 | 
			
		||||
 | 
			
		||||
                    val service = enhancedServices
 | 
			
		||||
                        .firstOrNull { it.isTrackFrom(track, prevManga, prevSource) }
 | 
			
		||||
                    if (service != null) service.migrateTrack(track, manga, source)
 | 
			
		||||
                    else track
 | 
			
		||||
                }
 | 
			
		||||
                db.insertTracks(tracksToUpdate).executeAsBlocking()
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            // Update favorite status
 | 
			
		||||
            if (replace) {
 | 
			
		||||
                prevManga.favorite = false
 | 
			
		||||
                db.updateMangaFavorite(prevManga).executeAsBlocking()
 | 
			
		||||
            }
 | 
			
		||||
            manga.favorite = true
 | 
			
		||||
 | 
			
		||||
            // Update reading preferences
 | 
			
		||||
            manga.chapter_flags = prevManga.chapter_flags
 | 
			
		||||
            manga.viewer_flags = prevManga.viewer_flags
 | 
			
		||||
 | 
			
		||||
            // Update date added
 | 
			
		||||
            if (replace) {
 | 
			
		||||
                manga.date_added = prevManga.date_added
 | 
			
		||||
                prevManga.date_added = 0
 | 
			
		||||
            } else {
 | 
			
		||||
                manga.date_added = Date().time
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            // Update custom cover
 | 
			
		||||
            if (migrateCustomCover) {
 | 
			
		||||
                coverCache.setCustomCoverToCache(manga, coverCache.getCustomCoverFile(prevManga.id).inputStream())
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            // SearchPresenter#networkToLocalManga may have updated the manga title,
 | 
			
		||||
            // so ensure db gets updated title too
 | 
			
		||||
            db.insertManga(manga).executeAsBlocking()
 | 
			
		||||
            val chapterUpdates = updatedMangaChapters.map { it.toChapterUpdate() }
 | 
			
		||||
            updateChapter.awaitAll(chapterUpdates)
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // Update categories
 | 
			
		||||
        if (migrateCategories) {
 | 
			
		||||
            val categoryIds = getCategories.await(prevDomainManga.id).map { it.id }
 | 
			
		||||
            moveMangaToCategories.await(domainManga.id, categoryIds)
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // Update track
 | 
			
		||||
        if (migrateTracks) {
 | 
			
		||||
            val tracks = getTracks.await(prevDomainManga.id).mapNotNull { track ->
 | 
			
		||||
                val updatedTrack = track.copy(mangaId = domainManga.id)
 | 
			
		||||
 | 
			
		||||
                val service = enhancedServices
 | 
			
		||||
                    .firstOrNull { it.isTrackFrom(updatedTrack, prevDomainManga, prevSource) }
 | 
			
		||||
 | 
			
		||||
                if (service != null) service.migrateTrack(updatedTrack, domainManga, source)
 | 
			
		||||
                else track
 | 
			
		||||
            }
 | 
			
		||||
            insertTrack.awaitAll(tracks)
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (replace) {
 | 
			
		||||
            updateManga.await(MangaUpdate(prevDomainManga.id, favorite = false, dateAdded = 0))
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // Update custom cover (recheck if custom cover exists)
 | 
			
		||||
        if (migrateCustomCover && prevDomainManga.hasCustomCover()) {
 | 
			
		||||
            @Suppress("BlockingMethodInNonBlockingContext")
 | 
			
		||||
            coverCache.setCustomCoverToCache(domainManga.toDbManga(), coverCache.getCustomCoverFile(prevDomainManga.id).inputStream())
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        updateManga.await(
 | 
			
		||||
            MangaUpdate(
 | 
			
		||||
                id = domainManga.id,
 | 
			
		||||
                favorite = true,
 | 
			
		||||
                chapterFlags = prevDomainManga.chapterFlags,
 | 
			
		||||
                viewerFlags = prevDomainManga.viewerFlags,
 | 
			
		||||
                dateAdded = if (replace) prevDomainManga.dateAdded else Date().time,
 | 
			
		||||
            ),
 | 
			
		||||
        )
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -3,10 +3,12 @@ package eu.kanade.tachiyomi.ui.manga
 | 
			
		||||
import android.os.Bundle
 | 
			
		||||
import com.jakewharton.rxrelay.PublishRelay
 | 
			
		||||
import eu.kanade.domain.category.interactor.GetCategories
 | 
			
		||||
import eu.kanade.domain.chapter.interactor.GetChapterByMangaId
 | 
			
		||||
import eu.kanade.domain.chapter.model.toDbChapter
 | 
			
		||||
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.toMangaInfo
 | 
			
		||||
import eu.kanade.tachiyomi.data.cache.CoverCache
 | 
			
		||||
import eu.kanade.tachiyomi.data.database.DatabaseHelper
 | 
			
		||||
import eu.kanade.tachiyomi.data.database.models.Category
 | 
			
		||||
@@ -14,6 +16,7 @@ import eu.kanade.tachiyomi.data.database.models.Chapter
 | 
			
		||||
import eu.kanade.tachiyomi.data.database.models.Manga
 | 
			
		||||
import eu.kanade.tachiyomi.data.database.models.MangaCategory
 | 
			
		||||
import eu.kanade.tachiyomi.data.database.models.Track
 | 
			
		||||
import eu.kanade.tachiyomi.data.database.models.toDomainManga
 | 
			
		||||
import eu.kanade.tachiyomi.data.database.models.toMangaInfo
 | 
			
		||||
import eu.kanade.tachiyomi.data.download.DownloadManager
 | 
			
		||||
import eu.kanade.tachiyomi.data.download.model.Download
 | 
			
		||||
@@ -23,7 +26,6 @@ import eu.kanade.tachiyomi.data.track.TrackManager
 | 
			
		||||
import eu.kanade.tachiyomi.data.track.TrackService
 | 
			
		||||
import eu.kanade.tachiyomi.source.Source
 | 
			
		||||
import eu.kanade.tachiyomi.source.model.toSChapter
 | 
			
		||||
import eu.kanade.tachiyomi.source.model.toSManga
 | 
			
		||||
import eu.kanade.tachiyomi.ui.base.presenter.BasePresenter
 | 
			
		||||
import eu.kanade.tachiyomi.ui.manga.chapter.ChapterItem
 | 
			
		||||
import eu.kanade.tachiyomi.ui.manga.track.TrackItem
 | 
			
		||||
@@ -34,7 +36,6 @@ import eu.kanade.tachiyomi.util.chapter.syncChaptersWithTrackServiceTwoWay
 | 
			
		||||
import eu.kanade.tachiyomi.util.isLocal
 | 
			
		||||
import eu.kanade.tachiyomi.util.lang.launchIO
 | 
			
		||||
import eu.kanade.tachiyomi.util.lang.withUIContext
 | 
			
		||||
import eu.kanade.tachiyomi.util.prepUpdateCover
 | 
			
		||||
import eu.kanade.tachiyomi.util.removeCovers
 | 
			
		||||
import eu.kanade.tachiyomi.util.shouldDownloadNewChapters
 | 
			
		||||
import eu.kanade.tachiyomi.util.system.logcat
 | 
			
		||||
@@ -64,9 +65,10 @@ class MangaPresenter(
 | 
			
		||||
    private val trackManager: TrackManager = Injekt.get(),
 | 
			
		||||
    private val downloadManager: DownloadManager = Injekt.get(),
 | 
			
		||||
    private val coverCache: CoverCache = Injekt.get(),
 | 
			
		||||
    private val getChapterByMangaId: GetChapterByMangaId = Injekt.get(),
 | 
			
		||||
    private val getMangaWithChapters: GetMangaWithChapters = Injekt.get(),
 | 
			
		||||
    private val getDuplicateLibraryManga: GetDuplicateLibraryManga = Injekt.get(),
 | 
			
		||||
    private val getCategories: GetCategories = Injekt.get(),
 | 
			
		||||
    private val updateManga: UpdateManga = Injekt.get(),
 | 
			
		||||
) : BasePresenter<MangaController>() {
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
@@ -118,7 +120,6 @@ class MangaPresenter(
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // Manga info - start
 | 
			
		||||
 | 
			
		||||
        getMangaObservable()
 | 
			
		||||
            .observeOn(AndroidSchedulers.mainThread())
 | 
			
		||||
            .subscribeLatestCache({ view, manga -> view.onNextMangaInfo(manga, source) })
 | 
			
		||||
@@ -147,9 +148,9 @@ class MangaPresenter(
 | 
			
		||||
        // Keeps subscribed to changes and sends the list of chapters to the relay.
 | 
			
		||||
        presenterScope.launchIO {
 | 
			
		||||
            manga.id?.let { mangaId ->
 | 
			
		||||
                getChapterByMangaId.subscribe(mangaId)
 | 
			
		||||
                    .collectLatest { domainChapters ->
 | 
			
		||||
                        val chapterItems = domainChapters.map { it.toDbChapter().toModel() }
 | 
			
		||||
                getMangaWithChapters.subscribe(mangaId)
 | 
			
		||||
                    .collectLatest { (_, chapters) ->
 | 
			
		||||
                        val chapterItems = chapters.map { it.toDbChapter().toModel() }
 | 
			
		||||
                        setDownloadedChapters(chapterItems)
 | 
			
		||||
                        this@MangaPresenter.allChapters = chapterItems
 | 
			
		||||
                        observeDownloads()
 | 
			
		||||
@@ -168,7 +169,6 @@ class MangaPresenter(
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Manga info - start
 | 
			
		||||
 | 
			
		||||
    private fun getMangaObservable(): Observable<Manga> {
 | 
			
		||||
        return db.getManga(manga.url, manga.source).asRxObservable()
 | 
			
		||||
    }
 | 
			
		||||
@@ -193,16 +193,11 @@ class MangaPresenter(
 | 
			
		||||
        if (fetchMangaJob?.isActive == true) return
 | 
			
		||||
        fetchMangaJob = presenterScope.launchIO {
 | 
			
		||||
            try {
 | 
			
		||||
                val networkManga = source.getMangaDetails(manga.toMangaInfo())
 | 
			
		||||
                val sManga = networkManga.toSManga()
 | 
			
		||||
                manga.prepUpdateCover(coverCache, sManga, manualFetch)
 | 
			
		||||
                manga.copyFrom(sManga)
 | 
			
		||||
                if (!manga.favorite) {
 | 
			
		||||
                    // if the manga isn't a favorite, set its title from source and update in db
 | 
			
		||||
                    manga.title = sManga.title
 | 
			
		||||
                manga.toDomainManga()?.let { domainManga ->
 | 
			
		||||
                    val networkManga = source.getMangaDetails(domainManga.toMangaInfo())
 | 
			
		||||
 | 
			
		||||
                    updateManga.awaitUpdateFromSource(domainManga, networkManga, manualFetch, coverCache)
 | 
			
		||||
                }
 | 
			
		||||
                manga.initialized = true
 | 
			
		||||
                db.insertManga(manga).executeAsBlocking()
 | 
			
		||||
 | 
			
		||||
                withUIContext { view?.onFetchMangaInfoDone() }
 | 
			
		||||
            } catch (e: Throwable) {
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user