mirror of
https://github.com/mihonapp/mihon.git
synced 2024-11-21 20:47:03 -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.foundation)
|
||||||
implementation(compose.material3.core)
|
implementation(compose.material3.core)
|
||||||
implementation(compose.material3.adapter)
|
implementation(compose.material3.adapter)
|
||||||
|
implementation(compose.material.core)
|
||||||
implementation(compose.material.icons)
|
implementation(compose.material.icons)
|
||||||
implementation(compose.animation)
|
implementation(compose.animation)
|
||||||
implementation(compose.animation.graphics)
|
implementation(compose.animation.graphics)
|
||||||
|
@ -269,7 +270,6 @@ dependencies {
|
||||||
implementation(libs.markwon)
|
implementation(libs.markwon)
|
||||||
implementation(libs.aboutLibraries.compose)
|
implementation(libs.aboutLibraries.compose)
|
||||||
implementation(libs.cascade)
|
implementation(libs.cascade)
|
||||||
implementation(libs.numberpicker)
|
|
||||||
implementation(libs.bundles.voyager)
|
implementation(libs.bundles.voyager)
|
||||||
implementation(libs.wheelpicker)
|
implementation(libs.wheelpicker)
|
||||||
|
|
||||||
|
|
|
@ -1,13 +1,15 @@
|
||||||
package eu.kanade.presentation.more.settings.screen
|
package eu.kanade.presentation.more.settings.screen
|
||||||
|
|
||||||
import android.content.Context
|
|
||||||
import androidx.annotation.StringRes
|
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.Column
|
||||||
import androidx.compose.foundation.layout.Row
|
import androidx.compose.foundation.layout.Row
|
||||||
import androidx.compose.foundation.layout.fillMaxWidth
|
import androidx.compose.foundation.layout.fillMaxWidth
|
||||||
|
import androidx.compose.foundation.layout.size
|
||||||
import androidx.compose.material3.AlertDialog
|
import androidx.compose.material3.AlertDialog
|
||||||
import androidx.compose.material3.LocalTextStyle
|
|
||||||
import androidx.compose.material3.MaterialTheme
|
import androidx.compose.material3.MaterialTheme
|
||||||
|
import androidx.compose.material3.Surface
|
||||||
import androidx.compose.material3.Text
|
import androidx.compose.material3.Text
|
||||||
import androidx.compose.material3.TextButton
|
import androidx.compose.material3.TextButton
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
|
@ -21,15 +23,18 @@ import androidx.compose.runtime.saveable.rememberSaveable
|
||||||
import androidx.compose.runtime.setValue
|
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.draw.clipToBounds
|
import androidx.compose.ui.draw.alpha
|
||||||
import androidx.compose.ui.platform.LocalContext
|
import androidx.compose.ui.platform.LocalContext
|
||||||
import androidx.compose.ui.res.pluralStringResource
|
import androidx.compose.ui.res.pluralStringResource
|
||||||
import androidx.compose.ui.res.stringResource
|
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.compose.ui.util.fastMap
|
||||||
import androidx.core.content.ContextCompat
|
import androidx.core.content.ContextCompat
|
||||||
import cafe.adriel.voyager.navigator.currentOrThrow
|
import cafe.adriel.voyager.navigator.currentOrThrow
|
||||||
import com.bluelinelabs.conductor.Router
|
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.GetCategories
|
||||||
import eu.kanade.domain.category.interactor.ResetCategoryFlags
|
import eu.kanade.domain.category.interactor.ResetCategoryFlags
|
||||||
import eu.kanade.domain.category.model.Category
|
import eu.kanade.domain.category.model.Category
|
||||||
|
@ -78,7 +83,6 @@ class SettingsLibraryScreen : SearchableSettings {
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
private fun getDisplayGroup(libraryPreferences: LibraryPreferences): Preference.PreferenceGroup {
|
private fun getDisplayGroup(libraryPreferences: LibraryPreferences): Preference.PreferenceGroup {
|
||||||
val context = LocalContext.current
|
|
||||||
val scope = rememberCoroutineScope()
|
val scope = rememberCoroutineScope()
|
||||||
val portraitColumns by libraryPreferences.portraitColumns().stateIn(scope).collectAsState()
|
val portraitColumns by libraryPreferences.portraitColumns().stateIn(scope).collectAsState()
|
||||||
val landscapeColumns by libraryPreferences.landscapeColumns().stateIn(scope).collectAsState()
|
val landscapeColumns by libraryPreferences.landscapeColumns().stateIn(scope).collectAsState()
|
||||||
|
@ -102,8 +106,8 @@ class SettingsLibraryScreen : SearchableSettings {
|
||||||
preferenceItems = listOf(
|
preferenceItems = listOf(
|
||||||
Preference.PreferenceItem.TextPreference(
|
Preference.PreferenceItem.TextPreference(
|
||||||
title = stringResource(R.string.pref_library_columns),
|
title = stringResource(R.string.pref_library_columns),
|
||||||
subtitle = "${stringResource(R.string.portrait)}: ${getColumnValue(context, portraitColumns)}, " +
|
subtitle = "${stringResource(R.string.portrait)}: ${getColumnValue(portraitColumns)}, " +
|
||||||
"${stringResource(R.string.landscape)}: ${getColumnValue(context, landscapeColumns)}",
|
"${stringResource(R.string.landscape)}: ${getColumnValue(landscapeColumns)}",
|
||||||
onClick = { showDialog = true },
|
onClick = { showDialog = true },
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
@ -273,7 +277,6 @@ class SettingsLibraryScreen : SearchableSettings {
|
||||||
onDismissRequest: () -> Unit,
|
onDismissRequest: () -> Unit,
|
||||||
onValueChanged: (portrait: Int, landscape: Int) -> Unit,
|
onValueChanged: (portrait: Int, landscape: Int) -> Unit,
|
||||||
) {
|
) {
|
||||||
val context = LocalContext.current
|
|
||||||
var portraitValue by rememberSaveable { mutableStateOf(initialPortrait) }
|
var portraitValue by rememberSaveable { mutableStateOf(initialPortrait) }
|
||||||
var landscapeValue by rememberSaveable { mutableStateOf(initialLandscape) }
|
var landscapeValue by rememberSaveable { mutableStateOf(initialLandscape) }
|
||||||
|
|
||||||
|
@ -281,48 +284,30 @@ class SettingsLibraryScreen : SearchableSettings {
|
||||||
onDismissRequest = onDismissRequest,
|
onDismissRequest = onDismissRequest,
|
||||||
title = { Text(text = stringResource(R.string.pref_library_columns)) },
|
title = { Text(text = stringResource(R.string.pref_library_columns)) },
|
||||||
text = {
|
text = {
|
||||||
Row {
|
Column {
|
||||||
Column(
|
Row {
|
||||||
modifier = Modifier.weight(1f),
|
|
||||||
horizontalAlignment = Alignment.CenterHorizontally,
|
|
||||||
) {
|
|
||||||
Text(
|
Text(
|
||||||
|
modifier = Modifier.weight(1f),
|
||||||
text = stringResource(R.string.portrait),
|
text = stringResource(R.string.portrait),
|
||||||
|
textAlign = TextAlign.Center,
|
||||||
|
maxLines = 1,
|
||||||
style = MaterialTheme.typography.labelMedium,
|
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(
|
Text(
|
||||||
|
modifier = Modifier.weight(1f),
|
||||||
text = stringResource(R.string.landscape),
|
text = stringResource(R.string.landscape),
|
||||||
|
textAlign = TextAlign.Center,
|
||||||
|
maxLines = 1,
|
||||||
style = MaterialTheme.typography.labelMedium,
|
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 = {
|
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) {
|
return if (value == 0) {
|
||||||
context.getString(R.string.label_default)
|
stringResource(R.string.label_default)
|
||||||
} else {
|
} else {
|
||||||
value.toString()
|
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"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<resources>
|
<resources>
|
||||||
|
|
||||||
<declare-styleable name="MinMaxNumberPicker">
|
|
||||||
<attr name="min" format="integer"/>
|
|
||||||
<attr name="max" format="integer"/>
|
|
||||||
</declare-styleable>
|
|
||||||
|
|
||||||
<declare-styleable name="MaterialSpinnerView">
|
<declare-styleable name="MaterialSpinnerView">
|
||||||
<attr name="title" format="reference|string"/>
|
<attr name="title" format="reference|string"/>
|
||||||
<attr name="android:entries"/>
|
<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"
|
material3-adapter = "com.google.android.material:compose-theme-adapter-3:1.0.21"
|
||||||
material-icons = { module = "androidx.compose.material:material-icons-extended" }
|
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-webview = { module = "com.google.accompanist:accompanist-webview", version.ref = "accompanist" }
|
||||||
accompanist-swiperefresh = { module = "com.google.accompanist:accompanist-swiperefresh", 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" }
|
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"
|
directionalviewpager = "com.github.tachiyomiorg:DirectionalViewPager:1.0.0"
|
||||||
insetter = "dev.chrisbanes.insetter:insetter:0.6.1"
|
insetter = "dev.chrisbanes.insetter:insetter:0.6.1"
|
||||||
cascade = "me.saket.cascade:cascade-compose:2.0.0-beta1"
|
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"
|
wheelpicker = "com.github.commandiron:WheelPickerCompose:1.0.11"
|
||||||
|
|
||||||
conductor-core = { module = "com.bluelinelabs:conductor", version.ref = "conductor_version" }
|
conductor-core = { module = "com.bluelinelabs:conductor", version.ref = "conductor_version" }
|
||||||
|
|
Loading…
Reference in a new issue