mirror of
https://github.com/Suwayomi/TachideskJUI.git
synced 2025-12-10 06:42:05 +01:00
Use interactors for chapter data calls
This commit is contained in:
@@ -0,0 +1,40 @@
|
||||
/*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package ca.gosyer.jui.domain.chapter.interactor
|
||||
|
||||
import ca.gosyer.jui.domain.chapter.model.Chapter
|
||||
import ca.gosyer.jui.domain.chapter.service.ChapterRepository
|
||||
import ca.gosyer.jui.domain.manga.model.Manga
|
||||
import kotlinx.coroutines.flow.catch
|
||||
import kotlinx.coroutines.flow.collect
|
||||
import me.tatarka.inject.annotations.Inject
|
||||
import org.lighthousegames.logging.logging
|
||||
|
||||
class DeleteChapterDownload @Inject constructor(private val chapterRepository: ChapterRepository) {
|
||||
|
||||
suspend fun await(mangaId: Long, index: Int) = asFlow(mangaId, index)
|
||||
.catch { log.warn(it) { "Failed to delete chapter download for $index of $mangaId" } }
|
||||
.collect()
|
||||
|
||||
suspend fun await(manga: Manga, index: Int) = asFlow(manga, index)
|
||||
.catch { log.warn(it) { "Failed to delete chapter download for $index of ${manga.title}(${manga.id})" } }
|
||||
.collect()
|
||||
|
||||
suspend fun await(chapter: Chapter) = asFlow(chapter)
|
||||
.catch { log.warn(it) { "Failed to delete chapter download for ${chapter.index} of ${chapter.mangaId}" } }
|
||||
.collect()
|
||||
|
||||
fun asFlow(mangaId: Long, index: Int) = chapterRepository.deleteChapterDownload(mangaId, index)
|
||||
|
||||
fun asFlow(manga: Manga, index: Int) = chapterRepository.deleteChapterDownload(manga.id, index)
|
||||
|
||||
fun asFlow(chapter: Chapter) = chapterRepository.deleteChapterDownload(chapter.mangaId, chapter.index)
|
||||
|
||||
companion object {
|
||||
private val log = logging()
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
/*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package ca.gosyer.jui.domain.chapter.interactor
|
||||
|
||||
import ca.gosyer.jui.domain.chapter.model.Chapter
|
||||
import ca.gosyer.jui.domain.chapter.service.ChapterRepository
|
||||
import ca.gosyer.jui.domain.manga.model.Manga
|
||||
import kotlinx.coroutines.flow.catch
|
||||
import kotlinx.coroutines.flow.singleOrNull
|
||||
import me.tatarka.inject.annotations.Inject
|
||||
import org.lighthousegames.logging.logging
|
||||
|
||||
class GetChapter @Inject constructor(private val chapterRepository: ChapterRepository) {
|
||||
|
||||
suspend fun await(mangaId: Long, index: Int) = asFlow(mangaId, index)
|
||||
.catch { log.warn(it) { "Failed to get chapter $index for $mangaId" } }
|
||||
.singleOrNull()
|
||||
|
||||
suspend fun await(manga: Manga, index: Int) = asFlow(manga, index)
|
||||
.catch { log.warn(it) { "Failed to get chapter $index for ${manga.title}(${manga.id})" } }
|
||||
.singleOrNull()
|
||||
|
||||
suspend fun await(chapter: Chapter) = asFlow(chapter)
|
||||
.catch { log.warn(it) { "Failed to get chapter ${chapter.index} for ${chapter.mangaId}" } }
|
||||
.singleOrNull()
|
||||
|
||||
fun asFlow(mangaId: Long, index: Int) = chapterRepository.getChapter(mangaId, index)
|
||||
|
||||
fun asFlow(manga: Manga, index: Int) = chapterRepository.getChapter(manga.id, index)
|
||||
|
||||
fun asFlow(chapter: Chapter) = chapterRepository.getChapter(chapter.mangaId, chapter.index)
|
||||
|
||||
companion object {
|
||||
private val log = logging()
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,69 @@
|
||||
/*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package ca.gosyer.jui.domain.chapter.interactor
|
||||
|
||||
import ca.gosyer.jui.domain.chapter.model.Chapter
|
||||
import ca.gosyer.jui.domain.chapter.service.ChapterRepository
|
||||
import ca.gosyer.jui.domain.manga.model.Manga
|
||||
import io.ktor.client.request.HttpRequestBuilder
|
||||
import kotlinx.coroutines.flow.catch
|
||||
import kotlinx.coroutines.flow.singleOrNull
|
||||
import me.tatarka.inject.annotations.Inject
|
||||
import org.lighthousegames.logging.logging
|
||||
|
||||
class GetChapterPage @Inject constructor(private val chapterRepository: ChapterRepository) {
|
||||
|
||||
suspend fun await(
|
||||
mangaId: Long,
|
||||
index: Int,
|
||||
pageNum: Int,
|
||||
block: HttpRequestBuilder.() -> Unit
|
||||
) = asFlow(mangaId, index, pageNum, block)
|
||||
.catch { log.warn(it) { "Failed to get page $pageNum for chapter $index for $mangaId" } }
|
||||
.singleOrNull()
|
||||
|
||||
suspend fun await(
|
||||
manga: Manga,
|
||||
index: Int,
|
||||
pageNum: Int,
|
||||
block: HttpRequestBuilder.() -> Unit
|
||||
) = asFlow(manga, index, pageNum, block)
|
||||
.catch { log.warn(it) { "Failed to get page $pageNum for chapter $index for ${manga.title}(${manga.id})" } }
|
||||
.singleOrNull()
|
||||
|
||||
suspend fun await(
|
||||
chapter: Chapter,
|
||||
pageNum: Int,
|
||||
block: HttpRequestBuilder.() -> Unit
|
||||
) = asFlow(chapter, pageNum, block)
|
||||
.catch { log.warn(it) { "Failed to get page $pageNum for chapter ${chapter.index} for ${chapter.mangaId}" } }
|
||||
.singleOrNull()
|
||||
|
||||
fun asFlow(
|
||||
mangaId: Long,
|
||||
index: Int,
|
||||
pageNum: Int,
|
||||
block: HttpRequestBuilder.() -> Unit
|
||||
) = chapterRepository.getPage(mangaId, index, pageNum, block)
|
||||
|
||||
fun asFlow(
|
||||
manga: Manga,
|
||||
index: Int,
|
||||
pageNum: Int,
|
||||
block: HttpRequestBuilder.() -> Unit
|
||||
) = chapterRepository.getPage(manga.id, index, pageNum, block)
|
||||
|
||||
fun asFlow(
|
||||
chapter: Chapter,
|
||||
pageNum: Int,
|
||||
block: HttpRequestBuilder.() -> Unit
|
||||
) = chapterRepository.getPage(chapter.mangaId, chapter.index, pageNum, block)
|
||||
|
||||
companion object {
|
||||
private val log = logging()
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
/*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package ca.gosyer.jui.domain.chapter.interactor
|
||||
|
||||
import ca.gosyer.jui.domain.chapter.service.ChapterRepository
|
||||
import ca.gosyer.jui.domain.manga.model.Manga
|
||||
import ca.gosyer.jui.domain.manga.service.MangaRepository
|
||||
import kotlinx.coroutines.flow.catch
|
||||
import kotlinx.coroutines.flow.singleOrNull
|
||||
import me.tatarka.inject.annotations.Inject
|
||||
import org.lighthousegames.logging.logging
|
||||
|
||||
class GetChapters @Inject constructor(private val chapterRepository: ChapterRepository) {
|
||||
|
||||
suspend fun await(mangaId: Long) = asFlow(mangaId)
|
||||
.catch { log.warn(it) { "Failed to get chapters for $mangaId" } }
|
||||
.singleOrNull()
|
||||
|
||||
suspend fun await(manga: Manga) = asFlow(manga)
|
||||
.catch { log.warn(it) { "Failed to get chapters for ${manga.title}(${manga.id})" } }
|
||||
.singleOrNull()
|
||||
|
||||
fun asFlow(mangaId: Long) = chapterRepository.getChapters(mangaId)
|
||||
|
||||
fun asFlow(manga: Manga) = chapterRepository.getChapters(manga.id)
|
||||
|
||||
companion object {
|
||||
private val log = logging()
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
/*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package ca.gosyer.jui.domain.chapter.interactor
|
||||
|
||||
import ca.gosyer.jui.domain.chapter.model.Chapter
|
||||
import ca.gosyer.jui.domain.chapter.service.ChapterRepository
|
||||
import ca.gosyer.jui.domain.manga.model.Manga
|
||||
import kotlinx.coroutines.flow.catch
|
||||
import kotlinx.coroutines.flow.collect
|
||||
import me.tatarka.inject.annotations.Inject
|
||||
import org.lighthousegames.logging.logging
|
||||
|
||||
class QueueChapterDownload @Inject constructor(private val chapterRepository: ChapterRepository) {
|
||||
|
||||
suspend fun await(mangaId: Long, index: Int) = asFlow(mangaId, index)
|
||||
.catch { log.warn(it) { "Failed to queue chapter $index of $mangaId for a download" } }
|
||||
.collect()
|
||||
|
||||
suspend fun await(manga: Manga, index: Int) = asFlow(manga, index)
|
||||
.catch { log.warn(it) { "Failed to queue chapter $index of ${manga.title}(${manga.id}) for a download" } }
|
||||
.collect()
|
||||
|
||||
suspend fun await(chapter: Chapter) = asFlow(chapter)
|
||||
.catch { log.warn(it) { "Failed to queue chapter ${chapter.index} of ${chapter.mangaId} for a download" } }
|
||||
.collect()
|
||||
|
||||
fun asFlow(mangaId: Long, index: Int) = chapterRepository.queueChapterDownload(mangaId, index)
|
||||
|
||||
fun asFlow(manga: Manga, index: Int) = chapterRepository.queueChapterDownload(manga.id, index)
|
||||
|
||||
fun asFlow(chapter: Chapter) = chapterRepository.queueChapterDownload(chapter.mangaId, chapter.index)
|
||||
|
||||
companion object {
|
||||
private val log = logging()
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
/*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package ca.gosyer.jui.domain.chapter.interactor
|
||||
|
||||
import ca.gosyer.jui.domain.chapter.service.ChapterRepository
|
||||
import ca.gosyer.jui.domain.manga.model.Manga
|
||||
import kotlinx.coroutines.flow.catch
|
||||
import kotlinx.coroutines.flow.singleOrNull
|
||||
import me.tatarka.inject.annotations.Inject
|
||||
import org.lighthousegames.logging.logging
|
||||
|
||||
class RefreshChapters @Inject constructor(private val chapterRepository: ChapterRepository) {
|
||||
|
||||
suspend fun await(mangaId: Long) = asFlow(mangaId)
|
||||
.catch { log.warn(it) { "Failed to refresh chapters for $mangaId" } }
|
||||
.singleOrNull()
|
||||
|
||||
suspend fun await(manga: Manga) = asFlow(manga)
|
||||
.catch { log.warn(it) { "Failed to refresh chapters for ${manga.title}(${manga.id})" } }
|
||||
.singleOrNull()
|
||||
|
||||
fun asFlow(mangaId: Long) = chapterRepository.getChapters(mangaId, true)
|
||||
|
||||
fun asFlow(manga: Manga) = chapterRepository.getChapters(manga.id, true)
|
||||
|
||||
companion object {
|
||||
private val log = logging()
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
/*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package ca.gosyer.jui.domain.chapter.interactor
|
||||
|
||||
import ca.gosyer.jui.domain.chapter.model.Chapter
|
||||
import ca.gosyer.jui.domain.chapter.service.ChapterRepository
|
||||
import ca.gosyer.jui.domain.manga.model.Manga
|
||||
import kotlinx.coroutines.flow.catch
|
||||
import kotlinx.coroutines.flow.collect
|
||||
import kotlinx.coroutines.flow.singleOrNull
|
||||
import me.tatarka.inject.annotations.Inject
|
||||
import org.lighthousegames.logging.logging
|
||||
|
||||
class StopChapterDownload @Inject constructor(private val chapterRepository: ChapterRepository) {
|
||||
|
||||
suspend fun await(mangaId: Long, index: Int) = asFlow(mangaId, index)
|
||||
.catch { log.warn(it) { "Failed to stop chapter download for $index of $mangaId" } }
|
||||
.collect()
|
||||
|
||||
suspend fun await(manga: Manga, index: Int) = asFlow(manga, index)
|
||||
.catch { log.warn(it) { "Failed to stop chapter download for $index of ${manga.title}(${manga.id})" } }
|
||||
.collect()
|
||||
|
||||
suspend fun await(chapter: Chapter) = asFlow(chapter)
|
||||
.catch { log.warn(it) { "Failed to stop chapter download for ${chapter.index} of ${chapter.mangaId}" } }
|
||||
.collect()
|
||||
|
||||
fun asFlow(mangaId: Long, index: Int) = chapterRepository.stopChapterDownload(mangaId, index)
|
||||
|
||||
fun asFlow(manga: Manga, index: Int) = chapterRepository.stopChapterDownload(manga.id, index)
|
||||
|
||||
fun asFlow(chapter: Chapter) = chapterRepository.stopChapterDownload(chapter.mangaId, chapter.index)
|
||||
|
||||
companion object {
|
||||
private val log = logging()
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,101 @@
|
||||
/*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package ca.gosyer.jui.domain.chapter.interactor
|
||||
|
||||
import ca.gosyer.jui.domain.chapter.model.Chapter
|
||||
import ca.gosyer.jui.domain.chapter.service.ChapterRepository
|
||||
import ca.gosyer.jui.domain.manga.model.Manga
|
||||
import kotlinx.coroutines.flow.catch
|
||||
import kotlinx.coroutines.flow.collect
|
||||
import me.tatarka.inject.annotations.Inject
|
||||
import org.lighthousegames.logging.logging
|
||||
|
||||
class UpdateChapterFlags @Inject constructor(private val chapterRepository: ChapterRepository) {
|
||||
|
||||
suspend fun await(
|
||||
mangaId: Long,
|
||||
index: Int,
|
||||
read: Boolean? = null,
|
||||
bookmarked: Boolean? = null,
|
||||
lastPageRead: Int? = null,
|
||||
markPreviousRead: Boolean? = null
|
||||
) = asFlow(mangaId, index, read, bookmarked, lastPageRead, markPreviousRead)
|
||||
.catch { log.warn(it) { "Failed to update chapter flags for chapter $index of $mangaId" } }
|
||||
.collect()
|
||||
|
||||
suspend fun await(
|
||||
manga: Manga,
|
||||
index: Int,
|
||||
read: Boolean? = null,
|
||||
bookmarked: Boolean? = null,
|
||||
lastPageRead: Int? = null,
|
||||
markPreviousRead: Boolean? = null
|
||||
) = asFlow(manga, index, read, bookmarked, lastPageRead, markPreviousRead)
|
||||
.catch { log.warn(it) { "Failed to update chapter flags for chapter $index of ${manga.title}(${manga.id})" } }
|
||||
.collect()
|
||||
|
||||
suspend fun await(
|
||||
chapter: Chapter,
|
||||
read: Boolean? = null,
|
||||
bookmarked: Boolean? = null,
|
||||
lastPageRead: Int? = null,
|
||||
markPreviousRead: Boolean? = null
|
||||
) = asFlow(chapter, read, bookmarked, lastPageRead, markPreviousRead)
|
||||
.catch { log.warn(it) { "Failed to update chapter flags for chapter ${chapter.index} of ${chapter.mangaId}" } }
|
||||
.collect()
|
||||
|
||||
fun asFlow(
|
||||
mangaId: Long,
|
||||
index: Int,
|
||||
read: Boolean? = null,
|
||||
bookmarked: Boolean? = null,
|
||||
lastPageRead: Int? = null,
|
||||
markPreviousRead: Boolean? = null
|
||||
) = chapterRepository.updateChapter(
|
||||
mangaId = mangaId,
|
||||
chapterIndex = index,
|
||||
read = read,
|
||||
bookmarked = bookmarked,
|
||||
lastPageRead = lastPageRead,
|
||||
markPreviousRead = markPreviousRead
|
||||
)
|
||||
|
||||
fun asFlow(
|
||||
manga: Manga,
|
||||
index: Int,
|
||||
read: Boolean? = null,
|
||||
bookmarked: Boolean? = null,
|
||||
lastPageRead: Int? = null,
|
||||
markPreviousRead: Boolean? = null
|
||||
) = chapterRepository.updateChapter(
|
||||
mangaId = manga.id,
|
||||
chapterIndex = index,
|
||||
read = read,
|
||||
bookmarked = bookmarked,
|
||||
lastPageRead = lastPageRead,
|
||||
markPreviousRead = markPreviousRead
|
||||
)
|
||||
|
||||
fun asFlow(
|
||||
chapter: Chapter,
|
||||
read: Boolean? = null,
|
||||
bookmarked: Boolean? = null,
|
||||
lastPageRead: Int? = null,
|
||||
markPreviousRead: Boolean? = null
|
||||
) = chapterRepository.updateChapter(
|
||||
mangaId = chapter.mangaId,
|
||||
chapterIndex = chapter.index,
|
||||
read = read,
|
||||
bookmarked = bookmarked,
|
||||
lastPageRead = lastPageRead,
|
||||
markPreviousRead = markPreviousRead
|
||||
)
|
||||
|
||||
companion object {
|
||||
private val log = logging()
|
||||
}
|
||||
}
|
||||
@@ -31,7 +31,8 @@ import androidx.compose.runtime.getValue
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.unit.dp
|
||||
import ca.gosyer.jui.data.chapter.ChapterRepositoryImpl
|
||||
import ca.gosyer.jui.domain.chapter.interactor.DeleteChapterDownload
|
||||
import ca.gosyer.jui.domain.chapter.interactor.StopChapterDownload
|
||||
import ca.gosyer.jui.domain.chapter.model.Chapter
|
||||
import ca.gosyer.jui.domain.download.model.DownloadChapter
|
||||
import ca.gosyer.jui.domain.download.model.DownloadState
|
||||
@@ -40,11 +41,8 @@ import ca.gosyer.jui.i18n.MR
|
||||
import ca.gosyer.jui.uicore.components.DropdownIconButton
|
||||
import ca.gosyer.jui.uicore.components.DropdownMenuItem
|
||||
import ca.gosyer.jui.uicore.resources.stringResource
|
||||
import io.ktor.client.statement.HttpResponse
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
import kotlinx.coroutines.flow.asStateFlow
|
||||
import kotlinx.coroutines.flow.onEach
|
||||
|
||||
data class ChapterDownloadItem(
|
||||
val manga: Manga?,
|
||||
@@ -74,18 +72,14 @@ data class ChapterDownloadItem(
|
||||
_downloadChapterFlow.value = downloadingChapter
|
||||
}
|
||||
|
||||
fun deleteDownload(chapterHandler: ChapterRepositoryImpl): Flow<HttpResponse> {
|
||||
return chapterHandler.deleteChapterDownload(chapter.mangaId, chapter.index)
|
||||
.onEach {
|
||||
_downloadState.value = ChapterDownloadState.NotDownloaded
|
||||
}
|
||||
suspend fun deleteDownload(deleteChapterDownload: DeleteChapterDownload) {
|
||||
deleteChapterDownload.await(chapter)
|
||||
_downloadState.value = ChapterDownloadState.NotDownloaded
|
||||
}
|
||||
|
||||
fun stopDownloading(chapterHandler: ChapterRepositoryImpl): Flow<HttpResponse> {
|
||||
return chapterHandler.stopChapterDownload(chapter.mangaId, chapter.index)
|
||||
.onEach {
|
||||
_downloadState.value = ChapterDownloadState.NotDownloaded
|
||||
}
|
||||
suspend fun stopDownloading(stopChapterDownload: StopChapterDownload) {
|
||||
stopChapterDownload.await(chapter)
|
||||
_downloadState.value = ChapterDownloadState.NotDownloaded
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -6,8 +6,9 @@
|
||||
|
||||
package ca.gosyer.jui.ui.downloads
|
||||
|
||||
import ca.gosyer.jui.data.chapter.ChapterRepositoryImpl
|
||||
import ca.gosyer.jui.domain.base.WebsocketService.Actions
|
||||
import ca.gosyer.jui.domain.chapter.interactor.QueueChapterDownload
|
||||
import ca.gosyer.jui.domain.chapter.interactor.StopChapterDownload
|
||||
import ca.gosyer.jui.domain.chapter.model.Chapter
|
||||
import ca.gosyer.jui.domain.download.interactor.ClearDownloadQueue
|
||||
import ca.gosyer.jui.domain.download.interactor.StartDownloading
|
||||
@@ -19,10 +20,6 @@ import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.MainScope
|
||||
import kotlinx.coroutines.cancel
|
||||
import kotlinx.coroutines.flow.asStateFlow
|
||||
import kotlinx.coroutines.flow.catch
|
||||
import kotlinx.coroutines.flow.collect
|
||||
import kotlinx.coroutines.flow.launchIn
|
||||
import kotlinx.coroutines.flow.onEach
|
||||
import kotlinx.coroutines.launch
|
||||
import me.tatarka.inject.annotations.Inject
|
||||
import org.lighthousegames.logging.logging
|
||||
@@ -32,7 +29,8 @@ class DownloadsScreenViewModel @Inject constructor(
|
||||
private val startDownloading: StartDownloading,
|
||||
private val stopDownloading: StopDownloading,
|
||||
private val clearDownloadQueue: ClearDownloadQueue,
|
||||
private val chapterHandler: ChapterRepositoryImpl,
|
||||
private val queueChapterDownload: QueueChapterDownload,
|
||||
private val stopChapterDownload: StopChapterDownload,
|
||||
private val contextWrapper: ContextWrapper,
|
||||
standalone: Boolean
|
||||
) : ViewModel(contextWrapper) {
|
||||
@@ -60,26 +58,14 @@ class DownloadsScreenViewModel @Inject constructor(
|
||||
}
|
||||
|
||||
fun stopDownload(chapter: Chapter) {
|
||||
chapterHandler.stopChapterDownload(chapter.mangaId, chapter.index)
|
||||
.catch {
|
||||
log.warn(it) { "Error stop chapter download" }
|
||||
}
|
||||
.launchIn(scope)
|
||||
scope.launch { stopChapterDownload.await(chapter) }
|
||||
}
|
||||
|
||||
fun moveToBottom(chapter: Chapter) {
|
||||
chapterHandler.stopChapterDownload(chapter.mangaId, chapter.index)
|
||||
.onEach {
|
||||
chapterHandler.queueChapterDownload(chapter.mangaId, chapter.index)
|
||||
.catch {
|
||||
log.warn(it) { "Error adding download" }
|
||||
}
|
||||
.collect()
|
||||
}
|
||||
.catch {
|
||||
log.warn(it) { "Error stop chapter download" }
|
||||
}
|
||||
.launchIn(scope)
|
||||
scope.launch {
|
||||
stopChapterDownload.await(chapter)
|
||||
queueChapterDownload.await(chapter)
|
||||
}
|
||||
}
|
||||
|
||||
fun restartDownloader() = startDownloadService(contextWrapper, downloadService, Actions.RESTART)
|
||||
|
||||
@@ -8,12 +8,17 @@ package ca.gosyer.jui.ui.manga
|
||||
|
||||
import ca.gosyer.jui.core.lang.withIOContext
|
||||
import ca.gosyer.jui.data.base.DateHandler
|
||||
import ca.gosyer.jui.data.chapter.ChapterRepositoryImpl
|
||||
import ca.gosyer.jui.domain.category.interactor.AddMangaToCategory
|
||||
import ca.gosyer.jui.domain.category.interactor.GetCategories
|
||||
import ca.gosyer.jui.domain.category.interactor.GetMangaCategories
|
||||
import ca.gosyer.jui.domain.category.interactor.RemoveMangaFromCategory
|
||||
import ca.gosyer.jui.domain.category.model.Category
|
||||
import ca.gosyer.jui.domain.chapter.interactor.DeleteChapterDownload
|
||||
import ca.gosyer.jui.domain.chapter.interactor.GetChapters
|
||||
import ca.gosyer.jui.domain.chapter.interactor.QueueChapterDownload
|
||||
import ca.gosyer.jui.domain.chapter.interactor.RefreshChapters
|
||||
import ca.gosyer.jui.domain.chapter.interactor.StopChapterDownload
|
||||
import ca.gosyer.jui.domain.chapter.interactor.UpdateChapterFlags
|
||||
import ca.gosyer.jui.domain.chapter.model.Chapter
|
||||
import ca.gosyer.jui.domain.download.service.DownloadService
|
||||
import ca.gosyer.jui.domain.library.interactor.AddMangaToLibrary
|
||||
@@ -31,11 +36,9 @@ import kotlinx.coroutines.flow.MutableStateFlow
|
||||
import kotlinx.coroutines.flow.SharingStarted
|
||||
import kotlinx.coroutines.flow.asStateFlow
|
||||
import kotlinx.coroutines.flow.catch
|
||||
import kotlinx.coroutines.flow.collect
|
||||
import kotlinx.coroutines.flow.launchIn
|
||||
import kotlinx.coroutines.flow.map
|
||||
import kotlinx.coroutines.flow.mapLatest
|
||||
import kotlinx.coroutines.flow.single
|
||||
import kotlinx.coroutines.flow.stateIn
|
||||
import kotlinx.coroutines.launch
|
||||
import me.tatarka.inject.annotations.Inject
|
||||
@@ -45,7 +48,12 @@ class MangaScreenViewModel @Inject constructor(
|
||||
private val dateHandler: DateHandler,
|
||||
private val getManga: GetManga,
|
||||
private val refreshManga: RefreshManga,
|
||||
private val chapterHandler: ChapterRepositoryImpl,
|
||||
private val getChapters: GetChapters,
|
||||
private val refreshChapters: RefreshChapters,
|
||||
private val updateChapterFlags: UpdateChapterFlags,
|
||||
private val queueChapterDownload: QueueChapterDownload,
|
||||
private val stopChapterDownload: StopChapterDownload,
|
||||
private val deleteChapterDownload: DeleteChapterDownload,
|
||||
private val getCategories: GetCategories,
|
||||
private val getMangaCategories: GetMangaCategories,
|
||||
private val addMangaToCategory: AddMangaToCategory,
|
||||
@@ -138,23 +146,31 @@ class MangaScreenViewModel @Inject constructor(
|
||||
}
|
||||
if (manga != null) {
|
||||
_manga.value = manga
|
||||
} else {
|
||||
// TODO: 2022-07-01 Error toast
|
||||
}
|
||||
|
||||
val mangaCategories = getMangaCategories.await(mangaId)
|
||||
if (mangaCategories != null) {
|
||||
_mangaCategories.value = mangaCategories
|
||||
} else {
|
||||
// TODO: 2022-07-01 Error toast
|
||||
}
|
||||
getMangaCategories.await(mangaId)
|
||||
?.let {
|
||||
_mangaCategories.value = it
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private suspend fun refreshChaptersAsync(mangaId: Long, refresh: Boolean = false) = withIOContext {
|
||||
async {
|
||||
_chapters.value = chapterHandler.getChapters(mangaId, refresh)
|
||||
.catch {
|
||||
log.warn(it) { "Error getting chapters" }
|
||||
emit(emptyList())
|
||||
}
|
||||
.single()
|
||||
.toDownloadChapters()
|
||||
val chapters = if (refresh) {
|
||||
refreshChapters.await(mangaId)
|
||||
} else {
|
||||
getChapters.await(mangaId)
|
||||
}
|
||||
if (chapters != null) {
|
||||
_chapters.value = chapters.toDownloadChapters()
|
||||
} else {
|
||||
// TODO: 2022-07-01 Error toast
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -193,48 +209,24 @@ class MangaScreenViewModel @Inject constructor(
|
||||
}
|
||||
}
|
||||
|
||||
private fun findChapter(index: Int) = chapters.value.find { it.chapter.index == index }?.chapter
|
||||
|
||||
fun toggleRead(index: Int) {
|
||||
val chapter = findChapter(index) ?: return
|
||||
scope.launch {
|
||||
manga.value?.let { manga ->
|
||||
chapterHandler.updateChapter(
|
||||
manga.id,
|
||||
index,
|
||||
read = !_chapters.value.first { it.chapter.index == index }.chapter.read
|
||||
)
|
||||
.catch {
|
||||
log.warn(it) { "Error toggling read" }
|
||||
}
|
||||
.collect()
|
||||
_chapters.value = chapterHandler.getChapters(manga.id)
|
||||
.catch {
|
||||
log.warn(it) { "Error getting new chapters after toggling read" }
|
||||
emit(emptyList())
|
||||
}
|
||||
.single()
|
||||
.toDownloadChapters()
|
||||
updateChapterFlags.await(manga, index, read = chapter.read.not())
|
||||
refreshChaptersAsync(manga.id).await()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun toggleBookmarked(index: Int) {
|
||||
val chapter = findChapter(index) ?: return
|
||||
scope.launch {
|
||||
manga.value?.let { manga ->
|
||||
chapterHandler.updateChapter(
|
||||
manga.id,
|
||||
index,
|
||||
bookmarked = !_chapters.value.first { it.chapter.index == index }.chapter.bookmarked
|
||||
)
|
||||
.catch {
|
||||
log.warn(it) { "Error toggling bookmarked" }
|
||||
}
|
||||
.collect()
|
||||
_chapters.value = chapterHandler.getChapters(manga.id)
|
||||
.catch {
|
||||
log.warn(it) { "Error getting new chapters after toggling bookmarked" }
|
||||
emit(emptyList())
|
||||
}
|
||||
.single()
|
||||
.toDownloadChapters()
|
||||
updateChapterFlags.await(manga, index, bookmarked = chapter.bookmarked.not())
|
||||
refreshChaptersAsync(manga.id).await()
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -242,48 +234,30 @@ class MangaScreenViewModel @Inject constructor(
|
||||
fun markPreviousRead(index: Int) {
|
||||
scope.launch {
|
||||
manga.value?.let { manga ->
|
||||
chapterHandler.updateChapter(manga.id, index, markPreviousRead = true)
|
||||
.catch {
|
||||
log.warn(it) { "Error marking previous as read" }
|
||||
}
|
||||
.collect()
|
||||
_chapters.value = chapterHandler.getChapters(manga.id)
|
||||
.catch {
|
||||
log.warn(it) { "Error getting new chapters after marking previous as read" }
|
||||
emit(emptyList())
|
||||
}
|
||||
.single()
|
||||
.toDownloadChapters()
|
||||
updateChapterFlags.await(manga, index, markPreviousRead = true)
|
||||
refreshChaptersAsync(manga.id).await()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun downloadChapter(index: Int) {
|
||||
manga.value?.let { manga ->
|
||||
chapterHandler.queueChapterDownload(manga.id, index)
|
||||
.catch {
|
||||
log.warn(it) { "Error downloading chapter" }
|
||||
}
|
||||
.launchIn(scope)
|
||||
scope.launch { queueChapterDownload.await(manga, index) }
|
||||
}
|
||||
}
|
||||
|
||||
fun deleteDownload(index: Int) {
|
||||
chapters.value.find { it.chapter.index == index }
|
||||
?.deleteDownload(chapterHandler)
|
||||
?.catch {
|
||||
log.warn(it) { "Error deleting download" }
|
||||
}
|
||||
?.launchIn(scope)
|
||||
scope.launch {
|
||||
chapters.value.find { it.chapter.index == index }
|
||||
?.deleteDownload(deleteChapterDownload)
|
||||
}
|
||||
}
|
||||
|
||||
fun stopDownloadingChapter(index: Int) {
|
||||
chapters.value.find { it.chapter.index == index }
|
||||
?.stopDownloading(chapterHandler)
|
||||
?.catch {
|
||||
log.warn(it) { "Error stopping download" }
|
||||
}
|
||||
?.launchIn(scope)
|
||||
scope.launch {
|
||||
chapters.value.find { it.chapter.index == index }
|
||||
?.stopDownloading(stopChapterDownload)
|
||||
}
|
||||
}
|
||||
|
||||
private fun List<Chapter>.toDownloadChapters() = map {
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
|
||||
package ca.gosyer.jui.ui.reader
|
||||
|
||||
import ca.gosyer.jui.data.chapter.ChapterRepositoryImpl
|
||||
import ca.gosyer.jui.domain.chapter.interactor.GetChapterPage
|
||||
import ca.gosyer.jui.domain.reader.service.ReaderPreferences
|
||||
import ca.gosyer.jui.ui.reader.loader.TachideskPageLoader
|
||||
import ca.gosyer.jui.ui.reader.model.ReaderChapter
|
||||
@@ -20,7 +20,7 @@ import org.lighthousegames.logging.logging
|
||||
|
||||
class ChapterLoader(
|
||||
private val readerPreferences: ReaderPreferences,
|
||||
private val chapterHandler: ChapterRepositoryImpl
|
||||
private val getChapterPage: GetChapterPage
|
||||
) {
|
||||
fun loadChapter(chapter: ReaderChapter): StateFlow<List<ReaderPage>> {
|
||||
if (chapterIsReady(chapter)) {
|
||||
@@ -29,7 +29,7 @@ class ChapterLoader(
|
||||
chapter.state = ReaderChapter.State.Loading
|
||||
log.debug { "Loading pages for ${chapter.chapter.name}" }
|
||||
|
||||
val loader = TachideskPageLoader(chapter, readerPreferences, chapterHandler)
|
||||
val loader = TachideskPageLoader(chapter, readerPreferences, getChapterPage)
|
||||
|
||||
val pages = loader.getPages()
|
||||
|
||||
|
||||
@@ -8,7 +8,10 @@ package ca.gosyer.jui.ui.reader
|
||||
|
||||
import ca.gosyer.jui.core.lang.launchDefault
|
||||
import ca.gosyer.jui.core.prefs.getAsFlow
|
||||
import ca.gosyer.jui.data.chapter.ChapterRepositoryImpl
|
||||
import ca.gosyer.jui.domain.chapter.interactor.GetChapter
|
||||
import ca.gosyer.jui.domain.chapter.interactor.GetChapterPage
|
||||
import ca.gosyer.jui.domain.chapter.interactor.GetChapters
|
||||
import ca.gosyer.jui.domain.chapter.interactor.UpdateChapterFlags
|
||||
import ca.gosyer.jui.domain.chapter.interactor.UpdateChapterMeta
|
||||
import ca.gosyer.jui.domain.chapter.model.Chapter
|
||||
import ca.gosyer.jui.domain.manga.interactor.GetManga
|
||||
@@ -51,7 +54,10 @@ import org.lighthousegames.logging.logging
|
||||
class ReaderMenuViewModel @Inject constructor(
|
||||
private val readerPreferences: ReaderPreferences,
|
||||
private val getManga: GetManga,
|
||||
private val chapterHandler: ChapterRepositoryImpl,
|
||||
private val getChapters: GetChapters,
|
||||
private val getChapter: GetChapter,
|
||||
private val getChapterPage: GetChapterPage,
|
||||
private val updateChapterFlags: UpdateChapterFlags,
|
||||
private val updateMangaMeta: UpdateMangaMeta,
|
||||
private val updateChapterMeta: UpdateChapterMeta,
|
||||
contextWrapper: ContextWrapper,
|
||||
@@ -101,7 +107,7 @@ class ReaderMenuViewModel @Inject constructor(
|
||||
|
||||
val readerModeSettings = ReaderModeWatch(readerPreferences, scope, readerMode)
|
||||
|
||||
private val loader = ChapterLoader(readerPreferences, chapterHandler)
|
||||
private val loader = ChapterLoader(readerPreferences, getChapterPage)
|
||||
|
||||
init {
|
||||
init()
|
||||
@@ -217,7 +223,7 @@ class ReaderMenuViewModel @Inject constructor(
|
||||
private suspend fun initChapters(mangaId: Long, chapterIndex: Int) {
|
||||
resetValues()
|
||||
val chapter = ReaderChapter(
|
||||
chapterHandler.getChapter(mangaId, chapterIndex)
|
||||
getChapter.asFlow(mangaId, chapterIndex)
|
||||
.catch {
|
||||
_state.value = ReaderChapter.State.Error(it)
|
||||
log.warn(it) { "Error getting chapter" }
|
||||
@@ -227,9 +233,10 @@ class ReaderMenuViewModel @Inject constructor(
|
||||
val pages = loader.loadChapter(chapter)
|
||||
viewerChapters.currChapter.value = chapter
|
||||
scope.launchDefault {
|
||||
val chapters = chapterHandler.getChapters(mangaId)
|
||||
val chapters = getChapters.asFlow(mangaId)
|
||||
.catch {
|
||||
log.warn(it) { "Error getting chapter list" }
|
||||
// TODO: 2022-07-01 Error toast
|
||||
emit(emptyList())
|
||||
}
|
||||
.single()
|
||||
@@ -273,29 +280,21 @@ class ReaderMenuViewModel @Inject constructor(
|
||||
.onEach { index ->
|
||||
pages.value.getOrNull(_currentPage.value - 1)?.let { chapter.pageLoader?.loadPage(it) }
|
||||
if (index == pages.value.size) {
|
||||
markChapterRead(mangaId, chapter)
|
||||
markChapterRead(chapter)
|
||||
}
|
||||
}
|
||||
.launchIn(chapter.scope)
|
||||
}
|
||||
|
||||
private fun markChapterRead(mangaId: Long, chapter: ReaderChapter) {
|
||||
chapterHandler.updateChapter(mangaId, chapter.chapter.index, true)
|
||||
.catch {
|
||||
log.warn(it) { "Error marking chapter read" }
|
||||
}
|
||||
.launchIn(scope)
|
||||
private fun markChapterRead(chapter: ReaderChapter) {
|
||||
scope.launch { updateChapterFlags.await(chapter.chapter, read = true) }
|
||||
}
|
||||
|
||||
@OptIn(DelicateCoroutinesApi::class)
|
||||
fun sendProgress(chapter: Chapter? = this.chapter.value?.chapter, lastPageRead: Int = currentPage.value) {
|
||||
chapter ?: return
|
||||
if (chapter.read) return
|
||||
chapterHandler.updateChapter(chapter.mangaId, chapter.index, lastPageRead = lastPageRead)
|
||||
.catch {
|
||||
log.warn(it) { "Error sending progress" }
|
||||
}
|
||||
.launchIn(GlobalScope)
|
||||
GlobalScope.launch { updateChapterFlags.await(chapter, lastPageRead = lastPageRead) }
|
||||
}
|
||||
|
||||
fun updateLastPageReadOffset(offset: Int) {
|
||||
|
||||
@@ -8,7 +8,7 @@ package ca.gosyer.jui.ui.reader.loader
|
||||
|
||||
import ca.gosyer.jui.core.lang.IO
|
||||
import ca.gosyer.jui.core.lang.throwIfCancellation
|
||||
import ca.gosyer.jui.data.chapter.ChapterRepositoryImpl
|
||||
import ca.gosyer.jui.domain.chapter.interactor.GetChapterPage
|
||||
import ca.gosyer.jui.domain.reader.service.ReaderPreferences
|
||||
import ca.gosyer.jui.ui.reader.model.ReaderChapter
|
||||
import ca.gosyer.jui.ui.reader.model.ReaderPage
|
||||
@@ -33,7 +33,7 @@ import org.lighthousegames.logging.logging
|
||||
class TachideskPageLoader(
|
||||
val chapter: ReaderChapter,
|
||||
readerPreferences: ReaderPreferences,
|
||||
chapterHandler: ChapterRepositoryImpl
|
||||
getChapterPage: GetChapterPage
|
||||
) : PageLoader() {
|
||||
val scope = CoroutineScope(SupervisorJob() + Dispatchers.Default)
|
||||
|
||||
@@ -63,8 +63,7 @@ class TachideskPageLoader(
|
||||
val page = priorityPage.page
|
||||
log.debug { "Loading page ${page.index}" }
|
||||
if (page.status.value == ReaderPage.Status.QUEUE) {
|
||||
chapterHandler
|
||||
.getPage(chapter.chapter.mangaId, chapter.chapter.index, page.index) {
|
||||
getChapterPage.asFlow(chapter.chapter, page.index) {
|
||||
onDownload { bytesSentTotal, contentLength ->
|
||||
page.progress.value = (bytesSentTotal.toFloat() / contentLength).coerceAtMost(1.0F)
|
||||
}
|
||||
@@ -78,7 +77,7 @@ class TachideskPageLoader(
|
||||
page.bitmap.value = null
|
||||
page.status.value = ReaderPage.Status.ERROR
|
||||
page.error.value = it.message
|
||||
log.warn(it) { "Error getting image" }
|
||||
log.warn(it) { "Failed to get page ${page.index} for chapter ${chapter.chapter.index} for ${chapter.chapter.mangaId}" }
|
||||
}
|
||||
.flowOn(Dispatchers.IO)
|
||||
.collect()
|
||||
|
||||
@@ -10,7 +10,9 @@ import androidx.compose.runtime.mutableStateListOf
|
||||
import androidx.compose.runtime.mutableStateMapOf
|
||||
import androidx.compose.runtime.snapshotFlow
|
||||
import androidx.compose.runtime.snapshots.SnapshotStateList
|
||||
import ca.gosyer.jui.data.chapter.ChapterRepositoryImpl
|
||||
import ca.gosyer.jui.domain.chapter.interactor.DeleteChapterDownload
|
||||
import ca.gosyer.jui.domain.chapter.interactor.QueueChapterDownload
|
||||
import ca.gosyer.jui.domain.chapter.interactor.StopChapterDownload
|
||||
import ca.gosyer.jui.domain.chapter.model.Chapter
|
||||
import ca.gosyer.jui.domain.download.service.DownloadService
|
||||
import ca.gosyer.jui.domain.updates.interactor.GetRecentUpdates
|
||||
@@ -37,7 +39,9 @@ import me.tatarka.inject.annotations.Inject
|
||||
import org.lighthousegames.logging.logging
|
||||
|
||||
class UpdatesScreenViewModel @Inject constructor(
|
||||
private val chapterHandler: ChapterRepositoryImpl,
|
||||
private val queueChapterDownload: QueueChapterDownload,
|
||||
private val stopChapterDownload: StopChapterDownload,
|
||||
private val deleteChapterDownload: DeleteChapterDownload,
|
||||
private val getRecentUpdates: GetRecentUpdates,
|
||||
contextWrapper: ContextWrapper
|
||||
) : ViewModel(contextWrapper) {
|
||||
@@ -117,41 +121,33 @@ class UpdatesScreenViewModel @Inject constructor(
|
||||
}
|
||||
|
||||
fun downloadChapter(chapter: Chapter) {
|
||||
chapterHandler.queueChapterDownload(chapter.mangaId, chapter.index)
|
||||
.catch {
|
||||
log.warn(it) { "Error queueing chapter" }
|
||||
}
|
||||
.launchIn(scope)
|
||||
scope.launch { queueChapterDownload.await(chapter) }
|
||||
}
|
||||
|
||||
fun deleteDownloadedChapter(chapter: Chapter) {
|
||||
_updates
|
||||
.firstNotNullOfOrNull { (_, chapters) ->
|
||||
chapters.find {
|
||||
it.chapter.mangaId == chapter.mangaId &&
|
||||
it.chapter.index == chapter.index
|
||||
scope.launch {
|
||||
_updates
|
||||
.firstNotNullOfOrNull { (_, chapters) ->
|
||||
chapters.find {
|
||||
it.chapter.mangaId == chapter.mangaId &&
|
||||
it.chapter.index == chapter.index
|
||||
}
|
||||
}
|
||||
}
|
||||
?.deleteDownload(chapterHandler)
|
||||
?.catch {
|
||||
log.warn(it) { "Error deleting download" }
|
||||
}
|
||||
?.launchIn(scope)
|
||||
?.deleteDownload(deleteChapterDownload)
|
||||
}
|
||||
}
|
||||
|
||||
fun stopDownloadingChapter(chapter: Chapter) {
|
||||
_updates
|
||||
.firstNotNullOfOrNull { (_, chapters) ->
|
||||
chapters.find {
|
||||
it.chapter.mangaId == chapter.mangaId &&
|
||||
it.chapter.index == chapter.index
|
||||
scope.launch {
|
||||
_updates
|
||||
.firstNotNullOfOrNull { (_, chapters) ->
|
||||
chapters.find {
|
||||
it.chapter.mangaId == chapter.mangaId &&
|
||||
it.chapter.index == chapter.index
|
||||
}
|
||||
}
|
||||
}
|
||||
?.stopDownloading(chapterHandler)
|
||||
?.catch {
|
||||
log.warn(it) { "Error stopping download" }
|
||||
}
|
||||
?.launchIn(scope)
|
||||
?.stopDownloading(stopChapterDownload)
|
||||
}
|
||||
}
|
||||
|
||||
private companion object {
|
||||
|
||||
Reference in New Issue
Block a user