From 9b3fef3bba9a303b4fc122b19e05b9f95d77f744 Mon Sep 17 00:00:00 2001 From: jeluchu Date: Sat, 14 Oct 2023 19:00:46 +0200 Subject: [PATCH] Refactor components and include new composables for premium screens --- .../ktx/bitmaps/BitmapExtensions.kt | 10 +- .../ktx/calendar/CalendarExtensions.kt | 17 +- .../ktx/colors/ColorsExtensions.kt | 6 +- .../ui/composables/cards/CategoryCard.kt | 8 +- .../ui/composables/cards/InfoCard.kt | 5 +- .../jchucomponents/ui/composables/cards/Te.kt | 163 ++++++++++++++++++ .../composables/preferences/PreferenceItem.kt | 6 +- .../preferences/PreferenceItemTitle.kt | 6 +- .../preferences/PreferenceSwitch.kt | 4 +- .../ui/composables/premium/TimeCard.kt | 118 +++++++++++++ .../composables/progress/LinearProgressbar.kt | 6 + .../composables/progress/ReadingIndicator.kt | 73 ++++++++ .../ui/extensions/Extensions.kt | 2 +- .../modifier/ClickableExtensions.kt | 75 ++++++++ .../extensions/modifier/ModifierExtensions.kt | 29 +--- .../ui/foundation/canva/CanvasBackground.kt | 5 - .../jchucomponents/ui/themes/Colors.kt | 10 ++ 17 files changed, 480 insertions(+), 63 deletions(-) create mode 100644 jchucomponents-ui/src/main/kotlin/com/jeluchu/jchucomponents/ui/composables/cards/Te.kt create mode 100644 jchucomponents-ui/src/main/kotlin/com/jeluchu/jchucomponents/ui/composables/premium/TimeCard.kt create mode 100644 jchucomponents-ui/src/main/kotlin/com/jeluchu/jchucomponents/ui/composables/progress/ReadingIndicator.kt create mode 100644 jchucomponents-ui/src/main/kotlin/com/jeluchu/jchucomponents/ui/extensions/modifier/ClickableExtensions.kt diff --git a/jchucomponents-ktx/src/main/kotlin/com/jeluchu/jchucomponents/ktx/bitmaps/BitmapExtensions.kt b/jchucomponents-ktx/src/main/kotlin/com/jeluchu/jchucomponents/ktx/bitmaps/BitmapExtensions.kt index 9f39a398..051ab641 100644 --- a/jchucomponents-ktx/src/main/kotlin/com/jeluchu/jchucomponents/ktx/bitmaps/BitmapExtensions.kt +++ b/jchucomponents-ktx/src/main/kotlin/com/jeluchu/jchucomponents/ktx/bitmaps/BitmapExtensions.kt @@ -16,7 +16,6 @@ import kotlin.math.floor import kotlin.math.sqrt - /** * * [Bitmap] Extension to show the original [Bitmap] that we pass from @@ -32,7 +31,6 @@ fun Bitmap?.orEmpty( defaultValue: Bitmap = Bitmap.createBitmap(1, 1, Bitmap.Config.ARGB_8888) ): Bitmap = this ?: defaultValue - /** * * [ImageBitmap] Extension to show the original [ImageBitmap] that we pass from @@ -56,9 +54,9 @@ fun ImageBitmap?.orEmpty( * @param bitmap the bitmap * @return the string */ -fun bitmapToBase64(bitmap: Bitmap): String? { +fun Bitmap.toBase64(): String? { val byteArrayOutputStream = ByteArrayOutputStream() - bitmap.compress(Bitmap.CompressFormat.PNG, 100, byteArrayOutputStream) + compress(Bitmap.CompressFormat.PNG, 100, byteArrayOutputStream) val byteArray: ByteArray = byteArrayOutputStream.toByteArray() return Base64.encodeToString(byteArray, Base64.DEFAULT) } @@ -68,9 +66,7 @@ fun Bitmap.scaleBitmap(maxBytes: Long = SIZE_2MB_BYTES.toLong()): Bitmap? { val currentHeight = this.height val currentPixels = currentWidth * currentHeight val maxPixels = maxBytes / 4 - if (currentPixels <= maxPixels) { - return this - } + if (currentPixels <= maxPixels) return this val scaleFactor = sqrt(maxPixels / currentPixels.toDouble()) val newWidthPx = floor(currentWidth * scaleFactor).toInt() val newHeightPx = floor(currentHeight * scaleFactor).toInt() diff --git a/jchucomponents-ktx/src/main/kotlin/com/jeluchu/jchucomponents/ktx/calendar/CalendarExtensions.kt b/jchucomponents-ktx/src/main/kotlin/com/jeluchu/jchucomponents/ktx/calendar/CalendarExtensions.kt index 246ce832..1a8404ad 100644 --- a/jchucomponents-ktx/src/main/kotlin/com/jeluchu/jchucomponents/ktx/calendar/CalendarExtensions.kt +++ b/jchucomponents-ktx/src/main/kotlin/com/jeluchu/jchucomponents/ktx/calendar/CalendarExtensions.kt @@ -1,6 +1,6 @@ package com.jeluchu.jchucomponents.ktx.calendar -import java.util.* +import java.util.Calendar var Calendar.year: Int get() = get(Calendar.YEAR) @@ -20,17 +20,14 @@ var Calendar.day: Int set(Calendar.DAY_OF_MONTH, value) } -fun Calendar.previousYear() = if (get(Calendar.MONTH) == Calendar.JANUARY) { - get(Calendar.YEAR) - 2 -} else get(Calendar.YEAR) - 1 +fun Calendar.previousYear() = if (get(Calendar.MONTH) == Calendar.JANUARY) get(Calendar.YEAR) - 2 +else get(Calendar.YEAR) - 1 -fun Calendar.previousMonth() = if (get(Calendar.MONTH) == Calendar.JANUARY) { - Calendar.DECEMBER -} else get(Calendar.MONTH) - 1 +fun Calendar.previousMonth() = if (get(Calendar.MONTH) == Calendar.JANUARY) Calendar.DECEMBER +else get(Calendar.MONTH) - 1 -fun Calendar.nextMonth() = if (get(Calendar.MONTH) == Calendar.DECEMBER) { - Calendar.JANUARY -} else get(Calendar.MONTH) + 1 +fun Calendar.nextMonth() = if (get(Calendar.MONTH) == Calendar.DECEMBER) Calendar.JANUARY +else get(Calendar.MONTH) + 1 fun Calendar.setLastDayOfMonth() = apply { add(Calendar.MONTH, 1) diff --git a/jchucomponents-ktx/src/main/kotlin/com/jeluchu/jchucomponents/ktx/colors/ColorsExtensions.kt b/jchucomponents-ktx/src/main/kotlin/com/jeluchu/jchucomponents/ktx/colors/ColorsExtensions.kt index 9a22f0fb..3dea527c 100644 --- a/jchucomponents-ktx/src/main/kotlin/com/jeluchu/jchucomponents/ktx/colors/ColorsExtensions.kt +++ b/jchucomponents-ktx/src/main/kotlin/com/jeluchu/jchucomponents/ktx/colors/ColorsExtensions.kt @@ -37,8 +37,10 @@ val Color.Companion.Random */ fun Color?.orTransparent(defaultValue: Color = Color.Transparent): Color = this ?: defaultValue - -fun Color.applyOpacity(enabled: Boolean): Color = if (enabled) this else this.copy(alpha = 0.62f) +fun Color.opacity( + enabled: Boolean, + opacity: Float = .62f +): Color = copy(alpha = if (enabled) 1f else opacity) fun Color.isDark() = ColorUtils.calculateLuminance(toArgb()) < 0.5 diff --git a/jchucomponents-ui/src/main/kotlin/com/jeluchu/jchucomponents/ui/composables/cards/CategoryCard.kt b/jchucomponents-ui/src/main/kotlin/com/jeluchu/jchucomponents/ui/composables/cards/CategoryCard.kt index 355d23d4..e425c7b0 100644 --- a/jchucomponents-ui/src/main/kotlin/com/jeluchu/jchucomponents/ui/composables/cards/CategoryCard.kt +++ b/jchucomponents-ui/src/main/kotlin/com/jeluchu/jchucomponents/ui/composables/cards/CategoryCard.kt @@ -24,7 +24,7 @@ import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.TextUnit import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp -import com.jeluchu.jchucomponents.ktx.colors.applyOpacity +import com.jeluchu.jchucomponents.ktx.colors.opacity import com.jeluchu.jchucomponents.ktx.strings.empty import com.jeluchu.jchucomponents.ui.R import com.jeluchu.jchucomponents.ui.composables.chips.Type @@ -46,14 +46,14 @@ fun CategoryCard( modifier = modifier .height(110.dp) .clip(16.cornerRadius()) - .background(backgroundColor.applyOpacity(enabled)) + .background(backgroundColor.opacity(enabled)) .clickable(onClick = onClick) .padding(10.dp) ) { Icon( imageVector = ImageVector.vectorResource(id = icon), contentDescription = String.empty(), - tint = textColor.applyOpacity(enabled), + tint = textColor.opacity(enabled), modifier = Modifier .size(35.dp) .align(Alignment.TopStart) @@ -63,7 +63,7 @@ fun CategoryCard( modifier = Modifier.align(Alignment.BottomEnd), text = title, colors = TypeColors( - container = textColor.applyOpacity(enabled) + container = textColor.opacity(enabled) ), fontSize = fontSize, style = textStyle diff --git a/jchucomponents-ui/src/main/kotlin/com/jeluchu/jchucomponents/ui/composables/cards/InfoCard.kt b/jchucomponents-ui/src/main/kotlin/com/jeluchu/jchucomponents/ui/composables/cards/InfoCard.kt index 34205a25..3d94aee1 100644 --- a/jchucomponents-ui/src/main/kotlin/com/jeluchu/jchucomponents/ui/composables/cards/InfoCard.kt +++ b/jchucomponents-ui/src/main/kotlin/com/jeluchu/jchucomponents/ui/composables/cards/InfoCard.kt @@ -118,13 +118,14 @@ fun InfoCard( ) } -@Preview +@Preview(backgroundColor = 0xFFFFFFFF, showBackground = true) @Composable fun InfoCardPreviewLight() { InfoCard( text = "Info", icon = R.drawable.ic_up_arrow, modifier = Modifier, - color = Color.White + color = Color.DarkGray, + tint = Color.DarkGray ) } diff --git a/jchucomponents-ui/src/main/kotlin/com/jeluchu/jchucomponents/ui/composables/cards/Te.kt b/jchucomponents-ui/src/main/kotlin/com/jeluchu/jchucomponents/ui/composables/cards/Te.kt new file mode 100644 index 00000000..aa63082a --- /dev/null +++ b/jchucomponents-ui/src/main/kotlin/com/jeluchu/jchucomponents/ui/composables/cards/Te.kt @@ -0,0 +1,163 @@ +package com.jeluchu.jchucomponents.ui.composables.cards + +import androidx.compose.foundation.background +import androidx.compose.foundation.clickable +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.fillMaxSize +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.layout.width +import androidx.compose.foundation.shape.CircleShape +import androidx.compose.foundation.shape.RoundedCornerShape +import androidx.compose.material.Button +import androidx.compose.material.ButtonDefaults +import androidx.compose.material.Card +import androidx.compose.material.ExperimentalMaterialApi +import androidx.compose.material.Icon +import androidx.compose.material.MaterialTheme +import androidx.compose.material.Surface +import androidx.compose.material.Text +import androidx.compose.runtime.Composable +import androidx.compose.runtime.Immutable +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.draw.clip +import androidx.compose.ui.draw.drawBehind +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.text.font.FontWeight +import androidx.compose.ui.text.style.TextAlign +import androidx.compose.ui.tooling.preview.Preview +import androidx.compose.ui.unit.Dp +import androidx.compose.ui.unit.dp +import androidx.compose.ui.unit.sp +import com.jeluchu.jchucomponents.ktx.compose.toPainter +import com.jeluchu.jchucomponents.ui.R +import com.jeluchu.jchucomponents.ui.composables.images.NetworkImage + +@OptIn(ExperimentalMaterialApi::class) +@Composable +fun Te( + image: String, + width: Dp = 270.dp, + height: Dp = 340.dp, + tag: String? = null, + onClick: () -> Unit = {}, + colors: TeColors = TeColors(), + onPrimaryButtonClick: () -> Unit = {}, + onSecondaryButtonClick: () -> Unit = {} +) = Card( + modifier = Modifier.width(width).height(height), + shape = RoundedCornerShape(28.dp), + elevation = 0.dp, + onClick = onClick +) { + Box { + NetworkImage( + modifier = Modifier.fillMaxSize(), + url = image + ) + + tag?.let { tag -> + Box( + modifier = Modifier + .fillMaxSize() + .padding(16.dp), + contentAlignment = Alignment.TopStart + ) { + Card( + backgroundColor = MaterialTheme.colors.secondary, + shape = RoundedCornerShape(9.dp), + modifier = Modifier + .size(height = 30.dp, width = 100.dp), + elevation = 0.dp + ) { + Text( + text = tag, + fontSize = 14.sp, + textAlign = TextAlign.Center, + fontWeight = FontWeight.Medium, + color = MaterialTheme.colors.onSecondary, + modifier = Modifier.padding(top = 4.dp, bottom = 4.dp) + ) + } + } + } + + Box( + modifier = Modifier + .fillMaxSize() + .padding(16.dp), + contentAlignment = Alignment.BottomStart + ) { + Row( + modifier = Modifier.fillMaxWidth(), + verticalAlignment = Alignment.CenterVertically, + horizontalArrangement = Arrangement.spacedBy(16.dp) + ) { + Button( + onClick = onPrimaryButtonClick, + modifier = Modifier + .width(176.dp) + .height(40.dp), + elevation = ButtonDefaults.elevation( + defaultElevation = 0.dp, + pressedElevation = 0.dp, + disabledElevation = 0.dp, + hoveredElevation = 0.dp, + focusedElevation = 0.dp, + ), + shape = RoundedCornerShape(45.dp), + colors = ButtonDefaults.buttonColors( + backgroundColor = colors.containerPrimaryButtonColor + ) + ) { + Text( + text = "Bid Now", + fontWeight = FontWeight.Medium, + fontSize = 16.sp, + color = colors.contentPrimaryButtonColor + ) + } + Surface( + modifier = Modifier.size(40.dp), + shape = CircleShape, + color = colors.containerSecondaryButtonColor, + contentColor = colors.contentSecondaryButtonColor, + onClick = onPrimaryButtonClick + ) { + Icon( + painter = R.drawable.ic_btn_qrcode.toPainter(), + contentDescription = "", + modifier = Modifier.padding(8.dp) + ) + } + } + } + } +} + +@Immutable +data class TeColors( + val containerPrimaryButtonColor: Color = Color.DarkGray, + val contentPrimaryButtonColor: Color = Color.White, + val containerSecondaryButtonColor: Color = Color.LightGray, + val contentSecondaryButtonColor: Color = Color.DarkGray, +) + +@Preview +@Composable +fun TePreview() { + Te( + image = "https://raw.githubusercontent.com/jeluchu/jeluchu.github.io/master/assets/img/home/project-img-2.png" + ) + + Te( + image = "https://raw.githubusercontent.com/jeluchu/jeluchu.github.io/master/assets/img/home/project-img-2.png", + tag = "Tendencia" + ) +} \ No newline at end of file diff --git a/jchucomponents-ui/src/main/kotlin/com/jeluchu/jchucomponents/ui/composables/preferences/PreferenceItem.kt b/jchucomponents-ui/src/main/kotlin/com/jeluchu/jchucomponents/ui/composables/preferences/PreferenceItem.kt index 84d1a523..8374d6c0 100644 --- a/jchucomponents-ui/src/main/kotlin/com/jeluchu/jchucomponents/ui/composables/preferences/PreferenceItem.kt +++ b/jchucomponents-ui/src/main/kotlin/com/jeluchu/jchucomponents/ui/composables/preferences/PreferenceItem.kt @@ -20,7 +20,7 @@ import androidx.compose.ui.graphics.painter.Painter import androidx.compose.ui.graphics.vector.ImageVector import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp -import com.jeluchu.jchucomponents.ktx.colors.applyOpacity +import com.jeluchu.jchucomponents.ktx.colors.opacity @OptIn(ExperimentalFoundationApi::class) @Composable @@ -56,7 +56,7 @@ fun PreferenceItem( modifier = Modifier .padding(start = 8.dp, end = 16.dp) .size(24.dp), - tint = MaterialTheme.colorScheme.onSurfaceVariant.applyOpacity(enabled) + tint = MaterialTheme.colorScheme.onSurfaceVariant.opacity(enabled) ) } @@ -67,7 +67,7 @@ fun PreferenceItem( modifier = Modifier .padding(start = 8.dp, end = 16.dp) .size(24.dp), - tint = MaterialTheme.colorScheme.onSurfaceVariant.applyOpacity(enabled) + tint = MaterialTheme.colorScheme.onSurfaceVariant.opacity(enabled) ) } diff --git a/jchucomponents-ui/src/main/kotlin/com/jeluchu/jchucomponents/ui/composables/preferences/PreferenceItemTitle.kt b/jchucomponents-ui/src/main/kotlin/com/jeluchu/jchucomponents/ui/composables/preferences/PreferenceItemTitle.kt index c73e0f3f..d081925b 100644 --- a/jchucomponents-ui/src/main/kotlin/com/jeluchu/jchucomponents/ui/composables/preferences/PreferenceItemTitle.kt +++ b/jchucomponents-ui/src/main/kotlin/com/jeluchu/jchucomponents/ui/composables/preferences/PreferenceItemTitle.kt @@ -12,7 +12,7 @@ import androidx.compose.ui.unit.Dp import androidx.compose.ui.unit.TextUnit import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp -import com.jeluchu.jchucomponents.ktx.colors.applyOpacity +import com.jeluchu.jchucomponents.ktx.colors.opacity @Composable internal fun PreferenceItemTitle( @@ -31,7 +31,7 @@ internal fun PreferenceItemTitle( maxLines = maxLines, fontSize = fontSize, style = style, - color = color.applyOpacity(enabled), + color = color.opacity(enabled), overflow = overflow ) } @@ -53,7 +53,7 @@ internal fun PreferenceItemDescription( maxLines = maxLines, fontSize = fontSize, style = style, - color = color.applyOpacity(enabled), + color = color.opacity(enabled), overflow = overflow ) } \ No newline at end of file diff --git a/jchucomponents-ui/src/main/kotlin/com/jeluchu/jchucomponents/ui/composables/preferences/PreferenceSwitch.kt b/jchucomponents-ui/src/main/kotlin/com/jeluchu/jchucomponents/ui/composables/preferences/PreferenceSwitch.kt index ff9eb5f1..0edc967c 100644 --- a/jchucomponents-ui/src/main/kotlin/com/jeluchu/jchucomponents/ui/composables/preferences/PreferenceSwitch.kt +++ b/jchucomponents-ui/src/main/kotlin/com/jeluchu/jchucomponents/ui/composables/preferences/PreferenceSwitch.kt @@ -21,7 +21,7 @@ import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.vector.ImageVector import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp -import com.jeluchu.jchucomponents.ktx.colors.applyOpacity +import com.jeluchu.jchucomponents.ktx.colors.opacity @Composable fun PreferenceSwitch( @@ -63,7 +63,7 @@ fun PreferenceSwitch( modifier = Modifier .padding(start = 8.dp, end = 16.dp) .size(24.dp), - tint = MaterialTheme.colorScheme.onSurfaceVariant.applyOpacity(enabled) + tint = MaterialTheme.colorScheme.onSurfaceVariant.opacity(enabled) ) } Column( diff --git a/jchucomponents-ui/src/main/kotlin/com/jeluchu/jchucomponents/ui/composables/premium/TimeCard.kt b/jchucomponents-ui/src/main/kotlin/com/jeluchu/jchucomponents/ui/composables/premium/TimeCard.kt new file mode 100644 index 00000000..915348fb --- /dev/null +++ b/jchucomponents-ui/src/main/kotlin/com/jeluchu/jchucomponents/ui/composables/premium/TimeCard.kt @@ -0,0 +1,118 @@ +package com.jeluchu.jchucomponents.ui.composables.premium + +import androidx.compose.animation.core.animateFloatAsState +import androidx.compose.foundation.background +import androidx.compose.foundation.border +import androidx.compose.foundation.clickable +import androidx.compose.foundation.gestures.awaitFirstDown +import androidx.compose.foundation.gestures.waitForUpOrCancellation +import androidx.compose.foundation.interaction.MutableInteractionSource +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.padding +import androidx.compose.material.Divider +import androidx.compose.material.MaterialTheme +import androidx.compose.material.Text +import androidx.compose.runtime.Composable +import androidx.compose.runtime.Immutable +import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.remember +import androidx.compose.runtime.setValue +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.composed +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.graphics.graphicsLayer +import androidx.compose.ui.input.pointer.pointerInput +import androidx.compose.ui.text.TextStyle +import androidx.compose.ui.text.font.FontWeight +import androidx.compose.ui.text.style.TextAlign +import androidx.compose.ui.tooling.preview.Preview +import androidx.compose.ui.unit.dp +import androidx.compose.ui.unit.sp +import com.jeluchu.jchucomponents.ui.extensions.modifier.bounceClick +import com.jeluchu.jchucomponents.ui.extensions.modifier.cornerRadius +import com.jeluchu.jchucomponents.ui.themes.primary + +@Composable +fun TimeCard( + title: String, + amount: String, + description: String, + colors: TimeCardColors = TimeCardColors(), + style: TextStyle = MaterialTheme.typography.subtitle2 +) = + Column( + modifier = Modifier + .bounceClick { + } + .background( + shape = 16.cornerRadius(), + color = colors.containerColor + ) + .border( + 1.dp, + color = colors.contentPrimaryColor, + shape = 16.cornerRadius(), + ), + horizontalAlignment = Alignment.CenterHorizontally, + verticalArrangement = Arrangement.spacedBy(15.dp) + ) { + Text( + text = title, + color = colors.contentPrimaryColor, + style = style.copy( + fontSize = 16.sp, + fontWeight = FontWeight.W600, + lineHeight = 25.sp + ), + textAlign = TextAlign.Center, + modifier = Modifier.padding(top = 15.dp) + ) + Divider( + color = colors.contentPrimaryColor, + thickness = 1.dp + ) + Text( + text = amount, + color = colors.contentSecondaryColor, + style = style.copy( + fontSize = 16.sp, + fontWeight = FontWeight.W600, + lineHeight = 25.sp + ), + textAlign = TextAlign.Center, + //modifier = Modifier.padding(15.dp) + ) + + Text( + text = description, + color = colors.contentSecondaryColor.copy(.5f), + style = style.copy( + fontSize = 12.sp, + fontWeight = FontWeight.W500, + lineHeight = 25.sp + ), + textAlign = TextAlign.Center, + modifier = Modifier.padding(bottom = 15.dp) + ) + } + +@Immutable +data class TimeCardColors( + val containerColor: Color = Color.DarkGray, + val contentPrimaryColor: Color = primary, + val contentSecondaryColor: Color = Color.White +) + + +@Preview +@Composable +fun TimeCardPreview() { + TimeCard( + title = "Mensual", + amount = "1,99€", + description = "por mes" + ) +} \ No newline at end of file diff --git a/jchucomponents-ui/src/main/kotlin/com/jeluchu/jchucomponents/ui/composables/progress/LinearProgressbar.kt b/jchucomponents-ui/src/main/kotlin/com/jeluchu/jchucomponents/ui/composables/progress/LinearProgressbar.kt index 2cf6ebc6..511f1360 100644 --- a/jchucomponents-ui/src/main/kotlin/com/jeluchu/jchucomponents/ui/composables/progress/LinearProgressbar.kt +++ b/jchucomponents-ui/src/main/kotlin/com/jeluchu/jchucomponents/ui/composables/progress/LinearProgressbar.kt @@ -11,6 +11,8 @@ import androidx.compose.animation.core.tween import androidx.compose.foundation.Canvas import androidx.compose.foundation.Image import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.BoxWithConstraints import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.fillMaxWidth @@ -25,8 +27,12 @@ import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.runtime.Immutable import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.remember +import androidx.compose.runtime.setValue import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier +import androidx.compose.ui.draw.drawBehind import androidx.compose.ui.geometry.Offset import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.StrokeCap diff --git a/jchucomponents-ui/src/main/kotlin/com/jeluchu/jchucomponents/ui/composables/progress/ReadingIndicator.kt b/jchucomponents-ui/src/main/kotlin/com/jeluchu/jchucomponents/ui/composables/progress/ReadingIndicator.kt new file mode 100644 index 00000000..30803cc3 --- /dev/null +++ b/jchucomponents-ui/src/main/kotlin/com/jeluchu/jchucomponents/ui/composables/progress/ReadingIndicator.kt @@ -0,0 +1,73 @@ +package com.jeluchu.jchucomponents.ui.composables.progress + +import androidx.compose.animation.core.animateFloatAsState +import androidx.compose.animation.core.tween +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.BoxWithConstraints +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.height +import androidx.compose.foundation.layout.padding +import androidx.compose.material.MaterialTheme +import androidx.compose.runtime.* +import androidx.compose.ui.Modifier +import androidx.compose.ui.draw.drawBehind +import androidx.compose.ui.geometry.Offset +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.graphics.StrokeCap +import androidx.compose.ui.tooling.preview.Preview +import androidx.compose.ui.unit.dp + +@Composable +fun ReadingIndicator( + lastPage: Float, + totalPage: Float, + modifier: Modifier = Modifier +) { + val color = if (MaterialTheme.colors.isLight) Color.LightGray else Color.DarkGray + + var width by remember { + mutableStateOf(0f) + } + + val anim by animateFloatAsState( + targetValue = width * (lastPage / totalPage), + tween(durationMillis = 2000) + ) + + BoxWithConstraints( + modifier = Modifier.fillMaxWidth().padding(20.dp).height(20.dp) + ) { + Box( + modifier = modifier + .fillMaxWidth() + .drawBehind { + width = size.width + drawLine( + color = color, + start = Offset.Zero, + end = Offset(size.width, 0f), + cap = StrokeCap.Round, + strokeWidth = 20f + ) + } + .drawBehind { + drawLine( + color = Color.DarkGray, + start = Offset.Zero, + end = Offset(anim, 0f), + cap = StrokeCap.Round, + strokeWidth = 20f + ) + } + ) + } +} + +@Preview +@Composable +fun ReadingIndicatorPreview() { + ReadingIndicator( + lastPage = 2f, + totalPage = 10f, + ) +} \ No newline at end of file diff --git a/jchucomponents-ui/src/main/kotlin/com/jeluchu/jchucomponents/ui/extensions/Extensions.kt b/jchucomponents-ui/src/main/kotlin/com/jeluchu/jchucomponents/ui/extensions/Extensions.kt index a1c3b545..36ca61e5 100644 --- a/jchucomponents-ui/src/main/kotlin/com/jeluchu/jchucomponents/ui/extensions/Extensions.kt +++ b/jchucomponents-ui/src/main/kotlin/com/jeluchu/jchucomponents/ui/extensions/Extensions.kt @@ -11,7 +11,7 @@ fun Context.getBitmapFromVectorDrawable( width: Int?, height: Int?, drawableId: Int -): Bitmap? { +): Bitmap { val drawable = ContextCompat.getDrawable(this, drawableId) val bitmap = Bitmap.createBitmap( width ?: drawable?.intrinsicWidth ?: 1, diff --git a/jchucomponents-ui/src/main/kotlin/com/jeluchu/jchucomponents/ui/extensions/modifier/ClickableExtensions.kt b/jchucomponents-ui/src/main/kotlin/com/jeluchu/jchucomponents/ui/extensions/modifier/ClickableExtensions.kt new file mode 100644 index 00000000..43f2fdf1 --- /dev/null +++ b/jchucomponents-ui/src/main/kotlin/com/jeluchu/jchucomponents/ui/extensions/modifier/ClickableExtensions.kt @@ -0,0 +1,75 @@ +package com.jeluchu.jchucomponents.ui.extensions.modifier + +import androidx.compose.animation.core.animateFloatAsState +import androidx.compose.foundation.clickable +import androidx.compose.foundation.gestures.awaitFirstDown +import androidx.compose.foundation.gestures.waitForUpOrCancellation +import androidx.compose.foundation.interaction.MutableInteractionSource +import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.remember +import androidx.compose.runtime.setValue +import androidx.compose.ui.Modifier +import androidx.compose.ui.composed +import androidx.compose.ui.graphics.graphicsLayer +import androidx.compose.ui.input.pointer.pointerInput +import androidx.compose.ui.semantics.Role + +inline fun Modifier.noRippleClickable( + role: Role? = null, + enabled: Boolean = true, + onClickLabel: String? = null, + crossinline onClick: () -> Unit +) = composed { + clickable( + role = role, + enabled = enabled, + indication = null, + onClickLabel = onClickLabel, + interactionSource = remember { MutableInteractionSource() } + ) { onClick() } +} + +fun Modifier.interceptionClickable(): Modifier = composed { + clickable( + indication = null, + interactionSource = remember { MutableInteractionSource() } + ) {} +} + +fun Modifier.bounceClick(onClick: () -> Unit = {}) = composed { + var buttonState by remember { mutableStateOf(ButtonState.Idle) } + val scale by animateFloatAsState(if (buttonState == ButtonState.Pressed) 0.90f else 1f) + + this + .graphicsLayer { + scaleX = scale + scaleY = scale + } + .click { + onClick() + } + .pointerInput(buttonState) { + awaitPointerEventScope { + buttonState = if (buttonState == ButtonState.Pressed) { + waitForUpOrCancellation() + ButtonState.Idle + } else { + awaitFirstDown(false) + ButtonState.Pressed + } + } + } +} + +enum class ButtonState { Pressed, Idle } + +fun Modifier.click(onClick: () -> Unit = {}) = composed { + clickable( + interactionSource = remember { MutableInteractionSource() }, + indication = null, + onClick = { + onClick() + } + ) +} \ No newline at end of file diff --git a/jchucomponents-ui/src/main/kotlin/com/jeluchu/jchucomponents/ui/extensions/modifier/ModifierExtensions.kt b/jchucomponents-ui/src/main/kotlin/com/jeluchu/jchucomponents/ui/extensions/modifier/ModifierExtensions.kt index c46e9772..f2b5b07e 100644 --- a/jchucomponents-ui/src/main/kotlin/com/jeluchu/jchucomponents/ui/extensions/modifier/ModifierExtensions.kt +++ b/jchucomponents-ui/src/main/kotlin/com/jeluchu/jchucomponents/ui/extensions/modifier/ModifierExtensions.kt @@ -15,6 +15,7 @@ import androidx.compose.foundation.lazy.LazyListState import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.runtime.Composable import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableFloatStateOf import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember import androidx.compose.runtime.setValue @@ -33,6 +34,8 @@ import androidx.compose.ui.input.nestedscroll.nestedScroll import androidx.compose.ui.semantics.Role import androidx.compose.ui.unit.Dp import androidx.compose.ui.unit.dp +import com.jeluchu.jchucomponents.ui.runtime.remember.rememberMutableFloatStateOf +import com.jeluchu.jchucomponents.ui.runtime.remember.rememberMutableIntStateOf /** ---- MODIFIER EXT -------------------------------------------------------------------------- **/ @@ -51,8 +54,8 @@ fun Int.Width() = Spacer(modifier = Modifier.width(this.dp)) fun Modifier.graphicsCollapse( state: LazyListState ) = this.composed { - var scrolledY by remember { mutableStateOf(0f) } - var previousOffset by remember { mutableStateOf(0) } + var scrolledY by rememberMutableFloatStateOf(0f) + var previousOffset by rememberMutableIntStateOf(0) graphicsLayer { scrolledY += state.firstVisibleItemScrollOffset - previousOffset translationY = scrolledY * 0.5f @@ -60,28 +63,6 @@ fun Modifier.graphicsCollapse( } } -inline fun Modifier.noRippleClickable( - role: Role? = null, - enabled: Boolean = true, - onClickLabel: String? = null, - crossinline onClick: () -> Unit -) = composed { - clickable( - role = role, - enabled = enabled, - indication = null, - onClickLabel = onClickLabel, - interactionSource = remember { MutableInteractionSource() } - ) { onClick() } -} - -fun Modifier.interceptionClickable(): Modifier = composed { - clickable( - indication = null, - interactionSource = remember { MutableInteractionSource() } - ) {} -} - /** ---- LISTS -------------------------------------------------------------------------------- **/ fun Modifier.disableVerticalScroll() = diff --git a/jchucomponents-ui/src/main/kotlin/com/jeluchu/jchucomponents/ui/foundation/canva/CanvasBackground.kt b/jchucomponents-ui/src/main/kotlin/com/jeluchu/jchucomponents/ui/foundation/canva/CanvasBackground.kt index e7e8f463..cc29d610 100644 --- a/jchucomponents-ui/src/main/kotlin/com/jeluchu/jchucomponents/ui/foundation/canva/CanvasBackground.kt +++ b/jchucomponents-ui/src/main/kotlin/com/jeluchu/jchucomponents/ui/foundation/canva/CanvasBackground.kt @@ -6,7 +6,6 @@ package com.jeluchu.jchucomponents.ui.foundation.canva -import android.graphics.Bitmap import androidx.compose.foundation.Canvas import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier @@ -37,10 +36,6 @@ fun CanvasBackground( context.getBitmapFromVectorDrawable( with, height, drawable - )?.asImageBitmap() ?: Bitmap.createBitmap( - 1, - 1, - Bitmap.Config.ARGB_8888 ).asImageBitmap() val paint = Paint().asFrameworkPaint().apply { diff --git a/jchucomponents-ui/src/main/kotlin/com/jeluchu/jchucomponents/ui/themes/Colors.kt b/jchucomponents-ui/src/main/kotlin/com/jeluchu/jchucomponents/ui/themes/Colors.kt index fc07f3eb..3e6bf810 100644 --- a/jchucomponents-ui/src/main/kotlin/com/jeluchu/jchucomponents/ui/themes/Colors.kt +++ b/jchucomponents-ui/src/main/kotlin/com/jeluchu/jchucomponents/ui/themes/Colors.kt @@ -6,8 +6,18 @@ package com.jeluchu.jchucomponents.ui.themes +import androidx.compose.runtime.Stable import androidx.compose.ui.graphics.Color +@Stable +val primary = Color(0xFFA9D2B5) + +@Stable +val secondary = Color(0xFF79BA98) + +@Stable +val darkGreen = Color(0xFF4D7C63) + val green200 = Color(0xffa5d6a7) val green500 = Color(0xff4caf50) val green700 = Color(0xff388e3c)