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
|
||||
|
||||
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 {
|
||||
@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
|
||||
}
|
||||
}
|
||||
|
||||
query AboutServer {
|
||||
aboutServer {
|
||||
buildTime
|
||||
buildType
|
||||
discord
|
||||
github
|
||||
name
|
||||
version
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
|
||||
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.SetSettingsMutation
|
||||
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.WebUIInterface
|
||||
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.Settings
|
||||
import ca.gosyer.jui.domain.settings.service.SettingsRepository
|
||||
@@ -350,4 +353,26 @@ class SettingsRepositoryImpl(
|
||||
Unit
|
||||
}
|
||||
.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
|
||||
|
||||
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 {
|
||||
@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
|
||||
|
||||
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 {
|
||||
@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.asSharedFlow
|
||||
import kotlinx.coroutines.flow.buffer
|
||||
import kotlinx.coroutines.flow.combine
|
||||
import kotlinx.coroutines.flow.filter
|
||||
import kotlinx.coroutines.flow.flatMapLatest
|
||||
import kotlinx.coroutines.flow.onStart
|
||||
@@ -39,6 +40,11 @@ class ServerListeners
|
||||
)
|
||||
val chapterIdsListener = _chapterIdsListener.asSharedFlow()
|
||||
|
||||
private val _mangaChapterIdsListener = MutableSharedFlow<List<Long>>(
|
||||
extraBufferCapacity = Channel.UNLIMITED,
|
||||
)
|
||||
val mangaChapterIdsListener = _mangaChapterIdsListener.asSharedFlow()
|
||||
|
||||
private val categoryMangaListener = MutableSharedFlow<Long>(
|
||||
extraBufferCapacity = Channel.UNLIMITED,
|
||||
)
|
||||
@@ -85,13 +91,16 @@ class ServerListeners
|
||||
|
||||
fun <T> combineChapters(
|
||||
flow: Flow<T>,
|
||||
idPredate: (suspend (List<Long>) -> Boolean)? = null,
|
||||
chapterIdPredate: (suspend (List<Long>) -> Boolean)? = null,
|
||||
mangaIdPredate: (suspend (List<Long>) -> Boolean)? = null,
|
||||
): Flow<T> {
|
||||
val idsListener = if (idPredate != null) {
|
||||
_chapterIdsListener.filter { idPredate(it) }.startWith(Unit)
|
||||
} else {
|
||||
_chapterIdsListener.startWith(Unit)
|
||||
}
|
||||
val idsListener = _chapterIdsListener
|
||||
.filter { chapterIdPredate?.invoke(it) ?: false }
|
||||
.startWith(Unit)
|
||||
.combine(
|
||||
_mangaChapterIdsListener.filter { mangaIdPredate?.invoke(it) ?: false }
|
||||
.startWith(Unit)
|
||||
) { _, _ -> }
|
||||
|
||||
return idsListener
|
||||
.buffer(capacity = 1, onBufferOverflow = BufferOverflow.DROP_OLDEST)
|
||||
|
||||
@@ -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,
|
||||
) = serverListeners.combineChapters(
|
||||
chapterRepository.getChapter(chapterId),
|
||||
idPredate = { ids -> chapterId in ids },
|
||||
chapterIdPredate = { ids -> chapterId in ids },
|
||||
)
|
||||
|
||||
fun asFlow(chapter: Chapter) =
|
||||
serverListeners.combineChapters(
|
||||
chapterRepository.getChapter(chapter.id),
|
||||
idPredate = { ids -> chapter.id in ids },
|
||||
chapterIdPredate = { ids -> chapter.id in ids },
|
||||
)
|
||||
|
||||
companion object {
|
||||
|
||||
@@ -46,13 +46,13 @@ class GetChapters
|
||||
fun asFlow(mangaId: Long) =
|
||||
serverListeners.combineChapters(
|
||||
chapterRepository.getChapters(mangaId),
|
||||
idPredate = { ids -> false }, // todo
|
||||
chapterIdPredate = { ids -> false }, // todo
|
||||
)
|
||||
|
||||
fun asFlow(manga: Manga) =
|
||||
serverListeners.combineChapters(
|
||||
chapterRepository.getChapters(manga.id),
|
||||
idPredate = { ids -> false }, // todo
|
||||
chapterIdPredate = { ids -> false }, // todo
|
||||
)
|
||||
|
||||
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
|
||||
|
||||
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.singleOrNull
|
||||
import me.tatarka.inject.annotations.Inject
|
||||
@@ -15,7 +15,7 @@ import org.lighthousegames.logging.logging
|
||||
class AboutServer
|
||||
@Inject
|
||||
constructor(
|
||||
private val settingsRepositoryOld: SettingsRepositoryOld,
|
||||
private val settingsRepository: SettingsRepository,
|
||||
) {
|
||||
suspend fun await(onError: suspend (Throwable) -> Unit = {}) =
|
||||
asFlow()
|
||||
@@ -25,7 +25,7 @@ class AboutServer
|
||||
}
|
||||
.singleOrNull()
|
||||
|
||||
fun asFlow() = settingsRepositoryOld.aboutServer()
|
||||
fun asFlow() = settingsRepository.aboutServer()
|
||||
|
||||
companion object {
|
||||
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(
|
||||
val name: String,
|
||||
val version: String,
|
||||
val revision: String,
|
||||
val buildType: AboutBuildType,
|
||||
val buildTime: Long,
|
||||
val github: String,
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
|
||||
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.Settings
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
@@ -14,4 +15,6 @@ interface SettingsRepository {
|
||||
fun getSettings(): Flow<Settings>
|
||||
|
||||
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 {
|
||||
PreferenceRow(
|
||||
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.catch
|
||||
import kotlinx.coroutines.flow.combine
|
||||
import kotlinx.coroutines.flow.first
|
||||
import kotlinx.coroutines.flow.flatMapLatest
|
||||
import kotlinx.coroutines.flow.launchIn
|
||||
import kotlinx.coroutines.flow.map
|
||||
@@ -90,7 +91,9 @@ class MangaScreenViewModel
|
||||
|
||||
private val loadingManga = 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)
|
||||
|
||||
val categories = getCategories.asFlow(true)
|
||||
@@ -137,19 +140,11 @@ class MangaScreenViewModel
|
||||
}
|
||||
.onEach {
|
||||
_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
|
||||
}
|
||||
.catch {
|
||||
toast(it.message.orEmpty())
|
||||
log.warn(it) { "Error when loading manga" }
|
||||
loadingManga.value = false
|
||||
}
|
||||
.launchIn(scope)
|
||||
@@ -159,16 +154,7 @@ class MangaScreenViewModel
|
||||
getChapters.asFlow(params.mangaId)
|
||||
}
|
||||
.onEach {
|
||||
_chapters.value = it.toDownloadChapters()
|
||||
if (_chapters.value.isEmpty()) {
|
||||
refreshChapters.await(
|
||||
params.mangaId,
|
||||
onError = {
|
||||
log.warn(it) { "Error when fetching chapters" }
|
||||
toast(it.message.orEmpty())
|
||||
}
|
||||
)
|
||||
}
|
||||
updateChapters(it)
|
||||
loadingChapters.value = false
|
||||
}
|
||||
.catch {
|
||||
@@ -184,6 +170,13 @@ class MangaScreenViewModel
|
||||
_mangaCategories.value = mangaCategories.toImmutableList()
|
||||
}
|
||||
}
|
||||
|
||||
scope.launch {
|
||||
val manga = manga.first { it != null }!!
|
||||
if (!manga.initialized) {
|
||||
refreshManga()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun loadManga() {
|
||||
@@ -198,28 +191,38 @@ class MangaScreenViewModel
|
||||
}
|
||||
}
|
||||
|
||||
fun updateChapters(chapters: List<Chapter>) {
|
||||
_chapters.value = chapters.sortedByDescending { it.index }.toDownloadChapters()
|
||||
}
|
||||
|
||||
fun refreshManga() {
|
||||
scope.launch {
|
||||
loadingManga.value = true
|
||||
refreshManga.await(
|
||||
refreshingManga.value = true
|
||||
val manga = refreshManga.await(
|
||||
params.mangaId,
|
||||
onError = {
|
||||
log.warn(it) { "Error when refreshing manga" }
|
||||
toast(it.message.orEmpty())
|
||||
}
|
||||
)
|
||||
loadingManga.value = false
|
||||
if (manga != null) {
|
||||
_manga.value = manga
|
||||
}
|
||||
refreshingManga.value = false
|
||||
}
|
||||
scope.launch {
|
||||
loadingChapters.value = true
|
||||
refreshChapters.await(
|
||||
refreshingChapters.value = true
|
||||
val chapters = refreshChapters.await(
|
||||
params.mangaId,
|
||||
onError = {
|
||||
log.warn(it) { "Error when refreshing chapters" }
|
||||
toast(it.message.orEmpty())
|
||||
}
|
||||
)
|
||||
loadingChapters.value = false
|
||||
if (!chapters.isNullOrEmpty()) {
|
||||
updateChapters(chapters)
|
||||
}
|
||||
refreshingChapters.value = false
|
||||
}
|
||||
}
|
||||
|
||||
@@ -242,6 +245,7 @@ class MangaScreenViewModel
|
||||
chooseCategoriesFlow.emit(Unit)
|
||||
}
|
||||
}
|
||||
loadManga()
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -275,6 +279,8 @@ class MangaScreenViewModel
|
||||
if (mangaCategories != null) {
|
||||
_mangaCategories.value = mangaCategories.toImmutableList()
|
||||
}
|
||||
|
||||
loadManga()
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -287,6 +293,7 @@ class MangaScreenViewModel
|
||||
manga.value?.let {
|
||||
updateChapter.await(chapterIds, read = read, onError = { toast(it.message.orEmpty()) })
|
||||
_selectedIds.value = persistentListOf()
|
||||
loadChapters()
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -303,6 +310,7 @@ class MangaScreenViewModel
|
||||
manga.value?.let {
|
||||
updateChapter.await(chapterIds, bookmarked = bookmark, onError = { toast(it.message.orEmpty()) })
|
||||
_selectedIds.value = persistentListOf()
|
||||
loadChapters()
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -319,6 +327,7 @@ class MangaScreenViewModel
|
||||
.subList(0, index).map{it.chapter.id} // todo test
|
||||
updateChapter.await(chapters, read = true, onError = { toast(it.message.orEmpty()) })
|
||||
_selectedIds.value = persistentListOf()
|
||||
loadChapters()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user