Settings: Tint icon with primary color and separate info item layout (#8217)
This commit is contained in:
parent
e4292719d3
commit
aea0cadbfb
@ -15,6 +15,7 @@ import eu.kanade.domain.track.service.TrackPreferences
|
||||
import eu.kanade.domain.ui.UiPreferences
|
||||
import eu.kanade.presentation.more.settings.widget.AppThemePreferenceWidget
|
||||
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
|
||||
@ -163,6 +164,9 @@ internal fun PreferenceItem(
|
||||
)
|
||||
}
|
||||
}
|
||||
is Preference.PreferenceItem.InfoPreference -> {
|
||||
InfoWidget(text = item.title)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,7 +1,5 @@
|
||||
package eu.kanade.presentation.more.settings
|
||||
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.outlined.Info
|
||||
import androidx.compose.ui.graphics.vector.ImageVector
|
||||
import eu.kanade.domain.ui.model.AppTheme
|
||||
import eu.kanade.tachiyomi.data.track.TrackService
|
||||
@ -127,6 +125,15 @@ sealed class Preference {
|
||||
override val icon: ImageVector? = null
|
||||
override val onValueChanged: suspend (newValue: String) -> Boolean = { true }
|
||||
}
|
||||
|
||||
data class InfoPreference(
|
||||
override val title: String,
|
||||
) : PreferenceItem<String>() {
|
||||
override val enabled: Boolean = true
|
||||
override val subtitle: String? = null
|
||||
override val icon: ImageVector? = null
|
||||
override val onValueChanged: suspend (newValue: String) -> Boolean = { true }
|
||||
}
|
||||
}
|
||||
|
||||
data class PreferenceGroup(
|
||||
@ -135,12 +142,4 @@ sealed class Preference {
|
||||
|
||||
val preferenceItems: List<PreferenceItem<out Any>>,
|
||||
) : Preference()
|
||||
|
||||
companion object {
|
||||
fun infoPreference(info: String) = PreferenceItem.TextPreference(
|
||||
title = "",
|
||||
subtitle = info,
|
||||
icon = Icons.Outlined.Info,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
@ -356,7 +356,7 @@ class SettingsBackupScreen : SearchableSettings {
|
||||
title = stringResource(R.string.pref_backup_slots),
|
||||
entries = listOf(2, 3, 4, 5).associateWith { it.toString() },
|
||||
),
|
||||
Preference.infoPreference(stringResource(R.string.backup_info)),
|
||||
Preference.PreferenceItem.InfoPreference(stringResource(R.string.backup_info)),
|
||||
),
|
||||
)
|
||||
}
|
||||
|
@ -74,7 +74,7 @@ class SettingsBrowseScreen : SearchableSettings {
|
||||
)
|
||||
},
|
||||
),
|
||||
Preference.infoPreference(stringResource(R.string.parental_controls_info)),
|
||||
Preference.PreferenceItem.InfoPreference(stringResource(R.string.parental_controls_info)),
|
||||
),
|
||||
),
|
||||
)
|
||||
|
@ -265,7 +265,7 @@ class SettingsDownloadScreen : SearchableSettings {
|
||||
}
|
||||
},
|
||||
),
|
||||
Preference.infoPreference(stringResource(R.string.download_ahead_info)),
|
||||
Preference.PreferenceItem.InfoPreference(stringResource(R.string.download_ahead_info)),
|
||||
),
|
||||
)
|
||||
}
|
||||
|
@ -182,9 +182,10 @@ private fun SearchResult(
|
||||
}
|
||||
}
|
||||
is Preference.PreferenceItem<*> -> sequenceOf(null to p)
|
||||
else -> emptySequence() // Ignore other prefs
|
||||
}
|
||||
}
|
||||
// Don't show info preference
|
||||
.filterNot { it.second is Preference.PreferenceItem.InfoPreference }
|
||||
// Filter by search query
|
||||
.filter { (_, p) ->
|
||||
val inTitle = p.title.contains(searchKey, true)
|
||||
|
@ -76,7 +76,7 @@ class SettingsSecurityScreen : SearchableSettings {
|
||||
entries = SecurityPreferences.SecureScreenMode.values()
|
||||
.associateWith { stringResource(it.titleResId) },
|
||||
),
|
||||
Preference.infoPreference(stringResource(R.string.secure_screen_summary)),
|
||||
Preference.PreferenceItem.InfoPreference(stringResource(R.string.secure_screen_summary)),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
@ -145,7 +145,7 @@ class SettingsTrackingScreen : SearchableSettings {
|
||||
login = { context.openInBrowser(BangumiApi.authUrl(), forceDefaultBrowser = true) },
|
||||
logout = { dialog = LogoutDialog(trackManager.bangumi) },
|
||||
),
|
||||
Preference.infoPreference(stringResource(R.string.tracking_info)),
|
||||
Preference.PreferenceItem.InfoPreference(stringResource(R.string.tracking_info)),
|
||||
),
|
||||
),
|
||||
Preference.PreferenceGroup(
|
||||
@ -168,7 +168,7 @@ class SettingsTrackingScreen : SearchableSettings {
|
||||
},
|
||||
logout = trackManager.komga::logout,
|
||||
),
|
||||
Preference.infoPreference(stringResource(R.string.enhanced_tracking_info)),
|
||||
Preference.PreferenceItem.InfoPreference(stringResource(R.string.enhanced_tracking_info)),
|
||||
),
|
||||
),
|
||||
)
|
||||
|
@ -15,7 +15,6 @@ import androidx.compose.foundation.layout.Row
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.layout.sizeIn
|
||||
import androidx.compose.material3.Icon
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
@ -28,68 +27,18 @@ import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.composed
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.graphics.vector.ImageVector
|
||||
import androidx.compose.ui.text.style.TextOverflow
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.compose.ui.unit.sp
|
||||
import eu.kanade.presentation.more.settings.LocalPreferenceHighlighted
|
||||
import eu.kanade.presentation.util.secondaryItemAlpha
|
||||
import kotlinx.coroutines.delay
|
||||
|
||||
@Composable
|
||||
internal fun BasePreferenceWidget(
|
||||
modifier: Modifier = Modifier,
|
||||
title: String,
|
||||
subtitle: String? = null,
|
||||
icon: ImageVector? = null,
|
||||
onClick: (() -> Unit)? = null,
|
||||
widget: @Composable (() -> Unit)? = null,
|
||||
) {
|
||||
BasePreferenceWidget(
|
||||
modifier = modifier,
|
||||
title = title,
|
||||
subcomponent = if (!subtitle.isNullOrBlank()) {
|
||||
{
|
||||
Text(
|
||||
text = subtitle,
|
||||
modifier = Modifier
|
||||
.padding(
|
||||
start = HorizontalPadding,
|
||||
top = 0.dp,
|
||||
end = HorizontalPadding,
|
||||
)
|
||||
.secondaryItemAlpha(),
|
||||
style = MaterialTheme.typography.bodyMedium,
|
||||
maxLines = 10,
|
||||
)
|
||||
}
|
||||
} else {
|
||||
null
|
||||
},
|
||||
icon = icon,
|
||||
onClick = onClick,
|
||||
widget = widget,
|
||||
)
|
||||
}
|
||||
|
||||
@Composable
|
||||
internal fun BasePreferenceWidget(
|
||||
modifier: Modifier = Modifier,
|
||||
title: String,
|
||||
title: String? = null,
|
||||
subcomponent: @Composable (ColumnScope.() -> Unit)? = null,
|
||||
icon: ImageVector? = null,
|
||||
onClick: (() -> Unit)? = null,
|
||||
widget: @Composable (() -> Unit)? = null,
|
||||
) {
|
||||
BasePreferenceWidgetImpl(modifier, title, subcomponent, icon, onClick, widget)
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun BasePreferenceWidgetImpl(
|
||||
modifier: Modifier = Modifier,
|
||||
title: String,
|
||||
subcomponent: @Composable (ColumnScope.() -> Unit)? = null,
|
||||
icon: ImageVector? = null,
|
||||
icon: @Composable (() -> Unit)? = null,
|
||||
onClick: (() -> Unit)? = null,
|
||||
widget: @Composable (() -> Unit)? = null,
|
||||
) {
|
||||
@ -103,11 +52,9 @@ private fun BasePreferenceWidgetImpl(
|
||||
verticalAlignment = Alignment.CenterVertically,
|
||||
) {
|
||||
if (icon != null) {
|
||||
Icon(
|
||||
imageVector = icon,
|
||||
contentDescription = null,
|
||||
modifier = Modifier
|
||||
.padding(start = HorizontalPadding, end = 0.dp),
|
||||
Box(
|
||||
modifier = Modifier.padding(start = HorizontalPadding),
|
||||
content = { icon() },
|
||||
)
|
||||
}
|
||||
Column(
|
||||
@ -115,12 +62,9 @@ private fun BasePreferenceWidgetImpl(
|
||||
.weight(1f)
|
||||
.padding(vertical = 16.dp),
|
||||
) {
|
||||
if (title.isNotBlank()) {
|
||||
Row(
|
||||
modifier = Modifier.padding(horizontal = HorizontalPadding),
|
||||
verticalAlignment = Alignment.CenterVertically,
|
||||
) {
|
||||
if (!title.isNullOrBlank()) {
|
||||
Text(
|
||||
modifier = Modifier.padding(horizontal = HorizontalPadding),
|
||||
text = title,
|
||||
overflow = TextOverflow.Ellipsis,
|
||||
maxLines = 2,
|
||||
@ -128,13 +72,13 @@ private fun BasePreferenceWidgetImpl(
|
||||
fontSize = 20.sp,
|
||||
)
|
||||
}
|
||||
}
|
||||
subcomponent?.invoke(this)
|
||||
}
|
||||
if (widget != null) {
|
||||
Box(modifier = Modifier.padding(end = HorizontalPadding)) {
|
||||
widget()
|
||||
}
|
||||
Box(
|
||||
modifier = Modifier.padding(end = HorizontalPadding),
|
||||
content = { widget() },
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,58 @@
|
||||
package eu.kanade.presentation.more.settings.widget
|
||||
|
||||
import android.content.res.Configuration.UI_MODE_NIGHT_YES
|
||||
import androidx.compose.foundation.layout.Arrangement
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.outlined.Info
|
||||
import androidx.compose.material3.Icon
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.material3.Surface
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import androidx.compose.ui.unit.dp
|
||||
import eu.kanade.presentation.theme.TachiyomiTheme
|
||||
import eu.kanade.presentation.util.secondaryItemAlpha
|
||||
import eu.kanade.tachiyomi.R
|
||||
|
||||
@Composable
|
||||
internal fun InfoWidget(text: String) {
|
||||
Column(
|
||||
modifier = Modifier
|
||||
.padding(horizontal = HorizontalPadding, vertical = 16.dp)
|
||||
.secondaryItemAlpha(),
|
||||
verticalArrangement = Arrangement.spacedBy(16.dp),
|
||||
) {
|
||||
Icon(
|
||||
imageVector = Icons.Outlined.Info,
|
||||
contentDescription = null,
|
||||
)
|
||||
Text(
|
||||
text = text,
|
||||
style = MaterialTheme.typography.bodyMedium,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Preview(
|
||||
name = "Light",
|
||||
showBackground = true,
|
||||
)
|
||||
@Preview(
|
||||
name = "Dark",
|
||||
showBackground = true,
|
||||
uiMode = UI_MODE_NIGHT_YES,
|
||||
|
||||
)
|
||||
@Composable
|
||||
private fun InfoWidgetPreview() {
|
||||
TachiyomiTheme {
|
||||
Surface {
|
||||
InfoWidget(text = stringResource(id = R.string.download_ahead_info))
|
||||
}
|
||||
}
|
||||
}
|
@ -20,23 +20,24 @@ fun SwitchPreferenceWidget(
|
||||
checked: Boolean = false,
|
||||
onCheckedChanged: (Boolean) -> Unit,
|
||||
) {
|
||||
BasePreferenceWidget(
|
||||
TextPreferenceWidget(
|
||||
title = title,
|
||||
subtitle = subtitle,
|
||||
icon = icon,
|
||||
onClick = { onCheckedChanged(!checked) },
|
||||
) {
|
||||
widget = {
|
||||
Switch(
|
||||
checked = checked,
|
||||
onCheckedChange = null,
|
||||
modifier = Modifier.padding(start = TrailingWidgetBuffer),
|
||||
)
|
||||
}
|
||||
},
|
||||
onPreferenceClick = { onCheckedChanged(!checked) },
|
||||
)
|
||||
}
|
||||
|
||||
@Preview
|
||||
@Composable
|
||||
fun SwitchPreferenceWidgetPreview() {
|
||||
private fun SwitchPreferenceWidgetPreview() {
|
||||
MaterialTheme {
|
||||
Surface {
|
||||
Column {
|
||||
|
@ -1,37 +1,66 @@
|
||||
package eu.kanade.presentation.more.settings.widget
|
||||
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.filled.Preview
|
||||
import androidx.compose.material3.Icon
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.material3.Surface
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.setValue
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.graphics.vector.ImageVector
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import eu.kanade.presentation.util.secondaryItemAlpha
|
||||
|
||||
@Composable
|
||||
fun TextPreferenceWidget(
|
||||
modifier: Modifier = Modifier,
|
||||
title: String,
|
||||
title: String? = null,
|
||||
subtitle: String? = null,
|
||||
icon: ImageVector? = null,
|
||||
iconTint: Color = MaterialTheme.colorScheme.primary,
|
||||
widget: @Composable (() -> Unit)? = null,
|
||||
onPreferenceClick: (() -> Unit)? = null,
|
||||
) {
|
||||
BasePreferenceWidget(
|
||||
modifier = modifier,
|
||||
title = title,
|
||||
subtitle = subtitle,
|
||||
icon = icon,
|
||||
subcomponent = if (!subtitle.isNullOrBlank()) {
|
||||
{
|
||||
Text(
|
||||
text = subtitle,
|
||||
modifier = Modifier
|
||||
.padding(horizontal = HorizontalPadding)
|
||||
.secondaryItemAlpha(),
|
||||
style = MaterialTheme.typography.bodyMedium,
|
||||
maxLines = 10,
|
||||
)
|
||||
}
|
||||
} else {
|
||||
null
|
||||
},
|
||||
icon = if (icon != null) {
|
||||
{
|
||||
Icon(
|
||||
imageVector = icon,
|
||||
tint = iconTint,
|
||||
contentDescription = null,
|
||||
)
|
||||
}
|
||||
} else {
|
||||
null
|
||||
},
|
||||
onClick = onPreferenceClick,
|
||||
widget = widget,
|
||||
)
|
||||
}
|
||||
|
||||
@Preview
|
||||
@Composable
|
||||
fun TextPreferenceWidgetPreview() {
|
||||
private fun TextPreferenceWidgetPreview() {
|
||||
MaterialTheme {
|
||||
Surface {
|
||||
Column {
|
||||
|
Loading…
Reference in New Issue
Block a user