mirror of
https://github.com/Suwayomi/TachideskJUI.git
synced 2025-12-10 06:42:05 +01:00
Format round 2
This commit is contained in:
@@ -29,26 +29,26 @@ class ServerListeners @Inject constructor() {
|
||||
private fun <T> Flow<T>.startWith(value: T) = onStart { emit(value) }
|
||||
|
||||
private val _mangaListener = MutableSharedFlow<List<Long>>(
|
||||
extraBufferCapacity = Channel.UNLIMITED
|
||||
extraBufferCapacity = Channel.UNLIMITED,
|
||||
)
|
||||
val mangaListener = _mangaListener.asSharedFlow()
|
||||
|
||||
private val _chapterIndexesListener = MutableSharedFlow<Pair<Long, List<Int>?>>(
|
||||
extraBufferCapacity = Channel.UNLIMITED
|
||||
extraBufferCapacity = Channel.UNLIMITED,
|
||||
)
|
||||
val chapterIndexesListener = _chapterIndexesListener.asSharedFlow()
|
||||
|
||||
private val _chapterIdsListener = MutableSharedFlow<Pair<Long?, List<Long>>>(
|
||||
extraBufferCapacity = Channel.UNLIMITED
|
||||
extraBufferCapacity = Channel.UNLIMITED,
|
||||
)
|
||||
val chapterIdsListener = _chapterIdsListener.asSharedFlow()
|
||||
|
||||
private val categoryMangaListener = MutableSharedFlow<Long>(
|
||||
extraBufferCapacity = Channel.UNLIMITED
|
||||
extraBufferCapacity = Channel.UNLIMITED,
|
||||
)
|
||||
|
||||
private val extensionListener = MutableSharedFlow<List<String>>(
|
||||
extraBufferCapacity = Channel.UNLIMITED
|
||||
extraBufferCapacity = Channel.UNLIMITED,
|
||||
)
|
||||
|
||||
fun <T> combineMangaUpdates(flow: Flow<T>, predate: (suspend (List<Long>) -> Boolean)? = null) =
|
||||
@@ -86,7 +86,7 @@ class ServerListeners @Inject constructor() {
|
||||
fun <T> combineChapters(
|
||||
flow: Flow<T>,
|
||||
indexPredate: (suspend (Long, List<Int>?) -> Boolean)? = null,
|
||||
idPredate: (suspend (Long?, List<Long>) -> Boolean)? = null
|
||||
idPredate: (suspend (Long?, List<Long>) -> Boolean)? = null,
|
||||
): Flow<T> {
|
||||
val indexListener = if (indexPredate != null) {
|
||||
_chapterIndexesListener.filter { indexPredate(it.first, it.second) }.startWith(Unit)
|
||||
|
||||
@@ -11,5 +11,5 @@ import kotlinx.serialization.Serializable
|
||||
@Serializable
|
||||
data class BackupValidationResult(
|
||||
val missingSources: List<String>,
|
||||
val missingTrackers: List<String>
|
||||
val missingTrackers: List<String>,
|
||||
)
|
||||
|
||||
@@ -31,19 +31,19 @@ interface BackupRepository {
|
||||
@POST("api/v1/backup/import/file")
|
||||
fun importBackupFile(
|
||||
@Part("") formData: List<PartData>,
|
||||
@ReqBuilder block: HttpRequestBuilder.() -> Unit = {}
|
||||
@ReqBuilder block: HttpRequestBuilder.() -> Unit = {},
|
||||
): Flow<HttpResponse>
|
||||
|
||||
@Multipart
|
||||
@POST("api/v1/backup/validate/file")
|
||||
fun validateBackupFile(
|
||||
@Part("") formData: List<PartData>,
|
||||
@ReqBuilder block: HttpRequestBuilder.() -> Unit = {}
|
||||
@ReqBuilder block: HttpRequestBuilder.() -> Unit = {},
|
||||
): Flow<BackupValidationResult>
|
||||
|
||||
@GET("api/v1/backup/export/file")
|
||||
fun exportBackupFile(
|
||||
@ReqBuilder block: HttpRequestBuilder.() -> Unit = {}
|
||||
@ReqBuilder block: HttpRequestBuilder.() -> Unit = {},
|
||||
): Flow<HttpResponse>
|
||||
|
||||
companion object {
|
||||
@@ -54,7 +54,7 @@ interface BackupRepository {
|
||||
Headers.build {
|
||||
append(HttpHeaders.ContentType, ContentType.MultiPart.FormData.toString())
|
||||
append(HttpHeaders.ContentDisposition, "filename=backup.proto.gz")
|
||||
}
|
||||
},
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -29,7 +29,7 @@ import org.lighthousegames.logging.logging
|
||||
@OptIn(DelicateCoroutinesApi::class)
|
||||
abstract class WebsocketService(
|
||||
protected val serverPreferences: ServerPreferences,
|
||||
protected val client: Http
|
||||
protected val client: Http,
|
||||
) {
|
||||
protected val json = Json {
|
||||
ignoreUnknownKeys = true
|
||||
@@ -62,7 +62,7 @@ abstract class WebsocketService(
|
||||
if (serverUrl.protocol == URLProtocol.HTTPS) {
|
||||
url.protocol = URLProtocol.WSS
|
||||
}
|
||||
}
|
||||
},
|
||||
) {
|
||||
errorConnectionCount = 0
|
||||
_status.value = Status.RUNNING
|
||||
@@ -96,13 +96,13 @@ abstract class WebsocketService(
|
||||
enum class Status {
|
||||
STARTING,
|
||||
RUNNING,
|
||||
STOPPED
|
||||
STOPPED,
|
||||
}
|
||||
|
||||
enum class Actions {
|
||||
STOP,
|
||||
START,
|
||||
RESTART
|
||||
RESTART,
|
||||
}
|
||||
|
||||
private companion object {
|
||||
|
||||
@@ -19,7 +19,7 @@ import org.lighthousegames.logging.logging
|
||||
|
||||
class AddMangaToCategory @Inject constructor(
|
||||
private val categoryRepository: CategoryRepository,
|
||||
private val serverListeners: ServerListeners
|
||||
private val serverListeners: ServerListeners,
|
||||
) {
|
||||
|
||||
suspend fun await(mangaId: Long, categoryId: Long, onError: suspend (Throwable) -> Unit = {}) = asFlow(mangaId, categoryId)
|
||||
|
||||
@@ -17,7 +17,7 @@ import org.lighthousegames.logging.logging
|
||||
|
||||
class GetMangaListFromCategory @Inject constructor(
|
||||
private val categoryRepository: CategoryRepository,
|
||||
private val serverListeners: ServerListeners
|
||||
private val serverListeners: ServerListeners,
|
||||
) {
|
||||
|
||||
suspend fun await(categoryId: Long, onError: suspend (Throwable) -> Unit = {}) = asFlow(categoryId)
|
||||
@@ -37,11 +37,11 @@ class GetMangaListFromCategory @Inject constructor(
|
||||
.singleOrNull()
|
||||
|
||||
fun asFlow(categoryId: Long) = serverListeners.combineCategoryManga(
|
||||
categoryRepository.getMangaFromCategory(categoryId)
|
||||
categoryRepository.getMangaFromCategory(categoryId),
|
||||
) { categoryId == it }
|
||||
|
||||
fun asFlow(category: Category) = serverListeners.combineCategoryManga(
|
||||
categoryRepository.getMangaFromCategory(category.id)
|
||||
categoryRepository.getMangaFromCategory(category.id),
|
||||
) { category.id == it }
|
||||
|
||||
companion object {
|
||||
|
||||
@@ -17,7 +17,7 @@ class ModifyCategory @Inject constructor(private val categoryRepository: Categor
|
||||
|
||||
suspend fun await(categoryId: Long, name: String, onError: suspend (Throwable) -> Unit = {}) = asFlow(
|
||||
categoryId = categoryId,
|
||||
name = name
|
||||
name = name,
|
||||
).catch {
|
||||
onError(it)
|
||||
log.warn(it) { "Failed to modify category $categoryId with options: name=$name" }
|
||||
@@ -25,7 +25,7 @@ class ModifyCategory @Inject constructor(private val categoryRepository: Categor
|
||||
|
||||
suspend fun await(category: Category, name: String? = null, onError: suspend (Throwable) -> Unit = {}) = asFlow(
|
||||
category = category,
|
||||
name = name
|
||||
name = name,
|
||||
).catch {
|
||||
onError(it)
|
||||
log.warn(it) { "Failed to modify category ${category.name} with options: name=$name" }
|
||||
@@ -33,12 +33,12 @@ class ModifyCategory @Inject constructor(private val categoryRepository: Categor
|
||||
|
||||
fun asFlow(categoryId: Long, name: String) = categoryRepository.modifyCategory(
|
||||
categoryId = categoryId,
|
||||
name = name
|
||||
name = name,
|
||||
)
|
||||
|
||||
fun asFlow(category: Category, name: String? = null) = categoryRepository.modifyCategory(
|
||||
categoryId = category.id,
|
||||
name = name ?: category.name
|
||||
name = name ?: category.name,
|
||||
)
|
||||
|
||||
companion object {
|
||||
|
||||
@@ -19,7 +19,7 @@ import org.lighthousegames.logging.logging
|
||||
|
||||
class RemoveMangaFromCategory @Inject constructor(
|
||||
private val categoryRepository: CategoryRepository,
|
||||
private val serverListeners: ServerListeners
|
||||
private val serverListeners: ServerListeners,
|
||||
) {
|
||||
|
||||
suspend fun await(mangaId: Long, categoryId: Long, onError: suspend (Throwable) -> Unit = {}) = asFlow(mangaId, categoryId)
|
||||
|
||||
@@ -19,7 +19,7 @@ class UpdateCategoryMeta @Inject constructor(private val categoryRepository: Cat
|
||||
suspend fun await(
|
||||
category: Category,
|
||||
example: Int = category.meta.example,
|
||||
onError: suspend (Throwable) -> Unit = {}
|
||||
onError: suspend (Throwable) -> Unit = {},
|
||||
) = asFlow(category, example)
|
||||
.catch {
|
||||
onError(it)
|
||||
@@ -29,13 +29,13 @@ class UpdateCategoryMeta @Inject constructor(private val categoryRepository: Cat
|
||||
|
||||
fun asFlow(
|
||||
category: Category,
|
||||
example: Int = category.meta.example
|
||||
example: Int = category.meta.example,
|
||||
) = flow {
|
||||
if (example != category.meta.example) {
|
||||
categoryRepository.updateCategoryMeta(
|
||||
category.id,
|
||||
"example",
|
||||
example.toString()
|
||||
example.toString(),
|
||||
).collect()
|
||||
}
|
||||
emit(Unit)
|
||||
|
||||
@@ -16,11 +16,11 @@ data class Category(
|
||||
val order: Int,
|
||||
val name: String,
|
||||
val default: Boolean,
|
||||
val meta: CategoryMeta
|
||||
val meta: CategoryMeta,
|
||||
)
|
||||
|
||||
@Serializable
|
||||
@Immutable
|
||||
data class CategoryMeta(
|
||||
val example: Int = 0
|
||||
val example: Int = 0,
|
||||
)
|
||||
|
||||
@@ -21,19 +21,19 @@ import kotlinx.coroutines.flow.Flow
|
||||
interface CategoryRepository {
|
||||
@GET("api/v1/manga/{mangaId}/category/")
|
||||
fun getMangaCategories(
|
||||
@Path("mangaId") mangaId: Long
|
||||
@Path("mangaId") mangaId: Long,
|
||||
): Flow<List<Category>>
|
||||
|
||||
@GET("api/v1/manga/{mangaId}/category/{categoryId}")
|
||||
fun addMangaToCategory(
|
||||
@Path("mangaId") mangaId: Long,
|
||||
@Path("categoryId") categoryId: Long
|
||||
@Path("categoryId") categoryId: Long,
|
||||
): Flow<HttpResponse>
|
||||
|
||||
@DELETE("api/v1/manga/{mangaId}/category/{categoryId}")
|
||||
fun removeMangaFromCategory(
|
||||
@Path("mangaId") mangaId: Long,
|
||||
@Path("categoryId") categoryId: Long
|
||||
@Path("categoryId") categoryId: Long,
|
||||
): Flow<HttpResponse>
|
||||
|
||||
@GET("api/v1/category/")
|
||||
@@ -42,31 +42,31 @@ interface CategoryRepository {
|
||||
@FormUrlEncoded
|
||||
@POST("api/v1/category/")
|
||||
fun createCategory(
|
||||
@Field("name") name: String
|
||||
@Field("name") name: String,
|
||||
): Flow<HttpResponse>
|
||||
|
||||
@FormUrlEncoded
|
||||
@PATCH("api/v1/category/{categoryId}")
|
||||
fun modifyCategory(
|
||||
@Path("categoryId") categoryId: Long,
|
||||
@Field("name") name: String
|
||||
@Field("name") name: String,
|
||||
): Flow<HttpResponse>
|
||||
|
||||
@FormUrlEncoded
|
||||
@PATCH("api/v1/category/reorder")
|
||||
fun reorderCategory(
|
||||
@Field("to") to: Int,
|
||||
@Field("from") from: Int
|
||||
@Field("from") from: Int,
|
||||
): Flow<HttpResponse>
|
||||
|
||||
@DELETE("api/v1/category/{categoryId}")
|
||||
fun deleteCategory(
|
||||
@Path("categoryId") categoryId: Long
|
||||
@Path("categoryId") categoryId: Long,
|
||||
): Flow<HttpResponse>
|
||||
|
||||
@GET("api/v1/category/{categoryId}")
|
||||
fun getMangaFromCategory(
|
||||
@Path("categoryId") categoryId: Long
|
||||
@Path("categoryId") categoryId: Long,
|
||||
): Flow<List<Manga>>
|
||||
|
||||
@FormUrlEncoded
|
||||
@@ -74,6 +74,6 @@ interface CategoryRepository {
|
||||
fun updateCategoryMeta(
|
||||
@Path("categoryId") categoryId: Long,
|
||||
@Field("key") key: String,
|
||||
@Field("value") value: String
|
||||
@Field("value") value: String,
|
||||
): Flow<HttpResponse>
|
||||
}
|
||||
|
||||
@@ -22,7 +22,7 @@ import kotlin.jvm.JvmName
|
||||
|
||||
class BatchUpdateChapter @Inject constructor(
|
||||
private val chapterRepository: ChapterRepository,
|
||||
private val serverListeners: ServerListeners
|
||||
private val serverListeners: ServerListeners,
|
||||
) {
|
||||
|
||||
@JvmName("awaitChapters")
|
||||
@@ -33,7 +33,7 @@ class BatchUpdateChapter @Inject constructor(
|
||||
isBookmarked: Boolean? = null,
|
||||
lastPageRead: Int? = null,
|
||||
delete: Boolean? = null,
|
||||
onError: suspend (Throwable) -> Unit = {}
|
||||
onError: suspend (Throwable) -> Unit = {},
|
||||
) = asFlow(mangaId, chapters, isRead, isBookmarked, lastPageRead, delete)
|
||||
.catch {
|
||||
onError(it)
|
||||
@@ -48,7 +48,7 @@ class BatchUpdateChapter @Inject constructor(
|
||||
isBookmarked: Boolean? = null,
|
||||
lastPageRead: Int? = null,
|
||||
delete: Boolean? = null,
|
||||
onError: suspend (Throwable) -> Unit = {}
|
||||
onError: suspend (Throwable) -> Unit = {},
|
||||
) = asFlow(mangaId, chapterIds, isRead, isBookmarked, lastPageRead, delete)
|
||||
.catch {
|
||||
onError(it)
|
||||
@@ -64,7 +64,7 @@ class BatchUpdateChapter @Inject constructor(
|
||||
isBookmarked: Boolean? = null,
|
||||
lastPageRead: Int? = null,
|
||||
delete: Boolean? = null,
|
||||
onError: suspend (Throwable) -> Unit = {}
|
||||
onError: suspend (Throwable) -> Unit = {},
|
||||
) = asFlow(manga, chapters, isRead, isBookmarked, lastPageRead, delete)
|
||||
.catch {
|
||||
onError(it)
|
||||
@@ -79,7 +79,7 @@ class BatchUpdateChapter @Inject constructor(
|
||||
isBookmarked: Boolean? = null,
|
||||
lastPageRead: Int? = null,
|
||||
delete: Boolean? = null,
|
||||
onError: suspend (Throwable) -> Unit = {}
|
||||
onError: suspend (Throwable) -> Unit = {},
|
||||
) = asFlow(manga, chapterIds, isRead, isBookmarked, lastPageRead, delete)
|
||||
.catch {
|
||||
onError(it)
|
||||
@@ -94,7 +94,7 @@ class BatchUpdateChapter @Inject constructor(
|
||||
isBookmarked: Boolean? = null,
|
||||
lastPageRead: Int? = null,
|
||||
delete: Boolean? = null,
|
||||
onError: suspend (Throwable) -> Unit = {}
|
||||
onError: suspend (Throwable) -> Unit = {},
|
||||
) = asFlow(chapters, isRead, isBookmarked, lastPageRead, delete)
|
||||
.catch {
|
||||
onError(it)
|
||||
@@ -108,7 +108,7 @@ class BatchUpdateChapter @Inject constructor(
|
||||
isBookmarked: Boolean? = null,
|
||||
lastPageRead: Int? = null,
|
||||
delete: Boolean? = null,
|
||||
onError: suspend (Throwable) -> Unit = {}
|
||||
onError: suspend (Throwable) -> Unit = {},
|
||||
) = asFlow(chapterIds, isRead, isBookmarked, lastPageRead, delete)
|
||||
.catch {
|
||||
onError(it)
|
||||
@@ -123,14 +123,14 @@ class BatchUpdateChapter @Inject constructor(
|
||||
isRead: Boolean? = null,
|
||||
isBookmarked: Boolean? = null,
|
||||
lastPageRead: Int? = null,
|
||||
delete: Boolean? = null
|
||||
delete: Boolean? = null,
|
||||
) = getFlow(
|
||||
mangaId = mangaId,
|
||||
chapterIds = chapters.map { it.id },
|
||||
isRead = isRead,
|
||||
isBookmarked = isBookmarked,
|
||||
lastPageRead = lastPageRead,
|
||||
delete = delete
|
||||
delete = delete,
|
||||
)
|
||||
|
||||
fun asFlow(
|
||||
@@ -139,14 +139,14 @@ class BatchUpdateChapter @Inject constructor(
|
||||
isRead: Boolean? = null,
|
||||
isBookmarked: Boolean? = null,
|
||||
lastPageRead: Int? = null,
|
||||
delete: Boolean? = null
|
||||
delete: Boolean? = null,
|
||||
) = getFlow(
|
||||
mangaId = mangaId,
|
||||
chapterIds = chapterIds,
|
||||
isRead = isRead,
|
||||
isBookmarked = isBookmarked,
|
||||
lastPageRead = lastPageRead,
|
||||
delete = delete
|
||||
delete = delete,
|
||||
)
|
||||
|
||||
@JvmName("asFlowChapters")
|
||||
@@ -156,14 +156,14 @@ class BatchUpdateChapter @Inject constructor(
|
||||
isRead: Boolean? = null,
|
||||
isBookmarked: Boolean? = null,
|
||||
lastPageRead: Int? = null,
|
||||
delete: Boolean? = null
|
||||
delete: Boolean? = null,
|
||||
) = getFlow(
|
||||
mangaId = manga.id,
|
||||
chapterIds = chapters.map { it.id },
|
||||
isRead = isRead,
|
||||
isBookmarked = isBookmarked,
|
||||
lastPageRead = lastPageRead,
|
||||
delete = delete
|
||||
delete = delete,
|
||||
)
|
||||
|
||||
fun asFlow(
|
||||
@@ -172,14 +172,14 @@ class BatchUpdateChapter @Inject constructor(
|
||||
isRead: Boolean? = null,
|
||||
isBookmarked: Boolean? = null,
|
||||
lastPageRead: Int? = null,
|
||||
delete: Boolean? = null
|
||||
delete: Boolean? = null,
|
||||
) = getFlow(
|
||||
mangaId = manga.id,
|
||||
chapterIds = chapterIds,
|
||||
isRead = isRead,
|
||||
isBookmarked = isBookmarked,
|
||||
lastPageRead = lastPageRead,
|
||||
delete = delete
|
||||
delete = delete,
|
||||
)
|
||||
|
||||
@JvmName("asFlowChapters")
|
||||
@@ -188,14 +188,14 @@ class BatchUpdateChapter @Inject constructor(
|
||||
isRead: Boolean? = null,
|
||||
isBookmarked: Boolean? = null,
|
||||
lastPageRead: Int? = null,
|
||||
delete: Boolean? = null
|
||||
delete: Boolean? = null,
|
||||
) = getFlow(
|
||||
mangaId = null,
|
||||
chapterIds = chapters.map { it.id },
|
||||
isRead = isRead,
|
||||
isBookmarked = isBookmarked,
|
||||
lastPageRead = lastPageRead,
|
||||
delete = delete
|
||||
delete = delete,
|
||||
)
|
||||
|
||||
fun asFlow(
|
||||
@@ -203,14 +203,14 @@ class BatchUpdateChapter @Inject constructor(
|
||||
isRead: Boolean? = null,
|
||||
isBookmarked: Boolean? = null,
|
||||
lastPageRead: Int? = null,
|
||||
delete: Boolean? = null
|
||||
delete: Boolean? = null,
|
||||
) = getFlow(
|
||||
mangaId = null,
|
||||
chapterIds = chapterIds,
|
||||
isRead = isRead,
|
||||
isBookmarked = isBookmarked,
|
||||
lastPageRead = lastPageRead,
|
||||
delete = delete
|
||||
delete = delete,
|
||||
)
|
||||
|
||||
private fun getFlow(
|
||||
@@ -219,7 +219,7 @@ class BatchUpdateChapter @Inject constructor(
|
||||
isRead: Boolean? = null,
|
||||
isBookmarked: Boolean? = null,
|
||||
lastPageRead: Int? = null,
|
||||
delete: Boolean? = null
|
||||
delete: Boolean? = null,
|
||||
) = if (mangaId != null) {
|
||||
chapterRepository.batchUpdateChapter(
|
||||
mangaId,
|
||||
@@ -229,9 +229,9 @@ class BatchUpdateChapter @Inject constructor(
|
||||
isRead = isRead,
|
||||
isBookmarked = isBookmarked,
|
||||
lastPageRead = lastPageRead,
|
||||
delete = delete
|
||||
)
|
||||
)
|
||||
delete = delete,
|
||||
),
|
||||
),
|
||||
)
|
||||
} else {
|
||||
chapterRepository.batchUpdateChapter(
|
||||
@@ -241,9 +241,9 @@ class BatchUpdateChapter @Inject constructor(
|
||||
isRead = isRead,
|
||||
isBookmarked = isBookmarked,
|
||||
lastPageRead = lastPageRead,
|
||||
delete = delete
|
||||
)
|
||||
)
|
||||
delete = delete,
|
||||
),
|
||||
),
|
||||
)
|
||||
}.onEach {
|
||||
serverListeners.updateChapters(mangaId, chapterIds)
|
||||
|
||||
@@ -18,7 +18,7 @@ import org.lighthousegames.logging.logging
|
||||
|
||||
class DeleteChapterDownload @Inject constructor(
|
||||
private val chapterRepository: ChapterRepository,
|
||||
private val serverListeners: ServerListeners
|
||||
private val serverListeners: ServerListeners,
|
||||
) {
|
||||
|
||||
suspend fun await(mangaId: Long, index: Int, onError: suspend (Throwable) -> Unit = {}) = asFlow(mangaId, index)
|
||||
|
||||
@@ -18,7 +18,7 @@ import org.lighthousegames.logging.logging
|
||||
|
||||
class GetChapter @Inject constructor(
|
||||
private val chapterRepository: ChapterRepository,
|
||||
private val serverListeners: ServerListeners
|
||||
private val serverListeners: ServerListeners,
|
||||
) {
|
||||
|
||||
suspend fun await(mangaId: Long, index: Int, onError: suspend (Throwable) -> Unit = {}) = asFlow(mangaId, index)
|
||||
@@ -50,7 +50,7 @@ class GetChapter @Inject constructor(
|
||||
indexPredate = { id, chapterIndexes ->
|
||||
id == mangaId && (chapterIndexes == null || index in chapterIndexes)
|
||||
},
|
||||
idPredate = { id, _ -> id == mangaId }
|
||||
idPredate = { id, _ -> id == mangaId },
|
||||
)
|
||||
|
||||
fun asFlow(manga: Manga, index: Int) = serverListeners.combineChapters(
|
||||
@@ -58,7 +58,7 @@ class GetChapter @Inject constructor(
|
||||
indexPredate = { id, chapterIndexes ->
|
||||
id == manga.id && (chapterIndexes == null || index in chapterIndexes)
|
||||
},
|
||||
idPredate = { id, _ -> id == manga.id }
|
||||
idPredate = { id, _ -> id == manga.id },
|
||||
)
|
||||
|
||||
fun asFlow(chapter: Chapter) = serverListeners.combineChapters(
|
||||
@@ -66,7 +66,7 @@ class GetChapter @Inject constructor(
|
||||
indexPredate = { id, chapterIndexes ->
|
||||
id == chapter.mangaId && (chapterIndexes == null || chapter.index in chapterIndexes)
|
||||
},
|
||||
idPredate = { id, _ -> id == chapter.mangaId }
|
||||
idPredate = { id, _ -> id == chapter.mangaId },
|
||||
)
|
||||
|
||||
companion object {
|
||||
|
||||
@@ -22,7 +22,7 @@ class GetChapterPage @Inject constructor(private val chapterRepository: ChapterR
|
||||
index: Int,
|
||||
pageNum: Int,
|
||||
block: HttpRequestBuilder.() -> Unit,
|
||||
onError: suspend (Throwable) -> Unit = {}
|
||||
onError: suspend (Throwable) -> Unit = {},
|
||||
) = asFlow(mangaId, index, pageNum, block)
|
||||
.catch {
|
||||
onError(it)
|
||||
@@ -35,7 +35,7 @@ class GetChapterPage @Inject constructor(private val chapterRepository: ChapterR
|
||||
index: Int,
|
||||
pageNum: Int,
|
||||
block: HttpRequestBuilder.() -> Unit,
|
||||
onError: suspend (Throwable) -> Unit = {}
|
||||
onError: suspend (Throwable) -> Unit = {},
|
||||
) = asFlow(manga, index, pageNum, block)
|
||||
.catch {
|
||||
onError(it)
|
||||
@@ -47,7 +47,7 @@ class GetChapterPage @Inject constructor(private val chapterRepository: ChapterR
|
||||
chapter: Chapter,
|
||||
pageNum: Int,
|
||||
block: HttpRequestBuilder.() -> Unit,
|
||||
onError: suspend (Throwable) -> Unit = {}
|
||||
onError: suspend (Throwable) -> Unit = {},
|
||||
) = asFlow(chapter, pageNum, block)
|
||||
.catch {
|
||||
onError(it)
|
||||
@@ -59,20 +59,20 @@ class GetChapterPage @Inject constructor(private val chapterRepository: ChapterR
|
||||
mangaId: Long,
|
||||
index: Int,
|
||||
pageNum: Int,
|
||||
block: HttpRequestBuilder.() -> Unit
|
||||
block: HttpRequestBuilder.() -> Unit,
|
||||
) = chapterRepository.getPage(mangaId, index, pageNum, block)
|
||||
|
||||
fun asFlow(
|
||||
manga: Manga,
|
||||
index: Int,
|
||||
pageNum: Int,
|
||||
block: HttpRequestBuilder.() -> Unit
|
||||
block: HttpRequestBuilder.() -> Unit,
|
||||
) = chapterRepository.getPage(manga.id, index, pageNum, block)
|
||||
|
||||
fun asFlow(
|
||||
chapter: Chapter,
|
||||
pageNum: Int,
|
||||
block: HttpRequestBuilder.() -> Unit
|
||||
block: HttpRequestBuilder.() -> Unit,
|
||||
) = chapterRepository.getPage(chapter.mangaId, chapter.index, pageNum, block)
|
||||
|
||||
companion object {
|
||||
|
||||
@@ -17,7 +17,7 @@ import org.lighthousegames.logging.logging
|
||||
|
||||
class GetChapters @Inject constructor(
|
||||
private val chapterRepository: ChapterRepository,
|
||||
private val serverListeners: ServerListeners
|
||||
private val serverListeners: ServerListeners,
|
||||
) {
|
||||
|
||||
suspend fun await(mangaId: Long, onError: suspend (Throwable) -> Unit = {}) = asFlow(mangaId)
|
||||
@@ -39,13 +39,13 @@ class GetChapters @Inject constructor(
|
||||
fun asFlow(mangaId: Long) = serverListeners.combineChapters(
|
||||
chapterRepository.getChapters(mangaId),
|
||||
indexPredate = { id, _ -> id == mangaId },
|
||||
idPredate = { id, _ -> id == mangaId }
|
||||
idPredate = { id, _ -> id == mangaId },
|
||||
)
|
||||
|
||||
fun asFlow(manga: Manga) = serverListeners.combineChapters(
|
||||
chapterRepository.getChapters(manga.id),
|
||||
indexPredate = { id, _ -> id == manga.id },
|
||||
idPredate = { id, _ -> id == manga.id }
|
||||
idPredate = { id, _ -> id == manga.id },
|
||||
)
|
||||
|
||||
companion object {
|
||||
|
||||
@@ -17,7 +17,7 @@ import org.lighthousegames.logging.logging
|
||||
|
||||
class RefreshChapters @Inject constructor(
|
||||
private val chapterRepository: ChapterRepository,
|
||||
private val serverListeners: ServerListeners
|
||||
private val serverListeners: ServerListeners,
|
||||
) {
|
||||
|
||||
suspend fun await(mangaId: Long, onError: suspend (Throwable) -> Unit = {}) = asFlow(mangaId)
|
||||
|
||||
@@ -18,14 +18,14 @@ import org.lighthousegames.logging.logging
|
||||
|
||||
class UpdateChapterBookmarked @Inject constructor(
|
||||
private val chapterRepository: ChapterRepository,
|
||||
private val serverListeners: ServerListeners
|
||||
private val serverListeners: ServerListeners,
|
||||
) {
|
||||
|
||||
suspend fun await(
|
||||
mangaId: Long,
|
||||
index: Int,
|
||||
bookmarked: Boolean,
|
||||
onError: suspend (Throwable) -> Unit = {}
|
||||
onError: suspend (Throwable) -> Unit = {},
|
||||
) = asFlow(mangaId, index, bookmarked)
|
||||
.catch {
|
||||
onError(it)
|
||||
@@ -37,7 +37,7 @@ class UpdateChapterBookmarked @Inject constructor(
|
||||
manga: Manga,
|
||||
index: Int,
|
||||
bookmarked: Boolean,
|
||||
onError: suspend (Throwable) -> Unit = {}
|
||||
onError: suspend (Throwable) -> Unit = {},
|
||||
) = asFlow(manga, index, bookmarked)
|
||||
.catch {
|
||||
onError(it)
|
||||
@@ -48,7 +48,7 @@ class UpdateChapterBookmarked @Inject constructor(
|
||||
suspend fun await(
|
||||
chapter: Chapter,
|
||||
bookmarked: Boolean,
|
||||
onError: suspend (Throwable) -> Unit = {}
|
||||
onError: suspend (Throwable) -> Unit = {},
|
||||
) = asFlow(chapter, bookmarked)
|
||||
.catch {
|
||||
onError(it)
|
||||
@@ -59,30 +59,30 @@ class UpdateChapterBookmarked @Inject constructor(
|
||||
fun asFlow(
|
||||
mangaId: Long,
|
||||
index: Int,
|
||||
bookmarked: Boolean
|
||||
bookmarked: Boolean,
|
||||
) = chapterRepository.updateChapter(
|
||||
mangaId = mangaId,
|
||||
chapterIndex = index,
|
||||
bookmarked = bookmarked
|
||||
bookmarked = bookmarked,
|
||||
).onEach { serverListeners.updateChapters(mangaId, index) }
|
||||
|
||||
fun asFlow(
|
||||
manga: Manga,
|
||||
index: Int,
|
||||
bookmarked: Boolean
|
||||
bookmarked: Boolean,
|
||||
) = chapterRepository.updateChapter(
|
||||
mangaId = manga.id,
|
||||
chapterIndex = index,
|
||||
bookmarked = bookmarked
|
||||
bookmarked = bookmarked,
|
||||
).onEach { serverListeners.updateChapters(manga.id, index) }
|
||||
|
||||
fun asFlow(
|
||||
chapter: Chapter,
|
||||
bookmarked: Boolean
|
||||
bookmarked: Boolean,
|
||||
) = chapterRepository.updateChapter(
|
||||
mangaId = chapter.mangaId,
|
||||
chapterIndex = chapter.index,
|
||||
bookmarked = bookmarked
|
||||
bookmarked = bookmarked,
|
||||
).onEach { serverListeners.updateChapters(chapter.mangaId, chapter.index) }
|
||||
|
||||
companion object {
|
||||
|
||||
@@ -18,14 +18,14 @@ import org.lighthousegames.logging.logging
|
||||
|
||||
class UpdateChapterLastPageRead @Inject constructor(
|
||||
private val chapterRepository: ChapterRepository,
|
||||
private val serverListeners: ServerListeners
|
||||
private val serverListeners: ServerListeners,
|
||||
) {
|
||||
|
||||
suspend fun await(
|
||||
mangaId: Long,
|
||||
index: Int,
|
||||
lastPageRead: Int,
|
||||
onError: suspend (Throwable) -> Unit = {}
|
||||
onError: suspend (Throwable) -> Unit = {},
|
||||
) = asFlow(mangaId, index, lastPageRead)
|
||||
.catch {
|
||||
onError(it)
|
||||
@@ -37,7 +37,7 @@ class UpdateChapterLastPageRead @Inject constructor(
|
||||
manga: Manga,
|
||||
index: Int,
|
||||
lastPageRead: Int,
|
||||
onError: suspend (Throwable) -> Unit = {}
|
||||
onError: suspend (Throwable) -> Unit = {},
|
||||
) = asFlow(manga, index, lastPageRead)
|
||||
.catch {
|
||||
onError(it)
|
||||
@@ -48,7 +48,7 @@ class UpdateChapterLastPageRead @Inject constructor(
|
||||
suspend fun await(
|
||||
chapter: Chapter,
|
||||
lastPageRead: Int,
|
||||
onError: suspend (Throwable) -> Unit = {}
|
||||
onError: suspend (Throwable) -> Unit = {},
|
||||
) = asFlow(chapter, lastPageRead)
|
||||
.catch {
|
||||
onError(it)
|
||||
@@ -59,30 +59,30 @@ class UpdateChapterLastPageRead @Inject constructor(
|
||||
fun asFlow(
|
||||
mangaId: Long,
|
||||
index: Int,
|
||||
lastPageRead: Int
|
||||
lastPageRead: Int,
|
||||
) = chapterRepository.updateChapter(
|
||||
mangaId = mangaId,
|
||||
chapterIndex = index,
|
||||
lastPageRead = lastPageRead
|
||||
lastPageRead = lastPageRead,
|
||||
).onEach { serverListeners.updateChapters(mangaId, index) }
|
||||
|
||||
fun asFlow(
|
||||
manga: Manga,
|
||||
index: Int,
|
||||
lastPageRead: Int
|
||||
lastPageRead: Int,
|
||||
) = chapterRepository.updateChapter(
|
||||
mangaId = manga.id,
|
||||
chapterIndex = index,
|
||||
lastPageRead = lastPageRead
|
||||
lastPageRead = lastPageRead,
|
||||
).onEach { serverListeners.updateChapters(manga.id, index) }
|
||||
|
||||
fun asFlow(
|
||||
chapter: Chapter,
|
||||
lastPageRead: Int
|
||||
lastPageRead: Int,
|
||||
) = chapterRepository.updateChapter(
|
||||
mangaId = chapter.mangaId,
|
||||
chapterIndex = chapter.index,
|
||||
lastPageRead = lastPageRead
|
||||
lastPageRead = lastPageRead,
|
||||
).onEach { serverListeners.updateChapters(chapter.mangaId, chapter.index) }
|
||||
|
||||
companion object {
|
||||
|
||||
@@ -18,13 +18,13 @@ import org.lighthousegames.logging.logging
|
||||
|
||||
class UpdateChapterMarkPreviousRead @Inject constructor(
|
||||
private val chapterRepository: ChapterRepository,
|
||||
private val serverListeners: ServerListeners
|
||||
private val serverListeners: ServerListeners,
|
||||
) {
|
||||
|
||||
suspend fun await(
|
||||
mangaId: Long,
|
||||
index: Int,
|
||||
onError: suspend (Throwable) -> Unit = {}
|
||||
onError: suspend (Throwable) -> Unit = {},
|
||||
) = asFlow(mangaId, index)
|
||||
.catch {
|
||||
onError(it)
|
||||
@@ -35,7 +35,7 @@ class UpdateChapterMarkPreviousRead @Inject constructor(
|
||||
suspend fun await(
|
||||
manga: Manga,
|
||||
index: Int,
|
||||
onError: suspend (Throwable) -> Unit = {}
|
||||
onError: suspend (Throwable) -> Unit = {},
|
||||
) = asFlow(manga, index)
|
||||
.catch {
|
||||
onError(it)
|
||||
@@ -45,7 +45,7 @@ class UpdateChapterMarkPreviousRead @Inject constructor(
|
||||
|
||||
suspend fun await(
|
||||
chapter: Chapter,
|
||||
onError: suspend (Throwable) -> Unit = {}
|
||||
onError: suspend (Throwable) -> Unit = {},
|
||||
) = asFlow(chapter)
|
||||
.catch {
|
||||
onError(it)
|
||||
@@ -55,28 +55,28 @@ class UpdateChapterMarkPreviousRead @Inject constructor(
|
||||
|
||||
fun asFlow(
|
||||
mangaId: Long,
|
||||
index: Int
|
||||
index: Int,
|
||||
) = chapterRepository.updateChapter(
|
||||
mangaId = mangaId,
|
||||
chapterIndex = index,
|
||||
markPreviousRead = true
|
||||
markPreviousRead = true,
|
||||
).onEach { serverListeners.updateChapters(mangaId, index) }
|
||||
|
||||
fun asFlow(
|
||||
manga: Manga,
|
||||
index: Int
|
||||
index: Int,
|
||||
) = chapterRepository.updateChapter(
|
||||
mangaId = manga.id,
|
||||
chapterIndex = index,
|
||||
markPreviousRead = true
|
||||
markPreviousRead = true,
|
||||
).onEach { serverListeners.updateChapters(manga.id, index) }
|
||||
|
||||
fun asFlow(
|
||||
chapter: Chapter
|
||||
chapter: Chapter,
|
||||
) = chapterRepository.updateChapter(
|
||||
mangaId = chapter.mangaId,
|
||||
chapterIndex = chapter.index,
|
||||
markPreviousRead = true
|
||||
markPreviousRead = true,
|
||||
).onEach { serverListeners.updateChapters(chapter.mangaId, chapter.index) }
|
||||
|
||||
companion object {
|
||||
|
||||
@@ -17,13 +17,13 @@ import org.lighthousegames.logging.logging
|
||||
|
||||
class UpdateChapterMeta @Inject constructor(
|
||||
private val chapterRepository: ChapterRepository,
|
||||
private val serverListeners: ServerListeners
|
||||
private val serverListeners: ServerListeners,
|
||||
) {
|
||||
|
||||
suspend fun await(
|
||||
chapter: Chapter,
|
||||
pageOffset: Int = chapter.meta.juiPageOffset,
|
||||
onError: suspend (Throwable) -> Unit = {}
|
||||
onError: suspend (Throwable) -> Unit = {},
|
||||
) = asFlow(chapter, pageOffset)
|
||||
.catch {
|
||||
onError(it)
|
||||
@@ -33,14 +33,14 @@ class UpdateChapterMeta @Inject constructor(
|
||||
|
||||
fun asFlow(
|
||||
chapter: Chapter,
|
||||
pageOffset: Int = chapter.meta.juiPageOffset
|
||||
pageOffset: Int = chapter.meta.juiPageOffset,
|
||||
) = flow {
|
||||
if (pageOffset != chapter.meta.juiPageOffset) {
|
||||
chapterRepository.updateChapterMeta(
|
||||
chapter.mangaId,
|
||||
chapter.index,
|
||||
"juiPageOffset",
|
||||
pageOffset.toString()
|
||||
pageOffset.toString(),
|
||||
).collect()
|
||||
serverListeners.updateChapters(chapter.mangaId, chapter.index)
|
||||
}
|
||||
|
||||
@@ -18,14 +18,14 @@ import org.lighthousegames.logging.logging
|
||||
|
||||
class UpdateChapterRead @Inject constructor(
|
||||
private val chapterRepository: ChapterRepository,
|
||||
private val serverListeners: ServerListeners
|
||||
private val serverListeners: ServerListeners,
|
||||
) {
|
||||
|
||||
suspend fun await(
|
||||
mangaId: Long,
|
||||
index: Int,
|
||||
read: Boolean,
|
||||
onError: suspend (Throwable) -> Unit = {}
|
||||
onError: suspend (Throwable) -> Unit = {},
|
||||
) = asFlow(mangaId, index, read)
|
||||
.catch {
|
||||
onError(it)
|
||||
@@ -37,7 +37,7 @@ class UpdateChapterRead @Inject constructor(
|
||||
manga: Manga,
|
||||
index: Int,
|
||||
read: Boolean,
|
||||
onError: suspend (Throwable) -> Unit = {}
|
||||
onError: suspend (Throwable) -> Unit = {},
|
||||
) = asFlow(manga, index, read)
|
||||
.catch {
|
||||
onError(it)
|
||||
@@ -48,7 +48,7 @@ class UpdateChapterRead @Inject constructor(
|
||||
suspend fun await(
|
||||
chapter: Chapter,
|
||||
read: Boolean,
|
||||
onError: suspend (Throwable) -> Unit = {}
|
||||
onError: suspend (Throwable) -> Unit = {},
|
||||
) = asFlow(chapter, read)
|
||||
.catch {
|
||||
onError(it)
|
||||
@@ -59,30 +59,30 @@ class UpdateChapterRead @Inject constructor(
|
||||
fun asFlow(
|
||||
mangaId: Long,
|
||||
index: Int,
|
||||
read: Boolean
|
||||
read: Boolean,
|
||||
) = chapterRepository.updateChapter(
|
||||
mangaId = mangaId,
|
||||
chapterIndex = index,
|
||||
read = read
|
||||
read = read,
|
||||
).onEach { serverListeners.updateChapters(mangaId, index) }
|
||||
|
||||
fun asFlow(
|
||||
manga: Manga,
|
||||
index: Int,
|
||||
read: Boolean
|
||||
read: Boolean,
|
||||
) = chapterRepository.updateChapter(
|
||||
mangaId = manga.id,
|
||||
chapterIndex = index,
|
||||
read = read
|
||||
read = read,
|
||||
).onEach { serverListeners.updateChapters(manga.id, index) }
|
||||
|
||||
fun asFlow(
|
||||
chapter: Chapter,
|
||||
read: Boolean
|
||||
read: Boolean,
|
||||
) = chapterRepository.updateChapter(
|
||||
mangaId = chapter.mangaId,
|
||||
chapterIndex = chapter.index,
|
||||
read = read
|
||||
read = read,
|
||||
).onEach { serverListeners.updateChapters(chapter.mangaId, chapter.index) }
|
||||
|
||||
companion object {
|
||||
|
||||
@@ -29,11 +29,11 @@ data class Chapter(
|
||||
val pageCount: Int?,
|
||||
val lastReadAt: Int?,
|
||||
val downloaded: Boolean,
|
||||
val meta: ChapterMeta
|
||||
val meta: ChapterMeta,
|
||||
)
|
||||
|
||||
@Serializable
|
||||
@Immutable
|
||||
data class ChapterMeta(
|
||||
val juiPageOffset: Int = 0
|
||||
val juiPageOffset: Int = 0,
|
||||
)
|
||||
|
||||
@@ -11,5 +11,5 @@ import kotlinx.serialization.Serializable
|
||||
@Serializable
|
||||
data class ChapterBatchEditInput(
|
||||
val chapterIds: List<Long>? = null,
|
||||
val change: ChapterChange?
|
||||
val change: ChapterChange?,
|
||||
)
|
||||
|
||||
@@ -13,5 +13,5 @@ data class ChapterChange(
|
||||
val isRead: Boolean? = null,
|
||||
val isBookmarked: Boolean? = null,
|
||||
val lastPageRead: Int? = null,
|
||||
val delete: Boolean? = null
|
||||
val delete: Boolean? = null,
|
||||
)
|
||||
|
||||
@@ -12,5 +12,5 @@ import kotlinx.serialization.Serializable
|
||||
data class MangaChapterBatchEditInput(
|
||||
val chapterIds: List<Long>? = null,
|
||||
val chapterIndexes: List<Int>? = null,
|
||||
val change: ChapterChange?
|
||||
val change: ChapterChange?,
|
||||
)
|
||||
|
||||
@@ -29,13 +29,13 @@ interface ChapterRepository {
|
||||
@GET("api/v1/manga/{mangaId}/chapters")
|
||||
fun getChapters(
|
||||
@Path("mangaId") mangaId: Long,
|
||||
@Query("onlineFetch") refresh: Boolean = false
|
||||
@Query("onlineFetch") refresh: Boolean = false,
|
||||
): Flow<List<Chapter>>
|
||||
|
||||
@GET("api/v1/manga/{mangaId}/chapter/{chapterIndex}")
|
||||
fun getChapter(
|
||||
@Path("mangaId") mangaId: Long,
|
||||
@Path("chapterIndex") chapterIndex: Int
|
||||
@Path("chapterIndex") chapterIndex: Int,
|
||||
): Flow<Chapter>
|
||||
|
||||
@FormUrlEncoded
|
||||
@@ -46,20 +46,20 @@ interface ChapterRepository {
|
||||
@Field("read") read: Boolean? = null,
|
||||
@Field("bookmarked") bookmarked: Boolean? = null,
|
||||
@Field("lastPageRead") lastPageRead: Int? = null,
|
||||
@Field("markPrevRead") markPreviousRead: Boolean? = null
|
||||
@Field("markPrevRead") markPreviousRead: Boolean? = null,
|
||||
): Flow<HttpResponse>
|
||||
|
||||
@POST("api/v1/manga/{mangaId}/chapter/batch")
|
||||
@Headers("Content-Type: application/json")
|
||||
fun batchUpdateChapter(
|
||||
@Path("mangaId") mangaId: Long,
|
||||
@Body input: MangaChapterBatchEditInput
|
||||
@Body input: MangaChapterBatchEditInput,
|
||||
): Flow<HttpResponse>
|
||||
|
||||
@POST("api/v1/chapter/batch")
|
||||
@Headers("Content-Type: application/json")
|
||||
fun batchUpdateChapter(
|
||||
@Body input: ChapterBatchEditInput
|
||||
@Body input: ChapterBatchEditInput,
|
||||
): Flow<HttpResponse>
|
||||
|
||||
@GET("api/v1/manga/{mangaId}/chapter/{chapterIndex}/page/{pageNum}")
|
||||
@@ -67,13 +67,13 @@ interface ChapterRepository {
|
||||
@Path("mangaId") mangaId: Long,
|
||||
@Path("chapterIndex") chapterIndex: Int,
|
||||
@Path("pageNum") pageNum: Int,
|
||||
@ReqBuilder block: HttpRequestBuilder.() -> Unit
|
||||
@ReqBuilder block: HttpRequestBuilder.() -> Unit,
|
||||
): Flow<HttpResponse>
|
||||
|
||||
@DELETE("api/v1/manga/{mangaId}/chapter/{chapterIndex}")
|
||||
fun deleteChapterDownload(
|
||||
@Path("mangaId") mangaId: Long,
|
||||
@Path("chapterIndex") chapterIndex: Int
|
||||
@Path("chapterIndex") chapterIndex: Int,
|
||||
): Flow<HttpResponse>
|
||||
|
||||
@FormUrlEncoded
|
||||
@@ -82,6 +82,6 @@ interface ChapterRepository {
|
||||
@Path("mangaId") mangaId: Long,
|
||||
@Path("chapterIndex") chapterIndex: Int,
|
||||
@Field("key") key: String,
|
||||
@Field("value") value: String
|
||||
@Field("value") value: String,
|
||||
): Flow<HttpResponse>
|
||||
}
|
||||
|
||||
@@ -20,5 +20,5 @@ data class DownloadChapter(
|
||||
val manga: Manga,
|
||||
val state: DownloadState = DownloadState.Queued,
|
||||
val progress: Float = 0f,
|
||||
val tries: Int = 0
|
||||
val tries: Int = 0,
|
||||
)
|
||||
|
||||
@@ -10,5 +10,5 @@ import kotlinx.serialization.Serializable
|
||||
|
||||
@Serializable
|
||||
data class DownloadEnqueue(
|
||||
val chapterIds: List<Long>
|
||||
val chapterIds: List<Long>,
|
||||
)
|
||||
|
||||
@@ -15,5 +15,5 @@ enum class DownloadState(val state: Int) {
|
||||
Queued(0),
|
||||
Downloading(1),
|
||||
Finished(2),
|
||||
Error(3)
|
||||
Error(3),
|
||||
}
|
||||
|
||||
@@ -13,5 +13,5 @@ import kotlinx.serialization.Serializable
|
||||
@Immutable
|
||||
data class DownloadStatus(
|
||||
val status: DownloaderStatus,
|
||||
val queue: List<DownloadChapter>
|
||||
val queue: List<DownloadChapter>,
|
||||
)
|
||||
|
||||
@@ -13,5 +13,5 @@ import kotlinx.serialization.Serializable
|
||||
@Stable
|
||||
enum class DownloaderStatus {
|
||||
Started,
|
||||
Stopped
|
||||
Stopped,
|
||||
}
|
||||
|
||||
@@ -30,25 +30,25 @@ interface DownloadRepository {
|
||||
@GET("api/v1/download/{mangaId}/chapter/{chapterIndex}")
|
||||
fun queueChapterDownload(
|
||||
@Path("mangaId") mangaId: Long,
|
||||
@Path("chapterIndex") chapterIndex: Int
|
||||
@Path("chapterIndex") chapterIndex: Int,
|
||||
): Flow<HttpResponse>
|
||||
|
||||
@DELETE("api/v1/download/{mangaId}/chapter/{chapterIndex}")
|
||||
fun stopChapterDownload(
|
||||
@Path("mangaId") mangaId: Long,
|
||||
@Path("chapterIndex") chapterIndex: Int
|
||||
@Path("chapterIndex") chapterIndex: Int,
|
||||
): Flow<HttpResponse>
|
||||
|
||||
@PATCH("api/v1/download/{mangaId}/chapter/{chapterIndex}/reorder/{to}")
|
||||
fun reorderChapterDownload(
|
||||
@Path("mangaId") mangaId: Long,
|
||||
@Path("chapterIndex") chapterIndex: Int,
|
||||
@Path("to") to: Int
|
||||
@Path("to") to: Int,
|
||||
): Flow<HttpResponse>
|
||||
|
||||
@POST("api/v1/download/batch")
|
||||
@Headers("Content-Type: application/json")
|
||||
fun batchDownload(
|
||||
@Body downloadEnqueue: DownloadEnqueue
|
||||
@Body downloadEnqueue: DownloadEnqueue,
|
||||
): Flow<HttpResponse>
|
||||
}
|
||||
|
||||
@@ -21,7 +21,7 @@ import me.tatarka.inject.annotations.Inject
|
||||
|
||||
class DownloadService @Inject constructor(
|
||||
serverPreferences: ServerPreferences,
|
||||
client: Http
|
||||
client: Http,
|
||||
) : WebsocketService(serverPreferences, client) {
|
||||
override val _status: MutableStateFlow<Status>
|
||||
get() = status
|
||||
|
||||
@@ -22,5 +22,5 @@ data class Extension(
|
||||
val installed: Boolean,
|
||||
val hasUpdate: Boolean,
|
||||
val obsolete: Boolean,
|
||||
val isNsfw: Boolean
|
||||
val isNsfw: Boolean,
|
||||
)
|
||||
|
||||
@@ -33,28 +33,28 @@ interface ExtensionRepository {
|
||||
@Multipart
|
||||
@POST("api/v1/extension/install")
|
||||
fun installExtension(
|
||||
@Part("") formData: List<PartData>
|
||||
@Part("") formData: List<PartData>,
|
||||
): Flow<HttpResponse>
|
||||
|
||||
@GET("api/v1/extension/install/{pkgName}")
|
||||
fun installExtension(
|
||||
@Path("pkgName") pkgName: String
|
||||
@Path("pkgName") pkgName: String,
|
||||
): Flow<HttpResponse>
|
||||
|
||||
@GET("api/v1/extension/update/{pkgName}")
|
||||
fun updateExtension(
|
||||
@Path("pkgName") pkgName: String
|
||||
@Path("pkgName") pkgName: String,
|
||||
): Flow<HttpResponse>
|
||||
|
||||
@GET("api/v1/extension/uninstall/{pkgName}")
|
||||
fun uninstallExtension(
|
||||
@Path("pkgName") pkgName: String
|
||||
@Path("pkgName") pkgName: String,
|
||||
): Flow<HttpResponse>
|
||||
|
||||
@GET("api/v1/extension/icon/{apkName}")
|
||||
fun getApkIcon(
|
||||
@Path("apkName") apkName: String,
|
||||
@ReqBuilder block: HttpRequestBuilder.() -> Unit
|
||||
@ReqBuilder block: HttpRequestBuilder.() -> Unit,
|
||||
): Flow<ByteReadChannel>
|
||||
|
||||
companion object {
|
||||
@@ -65,7 +65,7 @@ interface ExtensionRepository {
|
||||
Headers.build {
|
||||
append(HttpHeaders.ContentType, ContentType.MultiPart.FormData.toString())
|
||||
append(HttpHeaders.ContentDisposition, "filename=file")
|
||||
}
|
||||
},
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,7 +19,7 @@ class UpdateGlobalMeta @Inject constructor(private val globalRepository: GlobalR
|
||||
suspend fun await(
|
||||
globalMeta: GlobalMeta,
|
||||
example: Int = globalMeta.example,
|
||||
onError: suspend (Throwable) -> Unit = {}
|
||||
onError: suspend (Throwable) -> Unit = {},
|
||||
) = asFlow(globalMeta, example)
|
||||
.catch {
|
||||
onError(it)
|
||||
@@ -29,12 +29,12 @@ class UpdateGlobalMeta @Inject constructor(private val globalRepository: GlobalR
|
||||
|
||||
fun asFlow(
|
||||
globalMeta: GlobalMeta,
|
||||
example: Int = globalMeta.example
|
||||
example: Int = globalMeta.example,
|
||||
) = flow {
|
||||
if (example != globalMeta.example) {
|
||||
globalRepository.updateGlobalMeta(
|
||||
"example",
|
||||
example.toString()
|
||||
example.toString(),
|
||||
).collect()
|
||||
}
|
||||
emit(Unit)
|
||||
|
||||
@@ -12,5 +12,5 @@ import kotlinx.serialization.Serializable
|
||||
@Serializable
|
||||
@Immutable
|
||||
data class GlobalMeta(
|
||||
val example: Int = 0
|
||||
val example: Int = 0,
|
||||
)
|
||||
|
||||
@@ -22,6 +22,6 @@ interface GlobalRepository {
|
||||
@PATCH("api/v1/meta")
|
||||
fun updateGlobalMeta(
|
||||
@Field("key") key: String,
|
||||
@Field("value") value: String
|
||||
@Field("value") value: String,
|
||||
): Flow<HttpResponse>
|
||||
}
|
||||
|
||||
@@ -17,7 +17,7 @@ import org.lighthousegames.logging.logging
|
||||
|
||||
class AddMangaToLibrary @Inject constructor(
|
||||
private val libraryRepository: LibraryRepository,
|
||||
private val serverListeners: ServerListeners
|
||||
private val serverListeners: ServerListeners,
|
||||
) {
|
||||
|
||||
suspend fun await(mangaId: Long, onError: suspend (Throwable) -> Unit = {}) = asFlow(mangaId)
|
||||
|
||||
@@ -17,7 +17,7 @@ import org.lighthousegames.logging.logging
|
||||
|
||||
class RemoveMangaFromLibrary @Inject constructor(
|
||||
private val libraryRepository: LibraryRepository,
|
||||
private val serverListeners: ServerListeners
|
||||
private val serverListeners: ServerListeners,
|
||||
) {
|
||||
|
||||
suspend fun await(mangaId: Long, onError: suspend (Throwable) -> Unit = {}) = asFlow(mangaId)
|
||||
|
||||
@@ -18,7 +18,8 @@ enum class DisplayMode(@Transient val res: StringResource) {
|
||||
CompactGrid(MR.strings.display_compact),
|
||||
ComfortableGrid(MR.strings.display_comfortable),
|
||||
CoverOnlyGrid(MR.strings.display_cover_only),
|
||||
List(MR.strings.display_list);
|
||||
List(MR.strings.display_list),
|
||||
;
|
||||
|
||||
companion object {
|
||||
val values by lazy {
|
||||
|
||||
@@ -14,5 +14,5 @@ import kotlinx.serialization.Serializable
|
||||
enum class FilterState {
|
||||
IGNORED,
|
||||
INCLUDED,
|
||||
EXCLUDED
|
||||
EXCLUDED,
|
||||
}
|
||||
|
||||
@@ -15,5 +15,5 @@ enum class JobStatus {
|
||||
PENDING,
|
||||
RUNNING,
|
||||
COMPLETE,
|
||||
FAILED
|
||||
FAILED,
|
||||
}
|
||||
|
||||
@@ -24,5 +24,5 @@ enum class Sort(@Transient val res: StringResource) {
|
||||
// TOTAL_CHAPTERS,
|
||||
// LATEST_CHAPTER,
|
||||
// DATE_FETCHED,
|
||||
DATE_ADDED(MR.strings.sort_date_added)
|
||||
DATE_ADDED(MR.strings.sort_date_added),
|
||||
}
|
||||
|
||||
@@ -14,5 +14,5 @@ import kotlinx.serialization.Serializable
|
||||
@Immutable
|
||||
data class UpdateStatus(
|
||||
val statusMap: Map<JobStatus, List<Manga>>,
|
||||
val running: Boolean
|
||||
val running: Boolean,
|
||||
)
|
||||
|
||||
@@ -16,11 +16,11 @@ interface LibraryRepository {
|
||||
|
||||
@GET("api/v1/manga/{mangaId}/library")
|
||||
fun addMangaToLibrary(
|
||||
@Path("mangaId") mangaId: Long
|
||||
@Path("mangaId") mangaId: Long,
|
||||
): Flow<HttpResponse>
|
||||
|
||||
@DELETE("api/v1/manga/{mangaId}/library")
|
||||
fun removeMangaFromLibrary(
|
||||
@Path("mangaId") mangaId: Long
|
||||
@Path("mangaId") mangaId: Long,
|
||||
): Flow<HttpResponse>
|
||||
}
|
||||
|
||||
@@ -19,7 +19,7 @@ import org.lighthousegames.logging.logging
|
||||
|
||||
class LibraryUpdateService @Inject constructor(
|
||||
serverPreferences: ServerPreferences,
|
||||
client: Http
|
||||
client: Http,
|
||||
) : WebsocketService(serverPreferences, client) {
|
||||
|
||||
override val _status: MutableStateFlow<Status>
|
||||
|
||||
@@ -17,7 +17,7 @@ import org.lighthousegames.logging.logging
|
||||
|
||||
class GetManga @Inject constructor(
|
||||
private val mangaRepository: MangaRepository,
|
||||
private val serverListeners: ServerListeners
|
||||
private val serverListeners: ServerListeners,
|
||||
) {
|
||||
|
||||
suspend fun await(mangaId: Long, onError: suspend (Throwable) -> Unit = {}) = asFlow(mangaId)
|
||||
@@ -37,11 +37,11 @@ class GetManga @Inject constructor(
|
||||
.singleOrNull()
|
||||
|
||||
fun asFlow(mangaId: Long) = serverListeners.combineMangaUpdates(
|
||||
mangaRepository.getManga(mangaId)
|
||||
mangaRepository.getManga(mangaId),
|
||||
) { mangaId in it }
|
||||
|
||||
fun asFlow(manga: Manga) = serverListeners.combineMangaUpdates(
|
||||
mangaRepository.getManga(manga.id)
|
||||
mangaRepository.getManga(manga.id),
|
||||
) { manga.id in it }
|
||||
|
||||
companion object {
|
||||
|
||||
@@ -17,7 +17,7 @@ import org.lighthousegames.logging.logging
|
||||
|
||||
class GetMangaFull @Inject constructor(
|
||||
private val mangaRepository: MangaRepository,
|
||||
private val serverListeners: ServerListeners
|
||||
private val serverListeners: ServerListeners,
|
||||
) {
|
||||
|
||||
suspend fun await(mangaId: Long, onError: suspend (Throwable) -> Unit = {}) = asFlow(mangaId)
|
||||
@@ -37,11 +37,11 @@ class GetMangaFull @Inject constructor(
|
||||
.singleOrNull()
|
||||
|
||||
fun asFlow(mangaId: Long) = serverListeners.combineMangaUpdates(
|
||||
mangaRepository.getMangaFull(mangaId)
|
||||
mangaRepository.getMangaFull(mangaId),
|
||||
) { mangaId in it }
|
||||
|
||||
fun asFlow(manga: Manga) = serverListeners.combineMangaUpdates(
|
||||
mangaRepository.getMangaFull(manga.id)
|
||||
mangaRepository.getMangaFull(manga.id),
|
||||
) { manga.id in it }
|
||||
|
||||
companion object {
|
||||
|
||||
@@ -18,7 +18,7 @@ import org.lighthousegames.logging.logging
|
||||
|
||||
class RefreshManga @Inject constructor(
|
||||
private val mangaRepository: MangaRepository,
|
||||
private val serverListeners: ServerListeners
|
||||
private val serverListeners: ServerListeners,
|
||||
) {
|
||||
|
||||
suspend fun await(mangaId: Long, onError: suspend (Throwable) -> Unit = {}) = asFlow(mangaId)
|
||||
|
||||
@@ -18,7 +18,7 @@ import org.lighthousegames.logging.logging
|
||||
|
||||
class RefreshMangaFull @Inject constructor(
|
||||
private val mangaRepository: MangaRepository,
|
||||
private val serverListeners: ServerListeners
|
||||
private val serverListeners: ServerListeners,
|
||||
) {
|
||||
|
||||
suspend fun await(mangaId: Long, onError: suspend (Throwable) -> Unit = {}) = asFlow(mangaId)
|
||||
|
||||
@@ -19,13 +19,13 @@ import org.lighthousegames.logging.logging
|
||||
|
||||
class UpdateMangaMeta @Inject constructor(
|
||||
private val mangaRepository: MangaRepository,
|
||||
private val serverListeners: ServerListeners
|
||||
private val serverListeners: ServerListeners,
|
||||
) {
|
||||
|
||||
suspend fun await(
|
||||
manga: Manga,
|
||||
readerMode: String = manga.meta.juiReaderMode,
|
||||
onError: suspend (Throwable) -> Unit = {}
|
||||
onError: suspend (Throwable) -> Unit = {},
|
||||
) = asFlow(manga, readerMode)
|
||||
.catch {
|
||||
onError(it)
|
||||
@@ -35,13 +35,13 @@ class UpdateMangaMeta @Inject constructor(
|
||||
|
||||
fun asFlow(
|
||||
manga: Manga,
|
||||
readerMode: String = manga.meta.juiReaderMode.decodeURLQueryComponent()
|
||||
readerMode: String = manga.meta.juiReaderMode.decodeURLQueryComponent(),
|
||||
) = flow {
|
||||
if (readerMode.encodeURLQueryComponent() != manga.meta.juiReaderMode) {
|
||||
mangaRepository.updateMangaMeta(
|
||||
manga.id,
|
||||
"juiReaderMode",
|
||||
readerMode
|
||||
readerMode,
|
||||
).collect()
|
||||
serverListeners.updateManga(manga.id)
|
||||
}
|
||||
|
||||
@@ -44,13 +44,13 @@ data class Manga(
|
||||
val chapterCount: Int?,
|
||||
val lastChapterRead: Chapter? = null,
|
||||
val age: Long?,
|
||||
val chaptersAge: Long?
|
||||
val chaptersAge: Long?,
|
||||
)
|
||||
|
||||
@Serializable
|
||||
@Immutable
|
||||
data class MangaMeta(
|
||||
val juiReaderMode: String = DEFAULT_READER_MODE
|
||||
val juiReaderMode: String = DEFAULT_READER_MODE,
|
||||
) {
|
||||
companion object {
|
||||
const val DEFAULT_READER_MODE = "default"
|
||||
@@ -66,12 +66,12 @@ enum class MangaStatus(@Transient val res: StringResource) {
|
||||
LICENSED(MR.strings.status_licensed),
|
||||
PUBLISHING_FINISHED(MR.strings.status_publishing_finished),
|
||||
CANCELLED(MR.strings.status_cancelled),
|
||||
ON_HIATUS(MR.strings.status_on_hiatus)
|
||||
ON_HIATUS(MR.strings.status_on_hiatus),
|
||||
}
|
||||
|
||||
@Serializable
|
||||
@Stable
|
||||
enum class UpdateStrategy {
|
||||
ALWAYS_UPDATE,
|
||||
ONLY_FETCH_ONCE
|
||||
ONLY_FETCH_ONCE,
|
||||
}
|
||||
|
||||
@@ -23,19 +23,19 @@ interface MangaRepository {
|
||||
@GET("api/v1/manga/{mangaId}/")
|
||||
fun getManga(
|
||||
@Path("mangaId") mangaId: Long,
|
||||
@Query("onlineFetch") refresh: Boolean = false
|
||||
@Query("onlineFetch") refresh: Boolean = false,
|
||||
): Flow<Manga>
|
||||
|
||||
@GET("api/v1/manga/{mangaId}/full")
|
||||
fun getMangaFull(
|
||||
@Path("mangaId") mangaId: Long,
|
||||
@Query("onlineFetch") refresh: Boolean = false
|
||||
@Query("onlineFetch") refresh: Boolean = false,
|
||||
): Flow<Manga>
|
||||
|
||||
@GET("api/v1/manga/{mangaId}/thumbnail")
|
||||
fun getMangaThumbnail(
|
||||
@Path("mangaId") mangaId: Long,
|
||||
@ReqBuilder block: HttpRequestBuilder.() -> Unit
|
||||
@ReqBuilder block: HttpRequestBuilder.() -> Unit,
|
||||
): Flow<ByteReadChannel>
|
||||
|
||||
@PATCH("api/v1/manga/{mangaId}/meta")
|
||||
@@ -43,6 +43,6 @@ interface MangaRepository {
|
||||
fun updateMangaMeta(
|
||||
@Path("mangaId") mangaId: Long,
|
||||
@Field("key") key: String,
|
||||
@Field("value") value: String
|
||||
@Field("value") value: String,
|
||||
): Flow<HttpResponse>
|
||||
}
|
||||
|
||||
@@ -13,7 +13,7 @@ import me.tatarka.inject.annotations.Inject
|
||||
|
||||
class RunMigrations @Inject constructor(
|
||||
private val migrationPreferences: MigrationPreferences,
|
||||
private val readerPreferences: ReaderPreferences
|
||||
private val readerPreferences: ReaderPreferences,
|
||||
) {
|
||||
|
||||
fun runMigrations() {
|
||||
|
||||
@@ -21,8 +21,8 @@ class ReaderModeWatch(
|
||||
private val scope: CoroutineScope,
|
||||
private val mode: StateFlow<String> = readerPreferences.mode().stateIn(scope),
|
||||
initialPreferences: ReaderModePreferences = readerPreferences.getMode(
|
||||
mode.value
|
||||
)
|
||||
mode.value,
|
||||
),
|
||||
) {
|
||||
private val preferenceJobs = mutableListOf<Job>()
|
||||
val direction = MutableStateFlow(initialPreferences.direction().get())
|
||||
|
||||
@@ -15,11 +15,11 @@ enum class DefaultReaderMode(
|
||||
val direction: Direction = Direction.Down,
|
||||
val padding: Int = 0,
|
||||
val imageScale: ImageScale = ImageScale.FitScreen,
|
||||
val navigationMode: NavigationMode = NavigationMode.LNavigation
|
||||
val navigationMode: NavigationMode = NavigationMode.LNavigation,
|
||||
) {
|
||||
RTL("RTL", false, Direction.Left, navigationMode = NavigationMode.RightAndLeftNavigation),
|
||||
LTR("LTR", false, Direction.Right, navigationMode = NavigationMode.RightAndLeftNavigation),
|
||||
Vertical("Vertical", false),
|
||||
ContinuesVertical("Continues Vertical", true, padding = 16),
|
||||
LongStrip("Long Strip", true)
|
||||
LongStrip("Long Strip", true),
|
||||
}
|
||||
|
||||
@@ -18,7 +18,8 @@ enum class Direction(@Transient val res: StringResource) {
|
||||
Down(MR.strings.dir_down),
|
||||
Left(MR.strings.dir_rtl),
|
||||
Right(MR.strings.dir_ltr),
|
||||
Up(MR.strings.dir_up);
|
||||
Up(MR.strings.dir_up),
|
||||
;
|
||||
|
||||
val isVertical
|
||||
get() = this == Down || this == Up
|
||||
|
||||
@@ -20,5 +20,5 @@ enum class ImageScale(@Transient val res: StringResource) {
|
||||
FitWidth(MR.strings.scale_fit_width),
|
||||
FitHeight(MR.strings.scale_fit_height),
|
||||
OriginalSize(MR.strings.scale_original),
|
||||
SmartFit(MR.strings.scale_smart)
|
||||
SmartFit(MR.strings.scale_smart),
|
||||
}
|
||||
|
||||
@@ -19,5 +19,5 @@ enum class NavigationMode(@Transient val res: StringResource) {
|
||||
LNavigation(MR.strings.nav_l_shaped),
|
||||
KindlishNavigation(MR.strings.nav_kindle_ish),
|
||||
EdgeNavigation(MR.strings.nav_edge),
|
||||
RightAndLeftNavigation(MR.strings.nav_left_right)
|
||||
RightAndLeftNavigation(MR.strings.nav_left_right),
|
||||
}
|
||||
|
||||
@@ -15,5 +15,5 @@ enum class TappingInvertMode(val shouldInvertHorizontal: Boolean = false, val sh
|
||||
NONE,
|
||||
HORIZONTAL(shouldInvertHorizontal = true),
|
||||
VERTICAL(shouldInvertVertical = true),
|
||||
BOTH(shouldInvertHorizontal = true, shouldInvertVertical = true)
|
||||
BOTH(shouldInvertHorizontal = true, shouldInvertVertical = true),
|
||||
}
|
||||
|
||||
@@ -54,7 +54,7 @@ class ReaderModePreferences(private val mode: String, private val preferenceStor
|
||||
}
|
||||
} else {
|
||||
0
|
||||
}
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@@ -26,7 +26,7 @@ class ReaderPreferences(private val preferenceStore: PreferenceStore, private va
|
||||
return preferenceStore.getJsonObject(
|
||||
"modes",
|
||||
DefaultReaderMode.values().map { it.res },
|
||||
ListSerializer(String.serializer())
|
||||
ListSerializer(String.serializer()),
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@@ -52,12 +52,12 @@ fun httpClient(serverPreferences: ServerPreferences, json: Json): Http {
|
||||
Proxy.HTTP_PROXY -> ProxyBuilder.http(
|
||||
URLBuilder(
|
||||
host = serverPreferences.proxyHttpHost().get(),
|
||||
port = serverPreferences.proxyHttpPort().get()
|
||||
).build()
|
||||
port = serverPreferences.proxyHttpPort().get(),
|
||||
).build(),
|
||||
)
|
||||
Proxy.SOCKS_PROXY -> ProxyBuilder.socks(
|
||||
serverPreferences.proxySocksHost().get(),
|
||||
serverPreferences.proxySocksPort().get()
|
||||
serverPreferences.proxySocksPort().get(),
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -71,7 +71,7 @@ fun httpClient(serverPreferences: ServerPreferences, json: Json): Http {
|
||||
credentials {
|
||||
BasicAuthCredentials(
|
||||
serverPreferences.authUsername().get(),
|
||||
serverPreferences.authPassword().get()
|
||||
serverPreferences.authPassword().get(),
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -81,7 +81,7 @@ fun httpClient(serverPreferences: ServerPreferences, json: Json): Http {
|
||||
credentials {
|
||||
DigestAuthCredentials(
|
||||
serverPreferences.authUsername().get(),
|
||||
serverPreferences.authPassword().get()
|
||||
serverPreferences.authPassword().get(),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,5 +14,5 @@ import kotlinx.serialization.Serializable
|
||||
enum class Auth {
|
||||
NONE,
|
||||
BASIC,
|
||||
DIGEST
|
||||
DIGEST,
|
||||
}
|
||||
|
||||
@@ -14,5 +14,5 @@ import kotlinx.serialization.Serializable
|
||||
enum class Proxy {
|
||||
NO_PROXY,
|
||||
HTTP_PROXY,
|
||||
SOCKS_PROXY
|
||||
SOCKS_PROXY,
|
||||
}
|
||||
|
||||
@@ -23,7 +23,7 @@ class ServerUrlPreference(
|
||||
private val key: String,
|
||||
private val server: Preference<String>,
|
||||
private val port: Preference<Int>,
|
||||
private val pathPrefix: Preference<String>
|
||||
private val pathPrefix: Preference<String>,
|
||||
) : Preference<Url> {
|
||||
override fun key(): String {
|
||||
return key
|
||||
|
||||
@@ -19,12 +19,12 @@ data class About(
|
||||
val buildType: AboutBuildType,
|
||||
val buildTime: Long,
|
||||
val github: String,
|
||||
val discord: String
|
||||
val discord: String,
|
||||
)
|
||||
|
||||
@Serializable
|
||||
@Stable
|
||||
enum class AboutBuildType {
|
||||
Preview,
|
||||
Stable
|
||||
Stable,
|
||||
}
|
||||
|
||||
@@ -36,8 +36,8 @@ class GetQuickSearchManga @Inject constructor(private val sourceRepository: Sour
|
||||
page,
|
||||
SourceFilterData(
|
||||
searchTerm?.ifBlank { null },
|
||||
filters?.ifEmpty { null }
|
||||
)
|
||||
filters?.ifEmpty { null },
|
||||
),
|
||||
)
|
||||
|
||||
fun asFlow(sourceId: Long, searchTerm: String?, page: Int, filters: List<SourceFilterChange>?) = sourceRepository.getQuickSearchResults(
|
||||
@@ -45,8 +45,8 @@ class GetQuickSearchManga @Inject constructor(private val sourceRepository: Sour
|
||||
page,
|
||||
SourceFilterData(
|
||||
searchTerm?.ifBlank { null },
|
||||
filters?.ifEmpty { null }
|
||||
)
|
||||
filters?.ifEmpty { null },
|
||||
),
|
||||
)
|
||||
|
||||
companion object {
|
||||
|
||||
@@ -32,13 +32,13 @@ class GetSearchManga @Inject constructor(private val sourceRepository: SourceRep
|
||||
fun asFlow(source: Source, searchTerm: String?, page: Int) = sourceRepository.getSearchResults(
|
||||
source.id,
|
||||
searchTerm?.ifBlank { null },
|
||||
page
|
||||
page,
|
||||
)
|
||||
|
||||
fun asFlow(sourceId: Long, searchTerm: String?, page: Int) = sourceRepository.getSearchResults(
|
||||
sourceId,
|
||||
searchTerm?.ifBlank { null },
|
||||
page
|
||||
page,
|
||||
)
|
||||
|
||||
companion object {
|
||||
|
||||
@@ -48,22 +48,22 @@ class SetSourceFilter @Inject constructor(private val sourceRepository: SourceRe
|
||||
|
||||
fun asFlow(source: Source, filterIndex: Int, filter: Any) = sourceRepository.setFilter(
|
||||
source.id,
|
||||
SourceFilterChange(filterIndex, filter)
|
||||
SourceFilterChange(filterIndex, filter),
|
||||
)
|
||||
|
||||
fun asFlow(sourceId: Long, filterIndex: Int, filter: Any) = sourceRepository.setFilter(
|
||||
sourceId,
|
||||
SourceFilterChange(filterIndex, filter)
|
||||
SourceFilterChange(filterIndex, filter),
|
||||
)
|
||||
|
||||
fun asFlow(source: Source, filterIndex: Int, childFilterIndex: Int, filter: Any) = sourceRepository.setFilter(
|
||||
source.id,
|
||||
SourceFilterChange(filterIndex, Json.encodeToString(SourceFilterChange(childFilterIndex, filter)))
|
||||
SourceFilterChange(filterIndex, Json.encodeToString(SourceFilterChange(childFilterIndex, filter))),
|
||||
)
|
||||
|
||||
fun asFlow(sourceId: Long, filterIndex: Int, childFilterIndex: Int, filter: Any) = sourceRepository.setFilter(
|
||||
sourceId,
|
||||
SourceFilterChange(filterIndex, Json.encodeToString(SourceFilterChange(childFilterIndex, filter)))
|
||||
SourceFilterChange(filterIndex, Json.encodeToString(SourceFilterChange(childFilterIndex, filter))),
|
||||
)
|
||||
|
||||
companion object {
|
||||
|
||||
@@ -32,12 +32,12 @@ class SetSourceSetting @Inject constructor(private val sourceRepository: SourceR
|
||||
|
||||
fun asFlow(source: Source, settingIndex: Int, setting: Any) = sourceRepository.setSourceSetting(
|
||||
source.id,
|
||||
SourcePreferenceChange(settingIndex, setting)
|
||||
SourcePreferenceChange(settingIndex, setting),
|
||||
)
|
||||
|
||||
fun asFlow(sourceId: Long, settingIndex: Int, setting: Any) = sourceRepository.setSourceSetting(
|
||||
sourceId,
|
||||
SourcePreferenceChange(settingIndex, setting)
|
||||
SourcePreferenceChange(settingIndex, setting),
|
||||
)
|
||||
|
||||
companion object {
|
||||
|
||||
@@ -34,7 +34,7 @@ typealias GetMangaPage = @param:Assisted suspend (page: Int) -> MangaPage?
|
||||
class SourcePager @Inject constructor(
|
||||
private val getManga: GetManga,
|
||||
private val serverListeners: ServerListeners,
|
||||
private val fetcher: GetMangaPage
|
||||
private val fetcher: GetMangaPage,
|
||||
) : CoroutineScope by CoroutineScope(Dispatchers.Default + SupervisorJob()) {
|
||||
private val sourceMutex = Mutex()
|
||||
|
||||
|
||||
@@ -14,5 +14,5 @@ import kotlinx.serialization.Serializable
|
||||
@Stable
|
||||
data class MangaPage(
|
||||
val mangaList: List<Manga>,
|
||||
val hasNextPage: Boolean
|
||||
val hasNextPage: Boolean,
|
||||
)
|
||||
|
||||
@@ -20,7 +20,7 @@ data class Source(
|
||||
val supportsLatest: Boolean,
|
||||
val isConfigurable: Boolean,
|
||||
val isNsfw: Boolean,
|
||||
val displayName: String
|
||||
val displayName: String,
|
||||
) : JvmSerializable {
|
||||
val displayLang: String
|
||||
get() = if (id == LOCAL_SOURCE_ID) {
|
||||
|
||||
@@ -12,11 +12,11 @@ import kotlinx.serialization.Serializable
|
||||
@Serializable
|
||||
@SerialName("CheckBox")
|
||||
data class CheckBoxFilter(
|
||||
override val filter: CheckBoxProps
|
||||
override val filter: CheckBoxProps,
|
||||
) : SourceFilter() {
|
||||
@Serializable
|
||||
data class CheckBoxProps(
|
||||
override val name: String,
|
||||
override val state: Boolean
|
||||
override val state: Boolean,
|
||||
) : Props<Boolean>
|
||||
}
|
||||
|
||||
@@ -12,11 +12,11 @@ import kotlinx.serialization.Serializable
|
||||
@Serializable
|
||||
@SerialName("Group")
|
||||
data class GroupFilter(
|
||||
override val filter: GroupProps
|
||||
override val filter: GroupProps,
|
||||
) : SourceFilter() {
|
||||
@Serializable
|
||||
data class GroupProps(
|
||||
override val name: String,
|
||||
override val state: List<SourceFilter>
|
||||
override val state: List<SourceFilter>,
|
||||
) : Props<List<SourceFilter>>
|
||||
}
|
||||
|
||||
@@ -13,12 +13,12 @@ import kotlinx.serialization.Transient
|
||||
@Serializable
|
||||
@SerialName("Header")
|
||||
data class HeaderFilter(
|
||||
override val filter: HeaderProps
|
||||
override val filter: HeaderProps,
|
||||
) : SourceFilter() {
|
||||
@Serializable
|
||||
data class HeaderProps(
|
||||
override val name: String,
|
||||
@Transient
|
||||
override val state: Int = 0
|
||||
override val state: Int = 0,
|
||||
) : Props<Int>
|
||||
}
|
||||
|
||||
@@ -13,13 +13,13 @@ import kotlinx.serialization.json.JsonElement
|
||||
@Serializable
|
||||
@SerialName("Select")
|
||||
data class SelectFilter(
|
||||
override val filter: SelectProps
|
||||
override val filter: SelectProps,
|
||||
) : SourceFilter() {
|
||||
@Serializable
|
||||
data class SelectProps(
|
||||
override val name: String,
|
||||
override val state: Int,
|
||||
val values: List<JsonElement>,
|
||||
val displayValues: List<String>? = null
|
||||
val displayValues: List<String>? = null,
|
||||
) : Props<Int>
|
||||
}
|
||||
|
||||
@@ -13,12 +13,12 @@ import kotlinx.serialization.Transient
|
||||
@Serializable
|
||||
@SerialName("Separator")
|
||||
data class SeparatorFilter(
|
||||
override val filter: SeparatorProps
|
||||
override val filter: SeparatorProps,
|
||||
) : SourceFilter() {
|
||||
@Serializable
|
||||
data class SeparatorProps(
|
||||
override val name: String,
|
||||
@Transient
|
||||
override val state: Int = 0
|
||||
override val state: Int = 0,
|
||||
) : Props<Int>
|
||||
}
|
||||
|
||||
@@ -12,18 +12,18 @@ import kotlinx.serialization.Serializable
|
||||
@Serializable
|
||||
@SerialName("Sort")
|
||||
data class SortFilter(
|
||||
override val filter: SortProps
|
||||
override val filter: SortProps,
|
||||
) : SourceFilter() {
|
||||
@Serializable
|
||||
data class SortProps(
|
||||
override val name: String,
|
||||
override val state: Selection?,
|
||||
val values: List<String>
|
||||
val values: List<String>,
|
||||
) : Props<Selection?>
|
||||
|
||||
@Serializable
|
||||
data class Selection(
|
||||
val index: Int,
|
||||
val ascending: Boolean
|
||||
val ascending: Boolean,
|
||||
)
|
||||
}
|
||||
|
||||
@@ -18,6 +18,6 @@ data class SourceFilterChange(val position: Int, val state: String) {
|
||||
Json.encodeToString(state)
|
||||
} else {
|
||||
state.toString()
|
||||
}
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
@@ -11,5 +11,5 @@ import kotlinx.serialization.Serializable
|
||||
@Serializable
|
||||
data class SourceFilterData(
|
||||
val searchTerm: String?,
|
||||
val filter: List<SourceFilterChange>?
|
||||
val filter: List<SourceFilterChange>?,
|
||||
)
|
||||
|
||||
@@ -12,11 +12,11 @@ import kotlinx.serialization.Serializable
|
||||
@Serializable
|
||||
@SerialName("Text")
|
||||
data class TextFilter(
|
||||
override val filter: TextProps
|
||||
override val filter: TextProps,
|
||||
) : SourceFilter() {
|
||||
@Serializable
|
||||
data class TextProps(
|
||||
override val name: String,
|
||||
override val state: String
|
||||
override val state: String,
|
||||
) : Props<String>
|
||||
}
|
||||
|
||||
@@ -12,11 +12,11 @@ import kotlinx.serialization.Serializable
|
||||
@Serializable
|
||||
@SerialName("TriState")
|
||||
data class TriStateFilter(
|
||||
override val filter: TriStateProps
|
||||
override val filter: TriStateProps,
|
||||
) : SourceFilter() {
|
||||
@Serializable
|
||||
data class TriStateProps(
|
||||
override val name: String,
|
||||
override val state: Int
|
||||
override val state: Int,
|
||||
) : Props<Int>
|
||||
}
|
||||
|
||||
@@ -14,5 +14,5 @@ import kotlinx.serialization.Serializable
|
||||
@SerialName("CheckBoxPreference")
|
||||
@Immutable
|
||||
data class CheckBoxPreference(
|
||||
override val props: TwoStateProps
|
||||
override val props: TwoStateProps,
|
||||
) : SourcePreference()
|
||||
|
||||
@@ -14,7 +14,7 @@ import kotlinx.serialization.Serializable
|
||||
@SerialName("EditTextPreference")
|
||||
@Immutable
|
||||
data class EditTextPreference(
|
||||
override val props: EditTextProps
|
||||
override val props: EditTextProps,
|
||||
) : SourcePreference() {
|
||||
@Serializable
|
||||
@Immutable
|
||||
@@ -27,6 +27,6 @@ data class EditTextPreference(
|
||||
override val defaultValueType: String,
|
||||
val dialogTitle: String?,
|
||||
val dialogMessage: String?,
|
||||
val text: String?
|
||||
val text: String?,
|
||||
) : Props<String?>
|
||||
}
|
||||
|
||||
@@ -24,6 +24,6 @@ data class ListPreference(override val props: ListProps) : SourcePreference() {
|
||||
override val defaultValue: String?,
|
||||
override val defaultValueType: String,
|
||||
val entries: List<String>,
|
||||
val entryValues: List<String>
|
||||
val entryValues: List<String>,
|
||||
) : Props<String?>
|
||||
}
|
||||
|
||||
@@ -26,6 +26,6 @@ data class MultiSelectListPreference(override val props: MultiSelectListProps) :
|
||||
val dialogTitle: String?,
|
||||
val dialogMessage: String?,
|
||||
val entries: List<String>,
|
||||
val entryValues: List<String>
|
||||
val entryValues: List<String>,
|
||||
) : Props<List<String>?>
|
||||
}
|
||||
|
||||
@@ -19,6 +19,6 @@ data class SourcePreferenceChange(val position: Int, val value: String) {
|
||||
Json.encodeToString(value as List<String>)
|
||||
} else {
|
||||
value.toString()
|
||||
}
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
@@ -14,5 +14,5 @@ import kotlinx.serialization.Serializable
|
||||
@SerialName("SwitchPreferenceCompat")
|
||||
@Immutable
|
||||
data class SwitchPreference(
|
||||
override val props: TwoStateProps
|
||||
override val props: TwoStateProps,
|
||||
) : SourcePreference()
|
||||
|
||||
@@ -17,5 +17,5 @@ data class TwoStateProps(
|
||||
override val summary: String?,
|
||||
override val currentValue: Boolean?,
|
||||
override val defaultValue: Boolean?,
|
||||
override val defaultValueType: String
|
||||
override val defaultValueType: String,
|
||||
) : Props<Boolean?>
|
||||
|
||||
@@ -28,46 +28,46 @@ interface SourceRepository {
|
||||
|
||||
@GET("api/v1/source/{sourceId}")
|
||||
fun getSourceInfo(
|
||||
@Path("sourceId") sourceId: Long
|
||||
@Path("sourceId") sourceId: Long,
|
||||
): Flow<Source>
|
||||
|
||||
@GET("api/v1/source/{sourceId}/popular/{pageNum}")
|
||||
fun getPopularManga(
|
||||
@Path("sourceId") sourceId: Long,
|
||||
@Path("pageNum") pageNum: Int
|
||||
@Path("pageNum") pageNum: Int,
|
||||
): Flow<MangaPage>
|
||||
|
||||
@GET("api/v1/source/{sourceId}/latest/{pageNum}")
|
||||
fun getLatestManga(
|
||||
@Path("sourceId") sourceId: Long,
|
||||
@Path("pageNum") pageNum: Int
|
||||
@Path("pageNum") pageNum: Int,
|
||||
): Flow<MangaPage>
|
||||
|
||||
@GET("api/v1/source/{sourceId}/search")
|
||||
fun getSearchResults(
|
||||
@Path("sourceId") sourceId: Long,
|
||||
@Query("searchTerm") searchTerm: String?,
|
||||
@Query("pageNum") pageNum: Int
|
||||
@Query("pageNum") pageNum: Int,
|
||||
): Flow<MangaPage>
|
||||
|
||||
@GET("api/v1/source/{sourceId}/filters")
|
||||
fun getFilterList(
|
||||
@Path("sourceId") sourceId: Long,
|
||||
@Query("reset") reset: Boolean = false
|
||||
@Query("reset") reset: Boolean = false,
|
||||
): Flow<List<SourceFilter>>
|
||||
|
||||
@POST("api/v1/source/{sourceId}/filters")
|
||||
@Headers("Content-Type: application/json")
|
||||
fun setFilter(
|
||||
@Path("sourceId") sourceId: Long,
|
||||
@Body sourceFilter: SourceFilterChange
|
||||
@Body sourceFilter: SourceFilterChange,
|
||||
): Flow<HttpResponse>
|
||||
|
||||
@POST("api/v1/source/{sourceId}/filters")
|
||||
@Headers("Content-Type: application/json")
|
||||
fun setFilters(
|
||||
@Path("sourceId") sourceId: Long,
|
||||
@Body sourceFilters: List<SourceFilterChange>
|
||||
@Body sourceFilters: List<SourceFilterChange>,
|
||||
): Flow<HttpResponse>
|
||||
|
||||
@POST("api/v1/source/{sourceId}/quick-search")
|
||||
@@ -75,18 +75,18 @@ interface SourceRepository {
|
||||
fun getQuickSearchResults(
|
||||
@Path("sourceId") sourceId: Long,
|
||||
@Query("pageNum") pageNum: Int,
|
||||
@Body filterData: SourceFilterData
|
||||
@Body filterData: SourceFilterData,
|
||||
): Flow<MangaPage>
|
||||
|
||||
@GET("api/v1/source/{sourceId}/preferences")
|
||||
fun getSourceSettings(
|
||||
@Path("sourceId") sourceId: Long
|
||||
@Path("sourceId") sourceId: Long,
|
||||
): Flow<List<SourcePreference>>
|
||||
|
||||
@POST("api/v1/source/{sourceId}/preferences")
|
||||
@Headers("Content-Type: application/json")
|
||||
fun setSourceSetting(
|
||||
@Path("sourceId") sourceId: Long,
|
||||
@Body sourcePreference: SourcePreferenceChange
|
||||
@Body sourcePreference: SourcePreferenceChange,
|
||||
): Flow<HttpResponse>
|
||||
}
|
||||
|
||||
@@ -17,5 +17,5 @@ enum class StartScreen {
|
||||
|
||||
// History,
|
||||
Sources,
|
||||
Extensions
|
||||
Extensions,
|
||||
}
|
||||
|
||||
@@ -14,5 +14,5 @@ import kotlinx.serialization.Serializable
|
||||
enum class ThemeMode {
|
||||
System,
|
||||
Light,
|
||||
Dark
|
||||
Dark,
|
||||
}
|
||||
|
||||
@@ -17,5 +17,5 @@ data class WindowSettings(
|
||||
val width: Int? = null,
|
||||
val height: Int? = null,
|
||||
val maximized: Boolean? = null,
|
||||
val fullscreen: Boolean? = null
|
||||
val fullscreen: Boolean? = null,
|
||||
)
|
||||
|
||||
@@ -23,7 +23,7 @@ import org.lighthousegames.logging.logging
|
||||
|
||||
class UpdateChecker @Inject constructor(
|
||||
private val updatePreferences: UpdatePreferences,
|
||||
private val client: Http
|
||||
private val client: Http,
|
||||
) {
|
||||
suspend fun await(manualFetch: Boolean, onError: suspend (Throwable) -> Unit = {}) = asFlow(manualFetch)
|
||||
.catch {
|
||||
@@ -35,7 +35,7 @@ class UpdateChecker @Inject constructor(
|
||||
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"
|
||||
"https://api.github.com/repos/$GITHUB_REPO/releases/latest",
|
||||
).body<GithubRelease>()
|
||||
|
||||
if (isNewVersion(latestRelease.version)) {
|
||||
|
||||
@@ -41,7 +41,7 @@ class UpdatesPager @Inject constructor(
|
||||
private val getRecentUpdates: GetRecentUpdates,
|
||||
private val getManga: GetManga,
|
||||
private val getChapter: GetChapter,
|
||||
private val serverListeners: ServerListeners
|
||||
private val serverListeners: ServerListeners,
|
||||
) : CoroutineScope by CoroutineScope(Dispatchers.Default + SupervisorJob()) {
|
||||
private val updatesMutex = Mutex()
|
||||
|
||||
@@ -53,8 +53,8 @@ class UpdatesPager @Inject constructor(
|
||||
Updates.Date(
|
||||
Instant.fromEpochSeconds(first.fetchedAt)
|
||||
.toLocalDateTime(TimeZone.currentSystemDefault())
|
||||
.date
|
||||
)
|
||||
.date,
|
||||
),
|
||||
)
|
||||
} + newUpdates.fold(emptyList()) { list, (manga, chapter) ->
|
||||
val date = (list.lastOrNull() as? Updates.Update)?.let {
|
||||
@@ -136,14 +136,14 @@ class UpdatesPager @Inject constructor(
|
||||
val updates = combine(
|
||||
foldedUpdates,
|
||||
changedManga,
|
||||
changedChapters
|
||||
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
|
||||
chapter = changedChapters[it.chapter.id] ?: it.chapter,
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -165,7 +165,7 @@ class UpdatesPager @Inject constructor(
|
||||
|
||||
fun loadNextPage(
|
||||
onComplete: (() -> Unit)? = null,
|
||||
onError: suspend (Throwable) -> Unit
|
||||
onError: suspend (Throwable) -> Unit,
|
||||
) {
|
||||
launch {
|
||||
if (hasNextPage.value && updatesMutex.tryLock()) {
|
||||
|
||||
@@ -15,5 +15,5 @@ import kotlinx.serialization.Serializable
|
||||
data class GithubRelease(
|
||||
@SerialName("tag_name") val version: String,
|
||||
@SerialName("body") val info: String,
|
||||
@SerialName("html_url") val releaseLink: String
|
||||
@SerialName("html_url") val releaseLink: String,
|
||||
)
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user