Integrate Ktorfit

This commit is contained in:
Syer10
2022-09-22 22:30:24 -04:00
parent 0057de2e25
commit 7a7e92a7b4
61 changed files with 798 additions and 1455 deletions

View File

@@ -6,57 +6,60 @@
package ca.gosyer.jui.data
import ca.gosyer.jui.data.backup.BackupRepositoryImpl
import ca.gosyer.jui.data.category.CategoryRepositoryImpl
import ca.gosyer.jui.data.chapter.ChapterRepositoryImpl
import ca.gosyer.jui.data.download.DownloadRepositoryImpl
import ca.gosyer.jui.data.extension.ExtensionRepositoryImpl
import ca.gosyer.jui.data.library.LibraryRepositoryImpl
import ca.gosyer.jui.data.manga.MangaRepositoryImpl
import ca.gosyer.jui.data.settings.SettingsRepositoryImpl
import ca.gosyer.jui.data.source.SourceRepositoryImpl
import ca.gosyer.jui.data.updates.UpdatesRepositoryImpl
import ca.gosyer.jui.core.lang.addSuffix
import ca.gosyer.jui.domain.backup.service.BackupRepository
import ca.gosyer.jui.domain.category.service.CategoryRepository
import ca.gosyer.jui.domain.chapter.service.ChapterRepository
import ca.gosyer.jui.domain.createIt
import ca.gosyer.jui.domain.download.service.DownloadRepository
import ca.gosyer.jui.domain.extension.service.ExtensionRepository
import ca.gosyer.jui.domain.library.service.LibraryRepository
import ca.gosyer.jui.domain.manga.service.MangaRepository
import ca.gosyer.jui.domain.server.Http
import ca.gosyer.jui.domain.server.service.ServerPreferences
import ca.gosyer.jui.domain.settings.service.SettingsRepository
import ca.gosyer.jui.domain.source.service.SourceRepository
import ca.gosyer.jui.domain.updates.service.UpdatesRepository
import de.jensklingenberg.ktorfit.Ktorfit
import me.tatarka.inject.annotations.Provides
interface DataComponent {
val BackupRepositoryImpl.bind: BackupRepository
@Provides get() = this
@Provides
fun ktorfit(http: Http, serverPreferences: ServerPreferences) = Ktorfit
.Builder()
.httpClient(http)
.requestConverter(FlowIORequestConverter())
.baseUrl(serverPreferences.serverUrl().get().toString().addSuffix('/'))
.build()
val CategoryRepositoryImpl.bind: CategoryRepository
@Provides get() = this
@Provides
fun backupRepository(ktorfit: Ktorfit) = ktorfit.createIt<BackupRepository>()
val ChapterRepositoryImpl.bind: ChapterRepository
@Provides get() = this
@Provides
fun categoryRepository(ktorfit: Ktorfit) = ktorfit.createIt<CategoryRepository>()
val DownloadRepositoryImpl.bind: DownloadRepository
@Provides get() = this
@Provides
fun chapterRepository(ktorfit: Ktorfit) = ktorfit.createIt<ChapterRepository>()
val ExtensionRepositoryImpl.bind: ExtensionRepository
@Provides get() = this
@Provides
fun downloadRepository(ktorfit: Ktorfit) = ktorfit.createIt<DownloadRepository>()
val LibraryRepositoryImpl.bind: LibraryRepository
@Provides get() = this
@Provides
fun extensionRepository(ktorfit: Ktorfit) = ktorfit.createIt<ExtensionRepository>()
val MangaRepositoryImpl.bind: MangaRepository
@Provides get() = this
@Provides
fun libraryRepository(ktorfit: Ktorfit) = ktorfit.createIt<LibraryRepository>()
val SettingsRepositoryImpl.bind: SettingsRepository
@Provides get() = this
@Provides
fun mangaRepository(ktorfit: Ktorfit) = ktorfit.createIt<MangaRepository>()
val SourceRepositoryImpl.bind: SourceRepository
@Provides get() = this
@Provides
fun settingsRepository(ktorfit: Ktorfit) = ktorfit.createIt<SettingsRepository>()
val UpdatesRepositoryImpl.bind: UpdatesRepository
@Provides get() = this
@Provides
fun sourceRepository(ktorfit: Ktorfit) = ktorfit.createIt<SourceRepository>()
@Provides
fun updatesRepository(ktorfit: Ktorfit) = ktorfit.createIt<UpdatesRepository>()
}

View File

@@ -0,0 +1,44 @@
/*
* 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.data
import ca.gosyer.jui.core.lang.IO
import de.jensklingenberg.ktorfit.Ktorfit
import de.jensklingenberg.ktorfit.converter.request.RequestConverter
import de.jensklingenberg.ktorfit.internal.TypeData
import io.ktor.client.call.body
import io.ktor.client.statement.HttpResponse
import io.ktor.util.reflect.TypeInfo
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.flow.flow
import kotlinx.coroutines.flow.flowOn
class FlowIORequestConverter : RequestConverter {
override fun supportedType(typeData: TypeData, isSuspend: Boolean): Boolean {
return typeData.qualifiedName == "kotlinx.coroutines.flow.Flow"
}
override fun <RequestType> convertRequest(
typeData: TypeData,
requestFunction: suspend () -> Pair<TypeInfo, HttpResponse?>,
ktorfit: Ktorfit
): Any {
return flow {
try {
val (info, response) = requestFunction()
if (info.type == HttpResponse::class) {
emit(response!!)
} else {
emit(response!!.body(info))
}
} catch (exception: Exception) {
throw exception
}
}.flowOn(Dispatchers.IO)
}
}

View File

@@ -1,84 +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.data.backup
import ca.gosyer.jui.core.io.SYSTEM
import ca.gosyer.jui.core.lang.IO
import ca.gosyer.jui.data.base.BaseRepository
import ca.gosyer.jui.domain.backup.model.BackupValidationResult
import ca.gosyer.jui.domain.backup.service.BackupRepository
import ca.gosyer.jui.domain.server.Http
import ca.gosyer.jui.domain.server.model.requests.backupFileExportRequest
import ca.gosyer.jui.domain.server.model.requests.backupFileImportRequest
import ca.gosyer.jui.domain.server.model.requests.validateBackupFileRequest
import ca.gosyer.jui.domain.server.service.ServerPreferences
import io.ktor.client.call.body
import io.ktor.client.plugins.expectSuccess
import io.ktor.client.request.HttpRequestBuilder
import io.ktor.client.request.forms.formData
import io.ktor.client.request.forms.submitFormWithBinaryData
import io.ktor.client.request.get
import io.ktor.http.ContentType
import io.ktor.http.Headers
import io.ktor.http.HttpHeaders
import io.ktor.http.path
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.flow.flow
import kotlinx.coroutines.flow.flowOn
import me.tatarka.inject.annotations.Inject
import okio.FileSystem
import okio.Path
import okio.buffer
class BackupRepositoryImpl @Inject constructor(
client: Http,
serverPreferences: ServerPreferences
) : BaseRepository(client, serverPreferences), BackupRepository {
private fun buildFormData(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")
}
)
}
override fun importBackupFile(file: Path, block: HttpRequestBuilder.() -> Unit) = flow {
val response = client.submitFormWithBinaryData(
buildUrl { path(backupFileImportRequest()) },
formData = buildFormData(file)
) {
expectSuccess = true
block()
}
emit(response)
}.flowOn(Dispatchers.IO)
override fun validateBackupFile(file: Path, block: HttpRequestBuilder.() -> Unit) = flow {
val response = client.submitFormWithBinaryData(
buildUrl { path(validateBackupFileRequest()) },
formData = buildFormData(file)
) {
expectSuccess = true
block()
}.body<BackupValidationResult>()
emit(response)
}.flowOn(Dispatchers.IO)
override fun exportBackupFile(block: HttpRequestBuilder.() -> Unit) = flow {
val response = client.get(
buildUrl { path(backupFileExportRequest()) }
) {
expectSuccess = true
block()
}
emit(response)
}.flowOn(Dispatchers.IO)
}

View File

@@ -1,23 +0,0 @@
/*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
package ca.gosyer.jui.data.base
import ca.gosyer.jui.domain.server.Http
import ca.gosyer.jui.domain.server.service.ServerPreferences
import io.ktor.http.URLBuilder
open class BaseRepository(
protected val client: Http,
serverPreferences: ServerPreferences
) {
private val _serverUrl = serverPreferences.serverUrl()
val serverUrl get() = _serverUrl.get().toString()
fun buildUrl(builder: URLBuilder.() -> Unit) = URLBuilder(serverUrl).apply(builder).buildString()
fun URLBuilder.parameter(key: String, value: Any) = encodedParameters.append(key, value.toString())
}

View File

@@ -1,144 +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.data.category
import ca.gosyer.jui.core.lang.IO
import ca.gosyer.jui.data.base.BaseRepository
import ca.gosyer.jui.domain.category.model.Category
import ca.gosyer.jui.domain.category.service.CategoryRepository
import ca.gosyer.jui.domain.manga.model.Manga
import ca.gosyer.jui.domain.server.Http
import ca.gosyer.jui.domain.server.model.requests.addMangaToCategoryQuery
import ca.gosyer.jui.domain.server.model.requests.categoryDeleteRequest
import ca.gosyer.jui.domain.server.model.requests.categoryModifyRequest
import ca.gosyer.jui.domain.server.model.requests.categoryReorderRequest
import ca.gosyer.jui.domain.server.model.requests.createCategoryRequest
import ca.gosyer.jui.domain.server.model.requests.getCategoriesQuery
import ca.gosyer.jui.domain.server.model.requests.getMangaCategoriesQuery
import ca.gosyer.jui.domain.server.model.requests.getMangaInCategoryQuery
import ca.gosyer.jui.domain.server.model.requests.removeMangaFromCategoryRequest
import ca.gosyer.jui.domain.server.service.ServerPreferences
import io.ktor.client.call.body
import io.ktor.client.plugins.expectSuccess
import io.ktor.client.request.delete
import io.ktor.client.request.forms.submitForm
import io.ktor.client.request.get
import io.ktor.http.HttpMethod
import io.ktor.http.Parameters
import io.ktor.http.path
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.flow.flow
import kotlinx.coroutines.flow.flowOn
import me.tatarka.inject.annotations.Inject
class CategoryRepositoryImpl @Inject constructor(
client: Http,
serverPreferences: ServerPreferences
) : BaseRepository(client, serverPreferences), CategoryRepository {
override fun getMangaCategories(mangaId: Long) = flow {
val response = client.get(
buildUrl { path(getMangaCategoriesQuery(mangaId)) }
) {
expectSuccess = true
}.body<List<Category>>()
emit(response)
}.flowOn(Dispatchers.IO)
override fun addMangaToCategory(mangaId: Long, categoryId: Long) = flow {
val response = client.get(
buildUrl { path(addMangaToCategoryQuery(mangaId, categoryId)) }
) {
expectSuccess = true
}
emit(response)
}.flowOn(Dispatchers.IO)
override fun removeMangaFromCategory(mangaId: Long, categoryId: Long) = flow {
val response = client.delete(
buildUrl { path(removeMangaFromCategoryRequest(mangaId, categoryId)) }
) {
expectSuccess = true
}
emit(response)
}.flowOn(Dispatchers.IO)
override fun getCategories(dropDefault: Boolean) = flow {
val response = client.get(
buildUrl { path(getCategoriesQuery()) }
) {
expectSuccess = true
}.body<List<Category>>().let { categories ->
if (dropDefault) {
categories.filterNot { it.name.equals("default", true) }
} else categories
}
emit(response)
}.flowOn(Dispatchers.IO)
override fun createCategory(name: String) = flow {
val response = client.submitForm(
buildUrl { path(createCategoryRequest()) },
formParameters = Parameters.build {
append("name", name)
}
) {
expectSuccess = true
}
emit(response)
}.flowOn(Dispatchers.IO)
override fun modifyCategory(categoryId: Long, name: String?, isLanding: Boolean?) = flow {
val response = client.submitForm(
buildUrl { path(categoryModifyRequest(categoryId)) },
formParameters = Parameters.build {
if (name != null) {
append("name", name)
}
if (isLanding != null) {
append("isLanding", isLanding.toString())
}
}
) {
method = HttpMethod.Patch
expectSuccess = true
}
emit(response)
}.flowOn(Dispatchers.IO)
override fun reorderCategory(to: Int, from: Int) = flow {
val response = client.submitForm(
buildUrl { path(categoryReorderRequest()) },
formParameters = Parameters.build {
append("to", to.toString())
append("from", from.toString())
}
) {
method = HttpMethod.Patch
expectSuccess = true
}
emit(response)
}.flowOn(Dispatchers.IO)
override fun deleteCategory(categoryId: Long) = flow {
val response = client.delete(
buildUrl { path(categoryDeleteRequest(categoryId)) }
) {
expectSuccess = true
}
emit(response)
}.flowOn(Dispatchers.IO)
override fun getMangaFromCategory(categoryId: Long) = flow {
val response = client.get(
buildUrl { path(getMangaInCategoryQuery(categoryId)) }
) {
expectSuccess = true
}.body<List<Manga>>()
emit(response)
}.flowOn(Dispatchers.IO)
}

View File

@@ -1,146 +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.data.chapter
import ca.gosyer.jui.core.lang.IO
import ca.gosyer.jui.data.base.BaseRepository
import ca.gosyer.jui.domain.chapter.model.Chapter
import ca.gosyer.jui.domain.chapter.service.ChapterRepository
import ca.gosyer.jui.domain.server.Http
import ca.gosyer.jui.domain.server.model.requests.deleteDownloadedChapterRequest
import ca.gosyer.jui.domain.server.model.requests.getChapterQuery
import ca.gosyer.jui.domain.server.model.requests.getMangaChaptersQuery
import ca.gosyer.jui.domain.server.model.requests.getPageQuery
import ca.gosyer.jui.domain.server.model.requests.queueDownloadChapterRequest
import ca.gosyer.jui.domain.server.model.requests.stopDownloadingChapterRequest
import ca.gosyer.jui.domain.server.model.requests.updateChapterMetaRequest
import ca.gosyer.jui.domain.server.model.requests.updateChapterRequest
import ca.gosyer.jui.domain.server.service.ServerPreferences
import io.ktor.client.call.body
import io.ktor.client.plugins.expectSuccess
import io.ktor.client.request.HttpRequestBuilder
import io.ktor.client.request.delete
import io.ktor.client.request.forms.submitForm
import io.ktor.client.request.get
import io.ktor.http.HttpMethod
import io.ktor.http.Parameters
import io.ktor.http.path
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.flow.flow
import kotlinx.coroutines.flow.flowOn
import me.tatarka.inject.annotations.Inject
class ChapterRepositoryImpl @Inject constructor(
client: Http,
serverPreferences: ServerPreferences
) : BaseRepository(client, serverPreferences), ChapterRepository {
override fun getChapters(mangaId: Long, refresh: Boolean) = flow {
val response = client.get(
buildUrl {
path(getMangaChaptersQuery(mangaId))
if (refresh) {
parameter("onlineFetch", true)
}
}
) {
expectSuccess = true
}.body<List<Chapter>>()
emit(response)
}.flowOn(Dispatchers.IO)
override fun getChapter(mangaId: Long, chapterIndex: Int) = flow {
val response = client.get(
buildUrl { path(getChapterQuery(mangaId, chapterIndex)) }
) {
expectSuccess = true
}.body<Chapter>()
emit(response)
}.flowOn(Dispatchers.IO)
override fun updateChapter(
mangaId: Long,
chapterIndex: Int,
read: Boolean?,
bookmarked: Boolean?,
lastPageRead: Int?,
markPreviousRead: Boolean?
) = flow {
val response = client.submitForm(
buildUrl { path(updateChapterRequest(mangaId, chapterIndex)) },
formParameters = Parameters.build {
if (read != null) {
append("read", read.toString())
}
if (bookmarked != null) {
append("bookmarked", bookmarked.toString())
}
if (lastPageRead != null) {
append("lastPageRead", lastPageRead.toString())
}
if (markPreviousRead != null) {
append("markPrevRead", markPreviousRead.toString())
}
}
) {
method = HttpMethod.Patch
expectSuccess = true
}
emit(response)
}.flowOn(Dispatchers.IO)
override fun getPage(mangaId: Long, chapterIndex: Int, pageNum: Int, block: HttpRequestBuilder.() -> Unit) = flow {
val response = client.get(
buildUrl { path(getPageQuery(mangaId, chapterIndex, pageNum)) }
) {
expectSuccess = true
block()
}
emit(response)
}.flowOn(Dispatchers.IO)
override fun deleteChapterDownload(mangaId: Long, chapterIndex: Int) = flow {
val response = client.delete(
buildUrl { path(deleteDownloadedChapterRequest(mangaId, chapterIndex)) }
) {
expectSuccess = true
}
emit(response)
}.flowOn(Dispatchers.IO)
override fun queueChapterDownload(mangaId: Long, chapterIndex: Int) = flow {
val response = client.get(
buildUrl { path(queueDownloadChapterRequest(mangaId, chapterIndex)) }
) {
expectSuccess = true
}
emit(response)
}.flowOn(Dispatchers.IO)
override fun stopChapterDownload(mangaId: Long, chapterIndex: Int) = flow {
val response = client.delete(
buildUrl { path(stopDownloadingChapterRequest(mangaId, chapterIndex)) }
) {
expectSuccess = true
}
emit(response)
}.flowOn(Dispatchers.IO)
override fun updateChapterMeta(mangaId: Long, chapterIndex: Int, key: String, value: String) = flow {
val response = client.submitForm(
buildUrl { path(updateChapterMetaRequest(mangaId, chapterIndex)) },
formParameters = Parameters.build {
append("key", key)
append("value", value)
}
) {
method = HttpMethod.Patch
expectSuccess = true
}
emit(response)
}.flowOn(Dispatchers.IO)
}

View File

@@ -1,56 +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.data.download
import ca.gosyer.jui.core.lang.IO
import ca.gosyer.jui.data.base.BaseRepository
import ca.gosyer.jui.domain.download.service.DownloadRepository
import ca.gosyer.jui.domain.server.Http
import ca.gosyer.jui.domain.server.model.requests.downloadsClearRequest
import ca.gosyer.jui.domain.server.model.requests.downloadsStartRequest
import ca.gosyer.jui.domain.server.model.requests.downloadsStopRequest
import ca.gosyer.jui.domain.server.service.ServerPreferences
import io.ktor.client.plugins.expectSuccess
import io.ktor.client.request.get
import io.ktor.http.path
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.flow.flow
import kotlinx.coroutines.flow.flowOn
import me.tatarka.inject.annotations.Inject
class DownloadRepositoryImpl @Inject constructor(
client: Http,
serverPreferences: ServerPreferences
) : BaseRepository(client, serverPreferences), DownloadRepository {
override fun startDownloading() = flow {
val response = client.get(
buildUrl { path(downloadsStartRequest()) }
) {
expectSuccess = true
}
emit(response)
}.flowOn(Dispatchers.IO)
override fun stopDownloading() = flow {
val response = client.get(
buildUrl { path(downloadsStopRequest()) }
) {
expectSuccess = true
}
emit(response)
}.flowOn(Dispatchers.IO)
override fun clearDownloadQueue() = flow {
val response = client.get(
buildUrl { path(downloadsClearRequest()) }
) {
expectSuccess = true
}
emit(response)
}.flowOn(Dispatchers.IO)
}

View File

@@ -1,81 +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.data.extension
import ca.gosyer.jui.core.lang.IO
import ca.gosyer.jui.data.base.BaseRepository
import ca.gosyer.jui.domain.extension.model.Extension
import ca.gosyer.jui.domain.extension.service.ExtensionRepository
import ca.gosyer.jui.domain.server.Http
import ca.gosyer.jui.domain.server.model.requests.apkIconQuery
import ca.gosyer.jui.domain.server.model.requests.apkInstallQuery
import ca.gosyer.jui.domain.server.model.requests.apkUninstallQuery
import ca.gosyer.jui.domain.server.model.requests.apkUpdateQuery
import ca.gosyer.jui.domain.server.model.requests.extensionListQuery
import ca.gosyer.jui.domain.server.service.ServerPreferences
import io.ktor.client.call.body
import io.ktor.client.plugins.expectSuccess
import io.ktor.client.request.HttpRequestBuilder
import io.ktor.client.request.get
import io.ktor.client.statement.bodyAsChannel
import io.ktor.http.path
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.flow.flow
import kotlinx.coroutines.flow.flowOn
import me.tatarka.inject.annotations.Inject
class ExtensionRepositoryImpl @Inject constructor(
client: Http,
serverPreferences: ServerPreferences
) : BaseRepository(client, serverPreferences), ExtensionRepository {
override fun getExtensionList() = flow {
val response = client.get(
buildUrl { path(extensionListQuery()) }
) {
expectSuccess = true
}.body<List<Extension>>()
emit(response)
}.flowOn(Dispatchers.IO)
override fun installExtension(extension: Extension) = flow {
val response = client.get(
buildUrl { path(apkInstallQuery(extension.pkgName)) }
) {
expectSuccess = true
}
emit(response)
}.flowOn(Dispatchers.IO)
override fun updateExtension(extension: Extension) = flow {
val response = client.get(
buildUrl { path(apkUpdateQuery(extension.pkgName)) }
) {
expectSuccess = true
}
emit(response)
}.flowOn(Dispatchers.IO)
override fun uninstallExtension(extension: Extension) = flow {
val response = client.get(
buildUrl { path(apkUninstallQuery(extension.pkgName)) }
) {
expectSuccess = true
}
emit(response)
}.flowOn(Dispatchers.IO)
override fun getApkIcon(extension: Extension, block: HttpRequestBuilder.() -> Unit) = flow {
val response = client.get(
buildUrl { path(apkIconQuery(extension.apkName)) }
) {
expectSuccess = true
block()
}.bodyAsChannel()
emit(response)
}.flowOn(Dispatchers.IO)
}

View File

@@ -1,47 +0,0 @@
/*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
package ca.gosyer.jui.data.library
import ca.gosyer.jui.core.lang.IO
import ca.gosyer.jui.data.base.BaseRepository
import ca.gosyer.jui.domain.library.service.LibraryRepository
import ca.gosyer.jui.domain.server.Http
import ca.gosyer.jui.domain.server.model.requests.addMangaToLibraryQuery
import ca.gosyer.jui.domain.server.model.requests.removeMangaFromLibraryRequest
import ca.gosyer.jui.domain.server.service.ServerPreferences
import io.ktor.client.plugins.expectSuccess
import io.ktor.client.request.delete
import io.ktor.client.request.get
import io.ktor.http.path
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.flow.flow
import kotlinx.coroutines.flow.flowOn
import me.tatarka.inject.annotations.Inject
class LibraryRepositoryImpl @Inject constructor(
client: Http,
serverPreferences: ServerPreferences
) : BaseRepository(client, serverPreferences), LibraryRepository {
override fun addMangaToLibrary(mangaId: Long) = flow {
val response = client.get(
buildUrl { path(addMangaToLibraryQuery(mangaId)) }
) {
expectSuccess = true
}
emit(response)
}.flowOn(Dispatchers.IO)
override fun removeMangaFromLibrary(mangaId: Long) = flow {
val response = client.delete(
buildUrl { path(removeMangaFromLibraryRequest(mangaId)) }
) {
expectSuccess = true
}
emit(response)
}.flowOn(Dispatchers.IO)
}

View File

@@ -1,74 +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.data.manga
import ca.gosyer.jui.core.lang.IO
import ca.gosyer.jui.data.base.BaseRepository
import ca.gosyer.jui.domain.manga.model.Manga
import ca.gosyer.jui.domain.manga.service.MangaRepository
import ca.gosyer.jui.domain.server.Http
import ca.gosyer.jui.domain.server.model.requests.mangaQuery
import ca.gosyer.jui.domain.server.model.requests.mangaThumbnailQuery
import ca.gosyer.jui.domain.server.model.requests.updateMangaMetaRequest
import ca.gosyer.jui.domain.server.service.ServerPreferences
import io.ktor.client.call.body
import io.ktor.client.plugins.expectSuccess
import io.ktor.client.request.HttpRequestBuilder
import io.ktor.client.request.forms.submitForm
import io.ktor.client.request.get
import io.ktor.client.statement.bodyAsChannel
import io.ktor.http.HttpMethod
import io.ktor.http.Parameters
import io.ktor.http.path
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.flow.flow
import kotlinx.coroutines.flow.flowOn
import me.tatarka.inject.annotations.Inject
class MangaRepositoryImpl @Inject constructor(
client: Http,
serverPreferences: ServerPreferences
) : BaseRepository(client, serverPreferences), MangaRepository {
override fun getManga(mangaId: Long, refresh: Boolean) = flow {
val response = client.get(
buildUrl {
path(mangaQuery(mangaId))
if (refresh) {
parameter("onlineFetch", true)
}
}
) {
expectSuccess = true
}.body<Manga>()
emit(response)
}.flowOn(Dispatchers.IO)
override fun getMangaThumbnail(mangaId: Long, block: HttpRequestBuilder.() -> Unit) = flow {
val response = client.get(
buildUrl { path(mangaThumbnailQuery(mangaId)) }
) {
expectSuccess = true
block()
}.bodyAsChannel()
emit(response)
}.flowOn(Dispatchers.IO)
override fun updateMangaMeta(mangaId: Long, key: String, value: String) = flow {
val response = client.submitForm(
buildUrl { path(updateMangaMetaRequest(mangaId)) },
formParameters = Parameters.build {
append("key", key)
append("value", value)
}
) {
method = HttpMethod.Patch
expectSuccess = true
}
emit(response)
}.flowOn(Dispatchers.IO)
}

View File

@@ -1,49 +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.data.settings
import ca.gosyer.jui.core.lang.IO
import ca.gosyer.jui.data.base.BaseRepository
import ca.gosyer.jui.domain.server.Http
import ca.gosyer.jui.domain.server.model.requests.aboutQuery
import ca.gosyer.jui.domain.server.model.requests.checkUpdateQuery
import ca.gosyer.jui.domain.server.service.ServerPreferences
import ca.gosyer.jui.domain.settings.model.About
import ca.gosyer.jui.domain.settings.service.SettingsRepository
import io.ktor.client.call.body
import io.ktor.client.plugins.expectSuccess
import io.ktor.client.request.get
import io.ktor.client.request.post
import io.ktor.http.path
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.flow.flow
import kotlinx.coroutines.flow.flowOn
import me.tatarka.inject.annotations.Inject
class SettingsRepositoryImpl @Inject constructor(
client: Http,
serverPreferences: ServerPreferences
) : BaseRepository(client, serverPreferences), SettingsRepository {
override fun aboutServer() = flow {
val response = client.get(
buildUrl { path(aboutQuery()) }
) {
expectSuccess = true
}.body<About>()
emit(response)
}.flowOn(Dispatchers.IO)
override fun checkUpdate() = flow {
val response = client.post(
buildUrl { path(checkUpdateQuery()) }
) {
expectSuccess = true
}
emit(response)
}.flowOn(Dispatchers.IO)
}

View File

@@ -1,162 +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.data.source
import ca.gosyer.jui.core.lang.IO
import ca.gosyer.jui.data.base.BaseRepository
import ca.gosyer.jui.domain.server.Http
import ca.gosyer.jui.domain.server.model.requests.getFilterListQuery
import ca.gosyer.jui.domain.server.model.requests.getSourceSettingsQuery
import ca.gosyer.jui.domain.server.model.requests.setFilterRequest
import ca.gosyer.jui.domain.server.model.requests.sourceInfoQuery
import ca.gosyer.jui.domain.server.model.requests.sourceLatestQuery
import ca.gosyer.jui.domain.server.model.requests.sourceListQuery
import ca.gosyer.jui.domain.server.model.requests.sourcePopularQuery
import ca.gosyer.jui.domain.server.model.requests.sourceSearchQuery
import ca.gosyer.jui.domain.server.model.requests.updateSourceSettingQuery
import ca.gosyer.jui.domain.server.service.ServerPreferences
import ca.gosyer.jui.domain.source.model.MangaPage
import ca.gosyer.jui.domain.source.model.Source
import ca.gosyer.jui.domain.source.model.sourcefilters.SourceFilter
import ca.gosyer.jui.domain.source.model.sourcefilters.SourceFilterChange
import ca.gosyer.jui.domain.source.model.sourcepreference.SourcePreference
import ca.gosyer.jui.domain.source.model.sourcepreference.SourcePreferenceChange
import ca.gosyer.jui.domain.source.service.SourceRepository
import io.ktor.client.call.body
import io.ktor.client.plugins.expectSuccess
import io.ktor.client.request.get
import io.ktor.client.request.post
import io.ktor.client.request.setBody
import io.ktor.http.ContentType
import io.ktor.http.contentType
import io.ktor.http.path
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.flow.flow
import kotlinx.coroutines.flow.flowOn
import kotlinx.serialization.encodeToString
import kotlinx.serialization.json.Json
import me.tatarka.inject.annotations.Inject
class SourceRepositoryImpl @Inject constructor(
client: Http,
serverPreferences: ServerPreferences
) : BaseRepository(client, serverPreferences), SourceRepository {
override fun getSourceList() = flow {
val response = client.get(
buildUrl { path(sourceListQuery()) }
) {
expectSuccess = true
}.body<List<Source>>()
emit(response)
}.flowOn(Dispatchers.IO)
override fun getSourceInfo(sourceId: Long) = flow {
val response = client.get(
buildUrl { path(sourceInfoQuery(sourceId)) }
) {
expectSuccess = true
}.body<Source>()
emit(response)
}.flowOn(Dispatchers.IO)
override fun getPopularManga(sourceId: Long, pageNum: Int) = flow {
val response = client.get(
buildUrl { path(sourcePopularQuery(sourceId, pageNum)) }
) {
expectSuccess = true
}.body<MangaPage>()
emit(response)
}.flowOn(Dispatchers.IO)
override fun getLatestManga(sourceId: Long, pageNum: Int) = flow {
val response = client.get(
buildUrl { path(sourceLatestQuery(sourceId, pageNum)) }
) {
expectSuccess = true
}.body<MangaPage>()
emit(response)
}.flowOn(Dispatchers.IO)
override fun getSearchResults(sourceId: Long, searchTerm: String, pageNum: Int) = flow {
val response = client.get(
buildUrl {
path(sourceSearchQuery(sourceId))
parameter("pageNum", pageNum)
if (searchTerm.isNotBlank()) {
parameter("searchTerm", searchTerm)
}
}
) {
expectSuccess = true
}.body<MangaPage>()
emit(response)
}.flowOn(Dispatchers.IO)
override fun getFilterList(sourceId: Long, reset: Boolean) = flow {
val response = client.get(
buildUrl {
path(getFilterListQuery(sourceId))
if (reset) {
parameter("reset", true)
}
}
) {
expectSuccess = true
}.body<List<SourceFilter>>()
emit(response)
}.flowOn(Dispatchers.IO)
override fun setFilter(sourceId: Long, sourceFilter: SourceFilterChange) = flow {
val response = client.post(
buildUrl { path(setFilterRequest(sourceId)) }
) {
contentType(ContentType.Application.Json)
setBody(sourceFilter)
expectSuccess = true
}
emit(response)
}.flowOn(Dispatchers.IO)
override fun setFilter(sourceId: Long, position: Int, value: Any) = setFilter(
sourceId,
SourceFilterChange(position, value)
)
override fun setFilter(sourceId: Long, parentPosition: Int, childPosition: Int, value: Any) = setFilter(
sourceId,
SourceFilterChange(
parentPosition,
Json.encodeToString(SourceFilterChange(childPosition, value))
)
)
override fun getSourceSettings(sourceId: Long) = flow {
val response = client.get(
buildUrl { path(getSourceSettingsQuery(sourceId)) }
) {
expectSuccess = true
}.body<List<SourcePreference>>()
emit(response)
}.flowOn(Dispatchers.IO)
override fun setSourceSetting(sourceId: Long, sourcePreference: SourcePreferenceChange) = flow {
val response = client.post(
buildUrl { path(updateSourceSettingQuery(sourceId)) }
) {
contentType(ContentType.Application.Json)
setBody(sourcePreference)
expectSuccess = true
}
emit(response)
}.flowOn(Dispatchers.IO)
override fun setSourceSetting(sourceId: Long, position: Int, value: Any) = setSourceSetting(
sourceId,
SourcePreferenceChange(position, value)
)
}

View File

@@ -1,63 +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.data.updates
import ca.gosyer.jui.core.lang.IO
import ca.gosyer.jui.data.base.BaseRepository
import ca.gosyer.jui.domain.server.Http
import ca.gosyer.jui.domain.server.model.requests.fetchUpdatesRequest
import ca.gosyer.jui.domain.server.model.requests.recentUpdatesQuery
import ca.gosyer.jui.domain.server.service.ServerPreferences
import ca.gosyer.jui.domain.updates.model.Updates
import ca.gosyer.jui.domain.updates.service.UpdatesRepository
import io.ktor.client.call.body
import io.ktor.client.plugins.expectSuccess
import io.ktor.client.request.forms.submitForm
import io.ktor.client.request.get
import io.ktor.client.request.post
import io.ktor.http.Parameters
import io.ktor.http.path
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.flow.flow
import kotlinx.coroutines.flow.flowOn
import me.tatarka.inject.annotations.Inject
class UpdatesRepositoryImpl @Inject constructor(
client: Http,
serverPreferences: ServerPreferences
) : BaseRepository(client, serverPreferences), UpdatesRepository {
override fun getRecentUpdates(pageNum: Int) = flow {
val response = client.get(
buildUrl { path(recentUpdatesQuery(pageNum)) }
) {
expectSuccess = true
}.body<Updates>()
emit(response)
}.flowOn(Dispatchers.IO)
override fun updateLibrary() = flow {
val response = client.post(
buildUrl { path(fetchUpdatesRequest()) }
) {
expectSuccess = true
}
emit(response)
}.flowOn(Dispatchers.IO)
override fun updateCategory(categoryId: Long) = flow {
val response = client.submitForm(
buildUrl { path(fetchUpdatesRequest()) },
formParameters = Parameters.build {
append("category", categoryId.toString())
}
) {
expectSuccess = true
}
emit(response)
}.flowOn(Dispatchers.IO)
}