diff --git a/app/src/main/java/eu/kanade/presentation/more/settings/widget/CustomBrightnessSlider.kt b/app/src/main/java/eu/kanade/presentation/more/settings/widget/CustomBrightnessSlider.kt
deleted file mode 100644
index a1da01d20..000000000
--- a/app/src/main/java/eu/kanade/presentation/more/settings/widget/CustomBrightnessSlider.kt
+++ /dev/null
@@ -1,100 +0,0 @@
-package eu.kanade.presentation.more.settings.widget
-
-import androidx.compose.foundation.layout.fillMaxWidth
-import androidx.compose.foundation.layout.height
-import androidx.compose.foundation.layout.padding
-import androidx.compose.runtime.Composable
-import androidx.compose.runtime.remember
-import androidx.compose.ui.Modifier
-import androidx.compose.ui.geometry.Offset
-import androidx.compose.ui.graphics.Canvas
-import androidx.compose.ui.graphics.Color
-import androidx.compose.ui.graphics.ImageBitmap
-import androidx.compose.ui.graphics.ImageBitmapConfig
-import androidx.compose.ui.graphics.LinearGradientShader
-import androidx.compose.ui.graphics.Paint
-import androidx.compose.ui.graphics.TileMode
-import androidx.compose.ui.platform.LocalDensity
-import androidx.compose.ui.unit.Dp
-import androidx.compose.ui.unit.IntSize
-import androidx.compose.ui.unit.dp
-import com.github.skydoves.colorpicker.compose.BrightnessSlider
-import com.github.skydoves.colorpicker.compose.ColorPickerController
-
-@Composable
-fun CustomBrightnessSlider(
- initialColor: Color,
- controller: ColorPickerController,
- modifier: Modifier = Modifier,
-) {
- // Define your colors and sizes directly
- val borderColor = Color.LightGray // Color for the slider border
- val thumbRadius = 12.dp // Example thumb radius
- val trackHeight = 4.dp // Example track height
- val borderSize = 1.dp // Example border size for the slider
-
- // Set up the paint for the thumb (wheel)
- val wheelPaint = Paint().apply {
- color = Color.White
- alpha = 1.0f
- }
-
- // This function creates the ImageBitmap for the gradient background of the slider
- @Composable
- fun rememberSliderGradientBitmap(
- width: Dp,
- height: Dp,
- startColor: Color,
- endColor: Color,
- ): ImageBitmap {
- val sizePx = with(LocalDensity.current) { IntSize(width.roundToPx(), height.roundToPx()) }
- return remember(sizePx, startColor, endColor) {
- ImageBitmap(sizePx.width, sizePx.height, ImageBitmapConfig.Argb8888).apply {
- val canvas = Canvas(this)
- val shader = LinearGradientShader(
- colors = listOf(startColor, endColor),
- from = Offset(0f, 0f),
- to = Offset(sizePx.width.toFloat(), 0f),
- tileMode = TileMode.Clamp,
- )
- val paint = Paint().apply {
- this.shader = shader
- }
- canvas.drawRect(
- 0f,
- 0f,
- sizePx.width.toFloat(),
- sizePx.height.toFloat(),
- paint,
- )
- }
- }
- }
-
- // Obtain the Composable's size for the gradient background
- val sliderWidth = 20.dp // Example width, adjust to your needs
- val sliderHeight = thumbRadius * 2 // The height is double the thumb radius
- val gradientBitmap = rememberSliderGradientBitmap(
- width = sliderWidth, // Subtract the thumb radii from the total width
- height = trackHeight,
- startColor = Color.White,
- endColor = Color.White,
- )
-
- BrightnessSlider(
- modifier = modifier
- .height(sliderHeight)
- .fillMaxWidth()
- .padding(horizontal = thumbRadius), // Padding equals thumb radius
- controller = controller,
- initialColor = initialColor,
- borderRadius = thumbRadius, // Use thumbRadius for the rounded corners
- borderSize = borderSize,
- borderColor = borderColor, // Use borderColor for the slider border
- wheelRadius = thumbRadius,
- wheelColor = Color.White, // Thumb (wheel) color
- wheelImageBitmap = gradientBitmap, // Use the generated gradient bitmap as the background
- wheelAlpha = 1.0f, // Full opacity for the thumb
- wheelPaint = wheelPaint, // Use the defined wheel paint
- )
-}
diff --git a/app/src/main/java/eu/kanade/presentation/more/settings/widget/ThemeColorPickerWidget.kt b/app/src/main/java/eu/kanade/presentation/more/settings/widget/ThemeColorPickerWidget.kt
index 9f628f540..378cec75d 100644
--- a/app/src/main/java/eu/kanade/presentation/more/settings/widget/ThemeColorPickerWidget.kt
+++ b/app/src/main/java/eu/kanade/presentation/more/settings/widget/ThemeColorPickerWidget.kt
@@ -1,48 +1,68 @@
package eu.kanade.presentation.more.settings.widget
import android.graphics.Bitmap
-import androidx.compose.animation.AnimatedVisibility
-import androidx.compose.animation.expandVertically
-import androidx.compose.animation.fadeIn
+import androidx.compose.animation.animateColorAsState
+import androidx.compose.animation.core.tween
+import androidx.compose.foundation.background
+import androidx.compose.foundation.clickable
+import androidx.compose.foundation.interaction.MutableInteractionSource
+import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
+import androidx.compose.foundation.layout.FlowRow
+import androidx.compose.foundation.layout.Row
+import androidx.compose.foundation.layout.aspectRatio
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.verticalScroll
-import androidx.compose.material3.Button
+import androidx.compose.material.icons.Icons
+import androidx.compose.material.icons.automirrored.outlined.ArrowForward
+import androidx.compose.material3.Icon
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
+import androidx.compose.runtime.rememberCoroutineScope
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.graphics.asImageBitmap
+import androidx.compose.ui.graphics.toArgb
import androidx.compose.ui.platform.LocalDensity
+import androidx.compose.ui.semantics.Role
+import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
+import com.github.skydoves.colorpicker.compose.AlphaTile
+import com.github.skydoves.colorpicker.compose.BrightnessSlider
import com.github.skydoves.colorpicker.compose.ColorEnvelope
import com.github.skydoves.colorpicker.compose.ColorPickerController
import com.github.skydoves.colorpicker.compose.HsvColorPicker
import eu.kanade.domain.ui.model.AppTheme
+import kotlinx.coroutines.launch
import tachiyomi.i18n.kmk.KMR
+import tachiyomi.presentation.core.components.material.Button
+import tachiyomi.presentation.core.components.material.ButtonDefaults.buttonColors
import tachiyomi.presentation.core.components.material.padding
import tachiyomi.presentation.core.i18n.stringResource
import kotlin.math.roundToInt
+@OptIn(ExperimentalStdlibApi::class)
@Composable
internal fun ThemeColorPickerWidget(
initialColor: Color,
controller: ColorPickerController,
onItemClick: (Color, AppTheme) -> Unit,
) {
+ val interactionSource = remember { MutableInteractionSource() }
var selectedColor by remember { mutableStateOf(initialColor) }
- var showConfirmButton by remember { mutableStateOf(false) }
+ var hexCode by remember { mutableStateOf(initialColor.toArgb().toHexString()) }
val wheelSize = with(LocalDensity.current) { 20.dp.toPx().roundToInt() }
val wheelStrokeWidth = with(LocalDensity.current) { 2.dp.toPx() }
@@ -70,16 +90,18 @@ internal fun ThemeColorPickerWidget(
BasePreferenceWidget(
subcomponent = {
+ val scope = rememberCoroutineScope()
+ val scrollState = rememberScrollState()
Column(
modifier = Modifier
.padding(horizontal = MaterialTheme.padding.large)
- .verticalScroll(rememberScrollState()),
+ .verticalScroll(scrollState),
horizontalAlignment = Alignment.CenterHorizontally,
) {
Box(
modifier = Modifier
.padding(
- vertical = MaterialTheme.padding.medium,
+ vertical = MaterialTheme.padding.small,
),
) {
HsvColorPicker(
@@ -89,36 +111,240 @@ internal fun ThemeColorPickerWidget(
wheelImageBitmap = wheelBitmap,
initialColor = initialColor,
onColorChanged = { colorEnvelope: ColorEnvelope ->
+ hexCode = colorEnvelope.hexCode
selectedColor = colorEnvelope.color
- showConfirmButton = true
},
)
}
- CustomBrightnessSlider(
+ BrightnessSlider(
modifier = Modifier
- .fillMaxWidth(),
+ .fillMaxWidth()
+ .padding(MaterialTheme.padding.small)
+ .height(24.dp),
controller = controller,
+ borderRadius = 12.dp,
+ wheelImageBitmap = wheelBitmap,
initialColor = initialColor,
)
- AnimatedVisibility(
- visible = showConfirmButton,
- enter = fadeIn() + expandVertically(),
+ Row(
modifier = Modifier
- .padding(top = MaterialTheme.padding.large),
+ .fillMaxWidth()
+ .padding(MaterialTheme.padding.small),
+ horizontalArrangement = Arrangement.Center,
) {
- Button(
- onClick = {
- onItemClick(selectedColor, AppTheme.CUSTOM)
- },
+ Column {
+ Text(
+ modifier = Modifier.align(Alignment.CenterHorizontally),
+ text = "#${initialColor.toArgb().toHexString()}",
+ style = MaterialTheme.typography.labelMedium.copy(
+ color = initialColor,
+ ),
+ )
+ AlphaTile(
+ modifier = Modifier
+ .size(64.dp)
+ .clip(MaterialTheme.shapes.small),
+ selectedColor = initialColor,
+ )
+ }
+
+ Icon(
+ imageVector = Icons.AutoMirrored.Outlined.ArrowForward,
+ tint = Color.Gray,
+ modifier = Modifier
+ .size(64.dp)
+ .align(Alignment.CenterVertically)
+ .padding(MaterialTheme.padding.small)
+ .padding(top = MaterialTheme.padding.small),
+ contentDescription = null,
+ )
+
+ Column {
+ Text(
+ modifier = Modifier.align(Alignment.CenterHorizontally),
+ text = "#$hexCode",
+ style = MaterialTheme.typography.labelMedium.copy(
+ color = selectedColor,
+ ),
+ )
+ AlphaTile(
+ modifier = Modifier
+ .size(64.dp)
+ .clip(MaterialTheme.shapes.small),
+ controller = controller,
+ )
+ }
+ }
+ Button(
+ onClick = {
+ onItemClick(selectedColor, AppTheme.CUSTOM)
+ },
+ colors = buttonColors(
+ containerColor = animateColorAsState(
+ label = "animateColorAsState",
+ targetValue = MaterialTheme.colorScheme.primary,
+ animationSpec = tween(durationMillis = 500),
+ ).value,
+ ),
+ interactionSource = interactionSource,
+ modifier = Modifier
+ .padding(vertical = MaterialTheme.padding.medium)
+ .fillMaxWidth()
+ .height(48.dp),
+ content = {
+ Text(text = stringResource(KMR.strings.action_confirm_color))
+ },
+ )
+
+ val colorsPalette = mapOf(
+ KMR.strings.custom_theme_palette_sunset to listOf(
+ Color(0xFF3e9cbf),
+ Color(0xFFa7ecf2),
+ Color(0xFFf2c43d),
+ Color(0xFFf17c37),
+ Color(0xFFf26d50),
+ ),
+ KMR.strings.custom_theme_palette_outrun to listOf(
+ Color(0xFFfffc40),
+ Color(0xFFfaba61),
+ Color(0xFFff8172),
+ Color(0xFFff2fa9),
+ Color(0xFF3a579a),
+ ),
+ KMR.strings.custom_theme_palette_raspberry to listOf(
+ Color(0xFF730517),
+ Color(0xFFf44560),
+ Color(0xFF44d1df),
+ Color(0xFF32a4a7),
+ Color(0xFF1e7069),
+ ),
+ KMR.strings.custom_theme_palette_cathode to listOf(
+ Color(0xFFa8216b),
+ Color(0xFFf1184c),
+ Color(0xFFf36943),
+ Color(0xFFf7dc66),
+ Color(0xFF2e9599),
+ ),
+ KMR.strings.custom_theme_palette_bubblegum to listOf(
+ Color(0xFFf8cd82),
+ Color(0xFFf65b74),
+ Color(0xFFf72078),
+ Color(0xFF23b0bd),
+ Color(0xFF0df7db),
+ ),
+ KMR.strings.custom_theme_palette_springfield to listOf(
+ Color(0xFF89d1dc),
+ Color(0xFFf89cfa),
+ Color(0xFFc386f1),
+ Color(0xFFf0d689),
+ Color(0xFFaff28b),
+ ),
+ KMR.strings.custom_theme_palette_spectral to listOf(
+ Color(0xFF471337),
+ Color(0xFFb13254),
+ Color(0xFFff5349),
+ Color(0xFFff7249),
+ Color(0xFFff9248),
+ ),
+ KMR.strings.custom_theme_palette_night_at_the_beach to listOf(
+ Color(0xFF262335),
+ Color(0xFF503c52),
+ Color(0xFF9f6c66),
+ Color(0xFFd4896a),
+ Color(0xFFffbb6c),
+ ),
+ KMR.strings.custom_theme_palette_casual to listOf(
+ Color(0xFF4f6a8f),
+ Color(0xFF88a2bc),
+ Color(0xFFf0dbb0),
+ Color(0xFFefb680),
+ Color(0xFFd99477),
+ ),
+ KMR.strings.custom_theme_palette_patagonia to listOf(
+ Color(0xFF202e32),
+ Color(0xFF85937a),
+ Color(0xFF586c5c),
+ Color(0xFFa9af90),
+ Color(0xFFdfdcb9),
+ ),
+ KMR.strings.custom_theme_palette_lcd to listOf(
+ Color(0xFF0f370e),
+ Color(0xFF30622f),
+ Color(0xFF8bad0d),
+ Color(0xFF9bbc0e),
+ ),
+ KMR.strings.custom_theme_palette_pop to listOf(
+ Color(0xFF00ff3f),
+ Color(0xFF35b5ff),
+ Color(0xFFff479c),
+ Color(0xFFfffb38),
+ ),
+ KMR.strings.custom_theme_palette_pico to listOf(
+ Color(0xFF1d2b53),
+ Color(0xFF7e2453),
+ Color(0xFF008751),
+ Color(0xFFab5236),
+ Color(0xFF5f574e),
+ Color(0xFFc2c3c7),
+ Color(0xFFff004d),
+ Color(0xFFffa300),
+ Color(0xFFffec27),
+ Color(0xFF00e536),
+ Color(0xFF29aeff),
+ Color(0xFF83769c),
+ Color(0xFFff77a8),
+ Color(0xFFffcdaa),
+ ),
+ )
+
+ colorsPalette.forEach { (title, colors) ->
+ Text(
+ text = stringResource(title),
+ style = MaterialTheme.typography.bodyLarge,
+ modifier = Modifier
+ .padding(top = MaterialTheme.padding.medium),
+ )
+
+ FlowRow(
modifier = Modifier
.fillMaxWidth()
- .height(48.dp),
- content = {
- Text(text = stringResource(KMR.strings.action_confirm_color))
- },
- )
+ .padding(top = MaterialTheme.padding.small),
+ horizontalArrangement = Arrangement.SpaceEvenly,
+ ) {
+ colors.forEach { color ->
+ Box(
+ modifier = Modifier
+ .background(
+ color = color,
+ shape = MaterialTheme.shapes.small,
+ )
+ .height(48.dp)
+ .aspectRatio(1f)
+ .clickable(
+ role = Role.Button,
+ onClick = {
+ controller.selectByColor(color, true)
+ scope.launch {
+ scrollState.animateScrollTo(0)
+ }
+ },
+ ),
+ content = { },
+ )
+ }
+ }
}
}
},
)
}
+
+@Preview
+@Composable
+fun ThemeColorPickerWidgetPreview() {
+ ThemeColorPickerWidget(
+ initialColor = Color(0xFFDF0090),
+ controller = ColorPickerController(),
+ onItemClick = { _, _ -> },
+ )
+}
diff --git a/i18n-kmk/src/commonMain/moko-resources/base/strings.xml b/i18n-kmk/src/commonMain/moko-resources/base/strings.xml
index 065e6b8f7..09eca6532 100644
--- a/i18n-kmk/src/commonMain/moko-resources/base/strings.xml
+++ b/i18n-kmk/src/commonMain/moko-resources/base/strings.xml
@@ -47,6 +47,19 @@
Palette Personalizer
Pick a seed color for the custom Theme
Custom Theme
+ Casual
+ Sunset
+ Outrun
+ Raspberry
+ Pop
+ Cathode
+ Bubblegum
+ Night at the beach
+ Spectral
+ Patagonia
+ Springfield
+ LCD
+ PICO-8
Show updating progress banner