Cleanup uneeded StableHolder classes

This commit is contained in:
Syer10
2022-10-31 17:19:44 -04:00
parent 6bfcf28da9
commit 801a6899e7
33 changed files with 192 additions and 269 deletions

View File

@@ -39,7 +39,6 @@ import ca.gosyer.jui.domain.download.model.DownloadChapter
import ca.gosyer.jui.domain.download.model.DownloadState
import ca.gosyer.jui.domain.manga.model.Manga
import ca.gosyer.jui.i18n.MR
import ca.gosyer.jui.ui.base.model.StableHolder
import ca.gosyer.jui.uicore.components.DropdownIconButton
import ca.gosyer.jui.uicore.components.DropdownMenuItem
import ca.gosyer.jui.uicore.resources.stringResource
@@ -57,7 +56,7 @@ data class ChapterDownloadItem(
ChapterDownloadState.NotDownloaded
}
),
private val _downloadChapterFlow: MutableStateFlow<StableHolder<DownloadChapter?>> = MutableStateFlow(StableHolder(null))
private val _downloadChapterFlow: MutableStateFlow<DownloadChapter?> = MutableStateFlow(null)
) {
val downloadState = _downloadState.asStateFlow()
val downloadChapterFlow = _downloadChapterFlow.asStateFlow()
@@ -72,7 +71,7 @@ data class ChapterDownloadItem(
if (downloadState.value == ChapterDownloadState.Downloading && downloadingChapter == null) {
_downloadState.value = ChapterDownloadState.Downloaded
}
_downloadChapterFlow.value = StableHolder(downloadingChapter)
_downloadChapterFlow.value = downloadingChapter
}
suspend fun deleteDownload(deleteChapterDownload: DeleteChapterDownload) {
@@ -144,8 +143,7 @@ private fun DownloadIconButton(onClick: () -> Unit) {
}
@Composable
private fun DownloadingIconButton(downloadChapterHolder: StableHolder<DownloadChapter?>, onClick: () -> Unit) {
val downloadChapter = downloadChapterHolder.item
private fun DownloadingIconButton(downloadChapter: DownloadChapter?, onClick: () -> Unit) {
DropdownIconButton(
downloadChapter?.mangaId to downloadChapter?.chapterIndex,
{

View File

@@ -14,7 +14,6 @@ import ca.gosyer.jui.domain.download.interactor.ClearDownloadQueue
import ca.gosyer.jui.domain.download.interactor.StartDownloading
import ca.gosyer.jui.domain.download.interactor.StopDownloading
import ca.gosyer.jui.domain.download.service.DownloadService
import ca.gosyer.jui.ui.base.model.StableHolder
import ca.gosyer.jui.uicore.vm.ContextWrapper
import ca.gosyer.jui.uicore.vm.ViewModel
import kotlinx.collections.immutable.persistentListOf
@@ -51,7 +50,7 @@ class DownloadsScreenViewModel @Inject constructor(
val serviceStatus get() = DownloadService.status.asStateFlow()
val downloaderStatus get() = DownloadService.downloaderStatus.asStateFlow()
val downloadQueue get() = DownloadService.downloadQueue.map { it.map(::StableHolder).toImmutableList() }
val downloadQueue get() = DownloadService.downloadQueue.map { it.toImmutableList() }
.stateIn(scope, SharingStarted.Eagerly, persistentListOf())
fun start() {

View File

@@ -49,7 +49,6 @@ import ca.gosyer.jui.domain.chapter.model.Chapter
import ca.gosyer.jui.domain.download.model.DownloadChapter
import ca.gosyer.jui.domain.download.model.DownloaderStatus
import ca.gosyer.jui.i18n.MR
import ca.gosyer.jui.ui.base.model.StableHolder
import ca.gosyer.jui.ui.base.navigation.ActionItem
import ca.gosyer.jui.ui.base.navigation.Toolbar
import ca.gosyer.jui.ui.main.components.bottomNav
@@ -72,7 +71,7 @@ import kotlinx.collections.immutable.toImmutableList
@Composable
fun DownloadsScreenContent(
downloadQueue: ImmutableList<StableHolder<DownloadChapter>>,
downloadQueue: ImmutableList<DownloadChapter>,
downloadStatus: DownloaderStatus,
startDownloading: () -> Unit,
pauseDownloading: () -> Unit,
@@ -115,7 +114,7 @@ fun DownloadsScreenContent(
items(downloadQueue) {
DownloadsItem(
it,
{ onMangaClick(it.item.mangaId) },
{ onMangaClick(it.mangaId) },
stopDownload,
moveDownloadToBottom
)
@@ -140,12 +139,11 @@ fun DownloadsScreenContent(
@Composable
fun DownloadsItem(
itemHolder: StableHolder<DownloadChapter>,
item: DownloadChapter,
onClickCover: () -> Unit,
onClickCancel: (Chapter) -> Unit,
onClickMoveToBottom: (Chapter) -> Unit
) {
val item = itemHolder.item
MangaListItem(
modifier = Modifier
.height(96.dp)

View File

@@ -23,7 +23,6 @@ import ca.gosyer.jui.domain.manga.model.MangaStatus
import ca.gosyer.jui.domain.updates.interactor.UpdateCategory
import ca.gosyer.jui.domain.updates.interactor.UpdateLibrary
import ca.gosyer.jui.i18n.MR
import ca.gosyer.jui.ui.base.model.StableHolder
import ca.gosyer.jui.ui.base.state.SavedStateHandle
import ca.gosyer.jui.ui.base.state.getStateFlow
import ca.gosyer.jui.ui.util.lang.Collator
@@ -65,13 +64,13 @@ sealed class CategoryState {
@Stable
data class Loaded(
val items: StateFlow<ImmutableList<StableHolder<Manga>>>,
val unfilteredItems: MutableStateFlow<ImmutableList<StableHolder<Manga>>>
val items: StateFlow<ImmutableList<Manga>>,
val unfilteredItems: MutableStateFlow<ImmutableList<Manga>>
) : CategoryState()
}
private typealias LibraryMap = MutableMap<Long, MutableStateFlow<CategoryState>>
private data class Library(val categories: MutableStateFlow<ImmutableList<StableHolder<Category>>>, val mangaMap: LibraryMap)
private data class Library(val categories: MutableStateFlow<ImmutableList<Category>>, val mangaMap: LibraryMap)
private fun LibraryMap.getManga(id: Long) =
getOrPut(id) {
@@ -80,7 +79,7 @@ private fun LibraryMap.getManga(id: Long) =
private fun LibraryMap.setError(id: Long, e: Throwable) {
getManga(id).value = CategoryState.Failed(e)
}
private fun LibraryMap.setManga(id: Long, manga: ImmutableList<StableHolder<Manga>>, getItemsFlow: (StateFlow<List<StableHolder<Manga>>>) -> StateFlow<ImmutableList<StableHolder<Manga>>>) {
private fun LibraryMap.setManga(id: Long, manga: ImmutableList<Manga>, getItemsFlow: (StateFlow<List<Manga>>) -> StateFlow<ImmutableList<Manga>>) {
val flow = getManga(id)
when (val state = flow.value) {
is CategoryState.Loaded -> state.unfilteredItems.value = manga
@@ -121,12 +120,12 @@ class LibraryScreenViewModel @Inject constructor(
private val sortMode = libraryPreferences.sortMode().stateIn(scope)
private val sortAscending = libraryPreferences.sortAscending().stateIn(scope)
private val filter: Flow<(StableHolder<Manga>) -> Boolean> = combine(
private val filter: Flow<(Manga) -> Boolean> = combine(
libraryPreferences.filterDownloaded().getAsFlow(),
libraryPreferences.filterUnread().getAsFlow(),
libraryPreferences.filterCompleted().getAsFlow()
) { downloaded, unread, completed ->
{ (manga) ->
{ manga ->
when (downloaded) {
FilterState.EXCLUDED -> manga.downloadCount == null || manga.downloadCount == 0
FilterState.INCLUDED -> manga.downloadCount != null && (manga.downloadCount ?: 0) > 0
@@ -154,7 +153,7 @@ class LibraryScreenViewModel @Inject constructor(
private val comparator = combine(sortMode, sortAscending) { sortMode, sortAscending ->
getComparator(sortMode, sortAscending)
}.stateIn(scope, SharingStarted.Eagerly, compareBy { it.item.title })
}.stateIn(scope, SharingStarted.Eagerly, compareBy { it.title })
init {
getLibrary()
@@ -168,7 +167,6 @@ class LibraryScreenViewModel @Inject constructor(
throw Exception(MR.strings.library_empty.toPlatformString())
}
library.categories.value = categories.sortedBy { it.order }
.map(::StableHolder)
.toImmutableList()
updateCategories(categories)
_isLoading.value = false
@@ -189,18 +187,18 @@ class LibraryScreenViewModel @Inject constructor(
_showingMenu.value = showingMenu
}
private fun getComparator(sortMode: Sort, ascending: Boolean): Comparator<StableHolder<Manga>> {
val sortFn: (StableHolder<Manga>, StableHolder<Manga>) -> Int = when (sortMode) {
private fun getComparator(sortMode: Sort, ascending: Boolean): Comparator<Manga> {
val sortFn: (Manga, Manga) -> Int = when (sortMode) {
Sort.ALPHABETICAL -> {
val locale = Locale.current
val collator = Collator(locale);
{ (a), (b) ->
{ a, b ->
collator.compare(a.title.toLowerCase(locale), b.title.toLowerCase(locale))
}
}
Sort.UNREAD -> {
{ (a), (b) ->
{ a, b ->
when {
// Ensure unread content comes first
(a.unreadCount ?: 0) == (b.unreadCount ?: 0) -> 0
@@ -211,7 +209,7 @@ class LibraryScreenViewModel @Inject constructor(
}
}
Sort.DATE_ADDED -> {
{ (a), (b) ->
{ a, b ->
a.inLibraryAt.compareTo(b.inLibraryAt)
}
}
@@ -223,11 +221,11 @@ class LibraryScreenViewModel @Inject constructor(
}
}
private suspend fun filterManga(query: String, mangaList: List<StableHolder<Manga>>): List<StableHolder<Manga>> {
private suspend fun filterManga(query: String, mangaList: List<Manga>): List<Manga> {
if (query.isBlank()) return mangaList
val queries = query.split(" ")
return mangaList.asFlow()
.filter { (manga) ->
.filter { manga ->
queries.all { query ->
manga.title.contains(query, true) ||
manga.author.orEmpty().contains(query, true) ||
@@ -242,7 +240,7 @@ class LibraryScreenViewModel @Inject constructor(
.toList()
}
private fun getMangaItemsFlow(unfilteredItemsFlow: StateFlow<List<StableHolder<Manga>>>): StateFlow<ImmutableList<StableHolder<Manga>>> {
private fun getMangaItemsFlow(unfilteredItemsFlow: StateFlow<List<Manga>>): StateFlow<ImmutableList<Manga>> {
return combine(unfilteredItemsFlow, query) { unfilteredItems, query ->
filterManga(query, unfilteredItems)
}.combine(filter) { filteredManga, filterer ->
@@ -266,7 +264,7 @@ class LibraryScreenViewModel @Inject constructor(
.onEach {
library.mangaMap.setManga(
id = category.id,
manga = it.map(::StableHolder).toImmutableList(),
manga = it.toImmutableList(),
getItemsFlow = ::getMangaItemsFlow
)
}
@@ -280,12 +278,12 @@ class LibraryScreenViewModel @Inject constructor(
}
}
private fun getCategoriesToUpdate(mangaId: Long): List<StableHolder<Category>> {
private fun getCategoriesToUpdate(mangaId: Long): List<Category> {
return library.mangaMap
.filter { mangaMapEntry ->
(mangaMapEntry.value.value as? CategoryState.Loaded)?.items?.value?.firstOrNull { it.item.id == mangaId } != null
(mangaMapEntry.value.value as? CategoryState.Loaded)?.items?.value?.firstOrNull { it.id == mangaId } != null
}
.map { (id) -> library.categories.value.first { it.item.id == id } }
.map { (id) -> library.categories.value.first { it.id == id } }
}
fun removeManga(mangaId: Long) {

View File

@@ -23,19 +23,17 @@ import androidx.compose.ui.unit.dp
import ca.gosyer.jui.domain.manga.model.Manga
import ca.gosyer.jui.domain.source.model.Source
import ca.gosyer.jui.i18n.MR
import ca.gosyer.jui.ui.base.model.StableHolder
import ca.gosyer.jui.uicore.resources.stringResource
@Composable
fun LibraryMangaBadges(
modifier: Modifier = Modifier,
mangaHolder: StableHolder<Manga>,
manga: Manga,
showUnread: Boolean,
showDownloaded: Boolean,
showLanguage: Boolean,
showLocal: Boolean
) {
val manga = mangaHolder.item
val unread = manga.unreadCount
val downloaded = manga.downloadCount
val isLocal = manga.sourceId == Source.LOCAL_SOURCE_ID

View File

@@ -30,7 +30,6 @@ import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.unit.dp
import ca.gosyer.jui.domain.manga.model.Manga
import ca.gosyer.jui.ui.base.model.StableHolder
import ca.gosyer.jui.ui.main.components.bottomNav
import ca.gosyer.jui.uicore.components.MangaListItem
import ca.gosyer.jui.uicore.components.MangaListItemImage
@@ -43,7 +42,7 @@ import kotlinx.collections.immutable.ImmutableList
@Composable
fun LibraryMangaList(
library: ImmutableList<StableHolder<Manga>>,
library: ImmutableList<Manga>,
onClickManga: (Long) -> Unit,
onRemoveMangaClicked: (Long) -> Unit,
showUnread: Boolean,
@@ -62,13 +61,13 @@ fun LibraryMangaList(
)
).asPaddingValues()
) {
items(library) { mangaHolder ->
items(library) { manga ->
LibraryMangaListItem(
modifier = Modifier.libraryMangaModifier(
{ onClickManga(mangaHolder.item.id) },
{ onRemoveMangaClicked(mangaHolder.item.id) }
{ onClickManga(manga.id) },
{ onRemoveMangaClicked(manga.id) }
),
mangaHolder = mangaHolder,
manga = manga,
showUnread = showUnread,
showDownloaded = showDownloaded,
showLanguage = showLanguage,
@@ -95,13 +94,12 @@ fun LibraryMangaList(
@Composable
private fun LibraryMangaListItem(
modifier: Modifier,
mangaHolder: StableHolder<Manga>,
manga: Manga,
showUnread: Boolean,
showDownloaded: Boolean,
showLanguage: Boolean,
showLocal: Boolean
) {
val manga = mangaHolder.item
MangaListItem(
modifier = modifier then Modifier
.requiredHeight(56.dp)
@@ -122,7 +120,7 @@ private fun LibraryMangaListItem(
)
Box(Modifier.width(IntrinsicSize.Min)) {
LibraryMangaBadges(
mangaHolder = mangaHolder,
manga = manga,
showUnread = showUnread,
showDownloaded = showDownloaded,
showLanguage = showLanguage,

View File

@@ -13,7 +13,6 @@ import androidx.compose.runtime.collectAsState
import androidx.compose.runtime.getValue
import ca.gosyer.jui.domain.category.model.Category
import ca.gosyer.jui.domain.library.model.DisplayMode
import ca.gosyer.jui.ui.base.model.StableHolder
import ca.gosyer.jui.ui.library.CategoryState
import ca.gosyer.jui.uicore.components.ErrorScreen
import ca.gosyer.jui.uicore.components.LoadingScreen
@@ -24,7 +23,7 @@ import kotlinx.collections.immutable.ImmutableList
@Composable
fun LibraryPager(
pagerState: PagerState,
categories: ImmutableList<StableHolder<Category>>,
categories: ImmutableList<Category>,
displayMode: DisplayMode,
gridColumns: Int,
gridSize: Int,
@@ -39,7 +38,7 @@ fun LibraryPager(
if (categories.isEmpty()) return
HorizontalPager(categories.size, state = pagerState) {
when (val library = getLibraryForPage(categories[it].item.id).value) {
when (val library = getLibraryForPage(categories[it].id).value) {
CategoryState.Loading -> LoadingScreen()
is CategoryState.Failed -> ErrorScreen(library.e.message)
is CategoryState.Loaded -> LibraryLoadedPage(

View File

@@ -40,7 +40,6 @@ import androidx.compose.ui.unit.dp
import ca.gosyer.jui.domain.category.model.Category
import ca.gosyer.jui.domain.library.model.DisplayMode
import ca.gosyer.jui.i18n.MR
import ca.gosyer.jui.ui.base.model.StableHolder
import ca.gosyer.jui.ui.base.navigation.ActionItem
import ca.gosyer.jui.ui.base.navigation.BackHandler
import ca.gosyer.jui.ui.base.navigation.Toolbar
@@ -58,7 +57,7 @@ import kotlinx.collections.immutable.toImmutableList
@Composable
fun LibraryScreenContent(
categories: ImmutableList<StableHolder<Category>>,
categories: ImmutableList<Category>,
selectedCategoryIndex: Int,
displayMode: DisplayMode,
gridColumns: Int,
@@ -156,7 +155,7 @@ fun LibraryScreenContent(
@Composable
fun WideLibraryScreenContent(
pagerState: PagerState,
categories: ImmutableList<StableHolder<Category>>,
categories: ImmutableList<Category>,
selectedCategoryIndex: Int,
displayMode: DisplayMode,
gridColumns: Int,
@@ -257,7 +256,7 @@ fun WideLibraryScreenContent(
@Composable
fun ThinLibraryScreenContent(
pagerState: PagerState,
categories: ImmutableList<StableHolder<Category>>,
categories: ImmutableList<Category>,
selectedCategoryIndex: Int,
displayMode: DisplayMode,
gridColumns: Int,

View File

@@ -19,7 +19,6 @@ import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp
import androidx.compose.ui.util.fastForEachIndexed
import ca.gosyer.jui.domain.category.model.Category
import ca.gosyer.jui.ui.base.model.StableHolder
import com.google.accompanist.pager.PagerState
import com.google.accompanist.pager.pagerTabIndicatorOffset
import kotlinx.collections.immutable.ImmutableList
@@ -28,7 +27,7 @@ import kotlinx.collections.immutable.ImmutableList
fun LibraryTabs(
visible: Boolean,
pagerState: PagerState,
categories: ImmutableList<StableHolder<Category>>,
categories: ImmutableList<Category>,
selectedPage: Int,
onPageChanged: (Int) -> Unit
) {
@@ -50,7 +49,7 @@ fun LibraryTabs(
)
}
) {
categories.fastForEachIndexed { i, (category) ->
categories.fastForEachIndexed { i, category ->
Tab(
selected = selectedPage == i,
onClick = { onPageChanged(i) },

View File

@@ -37,7 +37,6 @@ import androidx.compose.ui.text.font.FontFamily
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import ca.gosyer.jui.domain.manga.model.Manga
import ca.gosyer.jui.ui.base.model.StableHolder
import ca.gosyer.jui.ui.main.components.bottomNav
import ca.gosyer.jui.uicore.components.VerticalScrollbar
import ca.gosyer.jui.uicore.components.mangaAspectRatio
@@ -49,7 +48,7 @@ import kotlinx.collections.immutable.ImmutableList
@Composable
fun LibraryMangaComfortableGrid(
library: ImmutableList<StableHolder<Manga>>,
library: ImmutableList<Manga>,
gridColumns: Int,
gridSize: Int,
onClickManga: (Long) -> Unit,
@@ -76,13 +75,13 @@ fun LibraryMangaComfortableGrid(
)
).asPaddingValues()
) {
items(library) { mangaHolder ->
items(library) { manga ->
LibraryMangaComfortableGridItem(
modifier = Modifier.libraryMangaModifier(
{ onClickManga(mangaHolder.item.id) },
{ onRemoveMangaClicked(mangaHolder.item.id) }
{ onClickManga(manga.id) },
{ onRemoveMangaClicked(manga.id) }
),
mangaHolder = mangaHolder,
manga = manga,
showUnread = showUnread,
showDownloaded = showDownloaded,
showLanguage = showLanguage,
@@ -109,13 +108,12 @@ fun LibraryMangaComfortableGrid(
@Composable
private fun LibraryMangaComfortableGridItem(
modifier: Modifier,
mangaHolder: StableHolder<Manga>,
manga: Manga,
showUnread: Boolean,
showDownloaded: Boolean,
showLanguage: Boolean,
showLocal: Boolean
) {
val manga = mangaHolder.item
val fontStyle = LocalTextStyle.current.merge(
TextStyle(letterSpacing = 0.sp, fontFamily = FontFamily.SansSerif, fontSize = 14.sp)
)
@@ -146,7 +144,7 @@ private fun LibraryMangaComfortableGridItem(
}
LibraryMangaBadges(
modifier = Modifier.padding(4.dp),
mangaHolder = mangaHolder,
manga = manga,
showUnread = showUnread,
showDownloaded = showDownloaded,
showLanguage = showLanguage,

View File

@@ -40,7 +40,6 @@ import androidx.compose.ui.text.font.FontFamily
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import ca.gosyer.jui.domain.manga.model.Manga
import ca.gosyer.jui.ui.base.model.StableHolder
import ca.gosyer.jui.ui.main.components.bottomNav
import ca.gosyer.jui.uicore.components.VerticalScrollbar
import ca.gosyer.jui.uicore.components.mangaAspectRatio
@@ -57,7 +56,7 @@ expect fun Modifier.libraryMangaModifier(
@Composable
fun LibraryMangaCompactGrid(
library: ImmutableList<StableHolder<Manga>>,
library: ImmutableList<Manga>,
gridColumns: Int,
gridSize: Int,
onClickManga: (Long) -> Unit,
@@ -84,13 +83,13 @@ fun LibraryMangaCompactGrid(
)
).asPaddingValues()
) {
items(library) { mangaHolder ->
items(library) { manga ->
LibraryMangaCompactGridItem(
modifier = Modifier.libraryMangaModifier(
{ onClickManga(mangaHolder.item.id) },
{ onRemoveMangaClicked(mangaHolder.item.id) }
{ onClickManga(manga.id) },
{ onRemoveMangaClicked(manga.id) }
),
mangaHolder = mangaHolder,
manga = manga,
showUnread = showUnread,
showDownloaded = showDownloaded,
showLanguage = showLanguage,
@@ -117,13 +116,12 @@ fun LibraryMangaCompactGrid(
@Composable
private fun LibraryMangaCompactGridItem(
modifier: Modifier,
mangaHolder: StableHolder<Manga>,
manga: Manga,
showUnread: Boolean,
showDownloaded: Boolean,
showLanguage: Boolean,
showLocal: Boolean
) {
val manga = mangaHolder.item
val fontStyle = LocalTextStyle.current.merge(
TextStyle(letterSpacing = 0.sp, fontFamily = FontFamily.SansSerif, fontSize = 14.sp)
)
@@ -151,7 +149,7 @@ private fun LibraryMangaCompactGridItem(
)
LibraryMangaBadges(
modifier = Modifier.padding(4.dp),
mangaHolder = mangaHolder,
manga = manga,
showUnread = showUnread,
showDownloaded = showDownloaded,
showLanguage = showLanguage,

View File

@@ -31,7 +31,6 @@ import androidx.compose.ui.graphics.FilterQuality
import androidx.compose.ui.layout.ContentScale
import androidx.compose.ui.unit.dp
import ca.gosyer.jui.domain.manga.model.Manga
import ca.gosyer.jui.ui.base.model.StableHolder
import ca.gosyer.jui.ui.main.components.bottomNav
import ca.gosyer.jui.uicore.components.VerticalScrollbar
import ca.gosyer.jui.uicore.components.mangaAspectRatio
@@ -43,7 +42,7 @@ import kotlinx.collections.immutable.ImmutableList
@Composable
fun LibraryMangaCoverOnlyGrid(
library: ImmutableList<StableHolder<Manga>>,
library: ImmutableList<Manga>,
gridColumns: Int,
gridSize: Int,
onClickManga: (Long) -> Unit,
@@ -70,13 +69,13 @@ fun LibraryMangaCoverOnlyGrid(
)
).asPaddingValues()
) {
items(library) { mangaHolder ->
items(library) { manga ->
LibraryMangaCoverOnlyGridItem(
modifier = Modifier.libraryMangaModifier(
{ onClickManga(mangaHolder.item.id) },
{ onRemoveMangaClicked(mangaHolder.item.id) }
{ onClickManga(manga.id) },
{ onRemoveMangaClicked(manga.id) }
),
mangaHolder = mangaHolder,
manga = manga,
showUnread = showUnread,
showDownloaded = showDownloaded,
showLanguage = showLanguage,
@@ -103,13 +102,12 @@ fun LibraryMangaCoverOnlyGrid(
@Composable
private fun LibraryMangaCoverOnlyGridItem(
modifier: Modifier,
mangaHolder: StableHolder<Manga>,
manga: Manga,
showUnread: Boolean,
showDownloaded: Boolean,
showLanguage: Boolean,
showLocal: Boolean
) {
val manga = mangaHolder.item
Box(
modifier = Modifier.padding(4.dp)
.fillMaxWidth()
@@ -125,7 +123,7 @@ private fun LibraryMangaCoverOnlyGridItem(
)
LibraryMangaBadges(
modifier = Modifier.padding(4.dp),
mangaHolder = mangaHolder,
manga = manga,
showUnread = showUnread,
showDownloaded = showDownloaded,
showLanguage = showLanguage,

View File

@@ -37,7 +37,7 @@ class AboutScreen : Screen {
}
}
AboutContent(
aboutHolder = vm.aboutHolder.collectAsState().value,
about = vm.aboutHolder.collectAsState().value,
formattedBuildTime = vm.formattedBuildTime.collectAsState().value,
checkForUpdates = vm::checkForUpdates,
openSourceLicenses = {

View File

@@ -11,7 +11,6 @@ import ca.gosyer.jui.domain.settings.interactor.AboutServer
import ca.gosyer.jui.domain.settings.model.About
import ca.gosyer.jui.domain.updates.interactor.UpdateChecker
import ca.gosyer.jui.domain.updates.interactor.UpdateChecker.Update
import ca.gosyer.jui.ui.base.model.StableHolder
import ca.gosyer.jui.uicore.vm.ContextWrapper
import ca.gosyer.jui.uicore.vm.ViewModel
import kotlinx.coroutines.flow.MutableSharedFlow
@@ -33,10 +32,10 @@ class AboutViewModel @Inject constructor(
contextWrapper: ContextWrapper
) : ViewModel(contextWrapper) {
private val _aboutHolder = MutableStateFlow<StableHolder<About?>>(StableHolder(null))
private val _aboutHolder = MutableStateFlow<About?>(null)
val aboutHolder = _aboutHolder.asStateFlow()
val formattedBuildTime = aboutHolder.map { (about) ->
val formattedBuildTime = aboutHolder.map { about ->
about ?: return@map ""
getFormattedDate(Instant.fromEpochSeconds(about.buildTime))
}.stateIn(scope, SharingStarted.Eagerly, "")
@@ -50,7 +49,7 @@ class AboutViewModel @Inject constructor(
private fun getAbout() {
scope.launch {
_aboutHolder.value = StableHolder(aboutServer.await())
_aboutHolder.value = aboutServer.await()
}
}

View File

@@ -43,7 +43,6 @@ import ca.gosyer.jui.domain.settings.model.About
import ca.gosyer.jui.domain.updates.interactor.UpdateChecker
import ca.gosyer.jui.i18n.MR
import ca.gosyer.jui.presentation.build.BuildKonfig
import ca.gosyer.jui.ui.base.model.StableHolder
import ca.gosyer.jui.ui.base.navigation.Toolbar
import ca.gosyer.jui.ui.base.prefs.PreferenceRow
import ca.gosyer.jui.ui.main.components.bottomNav
@@ -61,7 +60,7 @@ import dev.icerock.moko.resources.StringResource
@Composable
fun AboutContent(
aboutHolder: StableHolder<About?>,
about: About?,
formattedBuildTime: String,
checkForUpdates: () -> Unit,
openSourceLicenses: () -> Unit
@@ -100,7 +99,7 @@ fun AboutContent(
ClientVersionInfo()
}
item {
ServerVersionInfo(aboutHolder, formattedBuildTime)
ServerVersionInfo(about, formattedBuildTime)
}
item {
WhatsNew()
@@ -174,8 +173,7 @@ private fun ClientVersionInfo() {
}
@Composable
private fun ServerVersionInfo(aboutHolder: StableHolder<About?>, formattedBuildTime: String) {
val about = aboutHolder.item
private fun ServerVersionInfo(about: About?, formattedBuildTime: String) {
if (about == null) {
Box(Modifier.fillMaxWidth().height(48.dp), contentAlignment = Alignment.Center) {
CircularProgressIndicator()

View File

@@ -26,7 +26,7 @@ class MangaScreen(private val mangaId: Long) : Screen {
MangaScreenContent(
isLoading = vm.isLoading.collectAsState().value,
mangaHolder = vm.manga.collectAsState().value,
manga = vm.manga.collectAsState().value,
chapters = vm.chapters.collectAsState().value,
dateTimeFormatter = vm.dateTimeFormatter.collectAsState().value,
categoriesExist = vm.categoriesExist.collectAsState().value,

View File

@@ -73,7 +73,7 @@ class MangaScreenViewModel @Inject constructor(
contextWrapper: ContextWrapper,
private val params: Params
) : ViewModel(contextWrapper) {
private val _manga = MutableStateFlow<StableHolder<Manga?>>(StableHolder(null))
private val _manga = MutableStateFlow<Manga?>(null)
val manga = _manga.asStateFlow()
private val _chapters = MutableStateFlow<ImmutableList<ChapterDownloadItem>>(persistentListOf())
@@ -83,11 +83,11 @@ class MangaScreenViewModel @Inject constructor(
val isLoading = _isLoading.asStateFlow()
val categories = getCategories.asFlow(true)
.map { it.map(::StableHolder).toImmutableList() }
.map { it.toImmutableList() }
.catch { log.warn(it) { "Failed to get categories" } }
.stateIn(scope, SharingStarted.Eagerly, persistentListOf())
private val _mangaCategories = MutableStateFlow<ImmutableList<StableHolder<Category>>>(persistentListOf())
private val _mangaCategories = MutableStateFlow<ImmutableList<Category>>(persistentListOf())
val mangaCategories = _mangaCategories.asStateFlow()
val categoriesExist = categories.map { it.isNotEmpty() }
@@ -143,7 +143,7 @@ class MangaScreenViewModel @Inject constructor(
fun setCategories() {
scope.launch {
manga.value.item ?: return@launch
manga.value ?: return@launch
chooseCategoriesFlow.emit(Unit)
}
}
@@ -156,14 +156,14 @@ class MangaScreenViewModel @Inject constructor(
getManga.await(mangaId)
}
if (manga != null) {
_manga.value = StableHolder(manga)
_manga.value = manga
} else {
// TODO: 2022-07-01 Error toast
}
val mangaCategories = getMangaCategories.await(mangaId)
if (mangaCategories != null) {
_mangaCategories.value = mangaCategories.map(::StableHolder).toImmutableList()
_mangaCategories.value = mangaCategories.toImmutableList()
} else {
// TODO: 2022-07-01 Error toast
}
@@ -187,7 +187,7 @@ class MangaScreenViewModel @Inject constructor(
fun toggleFavorite() {
scope.launch {
manga.value.item?.let { manga ->
manga.value?.let { manga ->
if (manga.inLibrary) {
removeMangaFromLibrary.await(manga)
refreshMangaAsync(manga.id).await()
@@ -204,7 +204,7 @@ class MangaScreenViewModel @Inject constructor(
fun addFavorite(categories: List<Category>, oldCategories: List<Category>) {
scope.launch {
manga.value.item?.let { manga ->
manga.value?.let { manga ->
if (manga.inLibrary) {
oldCategories.filterNot { it in categories }.forEach {
removeMangaFromCategory.await(manga, it)
@@ -225,7 +225,7 @@ class MangaScreenViewModel @Inject constructor(
fun toggleRead(index: Int) {
val chapter = findChapter(index) ?: return
scope.launch {
manga.value.item?.let { manga ->
manga.value?.let { manga ->
updateChapterRead.await(manga, index, read = chapter.read.not())
refreshChaptersAsync(manga.id).await()
}
@@ -235,7 +235,7 @@ class MangaScreenViewModel @Inject constructor(
fun toggleBookmarked(index: Int) {
val chapter = findChapter(index) ?: return
scope.launch {
manga.value.item?.let { manga ->
manga.value?.let { manga ->
updateChapterBookmarked.await(manga, index, bookmarked = chapter.bookmarked.not())
refreshChaptersAsync(manga.id).await()
}
@@ -244,7 +244,7 @@ class MangaScreenViewModel @Inject constructor(
fun markPreviousRead(index: Int) {
scope.launch {
manga.value.item?.let { manga ->
manga.value?.let { manga ->
updateChapterMarkPreviousRead.await(manga, index)
refreshChaptersAsync(manga.id).await()
}
@@ -252,7 +252,7 @@ class MangaScreenViewModel @Inject constructor(
}
fun downloadChapter(index: Int) {
manga.value.item?.let { manga ->
manga.value?.let { manga ->
scope.launch { queueChapterDownload.await(manga, index) }
}
}

View File

@@ -37,7 +37,6 @@ import ca.gosyer.jui.domain.category.model.Category
import ca.gosyer.jui.domain.manga.model.Manga
import ca.gosyer.jui.i18n.MR
import ca.gosyer.jui.ui.base.dialog.getMaterialDialogProperties
import ca.gosyer.jui.ui.base.model.StableHolder
import ca.gosyer.jui.uicore.components.VerticalScrollbar
import ca.gosyer.jui.uicore.components.mangaAspectRatio
import ca.gosyer.jui.uicore.components.rememberScrollbarAdapter
@@ -52,30 +51,29 @@ import com.vanpra.composematerialdialogs.title
import kotlinx.collections.immutable.ImmutableList
@Composable
fun MangaItem(mangaHolder: StableHolder<Manga>) {
fun MangaItem(manga: Manga) {
BoxWithConstraints(Modifier.padding(8.dp)) {
if (maxWidth > 720.dp) {
Row {
Cover(mangaHolder, Modifier.width(300.dp))
Cover(manga, Modifier.width(300.dp))
Spacer(Modifier.width(16.dp))
MangaInfo(mangaHolder)
MangaInfo(manga)
}
} else {
Column(horizontalAlignment = Alignment.CenterHorizontally) {
Cover(
mangaHolder,
manga,
Modifier.heightIn(120.dp, 300.dp)
)
Spacer(Modifier.height(16.dp))
MangaInfo(mangaHolder)
MangaInfo(manga)
}
}
}
}
@Composable
private fun Cover(mangaHolder: StableHolder<Manga>, modifier: Modifier = Modifier) {
val manga = mangaHolder.item
private fun Cover(manga: Manga, modifier: Modifier = Modifier) {
ImageLoaderImage(
data = manga,
contentDescription = manga.title,
@@ -90,8 +88,7 @@ private fun Cover(mangaHolder: StableHolder<Manga>, modifier: Modifier = Modifie
}
@Composable
private fun MangaInfo(mangaHolder: StableHolder<Manga>, modifier: Modifier = Modifier) {
val manga = mangaHolder.item
private fun MangaInfo(manga: Manga, modifier: Modifier = Modifier) {
SelectionContainer {
Column(modifier) {
Text(
@@ -165,8 +162,8 @@ private fun Chip(text: String) {
@Composable
fun CategorySelectDialog(
state: MaterialDialogState,
categories: ImmutableList<StableHolder<Category>>,
oldCategories: ImmutableList<StableHolder<Category>>,
categories: ImmutableList<Category>,
oldCategories: ImmutableList<Category>,
onPositiveClick: (List<Category>, List<Category>) -> Unit
) {
MaterialDialog(
@@ -182,13 +179,13 @@ fun CategorySelectDialog(
Box {
val listState = rememberLazyListState()
listItemsMultiChoice(
list = categories.map { it.item.name },
list = categories.map { it.name },
state = listState,
initialSelection = oldCategories.mapNotNull { category ->
categories.indexOfFirst { it.item.id == category.item.id }.takeUnless { it == -1 }
categories.indexOfFirst { it.id == category.id }.takeUnless { it == -1 }
}.toSet(),
onCheckedChange = { indexes ->
onPositiveClick(indexes.map { categories[it].item }, oldCategories.map { it.item })
onPositiveClick(indexes.map { categories[it] }, oldCategories)
}
)
VerticalScrollbar(

View File

@@ -61,13 +61,13 @@ import kotlinx.datetime.Instant
@Composable
fun MangaScreenContent(
isLoading: Boolean,
mangaHolder: StableHolder<Manga?>,
manga: Manga?,
chapters: ImmutableList<ChapterDownloadItem>,
dateTimeFormatter: (Instant) -> String,
categoriesExist: Boolean,
chooseCategoriesFlowHolder: StableHolder<SharedFlow<Unit>>,
availableCategories: ImmutableList<StableHolder<Category>>,
mangaCategories: ImmutableList<StableHolder<Category>>,
availableCategories: ImmutableList<Category>,
mangaCategories: ImmutableList<Category>,
addFavorite: (List<Category>, List<Category>) -> Unit,
setCategories: () -> Unit,
toggleFavorite: () -> Unit,
@@ -100,7 +100,6 @@ fun MangaScreenContent(
Toolbar(
stringResource(MR.strings.location_manga),
actions = {
val manga = mangaHolder.item
val uriHandler = LocalUriHandler.current
getActionItems(
refreshManga = refreshManga,
@@ -120,8 +119,8 @@ fun MangaScreenContent(
}
) {
Box(Modifier.padding(it)) {
mangaHolder.let { mangaHolder ->
if (mangaHolder.item != null) {
manga.let { manga ->
if (manga != null) {
Box {
val state = rememberLazyListState()
LazyColumn(
@@ -135,14 +134,14 @@ fun MangaScreenContent(
) {
item {
@Suppress("UNCHECKED_CAST")
MangaItem(mangaHolder as StableHolder<Manga>)
MangaItem(manga)
}
if (chapters.isNotEmpty()) {
items(chapters) { chapter ->
ChapterItem(
chapter,
dateTimeFormatter,
onClick = { readerLauncher.launch(it, mangaHolder.item.id) },
onClick = { readerLauncher.launch(it, manga.id) },
toggleRead = toggleRead,
toggleBookmarked = toggleBookmarked,
markPreviousAsRead = markPreviousRead,

View File

@@ -8,9 +8,7 @@ package ca.gosyer.jui.ui.sources.browse
import androidx.compose.runtime.Composable
import androidx.compose.runtime.collectAsState
import androidx.compose.runtime.remember
import ca.gosyer.jui.domain.source.model.Source
import ca.gosyer.jui.ui.base.model.StableHolder
import ca.gosyer.jui.ui.manga.MangaScreen
import ca.gosyer.jui.ui.sources.browse.components.SourceScreenContent
import ca.gosyer.jui.ui.sources.browse.filter.SourceFiltersViewModel
@@ -28,7 +26,6 @@ class SourceScreen(val source: Source, private val initialQuery: String? = null)
@Composable
override fun Content() {
val sourceHolder = remember { StableHolder(source) }
val sourceVM = viewModel {
sourceViewModel(SourceScreenViewModel.Params(source, initialQuery))
}
@@ -38,7 +35,7 @@ class SourceScreen(val source: Source, private val initialQuery: String? = null)
val sourcesNavigator = LocalSourcesNavigator.current
val navigator = LocalNavigator.currentOrThrow
SourceScreenContent(
sourceHolder = sourceHolder,
source = source,
onMangaClick = { navigator push MangaScreen(it) },
onCloseSourceTabClick = if (sourcesNavigator != null) {
{ sourcesNavigator.remove(it) }

View File

@@ -13,7 +13,6 @@ import ca.gosyer.jui.domain.source.model.MangaPage
import ca.gosyer.jui.domain.source.model.Source
import ca.gosyer.jui.domain.source.service.CatalogPreferences
import ca.gosyer.jui.domain.source.service.SourceRepository
import ca.gosyer.jui.ui.base.model.StableHolder
import ca.gosyer.jui.uicore.vm.ContextWrapper
import ca.gosyer.jui.uicore.vm.ViewModel
import kotlinx.collections.immutable.ImmutableList
@@ -58,7 +57,7 @@ class SourceScreenViewModel(
val gridColumns = libraryPreferences.gridColumns().stateIn(scope)
val gridSize = libraryPreferences.gridSize().stateIn(scope)
private val _mangas = MutableStateFlow<ImmutableList<StableHolder<Manga>>>(persistentListOf())
private val _mangas = MutableStateFlow<ImmutableList<Manga>>(persistentListOf())
val mangas = _mangas.asStateFlow()
private val _hasNextPage = MutableStateFlow(false)
@@ -88,7 +87,7 @@ class SourceScreenViewModel(
init {
scope.launch {
getPage()?.let { (mangas, hasNextPage) ->
_mangas.value = mangas.map(::StableHolder).toImmutableList()
_mangas.value = mangas.toImmutableList()
_hasNextPage.value = hasNextPage
}
@@ -102,7 +101,7 @@ class SourceScreenViewModel(
_pageNum.value++
val page = getPage()
if (page != null) {
_mangas.value = _mangas.value.toPersistentList() + page.mangaList.map(::StableHolder)
_mangas.value = _mangas.value.toPersistentList() + page.mangaList
_hasNextPage.value = page.hasNextPage
} else {
_pageNum.value--

View File

@@ -39,7 +39,6 @@ import androidx.compose.ui.text.font.FontFamily
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import ca.gosyer.jui.domain.manga.model.Manga
import ca.gosyer.jui.ui.base.model.StableHolder
import ca.gosyer.jui.ui.main.components.bottomNav
import ca.gosyer.jui.uicore.components.VerticalScrollbar
import ca.gosyer.jui.uicore.components.mangaAspectRatio
@@ -51,7 +50,7 @@ import kotlinx.collections.immutable.ImmutableList
@Composable
fun SourceMangaComfortableGrid(
mangas: ImmutableList<StableHolder<Manga>>,
mangas: ImmutableList<Manga>,
gridColumns: Int,
gridSize: Int,
onClickManga: (Long) -> Unit,
@@ -75,16 +74,16 @@ fun SourceMangaComfortableGrid(
)
).asPaddingValues()
) {
itemsIndexed(mangas) { index, mangaHolder ->
itemsIndexed(mangas) { index, manga ->
if (hasNextPage && index == mangas.lastIndex) {
LaunchedEffect(Unit) { onLoadNextPage() }
}
SourceMangaComfortableGridItem(
modifier = Modifier.clickable(
onClick = { onClickManga(mangaHolder.item.id) }
onClick = { onClickManga(manga.id) }
),
mangaHolder = mangaHolder,
inLibrary = mangaHolder.item.inLibrary
manga = manga,
inLibrary = manga.inLibrary
)
}
}
@@ -107,10 +106,9 @@ fun SourceMangaComfortableGrid(
@Composable
private fun SourceMangaComfortableGridItem(
modifier: Modifier,
mangaHolder: StableHolder<Manga>,
manga: Manga,
inLibrary: Boolean
) {
val manga = mangaHolder.item
val fontStyle = LocalTextStyle.current.merge(
TextStyle(letterSpacing = 0.sp, fontFamily = FontFamily.SansSerif, fontSize = 14.sp)
)

View File

@@ -42,7 +42,6 @@ import androidx.compose.ui.text.font.FontFamily
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import ca.gosyer.jui.domain.manga.model.Manga
import ca.gosyer.jui.ui.base.model.StableHolder
import ca.gosyer.jui.ui.main.components.bottomNav
import ca.gosyer.jui.uicore.components.VerticalScrollbar
import ca.gosyer.jui.uicore.components.mangaAspectRatio
@@ -54,7 +53,7 @@ import kotlinx.collections.immutable.ImmutableList
@Composable
fun SourceMangaCompactGrid(
mangas: ImmutableList<StableHolder<Manga>>,
mangas: ImmutableList<Manga>,
gridColumns: Int,
gridSize: Int,
onClickManga: (Long) -> Unit,
@@ -78,16 +77,16 @@ fun SourceMangaCompactGrid(
)
).asPaddingValues()
) {
itemsIndexed(mangas) { index, mangaHolder ->
itemsIndexed(mangas) { index, manga ->
if (hasNextPage && index == mangas.lastIndex) {
LaunchedEffect(Unit) { onLoadNextPage() }
}
SourceMangaCompactGridItem(
modifier = Modifier.clickable(
onClick = { onClickManga(mangaHolder.item.id) }
onClick = { onClickManga(manga.id) }
),
mangaHolder = mangaHolder,
inLibrary = mangaHolder.item.inLibrary
manga = manga,
inLibrary = manga.inLibrary
)
}
}
@@ -110,10 +109,9 @@ fun SourceMangaCompactGrid(
@Composable
private fun SourceMangaCompactGridItem(
modifier: Modifier,
mangaHolder: StableHolder<Manga>,
manga: Manga,
inLibrary: Boolean
) {
val manga = mangaHolder.item
val fontStyle = LocalTextStyle.current.merge(
TextStyle(letterSpacing = 0.sp, fontFamily = FontFamily.SansSerif, fontSize = 14.sp)
)

View File

@@ -30,7 +30,6 @@ import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.unit.dp
import ca.gosyer.jui.domain.manga.model.Manga
import ca.gosyer.jui.ui.base.model.StableHolder
import ca.gosyer.jui.ui.main.components.bottomNav
import ca.gosyer.jui.uicore.components.MangaListItem
import ca.gosyer.jui.uicore.components.MangaListItemImage
@@ -43,7 +42,7 @@ import kotlinx.collections.immutable.ImmutableList
@Composable
fun SourceMangaList(
mangas: ImmutableList<StableHolder<Manga>>,
mangas: ImmutableList<Manga>,
onClickManga: (Long) -> Unit,
hasNextPage: Boolean = false,
onLoadNextPage: () -> Unit
@@ -59,16 +58,16 @@ fun SourceMangaList(
)
).asPaddingValues()
) {
itemsIndexed(mangas) { index, mangaHolder ->
itemsIndexed(mangas) { index, manga ->
if (hasNextPage && index == mangas.lastIndex) {
LaunchedEffect(Unit) { onLoadNextPage() }
}
MangaListItem(
modifier = Modifier.clickable(
onClick = { onClickManga(mangaHolder.item.id) }
onClick = { onClickManga(manga.id) }
),
mangaHolder = mangaHolder,
inLibrary = mangaHolder.item.inLibrary
manga = manga,
inLibrary = manga.inLibrary
)
}
}
@@ -91,10 +90,9 @@ fun SourceMangaList(
@Composable
private fun MangaListItem(
modifier: Modifier,
mangaHolder: StableHolder<Manga>,
manga: Manga,
inLibrary: Boolean
) {
val manga = mangaHolder.item
MangaListItem(
modifier = modifier then Modifier
.requiredHeight(56.dp)

View File

@@ -52,7 +52,6 @@ import ca.gosyer.jui.domain.library.model.DisplayMode
import ca.gosyer.jui.domain.manga.model.Manga
import ca.gosyer.jui.domain.source.model.Source
import ca.gosyer.jui.i18n.MR
import ca.gosyer.jui.ui.base.model.StableHolder
import ca.gosyer.jui.ui.base.navigation.ActionItem
import ca.gosyer.jui.ui.base.navigation.BackHandler
import ca.gosyer.jui.ui.base.navigation.Toolbar
@@ -70,14 +69,14 @@ import kotlinx.collections.immutable.toImmutableList
@Composable
fun SourceScreenContent(
sourceHolder: StableHolder<Source>,
source: Source,
onMangaClick: (Long) -> Unit,
onCloseSourceTabClick: (Source) -> Unit,
onSourceSettingsClick: (Long) -> Unit,
displayMode: DisplayMode,
gridColumns: Int,
gridSize: Int,
mangas: ImmutableList<StableHolder<Manga>>,
mangas: ImmutableList<Manga>,
hasNextPage: Boolean,
loading: Boolean,
isLatest: Boolean,
@@ -91,13 +90,12 @@ fun SourceScreenContent(
setUsingFilters: (Boolean) -> Unit,
onSelectDisplayMode: (DisplayMode) -> Unit,
// filter
filters: ImmutableList<StableHolder<SourceFiltersView<*, *>>>,
filters: ImmutableList<SourceFiltersView<*, *>>,
showingFilters: Boolean,
showFilterButton: Boolean,
setShowingFilters: (Boolean) -> Unit,
resetFiltersClicked: () -> Unit
) {
val source = sourceHolder.item
LaunchedEffect(source) {
enableLatest(source.supportsLatest)
}
@@ -113,7 +111,7 @@ fun SourceScreenContent(
BoxWithConstraints {
if (maxWidth > 720.dp) {
SourceWideScreenContent(
sourceHolder = sourceHolder,
source = source,
onMangaClick = onMangaClick,
onCloseSourceTabClick = onCloseSourceTabClick,
onSourceSettingsClick = onSourceSettingsClick,
@@ -140,7 +138,7 @@ fun SourceScreenContent(
)
} else {
SourceThinScreenContent(
sourceHolder = sourceHolder,
source = source,
onMangaClick = onMangaClick,
onCloseSourceTabClick = onCloseSourceTabClick,
onSourceSettingsClick = onSourceSettingsClick,
@@ -171,14 +169,14 @@ fun SourceScreenContent(
@Composable
private fun SourceWideScreenContent(
sourceHolder: StableHolder<Source>,
source: Source,
onMangaClick: (Long) -> Unit,
onCloseSourceTabClick: (Source) -> Unit,
onSourceSettingsClick: (Long) -> Unit,
displayMode: DisplayMode,
gridColumns: Int,
gridSize: Int,
mangas: ImmutableList<StableHolder<Manga>>,
mangas: ImmutableList<Manga>,
hasNextPage: Boolean,
loading: Boolean,
isLatest: Boolean,
@@ -190,7 +188,7 @@ private fun SourceWideScreenContent(
loadNextPage: () -> Unit,
setUsingFilters: (Boolean) -> Unit,
// filter
filters: ImmutableList<StableHolder<SourceFiltersView<*, *>>>,
filters: ImmutableList<SourceFiltersView<*, *>>,
showingFilters: Boolean,
showFilterButton: Boolean,
setShowingFilters: (Boolean) -> Unit,
@@ -205,7 +203,7 @@ private fun SourceWideScreenContent(
),
topBar = {
SourceToolbar(
sourceHolder = sourceHolder,
source = source,
onCloseSourceTabClick = onCloseSourceTabClick,
sourceSearchQuery = sourceSearchQuery,
onSearch = search,
@@ -266,14 +264,14 @@ private fun SourceWideScreenContent(
@Composable
private fun SourceThinScreenContent(
sourceHolder: StableHolder<Source>,
source: Source,
onMangaClick: (Long) -> Unit,
onCloseSourceTabClick: (Source) -> Unit,
onSourceSettingsClick: (Long) -> Unit,
displayMode: DisplayMode,
gridColumns: Int,
gridSize: Int,
mangas: ImmutableList<StableHolder<Manga>>,
mangas: ImmutableList<Manga>,
hasNextPage: Boolean,
loading: Boolean,
isLatest: Boolean,
@@ -285,7 +283,7 @@ private fun SourceThinScreenContent(
loadNextPage: () -> Unit,
setUsingFilters: (Boolean) -> Unit,
// filter
filters: ImmutableList<StableHolder<SourceFiltersView<*, *>>>,
filters: ImmutableList<SourceFiltersView<*, *>>,
showingFilters: Boolean,
showFilterButton: Boolean,
setShowingFilters: (Boolean) -> Unit,
@@ -318,7 +316,7 @@ private fun SourceThinScreenContent(
),
topBar = {
SourceToolbar(
sourceHolder = sourceHolder,
source = source,
onCloseSourceTabClick = onCloseSourceTabClick,
sourceSearchQuery = sourceSearchQuery,
onSearch = search,
@@ -410,7 +408,7 @@ private fun SourceThinScreenContent(
@Composable
fun SourceToolbar(
sourceHolder: StableHolder<Source>,
source: Source,
onCloseSourceTabClick: (Source) -> Unit,
sourceSearchQuery: String?,
onSearch: (String) -> Unit,
@@ -424,7 +422,6 @@ fun SourceToolbar(
onToggleFiltersClick: (Boolean) -> Unit,
onSelectDisplayMode: (DisplayMode) -> Unit
) {
val source = sourceHolder.item
Toolbar(
source.name,
closable = true,
@@ -490,7 +487,7 @@ private fun MangaTable(
displayMode: DisplayMode,
gridColumns: Int,
gridSize: Int,
mangas: ImmutableList<StableHolder<Manga>>,
mangas: ImmutableList<Manga>,
isLoading: Boolean = false,
hasNextPage: Boolean = false,
onLoadNextPage: () -> Unit,

View File

@@ -60,7 +60,6 @@ import androidx.compose.ui.util.fastForEach
import androidx.compose.ui.util.fastForEachIndexed
import ca.gosyer.jui.domain.source.model.sourcefilters.SortFilter
import ca.gosyer.jui.i18n.MR
import ca.gosyer.jui.ui.base.model.StableHolder
import ca.gosyer.jui.ui.base.prefs.ExpandablePreference
import ca.gosyer.jui.ui.sources.browse.filter.model.SourceFiltersView
import ca.gosyer.jui.uicore.components.Spinner
@@ -75,7 +74,7 @@ import kotlinx.coroutines.flow.filterIsInstance
@Composable
fun SourceFiltersMenu(
modifier: Modifier,
filters: ImmutableList<StableHolder<SourceFiltersView<*, *>>>,
filters: ImmutableList<SourceFiltersView<*, *>>,
onSearchClicked: () -> Unit,
resetFiltersClicked: () -> Unit
) {
@@ -100,7 +99,7 @@ fun SourceFiltersMenu(
val scrollState = rememberScrollState()
Column(Modifier.fillMaxSize().verticalScroll(scrollState)) {
filters.fastForEach { item ->
item.toView(startExpanded = item.item.index in expandedGroups) { expanded, index ->
item.toView(startExpanded = item.index in expandedGroups) { expanded, index ->
if (expanded) {
expandedGroups += index
} else {
@@ -120,32 +119,17 @@ fun SourceFiltersMenu(
}
}
@Suppress("UNCHECKED_CAST")
@Composable
fun StableHolder<SourceFiltersView<*, *>>.toView(startExpanded: Boolean = false, onExpandChanged: ((Boolean, Int) -> Unit)? = null) {
when (this.item) {
is SourceFiltersView.CheckBox -> CheckboxView(this as StableHolder<SourceFiltersView.CheckBox>)
is SourceFiltersView.Group -> GroupView(this as StableHolder<SourceFiltersView.Group>, startExpanded, onExpandChanged)
is SourceFiltersView.Header -> HeaderView(this as StableHolder<SourceFiltersView.Header>)
is SourceFiltersView.Select -> SelectView(this as StableHolder<SourceFiltersView.Select>)
is SourceFiltersView.Separator -> SeparatorView()
is SourceFiltersView.Sort -> SortView(this as StableHolder<SourceFiltersView.Sort>, startExpanded, onExpandChanged)
is SourceFiltersView.Text -> TextView(this as StableHolder<SourceFiltersView.Text>)
is SourceFiltersView.TriState -> TriStateView(this as StableHolder<SourceFiltersView.TriState>)
}
}
@Composable
fun SourceFiltersView<*, *>.toView(startExpanded: Boolean = false, onExpandChanged: ((Boolean, Int) -> Unit)? = null) {
when (this) {
is SourceFiltersView.CheckBox -> CheckboxView(StableHolder(this))
is SourceFiltersView.Group -> GroupView(StableHolder(this), startExpanded, onExpandChanged)
is SourceFiltersView.Header -> HeaderView(StableHolder(this))
is SourceFiltersView.Select -> SelectView(StableHolder(this))
is SourceFiltersView.CheckBox -> CheckboxView(this)
is SourceFiltersView.Group -> GroupView(this, startExpanded, onExpandChanged)
is SourceFiltersView.Header -> HeaderView(this)
is SourceFiltersView.Select -> SelectView(this)
is SourceFiltersView.Separator -> SeparatorView()
is SourceFiltersView.Sort -> SortView(StableHolder(this), startExpanded, onExpandChanged)
is SourceFiltersView.Text -> TextView(StableHolder(this))
is SourceFiltersView.TriState -> TriStateView(StableHolder(this))
is SourceFiltersView.Sort -> SortView(this, startExpanded, onExpandChanged)
is SourceFiltersView.Text -> TextView(this)
is SourceFiltersView.TriState -> TriStateView(this)
}
}
@@ -175,8 +159,7 @@ fun SourceFilterAction(
}
@Composable
fun GroupView(groupHolder: StableHolder<SourceFiltersView.Group>, startExpanded: Boolean, onExpandChanged: ((Boolean, Int) -> Unit)? = null) {
val group = groupHolder.item
fun GroupView(group: SourceFiltersView.Group, startExpanded: Boolean, onExpandChanged: ((Boolean, Int) -> Unit)? = null) {
val state by key(group.hashCode()) { group.state.collectAsState() }
ExpandablePreference(
title = group.name,
@@ -192,8 +175,7 @@ fun GroupView(groupHolder: StableHolder<SourceFiltersView.Group>, startExpanded:
}
@Composable
fun CheckboxView(checkBoxHolder: StableHolder<SourceFiltersView.CheckBox>) {
val checkBox = checkBoxHolder.item
fun CheckboxView(checkBox: SourceFiltersView.CheckBox) {
val state by key(checkBox.hashCode()) { checkBox.state.collectAsState() }
SourceFilterAction(
name = checkBox.name,
@@ -205,8 +187,7 @@ fun CheckboxView(checkBoxHolder: StableHolder<SourceFiltersView.CheckBox>) {
}
@Composable
fun HeaderView(headerHolder: StableHolder<SourceFiltersView.Header>) {
val header = headerHolder.item
fun HeaderView(header: SourceFiltersView.Header) {
Box(Modifier.padding(horizontal = 16.dp, vertical = 8.dp).fillMaxWidth()) {
Text(
text = header.name,
@@ -219,8 +200,7 @@ fun HeaderView(headerHolder: StableHolder<SourceFiltersView.Header>) {
}
@Composable
fun SelectView(selectHolder: StableHolder<SourceFiltersView.Select>) {
val select = selectHolder.item
fun SelectView(select: SourceFiltersView.Select) {
val state by key(select.hashCode()) { select.state.collectAsState() }
Row(
Modifier.fillMaxWidth().defaultMinSize(minHeight = 56.dp)
@@ -279,8 +259,7 @@ fun SortRow(name: String, selected: Boolean, asc: Boolean, onClick: () -> Unit)
}
@Composable
fun SortView(sortHolder: StableHolder<SourceFiltersView.Sort>, startExpanded: Boolean, onExpandChanged: ((Boolean, Int) -> Unit)?) {
val sort = sortHolder.item
fun SortView(sort: SourceFiltersView.Sort, startExpanded: Boolean, onExpandChanged: ((Boolean, Int) -> Unit)?) {
val state by key(sort.hashCode()) { sort.state.collectAsState() }
ExpandablePreference(
sort.name,
@@ -313,8 +292,7 @@ fun SortView(sortHolder: StableHolder<SourceFiltersView.Sort>, startExpanded: Bo
}
@Composable
fun TextView(textHolder: StableHolder<SourceFiltersView.Text>) {
val text = textHolder.item
fun TextView(text: SourceFiltersView.Text) {
val placeholderText = remember(text) { text.filter.name }
val state by key(text.hashCode()) { text.state.collectAsState() }
var stateText by remember(text, state) {
@@ -350,8 +328,7 @@ fun TextView(textHolder: StableHolder<SourceFiltersView.Text>) {
}
@Composable
fun TriStateView(triStateHolder: StableHolder<SourceFiltersView.TriState>) {
val triState = triStateHolder.item
fun TriStateView(triState: SourceFiltersView.TriState) {
val state by key(triState.hashCode()) { triState.state.collectAsState() }
SourceFilterAction(
name = triState.name,

View File

@@ -9,7 +9,6 @@ package ca.gosyer.jui.ui.sources.browse.filter
import ca.gosyer.jui.domain.source.model.sourcefilters.SourceFilter
import ca.gosyer.jui.domain.source.model.sourcefilters.SourceFilterChange
import ca.gosyer.jui.domain.source.service.SourceRepository
import ca.gosyer.jui.ui.base.model.StableHolder
import ca.gosyer.jui.ui.sources.browse.filter.model.SourceFiltersView
import ca.gosyer.jui.uicore.vm.ContextWrapper
import ca.gosyer.jui.uicore.vm.ViewModel
@@ -49,7 +48,7 @@ class SourceFiltersViewModel(
private val _loading = MutableStateFlow(true)
val loading = _loading.asStateFlow()
private val _filters = MutableStateFlow<ImmutableList<StableHolder<SourceFiltersView<*, *>>>>(persistentListOf())
private val _filters = MutableStateFlow<ImmutableList<SourceFiltersView<*, *>>>(persistentListOf())
val filters = _filters.asStateFlow()
private val _showingFilters = MutableStateFlow(false)
@@ -64,7 +63,7 @@ class SourceFiltersViewModel(
filters.mapLatest { settings ->
_filterButtonEnabled.value = settings.isNotEmpty()
supervisorScope {
settings.forEach { (filter) ->
settings.forEach { filter ->
if (filter is SourceFiltersView.Group) {
filter.state.value.forEach { childFilter ->
childFilter.state.drop(1)
@@ -124,7 +123,7 @@ class SourceFiltersViewModel(
private fun List<SourceFilter>.toView() = mapIndexed { index, sourcePreference ->
SourceFiltersView(index, sourcePreference)
}.map(::StableHolder).toImmutableList()
}.toImmutableList()
private companion object {
private val log = logging()

View File

@@ -12,7 +12,6 @@ import ca.gosyer.jui.domain.source.model.Source
import ca.gosyer.jui.domain.source.service.CatalogPreferences
import ca.gosyer.jui.domain.source.service.SourceRepository
import ca.gosyer.jui.i18n.MR
import ca.gosyer.jui.ui.base.model.StableHolder
import ca.gosyer.jui.uicore.vm.ContextWrapper
import ca.gosyer.jui.uicore.vm.ViewModel
import kotlinx.collections.immutable.ImmutableList
@@ -59,7 +58,7 @@ class GlobalSearchViewModel @Inject constructor(
val sources = combine(installedSources, languages) { installedSources, languages ->
installedSources.filter {
it.lang in languages || it.id == Source.LOCAL_SOURCE_ID
}.map(::StableHolder).toImmutableList()
}.toImmutableList()
}.stateIn(scope, SharingStarted.Eagerly, persistentListOf())
private val search = MutableStateFlow(params.initialQuery)
@@ -99,7 +98,7 @@ class GlobalSearchViewModel @Inject constructor(
.mapLatest { (query, sources) ->
results.clear()
supervisorScope {
sources.map { (source) ->
sources.map { source ->
async {
semaphore.withPermit {
sourceHandler
@@ -108,7 +107,7 @@ class GlobalSearchViewModel @Inject constructor(
if (it.mangaList.isEmpty()) {
Search.Failure(MR.strings.no_results_found.toPlatformString())
} else {
Search.Success(it.mangaList.map(::StableHolder).toImmutableList())
Search.Success(it.mangaList.toImmutableList())
}
}
.catch {
@@ -143,7 +142,7 @@ class GlobalSearchViewModel @Inject constructor(
sealed class Search {
object Searching : Search()
data class Success(val mangaList: ImmutableList<StableHolder<Manga>>) : Search()
data class Success(val mangaList: ImmutableList<Manga>) : Search()
data class Failure(val e: String?) : Search() {
constructor(e: Throwable) : this(e.message)
}

View File

@@ -26,7 +26,6 @@ import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import androidx.compose.ui.unit.times
import ca.gosyer.jui.domain.manga.model.Manga
import ca.gosyer.jui.ui.base.model.StableHolder
import ca.gosyer.jui.ui.sources.browse.components.SourceMangaBadges
import ca.gosyer.jui.uicore.components.mangaAspectRatio
import ca.gosyer.jui.uicore.image.ImageLoaderImage
@@ -34,10 +33,9 @@ import ca.gosyer.jui.uicore.image.ImageLoaderImage
@Composable
fun GlobalSearchMangaComfortableGridItem(
modifier: Modifier,
mangaHolder: StableHolder<Manga>,
manga: Manga,
inLibrary: Boolean
) {
val manga = mangaHolder.item
val fontStyle = LocalTextStyle.current.merge(
TextStyle(letterSpacing = 0.sp, fontFamily = FontFamily.SansSerif, fontSize = 14.sp)
)

View File

@@ -29,7 +29,6 @@ import androidx.compose.ui.text.font.FontFamily
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import ca.gosyer.jui.domain.manga.model.Manga
import ca.gosyer.jui.ui.base.model.StableHolder
import ca.gosyer.jui.ui.sources.browse.components.SourceMangaBadges
import ca.gosyer.jui.uicore.components.mangaAspectRatio
import ca.gosyer.jui.uicore.image.ImageLoaderImage
@@ -37,10 +36,9 @@ import ca.gosyer.jui.uicore.image.ImageLoaderImage
@Composable
fun GlobalSearchMangaCompactGridItem(
modifier: Modifier,
mangaHolder: StableHolder<Manga>,
manga: Manga,
inLibrary: Boolean
) {
val manga = mangaHolder.item
val fontStyle = LocalTextStyle.current.merge(
TextStyle(letterSpacing = 0.sp, fontFamily = FontFamily.SansSerif, fontSize = 14.sp)
)

View File

@@ -47,7 +47,6 @@ import ca.gosyer.jui.domain.manga.model.Manga
import ca.gosyer.jui.domain.source.model.Source
import ca.gosyer.jui.i18n.MR
import ca.gosyer.jui.ui.base.components.localeToString
import ca.gosyer.jui.ui.base.model.StableHolder
import ca.gosyer.jui.ui.base.navigation.Toolbar
import ca.gosyer.jui.ui.main.components.bottomNav
import ca.gosyer.jui.ui.sources.globalsearch.GlobalSearchViewModel.Search
@@ -63,7 +62,7 @@ import kotlinx.collections.immutable.ImmutableList
@Composable
fun GlobalSearchScreenContent(
sources: ImmutableList<StableHolder<Source>>,
sources: ImmutableList<Source>,
results: SnapshotStateMap<Long, Search>,
displayMode: DisplayMode,
query: String,
@@ -91,17 +90,17 @@ fun GlobalSearchScreenContent(
val state = rememberLazyListState()
val sourcesSuccess by remember(sources) {
derivedStateOf {
sources.filter { results[it.item.id] is Search.Success }
sources.filter { results[it.id] is Search.Success }
}
}
val loadingSources by remember(sources) {
derivedStateOf {
sources.filter { results[it.item.id] == null }
sources.filter { results[it.id] == null }
}
}
val failedSources by remember(sources) {
derivedStateOf {
sources.filter { results[it.item.id] is Search.Failure }
sources.filter { results[it.id] is Search.Failure }
}
}
LazyColumn(
@@ -115,8 +114,8 @@ fun GlobalSearchScreenContent(
) {
items(sourcesSuccess) {
GlobalSearchItem(
sourceHolder = it,
search = results[it.item.id] ?: Search.Searching,
source = it,
search = results[it.id] ?: Search.Searching,
displayMode = displayMode,
onSourceClick = onSourceClick,
onMangaClick = onMangaClick
@@ -124,8 +123,8 @@ fun GlobalSearchScreenContent(
}
items(loadingSources) {
GlobalSearchItem(
sourceHolder = it,
search = results[it.item.id] ?: Search.Searching,
source = it,
search = results[it.id] ?: Search.Searching,
displayMode = displayMode,
onSourceClick = onSourceClick,
onMangaClick = onMangaClick
@@ -133,8 +132,8 @@ fun GlobalSearchScreenContent(
}
items(failedSources) {
GlobalSearchItem(
sourceHolder = it,
search = results[it.item.id] ?: Search.Searching,
source = it,
search = results[it.id] ?: Search.Searching,
displayMode = displayMode,
onSourceClick = onSourceClick,
onMangaClick = onMangaClick
@@ -160,13 +159,12 @@ fun GlobalSearchScreenContent(
@Composable
fun GlobalSearchItem(
sourceHolder: StableHolder<Source>,
source: Source,
search: Search,
displayMode: DisplayMode,
onSourceClick: (Source) -> Unit,
onMangaClick: (Manga) -> Unit
) {
val source = sourceHolder.item
Column {
Row(
Modifier.fillMaxWidth()
@@ -209,15 +207,15 @@ fun GlobalSearchItem(
items(search.mangaList) {
if (displayMode == DisplayMode.ComfortableGrid) {
GlobalSearchMangaComfortableGridItem(
Modifier.clickable { onMangaClick(it.item) },
Modifier.clickable { onMangaClick(it) },
it,
it.item.inLibrary
it.inLibrary
)
} else {
GlobalSearchMangaCompactGridItem(
Modifier.clickable { onMangaClick(it.item) },
Modifier.clickable { onMangaClick(it) },
it,
it.item.inLibrary
it.inLibrary
)
}
}

View File

@@ -9,7 +9,6 @@ package ca.gosyer.jui.ui.sources.settings
import ca.gosyer.jui.domain.source.model.sourcepreference.SourcePreference
import ca.gosyer.jui.domain.source.model.sourcepreference.SourcePreferenceChange
import ca.gosyer.jui.domain.source.service.SourceRepository
import ca.gosyer.jui.ui.base.model.StableHolder
import ca.gosyer.jui.ui.sources.settings.model.SourceSettingsView
import ca.gosyer.jui.uicore.vm.ContextWrapper
import ca.gosyer.jui.uicore.vm.ViewModel
@@ -37,14 +36,14 @@ class SourceSettingsScreenViewModel @Inject constructor(
private val _loading = MutableStateFlow(true)
val loading = _loading.asStateFlow()
private val _sourceSettings = MutableStateFlow<ImmutableList<StableHolder<SourceSettingsView<*, *>>>>(persistentListOf())
private val _sourceSettings = MutableStateFlow<ImmutableList<SourceSettingsView<*, *>>>(persistentListOf())
val sourceSettings = _sourceSettings.asStateFlow()
init {
getSourceSettings()
sourceSettings.mapLatest { settings ->
supervisorScope {
settings.forEach { (setting) ->
settings.forEach { setting ->
setting.state.drop(1)
.filterNotNull()
.onEach {
@@ -78,7 +77,7 @@ class SourceSettingsScreenViewModel @Inject constructor(
private fun List<SourcePreference>.toView() = mapIndexed { index, sourcePreference ->
SourceSettingsView(index, sourcePreference)
}.map(::StableHolder).toImmutableList()
}.toImmutableList()
private companion object {
private val log = logging()

View File

@@ -31,7 +31,6 @@ import androidx.compose.ui.Modifier
import ca.gosyer.jui.i18n.MR
import ca.gosyer.jui.presentation.build.BuildKonfig
import ca.gosyer.jui.ui.base.dialog.getMaterialDialogProperties
import ca.gosyer.jui.ui.base.model.StableHolder
import ca.gosyer.jui.ui.base.navigation.Toolbar
import ca.gosyer.jui.ui.base.prefs.ChoiceDialog
import ca.gosyer.jui.ui.base.prefs.MultiSelectDialog
@@ -61,7 +60,7 @@ import kotlinx.collections.immutable.ImmutableList
@Composable
fun SourceSettingsScreenContent(
settings: ImmutableList<StableHolder<SourceSettingsView<*, *>>>
settings: ImmutableList<SourceSettingsView<*, *>>
) {
Scaffold(
modifier = Modifier.windowInsetsPadding(
@@ -84,20 +83,20 @@ fun SourceSettingsScreenContent(
)
).asPaddingValues()
) {
items(settings, { it.item.props.hashCode() }) {
items(settings, { it.props.hashCode() }) {
@Suppress("UNCHECKED_CAST")
when (it.item) {
when (it) {
is CheckBox, is Switch -> {
TwoStatePreference(it as StableHolder<TwoState>, it.item is CheckBox)
TwoStatePreference(it as TwoState, it is CheckBox)
}
is List -> {
ListPreference(it as StableHolder<List>)
ListPreference(it)
}
is EditText -> {
EditTextPreference(it as StableHolder<EditText>)
EditTextPreference(it)
}
is MultiSelect -> {
MultiSelectPreference(it as StableHolder<MultiSelect>)
MultiSelectPreference(it)
}
}
}
@@ -120,8 +119,7 @@ fun SourceSettingsScreenContent(
}
@Composable
private fun TwoStatePreference(twoStateHolder: StableHolder<TwoState>, checkbox: Boolean) {
val twoState = twoStateHolder.item
private fun TwoStatePreference(twoState: TwoState, checkbox: Boolean) {
val state by twoState.state.collectAsState()
val title = remember(state) { twoState.title ?: twoState.summary ?: "No title" }
val subtitle = remember(state) {
@@ -146,8 +144,7 @@ private fun TwoStatePreference(twoStateHolder: StableHolder<TwoState>, checkbox:
}
@Composable
private fun ListPreference(listHolder: StableHolder<List>) {
val list = listHolder.item
private fun ListPreference(list: List) {
val state by list.state.collectAsState()
val title = remember(state) { list.title ?: list.summary ?: "No title" }
val subtitle = remember(state) {
@@ -175,8 +172,7 @@ private fun ListPreference(listHolder: StableHolder<List>) {
}
@Composable
private fun MultiSelectPreference(multiSelectHolder: StableHolder<MultiSelect>) {
val multiSelect = multiSelectHolder.item
private fun MultiSelectPreference(multiSelect: MultiSelect) {
val state by multiSelect.state.collectAsState()
val title = remember(state) { multiSelect.title ?: multiSelect.summary ?: "No title" }
val subtitle = remember(state) {
@@ -205,8 +201,7 @@ private fun MultiSelectPreference(multiSelectHolder: StableHolder<MultiSelect>)
}
@Composable
private fun EditTextPreference(editTextHolder: StableHolder<EditText>) {
val editText = editTextHolder.item
private fun EditTextPreference(editText: EditText) {
val state by editText.state.collectAsState()
val title = remember(state) { editText.title ?: editText.summary ?: "No title" }
val subtitle = remember(state) {