mirror of
https://github.com/mihonapp/mihon.git
synced 2024-11-14 20:39:59 -05:00
Replace numberpicker with wheelpicker (#8501)
* Replace numberpicker with wheelpicker * cleanups
This commit is contained in:
parent
3061f198e9
commit
acc65529a0
6 changed files with 101 additions and 90 deletions
|
@ -173,6 +173,7 @@ dependencies {
|
|||
implementation(compose.foundation)
|
||||
implementation(compose.material3.core)
|
||||
implementation(compose.material3.adapter)
|
||||
implementation(compose.material.core)
|
||||
implementation(compose.material.icons)
|
||||
implementation(compose.animation)
|
||||
implementation(compose.animation.graphics)
|
||||
|
@ -269,7 +270,6 @@ dependencies {
|
|||
implementation(libs.markwon)
|
||||
implementation(libs.aboutLibraries.compose)
|
||||
implementation(libs.cascade)
|
||||
implementation(libs.numberpicker)
|
||||
implementation(libs.bundles.voyager)
|
||||
implementation(libs.wheelpicker)
|
||||
|
||||
|
|
|
@ -1,13 +1,15 @@
|
|||
package eu.kanade.presentation.more.settings.screen
|
||||
|
||||
import android.content.Context
|
||||
import androidx.annotation.StringRes
|
||||
import androidx.compose.foundation.BorderStroke
|
||||
import androidx.compose.foundation.layout.BoxWithConstraints
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.Row
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.size
|
||||
import androidx.compose.material3.AlertDialog
|
||||
import androidx.compose.material3.LocalTextStyle
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.material3.Surface
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.material3.TextButton
|
||||
import androidx.compose.runtime.Composable
|
||||
|
@ -21,15 +23,18 @@ import androidx.compose.runtime.saveable.rememberSaveable
|
|||
import androidx.compose.runtime.setValue
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.draw.clipToBounds
|
||||
import androidx.compose.ui.draw.alpha
|
||||
import androidx.compose.ui.platform.LocalContext
|
||||
import androidx.compose.ui.res.pluralStringResource
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.text.style.TextAlign
|
||||
import androidx.compose.ui.unit.DpSize
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.compose.ui.util.fastMap
|
||||
import androidx.core.content.ContextCompat
|
||||
import cafe.adriel.voyager.navigator.currentOrThrow
|
||||
import com.bluelinelabs.conductor.Router
|
||||
import com.chargemap.compose.numberpicker.NumberPicker
|
||||
import com.commandiron.wheel_picker_compose.WheelPicker
|
||||
import eu.kanade.domain.category.interactor.GetCategories
|
||||
import eu.kanade.domain.category.interactor.ResetCategoryFlags
|
||||
import eu.kanade.domain.category.model.Category
|
||||
|
@ -78,7 +83,6 @@ class SettingsLibraryScreen : SearchableSettings {
|
|||
|
||||
@Composable
|
||||
private fun getDisplayGroup(libraryPreferences: LibraryPreferences): Preference.PreferenceGroup {
|
||||
val context = LocalContext.current
|
||||
val scope = rememberCoroutineScope()
|
||||
val portraitColumns by libraryPreferences.portraitColumns().stateIn(scope).collectAsState()
|
||||
val landscapeColumns by libraryPreferences.landscapeColumns().stateIn(scope).collectAsState()
|
||||
|
@ -102,8 +106,8 @@ class SettingsLibraryScreen : SearchableSettings {
|
|||
preferenceItems = listOf(
|
||||
Preference.PreferenceItem.TextPreference(
|
||||
title = stringResource(R.string.pref_library_columns),
|
||||
subtitle = "${stringResource(R.string.portrait)}: ${getColumnValue(context, portraitColumns)}, " +
|
||||
"${stringResource(R.string.landscape)}: ${getColumnValue(context, landscapeColumns)}",
|
||||
subtitle = "${stringResource(R.string.portrait)}: ${getColumnValue(portraitColumns)}, " +
|
||||
"${stringResource(R.string.landscape)}: ${getColumnValue(landscapeColumns)}",
|
||||
onClick = { showDialog = true },
|
||||
),
|
||||
),
|
||||
|
@ -273,7 +277,6 @@ class SettingsLibraryScreen : SearchableSettings {
|
|||
onDismissRequest: () -> Unit,
|
||||
onValueChanged: (portrait: Int, landscape: Int) -> Unit,
|
||||
) {
|
||||
val context = LocalContext.current
|
||||
var portraitValue by rememberSaveable { mutableStateOf(initialPortrait) }
|
||||
var landscapeValue by rememberSaveable { mutableStateOf(initialLandscape) }
|
||||
|
||||
|
@ -281,48 +284,30 @@ class SettingsLibraryScreen : SearchableSettings {
|
|||
onDismissRequest = onDismissRequest,
|
||||
title = { Text(text = stringResource(R.string.pref_library_columns)) },
|
||||
text = {
|
||||
Row {
|
||||
Column(
|
||||
modifier = Modifier.weight(1f),
|
||||
horizontalAlignment = Alignment.CenterHorizontally,
|
||||
) {
|
||||
Column {
|
||||
Row {
|
||||
Text(
|
||||
modifier = Modifier.weight(1f),
|
||||
text = stringResource(R.string.portrait),
|
||||
textAlign = TextAlign.Center,
|
||||
maxLines = 1,
|
||||
style = MaterialTheme.typography.labelMedium,
|
||||
)
|
||||
NumberPicker(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.clipToBounds(),
|
||||
value = portraitValue,
|
||||
onValueChange = { portraitValue = it },
|
||||
range = 0..10,
|
||||
label = { getColumnValue(context, it) },
|
||||
dividersColor = MaterialTheme.colorScheme.primary,
|
||||
textStyle = LocalTextStyle.current.copy(color = MaterialTheme.colorScheme.onSurface),
|
||||
)
|
||||
}
|
||||
|
||||
Column(
|
||||
modifier = Modifier.weight(1f),
|
||||
horizontalAlignment = Alignment.CenterHorizontally,
|
||||
) {
|
||||
Text(
|
||||
modifier = Modifier.weight(1f),
|
||||
text = stringResource(R.string.landscape),
|
||||
textAlign = TextAlign.Center,
|
||||
maxLines = 1,
|
||||
style = MaterialTheme.typography.labelMedium,
|
||||
)
|
||||
NumberPicker(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.clipToBounds(),
|
||||
value = landscapeValue,
|
||||
onValueChange = { landscapeValue = it },
|
||||
range = 0..10,
|
||||
label = { getColumnValue(context, it) },
|
||||
dividersColor = MaterialTheme.colorScheme.primary,
|
||||
textStyle = LocalTextStyle.current.copy(color = MaterialTheme.colorScheme.onSurface),
|
||||
)
|
||||
}
|
||||
LibraryColumnsPicker(
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
portraitValue = portraitValue,
|
||||
onPortraitChange = { portraitValue = it },
|
||||
landscapeValue = landscapeValue,
|
||||
onLandscapeChange = { landscapeValue = it },
|
||||
)
|
||||
}
|
||||
},
|
||||
dismissButton = {
|
||||
|
@ -338,9 +323,78 @@ class SettingsLibraryScreen : SearchableSettings {
|
|||
)
|
||||
}
|
||||
|
||||
private fun getColumnValue(context: Context, value: Int): String {
|
||||
@Composable
|
||||
private fun LibraryColumnsPicker(
|
||||
modifier: Modifier = Modifier,
|
||||
portraitValue: Int,
|
||||
onPortraitChange: (Int) -> Unit,
|
||||
landscapeValue: Int,
|
||||
onLandscapeChange: (Int) -> Unit,
|
||||
) {
|
||||
BoxWithConstraints(
|
||||
modifier = modifier,
|
||||
contentAlignment = Alignment.Center,
|
||||
) {
|
||||
Surface(
|
||||
modifier = Modifier.size(maxWidth, maxHeight / 3),
|
||||
shape = MaterialTheme.shapes.large,
|
||||
color = MaterialTheme.colorScheme.primary.copy(alpha = 0.2f),
|
||||
border = BorderStroke(1.dp, MaterialTheme.colorScheme.primary),
|
||||
) {}
|
||||
|
||||
val size = DpSize(width = maxWidth / 2, height = 128.dp)
|
||||
Row {
|
||||
WheelPicker(
|
||||
size = size,
|
||||
count = 10,
|
||||
startIndex = portraitValue,
|
||||
onScrollFinished = {
|
||||
onPortraitChange(it)
|
||||
null
|
||||
},
|
||||
) { index, snappedIndex ->
|
||||
ColumnPickerLabel(index = index, snappedIndex = snappedIndex)
|
||||
}
|
||||
WheelPicker(
|
||||
size = size,
|
||||
count = 10,
|
||||
startIndex = landscapeValue,
|
||||
onScrollFinished = {
|
||||
onLandscapeChange(it)
|
||||
null
|
||||
},
|
||||
) { index, snappedIndex ->
|
||||
ColumnPickerLabel(index = index, snappedIndex = snappedIndex)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun ColumnPickerLabel(
|
||||
index: Int,
|
||||
snappedIndex: Int,
|
||||
) {
|
||||
Text(
|
||||
modifier = Modifier.alpha(
|
||||
when (snappedIndex) {
|
||||
index + 1 -> 0.2f
|
||||
index -> 1f
|
||||
index - 1 -> 0.2f
|
||||
else -> 0.2f
|
||||
},
|
||||
),
|
||||
text = getColumnValue(index),
|
||||
style = MaterialTheme.typography.titleMedium,
|
||||
maxLines = 1,
|
||||
)
|
||||
}
|
||||
|
||||
@Composable
|
||||
@ReadOnlyComposable
|
||||
private fun getColumnValue(value: Int): String {
|
||||
return if (value == 0) {
|
||||
context.getString(R.string.label_default)
|
||||
stringResource(R.string.label_default)
|
||||
} else {
|
||||
value.toString()
|
||||
}
|
||||
|
|
|
@ -1,40 +0,0 @@
|
|||
package eu.kanade.tachiyomi.widget
|
||||
|
||||
import android.content.Context
|
||||
import android.text.InputType
|
||||
import android.util.AttributeSet
|
||||
import android.widget.EditText
|
||||
import android.widget.NumberPicker
|
||||
import androidx.core.view.doOnLayout
|
||||
import eu.kanade.tachiyomi.R
|
||||
import eu.kanade.tachiyomi.util.view.findDescendant
|
||||
|
||||
class MinMaxNumberPicker @JvmOverloads constructor(context: Context, attrs: AttributeSet? = null) :
|
||||
NumberPicker(context, attrs) {
|
||||
|
||||
override fun setDisplayedValues(displayedValues: Array<out String>?) {
|
||||
super.setDisplayedValues(displayedValues)
|
||||
|
||||
// Disable keyboard input when a value that can't be auto-filled with number exists
|
||||
val notNumberValue = displayedValues?.find { it.getOrNull(0)?.digitToIntOrNull() == null }
|
||||
if (notNumberValue != null) {
|
||||
descendantFocusability = FOCUS_BLOCK_DESCENDANTS
|
||||
}
|
||||
}
|
||||
|
||||
init {
|
||||
if (attrs != null) {
|
||||
val ta = context.obtainStyledAttributes(attrs, R.styleable.MinMaxNumberPicker, 0, 0)
|
||||
try {
|
||||
minValue = ta.getInt(R.styleable.MinMaxNumberPicker_min, 0)
|
||||
maxValue = ta.getInt(R.styleable.MinMaxNumberPicker_max, 0)
|
||||
} finally {
|
||||
ta.recycle()
|
||||
}
|
||||
}
|
||||
|
||||
doOnLayout {
|
||||
findDescendant<EditText>()?.setRawInputType(InputType.TYPE_CLASS_NUMBER)
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,11 +1,6 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
|
||||
<declare-styleable name="MinMaxNumberPicker">
|
||||
<attr name="min" format="integer"/>
|
||||
<attr name="max" format="integer"/>
|
||||
</declare-styleable>
|
||||
|
||||
<declare-styleable name="MaterialSpinnerView">
|
||||
<attr name="title" format="reference|string"/>
|
||||
<attr name="android:entries"/>
|
||||
|
|
|
@ -16,6 +16,9 @@ material3-core = { module = "androidx.compose.material3:material3" }
|
|||
material3-adapter = "com.google.android.material:compose-theme-adapter-3:1.0.21"
|
||||
material-icons = { module = "androidx.compose.material:material-icons-extended" }
|
||||
|
||||
# Here until M3's swipeable became public https://issuetracker.google.com/issues/234640556
|
||||
material-core = { module = "androidx.compose.material:material" }
|
||||
|
||||
accompanist-webview = { module = "com.google.accompanist:accompanist-webview", version.ref = "accompanist" }
|
||||
accompanist-swiperefresh = { module = "com.google.accompanist:accompanist-swiperefresh", version.ref = "accompanist" }
|
||||
accompanist-flowlayout = { module = "com.google.accompanist:accompanist-flowlayout", version.ref = "accompanist" }
|
||||
|
|
|
@ -63,7 +63,6 @@ photoview = "com.github.chrisbanes:PhotoView:2.3.0"
|
|||
directionalviewpager = "com.github.tachiyomiorg:DirectionalViewPager:1.0.0"
|
||||
insetter = "dev.chrisbanes.insetter:insetter:0.6.1"
|
||||
cascade = "me.saket.cascade:cascade-compose:2.0.0-beta1"
|
||||
numberpicker = "com.chargemap.compose:numberpicker:1.0.3"
|
||||
wheelpicker = "com.github.commandiron:WheelPickerCompose:1.0.11"
|
||||
|
||||
conductor-core = { module = "com.bluelinelabs:conductor", version.ref = "conductor_version" }
|
||||
|
|
Loading…
Reference in a new issue