mirror of
https://github.com/Suwayomi/TachideskJUI.git
synced 2025-12-10 06:42:05 +01:00
Library filtering and sorting modes
This commit is contained in:
@@ -9,12 +9,25 @@ package ca.gosyer.jui.data.library
|
||||
import ca.gosyer.jui.core.prefs.Preference
|
||||
import ca.gosyer.jui.core.prefs.PreferenceStore
|
||||
import ca.gosyer.jui.data.library.model.DisplayMode
|
||||
import ca.gosyer.jui.data.library.model.FilterState
|
||||
import ca.gosyer.jui.data.library.model.Sort
|
||||
|
||||
class LibraryPreferences(private val preferenceStore: PreferenceStore) {
|
||||
|
||||
fun displayMode(): Preference<DisplayMode> {
|
||||
return preferenceStore.getJsonObject("display_mode", DisplayMode.CompactGrid, DisplayMode.serializer())
|
||||
fun showAllCategory(): Preference<Boolean> {
|
||||
return preferenceStore.getBoolean("show_all_category", false)
|
||||
}
|
||||
|
||||
fun filterDownloaded(): Preference<FilterState> {
|
||||
return preferenceStore.getJsonObject("filter_downloaded", FilterState.IGNORED, FilterState.serializer())
|
||||
}
|
||||
|
||||
fun filterUnread(): Preference<FilterState> {
|
||||
return preferenceStore.getJsonObject("filter_unread", FilterState.IGNORED, FilterState.serializer())
|
||||
}
|
||||
|
||||
fun filterCompleted(): Preference<FilterState> {
|
||||
return preferenceStore.getJsonObject("filter_completed", FilterState.IGNORED, FilterState.serializer())
|
||||
}
|
||||
|
||||
fun sortMode(): Preference<Sort> {
|
||||
@@ -25,6 +38,10 @@ class LibraryPreferences(private val preferenceStore: PreferenceStore) {
|
||||
return preferenceStore.getBoolean("sort_ascending", true)
|
||||
}
|
||||
|
||||
fun displayMode(): Preference<DisplayMode> {
|
||||
return preferenceStore.getJsonObject("display_mode", DisplayMode.CompactGrid, DisplayMode.serializer())
|
||||
}
|
||||
|
||||
fun gridColumns(): Preference<Int> {
|
||||
return preferenceStore.getInt("grid_columns", 0)
|
||||
}
|
||||
@@ -33,7 +50,19 @@ class LibraryPreferences(private val preferenceStore: PreferenceStore) {
|
||||
return preferenceStore.getInt("grid_size", 160)
|
||||
}
|
||||
|
||||
fun showAllCategory(): Preference<Boolean> {
|
||||
return preferenceStore.getBoolean("show_all_category", false)
|
||||
fun unreadBadge(): Preference<Boolean> {
|
||||
return preferenceStore.getBoolean("unread_badge", true)
|
||||
}
|
||||
|
||||
fun downloadBadge(): Preference<Boolean> {
|
||||
return preferenceStore.getBoolean("download_badge", false)
|
||||
}
|
||||
|
||||
fun languageBadge(): Preference<Boolean> {
|
||||
return preferenceStore.getBoolean("language_badge", false)
|
||||
}
|
||||
|
||||
fun localBadge(): Preference<Boolean> {
|
||||
return preferenceStore.getBoolean("local_badge", false)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,6 +19,6 @@ enum class DisplayMode(@Transient val res: StringResource) {
|
||||
List(MR.strings.display_list);
|
||||
|
||||
companion object {
|
||||
val values = values()
|
||||
val values = values().asList()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
/*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package ca.gosyer.jui.data.library.model
|
||||
|
||||
import kotlinx.serialization.Serializable
|
||||
|
||||
@Serializable
|
||||
enum class FilterState {
|
||||
IGNORED,
|
||||
INCLUDED,
|
||||
EXCLUDED
|
||||
}
|
||||
@@ -6,18 +6,21 @@
|
||||
|
||||
package ca.gosyer.jui.data.library.model
|
||||
|
||||
import ca.gosyer.jui.i18n.MR
|
||||
import dev.icerock.moko.resources.StringResource
|
||||
import kotlinx.serialization.Serializable
|
||||
import kotlinx.serialization.Transient
|
||||
|
||||
@Serializable
|
||||
enum class Sort {
|
||||
ALPHABETICAL,
|
||||
enum class Sort(@Transient val res: StringResource) {
|
||||
ALPHABETICAL(MR.strings.sort_alphabetical),
|
||||
|
||||
// LAST_READ,
|
||||
// LAST_CHECKED,
|
||||
UNREAD,
|
||||
UNREAD(MR.strings.sort_unread),
|
||||
|
||||
// TOTAL_CHAPTERS,
|
||||
// LATEST_CHAPTER,
|
||||
// DATE_FETCHED,
|
||||
DATE_ADDED;
|
||||
DATE_ADDED(MR.strings.sort_date_added);
|
||||
}
|
||||
|
||||
@@ -45,6 +45,7 @@
|
||||
<string name="action_more_actions">More actions</string>
|
||||
<string name="action_ok">Ok</string>
|
||||
<string name="action_browser">Browser</string>
|
||||
<string name="action_filter">Filter</string>
|
||||
|
||||
<!-- Locations -->
|
||||
<string name="location_library">Library</string>
|
||||
@@ -81,6 +82,23 @@
|
||||
<string name="default_category">Default</string>
|
||||
<string name="library_empty">Library is empty</string>
|
||||
|
||||
<string name="library_sort">Sort</string>
|
||||
<string name="library_display">Display</string>
|
||||
|
||||
<string name="filter_downloaded">Downloaded</string>
|
||||
<string name="filter_unread">Unread</string>
|
||||
<string name="filter_completed">Completed</string>
|
||||
|
||||
<string name="sort_alphabetical">Alphabetically</string>
|
||||
<string name="sort_unread">Unread</string>
|
||||
<string name="sort_date_added">Date added</string>
|
||||
|
||||
<string name="display_badges">Badges</string>
|
||||
<string name="display_badge_downloaded">Downloaded chapters</string>
|
||||
<string name="display_badge_unread">Unread chapters</string>
|
||||
<string name="display_badge_local">Local manga</string>
|
||||
<string name="display_badge_language">Language</string>
|
||||
|
||||
<!-- Manga Menu -->
|
||||
<string name="page_progress">Page %1$d</string>
|
||||
<string name="no_chapters_found">No chapters found</string>
|
||||
@@ -100,7 +118,6 @@
|
||||
<string name="move_to_browse">Browse</string>
|
||||
<string name="move_to_latest">Latest</string>
|
||||
<string name="reset_filters">Reset</string>
|
||||
<string name="filter_source">Filter</string>
|
||||
<string name="in_library">In library</string>
|
||||
<string name="no_results_found">No results found</string>
|
||||
|
||||
|
||||
@@ -11,6 +11,7 @@ import ca.gosyer.jui.ui.categories.CategoriesScreenViewModel
|
||||
import ca.gosyer.jui.ui.downloads.DownloadsScreenViewModel
|
||||
import ca.gosyer.jui.ui.extensions.ExtensionsScreenViewModel
|
||||
import ca.gosyer.jui.ui.library.LibraryScreenViewModel
|
||||
import ca.gosyer.jui.ui.library.settings.LibrarySettingsViewModel
|
||||
import ca.gosyer.jui.ui.main.MainViewModel
|
||||
import ca.gosyer.jui.ui.main.about.AboutViewModel
|
||||
import ca.gosyer.jui.ui.main.components.DebugOverlayViewModel
|
||||
@@ -43,6 +44,7 @@ actual class ViewModelFactoryImpl(
|
||||
private val downloadsFactory: (Boolean) -> DownloadsScreenViewModel,
|
||||
private val extensionsFactory: () -> ExtensionsScreenViewModel,
|
||||
private val libraryFactory: () -> LibraryScreenViewModel,
|
||||
private val librarySettingsFactory: () -> LibrarySettingsViewModel,
|
||||
private val debugOverlayFactory: () -> DebugOverlayViewModel,
|
||||
private val mainFactory: () -> MainViewModel,
|
||||
private val mangaFactory: (params: MangaScreenViewModel.Params) -> MangaScreenViewModel,
|
||||
@@ -72,6 +74,7 @@ actual class ViewModelFactoryImpl(
|
||||
DownloadsScreenViewModel::class -> downloadsFactory(arg1 as Boolean)
|
||||
ExtensionsScreenViewModel::class -> extensionsFactory()
|
||||
LibraryScreenViewModel::class -> libraryFactory()
|
||||
LibrarySettingsViewModel::class -> librarySettingsFactory()
|
||||
DebugOverlayViewModel::class -> debugOverlayFactory()
|
||||
MainViewModel::class -> mainFactory()
|
||||
MangaScreenViewModel::class -> mangaFactory(arg1 as MangaScreenViewModel.Params)
|
||||
|
||||
@@ -9,6 +9,10 @@ package ca.gosyer.jui.ui.library
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.collectAsState
|
||||
import ca.gosyer.jui.ui.library.components.LibraryScreenContent
|
||||
import ca.gosyer.jui.ui.library.settings.LibrarySettingsViewModel
|
||||
import ca.gosyer.jui.ui.library.settings.getLibraryDisplay
|
||||
import ca.gosyer.jui.ui.library.settings.getLibraryFilters
|
||||
import ca.gosyer.jui.ui.library.settings.getLibrarySort
|
||||
import ca.gosyer.jui.ui.manga.MangaScreen
|
||||
import ca.gosyer.jui.uicore.vm.viewModel
|
||||
import cafe.adriel.voyager.core.screen.Screen
|
||||
@@ -24,6 +28,7 @@ class LibraryScreen : Screen {
|
||||
@Composable
|
||||
override fun Content() {
|
||||
val vm = viewModel<LibraryScreenViewModel>()
|
||||
val settingsVM = viewModel<LibrarySettingsViewModel>()
|
||||
val navigator = LocalNavigator.currentOrThrow
|
||||
LibraryScreenContent(
|
||||
categories = vm.categories.collectAsState().value,
|
||||
@@ -38,7 +43,16 @@ class LibraryScreen : Screen {
|
||||
getLibraryForPage = { vm.getLibraryForCategoryId(it).collectAsState() },
|
||||
onPageChanged = vm::setSelectedPage,
|
||||
onClickManga = { navigator push MangaScreen(it) },
|
||||
onRemoveMangaClicked = vm::removeManga
|
||||
onRemoveMangaClicked = vm::removeManga,
|
||||
showingMenu = vm.showingMenu.collectAsState().value,
|
||||
setShowingMenu = vm::setShowingMenu,
|
||||
libraryFilters = getLibraryFilters(settingsVM),
|
||||
librarySort = getLibrarySort(settingsVM),
|
||||
libraryDisplay = getLibraryDisplay(settingsVM),
|
||||
showUnread = vm.unreadBadges.collectAsState().value,
|
||||
showDownloaded = vm.downloadBadges.collectAsState().value,
|
||||
showLanguage = vm.languageBadges.collectAsState().value,
|
||||
showLocal = vm.localBadges.collectAsState().value
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,10 +9,13 @@ package ca.gosyer.jui.ui.library
|
||||
import ca.gosyer.jui.core.lang.getDefault
|
||||
import ca.gosyer.jui.core.lang.lowercase
|
||||
import ca.gosyer.jui.core.lang.withDefaultContext
|
||||
import ca.gosyer.jui.core.prefs.getAsFlow
|
||||
import ca.gosyer.jui.data.library.LibraryPreferences
|
||||
import ca.gosyer.jui.data.library.model.FilterState
|
||||
import ca.gosyer.jui.data.library.model.Sort
|
||||
import ca.gosyer.jui.data.models.Category
|
||||
import ca.gosyer.jui.data.models.Manga
|
||||
import ca.gosyer.jui.data.models.MangaStatus
|
||||
import ca.gosyer.jui.data.server.interactions.CategoryInteractionHandler
|
||||
import ca.gosyer.jui.data.server.interactions.LibraryInteractionHandler
|
||||
import ca.gosyer.jui.data.server.interactions.UpdatesInteractionHandler
|
||||
@@ -67,13 +70,42 @@ class LibraryScreenViewModel @Inject constructor(
|
||||
private val _selectedCategoryIndex = MutableStateFlow(0)
|
||||
val selectedCategoryIndex = _selectedCategoryIndex.asStateFlow()
|
||||
|
||||
private val _showingMenu = MutableStateFlow(false)
|
||||
val showingMenu = _showingMenu.asStateFlow()
|
||||
|
||||
val displayMode = libraryPreferences.displayMode().stateIn(scope)
|
||||
val gridColumns = libraryPreferences.gridColumns().stateIn(scope)
|
||||
val gridSize = libraryPreferences.gridSize().stateIn(scope)
|
||||
val unreadBadges = libraryPreferences.unreadBadge().stateIn(scope)
|
||||
val downloadBadges = libraryPreferences.downloadBadge().stateIn(scope)
|
||||
val languageBadges = libraryPreferences.languageBadge().stateIn(scope)
|
||||
val localBadges = libraryPreferences.localBadge().stateIn(scope)
|
||||
|
||||
private val sortMode = libraryPreferences.sortMode().stateIn(scope)
|
||||
private val sortAscending = libraryPreferences.sortAscending().stateIn(scope)
|
||||
|
||||
private val filter = 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
|
||||
FilterState.IGNORED -> true
|
||||
} && when (unread) {
|
||||
FilterState.EXCLUDED -> manga.unreadCount == null || manga.unreadCount == 0
|
||||
FilterState.INCLUDED -> manga.unreadCount != null && (manga.unreadCount ?: 0) > 0
|
||||
FilterState.IGNORED -> true
|
||||
} && when (completed) {
|
||||
FilterState.EXCLUDED -> manga.status != MangaStatus.COMPLETED
|
||||
FilterState.INCLUDED -> manga.status == MangaStatus.COMPLETED
|
||||
FilterState.IGNORED -> true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private val _isLoading = MutableStateFlow(true)
|
||||
val isLoading = _isLoading.asStateFlow()
|
||||
|
||||
@@ -114,6 +146,10 @@ class LibraryScreenViewModel @Inject constructor(
|
||||
_selectedCategoryIndex.value = page
|
||||
}
|
||||
|
||||
fun setShowingMenu(showingMenu: Boolean) {
|
||||
_showingMenu.value = showingMenu
|
||||
}
|
||||
|
||||
private fun getComparator(sortMode: Sort, ascending: Boolean): Comparator<Manga> {
|
||||
val sortFn = when (sortMode) {
|
||||
Sort.ALPHABETICAL -> {
|
||||
@@ -164,6 +200,8 @@ class LibraryScreenViewModel @Inject constructor(
|
||||
private fun getMangaItemsFlow(unfilteredItemsFlow: StateFlow<List<Manga>>): StateFlow<List<Manga>> {
|
||||
return combine(unfilteredItemsFlow, query) { unfilteredItems, query ->
|
||||
filterManga(query, unfilteredItems)
|
||||
}.combine(filter) { filteredManga, filterer ->
|
||||
filteredManga.filter(filterer)
|
||||
}.combine(comparator) { filteredManga, comparator ->
|
||||
filteredManga.sortedWith(comparator)
|
||||
}.stateIn(scope, SharingStarted.Eagerly, emptyList())
|
||||
|
||||
@@ -7,7 +7,10 @@
|
||||
package ca.gosyer.jui.ui.library.components
|
||||
|
||||
import androidx.compose.foundation.background
|
||||
import androidx.compose.foundation.layout.Arrangement
|
||||
import androidx.compose.foundation.layout.Row
|
||||
import androidx.compose.foundation.layout.Spacer
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.material.MaterialTheme
|
||||
import androidx.compose.material.Text
|
||||
@@ -15,33 +18,66 @@ import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.draw.clip
|
||||
import androidx.compose.ui.unit.dp
|
||||
import ca.gosyer.jui.data.models.Manga
|
||||
import ca.gosyer.jui.data.models.Source
|
||||
|
||||
@Composable
|
||||
fun LibraryMangaBadges(
|
||||
unread: Int?,
|
||||
downloaded: Int?,
|
||||
modifier: Modifier = Modifier,
|
||||
manga: Manga,
|
||||
showUnread: Boolean,
|
||||
showDownloaded: Boolean,
|
||||
showLanguage: Boolean,
|
||||
showLocal: Boolean
|
||||
) {
|
||||
if (unread == null && downloaded == null) return
|
||||
val unread = manga.unreadCount
|
||||
val downloaded = manga.downloadCount
|
||||
val isLocal = manga.sourceId == Source.LOCAL_SOURCE_ID
|
||||
|
||||
Row(modifier = modifier.clip(MaterialTheme.shapes.medium)) {
|
||||
if (unread != null && unread > 0) {
|
||||
Text(
|
||||
text = unread.toString(),
|
||||
modifier = Modifier.background(MaterialTheme.colors.primary).then(BadgesInnerPadding),
|
||||
style = MaterialTheme.typography.caption,
|
||||
color = MaterialTheme.colors.onPrimary
|
||||
)
|
||||
Row(modifier then Modifier.fillMaxWidth(), horizontalArrangement = Arrangement.SpaceBetween) {
|
||||
if ((unread != null && unread > 0) || (downloaded != null && downloaded > 0) || isLocal) {
|
||||
Row(modifier = Modifier.clip(MaterialTheme.shapes.medium)) {
|
||||
if (showLocal && isLocal) {
|
||||
Text(
|
||||
text = unread.toString(),
|
||||
modifier = Modifier.background(MaterialTheme.colors.secondary).then(BadgesInnerPadding),
|
||||
style = MaterialTheme.typography.caption,
|
||||
color = MaterialTheme.colors.onSecondary
|
||||
)
|
||||
}
|
||||
if (showUnread && unread != null && unread > 0) {
|
||||
Text(
|
||||
text = unread.toString(),
|
||||
modifier = Modifier.background(MaterialTheme.colors.primary).then(BadgesInnerPadding),
|
||||
style = MaterialTheme.typography.caption,
|
||||
color = MaterialTheme.colors.onPrimary
|
||||
)
|
||||
}
|
||||
if (showDownloaded && downloaded != null && downloaded > 0) {
|
||||
Text(
|
||||
text = downloaded.toString(),
|
||||
modifier = Modifier.background(MaterialTheme.colors.secondary).then(
|
||||
BadgesInnerPadding
|
||||
),
|
||||
style = MaterialTheme.typography.caption,
|
||||
color = MaterialTheme.colors.onSecondary
|
||||
)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
Spacer(Modifier)
|
||||
}
|
||||
if (downloaded != null && downloaded > 0) {
|
||||
Text(
|
||||
text = downloaded.toString(),
|
||||
modifier = Modifier.background(MaterialTheme.colors.secondary).then(
|
||||
BadgesInnerPadding
|
||||
),
|
||||
style = MaterialTheme.typography.caption,
|
||||
color = MaterialTheme.colors.onSecondary
|
||||
)
|
||||
|
||||
val lang = manga.source?.lang
|
||||
if (showLanguage && lang != null) {
|
||||
Row(modifier = Modifier.clip(MaterialTheme.shapes.medium)) {
|
||||
Text(
|
||||
text = lang.uppercase(),
|
||||
modifier = Modifier.background(MaterialTheme.colors.secondary).then(BadgesInnerPadding),
|
||||
style = MaterialTheme.typography.caption,
|
||||
color = MaterialTheme.colors.onSecondary
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,11 +7,13 @@
|
||||
package ca.gosyer.jui.ui.library.components
|
||||
|
||||
import androidx.compose.foundation.layout.Box
|
||||
import androidx.compose.foundation.layout.IntrinsicSize
|
||||
import androidx.compose.foundation.layout.fillMaxHeight
|
||||
import androidx.compose.foundation.layout.fillMaxSize
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.layout.requiredHeight
|
||||
import androidx.compose.foundation.layout.size
|
||||
import androidx.compose.foundation.layout.width
|
||||
import androidx.compose.foundation.lazy.LazyColumn
|
||||
import androidx.compose.foundation.lazy.items
|
||||
import androidx.compose.foundation.lazy.rememberLazyListState
|
||||
@@ -34,7 +36,11 @@ import io.kamel.image.lazyPainterResource
|
||||
fun LibraryMangaList(
|
||||
library: List<Manga>,
|
||||
onClickManga: (Long) -> Unit,
|
||||
onRemoveMangaClicked: (Long) -> Unit
|
||||
onRemoveMangaClicked: (Long) -> Unit,
|
||||
showUnread: Boolean,
|
||||
showDownloaded: Boolean,
|
||||
showLanguage: Boolean,
|
||||
showLocal: Boolean
|
||||
) {
|
||||
Box {
|
||||
val state = rememberLazyListState()
|
||||
@@ -49,8 +55,10 @@ fun LibraryMangaList(
|
||||
{ onRemoveMangaClicked(manga.id) }
|
||||
),
|
||||
manga = manga,
|
||||
unread = manga.unreadCount,
|
||||
downloaded = manga.downloadCount,
|
||||
showUnread = showUnread,
|
||||
showDownloaded = showDownloaded,
|
||||
showLanguage = showLanguage,
|
||||
showLocal = showLocal
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -67,8 +75,10 @@ fun LibraryMangaList(
|
||||
private fun LibraryMangaListItem(
|
||||
modifier: Modifier,
|
||||
manga: Manga,
|
||||
unread: Int?,
|
||||
downloaded: Int?,
|
||||
showUnread: Boolean,
|
||||
showDownloaded: Boolean,
|
||||
showLanguage: Boolean,
|
||||
showLocal: Boolean
|
||||
) {
|
||||
val cover = lazyPainterResource(manga, filterQuality = FilterQuality.Medium)
|
||||
MangaListItem(
|
||||
@@ -89,6 +99,14 @@ private fun LibraryMangaListItem(
|
||||
.padding(horizontal = 16.dp),
|
||||
text = manga.title,
|
||||
)
|
||||
LibraryMangaBadges(unread, downloaded)
|
||||
Box(Modifier.width(IntrinsicSize.Min)) {
|
||||
LibraryMangaBadges(
|
||||
manga = manga,
|
||||
showUnread = showUnread,
|
||||
showDownloaded = showDownloaded,
|
||||
showLanguage = showLanguage,
|
||||
showLocal = showLocal
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -25,7 +25,11 @@ fun LibraryPager(
|
||||
gridSize: Int,
|
||||
getLibraryForPage: @Composable (Long) -> State<List<Manga>>,
|
||||
onClickManga: (Long) -> Unit,
|
||||
onRemoveMangaClicked: (Long) -> Unit
|
||||
onRemoveMangaClicked: (Long) -> Unit,
|
||||
showUnread: Boolean,
|
||||
showDownloaded: Boolean,
|
||||
showLanguage: Boolean,
|
||||
showLocal: Boolean
|
||||
) {
|
||||
if (categories.isEmpty()) return
|
||||
|
||||
@@ -37,26 +41,42 @@ fun LibraryPager(
|
||||
gridColumns = gridColumns,
|
||||
gridSize = gridSize,
|
||||
onClickManga = onClickManga,
|
||||
onRemoveMangaClicked = onRemoveMangaClicked
|
||||
onRemoveMangaClicked = onRemoveMangaClicked,
|
||||
showUnread = showUnread,
|
||||
showDownloaded = showDownloaded,
|
||||
showLanguage = showLanguage,
|
||||
showLocal = showLocal
|
||||
)
|
||||
DisplayMode.ComfortableGrid -> LibraryMangaComfortableGrid(
|
||||
library = library,
|
||||
gridColumns = gridColumns,
|
||||
gridSize = gridSize,
|
||||
onClickManga = onClickManga,
|
||||
onRemoveMangaClicked = onRemoveMangaClicked
|
||||
onRemoveMangaClicked = onRemoveMangaClicked,
|
||||
showUnread = showUnread,
|
||||
showDownloaded = showDownloaded,
|
||||
showLanguage = showLanguage,
|
||||
showLocal = showLocal
|
||||
)
|
||||
DisplayMode.CoverOnlyGrid -> LibraryMangaCoverOnlyGrid(
|
||||
library = library,
|
||||
gridColumns = gridColumns,
|
||||
gridSize = gridSize,
|
||||
onClickManga = onClickManga,
|
||||
onRemoveMangaClicked = onRemoveMangaClicked
|
||||
onRemoveMangaClicked = onRemoveMangaClicked,
|
||||
showUnread = showUnread,
|
||||
showDownloaded = showDownloaded,
|
||||
showLanguage = showLanguage,
|
||||
showLocal = showLocal
|
||||
)
|
||||
DisplayMode.List -> LibraryMangaList(
|
||||
library = library,
|
||||
onClickManga = onClickManga,
|
||||
onRemoveMangaClicked = onRemoveMangaClicked
|
||||
onRemoveMangaClicked = onRemoveMangaClicked,
|
||||
showUnread = showUnread,
|
||||
showDownloaded = showDownloaded,
|
||||
showLanguage = showLanguage,
|
||||
showLocal = showLocal
|
||||
)
|
||||
else -> Box {}
|
||||
}
|
||||
|
||||
@@ -6,23 +6,40 @@
|
||||
|
||||
package ca.gosyer.jui.ui.library.components
|
||||
|
||||
import androidx.compose.animation.AnimatedVisibility
|
||||
import androidx.compose.animation.fadeIn
|
||||
import androidx.compose.animation.fadeOut
|
||||
import androidx.compose.animation.slideInHorizontally
|
||||
import androidx.compose.animation.slideOutHorizontally
|
||||
import androidx.compose.foundation.gestures.detectTapGestures
|
||||
import androidx.compose.foundation.gestures.forEachGesture
|
||||
import androidx.compose.foundation.layout.Box
|
||||
import androidx.compose.foundation.layout.BoxWithConstraints
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.fillMaxSize
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.material.BottomSheetScaffold
|
||||
import androidx.compose.material.ModalBottomSheetLayout
|
||||
import androidx.compose.material.ModalBottomSheetValue
|
||||
import androidx.compose.material.Scaffold
|
||||
import androidx.compose.material.rememberBottomSheetScaffoldState
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.rounded.FilterList
|
||||
import androidx.compose.material.rememberModalBottomSheetState
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.LaunchedEffect
|
||||
import androidx.compose.runtime.Stable
|
||||
import androidx.compose.runtime.State
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.input.pointer.pointerInput
|
||||
import androidx.compose.ui.unit.dp
|
||||
import ca.gosyer.jui.data.library.model.DisplayMode
|
||||
import ca.gosyer.jui.data.models.Category
|
||||
import ca.gosyer.jui.data.models.Manga
|
||||
import ca.gosyer.jui.i18n.MR
|
||||
import ca.gosyer.jui.ui.base.navigation.ActionItem
|
||||
import ca.gosyer.jui.ui.base.navigation.Toolbar
|
||||
import ca.gosyer.jui.ui.library.settings.LibrarySheet
|
||||
import ca.gosyer.jui.ui.library.settings.LibrarySideMenu
|
||||
import ca.gosyer.jui.uicore.components.LoadingScreen
|
||||
import ca.gosyer.jui.uicore.resources.stringResource
|
||||
import com.google.accompanist.pager.PagerState
|
||||
@@ -42,7 +59,16 @@ fun LibraryScreenContent(
|
||||
getLibraryForPage: @Composable (Long) -> State<List<Manga>>,
|
||||
onPageChanged: (Int) -> Unit,
|
||||
onClickManga: (Long) -> Unit,
|
||||
onRemoveMangaClicked: (Long) -> Unit
|
||||
onRemoveMangaClicked: (Long) -> Unit,
|
||||
showingMenu: Boolean,
|
||||
setShowingMenu: (Boolean) -> Unit,
|
||||
libraryFilters: @Composable () -> Unit,
|
||||
librarySort: @Composable () -> Unit,
|
||||
libraryDisplay: @Composable () -> Unit,
|
||||
showUnread: Boolean,
|
||||
showDownloaded: Boolean,
|
||||
showLanguage: Boolean,
|
||||
showLocal: Boolean
|
||||
) {
|
||||
BoxWithConstraints {
|
||||
val pagerState = rememberPagerState(selectedCategoryIndex)
|
||||
@@ -71,7 +97,16 @@ fun LibraryScreenContent(
|
||||
getLibraryForPage = getLibraryForPage,
|
||||
onPageChanged = onPageChanged,
|
||||
onClickManga = onClickManga,
|
||||
onRemoveMangaClicked = onRemoveMangaClicked
|
||||
onRemoveMangaClicked = onRemoveMangaClicked,
|
||||
showingMenu = showingMenu,
|
||||
setShowingMenu = setShowingMenu,
|
||||
libraryFilters = libraryFilters,
|
||||
librarySort = librarySort,
|
||||
libraryDisplay = libraryDisplay,
|
||||
showUnread = showUnread,
|
||||
showDownloaded = showDownloaded,
|
||||
showLanguage = showLanguage,
|
||||
showLocal = showLocal
|
||||
)
|
||||
} else {
|
||||
ThinLibraryScreenContent(
|
||||
@@ -88,7 +123,16 @@ fun LibraryScreenContent(
|
||||
getLibraryForPage = getLibraryForPage,
|
||||
onPageChanged = onPageChanged,
|
||||
onClickManga = onClickManga,
|
||||
onRemoveMangaClicked = onRemoveMangaClicked
|
||||
onRemoveMangaClicked = onRemoveMangaClicked,
|
||||
showingSheet = showingMenu,
|
||||
setShowingSheet = setShowingMenu,
|
||||
libraryFilters = libraryFilters,
|
||||
librarySort = librarySort,
|
||||
libraryDisplay = libraryDisplay,
|
||||
showUnread = showUnread,
|
||||
showDownloaded = showDownloaded,
|
||||
showLanguage = showLanguage,
|
||||
showLocal = showLocal
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -109,7 +153,16 @@ fun WideLibraryScreenContent(
|
||||
getLibraryForPage: @Composable (Long) -> State<List<Manga>>,
|
||||
onPageChanged: (Int) -> Unit,
|
||||
onClickManga: (Long) -> Unit,
|
||||
onRemoveMangaClicked: (Long) -> Unit
|
||||
onRemoveMangaClicked: (Long) -> Unit,
|
||||
showingMenu: Boolean,
|
||||
setShowingMenu: (Boolean) -> Unit,
|
||||
libraryFilters: @Composable () -> Unit,
|
||||
librarySort: @Composable () -> Unit,
|
||||
libraryDisplay: @Composable () -> Unit,
|
||||
showUnread: Boolean,
|
||||
showDownloaded: Boolean,
|
||||
showLanguage: Boolean,
|
||||
showLocal: Boolean
|
||||
) {
|
||||
Scaffold(
|
||||
topBar = {
|
||||
@@ -117,7 +170,12 @@ fun WideLibraryScreenContent(
|
||||
Toolbar(
|
||||
stringResource(MR.strings.location_library),
|
||||
searchText = query,
|
||||
search = updateQuery
|
||||
search = updateQuery,
|
||||
actions = {
|
||||
getActionItems(
|
||||
onToggleFiltersClick = { setShowingMenu(true) }
|
||||
)
|
||||
}
|
||||
)
|
||||
LibraryTabs(
|
||||
visible = true, // vm.showCategoryTabs,
|
||||
@@ -128,8 +186,8 @@ fun WideLibraryScreenContent(
|
||||
)
|
||||
}
|
||||
}
|
||||
) {
|
||||
Box(Modifier.padding(it)) {
|
||||
) { padding ->
|
||||
Box(Modifier.padding(padding)) {
|
||||
if (categories.isEmpty()) {
|
||||
LoadingScreen(isLoading, errorMessage = error)
|
||||
} else {
|
||||
@@ -141,8 +199,36 @@ fun WideLibraryScreenContent(
|
||||
gridSize = gridSize,
|
||||
getLibraryForPage = getLibraryForPage,
|
||||
onClickManga = onClickManga,
|
||||
onRemoveMangaClicked = onRemoveMangaClicked
|
||||
onRemoveMangaClicked = onRemoveMangaClicked,
|
||||
showUnread = showUnread,
|
||||
showDownloaded = showDownloaded,
|
||||
showLanguage = showLanguage,
|
||||
showLocal = showLocal
|
||||
)
|
||||
|
||||
if (showingMenu) {
|
||||
Box(
|
||||
Modifier.fillMaxSize().pointerInput(isLoading) {
|
||||
forEachGesture {
|
||||
detectTapGestures {
|
||||
setShowingMenu(false)
|
||||
}
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
||||
AnimatedVisibility(
|
||||
showingMenu,
|
||||
enter = fadeIn() + slideInHorizontally(initialOffsetX = { it * 2 }),
|
||||
exit = fadeOut() + slideOutHorizontally(targetOffsetX = { it * 2 }),
|
||||
modifier = Modifier.align(Alignment.TopEnd)
|
||||
) {
|
||||
LibrarySideMenu(
|
||||
libraryFilters = libraryFilters,
|
||||
librarySort = librarySort,
|
||||
libraryDisplay = libraryDisplay
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -163,17 +249,47 @@ fun ThinLibraryScreenContent(
|
||||
getLibraryForPage: @Composable (Long) -> State<List<Manga>>,
|
||||
onPageChanged: (Int) -> Unit,
|
||||
onClickManga: (Long) -> Unit,
|
||||
onRemoveMangaClicked: (Long) -> Unit
|
||||
onRemoveMangaClicked: (Long) -> Unit,
|
||||
showingSheet: Boolean,
|
||||
setShowingSheet: (Boolean) -> Unit,
|
||||
libraryFilters: @Composable () -> Unit,
|
||||
librarySort: @Composable () -> Unit,
|
||||
libraryDisplay: @Composable () -> Unit,
|
||||
showUnread: Boolean,
|
||||
showDownloaded: Boolean,
|
||||
showLanguage: Boolean,
|
||||
showLocal: Boolean
|
||||
) {
|
||||
val sheetState = rememberBottomSheetScaffoldState()
|
||||
BottomSheetScaffold(
|
||||
scaffoldState = sheetState,
|
||||
val bottomSheetState = rememberModalBottomSheetState(
|
||||
ModalBottomSheetValue.Hidden,
|
||||
confirmStateChange = {
|
||||
when (it) {
|
||||
ModalBottomSheetValue.Hidden -> setShowingSheet(false)
|
||||
ModalBottomSheetValue.Expanded,
|
||||
ModalBottomSheetValue.HalfExpanded -> setShowingSheet(true)
|
||||
}
|
||||
true
|
||||
}
|
||||
)
|
||||
LaunchedEffect(showingSheet) {
|
||||
if (showingSheet) {
|
||||
bottomSheetState.show()
|
||||
} else {
|
||||
bottomSheetState.hide()
|
||||
}
|
||||
}
|
||||
Scaffold(
|
||||
topBar = {
|
||||
Column {
|
||||
Toolbar(
|
||||
stringResource(MR.strings.location_library),
|
||||
searchText = query,
|
||||
search = updateQuery
|
||||
search = updateQuery,
|
||||
actions = {
|
||||
getActionItems(
|
||||
onToggleFiltersClick = { setShowingSheet(true) }
|
||||
)
|
||||
}
|
||||
)
|
||||
LibraryTabs(
|
||||
visible = true, // vm.showCategoryTabs,
|
||||
@@ -183,13 +299,19 @@ fun ThinLibraryScreenContent(
|
||||
onPageChanged = onPageChanged
|
||||
)
|
||||
}
|
||||
},
|
||||
sheetContent = {
|
||||
// LibrarySheetContent()
|
||||
},
|
||||
sheetPeekHeight = 0.dp
|
||||
) {
|
||||
Box(Modifier.padding(it)) {
|
||||
}
|
||||
) { padding ->
|
||||
ModalBottomSheetLayout(
|
||||
sheetState = bottomSheetState,
|
||||
modifier = Modifier.padding(padding),
|
||||
sheetContent = {
|
||||
LibrarySheet(
|
||||
libraryFilters = libraryFilters,
|
||||
librarySort = librarySort,
|
||||
libraryDisplay = libraryDisplay
|
||||
)
|
||||
}
|
||||
) {
|
||||
if (categories.isEmpty()) {
|
||||
LoadingScreen(isLoading, errorMessage = error)
|
||||
} else {
|
||||
@@ -201,9 +323,27 @@ fun ThinLibraryScreenContent(
|
||||
gridSize = gridSize,
|
||||
getLibraryForPage = getLibraryForPage,
|
||||
onClickManga = onClickManga,
|
||||
onRemoveMangaClicked = onRemoveMangaClicked
|
||||
onRemoveMangaClicked = onRemoveMangaClicked,
|
||||
showUnread = showUnread,
|
||||
showDownloaded = showDownloaded,
|
||||
showLanguage = showLanguage,
|
||||
showLocal = showLocal
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
@Stable
|
||||
private fun getActionItems(
|
||||
onToggleFiltersClick: () -> Unit,
|
||||
): List<ActionItem> {
|
||||
return listOfNotNull(
|
||||
ActionItem(
|
||||
name = stringResource(MR.strings.action_filter),
|
||||
icon = Icons.Rounded.FilterList,
|
||||
doAction = onToggleFiltersClick
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -43,7 +43,11 @@ fun LibraryMangaComfortableGrid(
|
||||
gridColumns: Int,
|
||||
gridSize: Int,
|
||||
onClickManga: (Long) -> Unit,
|
||||
onRemoveMangaClicked: (Long) -> Unit
|
||||
onRemoveMangaClicked: (Long) -> Unit,
|
||||
showUnread: Boolean,
|
||||
showDownloaded: Boolean,
|
||||
showLanguage: Boolean,
|
||||
showLocal: Boolean
|
||||
) {
|
||||
Box {
|
||||
val state = rememberLazyListState()
|
||||
@@ -64,8 +68,10 @@ fun LibraryMangaComfortableGrid(
|
||||
{ onRemoveMangaClicked(manga.id) }
|
||||
),
|
||||
manga = manga,
|
||||
unread = manga.unreadCount,
|
||||
downloaded = manga.downloadCount
|
||||
showUnread = showUnread,
|
||||
showDownloaded = showDownloaded,
|
||||
showLanguage = showLanguage,
|
||||
showLocal = showLocal
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -82,8 +88,10 @@ fun LibraryMangaComfortableGrid(
|
||||
private fun LibraryMangaComfortableGridItem(
|
||||
modifier: Modifier,
|
||||
manga: Manga,
|
||||
unread: Int?,
|
||||
downloaded: Int?
|
||||
showUnread: Boolean,
|
||||
showDownloaded: Boolean,
|
||||
showLanguage: Boolean,
|
||||
showLocal: Boolean
|
||||
) {
|
||||
val cover = lazyPainterResource(manga, filterQuality = FilterQuality.Medium)
|
||||
val fontStyle = LocalTextStyle.current.merge(
|
||||
@@ -114,9 +122,12 @@ private fun LibraryMangaComfortableGridItem(
|
||||
)
|
||||
}
|
||||
LibraryMangaBadges(
|
||||
unread = unread,
|
||||
downloaded = downloaded,
|
||||
modifier = Modifier.padding(4.dp)
|
||||
modifier = Modifier.padding(4.dp),
|
||||
manga = manga,
|
||||
showUnread = showUnread,
|
||||
showDownloaded = showDownloaded,
|
||||
showLanguage = showLanguage,
|
||||
showLocal = showLocal
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -51,7 +51,11 @@ fun LibraryMangaCompactGrid(
|
||||
gridColumns: Int,
|
||||
gridSize: Int,
|
||||
onClickManga: (Long) -> Unit,
|
||||
onRemoveMangaClicked: (Long) -> Unit
|
||||
onRemoveMangaClicked: (Long) -> Unit,
|
||||
showUnread: Boolean,
|
||||
showDownloaded: Boolean,
|
||||
showLanguage: Boolean,
|
||||
showLocal: Boolean
|
||||
) {
|
||||
Box {
|
||||
val state = rememberLazyListState()
|
||||
@@ -72,8 +76,10 @@ fun LibraryMangaCompactGrid(
|
||||
{ onRemoveMangaClicked(manga.id) }
|
||||
),
|
||||
manga = manga,
|
||||
unread = manga.unreadCount,
|
||||
downloaded = manga.downloadCount
|
||||
showUnread = showUnread,
|
||||
showDownloaded = showDownloaded,
|
||||
showLanguage = showLanguage,
|
||||
showLocal = showLocal
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -90,8 +96,10 @@ fun LibraryMangaCompactGrid(
|
||||
private fun LibraryMangaCompactGridItem(
|
||||
modifier: Modifier,
|
||||
manga: Manga,
|
||||
unread: Int?,
|
||||
downloaded: Int?,
|
||||
showUnread: Boolean,
|
||||
showDownloaded: Boolean,
|
||||
showLanguage: Boolean,
|
||||
showLocal: Boolean
|
||||
) {
|
||||
val cover = lazyPainterResource(manga, filterQuality = FilterQuality.Medium)
|
||||
val fontStyle = LocalTextStyle.current.merge(
|
||||
@@ -119,9 +127,12 @@ private fun LibraryMangaCompactGridItem(
|
||||
modifier = Modifier.align(Alignment.BottomStart).padding(8.dp)
|
||||
)
|
||||
LibraryMangaBadges(
|
||||
unread = unread,
|
||||
downloaded = downloaded,
|
||||
modifier = Modifier.padding(4.dp)
|
||||
modifier = Modifier.padding(4.dp),
|
||||
manga = manga,
|
||||
showUnread = showUnread,
|
||||
showDownloaded = showDownloaded,
|
||||
showLanguage = showLanguage,
|
||||
showLocal = showLocal
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -37,7 +37,11 @@ fun LibraryMangaCoverOnlyGrid(
|
||||
gridColumns: Int,
|
||||
gridSize: Int,
|
||||
onClickManga: (Long) -> Unit,
|
||||
onRemoveMangaClicked: (Long) -> Unit
|
||||
onRemoveMangaClicked: (Long) -> Unit,
|
||||
showUnread: Boolean,
|
||||
showDownloaded: Boolean,
|
||||
showLanguage: Boolean,
|
||||
showLocal: Boolean
|
||||
) {
|
||||
Box {
|
||||
val state = rememberLazyListState()
|
||||
@@ -58,8 +62,10 @@ fun LibraryMangaCoverOnlyGrid(
|
||||
{ onRemoveMangaClicked(manga.id) }
|
||||
),
|
||||
manga = manga,
|
||||
unread = manga.unreadCount,
|
||||
downloaded = manga.downloadCount
|
||||
showUnread = showUnread,
|
||||
showDownloaded = showDownloaded,
|
||||
showLanguage = showLanguage,
|
||||
showLocal = showLocal
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -76,8 +82,10 @@ fun LibraryMangaCoverOnlyGrid(
|
||||
private fun LibraryMangaCoverOnlyGridItem(
|
||||
modifier: Modifier,
|
||||
manga: Manga,
|
||||
unread: Int?,
|
||||
downloaded: Int?
|
||||
showUnread: Boolean,
|
||||
showDownloaded: Boolean,
|
||||
showLanguage: Boolean,
|
||||
showLocal: Boolean
|
||||
) {
|
||||
val cover = lazyPainterResource(manga, filterQuality = FilterQuality.Medium)
|
||||
|
||||
@@ -94,9 +102,12 @@ private fun LibraryMangaCoverOnlyGridItem(
|
||||
contentScale = ContentScale.Crop
|
||||
)
|
||||
LibraryMangaBadges(
|
||||
unread = unread,
|
||||
downloaded = downloaded,
|
||||
modifier = Modifier.padding(4.dp)
|
||||
modifier = Modifier.padding(4.dp),
|
||||
manga = manga,
|
||||
showUnread = showUnread,
|
||||
showDownloaded = showDownloaded,
|
||||
showLanguage = showLanguage,
|
||||
showLocal = showLocal
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,127 @@
|
||||
/*
|
||||
* 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.ui.library.settings
|
||||
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.material.Checkbox
|
||||
import androidx.compose.material.RadioButton
|
||||
import androidx.compose.material.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.collectAsState
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.text.font.FontWeight
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.compose.ui.util.fastForEach
|
||||
import ca.gosyer.jui.data.library.model.DisplayMode
|
||||
import ca.gosyer.jui.i18n.MR
|
||||
import ca.gosyer.jui.ui.sources.browse.filter.SourceFilterAction
|
||||
import ca.gosyer.jui.uicore.resources.stringResource
|
||||
|
||||
@Composable
|
||||
fun getLibraryDisplay(vm: LibrarySettingsViewModel): @Composable () -> Unit = remember(vm) {
|
||||
@Composable {
|
||||
LibraryDisplay(
|
||||
displayMode = vm.displayMode.collectAsState().value,
|
||||
unreadBadges = vm.unreadBadges.collectAsState().value,
|
||||
downloadBadges = vm.downloadBadges.collectAsState().value,
|
||||
languageBadges = vm.languageBadges.collectAsState().value,
|
||||
localBadges = vm.localBadges.collectAsState().value,
|
||||
setDisplayMode = { vm.displayMode.value = it },
|
||||
setUnreadBadges = { vm.unreadBadges.value = it },
|
||||
setDownloadBadges = { vm.downloadBadges.value = it },
|
||||
setLanguageBadges = { vm.languageBadges.value = it },
|
||||
setLocalBadges = { vm.localBadges.value = it }
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun LibraryDisplay(
|
||||
displayMode: DisplayMode,
|
||||
unreadBadges: Boolean,
|
||||
downloadBadges: Boolean,
|
||||
languageBadges: Boolean,
|
||||
localBadges: Boolean,
|
||||
setDisplayMode: (DisplayMode) -> Unit,
|
||||
setUnreadBadges: (Boolean) -> Unit,
|
||||
setDownloadBadges: (Boolean) -> Unit,
|
||||
setLanguageBadges: (Boolean) -> Unit,
|
||||
setLocalBadges: (Boolean) -> Unit
|
||||
) {
|
||||
Column(Modifier.fillMaxWidth()) {
|
||||
TitleText(stringResource(MR.strings.display_mode))
|
||||
DisplayMode.values.fastForEach {
|
||||
RadioSelectionItem(
|
||||
text = stringResource(it.res),
|
||||
selected = it == displayMode,
|
||||
onClick = { setDisplayMode(it) }
|
||||
)
|
||||
}
|
||||
TitleText(stringResource(MR.strings.display_badges))
|
||||
CheckboxItem(
|
||||
text = stringResource(MR.strings.display_badge_downloaded),
|
||||
checked = downloadBadges,
|
||||
onClick = { setDownloadBadges(!downloadBadges) }
|
||||
)
|
||||
CheckboxItem(
|
||||
text = stringResource(MR.strings.display_badge_unread),
|
||||
checked = unreadBadges,
|
||||
onClick = { setUnreadBadges(!unreadBadges) }
|
||||
)
|
||||
CheckboxItem(
|
||||
text = stringResource(MR.strings.display_badge_local),
|
||||
checked = localBadges,
|
||||
onClick = { setLocalBadges(!localBadges) }
|
||||
)
|
||||
// TODO: 2022-04-06 Enable when library contains manga source in manga object
|
||||
/*CheckboxItem(
|
||||
text = stringResource(MR.strings.display_badge_language),
|
||||
checked = languageBadges,
|
||||
onClick = { setLanguageBadges(!languageBadges) }
|
||||
)*/
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun TitleText(text: String) {
|
||||
Text(
|
||||
text = text,
|
||||
fontWeight = FontWeight.Bold,
|
||||
modifier = Modifier.padding(horizontal = 8.dp, vertical = 4.dp)
|
||||
)
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun RadioSelectionItem(text: String, selected: Boolean, onClick: () -> Unit) {
|
||||
SourceFilterAction(
|
||||
name = text,
|
||||
onClick = onClick,
|
||||
action = {
|
||||
RadioButton(
|
||||
selected = selected,
|
||||
onClick = null
|
||||
)
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun CheckboxItem(text: String, checked: Boolean, onClick: () -> Unit) {
|
||||
SourceFilterAction(
|
||||
name = text,
|
||||
onClick = onClick,
|
||||
action = {
|
||||
Checkbox(
|
||||
checked = checked,
|
||||
onCheckedChange = null
|
||||
)
|
||||
}
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,86 @@
|
||||
/*
|
||||
* 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.ui.library.settings
|
||||
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.material.TriStateCheckbox
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.collectAsState
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.state.ToggleableState
|
||||
import ca.gosyer.jui.data.library.model.FilterState
|
||||
import ca.gosyer.jui.i18n.MR
|
||||
import ca.gosyer.jui.ui.sources.browse.filter.SourceFilterAction
|
||||
import ca.gosyer.jui.uicore.resources.stringResource
|
||||
|
||||
@Composable
|
||||
fun getLibraryFilters(vm: LibrarySettingsViewModel): @Composable () -> Unit = remember(vm) {
|
||||
@Composable {
|
||||
LibraryFilters(
|
||||
downloaded = vm.filterDownloaded.collectAsState().value,
|
||||
unread = vm.filterUnread.collectAsState().value,
|
||||
completed = vm.filterCompleted.collectAsState().value,
|
||||
setDownloadedFilter = { vm.filterDownloaded.value = it },
|
||||
setUnreadFilter = { vm.filterUnread.value = it },
|
||||
setCompletedFilter = { vm.filterCompleted.value = it },
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun LibraryFilters(
|
||||
downloaded: FilterState,
|
||||
unread: FilterState,
|
||||
completed: FilterState,
|
||||
setDownloadedFilter: (FilterState) -> Unit,
|
||||
setUnreadFilter: (FilterState) -> Unit,
|
||||
setCompletedFilter: (FilterState) -> Unit,
|
||||
) {
|
||||
Column(Modifier.fillMaxWidth()) {
|
||||
Filter(
|
||||
stringResource(MR.strings.filter_downloaded),
|
||||
downloaded,
|
||||
onClick = { setDownloadedFilter(toggleState(downloaded)) }
|
||||
)
|
||||
Filter(
|
||||
stringResource(MR.strings.filter_unread),
|
||||
unread,
|
||||
onClick = { setUnreadFilter(toggleState(unread)) }
|
||||
)
|
||||
Filter(
|
||||
stringResource(MR.strings.filter_completed),
|
||||
completed,
|
||||
onClick = { setCompletedFilter(toggleState(completed)) }
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
fun toggleState(filterState: FilterState) = when (filterState) {
|
||||
FilterState.IGNORED -> FilterState.INCLUDED
|
||||
FilterState.INCLUDED -> FilterState.EXCLUDED
|
||||
FilterState.EXCLUDED -> FilterState.IGNORED
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun Filter(text: String, state: FilterState, onClick: () -> Unit) {
|
||||
SourceFilterAction(
|
||||
text,
|
||||
onClick = onClick,
|
||||
action = {
|
||||
TriStateCheckbox(
|
||||
state = when (state) {
|
||||
FilterState.INCLUDED -> ToggleableState.On
|
||||
FilterState.EXCLUDED -> ToggleableState.Indeterminate
|
||||
FilterState.IGNORED -> ToggleableState.Off
|
||||
},
|
||||
onClick = null
|
||||
)
|
||||
}
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
/*
|
||||
* 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.ui.library.settings
|
||||
|
||||
import ca.gosyer.jui.data.library.LibraryPreferences
|
||||
import ca.gosyer.jui.uicore.vm.ContextWrapper
|
||||
import ca.gosyer.jui.uicore.vm.ViewModel
|
||||
import me.tatarka.inject.annotations.Inject
|
||||
|
||||
class LibrarySettingsViewModel @Inject constructor(
|
||||
libraryPreferences: LibraryPreferences,
|
||||
contextWrapper: ContextWrapper
|
||||
) : ViewModel(contextWrapper) {
|
||||
val filterDownloaded = libraryPreferences.filterDownloaded().asStateFlow()
|
||||
val filterUnread = libraryPreferences.filterUnread().asStateFlow()
|
||||
val filterCompleted = libraryPreferences.filterCompleted().asStateFlow()
|
||||
|
||||
val sortMode = libraryPreferences.sortMode().asStateFlow()
|
||||
val sortAscending = libraryPreferences.sortAscending().asStateFlow()
|
||||
|
||||
val displayMode = libraryPreferences.displayMode().asStateFlow()
|
||||
val unreadBadges = libraryPreferences.unreadBadge().asStateFlow()
|
||||
val downloadBadges = libraryPreferences.downloadBadge().asStateFlow()
|
||||
val languageBadges = libraryPreferences.languageBadge().asStateFlow()
|
||||
val localBadges = libraryPreferences.localBadge().asStateFlow()
|
||||
}
|
||||
@@ -0,0 +1,98 @@
|
||||
/*
|
||||
* 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.ui.library.settings
|
||||
|
||||
import androidx.compose.foundation.layout.Box
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.fillMaxHeight
|
||||
import androidx.compose.foundation.layout.fillMaxSize
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.rememberScrollState
|
||||
import androidx.compose.foundation.verticalScroll
|
||||
import androidx.compose.material.Tab
|
||||
import androidx.compose.material.TabRow
|
||||
import androidx.compose.material.TabRowDefaults
|
||||
import androidx.compose.material.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.rememberCoroutineScope
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.compose.ui.util.fastForEachIndexed
|
||||
import ca.gosyer.jui.i18n.MR
|
||||
import ca.gosyer.jui.uicore.components.VerticalScrollbar
|
||||
import ca.gosyer.jui.uicore.components.rememberScrollbarAdapter
|
||||
import ca.gosyer.jui.uicore.resources.stringResource
|
||||
import com.google.accompanist.pager.HorizontalPager
|
||||
import com.google.accompanist.pager.pagerTabIndicatorOffset
|
||||
import com.google.accompanist.pager.rememberPagerState
|
||||
import dev.icerock.moko.resources.StringResource
|
||||
import kotlinx.coroutines.launch
|
||||
|
||||
enum class LibrarySheetTabs(val res: StringResource) {
|
||||
FILTERS(MR.strings.action_filter),
|
||||
SORT(MR.strings.library_sort),
|
||||
DISPLAY(MR.strings.library_display)
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun LibrarySheet(
|
||||
libraryFilters: @Composable () -> Unit,
|
||||
librarySort: @Composable () -> Unit,
|
||||
libraryDisplay: @Composable () -> Unit
|
||||
) {
|
||||
val pagerState = rememberPagerState()
|
||||
val selectedPage = pagerState.currentPage
|
||||
val scope = rememberCoroutineScope()
|
||||
Column(Modifier.fillMaxSize()) {
|
||||
TabRow(
|
||||
selectedTabIndex = pagerState.currentPage,
|
||||
indicator = { tabPositions ->
|
||||
TabRowDefaults.Indicator(
|
||||
Modifier.pagerTabIndicatorOffset(pagerState, tabPositions)
|
||||
)
|
||||
}
|
||||
) {
|
||||
LibrarySheetTabs.values().asList().fastForEachIndexed { index, tab ->
|
||||
Tab(
|
||||
selected = selectedPage == index,
|
||||
onClick = {
|
||||
scope.launch { pagerState.animateScrollToPage(index) }
|
||||
},
|
||||
text = { Text(stringResource(tab.res)) }
|
||||
)
|
||||
}
|
||||
}
|
||||
HorizontalPager(
|
||||
count = LibrarySheetTabs.values().size,
|
||||
state = pagerState,
|
||||
verticalAlignment = Alignment.Top
|
||||
) {
|
||||
val scrollState = rememberScrollState()
|
||||
Box {
|
||||
Column(
|
||||
Modifier.fillMaxWidth()
|
||||
.verticalScroll(scrollState)
|
||||
) {
|
||||
when (it) {
|
||||
LibrarySheetTabs.FILTERS.ordinal -> libraryFilters()
|
||||
LibrarySheetTabs.SORT.ordinal -> librarySort()
|
||||
LibrarySheetTabs.DISPLAY.ordinal -> libraryDisplay()
|
||||
}
|
||||
}
|
||||
|
||||
VerticalScrollbar(
|
||||
rememberScrollbarAdapter(scrollState),
|
||||
Modifier.align(Alignment.CenterEnd)
|
||||
.fillMaxHeight()
|
||||
.padding(horizontal = 4.dp, vertical = 8.dp)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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.ui.library.settings
|
||||
|
||||
import androidx.compose.foundation.layout.Box
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.fillMaxHeight
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.layout.width
|
||||
import androidx.compose.foundation.rememberScrollState
|
||||
import androidx.compose.foundation.verticalScroll
|
||||
import androidx.compose.material.Divider
|
||||
import androidx.compose.material.Surface
|
||||
import androidx.compose.material.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.text.font.FontWeight
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.compose.ui.unit.sp
|
||||
import ca.gosyer.jui.i18n.MR
|
||||
import ca.gosyer.jui.uicore.components.VerticalScrollbar
|
||||
import ca.gosyer.jui.uicore.components.rememberScrollbarAdapter
|
||||
import ca.gosyer.jui.uicore.resources.stringResource
|
||||
|
||||
@Composable
|
||||
fun LibrarySideMenu(
|
||||
libraryFilters: @Composable () -> Unit,
|
||||
librarySort: @Composable () -> Unit,
|
||||
libraryDisplay: @Composable () -> Unit,
|
||||
) {
|
||||
Surface(Modifier.fillMaxHeight().width(260.dp), elevation = 1.dp) {
|
||||
Box {
|
||||
val scrollState = rememberScrollState()
|
||||
Column(
|
||||
Modifier.fillMaxWidth()
|
||||
.verticalScroll(scrollState)
|
||||
) {
|
||||
TitleText(stringResource(MR.strings.action_filter))
|
||||
libraryFilters()
|
||||
Divider()
|
||||
TitleText(stringResource(MR.strings.library_sort))
|
||||
librarySort()
|
||||
Divider()
|
||||
TitleText(stringResource(MR.strings.library_display))
|
||||
libraryDisplay()
|
||||
}
|
||||
|
||||
VerticalScrollbar(
|
||||
rememberScrollbarAdapter(scrollState),
|
||||
Modifier.align(Alignment.CenterEnd)
|
||||
.fillMaxHeight()
|
||||
.padding(horizontal = 4.dp, vertical = 8.dp)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun TitleText(text: String) {
|
||||
Box(Modifier.fillMaxWidth().padding(vertical = 8.dp), contentAlignment = Alignment.Center) {
|
||||
Text(text, fontWeight = FontWeight.Bold, fontSize = 18.sp)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,78 @@
|
||||
/*
|
||||
* 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.ui.library.settings
|
||||
|
||||
import androidx.compose.foundation.layout.Box
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.fillMaxHeight
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.size
|
||||
import androidx.compose.material.Icon
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.rounded.ArrowDownward
|
||||
import androidx.compose.material.icons.rounded.ArrowUpward
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.collectAsState
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.compose.ui.util.fastForEach
|
||||
import ca.gosyer.jui.data.library.model.Sort
|
||||
import ca.gosyer.jui.ui.sources.browse.filter.SourceFilterAction
|
||||
import ca.gosyer.jui.uicore.resources.stringResource
|
||||
|
||||
@Composable
|
||||
fun getLibrarySort(vm: LibrarySettingsViewModel): @Composable () -> Unit = remember(vm) {
|
||||
@Composable {
|
||||
LibrarySort(
|
||||
mode = vm.sortMode.collectAsState().value,
|
||||
ascending = vm.sortAscending.collectAsState().value,
|
||||
setMode = {
|
||||
vm.sortMode.value = it
|
||||
vm.sortAscending.value = true
|
||||
},
|
||||
setAscending = { vm.sortAscending.value = it }
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun LibrarySort(
|
||||
mode: Sort,
|
||||
ascending: Boolean,
|
||||
setMode: (Sort) -> Unit,
|
||||
setAscending: (Boolean) -> Unit
|
||||
) {
|
||||
Column(Modifier.fillMaxWidth()) {
|
||||
Sort.values().asList().fastForEach { sort ->
|
||||
SourceFilterAction(
|
||||
name = stringResource(sort.res),
|
||||
onClick = {
|
||||
if (mode == sort) {
|
||||
setAscending(!ascending)
|
||||
} else {
|
||||
setMode(sort)
|
||||
}
|
||||
},
|
||||
action = {
|
||||
if (mode == sort) {
|
||||
Icon(
|
||||
imageVector = when (ascending) {
|
||||
true -> Icons.Rounded.ArrowUpward
|
||||
false -> Icons.Rounded.ArrowDownward
|
||||
},
|
||||
contentDescription = stringResource(sort.res),
|
||||
modifier = Modifier.fillMaxHeight()
|
||||
)
|
||||
} else {
|
||||
Box(Modifier.size(24.dp))
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -353,7 +353,7 @@ private fun SourceThinScreenContent(
|
||||
if (showFilterButton && !isLatest) {
|
||||
ExtendedFloatingActionButton(
|
||||
text = {
|
||||
Text(stringResource(MR.strings.filter_source))
|
||||
Text(stringResource(MR.strings.action_filter))
|
||||
},
|
||||
onClick = {
|
||||
setShowingFilters(true)
|
||||
@@ -361,7 +361,7 @@ private fun SourceThinScreenContent(
|
||||
icon = {
|
||||
Icon(
|
||||
Icons.Rounded.FilterList,
|
||||
stringResource(MR.strings.filter_source)
|
||||
stringResource(MR.strings.action_filter)
|
||||
)
|
||||
},
|
||||
modifier = Modifier.align(Alignment.BottomEnd)
|
||||
@@ -506,7 +506,7 @@ private fun getActionItems(
|
||||
return listOfNotNull(
|
||||
if (showFilterButton) {
|
||||
ActionItem(
|
||||
name = stringResource(MR.strings.filter_source),
|
||||
name = stringResource(MR.strings.action_filter),
|
||||
icon = Icons.Rounded.FilterList,
|
||||
doAction = onToggleFiltersClick,
|
||||
enabled = !isLatest
|
||||
|
||||
@@ -15,6 +15,7 @@ import androidx.compose.foundation.interaction.MutableInteractionSource
|
||||
import androidx.compose.foundation.layout.Arrangement
|
||||
import androidx.compose.foundation.layout.Box
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.IntrinsicSize
|
||||
import androidx.compose.foundation.layout.Row
|
||||
import androidx.compose.foundation.layout.defaultMinSize
|
||||
import androidx.compose.foundation.layout.fillMaxHeight
|
||||
@@ -86,7 +87,7 @@ fun SourceFiltersMenu(
|
||||
Text(stringResource(MR.strings.reset_filters))
|
||||
}
|
||||
Button(onSearchClicked) {
|
||||
Text(stringResource(MR.strings.filter_source))
|
||||
Text(stringResource(MR.strings.action_filter))
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -141,7 +142,8 @@ fun SourceFilterAction(
|
||||
Row(
|
||||
Modifier.fillMaxWidth().defaultMinSize(minHeight = 56.dp)
|
||||
.clickable(onClick = onClick)
|
||||
.padding(horizontal = 16.dp),
|
||||
.padding(horizontal = 16.dp)
|
||||
.height(IntrinsicSize.Min),
|
||||
verticalAlignment = Alignment.CenterVertically
|
||||
) {
|
||||
action()
|
||||
|
||||
@@ -11,10 +11,12 @@ import ca.gosyer.jui.ui.categories.CategoriesScreenViewModel
|
||||
import ca.gosyer.jui.ui.downloads.DownloadsScreenViewModel
|
||||
import ca.gosyer.jui.ui.extensions.ExtensionsScreenViewModel
|
||||
import ca.gosyer.jui.ui.library.LibraryScreenViewModel
|
||||
import ca.gosyer.jui.ui.library.settings.LibrarySettingsViewModel
|
||||
import ca.gosyer.jui.ui.main.MainViewModel
|
||||
import ca.gosyer.jui.ui.main.about.AboutViewModel
|
||||
import ca.gosyer.jui.ui.main.components.DebugOverlayViewModel
|
||||
import ca.gosyer.jui.ui.main.components.TrayViewModel
|
||||
import ca.gosyer.jui.ui.manga.MangaScreenViewModel
|
||||
import ca.gosyer.jui.ui.reader.ReaderMenuViewModel
|
||||
import ca.gosyer.jui.ui.settings.SettingsAdvancedViewModel
|
||||
import ca.gosyer.jui.ui.settings.SettingsBackupViewModel
|
||||
@@ -43,10 +45,11 @@ actual class ViewModelFactoryImpl(
|
||||
private val downloadsFactory: (Boolean) -> DownloadsScreenViewModel,
|
||||
private val extensionsFactory: () -> ExtensionsScreenViewModel,
|
||||
private val libraryFactory: () -> LibraryScreenViewModel,
|
||||
private val librarySettingsFactory: () -> LibrarySettingsViewModel,
|
||||
private val debugOverlayFactory: () -> DebugOverlayViewModel,
|
||||
private val trayFactory: () -> TrayViewModel,
|
||||
private val mainFactory: () -> MainViewModel,
|
||||
private val mangaFactory: (params: ca.gosyer.jui.ui.manga.MangaScreenViewModel.Params) -> ca.gosyer.jui.ui.manga.MangaScreenViewModel,
|
||||
private val mangaFactory: (params: MangaScreenViewModel.Params) -> MangaScreenViewModel,
|
||||
private val readerFactory: (params: ReaderMenuViewModel.Params) -> ReaderMenuViewModel,
|
||||
private val settingsAdvancedFactory: () -> SettingsAdvancedViewModel,
|
||||
private val themesFactory: () -> ThemesViewModel,
|
||||
@@ -73,10 +76,11 @@ actual class ViewModelFactoryImpl(
|
||||
DownloadsScreenViewModel::class -> downloadsFactory(arg1 as Boolean)
|
||||
ExtensionsScreenViewModel::class -> extensionsFactory()
|
||||
LibraryScreenViewModel::class -> libraryFactory()
|
||||
LibrarySettingsViewModel::class -> librarySettingsFactory()
|
||||
DebugOverlayViewModel::class -> debugOverlayFactory()
|
||||
TrayViewModel::class -> trayFactory()
|
||||
MainViewModel::class -> mainFactory()
|
||||
ca.gosyer.jui.ui.manga.MangaScreenViewModel::class -> mangaFactory(arg1 as ca.gosyer.jui.ui.manga.MangaScreenViewModel.Params)
|
||||
MangaScreenViewModel::class -> mangaFactory(arg1 as MangaScreenViewModel.Params)
|
||||
ReaderMenuViewModel::class -> readerFactory(arg1 as ReaderMenuViewModel.Params)
|
||||
SettingsAdvancedViewModel::class -> settingsAdvancedFactory()
|
||||
ThemesViewModel::class -> themesFactory()
|
||||
|
||||
Reference in New Issue
Block a user