diff --git a/feature/glance/src/main/java/com/sadellie/unitto/feature/glance/glance/CalculatorWidget.kt b/feature/glance/src/main/java/com/sadellie/unitto/feature/glance/glance/CalculatorWidget.kt index ccd5a581..a73df471 100644 --- a/feature/glance/src/main/java/com/sadellie/unitto/feature/glance/glance/CalculatorWidget.kt +++ b/feature/glance/src/main/java/com/sadellie/unitto/feature/glance/glance/CalculatorWidget.kt @@ -22,7 +22,7 @@ import android.content.Context import android.util.Log import androidx.compose.runtime.Composable import androidx.compose.runtime.collectAsState -import androidx.compose.ui.unit.TextUnit +import androidx.compose.ui.unit.DpSize import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp import androidx.datastore.preferences.core.Preferences @@ -32,9 +32,11 @@ import androidx.glance.GlanceId import androidx.glance.GlanceModifier import androidx.glance.GlanceTheme import androidx.glance.LocalContext +import androidx.glance.LocalSize import androidx.glance.action.Action import androidx.glance.action.ActionParameters import androidx.glance.appwidget.GlanceAppWidget +import androidx.glance.appwidget.SizeMode import androidx.glance.appwidget.action.actionRunCallback import androidx.glance.appwidget.appWidgetBackground import androidx.glance.appwidget.provideContent @@ -46,12 +48,12 @@ import androidx.glance.layout.Column import androidx.glance.layout.Row import androidx.glance.layout.fillMaxSize import androidx.glance.layout.fillMaxWidth -import androidx.glance.layout.padding import androidx.glance.state.GlanceStateDefinition import androidx.glance.state.PreferencesGlanceStateDefinition import androidx.glance.text.Text import androidx.glance.text.TextAlign import androidx.glance.text.TextStyle +import androidx.glance.unit.ColorProvider import com.sadellie.unitto.core.base.Token import com.sadellie.unitto.core.ui.common.textfield.AllFormatterSymbols import com.sadellie.unitto.core.ui.common.textfield.FormatterSymbols @@ -72,18 +74,25 @@ class CalculatorWidget : GlanceAppWidget() { fun userPrefRep(): UserPreferencesRepository } + override val sizeMode = SizeMode.Responsive( + setOf(SMALL, BIG) + ) + override val stateDefinition: GlanceStateDefinition<*> = PreferencesGlanceStateDefinition companion object { - val inputKey = ActionParameters.Key("inputKey") - val outputKey = ActionParameters.Key("outputKey") - val equalClickedKey = ActionParameters.Key("equalClickedKey") - val precisionKey = ActionParameters.Key("precisionKey") - val outputFormatKey = ActionParameters.Key("outputFormatKey") + internal val inputKey = ActionParameters.Key("inputKey") + internal val outputKey = ActionParameters.Key("outputKey") + internal val equalClickedKey = ActionParameters.Key("equalClickedKey") + internal val precisionKey = ActionParameters.Key("precisionKey") + internal val outputFormatKey = ActionParameters.Key("outputFormatKey") - val inputPrefKey = stringPreferencesKey("GLANCE_INPUT") - val outputPrefKey = stringPreferencesKey("GLANCE_OUTPUT") - val equalClickedPrefKey = booleanPreferencesKey("GLANCE_EQUAL_CLICKED") + internal val inputPrefKey = stringPreferencesKey("GLANCE_INPUT") + internal val outputPrefKey = stringPreferencesKey("GLANCE_OUTPUT") + internal val equalClickedPrefKey = booleanPreferencesKey("GLANCE_EQUAL_CLICKED") + + internal val SMALL = DpSize(200.dp, 250.dp) + internal val BIG = DpSize(250.dp, 400.dp) } override suspend fun provideGlance(context: Context, id: GlanceId) { @@ -148,38 +157,28 @@ private fun ReadyUI( .background(GlanceTheme.colors.background) .fillMaxSize() ) { - Column( - modifier = GlanceModifier - .background(GlanceTheme.colors.surfaceVariant) - .padding(8.dp) - ) { + val uiSectionModifier = GlanceModifier.fillMaxWidth() + + if (LocalSize.current != CalculatorWidget.SMALL) { ActionButtons( - modifier = GlanceModifier.fillMaxWidth().padding(vertical = 8.dp), - onCopyClick = copyAction( - output = output, - fractional = formatterSymbols.fractional - ), - onLaunchClick = launchAction(LocalContext.current) - ) - TextField( - modifier = GlanceModifier.fillMaxWidth(), - input = input, - formatterSymbols = formatterSymbols, - fontSize = 36.sp, - maxLines = 1 - ) - TextField( - modifier = GlanceModifier.fillMaxWidth(), - input = output, - formatterSymbols = formatterSymbols, - fontSize = 28.sp, - maxLines = 1 + modifier = uiSectionModifier + .background(GlanceTheme.colors.surfaceVariant), + output = output, + formatterSymbols = formatterSymbols ) } + TextFields( + modifier = uiSectionModifier + .background(GlanceTheme.colors.surfaceVariant) + .defaultWeight(), + input = input, + formatterSymbols = formatterSymbols, + output = output + ) + GlanceKeyboard( - modifier = GlanceModifier - .padding(8.dp), + modifier = uiSectionModifier, addTokenAction = { runCalculateAction( // Clear input if equal is clicked and new token is a Digit @@ -210,47 +209,66 @@ private fun ReadyUI( @Composable private fun ActionButtons( modifier: GlanceModifier, - onCopyClick: Action, - onLaunchClick: Action, + output: String, + formatterSymbols: FormatterSymbols, ) { Row( modifier = modifier ) { - val boxModifier = GlanceModifier.fillMaxWidth().defaultWeight() + val buttonModifier = GlanceModifier.fillMaxWidth().defaultWeight() IconButton( - glanceModifier = boxModifier, + glanceModifier = buttonModifier, containerColor = GlanceTheme.colors.primary, iconRes = R.drawable.content_copy, - onClick = onCopyClick + onClick = copyAction( + output = output, + fractional = formatterSymbols.fractional + ) ) IconButton( - glanceModifier = boxModifier, + glanceModifier = buttonModifier, containerColor = GlanceTheme.colors.primary, iconRes = R.drawable.open_in_new, - onClick = onLaunchClick + onClick = launchAction(LocalContext.current) ) } } @Composable -private fun TextField( +private fun TextFields( modifier: GlanceModifier, input: String, formatterSymbols: FormatterSymbols, - fontSize: TextUnit, - maxLines: Int, + output: String, ) { - Text( - text = input.formatExpression(formatterSymbols), + Column( modifier = modifier, - maxLines = maxLines, - style = TextStyle( - fontSize = fontSize, - textAlign = TextAlign.End, - color = GlanceTheme.colors.onSurfaceVariant + verticalAlignment = Alignment.Bottom + ) { + val textModifier = GlanceModifier.fillMaxWidth() + + Text( + text = input.formatExpression(formatterSymbols), + modifier = textModifier, + maxLines = 1, + style = TextStyle( + fontSize = 36.sp, + textAlign = TextAlign.End, + color = GlanceTheme.colors.onSurfaceVariant + ) ) - ) + Text( + text = output.formatExpression(formatterSymbols), + modifier = textModifier, + maxLines = 1, + style = TextStyle( + fontSize = 36.sp, + textAlign = TextAlign.End, + color = GlanceTheme.colors.onSurfaceVariant.withAlpha(alpha = 0.5f) + ) + ) + } } @Composable @@ -264,12 +282,10 @@ private fun GlanceKeyboard( useDot: Boolean, middleZero: Boolean, ) = Column(modifier = modifier) { - val rowModifier = GlanceModifier.defaultWeight().fillMaxWidth() + val rowModifier = GlanceModifier.fillMaxWidth() - Row( - modifier = rowModifier - ) { - val buttonModifier = GlanceModifier.fillMaxSize().defaultWeight() + Row(rowModifier) { + val buttonModifier = GlanceModifier.defaultWeight() IconButton( glanceModifier = buttonModifier, @@ -296,11 +312,8 @@ private fun GlanceKeyboard( onClick = addTokenAction(Token.Operator.divide) ) } - - Row( - modifier = rowModifier - ) { - val buttonModifier = GlanceModifier.fillMaxSize().defaultWeight() + Row(rowModifier) { + val buttonModifier = GlanceModifier.defaultWeight() IconButton( glanceModifier = buttonModifier, @@ -327,11 +340,8 @@ private fun GlanceKeyboard( onClick = addTokenAction(Token.Operator.multiply) ) } - - Row( - modifier = rowModifier - ) { - val buttonModifier = GlanceModifier.fillMaxSize().defaultWeight() + Row(rowModifier) { + val buttonModifier = GlanceModifier.defaultWeight() IconButton( glanceModifier = buttonModifier, @@ -358,11 +368,8 @@ private fun GlanceKeyboard( onClick = addTokenAction(Token.Operator.minus) ) } - - Row( - modifier = rowModifier - ) { - val buttonModifier = GlanceModifier.fillMaxSize().defaultWeight() + Row(rowModifier) { + val buttonModifier = GlanceModifier.defaultWeight() IconButton( glanceModifier = buttonModifier, @@ -389,11 +396,8 @@ private fun GlanceKeyboard( onClick = addTokenAction(Token.Operator.plus) ) } - - Row( - modifier = rowModifier - ) { - val buttonModifier = GlanceModifier.fillMaxSize().defaultWeight() + Row(rowModifier) { + val buttonModifier = GlanceModifier.defaultWeight() if (middleZero) { IconButton( @@ -436,3 +440,11 @@ private fun GlanceKeyboard( ) } } + +@Composable +private fun ColorProvider.withAlpha(alpha: Float): ColorProvider = + ColorProvider( + this + .getColor(LocalContext.current) + .copy(alpha = alpha) + ) diff --git a/feature/glance/src/main/java/com/sadellie/unitto/feature/glance/glance/IconButton.kt b/feature/glance/src/main/java/com/sadellie/unitto/feature/glance/glance/IconButton.kt index 893f7e43..128e8fc3 100644 --- a/feature/glance/src/main/java/com/sadellie/unitto/feature/glance/glance/IconButton.kt +++ b/feature/glance/src/main/java/com/sadellie/unitto/feature/glance/glance/IconButton.kt @@ -18,14 +18,20 @@ package com.sadellie.unitto.feature.glance.glance +import android.content.Context +import android.os.Build import androidx.annotation.DrawableRes import androidx.compose.runtime.Composable +import androidx.compose.ui.graphics.toArgb +import androidx.compose.ui.unit.Dp import androidx.compose.ui.unit.dp +import androidx.core.graphics.drawable.IconCompat import androidx.glance.ColorFilter import androidx.glance.GlanceModifier import androidx.glance.GlanceTheme import androidx.glance.Image import androidx.glance.ImageProvider +import androidx.glance.LocalContext import androidx.glance.action.Action import androidx.glance.action.clickable import androidx.glance.appwidget.cornerRadius @@ -34,8 +40,10 @@ import androidx.glance.color.ColorProviders import androidx.glance.layout.Alignment import androidx.glance.layout.Box import androidx.glance.layout.fillMaxWidth +import androidx.glance.layout.height import androidx.glance.layout.padding import androidx.glance.unit.ColorProvider +import com.sadellie.unitto.feature.glance.R @Composable internal fun IconButton( @@ -43,11 +51,11 @@ internal fun IconButton( containerColor: ColorProvider, @DrawableRes iconRes: Int, contentColor: ColorProvider = GlanceTheme.colors.contentColorFor(containerColor), - onClickKey: String = iconRes.toString(), onClick: Action, ) { Box( modifier = glanceModifier + .height(48.dp) .padding(4.dp), contentAlignment = Alignment.Center ) { @@ -55,8 +63,11 @@ internal fun IconButton( modifier = GlanceModifier .fillMaxWidth() .clickable(onClick) - .cornerRadius(100.dp) - .background(containerColor) + .cornerRadius( + context = LocalContext.current, + cornerRadius = 24.dp, + color = containerColor + ) .padding(horizontal = 16.dp, vertical = 8.dp), provider = ImageProvider(iconRes), contentDescription = null, @@ -74,22 +85,24 @@ private fun ColorProviders.contentColorFor(backgroundColor: ColorProvider): Colo else -> onBackground } -// https://gist.github.com/rozPierog/1145af6e1f10c9199000828ab4bd6bad -// Kinda works, but corners parameter needs to be split -//@SuppressLint("RestrictedApi") -//fun GlanceModifier.cornerRadiusCompat( -// cornerRadius: Int, -// @ColorInt color: Int, -// @FloatRange(from = 0.0, to = 1.0) backgroundAlpha: Float = 1f, -//): GlanceModifier { -// return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) { -// this.background(Color(color).copy(alpha = backgroundAlpha)) -// .cornerRadius(cornerRadius.dp) -// } else { -// val radii = FloatArray(8) { cornerRadius.toFloat() } -// val shape = ShapeDrawable(RoundRectShape(radii, null, null)) -// shape.paint.color = ColorUtils.setAlphaComponent(color, (255 * backgroundAlpha).toInt()) -// val bitmap = shape.toBitmap(width = 150, height = 75) -// this.background(BitmapImageProvider(bitmap)) -// } -//} +fun GlanceModifier.cornerRadius( + context: Context, + cornerRadius: Dp, + color: ColorProvider, +): GlanceModifier = when { + Build.VERSION.SDK_INT >= Build.VERSION_CODES.S -> this.background(color).cornerRadius(cornerRadius) + Build.VERSION.SDK_INT >= Build.VERSION_CODES.M -> this.background( + // This + ImageProvider( + // is + IconCompat + // so + .createWithResource(context, R.drawable.rounded_corners_rectangle_shape) + // fucking + .toIcon(context) + // stupid + .setTint(color.getColor(context).toArgb()) + ) + ) + else -> this.background(color) + } diff --git a/feature/glance/src/main/res/drawable/rounded_corners_rectangle_shape.xml b/feature/glance/src/main/res/drawable/rounded_corners_rectangle_shape.xml new file mode 100644 index 00000000..cdc0b02e --- /dev/null +++ b/feature/glance/src/main/res/drawable/rounded_corners_rectangle_shape.xml @@ -0,0 +1,23 @@ + + + + + + + diff --git a/feature/glance/src/main/res/xml/unitto_calculator_widget_info.xml b/feature/glance/src/main/res/xml/unitto_calculator_widget_info.xml index 746860d9..eaeb0755 100644 --- a/feature/glance/src/main/res/xml/unitto_calculator_widget_info.xml +++ b/feature/glance/src/main/res/xml/unitto_calculator_widget_info.xml @@ -18,13 +18,12 @@ \ No newline at end of file