Rewrite Tachidesk interactions

- Fix crashing on android when things fail to load
- Improve error handling
This commit is contained in:
Syer10
2022-03-01 13:31:50 -05:00
parent 0e65265ed0
commit a2247cfa1e
26 changed files with 844 additions and 520 deletions

View File

@@ -7,6 +7,8 @@
package ca.gosyer.data.models
import ca.gosyer.data.server.interactions.ChapterInteractionHandler
import kotlinx.coroutines.flow.collect
import kotlinx.coroutines.flow.flow
import kotlinx.serialization.Serializable
@Serializable
@@ -28,13 +30,15 @@ data class Chapter(
val downloaded: Boolean,
val meta: ChapterMeta
) {
suspend fun updateRemote(
fun updateRemote(
chapterHandler: ChapterInteractionHandler,
pageOffset: Int = meta.juiPageOffset
) {
) = flow {
if (pageOffset != meta.juiPageOffset) {
chapterHandler.updateChapterMeta(this, "juiPageOffset", pageOffset.toString())
chapterHandler.updateChapterMeta(this@Chapter, "juiPageOffset", pageOffset.toString())
.collect()
}
emit(Unit)
}
}

View File

@@ -9,6 +9,8 @@ package ca.gosyer.data.models
import ca.gosyer.data.server.interactions.MangaInteractionHandler
import ca.gosyer.i18n.MR
import dev.icerock.moko.resources.StringResource
import kotlinx.coroutines.flow.collect
import kotlinx.coroutines.flow.flow
import kotlinx.serialization.Serializable
import kotlinx.serialization.Transient
@@ -37,10 +39,12 @@ data class Manga(
suspend fun updateRemote(
mangaHandler: MangaInteractionHandler,
readerMode: String = meta.juiReaderMode
) {
) = flow {
if (readerMode != meta.juiReaderMode) {
mangaHandler.updateMangaMeta(this, "juiReaderMode", readerMode)
mangaHandler.updateMangaMeta(this@Manga, "juiReaderMode", readerMode)
.collect()
}
emit(Unit)
}
}

View File

@@ -6,7 +6,6 @@
package ca.gosyer.data.server.interactions
import ca.gosyer.core.lang.withIOContext
import ca.gosyer.data.models.BackupValidationResult
import ca.gosyer.data.server.Http
import ca.gosyer.data.server.ServerPreferences
@@ -21,6 +20,9 @@ import io.ktor.client.statement.HttpResponse
import io.ktor.http.ContentType
import io.ktor.http.Headers
import io.ktor.http.HttpHeaders
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
@@ -31,8 +33,8 @@ class BackupInteractionHandler @Inject constructor(
serverPreferences: ServerPreferences
) : BaseInteractionHandler(client, serverPreferences) {
suspend fun importBackupFile(file: Path, block: HttpRequestBuilder.() -> Unit = {}) = withIOContext {
client.submitFormWithBinaryData<HttpResponse>(
fun importBackupFile(file: Path, block: HttpRequestBuilder.() -> Unit = {}) = flow {
val response = client.submitFormWithBinaryData<HttpResponse>(
serverUrl + backupFileImportRequest(),
formData = formData {
append(
@@ -45,10 +47,11 @@ class BackupInteractionHandler @Inject constructor(
},
block = block
)
}
emit(response)
}.flowOn(Dispatchers.IO)
suspend fun validateBackupFile(file: Path, block: HttpRequestBuilder.() -> Unit = {}) = withIOContext {
client.submitFormWithBinaryData<BackupValidationResult>(
fun validateBackupFile(file: Path, block: HttpRequestBuilder.() -> Unit = {}) = flow {
val response = client.submitFormWithBinaryData<BackupValidationResult>(
serverUrl + validateBackupFileRequest(),
formData = formData {
append(
@@ -61,12 +64,14 @@ class BackupInteractionHandler @Inject constructor(
},
block = block
)
}
emit(response)
}.flowOn(Dispatchers.IO)
suspend fun exportBackupFile(block: HttpRequestBuilder.() -> Unit = {}) = withIOContext {
client.get<HttpResponse>(
fun exportBackupFile(block: HttpRequestBuilder.() -> Unit = {}) = flow {
val response = client.get<HttpResponse>(
serverUrl + backupFileExportRequest(),
block
)
}
emit(response)
}.flowOn(Dispatchers.IO)
}

View File

@@ -6,7 +6,6 @@
package ca.gosyer.data.server.interactions
import ca.gosyer.core.lang.withIOContext
import ca.gosyer.data.models.Category
import ca.gosyer.data.models.Manga
import ca.gosyer.data.server.Http
@@ -26,6 +25,9 @@ import io.ktor.client.request.get
import io.ktor.client.statement.HttpResponse
import io.ktor.http.HttpMethod
import io.ktor.http.Parameters
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.flow.flow
import kotlinx.coroutines.flow.flowOn
import me.tatarka.inject.annotations.Inject
class CategoryInteractionHandler @Inject constructor(
@@ -33,53 +35,58 @@ class CategoryInteractionHandler @Inject constructor(
serverPreferences: ServerPreferences
) : BaseInteractionHandler(client, serverPreferences) {
suspend fun getMangaCategories(mangaId: Long) = withIOContext {
client.get<List<Category>>(
fun getMangaCategories(mangaId: Long) = flow {
val response = client.get<List<Category>>(
serverUrl + getMangaCategoriesQuery(mangaId)
)
}
emit(response)
}.flowOn(Dispatchers.IO)
suspend fun getMangaCategories(manga: Manga) = getMangaCategories(manga.id)
fun getMangaCategories(manga: Manga) = getMangaCategories(manga.id)
suspend fun addMangaToCategory(mangaId: Long, categoryId: Long) = withIOContext {
client.get<HttpResponse>(
fun addMangaToCategory(mangaId: Long, categoryId: Long) = flow {
val response = client.get<HttpResponse>(
serverUrl + addMangaToCategoryQuery(mangaId, categoryId)
)
}
suspend fun addMangaToCategory(manga: Manga, category: Category) = addMangaToCategory(manga.id, category.id)
suspend fun addMangaToCategory(manga: Manga, categoryId: Long) = addMangaToCategory(manga.id, categoryId)
suspend fun addMangaToCategory(mangaId: Long, category: Category) = addMangaToCategory(mangaId, category.id)
emit(response)
}.flowOn(Dispatchers.IO)
fun addMangaToCategory(manga: Manga, category: Category) = addMangaToCategory(manga.id, category.id)
fun addMangaToCategory(manga: Manga, categoryId: Long) = addMangaToCategory(manga.id, categoryId)
fun addMangaToCategory(mangaId: Long, category: Category) = addMangaToCategory(mangaId, category.id)
suspend fun removeMangaFromCategory(mangaId: Long, categoryId: Long) = withIOContext {
client.delete<HttpResponse>(
fun removeMangaFromCategory(mangaId: Long, categoryId: Long) = flow {
val response = client.delete<HttpResponse>(
serverUrl + removeMangaFromCategoryRequest(mangaId, categoryId)
)
}
suspend fun removeMangaFromCategory(manga: Manga, category: Category) = removeMangaFromCategory(manga.id, category.id)
suspend fun removeMangaFromCategory(manga: Manga, categoryId: Long) = removeMangaFromCategory(manga.id, categoryId)
suspend fun removeMangaFromCategory(mangaId: Long, category: Category) = removeMangaFromCategory(mangaId, category.id)
emit(response)
}.flowOn(Dispatchers.IO)
fun removeMangaFromCategory(manga: Manga, category: Category) = removeMangaFromCategory(manga.id, category.id)
fun removeMangaFromCategory(manga: Manga, categoryId: Long) = removeMangaFromCategory(manga.id, categoryId)
fun removeMangaFromCategory(mangaId: Long, category: Category) = removeMangaFromCategory(mangaId, category.id)
suspend fun getCategories(dropDefault: Boolean = false) = withIOContext {
client.get<List<Category>>(
fun getCategories(dropDefault: Boolean = false) = flow {
val response = client.get<List<Category>>(
serverUrl + getCategoriesQuery()
).let { categories ->
if (dropDefault) {
categories.filterNot { it.name.equals("default", true) }
} else categories
}
}
emit(response)
}.flowOn(Dispatchers.IO)
suspend fun createCategory(name: String) = withIOContext {
client.submitForm<HttpResponse>(
fun createCategory(name: String) = flow {
val response = client.submitForm<HttpResponse>(
serverUrl + createCategoryRequest(),
formParameters = Parameters.build {
append("name", name)
}
)
}
emit(response)
}.flowOn(Dispatchers.IO)
suspend fun modifyCategory(categoryId: Long, name: String? = null, isLanding: Boolean? = null) = withIOContext {
client.submitForm<HttpResponse>(
fun modifyCategory(categoryId: Long, name: String? = null, isLanding: Boolean? = null) = flow {
val response = client.submitForm<HttpResponse>(
serverUrl + categoryModifyRequest(categoryId),
formParameters = Parameters.build {
if (name != null) {
@@ -92,11 +99,12 @@ class CategoryInteractionHandler @Inject constructor(
) {
method = HttpMethod.Patch
}
}
suspend fun modifyCategory(category: Category, name: String? = null, isLanding: Boolean? = null) = modifyCategory(category.id, name, isLanding)
emit(response)
}.flowOn(Dispatchers.IO)
fun modifyCategory(category: Category, name: String? = null, isLanding: Boolean? = null) = modifyCategory(category.id, name, isLanding)
suspend fun reorderCategory(to: Int, from: Int) = withIOContext {
client.submitForm<HttpResponse>(
fun reorderCategory(to: Int, from: Int) = flow {
val response = client.submitForm<HttpResponse>(
serverUrl + categoryReorderRequest(),
formParameters = Parameters.build {
append("to", to.toString())
@@ -105,19 +113,22 @@ class CategoryInteractionHandler @Inject constructor(
) {
method = HttpMethod.Patch
}
}
emit(response)
}.flowOn(Dispatchers.IO)
suspend fun deleteCategory(categoryId: Long) = withIOContext {
client.delete<HttpResponse>(
fun deleteCategory(categoryId: Long) = flow {
val response = client.delete<HttpResponse>(
serverUrl + categoryDeleteRequest(categoryId)
)
}
suspend fun deleteCategory(category: Category) = deleteCategory(category.id)
emit(response)
}.flowOn(Dispatchers.IO)
fun deleteCategory(category: Category) = deleteCategory(category.id)
suspend fun getMangaFromCategory(categoryId: Long) = withIOContext {
client.get<List<Manga>>(
fun getMangaFromCategory(categoryId: Long) = flow {
val response = client.get<List<Manga>>(
serverUrl + getMangaInCategoryQuery(categoryId)
)
}
suspend fun getMangaFromCategory(category: Category) = getMangaFromCategory(category.id)
emit(response)
}.flowOn(Dispatchers.IO)
fun getMangaFromCategory(category: Category) = getMangaFromCategory(category.id)
}

View File

@@ -6,7 +6,6 @@
package ca.gosyer.data.server.interactions
import ca.gosyer.core.lang.withIOContext
import ca.gosyer.data.models.Chapter
import ca.gosyer.data.models.Manga
import ca.gosyer.data.server.Http
@@ -28,6 +27,9 @@ import io.ktor.client.statement.HttpResponse
import io.ktor.http.HttpMethod
import io.ktor.http.Parameters
import io.ktor.utils.io.ByteReadChannel
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.flow.flow
import kotlinx.coroutines.flow.flowOn
import me.tatarka.inject.annotations.Inject
class ChapterInteractionHandler @Inject constructor(
@@ -35,8 +37,8 @@ class ChapterInteractionHandler @Inject constructor(
serverPreferences: ServerPreferences
) : BaseInteractionHandler(client, serverPreferences) {
suspend fun getChapters(mangaId: Long, refresh: Boolean = false) = withIOContext {
client.get<List<Chapter>>(
fun getChapters(mangaId: Long, refresh: Boolean = false) = flow {
val response = client.get<List<Chapter>>(
serverUrl + getMangaChaptersQuery(mangaId)
) {
url {
@@ -45,31 +47,33 @@ class ChapterInteractionHandler @Inject constructor(
}
}
}
}
emit(response)
}.flowOn(Dispatchers.IO)
suspend fun getChapters(manga: Manga, refresh: Boolean = false) = getChapters(manga.id, refresh)
fun getChapters(manga: Manga, refresh: Boolean = false) = getChapters(manga.id, refresh)
suspend fun getChapter(mangaId: Long, chapterIndex: Int) = withIOContext {
client.get<Chapter>(
fun getChapter(mangaId: Long, chapterIndex: Int) = flow {
val response = client.get<Chapter>(
serverUrl + getChapterQuery(mangaId, chapterIndex)
)
}
emit(response)
}.flowOn(Dispatchers.IO)
suspend fun getChapter(chapter: Chapter) = getChapter(chapter.mangaId, chapter.index)
fun getChapter(chapter: Chapter) = getChapter(chapter.mangaId, chapter.index)
suspend fun getChapter(manga: Manga, chapterIndex: Int) = getChapter(manga.id, chapterIndex)
fun getChapter(manga: Manga, chapterIndex: Int) = getChapter(manga.id, chapterIndex)
suspend fun getChapter(manga: Manga, chapter: Chapter) = getChapter(manga.id, chapter.index)
fun getChapter(manga: Manga, chapter: Chapter) = getChapter(manga.id, chapter.index)
suspend fun updateChapter(
fun updateChapter(
mangaId: Long,
chapterIndex: Int,
read: Boolean? = null,
bookmarked: Boolean? = null,
lastPageRead: Int? = null,
markPreviousRead: Boolean? = null
) = withIOContext {
client.submitForm<HttpResponse>(
) = flow {
val response = client.submitForm<HttpResponse>(
serverUrl + updateChapterRequest(mangaId, chapterIndex),
formParameters = Parameters.build {
if (read != null) {
@@ -88,9 +92,10 @@ class ChapterInteractionHandler @Inject constructor(
) {
method = HttpMethod.Patch
}
}
emit(response)
}.flowOn(Dispatchers.IO)
suspend fun updateChapter(
fun updateChapter(
manga: Manga,
chapterIndex: Int,
read: Boolean? = null,
@@ -106,7 +111,7 @@ class ChapterInteractionHandler @Inject constructor(
markPreviousRead
)
suspend fun updateChapter(
fun updateChapter(
manga: Manga,
chapter: Chapter,
read: Boolean? = null,
@@ -122,57 +127,61 @@ class ChapterInteractionHandler @Inject constructor(
markPreviousRead
)
suspend fun getPage(mangaId: Long, chapterIndex: Int, pageNum: Int, block: HttpRequestBuilder.() -> Unit) = withIOContext {
client.get<ByteReadChannel>(
fun getPage(mangaId: Long, chapterIndex: Int, pageNum: Int, block: HttpRequestBuilder.() -> Unit) = flow {
val response = client.get<ByteReadChannel>(
serverUrl + getPageQuery(mangaId, chapterIndex, pageNum),
block
)
}
emit(response)
}.flowOn(Dispatchers.IO)
suspend fun getPage(chapter: Chapter, pageNum: Int, block: HttpRequestBuilder.() -> Unit) = getPage(chapter.mangaId, chapter.index, pageNum, block)
fun getPage(chapter: Chapter, pageNum: Int, block: HttpRequestBuilder.() -> Unit) = getPage(chapter.mangaId, chapter.index, pageNum, block)
suspend fun getPage(manga: Manga, chapterIndex: Int, pageNum: Int, block: HttpRequestBuilder.() -> Unit) = getPage(manga.id, chapterIndex, pageNum, block)
fun getPage(manga: Manga, chapterIndex: Int, pageNum: Int, block: HttpRequestBuilder.() -> Unit) = getPage(manga.id, chapterIndex, pageNum, block)
suspend fun getPage(manga: Manga, chapter: Chapter, pageNum: Int, block: HttpRequestBuilder.() -> Unit) = getPage(manga.id, chapter.index, pageNum, block)
fun getPage(manga: Manga, chapter: Chapter, pageNum: Int, block: HttpRequestBuilder.() -> Unit) = getPage(manga.id, chapter.index, pageNum, block)
suspend fun deleteChapterDownload(mangaId: Long, chapterIndex: Int) = withIOContext {
client.delete<HttpResponse>(
fun deleteChapterDownload(mangaId: Long, chapterIndex: Int) = flow {
val response = client.delete<HttpResponse>(
serverUrl + deleteDownloadedChapterRequest(mangaId, chapterIndex)
)
}
emit(response)
}.flowOn(Dispatchers.IO)
suspend fun deleteChapterDownload(chapter: Chapter) = deleteChapterDownload(chapter.mangaId, chapter.index)
fun deleteChapterDownload(chapter: Chapter) = deleteChapterDownload(chapter.mangaId, chapter.index)
suspend fun deleteChapterDownload(manga: Manga, chapterIndex: Int) = deleteChapterDownload(manga.id, chapterIndex)
fun deleteChapterDownload(manga: Manga, chapterIndex: Int) = deleteChapterDownload(manga.id, chapterIndex)
suspend fun deleteChapterDownload(manga: Manga, chapter: Chapter) = deleteChapterDownload(manga.id, chapter.index)
fun deleteChapterDownload(manga: Manga, chapter: Chapter) = deleteChapterDownload(manga.id, chapter.index)
suspend fun queueChapterDownload(mangaId: Long, chapterIndex: Int) = withIOContext {
client.get<HttpResponse>(
fun queueChapterDownload(mangaId: Long, chapterIndex: Int) = flow {
val response = client.get<HttpResponse>(
serverUrl + queueDownloadChapterRequest(mangaId, chapterIndex)
)
}
emit(response)
}.flowOn(Dispatchers.IO)
suspend fun queueChapterDownload(chapter: Chapter) = queueChapterDownload(chapter.mangaId, chapter.index)
fun queueChapterDownload(chapter: Chapter) = queueChapterDownload(chapter.mangaId, chapter.index)
suspend fun queueChapterDownload(manga: Manga, chapterIndex: Int) = queueChapterDownload(manga.id, chapterIndex)
fun queueChapterDownload(manga: Manga, chapterIndex: Int) = queueChapterDownload(manga.id, chapterIndex)
suspend fun queueChapterDownload(manga: Manga, chapter: Chapter) = queueChapterDownload(manga.id, chapter.index)
fun queueChapterDownload(manga: Manga, chapter: Chapter) = queueChapterDownload(manga.id, chapter.index)
suspend fun stopChapterDownload(mangaId: Long, chapterIndex: Int) = withIOContext {
client.delete<HttpResponse>(
fun stopChapterDownload(mangaId: Long, chapterIndex: Int) = flow {
val response = client.delete<HttpResponse>(
serverUrl + stopDownloadingChapterRequest(mangaId, chapterIndex)
)
}
emit(response)
}.flowOn(Dispatchers.IO)
suspend fun stopChapterDownload(chapter: Chapter) = stopChapterDownload(chapter.mangaId, chapter.index)
fun stopChapterDownload(chapter: Chapter) = stopChapterDownload(chapter.mangaId, chapter.index)
suspend fun stopChapterDownload(manga: Manga, chapterIndex: Int) = stopChapterDownload(manga.id, chapterIndex)
fun stopChapterDownload(manga: Manga, chapterIndex: Int) = stopChapterDownload(manga.id, chapterIndex)
suspend fun stopChapterDownload(manga: Manga, chapter: Chapter) = stopChapterDownload(manga.id, chapter.index)
fun stopChapterDownload(manga: Manga, chapter: Chapter) = stopChapterDownload(manga.id, chapter.index)
suspend fun updateChapterMeta(mangaId: Long, chapterIndex: Int, key: String, value: String) = withIOContext {
client.submitForm<HttpResponse>(
fun updateChapterMeta(mangaId: Long, chapterIndex: Int, key: String, value: String) = flow {
val response = client.submitForm<HttpResponse>(
serverUrl + updateChapterMetaRequest(mangaId, chapterIndex),
formParameters = Parameters.build {
append("key", key)
@@ -181,11 +190,12 @@ class ChapterInteractionHandler @Inject constructor(
) {
method = HttpMethod.Patch
}
}
emit(response)
}.flowOn(Dispatchers.IO)
suspend fun updateChapterMeta(chapter: Chapter, key: String, value: String) = updateChapterMeta(chapter.mangaId, chapter.index, key, value)
fun updateChapterMeta(chapter: Chapter, key: String, value: String) = updateChapterMeta(chapter.mangaId, chapter.index, key, value)
suspend fun updateChapterMeta(manga: Manga, chapterIndex: Int, key: String, value: String) = updateChapterMeta(manga.id, chapterIndex, key, value)
fun updateChapterMeta(manga: Manga, chapterIndex: Int, key: String, value: String) = updateChapterMeta(manga.id, chapterIndex, key, value)
suspend fun updateChapterMeta(manga: Manga, chapter: Chapter, key: String, value: String) = updateChapterMeta(manga.id, chapter.index, key, value)
fun updateChapterMeta(manga: Manga, chapter: Chapter, key: String, value: String) = updateChapterMeta(manga.id, chapter.index, key, value)
}

View File

@@ -6,7 +6,6 @@
package ca.gosyer.data.server.interactions
import ca.gosyer.core.lang.withIOContext
import ca.gosyer.data.server.Http
import ca.gosyer.data.server.ServerPreferences
import ca.gosyer.data.server.requests.downloadsClearRequest
@@ -14,6 +13,9 @@ import ca.gosyer.data.server.requests.downloadsStartRequest
import ca.gosyer.data.server.requests.downloadsStopRequest
import io.ktor.client.request.get
import io.ktor.client.statement.HttpResponse
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.flow.flow
import kotlinx.coroutines.flow.flowOn
import me.tatarka.inject.annotations.Inject
class DownloadInteractionHandler @Inject constructor(
@@ -21,21 +23,24 @@ class DownloadInteractionHandler @Inject constructor(
serverPreferences: ServerPreferences
) : BaseInteractionHandler(client, serverPreferences) {
suspend fun startDownloading() = withIOContext {
client.get<HttpResponse>(
fun startDownloading() = flow {
val response = client.get<HttpResponse>(
serverUrl + downloadsStartRequest()
)
}
emit(response)
}.flowOn(Dispatchers.IO)
suspend fun stopDownloading() = withIOContext {
client.get<HttpResponse>(
fun stopDownloading() = flow {
val response = client.get<HttpResponse>(
serverUrl + downloadsStopRequest()
)
}
emit(response)
}.flowOn(Dispatchers.IO)
suspend fun clearDownloadQueue() = withIOContext {
client.get<HttpResponse>(
fun clearDownloadQueue() = flow {
val response = client.get<HttpResponse>(
serverUrl + downloadsClearRequest()
)
}
emit(response)
}.flowOn(Dispatchers.IO)
}

View File

@@ -6,7 +6,6 @@
package ca.gosyer.data.server.interactions
import ca.gosyer.core.lang.withIOContext
import ca.gosyer.data.models.Extension
import ca.gosyer.data.server.Http
import ca.gosyer.data.server.ServerPreferences
@@ -19,6 +18,9 @@ import io.ktor.client.request.HttpRequestBuilder
import io.ktor.client.request.get
import io.ktor.client.statement.HttpResponse
import io.ktor.utils.io.ByteReadChannel
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.flow.flow
import kotlinx.coroutines.flow.flowOn
import me.tatarka.inject.annotations.Inject
class ExtensionInteractionHandler @Inject constructor(
@@ -26,34 +28,39 @@ class ExtensionInteractionHandler @Inject constructor(
serverPreferences: ServerPreferences
) : BaseInteractionHandler(client, serverPreferences) {
suspend fun getExtensionList() = withIOContext {
client.get<List<Extension>>(
fun getExtensionList() = flow {
val response = client.get<List<Extension>>(
serverUrl + extensionListQuery()
)
}
emit(response)
}.flowOn(Dispatchers.IO)
suspend fun installExtension(extension: Extension) = withIOContext {
client.get<HttpResponse>(
fun installExtension(extension: Extension) = flow {
val response = client.get<HttpResponse>(
serverUrl + apkInstallQuery(extension.pkgName)
)
}
emit(response)
}.flowOn(Dispatchers.IO)
suspend fun updateExtension(extension: Extension) = withIOContext {
client.get<HttpResponse>(
fun updateExtension(extension: Extension) = flow {
val response = client.get<HttpResponse>(
serverUrl + apkUpdateQuery(extension.pkgName)
)
}
emit(response)
}.flowOn(Dispatchers.IO)
suspend fun uninstallExtension(extension: Extension) = withIOContext {
client.get<HttpResponse>(
fun uninstallExtension(extension: Extension) = flow {
val response = client.get<HttpResponse>(
serverUrl + apkUninstallQuery(extension.pkgName)
)
}
emit(response)
}.flowOn(Dispatchers.IO)
suspend fun getApkIcon(extension: Extension, block: HttpRequestBuilder.() -> Unit) = withIOContext {
client.get<ByteReadChannel>(
fun getApkIcon(extension: Extension, block: HttpRequestBuilder.() -> Unit) = flow {
val response = client.get<ByteReadChannel>(
serverUrl + apkIconQuery(extension.apkName),
block
)
}
emit(response)
}.flowOn(Dispatchers.IO)
}

View File

@@ -6,7 +6,6 @@
package ca.gosyer.data.server.interactions
import ca.gosyer.core.lang.withIOContext
import ca.gosyer.data.models.Manga
import ca.gosyer.data.server.Http
import ca.gosyer.data.server.ServerPreferences
@@ -15,6 +14,9 @@ import ca.gosyer.data.server.requests.removeMangaFromLibraryRequest
import io.ktor.client.request.delete
import io.ktor.client.request.get
import io.ktor.client.statement.HttpResponse
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.flow.flow
import kotlinx.coroutines.flow.flowOn
import me.tatarka.inject.annotations.Inject
class LibraryInteractionHandler @Inject constructor(
@@ -22,19 +24,21 @@ class LibraryInteractionHandler @Inject constructor(
serverPreferences: ServerPreferences
) : BaseInteractionHandler(client, serverPreferences) {
suspend fun addMangaToLibrary(mangaId: Long) = withIOContext {
client.get<HttpResponse>(
fun addMangaToLibrary(mangaId: Long) = flow {
val response = client.get<HttpResponse>(
serverUrl + addMangaToLibraryQuery(mangaId)
)
}
emit(response)
}.flowOn(Dispatchers.IO)
suspend fun addMangaToLibrary(manga: Manga) = addMangaToLibrary(manga.id)
fun addMangaToLibrary(manga: Manga) = addMangaToLibrary(manga.id)
suspend fun removeMangaFromLibrary(mangaId: Long) = withIOContext {
client.delete<HttpResponse>(
fun removeMangaFromLibrary(mangaId: Long) = flow {
val response = client.delete<HttpResponse>(
serverUrl + removeMangaFromLibraryRequest(mangaId)
)
}
emit(response)
}.flowOn(Dispatchers.IO)
suspend fun removeMangaFromLibrary(manga: Manga) = removeMangaFromLibrary(manga.id)
fun removeMangaFromLibrary(manga: Manga) = removeMangaFromLibrary(manga.id)
}

View File

@@ -6,7 +6,6 @@
package ca.gosyer.data.server.interactions
import ca.gosyer.core.lang.withIOContext
import ca.gosyer.data.models.Manga
import ca.gosyer.data.server.Http
import ca.gosyer.data.server.ServerPreferences
@@ -21,6 +20,9 @@ import io.ktor.client.statement.HttpResponse
import io.ktor.http.HttpMethod
import io.ktor.http.Parameters
import io.ktor.utils.io.ByteReadChannel
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.flow.flow
import kotlinx.coroutines.flow.flowOn
import me.tatarka.inject.annotations.Inject
class MangaInteractionHandler @Inject constructor(
@@ -28,8 +30,8 @@ class MangaInteractionHandler @Inject constructor(
serverPreferences: ServerPreferences
) : BaseInteractionHandler(client, serverPreferences) {
suspend fun getManga(mangaId: Long, refresh: Boolean = false) = withIOContext {
client.get<Manga>(
fun getManga(mangaId: Long, refresh: Boolean = false) = flow {
val response = client.get<Manga>(
serverUrl + mangaQuery(mangaId)
) {
url {
@@ -38,19 +40,21 @@ class MangaInteractionHandler @Inject constructor(
}
}
}
}
emit(response)
}.flowOn(Dispatchers.IO)
suspend fun getManga(manga: Manga, refresh: Boolean = false) = getManga(manga.id, refresh)
fun getManga(manga: Manga, refresh: Boolean = false) = getManga(manga.id, refresh)
suspend fun getMangaThumbnail(mangaId: Long, block: HttpRequestBuilder.() -> Unit) = withIOContext {
client.get<ByteReadChannel>(
fun getMangaThumbnail(mangaId: Long, block: HttpRequestBuilder.() -> Unit) = flow {
val response = client.get<ByteReadChannel>(
serverUrl + mangaThumbnailQuery(mangaId),
block
)
}
emit(response)
}.flowOn(Dispatchers.IO)
suspend fun updateMangaMeta(mangaId: Long, key: String, value: String) = withIOContext {
client.submitForm<HttpResponse>(
fun updateMangaMeta(mangaId: Long, key: String, value: String) = flow {
val response = client.submitForm<HttpResponse>(
serverUrl + updateMangaMetaRequest(mangaId),
formParameters = Parameters.build {
append("key", key)
@@ -59,7 +63,8 @@ class MangaInteractionHandler @Inject constructor(
) {
method = HttpMethod.Patch
}
}
emit(response)
}.flowOn(Dispatchers.IO)
suspend fun updateMangaMeta(manga: Manga, key: String, value: String) = updateMangaMeta(manga.id, key, value)
fun updateMangaMeta(manga: Manga, key: String, value: String) = updateMangaMeta(manga.id, key, value)
}

View File

@@ -6,7 +6,6 @@
package ca.gosyer.data.server.interactions
import ca.gosyer.core.lang.withIOContext
import ca.gosyer.data.models.MangaPage
import ca.gosyer.data.models.Source
import ca.gosyer.data.models.sourcefilters.SourceFilter
@@ -31,6 +30,9 @@ import io.ktor.client.request.post
import io.ktor.client.statement.HttpResponse
import io.ktor.http.ContentType
import io.ktor.http.contentType
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
@@ -40,45 +42,49 @@ class SourceInteractionHandler @Inject constructor(
serverPreferences: ServerPreferences
) : BaseInteractionHandler(client, serverPreferences) {
suspend fun getSourceList() = withIOContext {
client.get<List<Source>>(
fun getSourceList() = flow {
val response = client.get<List<Source>>(
serverUrl + sourceListQuery()
)
}
emit(response)
}.flowOn(Dispatchers.IO)
suspend fun getSourceInfo(sourceId: Long) = withIOContext {
client.get<Source>(
fun getSourceInfo(sourceId: Long) = flow {
val response = client.get<Source>(
serverUrl + sourceInfoQuery(sourceId)
)
}
emit(response)
}.flowOn(Dispatchers.IO)
suspend fun getSourceInfo(source: Source) = getSourceInfo(source.id)
fun getSourceInfo(source: Source) = getSourceInfo(source.id)
suspend fun getPopularManga(sourceId: Long, pageNum: Int) = withIOContext {
client.get<MangaPage>(
fun getPopularManga(sourceId: Long, pageNum: Int) = flow {
val response = client.get<MangaPage>(
serverUrl + sourcePopularQuery(sourceId, pageNum)
)
}
emit(response)
}.flowOn(Dispatchers.IO)
suspend fun getPopularManga(source: Source, pageNum: Int) = getPopularManga(
fun getPopularManga(source: Source, pageNum: Int) = getPopularManga(
source.id,
pageNum
)
suspend fun getLatestManga(sourceId: Long, pageNum: Int) = withIOContext {
client.get<MangaPage>(
fun getLatestManga(sourceId: Long, pageNum: Int) = flow {
val response = client.get<MangaPage>(
serverUrl + sourceLatestQuery(sourceId, pageNum)
)
}
emit(response)
}.flowOn(Dispatchers.IO)
suspend fun getLatestManga(source: Source, pageNum: Int) = getLatestManga(
fun getLatestManga(source: Source, pageNum: Int) = getLatestManga(
source.id,
pageNum
)
// TODO: 2021-03-14
suspend fun getGlobalSearchResults(searchTerm: String) = withIOContext {
client.get<HttpResponse>(
fun getGlobalSearchResults(searchTerm: String) = flow {
val response = client.get<HttpResponse>(
serverUrl + globalSearchQuery()
) {
url {
@@ -87,10 +93,11 @@ class SourceInteractionHandler @Inject constructor(
}
}
}
}
emit(response)
}.flowOn(Dispatchers.IO)
suspend fun getSearchResults(sourceId: Long, searchTerm: String, pageNum: Int) = withIOContext {
client.get<MangaPage>(
fun getSearchResults(sourceId: Long, searchTerm: String, pageNum: Int) = flow {
val response = client.get<MangaPage>(
serverUrl + sourceSearchQuery(sourceId)
) {
url {
@@ -100,16 +107,17 @@ class SourceInteractionHandler @Inject constructor(
}
}
}
}
emit(response)
}.flowOn(Dispatchers.IO)
suspend fun getSearchResults(source: Source, searchTerm: String, pageNum: Int) = getSearchResults(
fun getSearchResults(source: Source, searchTerm: String, pageNum: Int) = getSearchResults(
source.id,
searchTerm,
pageNum
)
suspend fun getFilterList(sourceId: Long, reset: Boolean = false) = withIOContext {
client.get<List<SourceFilter>>(
fun getFilterList(sourceId: Long, reset: Boolean = false) = flow {
val response = client.get<List<SourceFilter>>(
serverUrl + getFilterListQuery(sourceId)
) {
url {
@@ -118,25 +126,27 @@ class SourceInteractionHandler @Inject constructor(
}
}
}
}
emit(response)
}.flowOn(Dispatchers.IO)
suspend fun getFilterList(source: Source, reset: Boolean = false) = getFilterList(source.id, reset)
fun getFilterList(source: Source, reset: Boolean = false) = getFilterList(source.id, reset)
suspend fun setFilter(sourceId: Long, sourceFilter: SourceFilterChange) = withIOContext {
client.post<HttpResponse>(
fun setFilter(sourceId: Long, sourceFilter: SourceFilterChange) = flow {
val response = client.post<HttpResponse>(
serverUrl + setFilterRequest(sourceId)
) {
contentType(ContentType.Application.Json)
body = sourceFilter
}
}
emit(response)
}.flowOn(Dispatchers.IO)
suspend fun setFilter(sourceId: Long, position: Int, value: Any) = setFilter(
fun setFilter(sourceId: Long, position: Int, value: Any) = setFilter(
sourceId,
SourceFilterChange(position, value)
)
suspend fun setFilter(sourceId: Long, parentPosition: Int, childPosition: Int, value: Any) = setFilter(
fun setFilter(sourceId: Long, parentPosition: Int, childPosition: Int, value: Any) = setFilter(
sourceId,
SourceFilterChange(
parentPosition,
@@ -144,24 +154,26 @@ class SourceInteractionHandler @Inject constructor(
)
)
suspend fun getSourceSettings(sourceId: Long) = withIOContext {
client.get<List<SourcePreference>>(
fun getSourceSettings(sourceId: Long) = flow {
val response = client.get<List<SourcePreference>>(
serverUrl + getSourceSettingsQuery(sourceId)
)
}
emit(response)
}.flowOn(Dispatchers.IO)
suspend fun getSourceSettings(source: Source) = getSourceSettings(source.id)
fun getSourceSettings(source: Source) = getSourceSettings(source.id)
suspend fun setSourceSetting(sourceId: Long, sourcePreference: SourcePreferenceChange) = withIOContext {
client.post<HttpResponse>(
fun setSourceSetting(sourceId: Long, sourcePreference: SourcePreferenceChange) = flow {
val response = client.post<HttpResponse>(
serverUrl + updateSourceSettingQuery(sourceId)
) {
contentType(ContentType.Application.Json)
body = sourcePreference
}
}
emit(response)
}.flowOn(Dispatchers.IO)
suspend fun setSourceSetting(sourceId: Long, position: Int, value: Any) = setSourceSetting(
fun setSourceSetting(sourceId: Long, position: Int, value: Any) = setSourceSetting(
sourceId,
SourcePreferenceChange(position, value)
)

View File

@@ -6,7 +6,6 @@
package ca.gosyer.data.server.interactions
import ca.gosyer.core.lang.withIOContext
import ca.gosyer.data.models.Category
import ca.gosyer.data.models.Updates
import ca.gosyer.data.server.Http
@@ -18,6 +17,9 @@ import io.ktor.client.request.get
import io.ktor.client.request.post
import io.ktor.client.statement.HttpResponse
import io.ktor.http.Parameters
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.flow.flow
import kotlinx.coroutines.flow.flowOn
import me.tatarka.inject.annotations.Inject
class UpdatesInteractionHandler @Inject constructor(
@@ -25,26 +27,29 @@ class UpdatesInteractionHandler @Inject constructor(
serverPreferences: ServerPreferences
) : BaseInteractionHandler(client, serverPreferences) {
suspend fun getRecentUpdates(pageNum: Int) = withIOContext {
client.get<Updates>(
fun getRecentUpdates(pageNum: Int) = flow {
val response = client.get<Updates>(
serverUrl + recentUpdatesQuery(pageNum)
)
}
emit(response)
}.flowOn(Dispatchers.IO)
suspend fun updateLibrary() = withIOContext {
client.post<HttpResponse>(
fun updateLibrary() = flow {
val response = client.post<HttpResponse>(
serverUrl + fetchUpdatesRequest()
)
}
emit(response)
}.flowOn(Dispatchers.IO)
suspend fun updateCategory(categoryId: Long) = withIOContext {
client.submitForm<HttpResponse>(
fun updateCategory(categoryId: Long) = flow {
val response = client.submitForm<HttpResponse>(
serverUrl + fetchUpdatesRequest(),
formParameters = Parameters.build {
append("category", categoryId.toString())
}
)
}
emit(response)
}.flowOn(Dispatchers.IO)
suspend fun updateCategory(category: Category) = updateCategory(category.id)
fun updateCategory(category: Category) = updateCategory(category.id)
}