Move SettingsItems composables to presentation-core
This commit is contained in:
parent
efabe801be
commit
87bdee5990
@ -7,9 +7,9 @@ import eu.kanade.tachiyomi.ui.reader.setting.OrientationType
|
||||
import eu.kanade.tachiyomi.ui.reader.setting.ReadingModeType
|
||||
import tachiyomi.core.metadata.comicinfo.ComicInfo
|
||||
import tachiyomi.core.metadata.comicinfo.ComicInfoPublishingStatus
|
||||
import tachiyomi.core.preference.TriState
|
||||
import tachiyomi.domain.chapter.model.Chapter
|
||||
import tachiyomi.domain.manga.model.Manga
|
||||
import tachiyomi.domain.manga.model.TriStateFilter
|
||||
import uy.kohesive.injekt.Injekt
|
||||
import uy.kohesive.injekt.api.get
|
||||
|
||||
@ -20,19 +20,19 @@ val Manga.readingModeType: Long
|
||||
val Manga.orientationType: Long
|
||||
get() = viewerFlags and OrientationType.MASK.toLong()
|
||||
|
||||
val Manga.downloadedFilter: TriStateFilter
|
||||
val Manga.downloadedFilter: TriState
|
||||
get() {
|
||||
if (forceDownloaded()) return TriStateFilter.ENABLED_IS
|
||||
if (forceDownloaded()) return TriState.ENABLED_IS
|
||||
return when (downloadedFilterRaw) {
|
||||
Manga.CHAPTER_SHOW_DOWNLOADED -> TriStateFilter.ENABLED_IS
|
||||
Manga.CHAPTER_SHOW_NOT_DOWNLOADED -> TriStateFilter.ENABLED_NOT
|
||||
else -> TriStateFilter.DISABLED
|
||||
Manga.CHAPTER_SHOW_DOWNLOADED -> TriState.ENABLED_IS
|
||||
Manga.CHAPTER_SHOW_NOT_DOWNLOADED -> TriState.ENABLED_NOT
|
||||
else -> TriState.DISABLED
|
||||
}
|
||||
}
|
||||
fun Manga.chaptersFiltered(): Boolean {
|
||||
return unreadFilter != TriStateFilter.DISABLED ||
|
||||
downloadedFilter != TriStateFilter.DISABLED ||
|
||||
bookmarkedFilter != TriStateFilter.DISABLED
|
||||
return unreadFilter != TriState.DISABLED ||
|
||||
downloadedFilter != TriState.DISABLED ||
|
||||
bookmarkedFilter != TriState.DISABLED
|
||||
}
|
||||
fun Manga.forceDownloaded(): Boolean {
|
||||
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 eu.kanade.presentation.components.TabbedDialog
|
||||
import eu.kanade.presentation.components.TabbedDialogPaddings
|
||||
import eu.kanade.presentation.components.TriStateItem
|
||||
import eu.kanade.presentation.util.collectAsState
|
||||
import eu.kanade.tachiyomi.R
|
||||
import eu.kanade.tachiyomi.ui.library.LibrarySettingsScreenModel
|
||||
import tachiyomi.core.preference.TriState
|
||||
import tachiyomi.domain.category.model.Category
|
||||
import tachiyomi.domain.library.model.LibraryDisplayMode
|
||||
import tachiyomi.domain.library.model.LibrarySort
|
||||
import tachiyomi.domain.library.model.sort
|
||||
import tachiyomi.domain.library.service.LibraryPreferences
|
||||
import tachiyomi.domain.manga.model.TriStateFilter
|
||||
import tachiyomi.presentation.core.components.CheckboxItem
|
||||
import tachiyomi.presentation.core.components.HeadingItem
|
||||
import tachiyomi.presentation.core.components.RadioItem
|
||||
import tachiyomi.presentation.core.components.SliderItem
|
||||
import tachiyomi.presentation.core.components.SortItem
|
||||
import tachiyomi.presentation.core.components.TriStateItem
|
||||
|
||||
@Composable
|
||||
fun LibrarySettingsDialog(
|
||||
@ -74,7 +74,7 @@ private fun ColumnScope.FilterPage(
|
||||
TriStateItem(
|
||||
label = stringResource(R.string.label_downloaded),
|
||||
state = if (downloadedOnly) {
|
||||
TriStateFilter.ENABLED_IS
|
||||
TriState.ENABLED_IS
|
||||
} else {
|
||||
filterDownloaded
|
||||
},
|
||||
|
@ -27,20 +27,20 @@ import eu.kanade.domain.manga.model.downloadedFilter
|
||||
import eu.kanade.domain.manga.model.forceDownloaded
|
||||
import eu.kanade.presentation.components.TabbedDialog
|
||||
import eu.kanade.presentation.components.TabbedDialogPaddings
|
||||
import eu.kanade.presentation.components.TriStateItem
|
||||
import eu.kanade.tachiyomi.R
|
||||
import tachiyomi.core.preference.TriState
|
||||
import tachiyomi.domain.manga.model.Manga
|
||||
import tachiyomi.domain.manga.model.TriStateFilter
|
||||
import tachiyomi.presentation.core.components.RadioItem
|
||||
import tachiyomi.presentation.core.components.SortItem
|
||||
import tachiyomi.presentation.core.components.TriStateItem
|
||||
|
||||
@Composable
|
||||
fun ChapterSettingsDialog(
|
||||
onDismissRequest: () -> Unit,
|
||||
manga: Manga? = null,
|
||||
onDownloadFilterChanged: (TriStateFilter) -> Unit,
|
||||
onUnreadFilterChanged: (TriStateFilter) -> Unit,
|
||||
onBookmarkedFilterChanged: (TriStateFilter) -> Unit,
|
||||
onDownloadFilterChanged: (TriState) -> Unit,
|
||||
onUnreadFilterChanged: (TriState) -> Unit,
|
||||
onBookmarkedFilterChanged: (TriState) -> Unit,
|
||||
onSortModeChanged: (Long) -> Unit,
|
||||
onDisplayModeChanged: (Long) -> Unit,
|
||||
onSetAsDefault: (applyToExistingManga: Boolean) -> Unit,
|
||||
@ -78,11 +78,11 @@ fun ChapterSettingsDialog(
|
||||
when (page) {
|
||||
0 -> {
|
||||
FilterPage(
|
||||
downloadFilter = manga?.downloadedFilter ?: TriStateFilter.DISABLED,
|
||||
downloadFilter = manga?.downloadedFilter ?: TriState.DISABLED,
|
||||
onDownloadFilterChanged = onDownloadFilterChanged.takeUnless { manga?.forceDownloaded() == true },
|
||||
unreadFilter = manga?.unreadFilter ?: TriStateFilter.DISABLED,
|
||||
unreadFilter = manga?.unreadFilter ?: TriState.DISABLED,
|
||||
onUnreadFilterChanged = onUnreadFilterChanged,
|
||||
bookmarkedFilter = manga?.bookmarkedFilter ?: TriStateFilter.DISABLED,
|
||||
bookmarkedFilter = manga?.bookmarkedFilter ?: TriState.DISABLED,
|
||||
onBookmarkedFilterChanged = onBookmarkedFilterChanged,
|
||||
)
|
||||
}
|
||||
@ -106,12 +106,12 @@ fun ChapterSettingsDialog(
|
||||
|
||||
@Composable
|
||||
private fun ColumnScope.FilterPage(
|
||||
downloadFilter: TriStateFilter,
|
||||
onDownloadFilterChanged: ((TriStateFilter) -> Unit)?,
|
||||
unreadFilter: TriStateFilter,
|
||||
onUnreadFilterChanged: (TriStateFilter) -> Unit,
|
||||
bookmarkedFilter: TriStateFilter,
|
||||
onBookmarkedFilterChanged: (TriStateFilter) -> Unit,
|
||||
downloadFilter: TriState,
|
||||
onDownloadFilterChanged: ((TriState) -> Unit)?,
|
||||
unreadFilter: TriState,
|
||||
onUnreadFilterChanged: (TriState) -> Unit,
|
||||
bookmarkedFilter: TriState,
|
||||
onBookmarkedFilterChanged: (TriState) -> Unit,
|
||||
) {
|
||||
TriStateItem(
|
||||
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.workManager
|
||||
import tachiyomi.core.preference.PreferenceStore
|
||||
import tachiyomi.core.preference.TriState
|
||||
import tachiyomi.core.preference.getEnum
|
||||
import tachiyomi.domain.backup.service.BackupPreferences
|
||||
import tachiyomi.domain.library.service.LibraryPreferences
|
||||
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
|
||||
|
||||
object Migrations {
|
||||
@ -350,12 +349,12 @@ object Migrations {
|
||||
remove(key)
|
||||
|
||||
val newValue = when (pref.get()) {
|
||||
1 -> TriStateFilter.ENABLED_IS
|
||||
2 -> TriStateFilter.ENABLED_NOT
|
||||
else -> TriStateFilter.DISABLED
|
||||
1 -> TriState.ENABLED_IS
|
||||
2 -> TriState.ENABLED_NOT
|
||||
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.unit.dp
|
||||
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.source.model.Filter
|
||||
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.CollapsibleBox
|
||||
import tachiyomi.presentation.core.components.HeadingItem
|
||||
import tachiyomi.presentation.core.components.SelectItem
|
||||
import tachiyomi.presentation.core.components.SortItem
|
||||
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.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) {
|
||||
Filter.TriState.STATE_IGNORE -> TriStateFilter.DISABLED
|
||||
Filter.TriState.STATE_INCLUDE -> TriStateFilter.ENABLED_IS
|
||||
Filter.TriState.STATE_EXCLUDE -> TriStateFilter.ENABLED_NOT
|
||||
Filter.TriState.STATE_IGNORE -> TriState.DISABLED
|
||||
Filter.TriState.STATE_INCLUDE -> TriState.ENABLED_IS
|
||||
Filter.TriState.STATE_EXCLUDE -> TriState.ENABLED_NOT
|
||||
else -> throw IllegalStateException("Unknown TriState state: $this")
|
||||
}
|
||||
}
|
||||
|
||||
private fun TriStateFilter.toTriStateInt(): Int {
|
||||
private fun TriState.toTriStateInt(): Int {
|
||||
return when (this) {
|
||||
TriStateFilter.DISABLED -> Filter.TriState.STATE_IGNORE
|
||||
TriStateFilter.ENABLED_IS -> Filter.TriState.STATE_INCLUDE
|
||||
TriStateFilter.ENABLED_NOT -> Filter.TriState.STATE_EXCLUDE
|
||||
TriState.DISABLED -> Filter.TriState.STATE_IGNORE
|
||||
TriState.ENABLED_IS -> Filter.TriState.STATE_INCLUDE
|
||||
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.update
|
||||
import tachiyomi.core.preference.CheckboxState
|
||||
import tachiyomi.core.preference.TriState
|
||||
import tachiyomi.core.util.lang.launchIO
|
||||
import tachiyomi.core.util.lang.launchNonCancellable
|
||||
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.model.Manga
|
||||
import tachiyomi.domain.manga.model.MangaUpdate
|
||||
import tachiyomi.domain.manga.model.TriStateFilter
|
||||
import tachiyomi.domain.manga.model.applyFilter
|
||||
import tachiyomi.domain.source.service.SourceManager
|
||||
import tachiyomi.domain.track.interactor.GetTracksPerManga
|
||||
@ -153,7 +153,7 @@ class LibraryScreenModel(
|
||||
prefs.filterBookmarked,
|
||||
prefs.filterCompleted,
|
||||
) + trackFilter.values
|
||||
).any { it != TriStateFilter.DISABLED }
|
||||
).any { it != TriState.DISABLED }
|
||||
}
|
||||
.distinctUntilChanged()
|
||||
.onEach {
|
||||
@ -169,12 +169,12 @@ class LibraryScreenModel(
|
||||
*/
|
||||
private suspend fun LibraryMap.applyFilters(
|
||||
trackMap: Map<Long, List<Long>>,
|
||||
loggedInTrackServices: Map<Long, TriStateFilter>,
|
||||
loggedInTrackServices: Map<Long, TriState>,
|
||||
): LibraryMap {
|
||||
val prefs = getLibraryItemPreferencesFlow().first()
|
||||
val downloadedOnly = prefs.globalFilterDownloaded
|
||||
val filterDownloaded =
|
||||
if (downloadedOnly) TriStateFilter.ENABLED_IS else prefs.filterDownloaded
|
||||
if (downloadedOnly) TriState.ENABLED_IS else prefs.filterDownloaded
|
||||
val filterUnread = prefs.filterUnread
|
||||
val filterStarted = prefs.filterStarted
|
||||
val filterBookmarked = prefs.filterBookmarked
|
||||
@ -182,8 +182,8 @@ class LibraryScreenModel(
|
||||
|
||||
val isNotLoggedInAnyTrack = loggedInTrackServices.isEmpty()
|
||||
|
||||
val excludedTracks = loggedInTrackServices.mapNotNull { if (it.value == TriStateFilter.ENABLED_NOT) it.key else null }
|
||||
val includedTracks = loggedInTrackServices.mapNotNull { if (it.value == TriStateFilter.ENABLED_IS) 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 == TriState.ENABLED_IS) it.key else null }
|
||||
val trackFiltersIsIgnored = includedTracks.isEmpty() && excludedTracks.isEmpty()
|
||||
|
||||
val filterFnDownloaded: (LibraryItem) -> Boolean = {
|
||||
@ -308,11 +308,11 @@ class LibraryScreenModel(
|
||||
localBadge = it[1] as Boolean,
|
||||
languageBadge = it[2] as Boolean,
|
||||
globalFilterDownloaded = it[3] as Boolean,
|
||||
filterDownloaded = it[4] as TriStateFilter,
|
||||
filterUnread = it[5] as TriStateFilter,
|
||||
filterStarted = it[6] as TriStateFilter,
|
||||
filterBookmarked = it[7] as TriStateFilter,
|
||||
filterCompleted = it[8] as TriStateFilter,
|
||||
filterDownloaded = it[4] as TriState,
|
||||
filterUnread = it[5] as TriState,
|
||||
filterStarted = it[6] as TriState,
|
||||
filterBookmarked = it[7] as TriState,
|
||||
filterCompleted = it[8] as TriState,
|
||||
)
|
||||
},
|
||||
)
|
||||
@ -365,7 +365,7 @@ class LibraryScreenModel(
|
||||
*
|
||||
* @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 }
|
||||
return if (loggedServices.isNotEmpty()) {
|
||||
val prefFlows = loggedServices
|
||||
@ -670,11 +670,11 @@ class LibraryScreenModel(
|
||||
val languageBadge: Boolean,
|
||||
|
||||
val globalFilterDownloaded: Boolean,
|
||||
val filterDownloaded: TriStateFilter,
|
||||
val filterUnread: TriStateFilter,
|
||||
val filterStarted: TriStateFilter,
|
||||
val filterBookmarked: TriStateFilter,
|
||||
val filterCompleted: TriStateFilter,
|
||||
val filterDownloaded: TriState,
|
||||
val filterUnread: TriState,
|
||||
val filterStarted: TriState,
|
||||
val filterBookmarked: TriState,
|
||||
val filterCompleted: TriState,
|
||||
)
|
||||
|
||||
@Immutable
|
||||
|
@ -6,6 +6,7 @@ import eu.kanade.domain.base.BasePreferences
|
||||
import eu.kanade.tachiyomi.data.track.TrackManager
|
||||
import eu.kanade.tachiyomi.util.preference.toggle
|
||||
import tachiyomi.core.preference.Preference
|
||||
import tachiyomi.core.preference.TriState
|
||||
import tachiyomi.core.preference.getAndSet
|
||||
import tachiyomi.core.util.lang.launchIO
|
||||
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.LibrarySort
|
||||
import tachiyomi.domain.library.service.LibraryPreferences
|
||||
import tachiyomi.domain.manga.model.TriStateFilter
|
||||
import uy.kohesive.injekt.Injekt
|
||||
import uy.kohesive.injekt.api.get
|
||||
|
||||
@ -33,7 +33,7 @@ class LibrarySettingsScreenModel(
|
||||
preference(libraryPreferences).toggle()
|
||||
}
|
||||
|
||||
fun toggleFilter(preference: (LibraryPreferences) -> Preference<TriStateFilter>) {
|
||||
fun toggleFilter(preference: (LibraryPreferences) -> Preference<TriState>) {
|
||||
preference(libraryPreferences).getAndSet {
|
||||
it.next()
|
||||
}
|
||||
|
@ -46,6 +46,7 @@ import kotlinx.coroutines.isActive
|
||||
import kotlinx.coroutines.launch
|
||||
import logcat.LogPriority
|
||||
import tachiyomi.core.preference.CheckboxState
|
||||
import tachiyomi.core.preference.TriState
|
||||
import tachiyomi.core.preference.mapAsCheckboxState
|
||||
import tachiyomi.core.util.lang.launchIO
|
||||
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.SetMangaChapterFlags
|
||||
import tachiyomi.domain.manga.model.Manga
|
||||
import tachiyomi.domain.manga.model.TriStateFilter
|
||||
import tachiyomi.domain.manga.model.applyFilter
|
||||
import tachiyomi.domain.source.service.SourceManager
|
||||
import tachiyomi.domain.track.interactor.GetTracks
|
||||
@ -743,13 +743,13 @@ class MangaInfoScreenModel(
|
||||
* Sets the read filter and requests an UI update.
|
||||
* @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 flag = when (state) {
|
||||
TriStateFilter.DISABLED -> Manga.SHOW_ALL
|
||||
TriStateFilter.ENABLED_IS -> Manga.CHAPTER_SHOW_UNREAD
|
||||
TriStateFilter.ENABLED_NOT -> Manga.CHAPTER_SHOW_READ
|
||||
TriState.DISABLED -> Manga.SHOW_ALL
|
||||
TriState.ENABLED_IS -> Manga.CHAPTER_SHOW_UNREAD
|
||||
TriState.ENABLED_NOT -> Manga.CHAPTER_SHOW_READ
|
||||
}
|
||||
coroutineScope.launchNonCancellable {
|
||||
setMangaChapterFlags.awaitSetUnreadFilter(manga, flag)
|
||||
@ -760,13 +760,13 @@ class MangaInfoScreenModel(
|
||||
* Sets the download filter and requests an UI update.
|
||||
* @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 flag = when (state) {
|
||||
TriStateFilter.DISABLED -> Manga.SHOW_ALL
|
||||
TriStateFilter.ENABLED_IS -> Manga.CHAPTER_SHOW_DOWNLOADED
|
||||
TriStateFilter.ENABLED_NOT -> Manga.CHAPTER_SHOW_NOT_DOWNLOADED
|
||||
TriState.DISABLED -> Manga.SHOW_ALL
|
||||
TriState.ENABLED_IS -> Manga.CHAPTER_SHOW_DOWNLOADED
|
||||
TriState.ENABLED_NOT -> Manga.CHAPTER_SHOW_NOT_DOWNLOADED
|
||||
}
|
||||
|
||||
coroutineScope.launchNonCancellable {
|
||||
@ -778,13 +778,13 @@ class MangaInfoScreenModel(
|
||||
* Sets the bookmark filter and requests an UI update.
|
||||
* @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 flag = when (state) {
|
||||
TriStateFilter.DISABLED -> Manga.SHOW_ALL
|
||||
TriStateFilter.ENABLED_IS -> Manga.CHAPTER_SHOW_BOOKMARKED
|
||||
TriStateFilter.ENABLED_NOT -> Manga.CHAPTER_SHOW_NOT_BOOKMARKED
|
||||
TriState.DISABLED -> Manga.SHOW_ALL
|
||||
TriState.ENABLED_IS -> Manga.CHAPTER_SHOW_BOOKMARKED
|
||||
TriState.ENABLED_NOT -> Manga.CHAPTER_SHOW_NOT_BOOKMARKED
|
||||
}
|
||||
|
||||
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
|
||||
|
||||
import tachiyomi.core.preference.PreferenceStore
|
||||
import tachiyomi.core.preference.TriState
|
||||
import tachiyomi.core.preference.getEnum
|
||||
import tachiyomi.domain.library.model.LibraryDisplayMode
|
||||
import tachiyomi.domain.library.model.LibrarySort
|
||||
import tachiyomi.domain.manga.model.Manga
|
||||
import tachiyomi.domain.manga.model.TriStateFilter
|
||||
|
||||
class LibraryPreferences(
|
||||
private val preferenceStore: PreferenceStore,
|
||||
@ -49,27 +49,27 @@ class LibraryPreferences(
|
||||
|
||||
// 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
|
||||
|
||||
|
@ -1,6 +1,7 @@
|
||||
package tachiyomi.domain.manga.model
|
||||
|
||||
import eu.kanade.tachiyomi.source.model.UpdateStrategy
|
||||
import tachiyomi.core.preference.TriState
|
||||
import java.io.Serializable
|
||||
|
||||
data class Manga(
|
||||
@ -43,18 +44,18 @@ data class Manga(
|
||||
val bookmarkedFilterRaw: Long
|
||||
get() = chapterFlags and CHAPTER_BOOKMARKED_MASK
|
||||
|
||||
val unreadFilter: TriStateFilter
|
||||
val unreadFilter: TriState
|
||||
get() = when (unreadFilterRaw) {
|
||||
CHAPTER_SHOW_UNREAD -> TriStateFilter.ENABLED_IS
|
||||
CHAPTER_SHOW_READ -> TriStateFilter.ENABLED_NOT
|
||||
else -> TriStateFilter.DISABLED
|
||||
CHAPTER_SHOW_UNREAD -> TriState.ENABLED_IS
|
||||
CHAPTER_SHOW_READ -> TriState.ENABLED_NOT
|
||||
else -> TriState.DISABLED
|
||||
}
|
||||
|
||||
val bookmarkedFilter: TriStateFilter
|
||||
val bookmarkedFilter: TriState
|
||||
get() = when (bookmarkedFilterRaw) {
|
||||
CHAPTER_SHOW_BOOKMARKED -> TriStateFilter.ENABLED_IS
|
||||
CHAPTER_SHOW_NOT_BOOKMARKED -> TriStateFilter.ENABLED_NOT
|
||||
else -> TriStateFilter.DISABLED
|
||||
CHAPTER_SHOW_BOOKMARKED -> TriState.ENABLED_IS
|
||||
CHAPTER_SHOW_NOT_BOOKMARKED -> TriState.ENABLED_NOT
|
||||
else -> TriState.DISABLED
|
||||
}
|
||||
|
||||
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 {
|
||||
implementation(project(":core"))
|
||||
|
||||
// Compose
|
||||
implementation(platform(compose.bom))
|
||||
implementation(compose.activity)
|
||||
|
@ -10,10 +10,17 @@ import androidx.compose.foundation.layout.Spacer
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.layout.size
|
||||
import androidx.compose.material.ContentAlpha
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.filled.ArrowDownward
|
||||
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.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
|
||||
@ -21,11 +28,16 @@ import androidx.compose.material3.RadioButton
|
||||
import androidx.compose.material3.Slider
|
||||
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.graphics.vector.ImageVector
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.unit.dp
|
||||
import tachiyomi.core.preference.TriState
|
||||
import tachiyomi.presentation.core.theme.header
|
||||
|
||||
object SettingsItemsPaddings {
|
||||
@ -175,22 +187,99 @@ fun SliderItem(
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun BaseSettingsItem(
|
||||
fun SelectItem(
|
||||
label: String,
|
||||
widget: @Composable RowScope.() -> Unit,
|
||||
onClick: () -> Unit,
|
||||
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
|
||||
},
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun TriStateItem(
|
||||
label: String,
|
||||
state: TriState,
|
||||
enabled: Boolean = true,
|
||||
onClick: ((TriState) -> Unit)?,
|
||||
) {
|
||||
Row(
|
||||
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()
|
||||
.padding(horizontal = SettingsItemsPaddings.Horizontal, vertical = SettingsItemsPaddings.Vertical),
|
||||
verticalAlignment = Alignment.CenterVertically,
|
||||
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 = label,
|
||||
color = MaterialTheme.colorScheme.onSurface.copy(alpha = stateAlpha),
|
||||
style = MaterialTheme.typography.bodyMedium,
|
||||
)
|
||||
}
|
||||
@ -212,3 +301,25 @@ fun TextItem(
|
||||
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,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user