diff --git a/app/src/main/java/com/llsl/viper4android/ui/screens/main/EffectSections.kt b/app/src/main/java/com/llsl/viper4android/ui/screens/main/EffectSections.kt index 6da3916..ebcf750 100644 --- a/app/src/main/java/com/llsl/viper4android/ui/screens/main/EffectSections.kt +++ b/app/src/main/java/com/llsl/viper4android/ui/screens/main/EffectSections.kt @@ -2,11 +2,15 @@ package com.llsl.viper4android.ui.screens.main 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.foundation.background import androidx.compose.foundation.clickable import androidx.compose.foundation.combinedClickable import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.BoxScope import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.Spacer @@ -21,6 +25,8 @@ import androidx.compose.foundation.verticalScroll import androidx.compose.material.icons.Icons import androidx.compose.material.icons.automirrored.filled.TrendingUp import androidx.compose.material.icons.filled.Add +import androidx.compose.material.icons.filled.KeyboardArrowDown +import androidx.compose.material.icons.filled.KeyboardArrowUp import androidx.compose.material.icons.filled.AspectRatio import androidx.compose.material.icons.filled.BlurCircular import androidx.compose.material.icons.filled.BlurOn @@ -66,6 +72,7 @@ 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.graphics.Color import androidx.compose.ui.graphics.vector.ImageVector import androidx.compose.ui.hapticfeedback.HapticFeedbackType import androidx.compose.ui.platform.LocalDensity @@ -95,6 +102,33 @@ private fun rawToDb(raw: Number): Double = 20.0 * log10(raw.toDouble() / 100.0) private fun dbToRaw(db: Double): Int = (10.0.pow(db / 20.0) * 100.0).roundToInt() +@Composable +private fun BoxScope.ScrollArrowHint( + visible: Boolean, + alignment: Alignment, + icon: ImageVector, + color: Color, +) { + AnimatedVisibility( + visible = visible, + modifier = Modifier.align(alignment), + enter = fadeIn(), + exit = fadeOut(), + ) { + Box( + modifier = Modifier.fillMaxWidth().height(28.dp).background(color), + contentAlignment = Alignment.Center, + ) { + Icon( + imageVector = icon, + contentDescription = null, + tint = MaterialTheme.colorScheme.onSurfaceVariant, + modifier = Modifier.size(20.dp), + ) + } + } +} + @OptIn(androidx.compose.foundation.ExperimentalFoundationApi::class) @Composable fun EffectSection( @@ -204,9 +238,19 @@ fun EffectSection( LocalWindowInfo.current.containerSize.height .toDp() / 2 } - Column( - modifier = Modifier.heightIn(max = maxHeight).verticalScroll(rememberScrollState()), - ) { RichText(text = stringResource(descriptionRes)) } + val scrollState = rememberScrollState() + // Show bottom ↓ only when resting at the very top and there is content below + val showBottomArrow = scrollState.value == 0 && scrollState.maxValue > 0 + // Show top ↑ only when resting at the very bottom and there is content above + val showTopArrow = scrollState.maxValue > 0 && scrollState.value == scrollState.maxValue + val dialogColor = MaterialTheme.colorScheme.surfaceContainerHigh + Box(modifier = Modifier.heightIn(max = maxHeight)) { + Column( + modifier = Modifier.verticalScroll(scrollState), + ) { RichText(text = stringResource(descriptionRes)) } + ScrollArrowHint(showTopArrow, Alignment.TopCenter, Icons.Default.KeyboardArrowUp, dialogColor) + ScrollArrowHint(showBottomArrow, Alignment.BottomCenter, Icons.Default.KeyboardArrowDown, dialogColor) + } }, confirmButton = { TextButton(onClick = { showHelpDialog = false }) {