tachiyomi/app/src/main/java/eu/kanade/presentation/more/settings/PreferenceItem.kt
2023-12-24 22:25:22 -05:00

179 lines
6.9 KiB
Kotlin

package eu.kanade.presentation.more.settings
import androidx.compose.animation.AnimatedVisibility
import androidx.compose.animation.expandVertically
import androidx.compose.animation.fadeIn
import androidx.compose.animation.fadeOut
import androidx.compose.animation.shrinkVertically
import androidx.compose.runtime.Composable
import androidx.compose.runtime.CompositionLocalProvider
import androidx.compose.runtime.compositionLocalOf
import androidx.compose.runtime.getValue
import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.runtime.structuralEqualityPolicy
import androidx.compose.ui.unit.dp
import eu.kanade.domain.track.service.TrackPreferences
import eu.kanade.presentation.more.settings.widget.EditTextPreferenceWidget
import eu.kanade.presentation.more.settings.widget.InfoWidget
import eu.kanade.presentation.more.settings.widget.ListPreferenceWidget
import eu.kanade.presentation.more.settings.widget.MultiSelectListPreferenceWidget
import eu.kanade.presentation.more.settings.widget.SwitchPreferenceWidget
import eu.kanade.presentation.more.settings.widget.TextPreferenceWidget
import eu.kanade.presentation.more.settings.widget.TrackingPreferenceWidget
import kotlinx.coroutines.launch
import tachiyomi.presentation.core.components.SliderItem
import tachiyomi.presentation.core.util.collectAsState
import uy.kohesive.injekt.Injekt
import uy.kohesive.injekt.api.get
val LocalPreferenceHighlighted = compositionLocalOf(structuralEqualityPolicy()) { false }
val LocalPreferenceMinHeight = compositionLocalOf(structuralEqualityPolicy()) { 56.dp }
@Composable
fun StatusWrapper(
item: Preference.PreferenceItem<*>,
highlightKey: String?,
content: @Composable () -> Unit,
) {
val enabled = item.enabled
val highlighted = item.title == highlightKey
AnimatedVisibility(
visible = enabled,
enter = expandVertically() + fadeIn(),
exit = shrinkVertically() + fadeOut(),
content = {
CompositionLocalProvider(
LocalPreferenceHighlighted provides highlighted,
content = content,
)
},
)
}
@Composable
internal fun PreferenceItem(
item: Preference.PreferenceItem<*>,
highlightKey: String?,
) {
val scope = rememberCoroutineScope()
StatusWrapper(
item = item,
highlightKey = highlightKey,
) {
when (item) {
is Preference.PreferenceItem.SwitchPreference -> {
val value by item.pref.collectAsState()
SwitchPreferenceWidget(
title = item.title,
subtitle = item.subtitle,
icon = item.icon,
checked = value,
onCheckedChanged = { newValue ->
scope.launch {
if (item.onValueChanged(newValue)) {
item.pref.set(newValue)
}
}
},
)
}
is Preference.PreferenceItem.SliderPreference -> {
// TODO: use different composable?
SliderItem(
label = item.title,
min = item.min,
max = item.max,
value = item.value,
valueText = item.subtitle.takeUnless { it.isNullOrEmpty() } ?: item.value.toString(),
onChange = {
scope.launch {
item.onValueChanged(it)
}
},
)
}
is Preference.PreferenceItem.ListPreference<*> -> {
val value by item.pref.collectAsState()
ListPreferenceWidget(
value = value,
title = item.title,
subtitle = item.internalSubtitleProvider(value, item.entries),
icon = item.icon,
entries = item.entries,
onValueChange = { newValue ->
scope.launch {
if (item.internalOnValueChanged(newValue!!)) {
item.internalSet(newValue)
}
}
},
)
}
is Preference.PreferenceItem.BasicListPreference -> {
ListPreferenceWidget(
value = item.value,
title = item.title,
subtitle = item.subtitleProvider(item.value, item.entries),
icon = item.icon,
entries = item.entries,
onValueChange = { scope.launch { item.onValueChanged(it) } },
)
}
is Preference.PreferenceItem.MultiSelectListPreference -> {
val values by item.pref.collectAsState()
MultiSelectListPreferenceWidget(
preference = item,
values = values,
onValuesChange = { newValues ->
scope.launch {
if (item.onValueChanged(newValues)) {
item.pref.set(newValues.toMutableSet())
}
}
},
)
}
is Preference.PreferenceItem.TextPreference -> {
TextPreferenceWidget(
title = item.title,
subtitle = item.subtitle,
icon = item.icon,
onPreferenceClick = item.onClick,
)
}
is Preference.PreferenceItem.EditTextPreference -> {
val values by item.pref.collectAsState()
EditTextPreferenceWidget(
title = item.title,
subtitle = item.subtitle,
icon = item.icon,
value = values,
onConfirm = {
val accepted = item.onValueChanged(it)
if (accepted) item.pref.set(it)
accepted
},
)
}
is Preference.PreferenceItem.TrackerPreference -> {
val uName by Injekt.get<TrackPreferences>()
.trackUsername(item.tracker)
.collectAsState()
item.tracker.run {
TrackingPreferenceWidget(
tracker = this,
checked = uName.isNotEmpty(),
onClick = { if (isLoggedIn) item.logout() else item.login() },
)
}
}
is Preference.PreferenceItem.InfoPreference -> {
InfoWidget(text = item.title)
}
is Preference.PreferenceItem.CustomPreference -> {
item.content(item)
}
}
}
}