mirror of
https://github.com/Suwayomi/TachideskJUI.git
synced 2025-12-10 06:42:05 +01:00
Fix formatting in a bunch of files
This commit is contained in:
@@ -23,103 +23,102 @@ import kotlinx.coroutines.launch
|
||||
import me.tatarka.inject.annotations.Inject
|
||||
import org.lighthousegames.logging.logging
|
||||
|
||||
class ServerListeners
|
||||
@Inject
|
||||
constructor() {
|
||||
val scope = CoroutineScope(SupervisorJob() + Dispatchers.Default)
|
||||
@Inject
|
||||
class ServerListeners {
|
||||
val scope = CoroutineScope(SupervisorJob() + Dispatchers.Default)
|
||||
|
||||
private fun <T> Flow<T>.startWith(value: T) = onStart { emit(value) }
|
||||
private fun <T> Flow<T>.startWith(value: T) = onStart { emit(value) }
|
||||
|
||||
private val _mangaListener = MutableSharedFlow<List<Long>>(
|
||||
extraBufferCapacity = Channel.UNLIMITED,
|
||||
)
|
||||
val mangaListener = _mangaListener.asSharedFlow()
|
||||
private val _mangaListener = MutableSharedFlow<List<Long>>(
|
||||
extraBufferCapacity = Channel.UNLIMITED,
|
||||
)
|
||||
val mangaListener = _mangaListener.asSharedFlow()
|
||||
|
||||
private val _chapterIdsListener = MutableSharedFlow<List<Long>>(
|
||||
extraBufferCapacity = Channel.UNLIMITED,
|
||||
)
|
||||
val chapterIdsListener = _chapterIdsListener.asSharedFlow()
|
||||
private val _chapterIdsListener = MutableSharedFlow<List<Long>>(
|
||||
extraBufferCapacity = Channel.UNLIMITED,
|
||||
)
|
||||
val chapterIdsListener = _chapterIdsListener.asSharedFlow()
|
||||
|
||||
private val _mangaChapterIdsListener = MutableSharedFlow<List<Long>>(
|
||||
extraBufferCapacity = Channel.UNLIMITED,
|
||||
)
|
||||
val mangaChapterIdsListener = _mangaChapterIdsListener.asSharedFlow()
|
||||
private val _mangaChapterIdsListener = MutableSharedFlow<List<Long>>(
|
||||
extraBufferCapacity = Channel.UNLIMITED,
|
||||
)
|
||||
val mangaChapterIdsListener = _mangaChapterIdsListener.asSharedFlow()
|
||||
|
||||
private val categoryMangaListener = MutableSharedFlow<Long>(
|
||||
extraBufferCapacity = Channel.UNLIMITED,
|
||||
)
|
||||
private val categoryMangaListener = MutableSharedFlow<Long>(
|
||||
extraBufferCapacity = Channel.UNLIMITED,
|
||||
)
|
||||
|
||||
private val extensionListener = MutableSharedFlow<List<String>>(
|
||||
extraBufferCapacity = Channel.UNLIMITED,
|
||||
)
|
||||
private val extensionListener = MutableSharedFlow<List<String>>(
|
||||
extraBufferCapacity = Channel.UNLIMITED,
|
||||
)
|
||||
|
||||
fun <T> combineMangaUpdates(
|
||||
flow: Flow<T>,
|
||||
predate: (suspend (List<Long>) -> Boolean)? = null,
|
||||
) = if (predate != null) {
|
||||
_mangaListener
|
||||
.filter(predate)
|
||||
.startWith(Unit)
|
||||
} else {
|
||||
_mangaListener.startWith(Unit)
|
||||
}
|
||||
.buffer(capacity = 1, onBufferOverflow = BufferOverflow.DROP_OLDEST)
|
||||
.flatMapLatest { flow }
|
||||
fun <T> combineMangaUpdates(
|
||||
flow: Flow<T>,
|
||||
predate: (suspend (List<Long>) -> Boolean)? = null,
|
||||
) = if (predate != null) {
|
||||
_mangaListener
|
||||
.filter(predate)
|
||||
.startWith(Unit)
|
||||
} else {
|
||||
_mangaListener.startWith(Unit)
|
||||
}
|
||||
.buffer(capacity = 1, onBufferOverflow = BufferOverflow.DROP_OLDEST)
|
||||
.flatMapLatest { flow }
|
||||
|
||||
fun updateManga(vararg ids: Long) {
|
||||
scope.launch {
|
||||
_mangaListener.emit(ids.toList())
|
||||
}
|
||||
}
|
||||
|
||||
fun <T> combineCategoryManga(
|
||||
flow: Flow<T>,
|
||||
predate: (suspend (Long) -> Boolean)? = null,
|
||||
) = if (predate != null) {
|
||||
categoryMangaListener.filter(predate).startWith(-1)
|
||||
} else {
|
||||
categoryMangaListener.startWith(-1)
|
||||
}
|
||||
.buffer(capacity = 1, onBufferOverflow = BufferOverflow.DROP_OLDEST)
|
||||
.flatMapLatest { flow }
|
||||
|
||||
fun updateCategoryManga(id: Long) {
|
||||
scope.launch {
|
||||
categoryMangaListener.emit(id)
|
||||
}
|
||||
}
|
||||
|
||||
fun <T> combineChapters(
|
||||
flow: Flow<T>,
|
||||
chapterIdPredate: (suspend (List<Long>) -> Boolean)? = null,
|
||||
mangaIdPredate: (suspend (List<Long>) -> Boolean)? = null,
|
||||
): Flow<T> {
|
||||
val idsListener = _chapterIdsListener
|
||||
.filter { chapterIdPredate?.invoke(it) ?: false }
|
||||
.startWith(Unit)
|
||||
.combine(
|
||||
_mangaChapterIdsListener.filter { mangaIdPredate?.invoke(it) ?: false }
|
||||
.startWith(Unit),
|
||||
) { _, _ -> }
|
||||
|
||||
return idsListener
|
||||
.buffer(capacity = 1, onBufferOverflow = BufferOverflow.DROP_OLDEST)
|
||||
.flatMapLatest { flow }
|
||||
}
|
||||
|
||||
fun updateChapters(chapterIds: List<Long>) {
|
||||
scope.launch {
|
||||
_chapterIdsListener.emit(chapterIds)
|
||||
}
|
||||
}
|
||||
|
||||
fun updateChapters(vararg chapterIds: Long) {
|
||||
scope.launch {
|
||||
_chapterIdsListener.emit(chapterIds.toList())
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
private val log = logging()
|
||||
fun updateManga(vararg ids: Long) {
|
||||
scope.launch {
|
||||
_mangaListener.emit(ids.toList())
|
||||
}
|
||||
}
|
||||
|
||||
fun <T> combineCategoryManga(
|
||||
flow: Flow<T>,
|
||||
predate: (suspend (Long) -> Boolean)? = null,
|
||||
) = if (predate != null) {
|
||||
categoryMangaListener.filter(predate).startWith(-1)
|
||||
} else {
|
||||
categoryMangaListener.startWith(-1)
|
||||
}
|
||||
.buffer(capacity = 1, onBufferOverflow = BufferOverflow.DROP_OLDEST)
|
||||
.flatMapLatest { flow }
|
||||
|
||||
fun updateCategoryManga(id: Long) {
|
||||
scope.launch {
|
||||
categoryMangaListener.emit(id)
|
||||
}
|
||||
}
|
||||
|
||||
fun <T> combineChapters(
|
||||
flow: Flow<T>,
|
||||
chapterIdPredate: (suspend (List<Long>) -> Boolean)? = null,
|
||||
mangaIdPredate: (suspend (List<Long>) -> Boolean)? = null,
|
||||
): Flow<T> {
|
||||
val idsListener = _chapterIdsListener
|
||||
.filter { chapterIdPredate?.invoke(it) ?: false }
|
||||
.startWith(Unit)
|
||||
.combine(
|
||||
_mangaChapterIdsListener.filter { mangaIdPredate?.invoke(it) ?: false }
|
||||
.startWith(Unit),
|
||||
) { _, _ -> }
|
||||
|
||||
return idsListener
|
||||
.buffer(capacity = 1, onBufferOverflow = BufferOverflow.DROP_OLDEST)
|
||||
.flatMapLatest { flow }
|
||||
}
|
||||
|
||||
fun updateChapters(chapterIds: List<Long>) {
|
||||
scope.launch {
|
||||
_chapterIdsListener.emit(chapterIds)
|
||||
}
|
||||
}
|
||||
|
||||
fun updateChapters(vararg chapterIds: Long) {
|
||||
scope.launch {
|
||||
_chapterIdsListener.emit(chapterIds.toList())
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
private val log = logging()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,30 +13,29 @@ import kotlinx.coroutines.flow.singleOrNull
|
||||
import me.tatarka.inject.annotations.Inject
|
||||
import org.lighthousegames.logging.logging
|
||||
|
||||
class ExportBackupFile
|
||||
@Inject
|
||||
constructor(
|
||||
private val backupRepository: BackupRepository,
|
||||
) {
|
||||
suspend fun await(
|
||||
includeCategories: Boolean,
|
||||
includeChapters: Boolean,
|
||||
block: HttpRequestBuilder.() -> Unit = {},
|
||||
onError: suspend (Throwable) -> Unit = {},
|
||||
) = asFlow(includeCategories, includeChapters, block)
|
||||
.catch {
|
||||
onError(it)
|
||||
log.warn(it) { "Failed to export backup" }
|
||||
}
|
||||
.singleOrNull()
|
||||
|
||||
fun asFlow(
|
||||
includeCategories: Boolean,
|
||||
includeChapters: Boolean,
|
||||
block: HttpRequestBuilder.() -> Unit = {},
|
||||
) = backupRepository.createBackup(includeCategories, includeChapters, block)
|
||||
|
||||
companion object {
|
||||
private val log = logging()
|
||||
@Inject
|
||||
class ExportBackupFile(
|
||||
private val backupRepository: BackupRepository,
|
||||
) {
|
||||
suspend fun await(
|
||||
includeCategories: Boolean,
|
||||
includeChapters: Boolean,
|
||||
block: HttpRequestBuilder.() -> Unit = {},
|
||||
onError: suspend (Throwable) -> Unit = {},
|
||||
) = asFlow(includeCategories, includeChapters, block)
|
||||
.catch {
|
||||
onError(it)
|
||||
log.warn(it) { "Failed to export backup" }
|
||||
}
|
||||
.singleOrNull()
|
||||
|
||||
fun asFlow(
|
||||
includeCategories: Boolean,
|
||||
includeChapters: Boolean,
|
||||
block: HttpRequestBuilder.() -> Unit = {},
|
||||
) = backupRepository.createBackup(includeCategories, includeChapters, block)
|
||||
|
||||
companion object {
|
||||
private val log = logging()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,24 +15,23 @@ import okio.Path
|
||||
import okio.SYSTEM
|
||||
import org.lighthousegames.logging.logging
|
||||
|
||||
class ImportBackupFile
|
||||
@Inject
|
||||
constructor(
|
||||
private val backupRepository: BackupRepository,
|
||||
) {
|
||||
suspend fun await(
|
||||
file: Path,
|
||||
onError: suspend (Throwable) -> Unit = {},
|
||||
) = asFlow(file)
|
||||
.catch {
|
||||
onError(it)
|
||||
log.warn(it) { "Failed to import backup ${file.name}" }
|
||||
}
|
||||
.singleOrNull()
|
||||
|
||||
fun asFlow(file: Path) = backupRepository.restoreBackup(FileSystem.SYSTEM.source(file))
|
||||
|
||||
companion object {
|
||||
private val log = logging()
|
||||
@Inject
|
||||
class ImportBackupFile(
|
||||
private val backupRepository: BackupRepository,
|
||||
) {
|
||||
suspend fun await(
|
||||
file: Path,
|
||||
onError: suspend (Throwable) -> Unit = {},
|
||||
) = asFlow(file)
|
||||
.catch {
|
||||
onError(it)
|
||||
log.warn(it) { "Failed to import backup ${file.name}" }
|
||||
}
|
||||
.singleOrNull()
|
||||
|
||||
fun asFlow(file: Path) = backupRepository.restoreBackup(FileSystem.SYSTEM.source(file))
|
||||
|
||||
companion object {
|
||||
private val log = logging()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,24 +15,23 @@ import okio.Path
|
||||
import okio.SYSTEM
|
||||
import org.lighthousegames.logging.logging
|
||||
|
||||
class ValidateBackupFile
|
||||
@Inject
|
||||
constructor(
|
||||
private val backupRepository: BackupRepository,
|
||||
) {
|
||||
suspend fun await(
|
||||
file: Path,
|
||||
onError: suspend (Throwable) -> Unit = {},
|
||||
) = asFlow(file)
|
||||
.catch {
|
||||
onError(it)
|
||||
log.warn(it) { "Failed to validate backup ${file.name}" }
|
||||
}
|
||||
.singleOrNull()
|
||||
|
||||
fun asFlow(file: Path) = backupRepository.validateBackup(FileSystem.SYSTEM.source(file))
|
||||
|
||||
companion object {
|
||||
private val log = logging()
|
||||
@Inject
|
||||
class ValidateBackupFile(
|
||||
private val backupRepository: BackupRepository,
|
||||
) {
|
||||
suspend fun await(
|
||||
file: Path,
|
||||
onError: suspend (Throwable) -> Unit = {},
|
||||
) = asFlow(file)
|
||||
.catch {
|
||||
onError(it)
|
||||
log.warn(it) { "Failed to validate backup ${file.name}" }
|
||||
}
|
||||
.singleOrNull()
|
||||
|
||||
fun asFlow(file: Path) = backupRepository.validateBackup(FileSystem.SYSTEM.source(file))
|
||||
|
||||
companion object {
|
||||
private val log = logging()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,61 +17,60 @@ import kotlinx.coroutines.flow.map
|
||||
import me.tatarka.inject.annotations.Inject
|
||||
import org.lighthousegames.logging.logging
|
||||
|
||||
class AddMangaToCategory
|
||||
@Inject
|
||||
constructor(
|
||||
private val categoryRepository: CategoryRepository,
|
||||
private val serverListeners: ServerListeners,
|
||||
) {
|
||||
suspend fun await(
|
||||
mangaId: Long,
|
||||
categoryId: Long,
|
||||
onError: suspend (Throwable) -> Unit = {},
|
||||
) = asFlow(mangaId, categoryId)
|
||||
.catch {
|
||||
onError(it)
|
||||
log.warn(it) { "Failed to add $mangaId to category $categoryId" }
|
||||
}
|
||||
.collect()
|
||||
|
||||
suspend fun await(
|
||||
manga: Manga,
|
||||
category: Category,
|
||||
onError: suspend (Throwable) -> Unit = {},
|
||||
) = asFlow(manga, category)
|
||||
.catch {
|
||||
onError(it)
|
||||
log.warn(it) { "Failed to add ${manga.title}(${manga.id}) to category ${category.name}" }
|
||||
}
|
||||
.collect()
|
||||
|
||||
fun asFlow(
|
||||
mangaId: Long,
|
||||
categoryId: Long,
|
||||
) = if (categoryId != 0L) {
|
||||
categoryRepository.addMangaToCategory(mangaId, categoryId)
|
||||
.map { serverListeners.updateCategoryManga(categoryId) }
|
||||
} else {
|
||||
flow {
|
||||
serverListeners.updateCategoryManga(categoryId)
|
||||
emit(Unit)
|
||||
}
|
||||
@Inject
|
||||
class AddMangaToCategory(
|
||||
private val categoryRepository: CategoryRepository,
|
||||
private val serverListeners: ServerListeners,
|
||||
) {
|
||||
suspend fun await(
|
||||
mangaId: Long,
|
||||
categoryId: Long,
|
||||
onError: suspend (Throwable) -> Unit = {},
|
||||
) = asFlow(mangaId, categoryId)
|
||||
.catch {
|
||||
onError(it)
|
||||
log.warn(it) { "Failed to add $mangaId to category $categoryId" }
|
||||
}
|
||||
.collect()
|
||||
|
||||
fun asFlow(
|
||||
manga: Manga,
|
||||
category: Category,
|
||||
) = if (category.id != 0L) {
|
||||
categoryRepository.addMangaToCategory(manga.id, category.id)
|
||||
.map { serverListeners.updateCategoryManga(category.id) }
|
||||
} else {
|
||||
flow {
|
||||
serverListeners.updateCategoryManga(category.id)
|
||||
emit(Unit)
|
||||
}
|
||||
suspend fun await(
|
||||
manga: Manga,
|
||||
category: Category,
|
||||
onError: suspend (Throwable) -> Unit = {},
|
||||
) = asFlow(manga, category)
|
||||
.catch {
|
||||
onError(it)
|
||||
log.warn(it) { "Failed to add ${manga.title}(${manga.id}) to category ${category.name}" }
|
||||
}
|
||||
.collect()
|
||||
|
||||
companion object {
|
||||
private val log = logging()
|
||||
fun asFlow(
|
||||
mangaId: Long,
|
||||
categoryId: Long,
|
||||
) = if (categoryId != 0L) {
|
||||
categoryRepository.addMangaToCategory(mangaId, categoryId)
|
||||
.map { serverListeners.updateCategoryManga(categoryId) }
|
||||
} else {
|
||||
flow {
|
||||
serverListeners.updateCategoryManga(categoryId)
|
||||
emit(Unit)
|
||||
}
|
||||
}
|
||||
|
||||
fun asFlow(
|
||||
manga: Manga,
|
||||
category: Category,
|
||||
) = if (category.id != 0L) {
|
||||
categoryRepository.addMangaToCategory(manga.id, category.id)
|
||||
.map { serverListeners.updateCategoryManga(category.id) }
|
||||
} else {
|
||||
flow {
|
||||
serverListeners.updateCategoryManga(category.id)
|
||||
emit(Unit)
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
private val log = logging()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,24 +12,23 @@ import kotlinx.coroutines.flow.collect
|
||||
import me.tatarka.inject.annotations.Inject
|
||||
import org.lighthousegames.logging.logging
|
||||
|
||||
class CreateCategory
|
||||
@Inject
|
||||
constructor(
|
||||
private val categoryRepository: CategoryRepository,
|
||||
) {
|
||||
suspend fun await(
|
||||
name: String,
|
||||
onError: suspend (Throwable) -> Unit = {},
|
||||
) = asFlow(name)
|
||||
.catch {
|
||||
onError(it)
|
||||
log.warn(it) { "Failed to create category $name" }
|
||||
}
|
||||
.collect()
|
||||
|
||||
fun asFlow(name: String) = categoryRepository.createCategory(name)
|
||||
|
||||
companion object {
|
||||
private val log = logging()
|
||||
@Inject
|
||||
class CreateCategory(
|
||||
private val categoryRepository: CategoryRepository,
|
||||
) {
|
||||
suspend fun await(
|
||||
name: String,
|
||||
onError: suspend (Throwable) -> Unit = {},
|
||||
) = asFlow(name)
|
||||
.catch {
|
||||
onError(it)
|
||||
log.warn(it) { "Failed to create category $name" }
|
||||
}
|
||||
.collect()
|
||||
|
||||
fun asFlow(name: String) = categoryRepository.createCategory(name)
|
||||
|
||||
companion object {
|
||||
private val log = logging()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,36 +13,35 @@ import kotlinx.coroutines.flow.collect
|
||||
import me.tatarka.inject.annotations.Inject
|
||||
import org.lighthousegames.logging.logging
|
||||
|
||||
class DeleteCategory
|
||||
@Inject
|
||||
constructor(
|
||||
private val categoryRepository: CategoryRepository,
|
||||
) {
|
||||
suspend fun await(
|
||||
categoryId: Long,
|
||||
onError: suspend (Throwable) -> Unit = {},
|
||||
) = asFlow(categoryId)
|
||||
.catch {
|
||||
onError(it)
|
||||
log.warn(it) { "Failed to delete category $categoryId" }
|
||||
}
|
||||
.collect()
|
||||
|
||||
suspend fun await(
|
||||
category: Category,
|
||||
onError: suspend (Throwable) -> Unit = {},
|
||||
) = asFlow(category)
|
||||
.catch {
|
||||
onError(it)
|
||||
log.warn(it) { "Failed to delete category ${category.name}" }
|
||||
}
|
||||
.collect()
|
||||
|
||||
fun asFlow(categoryId: Long) = categoryRepository.deleteCategory(categoryId)
|
||||
|
||||
fun asFlow(category: Category) = categoryRepository.deleteCategory(category.id)
|
||||
|
||||
companion object {
|
||||
private val log = logging()
|
||||
@Inject
|
||||
class DeleteCategory(
|
||||
private val categoryRepository: CategoryRepository,
|
||||
) {
|
||||
suspend fun await(
|
||||
categoryId: Long,
|
||||
onError: suspend (Throwable) -> Unit = {},
|
||||
) = asFlow(categoryId)
|
||||
.catch {
|
||||
onError(it)
|
||||
log.warn(it) { "Failed to delete category $categoryId" }
|
||||
}
|
||||
.collect()
|
||||
|
||||
suspend fun await(
|
||||
category: Category,
|
||||
onError: suspend (Throwable) -> Unit = {},
|
||||
) = asFlow(category)
|
||||
.catch {
|
||||
onError(it)
|
||||
log.warn(it) { "Failed to delete category ${category.name}" }
|
||||
}
|
||||
.collect()
|
||||
|
||||
fun asFlow(categoryId: Long) = categoryRepository.deleteCategory(categoryId)
|
||||
|
||||
fun asFlow(category: Category) = categoryRepository.deleteCategory(category.id)
|
||||
|
||||
companion object {
|
||||
private val log = logging()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,32 +13,31 @@ import kotlinx.coroutines.flow.singleOrNull
|
||||
import me.tatarka.inject.annotations.Inject
|
||||
import org.lighthousegames.logging.logging
|
||||
|
||||
class GetCategories
|
||||
@Inject
|
||||
constructor(
|
||||
private val categoryRepository: CategoryRepository,
|
||||
) {
|
||||
suspend fun await(
|
||||
dropDefault: Boolean = false,
|
||||
onError: suspend (Throwable) -> Unit = {},
|
||||
) = asFlow(dropDefault)
|
||||
.catch {
|
||||
onError(it)
|
||||
log.warn(it) { "Failed to get categories" }
|
||||
}
|
||||
.singleOrNull()
|
||||
|
||||
fun asFlow(dropDefault: Boolean = false) =
|
||||
categoryRepository.getCategories()
|
||||
.map { categories ->
|
||||
if (dropDefault) {
|
||||
categories.filterNot { it.name.equals("default", true) }
|
||||
} else {
|
||||
categories
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
private val log = logging()
|
||||
@Inject
|
||||
class GetCategories(
|
||||
private val categoryRepository: CategoryRepository,
|
||||
) {
|
||||
suspend fun await(
|
||||
dropDefault: Boolean = false,
|
||||
onError: suspend (Throwable) -> Unit = {},
|
||||
) = asFlow(dropDefault)
|
||||
.catch {
|
||||
onError(it)
|
||||
log.warn(it) { "Failed to get categories" }
|
||||
}
|
||||
.singleOrNull()
|
||||
|
||||
fun asFlow(dropDefault: Boolean = false) =
|
||||
categoryRepository.getCategories()
|
||||
.map { categories ->
|
||||
if (dropDefault) {
|
||||
categories.filterNot { it.name.equals("default", true) }
|
||||
} else {
|
||||
categories
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
private val log = logging()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,36 +13,35 @@ import kotlinx.coroutines.flow.singleOrNull
|
||||
import me.tatarka.inject.annotations.Inject
|
||||
import org.lighthousegames.logging.logging
|
||||
|
||||
class GetMangaCategories
|
||||
@Inject
|
||||
constructor(
|
||||
private val categoryRepository: CategoryRepository,
|
||||
) {
|
||||
suspend fun await(
|
||||
mangaId: Long,
|
||||
onError: suspend (Throwable) -> Unit = {},
|
||||
) = asFlow(mangaId)
|
||||
.catch {
|
||||
onError(it)
|
||||
log.warn(it) { "Failed to get categories for $mangaId" }
|
||||
}
|
||||
.singleOrNull()
|
||||
|
||||
suspend fun await(
|
||||
manga: Manga,
|
||||
onError: suspend (Throwable) -> Unit = {},
|
||||
) = asFlow(manga)
|
||||
.catch {
|
||||
onError(it)
|
||||
log.warn(it) { "Failed to get categories for ${manga.title}(${manga.id})" }
|
||||
}
|
||||
.singleOrNull()
|
||||
|
||||
fun asFlow(mangaId: Long) = categoryRepository.getMangaCategories(mangaId)
|
||||
|
||||
fun asFlow(manga: Manga) = categoryRepository.getMangaCategories(manga.id)
|
||||
|
||||
companion object {
|
||||
private val log = logging()
|
||||
@Inject
|
||||
class GetMangaCategories(
|
||||
private val categoryRepository: CategoryRepository,
|
||||
) {
|
||||
suspend fun await(
|
||||
mangaId: Long,
|
||||
onError: suspend (Throwable) -> Unit = {},
|
||||
) = asFlow(mangaId)
|
||||
.catch {
|
||||
onError(it)
|
||||
log.warn(it) { "Failed to get categories for $mangaId" }
|
||||
}
|
||||
.singleOrNull()
|
||||
|
||||
suspend fun await(
|
||||
manga: Manga,
|
||||
onError: suspend (Throwable) -> Unit = {},
|
||||
) = asFlow(manga)
|
||||
.catch {
|
||||
onError(it)
|
||||
log.warn(it) { "Failed to get categories for ${manga.title}(${manga.id})" }
|
||||
}
|
||||
.singleOrNull()
|
||||
|
||||
fun asFlow(mangaId: Long) = categoryRepository.getMangaCategories(mangaId)
|
||||
|
||||
fun asFlow(manga: Manga) = categoryRepository.getMangaCategories(manga.id)
|
||||
|
||||
companion object {
|
||||
private val log = logging()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,45 +15,44 @@ import kotlinx.coroutines.flow.take
|
||||
import me.tatarka.inject.annotations.Inject
|
||||
import org.lighthousegames.logging.logging
|
||||
|
||||
class GetMangaListFromCategory
|
||||
@Inject
|
||||
constructor(
|
||||
private val categoryRepository: CategoryRepository,
|
||||
private val serverListeners: ServerListeners,
|
||||
) {
|
||||
suspend fun await(
|
||||
categoryId: Long,
|
||||
onError: suspend (Throwable) -> Unit = {},
|
||||
) = asFlow(categoryId)
|
||||
.take(1)
|
||||
.catch {
|
||||
onError(it)
|
||||
log.warn(it) { "Failed to get manga list from category $categoryId" }
|
||||
}
|
||||
.singleOrNull()
|
||||
|
||||
suspend fun await(
|
||||
category: Category,
|
||||
onError: suspend (Throwable) -> Unit = {},
|
||||
) = asFlow(category)
|
||||
.take(1)
|
||||
.catch {
|
||||
onError(it)
|
||||
log.warn(it) { "Failed to get manga list from category ${category.name}" }
|
||||
}
|
||||
.singleOrNull()
|
||||
|
||||
fun asFlow(categoryId: Long) =
|
||||
serverListeners.combineCategoryManga(
|
||||
categoryRepository.getMangaFromCategory(categoryId),
|
||||
) { categoryId == it }
|
||||
|
||||
fun asFlow(category: Category) =
|
||||
serverListeners.combineCategoryManga(
|
||||
categoryRepository.getMangaFromCategory(category.id),
|
||||
) { category.id == it }
|
||||
|
||||
companion object {
|
||||
private val log = logging()
|
||||
@Inject
|
||||
class GetMangaListFromCategory(
|
||||
private val categoryRepository: CategoryRepository,
|
||||
private val serverListeners: ServerListeners,
|
||||
) {
|
||||
suspend fun await(
|
||||
categoryId: Long,
|
||||
onError: suspend (Throwable) -> Unit = {},
|
||||
) = asFlow(categoryId)
|
||||
.take(1)
|
||||
.catch {
|
||||
onError(it)
|
||||
log.warn(it) { "Failed to get manga list from category $categoryId" }
|
||||
}
|
||||
.singleOrNull()
|
||||
|
||||
suspend fun await(
|
||||
category: Category,
|
||||
onError: suspend (Throwable) -> Unit = {},
|
||||
) = asFlow(category)
|
||||
.take(1)
|
||||
.catch {
|
||||
onError(it)
|
||||
log.warn(it) { "Failed to get manga list from category ${category.name}" }
|
||||
}
|
||||
.singleOrNull()
|
||||
|
||||
fun asFlow(categoryId: Long) =
|
||||
serverListeners.combineCategoryManga(
|
||||
categoryRepository.getMangaFromCategory(categoryId),
|
||||
) { categoryId == it }
|
||||
|
||||
fun asFlow(category: Category) =
|
||||
serverListeners.combineCategoryManga(
|
||||
categoryRepository.getMangaFromCategory(category.id),
|
||||
) { category.id == it }
|
||||
|
||||
companion object {
|
||||
private val log = logging()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,52 +13,51 @@ import kotlinx.coroutines.flow.collect
|
||||
import me.tatarka.inject.annotations.Inject
|
||||
import org.lighthousegames.logging.logging
|
||||
|
||||
class ModifyCategory
|
||||
@Inject
|
||||
constructor(
|
||||
private val categoryRepository: CategoryRepository,
|
||||
) {
|
||||
suspend fun await(
|
||||
categoryId: Long,
|
||||
name: String,
|
||||
onError: suspend (Throwable) -> Unit = {},
|
||||
) = asFlow(
|
||||
categoryId = categoryId,
|
||||
name = name,
|
||||
).catch {
|
||||
onError(it)
|
||||
log.warn(it) { "Failed to modify category $categoryId with options: name=$name" }
|
||||
}.collect()
|
||||
@Inject
|
||||
class ModifyCategory(
|
||||
private val categoryRepository: CategoryRepository,
|
||||
) {
|
||||
suspend fun await(
|
||||
categoryId: Long,
|
||||
name: String,
|
||||
onError: suspend (Throwable) -> Unit = {},
|
||||
) = asFlow(
|
||||
categoryId = categoryId,
|
||||
name = name,
|
||||
).catch {
|
||||
onError(it)
|
||||
log.warn(it) { "Failed to modify category $categoryId with options: name=$name" }
|
||||
}.collect()
|
||||
|
||||
suspend fun await(
|
||||
category: Category,
|
||||
name: String? = null,
|
||||
onError: suspend (Throwable) -> Unit = {},
|
||||
) = asFlow(
|
||||
category = category,
|
||||
name = name,
|
||||
).catch {
|
||||
onError(it)
|
||||
log.warn(it) { "Failed to modify category ${category.name} with options: name=$name" }
|
||||
}.collect()
|
||||
suspend fun await(
|
||||
category: Category,
|
||||
name: String? = null,
|
||||
onError: suspend (Throwable) -> Unit = {},
|
||||
) = asFlow(
|
||||
category = category,
|
||||
name = name,
|
||||
).catch {
|
||||
onError(it)
|
||||
log.warn(it) { "Failed to modify category ${category.name} with options: name=$name" }
|
||||
}.collect()
|
||||
|
||||
fun asFlow(
|
||||
categoryId: Long,
|
||||
name: String,
|
||||
) = categoryRepository.modifyCategory(
|
||||
categoryId = categoryId,
|
||||
name = name,
|
||||
)
|
||||
fun asFlow(
|
||||
categoryId: Long,
|
||||
name: String,
|
||||
) = categoryRepository.modifyCategory(
|
||||
categoryId = categoryId,
|
||||
name = name,
|
||||
)
|
||||
|
||||
fun asFlow(
|
||||
category: Category,
|
||||
name: String? = null,
|
||||
) = categoryRepository.modifyCategory(
|
||||
categoryId = category.id,
|
||||
name = name ?: category.name,
|
||||
)
|
||||
fun asFlow(
|
||||
category: Category,
|
||||
name: String? = null,
|
||||
) = categoryRepository.modifyCategory(
|
||||
categoryId = category.id,
|
||||
name = name ?: category.name,
|
||||
)
|
||||
|
||||
companion object {
|
||||
private val log = logging()
|
||||
}
|
||||
companion object {
|
||||
private val log = logging()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,61 +17,60 @@ import kotlinx.coroutines.flow.map
|
||||
import me.tatarka.inject.annotations.Inject
|
||||
import org.lighthousegames.logging.logging
|
||||
|
||||
class RemoveMangaFromCategory
|
||||
@Inject
|
||||
constructor(
|
||||
private val categoryRepository: CategoryRepository,
|
||||
private val serverListeners: ServerListeners,
|
||||
) {
|
||||
suspend fun await(
|
||||
mangaId: Long,
|
||||
categoryId: Long,
|
||||
onError: suspend (Throwable) -> Unit = {},
|
||||
) = asFlow(mangaId, categoryId)
|
||||
.catch {
|
||||
onError(it)
|
||||
log.warn(it) { "Failed to remove $mangaId from category $categoryId" }
|
||||
}
|
||||
.collect()
|
||||
|
||||
suspend fun await(
|
||||
manga: Manga,
|
||||
category: Category,
|
||||
onError: suspend (Throwable) -> Unit = {},
|
||||
) = asFlow(manga, category)
|
||||
.catch {
|
||||
onError(it)
|
||||
log.warn(it) { "Failed to remove ${manga.title}(${manga.id}) from category ${category.name}" }
|
||||
}
|
||||
.collect()
|
||||
|
||||
fun asFlow(
|
||||
mangaId: Long,
|
||||
categoryId: Long,
|
||||
) = if (categoryId != 0L) {
|
||||
categoryRepository.removeMangaFromCategory(mangaId, categoryId)
|
||||
.map { serverListeners.updateCategoryManga(categoryId) }
|
||||
} else {
|
||||
flow {
|
||||
serverListeners.updateCategoryManga(categoryId)
|
||||
emit(Unit)
|
||||
}
|
||||
@Inject
|
||||
class RemoveMangaFromCategory(
|
||||
private val categoryRepository: CategoryRepository,
|
||||
private val serverListeners: ServerListeners,
|
||||
) {
|
||||
suspend fun await(
|
||||
mangaId: Long,
|
||||
categoryId: Long,
|
||||
onError: suspend (Throwable) -> Unit = {},
|
||||
) = asFlow(mangaId, categoryId)
|
||||
.catch {
|
||||
onError(it)
|
||||
log.warn(it) { "Failed to remove $mangaId from category $categoryId" }
|
||||
}
|
||||
.collect()
|
||||
|
||||
fun asFlow(
|
||||
manga: Manga,
|
||||
category: Category,
|
||||
) = if (category.id != 0L) {
|
||||
categoryRepository.removeMangaFromCategory(manga.id, category.id)
|
||||
.map { serverListeners.updateCategoryManga(category.id) }
|
||||
} else {
|
||||
flow {
|
||||
serverListeners.updateCategoryManga(category.id)
|
||||
emit(Unit)
|
||||
}
|
||||
suspend fun await(
|
||||
manga: Manga,
|
||||
category: Category,
|
||||
onError: suspend (Throwable) -> Unit = {},
|
||||
) = asFlow(manga, category)
|
||||
.catch {
|
||||
onError(it)
|
||||
log.warn(it) { "Failed to remove ${manga.title}(${manga.id}) from category ${category.name}" }
|
||||
}
|
||||
.collect()
|
||||
|
||||
companion object {
|
||||
private val log = logging()
|
||||
fun asFlow(
|
||||
mangaId: Long,
|
||||
categoryId: Long,
|
||||
) = if (categoryId != 0L) {
|
||||
categoryRepository.removeMangaFromCategory(mangaId, categoryId)
|
||||
.map { serverListeners.updateCategoryManga(categoryId) }
|
||||
} else {
|
||||
flow {
|
||||
serverListeners.updateCategoryManga(categoryId)
|
||||
emit(Unit)
|
||||
}
|
||||
}
|
||||
|
||||
fun asFlow(
|
||||
manga: Manga,
|
||||
category: Category,
|
||||
) = if (category.id != 0L) {
|
||||
categoryRepository.removeMangaFromCategory(manga.id, category.id)
|
||||
.map { serverListeners.updateCategoryManga(category.id) }
|
||||
} else {
|
||||
flow {
|
||||
serverListeners.updateCategoryManga(category.id)
|
||||
emit(Unit)
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
private val log = logging()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,28 +12,27 @@ import kotlinx.coroutines.flow.collect
|
||||
import me.tatarka.inject.annotations.Inject
|
||||
import org.lighthousegames.logging.logging
|
||||
|
||||
class ReorderCategory
|
||||
@Inject
|
||||
constructor(
|
||||
private val categoryRepository: CategoryRepository,
|
||||
) {
|
||||
suspend fun await(
|
||||
categoryId: Long,
|
||||
position: Int,
|
||||
onError: suspend (Throwable) -> Unit = {},
|
||||
) = asFlow(categoryId, position)
|
||||
.catch {
|
||||
onError(it)
|
||||
log.warn(it) { "Failed to move category $categoryId to $position" }
|
||||
}
|
||||
.collect()
|
||||
|
||||
fun asFlow(
|
||||
categoryId: Long,
|
||||
position: Int,
|
||||
) = categoryRepository.reorderCategory(categoryId, position)
|
||||
|
||||
companion object {
|
||||
private val log = logging()
|
||||
@Inject
|
||||
class ReorderCategory(
|
||||
private val categoryRepository: CategoryRepository,
|
||||
) {
|
||||
suspend fun await(
|
||||
categoryId: Long,
|
||||
position: Int,
|
||||
onError: suspend (Throwable) -> Unit = {},
|
||||
) = asFlow(categoryId, position)
|
||||
.catch {
|
||||
onError(it)
|
||||
log.warn(it) { "Failed to move category $categoryId to $position" }
|
||||
}
|
||||
.collect()
|
||||
|
||||
fun asFlow(
|
||||
categoryId: Long,
|
||||
position: Int,
|
||||
) = categoryRepository.reorderCategory(categoryId, position)
|
||||
|
||||
companion object {
|
||||
private val log = logging()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,37 +14,36 @@ import kotlinx.coroutines.flow.flow
|
||||
import me.tatarka.inject.annotations.Inject
|
||||
import org.lighthousegames.logging.logging
|
||||
|
||||
class UpdateCategoryMeta
|
||||
@Inject
|
||||
constructor(
|
||||
private val categoryRepository: CategoryRepository,
|
||||
) {
|
||||
suspend fun await(
|
||||
category: Category,
|
||||
example: Int = category.meta.example,
|
||||
onError: suspend (Throwable) -> Unit = {},
|
||||
) = asFlow(category, example)
|
||||
.catch {
|
||||
onError(it)
|
||||
log.warn(it) { "Failed to update ${category.name}(${category.id}) meta" }
|
||||
}
|
||||
.collect()
|
||||
|
||||
fun asFlow(
|
||||
category: Category,
|
||||
example: Int = category.meta.example,
|
||||
) = flow {
|
||||
if (example != category.meta.example) {
|
||||
categoryRepository.updateCategoryMeta(
|
||||
category.id,
|
||||
"example",
|
||||
example.toString(),
|
||||
).collect()
|
||||
}
|
||||
emit(Unit)
|
||||
@Inject
|
||||
class UpdateCategoryMeta(
|
||||
private val categoryRepository: CategoryRepository,
|
||||
) {
|
||||
suspend fun await(
|
||||
category: Category,
|
||||
example: Int = category.meta.example,
|
||||
onError: suspend (Throwable) -> Unit = {},
|
||||
) = asFlow(category, example)
|
||||
.catch {
|
||||
onError(it)
|
||||
log.warn(it) { "Failed to update ${category.name}(${category.id}) meta" }
|
||||
}
|
||||
.collect()
|
||||
|
||||
companion object {
|
||||
private val log = logging()
|
||||
fun asFlow(
|
||||
category: Category,
|
||||
example: Int = category.meta.example,
|
||||
) = flow {
|
||||
if (example != category.meta.example) {
|
||||
categoryRepository.updateCategoryMeta(
|
||||
category.id,
|
||||
"example",
|
||||
example.toString(),
|
||||
).collect()
|
||||
}
|
||||
emit(Unit)
|
||||
}
|
||||
|
||||
companion object {
|
||||
private val log = logging()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,73 +16,72 @@ import me.tatarka.inject.annotations.Inject
|
||||
import org.lighthousegames.logging.logging
|
||||
import kotlin.jvm.JvmName
|
||||
|
||||
class DeleteChapterDownload
|
||||
@Inject
|
||||
constructor(
|
||||
private val chapterRepository: ChapterRepository,
|
||||
private val serverListeners: ServerListeners,
|
||||
) {
|
||||
suspend fun await(
|
||||
chapterId: Long,
|
||||
onError: suspend (Throwable) -> Unit = {},
|
||||
) = asFlow(chapterId)
|
||||
.catch {
|
||||
onError(it)
|
||||
log.warn(it) { "Failed to delete chapter download for $chapterId" }
|
||||
}
|
||||
.collect()
|
||||
|
||||
@JvmName("awaitChapter")
|
||||
suspend fun await(
|
||||
chapter: Chapter,
|
||||
onError: suspend (Throwable) -> Unit = {},
|
||||
) = asFlow(chapter)
|
||||
.catch {
|
||||
onError(it)
|
||||
log.warn(it) { "Failed to delete chapter download for ${chapter.index} of ${chapter.mangaId}" }
|
||||
}
|
||||
.collect()
|
||||
|
||||
suspend fun await(
|
||||
chapterIds: List<Long>,
|
||||
onError: suspend (Throwable) -> Unit = {},
|
||||
) = asFlow(chapterIds)
|
||||
.catch {
|
||||
onError(it)
|
||||
log.warn(it) { "Failed to delete chapter download for $chapterIds" }
|
||||
}
|
||||
.collect()
|
||||
|
||||
@JvmName("awaitChapters")
|
||||
suspend fun await(
|
||||
chapters: List<Chapter>,
|
||||
onError: suspend (Throwable) -> Unit = {},
|
||||
) = asFlow(chapters)
|
||||
.catch {
|
||||
onError(it)
|
||||
log.warn(it) { "Failed to delete chapter download for ${chapters.joinToString { it.id.toString() }}" }
|
||||
}
|
||||
.collect()
|
||||
|
||||
fun asFlow(chapterId: Long) =
|
||||
chapterRepository.deleteDownloadedChapter(chapterId)
|
||||
.onEach { serverListeners.updateChapters(chapterId) }
|
||||
|
||||
@JvmName("asFlowChapter")
|
||||
fun asFlow(chapter: Chapter) =
|
||||
chapterRepository.deleteDownloadedChapter(chapter.id)
|
||||
.onEach { serverListeners.updateChapters(chapter.id) }
|
||||
|
||||
fun asFlow(chapterIds: List<Long>) =
|
||||
chapterRepository.deleteDownloadedChapters(chapterIds)
|
||||
.onEach { serverListeners.updateChapters(chapterIds) }
|
||||
|
||||
@JvmName("asFlowChapters")
|
||||
fun asFlow(chapter: List<Chapter>) =
|
||||
chapterRepository.deleteDownloadedChapters(chapter.map { it.id })
|
||||
.onEach { serverListeners.updateChapters(chapter.map { it.id }) }
|
||||
|
||||
companion object {
|
||||
private val log = logging()
|
||||
@Inject
|
||||
class DeleteChapterDownload(
|
||||
private val chapterRepository: ChapterRepository,
|
||||
private val serverListeners: ServerListeners,
|
||||
) {
|
||||
suspend fun await(
|
||||
chapterId: Long,
|
||||
onError: suspend (Throwable) -> Unit = {},
|
||||
) = asFlow(chapterId)
|
||||
.catch {
|
||||
onError(it)
|
||||
log.warn(it) { "Failed to delete chapter download for $chapterId" }
|
||||
}
|
||||
.collect()
|
||||
|
||||
@JvmName("awaitChapter")
|
||||
suspend fun await(
|
||||
chapter: Chapter,
|
||||
onError: suspend (Throwable) -> Unit = {},
|
||||
) = asFlow(chapter)
|
||||
.catch {
|
||||
onError(it)
|
||||
log.warn(it) { "Failed to delete chapter download for ${chapter.index} of ${chapter.mangaId}" }
|
||||
}
|
||||
.collect()
|
||||
|
||||
suspend fun await(
|
||||
chapterIds: List<Long>,
|
||||
onError: suspend (Throwable) -> Unit = {},
|
||||
) = asFlow(chapterIds)
|
||||
.catch {
|
||||
onError(it)
|
||||
log.warn(it) { "Failed to delete chapter download for $chapterIds" }
|
||||
}
|
||||
.collect()
|
||||
|
||||
@JvmName("awaitChapters")
|
||||
suspend fun await(
|
||||
chapters: List<Chapter>,
|
||||
onError: suspend (Throwable) -> Unit = {},
|
||||
) = asFlow(chapters)
|
||||
.catch {
|
||||
onError(it)
|
||||
log.warn(it) { "Failed to delete chapter download for ${chapters.joinToString { it.id.toString() }}" }
|
||||
}
|
||||
.collect()
|
||||
|
||||
fun asFlow(chapterId: Long) =
|
||||
chapterRepository.deleteDownloadedChapter(chapterId)
|
||||
.onEach { serverListeners.updateChapters(chapterId) }
|
||||
|
||||
@JvmName("asFlowChapter")
|
||||
fun asFlow(chapter: Chapter) =
|
||||
chapterRepository.deleteDownloadedChapter(chapter.id)
|
||||
.onEach { serverListeners.updateChapters(chapter.id) }
|
||||
|
||||
fun asFlow(chapterIds: List<Long>) =
|
||||
chapterRepository.deleteDownloadedChapters(chapterIds)
|
||||
.onEach { serverListeners.updateChapters(chapterIds) }
|
||||
|
||||
@JvmName("asFlowChapters")
|
||||
fun asFlow(chapter: List<Chapter>) =
|
||||
chapterRepository.deleteDownloadedChapters(chapter.map { it.id })
|
||||
.onEach { serverListeners.updateChapters(chapter.map { it.id }) }
|
||||
|
||||
companion object {
|
||||
private val log = logging()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,47 +15,46 @@ import kotlinx.coroutines.flow.take
|
||||
import me.tatarka.inject.annotations.Inject
|
||||
import org.lighthousegames.logging.logging
|
||||
|
||||
class GetChapter
|
||||
@Inject
|
||||
constructor(
|
||||
private val chapterRepository: ChapterRepository,
|
||||
private val serverListeners: ServerListeners,
|
||||
) {
|
||||
suspend fun await(
|
||||
chapterId: Long,
|
||||
onError: suspend (Throwable) -> Unit = {},
|
||||
) = asFlow(chapterId)
|
||||
.take(1)
|
||||
.catch {
|
||||
onError(it)
|
||||
log.warn(it) { "Failed to get chapter $chapterId" }
|
||||
}
|
||||
.singleOrNull()
|
||||
|
||||
suspend fun await(
|
||||
chapter: Chapter,
|
||||
onError: suspend (Throwable) -> Unit = {},
|
||||
) = asFlow(chapter)
|
||||
.take(1)
|
||||
.catch {
|
||||
onError(it)
|
||||
log.warn(it) { "Failed to get chapter ${chapter.index} for ${chapter.mangaId}" }
|
||||
}
|
||||
.singleOrNull()
|
||||
|
||||
fun asFlow(chapterId: Long) =
|
||||
serverListeners.combineChapters(
|
||||
chapterRepository.getChapter(chapterId),
|
||||
chapterIdPredate = { ids -> chapterId in ids },
|
||||
)
|
||||
|
||||
fun asFlow(chapter: Chapter) =
|
||||
serverListeners.combineChapters(
|
||||
chapterRepository.getChapter(chapter.id),
|
||||
chapterIdPredate = { ids -> chapter.id in ids },
|
||||
)
|
||||
|
||||
companion object {
|
||||
private val log = logging()
|
||||
@Inject
|
||||
class GetChapter(
|
||||
private val chapterRepository: ChapterRepository,
|
||||
private val serverListeners: ServerListeners,
|
||||
) {
|
||||
suspend fun await(
|
||||
chapterId: Long,
|
||||
onError: suspend (Throwable) -> Unit = {},
|
||||
) = asFlow(chapterId)
|
||||
.take(1)
|
||||
.catch {
|
||||
onError(it)
|
||||
log.warn(it) { "Failed to get chapter $chapterId" }
|
||||
}
|
||||
.singleOrNull()
|
||||
|
||||
suspend fun await(
|
||||
chapter: Chapter,
|
||||
onError: suspend (Throwable) -> Unit = {},
|
||||
) = asFlow(chapter)
|
||||
.take(1)
|
||||
.catch {
|
||||
onError(it)
|
||||
log.warn(it) { "Failed to get chapter ${chapter.index} for ${chapter.mangaId}" }
|
||||
}
|
||||
.singleOrNull()
|
||||
|
||||
fun asFlow(chapterId: Long) =
|
||||
serverListeners.combineChapters(
|
||||
chapterRepository.getChapter(chapterId),
|
||||
chapterIdPredate = { ids -> chapterId in ids },
|
||||
)
|
||||
|
||||
fun asFlow(chapter: Chapter) =
|
||||
serverListeners.combineChapters(
|
||||
chapterRepository.getChapter(chapter.id),
|
||||
chapterIdPredate = { ids -> chapter.id in ids },
|
||||
)
|
||||
|
||||
companion object {
|
||||
private val log = logging()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,40 +13,39 @@ import kotlinx.coroutines.flow.singleOrNull
|
||||
import me.tatarka.inject.annotations.Inject
|
||||
import org.lighthousegames.logging.logging
|
||||
|
||||
class GetChapterPages
|
||||
@Inject
|
||||
constructor(
|
||||
private val chapterRepository: ChapterRepository,
|
||||
) {
|
||||
suspend fun await(
|
||||
chapterId: Long,
|
||||
onError: suspend (Throwable) -> Unit = {},
|
||||
) = asFlow(chapterId)
|
||||
.catch {
|
||||
onError(it)
|
||||
log.warn(it) { "Failed to get pages for $chapterId" }
|
||||
}
|
||||
.singleOrNull()
|
||||
|
||||
suspend fun await(
|
||||
url: String,
|
||||
onError: suspend (Throwable) -> Unit = {},
|
||||
block: HttpRequestBuilder.() -> Unit,
|
||||
) = asFlow(url, block)
|
||||
.catch {
|
||||
onError(it)
|
||||
log.warn(it) { "Failed to get page $url" }
|
||||
}
|
||||
.singleOrNull()
|
||||
|
||||
fun asFlow(chapterId: Long) = chapterRepository.getPages(chapterId)
|
||||
|
||||
fun asFlow(
|
||||
url: String,
|
||||
block: HttpRequestBuilder.() -> Unit,
|
||||
) = chapterRepository.getPage(url, block)
|
||||
|
||||
companion object {
|
||||
private val log = logging()
|
||||
@Inject
|
||||
class GetChapterPages(
|
||||
private val chapterRepository: ChapterRepository,
|
||||
) {
|
||||
suspend fun await(
|
||||
chapterId: Long,
|
||||
onError: suspend (Throwable) -> Unit = {},
|
||||
) = asFlow(chapterId)
|
||||
.catch {
|
||||
onError(it)
|
||||
log.warn(it) { "Failed to get pages for $chapterId" }
|
||||
}
|
||||
.singleOrNull()
|
||||
|
||||
suspend fun await(
|
||||
url: String,
|
||||
onError: suspend (Throwable) -> Unit = {},
|
||||
block: HttpRequestBuilder.() -> Unit,
|
||||
) = asFlow(url, block)
|
||||
.catch {
|
||||
onError(it)
|
||||
log.warn(it) { "Failed to get page $url" }
|
||||
}
|
||||
.singleOrNull()
|
||||
|
||||
fun asFlow(chapterId: Long) = chapterRepository.getPages(chapterId)
|
||||
|
||||
fun asFlow(
|
||||
url: String,
|
||||
block: HttpRequestBuilder.() -> Unit,
|
||||
) = chapterRepository.getPage(url, block)
|
||||
|
||||
companion object {
|
||||
private val log = logging()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,47 +15,46 @@ import kotlinx.coroutines.flow.take
|
||||
import me.tatarka.inject.annotations.Inject
|
||||
import org.lighthousegames.logging.logging
|
||||
|
||||
class GetChapters
|
||||
@Inject
|
||||
constructor(
|
||||
private val chapterRepository: ChapterRepository,
|
||||
private val serverListeners: ServerListeners,
|
||||
) {
|
||||
suspend fun await(
|
||||
mangaId: Long,
|
||||
onError: suspend (Throwable) -> Unit = {},
|
||||
) = asFlow(mangaId)
|
||||
.take(1)
|
||||
.catch {
|
||||
onError(it)
|
||||
log.warn(it) { "Failed to get chapters for $mangaId" }
|
||||
}
|
||||
.singleOrNull()
|
||||
|
||||
suspend fun await(
|
||||
manga: Manga,
|
||||
onError: suspend (Throwable) -> Unit = {},
|
||||
) = asFlow(manga)
|
||||
.take(1)
|
||||
.catch {
|
||||
onError(it)
|
||||
log.warn(it) { "Failed to get chapters for ${manga.title}(${manga.id})" }
|
||||
}
|
||||
.singleOrNull()
|
||||
|
||||
fun asFlow(mangaId: Long) =
|
||||
serverListeners.combineChapters(
|
||||
chapterRepository.getChapters(mangaId),
|
||||
chapterIdPredate = { ids -> false }, // todo
|
||||
)
|
||||
|
||||
fun asFlow(manga: Manga) =
|
||||
serverListeners.combineChapters(
|
||||
chapterRepository.getChapters(manga.id),
|
||||
chapterIdPredate = { ids -> false }, // todo
|
||||
)
|
||||
|
||||
companion object {
|
||||
private val log = logging()
|
||||
@Inject
|
||||
class GetChapters(
|
||||
private val chapterRepository: ChapterRepository,
|
||||
private val serverListeners: ServerListeners,
|
||||
) {
|
||||
suspend fun await(
|
||||
mangaId: Long,
|
||||
onError: suspend (Throwable) -> Unit = {},
|
||||
) = asFlow(mangaId)
|
||||
.take(1)
|
||||
.catch {
|
||||
onError(it)
|
||||
log.warn(it) { "Failed to get chapters for $mangaId" }
|
||||
}
|
||||
.singleOrNull()
|
||||
|
||||
suspend fun await(
|
||||
manga: Manga,
|
||||
onError: suspend (Throwable) -> Unit = {},
|
||||
) = asFlow(manga)
|
||||
.take(1)
|
||||
.catch {
|
||||
onError(it)
|
||||
log.warn(it) { "Failed to get chapters for ${manga.title}(${manga.id})" }
|
||||
}
|
||||
.singleOrNull()
|
||||
|
||||
fun asFlow(mangaId: Long) =
|
||||
serverListeners.combineChapters(
|
||||
chapterRepository.getChapters(mangaId),
|
||||
chapterIdPredate = { ids -> false }, // todo
|
||||
)
|
||||
|
||||
fun asFlow(manga: Manga) =
|
||||
serverListeners.combineChapters(
|
||||
chapterRepository.getChapters(manga.id),
|
||||
chapterIdPredate = { ids -> false }, // todo
|
||||
)
|
||||
|
||||
companion object {
|
||||
private val log = logging()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,41 +15,40 @@ import kotlinx.coroutines.flow.singleOrNull
|
||||
import me.tatarka.inject.annotations.Inject
|
||||
import org.lighthousegames.logging.logging
|
||||
|
||||
class RefreshChapters
|
||||
@Inject
|
||||
constructor(
|
||||
private val chapterRepository: ChapterRepository,
|
||||
private val serverListeners: ServerListeners,
|
||||
) {
|
||||
suspend fun await(
|
||||
mangaId: Long,
|
||||
onError: suspend (Throwable) -> Unit = {},
|
||||
) = asFlow(mangaId)
|
||||
.catch {
|
||||
onError(it)
|
||||
log.warn(it) { "Failed to refresh chapters for $mangaId" }
|
||||
}
|
||||
.singleOrNull()
|
||||
|
||||
suspend fun await(
|
||||
manga: Manga,
|
||||
onError: suspend (Throwable) -> Unit = {},
|
||||
) = asFlow(manga)
|
||||
.catch {
|
||||
onError(it)
|
||||
log.warn(it) { "Failed to refresh chapters for ${manga.title}(${manga.id})" }
|
||||
}
|
||||
.singleOrNull()
|
||||
|
||||
fun asFlow(mangaId: Long) =
|
||||
chapterRepository.fetchChapters(mangaId)
|
||||
.onEach { serverListeners.updateChapters(mangaId) }
|
||||
|
||||
fun asFlow(manga: Manga) =
|
||||
chapterRepository.fetchChapters(manga.id)
|
||||
.onEach { serverListeners.updateChapters(manga.id) }
|
||||
|
||||
companion object {
|
||||
private val log = logging()
|
||||
@Inject
|
||||
class RefreshChapters(
|
||||
private val chapterRepository: ChapterRepository,
|
||||
private val serverListeners: ServerListeners,
|
||||
) {
|
||||
suspend fun await(
|
||||
mangaId: Long,
|
||||
onError: suspend (Throwable) -> Unit = {},
|
||||
) = asFlow(mangaId)
|
||||
.catch {
|
||||
onError(it)
|
||||
log.warn(it) { "Failed to refresh chapters for $mangaId" }
|
||||
}
|
||||
.singleOrNull()
|
||||
|
||||
suspend fun await(
|
||||
manga: Manga,
|
||||
onError: suspend (Throwable) -> Unit = {},
|
||||
) = asFlow(manga)
|
||||
.catch {
|
||||
onError(it)
|
||||
log.warn(it) { "Failed to refresh chapters for ${manga.title}(${manga.id})" }
|
||||
}
|
||||
.singleOrNull()
|
||||
|
||||
fun asFlow(mangaId: Long) =
|
||||
chapterRepository.fetchChapters(mangaId)
|
||||
.onEach { serverListeners.updateChapters(mangaId) }
|
||||
|
||||
fun asFlow(manga: Manga) =
|
||||
chapterRepository.fetchChapters(manga.id)
|
||||
.onEach { serverListeners.updateChapters(manga.id) }
|
||||
|
||||
companion object {
|
||||
private val log = logging()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,115 +16,114 @@ import me.tatarka.inject.annotations.Inject
|
||||
import org.lighthousegames.logging.logging
|
||||
import kotlin.jvm.JvmName
|
||||
|
||||
class UpdateChapter
|
||||
@Inject
|
||||
constructor(
|
||||
private val chapterRepository: ChapterRepository,
|
||||
private val serverListeners: ServerListeners,
|
||||
) {
|
||||
suspend fun await(
|
||||
chapterId: Long,
|
||||
bookmarked: Boolean? = null,
|
||||
read: Boolean? = null,
|
||||
lastPageRead: Int? = null,
|
||||
onError: suspend (Throwable) -> Unit = {},
|
||||
) = asFlow(chapterId, bookmarked, read, lastPageRead)
|
||||
.catch {
|
||||
onError(it)
|
||||
log.warn(it) { "Failed to update chapter bookmark for chapter $chapterId" }
|
||||
}
|
||||
.collect()
|
||||
|
||||
suspend fun await(
|
||||
chapter: Chapter,
|
||||
bookmarked: Boolean? = null,
|
||||
read: Boolean? = null,
|
||||
lastPageRead: Int? = null,
|
||||
onError: suspend (Throwable) -> Unit = {},
|
||||
) = asFlow(chapter, bookmarked, read, lastPageRead)
|
||||
.catch {
|
||||
onError(it)
|
||||
log.warn(it) { "Failed to update chapter bookmark for chapter ${chapter.index} of ${chapter.mangaId}" }
|
||||
}
|
||||
.collect()
|
||||
|
||||
suspend fun await(
|
||||
chapterIds: List<Long>,
|
||||
bookmarked: Boolean? = null,
|
||||
read: Boolean? = null,
|
||||
lastPageRead: Int? = null,
|
||||
onError: suspend (Throwable) -> Unit = {},
|
||||
) = asFlow(chapterIds, bookmarked, read, lastPageRead)
|
||||
.catch {
|
||||
onError(it)
|
||||
log.warn(it) { "Failed to update chapter bookmark for chapters $chapterIds" }
|
||||
}
|
||||
.collect()
|
||||
|
||||
@JvmName("awaitChapters")
|
||||
suspend fun await(
|
||||
chapters: List<Chapter>,
|
||||
bookmarked: Boolean? = null,
|
||||
read: Boolean? = null,
|
||||
lastPageRead: Int? = null,
|
||||
onError: suspend (Throwable) -> Unit = {},
|
||||
) = asFlow(chapters, bookmarked, read, lastPageRead)
|
||||
.catch {
|
||||
onError(it)
|
||||
log.warn(it) { "Failed to update chapter bookmark for chapters ${chapters.joinToString { it.id.toString() }}" }
|
||||
}
|
||||
.collect()
|
||||
|
||||
fun asFlow(
|
||||
chapterId: Long,
|
||||
bookmarked: Boolean? = null,
|
||||
read: Boolean? = null,
|
||||
lastPageRead: Int? = null,
|
||||
) = chapterRepository.updateChapter(
|
||||
chapterId = chapterId,
|
||||
bookmarked = bookmarked,
|
||||
read = read,
|
||||
lastPageRead = lastPageRead,
|
||||
).onEach { serverListeners.updateChapters(chapterId) }
|
||||
|
||||
fun asFlow(
|
||||
chapter: Chapter,
|
||||
bookmarked: Boolean? = null,
|
||||
read: Boolean? = null,
|
||||
lastPageRead: Int? = null,
|
||||
) = chapterRepository.updateChapter(
|
||||
chapterId = chapter.id,
|
||||
bookmarked = bookmarked,
|
||||
read = read,
|
||||
lastPageRead = lastPageRead,
|
||||
).onEach { serverListeners.updateChapters(chapter.id) }
|
||||
|
||||
fun asFlow(
|
||||
chapterIds: List<Long>,
|
||||
bookmarked: Boolean? = null,
|
||||
read: Boolean? = null,
|
||||
lastPageRead: Int? = null,
|
||||
) = chapterRepository.updateChapters(
|
||||
chapterIds = chapterIds,
|
||||
bookmarked = bookmarked,
|
||||
read = read,
|
||||
lastPageRead = lastPageRead,
|
||||
).onEach { serverListeners.updateChapters(chapterIds) }
|
||||
|
||||
@JvmName("asFlowChapters")
|
||||
fun asFlow(
|
||||
chapters: List<Chapter>,
|
||||
bookmarked: Boolean? = null,
|
||||
read: Boolean? = null,
|
||||
lastPageRead: Int? = null,
|
||||
) = chapterRepository.updateChapters(
|
||||
chapterIds = chapters.map { it.id },
|
||||
bookmarked = bookmarked,
|
||||
read = read,
|
||||
lastPageRead = lastPageRead,
|
||||
).onEach { serverListeners.updateChapters(chapters.map { it.id }) }
|
||||
|
||||
companion object {
|
||||
private val log = logging()
|
||||
@Inject
|
||||
class UpdateChapter(
|
||||
private val chapterRepository: ChapterRepository,
|
||||
private val serverListeners: ServerListeners,
|
||||
) {
|
||||
suspend fun await(
|
||||
chapterId: Long,
|
||||
bookmarked: Boolean? = null,
|
||||
read: Boolean? = null,
|
||||
lastPageRead: Int? = null,
|
||||
onError: suspend (Throwable) -> Unit = {},
|
||||
) = asFlow(chapterId, bookmarked, read, lastPageRead)
|
||||
.catch {
|
||||
onError(it)
|
||||
log.warn(it) { "Failed to update chapter bookmark for chapter $chapterId" }
|
||||
}
|
||||
.collect()
|
||||
|
||||
suspend fun await(
|
||||
chapter: Chapter,
|
||||
bookmarked: Boolean? = null,
|
||||
read: Boolean? = null,
|
||||
lastPageRead: Int? = null,
|
||||
onError: suspend (Throwable) -> Unit = {},
|
||||
) = asFlow(chapter, bookmarked, read, lastPageRead)
|
||||
.catch {
|
||||
onError(it)
|
||||
log.warn(it) { "Failed to update chapter bookmark for chapter ${chapter.index} of ${chapter.mangaId}" }
|
||||
}
|
||||
.collect()
|
||||
|
||||
suspend fun await(
|
||||
chapterIds: List<Long>,
|
||||
bookmarked: Boolean? = null,
|
||||
read: Boolean? = null,
|
||||
lastPageRead: Int? = null,
|
||||
onError: suspend (Throwable) -> Unit = {},
|
||||
) = asFlow(chapterIds, bookmarked, read, lastPageRead)
|
||||
.catch {
|
||||
onError(it)
|
||||
log.warn(it) { "Failed to update chapter bookmark for chapters $chapterIds" }
|
||||
}
|
||||
.collect()
|
||||
|
||||
@JvmName("awaitChapters")
|
||||
suspend fun await(
|
||||
chapters: List<Chapter>,
|
||||
bookmarked: Boolean? = null,
|
||||
read: Boolean? = null,
|
||||
lastPageRead: Int? = null,
|
||||
onError: suspend (Throwable) -> Unit = {},
|
||||
) = asFlow(chapters, bookmarked, read, lastPageRead)
|
||||
.catch {
|
||||
onError(it)
|
||||
log.warn(it) { "Failed to update chapter bookmark for chapters ${chapters.joinToString { it.id.toString() }}" }
|
||||
}
|
||||
.collect()
|
||||
|
||||
fun asFlow(
|
||||
chapterId: Long,
|
||||
bookmarked: Boolean? = null,
|
||||
read: Boolean? = null,
|
||||
lastPageRead: Int? = null,
|
||||
) = chapterRepository.updateChapter(
|
||||
chapterId = chapterId,
|
||||
bookmarked = bookmarked,
|
||||
read = read,
|
||||
lastPageRead = lastPageRead,
|
||||
).onEach { serverListeners.updateChapters(chapterId) }
|
||||
|
||||
fun asFlow(
|
||||
chapter: Chapter,
|
||||
bookmarked: Boolean? = null,
|
||||
read: Boolean? = null,
|
||||
lastPageRead: Int? = null,
|
||||
) = chapterRepository.updateChapter(
|
||||
chapterId = chapter.id,
|
||||
bookmarked = bookmarked,
|
||||
read = read,
|
||||
lastPageRead = lastPageRead,
|
||||
).onEach { serverListeners.updateChapters(chapter.id) }
|
||||
|
||||
fun asFlow(
|
||||
chapterIds: List<Long>,
|
||||
bookmarked: Boolean? = null,
|
||||
read: Boolean? = null,
|
||||
lastPageRead: Int? = null,
|
||||
) = chapterRepository.updateChapters(
|
||||
chapterIds = chapterIds,
|
||||
bookmarked = bookmarked,
|
||||
read = read,
|
||||
lastPageRead = lastPageRead,
|
||||
).onEach { serverListeners.updateChapters(chapterIds) }
|
||||
|
||||
@JvmName("asFlowChapters")
|
||||
fun asFlow(
|
||||
chapters: List<Chapter>,
|
||||
bookmarked: Boolean? = null,
|
||||
read: Boolean? = null,
|
||||
lastPageRead: Int? = null,
|
||||
) = chapterRepository.updateChapters(
|
||||
chapterIds = chapters.map { it.id },
|
||||
bookmarked = bookmarked,
|
||||
read = read,
|
||||
lastPageRead = lastPageRead,
|
||||
).onEach { serverListeners.updateChapters(chapters.map { it.id }) }
|
||||
|
||||
companion object {
|
||||
private val log = logging()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,51 +15,50 @@ import kotlinx.coroutines.flow.onEach
|
||||
import me.tatarka.inject.annotations.Inject
|
||||
import org.lighthousegames.logging.logging
|
||||
|
||||
class UpdateChapterLastPageRead
|
||||
@Inject
|
||||
constructor(
|
||||
private val chapterRepository: ChapterRepository,
|
||||
private val serverListeners: ServerListeners,
|
||||
) {
|
||||
suspend fun await(
|
||||
chapterId: Long,
|
||||
lastPageRead: Int,
|
||||
onError: suspend (Throwable) -> Unit = {},
|
||||
) = asFlow(chapterId, lastPageRead)
|
||||
.catch {
|
||||
onError(it)
|
||||
log.warn(it) { "Failed to update chapter last page read for chapter $chapterId" }
|
||||
}
|
||||
.collect()
|
||||
|
||||
suspend fun await(
|
||||
chapter: Chapter,
|
||||
lastPageRead: Int,
|
||||
onError: suspend (Throwable) -> Unit = {},
|
||||
) = asFlow(chapter, lastPageRead)
|
||||
.catch {
|
||||
onError(it)
|
||||
log.warn(it) { "Failed to update chapter last page read for chapter ${chapter.index} of ${chapter.mangaId}" }
|
||||
}
|
||||
.collect()
|
||||
|
||||
fun asFlow(
|
||||
chapterId: Long,
|
||||
lastPageRead: Int,
|
||||
) = chapterRepository.updateChapter(
|
||||
chapterId = chapterId,
|
||||
lastPageRead = lastPageRead,
|
||||
).onEach { serverListeners.updateChapters(chapterId) }
|
||||
|
||||
fun asFlow(
|
||||
chapter: Chapter,
|
||||
lastPageRead: Int,
|
||||
) = chapterRepository.updateChapter(
|
||||
chapterId = chapter.id,
|
||||
lastPageRead = lastPageRead,
|
||||
).onEach { serverListeners.updateChapters(chapter.id) }
|
||||
|
||||
companion object {
|
||||
private val log = logging()
|
||||
@Inject
|
||||
class UpdateChapterLastPageRead(
|
||||
private val chapterRepository: ChapterRepository,
|
||||
private val serverListeners: ServerListeners,
|
||||
) {
|
||||
suspend fun await(
|
||||
chapterId: Long,
|
||||
lastPageRead: Int,
|
||||
onError: suspend (Throwable) -> Unit = {},
|
||||
) = asFlow(chapterId, lastPageRead)
|
||||
.catch {
|
||||
onError(it)
|
||||
log.warn(it) { "Failed to update chapter last page read for chapter $chapterId" }
|
||||
}
|
||||
.collect()
|
||||
|
||||
suspend fun await(
|
||||
chapter: Chapter,
|
||||
lastPageRead: Int,
|
||||
onError: suspend (Throwable) -> Unit = {},
|
||||
) = asFlow(chapter, lastPageRead)
|
||||
.catch {
|
||||
onError(it)
|
||||
log.warn(it) { "Failed to update chapter last page read for chapter ${chapter.index} of ${chapter.mangaId}" }
|
||||
}
|
||||
.collect()
|
||||
|
||||
fun asFlow(
|
||||
chapterId: Long,
|
||||
lastPageRead: Int,
|
||||
) = chapterRepository.updateChapter(
|
||||
chapterId = chapterId,
|
||||
lastPageRead = lastPageRead,
|
||||
).onEach { serverListeners.updateChapters(chapterId) }
|
||||
|
||||
fun asFlow(
|
||||
chapter: Chapter,
|
||||
lastPageRead: Int,
|
||||
) = chapterRepository.updateChapter(
|
||||
chapterId = chapter.id,
|
||||
lastPageRead = lastPageRead,
|
||||
).onEach { serverListeners.updateChapters(chapter.id) }
|
||||
|
||||
companion object {
|
||||
private val log = logging()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,39 +15,38 @@ import kotlinx.coroutines.flow.flow
|
||||
import me.tatarka.inject.annotations.Inject
|
||||
import org.lighthousegames.logging.logging
|
||||
|
||||
class UpdateChapterMeta
|
||||
@Inject
|
||||
constructor(
|
||||
private val chapterRepository: ChapterRepository,
|
||||
private val serverListeners: ServerListeners,
|
||||
) {
|
||||
suspend fun await(
|
||||
chapter: Chapter,
|
||||
pageOffset: Int = chapter.meta.juiPageOffset,
|
||||
onError: suspend (Throwable) -> Unit = {},
|
||||
) = asFlow(chapter, pageOffset)
|
||||
.catch {
|
||||
onError(it)
|
||||
log.warn(it) { "Failed to update ${chapter.name}(${chapter.index}) meta" }
|
||||
}
|
||||
.collect()
|
||||
|
||||
fun asFlow(
|
||||
chapter: Chapter,
|
||||
pageOffset: Int = chapter.meta.juiPageOffset,
|
||||
) = flow {
|
||||
if (pageOffset != chapter.meta.juiPageOffset) {
|
||||
chapterRepository.updateChapterMeta(
|
||||
chapter.id,
|
||||
"juiPageOffset",
|
||||
pageOffset.toString(),
|
||||
).collect()
|
||||
serverListeners.updateChapters(chapter.id)
|
||||
}
|
||||
emit(Unit)
|
||||
@Inject
|
||||
class UpdateChapterMeta(
|
||||
private val chapterRepository: ChapterRepository,
|
||||
private val serverListeners: ServerListeners,
|
||||
) {
|
||||
suspend fun await(
|
||||
chapter: Chapter,
|
||||
pageOffset: Int = chapter.meta.juiPageOffset,
|
||||
onError: suspend (Throwable) -> Unit = {},
|
||||
) = asFlow(chapter, pageOffset)
|
||||
.catch {
|
||||
onError(it)
|
||||
log.warn(it) { "Failed to update ${chapter.name}(${chapter.index}) meta" }
|
||||
}
|
||||
.collect()
|
||||
|
||||
companion object {
|
||||
private val log = logging()
|
||||
fun asFlow(
|
||||
chapter: Chapter,
|
||||
pageOffset: Int = chapter.meta.juiPageOffset,
|
||||
) = flow {
|
||||
if (pageOffset != chapter.meta.juiPageOffset) {
|
||||
chapterRepository.updateChapterMeta(
|
||||
chapter.id,
|
||||
"juiPageOffset",
|
||||
pageOffset.toString(),
|
||||
).collect()
|
||||
serverListeners.updateChapters(chapter.id)
|
||||
}
|
||||
emit(Unit)
|
||||
}
|
||||
|
||||
companion object {
|
||||
private val log = logging()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,59 +15,58 @@ import kotlinx.coroutines.flow.onEach
|
||||
import me.tatarka.inject.annotations.Inject
|
||||
import org.lighthousegames.logging.logging
|
||||
|
||||
class UpdateChapterRead
|
||||
@Inject
|
||||
constructor(
|
||||
private val chapterRepository: ChapterRepository,
|
||||
private val serverListeners: ServerListeners,
|
||||
) {
|
||||
suspend fun await(
|
||||
chapterId: Long,
|
||||
read: Boolean,
|
||||
onError: suspend (Throwable) -> Unit = {},
|
||||
) = asFlow(chapterId, read)
|
||||
.catch {
|
||||
onError(it)
|
||||
log.warn(it) { "Failed to update chapter read status for chapter $chapterId" }
|
||||
}
|
||||
.collect()
|
||||
|
||||
suspend fun await(
|
||||
chapter: Chapter,
|
||||
read: Boolean,
|
||||
onError: suspend (Throwable) -> Unit = {},
|
||||
) = asFlow(chapter, read)
|
||||
.catch {
|
||||
onError(it)
|
||||
log.warn(it) { "Failed to update chapter read status for chapter ${chapter.index} of ${chapter.mangaId}" }
|
||||
}
|
||||
.collect()
|
||||
|
||||
fun asFlow(
|
||||
chapterId: Long,
|
||||
read: Boolean,
|
||||
) = chapterRepository.updateChapter(
|
||||
chapterId = chapterId,
|
||||
read = read,
|
||||
).onEach { serverListeners.updateChapters(chapterId) }
|
||||
|
||||
fun asFlow(
|
||||
chapterIds: List<Long>,
|
||||
read: Boolean,
|
||||
) = chapterRepository.updateChapters(
|
||||
chapterIds = chapterIds,
|
||||
read = read,
|
||||
).onEach { serverListeners.updateChapters(chapterIds) }
|
||||
|
||||
fun asFlow(
|
||||
chapter: Chapter,
|
||||
read: Boolean,
|
||||
) = chapterRepository.updateChapter(
|
||||
chapterId = chapter.id,
|
||||
read = read,
|
||||
).onEach { serverListeners.updateChapters(chapter.id) }
|
||||
|
||||
companion object {
|
||||
private val log = logging()
|
||||
@Inject
|
||||
class UpdateChapterRead(
|
||||
private val chapterRepository: ChapterRepository,
|
||||
private val serverListeners: ServerListeners,
|
||||
) {
|
||||
suspend fun await(
|
||||
chapterId: Long,
|
||||
read: Boolean,
|
||||
onError: suspend (Throwable) -> Unit = {},
|
||||
) = asFlow(chapterId, read)
|
||||
.catch {
|
||||
onError(it)
|
||||
log.warn(it) { "Failed to update chapter read status for chapter $chapterId" }
|
||||
}
|
||||
.collect()
|
||||
|
||||
suspend fun await(
|
||||
chapter: Chapter,
|
||||
read: Boolean,
|
||||
onError: suspend (Throwable) -> Unit = {},
|
||||
) = asFlow(chapter, read)
|
||||
.catch {
|
||||
onError(it)
|
||||
log.warn(it) { "Failed to update chapter read status for chapter ${chapter.index} of ${chapter.mangaId}" }
|
||||
}
|
||||
.collect()
|
||||
|
||||
fun asFlow(
|
||||
chapterId: Long,
|
||||
read: Boolean,
|
||||
) = chapterRepository.updateChapter(
|
||||
chapterId = chapterId,
|
||||
read = read,
|
||||
).onEach { serverListeners.updateChapters(chapterId) }
|
||||
|
||||
fun asFlow(
|
||||
chapterIds: List<Long>,
|
||||
read: Boolean,
|
||||
) = chapterRepository.updateChapters(
|
||||
chapterIds = chapterIds,
|
||||
read = read,
|
||||
).onEach { serverListeners.updateChapters(chapterIds) }
|
||||
|
||||
fun asFlow(
|
||||
chapter: Chapter,
|
||||
read: Boolean,
|
||||
) = chapterRepository.updateChapter(
|
||||
chapterId = chapter.id,
|
||||
read = read,
|
||||
).onEach { serverListeners.updateChapters(chapter.id) }
|
||||
|
||||
companion object {
|
||||
private val log = logging()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,36 +12,35 @@ import kotlinx.coroutines.flow.collect
|
||||
import me.tatarka.inject.annotations.Inject
|
||||
import org.lighthousegames.logging.logging
|
||||
|
||||
class BatchChapterDownload
|
||||
@Inject
|
||||
constructor(
|
||||
private val downloadRepository: DownloadRepository,
|
||||
) {
|
||||
suspend fun await(
|
||||
chapterIds: List<Long>,
|
||||
onError: suspend (Throwable) -> Unit = {},
|
||||
) = asFlow(chapterIds)
|
||||
.catch {
|
||||
onError(it)
|
||||
log.warn(it) { "Failed to queue chapters $chapterIds for a download" }
|
||||
}
|
||||
.collect()
|
||||
|
||||
suspend fun await(
|
||||
vararg chapterIds: Long,
|
||||
onError: suspend (Throwable) -> Unit = {},
|
||||
) = asFlow(*chapterIds)
|
||||
.catch {
|
||||
onError(it)
|
||||
log.warn(it) { "Failed to queue chapters ${chapterIds.asList()} for a download" }
|
||||
}
|
||||
.collect()
|
||||
|
||||
fun asFlow(chapterIds: List<Long>) = downloadRepository.batchDownload(chapterIds)
|
||||
|
||||
fun asFlow(vararg chapterIds: Long) = downloadRepository.batchDownload(chapterIds.asList())
|
||||
|
||||
companion object {
|
||||
private val log = logging()
|
||||
@Inject
|
||||
class BatchChapterDownload(
|
||||
private val downloadRepository: DownloadRepository,
|
||||
) {
|
||||
suspend fun await(
|
||||
chapterIds: List<Long>,
|
||||
onError: suspend (Throwable) -> Unit = {},
|
||||
) = asFlow(chapterIds)
|
||||
.catch {
|
||||
onError(it)
|
||||
log.warn(it) { "Failed to queue chapters $chapterIds for a download" }
|
||||
}
|
||||
.collect()
|
||||
|
||||
suspend fun await(
|
||||
vararg chapterIds: Long,
|
||||
onError: suspend (Throwable) -> Unit = {},
|
||||
) = asFlow(*chapterIds)
|
||||
.catch {
|
||||
onError(it)
|
||||
log.warn(it) { "Failed to queue chapters ${chapterIds.asList()} for a download" }
|
||||
}
|
||||
.collect()
|
||||
|
||||
fun asFlow(chapterIds: List<Long>) = downloadRepository.batchDownload(chapterIds)
|
||||
|
||||
fun asFlow(vararg chapterIds: Long) = downloadRepository.batchDownload(chapterIds.asList())
|
||||
|
||||
companion object {
|
||||
private val log = logging()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,22 +12,21 @@ import kotlinx.coroutines.flow.collect
|
||||
import me.tatarka.inject.annotations.Inject
|
||||
import org.lighthousegames.logging.logging
|
||||
|
||||
class ClearDownloadQueue
|
||||
@Inject
|
||||
constructor(
|
||||
private val downloadRepository: DownloadRepository,
|
||||
) {
|
||||
suspend fun await(onError: suspend (Throwable) -> Unit = {}) =
|
||||
asFlow()
|
||||
.catch {
|
||||
onError(it)
|
||||
log.warn(it) { "Failed to clear download queue" }
|
||||
}
|
||||
.collect()
|
||||
@Inject
|
||||
class ClearDownloadQueue(
|
||||
private val downloadRepository: DownloadRepository,
|
||||
) {
|
||||
suspend fun await(onError: suspend (Throwable) -> Unit = {}) =
|
||||
asFlow()
|
||||
.catch {
|
||||
onError(it)
|
||||
log.warn(it) { "Failed to clear download queue" }
|
||||
}
|
||||
.collect()
|
||||
|
||||
fun asFlow() = downloadRepository.clearDownloadQueue()
|
||||
fun asFlow() = downloadRepository.clearDownloadQueue()
|
||||
|
||||
companion object {
|
||||
private val log = logging()
|
||||
}
|
||||
companion object {
|
||||
private val log = logging()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,24 +12,23 @@ import kotlinx.coroutines.flow.collect
|
||||
import me.tatarka.inject.annotations.Inject
|
||||
import org.lighthousegames.logging.logging
|
||||
|
||||
class QueueChapterDownload
|
||||
@Inject
|
||||
constructor(
|
||||
private val downloadRepository: DownloadRepository,
|
||||
) {
|
||||
suspend fun await(
|
||||
chapterId: Long,
|
||||
onError: suspend (Throwable) -> Unit = {},
|
||||
) = asFlow(chapterId)
|
||||
.catch {
|
||||
onError(it)
|
||||
log.warn(it) { "Failed to queue chapter $chapterId for a download" }
|
||||
}
|
||||
.collect()
|
||||
|
||||
fun asFlow(chapterId: Long) = downloadRepository.queueChapterDownload(chapterId)
|
||||
|
||||
companion object {
|
||||
private val log = logging()
|
||||
@Inject
|
||||
class QueueChapterDownload(
|
||||
private val downloadRepository: DownloadRepository,
|
||||
) {
|
||||
suspend fun await(
|
||||
chapterId: Long,
|
||||
onError: suspend (Throwable) -> Unit = {},
|
||||
) = asFlow(chapterId)
|
||||
.catch {
|
||||
onError(it)
|
||||
log.warn(it) { "Failed to queue chapter $chapterId for a download" }
|
||||
}
|
||||
.collect()
|
||||
|
||||
fun asFlow(chapterId: Long) = downloadRepository.queueChapterDownload(chapterId)
|
||||
|
||||
companion object {
|
||||
private val log = logging()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,28 +12,27 @@ import kotlinx.coroutines.flow.collect
|
||||
import me.tatarka.inject.annotations.Inject
|
||||
import org.lighthousegames.logging.logging
|
||||
|
||||
class ReorderChapterDownload
|
||||
@Inject
|
||||
constructor(
|
||||
private val downloadRepository: DownloadRepository,
|
||||
) {
|
||||
suspend fun await(
|
||||
chapterId: Long,
|
||||
to: Int,
|
||||
onError: suspend (Throwable) -> Unit = {},
|
||||
) = asFlow(chapterId, to)
|
||||
.catch {
|
||||
onError(it)
|
||||
log.warn(it) { "Failed to reorder chapter download for $chapterId to $to" }
|
||||
}
|
||||
.collect()
|
||||
|
||||
fun asFlow(
|
||||
chapterId: Long,
|
||||
to: Int,
|
||||
) = downloadRepository.reorderChapterDownload(chapterId, to)
|
||||
|
||||
companion object {
|
||||
private val log = logging()
|
||||
@Inject
|
||||
class ReorderChapterDownload(
|
||||
private val downloadRepository: DownloadRepository,
|
||||
) {
|
||||
suspend fun await(
|
||||
chapterId: Long,
|
||||
to: Int,
|
||||
onError: suspend (Throwable) -> Unit = {},
|
||||
) = asFlow(chapterId, to)
|
||||
.catch {
|
||||
onError(it)
|
||||
log.warn(it) { "Failed to reorder chapter download for $chapterId to $to" }
|
||||
}
|
||||
.collect()
|
||||
|
||||
fun asFlow(
|
||||
chapterId: Long,
|
||||
to: Int,
|
||||
) = downloadRepository.reorderChapterDownload(chapterId, to)
|
||||
|
||||
companion object {
|
||||
private val log = logging()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,22 +12,21 @@ import kotlinx.coroutines.flow.collect
|
||||
import me.tatarka.inject.annotations.Inject
|
||||
import org.lighthousegames.logging.logging
|
||||
|
||||
class StartDownloading
|
||||
@Inject
|
||||
constructor(
|
||||
private val downloadRepository: DownloadRepository,
|
||||
) {
|
||||
suspend fun await(onError: suspend (Throwable) -> Unit = {}) =
|
||||
asFlow()
|
||||
.catch {
|
||||
onError(it)
|
||||
log.warn(it) { "Failed to start downloader" }
|
||||
}
|
||||
.collect()
|
||||
@Inject
|
||||
class StartDownloading(
|
||||
private val downloadRepository: DownloadRepository,
|
||||
) {
|
||||
suspend fun await(onError: suspend (Throwable) -> Unit = {}) =
|
||||
asFlow()
|
||||
.catch {
|
||||
onError(it)
|
||||
log.warn(it) { "Failed to start downloader" }
|
||||
}
|
||||
.collect()
|
||||
|
||||
fun asFlow() = downloadRepository.startDownloading()
|
||||
fun asFlow() = downloadRepository.startDownloading()
|
||||
|
||||
companion object {
|
||||
private val log = logging()
|
||||
}
|
||||
companion object {
|
||||
private val log = logging()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,24 +12,23 @@ import kotlinx.coroutines.flow.collect
|
||||
import me.tatarka.inject.annotations.Inject
|
||||
import org.lighthousegames.logging.logging
|
||||
|
||||
class StopChapterDownload
|
||||
@Inject
|
||||
constructor(
|
||||
private val downloadRepository: DownloadRepository,
|
||||
) {
|
||||
suspend fun await(
|
||||
chapterId: Long,
|
||||
onError: suspend (Throwable) -> Unit = {},
|
||||
) = asFlow(chapterId)
|
||||
.catch {
|
||||
onError(it)
|
||||
log.warn(it) { "Failed to stop chapter download for $chapterId" }
|
||||
}
|
||||
.collect()
|
||||
|
||||
fun asFlow(chapterId: Long) = downloadRepository.stopChapterDownload(chapterId)
|
||||
|
||||
companion object {
|
||||
private val log = logging()
|
||||
@Inject
|
||||
class StopChapterDownload(
|
||||
private val downloadRepository: DownloadRepository,
|
||||
) {
|
||||
suspend fun await(
|
||||
chapterId: Long,
|
||||
onError: suspend (Throwable) -> Unit = {},
|
||||
) = asFlow(chapterId)
|
||||
.catch {
|
||||
onError(it)
|
||||
log.warn(it) { "Failed to stop chapter download for $chapterId" }
|
||||
}
|
||||
.collect()
|
||||
|
||||
fun asFlow(chapterId: Long) = downloadRepository.stopChapterDownload(chapterId)
|
||||
|
||||
companion object {
|
||||
private val log = logging()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,22 +12,21 @@ import kotlinx.coroutines.flow.collect
|
||||
import me.tatarka.inject.annotations.Inject
|
||||
import org.lighthousegames.logging.logging
|
||||
|
||||
class StopDownloading
|
||||
@Inject
|
||||
constructor(
|
||||
private val downloadRepository: DownloadRepository,
|
||||
) {
|
||||
suspend fun await(onError: suspend (Throwable) -> Unit = {}) =
|
||||
asFlow()
|
||||
.catch {
|
||||
onError(it)
|
||||
log.warn(it) { "Failed to stop downloader" }
|
||||
}
|
||||
.collect()
|
||||
@Inject
|
||||
class StopDownloading(
|
||||
private val downloadRepository: DownloadRepository,
|
||||
) {
|
||||
suspend fun await(onError: suspend (Throwable) -> Unit = {}) =
|
||||
asFlow()
|
||||
.catch {
|
||||
onError(it)
|
||||
log.warn(it) { "Failed to stop downloader" }
|
||||
}
|
||||
.collect()
|
||||
|
||||
fun asFlow() = downloadRepository.stopDownloading()
|
||||
fun asFlow() = downloadRepository.stopDownloading()
|
||||
|
||||
companion object {
|
||||
private val log = logging()
|
||||
}
|
||||
companion object {
|
||||
private val log = logging()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,42 +16,40 @@ import io.ktor.websocket.Frame
|
||||
import io.ktor.websocket.readText
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
import kotlinx.coroutines.flow.map
|
||||
import kotlinx.serialization.decodeFromString
|
||||
import me.tatarka.inject.annotations.Inject
|
||||
|
||||
class DownloadService
|
||||
@Inject
|
||||
constructor(
|
||||
serverPreferences: ServerPreferences,
|
||||
client: Http,
|
||||
) : WebsocketService(serverPreferences, client) {
|
||||
override val _status: MutableStateFlow<Status>
|
||||
get() = status
|
||||
@Inject
|
||||
class DownloadService(
|
||||
serverPreferences: ServerPreferences,
|
||||
client: Http,
|
||||
) : WebsocketService(serverPreferences, client) {
|
||||
override val _status: MutableStateFlow<Status>
|
||||
get() = status
|
||||
|
||||
override val query: String
|
||||
get() = "/api/v1/downloads"
|
||||
override val query: String
|
||||
get() = "/api/v1/downloads"
|
||||
|
||||
override suspend fun onReceived(frame: Frame.Text) {
|
||||
val status = json.decodeFromString<DownloadStatus>(frame.readText())
|
||||
downloaderStatus.value = status.status
|
||||
downloadQueue.value = status.queue
|
||||
}
|
||||
|
||||
companion object {
|
||||
val status = MutableStateFlow(Status.STARTING)
|
||||
val downloadQueue = MutableStateFlow(emptyList<DownloadChapter>())
|
||||
val downloaderStatus = MutableStateFlow(DownloaderStatus.Stopped)
|
||||
|
||||
fun registerWatch(mangaId: Long) =
|
||||
downloadQueue
|
||||
.map {
|
||||
it.filter { it.mangaId == mangaId }
|
||||
}
|
||||
|
||||
fun registerWatches(mangaIds: Set<Long>) =
|
||||
downloadQueue
|
||||
.map {
|
||||
it.filter { it.mangaId in mangaIds }
|
||||
}
|
||||
}
|
||||
override suspend fun onReceived(frame: Frame.Text) {
|
||||
val status = json.decodeFromString<DownloadStatus>(frame.readText())
|
||||
downloaderStatus.value = status.status
|
||||
downloadQueue.value = status.queue
|
||||
}
|
||||
|
||||
companion object {
|
||||
val status = MutableStateFlow(Status.STARTING)
|
||||
val downloadQueue = MutableStateFlow(emptyList<DownloadChapter>())
|
||||
val downloaderStatus = MutableStateFlow(DownloaderStatus.Stopped)
|
||||
|
||||
fun registerWatch(mangaId: Long) =
|
||||
downloadQueue
|
||||
.map {
|
||||
it.filter { it.mangaId == mangaId }
|
||||
}
|
||||
|
||||
fun registerWatches(mangaIds: Set<Long>) =
|
||||
downloadQueue
|
||||
.map {
|
||||
it.filter { it.mangaId in mangaIds }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,22 +12,21 @@ import kotlinx.coroutines.flow.singleOrNull
|
||||
import me.tatarka.inject.annotations.Inject
|
||||
import org.lighthousegames.logging.logging
|
||||
|
||||
class GetExtensionList
|
||||
@Inject
|
||||
constructor(
|
||||
private val extensionRepository: ExtensionRepository,
|
||||
) {
|
||||
suspend fun await(onError: suspend (Throwable) -> Unit = {}) =
|
||||
asFlow()
|
||||
.catch {
|
||||
onError(it)
|
||||
log.warn(it) { "Failed to get extension list" }
|
||||
}
|
||||
.singleOrNull()
|
||||
@Inject
|
||||
class GetExtensionList(
|
||||
private val extensionRepository: ExtensionRepository,
|
||||
) {
|
||||
suspend fun await(onError: suspend (Throwable) -> Unit = {}) =
|
||||
asFlow()
|
||||
.catch {
|
||||
onError(it)
|
||||
log.warn(it) { "Failed to get extension list" }
|
||||
}
|
||||
.singleOrNull()
|
||||
|
||||
fun asFlow() = extensionRepository.getExtensionList()
|
||||
fun asFlow() = extensionRepository.getExtensionList()
|
||||
|
||||
companion object {
|
||||
private val log = logging()
|
||||
}
|
||||
companion object {
|
||||
private val log = logging()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,24 +13,23 @@ import kotlinx.coroutines.flow.collect
|
||||
import me.tatarka.inject.annotations.Inject
|
||||
import org.lighthousegames.logging.logging
|
||||
|
||||
class InstallExtension
|
||||
@Inject
|
||||
constructor(
|
||||
private val extensionRepository: ExtensionRepository,
|
||||
) {
|
||||
suspend fun await(
|
||||
extension: Extension,
|
||||
onError: suspend (Throwable) -> Unit = {},
|
||||
) = asFlow(extension)
|
||||
.catch {
|
||||
onError(it)
|
||||
log.warn(it) { "Failed to install extension ${extension.apkName}" }
|
||||
}
|
||||
.collect()
|
||||
|
||||
fun asFlow(extension: Extension) = extensionRepository.installExtension(extension.pkgName)
|
||||
|
||||
companion object {
|
||||
private val log = logging()
|
||||
@Inject
|
||||
class InstallExtension(
|
||||
private val extensionRepository: ExtensionRepository,
|
||||
) {
|
||||
suspend fun await(
|
||||
extension: Extension,
|
||||
onError: suspend (Throwable) -> Unit = {},
|
||||
) = asFlow(extension)
|
||||
.catch {
|
||||
onError(it)
|
||||
log.warn(it) { "Failed to install extension ${extension.apkName}" }
|
||||
}
|
||||
.collect()
|
||||
|
||||
fun asFlow(extension: Extension) = extensionRepository.installExtension(extension.pkgName)
|
||||
|
||||
companion object {
|
||||
private val log = logging()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,24 +15,23 @@ import okio.Path
|
||||
import okio.SYSTEM
|
||||
import org.lighthousegames.logging.logging
|
||||
|
||||
class InstallExtensionFile
|
||||
@Inject
|
||||
constructor(
|
||||
private val extensionRepository: ExtensionRepository,
|
||||
) {
|
||||
suspend fun await(
|
||||
path: Path,
|
||||
onError: suspend (Throwable) -> Unit = {},
|
||||
) = asFlow(path)
|
||||
.catch {
|
||||
onError(it)
|
||||
log.warn(it) { "Failed to install extension from $path" }
|
||||
}
|
||||
.collect()
|
||||
|
||||
fun asFlow(path: Path) = extensionRepository.installExtension(FileSystem.SYSTEM.source(path))
|
||||
|
||||
companion object {
|
||||
private val log = logging()
|
||||
@Inject
|
||||
class InstallExtensionFile(
|
||||
private val extensionRepository: ExtensionRepository,
|
||||
) {
|
||||
suspend fun await(
|
||||
path: Path,
|
||||
onError: suspend (Throwable) -> Unit = {},
|
||||
) = asFlow(path)
|
||||
.catch {
|
||||
onError(it)
|
||||
log.warn(it) { "Failed to install extension from $path" }
|
||||
}
|
||||
.collect()
|
||||
|
||||
fun asFlow(path: Path) = extensionRepository.installExtension(FileSystem.SYSTEM.source(path))
|
||||
|
||||
companion object {
|
||||
private val log = logging()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,24 +13,23 @@ import kotlinx.coroutines.flow.collect
|
||||
import me.tatarka.inject.annotations.Inject
|
||||
import org.lighthousegames.logging.logging
|
||||
|
||||
class UninstallExtension
|
||||
@Inject
|
||||
constructor(
|
||||
private val extensionRepository: ExtensionRepository,
|
||||
) {
|
||||
suspend fun await(
|
||||
extension: Extension,
|
||||
onError: suspend (Throwable) -> Unit = {},
|
||||
) = asFlow(extension)
|
||||
.catch {
|
||||
onError(it)
|
||||
log.warn(it) { "Failed to uninstall extension ${extension.apkName}" }
|
||||
}
|
||||
.collect()
|
||||
|
||||
fun asFlow(extension: Extension) = extensionRepository.uninstallExtension(extension.pkgName)
|
||||
|
||||
companion object {
|
||||
private val log = logging()
|
||||
@Inject
|
||||
class UninstallExtension(
|
||||
private val extensionRepository: ExtensionRepository,
|
||||
) {
|
||||
suspend fun await(
|
||||
extension: Extension,
|
||||
onError: suspend (Throwable) -> Unit = {},
|
||||
) = asFlow(extension)
|
||||
.catch {
|
||||
onError(it)
|
||||
log.warn(it) { "Failed to uninstall extension ${extension.apkName}" }
|
||||
}
|
||||
.collect()
|
||||
|
||||
fun asFlow(extension: Extension) = extensionRepository.uninstallExtension(extension.pkgName)
|
||||
|
||||
companion object {
|
||||
private val log = logging()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,24 +13,23 @@ import kotlinx.coroutines.flow.collect
|
||||
import me.tatarka.inject.annotations.Inject
|
||||
import org.lighthousegames.logging.logging
|
||||
|
||||
class UpdateExtension
|
||||
@Inject
|
||||
constructor(
|
||||
private val extensionRepository: ExtensionRepository,
|
||||
) {
|
||||
suspend fun await(
|
||||
extension: Extension,
|
||||
onError: suspend (Throwable) -> Unit = {},
|
||||
) = asFlow(extension)
|
||||
.catch {
|
||||
onError(it)
|
||||
log.warn(it) { "Failed to update extension ${extension.apkName}" }
|
||||
}
|
||||
.collect()
|
||||
|
||||
fun asFlow(extension: Extension) = extensionRepository.updateExtension(extension.pkgName)
|
||||
|
||||
companion object {
|
||||
private val log = logging()
|
||||
@Inject
|
||||
class UpdateExtension(
|
||||
private val extensionRepository: ExtensionRepository,
|
||||
) {
|
||||
suspend fun await(
|
||||
extension: Extension,
|
||||
onError: suspend (Throwable) -> Unit = {},
|
||||
) = asFlow(extension)
|
||||
.catch {
|
||||
onError(it)
|
||||
log.warn(it) { "Failed to update extension ${extension.apkName}" }
|
||||
}
|
||||
.collect()
|
||||
|
||||
fun asFlow(extension: Extension) = extensionRepository.updateExtension(extension.pkgName)
|
||||
|
||||
companion object {
|
||||
private val log = logging()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,22 +12,21 @@ import kotlinx.coroutines.flow.singleOrNull
|
||||
import me.tatarka.inject.annotations.Inject
|
||||
import org.lighthousegames.logging.logging
|
||||
|
||||
class GetGlobalMeta
|
||||
@Inject
|
||||
constructor(
|
||||
private val globalRepository: GlobalRepository,
|
||||
) {
|
||||
suspend fun await(onError: suspend (Throwable) -> Unit = {}) =
|
||||
asFlow()
|
||||
.catch {
|
||||
onError(it)
|
||||
log.warn(it) { "Failed to get global meta" }
|
||||
}
|
||||
.singleOrNull()
|
||||
@Inject
|
||||
class GetGlobalMeta(
|
||||
private val globalRepository: GlobalRepository,
|
||||
) {
|
||||
suspend fun await(onError: suspend (Throwable) -> Unit = {}) =
|
||||
asFlow()
|
||||
.catch {
|
||||
onError(it)
|
||||
log.warn(it) { "Failed to get global meta" }
|
||||
}
|
||||
.singleOrNull()
|
||||
|
||||
fun asFlow() = globalRepository.getGlobalMeta()
|
||||
fun asFlow() = globalRepository.getGlobalMeta()
|
||||
|
||||
companion object {
|
||||
private val log = logging()
|
||||
}
|
||||
companion object {
|
||||
private val log = logging()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,36 +14,35 @@ import kotlinx.coroutines.flow.flow
|
||||
import me.tatarka.inject.annotations.Inject
|
||||
import org.lighthousegames.logging.logging
|
||||
|
||||
class UpdateGlobalMeta
|
||||
@Inject
|
||||
constructor(
|
||||
private val globalRepository: GlobalRepository,
|
||||
) {
|
||||
suspend fun await(
|
||||
globalMeta: GlobalMeta,
|
||||
example: Int = globalMeta.example,
|
||||
onError: suspend (Throwable) -> Unit = {},
|
||||
) = asFlow(globalMeta, example)
|
||||
.catch {
|
||||
onError(it)
|
||||
log.warn(it) { "Failed to update global meta" }
|
||||
}
|
||||
.collect()
|
||||
|
||||
fun asFlow(
|
||||
globalMeta: GlobalMeta,
|
||||
example: Int = globalMeta.example,
|
||||
) = flow {
|
||||
if (example != globalMeta.example) {
|
||||
globalRepository.updateGlobalMeta(
|
||||
"example",
|
||||
example.toString(),
|
||||
).collect()
|
||||
}
|
||||
emit(Unit)
|
||||
@Inject
|
||||
class UpdateGlobalMeta(
|
||||
private val globalRepository: GlobalRepository,
|
||||
) {
|
||||
suspend fun await(
|
||||
globalMeta: GlobalMeta,
|
||||
example: Int = globalMeta.example,
|
||||
onError: suspend (Throwable) -> Unit = {},
|
||||
) = asFlow(globalMeta, example)
|
||||
.catch {
|
||||
onError(it)
|
||||
log.warn(it) { "Failed to update global meta" }
|
||||
}
|
||||
.collect()
|
||||
|
||||
companion object {
|
||||
private val log = logging()
|
||||
fun asFlow(
|
||||
globalMeta: GlobalMeta,
|
||||
example: Int = globalMeta.example,
|
||||
) = flow {
|
||||
if (example != globalMeta.example) {
|
||||
globalRepository.updateGlobalMeta(
|
||||
"example",
|
||||
example.toString(),
|
||||
).collect()
|
||||
}
|
||||
emit(Unit)
|
||||
}
|
||||
|
||||
companion object {
|
||||
private val log = logging()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,41 +15,40 @@ import kotlinx.coroutines.flow.singleOrNull
|
||||
import me.tatarka.inject.annotations.Inject
|
||||
import org.lighthousegames.logging.logging
|
||||
|
||||
class AddMangaToLibrary
|
||||
@Inject
|
||||
constructor(
|
||||
private val libraryRepository: LibraryRepository,
|
||||
private val serverListeners: ServerListeners,
|
||||
) {
|
||||
suspend fun await(
|
||||
mangaId: Long,
|
||||
onError: suspend (Throwable) -> Unit = {},
|
||||
) = asFlow(mangaId)
|
||||
.catch {
|
||||
onError(it)
|
||||
log.warn(it) { "Failed to add $mangaId to library" }
|
||||
}
|
||||
.singleOrNull()
|
||||
|
||||
suspend fun await(
|
||||
manga: Manga,
|
||||
onError: suspend (Throwable) -> Unit = {},
|
||||
) = asFlow(manga)
|
||||
.catch {
|
||||
onError(it)
|
||||
log.warn(it) { "Failed to add ${manga.title}(${manga.id}) to library" }
|
||||
}
|
||||
.singleOrNull()
|
||||
|
||||
fun asFlow(mangaId: Long) =
|
||||
libraryRepository.addMangaToLibrary(mangaId)
|
||||
.onEach { serverListeners.updateManga(mangaId) }
|
||||
|
||||
fun asFlow(manga: Manga) =
|
||||
libraryRepository.addMangaToLibrary(manga.id)
|
||||
.onEach { serverListeners.updateManga(manga.id) }
|
||||
|
||||
companion object {
|
||||
private val log = logging()
|
||||
@Inject
|
||||
class AddMangaToLibrary(
|
||||
private val libraryRepository: LibraryRepository,
|
||||
private val serverListeners: ServerListeners,
|
||||
) {
|
||||
suspend fun await(
|
||||
mangaId: Long,
|
||||
onError: suspend (Throwable) -> Unit = {},
|
||||
) = asFlow(mangaId)
|
||||
.catch {
|
||||
onError(it)
|
||||
log.warn(it) { "Failed to add $mangaId to library" }
|
||||
}
|
||||
.singleOrNull()
|
||||
|
||||
suspend fun await(
|
||||
manga: Manga,
|
||||
onError: suspend (Throwable) -> Unit = {},
|
||||
) = asFlow(manga)
|
||||
.catch {
|
||||
onError(it)
|
||||
log.warn(it) { "Failed to add ${manga.title}(${manga.id}) to library" }
|
||||
}
|
||||
.singleOrNull()
|
||||
|
||||
fun asFlow(mangaId: Long) =
|
||||
libraryRepository.addMangaToLibrary(mangaId)
|
||||
.onEach { serverListeners.updateManga(mangaId) }
|
||||
|
||||
fun asFlow(manga: Manga) =
|
||||
libraryRepository.addMangaToLibrary(manga.id)
|
||||
.onEach { serverListeners.updateManga(manga.id) }
|
||||
|
||||
companion object {
|
||||
private val log = logging()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,41 +15,40 @@ import kotlinx.coroutines.flow.singleOrNull
|
||||
import me.tatarka.inject.annotations.Inject
|
||||
import org.lighthousegames.logging.logging
|
||||
|
||||
class RemoveMangaFromLibrary
|
||||
@Inject
|
||||
constructor(
|
||||
private val libraryRepository: LibraryRepository,
|
||||
private val serverListeners: ServerListeners,
|
||||
) {
|
||||
suspend fun await(
|
||||
mangaId: Long,
|
||||
onError: suspend (Throwable) -> Unit = {},
|
||||
) = asFlow(mangaId)
|
||||
.catch {
|
||||
onError(it)
|
||||
log.warn(it) { "Failed to remove $mangaId from library" }
|
||||
}
|
||||
.singleOrNull()
|
||||
|
||||
suspend fun await(
|
||||
manga: Manga,
|
||||
onError: suspend (Throwable) -> Unit = {},
|
||||
) = asFlow(manga)
|
||||
.catch {
|
||||
onError(it)
|
||||
log.warn(it) { "Failed to remove ${manga.title}(${manga.id}) from library" }
|
||||
}
|
||||
.singleOrNull()
|
||||
|
||||
fun asFlow(mangaId: Long) =
|
||||
libraryRepository.removeMangaFromLibrary(mangaId)
|
||||
.onEach { serverListeners.updateManga(mangaId) }
|
||||
|
||||
fun asFlow(manga: Manga) =
|
||||
libraryRepository.removeMangaFromLibrary(manga.id)
|
||||
.onEach { serverListeners.updateManga(manga.id) }
|
||||
|
||||
companion object {
|
||||
private val log = logging()
|
||||
@Inject
|
||||
class RemoveMangaFromLibrary(
|
||||
private val libraryRepository: LibraryRepository,
|
||||
private val serverListeners: ServerListeners,
|
||||
) {
|
||||
suspend fun await(
|
||||
mangaId: Long,
|
||||
onError: suspend (Throwable) -> Unit = {},
|
||||
) = asFlow(mangaId)
|
||||
.catch {
|
||||
onError(it)
|
||||
log.warn(it) { "Failed to remove $mangaId from library" }
|
||||
}
|
||||
.singleOrNull()
|
||||
|
||||
suspend fun await(
|
||||
manga: Manga,
|
||||
onError: suspend (Throwable) -> Unit = {},
|
||||
) = asFlow(manga)
|
||||
.catch {
|
||||
onError(it)
|
||||
log.warn(it) { "Failed to remove ${manga.title}(${manga.id}) from library" }
|
||||
}
|
||||
.singleOrNull()
|
||||
|
||||
fun asFlow(mangaId: Long) =
|
||||
libraryRepository.removeMangaFromLibrary(mangaId)
|
||||
.onEach { serverListeners.updateManga(mangaId) }
|
||||
|
||||
fun asFlow(manga: Manga) =
|
||||
libraryRepository.removeMangaFromLibrary(manga.id)
|
||||
.onEach { serverListeners.updateManga(manga.id) }
|
||||
|
||||
companion object {
|
||||
private val log = logging()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,26 +16,25 @@ import kotlinx.coroutines.flow.MutableStateFlow
|
||||
import me.tatarka.inject.annotations.Inject
|
||||
import org.lighthousegames.logging.logging
|
||||
|
||||
class LibraryUpdateService
|
||||
@Inject
|
||||
constructor(
|
||||
serverPreferences: ServerPreferences,
|
||||
client: Http,
|
||||
) : WebsocketService(serverPreferences, client) {
|
||||
override val _status: MutableStateFlow<Status>
|
||||
get() = status
|
||||
@Inject
|
||||
class LibraryUpdateService(
|
||||
serverPreferences: ServerPreferences,
|
||||
client: Http,
|
||||
) : WebsocketService(serverPreferences, client) {
|
||||
override val _status: MutableStateFlow<Status>
|
||||
get() = status
|
||||
|
||||
override val query: String
|
||||
get() = "/api/v1/update"
|
||||
override val query: String
|
||||
get() = "/api/v1/update"
|
||||
|
||||
override suspend fun onReceived(frame: Frame.Text) {
|
||||
updateStatus.value = json.decodeFromString<UpdateStatus>(frame.readText())
|
||||
}
|
||||
|
||||
companion object {
|
||||
private val log = logging()
|
||||
|
||||
val status = MutableStateFlow(Status.STARTING)
|
||||
val updateStatus = MutableStateFlow(UpdateStatus(emptyMap(), emptyMap(), false))
|
||||
}
|
||||
override suspend fun onReceived(frame: Frame.Text) {
|
||||
updateStatus.value = json.decodeFromString<UpdateStatus>(frame.readText())
|
||||
}
|
||||
|
||||
companion object {
|
||||
private val log = logging()
|
||||
|
||||
val status = MutableStateFlow(Status.STARTING)
|
||||
val updateStatus = MutableStateFlow(UpdateStatus(emptyMap(), emptyMap(), false))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,45 +15,44 @@ import kotlinx.coroutines.flow.take
|
||||
import me.tatarka.inject.annotations.Inject
|
||||
import org.lighthousegames.logging.logging
|
||||
|
||||
class GetManga
|
||||
@Inject
|
||||
constructor(
|
||||
private val mangaRepository: MangaRepository,
|
||||
private val serverListeners: ServerListeners,
|
||||
) {
|
||||
suspend fun await(
|
||||
mangaId: Long,
|
||||
onError: suspend (Throwable) -> Unit = {},
|
||||
) = asFlow(mangaId)
|
||||
.take(1)
|
||||
.catch {
|
||||
onError(it)
|
||||
log.warn(it) { "Failed to get manga $mangaId" }
|
||||
}
|
||||
.singleOrNull()
|
||||
|
||||
suspend fun await(
|
||||
manga: Manga,
|
||||
onError: suspend (Throwable) -> Unit = {},
|
||||
) = asFlow(manga)
|
||||
.take(1)
|
||||
.catch {
|
||||
onError(it)
|
||||
log.warn(it) { "Failed to get manga ${manga.title}(${manga.id})" }
|
||||
}
|
||||
.singleOrNull()
|
||||
|
||||
fun asFlow(mangaId: Long) =
|
||||
serverListeners.combineMangaUpdates(
|
||||
mangaRepository.getManga(mangaId),
|
||||
) { mangaId in it }
|
||||
|
||||
fun asFlow(manga: Manga) =
|
||||
serverListeners.combineMangaUpdates(
|
||||
mangaRepository.getManga(manga.id),
|
||||
) { manga.id in it }
|
||||
|
||||
companion object {
|
||||
private val log = logging()
|
||||
@Inject
|
||||
class GetManga(
|
||||
private val mangaRepository: MangaRepository,
|
||||
private val serverListeners: ServerListeners,
|
||||
) {
|
||||
suspend fun await(
|
||||
mangaId: Long,
|
||||
onError: suspend (Throwable) -> Unit = {},
|
||||
) = asFlow(mangaId)
|
||||
.take(1)
|
||||
.catch {
|
||||
onError(it)
|
||||
log.warn(it) { "Failed to get manga $mangaId" }
|
||||
}
|
||||
.singleOrNull()
|
||||
|
||||
suspend fun await(
|
||||
manga: Manga,
|
||||
onError: suspend (Throwable) -> Unit = {},
|
||||
) = asFlow(manga)
|
||||
.take(1)
|
||||
.catch {
|
||||
onError(it)
|
||||
log.warn(it) { "Failed to get manga ${manga.title}(${manga.id})" }
|
||||
}
|
||||
.singleOrNull()
|
||||
|
||||
fun asFlow(mangaId: Long) =
|
||||
serverListeners.combineMangaUpdates(
|
||||
mangaRepository.getManga(mangaId),
|
||||
) { mangaId in it }
|
||||
|
||||
fun asFlow(manga: Manga) =
|
||||
serverListeners.combineMangaUpdates(
|
||||
mangaRepository.getManga(manga.id),
|
||||
) { manga.id in it }
|
||||
|
||||
companion object {
|
||||
private val log = logging()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,39 +16,38 @@ import kotlinx.coroutines.flow.take
|
||||
import me.tatarka.inject.annotations.Inject
|
||||
import org.lighthousegames.logging.logging
|
||||
|
||||
class RefreshManga
|
||||
@Inject
|
||||
constructor(
|
||||
private val mangaRepository: MangaRepository,
|
||||
private val serverListeners: ServerListeners,
|
||||
) {
|
||||
suspend fun await(
|
||||
mangaId: Long,
|
||||
onError: suspend (Throwable) -> Unit = {},
|
||||
) = asFlow(mangaId)
|
||||
.take(1)
|
||||
.catch {
|
||||
onError(it)
|
||||
log.warn(it) { "Failed to refresh manga $mangaId" }
|
||||
}
|
||||
.singleOrNull()
|
||||
|
||||
suspend fun await(
|
||||
manga: Manga,
|
||||
onError: suspend (Throwable) -> Unit = {},
|
||||
) = asFlow(manga)
|
||||
.take(1)
|
||||
.catch {
|
||||
onError(it)
|
||||
log.warn(it) { "Failed to refresh manga ${manga.title}(${manga.id})" }
|
||||
}
|
||||
.singleOrNull()
|
||||
|
||||
fun asFlow(mangaId: Long) = mangaRepository.refreshManga(mangaId).onEach { serverListeners.updateManga(mangaId) }
|
||||
|
||||
fun asFlow(manga: Manga) = mangaRepository.refreshManga(manga.id).onEach { serverListeners.updateManga(manga.id) }
|
||||
|
||||
companion object {
|
||||
private val log = logging()
|
||||
@Inject
|
||||
class RefreshManga(
|
||||
private val mangaRepository: MangaRepository,
|
||||
private val serverListeners: ServerListeners,
|
||||
) {
|
||||
suspend fun await(
|
||||
mangaId: Long,
|
||||
onError: suspend (Throwable) -> Unit = {},
|
||||
) = asFlow(mangaId)
|
||||
.take(1)
|
||||
.catch {
|
||||
onError(it)
|
||||
log.warn(it) { "Failed to refresh manga $mangaId" }
|
||||
}
|
||||
.singleOrNull()
|
||||
|
||||
suspend fun await(
|
||||
manga: Manga,
|
||||
onError: suspend (Throwable) -> Unit = {},
|
||||
) = asFlow(manga)
|
||||
.take(1)
|
||||
.catch {
|
||||
onError(it)
|
||||
log.warn(it) { "Failed to refresh manga ${manga.title}(${manga.id})" }
|
||||
}
|
||||
.singleOrNull()
|
||||
|
||||
fun asFlow(mangaId: Long) = mangaRepository.refreshManga(mangaId).onEach { serverListeners.updateManga(mangaId) }
|
||||
|
||||
fun asFlow(manga: Manga) = mangaRepository.refreshManga(manga.id).onEach { serverListeners.updateManga(manga.id) }
|
||||
|
||||
companion object {
|
||||
private val log = logging()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,39 +17,38 @@ import kotlinx.coroutines.flow.flow
|
||||
import me.tatarka.inject.annotations.Inject
|
||||
import org.lighthousegames.logging.logging
|
||||
|
||||
class UpdateMangaMeta
|
||||
@Inject
|
||||
constructor(
|
||||
private val mangaRepository: MangaRepository,
|
||||
private val serverListeners: ServerListeners,
|
||||
) {
|
||||
suspend fun await(
|
||||
manga: Manga,
|
||||
readerMode: String = manga.meta.juiReaderMode,
|
||||
onError: suspend (Throwable) -> Unit = {},
|
||||
) = asFlow(manga, readerMode)
|
||||
.catch {
|
||||
onError(it)
|
||||
log.warn(it) { "Failed to update ${manga.title}(${manga.id}) meta" }
|
||||
}
|
||||
.collect()
|
||||
|
||||
fun asFlow(
|
||||
manga: Manga,
|
||||
readerMode: String = manga.meta.juiReaderMode.decodeURLQueryComponent(),
|
||||
) = flow {
|
||||
if (readerMode.encodeURLQueryComponent() != manga.meta.juiReaderMode) {
|
||||
mangaRepository.updateMangaMeta(
|
||||
manga.id,
|
||||
"juiReaderMode",
|
||||
readerMode,
|
||||
).collect()
|
||||
serverListeners.updateManga(manga.id)
|
||||
}
|
||||
emit(Unit)
|
||||
@Inject
|
||||
class UpdateMangaMeta(
|
||||
private val mangaRepository: MangaRepository,
|
||||
private val serverListeners: ServerListeners,
|
||||
) {
|
||||
suspend fun await(
|
||||
manga: Manga,
|
||||
readerMode: String = manga.meta.juiReaderMode,
|
||||
onError: suspend (Throwable) -> Unit = {},
|
||||
) = asFlow(manga, readerMode)
|
||||
.catch {
|
||||
onError(it)
|
||||
log.warn(it) { "Failed to update ${manga.title}(${manga.id}) meta" }
|
||||
}
|
||||
.collect()
|
||||
|
||||
companion object {
|
||||
private val log = logging()
|
||||
fun asFlow(
|
||||
manga: Manga,
|
||||
readerMode: String = manga.meta.juiReaderMode.decodeURLQueryComponent(),
|
||||
) = flow {
|
||||
if (readerMode.encodeURLQueryComponent() != manga.meta.juiReaderMode) {
|
||||
mangaRepository.updateMangaMeta(
|
||||
manga.id,
|
||||
"juiReaderMode",
|
||||
readerMode,
|
||||
).collect()
|
||||
serverListeners.updateManga(manga.id)
|
||||
}
|
||||
emit(Unit)
|
||||
}
|
||||
|
||||
companion object {
|
||||
private val log = logging()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,20 +11,19 @@ import ca.gosyer.jui.domain.migration.service.MigrationPreferences
|
||||
import ca.gosyer.jui.domain.reader.service.ReaderPreferences
|
||||
import me.tatarka.inject.annotations.Inject
|
||||
|
||||
class RunMigrations
|
||||
@Inject
|
||||
constructor(
|
||||
private val migrationPreferences: MigrationPreferences,
|
||||
private val readerPreferences: ReaderPreferences,
|
||||
) {
|
||||
fun runMigrations() {
|
||||
val code = migrationPreferences.version().get()
|
||||
if (code <= 0) {
|
||||
readerPreferences.modes().get().forEach {
|
||||
readerPreferences.getMode(it).direction().delete()
|
||||
}
|
||||
migrationPreferences.version().set(BuildKonfig.MIGRATION_CODE)
|
||||
return
|
||||
@Inject
|
||||
class RunMigrations(
|
||||
private val migrationPreferences: MigrationPreferences,
|
||||
private val readerPreferences: ReaderPreferences,
|
||||
) {
|
||||
fun runMigrations() {
|
||||
val code = migrationPreferences.version().get()
|
||||
if (code <= 0) {
|
||||
readerPreferences.modes().get().forEach {
|
||||
readerPreferences.getMode(it).direction().delete()
|
||||
}
|
||||
migrationPreferences.version().set(BuildKonfig.MIGRATION_CODE)
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,22 +12,21 @@ import kotlinx.coroutines.flow.singleOrNull
|
||||
import me.tatarka.inject.annotations.Inject
|
||||
import org.lighthousegames.logging.logging
|
||||
|
||||
class AboutServer
|
||||
@Inject
|
||||
constructor(
|
||||
private val settingsRepository: SettingsRepository,
|
||||
) {
|
||||
suspend fun await(onError: suspend (Throwable) -> Unit = {}) =
|
||||
asFlow()
|
||||
.catch {
|
||||
onError(it)
|
||||
log.warn(it) { "Failed to get server information" }
|
||||
}
|
||||
.singleOrNull()
|
||||
@Inject
|
||||
class AboutServer(
|
||||
private val settingsRepository: SettingsRepository,
|
||||
) {
|
||||
suspend fun await(onError: suspend (Throwable) -> Unit = {}) =
|
||||
asFlow()
|
||||
.catch {
|
||||
onError(it)
|
||||
log.warn(it) { "Failed to get server information" }
|
||||
}
|
||||
.singleOrNull()
|
||||
|
||||
fun asFlow() = settingsRepository.aboutServer()
|
||||
fun asFlow() = settingsRepository.aboutServer()
|
||||
|
||||
companion object {
|
||||
private val log = logging()
|
||||
}
|
||||
companion object {
|
||||
private val log = logging()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,22 +12,21 @@ import kotlinx.coroutines.flow.singleOrNull
|
||||
import me.tatarka.inject.annotations.Inject
|
||||
import org.lighthousegames.logging.logging
|
||||
|
||||
class GetSettings
|
||||
@Inject
|
||||
constructor(
|
||||
private val settingsRepository: SettingsRepository,
|
||||
) {
|
||||
suspend fun await(onError: suspend (Throwable) -> Unit = {}) =
|
||||
asFlow()
|
||||
.catch {
|
||||
onError(it)
|
||||
log.warn(it) { "Failed to check for server updates" }
|
||||
}
|
||||
.singleOrNull()
|
||||
@Inject
|
||||
class GetSettings(
|
||||
private val settingsRepository: SettingsRepository,
|
||||
) {
|
||||
suspend fun await(onError: suspend (Throwable) -> Unit = {}) =
|
||||
asFlow()
|
||||
.catch {
|
||||
onError(it)
|
||||
log.warn(it) { "Failed to check for server updates" }
|
||||
}
|
||||
.singleOrNull()
|
||||
|
||||
fun asFlow() = settingsRepository.getSettings()
|
||||
fun asFlow() = settingsRepository.getSettings()
|
||||
|
||||
companion object {
|
||||
private val log = logging()
|
||||
}
|
||||
companion object {
|
||||
private val log = logging()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,24 +13,23 @@ import kotlinx.coroutines.flow.singleOrNull
|
||||
import me.tatarka.inject.annotations.Inject
|
||||
import org.lighthousegames.logging.logging
|
||||
|
||||
class SetSettings
|
||||
@Inject
|
||||
constructor(
|
||||
private val settingsRepository: SettingsRepository,
|
||||
) {
|
||||
suspend fun await(
|
||||
input: SetSettingsInput,
|
||||
onError: suspend (Throwable) -> Unit = {},
|
||||
) = asFlow(input)
|
||||
.catch {
|
||||
onError(it)
|
||||
log.warn(it) { "Failed to check for server updates" }
|
||||
}
|
||||
.singleOrNull()
|
||||
|
||||
fun asFlow(input: SetSettingsInput) = settingsRepository.setSettings(input)
|
||||
|
||||
companion object {
|
||||
private val log = logging()
|
||||
@Inject
|
||||
class SetSettings(
|
||||
private val settingsRepository: SettingsRepository,
|
||||
) {
|
||||
suspend fun await(
|
||||
input: SetSettingsInput,
|
||||
onError: suspend (Throwable) -> Unit = {},
|
||||
) = asFlow(input)
|
||||
.catch {
|
||||
onError(it)
|
||||
log.warn(it) { "Failed to check for server updates" }
|
||||
}
|
||||
.singleOrNull()
|
||||
|
||||
fun asFlow(input: SetSettingsInput) = settingsRepository.setSettings(input)
|
||||
|
||||
companion object {
|
||||
private val log = logging()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,36 +13,35 @@ import kotlinx.coroutines.flow.singleOrNull
|
||||
import me.tatarka.inject.annotations.Inject
|
||||
import org.lighthousegames.logging.logging
|
||||
|
||||
class GetFilterList
|
||||
@Inject
|
||||
constructor(
|
||||
private val sourceRepository: SourceRepository,
|
||||
) {
|
||||
suspend fun await(
|
||||
source: Source,
|
||||
onError: suspend (Throwable) -> Unit = {},
|
||||
) = asFlow(source.id)
|
||||
.catch {
|
||||
onError(it)
|
||||
log.warn(it) { "Failed to get filter list for ${source.displayName}" }
|
||||
}
|
||||
.singleOrNull()
|
||||
|
||||
suspend fun await(
|
||||
sourceId: Long,
|
||||
onError: suspend (Throwable) -> Unit = {},
|
||||
) = asFlow(sourceId)
|
||||
.catch {
|
||||
onError(it)
|
||||
log.warn(it) { "Failed to get filter list for $sourceId" }
|
||||
}
|
||||
.singleOrNull()
|
||||
|
||||
fun asFlow(source: Source) = sourceRepository.getFilterList(source.id)
|
||||
|
||||
fun asFlow(sourceId: Long) = sourceRepository.getFilterList(sourceId)
|
||||
|
||||
companion object {
|
||||
private val log = logging()
|
||||
@Inject
|
||||
class GetFilterList(
|
||||
private val sourceRepository: SourceRepository,
|
||||
) {
|
||||
suspend fun await(
|
||||
source: Source,
|
||||
onError: suspend (Throwable) -> Unit = {},
|
||||
) = asFlow(source.id)
|
||||
.catch {
|
||||
onError(it)
|
||||
log.warn(it) { "Failed to get filter list for ${source.displayName}" }
|
||||
}
|
||||
.singleOrNull()
|
||||
|
||||
suspend fun await(
|
||||
sourceId: Long,
|
||||
onError: suspend (Throwable) -> Unit = {},
|
||||
) = asFlow(sourceId)
|
||||
.catch {
|
||||
onError(it)
|
||||
log.warn(it) { "Failed to get filter list for $sourceId" }
|
||||
}
|
||||
.singleOrNull()
|
||||
|
||||
fun asFlow(source: Source) = sourceRepository.getFilterList(source.id)
|
||||
|
||||
fun asFlow(sourceId: Long) = sourceRepository.getFilterList(sourceId)
|
||||
|
||||
companion object {
|
||||
private val log = logging()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,44 +13,43 @@ import kotlinx.coroutines.flow.singleOrNull
|
||||
import me.tatarka.inject.annotations.Inject
|
||||
import org.lighthousegames.logging.logging
|
||||
|
||||
class GetLatestManga
|
||||
@Inject
|
||||
constructor(
|
||||
private val sourceRepository: SourceRepository,
|
||||
) {
|
||||
suspend fun await(
|
||||
source: Source,
|
||||
page: Int,
|
||||
onError: suspend (Throwable) -> Unit = {},
|
||||
) = asFlow(source.id, page)
|
||||
.catch {
|
||||
onError(it)
|
||||
log.warn(it) { "Failed to get latest manga from ${source.displayName} on page $page" }
|
||||
}
|
||||
.singleOrNull()
|
||||
|
||||
suspend fun await(
|
||||
sourceId: Long,
|
||||
page: Int,
|
||||
onError: suspend (Throwable) -> Unit = {},
|
||||
) = asFlow(sourceId, page)
|
||||
.catch {
|
||||
onError(it)
|
||||
log.warn(it) { "Failed to get latest manga from $sourceId on page $page" }
|
||||
}
|
||||
.singleOrNull()
|
||||
|
||||
fun asFlow(
|
||||
source: Source,
|
||||
page: Int,
|
||||
) = sourceRepository.getLatestManga(source.id, page)
|
||||
|
||||
fun asFlow(
|
||||
sourceId: Long,
|
||||
page: Int,
|
||||
) = sourceRepository.getLatestManga(sourceId, page)
|
||||
|
||||
companion object {
|
||||
private val log = logging()
|
||||
@Inject
|
||||
class GetLatestManga(
|
||||
private val sourceRepository: SourceRepository,
|
||||
) {
|
||||
suspend fun await(
|
||||
source: Source,
|
||||
page: Int,
|
||||
onError: suspend (Throwable) -> Unit = {},
|
||||
) = asFlow(source.id, page)
|
||||
.catch {
|
||||
onError(it)
|
||||
log.warn(it) { "Failed to get latest manga from ${source.displayName} on page $page" }
|
||||
}
|
||||
.singleOrNull()
|
||||
|
||||
suspend fun await(
|
||||
sourceId: Long,
|
||||
page: Int,
|
||||
onError: suspend (Throwable) -> Unit = {},
|
||||
) = asFlow(sourceId, page)
|
||||
.catch {
|
||||
onError(it)
|
||||
log.warn(it) { "Failed to get latest manga from $sourceId on page $page" }
|
||||
}
|
||||
.singleOrNull()
|
||||
|
||||
fun asFlow(
|
||||
source: Source,
|
||||
page: Int,
|
||||
) = sourceRepository.getLatestManga(source.id, page)
|
||||
|
||||
fun asFlow(
|
||||
sourceId: Long,
|
||||
page: Int,
|
||||
) = sourceRepository.getLatestManga(sourceId, page)
|
||||
|
||||
companion object {
|
||||
private val log = logging()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,44 +13,43 @@ import kotlinx.coroutines.flow.singleOrNull
|
||||
import me.tatarka.inject.annotations.Inject
|
||||
import org.lighthousegames.logging.logging
|
||||
|
||||
class GetPopularManga
|
||||
@Inject
|
||||
constructor(
|
||||
private val sourceRepository: SourceRepository,
|
||||
) {
|
||||
suspend fun await(
|
||||
source: Source,
|
||||
page: Int,
|
||||
onError: suspend (Throwable) -> Unit = {},
|
||||
) = asFlow(source.id, page)
|
||||
.catch {
|
||||
onError(it)
|
||||
log.warn(it) { "Failed to get popular manga from ${source.displayName} on page $page" }
|
||||
}
|
||||
.singleOrNull()
|
||||
|
||||
suspend fun await(
|
||||
sourceId: Long,
|
||||
page: Int,
|
||||
onError: suspend (Throwable) -> Unit = {},
|
||||
) = asFlow(sourceId, page)
|
||||
.catch {
|
||||
onError(it)
|
||||
log.warn(it) { "Failed to get popular manga from $sourceId on page $page" }
|
||||
}
|
||||
.singleOrNull()
|
||||
|
||||
fun asFlow(
|
||||
source: Source,
|
||||
page: Int,
|
||||
) = sourceRepository.getPopularManga(source.id, page)
|
||||
|
||||
fun asFlow(
|
||||
sourceId: Long,
|
||||
page: Int,
|
||||
) = sourceRepository.getPopularManga(sourceId, page)
|
||||
|
||||
companion object {
|
||||
private val log = logging()
|
||||
@Inject
|
||||
class GetPopularManga(
|
||||
private val sourceRepository: SourceRepository,
|
||||
) {
|
||||
suspend fun await(
|
||||
source: Source,
|
||||
page: Int,
|
||||
onError: suspend (Throwable) -> Unit = {},
|
||||
) = asFlow(source.id, page)
|
||||
.catch {
|
||||
onError(it)
|
||||
log.warn(it) { "Failed to get popular manga from ${source.displayName} on page $page" }
|
||||
}
|
||||
.singleOrNull()
|
||||
|
||||
suspend fun await(
|
||||
sourceId: Long,
|
||||
page: Int,
|
||||
onError: suspend (Throwable) -> Unit = {},
|
||||
) = asFlow(sourceId, page)
|
||||
.catch {
|
||||
onError(it)
|
||||
log.warn(it) { "Failed to get popular manga from $sourceId on page $page" }
|
||||
}
|
||||
.singleOrNull()
|
||||
|
||||
fun asFlow(
|
||||
source: Source,
|
||||
page: Int,
|
||||
) = sourceRepository.getPopularManga(source.id, page)
|
||||
|
||||
fun asFlow(
|
||||
sourceId: Long,
|
||||
page: Int,
|
||||
) = sourceRepository.getPopularManga(sourceId, page)
|
||||
|
||||
companion object {
|
||||
private val log = logging()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,64 +14,63 @@ import kotlinx.coroutines.flow.singleOrNull
|
||||
import me.tatarka.inject.annotations.Inject
|
||||
import org.lighthousegames.logging.logging
|
||||
|
||||
class GetSearchManga
|
||||
@Inject
|
||||
constructor(
|
||||
private val sourceRepository: SourceRepository,
|
||||
) {
|
||||
suspend fun await(
|
||||
source: Source,
|
||||
page: Int,
|
||||
searchTerm: String?,
|
||||
filters: List<SourceFilter>?,
|
||||
onError: suspend (Throwable) -> Unit = {
|
||||
},
|
||||
) = asFlow(source.id, page, searchTerm, filters)
|
||||
.catch {
|
||||
onError(it)
|
||||
log.warn(it) { "Failed to get search results from ${source.displayName} on page $page with query '$searchTerm'" }
|
||||
}
|
||||
.singleOrNull()
|
||||
|
||||
suspend fun await(
|
||||
sourceId: Long,
|
||||
searchTerm: String?,
|
||||
page: Int,
|
||||
filters: List<SourceFilter>?,
|
||||
onError: suspend (Throwable) -> Unit = {
|
||||
},
|
||||
) = asFlow(sourceId, page, searchTerm, filters)
|
||||
.catch {
|
||||
onError(it)
|
||||
log.warn(it) { "Failed to get search results from $sourceId on page $page with query '$searchTerm'" }
|
||||
}
|
||||
.singleOrNull()
|
||||
|
||||
fun asFlow(
|
||||
source: Source,
|
||||
page: Int,
|
||||
searchTerm: String?,
|
||||
filters: List<SourceFilter>?,
|
||||
) = sourceRepository.getSearchResults(
|
||||
source.id,
|
||||
page,
|
||||
searchTerm?.ifBlank { null },
|
||||
filters,
|
||||
)
|
||||
|
||||
fun asFlow(
|
||||
sourceId: Long,
|
||||
page: Int,
|
||||
searchTerm: String?,
|
||||
filters: List<SourceFilter>?,
|
||||
) = sourceRepository.getSearchResults(
|
||||
sourceId,
|
||||
page,
|
||||
searchTerm?.ifBlank { null },
|
||||
filters,
|
||||
)
|
||||
|
||||
companion object {
|
||||
private val log = logging()
|
||||
@Inject
|
||||
class GetSearchManga(
|
||||
private val sourceRepository: SourceRepository,
|
||||
) {
|
||||
suspend fun await(
|
||||
source: Source,
|
||||
page: Int,
|
||||
searchTerm: String?,
|
||||
filters: List<SourceFilter>?,
|
||||
onError: suspend (Throwable) -> Unit = {
|
||||
},
|
||||
) = asFlow(source.id, page, searchTerm, filters)
|
||||
.catch {
|
||||
onError(it)
|
||||
log.warn(it) { "Failed to get search results from ${source.displayName} on page $page with query '$searchTerm'" }
|
||||
}
|
||||
.singleOrNull()
|
||||
|
||||
suspend fun await(
|
||||
sourceId: Long,
|
||||
searchTerm: String?,
|
||||
page: Int,
|
||||
filters: List<SourceFilter>?,
|
||||
onError: suspend (Throwable) -> Unit = {
|
||||
},
|
||||
) = asFlow(sourceId, page, searchTerm, filters)
|
||||
.catch {
|
||||
onError(it)
|
||||
log.warn(it) { "Failed to get search results from $sourceId on page $page with query '$searchTerm'" }
|
||||
}
|
||||
.singleOrNull()
|
||||
|
||||
fun asFlow(
|
||||
source: Source,
|
||||
page: Int,
|
||||
searchTerm: String?,
|
||||
filters: List<SourceFilter>?,
|
||||
) = sourceRepository.getSearchResults(
|
||||
source.id,
|
||||
page,
|
||||
searchTerm?.ifBlank { null },
|
||||
filters,
|
||||
)
|
||||
|
||||
fun asFlow(
|
||||
sourceId: Long,
|
||||
page: Int,
|
||||
searchTerm: String?,
|
||||
filters: List<SourceFilter>?,
|
||||
) = sourceRepository.getSearchResults(
|
||||
sourceId,
|
||||
page,
|
||||
searchTerm?.ifBlank { null },
|
||||
filters,
|
||||
)
|
||||
|
||||
companion object {
|
||||
private val log = logging()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,22 +12,21 @@ import kotlinx.coroutines.flow.singleOrNull
|
||||
import me.tatarka.inject.annotations.Inject
|
||||
import org.lighthousegames.logging.logging
|
||||
|
||||
class GetSourceList
|
||||
@Inject
|
||||
constructor(
|
||||
private val sourceRepository: SourceRepository,
|
||||
) {
|
||||
suspend fun await(onError: suspend (Throwable) -> Unit = {}) =
|
||||
asFlow()
|
||||
.catch {
|
||||
onError(it)
|
||||
log.warn(it) { "Failed to get source list" }
|
||||
}
|
||||
.singleOrNull()
|
||||
@Inject
|
||||
class GetSourceList(
|
||||
private val sourceRepository: SourceRepository,
|
||||
) {
|
||||
suspend fun await(onError: suspend (Throwable) -> Unit = {}) =
|
||||
asFlow()
|
||||
.catch {
|
||||
onError(it)
|
||||
log.warn(it) { "Failed to get source list" }
|
||||
}
|
||||
.singleOrNull()
|
||||
|
||||
fun asFlow() = sourceRepository.getSourceList()
|
||||
fun asFlow() = sourceRepository.getSourceList()
|
||||
|
||||
companion object {
|
||||
private val log = logging()
|
||||
}
|
||||
companion object {
|
||||
private val log = logging()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,36 +13,35 @@ import kotlinx.coroutines.flow.singleOrNull
|
||||
import me.tatarka.inject.annotations.Inject
|
||||
import org.lighthousegames.logging.logging
|
||||
|
||||
class GetSourceSettings
|
||||
@Inject
|
||||
constructor(
|
||||
private val sourceRepository: SourceRepository,
|
||||
) {
|
||||
suspend fun await(
|
||||
source: Source,
|
||||
onError: suspend (Throwable) -> Unit = {},
|
||||
) = asFlow(source.id)
|
||||
.catch {
|
||||
onError(it)
|
||||
log.warn(it) { "Failed to get source settings for ${source.displayName}" }
|
||||
}
|
||||
.singleOrNull()
|
||||
|
||||
suspend fun await(
|
||||
sourceId: Long,
|
||||
onError: suspend (Throwable) -> Unit = {},
|
||||
) = asFlow(sourceId)
|
||||
.catch {
|
||||
onError(it)
|
||||
log.warn(it) { "Failed to get source settings for $sourceId" }
|
||||
}
|
||||
.singleOrNull()
|
||||
|
||||
fun asFlow(source: Source) = sourceRepository.getSourceSettings(source.id)
|
||||
|
||||
fun asFlow(sourceId: Long) = sourceRepository.getSourceSettings(sourceId)
|
||||
|
||||
companion object {
|
||||
private val log = logging()
|
||||
@Inject
|
||||
class GetSourceSettings(
|
||||
private val sourceRepository: SourceRepository,
|
||||
) {
|
||||
suspend fun await(
|
||||
source: Source,
|
||||
onError: suspend (Throwable) -> Unit = {},
|
||||
) = asFlow(source.id)
|
||||
.catch {
|
||||
onError(it)
|
||||
log.warn(it) { "Failed to get source settings for ${source.displayName}" }
|
||||
}
|
||||
.singleOrNull()
|
||||
|
||||
suspend fun await(
|
||||
sourceId: Long,
|
||||
onError: suspend (Throwable) -> Unit = {},
|
||||
) = asFlow(sourceId)
|
||||
.catch {
|
||||
onError(it)
|
||||
log.warn(it) { "Failed to get source settings for $sourceId" }
|
||||
}
|
||||
.singleOrNull()
|
||||
|
||||
fun asFlow(source: Source) = sourceRepository.getSourceSettings(source.id)
|
||||
|
||||
fun asFlow(sourceId: Long) = sourceRepository.getSourceSettings(sourceId)
|
||||
|
||||
companion object {
|
||||
private val log = logging()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,32 +13,31 @@ import kotlinx.coroutines.flow.collect
|
||||
import me.tatarka.inject.annotations.Inject
|
||||
import org.lighthousegames.logging.logging
|
||||
|
||||
class SetSourceSetting
|
||||
@Inject
|
||||
constructor(
|
||||
private val sourceRepository: SourceRepository,
|
||||
) {
|
||||
suspend fun await(
|
||||
sourceId: Long,
|
||||
sourcePreference: SourcePreference,
|
||||
onError: suspend (Throwable) -> Unit = {
|
||||
},
|
||||
) = asFlow(sourceId, sourcePreference)
|
||||
.catch {
|
||||
onError(it)
|
||||
log.warn(it) { "Failed to set setting for $sourceId with index = ${sourcePreference.position}" }
|
||||
}
|
||||
.collect()
|
||||
|
||||
fun asFlow(
|
||||
sourceId: Long,
|
||||
sourcePreference: SourcePreference,
|
||||
) = sourceRepository.setSourceSetting(
|
||||
sourceId,
|
||||
sourcePreference,
|
||||
)
|
||||
|
||||
companion object {
|
||||
private val log = logging()
|
||||
@Inject
|
||||
class SetSourceSetting(
|
||||
private val sourceRepository: SourceRepository,
|
||||
) {
|
||||
suspend fun await(
|
||||
sourceId: Long,
|
||||
sourcePreference: SourcePreference,
|
||||
onError: suspend (Throwable) -> Unit = {
|
||||
},
|
||||
) = asFlow(sourceId, sourcePreference)
|
||||
.catch {
|
||||
onError(it)
|
||||
log.warn(it) { "Failed to set setting for $sourceId with index = ${sourcePreference.position}" }
|
||||
}
|
||||
.collect()
|
||||
|
||||
fun asFlow(
|
||||
sourceId: Long,
|
||||
sourcePreference: SourcePreference,
|
||||
) = sourceRepository.setSourceSetting(
|
||||
sourceId,
|
||||
sourcePreference,
|
||||
)
|
||||
|
||||
companion object {
|
||||
private val log = logging()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -33,21 +33,21 @@ fun interface GetMangaPage {
|
||||
suspend fun get(page: Int): MangaPage?
|
||||
}
|
||||
|
||||
class SourcePager
|
||||
@Inject
|
||||
constructor(
|
||||
private val getManga: GetManga,
|
||||
private val serverListeners: ServerListeners,
|
||||
@Assisted private val fetcher: GetMangaPage,
|
||||
) : CoroutineScope by CoroutineScope(Dispatchers.Default + SupervisorJob()) {
|
||||
private val sourceMutex = Mutex()
|
||||
@Inject
|
||||
class SourcePager(
|
||||
private val getManga: GetManga,
|
||||
private val serverListeners: ServerListeners,
|
||||
@Assisted private val fetcher: GetMangaPage,
|
||||
) : CoroutineScope by CoroutineScope(Dispatchers.Default + SupervisorJob()) {
|
||||
private val sourceMutex = Mutex()
|
||||
|
||||
private val _sourceManga = MutableStateFlow<List<Manga>>(emptyList())
|
||||
private val _sourceManga = MutableStateFlow<List<Manga>>(emptyList())
|
||||
|
||||
private val mangaIds = _sourceManga.map { mangas -> mangas.map { it.id } }
|
||||
.stateIn(this, SharingStarted.Eagerly, emptyList())
|
||||
private val mangaIds = _sourceManga.map { mangas -> mangas.map { it.id } }
|
||||
.stateIn(this, SharingStarted.Eagerly, emptyList())
|
||||
|
||||
private val changedManga = serverListeners.mangaListener.runningFold(emptyMap<Long, Manga>()) { manga, updatedMangaIds ->
|
||||
private val changedManga =
|
||||
serverListeners.mangaListener.runningFold(emptyMap<Long, Manga>()) { manga, updatedMangaIds ->
|
||||
coroutineScope {
|
||||
manga + updatedMangaIds.filter { it in mangaIds.value }.map {
|
||||
async {
|
||||
@@ -57,37 +57,37 @@ class SourcePager
|
||||
}
|
||||
}.stateIn(this, SharingStarted.Eagerly, emptyMap())
|
||||
|
||||
val mangas = combine(_sourceManga, changedManga) { sourceManga, changedManga ->
|
||||
sourceManga.map { changedManga[it.id] ?: it }
|
||||
}.stateIn(this, SharingStarted.Eagerly, emptyList())
|
||||
val mangas = combine(_sourceManga, changedManga) { sourceManga, changedManga ->
|
||||
sourceManga.map { changedManga[it.id] ?: it }
|
||||
}.stateIn(this, SharingStarted.Eagerly, emptyList())
|
||||
|
||||
private val _pageNum = MutableStateFlow(0)
|
||||
val pageNum = _pageNum.asStateFlow()
|
||||
private val _pageNum = MutableStateFlow(0)
|
||||
val pageNum = _pageNum.asStateFlow()
|
||||
|
||||
private val _hasNextPage = MutableStateFlow(true)
|
||||
val hasNextPage = _hasNextPage.asStateFlow()
|
||||
private val _hasNextPage = MutableStateFlow(true)
|
||||
val hasNextPage = _hasNextPage.asStateFlow()
|
||||
|
||||
private val _loading = MutableStateFlow(true)
|
||||
val loading = _loading.asStateFlow()
|
||||
private val _loading = MutableStateFlow(true)
|
||||
val loading = _loading.asStateFlow()
|
||||
|
||||
fun loadNextPage() {
|
||||
launch {
|
||||
if (hasNextPage.value && sourceMutex.tryLock()) {
|
||||
_pageNum.value++
|
||||
val page = fetcher.get(_pageNum.value)
|
||||
if (page != null) {
|
||||
_sourceManga.value = _sourceManga.value + page.mangaList
|
||||
_hasNextPage.value = page.hasNextPage
|
||||
} else {
|
||||
_pageNum.value--
|
||||
}
|
||||
sourceMutex.unlock()
|
||||
fun loadNextPage() {
|
||||
launch {
|
||||
if (hasNextPage.value && sourceMutex.tryLock()) {
|
||||
_pageNum.value++
|
||||
val page = fetcher.get(_pageNum.value)
|
||||
if (page != null) {
|
||||
_sourceManga.value = _sourceManga.value + page.mangaList
|
||||
_hasNextPage.value = page.hasNextPage
|
||||
} else {
|
||||
_pageNum.value--
|
||||
}
|
||||
_loading.value = false
|
||||
sourceMutex.unlock()
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
private val log = logging()
|
||||
_loading.value = false
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
private val log = logging()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,7 +15,7 @@ enum class StartScreen {
|
||||
Library,
|
||||
Updates,
|
||||
|
||||
// History,
|
||||
// History,
|
||||
Sources,
|
||||
Extensions,
|
||||
}
|
||||
|
||||
@@ -12,24 +12,23 @@ import kotlinx.coroutines.flow.singleOrNull
|
||||
import me.tatarka.inject.annotations.Inject
|
||||
import org.lighthousegames.logging.logging
|
||||
|
||||
class GetRecentUpdates
|
||||
@Inject
|
||||
constructor(
|
||||
private val updatesRepository: UpdatesRepository,
|
||||
) {
|
||||
suspend fun await(
|
||||
pageNum: Int,
|
||||
onError: suspend (Throwable) -> Unit = {},
|
||||
) = asFlow(pageNum)
|
||||
.catch {
|
||||
onError(it)
|
||||
log.warn(it) { "Failed to get updates for page $pageNum" }
|
||||
}
|
||||
.singleOrNull()
|
||||
|
||||
fun asFlow(pageNum: Int) = updatesRepository.getRecentUpdates(pageNum)
|
||||
|
||||
companion object {
|
||||
private val log = logging()
|
||||
@Inject
|
||||
class GetRecentUpdates(
|
||||
private val updatesRepository: UpdatesRepository,
|
||||
) {
|
||||
suspend fun await(
|
||||
pageNum: Int,
|
||||
onError: suspend (Throwable) -> Unit = {},
|
||||
) = asFlow(pageNum)
|
||||
.catch {
|
||||
onError(it)
|
||||
log.warn(it) { "Failed to get updates for page $pageNum" }
|
||||
}
|
||||
.singleOrNull()
|
||||
|
||||
fun asFlow(pageNum: Int) = updatesRepository.getRecentUpdates(pageNum)
|
||||
|
||||
companion object {
|
||||
private val log = logging()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,36 +13,35 @@ import kotlinx.coroutines.flow.collect
|
||||
import me.tatarka.inject.annotations.Inject
|
||||
import org.lighthousegames.logging.logging
|
||||
|
||||
class UpdateCategory
|
||||
@Inject
|
||||
constructor(
|
||||
private val updatesRepository: UpdatesRepository,
|
||||
) {
|
||||
suspend fun await(
|
||||
categoryId: Long,
|
||||
onError: suspend (Throwable) -> Unit = {},
|
||||
) = asFlow(categoryId)
|
||||
.catch {
|
||||
onError(it)
|
||||
log.warn(it) { "Failed to update category $categoryId" }
|
||||
}
|
||||
.collect()
|
||||
|
||||
suspend fun await(
|
||||
category: Category,
|
||||
onError: suspend (Throwable) -> Unit = {},
|
||||
) = asFlow(category)
|
||||
.catch {
|
||||
onError(it)
|
||||
log.warn(it) { "Failed to update category ${category.name}(${category.id})" }
|
||||
}
|
||||
.collect()
|
||||
|
||||
fun asFlow(categoryId: Long) = updatesRepository.updateCategory(categoryId)
|
||||
|
||||
fun asFlow(category: Category) = updatesRepository.updateCategory(category.id)
|
||||
|
||||
companion object {
|
||||
private val log = logging()
|
||||
@Inject
|
||||
class UpdateCategory(
|
||||
private val updatesRepository: UpdatesRepository,
|
||||
) {
|
||||
suspend fun await(
|
||||
categoryId: Long,
|
||||
onError: suspend (Throwable) -> Unit = {},
|
||||
) = asFlow(categoryId)
|
||||
.catch {
|
||||
onError(it)
|
||||
log.warn(it) { "Failed to update category $categoryId" }
|
||||
}
|
||||
.collect()
|
||||
|
||||
suspend fun await(
|
||||
category: Category,
|
||||
onError: suspend (Throwable) -> Unit = {},
|
||||
) = asFlow(category)
|
||||
.catch {
|
||||
onError(it)
|
||||
log.warn(it) { "Failed to update category ${category.name}(${category.id})" }
|
||||
}
|
||||
.collect()
|
||||
|
||||
fun asFlow(categoryId: Long) = updatesRepository.updateCategory(categoryId)
|
||||
|
||||
fun asFlow(category: Category) = updatesRepository.updateCategory(category.id)
|
||||
|
||||
companion object {
|
||||
private val log = logging()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,77 +21,76 @@ import kotlinx.coroutines.flow.singleOrNull
|
||||
import me.tatarka.inject.annotations.Inject
|
||||
import org.lighthousegames.logging.logging
|
||||
|
||||
class UpdateChecker
|
||||
@Inject
|
||||
constructor(
|
||||
private val updatePreferences: UpdatePreferences,
|
||||
private val client: Http,
|
||||
) {
|
||||
suspend fun await(
|
||||
manualFetch: Boolean,
|
||||
onError: suspend (Throwable) -> Unit = {},
|
||||
) = asFlow(manualFetch)
|
||||
.catch {
|
||||
onError(it)
|
||||
log.warn(it) { "Failed to check for updates" }
|
||||
}
|
||||
.singleOrNull()
|
||||
|
||||
fun asFlow(manualFetch: Boolean) =
|
||||
flow {
|
||||
if (!manualFetch && !updatePreferences.enabled().get()) return@flow
|
||||
val latestRelease = client.get(
|
||||
"https://api.github.com/repos/$GITHUB_REPO/releases/latest",
|
||||
).body<GithubRelease>()
|
||||
|
||||
if (isNewVersion(latestRelease.version)) {
|
||||
emit(Update.UpdateFound(latestRelease))
|
||||
} else {
|
||||
emit(Update.NoUpdatesFound)
|
||||
}
|
||||
}.flowOn(Dispatchers.IO)
|
||||
|
||||
sealed class Update {
|
||||
data class UpdateFound(
|
||||
val release: GithubRelease,
|
||||
) : Update()
|
||||
|
||||
data object NoUpdatesFound : Update()
|
||||
@Inject
|
||||
class UpdateChecker(
|
||||
private val updatePreferences: UpdatePreferences,
|
||||
private val client: Http,
|
||||
) {
|
||||
suspend fun await(
|
||||
manualFetch: Boolean,
|
||||
onError: suspend (Throwable) -> Unit = {},
|
||||
) = asFlow(manualFetch)
|
||||
.catch {
|
||||
onError(it)
|
||||
log.warn(it) { "Failed to check for updates" }
|
||||
}
|
||||
.singleOrNull()
|
||||
|
||||
// Thanks to Tachiyomi for inspiration
|
||||
private fun isNewVersion(versionTag: String): Boolean {
|
||||
// Removes prefixes like "r" or "v"
|
||||
val newVersion = versionTag.replace("[^\\d.]".toRegex(), "")
|
||||
fun asFlow(manualFetch: Boolean) =
|
||||
flow {
|
||||
if (!manualFetch && !updatePreferences.enabled().get()) return@flow
|
||||
val latestRelease = client.get(
|
||||
"https://api.github.com/repos/$GITHUB_REPO/releases/latest",
|
||||
).body<GithubRelease>()
|
||||
|
||||
return if (BuildKonfig.IS_PREVIEW) {
|
||||
// Preview builds: based on releases in "Suwayomi/Suwayomi-JUI-preview" repo
|
||||
// tagged as something like "r123"
|
||||
newVersion.toInt() > BuildKonfig.PREVIEW_BUILD
|
||||
if (isNewVersion(latestRelease.version)) {
|
||||
emit(Update.UpdateFound(latestRelease))
|
||||
} else {
|
||||
// Release builds: based on releases in "Suwayomi/Suwayomi-JUI" repo
|
||||
// tagged as something like "v1.1.2"
|
||||
newVersion != BuildKonfig.VERSION
|
||||
emit(Update.NoUpdatesFound)
|
||||
}
|
||||
}
|
||||
}.flowOn(Dispatchers.IO)
|
||||
|
||||
companion object {
|
||||
private val GITHUB_REPO = if (BuildKonfig.IS_PREVIEW) {
|
||||
"Suwayomi/Suwayomi-JUI-preview"
|
||||
} else {
|
||||
"Suwayomi/Suwayomi-JUI"
|
||||
}
|
||||
sealed class Update {
|
||||
data class UpdateFound(
|
||||
val release: GithubRelease,
|
||||
) : Update()
|
||||
|
||||
private val RELEASE_TAG: String by lazy {
|
||||
if (BuildKonfig.IS_PREVIEW) {
|
||||
"r${BuildKonfig.PREVIEW_BUILD}"
|
||||
} else {
|
||||
"v${BuildKonfig.VERSION}"
|
||||
}
|
||||
}
|
||||
data object NoUpdatesFound : Update()
|
||||
}
|
||||
|
||||
val RELEASE_URL = "https://github.com/$GITHUB_REPO/releases/tag/$RELEASE_TAG"
|
||||
// Thanks to Tachiyomi for inspiration
|
||||
private fun isNewVersion(versionTag: String): Boolean {
|
||||
// Removes prefixes like "r" or "v"
|
||||
val newVersion = versionTag.replace("[^\\d.]".toRegex(), "")
|
||||
|
||||
private val log = logging()
|
||||
return if (BuildKonfig.IS_PREVIEW) {
|
||||
// Preview builds: based on releases in "Suwayomi/Suwayomi-JUI-preview" repo
|
||||
// tagged as something like "r123"
|
||||
newVersion.toInt() > BuildKonfig.PREVIEW_BUILD
|
||||
} else {
|
||||
// Release builds: based on releases in "Suwayomi/Suwayomi-JUI" repo
|
||||
// tagged as something like "v1.1.2"
|
||||
newVersion != BuildKonfig.VERSION
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
private val GITHUB_REPO = if (BuildKonfig.IS_PREVIEW) {
|
||||
"Suwayomi/Suwayomi-JUI-preview"
|
||||
} else {
|
||||
"Suwayomi/Suwayomi-JUI"
|
||||
}
|
||||
|
||||
private val RELEASE_TAG: String by lazy {
|
||||
if (BuildKonfig.IS_PREVIEW) {
|
||||
"r${BuildKonfig.PREVIEW_BUILD}"
|
||||
} else {
|
||||
"v${BuildKonfig.VERSION}"
|
||||
}
|
||||
}
|
||||
|
||||
val RELEASE_URL = "https://github.com/$GITHUB_REPO/releases/tag/$RELEASE_TAG"
|
||||
|
||||
private val log = logging()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,22 +12,21 @@ import kotlinx.coroutines.flow.collect
|
||||
import me.tatarka.inject.annotations.Inject
|
||||
import org.lighthousegames.logging.logging
|
||||
|
||||
class UpdateLibrary
|
||||
@Inject
|
||||
constructor(
|
||||
private val updatesRepository: UpdatesRepository,
|
||||
) {
|
||||
suspend fun await(onError: suspend (Throwable) -> Unit = {}) =
|
||||
asFlow()
|
||||
.catch {
|
||||
onError(it)
|
||||
log.warn(it) { "Failed to update library" }
|
||||
}
|
||||
.collect()
|
||||
@Inject
|
||||
class UpdateLibrary(
|
||||
private val updatesRepository: UpdatesRepository,
|
||||
) {
|
||||
suspend fun await(onError: suspend (Throwable) -> Unit = {}) =
|
||||
asFlow()
|
||||
.catch {
|
||||
onError(it)
|
||||
log.warn(it) { "Failed to update library" }
|
||||
}
|
||||
.collect()
|
||||
|
||||
fun asFlow() = updatesRepository.updateLibrary()
|
||||
fun asFlow() = updatesRepository.updateLibrary()
|
||||
|
||||
companion object {
|
||||
private val log = logging()
|
||||
}
|
||||
companion object {
|
||||
private val log = logging()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -37,54 +37,54 @@ import kotlinx.datetime.TimeZone
|
||||
import kotlinx.datetime.toLocalDateTime
|
||||
import me.tatarka.inject.annotations.Inject
|
||||
|
||||
class UpdatesPager
|
||||
@Inject
|
||||
constructor(
|
||||
private val getRecentUpdates: GetRecentUpdates,
|
||||
private val getManga: GetManga,
|
||||
private val getChapter: GetChapter,
|
||||
private val serverListeners: ServerListeners,
|
||||
) : CoroutineScope by CoroutineScope(Dispatchers.Default + SupervisorJob()) {
|
||||
private val updatesMutex = Mutex()
|
||||
@Inject
|
||||
class UpdatesPager(
|
||||
private val getRecentUpdates: GetRecentUpdates,
|
||||
private val getManga: GetManga,
|
||||
private val getChapter: GetChapter,
|
||||
private val serverListeners: ServerListeners,
|
||||
) : CoroutineScope by CoroutineScope(Dispatchers.Default + SupervisorJob()) {
|
||||
private val updatesMutex = Mutex()
|
||||
|
||||
private val fetchedUpdates = MutableSharedFlow<List<MangaAndChapter>>()
|
||||
private val foldedUpdates = fetchedUpdates.runningFold(emptyList<Updates>()) { updates, newUpdates ->
|
||||
updates.ifEmpty {
|
||||
val first = newUpdates.firstOrNull()?.chapter ?: return@runningFold updates
|
||||
listOf(
|
||||
Updates.Date(
|
||||
Instant.fromEpochSeconds(first.fetchedAt)
|
||||
.toLocalDateTime(TimeZone.currentSystemDefault())
|
||||
.date,
|
||||
),
|
||||
)
|
||||
} + newUpdates.fold(emptyList()) { list, (manga, chapter) ->
|
||||
val date = (list.lastOrNull() as? Updates.Update)?.let {
|
||||
val lastUpdateDate = Instant.fromEpochSeconds(it.chapter.fetchedAt)
|
||||
private val fetchedUpdates = MutableSharedFlow<List<MangaAndChapter>>()
|
||||
private val foldedUpdates = fetchedUpdates.runningFold(emptyList<Updates>()) { updates, newUpdates ->
|
||||
updates.ifEmpty {
|
||||
val first = newUpdates.firstOrNull()?.chapter ?: return@runningFold updates
|
||||
listOf(
|
||||
Updates.Date(
|
||||
Instant.fromEpochSeconds(first.fetchedAt)
|
||||
.toLocalDateTime(TimeZone.currentSystemDefault())
|
||||
.date
|
||||
val chapterDate = Instant.fromEpochSeconds(chapter.fetchedAt)
|
||||
.toLocalDateTime(TimeZone.currentSystemDefault())
|
||||
.date
|
||||
chapterDate.takeUnless { it == lastUpdateDate }
|
||||
}
|
||||
|
||||
if (date == null) {
|
||||
list + Updates.Update(manga, chapter)
|
||||
} else {
|
||||
list + Updates.Date(date) + Updates.Update(manga, chapter)
|
||||
}
|
||||
.date,
|
||||
),
|
||||
)
|
||||
} + newUpdates.fold(emptyList()) { list, (manga, chapter) ->
|
||||
val date = (list.lastOrNull() as? Updates.Update)?.let {
|
||||
val lastUpdateDate = Instant.fromEpochSeconds(it.chapter.fetchedAt)
|
||||
.toLocalDateTime(TimeZone.currentSystemDefault())
|
||||
.date
|
||||
val chapterDate = Instant.fromEpochSeconds(chapter.fetchedAt)
|
||||
.toLocalDateTime(TimeZone.currentSystemDefault())
|
||||
.date
|
||||
chapterDate.takeUnless { it == lastUpdateDate }
|
||||
}
|
||||
}.stateIn(this, SharingStarted.Eagerly, emptyList())
|
||||
|
||||
private val mangaIds = foldedUpdates.map { updates ->
|
||||
updates.filterIsInstance<Updates.Update>().map { it.manga.id }
|
||||
}.stateIn(this, SharingStarted.Eagerly, emptyList())
|
||||
private val chapterIds = foldedUpdates.map { updates ->
|
||||
updates.filterIsInstance<Updates.Update>().map { it.chapter.id }
|
||||
}.stateIn(this, SharingStarted.Eagerly, emptyList())
|
||||
if (date == null) {
|
||||
list + Updates.Update(manga, chapter)
|
||||
} else {
|
||||
list + Updates.Date(date) + Updates.Update(manga, chapter)
|
||||
}
|
||||
}
|
||||
}.stateIn(this, SharingStarted.Eagerly, emptyList())
|
||||
|
||||
private val changedManga = serverListeners.mangaListener.runningFold(emptyMap<Long, Manga>()) { manga, updatedMangaIds ->
|
||||
private val mangaIds = foldedUpdates.map { updates ->
|
||||
updates.filterIsInstance<Updates.Update>().map { it.manga.id }
|
||||
}.stateIn(this, SharingStarted.Eagerly, emptyList())
|
||||
private val chapterIds = foldedUpdates.map { updates ->
|
||||
updates.filterIsInstance<Updates.Update>().map { it.chapter.id }
|
||||
}.stateIn(this, SharingStarted.Eagerly, emptyList())
|
||||
|
||||
private val changedManga =
|
||||
serverListeners.mangaListener.runningFold(emptyMap<Long, Manga>()) { manga, updatedMangaIds ->
|
||||
coroutineScope {
|
||||
manga + updatedMangaIds.filter { it in mangaIds.value }.map {
|
||||
async {
|
||||
@@ -94,82 +94,82 @@ class UpdatesPager
|
||||
}
|
||||
}.stateIn(this, SharingStarted.Eagerly, emptyMap())
|
||||
|
||||
private val changedChapters = MutableStateFlow(emptyMap<Long, Chapter>())
|
||||
private val changedChapters = MutableStateFlow(emptyMap<Long, Chapter>())
|
||||
|
||||
init {
|
||||
serverListeners.chapterIdsListener
|
||||
.onEach { updatedChapterIds ->
|
||||
val chapters = coroutineScope {
|
||||
updatedChapterIds.mapNotNull { id -> chapterIds.value.find { it == id } }.map {
|
||||
async {
|
||||
getChapter.await(it)
|
||||
}
|
||||
}.awaitAll().filterNotNull().associateBy { it.id }
|
||||
}
|
||||
changedChapters.update { it + chapters }
|
||||
}
|
||||
.launchIn(this)
|
||||
}
|
||||
|
||||
val updates = combine(
|
||||
foldedUpdates,
|
||||
changedManga,
|
||||
changedChapters,
|
||||
) { updates, changedManga, changedChapters ->
|
||||
updates.map {
|
||||
when (it) {
|
||||
is Updates.Date -> it
|
||||
|
||||
is Updates.Update -> it.copy(
|
||||
manga = changedManga[it.manga.id] ?: it.manga,
|
||||
chapter = changedChapters[it.chapter.id] ?: it.chapter,
|
||||
)
|
||||
init {
|
||||
serverListeners.chapterIdsListener
|
||||
.onEach { updatedChapterIds ->
|
||||
val chapters = coroutineScope {
|
||||
updatedChapterIds.mapNotNull { id -> chapterIds.value.find { it == id } }.map {
|
||||
async {
|
||||
getChapter.await(it)
|
||||
}
|
||||
}.awaitAll().filterNotNull().associateBy { it.id }
|
||||
}
|
||||
changedChapters.update { it + chapters }
|
||||
}
|
||||
}.stateIn(this, SharingStarted.Eagerly, emptyList())
|
||||
.launchIn(this)
|
||||
}
|
||||
|
||||
private val currentPage = MutableStateFlow(0)
|
||||
private val hasNextPage = MutableStateFlow(true)
|
||||
val updates = combine(
|
||||
foldedUpdates,
|
||||
changedManga,
|
||||
changedChapters,
|
||||
) { updates, changedManga, changedChapters ->
|
||||
updates.map {
|
||||
when (it) {
|
||||
is Updates.Date -> it
|
||||
|
||||
is Updates.Update -> it.copy(
|
||||
manga = changedManga[it.manga.id] ?: it.manga,
|
||||
chapter = changedChapters[it.chapter.id] ?: it.chapter,
|
||||
)
|
||||
}
|
||||
}
|
||||
}.stateIn(this, SharingStarted.Eagerly, emptyList())
|
||||
|
||||
private val currentPage = MutableStateFlow(0)
|
||||
private val hasNextPage = MutableStateFlow(true)
|
||||
|
||||
@Immutable
|
||||
sealed class Updates {
|
||||
@Immutable
|
||||
data class Update(
|
||||
val manga: Manga,
|
||||
val chapter: Chapter,
|
||||
) : Updates()
|
||||
|
||||
@Immutable
|
||||
sealed class Updates {
|
||||
@Immutable
|
||||
data class Update(
|
||||
val manga: Manga,
|
||||
val chapter: Chapter,
|
||||
) : Updates()
|
||||
|
||||
@Immutable
|
||||
data class Date(
|
||||
val date: String,
|
||||
) : Updates() {
|
||||
constructor(date: LocalDate) : this(date.toString())
|
||||
}
|
||||
}
|
||||
|
||||
fun loadNextPage(
|
||||
onComplete: (() -> Unit)? = null,
|
||||
onError: suspend (Throwable) -> Unit,
|
||||
) {
|
||||
launch {
|
||||
if (hasNextPage.value && updatesMutex.tryLock()) {
|
||||
currentPage.value++
|
||||
if (!getUpdates(currentPage.value, onError)) {
|
||||
currentPage.value--
|
||||
}
|
||||
updatesMutex.unlock()
|
||||
}
|
||||
onComplete?.invoke()
|
||||
}
|
||||
}
|
||||
|
||||
private suspend fun getUpdates(
|
||||
page: Int,
|
||||
onError: suspend (Throwable) -> Unit,
|
||||
): Boolean {
|
||||
val updates = getRecentUpdates.await(page, onError) ?: return false
|
||||
hasNextPage.value = updates.hasNextPage
|
||||
fetchedUpdates.emit(updates.page)
|
||||
return true
|
||||
data class Date(
|
||||
val date: String,
|
||||
) : Updates() {
|
||||
constructor(date: LocalDate) : this(date.toString())
|
||||
}
|
||||
}
|
||||
|
||||
fun loadNextPage(
|
||||
onComplete: (() -> Unit)? = null,
|
||||
onError: suspend (Throwable) -> Unit,
|
||||
) {
|
||||
launch {
|
||||
if (hasNextPage.value && updatesMutex.tryLock()) {
|
||||
currentPage.value++
|
||||
if (!getUpdates(currentPage.value, onError)) {
|
||||
currentPage.value--
|
||||
}
|
||||
updatesMutex.unlock()
|
||||
}
|
||||
onComplete?.invoke()
|
||||
}
|
||||
}
|
||||
|
||||
private suspend fun getUpdates(
|
||||
page: Int,
|
||||
onError: suspend (Throwable) -> Unit,
|
||||
): Boolean {
|
||||
val updates = getRecentUpdates.await(page, onError) ?: return false
|
||||
hasNextPage.value = updates.hasNextPage
|
||||
fetchedUpdates.emit(updates.page)
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
@@ -38,169 +38,168 @@ import kotlin.io.path.exists
|
||||
import kotlin.io.path.isExecutable
|
||||
|
||||
@OptIn(DelicateCoroutinesApi::class)
|
||||
class ServerService
|
||||
@Inject
|
||||
constructor(
|
||||
private val serverHostPreferences: ServerHostPreferences,
|
||||
) {
|
||||
private val scope = CoroutineScope(SupervisorJob() + Dispatchers.Default)
|
||||
@Inject
|
||||
class ServerService(
|
||||
private val serverHostPreferences: ServerHostPreferences,
|
||||
) {
|
||||
private val scope = CoroutineScope(SupervisorJob() + Dispatchers.Default)
|
||||
|
||||
private val host = serverHostPreferences.host().stateIn(GlobalScope)
|
||||
private val _initialized = MutableStateFlow(
|
||||
if (host.value) {
|
||||
ServerResult.STARTING
|
||||
} else {
|
||||
ServerResult.UNUSED
|
||||
},
|
||||
)
|
||||
val initialized = _initialized.asStateFlow()
|
||||
private var process: Process? = null
|
||||
private val host = serverHostPreferences.host().stateIn(GlobalScope)
|
||||
private val _initialized = MutableStateFlow(
|
||||
if (host.value) {
|
||||
ServerResult.STARTING
|
||||
} else {
|
||||
ServerResult.UNUSED
|
||||
},
|
||||
)
|
||||
val initialized = _initialized.asStateFlow()
|
||||
private var process: Process? = null
|
||||
|
||||
fun startAnyway() {
|
||||
_initialized.value = ServerResult.UNUSED
|
||||
}
|
||||
fun startAnyway() {
|
||||
_initialized.value = ServerResult.UNUSED
|
||||
}
|
||||
|
||||
@Throws(IOException::class)
|
||||
private suspend fun copyJar(jarFile: Path) {
|
||||
javaClass.getResourceAsStream("/Tachidesk.jar")?.source()
|
||||
?.copyTo(FileSystem.SYSTEM.sink(jarFile).buffer())
|
||||
}
|
||||
@Throws(IOException::class)
|
||||
private suspend fun copyJar(jarFile: Path) {
|
||||
javaClass.getResourceAsStream("/Tachidesk.jar")?.source()
|
||||
?.copyTo(FileSystem.SYSTEM.sink(jarFile).buffer())
|
||||
}
|
||||
|
||||
private fun getJavaFromPath(javaPath: Path): String? {
|
||||
val javaExeFile = javaPath.resolve("java.exe").toNioPath()
|
||||
val javaUnixFile = javaPath.resolve("java").toNioPath()
|
||||
return when {
|
||||
javaExeFile.exists() && javaExeFile.isExecutable() -> javaExeFile.absolutePathString()
|
||||
javaUnixFile.exists() && javaUnixFile.isExecutable() -> javaUnixFile.absolutePathString()
|
||||
else -> null
|
||||
}
|
||||
}
|
||||
|
||||
private fun getRuntimeJava(): String? = System.getProperty("java.home")?.let { getJavaFromPath(it.toPath().resolve("bin")) }
|
||||
|
||||
private fun getPossibleJava(): String? =
|
||||
System.getProperty("java.library.path")?.split(pathSeparatorChar)
|
||||
.orEmpty()
|
||||
.asSequence()
|
||||
.mapNotNull {
|
||||
val file = it.toPath()
|
||||
if (file.toString().contains("java") || file.toString().contains("jdk")) {
|
||||
if (file.name.equals("bin", true)) {
|
||||
file
|
||||
} else {
|
||||
file.resolve("bin")
|
||||
}
|
||||
} else {
|
||||
null
|
||||
}
|
||||
}
|
||||
.mapNotNull { getJavaFromPath(it) }
|
||||
.firstOrNull()
|
||||
|
||||
private suspend fun runService() {
|
||||
process?.destroy()
|
||||
withIOContext {
|
||||
process?.waitFor()
|
||||
}
|
||||
_initialized.value = if (host.value) {
|
||||
ServerResult.STARTING
|
||||
} else {
|
||||
ServerResult.UNUSED
|
||||
return
|
||||
}
|
||||
|
||||
val jarFile = userDataDir / "Tachidesk.jar"
|
||||
if (!FileSystem.SYSTEM.exists(jarFile)) {
|
||||
log.info { "Copying server to resources" }
|
||||
withIOContext { copyJar(jarFile) }
|
||||
} else {
|
||||
try {
|
||||
val jarVersion = withIOContext {
|
||||
JarInputStream(FileSystem.SYSTEM.source(jarFile).buffer().inputStream()).use { jar ->
|
||||
jar.manifest?.mainAttributes?.getValue("JUI-KEY")?.toIntOrNull()
|
||||
}
|
||||
}
|
||||
|
||||
if (jarVersion != BuildKonfig.SERVER_CODE) {
|
||||
log.info { "Updating server file from resources" }
|
||||
withIOContext { copyJar(jarFile) }
|
||||
}
|
||||
} catch (e: IOException) {
|
||||
log.error(e) {
|
||||
"Error accessing server jar, cannot update server, ${BuildKonfig.NAME} may not work properly"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
val javaPath = getRuntimeJava() ?: getPossibleJava() ?: "java"
|
||||
log.info { "Starting server with $javaPath" }
|
||||
val properties = serverHostPreferences.properties()
|
||||
log.info { "Using server properties:\n" + properties.joinToString(separator = "\n") }
|
||||
|
||||
withIOContext {
|
||||
val reader: Reader
|
||||
process = ProcessBuilder(javaPath, *properties, "-jar", jarFile.toString())
|
||||
.redirectErrorStream(true)
|
||||
.start()
|
||||
.also {
|
||||
reader = it.inputStream.reader()
|
||||
}
|
||||
log.info { "Server started successfully" }
|
||||
val log = logging("Server")
|
||||
reader.forEachLine {
|
||||
if (_initialized.value == ServerResult.STARTING) {
|
||||
when {
|
||||
it.contains("Javalin started") ->
|
||||
_initialized.value = ServerResult.STARTED
|
||||
|
||||
it.contains("Javalin has stopped") ->
|
||||
_initialized.value = ServerResult.FAILED
|
||||
}
|
||||
}
|
||||
log.info { it }
|
||||
}
|
||||
if (_initialized.value == ServerResult.STARTING) {
|
||||
_initialized.value = ServerResult.FAILED
|
||||
}
|
||||
log.info { "Server closed" }
|
||||
val exitVal = process?.waitFor()
|
||||
log.info { "Process exitValue: $exitVal" }
|
||||
process = null
|
||||
}
|
||||
}
|
||||
|
||||
fun startServer() {
|
||||
scope.coroutineContext.cancelChildren()
|
||||
host
|
||||
.mapLatest {
|
||||
runService()
|
||||
}
|
||||
.catch {
|
||||
log.error(it) { "Error launching Tachidesk.jar" }
|
||||
if (_initialized.value == ServerResult.STARTING || _initialized.value == ServerResult.STARTED) {
|
||||
_initialized.value = ServerResult.FAILED
|
||||
}
|
||||
}
|
||||
.launchIn(scope)
|
||||
}
|
||||
|
||||
init {
|
||||
Runtime.getRuntime().addShutdownHook(
|
||||
thread(start = false) {
|
||||
process?.destroy()
|
||||
process = null
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
enum class ServerResult {
|
||||
UNUSED,
|
||||
STARTING,
|
||||
STARTED,
|
||||
FAILED,
|
||||
}
|
||||
|
||||
private companion object {
|
||||
private val log = logging()
|
||||
private fun getJavaFromPath(javaPath: Path): String? {
|
||||
val javaExeFile = javaPath.resolve("java.exe").toNioPath()
|
||||
val javaUnixFile = javaPath.resolve("java").toNioPath()
|
||||
return when {
|
||||
javaExeFile.exists() && javaExeFile.isExecutable() -> javaExeFile.absolutePathString()
|
||||
javaUnixFile.exists() && javaUnixFile.isExecutable() -> javaUnixFile.absolutePathString()
|
||||
else -> null
|
||||
}
|
||||
}
|
||||
|
||||
private fun getRuntimeJava(): String? = System.getProperty("java.home")?.let { getJavaFromPath(it.toPath().resolve("bin")) }
|
||||
|
||||
private fun getPossibleJava(): String? =
|
||||
System.getProperty("java.library.path")?.split(pathSeparatorChar)
|
||||
.orEmpty()
|
||||
.asSequence()
|
||||
.mapNotNull {
|
||||
val file = it.toPath()
|
||||
if (file.toString().contains("java") || file.toString().contains("jdk")) {
|
||||
if (file.name.equals("bin", true)) {
|
||||
file
|
||||
} else {
|
||||
file.resolve("bin")
|
||||
}
|
||||
} else {
|
||||
null
|
||||
}
|
||||
}
|
||||
.mapNotNull { getJavaFromPath(it) }
|
||||
.firstOrNull()
|
||||
|
||||
private suspend fun runService() {
|
||||
process?.destroy()
|
||||
withIOContext {
|
||||
process?.waitFor()
|
||||
}
|
||||
_initialized.value = if (host.value) {
|
||||
ServerResult.STARTING
|
||||
} else {
|
||||
ServerResult.UNUSED
|
||||
return
|
||||
}
|
||||
|
||||
val jarFile = userDataDir / "Tachidesk.jar"
|
||||
if (!FileSystem.SYSTEM.exists(jarFile)) {
|
||||
log.info { "Copying server to resources" }
|
||||
withIOContext { copyJar(jarFile) }
|
||||
} else {
|
||||
try {
|
||||
val jarVersion = withIOContext {
|
||||
JarInputStream(FileSystem.SYSTEM.source(jarFile).buffer().inputStream()).use { jar ->
|
||||
jar.manifest?.mainAttributes?.getValue("JUI-KEY")?.toIntOrNull()
|
||||
}
|
||||
}
|
||||
|
||||
if (jarVersion != BuildKonfig.SERVER_CODE) {
|
||||
log.info { "Updating server file from resources" }
|
||||
withIOContext { copyJar(jarFile) }
|
||||
}
|
||||
} catch (e: IOException) {
|
||||
log.error(e) {
|
||||
"Error accessing server jar, cannot update server, ${BuildKonfig.NAME} may not work properly"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
val javaPath = getRuntimeJava() ?: getPossibleJava() ?: "java"
|
||||
log.info { "Starting server with $javaPath" }
|
||||
val properties = serverHostPreferences.properties()
|
||||
log.info { "Using server properties:\n" + properties.joinToString(separator = "\n") }
|
||||
|
||||
withIOContext {
|
||||
val reader: Reader
|
||||
process = ProcessBuilder(javaPath, *properties, "-jar", jarFile.toString())
|
||||
.redirectErrorStream(true)
|
||||
.start()
|
||||
.also {
|
||||
reader = it.inputStream.reader()
|
||||
}
|
||||
log.info { "Server started successfully" }
|
||||
val log = logging("Server")
|
||||
reader.forEachLine {
|
||||
if (_initialized.value == ServerResult.STARTING) {
|
||||
when {
|
||||
it.contains("Javalin started") ->
|
||||
_initialized.value = ServerResult.STARTED
|
||||
|
||||
it.contains("Javalin has stopped") ->
|
||||
_initialized.value = ServerResult.FAILED
|
||||
}
|
||||
}
|
||||
log.info { it }
|
||||
}
|
||||
if (_initialized.value == ServerResult.STARTING) {
|
||||
_initialized.value = ServerResult.FAILED
|
||||
}
|
||||
log.info { "Server closed" }
|
||||
val exitVal = process?.waitFor()
|
||||
log.info { "Process exitValue: $exitVal" }
|
||||
process = null
|
||||
}
|
||||
}
|
||||
|
||||
fun startServer() {
|
||||
scope.coroutineContext.cancelChildren()
|
||||
host
|
||||
.mapLatest {
|
||||
runService()
|
||||
}
|
||||
.catch {
|
||||
log.error(it) { "Error launching Tachidesk.jar" }
|
||||
if (_initialized.value == ServerResult.STARTING || _initialized.value == ServerResult.STARTED) {
|
||||
_initialized.value = ServerResult.FAILED
|
||||
}
|
||||
}
|
||||
.launchIn(scope)
|
||||
}
|
||||
|
||||
init {
|
||||
Runtime.getRuntime().addShutdownHook(
|
||||
thread(start = false) {
|
||||
process?.destroy()
|
||||
process = null
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
enum class ServerResult {
|
||||
UNUSED,
|
||||
STARTING,
|
||||
STARTED,
|
||||
FAILED,
|
||||
}
|
||||
|
||||
private companion object {
|
||||
private val log = logging()
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user