mirror of
https://github.com/Suwayomi/TachideskJUI.git
synced 2025-12-10 06:42:05 +01:00
Fixes for Manga page with GraphQL
This commit is contained in:
@@ -1,50 +1,4 @@
|
|||||||
package ca.gosyer.jui.data
|
package ca.gosyer.jui.data
|
||||||
|
|
||||||
import ca.gosyer.jui.domain.backup.service.createBackupRepositoryOld
|
|
||||||
import ca.gosyer.jui.domain.category.service.createCategoryRepositoryOld
|
|
||||||
import ca.gosyer.jui.domain.chapter.service.createChapterRepositoryOld
|
|
||||||
import ca.gosyer.jui.domain.download.service.createDownloadRepositoryOld
|
|
||||||
import ca.gosyer.jui.domain.extension.service.createExtensionRepositoryOld
|
|
||||||
import ca.gosyer.jui.domain.global.service.createGlobalRepositoryOld
|
|
||||||
import ca.gosyer.jui.domain.library.service.createLibraryRepositoryOld
|
|
||||||
import ca.gosyer.jui.domain.manga.service.createMangaRepositoryOld
|
|
||||||
import ca.gosyer.jui.domain.settings.service.createSettingsRepositoryOld
|
|
||||||
import ca.gosyer.jui.domain.source.service.createSourceRepositoryOld
|
|
||||||
import ca.gosyer.jui.domain.updates.service.createUpdatesRepositoryOld
|
|
||||||
import de.jensklingenberg.ktorfit.Ktorfit
|
|
||||||
import me.tatarka.inject.annotations.Provides
|
|
||||||
|
|
||||||
actual interface SharedDataComponent {
|
actual interface SharedDataComponent {
|
||||||
@Provides
|
|
||||||
fun backupRepositoryOld(ktorfit: Ktorfit) = ktorfit.createBackupRepositoryOld()
|
|
||||||
|
|
||||||
@Provides
|
|
||||||
fun categoryRepositoryOld(ktorfit: Ktorfit) = ktorfit.createCategoryRepositoryOld()
|
|
||||||
|
|
||||||
@Provides
|
|
||||||
fun chapterRepositoryOld(ktorfit: Ktorfit) = ktorfit.createChapterRepositoryOld()
|
|
||||||
|
|
||||||
@Provides
|
|
||||||
fun downloadRepositoryOld(ktorfit: Ktorfit) = ktorfit.createDownloadRepositoryOld()
|
|
||||||
|
|
||||||
@Provides
|
|
||||||
fun extensionRepositoryOld(ktorfit: Ktorfit) = ktorfit.createExtensionRepositoryOld()
|
|
||||||
|
|
||||||
@Provides
|
|
||||||
fun globalRepositoryOld(ktorfit: Ktorfit) = ktorfit.createGlobalRepositoryOld()
|
|
||||||
|
|
||||||
@Provides
|
|
||||||
fun libraryRepositoryOld(ktorfit: Ktorfit) = ktorfit.createLibraryRepositoryOld()
|
|
||||||
|
|
||||||
@Provides
|
|
||||||
fun mangaRepositoryOld(ktorfit: Ktorfit) = ktorfit.createMangaRepositoryOld()
|
|
||||||
|
|
||||||
@Provides
|
|
||||||
fun settingsRepositoryOld(ktorfit: Ktorfit) = ktorfit.createSettingsRepositoryOld()
|
|
||||||
|
|
||||||
@Provides
|
|
||||||
fun sourceRepositoryOld(ktorfit: Ktorfit) = ktorfit.createSourceRepositoryOld()
|
|
||||||
|
|
||||||
@Provides
|
|
||||||
fun updatesRepositoryOld(ktorfit: Ktorfit) = ktorfit.createUpdatesRepositoryOld()
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -229,3 +229,14 @@ mutation SetSettings(
|
|||||||
clientMutationId
|
clientMutationId
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
query AboutServer {
|
||||||
|
aboutServer {
|
||||||
|
buildTime
|
||||||
|
buildType
|
||||||
|
discord
|
||||||
|
github
|
||||||
|
name
|
||||||
|
version
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -6,6 +6,7 @@
|
|||||||
|
|
||||||
package ca.gosyer.jui.data.settings
|
package ca.gosyer.jui.data.settings
|
||||||
|
|
||||||
|
import ca.gosyer.jui.data.graphql.AboutServerQuery
|
||||||
import ca.gosyer.jui.data.graphql.AllSettingsQuery
|
import ca.gosyer.jui.data.graphql.AllSettingsQuery
|
||||||
import ca.gosyer.jui.data.graphql.SetSettingsMutation
|
import ca.gosyer.jui.data.graphql.SetSettingsMutation
|
||||||
import ca.gosyer.jui.data.graphql.fragment.SettingsTypeFragment
|
import ca.gosyer.jui.data.graphql.fragment.SettingsTypeFragment
|
||||||
@@ -20,6 +21,8 @@ import ca.gosyer.jui.data.graphql.type.WebUIChannel
|
|||||||
import ca.gosyer.jui.data.graphql.type.WebUIFlavor
|
import ca.gosyer.jui.data.graphql.type.WebUIFlavor
|
||||||
import ca.gosyer.jui.data.graphql.type.WebUIInterface
|
import ca.gosyer.jui.data.graphql.type.WebUIInterface
|
||||||
import ca.gosyer.jui.data.util.toOptional
|
import ca.gosyer.jui.data.util.toOptional
|
||||||
|
import ca.gosyer.jui.domain.settings.model.About
|
||||||
|
import ca.gosyer.jui.domain.settings.model.AboutBuildType
|
||||||
import ca.gosyer.jui.domain.settings.model.SetSettingsInput
|
import ca.gosyer.jui.domain.settings.model.SetSettingsInput
|
||||||
import ca.gosyer.jui.domain.settings.model.Settings
|
import ca.gosyer.jui.domain.settings.model.Settings
|
||||||
import ca.gosyer.jui.domain.settings.service.SettingsRepository
|
import ca.gosyer.jui.domain.settings.service.SettingsRepository
|
||||||
@@ -350,4 +353,26 @@ class SettingsRepositoryImpl(
|
|||||||
Unit
|
Unit
|
||||||
}
|
}
|
||||||
.flowOn(Dispatchers.IO)
|
.flowOn(Dispatchers.IO)
|
||||||
|
|
||||||
|
override fun aboutServer(): Flow<About> {
|
||||||
|
return apolloClient.query(
|
||||||
|
AboutServerQuery()
|
||||||
|
)
|
||||||
|
.toFlow()
|
||||||
|
.map {
|
||||||
|
val data = it.dataAssertNoErrors
|
||||||
|
About(
|
||||||
|
data.aboutServer.name,
|
||||||
|
data.aboutServer.version,
|
||||||
|
when (data.aboutServer.buildType) {
|
||||||
|
"Preview" -> AboutBuildType.Preview
|
||||||
|
else -> AboutBuildType.Stable
|
||||||
|
},
|
||||||
|
data.aboutServer.buildTime,
|
||||||
|
data.aboutServer.github,
|
||||||
|
data.aboutServer.discord
|
||||||
|
)
|
||||||
|
}
|
||||||
|
.flowOn(Dispatchers.IO)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,50 +1,5 @@
|
|||||||
package ca.gosyer.jui.data
|
package ca.gosyer.jui.data
|
||||||
|
|
||||||
import ca.gosyer.jui.domain.backup.service.createBackupRepositoryOld
|
|
||||||
import ca.gosyer.jui.domain.category.service.createCategoryRepositoryOld
|
|
||||||
import ca.gosyer.jui.domain.chapter.service.createChapterRepositoryOld
|
|
||||||
import ca.gosyer.jui.domain.download.service.createDownloadRepositoryOld
|
|
||||||
import ca.gosyer.jui.domain.extension.service.createExtensionRepositoryOld
|
|
||||||
import ca.gosyer.jui.domain.global.service.createGlobalRepositoryOld
|
|
||||||
import ca.gosyer.jui.domain.library.service.createLibraryRepositoryOld
|
|
||||||
import ca.gosyer.jui.domain.manga.service.createMangaRepositoryOld
|
|
||||||
import ca.gosyer.jui.domain.settings.service.createSettingsRepositoryOld
|
|
||||||
import ca.gosyer.jui.domain.source.service.createSourceRepositoryOld
|
|
||||||
import ca.gosyer.jui.domain.updates.service.createUpdatesRepositoryOld
|
|
||||||
import de.jensklingenberg.ktorfit.Ktorfit
|
|
||||||
import me.tatarka.inject.annotations.Provides
|
|
||||||
|
|
||||||
actual interface SharedDataComponent {
|
actual interface SharedDataComponent {
|
||||||
@Provides
|
|
||||||
fun backupRepositoryOld(ktorfit: Ktorfit) = ktorfit.createBackupRepositoryOld()
|
|
||||||
|
|
||||||
@Provides
|
|
||||||
fun categoryRepositoryOld(ktorfit: Ktorfit) = ktorfit.createCategoryRepositoryOld()
|
|
||||||
|
|
||||||
@Provides
|
|
||||||
fun chapterRepositoryOld(ktorfit: Ktorfit) = ktorfit.createChapterRepositoryOld()
|
|
||||||
|
|
||||||
@Provides
|
|
||||||
fun downloadRepositoryOld(ktorfit: Ktorfit) = ktorfit.createDownloadRepositoryOld()
|
|
||||||
|
|
||||||
@Provides
|
|
||||||
fun extensionRepositoryOld(ktorfit: Ktorfit) = ktorfit.createExtensionRepositoryOld()
|
|
||||||
|
|
||||||
@Provides
|
|
||||||
fun globalRepositoryOld(ktorfit: Ktorfit) = ktorfit.createGlobalRepositoryOld()
|
|
||||||
|
|
||||||
@Provides
|
|
||||||
fun libraryRepositoryOld(ktorfit: Ktorfit) = ktorfit.createLibraryRepositoryOld()
|
|
||||||
|
|
||||||
@Provides
|
|
||||||
fun mangaRepositoryOld(ktorfit: Ktorfit) = ktorfit.createMangaRepositoryOld()
|
|
||||||
|
|
||||||
@Provides
|
|
||||||
fun settingsRepositoryOld(ktorfit: Ktorfit) = ktorfit.createSettingsRepositoryOld()
|
|
||||||
|
|
||||||
@Provides
|
|
||||||
fun sourceRepositoryOld(ktorfit: Ktorfit) = ktorfit.createSourceRepositoryOld()
|
|
||||||
|
|
||||||
@Provides
|
|
||||||
fun updatesRepositoryOld(ktorfit: Ktorfit) = ktorfit.createUpdatesRepositoryOld()
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,50 +1,5 @@
|
|||||||
package ca.gosyer.jui.data
|
package ca.gosyer.jui.data
|
||||||
|
|
||||||
import ca.gosyer.jui.domain.backup.service.createBackupRepositoryOld
|
|
||||||
import ca.gosyer.jui.domain.category.service.createCategoryRepositoryOld
|
|
||||||
import ca.gosyer.jui.domain.chapter.service.createChapterRepositoryOld
|
|
||||||
import ca.gosyer.jui.domain.download.service.createDownloadRepositoryOld
|
|
||||||
import ca.gosyer.jui.domain.extension.service.createExtensionRepositoryOld
|
|
||||||
import ca.gosyer.jui.domain.global.service.createGlobalRepositoryOld
|
|
||||||
import ca.gosyer.jui.domain.library.service.createLibraryRepositoryOld
|
|
||||||
import ca.gosyer.jui.domain.manga.service.createMangaRepositoryOld
|
|
||||||
import ca.gosyer.jui.domain.settings.service.createSettingsRepositoryOld
|
|
||||||
import ca.gosyer.jui.domain.source.service.createSourceRepositoryOld
|
|
||||||
import ca.gosyer.jui.domain.updates.service.createUpdatesRepositoryOld
|
|
||||||
import de.jensklingenberg.ktorfit.Ktorfit
|
|
||||||
import me.tatarka.inject.annotations.Provides
|
|
||||||
|
|
||||||
actual interface SharedDataComponent {
|
actual interface SharedDataComponent {
|
||||||
@Provides
|
|
||||||
fun backupRepositoryOld(ktorfit: Ktorfit) = ktorfit.createBackupRepositoryOld()
|
|
||||||
|
|
||||||
@Provides
|
|
||||||
fun categoryRepositoryOld(ktorfit: Ktorfit) = ktorfit.createCategoryRepositoryOld()
|
|
||||||
|
|
||||||
@Provides
|
|
||||||
fun chapterRepositoryOld(ktorfit: Ktorfit) = ktorfit.createChapterRepositoryOld()
|
|
||||||
|
|
||||||
@Provides
|
|
||||||
fun downloadRepositoryOld(ktorfit: Ktorfit) = ktorfit.createDownloadRepositoryOld()
|
|
||||||
|
|
||||||
@Provides
|
|
||||||
fun extensionRepositoryOld(ktorfit: Ktorfit) = ktorfit.createExtensionRepositoryOld()
|
|
||||||
|
|
||||||
@Provides
|
|
||||||
fun globalRepositoryOld(ktorfit: Ktorfit) = ktorfit.createGlobalRepositoryOld()
|
|
||||||
|
|
||||||
@Provides
|
|
||||||
fun libraryRepositoryOld(ktorfit: Ktorfit) = ktorfit.createLibraryRepositoryOld()
|
|
||||||
|
|
||||||
@Provides
|
|
||||||
fun mangaRepositoryOld(ktorfit: Ktorfit) = ktorfit.createMangaRepositoryOld()
|
|
||||||
|
|
||||||
@Provides
|
|
||||||
fun settingsRepositoryOld(ktorfit: Ktorfit) = ktorfit.createSettingsRepositoryOld()
|
|
||||||
|
|
||||||
@Provides
|
|
||||||
fun sourceRepositoryOld(ktorfit: Ktorfit) = ktorfit.createSourceRepositoryOld()
|
|
||||||
|
|
||||||
@Provides
|
|
||||||
fun updatesRepositoryOld(ktorfit: Ktorfit) = ktorfit.createUpdatesRepositoryOld()
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,6 +15,7 @@ import kotlinx.coroutines.flow.Flow
|
|||||||
import kotlinx.coroutines.flow.MutableSharedFlow
|
import kotlinx.coroutines.flow.MutableSharedFlow
|
||||||
import kotlinx.coroutines.flow.asSharedFlow
|
import kotlinx.coroutines.flow.asSharedFlow
|
||||||
import kotlinx.coroutines.flow.buffer
|
import kotlinx.coroutines.flow.buffer
|
||||||
|
import kotlinx.coroutines.flow.combine
|
||||||
import kotlinx.coroutines.flow.filter
|
import kotlinx.coroutines.flow.filter
|
||||||
import kotlinx.coroutines.flow.flatMapLatest
|
import kotlinx.coroutines.flow.flatMapLatest
|
||||||
import kotlinx.coroutines.flow.onStart
|
import kotlinx.coroutines.flow.onStart
|
||||||
@@ -39,6 +40,11 @@ class ServerListeners
|
|||||||
)
|
)
|
||||||
val chapterIdsListener = _chapterIdsListener.asSharedFlow()
|
val chapterIdsListener = _chapterIdsListener.asSharedFlow()
|
||||||
|
|
||||||
|
private val _mangaChapterIdsListener = MutableSharedFlow<List<Long>>(
|
||||||
|
extraBufferCapacity = Channel.UNLIMITED,
|
||||||
|
)
|
||||||
|
val mangaChapterIdsListener = _mangaChapterIdsListener.asSharedFlow()
|
||||||
|
|
||||||
private val categoryMangaListener = MutableSharedFlow<Long>(
|
private val categoryMangaListener = MutableSharedFlow<Long>(
|
||||||
extraBufferCapacity = Channel.UNLIMITED,
|
extraBufferCapacity = Channel.UNLIMITED,
|
||||||
)
|
)
|
||||||
@@ -85,13 +91,16 @@ class ServerListeners
|
|||||||
|
|
||||||
fun <T> combineChapters(
|
fun <T> combineChapters(
|
||||||
flow: Flow<T>,
|
flow: Flow<T>,
|
||||||
idPredate: (suspend (List<Long>) -> Boolean)? = null,
|
chapterIdPredate: (suspend (List<Long>) -> Boolean)? = null,
|
||||||
|
mangaIdPredate: (suspend (List<Long>) -> Boolean)? = null,
|
||||||
): Flow<T> {
|
): Flow<T> {
|
||||||
val idsListener = if (idPredate != null) {
|
val idsListener = _chapterIdsListener
|
||||||
_chapterIdsListener.filter { idPredate(it) }.startWith(Unit)
|
.filter { chapterIdPredate?.invoke(it) ?: false }
|
||||||
} else {
|
.startWith(Unit)
|
||||||
_chapterIdsListener.startWith(Unit)
|
.combine(
|
||||||
}
|
_mangaChapterIdsListener.filter { mangaIdPredate?.invoke(it) ?: false }
|
||||||
|
.startWith(Unit)
|
||||||
|
) { _, _ -> }
|
||||||
|
|
||||||
return idsListener
|
return idsListener
|
||||||
.buffer(capacity = 1, onBufferOverflow = BufferOverflow.DROP_OLDEST)
|
.buffer(capacity = 1, onBufferOverflow = BufferOverflow.DROP_OLDEST)
|
||||||
|
|||||||
@@ -1,61 +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.backup.service
|
|
||||||
|
|
||||||
import ca.gosyer.jui.core.io.SYSTEM
|
|
||||||
import ca.gosyer.jui.domain.backup.model.BackupValidationResult
|
|
||||||
import de.jensklingenberg.ktorfit.http.GET
|
|
||||||
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 BackupRepositoryOld {
|
|
||||||
@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>
|
|
||||||
|
|
||||||
@GET("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")
|
|
||||||
},
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,79 +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.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 CategoryRepositoryOld {
|
|
||||||
@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>>
|
|
||||||
|
|
||||||
@FormUrlEncoded
|
|
||||||
@PATCH("api/v1/category/{categoryId}/meta")
|
|
||||||
fun updateCategoryMeta(
|
|
||||||
@Path("categoryId") categoryId: Long,
|
|
||||||
@Field("key") key: String,
|
|
||||||
@Field("value") value: String,
|
|
||||||
): Flow<HttpResponse>
|
|
||||||
}
|
|
||||||
@@ -47,13 +47,13 @@ class GetChapter
|
|||||||
chapterId: Long,
|
chapterId: Long,
|
||||||
) = serverListeners.combineChapters(
|
) = serverListeners.combineChapters(
|
||||||
chapterRepository.getChapter(chapterId),
|
chapterRepository.getChapter(chapterId),
|
||||||
idPredate = { ids -> chapterId in ids },
|
chapterIdPredate = { ids -> chapterId in ids },
|
||||||
)
|
)
|
||||||
|
|
||||||
fun asFlow(chapter: Chapter) =
|
fun asFlow(chapter: Chapter) =
|
||||||
serverListeners.combineChapters(
|
serverListeners.combineChapters(
|
||||||
chapterRepository.getChapter(chapter.id),
|
chapterRepository.getChapter(chapter.id),
|
||||||
idPredate = { ids -> chapter.id in ids },
|
chapterIdPredate = { ids -> chapter.id in ids },
|
||||||
)
|
)
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
|
|||||||
@@ -46,13 +46,13 @@ class GetChapters
|
|||||||
fun asFlow(mangaId: Long) =
|
fun asFlow(mangaId: Long) =
|
||||||
serverListeners.combineChapters(
|
serverListeners.combineChapters(
|
||||||
chapterRepository.getChapters(mangaId),
|
chapterRepository.getChapters(mangaId),
|
||||||
idPredate = { ids -> false }, // todo
|
chapterIdPredate = { ids -> false }, // todo
|
||||||
)
|
)
|
||||||
|
|
||||||
fun asFlow(manga: Manga) =
|
fun asFlow(manga: Manga) =
|
||||||
serverListeners.combineChapters(
|
serverListeners.combineChapters(
|
||||||
chapterRepository.getChapters(manga.id),
|
chapterRepository.getChapters(manga.id),
|
||||||
idPredate = { ids -> false }, // todo
|
chapterIdPredate = { ids -> false }, // todo
|
||||||
)
|
)
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
|
|||||||
@@ -1,86 +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.service
|
|
||||||
|
|
||||||
import ca.gosyer.jui.domain.chapter.model.Chapter
|
|
||||||
import ca.gosyer.jui.domain.chapter.model.ChapterBatchEditInput
|
|
||||||
import ca.gosyer.jui.domain.chapter.model.MangaChapterBatchEditInput
|
|
||||||
import de.jensklingenberg.ktorfit.http.Body
|
|
||||||
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.Headers
|
|
||||||
import de.jensklingenberg.ktorfit.http.PATCH
|
|
||||||
import de.jensklingenberg.ktorfit.http.POST
|
|
||||||
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 ChapterRepositoryOld {
|
|
||||||
@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>
|
|
||||||
|
|
||||||
@FormUrlEncoded
|
|
||||||
@PATCH("api/v1/manga/{mangaId}/chapter/{chapterIndex}")
|
|
||||||
fun updateChapter(
|
|
||||||
@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>
|
|
||||||
|
|
||||||
@POST("api/v1/manga/{mangaId}/chapter/batch")
|
|
||||||
@Headers("Content-Type: application/json")
|
|
||||||
fun batchUpdateChapter(
|
|
||||||
@Path("mangaId") mangaId: Long,
|
|
||||||
@Body input: MangaChapterBatchEditInput,
|
|
||||||
): Flow<HttpResponse>
|
|
||||||
|
|
||||||
@POST("api/v1/chapter/batch")
|
|
||||||
@Headers("Content-Type: application/json")
|
|
||||||
fun batchUpdateChapter(
|
|
||||||
@Body input: ChapterBatchEditInput,
|
|
||||||
): Flow<HttpResponse>
|
|
||||||
|
|
||||||
@GET("api/v1/manga/{mangaId}/chapter/{chapterIndex}/page/{pageNum}")
|
|
||||||
fun getPage(
|
|
||||||
@Path("mangaId") mangaId: Long,
|
|
||||||
@Path("chapterIndex") chapterIndex: Int,
|
|
||||||
@Path("pageNum") pageNum: Int,
|
|
||||||
@ReqBuilder block: HttpRequestBuilder.() -> Unit,
|
|
||||||
): Flow<HttpResponse>
|
|
||||||
|
|
||||||
@DELETE("api/v1/manga/{mangaId}/chapter/{chapterIndex}")
|
|
||||||
fun deleteChapterDownload(
|
|
||||||
@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>
|
|
||||||
}
|
|
||||||
@@ -1,54 +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.download.service
|
|
||||||
|
|
||||||
import ca.gosyer.jui.domain.download.model.DownloadEnqueue
|
|
||||||
import de.jensklingenberg.ktorfit.http.Body
|
|
||||||
import de.jensklingenberg.ktorfit.http.DELETE
|
|
||||||
import de.jensklingenberg.ktorfit.http.GET
|
|
||||||
import de.jensklingenberg.ktorfit.http.Headers
|
|
||||||
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 DownloadRepositoryOld {
|
|
||||||
@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>
|
|
||||||
|
|
||||||
@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>
|
|
||||||
|
|
||||||
@PATCH("api/v1/download/{mangaId}/chapter/{chapterIndex}/reorder/{to}")
|
|
||||||
fun reorderChapterDownload(
|
|
||||||
@Path("mangaId") mangaId: Long,
|
|
||||||
@Path("chapterIndex") chapterIndex: Int,
|
|
||||||
@Path("to") to: Int,
|
|
||||||
): Flow<HttpResponse>
|
|
||||||
|
|
||||||
@POST("api/v1/download/batch")
|
|
||||||
@Headers("Content-Type: application/json")
|
|
||||||
fun batchDownload(
|
|
||||||
@Body downloadEnqueue: DownloadEnqueue,
|
|
||||||
): Flow<HttpResponse>
|
|
||||||
}
|
|
||||||
@@ -1,73 +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.extension.service
|
|
||||||
|
|
||||||
import ca.gosyer.jui.core.io.SYSTEM
|
|
||||||
import ca.gosyer.jui.domain.extension.model.Extension
|
|
||||||
import de.jensklingenberg.ktorfit.http.GET
|
|
||||||
import de.jensklingenberg.ktorfit.http.Multipart
|
|
||||||
import de.jensklingenberg.ktorfit.http.POST
|
|
||||||
import de.jensklingenberg.ktorfit.http.Part
|
|
||||||
import de.jensklingenberg.ktorfit.http.Path
|
|
||||||
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 io.ktor.utils.io.ByteReadChannel
|
|
||||||
import kotlinx.coroutines.flow.Flow
|
|
||||||
import okio.FileSystem
|
|
||||||
import okio.buffer
|
|
||||||
|
|
||||||
interface ExtensionRepositoryOld {
|
|
||||||
@GET("api/v1/extension/list")
|
|
||||||
fun getExtensionList(): Flow<List<Extension>>
|
|
||||||
|
|
||||||
@Multipart
|
|
||||||
@POST("api/v1/extension/install")
|
|
||||||
fun installExtension(
|
|
||||||
@Part("") formData: List<PartData>,
|
|
||||||
): Flow<HttpResponse>
|
|
||||||
|
|
||||||
@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>
|
|
||||||
|
|
||||||
companion object {
|
|
||||||
fun buildExtensionFormData(file: okio.Path) =
|
|
||||||
formData {
|
|
||||||
append(
|
|
||||||
"file",
|
|
||||||
FileSystem.SYSTEM.source(file).buffer().readByteArray(),
|
|
||||||
Headers.build {
|
|
||||||
append(HttpHeaders.ContentType, ContentType.MultiPart.FormData.toString())
|
|
||||||
append(HttpHeaders.ContentDisposition, "filename=file")
|
|
||||||
},
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -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.global.service
|
|
||||||
|
|
||||||
import ca.gosyer.jui.domain.global.model.GlobalMeta
|
|
||||||
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 io.ktor.client.statement.HttpResponse
|
|
||||||
import kotlinx.coroutines.flow.Flow
|
|
||||||
|
|
||||||
interface GlobalRepositoryOld {
|
|
||||||
@GET("api/v1/meta")
|
|
||||||
fun getGlobalMeta(): Flow<GlobalMeta>
|
|
||||||
|
|
||||||
@FormUrlEncoded
|
|
||||||
@PATCH("api/v1/meta")
|
|
||||||
fun updateGlobalMeta(
|
|
||||||
@Field("key") key: String,
|
|
||||||
@Field("value") value: String,
|
|
||||||
): Flow<HttpResponse>
|
|
||||||
}
|
|
||||||
@@ -1,25 +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.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 LibraryRepositoryOld {
|
|
||||||
@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>
|
|
||||||
}
|
|
||||||
@@ -1,48 +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.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 MangaRepositoryOld {
|
|
||||||
@GET("api/v1/manga/{mangaId}/")
|
|
||||||
fun getManga(
|
|
||||||
@Path("mangaId") mangaId: Long,
|
|
||||||
@Query("onlineFetch") refresh: Boolean = false,
|
|
||||||
): Flow<Manga>
|
|
||||||
|
|
||||||
@GET("api/v1/manga/{mangaId}/full")
|
|
||||||
fun getMangaFull(
|
|
||||||
@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>
|
|
||||||
}
|
|
||||||
@@ -6,7 +6,7 @@
|
|||||||
|
|
||||||
package ca.gosyer.jui.domain.settings.interactor
|
package ca.gosyer.jui.domain.settings.interactor
|
||||||
|
|
||||||
import ca.gosyer.jui.domain.settings.service.SettingsRepositoryOld
|
import ca.gosyer.jui.domain.settings.service.SettingsRepository
|
||||||
import kotlinx.coroutines.flow.catch
|
import kotlinx.coroutines.flow.catch
|
||||||
import kotlinx.coroutines.flow.singleOrNull
|
import kotlinx.coroutines.flow.singleOrNull
|
||||||
import me.tatarka.inject.annotations.Inject
|
import me.tatarka.inject.annotations.Inject
|
||||||
@@ -15,7 +15,7 @@ import org.lighthousegames.logging.logging
|
|||||||
class AboutServer
|
class AboutServer
|
||||||
@Inject
|
@Inject
|
||||||
constructor(
|
constructor(
|
||||||
private val settingsRepositoryOld: SettingsRepositoryOld,
|
private val settingsRepository: SettingsRepository,
|
||||||
) {
|
) {
|
||||||
suspend fun await(onError: suspend (Throwable) -> Unit = {}) =
|
suspend fun await(onError: suspend (Throwable) -> Unit = {}) =
|
||||||
asFlow()
|
asFlow()
|
||||||
@@ -25,7 +25,7 @@ class AboutServer
|
|||||||
}
|
}
|
||||||
.singleOrNull()
|
.singleOrNull()
|
||||||
|
|
||||||
fun asFlow() = settingsRepositoryOld.aboutServer()
|
fun asFlow() = settingsRepository.aboutServer()
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
private val log = logging()
|
private val log = logging()
|
||||||
|
|||||||
@@ -1,33 +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.settings.interactor
|
|
||||||
|
|
||||||
import ca.gosyer.jui.domain.settings.service.SettingsRepositoryOld
|
|
||||||
import kotlinx.coroutines.flow.catch
|
|
||||||
import kotlinx.coroutines.flow.singleOrNull
|
|
||||||
import me.tatarka.inject.annotations.Inject
|
|
||||||
import org.lighthousegames.logging.logging
|
|
||||||
|
|
||||||
class CheckUpdate
|
|
||||||
@Inject
|
|
||||||
constructor(
|
|
||||||
private val settingsRepositoryOld: SettingsRepositoryOld,
|
|
||||||
) {
|
|
||||||
suspend fun await(onError: suspend (Throwable) -> Unit = {}) =
|
|
||||||
asFlow()
|
|
||||||
.catch {
|
|
||||||
onError(it)
|
|
||||||
log.warn(it) { "Failed to check for server updates" }
|
|
||||||
}
|
|
||||||
.singleOrNull()
|
|
||||||
|
|
||||||
fun asFlow() = settingsRepositoryOld.checkUpdate()
|
|
||||||
|
|
||||||
companion object {
|
|
||||||
private val log = logging()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -15,7 +15,6 @@ import kotlinx.serialization.Serializable
|
|||||||
data class About(
|
data class About(
|
||||||
val name: String,
|
val name: String,
|
||||||
val version: String,
|
val version: String,
|
||||||
val revision: String,
|
|
||||||
val buildType: AboutBuildType,
|
val buildType: AboutBuildType,
|
||||||
val buildTime: Long,
|
val buildTime: Long,
|
||||||
val github: String,
|
val github: String,
|
||||||
|
|||||||
@@ -6,6 +6,7 @@
|
|||||||
|
|
||||||
package ca.gosyer.jui.domain.settings.service
|
package ca.gosyer.jui.domain.settings.service
|
||||||
|
|
||||||
|
import ca.gosyer.jui.domain.settings.model.About
|
||||||
import ca.gosyer.jui.domain.settings.model.SetSettingsInput
|
import ca.gosyer.jui.domain.settings.model.SetSettingsInput
|
||||||
import ca.gosyer.jui.domain.settings.model.Settings
|
import ca.gosyer.jui.domain.settings.model.Settings
|
||||||
import kotlinx.coroutines.flow.Flow
|
import kotlinx.coroutines.flow.Flow
|
||||||
@@ -14,4 +15,6 @@ interface SettingsRepository {
|
|||||||
fun getSettings(): Flow<Settings>
|
fun getSettings(): Flow<Settings>
|
||||||
|
|
||||||
fun setSettings(input: SetSettingsInput): Flow<Unit>
|
fun setSettings(input: SetSettingsInput): Flow<Unit>
|
||||||
|
|
||||||
|
fun aboutServer(): Flow<About>
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,21 +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.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 SettingsRepositoryOld {
|
|
||||||
@GET("api/v1/settings/about")
|
|
||||||
fun aboutServer(): Flow<About>
|
|
||||||
|
|
||||||
@POST("api/v1/settings/check-update")
|
|
||||||
fun checkUpdate(): Flow<HttpResponse>
|
|
||||||
}
|
|
||||||
@@ -1,92 +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.source.service
|
|
||||||
|
|
||||||
import ca.gosyer.jui.domain.source.model.MangaPage
|
|
||||||
import ca.gosyer.jui.domain.source.model.Source
|
|
||||||
import ca.gosyer.jui.domain.source.model.sourcefilters.SourceFilterChangeOld
|
|
||||||
import ca.gosyer.jui.domain.source.model.sourcefilters.SourceFilterData
|
|
||||||
import ca.gosyer.jui.domain.source.model.sourcefilters.SourceFilterOld
|
|
||||||
import ca.gosyer.jui.domain.source.model.sourcepreference.SourcePreferenceChange
|
|
||||||
import ca.gosyer.jui.domain.source.model.sourcepreference.SourcePreferenceOld
|
|
||||||
import de.jensklingenberg.ktorfit.http.Body
|
|
||||||
import de.jensklingenberg.ktorfit.http.GET
|
|
||||||
import de.jensklingenberg.ktorfit.http.Headers
|
|
||||||
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 SourceRepositoryOld {
|
|
||||||
@GET("api/v1/source/list")
|
|
||||||
fun getSourceList(): Flow<List<Source>>
|
|
||||||
|
|
||||||
@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<SourceFilterOld>>
|
|
||||||
|
|
||||||
@POST("api/v1/source/{sourceId}/filters")
|
|
||||||
@Headers("Content-Type: application/json")
|
|
||||||
fun setFilter(
|
|
||||||
@Path("sourceId") sourceId: Long,
|
|
||||||
@Body sourceFilter: SourceFilterChangeOld,
|
|
||||||
): Flow<HttpResponse>
|
|
||||||
|
|
||||||
@POST("api/v1/source/{sourceId}/filters")
|
|
||||||
@Headers("Content-Type: application/json")
|
|
||||||
fun setFilters(
|
|
||||||
@Path("sourceId") sourceId: Long,
|
|
||||||
@Body sourceFilters: List<SourceFilterChangeOld>,
|
|
||||||
): Flow<HttpResponse>
|
|
||||||
|
|
||||||
@POST("api/v1/source/{sourceId}/quick-search")
|
|
||||||
@Headers("Content-Type: application/json")
|
|
||||||
fun getQuickSearchResults(
|
|
||||||
@Path("sourceId") sourceId: Long,
|
|
||||||
@Query("pageNum") pageNum: Int,
|
|
||||||
@Body filterData: SourceFilterData,
|
|
||||||
): Flow<MangaPage>
|
|
||||||
|
|
||||||
@GET("api/v1/source/{sourceId}/preferences")
|
|
||||||
fun getSourceSettings(
|
|
||||||
@Path("sourceId") sourceId: Long,
|
|
||||||
): Flow<List<SourcePreferenceOld>>
|
|
||||||
|
|
||||||
@POST("api/v1/source/{sourceId}/preferences")
|
|
||||||
@Headers("Content-Type: application/json")
|
|
||||||
fun setSourceSetting(
|
|
||||||
@Path("sourceId") sourceId: Long,
|
|
||||||
@Body sourcePreference: SourcePreferenceChange,
|
|
||||||
): Flow<HttpResponse>
|
|
||||||
}
|
|
||||||
@@ -1,32 +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.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 UpdatesRepositoryOld {
|
|
||||||
@GET("api/v1/update/recentChapters/{pageNum}/")
|
|
||||||
fun getRecentUpdates(
|
|
||||||
@Path("pageNum") pageNum: Int,
|
|
||||||
): Flow<Updates>
|
|
||||||
|
|
||||||
@POST("api/v1/update/fetch/")
|
|
||||||
fun updateLibrary(): Flow<HttpResponse>
|
|
||||||
|
|
||||||
@POST("api/v1/update/fetch/")
|
|
||||||
@FormUrlEncoded
|
|
||||||
fun updateCategory(
|
|
||||||
@Field("category") categoryId: Long,
|
|
||||||
): Flow<HttpResponse>
|
|
||||||
}
|
|
||||||
@@ -187,7 +187,7 @@ private fun ServerVersionInfo(
|
|||||||
} else {
|
} else {
|
||||||
PreferenceRow(
|
PreferenceRow(
|
||||||
title = stringResource(MR.strings.server_version),
|
title = stringResource(MR.strings.server_version),
|
||||||
subtitle = "${about.buildType.name} ${about.version}-${about.revision} ($formattedBuildTime)",
|
subtitle = "${about.buildType.name} ${about.version} ($formattedBuildTime)",
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -42,6 +42,7 @@ import kotlinx.coroutines.flow.asSharedFlow
|
|||||||
import kotlinx.coroutines.flow.asStateFlow
|
import kotlinx.coroutines.flow.asStateFlow
|
||||||
import kotlinx.coroutines.flow.catch
|
import kotlinx.coroutines.flow.catch
|
||||||
import kotlinx.coroutines.flow.combine
|
import kotlinx.coroutines.flow.combine
|
||||||
|
import kotlinx.coroutines.flow.first
|
||||||
import kotlinx.coroutines.flow.flatMapLatest
|
import kotlinx.coroutines.flow.flatMapLatest
|
||||||
import kotlinx.coroutines.flow.launchIn
|
import kotlinx.coroutines.flow.launchIn
|
||||||
import kotlinx.coroutines.flow.map
|
import kotlinx.coroutines.flow.map
|
||||||
@@ -90,7 +91,9 @@ class MangaScreenViewModel
|
|||||||
|
|
||||||
private val loadingManga = MutableStateFlow(true)
|
private val loadingManga = MutableStateFlow(true)
|
||||||
private val loadingChapters = MutableStateFlow(true)
|
private val loadingChapters = MutableStateFlow(true)
|
||||||
val isLoading = combine(loadingManga, loadingChapters) { a, b -> a || b }
|
private val refreshingChapters = MutableStateFlow(false)
|
||||||
|
private val refreshingManga = MutableStateFlow(false)
|
||||||
|
val isLoading = combine(loadingManga, loadingChapters, refreshingManga, refreshingChapters) { a, b, c, d -> a || b || c || d }
|
||||||
.stateIn(scope, SharingStarted.Eagerly, true)
|
.stateIn(scope, SharingStarted.Eagerly, true)
|
||||||
|
|
||||||
val categories = getCategories.asFlow(true)
|
val categories = getCategories.asFlow(true)
|
||||||
@@ -137,19 +140,11 @@ class MangaScreenViewModel
|
|||||||
}
|
}
|
||||||
.onEach {
|
.onEach {
|
||||||
_manga.value = it
|
_manga.value = it
|
||||||
if (_manga.value?.initialized == false) {
|
|
||||||
refreshManga.await(
|
|
||||||
params.mangaId,
|
|
||||||
onError = {
|
|
||||||
log.warn(it) { "Error when fetching manga" }
|
|
||||||
toast(it.message.orEmpty())
|
|
||||||
}
|
|
||||||
)
|
|
||||||
}
|
|
||||||
loadingManga.value = false
|
loadingManga.value = false
|
||||||
}
|
}
|
||||||
.catch {
|
.catch {
|
||||||
toast(it.message.orEmpty())
|
toast(it.message.orEmpty())
|
||||||
|
log.warn(it) { "Error when loading manga" }
|
||||||
loadingManga.value = false
|
loadingManga.value = false
|
||||||
}
|
}
|
||||||
.launchIn(scope)
|
.launchIn(scope)
|
||||||
@@ -159,16 +154,7 @@ class MangaScreenViewModel
|
|||||||
getChapters.asFlow(params.mangaId)
|
getChapters.asFlow(params.mangaId)
|
||||||
}
|
}
|
||||||
.onEach {
|
.onEach {
|
||||||
_chapters.value = it.toDownloadChapters()
|
updateChapters(it)
|
||||||
if (_chapters.value.isEmpty()) {
|
|
||||||
refreshChapters.await(
|
|
||||||
params.mangaId,
|
|
||||||
onError = {
|
|
||||||
log.warn(it) { "Error when fetching chapters" }
|
|
||||||
toast(it.message.orEmpty())
|
|
||||||
}
|
|
||||||
)
|
|
||||||
}
|
|
||||||
loadingChapters.value = false
|
loadingChapters.value = false
|
||||||
}
|
}
|
||||||
.catch {
|
.catch {
|
||||||
@@ -184,6 +170,13 @@ class MangaScreenViewModel
|
|||||||
_mangaCategories.value = mangaCategories.toImmutableList()
|
_mangaCategories.value = mangaCategories.toImmutableList()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
scope.launch {
|
||||||
|
val manga = manga.first { it != null }!!
|
||||||
|
if (!manga.initialized) {
|
||||||
|
refreshManga()
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun loadManga() {
|
fun loadManga() {
|
||||||
@@ -198,28 +191,38 @@ class MangaScreenViewModel
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun updateChapters(chapters: List<Chapter>) {
|
||||||
|
_chapters.value = chapters.sortedByDescending { it.index }.toDownloadChapters()
|
||||||
|
}
|
||||||
|
|
||||||
fun refreshManga() {
|
fun refreshManga() {
|
||||||
scope.launch {
|
scope.launch {
|
||||||
loadingManga.value = true
|
refreshingManga.value = true
|
||||||
refreshManga.await(
|
val manga = refreshManga.await(
|
||||||
params.mangaId,
|
params.mangaId,
|
||||||
onError = {
|
onError = {
|
||||||
log.warn(it) { "Error when refreshing manga" }
|
log.warn(it) { "Error when refreshing manga" }
|
||||||
toast(it.message.orEmpty())
|
toast(it.message.orEmpty())
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
loadingManga.value = false
|
if (manga != null) {
|
||||||
|
_manga.value = manga
|
||||||
|
}
|
||||||
|
refreshingManga.value = false
|
||||||
}
|
}
|
||||||
scope.launch {
|
scope.launch {
|
||||||
loadingChapters.value = true
|
refreshingChapters.value = true
|
||||||
refreshChapters.await(
|
val chapters = refreshChapters.await(
|
||||||
params.mangaId,
|
params.mangaId,
|
||||||
onError = {
|
onError = {
|
||||||
log.warn(it) { "Error when refreshing chapters" }
|
log.warn(it) { "Error when refreshing chapters" }
|
||||||
toast(it.message.orEmpty())
|
toast(it.message.orEmpty())
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
loadingChapters.value = false
|
if (!chapters.isNullOrEmpty()) {
|
||||||
|
updateChapters(chapters)
|
||||||
|
}
|
||||||
|
refreshingChapters.value = false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -242,6 +245,7 @@ class MangaScreenViewModel
|
|||||||
chooseCategoriesFlow.emit(Unit)
|
chooseCategoriesFlow.emit(Unit)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
loadManga()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -275,6 +279,8 @@ class MangaScreenViewModel
|
|||||||
if (mangaCategories != null) {
|
if (mangaCategories != null) {
|
||||||
_mangaCategories.value = mangaCategories.toImmutableList()
|
_mangaCategories.value = mangaCategories.toImmutableList()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
loadManga()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -287,6 +293,7 @@ class MangaScreenViewModel
|
|||||||
manga.value?.let {
|
manga.value?.let {
|
||||||
updateChapter.await(chapterIds, read = read, onError = { toast(it.message.orEmpty()) })
|
updateChapter.await(chapterIds, read = read, onError = { toast(it.message.orEmpty()) })
|
||||||
_selectedIds.value = persistentListOf()
|
_selectedIds.value = persistentListOf()
|
||||||
|
loadChapters()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -303,6 +310,7 @@ class MangaScreenViewModel
|
|||||||
manga.value?.let {
|
manga.value?.let {
|
||||||
updateChapter.await(chapterIds, bookmarked = bookmark, onError = { toast(it.message.orEmpty()) })
|
updateChapter.await(chapterIds, bookmarked = bookmark, onError = { toast(it.message.orEmpty()) })
|
||||||
_selectedIds.value = persistentListOf()
|
_selectedIds.value = persistentListOf()
|
||||||
|
loadChapters()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -319,6 +327,7 @@ class MangaScreenViewModel
|
|||||||
.subList(0, index).map{it.chapter.id} // todo test
|
.subList(0, index).map{it.chapter.id} // todo test
|
||||||
updateChapter.await(chapters, read = true, onError = { toast(it.message.orEmpty()) })
|
updateChapter.await(chapters, read = true, onError = { toast(it.message.orEmpty()) })
|
||||||
_selectedIds.value = persistentListOf()
|
_selectedIds.value = persistentListOf()
|
||||||
|
loadChapters()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user