diff --git a/domain/src/commonMain/kotlin/ca/gosyer/jui/domain/ServerListeners.kt b/domain/src/commonMain/kotlin/ca/gosyer/jui/domain/ServerListeners.kt index dec1636b..04c78146 100644 --- a/domain/src/commonMain/kotlin/ca/gosyer/jui/domain/ServerListeners.kt +++ b/domain/src/commonMain/kotlin/ca/gosyer/jui/domain/ServerListeners.kt @@ -15,7 +15,6 @@ import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.MutableSharedFlow import kotlinx.coroutines.flow.asSharedFlow import kotlinx.coroutines.flow.buffer -import kotlinx.coroutines.flow.combine import kotlinx.coroutines.flow.filter import kotlinx.coroutines.flow.flatMapLatest import kotlinx.coroutines.flow.onStart @@ -34,16 +33,6 @@ class ServerListeners { ) val mangaListener = _mangaListener.asSharedFlow() - private val _chapterIdsListener = MutableSharedFlow>( - extraBufferCapacity = Channel.UNLIMITED, - ) - val chapterIdsListener = _chapterIdsListener.asSharedFlow() - - private val _mangaChapterIdsListener = MutableSharedFlow>( - extraBufferCapacity = Channel.UNLIMITED, - ) - val mangaChapterIdsListener = _mangaChapterIdsListener.asSharedFlow() - private val categoryMangaListener = MutableSharedFlow( extraBufferCapacity = Channel.UNLIMITED, ) @@ -65,9 +54,23 @@ class ServerListeners { .buffer(capacity = 1, onBufferOverflow = BufferOverflow.DROP_OLDEST) .flatMapLatest { flow } - fun updateManga(vararg ids: Long) { + fun updateManga(ids: List) { + val ids = ids.filter { id -> id >= 0 } + if (ids.isEmpty()) { + return + } scope.launch { - _mangaListener.emit(ids.toList()) + _mangaListener.emit(ids) + } + } + + fun updateManga(vararg ids: Long) { + val ids = ids.filter { id -> id >= 0 } + if (ids.isEmpty()) { + return + } + scope.launch { + _mangaListener.emit(ids) } } @@ -88,36 +91,6 @@ class ServerListeners { } } - fun combineChapters( - flow: Flow, - chapterIdPredate: (suspend (List) -> Boolean)? = null, - mangaIdPredate: (suspend (List) -> Boolean)? = null, - ): Flow { - val idsListener = _chapterIdsListener - .filter { chapterIdPredate?.invoke(it) ?: false } - .startWith(Unit) - .combine( - _mangaChapterIdsListener.filter { mangaIdPredate?.invoke(it) ?: false } - .startWith(Unit), - ) { _, _ -> } - - return idsListener - .buffer(capacity = 1, onBufferOverflow = BufferOverflow.DROP_OLDEST) - .flatMapLatest { flow } - } - - fun updateChapters(chapterIds: List) { - scope.launch { - _chapterIdsListener.emit(chapterIds) - } - } - - fun updateChapters(vararg chapterIds: Long) { - scope.launch { - _chapterIdsListener.emit(chapterIds.toList()) - } - } - companion object { private val log = logging() } diff --git a/domain/src/commonMain/kotlin/ca/gosyer/jui/domain/chapter/interactor/DeleteChapterDownload.kt b/domain/src/commonMain/kotlin/ca/gosyer/jui/domain/chapter/interactor/DeleteChapterDownload.kt index e7d123c4..9be69e20 100644 --- a/domain/src/commonMain/kotlin/ca/gosyer/jui/domain/chapter/interactor/DeleteChapterDownload.kt +++ b/domain/src/commonMain/kotlin/ca/gosyer/jui/domain/chapter/interactor/DeleteChapterDownload.kt @@ -23,8 +23,9 @@ class DeleteChapterDownload( ) { suspend fun await( chapterId: Long, + mangaId: Long?, onError: suspend (Throwable) -> Unit = {}, - ) = asFlow(chapterId) + ) = asFlow(chapterId, mangaId) .catch { onError(it) log.warn(it) { "Failed to delete chapter download for $chapterId" } @@ -44,8 +45,9 @@ class DeleteChapterDownload( suspend fun await( chapterIds: List, + mangaIds: List?, onError: suspend (Throwable) -> Unit = {}, - ) = asFlow(chapterIds) + ) = asFlow(chapterIds, mangaIds) .catch { onError(it) log.warn(it) { "Failed to delete chapter download for $chapterIds" } @@ -63,23 +65,23 @@ class DeleteChapterDownload( } .collect() - fun asFlow(chapterId: Long) = + fun asFlow(chapterId: Long, mangaId: Long?) = chapterRepository.deleteDownloadedChapter(chapterId) - .onEach { serverListeners.updateChapters(chapterId) } + .onEach { serverListeners.updateManga(mangaId ?: -1) } @JvmName("asFlowChapter") fun asFlow(chapter: Chapter) = chapterRepository.deleteDownloadedChapter(chapter.id) - .onEach { serverListeners.updateChapters(chapter.id) } + .onEach { serverListeners.updateManga(chapter.mangaId) } - fun asFlow(chapterIds: List) = + fun asFlow(chapterIds: List, mangaIds: List?) = chapterRepository.deleteDownloadedChapters(chapterIds) - .onEach { serverListeners.updateChapters(chapterIds) } + .onEach { serverListeners.updateManga(mangaIds.orEmpty()) } @JvmName("asFlowChapters") fun asFlow(chapter: List) = chapterRepository.deleteDownloadedChapters(chapter.map { it.id }) - .onEach { serverListeners.updateChapters(chapter.map { it.id }) } + .onEach { serverListeners.updateManga(chapter.map { it.mangaId }) } companion object { private val log = logging() diff --git a/domain/src/commonMain/kotlin/ca/gosyer/jui/domain/chapter/interactor/GetChapter.kt b/domain/src/commonMain/kotlin/ca/gosyer/jui/domain/chapter/interactor/GetChapter.kt index d1988980..754bffd5 100644 --- a/domain/src/commonMain/kotlin/ca/gosyer/jui/domain/chapter/interactor/GetChapter.kt +++ b/domain/src/commonMain/kotlin/ca/gosyer/jui/domain/chapter/interactor/GetChapter.kt @@ -22,8 +22,9 @@ class GetChapter( ) { suspend fun await( chapterId: Long, + mangaId: Long?, onError: suspend (Throwable) -> Unit = {}, - ) = asFlow(chapterId) + ) = asFlow(chapterId, mangaId) .take(1) .catch { onError(it) @@ -42,16 +43,16 @@ class GetChapter( } .singleOrNull() - fun asFlow(chapterId: Long) = - serverListeners.combineChapters( + fun asFlow(chapterId: Long, mangaId: Long?) = + serverListeners.combineMangaUpdates( chapterRepository.getChapter(chapterId), - chapterIdPredate = { ids -> chapterId in ids }, + predate = { ids -> mangaId in ids }, ) fun asFlow(chapter: Chapter) = - serverListeners.combineChapters( + serverListeners.combineMangaUpdates( chapterRepository.getChapter(chapter.id), - chapterIdPredate = { ids -> chapter.id in ids }, + predate = { ids -> chapter.mangaId in ids }, ) companion object { diff --git a/domain/src/commonMain/kotlin/ca/gosyer/jui/domain/chapter/interactor/GetChapters.kt b/domain/src/commonMain/kotlin/ca/gosyer/jui/domain/chapter/interactor/GetChapters.kt index 97645e52..2dfda23d 100644 --- a/domain/src/commonMain/kotlin/ca/gosyer/jui/domain/chapter/interactor/GetChapters.kt +++ b/domain/src/commonMain/kotlin/ca/gosyer/jui/domain/chapter/interactor/GetChapters.kt @@ -43,15 +43,15 @@ class GetChapters( .singleOrNull() fun asFlow(mangaId: Long) = - serverListeners.combineChapters( + serverListeners.combineMangaUpdates( chapterRepository.getChapters(mangaId), - chapterIdPredate = { ids -> false }, // todo + predate = { ids -> mangaId in ids }, ) fun asFlow(manga: Manga) = - serverListeners.combineChapters( + serverListeners.combineMangaUpdates( chapterRepository.getChapters(manga.id), - chapterIdPredate = { ids -> false }, // todo + predate = { ids -> manga.id in ids }, ) companion object { diff --git a/domain/src/commonMain/kotlin/ca/gosyer/jui/domain/chapter/interactor/RefreshChapters.kt b/domain/src/commonMain/kotlin/ca/gosyer/jui/domain/chapter/interactor/RefreshChapters.kt index d68868cc..7137bba1 100644 --- a/domain/src/commonMain/kotlin/ca/gosyer/jui/domain/chapter/interactor/RefreshChapters.kt +++ b/domain/src/commonMain/kotlin/ca/gosyer/jui/domain/chapter/interactor/RefreshChapters.kt @@ -40,13 +40,13 @@ class RefreshChapters( } .singleOrNull() - fun asFlow(mangaId: Long) = + fun asFlow(mangaId: Long, ) = chapterRepository.fetchChapters(mangaId) - .onEach { serverListeners.updateChapters(mangaId) } + .onEach { serverListeners.updateManga(mangaId) } fun asFlow(manga: Manga) = chapterRepository.fetchChapters(manga.id) - .onEach { serverListeners.updateChapters(manga.id) } + .onEach { serverListeners.updateManga(manga.id) } companion object { private val log = logging() diff --git a/domain/src/commonMain/kotlin/ca/gosyer/jui/domain/chapter/interactor/UpdateChapter.kt b/domain/src/commonMain/kotlin/ca/gosyer/jui/domain/chapter/interactor/UpdateChapter.kt index dc30e184..a2b49eb4 100644 --- a/domain/src/commonMain/kotlin/ca/gosyer/jui/domain/chapter/interactor/UpdateChapter.kt +++ b/domain/src/commonMain/kotlin/ca/gosyer/jui/domain/chapter/interactor/UpdateChapter.kt @@ -23,11 +23,12 @@ class UpdateChapter( ) { suspend fun await( chapterId: Long, + mangaId: Long?, bookmarked: Boolean? = null, read: Boolean? = null, lastPageRead: Int? = null, onError: suspend (Throwable) -> Unit = {}, - ) = asFlow(chapterId, bookmarked, read, lastPageRead) + ) = asFlow(chapterId, mangaId, bookmarked, read, lastPageRead) .catch { onError(it) log.warn(it) { "Failed to update chapter bookmark for chapter $chapterId" } @@ -49,11 +50,12 @@ class UpdateChapter( suspend fun await( chapterIds: List, + mangaIds: List?, bookmarked: Boolean? = null, read: Boolean? = null, lastPageRead: Int? = null, onError: suspend (Throwable) -> Unit = {}, - ) = asFlow(chapterIds, bookmarked, read, lastPageRead) + ) = asFlow(chapterIds, mangaIds, bookmarked, read, lastPageRead) .catch { onError(it) log.warn(it) { "Failed to update chapter bookmark for chapters $chapterIds" } @@ -76,6 +78,7 @@ class UpdateChapter( fun asFlow( chapterId: Long, + mangaId: Long?, bookmarked: Boolean? = null, read: Boolean? = null, lastPageRead: Int? = null, @@ -84,7 +87,7 @@ class UpdateChapter( bookmarked = bookmarked, read = read, lastPageRead = lastPageRead, - ).onEach { serverListeners.updateChapters(chapterId) } + ).onEach { serverListeners.updateManga(mangaId ?: -1) } fun asFlow( chapter: Chapter, @@ -96,10 +99,11 @@ class UpdateChapter( bookmarked = bookmarked, read = read, lastPageRead = lastPageRead, - ).onEach { serverListeners.updateChapters(chapter.id) } + ).onEach { serverListeners.updateManga(chapter.mangaId) } fun asFlow( chapterIds: List, + mangaIds: List?, bookmarked: Boolean? = null, read: Boolean? = null, lastPageRead: Int? = null, @@ -108,7 +112,7 @@ class UpdateChapter( bookmarked = bookmarked, read = read, lastPageRead = lastPageRead, - ).onEach { serverListeners.updateChapters(chapterIds) } + ).onEach { serverListeners.updateManga(mangaIds.orEmpty()) } @JvmName("asFlowChapters") fun asFlow( @@ -121,7 +125,7 @@ class UpdateChapter( bookmarked = bookmarked, read = read, lastPageRead = lastPageRead, - ).onEach { serverListeners.updateChapters(chapters.map { it.id }) } + ).onEach { serverListeners.updateManga(chapters.map { it.mangaId }.distinct()) } companion object { private val log = logging() diff --git a/domain/src/commonMain/kotlin/ca/gosyer/jui/domain/chapter/interactor/UpdateChapterLastPageRead.kt b/domain/src/commonMain/kotlin/ca/gosyer/jui/domain/chapter/interactor/UpdateChapterLastPageRead.kt index bbf4da26..3407320a 100644 --- a/domain/src/commonMain/kotlin/ca/gosyer/jui/domain/chapter/interactor/UpdateChapterLastPageRead.kt +++ b/domain/src/commonMain/kotlin/ca/gosyer/jui/domain/chapter/interactor/UpdateChapterLastPageRead.kt @@ -22,9 +22,10 @@ class UpdateChapterLastPageRead( ) { suspend fun await( chapterId: Long, + mangaId: Long?, lastPageRead: Int, onError: suspend (Throwable) -> Unit = {}, - ) = asFlow(chapterId, lastPageRead) + ) = asFlow(chapterId, mangaId, lastPageRead) .catch { onError(it) log.warn(it) { "Failed to update chapter last page read for chapter $chapterId" } @@ -44,11 +45,12 @@ class UpdateChapterLastPageRead( fun asFlow( chapterId: Long, + mangaId: Long?, lastPageRead: Int, ) = chapterRepository.updateChapter( chapterId = chapterId, lastPageRead = lastPageRead, - ).onEach { serverListeners.updateChapters(chapterId) } + ).onEach { serverListeners.updateManga(mangaId ?: -1) } fun asFlow( chapter: Chapter, @@ -56,7 +58,7 @@ class UpdateChapterLastPageRead( ) = chapterRepository.updateChapter( chapterId = chapter.id, lastPageRead = lastPageRead, - ).onEach { serverListeners.updateChapters(chapter.id) } + ).onEach { serverListeners.updateManga(chapter.mangaId) } companion object { private val log = logging() diff --git a/domain/src/commonMain/kotlin/ca/gosyer/jui/domain/chapter/interactor/UpdateChapterMeta.kt b/domain/src/commonMain/kotlin/ca/gosyer/jui/domain/chapter/interactor/UpdateChapterMeta.kt index bb06c8a1..7a5e4eb8 100644 --- a/domain/src/commonMain/kotlin/ca/gosyer/jui/domain/chapter/interactor/UpdateChapterMeta.kt +++ b/domain/src/commonMain/kotlin/ca/gosyer/jui/domain/chapter/interactor/UpdateChapterMeta.kt @@ -41,7 +41,7 @@ class UpdateChapterMeta( "juiPageOffset", pageOffset.toString(), ).collect() - serverListeners.updateChapters(chapter.id) + serverListeners.updateManga(chapter.mangaId) } emit(Unit) } diff --git a/domain/src/commonMain/kotlin/ca/gosyer/jui/domain/chapter/interactor/UpdateChapterRead.kt b/domain/src/commonMain/kotlin/ca/gosyer/jui/domain/chapter/interactor/UpdateChapterRead.kt index 8cac7444..aab90e5e 100644 --- a/domain/src/commonMain/kotlin/ca/gosyer/jui/domain/chapter/interactor/UpdateChapterRead.kt +++ b/domain/src/commonMain/kotlin/ca/gosyer/jui/domain/chapter/interactor/UpdateChapterRead.kt @@ -22,9 +22,10 @@ class UpdateChapterRead( ) { suspend fun await( chapterId: Long, + mangaId: Long?, read: Boolean, onError: suspend (Throwable) -> Unit = {}, - ) = asFlow(chapterId, read) + ) = asFlow(chapterId, mangaId, read) .catch { onError(it) log.warn(it) { "Failed to update chapter read status for chapter $chapterId" } @@ -44,19 +45,21 @@ class UpdateChapterRead( fun asFlow( chapterId: Long, + mangaId: Long?, read: Boolean, ) = chapterRepository.updateChapter( chapterId = chapterId, read = read, - ).onEach { serverListeners.updateChapters(chapterId) } + ).onEach { serverListeners.updateManga(mangaId ?: -1) } fun asFlow( chapterIds: List, + mangaIds: List?, read: Boolean, ) = chapterRepository.updateChapters( chapterIds = chapterIds, read = read, - ).onEach { serverListeners.updateChapters(chapterIds) } + ).onEach { serverListeners.updateManga(mangaIds.orEmpty()) } fun asFlow( chapter: Chapter, @@ -64,7 +67,7 @@ class UpdateChapterRead( ) = chapterRepository.updateChapter( chapterId = chapter.id, read = read, - ).onEach { serverListeners.updateChapters(chapter.id) } + ).onEach { serverListeners.updateManga(chapter.mangaId) } companion object { private val log = logging() diff --git a/domain/src/commonMain/kotlin/ca/gosyer/jui/domain/updates/interactor/UpdatesPager.kt b/domain/src/commonMain/kotlin/ca/gosyer/jui/domain/updates/interactor/UpdatesPager.kt index 3dbdb966..9e5ef18a 100644 --- a/domain/src/commonMain/kotlin/ca/gosyer/jui/domain/updates/interactor/UpdatesPager.kt +++ b/domain/src/commonMain/kotlin/ca/gosyer/jui/domain/updates/interactor/UpdatesPager.kt @@ -23,12 +23,9 @@ import kotlinx.coroutines.flow.MutableSharedFlow import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.SharingStarted import kotlinx.coroutines.flow.combine -import kotlinx.coroutines.flow.launchIn import kotlinx.coroutines.flow.map -import kotlinx.coroutines.flow.onEach import kotlinx.coroutines.flow.runningFold import kotlinx.coroutines.flow.stateIn -import kotlinx.coroutines.flow.update import kotlinx.coroutines.launch import kotlinx.coroutines.sync.Mutex import kotlinx.datetime.LocalDate @@ -96,20 +93,20 @@ class UpdatesPager( private val changedChapters = MutableStateFlow(emptyMap()) - init { - serverListeners.chapterIdsListener - .onEach { updatedChapterIds -> - val chapters = coroutineScope { - updatedChapterIds.mapNotNull { id -> chapterIds.value.find { it == id } }.map { - async { - getChapter.await(it) - } - }.awaitAll().filterNotNull().associateBy { it.id } - } - changedChapters.update { it + chapters } - } - .launchIn(this) - } +// init { +// serverListeners.chapterIdsListener +// .onEach { updatedChapterIds -> +// val chapters = coroutineScope { +// updatedChapterIds.mapNotNull { id -> chapterIds.value.find { it == id } }.map { +// async { +// getChapter.await(it) +// } +// }.awaitAll().filterNotNull().associateBy { it.id } +// } +// changedChapters.update { it + chapters } +// } +// .launchIn(this) +// } val updates = combine( foldedUpdates, diff --git a/presentation/src/commonMain/kotlin/ca/gosyer/jui/ui/base/prefs/PreferencesUiBuilder.kt b/presentation/src/commonMain/kotlin/ca/gosyer/jui/ui/base/prefs/PreferencesUiBuilder.kt index 0417ae39..7df28a7f 100644 --- a/presentation/src/commonMain/kotlin/ca/gosyer/jui/ui/base/prefs/PreferencesUiBuilder.kt +++ b/presentation/src/commonMain/kotlin/ca/gosyer/jui/ui/base/prefs/PreferencesUiBuilder.kt @@ -13,8 +13,8 @@ import androidx.compose.animation.core.MutableTransitionState import androidx.compose.animation.core.TweenSpec import androidx.compose.animation.core.animateDp import androidx.compose.animation.core.animateFloat +import androidx.compose.animation.core.rememberTransition import androidx.compose.animation.core.tween -import androidx.compose.animation.core.updateTransition import androidx.compose.animation.expandVertically import androidx.compose.animation.fadeIn import androidx.compose.animation.fadeOut @@ -408,7 +408,7 @@ fun ExpandablePreference( targetState = !expanded } } - val transition = updateTransition(transitionState) + val transition = rememberTransition(transitionState) val elevation by transition.animateDp({ tween(durationMillis = EXPAND_ANIMATION_DURATION) }) { diff --git a/presentation/src/commonMain/kotlin/ca/gosyer/jui/ui/base/state/SavedStateHandleFlow.kt b/presentation/src/commonMain/kotlin/ca/gosyer/jui/ui/base/state/SavedStateHandleFlow.kt index ddd6f29c..53eb0a09 100644 --- a/presentation/src/commonMain/kotlin/ca/gosyer/jui/ui/base/state/SavedStateHandleFlow.kt +++ b/presentation/src/commonMain/kotlin/ca/gosyer/jui/ui/base/state/SavedStateHandleFlow.kt @@ -7,6 +7,7 @@ package ca.gosyer.jui.ui.base.state import ca.gosyer.jui.uicore.vm.ViewModel +import kotlinx.coroutines.ExperimentalForInheritanceCoroutinesApi import kotlinx.coroutines.InternalCoroutinesApi import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.internal.SynchronizedObject @@ -39,6 +40,7 @@ class SavedStateHandleDelegate( } } +@OptIn(ExperimentalForInheritanceCoroutinesApi::class) class SavedStateHandleStateFlow( private val key: String, private val savedStateHandle: SavedStateHandle, diff --git a/presentation/src/commonMain/kotlin/ca/gosyer/jui/ui/library/components/LibraryPager.kt b/presentation/src/commonMain/kotlin/ca/gosyer/jui/ui/library/components/LibraryPager.kt index 065edb81..b3bd8026 100644 --- a/presentation/src/commonMain/kotlin/ca/gosyer/jui/ui/library/components/LibraryPager.kt +++ b/presentation/src/commonMain/kotlin/ca/gosyer/jui/ui/library/components/LibraryPager.kt @@ -6,7 +6,6 @@ package ca.gosyer.jui.ui.library.components -import androidx.compose.foundation.layout.Box import androidx.compose.foundation.pager.HorizontalPager import androidx.compose.foundation.pager.PagerState import androidx.compose.runtime.Composable @@ -119,7 +118,5 @@ private fun LibraryLoadedPage( showLanguage = showLanguage, showLocal = showLocal, ) - - else -> Box {} } } diff --git a/presentation/src/commonMain/kotlin/ca/gosyer/jui/ui/manga/MangaScreenViewModel.kt b/presentation/src/commonMain/kotlin/ca/gosyer/jui/ui/manga/MangaScreenViewModel.kt index f3b5eefd..3718ee9b 100644 --- a/presentation/src/commonMain/kotlin/ca/gosyer/jui/ui/manga/MangaScreenViewModel.kt +++ b/presentation/src/commonMain/kotlin/ca/gosyer/jui/ui/manga/MangaScreenViewModel.kt @@ -291,7 +291,7 @@ class MangaScreenViewModel( ) { scope.launch { manga.value?.let { - updateChapter.await(chapterIds, read = read, onError = { toast(it.message.orEmpty()) }) + updateChapter.await(chapterIds, listOf(params.mangaId), read = read, onError = { toast(it.message.orEmpty()) }) selectedIds.value = persistentListOf() loadChapters() } @@ -308,7 +308,7 @@ class MangaScreenViewModel( ) { scope.launch { manga.value?.let { - updateChapter.await(chapterIds, bookmarked = bookmark, onError = { toast(it.message.orEmpty()) }) + updateChapter.await(chapterIds, listOf(params.mangaId), bookmarked = bookmark, onError = { toast(it.message.orEmpty()) }) selectedIds.value = persistentListOf() loadChapters() } @@ -325,7 +325,7 @@ class MangaScreenViewModel( val chapters = chapters.value .sortedBy { it.chapter.index } .subList(0, index).map { it.chapter.id } // todo test - updateChapter.await(chapters, read = true, onError = { toast(it.message.orEmpty()) }) + updateChapter.await(chapters, listOf(params.mangaId), read = true, onError = { toast(it.message.orEmpty()) }) selectedIds.value = persistentListOf() loadChapters() } @@ -340,7 +340,7 @@ class MangaScreenViewModel( scope.launch { if (id == null) { val chapterIds = selectedIds.value - deleteChapterDownload.await(chapterIds, onError = { toast(it.message.orEmpty()) }) + deleteChapterDownload.await(chapterIds, listOf(params.mangaId), onError = { toast(it.message.orEmpty()) }) selectedItems.value.forEach { it.setNotDownloaded() } diff --git a/presentation/src/commonMain/kotlin/ca/gosyer/jui/ui/settings/SettingsServerScreen.kt b/presentation/src/commonMain/kotlin/ca/gosyer/jui/ui/settings/SettingsServerScreen.kt index 234a3153..49d34953 100644 --- a/presentation/src/commonMain/kotlin/ca/gosyer/jui/ui/settings/SettingsServerScreen.kt +++ b/presentation/src/commonMain/kotlin/ca/gosyer/jui/ui/settings/SettingsServerScreen.kt @@ -93,6 +93,7 @@ import kotlinx.collections.immutable.ImmutableMap import kotlinx.collections.immutable.persistentMapOf import kotlinx.collections.immutable.toImmutableMap import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.ExperimentalForInheritanceCoroutinesApi import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.flow.asStateFlow @@ -137,6 +138,7 @@ expect class SettingsServerHostViewModel : ViewModel @Composable expect fun getServerHostItems(viewModel: @Composable () -> SettingsServerHostViewModel): LazyListScope.() -> Unit +@OptIn(ExperimentalForInheritanceCoroutinesApi::class) private class ServerSettingMutableStateFlow( parent: StateFlow, getSetting: (Settings) -> T, diff --git a/presentation/src/commonMain/kotlin/ca/gosyer/jui/ui/sources/browse/filter/model/SourceFiltersView.kt b/presentation/src/commonMain/kotlin/ca/gosyer/jui/ui/sources/browse/filter/model/SourceFiltersView.kt index f5afce76..56a3053f 100644 --- a/presentation/src/commonMain/kotlin/ca/gosyer/jui/ui/sources/browse/filter/model/SourceFiltersView.kt +++ b/presentation/src/commonMain/kotlin/ca/gosyer/jui/ui/sources/browse/filter/model/SourceFiltersView.kt @@ -11,6 +11,7 @@ import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.flow.asStateFlow +@Suppress("DATA_CLASS_COPY_VISIBILITY_WILL_BE_CHANGED_WARNING") sealed class SourceFiltersView { abstract val index: Int abstract val name: String diff --git a/presentation/src/commonMain/kotlin/ca/gosyer/jui/ui/sources/settings/model/SourceSettingsView.kt b/presentation/src/commonMain/kotlin/ca/gosyer/jui/ui/sources/settings/model/SourceSettingsView.kt index dfb2f823..d72a0f56 100644 --- a/presentation/src/commonMain/kotlin/ca/gosyer/jui/ui/sources/settings/model/SourceSettingsView.kt +++ b/presentation/src/commonMain/kotlin/ca/gosyer/jui/ui/sources/settings/model/SourceSettingsView.kt @@ -27,6 +27,7 @@ import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.flow.asStateFlow +@Suppress("DATA_CLASS_COPY_VISIBILITY_WILL_BE_CHANGED_WARNING") sealed class SourceSettingsView { abstract val index: Int abstract val title: String? diff --git a/presentation/src/commonMain/kotlin/ca/gosyer/jui/ui/updates/UpdatesScreenViewModel.kt b/presentation/src/commonMain/kotlin/ca/gosyer/jui/ui/updates/UpdatesScreenViewModel.kt index 20e6416c..a51c70a8 100644 --- a/presentation/src/commonMain/kotlin/ca/gosyer/jui/ui/updates/UpdatesScreenViewModel.kt +++ b/presentation/src/commonMain/kotlin/ca/gosyer/jui/ui/updates/UpdatesScreenViewModel.kt @@ -118,7 +118,9 @@ class UpdatesScreenViewModel( read: Boolean, ) { scope.launch { - updateChapter.await(chapterIds, read = read, onError = { toast(it.message.orEmpty()) }) + val mangaIds = updates.value.filterIsInstance().filter { it.chapterDownloadItem.chapter.id in chapterIds } + .mapNotNull { it.chapterDownloadItem.manga?.id } + updateChapter.await(chapterIds, mangaIds, read = read, onError = { toast(it.message.orEmpty()) }) selectedIds.value = persistentListOf() } } @@ -132,7 +134,9 @@ class UpdatesScreenViewModel( bookmark: Boolean, ) { scope.launch { - updateChapter.await(chapterIds, bookmarked = bookmark, onError = { toast(it.message.orEmpty()) }) + val mangaIds = updates.value.filterIsInstance().filter { it.chapterDownloadItem.chapter.id in chapterIds } + .mapNotNull { it.chapterDownloadItem.manga?.id } + updateChapter.await(chapterIds, mangaIds, bookmarked = bookmark, onError = { toast(it.message.orEmpty()) }) selectedIds.value = persistentListOf() } } @@ -157,7 +161,9 @@ class UpdatesScreenViewModel( scope.launchDefault { if (chapter == null) { val selectedIds = selectedIds.value - deleteChapterDownload.await(selectedIds, onError = { toast(it.message.orEmpty()) }) + val mangaIds = updates.value.filterIsInstance().filter { it.chapterDownloadItem.chapter.id in selectedIds } + .mapNotNull { it.chapterDownloadItem.manga?.id } + deleteChapterDownload.await(selectedIds, mangaIds, onError = { toast(it.message.orEmpty()) }) selectedItems.value.forEach { it.setNotDownloaded() } diff --git a/ui-core/src/commonMain/kotlin/ca/gosyer/jui/uicore/image/ImageLoaderImage.kt b/ui-core/src/commonMain/kotlin/ca/gosyer/jui/uicore/image/ImageLoaderImage.kt index e691f204..7064fb5a 100644 --- a/ui-core/src/commonMain/kotlin/ca/gosyer/jui/uicore/image/ImageLoaderImage.kt +++ b/ui-core/src/commonMain/kotlin/ca/gosyer/jui/uicore/image/ImageLoaderImage.kt @@ -108,10 +108,6 @@ fun ImageLoaderImage( progress.value = 1.0F ImageLoaderImageState.Success } - - else -> { - ImageLoaderImageState.Loading - } } } Crossfade(state, animationSpec = animationSpec, modifier = modifier) { diff --git a/ui-core/src/commonMain/kotlin/ca/gosyer/jui/uicore/prefs/PreferenceMutableState.kt b/ui-core/src/commonMain/kotlin/ca/gosyer/jui/uicore/prefs/PreferenceMutableState.kt index 7170d281..da05b27c 100644 --- a/ui-core/src/commonMain/kotlin/ca/gosyer/jui/uicore/prefs/PreferenceMutableState.kt +++ b/ui-core/src/commonMain/kotlin/ca/gosyer/jui/uicore/prefs/PreferenceMutableState.kt @@ -8,10 +8,12 @@ package ca.gosyer.jui.uicore.prefs import ca.gosyer.jui.core.prefs.Preference import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.ExperimentalForInheritanceCoroutinesApi import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.launchIn import kotlinx.coroutines.flow.onEach +@OptIn(ExperimentalForInheritanceCoroutinesApi::class) class PreferenceMutableStateFlow( private val preference: Preference, scope: CoroutineScope, diff --git a/ui-core/src/desktopMain/kotlin/ca/gosyer/jui/uicore/vm/ContextWrapper.kt b/ui-core/src/desktopMain/kotlin/ca/gosyer/jui/uicore/vm/ContextWrapper.kt index 3bf49d87..da89e7ce 100644 --- a/ui-core/src/desktopMain/kotlin/ca/gosyer/jui/uicore/vm/ContextWrapper.kt +++ b/ui-core/src/desktopMain/kotlin/ca/gosyer/jui/uicore/vm/ContextWrapper.kt @@ -10,6 +10,7 @@ import androidx.compose.runtime.Stable import ca.gosyer.jui.core.lang.launchDefault import dev.icerock.moko.resources.StringResource import dev.icerock.moko.resources.format +import kotlinx.coroutines.DelicateCoroutinesApi import kotlinx.coroutines.GlobalScope import kotlinx.coroutines.flow.MutableSharedFlow import kotlinx.coroutines.flow.asSharedFlow @@ -26,6 +27,7 @@ actual class ContextWrapper { vararg args: Any, ): String = stringResource.format(*args).localized() + @OptIn(DelicateCoroutinesApi::class) actual fun toast( string: String, length: Length,