Move SettingsItems composables to presentation-core
This commit is contained in:
parent
efabe801be
commit
87bdee5990
16 changed files with 238 additions and 250 deletions
|
@ -7,9 +7,9 @@ import eu.kanade.tachiyomi.ui.reader.setting.OrientationType
|
||||||
import eu.kanade.tachiyomi.ui.reader.setting.ReadingModeType
|
import eu.kanade.tachiyomi.ui.reader.setting.ReadingModeType
|
||||||
import tachiyomi.core.metadata.comicinfo.ComicInfo
|
import tachiyomi.core.metadata.comicinfo.ComicInfo
|
||||||
import tachiyomi.core.metadata.comicinfo.ComicInfoPublishingStatus
|
import tachiyomi.core.metadata.comicinfo.ComicInfoPublishingStatus
|
||||||
|
import tachiyomi.core.preference.TriState
|
||||||
import tachiyomi.domain.chapter.model.Chapter
|
import tachiyomi.domain.chapter.model.Chapter
|
||||||
import tachiyomi.domain.manga.model.Manga
|
import tachiyomi.domain.manga.model.Manga
|
||||||
import tachiyomi.domain.manga.model.TriStateFilter
|
|
||||||
import uy.kohesive.injekt.Injekt
|
import uy.kohesive.injekt.Injekt
|
||||||
import uy.kohesive.injekt.api.get
|
import uy.kohesive.injekt.api.get
|
||||||
|
|
||||||
|
@ -20,19 +20,19 @@ val Manga.readingModeType: Long
|
||||||
val Manga.orientationType: Long
|
val Manga.orientationType: Long
|
||||||
get() = viewerFlags and OrientationType.MASK.toLong()
|
get() = viewerFlags and OrientationType.MASK.toLong()
|
||||||
|
|
||||||
val Manga.downloadedFilter: TriStateFilter
|
val Manga.downloadedFilter: TriState
|
||||||
get() {
|
get() {
|
||||||
if (forceDownloaded()) return TriStateFilter.ENABLED_IS
|
if (forceDownloaded()) return TriState.ENABLED_IS
|
||||||
return when (downloadedFilterRaw) {
|
return when (downloadedFilterRaw) {
|
||||||
Manga.CHAPTER_SHOW_DOWNLOADED -> TriStateFilter.ENABLED_IS
|
Manga.CHAPTER_SHOW_DOWNLOADED -> TriState.ENABLED_IS
|
||||||
Manga.CHAPTER_SHOW_NOT_DOWNLOADED -> TriStateFilter.ENABLED_NOT
|
Manga.CHAPTER_SHOW_NOT_DOWNLOADED -> TriState.ENABLED_NOT
|
||||||
else -> TriStateFilter.DISABLED
|
else -> TriState.DISABLED
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fun Manga.chaptersFiltered(): Boolean {
|
fun Manga.chaptersFiltered(): Boolean {
|
||||||
return unreadFilter != TriStateFilter.DISABLED ||
|
return unreadFilter != TriState.DISABLED ||
|
||||||
downloadedFilter != TriStateFilter.DISABLED ||
|
downloadedFilter != TriState.DISABLED ||
|
||||||
bookmarkedFilter != TriStateFilter.DISABLED
|
bookmarkedFilter != TriState.DISABLED
|
||||||
}
|
}
|
||||||
fun Manga.forceDownloaded(): Boolean {
|
fun Manga.forceDownloaded(): Boolean {
|
||||||
return favorite && Injekt.get<BasePreferences>().downloadedOnly().get()
|
return favorite && Injekt.get<BasePreferences>().downloadedOnly().get()
|
||||||
|
|
|
@ -1,128 +0,0 @@
|
||||||
package eu.kanade.presentation.components
|
|
||||||
|
|
||||||
import androidx.compose.foundation.clickable
|
|
||||||
import androidx.compose.foundation.layout.Arrangement
|
|
||||||
import androidx.compose.foundation.layout.Row
|
|
||||||
import androidx.compose.foundation.layout.fillMaxWidth
|
|
||||||
import androidx.compose.foundation.layout.padding
|
|
||||||
import androidx.compose.material.ContentAlpha
|
|
||||||
import androidx.compose.material.icons.Icons
|
|
||||||
import androidx.compose.material.icons.rounded.CheckBox
|
|
||||||
import androidx.compose.material.icons.rounded.CheckBoxOutlineBlank
|
|
||||||
import androidx.compose.material.icons.rounded.DisabledByDefault
|
|
||||||
import androidx.compose.material3.DropdownMenuItem
|
|
||||||
import androidx.compose.material3.ExposedDropdownMenuBox
|
|
||||||
import androidx.compose.material3.ExposedDropdownMenuDefaults
|
|
||||||
import androidx.compose.material3.Icon
|
|
||||||
import androidx.compose.material3.MaterialTheme
|
|
||||||
import androidx.compose.material3.OutlinedTextField
|
|
||||||
import androidx.compose.material3.Text
|
|
||||||
import androidx.compose.runtime.Composable
|
|
||||||
import androidx.compose.runtime.getValue
|
|
||||||
import androidx.compose.runtime.mutableStateOf
|
|
||||||
import androidx.compose.runtime.remember
|
|
||||||
import androidx.compose.runtime.setValue
|
|
||||||
import androidx.compose.ui.Alignment
|
|
||||||
import androidx.compose.ui.Modifier
|
|
||||||
import androidx.compose.ui.unit.dp
|
|
||||||
import tachiyomi.domain.manga.model.TriStateFilter
|
|
||||||
import tachiyomi.presentation.core.components.SettingsItemsPaddings
|
|
||||||
|
|
||||||
@Composable
|
|
||||||
fun TriStateItem(
|
|
||||||
label: String,
|
|
||||||
state: TriStateFilter,
|
|
||||||
enabled: Boolean = true,
|
|
||||||
onClick: ((TriStateFilter) -> Unit)?,
|
|
||||||
) {
|
|
||||||
Row(
|
|
||||||
modifier = Modifier
|
|
||||||
.clickable(
|
|
||||||
enabled = enabled && onClick != null,
|
|
||||||
onClick = {
|
|
||||||
when (state) {
|
|
||||||
TriStateFilter.DISABLED -> onClick?.invoke(TriStateFilter.ENABLED_IS)
|
|
||||||
TriStateFilter.ENABLED_IS -> onClick?.invoke(TriStateFilter.ENABLED_NOT)
|
|
||||||
TriStateFilter.ENABLED_NOT -> onClick?.invoke(TriStateFilter.DISABLED)
|
|
||||||
}
|
|
||||||
},
|
|
||||||
)
|
|
||||||
.fillMaxWidth()
|
|
||||||
.padding(horizontal = SettingsItemsPaddings.Horizontal, vertical = SettingsItemsPaddings.Vertical),
|
|
||||||
verticalAlignment = Alignment.CenterVertically,
|
|
||||||
horizontalArrangement = Arrangement.spacedBy(24.dp),
|
|
||||||
) {
|
|
||||||
val stateAlpha = if (enabled && onClick != null) 1f else ContentAlpha.disabled
|
|
||||||
|
|
||||||
Icon(
|
|
||||||
imageVector = when (state) {
|
|
||||||
TriStateFilter.DISABLED -> Icons.Rounded.CheckBoxOutlineBlank
|
|
||||||
TriStateFilter.ENABLED_IS -> Icons.Rounded.CheckBox
|
|
||||||
TriStateFilter.ENABLED_NOT -> Icons.Rounded.DisabledByDefault
|
|
||||||
},
|
|
||||||
contentDescription = null,
|
|
||||||
tint = if (!enabled || state == TriStateFilter.DISABLED) {
|
|
||||||
MaterialTheme.colorScheme.onSurfaceVariant.copy(alpha = stateAlpha)
|
|
||||||
} else {
|
|
||||||
when (onClick) {
|
|
||||||
null -> MaterialTheme.colorScheme.onSurface.copy(alpha = ContentAlpha.disabled)
|
|
||||||
else -> MaterialTheme.colorScheme.primary
|
|
||||||
}
|
|
||||||
},
|
|
||||||
)
|
|
||||||
Text(
|
|
||||||
text = label,
|
|
||||||
color = MaterialTheme.colorScheme.onSurface.copy(alpha = stateAlpha),
|
|
||||||
style = MaterialTheme.typography.bodyMedium,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Composable
|
|
||||||
fun SelectItem(
|
|
||||||
label: String,
|
|
||||||
options: Array<out Any?>,
|
|
||||||
selectedIndex: Int,
|
|
||||||
onSelect: (Int) -> Unit,
|
|
||||||
) {
|
|
||||||
var expanded by remember { mutableStateOf(false) }
|
|
||||||
|
|
||||||
ExposedDropdownMenuBox(
|
|
||||||
expanded = expanded,
|
|
||||||
onExpandedChange = { expanded = !expanded },
|
|
||||||
) {
|
|
||||||
OutlinedTextField(
|
|
||||||
modifier = Modifier
|
|
||||||
.menuAnchor()
|
|
||||||
.fillMaxWidth()
|
|
||||||
.padding(horizontal = SettingsItemsPaddings.Horizontal, vertical = SettingsItemsPaddings.Vertical),
|
|
||||||
label = { Text(text = label) },
|
|
||||||
value = options[selectedIndex].toString(),
|
|
||||||
onValueChange = {},
|
|
||||||
readOnly = true,
|
|
||||||
singleLine = true,
|
|
||||||
trailingIcon = {
|
|
||||||
ExposedDropdownMenuDefaults.TrailingIcon(
|
|
||||||
expanded = expanded,
|
|
||||||
)
|
|
||||||
},
|
|
||||||
colors = ExposedDropdownMenuDefaults.textFieldColors(),
|
|
||||||
)
|
|
||||||
|
|
||||||
ExposedDropdownMenu(
|
|
||||||
modifier = Modifier.exposedDropdownSize(matchTextFieldWidth = true),
|
|
||||||
expanded = expanded,
|
|
||||||
onDismissRequest = { expanded = false },
|
|
||||||
) {
|
|
||||||
options.forEachIndexed { index, text ->
|
|
||||||
DropdownMenuItem(
|
|
||||||
text = { Text(text.toString()) },
|
|
||||||
onClick = {
|
|
||||||
onSelect(index)
|
|
||||||
expanded = false
|
|
||||||
},
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -14,21 +14,21 @@ import androidx.compose.ui.platform.LocalConfiguration
|
||||||
import androidx.compose.ui.res.stringResource
|
import androidx.compose.ui.res.stringResource
|
||||||
import eu.kanade.presentation.components.TabbedDialog
|
import eu.kanade.presentation.components.TabbedDialog
|
||||||
import eu.kanade.presentation.components.TabbedDialogPaddings
|
import eu.kanade.presentation.components.TabbedDialogPaddings
|
||||||
import eu.kanade.presentation.components.TriStateItem
|
|
||||||
import eu.kanade.presentation.util.collectAsState
|
import eu.kanade.presentation.util.collectAsState
|
||||||
import eu.kanade.tachiyomi.R
|
import eu.kanade.tachiyomi.R
|
||||||
import eu.kanade.tachiyomi.ui.library.LibrarySettingsScreenModel
|
import eu.kanade.tachiyomi.ui.library.LibrarySettingsScreenModel
|
||||||
|
import tachiyomi.core.preference.TriState
|
||||||
import tachiyomi.domain.category.model.Category
|
import tachiyomi.domain.category.model.Category
|
||||||
import tachiyomi.domain.library.model.LibraryDisplayMode
|
import tachiyomi.domain.library.model.LibraryDisplayMode
|
||||||
import tachiyomi.domain.library.model.LibrarySort
|
import tachiyomi.domain.library.model.LibrarySort
|
||||||
import tachiyomi.domain.library.model.sort
|
import tachiyomi.domain.library.model.sort
|
||||||
import tachiyomi.domain.library.service.LibraryPreferences
|
import tachiyomi.domain.library.service.LibraryPreferences
|
||||||
import tachiyomi.domain.manga.model.TriStateFilter
|
|
||||||
import tachiyomi.presentation.core.components.CheckboxItem
|
import tachiyomi.presentation.core.components.CheckboxItem
|
||||||
import tachiyomi.presentation.core.components.HeadingItem
|
import tachiyomi.presentation.core.components.HeadingItem
|
||||||
import tachiyomi.presentation.core.components.RadioItem
|
import tachiyomi.presentation.core.components.RadioItem
|
||||||
import tachiyomi.presentation.core.components.SliderItem
|
import tachiyomi.presentation.core.components.SliderItem
|
||||||
import tachiyomi.presentation.core.components.SortItem
|
import tachiyomi.presentation.core.components.SortItem
|
||||||
|
import tachiyomi.presentation.core.components.TriStateItem
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun LibrarySettingsDialog(
|
fun LibrarySettingsDialog(
|
||||||
|
@ -74,7 +74,7 @@ private fun ColumnScope.FilterPage(
|
||||||
TriStateItem(
|
TriStateItem(
|
||||||
label = stringResource(R.string.label_downloaded),
|
label = stringResource(R.string.label_downloaded),
|
||||||
state = if (downloadedOnly) {
|
state = if (downloadedOnly) {
|
||||||
TriStateFilter.ENABLED_IS
|
TriState.ENABLED_IS
|
||||||
} else {
|
} else {
|
||||||
filterDownloaded
|
filterDownloaded
|
||||||
},
|
},
|
||||||
|
|
|
@ -27,20 +27,20 @@ import eu.kanade.domain.manga.model.downloadedFilter
|
||||||
import eu.kanade.domain.manga.model.forceDownloaded
|
import eu.kanade.domain.manga.model.forceDownloaded
|
||||||
import eu.kanade.presentation.components.TabbedDialog
|
import eu.kanade.presentation.components.TabbedDialog
|
||||||
import eu.kanade.presentation.components.TabbedDialogPaddings
|
import eu.kanade.presentation.components.TabbedDialogPaddings
|
||||||
import eu.kanade.presentation.components.TriStateItem
|
|
||||||
import eu.kanade.tachiyomi.R
|
import eu.kanade.tachiyomi.R
|
||||||
|
import tachiyomi.core.preference.TriState
|
||||||
import tachiyomi.domain.manga.model.Manga
|
import tachiyomi.domain.manga.model.Manga
|
||||||
import tachiyomi.domain.manga.model.TriStateFilter
|
|
||||||
import tachiyomi.presentation.core.components.RadioItem
|
import tachiyomi.presentation.core.components.RadioItem
|
||||||
import tachiyomi.presentation.core.components.SortItem
|
import tachiyomi.presentation.core.components.SortItem
|
||||||
|
import tachiyomi.presentation.core.components.TriStateItem
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun ChapterSettingsDialog(
|
fun ChapterSettingsDialog(
|
||||||
onDismissRequest: () -> Unit,
|
onDismissRequest: () -> Unit,
|
||||||
manga: Manga? = null,
|
manga: Manga? = null,
|
||||||
onDownloadFilterChanged: (TriStateFilter) -> Unit,
|
onDownloadFilterChanged: (TriState) -> Unit,
|
||||||
onUnreadFilterChanged: (TriStateFilter) -> Unit,
|
onUnreadFilterChanged: (TriState) -> Unit,
|
||||||
onBookmarkedFilterChanged: (TriStateFilter) -> Unit,
|
onBookmarkedFilterChanged: (TriState) -> Unit,
|
||||||
onSortModeChanged: (Long) -> Unit,
|
onSortModeChanged: (Long) -> Unit,
|
||||||
onDisplayModeChanged: (Long) -> Unit,
|
onDisplayModeChanged: (Long) -> Unit,
|
||||||
onSetAsDefault: (applyToExistingManga: Boolean) -> Unit,
|
onSetAsDefault: (applyToExistingManga: Boolean) -> Unit,
|
||||||
|
@ -78,11 +78,11 @@ fun ChapterSettingsDialog(
|
||||||
when (page) {
|
when (page) {
|
||||||
0 -> {
|
0 -> {
|
||||||
FilterPage(
|
FilterPage(
|
||||||
downloadFilter = manga?.downloadedFilter ?: TriStateFilter.DISABLED,
|
downloadFilter = manga?.downloadedFilter ?: TriState.DISABLED,
|
||||||
onDownloadFilterChanged = onDownloadFilterChanged.takeUnless { manga?.forceDownloaded() == true },
|
onDownloadFilterChanged = onDownloadFilterChanged.takeUnless { manga?.forceDownloaded() == true },
|
||||||
unreadFilter = manga?.unreadFilter ?: TriStateFilter.DISABLED,
|
unreadFilter = manga?.unreadFilter ?: TriState.DISABLED,
|
||||||
onUnreadFilterChanged = onUnreadFilterChanged,
|
onUnreadFilterChanged = onUnreadFilterChanged,
|
||||||
bookmarkedFilter = manga?.bookmarkedFilter ?: TriStateFilter.DISABLED,
|
bookmarkedFilter = manga?.bookmarkedFilter ?: TriState.DISABLED,
|
||||||
onBookmarkedFilterChanged = onBookmarkedFilterChanged,
|
onBookmarkedFilterChanged = onBookmarkedFilterChanged,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -106,12 +106,12 @@ fun ChapterSettingsDialog(
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
private fun ColumnScope.FilterPage(
|
private fun ColumnScope.FilterPage(
|
||||||
downloadFilter: TriStateFilter,
|
downloadFilter: TriState,
|
||||||
onDownloadFilterChanged: ((TriStateFilter) -> Unit)?,
|
onDownloadFilterChanged: ((TriState) -> Unit)?,
|
||||||
unreadFilter: TriStateFilter,
|
unreadFilter: TriState,
|
||||||
onUnreadFilterChanged: (TriStateFilter) -> Unit,
|
onUnreadFilterChanged: (TriState) -> Unit,
|
||||||
bookmarkedFilter: TriStateFilter,
|
bookmarkedFilter: TriState,
|
||||||
onBookmarkedFilterChanged: (TriStateFilter) -> Unit,
|
onBookmarkedFilterChanged: (TriState) -> Unit,
|
||||||
) {
|
) {
|
||||||
TriStateItem(
|
TriStateItem(
|
||||||
label = stringResource(R.string.label_downloaded),
|
label = stringResource(R.string.label_downloaded),
|
||||||
|
|
|
@ -21,12 +21,11 @@ import eu.kanade.tachiyomi.util.system.isReleaseBuildType
|
||||||
import eu.kanade.tachiyomi.util.system.toast
|
import eu.kanade.tachiyomi.util.system.toast
|
||||||
import eu.kanade.tachiyomi.util.system.workManager
|
import eu.kanade.tachiyomi.util.system.workManager
|
||||||
import tachiyomi.core.preference.PreferenceStore
|
import tachiyomi.core.preference.PreferenceStore
|
||||||
|
import tachiyomi.core.preference.TriState
|
||||||
import tachiyomi.core.preference.getEnum
|
import tachiyomi.core.preference.getEnum
|
||||||
import tachiyomi.domain.backup.service.BackupPreferences
|
import tachiyomi.domain.backup.service.BackupPreferences
|
||||||
import tachiyomi.domain.library.service.LibraryPreferences
|
import tachiyomi.domain.library.service.LibraryPreferences
|
||||||
import tachiyomi.domain.library.service.LibraryPreferences.Companion.MANGA_NON_COMPLETED
|
import tachiyomi.domain.library.service.LibraryPreferences.Companion.MANGA_NON_COMPLETED
|
||||||
import tachiyomi.domain.manga.model.TriStateFilter
|
|
||||||
import uy.kohesive.injekt.api.get
|
|
||||||
import java.io.File
|
import java.io.File
|
||||||
|
|
||||||
object Migrations {
|
object Migrations {
|
||||||
|
@ -350,12 +349,12 @@ object Migrations {
|
||||||
remove(key)
|
remove(key)
|
||||||
|
|
||||||
val newValue = when (pref.get()) {
|
val newValue = when (pref.get()) {
|
||||||
1 -> TriStateFilter.ENABLED_IS
|
1 -> TriState.ENABLED_IS
|
||||||
2 -> TriStateFilter.ENABLED_NOT
|
2 -> TriState.ENABLED_NOT
|
||||||
else -> TriStateFilter.DISABLED
|
else -> TriState.DISABLED
|
||||||
}
|
}
|
||||||
|
|
||||||
preferenceStore.getEnum("${key}_v2", TriStateFilter.DISABLED).set(newValue)
|
preferenceStore.getEnum("${key}_v2", TriState.DISABLED).set(newValue)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,17 +16,17 @@ import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.res.stringResource
|
import androidx.compose.ui.res.stringResource
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import eu.kanade.presentation.components.AdaptiveSheet
|
import eu.kanade.presentation.components.AdaptiveSheet
|
||||||
import eu.kanade.presentation.components.SelectItem
|
|
||||||
import eu.kanade.presentation.components.TriStateItem
|
|
||||||
import eu.kanade.tachiyomi.R
|
import eu.kanade.tachiyomi.R
|
||||||
import eu.kanade.tachiyomi.source.model.Filter
|
import eu.kanade.tachiyomi.source.model.Filter
|
||||||
import eu.kanade.tachiyomi.source.model.FilterList
|
import eu.kanade.tachiyomi.source.model.FilterList
|
||||||
import tachiyomi.domain.manga.model.TriStateFilter
|
import tachiyomi.core.preference.TriState
|
||||||
import tachiyomi.presentation.core.components.CheckboxItem
|
import tachiyomi.presentation.core.components.CheckboxItem
|
||||||
import tachiyomi.presentation.core.components.CollapsibleBox
|
import tachiyomi.presentation.core.components.CollapsibleBox
|
||||||
import tachiyomi.presentation.core.components.HeadingItem
|
import tachiyomi.presentation.core.components.HeadingItem
|
||||||
|
import tachiyomi.presentation.core.components.SelectItem
|
||||||
import tachiyomi.presentation.core.components.SortItem
|
import tachiyomi.presentation.core.components.SortItem
|
||||||
import tachiyomi.presentation.core.components.TextItem
|
import tachiyomi.presentation.core.components.TextItem
|
||||||
|
import tachiyomi.presentation.core.components.TriStateItem
|
||||||
import tachiyomi.presentation.core.components.material.Button
|
import tachiyomi.presentation.core.components.material.Button
|
||||||
import tachiyomi.presentation.core.components.material.Divider
|
import tachiyomi.presentation.core.components.material.Divider
|
||||||
|
|
||||||
|
@ -164,19 +164,19 @@ private fun FilterItem(filter: Filter<*>, onUpdate: () -> Unit) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun Int.toTriStateFilter(): TriStateFilter {
|
private fun Int.toTriStateFilter(): TriState {
|
||||||
return when (this) {
|
return when (this) {
|
||||||
Filter.TriState.STATE_IGNORE -> TriStateFilter.DISABLED
|
Filter.TriState.STATE_IGNORE -> TriState.DISABLED
|
||||||
Filter.TriState.STATE_INCLUDE -> TriStateFilter.ENABLED_IS
|
Filter.TriState.STATE_INCLUDE -> TriState.ENABLED_IS
|
||||||
Filter.TriState.STATE_EXCLUDE -> TriStateFilter.ENABLED_NOT
|
Filter.TriState.STATE_EXCLUDE -> TriState.ENABLED_NOT
|
||||||
else -> throw IllegalStateException("Unknown TriState state: $this")
|
else -> throw IllegalStateException("Unknown TriState state: $this")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun TriStateFilter.toTriStateInt(): Int {
|
private fun TriState.toTriStateInt(): Int {
|
||||||
return when (this) {
|
return when (this) {
|
||||||
TriStateFilter.DISABLED -> Filter.TriState.STATE_IGNORE
|
TriState.DISABLED -> Filter.TriState.STATE_IGNORE
|
||||||
TriStateFilter.ENABLED_IS -> Filter.TriState.STATE_INCLUDE
|
TriState.ENABLED_IS -> Filter.TriState.STATE_INCLUDE
|
||||||
TriStateFilter.ENABLED_NOT -> Filter.TriState.STATE_EXCLUDE
|
TriState.ENABLED_NOT -> Filter.TriState.STATE_EXCLUDE
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -40,6 +40,7 @@ import kotlinx.coroutines.flow.map
|
||||||
import kotlinx.coroutines.flow.onEach
|
import kotlinx.coroutines.flow.onEach
|
||||||
import kotlinx.coroutines.flow.update
|
import kotlinx.coroutines.flow.update
|
||||||
import tachiyomi.core.preference.CheckboxState
|
import tachiyomi.core.preference.CheckboxState
|
||||||
|
import tachiyomi.core.preference.TriState
|
||||||
import tachiyomi.core.util.lang.launchIO
|
import tachiyomi.core.util.lang.launchIO
|
||||||
import tachiyomi.core.util.lang.launchNonCancellable
|
import tachiyomi.core.util.lang.launchNonCancellable
|
||||||
import tachiyomi.core.util.lang.withIOContext
|
import tachiyomi.core.util.lang.withIOContext
|
||||||
|
@ -57,7 +58,6 @@ import tachiyomi.domain.library.service.LibraryPreferences
|
||||||
import tachiyomi.domain.manga.interactor.GetLibraryManga
|
import tachiyomi.domain.manga.interactor.GetLibraryManga
|
||||||
import tachiyomi.domain.manga.model.Manga
|
import tachiyomi.domain.manga.model.Manga
|
||||||
import tachiyomi.domain.manga.model.MangaUpdate
|
import tachiyomi.domain.manga.model.MangaUpdate
|
||||||
import tachiyomi.domain.manga.model.TriStateFilter
|
|
||||||
import tachiyomi.domain.manga.model.applyFilter
|
import tachiyomi.domain.manga.model.applyFilter
|
||||||
import tachiyomi.domain.source.service.SourceManager
|
import tachiyomi.domain.source.service.SourceManager
|
||||||
import tachiyomi.domain.track.interactor.GetTracksPerManga
|
import tachiyomi.domain.track.interactor.GetTracksPerManga
|
||||||
|
@ -153,7 +153,7 @@ class LibraryScreenModel(
|
||||||
prefs.filterBookmarked,
|
prefs.filterBookmarked,
|
||||||
prefs.filterCompleted,
|
prefs.filterCompleted,
|
||||||
) + trackFilter.values
|
) + trackFilter.values
|
||||||
).any { it != TriStateFilter.DISABLED }
|
).any { it != TriState.DISABLED }
|
||||||
}
|
}
|
||||||
.distinctUntilChanged()
|
.distinctUntilChanged()
|
||||||
.onEach {
|
.onEach {
|
||||||
|
@ -169,12 +169,12 @@ class LibraryScreenModel(
|
||||||
*/
|
*/
|
||||||
private suspend fun LibraryMap.applyFilters(
|
private suspend fun LibraryMap.applyFilters(
|
||||||
trackMap: Map<Long, List<Long>>,
|
trackMap: Map<Long, List<Long>>,
|
||||||
loggedInTrackServices: Map<Long, TriStateFilter>,
|
loggedInTrackServices: Map<Long, TriState>,
|
||||||
): LibraryMap {
|
): LibraryMap {
|
||||||
val prefs = getLibraryItemPreferencesFlow().first()
|
val prefs = getLibraryItemPreferencesFlow().first()
|
||||||
val downloadedOnly = prefs.globalFilterDownloaded
|
val downloadedOnly = prefs.globalFilterDownloaded
|
||||||
val filterDownloaded =
|
val filterDownloaded =
|
||||||
if (downloadedOnly) TriStateFilter.ENABLED_IS else prefs.filterDownloaded
|
if (downloadedOnly) TriState.ENABLED_IS else prefs.filterDownloaded
|
||||||
val filterUnread = prefs.filterUnread
|
val filterUnread = prefs.filterUnread
|
||||||
val filterStarted = prefs.filterStarted
|
val filterStarted = prefs.filterStarted
|
||||||
val filterBookmarked = prefs.filterBookmarked
|
val filterBookmarked = prefs.filterBookmarked
|
||||||
|
@ -182,8 +182,8 @@ class LibraryScreenModel(
|
||||||
|
|
||||||
val isNotLoggedInAnyTrack = loggedInTrackServices.isEmpty()
|
val isNotLoggedInAnyTrack = loggedInTrackServices.isEmpty()
|
||||||
|
|
||||||
val excludedTracks = loggedInTrackServices.mapNotNull { if (it.value == TriStateFilter.ENABLED_NOT) it.key else null }
|
val excludedTracks = loggedInTrackServices.mapNotNull { if (it.value == TriState.ENABLED_NOT) it.key else null }
|
||||||
val includedTracks = loggedInTrackServices.mapNotNull { if (it.value == TriStateFilter.ENABLED_IS) it.key else null }
|
val includedTracks = loggedInTrackServices.mapNotNull { if (it.value == TriState.ENABLED_IS) it.key else null }
|
||||||
val trackFiltersIsIgnored = includedTracks.isEmpty() && excludedTracks.isEmpty()
|
val trackFiltersIsIgnored = includedTracks.isEmpty() && excludedTracks.isEmpty()
|
||||||
|
|
||||||
val filterFnDownloaded: (LibraryItem) -> Boolean = {
|
val filterFnDownloaded: (LibraryItem) -> Boolean = {
|
||||||
|
@ -308,11 +308,11 @@ class LibraryScreenModel(
|
||||||
localBadge = it[1] as Boolean,
|
localBadge = it[1] as Boolean,
|
||||||
languageBadge = it[2] as Boolean,
|
languageBadge = it[2] as Boolean,
|
||||||
globalFilterDownloaded = it[3] as Boolean,
|
globalFilterDownloaded = it[3] as Boolean,
|
||||||
filterDownloaded = it[4] as TriStateFilter,
|
filterDownloaded = it[4] as TriState,
|
||||||
filterUnread = it[5] as TriStateFilter,
|
filterUnread = it[5] as TriState,
|
||||||
filterStarted = it[6] as TriStateFilter,
|
filterStarted = it[6] as TriState,
|
||||||
filterBookmarked = it[7] as TriStateFilter,
|
filterBookmarked = it[7] as TriState,
|
||||||
filterCompleted = it[8] as TriStateFilter,
|
filterCompleted = it[8] as TriState,
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
@ -365,7 +365,7 @@ class LibraryScreenModel(
|
||||||
*
|
*
|
||||||
* @return map of track id with the filter value
|
* @return map of track id with the filter value
|
||||||
*/
|
*/
|
||||||
private fun getTrackingFilterFlow(): Flow<Map<Long, TriStateFilter>> {
|
private fun getTrackingFilterFlow(): Flow<Map<Long, TriState>> {
|
||||||
val loggedServices = trackManager.services.filter { it.isLogged }
|
val loggedServices = trackManager.services.filter { it.isLogged }
|
||||||
return if (loggedServices.isNotEmpty()) {
|
return if (loggedServices.isNotEmpty()) {
|
||||||
val prefFlows = loggedServices
|
val prefFlows = loggedServices
|
||||||
|
@ -670,11 +670,11 @@ class LibraryScreenModel(
|
||||||
val languageBadge: Boolean,
|
val languageBadge: Boolean,
|
||||||
|
|
||||||
val globalFilterDownloaded: Boolean,
|
val globalFilterDownloaded: Boolean,
|
||||||
val filterDownloaded: TriStateFilter,
|
val filterDownloaded: TriState,
|
||||||
val filterUnread: TriStateFilter,
|
val filterUnread: TriState,
|
||||||
val filterStarted: TriStateFilter,
|
val filterStarted: TriState,
|
||||||
val filterBookmarked: TriStateFilter,
|
val filterBookmarked: TriState,
|
||||||
val filterCompleted: TriStateFilter,
|
val filterCompleted: TriState,
|
||||||
)
|
)
|
||||||
|
|
||||||
@Immutable
|
@Immutable
|
||||||
|
|
|
@ -6,6 +6,7 @@ import eu.kanade.domain.base.BasePreferences
|
||||||
import eu.kanade.tachiyomi.data.track.TrackManager
|
import eu.kanade.tachiyomi.data.track.TrackManager
|
||||||
import eu.kanade.tachiyomi.util.preference.toggle
|
import eu.kanade.tachiyomi.util.preference.toggle
|
||||||
import tachiyomi.core.preference.Preference
|
import tachiyomi.core.preference.Preference
|
||||||
|
import tachiyomi.core.preference.TriState
|
||||||
import tachiyomi.core.preference.getAndSet
|
import tachiyomi.core.preference.getAndSet
|
||||||
import tachiyomi.core.util.lang.launchIO
|
import tachiyomi.core.util.lang.launchIO
|
||||||
import tachiyomi.domain.category.interactor.SetDisplayMode
|
import tachiyomi.domain.category.interactor.SetDisplayMode
|
||||||
|
@ -14,7 +15,6 @@ import tachiyomi.domain.category.model.Category
|
||||||
import tachiyomi.domain.library.model.LibraryDisplayMode
|
import tachiyomi.domain.library.model.LibraryDisplayMode
|
||||||
import tachiyomi.domain.library.model.LibrarySort
|
import tachiyomi.domain.library.model.LibrarySort
|
||||||
import tachiyomi.domain.library.service.LibraryPreferences
|
import tachiyomi.domain.library.service.LibraryPreferences
|
||||||
import tachiyomi.domain.manga.model.TriStateFilter
|
|
||||||
import uy.kohesive.injekt.Injekt
|
import uy.kohesive.injekt.Injekt
|
||||||
import uy.kohesive.injekt.api.get
|
import uy.kohesive.injekt.api.get
|
||||||
|
|
||||||
|
@ -33,7 +33,7 @@ class LibrarySettingsScreenModel(
|
||||||
preference(libraryPreferences).toggle()
|
preference(libraryPreferences).toggle()
|
||||||
}
|
}
|
||||||
|
|
||||||
fun toggleFilter(preference: (LibraryPreferences) -> Preference<TriStateFilter>) {
|
fun toggleFilter(preference: (LibraryPreferences) -> Preference<TriState>) {
|
||||||
preference(libraryPreferences).getAndSet {
|
preference(libraryPreferences).getAndSet {
|
||||||
it.next()
|
it.next()
|
||||||
}
|
}
|
||||||
|
|
|
@ -46,6 +46,7 @@ import kotlinx.coroutines.isActive
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import logcat.LogPriority
|
import logcat.LogPriority
|
||||||
import tachiyomi.core.preference.CheckboxState
|
import tachiyomi.core.preference.CheckboxState
|
||||||
|
import tachiyomi.core.preference.TriState
|
||||||
import tachiyomi.core.preference.mapAsCheckboxState
|
import tachiyomi.core.preference.mapAsCheckboxState
|
||||||
import tachiyomi.core.util.lang.launchIO
|
import tachiyomi.core.util.lang.launchIO
|
||||||
import tachiyomi.core.util.lang.launchNonCancellable
|
import tachiyomi.core.util.lang.launchNonCancellable
|
||||||
|
@ -67,7 +68,6 @@ import tachiyomi.domain.manga.interactor.GetDuplicateLibraryManga
|
||||||
import tachiyomi.domain.manga.interactor.GetMangaWithChapters
|
import tachiyomi.domain.manga.interactor.GetMangaWithChapters
|
||||||
import tachiyomi.domain.manga.interactor.SetMangaChapterFlags
|
import tachiyomi.domain.manga.interactor.SetMangaChapterFlags
|
||||||
import tachiyomi.domain.manga.model.Manga
|
import tachiyomi.domain.manga.model.Manga
|
||||||
import tachiyomi.domain.manga.model.TriStateFilter
|
|
||||||
import tachiyomi.domain.manga.model.applyFilter
|
import tachiyomi.domain.manga.model.applyFilter
|
||||||
import tachiyomi.domain.source.service.SourceManager
|
import tachiyomi.domain.source.service.SourceManager
|
||||||
import tachiyomi.domain.track.interactor.GetTracks
|
import tachiyomi.domain.track.interactor.GetTracks
|
||||||
|
@ -743,13 +743,13 @@ class MangaInfoScreenModel(
|
||||||
* Sets the read filter and requests an UI update.
|
* Sets the read filter and requests an UI update.
|
||||||
* @param state whether to display only unread chapters or all chapters.
|
* @param state whether to display only unread chapters or all chapters.
|
||||||
*/
|
*/
|
||||||
fun setUnreadFilter(state: TriStateFilter) {
|
fun setUnreadFilter(state: TriState) {
|
||||||
val manga = successState?.manga ?: return
|
val manga = successState?.manga ?: return
|
||||||
|
|
||||||
val flag = when (state) {
|
val flag = when (state) {
|
||||||
TriStateFilter.DISABLED -> Manga.SHOW_ALL
|
TriState.DISABLED -> Manga.SHOW_ALL
|
||||||
TriStateFilter.ENABLED_IS -> Manga.CHAPTER_SHOW_UNREAD
|
TriState.ENABLED_IS -> Manga.CHAPTER_SHOW_UNREAD
|
||||||
TriStateFilter.ENABLED_NOT -> Manga.CHAPTER_SHOW_READ
|
TriState.ENABLED_NOT -> Manga.CHAPTER_SHOW_READ
|
||||||
}
|
}
|
||||||
coroutineScope.launchNonCancellable {
|
coroutineScope.launchNonCancellable {
|
||||||
setMangaChapterFlags.awaitSetUnreadFilter(manga, flag)
|
setMangaChapterFlags.awaitSetUnreadFilter(manga, flag)
|
||||||
|
@ -760,13 +760,13 @@ class MangaInfoScreenModel(
|
||||||
* Sets the download filter and requests an UI update.
|
* Sets the download filter and requests an UI update.
|
||||||
* @param state whether to display only downloaded chapters or all chapters.
|
* @param state whether to display only downloaded chapters or all chapters.
|
||||||
*/
|
*/
|
||||||
fun setDownloadedFilter(state: TriStateFilter) {
|
fun setDownloadedFilter(state: TriState) {
|
||||||
val manga = successState?.manga ?: return
|
val manga = successState?.manga ?: return
|
||||||
|
|
||||||
val flag = when (state) {
|
val flag = when (state) {
|
||||||
TriStateFilter.DISABLED -> Manga.SHOW_ALL
|
TriState.DISABLED -> Manga.SHOW_ALL
|
||||||
TriStateFilter.ENABLED_IS -> Manga.CHAPTER_SHOW_DOWNLOADED
|
TriState.ENABLED_IS -> Manga.CHAPTER_SHOW_DOWNLOADED
|
||||||
TriStateFilter.ENABLED_NOT -> Manga.CHAPTER_SHOW_NOT_DOWNLOADED
|
TriState.ENABLED_NOT -> Manga.CHAPTER_SHOW_NOT_DOWNLOADED
|
||||||
}
|
}
|
||||||
|
|
||||||
coroutineScope.launchNonCancellable {
|
coroutineScope.launchNonCancellable {
|
||||||
|
@ -778,13 +778,13 @@ class MangaInfoScreenModel(
|
||||||
* Sets the bookmark filter and requests an UI update.
|
* Sets the bookmark filter and requests an UI update.
|
||||||
* @param state whether to display only bookmarked chapters or all chapters.
|
* @param state whether to display only bookmarked chapters or all chapters.
|
||||||
*/
|
*/
|
||||||
fun setBookmarkedFilter(state: TriStateFilter) {
|
fun setBookmarkedFilter(state: TriState) {
|
||||||
val manga = successState?.manga ?: return
|
val manga = successState?.manga ?: return
|
||||||
|
|
||||||
val flag = when (state) {
|
val flag = when (state) {
|
||||||
TriStateFilter.DISABLED -> Manga.SHOW_ALL
|
TriState.DISABLED -> Manga.SHOW_ALL
|
||||||
TriStateFilter.ENABLED_IS -> Manga.CHAPTER_SHOW_BOOKMARKED
|
TriState.ENABLED_IS -> Manga.CHAPTER_SHOW_BOOKMARKED
|
||||||
TriStateFilter.ENABLED_NOT -> Manga.CHAPTER_SHOW_NOT_BOOKMARKED
|
TriState.ENABLED_NOT -> Manga.CHAPTER_SHOW_NOT_BOOKMARKED
|
||||||
}
|
}
|
||||||
|
|
||||||
coroutineScope.launchNonCancellable {
|
coroutineScope.launchNonCancellable {
|
||||||
|
|
16
core/src/main/java/tachiyomi/core/preference/TriState.kt
Normal file
16
core/src/main/java/tachiyomi/core/preference/TriState.kt
Normal file
|
@ -0,0 +1,16 @@
|
||||||
|
package tachiyomi.core.preference
|
||||||
|
|
||||||
|
enum class TriState {
|
||||||
|
DISABLED, // Disable filter
|
||||||
|
ENABLED_IS, // Enabled with "is" filter
|
||||||
|
ENABLED_NOT, // Enabled with "not" filter
|
||||||
|
;
|
||||||
|
|
||||||
|
fun next(): TriState {
|
||||||
|
return when (this) {
|
||||||
|
DISABLED -> ENABLED_IS
|
||||||
|
ENABLED_IS -> ENABLED_NOT
|
||||||
|
ENABLED_NOT -> DISABLED
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,11 +1,11 @@
|
||||||
package tachiyomi.domain.library.service
|
package tachiyomi.domain.library.service
|
||||||
|
|
||||||
import tachiyomi.core.preference.PreferenceStore
|
import tachiyomi.core.preference.PreferenceStore
|
||||||
|
import tachiyomi.core.preference.TriState
|
||||||
import tachiyomi.core.preference.getEnum
|
import tachiyomi.core.preference.getEnum
|
||||||
import tachiyomi.domain.library.model.LibraryDisplayMode
|
import tachiyomi.domain.library.model.LibraryDisplayMode
|
||||||
import tachiyomi.domain.library.model.LibrarySort
|
import tachiyomi.domain.library.model.LibrarySort
|
||||||
import tachiyomi.domain.manga.model.Manga
|
import tachiyomi.domain.manga.model.Manga
|
||||||
import tachiyomi.domain.manga.model.TriStateFilter
|
|
||||||
|
|
||||||
class LibraryPreferences(
|
class LibraryPreferences(
|
||||||
private val preferenceStore: PreferenceStore,
|
private val preferenceStore: PreferenceStore,
|
||||||
|
@ -49,27 +49,27 @@ class LibraryPreferences(
|
||||||
|
|
||||||
// region Filter
|
// region Filter
|
||||||
|
|
||||||
fun filterDownloaded() = preferenceStore.getEnum("pref_filter_library_downloaded_v2", TriStateFilter.DISABLED)
|
fun filterDownloaded() = preferenceStore.getEnum("pref_filter_library_downloaded_v2", TriState.DISABLED)
|
||||||
|
|
||||||
fun filterUnread() = preferenceStore.getEnum("pref_filter_library_unread_v2", TriStateFilter.DISABLED)
|
fun filterUnread() = preferenceStore.getEnum("pref_filter_library_unread_v2", TriState.DISABLED)
|
||||||
|
|
||||||
fun filterStarted() = preferenceStore.getEnum("pref_filter_library_started_v2", TriStateFilter.DISABLED)
|
fun filterStarted() = preferenceStore.getEnum("pref_filter_library_started_v2", TriState.DISABLED)
|
||||||
|
|
||||||
fun filterBookmarked() = preferenceStore.getEnum("pref_filter_library_bookmarked_v2", TriStateFilter.DISABLED)
|
fun filterBookmarked() = preferenceStore.getEnum("pref_filter_library_bookmarked_v2", TriState.DISABLED)
|
||||||
|
|
||||||
fun filterCompleted() = preferenceStore.getEnum("pref_filter_library_completed_v2", TriStateFilter.DISABLED)
|
fun filterCompleted() = preferenceStore.getEnum("pref_filter_library_completed_v2", TriState.DISABLED)
|
||||||
|
|
||||||
fun filterIntervalCustom() = preferenceStore.getEnum("pref_filter_library_interval_custom", TriStateFilter.DISABLED)
|
fun filterIntervalCustom() = preferenceStore.getEnum("pref_filter_library_interval_custom", TriState.DISABLED)
|
||||||
|
|
||||||
fun filterIntervalLong() = preferenceStore.getEnum("pref_filter_library_interval_long", TriStateFilter.DISABLED)
|
fun filterIntervalLong() = preferenceStore.getEnum("pref_filter_library_interval_long", TriState.DISABLED)
|
||||||
|
|
||||||
fun filterIntervalLate() = preferenceStore.getEnum("pref_filter_library_interval_late", TriStateFilter.DISABLED)
|
fun filterIntervalLate() = preferenceStore.getEnum("pref_filter_library_interval_late", TriState.DISABLED)
|
||||||
|
|
||||||
fun filterIntervalDropped() = preferenceStore.getEnum("pref_filter_library_interval_dropped", TriStateFilter.DISABLED)
|
fun filterIntervalDropped() = preferenceStore.getEnum("pref_filter_library_interval_dropped", TriState.DISABLED)
|
||||||
|
|
||||||
fun filterIntervalPassed() = preferenceStore.getEnum("pref_filter_library_interval_passed", TriStateFilter.DISABLED)
|
fun filterIntervalPassed() = preferenceStore.getEnum("pref_filter_library_interval_passed", TriState.DISABLED)
|
||||||
|
|
||||||
fun filterTracking(id: Int) = preferenceStore.getEnum("pref_filter_library_tracked_${id}_v2", TriStateFilter.DISABLED)
|
fun filterTracking(id: Int) = preferenceStore.getEnum("pref_filter_library_tracked_${id}_v2", TriState.DISABLED)
|
||||||
|
|
||||||
// endregion
|
// endregion
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
package tachiyomi.domain.manga.model
|
package tachiyomi.domain.manga.model
|
||||||
|
|
||||||
import eu.kanade.tachiyomi.source.model.UpdateStrategy
|
import eu.kanade.tachiyomi.source.model.UpdateStrategy
|
||||||
|
import tachiyomi.core.preference.TriState
|
||||||
import java.io.Serializable
|
import java.io.Serializable
|
||||||
|
|
||||||
data class Manga(
|
data class Manga(
|
||||||
|
@ -43,18 +44,18 @@ data class Manga(
|
||||||
val bookmarkedFilterRaw: Long
|
val bookmarkedFilterRaw: Long
|
||||||
get() = chapterFlags and CHAPTER_BOOKMARKED_MASK
|
get() = chapterFlags and CHAPTER_BOOKMARKED_MASK
|
||||||
|
|
||||||
val unreadFilter: TriStateFilter
|
val unreadFilter: TriState
|
||||||
get() = when (unreadFilterRaw) {
|
get() = when (unreadFilterRaw) {
|
||||||
CHAPTER_SHOW_UNREAD -> TriStateFilter.ENABLED_IS
|
CHAPTER_SHOW_UNREAD -> TriState.ENABLED_IS
|
||||||
CHAPTER_SHOW_READ -> TriStateFilter.ENABLED_NOT
|
CHAPTER_SHOW_READ -> TriState.ENABLED_NOT
|
||||||
else -> TriStateFilter.DISABLED
|
else -> TriState.DISABLED
|
||||||
}
|
}
|
||||||
|
|
||||||
val bookmarkedFilter: TriStateFilter
|
val bookmarkedFilter: TriState
|
||||||
get() = when (bookmarkedFilterRaw) {
|
get() = when (bookmarkedFilterRaw) {
|
||||||
CHAPTER_SHOW_BOOKMARKED -> TriStateFilter.ENABLED_IS
|
CHAPTER_SHOW_BOOKMARKED -> TriState.ENABLED_IS
|
||||||
CHAPTER_SHOW_NOT_BOOKMARKED -> TriStateFilter.ENABLED_NOT
|
CHAPTER_SHOW_NOT_BOOKMARKED -> TriState.ENABLED_NOT
|
||||||
else -> TriStateFilter.DISABLED
|
else -> TriState.DISABLED
|
||||||
}
|
}
|
||||||
|
|
||||||
fun sortDescending(): Boolean {
|
fun sortDescending(): Boolean {
|
||||||
|
|
|
@ -0,0 +1,9 @@
|
||||||
|
package tachiyomi.domain.manga.model
|
||||||
|
|
||||||
|
import tachiyomi.core.preference.TriState
|
||||||
|
|
||||||
|
inline fun applyFilter(filter: TriState, predicate: () -> Boolean): Boolean = when (filter) {
|
||||||
|
TriState.DISABLED -> true
|
||||||
|
TriState.ENABLED_IS -> predicate()
|
||||||
|
TriState.ENABLED_NOT -> !predicate()
|
||||||
|
}
|
|
@ -1,22 +0,0 @@
|
||||||
package tachiyomi.domain.manga.model
|
|
||||||
|
|
||||||
enum class TriStateFilter {
|
|
||||||
DISABLED, // Disable filter
|
|
||||||
ENABLED_IS, // Enabled with "is" filter
|
|
||||||
ENABLED_NOT, // Enabled with "not" filter
|
|
||||||
;
|
|
||||||
|
|
||||||
fun next(): TriStateFilter {
|
|
||||||
return when (this) {
|
|
||||||
DISABLED -> ENABLED_IS
|
|
||||||
ENABLED_IS -> ENABLED_NOT
|
|
||||||
ENABLED_NOT -> DISABLED
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
inline fun applyFilter(filter: TriStateFilter, predicate: () -> Boolean): Boolean = when (filter) {
|
|
||||||
TriStateFilter.DISABLED -> true
|
|
||||||
TriStateFilter.ENABLED_IS -> predicate()
|
|
||||||
TriStateFilter.ENABLED_NOT -> !predicate()
|
|
||||||
}
|
|
|
@ -21,6 +21,8 @@ android {
|
||||||
}
|
}
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
|
implementation(project(":core"))
|
||||||
|
|
||||||
// Compose
|
// Compose
|
||||||
implementation(platform(compose.bom))
|
implementation(platform(compose.bom))
|
||||||
implementation(compose.activity)
|
implementation(compose.activity)
|
||||||
|
|
|
@ -10,10 +10,17 @@ import androidx.compose.foundation.layout.Spacer
|
||||||
import androidx.compose.foundation.layout.fillMaxWidth
|
import androidx.compose.foundation.layout.fillMaxWidth
|
||||||
import androidx.compose.foundation.layout.padding
|
import androidx.compose.foundation.layout.padding
|
||||||
import androidx.compose.foundation.layout.size
|
import androidx.compose.foundation.layout.size
|
||||||
|
import androidx.compose.material.ContentAlpha
|
||||||
import androidx.compose.material.icons.Icons
|
import androidx.compose.material.icons.Icons
|
||||||
import androidx.compose.material.icons.filled.ArrowDownward
|
import androidx.compose.material.icons.filled.ArrowDownward
|
||||||
import androidx.compose.material.icons.filled.ArrowUpward
|
import androidx.compose.material.icons.filled.ArrowUpward
|
||||||
|
import androidx.compose.material.icons.rounded.CheckBox
|
||||||
|
import androidx.compose.material.icons.rounded.CheckBoxOutlineBlank
|
||||||
|
import androidx.compose.material.icons.rounded.DisabledByDefault
|
||||||
import androidx.compose.material3.Checkbox
|
import androidx.compose.material3.Checkbox
|
||||||
|
import androidx.compose.material3.DropdownMenuItem
|
||||||
|
import androidx.compose.material3.ExposedDropdownMenuBox
|
||||||
|
import androidx.compose.material3.ExposedDropdownMenuDefaults
|
||||||
import androidx.compose.material3.Icon
|
import androidx.compose.material3.Icon
|
||||||
import androidx.compose.material3.MaterialTheme
|
import androidx.compose.material3.MaterialTheme
|
||||||
import androidx.compose.material3.OutlinedTextField
|
import androidx.compose.material3.OutlinedTextField
|
||||||
|
@ -21,11 +28,16 @@ import androidx.compose.material3.RadioButton
|
||||||
import androidx.compose.material3.Slider
|
import androidx.compose.material3.Slider
|
||||||
import androidx.compose.material3.Text
|
import androidx.compose.material3.Text
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
|
import androidx.compose.runtime.getValue
|
||||||
|
import androidx.compose.runtime.mutableStateOf
|
||||||
|
import androidx.compose.runtime.remember
|
||||||
|
import androidx.compose.runtime.setValue
|
||||||
import androidx.compose.ui.Alignment
|
import androidx.compose.ui.Alignment
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.graphics.vector.ImageVector
|
import androidx.compose.ui.graphics.vector.ImageVector
|
||||||
import androidx.compose.ui.res.stringResource
|
import androidx.compose.ui.res.stringResource
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
|
import tachiyomi.core.preference.TriState
|
||||||
import tachiyomi.presentation.core.theme.header
|
import tachiyomi.presentation.core.theme.header
|
||||||
|
|
||||||
object SettingsItemsPaddings {
|
object SettingsItemsPaddings {
|
||||||
|
@ -175,22 +187,99 @@ fun SliderItem(
|
||||||
}
|
}
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
private fun BaseSettingsItem(
|
fun SelectItem(
|
||||||
label: String,
|
label: String,
|
||||||
widget: @Composable RowScope.() -> Unit,
|
options: Array<out Any?>,
|
||||||
onClick: () -> Unit,
|
selectedIndex: Int,
|
||||||
|
onSelect: (Int) -> Unit,
|
||||||
|
) {
|
||||||
|
var expanded by remember { mutableStateOf(false) }
|
||||||
|
|
||||||
|
ExposedDropdownMenuBox(
|
||||||
|
expanded = expanded,
|
||||||
|
onExpandedChange = { expanded = !expanded },
|
||||||
|
) {
|
||||||
|
OutlinedTextField(
|
||||||
|
modifier = Modifier
|
||||||
|
.menuAnchor()
|
||||||
|
.fillMaxWidth()
|
||||||
|
.padding(horizontal = SettingsItemsPaddings.Horizontal, vertical = SettingsItemsPaddings.Vertical),
|
||||||
|
label = { Text(text = label) },
|
||||||
|
value = options[selectedIndex].toString(),
|
||||||
|
onValueChange = {},
|
||||||
|
readOnly = true,
|
||||||
|
singleLine = true,
|
||||||
|
trailingIcon = {
|
||||||
|
ExposedDropdownMenuDefaults.TrailingIcon(
|
||||||
|
expanded = expanded,
|
||||||
|
)
|
||||||
|
},
|
||||||
|
colors = ExposedDropdownMenuDefaults.textFieldColors(),
|
||||||
|
)
|
||||||
|
|
||||||
|
ExposedDropdownMenu(
|
||||||
|
modifier = Modifier.exposedDropdownSize(matchTextFieldWidth = true),
|
||||||
|
expanded = expanded,
|
||||||
|
onDismissRequest = { expanded = false },
|
||||||
|
) {
|
||||||
|
options.forEachIndexed { index, text ->
|
||||||
|
DropdownMenuItem(
|
||||||
|
text = { Text(text.toString()) },
|
||||||
|
onClick = {
|
||||||
|
onSelect(index)
|
||||||
|
expanded = false
|
||||||
|
},
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
fun TriStateItem(
|
||||||
|
label: String,
|
||||||
|
state: TriState,
|
||||||
|
enabled: Boolean = true,
|
||||||
|
onClick: ((TriState) -> Unit)?,
|
||||||
) {
|
) {
|
||||||
Row(
|
Row(
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.clickable(onClick = onClick)
|
.clickable(
|
||||||
|
enabled = enabled && onClick != null,
|
||||||
|
onClick = {
|
||||||
|
when (state) {
|
||||||
|
TriState.DISABLED -> onClick?.invoke(TriState.ENABLED_IS)
|
||||||
|
TriState.ENABLED_IS -> onClick?.invoke(TriState.ENABLED_NOT)
|
||||||
|
TriState.ENABLED_NOT -> onClick?.invoke(TriState.DISABLED)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
)
|
||||||
.fillMaxWidth()
|
.fillMaxWidth()
|
||||||
.padding(horizontal = SettingsItemsPaddings.Horizontal, vertical = SettingsItemsPaddings.Vertical),
|
.padding(horizontal = SettingsItemsPaddings.Horizontal, vertical = SettingsItemsPaddings.Vertical),
|
||||||
verticalAlignment = Alignment.CenterVertically,
|
verticalAlignment = Alignment.CenterVertically,
|
||||||
horizontalArrangement = Arrangement.spacedBy(24.dp),
|
horizontalArrangement = Arrangement.spacedBy(24.dp),
|
||||||
) {
|
) {
|
||||||
widget(this)
|
val stateAlpha = if (enabled && onClick != null) 1f else ContentAlpha.disabled
|
||||||
|
|
||||||
|
Icon(
|
||||||
|
imageVector = when (state) {
|
||||||
|
TriState.DISABLED -> Icons.Rounded.CheckBoxOutlineBlank
|
||||||
|
TriState.ENABLED_IS -> Icons.Rounded.CheckBox
|
||||||
|
TriState.ENABLED_NOT -> Icons.Rounded.DisabledByDefault
|
||||||
|
},
|
||||||
|
contentDescription = null,
|
||||||
|
tint = if (!enabled || state == TriState.DISABLED) {
|
||||||
|
MaterialTheme.colorScheme.onSurfaceVariant.copy(alpha = stateAlpha)
|
||||||
|
} else {
|
||||||
|
when (onClick) {
|
||||||
|
null -> MaterialTheme.colorScheme.onSurface.copy(alpha = ContentAlpha.disabled)
|
||||||
|
else -> MaterialTheme.colorScheme.primary
|
||||||
|
}
|
||||||
|
},
|
||||||
|
)
|
||||||
Text(
|
Text(
|
||||||
text = label,
|
text = label,
|
||||||
|
color = MaterialTheme.colorScheme.onSurface.copy(alpha = stateAlpha),
|
||||||
style = MaterialTheme.typography.bodyMedium,
|
style = MaterialTheme.typography.bodyMedium,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -212,3 +301,25 @@ fun TextItem(
|
||||||
singleLine = true,
|
singleLine = true,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
private fun BaseSettingsItem(
|
||||||
|
label: String,
|
||||||
|
widget: @Composable RowScope.() -> Unit,
|
||||||
|
onClick: () -> Unit,
|
||||||
|
) {
|
||||||
|
Row(
|
||||||
|
modifier = Modifier
|
||||||
|
.clickable(onClick = onClick)
|
||||||
|
.fillMaxWidth()
|
||||||
|
.padding(horizontal = SettingsItemsPaddings.Horizontal, vertical = SettingsItemsPaddings.Vertical),
|
||||||
|
verticalAlignment = Alignment.CenterVertically,
|
||||||
|
horizontalArrangement = Arrangement.spacedBy(24.dp),
|
||||||
|
) {
|
||||||
|
widget(this)
|
||||||
|
Text(
|
||||||
|
text = label,
|
||||||
|
style = MaterialTheme.typography.bodyMedium,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
Reference in a new issue