mirror of
https://github.com/Myzel394/NumberHub.git
synced 2025-06-19 00:35:26 +02:00
Refactor widget
This commit is contained in:
parent
3638af2e45
commit
f88fba44bb
@ -0,0 +1,95 @@
|
||||
/*
|
||||
* Unitto is a unit converter for Android
|
||||
* Copyright (c) 2024 Elshan Agaev
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.sadellie.unitto.feature.glance.glance
|
||||
|
||||
import androidx.annotation.DrawableRes
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.glance.ColorFilter
|
||||
import androidx.glance.GlanceModifier
|
||||
import androidx.glance.GlanceTheme
|
||||
import androidx.glance.Image
|
||||
import androidx.glance.ImageProvider
|
||||
import androidx.glance.action.Action
|
||||
import androidx.glance.action.clickable
|
||||
import androidx.glance.appwidget.cornerRadius
|
||||
import androidx.glance.background
|
||||
import androidx.glance.color.ColorProviders
|
||||
import androidx.glance.layout.Alignment
|
||||
import androidx.glance.layout.Box
|
||||
import androidx.glance.layout.fillMaxWidth
|
||||
import androidx.glance.layout.padding
|
||||
import androidx.glance.unit.ColorProvider
|
||||
|
||||
@Composable
|
||||
internal fun IconButton(
|
||||
glanceModifier: GlanceModifier,
|
||||
containerColor: ColorProvider,
|
||||
@DrawableRes iconRes: Int,
|
||||
contentColor: ColorProvider = GlanceTheme.colors.contentColorFor(containerColor),
|
||||
onClickKey: String = iconRes.toString(),
|
||||
onClick: Action,
|
||||
) {
|
||||
Box(
|
||||
modifier = glanceModifier
|
||||
.padding(4.dp),
|
||||
contentAlignment = Alignment.Center
|
||||
) {
|
||||
Image(
|
||||
modifier = GlanceModifier
|
||||
.fillMaxWidth()
|
||||
.clickable(onClick)
|
||||
.cornerRadius(100.dp)
|
||||
.background(containerColor)
|
||||
.padding(horizontal = 16.dp, vertical = 8.dp),
|
||||
provider = ImageProvider(iconRes),
|
||||
contentDescription = null,
|
||||
colorFilter = ColorFilter.tint(contentColor)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private fun ColorProviders.contentColorFor(backgroundColor: ColorProvider): ColorProvider =
|
||||
when (backgroundColor) {
|
||||
primary -> onPrimary
|
||||
primaryContainer -> onPrimaryContainer
|
||||
inverseOnSurface -> onSurfaceVariant
|
||||
tertiaryContainer -> onTertiaryContainer
|
||||
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))
|
||||
// }
|
||||
//}
|
@ -0,0 +1,30 @@
|
||||
/*
|
||||
* Unitto is a unit converter for Android
|
||||
* Copyright (c) 2024 Elshan Agaev
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.sadellie.unitto.feature.glance.glance
|
||||
|
||||
import androidx.compose.ui.text.TextRange
|
||||
import androidx.compose.ui.text.input.TextFieldValue
|
||||
import com.sadellie.unitto.core.ui.common.textfield.addBracket
|
||||
import com.sadellie.unitto.core.ui.common.textfield.addTokens
|
||||
|
||||
internal fun String.addToken(token: String): String =
|
||||
TextFieldValue(this, TextRange(length)).addTokens(token).text
|
||||
|
||||
internal fun String.addBracket(): String =
|
||||
TextFieldValue(this, TextRange(length)).addBracket().text
|
@ -18,60 +18,42 @@
|
||||
|
||||
package com.sadellie.unitto.feature.glance.glance
|
||||
|
||||
import android.content.ComponentName
|
||||
import android.content.Context
|
||||
import android.os.Build
|
||||
import androidx.annotation.DrawableRes
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.collectAsState
|
||||
import androidx.compose.ui.text.TextRange
|
||||
import androidx.compose.ui.text.input.TextFieldValue
|
||||
import androidx.compose.ui.unit.TextUnit
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.compose.ui.unit.sp
|
||||
import androidx.datastore.preferences.core.Preferences
|
||||
import androidx.datastore.preferences.core.stringPreferencesKey
|
||||
import androidx.glance.ColorFilter
|
||||
import androidx.glance.GlanceId
|
||||
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.ActionParameters
|
||||
import androidx.glance.action.actionParametersOf
|
||||
import androidx.glance.action.actionStartActivity
|
||||
import androidx.glance.action.clickable
|
||||
import androidx.glance.appwidget.GlanceAppWidget
|
||||
import androidx.glance.appwidget.action.actionRunCallback
|
||||
import androidx.glance.appwidget.appWidgetBackground
|
||||
import androidx.glance.appwidget.cornerRadius
|
||||
import androidx.glance.appwidget.provideContent
|
||||
import androidx.glance.background
|
||||
import androidx.glance.color.ColorProviders
|
||||
import androidx.glance.currentState
|
||||
import androidx.glance.layout.Alignment
|
||||
import androidx.glance.layout.Box
|
||||
import androidx.glance.layout.Column
|
||||
import androidx.glance.layout.ColumnScope
|
||||
import androidx.glance.layout.Row
|
||||
import androidx.glance.layout.fillMaxSize
|
||||
import androidx.glance.layout.fillMaxWidth
|
||||
import androidx.glance.layout.padding
|
||||
import androidx.glance.material3.ColorProviders
|
||||
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.addBracket
|
||||
import com.sadellie.unitto.core.ui.common.textfield.addTokens
|
||||
import com.sadellie.unitto.core.ui.common.textfield.FormatterSymbols
|
||||
import com.sadellie.unitto.core.ui.common.textfield.formatExpression
|
||||
import com.sadellie.unitto.core.ui.theme.DarkThemeColors
|
||||
import com.sadellie.unitto.core.ui.theme.LightThemeColors
|
||||
import com.sadellie.unitto.data.model.repository.UserPreferencesRepository
|
||||
import com.sadellie.unitto.data.model.userprefs.CalculatorPreferences
|
||||
import com.sadellie.unitto.feature.glance.R
|
||||
@ -102,57 +84,50 @@ class UnittoCalculatorWidget : GlanceAppWidget() {
|
||||
|
||||
override suspend fun provideGlance(context: Context, id: GlanceId) {
|
||||
|
||||
val userPrefsRepository = EntryPoints.get(context, UserPrefEntryPoint::class.java).userPrefRep()
|
||||
val userPrefsRepository =
|
||||
EntryPoints.get(context, UserPrefEntryPoint::class.java).userPrefRep()
|
||||
|
||||
provideContent {
|
||||
val appPrefs = userPrefsRepository.calculatorPrefs.collectAsState(initial = null).value
|
||||
|
||||
WidgetTheme {
|
||||
if (appPrefs == null) {
|
||||
LoadingUI()
|
||||
return@WidgetTheme
|
||||
if (appPrefs == null) LoadingUI() else ReadyUI(appPrefs)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ReadyUI(appPrefs)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun WidgetTheme(content: @Composable () -> Unit) =
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
|
||||
GlanceTheme {
|
||||
content()
|
||||
}
|
||||
} else {
|
||||
GlanceTheme(
|
||||
colors = ColorProviders(light = LightThemeColors, dark = DarkThemeColors)
|
||||
@Composable
|
||||
private fun LoadingUI() {
|
||||
Box(
|
||||
modifier = GlanceModifier
|
||||
.appWidgetBackground()
|
||||
.background(GlanceTheme.colors.background)
|
||||
.fillMaxSize(),
|
||||
contentAlignment = Alignment.Center
|
||||
) {
|
||||
content()
|
||||
}
|
||||
IconButton(
|
||||
glanceModifier = GlanceModifier,
|
||||
containerColor = GlanceTheme.colors.primary,
|
||||
iconRes = R.drawable.refresh,
|
||||
onClick = actionRunCallback<RestartWidget>(),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun ReadyUI(
|
||||
@Composable
|
||||
private fun ReadyUI(
|
||||
appPrefs: CalculatorPreferences,
|
||||
) {
|
||||
) {
|
||||
val glancePrefs = currentState<Preferences>()
|
||||
val input = glancePrefs[inputPrefKey] ?: ""
|
||||
val output = glancePrefs[outputPrefKey] ?: ""
|
||||
val input = glancePrefs[UnittoCalculatorWidget.inputPrefKey] ?: ""
|
||||
val output = glancePrefs[UnittoCalculatorWidget.outputPrefKey] ?: ""
|
||||
val formatterSymbols = AllFormatterSymbols.getById(appPrefs.separator)
|
||||
|
||||
fun runCalculateAction(input: String): Action = actionRunCallback<UpdateInputAction>(
|
||||
actionParametersOf(
|
||||
inputKey to input,
|
||||
precisionKey to appPrefs.precision,
|
||||
outputFormatKey to appPrefs.outputFormat
|
||||
)
|
||||
)
|
||||
|
||||
fun runCopyAction(): Action = actionRunCallback<CopyResultAction>(
|
||||
actionParametersOf(
|
||||
outputKey to output.replace(Token.Digit.dot, formatterSymbols.fractional)
|
||||
)
|
||||
fun runCalculateAction(input: String): Action = updateInputAction(
|
||||
input = input,
|
||||
precision = appPrefs.precision,
|
||||
outputFormat = appPrefs.outputFormat
|
||||
)
|
||||
|
||||
Column(
|
||||
@ -165,40 +140,33 @@ class UnittoCalculatorWidget : GlanceAppWidget() {
|
||||
modifier = GlanceModifier
|
||||
.background(GlanceTheme.colors.surfaceVariant)
|
||||
) {
|
||||
Row(modifier = GlanceModifier.fillMaxWidth().padding(8.dp)) {
|
||||
val boxModifier = GlanceModifier.fillMaxWidth().defaultWeight()
|
||||
|
||||
GlanceKeyboardButton(boxModifier, GlanceTheme.colors.primary, R.drawable.content_copy, onClick = runCopyAction())
|
||||
GlanceKeyboardButton(boxModifier, GlanceTheme.colors.primary, R.drawable.open_in_new, onClick = actionStartActivity(ComponentName(LocalContext.current, "com.sadellie.unitto.MainActivity")))
|
||||
}
|
||||
|
||||
Text(
|
||||
text = input.formatExpression(formatterSymbols),
|
||||
modifier = GlanceModifier.fillMaxWidth(),
|
||||
maxLines = 2,
|
||||
style = TextStyle(
|
||||
fontSize = 36.sp,
|
||||
textAlign = TextAlign.End,
|
||||
color = GlanceTheme.colors.onSurfaceVariant
|
||||
ActionButtons(
|
||||
modifier = GlanceModifier.fillMaxWidth().padding(8.dp),
|
||||
onCopyClick = copyAction(
|
||||
output = output,
|
||||
fractional = formatterSymbols.fractional
|
||||
),
|
||||
onLaunchClick = launchAction(LocalContext.current)
|
||||
)
|
||||
Text(
|
||||
text = output.formatExpression(formatterSymbols),
|
||||
TextField(
|
||||
modifier = GlanceModifier.fillMaxWidth(),
|
||||
maxLines = 1,
|
||||
style = TextStyle(
|
||||
input = input,
|
||||
formatterSymbols = formatterSymbols,
|
||||
fontSize = 36.sp,
|
||||
textAlign = TextAlign.End,
|
||||
color = GlanceTheme.colors.onSurfaceVariant
|
||||
),
|
||||
maxLines = 2
|
||||
)
|
||||
TextField(
|
||||
modifier = GlanceModifier.fillMaxWidth(),
|
||||
input = output,
|
||||
formatterSymbols = formatterSymbols,
|
||||
fontSize = 28.sp,
|
||||
maxLines = 1
|
||||
)
|
||||
}
|
||||
|
||||
Column(
|
||||
modifier = GlanceModifier
|
||||
.padding(8.dp)
|
||||
) {
|
||||
GlanceKeyboard(
|
||||
modifier = GlanceModifier
|
||||
.padding(8.dp),
|
||||
addTokenAction = {
|
||||
runCalculateAction(input.addToken(it))
|
||||
},
|
||||
@ -212,7 +180,7 @@ class UnittoCalculatorWidget : GlanceAppWidget() {
|
||||
runCalculateAction(input.dropLast(1))
|
||||
},
|
||||
equalAction = equal@{
|
||||
if (input.isEmpty()) return@equal actionRunCallback<UpdateInputAction>()
|
||||
if (output.isEmpty()) return@equal actionRunCallback<UpdateInputAction>()
|
||||
|
||||
runCalculateAction(output)
|
||||
},
|
||||
@ -220,29 +188,57 @@ class UnittoCalculatorWidget : GlanceAppWidget() {
|
||||
middleZero = appPrefs.middleZero
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun LoadingUI() {
|
||||
Box(
|
||||
modifier = GlanceModifier
|
||||
.appWidgetBackground()
|
||||
.background(GlanceTheme.colors.background)
|
||||
.fillMaxSize(),
|
||||
contentAlignment = Alignment.Center
|
||||
@Composable
|
||||
private fun ActionButtons(
|
||||
modifier: GlanceModifier,
|
||||
onCopyClick: Action,
|
||||
onLaunchClick: Action,
|
||||
) {
|
||||
Row(
|
||||
modifier = modifier
|
||||
) {
|
||||
GlanceKeyboardButton(
|
||||
glanceModifier = GlanceModifier,
|
||||
val boxModifier = GlanceModifier.fillMaxWidth().defaultWeight()
|
||||
|
||||
IconButton(
|
||||
glanceModifier = boxModifier,
|
||||
containerColor = GlanceTheme.colors.primary,
|
||||
iconRes = R.drawable.refresh,
|
||||
onClick = actionRunCallback<RestartWidget>(),
|
||||
iconRes = R.drawable.content_copy,
|
||||
onClick = onCopyClick
|
||||
)
|
||||
IconButton(
|
||||
glanceModifier = boxModifier,
|
||||
containerColor = GlanceTheme.colors.primary,
|
||||
iconRes = R.drawable.open_in_new,
|
||||
onClick = onLaunchClick
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun ColumnScope.GlanceKeyboard(
|
||||
@Composable
|
||||
private fun TextField(
|
||||
modifier: GlanceModifier,
|
||||
input: String,
|
||||
formatterSymbols: FormatterSymbols,
|
||||
fontSize: TextUnit,
|
||||
maxLines: Int,
|
||||
) {
|
||||
Text(
|
||||
text = input.formatExpression(formatterSymbols),
|
||||
modifier = modifier,
|
||||
maxLines = maxLines,
|
||||
style = TextStyle(
|
||||
fontSize = fontSize,
|
||||
textAlign = TextAlign.End,
|
||||
color = GlanceTheme.colors.onSurfaceVariant
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun GlanceKeyboard(
|
||||
modifier: GlanceModifier,
|
||||
addTokenAction: (String) -> Action,
|
||||
replaceInputAction: (String) -> Action,
|
||||
addBracketAction: () -> Action,
|
||||
@ -250,7 +246,7 @@ class UnittoCalculatorWidget : GlanceAppWidget() {
|
||||
equalAction: () -> Action,
|
||||
useDot: Boolean,
|
||||
middleZero: Boolean,
|
||||
) {
|
||||
) = Column(modifier = modifier) {
|
||||
val rowModifier = GlanceModifier.defaultWeight().fillMaxWidth()
|
||||
|
||||
Row(
|
||||
@ -258,10 +254,30 @@ class UnittoCalculatorWidget : GlanceAppWidget() {
|
||||
) {
|
||||
val buttonModifier = GlanceModifier.fillMaxSize().defaultWeight()
|
||||
|
||||
GlanceKeyboardButton(buttonModifier, GlanceTheme.colors.tertiaryContainer, R.drawable.clear, onClick = replaceInputAction(""))
|
||||
GlanceKeyboardButton(buttonModifier, GlanceTheme.colors.primaryContainer, R.drawable.brackets, onClick = addBracketAction())
|
||||
GlanceKeyboardButton(buttonModifier, GlanceTheme.colors.primaryContainer, R.drawable.percent, onClick = addTokenAction(Token.Operator.percent))
|
||||
GlanceKeyboardButton(buttonModifier, GlanceTheme.colors.primaryContainer, R.drawable.divide, onClick = addTokenAction(Token.Operator.divide))
|
||||
IconButton(
|
||||
glanceModifier = buttonModifier,
|
||||
containerColor = GlanceTheme.colors.tertiaryContainer,
|
||||
iconRes = R.drawable.clear,
|
||||
onClick = replaceInputAction("")
|
||||
)
|
||||
IconButton(
|
||||
glanceModifier = buttonModifier,
|
||||
containerColor = GlanceTheme.colors.primaryContainer,
|
||||
iconRes = R.drawable.brackets,
|
||||
onClick = addBracketAction()
|
||||
)
|
||||
IconButton(
|
||||
glanceModifier = buttonModifier,
|
||||
containerColor = GlanceTheme.colors.primaryContainer,
|
||||
iconRes = R.drawable.percent,
|
||||
onClick = addTokenAction(Token.Operator.percent)
|
||||
)
|
||||
IconButton(
|
||||
glanceModifier = buttonModifier,
|
||||
containerColor = GlanceTheme.colors.primaryContainer,
|
||||
iconRes = R.drawable.divide,
|
||||
onClick = addTokenAction(Token.Operator.divide)
|
||||
)
|
||||
}
|
||||
|
||||
Row(
|
||||
@ -269,10 +285,30 @@ class UnittoCalculatorWidget : GlanceAppWidget() {
|
||||
) {
|
||||
val buttonModifier = GlanceModifier.fillMaxSize().defaultWeight()
|
||||
|
||||
GlanceKeyboardButton(buttonModifier, GlanceTheme.colors.inverseOnSurface, R.drawable.key7, onClick = addTokenAction(Token.Digit._7))
|
||||
GlanceKeyboardButton(buttonModifier, GlanceTheme.colors.inverseOnSurface, R.drawable.key8, onClick = addTokenAction(Token.Digit._8))
|
||||
GlanceKeyboardButton(buttonModifier, GlanceTheme.colors.inverseOnSurface, R.drawable.key9, onClick = addTokenAction(Token.Digit._9))
|
||||
GlanceKeyboardButton(buttonModifier, GlanceTheme.colors.primaryContainer, R.drawable.multiply, onClick = addTokenAction(Token.Operator.multiply))
|
||||
IconButton(
|
||||
glanceModifier = buttonModifier,
|
||||
containerColor = GlanceTheme.colors.inverseOnSurface,
|
||||
iconRes = R.drawable.key7,
|
||||
onClick = addTokenAction(Token.Digit._7)
|
||||
)
|
||||
IconButton(
|
||||
glanceModifier = buttonModifier,
|
||||
containerColor = GlanceTheme.colors.inverseOnSurface,
|
||||
iconRes = R.drawable.key8,
|
||||
onClick = addTokenAction(Token.Digit._8)
|
||||
)
|
||||
IconButton(
|
||||
glanceModifier = buttonModifier,
|
||||
containerColor = GlanceTheme.colors.inverseOnSurface,
|
||||
iconRes = R.drawable.key9,
|
||||
onClick = addTokenAction(Token.Digit._9)
|
||||
)
|
||||
IconButton(
|
||||
glanceModifier = buttonModifier,
|
||||
containerColor = GlanceTheme.colors.primaryContainer,
|
||||
iconRes = R.drawable.multiply,
|
||||
onClick = addTokenAction(Token.Operator.multiply)
|
||||
)
|
||||
}
|
||||
|
||||
Row(
|
||||
@ -280,10 +316,30 @@ class UnittoCalculatorWidget : GlanceAppWidget() {
|
||||
) {
|
||||
val buttonModifier = GlanceModifier.fillMaxSize().defaultWeight()
|
||||
|
||||
GlanceKeyboardButton(buttonModifier, GlanceTheme.colors.inverseOnSurface, R.drawable.key4, onClick = addTokenAction(Token.Digit._4))
|
||||
GlanceKeyboardButton(buttonModifier, GlanceTheme.colors.inverseOnSurface, R.drawable.key5, onClick = addTokenAction(Token.Digit._5))
|
||||
GlanceKeyboardButton(buttonModifier, GlanceTheme.colors.inverseOnSurface, R.drawable.key6, onClick = addTokenAction(Token.Digit._6))
|
||||
GlanceKeyboardButton(buttonModifier, GlanceTheme.colors.primaryContainer, R.drawable.minus, onClick = addTokenAction(Token.Operator.minus))
|
||||
IconButton(
|
||||
glanceModifier = buttonModifier,
|
||||
containerColor = GlanceTheme.colors.inverseOnSurface,
|
||||
iconRes = R.drawable.key4,
|
||||
onClick = addTokenAction(Token.Digit._4)
|
||||
)
|
||||
IconButton(
|
||||
glanceModifier = buttonModifier,
|
||||
containerColor = GlanceTheme.colors.inverseOnSurface,
|
||||
iconRes = R.drawable.key5,
|
||||
onClick = addTokenAction(Token.Digit._5)
|
||||
)
|
||||
IconButton(
|
||||
glanceModifier = buttonModifier,
|
||||
containerColor = GlanceTheme.colors.inverseOnSurface,
|
||||
iconRes = R.drawable.key6,
|
||||
onClick = addTokenAction(Token.Digit._6)
|
||||
)
|
||||
IconButton(
|
||||
glanceModifier = buttonModifier,
|
||||
containerColor = GlanceTheme.colors.primaryContainer,
|
||||
iconRes = R.drawable.minus,
|
||||
onClick = addTokenAction(Token.Operator.minus)
|
||||
)
|
||||
}
|
||||
|
||||
Row(
|
||||
@ -291,10 +347,30 @@ class UnittoCalculatorWidget : GlanceAppWidget() {
|
||||
) {
|
||||
val buttonModifier = GlanceModifier.fillMaxSize().defaultWeight()
|
||||
|
||||
GlanceKeyboardButton(buttonModifier, GlanceTheme.colors.inverseOnSurface, R.drawable.key1, onClick = addTokenAction(Token.Digit._1))
|
||||
GlanceKeyboardButton(buttonModifier, GlanceTheme.colors.inverseOnSurface, R.drawable.key2, onClick = addTokenAction(Token.Digit._2))
|
||||
GlanceKeyboardButton(buttonModifier, GlanceTheme.colors.inverseOnSurface, R.drawable.key3, onClick = addTokenAction(Token.Digit._3))
|
||||
GlanceKeyboardButton(buttonModifier, GlanceTheme.colors.primaryContainer, R.drawable.plus, onClick = addTokenAction(Token.Operator.plus))
|
||||
IconButton(
|
||||
glanceModifier = buttonModifier,
|
||||
containerColor = GlanceTheme.colors.inverseOnSurface,
|
||||
iconRes = R.drawable.key1,
|
||||
onClick = addTokenAction(Token.Digit._1)
|
||||
)
|
||||
IconButton(
|
||||
glanceModifier = buttonModifier,
|
||||
containerColor = GlanceTheme.colors.inverseOnSurface,
|
||||
iconRes = R.drawable.key2,
|
||||
onClick = addTokenAction(Token.Digit._2)
|
||||
)
|
||||
IconButton(
|
||||
glanceModifier = buttonModifier,
|
||||
containerColor = GlanceTheme.colors.inverseOnSurface,
|
||||
iconRes = R.drawable.key3,
|
||||
onClick = addTokenAction(Token.Digit._3)
|
||||
)
|
||||
IconButton(
|
||||
glanceModifier = buttonModifier,
|
||||
containerColor = GlanceTheme.colors.primaryContainer,
|
||||
iconRes = R.drawable.plus,
|
||||
onClick = addTokenAction(Token.Operator.plus)
|
||||
)
|
||||
}
|
||||
|
||||
Row(
|
||||
@ -303,77 +379,43 @@ class UnittoCalculatorWidget : GlanceAppWidget() {
|
||||
val buttonModifier = GlanceModifier.fillMaxSize().defaultWeight()
|
||||
|
||||
if (middleZero) {
|
||||
GlanceKeyboardButton(buttonModifier, GlanceTheme.colors.inverseOnSurface, if (useDot) R.drawable.dot else R.drawable.comma, onClick = addTokenAction(Token.Digit.dot))
|
||||
GlanceKeyboardButton(buttonModifier, GlanceTheme.colors.inverseOnSurface, R.drawable.key0, onClick = addTokenAction(Token.Digit._0))
|
||||
IconButton(
|
||||
glanceModifier = buttonModifier,
|
||||
containerColor = GlanceTheme.colors.inverseOnSurface,
|
||||
iconRes = if (useDot) R.drawable.dot else R.drawable.comma,
|
||||
onClick = addTokenAction(Token.Digit.dot)
|
||||
)
|
||||
IconButton(
|
||||
glanceModifier = buttonModifier,
|
||||
containerColor = GlanceTheme.colors.inverseOnSurface,
|
||||
iconRes = R.drawable.key0,
|
||||
onClick = addTokenAction(Token.Digit._0)
|
||||
)
|
||||
} else {
|
||||
GlanceKeyboardButton(buttonModifier, GlanceTheme.colors.inverseOnSurface, R.drawable.key0, onClick = addTokenAction(Token.Digit._0))
|
||||
GlanceKeyboardButton(buttonModifier, GlanceTheme.colors.inverseOnSurface, if (useDot) R.drawable.dot else R.drawable.comma, onClick = addTokenAction(Token.Digit.dot))
|
||||
}
|
||||
GlanceKeyboardButton(buttonModifier, GlanceTheme.colors.inverseOnSurface, R.drawable.backspace, onClick = deleteTokenAction())
|
||||
GlanceKeyboardButton(buttonModifier, GlanceTheme.colors.primaryContainer, R.drawable.equal, onClick = equalAction())
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun GlanceKeyboardButton(
|
||||
glanceModifier: GlanceModifier,
|
||||
containerColor: ColorProvider,
|
||||
@DrawableRes iconRes: Int,
|
||||
contentColor: ColorProvider = GlanceTheme.colors.contentColorFor(containerColor),
|
||||
onClickKey: String = iconRes.toString(),
|
||||
onClick: Action,
|
||||
) {
|
||||
Box(
|
||||
modifier = glanceModifier
|
||||
.padding(4.dp),
|
||||
contentAlignment = Alignment.Center
|
||||
) {
|
||||
Image(
|
||||
modifier = GlanceModifier
|
||||
.fillMaxWidth()
|
||||
.clickable(onClick)
|
||||
.cornerRadius(100.dp)
|
||||
.background(containerColor)
|
||||
.padding(horizontal = 16.dp, vertical = 8.dp),
|
||||
provider = ImageProvider(iconRes),
|
||||
contentDescription = null,
|
||||
colorFilter = ColorFilter.tint(contentColor)
|
||||
IconButton(
|
||||
glanceModifier = buttonModifier,
|
||||
containerColor = GlanceTheme.colors.inverseOnSurface,
|
||||
iconRes = R.drawable.key0,
|
||||
onClick = addTokenAction(Token.Digit._0)
|
||||
)
|
||||
IconButton(
|
||||
glanceModifier = buttonModifier,
|
||||
containerColor = GlanceTheme.colors.inverseOnSurface,
|
||||
iconRes = if (useDot) R.drawable.dot else R.drawable.comma,
|
||||
onClick = addTokenAction(Token.Digit.dot)
|
||||
)
|
||||
}
|
||||
IconButton(
|
||||
glanceModifier = buttonModifier,
|
||||
containerColor = GlanceTheme.colors.inverseOnSurface,
|
||||
iconRes = R.drawable.backspace,
|
||||
onClick = deleteTokenAction()
|
||||
)
|
||||
IconButton(
|
||||
glanceModifier = buttonModifier,
|
||||
containerColor = GlanceTheme.colors.primaryContainer,
|
||||
iconRes = R.drawable.equal,
|
||||
onClick = equalAction()
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
// 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))
|
||||
// }
|
||||
//}
|
||||
|
||||
private fun String.addToken(token: String): String =
|
||||
TextFieldValue(this, TextRange(length)).addTokens(token).text
|
||||
|
||||
private fun String.addBracket(): String =
|
||||
TextFieldValue(this, TextRange(length)).addBracket().text
|
||||
|
||||
private fun ColorProviders.contentColorFor(backgroundColor: ColorProvider): ColorProvider =
|
||||
when (backgroundColor) {
|
||||
primary -> onPrimary
|
||||
primaryContainer -> onPrimaryContainer
|
||||
inverseOnSurface -> onSurfaceVariant
|
||||
tertiaryContainer -> onTertiaryContainer
|
||||
else -> onBackground
|
||||
}
|
||||
|
@ -20,11 +20,17 @@ package com.sadellie.unitto.feature.glance.glance
|
||||
|
||||
import android.content.ClipData
|
||||
import android.content.ClipboardManager
|
||||
import android.content.ComponentName
|
||||
import android.content.Context
|
||||
import androidx.glance.GlanceId
|
||||
import androidx.glance.action.Action
|
||||
import androidx.glance.action.ActionParameters
|
||||
import androidx.glance.action.actionParametersOf
|
||||
import androidx.glance.action.actionStartActivity
|
||||
import androidx.glance.appwidget.action.ActionCallback
|
||||
import androidx.glance.appwidget.action.actionRunCallback
|
||||
import androidx.glance.appwidget.state.updateAppWidgetState
|
||||
import com.sadellie.unitto.core.base.Token
|
||||
import com.sadellie.unitto.data.common.format
|
||||
import com.sadellie.unitto.data.common.isExpression
|
||||
import io.github.sadellie.evaluatto.Expression
|
||||
@ -87,6 +93,36 @@ internal class RestartWidget : ActionCallback {
|
||||
}
|
||||
}
|
||||
|
||||
internal fun updateInputAction(
|
||||
input: String,
|
||||
precision: Int,
|
||||
outputFormat: Int
|
||||
): Action = actionRunCallback<UpdateInputAction>(
|
||||
actionParametersOf(
|
||||
UnittoCalculatorWidget.inputKey to input,
|
||||
UnittoCalculatorWidget.precisionKey to precision,
|
||||
UnittoCalculatorWidget.outputFormatKey to outputFormat
|
||||
)
|
||||
)
|
||||
|
||||
internal fun copyAction(
|
||||
output: String,
|
||||
fractional: String
|
||||
): Action = actionRunCallback<CopyResultAction>(
|
||||
actionParametersOf(
|
||||
UnittoCalculatorWidget.outputKey to output.replace(Token.Digit.dot, fractional)
|
||||
)
|
||||
)
|
||||
|
||||
internal fun launchAction(
|
||||
mContext: Context
|
||||
): Action = actionStartActivity(
|
||||
ComponentName(
|
||||
mContext,
|
||||
"com.sadellie.unitto.MainActivity"
|
||||
)
|
||||
)
|
||||
|
||||
private fun calculate(
|
||||
input: String,
|
||||
precision: Int,
|
||||
|
@ -0,0 +1,40 @@
|
||||
/*
|
||||
* Unitto is a unit converter for Android
|
||||
* Copyright (c) 2024 Elshan Agaev
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.sadellie.unitto.feature.glance.glance
|
||||
|
||||
import android.os.Build
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.glance.GlanceTheme
|
||||
import androidx.glance.material3.ColorProviders
|
||||
import com.sadellie.unitto.core.ui.theme.DarkThemeColors
|
||||
import com.sadellie.unitto.core.ui.theme.LightThemeColors
|
||||
|
||||
@Composable
|
||||
internal fun WidgetTheme(content: @Composable () -> Unit) =
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
|
||||
GlanceTheme {
|
||||
content()
|
||||
}
|
||||
} else {
|
||||
GlanceTheme(
|
||||
colors = ColorProviders(light = LightThemeColors, dark = DarkThemeColors)
|
||||
) {
|
||||
content()
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user