Move more things to domain module

This commit is contained in:
arkon
2023-02-18 15:14:04 -05:00
parent 753bf7de5d
commit f816196df2
48 changed files with 113 additions and 109 deletions

View File

@@ -0,0 +1,42 @@
package tachiyomi.domain.category.interactor
import logcat.LogPriority
import tachiyomi.core.util.lang.withNonCancellableContext
import tachiyomi.core.util.system.logcat
import tachiyomi.domain.category.model.CategoryUpdate
import tachiyomi.domain.category.repository.CategoryRepository
class DeleteCategory(
private val categoryRepository: CategoryRepository,
) {
suspend fun await(categoryId: Long) = withNonCancellableContext {
try {
categoryRepository.delete(categoryId)
} catch (e: Exception) {
logcat(LogPriority.ERROR, e)
return@withNonCancellableContext Result.InternalError(e)
}
val categories = categoryRepository.getAll()
val updates = categories.mapIndexed { index, category ->
CategoryUpdate(
id = category.id,
order = index.toLong(),
)
}
try {
categoryRepository.updatePartial(updates)
Result.Success
} catch (e: Exception) {
logcat(LogPriority.ERROR, e)
Result.InternalError(e)
}
}
sealed class Result {
object Success : Result()
data class InternalError(val error: Throwable) : Result()
}
}

View File

@@ -0,0 +1,35 @@
package tachiyomi.domain.category.interactor
import logcat.LogPriority
import tachiyomi.core.util.lang.withNonCancellableContext
import tachiyomi.core.util.system.logcat
import tachiyomi.domain.category.model.Category
import tachiyomi.domain.category.model.CategoryUpdate
import tachiyomi.domain.category.repository.CategoryRepository
class RenameCategory(
private val categoryRepository: CategoryRepository,
) {
suspend fun await(categoryId: Long, name: String) = withNonCancellableContext {
val update = CategoryUpdate(
id = categoryId,
name = name,
)
try {
categoryRepository.updatePartial(update)
Result.Success
} catch (e: Exception) {
logcat(LogPriority.ERROR, e)
Result.InternalError(e)
}
}
suspend fun await(category: Category, name: String) = await(category.id, name)
sealed class Result {
object Success : Result()
data class InternalError(val error: Throwable) : Result()
}
}

View File

@@ -0,0 +1,70 @@
package tachiyomi.domain.category.interactor
import kotlinx.coroutines.sync.Mutex
import kotlinx.coroutines.sync.withLock
import logcat.LogPriority
import tachiyomi.core.util.lang.withNonCancellableContext
import tachiyomi.core.util.system.logcat
import tachiyomi.domain.category.model.Category
import tachiyomi.domain.category.model.CategoryUpdate
import tachiyomi.domain.category.repository.CategoryRepository
import java.util.Collections
class ReorderCategory(
private val categoryRepository: CategoryRepository,
) {
private val mutex = Mutex()
suspend fun moveUp(category: Category): Result =
await(category, MoveTo.UP)
suspend fun moveDown(category: Category): Result =
await(category, MoveTo.DOWN)
private suspend fun await(category: Category, moveTo: MoveTo) = withNonCancellableContext {
mutex.withLock {
val categories = categoryRepository.getAll()
.filterNot(Category::isSystemCategory)
.toMutableList()
val currentIndex = categories.indexOfFirst { it.id == category.id }
if (currentIndex == -1) {
return@withNonCancellableContext Result.Unchanged
}
val newPosition = when (moveTo) {
MoveTo.UP -> currentIndex - 1
MoveTo.DOWN -> currentIndex + 1
}.toInt()
try {
Collections.swap(categories, currentIndex, newPosition)
val updates = categories.mapIndexed { index, category ->
CategoryUpdate(
id = category.id,
order = index.toLong(),
)
}
categoryRepository.updatePartial(updates)
Result.Success
} catch (e: Exception) {
logcat(LogPriority.ERROR, e)
Result.InternalError(e)
}
}
}
sealed class Result {
object Success : Result()
object Unchanged : Result()
data class InternalError(val error: Throwable) : Result()
}
private enum class MoveTo {
UP,
DOWN,
}
}

View File

@@ -0,0 +1,18 @@
package tachiyomi.domain.category.interactor
import logcat.LogPriority
import tachiyomi.core.util.system.logcat
import tachiyomi.domain.manga.repository.MangaRepository
class SetMangaCategories(
private val mangaRepository: MangaRepository,
) {
suspend fun await(mangaId: Long, categoryIds: List<Long>) {
try {
mangaRepository.setMangaCategories(mangaId, categoryIds)
} catch (e: Exception) {
logcat(LogPriority.ERROR, e)
}
}
}

View File

@@ -0,0 +1,24 @@
package tachiyomi.domain.category.interactor
import tachiyomi.core.util.lang.withNonCancellableContext
import tachiyomi.domain.category.model.CategoryUpdate
import tachiyomi.domain.category.repository.CategoryRepository
class UpdateCategory(
private val categoryRepository: CategoryRepository,
) {
suspend fun await(payload: CategoryUpdate): Result = withNonCancellableContext {
try {
categoryRepository.updatePartial(payload)
Result.Success
} catch (e: Exception) {
Result.Error(e)
}
}
sealed class Result {
object Success : Result()
data class Error(val error: Exception) : Result()
}
}

View File

@@ -0,0 +1,29 @@
package tachiyomi.domain.chapter.interactor
import logcat.LogPriority
import tachiyomi.core.util.system.logcat
import tachiyomi.domain.chapter.model.Chapter
import tachiyomi.domain.chapter.repository.ChapterRepository
class GetChapter(
private val chapterRepository: ChapterRepository,
) {
suspend fun await(id: Long): Chapter? {
return try {
chapterRepository.getChapterById(id)
} catch (e: Exception) {
logcat(LogPriority.ERROR, e)
null
}
}
suspend fun await(url: String, mangaId: Long): Chapter? {
return try {
chapterRepository.getChapterByUrlAndMangaId(url, mangaId)
} catch (e: Exception) {
logcat(LogPriority.ERROR, e)
null
}
}
}

View File

@@ -0,0 +1,20 @@
package tachiyomi.domain.chapter.interactor
import logcat.LogPriority
import tachiyomi.core.util.system.logcat
import tachiyomi.domain.chapter.model.Chapter
import tachiyomi.domain.chapter.repository.ChapterRepository
class GetChapterByMangaId(
private val chapterRepository: ChapterRepository,
) {
suspend fun await(mangaId: Long): List<Chapter> {
return try {
chapterRepository.getChapterByMangaId(mangaId)
} catch (e: Exception) {
logcat(LogPriority.ERROR, e)
emptyList()
}
}
}

View File

@@ -0,0 +1,27 @@
package tachiyomi.domain.chapter.interactor
import logcat.LogPriority
import tachiyomi.core.util.system.logcat
import tachiyomi.domain.chapter.model.ChapterUpdate
import tachiyomi.domain.chapter.repository.ChapterRepository
class UpdateChapter(
private val chapterRepository: ChapterRepository,
) {
suspend fun await(chapterUpdate: 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)
}
}
}

View File

@@ -0,0 +1,13 @@
package tachiyomi.domain.manga.interactor
import tachiyomi.domain.manga.model.Manga
import tachiyomi.domain.manga.repository.MangaRepository
class GetDuplicateLibraryManga(
private val mangaRepository: MangaRepository,
) {
suspend fun await(title: String): Manga? {
return mangaRepository.getDuplicateLibraryManga(title.lowercase())
}
}

View File

@@ -0,0 +1,18 @@
package tachiyomi.domain.manga.interactor
import kotlinx.coroutines.flow.Flow
import tachiyomi.domain.manga.model.Manga
import tachiyomi.domain.manga.repository.MangaRepository
class GetFavorites(
private val mangaRepository: MangaRepository,
) {
suspend fun await(): List<Manga> {
return mangaRepository.getFavorites()
}
fun subscribe(sourceId: Long): Flow<List<Manga>> {
return mangaRepository.getFavoritesBySourceId(sourceId)
}
}

View File

@@ -0,0 +1,18 @@
package tachiyomi.domain.manga.interactor
import kotlinx.coroutines.flow.Flow
import tachiyomi.domain.library.model.LibraryManga
import tachiyomi.domain.manga.repository.MangaRepository
class GetLibraryManga(
private val mangaRepository: MangaRepository,
) {
suspend fun await(): List<LibraryManga> {
return mangaRepository.getLibraryManga()
}
fun subscribe(): Flow<List<LibraryManga>> {
return mangaRepository.getLibraryMangaAsFlow()
}
}

View File

@@ -0,0 +1,29 @@
package tachiyomi.domain.manga.interactor
import kotlinx.coroutines.flow.Flow
import logcat.LogPriority
import tachiyomi.core.util.system.logcat
import tachiyomi.domain.manga.model.Manga
import tachiyomi.domain.manga.repository.MangaRepository
class GetManga(
private val mangaRepository: MangaRepository,
) {
suspend fun await(id: Long): Manga? {
return try {
mangaRepository.getMangaById(id)
} catch (e: Exception) {
logcat(LogPriority.ERROR, e)
null
}
}
suspend fun subscribe(id: Long): Flow<Manga> {
return mangaRepository.getMangaByIdAsFlow(id)
}
fun subscribe(url: String, sourceId: Long): Flow<Manga?> {
return mangaRepository.getMangaByUrlAndSourceIdAsFlow(url, sourceId)
}
}

View File

@@ -0,0 +1,31 @@
package tachiyomi.domain.manga.interactor
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.combine
import tachiyomi.domain.chapter.model.Chapter
import tachiyomi.domain.chapter.repository.ChapterRepository
import tachiyomi.domain.manga.model.Manga
import tachiyomi.domain.manga.repository.MangaRepository
class GetMangaWithChapters(
private val mangaRepository: MangaRepository,
private val chapterRepository: ChapterRepository,
) {
suspend fun subscribe(id: Long): Flow<Pair<Manga, List<Chapter>>> {
return combine(
mangaRepository.getMangaByIdAsFlow(id),
chapterRepository.getChapterByMangaIdAsFlow(id),
) { manga, chapters ->
Pair(manga, chapters)
}
}
suspend fun awaitManga(id: Long): Manga {
return mangaRepository.getMangaById(id)
}
suspend fun awaitChapters(id: Long): List<Chapter> {
return chapterRepository.getChapterByMangaId(id)
}
}

View File

@@ -0,0 +1,35 @@
package tachiyomi.domain.manga.interactor
import tachiyomi.domain.manga.model.Manga
import tachiyomi.domain.manga.repository.MangaRepository
class NetworkToLocalManga(
private val mangaRepository: MangaRepository,
) {
suspend fun await(manga: Manga): Manga {
val localManga = getManga(manga.url, manga.source)
return when {
localManga == null -> {
val id = insertManga(manga)
manga.copy(id = id!!)
}
!localManga.favorite -> {
// if the manga isn't a favorite, set its display title from source
// if it later becomes a favorite, updated title will go to db
localManga.copy(title = manga.title)
}
else -> {
localManga
}
}
}
private suspend fun getManga(url: String, sourceId: Long): Manga? {
return mangaRepository.getMangaByUrlAndSourceId(url, sourceId)
}
private suspend fun insertManga(manga: Manga): Long? {
return mangaRepository.insert(manga)
}
}

View File

@@ -0,0 +1,12 @@
package tachiyomi.domain.manga.interactor
import tachiyomi.domain.manga.repository.MangaRepository
class ResetViewerFlags(
private val mangaRepository: MangaRepository,
) {
suspend fun await(): Boolean {
return mangaRepository.resetViewerFlags()
}
}

View File

@@ -0,0 +1,97 @@
package tachiyomi.domain.manga.interactor
import tachiyomi.domain.manga.model.Manga
import tachiyomi.domain.manga.model.MangaUpdate
import tachiyomi.domain.manga.repository.MangaRepository
class SetMangaChapterFlags(
private val mangaRepository: MangaRepository,
) {
suspend fun awaitSetDownloadedFilter(manga: Manga, flag: Long): Boolean {
return mangaRepository.update(
MangaUpdate(
id = manga.id,
chapterFlags = manga.chapterFlags.setFlag(flag, Manga.CHAPTER_DOWNLOADED_MASK),
),
)
}
suspend fun awaitSetUnreadFilter(manga: Manga, flag: Long): Boolean {
return mangaRepository.update(
MangaUpdate(
id = manga.id,
chapterFlags = manga.chapterFlags.setFlag(flag, Manga.CHAPTER_UNREAD_MASK),
),
)
}
suspend fun awaitSetBookmarkFilter(manga: Manga, flag: Long): Boolean {
return mangaRepository.update(
MangaUpdate(
id = manga.id,
chapterFlags = manga.chapterFlags.setFlag(flag, Manga.CHAPTER_BOOKMARKED_MASK),
),
)
}
suspend fun awaitSetDisplayMode(manga: Manga, flag: Long): Boolean {
return mangaRepository.update(
MangaUpdate(
id = manga.id,
chapterFlags = manga.chapterFlags.setFlag(flag, Manga.CHAPTER_DISPLAY_MASK),
),
)
}
suspend fun awaitSetSortingModeOrFlipOrder(manga: Manga, flag: Long): Boolean {
val newFlags = manga.chapterFlags.let {
if (manga.sorting == flag) {
// Just flip the order
val orderFlag = if (manga.sortDescending()) {
Manga.CHAPTER_SORT_ASC
} else {
Manga.CHAPTER_SORT_DESC
}
it.setFlag(orderFlag, Manga.CHAPTER_SORT_DIR_MASK)
} else {
// Set new flag with ascending order
it
.setFlag(flag, Manga.CHAPTER_SORTING_MASK)
.setFlag(Manga.CHAPTER_SORT_ASC, Manga.CHAPTER_SORT_DIR_MASK)
}
}
return mangaRepository.update(
MangaUpdate(
id = manga.id,
chapterFlags = newFlags,
),
)
}
suspend fun awaitSetAllFlags(
mangaId: Long,
unreadFilter: Long,
downloadedFilter: Long,
bookmarkedFilter: Long,
sortingMode: Long,
sortingDirection: Long,
displayMode: Long,
): Boolean {
return mangaRepository.update(
MangaUpdate(
id = mangaId,
chapterFlags = 0L.setFlag(unreadFilter, Manga.CHAPTER_UNREAD_MASK)
.setFlag(downloadedFilter, Manga.CHAPTER_DOWNLOADED_MASK)
.setFlag(bookmarkedFilter, Manga.CHAPTER_BOOKMARKED_MASK)
.setFlag(sortingMode, Manga.CHAPTER_SORTING_MASK)
.setFlag(sortingDirection, Manga.CHAPTER_SORT_DIR_MASK)
.setFlag(displayMode, Manga.CHAPTER_DISPLAY_MASK),
),
)
}
private fun Long.setFlag(flag: Long, mask: Long): Long {
return this and mask.inv() or (flag and mask)
}
}

View File

@@ -0,0 +1,18 @@
package tachiyomi.domain.track.interactor
import logcat.LogPriority
import tachiyomi.core.util.system.logcat
import tachiyomi.domain.track.repository.TrackRepository
class DeleteTrack(
private val trackRepository: TrackRepository,
) {
suspend fun await(mangaId: Long, syncId: Long) {
try {
trackRepository.delete(mangaId, syncId)
} catch (e: Exception) {
logcat(LogPriority.ERROR, e)
}
}
}

View File

@@ -0,0 +1,34 @@
package tachiyomi.domain.track.interactor
import kotlinx.coroutines.flow.Flow
import logcat.LogPriority
import tachiyomi.core.util.system.logcat
import tachiyomi.domain.track.model.Track
import tachiyomi.domain.track.repository.TrackRepository
class GetTracks(
private val trackRepository: TrackRepository,
) {
suspend fun awaitOne(id: Long): Track? {
return try {
trackRepository.getTrackById(id)
} catch (e: Exception) {
logcat(LogPriority.ERROR, e)
null
}
}
suspend fun await(mangaId: Long): List<Track> {
return try {
trackRepository.getTracksByMangaId(mangaId)
} catch (e: Exception) {
logcat(LogPriority.ERROR, e)
emptyList()
}
}
fun subscribe(mangaId: Long): Flow<List<Track>> {
return trackRepository.getTracksByMangaIdAsFlow(mangaId)
}
}

View File

@@ -0,0 +1,20 @@
package tachiyomi.domain.track.interactor
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.map
import tachiyomi.domain.track.repository.TrackRepository
class GetTracksPerManga(
private val trackRepository: TrackRepository,
) {
fun subscribe(): Flow<Map<Long, List<Long>>> {
return trackRepository.getTracksAsFlow().map { tracks ->
tracks
.groupBy { it.mangaId }
.mapValues { entry ->
entry.value.map { it.syncId }
}
}
}
}

View File

@@ -0,0 +1,27 @@
package tachiyomi.domain.track.interactor
import logcat.LogPriority
import tachiyomi.core.util.system.logcat
import tachiyomi.domain.track.model.Track
import tachiyomi.domain.track.repository.TrackRepository
class InsertTrack(
private val trackRepository: TrackRepository,
) {
suspend fun await(track: Track) {
try {
trackRepository.insert(track)
} catch (e: Exception) {
logcat(LogPriority.ERROR, e)
}
}
suspend fun awaitAll(tracks: List<Track>) {
try {
trackRepository.insertAll(tracks)
} catch (e: Exception) {
logcat(LogPriority.ERROR, e)
}
}
}