diff --git a/app/src/main/java/eu/kanade/presentation/reader/appbars/ReaderAppBars.kt b/app/src/main/java/eu/kanade/presentation/reader/appbars/ReaderAppBars.kt index 9370ee567..8a1bd3c28 100644 --- a/app/src/main/java/eu/kanade/presentation/reader/appbars/ReaderAppBars.kt +++ b/app/src/main/java/eu/kanade/presentation/reader/appbars/ReaderAppBars.kt @@ -56,7 +56,7 @@ fun ReaderAppBars( enabledPrevious: Boolean, currentPage: Int, totalPages: Int, - onSliderValueChange: (Int) -> Unit, + onPageIndexChange: (Int) -> Unit, readingMode: ReadingMode, onClickReadingMode: () -> Unit, @@ -176,9 +176,8 @@ fun ReaderAppBars( enabledPrevious = enabledPrevious, currentPage = currentPage, totalPages = totalPages, - onSliderValueChange = onSliderValueChange, + onPageIndexChange = onPageIndexChange, ) - BottomReaderBar( backgroundColor = backgroundColor, readingMode = readingMode, diff --git a/app/src/main/java/eu/kanade/presentation/reader/components/ChapterNavigator.kt b/app/src/main/java/eu/kanade/presentation/reader/components/ChapterNavigator.kt index b9aa00c6b..d39391b74 100644 --- a/app/src/main/java/eu/kanade/presentation/reader/components/ChapterNavigator.kt +++ b/app/src/main/java/eu/kanade/presentation/reader/components/ChapterNavigator.kt @@ -4,6 +4,7 @@ import androidx.compose.foundation.background import androidx.compose.foundation.interaction.MutableInteractionSource import androidx.compose.foundation.interaction.collectIsDraggedAsState import androidx.compose.foundation.isSystemInDarkTheme +import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.Spacer import androidx.compose.foundation.layout.fillMaxWidth @@ -16,7 +17,6 @@ import androidx.compose.material3.FilledIconButton import androidx.compose.material3.Icon import androidx.compose.material3.IconButtonDefaults import androidx.compose.material3.MaterialTheme -import androidx.compose.material3.Slider import androidx.compose.material3.Text import androidx.compose.material3.surfaceColorAtElevation import androidx.compose.runtime.Composable @@ -29,6 +29,7 @@ import androidx.compose.runtime.setValue import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.draw.clip +import androidx.compose.ui.graphics.Color import androidx.compose.ui.hapticfeedback.HapticFeedbackType import androidx.compose.ui.platform.LocalHapticFeedback import androidx.compose.ui.platform.LocalLayoutDirection @@ -38,8 +39,8 @@ import androidx.compose.ui.unit.dp import eu.kanade.presentation.theme.TachiyomiPreviewTheme import eu.kanade.presentation.util.isTabletUi import tachiyomi.i18n.MR +import tachiyomi.presentation.core.components.material.Slider import tachiyomi.presentation.core.i18n.stringResource -import kotlin.math.roundToInt @Composable fun ChapterNavigator( @@ -50,7 +51,7 @@ fun ChapterNavigator( enabledPrevious: Boolean, currentPage: Int, totalPages: Int, - onSliderValueChange: (Int) -> Unit, + onPageIndexChange: (Int) -> Unit, ) { val isTabletUi = isTabletUi() val horizontalPadding = if (isTabletUi) 24.dp else 8.dp @@ -97,7 +98,11 @@ fun ChapterNavigator( .padding(horizontal = 16.dp), verticalAlignment = Alignment.CenterVertically, ) { - Text(text = currentPage.toString()) + Box(contentAlignment = Alignment.CenterEnd) { + Text(text = currentPage.toString()) + // Taking up full length so the slider doesn't shift when 'currentPage' length changes + Text(text = totalPages.toString(), color = Color.Transparent) + } val interactionSource = remember { MutableInteractionSource() } val sliderDragged by interactionSource.collectIsDraggedAsState() @@ -110,14 +115,11 @@ fun ChapterNavigator( modifier = Modifier .weight(1f) .padding(horizontal = 8.dp), - value = currentPage.toFloat(), - valueRange = 1f..totalPages.toFloat(), - steps = totalPages - 2, - onValueChange = { - val new = it.roundToInt() - 1 - if (new != currentPage) { - onSliderValueChange(new) - } + value = currentPage, + valueRange = 1..totalPages, + onValueChange = f@{ + if (it == currentPage) return@f + onPageIndexChange(it - 1) }, interactionSource = interactionSource, ) @@ -158,7 +160,7 @@ private fun ChapterNavigatorPreview() { enabledPrevious = true, currentPage = currentPage, totalPages = 10, - onSliderValueChange = { currentPage = it }, + onPageIndexChange = { currentPage = (it + 1) }, ) } } diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/reader/ReaderActivity.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/reader/ReaderActivity.kt index b9a89751c..d7a62fadb 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/reader/ReaderActivity.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/reader/ReaderActivity.kt @@ -401,7 +401,7 @@ class ReaderActivity : BaseActivity() { enabledPrevious = state.viewerChapters?.prevChapter != null, currentPage = state.currentPage, totalPages = state.totalPages, - onSliderValueChange = { + onPageIndexChange = { isScrollingThroughPages = true moveToPageIndex(it) }, diff --git a/presentation-core/src/main/java/tachiyomi/presentation/core/components/SettingsItems.kt b/presentation-core/src/main/java/tachiyomi/presentation/core/components/SettingsItems.kt index 7a1110857..acf55fcd7 100644 --- a/presentation-core/src/main/java/tachiyomi/presentation/core/components/SettingsItems.kt +++ b/presentation-core/src/main/java/tachiyomi/presentation/core/components/SettingsItems.kt @@ -28,7 +28,6 @@ import androidx.compose.material3.Icon import androidx.compose.material3.MaterialTheme import androidx.compose.material3.OutlinedTextField 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 @@ -46,6 +45,7 @@ import tachiyomi.core.common.preference.Preference import tachiyomi.core.common.preference.TriState import tachiyomi.core.common.preference.toggle import tachiyomi.presentation.core.components.material.DISABLED_ALPHA +import tachiyomi.presentation.core.components.material.Slider import tachiyomi.presentation.core.components.material.padding import tachiyomi.presentation.core.i18n.stringResource import tachiyomi.presentation.core.theme.header @@ -192,17 +192,14 @@ fun SliderItem( } Slider( - value = value.toFloat(), - onValueChange = { - val newValue = it.toInt() - if (newValue != value) { - onChange(newValue) - haptic.performHapticFeedback(HapticFeedbackType.TextHandleMove) - } - }, modifier = Modifier.weight(1.5f), - valueRange = min.toFloat()..max.toFloat(), - steps = max - min - 1, + value = value, + onValueChange = f@{ + if (it == value) return@f + onChange(it) + haptic.performHapticFeedback(HapticFeedbackType.TextHandleMove) + }, + valueRange = min..max, ) } } diff --git a/presentation-core/src/main/java/tachiyomi/presentation/core/components/material/Slider.kt b/presentation-core/src/main/java/tachiyomi/presentation/core/components/material/Slider.kt new file mode 100644 index 000000000..aa562ab32 --- /dev/null +++ b/presentation-core/src/main/java/tachiyomi/presentation/core/components/material/Slider.kt @@ -0,0 +1,48 @@ +package tachiyomi.presentation.core.components.material + +import androidx.annotation.IntRange +import androidx.compose.foundation.interaction.MutableInteractionSource +import androidx.compose.material3.Slider +import androidx.compose.material3.SliderColors +import androidx.compose.material3.SliderDefaults +import androidx.compose.material3.SliderState +import androidx.compose.runtime.Composable +import androidx.compose.runtime.remember +import androidx.compose.ui.Modifier + +@Composable +fun Slider( + value: Int, + onValueChange: (Int) -> Unit, + modifier: Modifier = Modifier, + enabled: Boolean = true, + valueRange: ClosedRange = 0..1, + @IntRange(from = 0) steps: Int = with(valueRange) { (endInclusive - start) - 1 }, + onValueChangeFinished: (() -> Unit)? = null, + colors: SliderColors = SliderDefaults.colors(), + interactionSource: MutableInteractionSource = remember { MutableInteractionSource() }, + thumb: @Composable (SliderState) -> Unit = { + SliderDefaults.Thumb( + interactionSource = interactionSource, + colors = colors, + enabled = enabled, + ) + }, + track: @Composable (SliderState) -> Unit = { sliderState -> + SliderDefaults.Track(colors = colors, enabled = enabled, sliderState = sliderState) + }, +) { + Slider( + value = value.toFloat(), + onValueChange = { onValueChange(it.toInt()) }, + modifier = modifier, + enabled = enabled, + valueRange = with(valueRange) { start.toFloat()..endInclusive.toFloat() }, + steps = steps, + onValueChangeFinished = onValueChangeFinished, + colors = colors, + interactionSource = interactionSource, + thumb = thumb, + track = track, + ) +}