mirror of
https://github.com/Suwayomi/TachideskJUI.git
synced 2025-12-10 06:42:05 +01:00
Integrate Ktorfit
This commit is contained in:
@@ -32,6 +32,7 @@ kotlin {
|
||||
languageSettings {
|
||||
optIn("kotlin.RequiresOptIn")
|
||||
optIn("kotlinx.coroutines.ExperimentalCoroutinesApi")
|
||||
optIn("de.jensklingenberg.ktorfit.internal.InternalKtorfitApi")
|
||||
}
|
||||
}
|
||||
val commonMain by getting {
|
||||
@@ -48,6 +49,7 @@ kotlin {
|
||||
api(libs.ktor.auth)
|
||||
api(libs.ktor.logging)
|
||||
api(libs.ktor.websockets)
|
||||
api(libs.ktorfit.lib)
|
||||
api(libs.okio)
|
||||
api(libs.dateTime)
|
||||
api(projects.core)
|
||||
@@ -113,6 +115,9 @@ kotlin {
|
||||
dependencies {
|
||||
add("kspDesktop", libs.kotlinInject.compiler)
|
||||
add("kspAndroid", libs.kotlinInject.compiler)
|
||||
add("kspCommonMainMetadata", libs.ktorfit.ksp)
|
||||
add("kspDesktop", libs.ktorfit.ksp)
|
||||
add("kspAndroid", libs.ktorfit.ksp)
|
||||
}
|
||||
|
||||
buildkonfig {
|
||||
|
||||
@@ -4,14 +4,9 @@
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package ca.gosyer.jui.domain.server.model.requests
|
||||
package ca.gosyer.jui.domain
|
||||
|
||||
annotation class Get
|
||||
import de.jensklingenberg.ktorfit.Ktorfit
|
||||
import de.jensklingenberg.ktorfit.create
|
||||
|
||||
annotation class Post
|
||||
|
||||
annotation class Delete
|
||||
|
||||
annotation class Patch
|
||||
|
||||
annotation class WS
|
||||
inline fun <reified T> Ktorfit.createIt(): T = create()
|
||||
@@ -21,7 +21,7 @@ class ImportBackupFile @Inject constructor(private val backupRepository: BackupR
|
||||
.singleOrNull()
|
||||
|
||||
fun asFlow(file: Path, block: HttpRequestBuilder.() -> Unit = {}) =
|
||||
backupRepository.importBackupFile(file, block)
|
||||
backupRepository.importBackupFile(BackupRepository.buildBackupFormData(file), block)
|
||||
|
||||
companion object {
|
||||
private val log = logging()
|
||||
|
||||
@@ -21,7 +21,7 @@ class ValidateBackupFile @Inject constructor(private val backupRepository: Backu
|
||||
.singleOrNull()
|
||||
|
||||
fun asFlow(file: Path, block: HttpRequestBuilder.() -> Unit = {}) =
|
||||
backupRepository.validateBackupFile(file, block)
|
||||
backupRepository.validateBackupFile(BackupRepository.buildBackupFormData(file), block)
|
||||
|
||||
companion object {
|
||||
private val log = logging()
|
||||
|
||||
@@ -6,14 +6,55 @@
|
||||
|
||||
package ca.gosyer.jui.domain.backup.service
|
||||
|
||||
import ca.gosyer.jui.core.io.SYSTEM
|
||||
import ca.gosyer.jui.domain.backup.model.BackupValidationResult
|
||||
import de.jensklingenberg.ktorfit.http.Multipart
|
||||
import de.jensklingenberg.ktorfit.http.POST
|
||||
import de.jensklingenberg.ktorfit.http.Part
|
||||
import de.jensklingenberg.ktorfit.http.ReqBuilder
|
||||
import io.ktor.client.request.HttpRequestBuilder
|
||||
import io.ktor.client.request.forms.formData
|
||||
import io.ktor.client.statement.HttpResponse
|
||||
import io.ktor.http.ContentType
|
||||
import io.ktor.http.Headers
|
||||
import io.ktor.http.HttpHeaders
|
||||
import io.ktor.http.content.PartData
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import okio.FileSystem
|
||||
import okio.Path
|
||||
import okio.buffer
|
||||
|
||||
interface BackupRepository {
|
||||
fun importBackupFile(file: Path, block: HttpRequestBuilder.() -> Unit = {}): Flow<HttpResponse>
|
||||
fun validateBackupFile(file: Path, block: HttpRequestBuilder.() -> Unit = {}): Flow<BackupValidationResult>
|
||||
fun exportBackupFile(block: HttpRequestBuilder.() -> Unit = {}): Flow<HttpResponse>
|
||||
|
||||
@Multipart
|
||||
@POST("api/v1/backup/import/file")
|
||||
fun importBackupFile(
|
||||
@Part("") formData: List<PartData>,
|
||||
@ReqBuilder block: HttpRequestBuilder.() -> Unit = {}
|
||||
): Flow<HttpResponse>
|
||||
|
||||
@Multipart
|
||||
@POST("api/v1/backup/validate/file")
|
||||
fun validateBackupFile(
|
||||
@Part("") formData: List<PartData>,
|
||||
@ReqBuilder block: HttpRequestBuilder.() -> Unit = {}
|
||||
): Flow<BackupValidationResult>
|
||||
|
||||
@POST("api/v1/backup/export/file")
|
||||
fun exportBackupFile(
|
||||
@ReqBuilder block: HttpRequestBuilder.() -> Unit = {}
|
||||
): Flow<HttpResponse>
|
||||
|
||||
companion object {
|
||||
fun buildBackupFormData(file: Path) = formData {
|
||||
append(
|
||||
"backup.proto.gz",
|
||||
FileSystem.SYSTEM.source(file).buffer().readByteArray(),
|
||||
Headers.build {
|
||||
append(HttpHeaders.ContentType, ContentType.MultiPart.FormData.toString())
|
||||
append(HttpHeaders.ContentDisposition, "filename=backup.proto.gz")
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,6 +8,7 @@ package ca.gosyer.jui.domain.category.interactor
|
||||
|
||||
import ca.gosyer.jui.domain.category.service.CategoryRepository
|
||||
import kotlinx.coroutines.flow.catch
|
||||
import kotlinx.coroutines.flow.map
|
||||
import kotlinx.coroutines.flow.singleOrNull
|
||||
import me.tatarka.inject.annotations.Inject
|
||||
import org.lighthousegames.logging.logging
|
||||
@@ -18,7 +19,12 @@ class GetCategories @Inject constructor(private val categoryRepository: Category
|
||||
.catch { log.warn(it) { "Failed to get categories" } }
|
||||
.singleOrNull()
|
||||
|
||||
fun asFlow(dropDefault: Boolean = false) = categoryRepository.getCategories(dropDefault)
|
||||
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()
|
||||
|
||||
@@ -15,28 +15,24 @@ import org.lighthousegames.logging.logging
|
||||
|
||||
class ModifyCategory @Inject constructor(private val categoryRepository: CategoryRepository) {
|
||||
|
||||
suspend fun await(categoryId: Long, name: String? = null, isLanding: Boolean? = null) = asFlow(
|
||||
suspend fun await(categoryId: Long, name: String) = asFlow(
|
||||
categoryId = categoryId,
|
||||
name = name,
|
||||
isLanding = isLanding
|
||||
).catch { log.warn(it) { "Failed to modify category $categoryId with options: name=$name,isLanding=$isLanding" } }.collect()
|
||||
name = name
|
||||
).catch { log.warn(it) { "Failed to modify category $categoryId with options: name=$name" } }.collect()
|
||||
|
||||
suspend fun await(category: Category, name: String? = null, isLanding: Boolean? = null) = asFlow(
|
||||
suspend fun await(category: Category, name: String? = null) = asFlow(
|
||||
category = category,
|
||||
name = name,
|
||||
isLanding = isLanding
|
||||
).catch { log.warn(it) { "Failed to modify category ${category.name} with options: name=$name,isLanding=$isLanding" } }.collect()
|
||||
name = name
|
||||
).catch { log.warn(it) { "Failed to modify category ${category.name} with options: name=$name" } }.collect()
|
||||
|
||||
fun asFlow(categoryId: Long, name: String? = null, isLanding: Boolean? = null) = categoryRepository.modifyCategory(
|
||||
fun asFlow(categoryId: Long, name: String) = categoryRepository.modifyCategory(
|
||||
categoryId = categoryId,
|
||||
name = name,
|
||||
isLanding = isLanding
|
||||
name = name
|
||||
)
|
||||
|
||||
fun asFlow(category: Category, name: String? = null, isLanding: Boolean? = null) = categoryRepository.modifyCategory(
|
||||
fun asFlow(category: Category, name: String? = null) = categoryRepository.modifyCategory(
|
||||
categoryId = category.id,
|
||||
name = name,
|
||||
isLanding = isLanding
|
||||
name = name ?: category.name
|
||||
)
|
||||
|
||||
companion object {
|
||||
|
||||
@@ -8,17 +8,64 @@ package ca.gosyer.jui.domain.category.service
|
||||
|
||||
import ca.gosyer.jui.domain.category.model.Category
|
||||
import ca.gosyer.jui.domain.manga.model.Manga
|
||||
import de.jensklingenberg.ktorfit.http.DELETE
|
||||
import de.jensklingenberg.ktorfit.http.Field
|
||||
import de.jensklingenberg.ktorfit.http.FormUrlEncoded
|
||||
import de.jensklingenberg.ktorfit.http.GET
|
||||
import de.jensklingenberg.ktorfit.http.PATCH
|
||||
import de.jensklingenberg.ktorfit.http.POST
|
||||
import de.jensklingenberg.ktorfit.http.Path
|
||||
import io.ktor.client.statement.HttpResponse
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
|
||||
interface CategoryRepository {
|
||||
fun getMangaCategories(mangaId: Long): Flow<List<Category>>
|
||||
fun addMangaToCategory(mangaId: Long, categoryId: Long): Flow<HttpResponse>
|
||||
fun removeMangaFromCategory(mangaId: Long, categoryId: Long): Flow<HttpResponse>
|
||||
fun getCategories(dropDefault: Boolean = false): Flow<List<Category>>
|
||||
fun createCategory(name: String): Flow<HttpResponse>
|
||||
fun modifyCategory(categoryId: Long, name: String? = null, isLanding: Boolean? = null): Flow<HttpResponse>
|
||||
fun reorderCategory(to: Int, from: Int): Flow<HttpResponse>
|
||||
fun deleteCategory(categoryId: Long): Flow<HttpResponse>
|
||||
fun getMangaFromCategory(categoryId: Long): Flow<List<Manga>>
|
||||
@GET("api/v1/manga/{mangaId}/category/")
|
||||
fun getMangaCategories(
|
||||
@Path("mangaId") mangaId: Long
|
||||
): Flow<List<Category>>
|
||||
|
||||
@GET("api/v1/manga/{mangaId}/category/{categoryId}")
|
||||
fun addMangaToCategory(
|
||||
@Path("mangaId") mangaId: Long,
|
||||
@Path("categoryId") categoryId: Long
|
||||
): Flow<HttpResponse>
|
||||
|
||||
@DELETE("api/v1/manga/{mangaId}/category/{categoryId}")
|
||||
fun removeMangaFromCategory(
|
||||
@Path("mangaId") mangaId: Long,
|
||||
@Path("categoryId") categoryId: Long
|
||||
): Flow<HttpResponse>
|
||||
|
||||
@GET("api/v1/category/")
|
||||
fun getCategories(): Flow<List<Category>>
|
||||
|
||||
@FormUrlEncoded
|
||||
@POST("api/v1/category/")
|
||||
fun createCategory(
|
||||
@Field("name") name: String
|
||||
): Flow<HttpResponse>
|
||||
|
||||
@FormUrlEncoded
|
||||
@PATCH("api/v1/category/{categoryId}")
|
||||
fun modifyCategory(
|
||||
@Path("categoryId") categoryId: Long,
|
||||
@Field("name") name: String
|
||||
): Flow<HttpResponse>
|
||||
|
||||
@FormUrlEncoded
|
||||
@PATCH("api/v1/category/reorder")
|
||||
fun reorderCategory(
|
||||
@Field("to") to: Int,
|
||||
@Field("from") from: Int
|
||||
): Flow<HttpResponse>
|
||||
|
||||
@DELETE("api/v1/category/{categoryId}")
|
||||
fun deleteCategory(
|
||||
@Path("categoryId") categoryId: Long
|
||||
): Flow<HttpResponse>
|
||||
|
||||
@GET("api/v1/category/{categoryId}")
|
||||
fun getMangaFromCategory(
|
||||
@Path("categoryId") categoryId: Long
|
||||
): Flow<List<Manga>>
|
||||
}
|
||||
|
||||
@@ -0,0 +1,74 @@
|
||||
/*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package ca.gosyer.jui.domain.chapter.interactor
|
||||
|
||||
import ca.gosyer.jui.domain.chapter.model.Chapter
|
||||
import ca.gosyer.jui.domain.chapter.service.ChapterRepository
|
||||
import ca.gosyer.jui.domain.manga.model.Manga
|
||||
import kotlinx.coroutines.flow.catch
|
||||
import kotlinx.coroutines.flow.collect
|
||||
import me.tatarka.inject.annotations.Inject
|
||||
import org.lighthousegames.logging.logging
|
||||
|
||||
class UpdateChapterBookmarked @Inject constructor(private val chapterRepository: ChapterRepository) {
|
||||
|
||||
suspend fun await(
|
||||
mangaId: Long,
|
||||
index: Int,
|
||||
bookmarked: Boolean,
|
||||
) = asFlow(mangaId, index, bookmarked)
|
||||
.catch { log.warn(it) { "Failed to update chapter bookmark for chapter $index of $mangaId" } }
|
||||
.collect()
|
||||
|
||||
suspend fun await(
|
||||
manga: Manga,
|
||||
index: Int,
|
||||
bookmarked: Boolean,
|
||||
) = asFlow(manga, index, bookmarked)
|
||||
.catch { log.warn(it) { "Failed to update chapter bookmark for chapter $index of ${manga.title}(${manga.id})" } }
|
||||
.collect()
|
||||
|
||||
suspend fun await(
|
||||
chapter: Chapter,
|
||||
bookmarked: Boolean,
|
||||
) = asFlow(chapter, bookmarked)
|
||||
.catch { log.warn(it) { "Failed to update chapter bookmark for chapter ${chapter.index} of ${chapter.mangaId}" } }
|
||||
.collect()
|
||||
|
||||
fun asFlow(
|
||||
mangaId: Long,
|
||||
index: Int,
|
||||
bookmarked: Boolean,
|
||||
) = chapterRepository.updateChapterBookmarked(
|
||||
mangaId = mangaId,
|
||||
chapterIndex = index,
|
||||
bookmarked = bookmarked,
|
||||
)
|
||||
|
||||
fun asFlow(
|
||||
manga: Manga,
|
||||
index: Int,
|
||||
bookmarked: Boolean,
|
||||
) = chapterRepository.updateChapterBookmarked(
|
||||
mangaId = manga.id,
|
||||
chapterIndex = index,
|
||||
bookmarked = bookmarked,
|
||||
)
|
||||
|
||||
fun asFlow(
|
||||
chapter: Chapter,
|
||||
bookmarked: Boolean,
|
||||
) = chapterRepository.updateChapterBookmarked(
|
||||
mangaId = chapter.mangaId,
|
||||
chapterIndex = chapter.index,
|
||||
bookmarked = bookmarked,
|
||||
)
|
||||
|
||||
companion object {
|
||||
private val log = logging()
|
||||
}
|
||||
}
|
||||
@@ -1,101 +0,0 @@
|
||||
/*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package ca.gosyer.jui.domain.chapter.interactor
|
||||
|
||||
import ca.gosyer.jui.domain.chapter.model.Chapter
|
||||
import ca.gosyer.jui.domain.chapter.service.ChapterRepository
|
||||
import ca.gosyer.jui.domain.manga.model.Manga
|
||||
import kotlinx.coroutines.flow.catch
|
||||
import kotlinx.coroutines.flow.collect
|
||||
import me.tatarka.inject.annotations.Inject
|
||||
import org.lighthousegames.logging.logging
|
||||
|
||||
class UpdateChapterFlags @Inject constructor(private val chapterRepository: ChapterRepository) {
|
||||
|
||||
suspend fun await(
|
||||
mangaId: Long,
|
||||
index: Int,
|
||||
read: Boolean? = null,
|
||||
bookmarked: Boolean? = null,
|
||||
lastPageRead: Int? = null,
|
||||
markPreviousRead: Boolean? = null
|
||||
) = asFlow(mangaId, index, read, bookmarked, lastPageRead, markPreviousRead)
|
||||
.catch { log.warn(it) { "Failed to update chapter flags for chapter $index of $mangaId" } }
|
||||
.collect()
|
||||
|
||||
suspend fun await(
|
||||
manga: Manga,
|
||||
index: Int,
|
||||
read: Boolean? = null,
|
||||
bookmarked: Boolean? = null,
|
||||
lastPageRead: Int? = null,
|
||||
markPreviousRead: Boolean? = null
|
||||
) = asFlow(manga, index, read, bookmarked, lastPageRead, markPreviousRead)
|
||||
.catch { log.warn(it) { "Failed to update chapter flags for chapter $index of ${manga.title}(${manga.id})" } }
|
||||
.collect()
|
||||
|
||||
suspend fun await(
|
||||
chapter: Chapter,
|
||||
read: Boolean? = null,
|
||||
bookmarked: Boolean? = null,
|
||||
lastPageRead: Int? = null,
|
||||
markPreviousRead: Boolean? = null
|
||||
) = asFlow(chapter, read, bookmarked, lastPageRead, markPreviousRead)
|
||||
.catch { log.warn(it) { "Failed to update chapter flags for chapter ${chapter.index} of ${chapter.mangaId}" } }
|
||||
.collect()
|
||||
|
||||
fun asFlow(
|
||||
mangaId: Long,
|
||||
index: Int,
|
||||
read: Boolean? = null,
|
||||
bookmarked: Boolean? = null,
|
||||
lastPageRead: Int? = null,
|
||||
markPreviousRead: Boolean? = null
|
||||
) = chapterRepository.updateChapter(
|
||||
mangaId = mangaId,
|
||||
chapterIndex = index,
|
||||
read = read,
|
||||
bookmarked = bookmarked,
|
||||
lastPageRead = lastPageRead,
|
||||
markPreviousRead = markPreviousRead
|
||||
)
|
||||
|
||||
fun asFlow(
|
||||
manga: Manga,
|
||||
index: Int,
|
||||
read: Boolean? = null,
|
||||
bookmarked: Boolean? = null,
|
||||
lastPageRead: Int? = null,
|
||||
markPreviousRead: Boolean? = null
|
||||
) = chapterRepository.updateChapter(
|
||||
mangaId = manga.id,
|
||||
chapterIndex = index,
|
||||
read = read,
|
||||
bookmarked = bookmarked,
|
||||
lastPageRead = lastPageRead,
|
||||
markPreviousRead = markPreviousRead
|
||||
)
|
||||
|
||||
fun asFlow(
|
||||
chapter: Chapter,
|
||||
read: Boolean? = null,
|
||||
bookmarked: Boolean? = null,
|
||||
lastPageRead: Int? = null,
|
||||
markPreviousRead: Boolean? = null
|
||||
) = chapterRepository.updateChapter(
|
||||
mangaId = chapter.mangaId,
|
||||
chapterIndex = chapter.index,
|
||||
read = read,
|
||||
bookmarked = bookmarked,
|
||||
lastPageRead = lastPageRead,
|
||||
markPreviousRead = markPreviousRead
|
||||
)
|
||||
|
||||
companion object {
|
||||
private val log = logging()
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,74 @@
|
||||
/*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package ca.gosyer.jui.domain.chapter.interactor
|
||||
|
||||
import ca.gosyer.jui.domain.chapter.model.Chapter
|
||||
import ca.gosyer.jui.domain.chapter.service.ChapterRepository
|
||||
import ca.gosyer.jui.domain.manga.model.Manga
|
||||
import kotlinx.coroutines.flow.catch
|
||||
import kotlinx.coroutines.flow.collect
|
||||
import me.tatarka.inject.annotations.Inject
|
||||
import org.lighthousegames.logging.logging
|
||||
|
||||
class UpdateChapterLastPageRead @Inject constructor(private val chapterRepository: ChapterRepository) {
|
||||
|
||||
suspend fun await(
|
||||
mangaId: Long,
|
||||
index: Int,
|
||||
lastPageRead: Int,
|
||||
) = asFlow(mangaId, index, lastPageRead)
|
||||
.catch { log.warn(it) { "Failed to update chapter last page read for chapter $index of $mangaId" } }
|
||||
.collect()
|
||||
|
||||
suspend fun await(
|
||||
manga: Manga,
|
||||
index: Int,
|
||||
lastPageRead: Int,
|
||||
) = asFlow(manga, index, lastPageRead)
|
||||
.catch { log.warn(it) { "Failed to update chapter last page read for chapter $index of ${manga.title}(${manga.id})" } }
|
||||
.collect()
|
||||
|
||||
suspend fun await(
|
||||
chapter: Chapter,
|
||||
lastPageRead: Int,
|
||||
) = asFlow(chapter, lastPageRead)
|
||||
.catch { log.warn(it) { "Failed to update chapter last page read for chapter ${chapter.index} of ${chapter.mangaId}" } }
|
||||
.collect()
|
||||
|
||||
fun asFlow(
|
||||
mangaId: Long,
|
||||
index: Int,
|
||||
lastPageRead: Int,
|
||||
) = chapterRepository.updateChapterLastPageRead(
|
||||
mangaId = mangaId,
|
||||
chapterIndex = index,
|
||||
lastPageRead = lastPageRead,
|
||||
)
|
||||
|
||||
fun asFlow(
|
||||
manga: Manga,
|
||||
index: Int,
|
||||
lastPageRead: Int,
|
||||
) = chapterRepository.updateChapterLastPageRead(
|
||||
mangaId = manga.id,
|
||||
chapterIndex = index,
|
||||
lastPageRead = lastPageRead,
|
||||
)
|
||||
|
||||
fun asFlow(
|
||||
chapter: Chapter,
|
||||
lastPageRead: Int,
|
||||
) = chapterRepository.updateChapterLastPageRead(
|
||||
mangaId = chapter.mangaId,
|
||||
chapterIndex = chapter.index,
|
||||
lastPageRead = lastPageRead,
|
||||
)
|
||||
|
||||
companion object {
|
||||
private val log = logging()
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,65 @@
|
||||
/*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package ca.gosyer.jui.domain.chapter.interactor
|
||||
|
||||
import ca.gosyer.jui.domain.chapter.model.Chapter
|
||||
import ca.gosyer.jui.domain.chapter.service.ChapterRepository
|
||||
import ca.gosyer.jui.domain.manga.model.Manga
|
||||
import kotlinx.coroutines.flow.catch
|
||||
import kotlinx.coroutines.flow.collect
|
||||
import me.tatarka.inject.annotations.Inject
|
||||
import org.lighthousegames.logging.logging
|
||||
|
||||
class UpdateChapterMarkPreviousRead @Inject constructor(private val chapterRepository: ChapterRepository) {
|
||||
|
||||
suspend fun await(
|
||||
mangaId: Long,
|
||||
index: Int
|
||||
) = asFlow(mangaId, index)
|
||||
.catch { log.warn(it) { "Failed to update chapter read status for chapter $index of $mangaId" } }
|
||||
.collect()
|
||||
|
||||
suspend fun await(
|
||||
manga: Manga,
|
||||
index: Int
|
||||
) = asFlow(manga, index)
|
||||
.catch { log.warn(it) { "Failed to update chapter read status for chapter $index of ${manga.title}(${manga.id})" } }
|
||||
.collect()
|
||||
|
||||
suspend fun await(
|
||||
chapter: Chapter
|
||||
) = asFlow(chapter)
|
||||
.catch { log.warn(it) { "Failed to update chapter read status for chapter ${chapter.index} of ${chapter.mangaId}" } }
|
||||
.collect()
|
||||
|
||||
fun asFlow(
|
||||
mangaId: Long,
|
||||
index: Int,
|
||||
) = chapterRepository.updateChapterMarkPrevRead(
|
||||
mangaId = mangaId,
|
||||
chapterIndex = index
|
||||
)
|
||||
|
||||
fun asFlow(
|
||||
manga: Manga,
|
||||
index: Int,
|
||||
) = chapterRepository.updateChapterMarkPrevRead(
|
||||
mangaId = manga.id,
|
||||
chapterIndex = index,
|
||||
)
|
||||
|
||||
fun asFlow(
|
||||
chapter: Chapter,
|
||||
) = chapterRepository.updateChapterMarkPrevRead(
|
||||
mangaId = chapter.mangaId,
|
||||
chapterIndex = chapter.index,
|
||||
)
|
||||
|
||||
companion object {
|
||||
private val log = logging()
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,74 @@
|
||||
/*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package ca.gosyer.jui.domain.chapter.interactor
|
||||
|
||||
import ca.gosyer.jui.domain.chapter.model.Chapter
|
||||
import ca.gosyer.jui.domain.chapter.service.ChapterRepository
|
||||
import ca.gosyer.jui.domain.manga.model.Manga
|
||||
import kotlinx.coroutines.flow.catch
|
||||
import kotlinx.coroutines.flow.collect
|
||||
import me.tatarka.inject.annotations.Inject
|
||||
import org.lighthousegames.logging.logging
|
||||
|
||||
class UpdateChapterRead @Inject constructor(private val chapterRepository: ChapterRepository) {
|
||||
|
||||
suspend fun await(
|
||||
mangaId: Long,
|
||||
index: Int,
|
||||
read: Boolean,
|
||||
) = asFlow(mangaId, index, read)
|
||||
.catch { log.warn(it) { "Failed to update chapter read status for chapter $index of $mangaId" } }
|
||||
.collect()
|
||||
|
||||
suspend fun await(
|
||||
manga: Manga,
|
||||
index: Int,
|
||||
read: Boolean,
|
||||
) = asFlow(manga, index, read)
|
||||
.catch { log.warn(it) { "Failed to update chapter read status for chapter $index of ${manga.title}(${manga.id})" } }
|
||||
.collect()
|
||||
|
||||
suspend fun await(
|
||||
chapter: Chapter,
|
||||
read: Boolean,
|
||||
) = asFlow(chapter, read)
|
||||
.catch { log.warn(it) { "Failed to update chapter read status for chapter ${chapter.index} of ${chapter.mangaId}" } }
|
||||
.collect()
|
||||
|
||||
fun asFlow(
|
||||
mangaId: Long,
|
||||
index: Int,
|
||||
read: Boolean,
|
||||
) = chapterRepository.updateChapterRead(
|
||||
mangaId = mangaId,
|
||||
chapterIndex = index,
|
||||
read = read,
|
||||
)
|
||||
|
||||
fun asFlow(
|
||||
manga: Manga,
|
||||
index: Int,
|
||||
read: Boolean,
|
||||
) = chapterRepository.updateChapterRead(
|
||||
mangaId = manga.id,
|
||||
chapterIndex = index,
|
||||
read = read,
|
||||
)
|
||||
|
||||
fun asFlow(
|
||||
chapter: Chapter,
|
||||
read: Boolean,
|
||||
) = chapterRepository.updateChapterRead(
|
||||
mangaId = chapter.mangaId,
|
||||
chapterIndex = chapter.index,
|
||||
read = read,
|
||||
)
|
||||
|
||||
companion object {
|
||||
private val log = logging()
|
||||
}
|
||||
}
|
||||
@@ -7,31 +7,109 @@
|
||||
package ca.gosyer.jui.domain.chapter.service
|
||||
|
||||
import ca.gosyer.jui.domain.chapter.model.Chapter
|
||||
import de.jensklingenberg.ktorfit.http.DELETE
|
||||
import de.jensklingenberg.ktorfit.http.Field
|
||||
import de.jensklingenberg.ktorfit.http.FormUrlEncoded
|
||||
import de.jensklingenberg.ktorfit.http.GET
|
||||
import de.jensklingenberg.ktorfit.http.PATCH
|
||||
import de.jensklingenberg.ktorfit.http.Path
|
||||
import de.jensklingenberg.ktorfit.http.Query
|
||||
import de.jensklingenberg.ktorfit.http.ReqBuilder
|
||||
import io.ktor.client.request.HttpRequestBuilder
|
||||
import io.ktor.client.statement.HttpResponse
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
|
||||
interface ChapterRepository {
|
||||
fun getChapters(mangaId: Long, refresh: Boolean = false): Flow<List<Chapter>>
|
||||
fun getChapter(mangaId: Long, chapterIndex: Int): Flow<Chapter>
|
||||
|
||||
@GET("api/v1/manga/{mangaId}/chapters")
|
||||
fun getChapters(
|
||||
@Path("mangaId") mangaId: Long,
|
||||
@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
|
||||
): Flow<Chapter>
|
||||
|
||||
/* TODO add once ktorfit supports nullable paremters
|
||||
@FormUrlEncoded
|
||||
@PATCH("/api/v1/manga/{mangaId}/chapter/{chapterIndex}")
|
||||
fun updateChapter(
|
||||
mangaId: Long,
|
||||
chapterIndex: Int,
|
||||
read: Boolean? = null,
|
||||
bookmarked: Boolean? = null,
|
||||
lastPageRead: Int? = null,
|
||||
markPreviousRead: Boolean? = null
|
||||
@Path("mangaId") mangaId: Long,
|
||||
@Path("chapterIndex") chapterIndex: Int,
|
||||
@Field("read") read: Boolean? = null,
|
||||
@Field("bookmarked") bookmarked: Boolean? = null,
|
||||
@Field("lastPageRead") lastPageRead: Int? = null,
|
||||
@Field("markPrevRead") markPreviousRead: Boolean? = null
|
||||
): Flow<HttpResponse>*/
|
||||
|
||||
//todo remove following updateChapter functions once ktorfit supports nullable parameters
|
||||
@FormUrlEncoded
|
||||
@PATCH("api/v1/manga/{mangaId}/chapter/{chapterIndex}")
|
||||
fun updateChapterRead(
|
||||
@Path("mangaId") mangaId: Long,
|
||||
@Path("chapterIndex") chapterIndex: Int,
|
||||
@Field("read") read: Boolean,
|
||||
): Flow<HttpResponse>
|
||||
|
||||
@FormUrlEncoded
|
||||
@PATCH("api/v1/manga/{mangaId}/chapter/{chapterIndex}")
|
||||
fun updateChapterBookmarked(
|
||||
@Path("mangaId") mangaId: Long,
|
||||
@Path("chapterIndex") chapterIndex: Int,
|
||||
@Field("bookmarked") bookmarked: Boolean,
|
||||
): Flow<HttpResponse>
|
||||
|
||||
@FormUrlEncoded
|
||||
@PATCH("api/v1/manga/{mangaId}/chapter/{chapterIndex}")
|
||||
fun updateChapterLastPageRead(
|
||||
@Path("mangaId") mangaId: Long,
|
||||
@Path("chapterIndex") chapterIndex: Int,
|
||||
@Field("lastPageRead") lastPageRead: Int,
|
||||
): Flow<HttpResponse>
|
||||
|
||||
@FormUrlEncoded
|
||||
@PATCH("api/v1/manga/{mangaId}/chapter/{chapterIndex}")
|
||||
fun updateChapterMarkPrevRead(
|
||||
@Path("mangaId") mangaId: Long,
|
||||
@Path("chapterIndex") chapterIndex: Int,
|
||||
@Field("markPrevRead") markPreviousRead: Boolean = true
|
||||
): Flow<HttpResponse>
|
||||
|
||||
@GET("api/v1/manga/{mangaId}/chapter/{chapterIndex}/page/{pageNum}")
|
||||
fun getPage(
|
||||
mangaId: Long,
|
||||
chapterIndex: Int,
|
||||
pageNum: Int,
|
||||
block: HttpRequestBuilder.() -> Unit
|
||||
@Path("mangaId") mangaId: Long,
|
||||
@Path("chapterIndex") chapterIndex: Int,
|
||||
@Path("pageNum") pageNum: Int,
|
||||
@ReqBuilder block: HttpRequestBuilder.() -> Unit
|
||||
): Flow<HttpResponse>
|
||||
|
||||
fun deleteChapterDownload(mangaId: Long, chapterIndex: Int): Flow<HttpResponse>
|
||||
fun queueChapterDownload(mangaId: Long, chapterIndex: Int): Flow<HttpResponse>
|
||||
fun stopChapterDownload(mangaId: Long, chapterIndex: Int): Flow<HttpResponse>
|
||||
fun updateChapterMeta(mangaId: Long, chapterIndex: Int, key: String, value: String): Flow<HttpResponse>
|
||||
@DELETE("api/v1/manga/{mangaId}/chapter/{chapterIndex}")
|
||||
fun deleteChapterDownload(
|
||||
@Path("mangaId") mangaId: Long,
|
||||
@Path("chapterIndex") chapterIndex: Int
|
||||
): Flow<HttpResponse>
|
||||
|
||||
@GET("api/v1/download/{mangaId}/chapter/{chapterIndex}")
|
||||
fun queueChapterDownload(
|
||||
@Path("mangaId") mangaId: Long,
|
||||
@Path("chapterIndex") chapterIndex: Int
|
||||
): Flow<HttpResponse>
|
||||
|
||||
@DELETE("api/v1/download/{mangaId}/chapter/{chapterIndex}")
|
||||
fun stopChapterDownload(
|
||||
@Path("mangaId") mangaId: Long,
|
||||
@Path("chapterIndex") chapterIndex: Int
|
||||
): Flow<HttpResponse>
|
||||
|
||||
@FormUrlEncoded
|
||||
@PATCH("api/v1/manga/{mangaId}/chapter/{chapterIndex}/meta")
|
||||
fun updateChapterMeta(
|
||||
@Path("mangaId") mangaId: Long,
|
||||
@Path("chapterIndex") chapterIndex: Int,
|
||||
@Field("key") key: String,
|
||||
@Field("value") value: String
|
||||
): Flow<HttpResponse>
|
||||
}
|
||||
|
||||
@@ -6,11 +6,17 @@
|
||||
|
||||
package ca.gosyer.jui.domain.download.service
|
||||
|
||||
import de.jensklingenberg.ktorfit.http.GET
|
||||
import io.ktor.client.statement.HttpResponse
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
|
||||
interface DownloadRepository {
|
||||
@GET("api/v1/downloads/start")
|
||||
fun startDownloading(): Flow<HttpResponse>
|
||||
|
||||
@GET("api/v1/downloads/stop")
|
||||
fun stopDownloading(): Flow<HttpResponse>
|
||||
|
||||
@GET("api/v1/downloads/clear")
|
||||
fun clearDownloadQueue(): Flow<HttpResponse>
|
||||
}
|
||||
|
||||
@@ -11,7 +11,6 @@ import ca.gosyer.jui.domain.download.model.DownloadChapter
|
||||
import ca.gosyer.jui.domain.download.model.DownloadStatus
|
||||
import ca.gosyer.jui.domain.download.model.DownloaderStatus
|
||||
import ca.gosyer.jui.domain.server.Http
|
||||
import ca.gosyer.jui.domain.server.model.requests.downloadsQuery
|
||||
import ca.gosyer.jui.domain.server.service.ServerPreferences
|
||||
import io.ktor.websocket.Frame
|
||||
import io.ktor.websocket.readText
|
||||
@@ -28,7 +27,7 @@ class DownloadService @Inject constructor(
|
||||
get() = status
|
||||
|
||||
override val query: String
|
||||
get() = downloadsQuery()
|
||||
get() = "/api/v1/downloads"
|
||||
|
||||
override suspend fun onReceived(frame: Frame.Text) {
|
||||
val status = json.decodeFromString<DownloadStatus>(frame.readText())
|
||||
|
||||
@@ -19,7 +19,7 @@ class InstallExtension @Inject constructor(private val extensionRepository: Exte
|
||||
.catch { log.warn(it) { "Failed to install extension ${extension.apkName}" } }
|
||||
.collect()
|
||||
|
||||
fun asFlow(extension: Extension) = extensionRepository.installExtension(extension)
|
||||
fun asFlow(extension: Extension) = extensionRepository.installExtension(extension.pkgName)
|
||||
|
||||
companion object {
|
||||
private val log = logging()
|
||||
|
||||
@@ -19,7 +19,7 @@ class UninstallExtension @Inject constructor(private val extensionRepository: Ex
|
||||
.catch { log.warn(it) { "Failed to uninstall extension ${extension.apkName}" } }
|
||||
.collect()
|
||||
|
||||
fun asFlow(extension: Extension) = extensionRepository.uninstallExtension(extension)
|
||||
fun asFlow(extension: Extension) = extensionRepository.uninstallExtension(extension.pkgName)
|
||||
|
||||
companion object {
|
||||
private val log = logging()
|
||||
|
||||
@@ -19,7 +19,7 @@ class UpdateExtension @Inject constructor(private val extensionRepository: Exten
|
||||
.catch { log.warn(it) { "Failed to update extension ${extension.apkName}" } }
|
||||
.collect()
|
||||
|
||||
fun asFlow(extension: Extension) = extensionRepository.updateExtension(extension)
|
||||
fun asFlow(extension: Extension) = extensionRepository.updateExtension(extension.pkgName)
|
||||
|
||||
companion object {
|
||||
private val log = logging()
|
||||
|
||||
@@ -7,15 +7,36 @@
|
||||
package ca.gosyer.jui.domain.extension.service
|
||||
|
||||
import ca.gosyer.jui.domain.extension.model.Extension
|
||||
import de.jensklingenberg.ktorfit.http.GET
|
||||
import de.jensklingenberg.ktorfit.http.Path
|
||||
import de.jensklingenberg.ktorfit.http.ReqBuilder
|
||||
import io.ktor.client.request.HttpRequestBuilder
|
||||
import io.ktor.client.statement.HttpResponse
|
||||
import io.ktor.utils.io.ByteReadChannel
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
|
||||
interface ExtensionRepository {
|
||||
@GET("api/v1/extension/list")
|
||||
fun getExtensionList(): Flow<List<Extension>>
|
||||
fun installExtension(extension: Extension): Flow<HttpResponse>
|
||||
fun updateExtension(extension: Extension): Flow<HttpResponse>
|
||||
fun uninstallExtension(extension: Extension): Flow<HttpResponse>
|
||||
fun getApkIcon(extension: Extension, block: HttpRequestBuilder.() -> Unit): Flow<ByteReadChannel>
|
||||
|
||||
@GET("api/v1/extension/install/{pkgName}")
|
||||
fun installExtension(
|
||||
@Path("pkgName") pkgName: String
|
||||
): Flow<HttpResponse>
|
||||
|
||||
@GET("api/v1/extension/update/{pkgName}")
|
||||
fun updateExtension(
|
||||
@Path("pkgName") pkgName: String
|
||||
): Flow<HttpResponse>
|
||||
|
||||
@GET("api/v1/extension/uninstall/{pkgName}")
|
||||
fun uninstallExtension(
|
||||
@Path("pkgName") pkgName: String
|
||||
): Flow<HttpResponse>
|
||||
|
||||
@GET("api/v1/extension/icon/{apkName}")
|
||||
fun getApkIcon(
|
||||
@Path("apkName") apkName: String,
|
||||
@ReqBuilder block: HttpRequestBuilder.() -> Unit
|
||||
): Flow<ByteReadChannel>
|
||||
}
|
||||
|
||||
@@ -6,10 +6,21 @@
|
||||
|
||||
package ca.gosyer.jui.domain.library.service
|
||||
|
||||
import de.jensklingenberg.ktorfit.http.DELETE
|
||||
import de.jensklingenberg.ktorfit.http.GET
|
||||
import de.jensklingenberg.ktorfit.http.Path
|
||||
import io.ktor.client.statement.HttpResponse
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
|
||||
interface LibraryRepository {
|
||||
fun addMangaToLibrary(mangaId: Long): Flow<HttpResponse>
|
||||
fun removeMangaFromLibrary(mangaId: Long): Flow<HttpResponse>
|
||||
|
||||
@GET("api/v1/manga/{mangaId}/library")
|
||||
fun addMangaToLibrary(
|
||||
@Path("mangaId") mangaId: Long
|
||||
): Flow<HttpResponse>
|
||||
|
||||
@DELETE("api/v1/manga/{mangaId}/library")
|
||||
fun removeMangaFromLibrary(
|
||||
@Path("mangaId") mangaId: Long
|
||||
): Flow<HttpResponse>
|
||||
}
|
||||
|
||||
@@ -9,7 +9,6 @@ package ca.gosyer.jui.domain.library.service
|
||||
import ca.gosyer.jui.domain.base.WebsocketService
|
||||
import ca.gosyer.jui.domain.library.model.UpdateStatus
|
||||
import ca.gosyer.jui.domain.server.Http
|
||||
import ca.gosyer.jui.domain.server.model.requests.updatesQuery
|
||||
import ca.gosyer.jui.domain.server.service.ServerPreferences
|
||||
import io.ktor.websocket.Frame
|
||||
import io.ktor.websocket.readText
|
||||
@@ -26,7 +25,7 @@ class LibraryUpdateService @Inject constructor(
|
||||
override val _status: MutableStateFlow<Status> = MutableStateFlow(Status.STARTING)
|
||||
|
||||
override val query: String
|
||||
get() = updatesQuery()
|
||||
get() = "/api/v1/update"
|
||||
|
||||
override suspend fun onReceived(frame: Frame.Text) {
|
||||
val status = json.decodeFromString<UpdateStatus>(frame.readText())
|
||||
|
||||
@@ -7,13 +7,36 @@
|
||||
package ca.gosyer.jui.domain.manga.service
|
||||
|
||||
import ca.gosyer.jui.domain.manga.model.Manga
|
||||
import de.jensklingenberg.ktorfit.http.Field
|
||||
import de.jensklingenberg.ktorfit.http.FormUrlEncoded
|
||||
import de.jensklingenberg.ktorfit.http.GET
|
||||
import de.jensklingenberg.ktorfit.http.PATCH
|
||||
import de.jensklingenberg.ktorfit.http.Path
|
||||
import de.jensklingenberg.ktorfit.http.Query
|
||||
import de.jensklingenberg.ktorfit.http.ReqBuilder
|
||||
import io.ktor.client.request.HttpRequestBuilder
|
||||
import io.ktor.client.statement.HttpResponse
|
||||
import io.ktor.utils.io.ByteReadChannel
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
|
||||
interface MangaRepository {
|
||||
fun getManga(mangaId: Long, refresh: Boolean = false): Flow<Manga>
|
||||
fun getMangaThumbnail(mangaId: Long, block: HttpRequestBuilder.() -> Unit): Flow<ByteReadChannel>
|
||||
fun updateMangaMeta(mangaId: Long, key: String, value: String): Flow<HttpResponse>
|
||||
@GET("api/v1/manga/{mangaId}/")
|
||||
fun getManga(
|
||||
@Path("mangaId") mangaId: Long,
|
||||
@Query("onlineFetch") refresh: Boolean = false
|
||||
): Flow<Manga>
|
||||
|
||||
@GET("api/v1/manga/{mangaId}/thumbnail")
|
||||
fun getMangaThumbnail(
|
||||
@Path("mangaId") mangaId: Long,
|
||||
@ReqBuilder block: HttpRequestBuilder.() -> Unit
|
||||
): Flow<ByteReadChannel>
|
||||
|
||||
@PATCH("api/v1/manga/{mangaId}/meta")
|
||||
@FormUrlEncoded
|
||||
fun updateMangaMeta(
|
||||
@Path("mangaId") mangaId: Long,
|
||||
@Field("key") key: String,
|
||||
@Field("value") value: String
|
||||
): Flow<HttpResponse>
|
||||
}
|
||||
|
||||
@@ -1,27 +0,0 @@
|
||||
/*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package ca.gosyer.jui.domain.server.model.requests
|
||||
|
||||
@Post
|
||||
fun backupImportRequest() =
|
||||
"/api/v1/backup/import"
|
||||
|
||||
@Post
|
||||
fun backupFileImportRequest() =
|
||||
"/api/v1/backup/import/file"
|
||||
|
||||
@Post
|
||||
fun backupExportRequest() =
|
||||
"/api/v1/backup/export"
|
||||
|
||||
@Post
|
||||
fun backupFileExportRequest() =
|
||||
"/api/v1/backup/export/file"
|
||||
|
||||
@Post
|
||||
fun validateBackupFileRequest() =
|
||||
"/api/v1/backup/validate/file"
|
||||
@@ -1,46 +0,0 @@
|
||||
/*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package ca.gosyer.jui.domain.server.model.requests
|
||||
|
||||
@Get
|
||||
fun getMangaCategoriesQuery(mangaId: Long) =
|
||||
"/api/v1/manga/$mangaId/category/"
|
||||
|
||||
@Get
|
||||
fun addMangaToCategoryQuery(mangaId: Long, categoryId: Long) =
|
||||
"/api/v1/manga/$mangaId/category/$categoryId"
|
||||
|
||||
@Delete
|
||||
fun removeMangaFromCategoryRequest(mangaId: Long, categoryId: Long) =
|
||||
"/api/v1/manga/$mangaId/category/$categoryId"
|
||||
|
||||
@Get
|
||||
fun getCategoriesQuery() =
|
||||
"/api/v1/category/"
|
||||
|
||||
/**
|
||||
* Post a formbody with the param {name} for creation of a category
|
||||
*/
|
||||
@Post
|
||||
fun createCategoryRequest() =
|
||||
"/api/v1/category/"
|
||||
|
||||
@Patch
|
||||
fun categoryModifyRequest(categoryId: Long) =
|
||||
"/api/v1/category/$categoryId"
|
||||
|
||||
@Patch
|
||||
fun categoryReorderRequest() =
|
||||
"/api/v1/category/reorder"
|
||||
|
||||
@Delete
|
||||
fun categoryDeleteRequest(categoryId: Long) =
|
||||
"/api/v1/category/$categoryId"
|
||||
|
||||
@Get
|
||||
fun getMangaInCategoryQuery(categoryId: Long) =
|
||||
"/api/v1/category/$categoryId"
|
||||
@@ -1,39 +0,0 @@
|
||||
/*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package ca.gosyer.jui.domain.server.model.requests
|
||||
|
||||
@Get
|
||||
fun getMangaChaptersQuery(mangaId: Long) =
|
||||
"/api/v1/manga/$mangaId/chapters"
|
||||
|
||||
@Get
|
||||
fun getChapterQuery(mangaId: Long, chapterIndex: Int) =
|
||||
"/api/v1/manga/$mangaId/chapter/$chapterIndex"
|
||||
|
||||
@Patch
|
||||
fun updateChapterRequest(mangaId: Long, chapterIndex: Int) =
|
||||
"/api/v1/manga/$mangaId/chapter/$chapterIndex"
|
||||
|
||||
@Get
|
||||
fun getPageQuery(mangaId: Long, chapterIndex: Int, index: Int) =
|
||||
"/api/v1/manga/$mangaId/chapter/$chapterIndex/page/$index"
|
||||
|
||||
@Delete
|
||||
fun deleteDownloadedChapterRequest(mangaId: Long, chapterIndex: Int) =
|
||||
"/api/v1/manga/$mangaId/chapter/$chapterIndex"
|
||||
|
||||
@Get
|
||||
fun queueDownloadChapterRequest(mangaId: Long, chapterIndex: Int) =
|
||||
"/api/v1/download/$mangaId/chapter/$chapterIndex"
|
||||
|
||||
@Delete
|
||||
fun stopDownloadingChapterRequest(mangaId: Long, chapterIndex: Int) =
|
||||
"/api/v1/download/$mangaId/chapter/$chapterIndex"
|
||||
|
||||
@Patch
|
||||
fun updateChapterMetaRequest(mangaId: Long, chapterIndex: Int) =
|
||||
"/api/v1/manga/$mangaId/chapter/$chapterIndex/meta"
|
||||
@@ -1,23 +0,0 @@
|
||||
/*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package ca.gosyer.jui.domain.server.model.requests
|
||||
|
||||
@WS
|
||||
fun downloadsQuery() =
|
||||
"/api/v1/downloads"
|
||||
|
||||
@Get
|
||||
fun downloadsStartRequest() =
|
||||
"/api/v1/downloads/start"
|
||||
|
||||
@Get
|
||||
fun downloadsStopRequest() =
|
||||
"/api/v1/downloads/stop"
|
||||
|
||||
@Get
|
||||
fun downloadsClearRequest() =
|
||||
"/api/v1/downloads/clear"
|
||||
@@ -1,27 +0,0 @@
|
||||
/*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package ca.gosyer.jui.domain.server.model.requests
|
||||
|
||||
@Get
|
||||
fun extensionListQuery() =
|
||||
"/api/v1/extension/list"
|
||||
|
||||
@Get
|
||||
fun apkInstallQuery(pkgName: String) =
|
||||
"/api/v1/extension/install/$pkgName"
|
||||
|
||||
@Get
|
||||
fun apkUpdateQuery(pkgName: String) =
|
||||
"/api/v1/extension/update/$pkgName"
|
||||
|
||||
@Get
|
||||
fun apkUninstallQuery(pkgName: String) =
|
||||
"/api/v1/extension/uninstall/$pkgName"
|
||||
|
||||
@Get
|
||||
fun apkIconQuery(apkName: String) =
|
||||
"/api/v1/extension/icon/$apkName"
|
||||
@@ -1,15 +0,0 @@
|
||||
/*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package ca.gosyer.jui.domain.server.model.requests
|
||||
|
||||
@Get
|
||||
fun addMangaToLibraryQuery(mangaId: Long) =
|
||||
"/api/v1/manga/$mangaId/library"
|
||||
|
||||
@Delete
|
||||
fun removeMangaFromLibraryRequest(mangaId: Long) =
|
||||
"/api/v1/manga/$mangaId/library"
|
||||
@@ -1,19 +0,0 @@
|
||||
/*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package ca.gosyer.jui.domain.server.model.requests
|
||||
|
||||
@Get
|
||||
fun mangaQuery(mangaId: Long) =
|
||||
"/api/v1/manga/$mangaId/"
|
||||
|
||||
@Get
|
||||
fun mangaThumbnailQuery(mangaId: Long) =
|
||||
"/api/v1/manga/$mangaId/thumbnail"
|
||||
|
||||
@Post
|
||||
fun updateMangaMetaRequest(mangaId: Long) =
|
||||
"/api/v1/manga/$mangaId/meta"
|
||||
@@ -1,15 +0,0 @@
|
||||
/*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package ca.gosyer.jui.domain.server.model.requests
|
||||
|
||||
@Get
|
||||
fun aboutQuery() =
|
||||
"/api/v1/settings/about"
|
||||
|
||||
@Get
|
||||
fun checkUpdateQuery() =
|
||||
"/api/v1/settings/check-update"
|
||||
@@ -1,47 +0,0 @@
|
||||
/*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package ca.gosyer.jui.domain.server.model.requests
|
||||
|
||||
@Get
|
||||
fun sourceListQuery() =
|
||||
"/api/v1/source/list"
|
||||
|
||||
@Get
|
||||
fun sourceInfoQuery(sourceId: Long) =
|
||||
"/api/v1/source/$sourceId"
|
||||
|
||||
@Get
|
||||
fun sourcePopularQuery(sourceId: Long, pageNum: Int) =
|
||||
"/api/v1/source/$sourceId/popular/$pageNum"
|
||||
|
||||
@Get
|
||||
fun sourceLatestQuery(sourceId: Long, pageNum: Int) =
|
||||
"/api/v1/source/$sourceId/latest/$pageNum"
|
||||
|
||||
@Get
|
||||
fun globalSearchQuery() =
|
||||
"/api/v1/source/all/search"
|
||||
|
||||
@Get
|
||||
fun sourceSearchQuery(sourceId: Long) =
|
||||
"/api/v1/source/$sourceId/search"
|
||||
|
||||
@Get
|
||||
fun getFilterListQuery(sourceId: Long) =
|
||||
"/api/v1/source/$sourceId/filters"
|
||||
|
||||
@Post
|
||||
fun setFilterRequest(sourceId: Long) =
|
||||
"/api/v1/source/$sourceId/filters"
|
||||
|
||||
@Get
|
||||
fun getSourceSettingsQuery(sourceId: Long) =
|
||||
"/api/v1/source/$sourceId/preferences"
|
||||
|
||||
@Post
|
||||
fun updateSourceSettingQuery(sourceId: Long) =
|
||||
"/api/v1/source/$sourceId/preferences"
|
||||
@@ -1,23 +0,0 @@
|
||||
/*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package ca.gosyer.jui.domain.server.model.requests
|
||||
|
||||
@Get
|
||||
fun recentUpdatesQuery(pageNum: Int) =
|
||||
"/api/v1/update/recentChapters/$pageNum"
|
||||
|
||||
@Post
|
||||
fun fetchUpdatesRequest() =
|
||||
"/api/v1/update/fetch"
|
||||
|
||||
@Get
|
||||
fun updatesSummaryQuery() =
|
||||
"/api/v1/update/summary"
|
||||
|
||||
@WS
|
||||
fun updatesQuery() =
|
||||
"/api/v1/update"
|
||||
@@ -7,10 +7,15 @@
|
||||
package ca.gosyer.jui.domain.settings.service
|
||||
|
||||
import ca.gosyer.jui.domain.settings.model.About
|
||||
import de.jensklingenberg.ktorfit.http.GET
|
||||
import de.jensklingenberg.ktorfit.http.POST
|
||||
import io.ktor.client.statement.HttpResponse
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
|
||||
interface SettingsRepository {
|
||||
@GET("api/v1/settings/about")
|
||||
fun aboutServer(): Flow<About>
|
||||
|
||||
@POST("api/v1/settings/check-update")
|
||||
fun checkUpdate(): Flow<HttpResponse>
|
||||
}
|
||||
|
||||
@@ -12,20 +12,62 @@ import ca.gosyer.jui.domain.source.model.sourcefilters.SourceFilter
|
||||
import ca.gosyer.jui.domain.source.model.sourcefilters.SourceFilterChange
|
||||
import ca.gosyer.jui.domain.source.model.sourcepreference.SourcePreference
|
||||
import ca.gosyer.jui.domain.source.model.sourcepreference.SourcePreferenceChange
|
||||
import de.jensklingenberg.ktorfit.http.Body
|
||||
import de.jensklingenberg.ktorfit.http.GET
|
||||
import de.jensklingenberg.ktorfit.http.POST
|
||||
import de.jensklingenberg.ktorfit.http.Path
|
||||
import de.jensklingenberg.ktorfit.http.Query
|
||||
import io.ktor.client.statement.HttpResponse
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
|
||||
interface SourceRepository {
|
||||
@GET("api/v1/source/list")
|
||||
fun getSourceList(): Flow<List<Source>>
|
||||
fun getSourceInfo(sourceId: Long): Flow<Source>
|
||||
fun getPopularManga(sourceId: Long, pageNum: Int): Flow<MangaPage>
|
||||
fun getLatestManga(sourceId: Long, pageNum: Int): Flow<MangaPage>
|
||||
fun getSearchResults(sourceId: Long, searchTerm: String, pageNum: Int): Flow<MangaPage>
|
||||
fun getFilterList(sourceId: Long, reset: Boolean = false): Flow<List<SourceFilter>>
|
||||
fun setFilter(sourceId: Long, sourceFilter: SourceFilterChange): Flow<HttpResponse>
|
||||
fun setFilter(sourceId: Long, position: Int, value: Any): Flow<HttpResponse>
|
||||
fun setFilter(sourceId: Long, parentPosition: Int, childPosition: Int, value: Any): Flow<HttpResponse>
|
||||
fun getSourceSettings(sourceId: Long): Flow<List<SourcePreference>>
|
||||
fun setSourceSetting(sourceId: Long, sourcePreference: SourcePreferenceChange): Flow<HttpResponse>
|
||||
fun setSourceSetting(sourceId: Long, position: Int, value: Any): Flow<HttpResponse>
|
||||
|
||||
@GET("api/v1/source/{sourceId}")
|
||||
fun getSourceInfo(
|
||||
@Path("sourceId") sourceId: Long
|
||||
): Flow<Source>
|
||||
|
||||
@GET("api/v1/source/{sourceId}/popular/{pageNum}")
|
||||
fun getPopularManga(
|
||||
@Path("sourceId") sourceId: Long,
|
||||
@Path("pageNum") pageNum: Int
|
||||
): Flow<MangaPage>
|
||||
|
||||
@GET("api/v1/source/{sourceId}/latest/{pageNum}")
|
||||
fun getLatestManga(
|
||||
@Path("sourceId") sourceId: Long,
|
||||
@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
|
||||
): Flow<MangaPage>
|
||||
|
||||
@GET("api/v1/source/{sourceId}/filters")
|
||||
fun getFilterList(
|
||||
@Path("sourceId") sourceId: Long,
|
||||
@Query("reset") reset: Boolean = false
|
||||
): Flow<List<SourceFilter>>
|
||||
|
||||
@POST("api/v1/source/{sourceId}/filters")
|
||||
fun setFilter(
|
||||
@Path("sourceId") sourceId: Long,
|
||||
@Body sourceFilter: SourceFilterChange
|
||||
): Flow<HttpResponse>
|
||||
|
||||
@GET("api/v1/source/{sourceId}/preferences")
|
||||
fun getSourceSettings(
|
||||
@Path("sourceId") sourceId: Long
|
||||
): Flow<List<SourcePreference>>
|
||||
|
||||
@POST("api/v1/source/{sourceId}/preferences")
|
||||
fun setSourceSetting(
|
||||
@Path("sourceId") sourceId: Long,
|
||||
@Body sourcePreference: SourcePreferenceChange
|
||||
): Flow<HttpResponse>
|
||||
}
|
||||
|
||||
@@ -7,11 +7,26 @@
|
||||
package ca.gosyer.jui.domain.updates.service
|
||||
|
||||
import ca.gosyer.jui.domain.updates.model.Updates
|
||||
import de.jensklingenberg.ktorfit.http.Field
|
||||
import de.jensklingenberg.ktorfit.http.FormUrlEncoded
|
||||
import de.jensklingenberg.ktorfit.http.GET
|
||||
import de.jensklingenberg.ktorfit.http.POST
|
||||
import de.jensklingenberg.ktorfit.http.Path
|
||||
import io.ktor.client.statement.HttpResponse
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
|
||||
interface UpdatesRepository {
|
||||
fun getRecentUpdates(pageNum: Int): Flow<Updates>
|
||||
@GET("api/v1/update/recentChapters/{pageNum}/")
|
||||
fun getRecentUpdates(
|
||||
@Path("pageNum") pageNum: Int
|
||||
): Flow<Updates>
|
||||
|
||||
@POST("api/v1/update/fetch/")
|
||||
fun updateLibrary(): Flow<HttpResponse>
|
||||
fun updateCategory(categoryId: Long): Flow<HttpResponse>
|
||||
|
||||
@POST("api/v1/update/fetch/")
|
||||
@FormUrlEncoded
|
||||
fun updateCategory(
|
||||
@Field("category") categoryId: Long
|
||||
): Flow<HttpResponse>
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user