diff --git a/app/build.gradle.kts b/app/build.gradle.kts index b10b20d..c928f1e 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -90,6 +90,8 @@ dependencies { implementation("androidx.lifecycle:lifecycle-viewmodel-compose:2.9.1") implementation("androidx.lifecycle:lifecycle-livedata-ktx:2.9.1") implementation("androidx.glance:glance-appwidget:1.1.1") + implementation("androidx.glance:glance-appwidget-preview:1.1.1") + implementation("androidx.glance:glance-preview:1.1.1") implementation("androidx.core:core-splashscreen:1.0.1") implementation("com.google.accompanist:accompanist-systemuicontroller:0.36.0") implementation("com.google.dagger:dagger:2.56.2") @@ -105,7 +107,6 @@ dependencies { // Debug debugImplementation("androidx.compose.ui:ui-tooling:1.8.3") debugImplementation("androidx.compose.ui:ui-test-manifest:1.8.3") - debugImplementation("com.google.android.glance.tools:appwidget-viewer:0.2.2") // Testing androidTestImplementation("org.jetbrains.kotlinx:kotlinx-coroutines-test:1.10.2") diff --git a/app/src/main/java/com/danilkinkin/buckwheat/widget/CanvasText.kt b/app/src/main/java/com/danilkinkin/buckwheat/widget/CanvasText.kt index 6c61e8f..97f0f4f 100644 --- a/app/src/main/java/com/danilkinkin/buckwheat/widget/CanvasText.kt +++ b/app/src/main/java/com/danilkinkin/buckwheat/widget/CanvasText.kt @@ -8,22 +8,28 @@ import android.graphics.Paint import android.graphics.Rect import android.graphics.Typeface import androidx.compose.runtime.Composable +import androidx.compose.runtime.CompositionLocalProvider import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.toArgb import androidx.compose.ui.unit.Dp import androidx.compose.ui.unit.dp +import androidx.compose.ui.unit.sp +import androidx.core.graphics.createBitmap import androidx.glance.ColorFilter import androidx.glance.GlanceComposable +import androidx.glance.GlanceModifier +import androidx.glance.GlanceTheme import androidx.glance.Image import androidx.glance.ImageProvider import androidx.glance.LocalContext -import androidx.glance.text.TextStyle -import androidx.glance.GlanceModifier import androidx.glance.layout.ContentScale +import androidx.glance.layout.Row import androidx.glance.layout.width +import androidx.glance.preview.ExperimentalGlancePreviewApi +import androidx.glance.preview.Preview import androidx.glance.text.FontWeight import androidx.glance.text.TextAlign -import androidx.glance.unit.ColorProvider +import androidx.glance.text.TextStyle import com.danilkinkin.buckwheat.base.Size @@ -77,11 +83,7 @@ fun drawText(context: Context, text: String, style: TextStyle): Bitmap { val paint = Paint().applyFontToPaint(context, style) val size = calcTextSize(context, text, style) - val bitmap: Bitmap = Bitmap.createBitmap( - size.width, - size.height, - Bitmap.Config.ARGB_8888, - ) + val bitmap: Bitmap = createBitmap(size.width, size.height) Canvas(bitmap).drawText(text, 0F, -paint.ascent(), paint) @@ -102,7 +104,7 @@ fun CanvasText( val width = 0.dp //.plus(modifier.collectPaddingInDp(context.resources)?.start ?: 0.dp) .plus(Dp(size.width / context.resources.displayMetrics.density)) - //.plus(modifier.collectPaddingInDp(context.resources)?.end ?: 0.dp) + //.plus(modifier.collectPaddingInDp(context.resources)?.end ?: 0.dp) if (noTint) { @@ -119,7 +121,7 @@ fun CanvasText( drawText( context, text, - style.copy(ColorProvider(Color.Black)) + style.copy(Color.Black.toColorProvider()) ) ), colorFilter = ColorFilter.tint(style.color), @@ -128,3 +130,84 @@ fun CanvasText( ) } } + +@OptIn(ExperimentalGlancePreviewApi::class) +@Preview(300, 55) +@Composable +@GlanceComposable +fun PreviewColoredText() { + GlanceTheme { + CompositionLocalProvider( + LocalContentColor provides GlanceTheme.colors.onSurface, + ) { + CanvasText( + text = "Hey!", + style = TextStyle( + fontWeight = FontWeight.Bold, + fontSize = 36.sp, + color = Color.Green.toColorProvider() + ) + ) + } + } +} + + +@OptIn(ExperimentalGlancePreviewApi::class) +@Preview(300, 55) +@Composable +@GlanceComposable +fun PreviewWithEmojiTint() { + GlanceTheme { + CompositionLocalProvider( + LocalContentColor provides GlanceTheme.colors.onSurface, + ) { + Row { + CanvasText( + text = "Hey \uD83D\uDC4B\uD83C\uDFFB!", + style = TextStyle( + fontWeight = FontWeight.Bold, + fontSize = 36.sp, + ) + ) + } + } + } +} + +@OptIn(ExperimentalGlancePreviewApi::class) +@Preview(300, 55) +@Composable +@GlanceComposable +fun PreviewWithEmojiNoTint() { + GlanceTheme { + CompositionLocalProvider( + LocalContentColor provides GlanceTheme.colors.onSurface, + ) { + Row { + CanvasText( + text = "Hey ", + style = TextStyle( + fontWeight = FontWeight.Bold, + fontSize = 36.sp, + ) + ) + CanvasText( + text = "\uD83D\uDC4B\uD83C\uDFFB", + style = TextStyle( + fontWeight = FontWeight.Bold, + fontSize = 36.sp, + ), + noTint = true + ) + CanvasText( + text = "!", + style = TextStyle( + fontWeight = FontWeight.Bold, + fontSize = 36.sp, + ) + ) + } + } + } +} diff --git a/app/src/main/java/com/danilkinkin/buckwheat/widget/CommonWidgetReceiver.kt b/app/src/main/java/com/danilkinkin/buckwheat/widget/CommonWidgetReceiver.kt index dcb51a0..6bad856 100644 --- a/app/src/main/java/com/danilkinkin/buckwheat/widget/CommonWidgetReceiver.kt +++ b/app/src/main/java/com/danilkinkin/buckwheat/widget/CommonWidgetReceiver.kt @@ -3,7 +3,9 @@ package com.danilkinkin.buckwheat.widget import android.appwidget.AppWidgetManager import android.content.Context import android.content.Intent +import androidx.compose.runtime.Composable import androidx.compose.runtime.compositionLocalOf +import androidx.compose.runtime.staticCompositionLocalOf import androidx.compose.ui.graphics.Color import androidx.datastore.preferences.core.floatPreferencesKey import androidx.datastore.preferences.core.stringPreferencesKey @@ -23,8 +25,20 @@ import java.math.RoundingMode import java.util.Date import javax.inject.Inject -val LocalContentColor = compositionLocalOf { ColorProvider(Color.Black) } -val LocalAccentColor = compositionLocalOf { ColorProvider(Color.White) } + +@Composable +fun Color.toColorProvider(): ColorProvider { + return try { + val constructor = ColorProvider::class.java.getDeclaredConstructor(Color::class.java) + constructor.isAccessible = true + constructor.newInstance(this) + } catch (e: Exception) { + LocalContentColor.current + } +} + +val LocalContentColor = compositionLocalOf { throw Error("No set") } +val LocalAccentColor = compositionLocalOf { throw Error("No set") } abstract class WidgetReceiver : GlanceAppWidgetReceiver() { diff --git a/app/src/main/java/com/danilkinkin/buckwheat/widget/extend/ExtendWidgetContent.kt b/app/src/main/java/com/danilkinkin/buckwheat/widget/extend/ExtendWidgetContent.kt index d17bce0..94bee60 100644 --- a/app/src/main/java/com/danilkinkin/buckwheat/widget/extend/ExtendWidgetContent.kt +++ b/app/src/main/java/com/danilkinkin/buckwheat/widget/extend/ExtendWidgetContent.kt @@ -3,7 +3,6 @@ package com.danilkinkin.buckwheat.widget.extend import android.content.Intent import androidx.compose.runtime.Composable import androidx.compose.runtime.CompositionLocalProvider -import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp import androidx.core.content.res.ResourcesCompat @@ -32,6 +31,8 @@ import androidx.glance.layout.fillMaxWidth import androidx.glance.layout.padding import androidx.glance.layout.size import androidx.glance.layout.width +import androidx.glance.preview.ExperimentalGlancePreviewApi +import androidx.glance.preview.Preview import androidx.glance.text.FontWeight import androidx.glance.text.TextStyle import com.danilkinkin.buckwheat.BuildConfig @@ -367,35 +368,37 @@ fun ExtendWidgetContent() { } } } - } - if (BuildConfig.DEBUG) { - Box( - modifier = GlanceModifier.fillMaxWidth(), - contentAlignment = Alignment.Center, - ) { - CanvasText( - modifier = GlanceModifier.padding(top = 8.dp), - text = "${size.width}x${size.height}", - style = TextStyle( - color = GlanceTheme.colors.onSurfaceVariant, - fontWeight = FontWeight.Bold, - fontSize = 10.sp, + if (BuildConfig.DEBUG) { + Box( + modifier = GlanceModifier.fillMaxWidth(), + contentAlignment = Alignment.Center, + ) { + CanvasText( + modifier = GlanceModifier.padding(top = 8.dp), + text = "${size.width}x${size.height}", + style = TextStyle( + color = GlanceTheme.colors.onSurfaceVariant, + fontWeight = FontWeight.Bold, + fontSize = 10.sp, + ) ) - ) + } } - } - Box( - modifier = GlanceModifier - .cornerRadius(32.dp) - .fillMaxSize() - .clickable(actionStartActivity(intent)) - ) {} + Box( + modifier = GlanceModifier + .cornerRadius(32.dp) + .fillMaxSize() + .clickable(actionStartActivity(intent)) + ) {} + } } -@Preview +@OptIn(ExperimentalGlancePreviewApi::class) +@Preview(400, 300) @Composable +@GlanceComposable private fun Preview() { GlanceTheme { ExtendWidgetContent() diff --git a/app/src/main/java/com/danilkinkin/buckwheat/widget/minimal/MinimalWidgetContent.kt b/app/src/main/java/com/danilkinkin/buckwheat/widget/minimal/MinimalWidgetContent.kt index cbe81dd..bdeedd8 100644 --- a/app/src/main/java/com/danilkinkin/buckwheat/widget/minimal/MinimalWidgetContent.kt +++ b/app/src/main/java/com/danilkinkin/buckwheat/widget/minimal/MinimalWidgetContent.kt @@ -2,6 +2,7 @@ package com.danilkinkin.buckwheat.widget.minimal import android.content.Intent import androidx.compose.runtime.Composable +import androidx.compose.runtime.CompositionLocalProvider import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp import androidx.core.content.res.ResourcesCompat @@ -28,13 +29,18 @@ import androidx.glance.layout.fillMaxSize import androidx.glance.layout.fillMaxWidth import androidx.glance.layout.padding import androidx.glance.layout.size +import androidx.glance.preview.ExperimentalGlancePreviewApi +import androidx.glance.preview.Preview import androidx.glance.text.FontWeight import androidx.glance.text.TextStyle import com.danilkinkin.buckwheat.BuildConfig import com.danilkinkin.buckwheat.MainActivity import com.danilkinkin.buckwheat.R import com.danilkinkin.buckwheat.widget.CanvasText +import com.danilkinkin.buckwheat.widget.LocalAccentColor +import com.danilkinkin.buckwheat.widget.LocalContentColor import com.danilkinkin.buckwheat.widget.WidgetReceiver +import com.danilkinkin.buckwheat.widget.extend.ExtendWidgetContent @Composable @GlanceComposable @@ -48,182 +54,198 @@ fun MinimalWidgetContent() { prefs[WidgetReceiver.stateBudgetPreferenceKey] ?: WidgetReceiver.StateBudget.NOT_SET.name ) - Box( - modifier = GlanceModifier - .cornerRadius(48.dp) - .fillMaxSize() - .background(ImageProvider(R.drawable.minimal_widget_preview_background)), - contentAlignment = Alignment.Center, + + CompositionLocalProvider( + LocalContentColor provides GlanceTheme.colors.onSurface, + LocalAccentColor provides GlanceTheme.colors.primary, ) { - Column( - modifier = GlanceModifier.padding(8.dp), - horizontalAlignment = Alignment.Start, - verticalAlignment = Alignment.CenterVertically, + Box( + modifier = GlanceModifier + .cornerRadius(48.dp) + .fillMaxSize() + .background(ImageProvider(R.drawable.minimal_widget_preview_background)), + contentAlignment = Alignment.Center, ) { - if ( - stateBudget !== WidgetReceiver.StateBudget.NOT_SET && - stateBudget !== WidgetReceiver.StateBudget.END_PERIOD + Column( + modifier = GlanceModifier.padding(8.dp), + horizontalAlignment = Alignment.Start, + verticalAlignment = Alignment.CenterVertically, ) { - Row( - modifier = GlanceModifier.padding(12.dp), - verticalAlignment = Alignment.CenterVertically, + if ( + stateBudget !== WidgetReceiver.StateBudget.NOT_SET && + stateBudget !== WidgetReceiver.StateBudget.END_PERIOD + ) { + Row( + modifier = GlanceModifier.padding(12.dp), + verticalAlignment = Alignment.CenterVertically, + ) { + CanvasText( + modifier = GlanceModifier.padding( + 0.dp, + 0.dp, + when (size) { + MinimalWidget.largeMode -> 8.dp + MinimalWidget.smallMode -> 4.dp + else -> 6.dp + }, + 0.dp, + ), + text = context.resources.getString( + when (size) { + MinimalWidget.smallMode -> R.string.add_spent_short + else -> R.string.add_spent + } + + ), + style = TextStyle( + color = GlanceTheme.colors.onSurface, + fontWeight = FontWeight.Medium, + fontSize = when (size) { + MinimalWidget.largeMode -> 22.sp + MinimalWidget.smallMode -> 14.sp + else -> 18.sp + }, + ) + ) + + val drawable = ResourcesCompat.getDrawable( + context.resources, + R.drawable.ic_add, + null, + )!! + + Image( + modifier = GlanceModifier.size( + when (size) { + MinimalWidget.largeMode -> 32.dp + MinimalWidget.smallMode -> 24.dp + else -> 28.dp + } + ), + provider = ImageProvider(drawable.toBitmap()), + colorFilter = ColorFilter.tint(GlanceTheme.colors.onSurface), + contentDescription = null, + ) + } + } + if ( + stateBudget === WidgetReceiver.StateBudget.NOT_SET || + stateBudget === WidgetReceiver.StateBudget.END_PERIOD ) { CanvasText( - modifier = GlanceModifier.padding( - 0.dp, - 0.dp, - when (size) { - MinimalWidget.largeMode -> 8.dp - MinimalWidget.smallMode -> 4.dp - else -> 6.dp - }, - 0.dp, - ), - text = context.resources.getString( - when (size) { - MinimalWidget.smallMode -> R.string.add_spent_short - else -> R.string.add_spent - } - - ), + modifier = GlanceModifier.padding(0.dp, 0.dp, 8.dp, 0.dp), + text = if (stateBudget === WidgetReceiver.StateBudget.NOT_SET) { + context.resources.getString( + R.string.budget_not_set + ) + } else { + context.resources.getString( + R.string.finish_period_title + ) + }, style = TextStyle( color = GlanceTheme.colors.onSurface, - fontWeight = FontWeight.Medium, + fontWeight = FontWeight.Bold, fontSize = when (size) { - MinimalWidget.largeMode -> 22.sp - MinimalWidget.smallMode -> 14.sp + MinimalWidget.largeMode -> 24.sp + MinimalWidget.smallMode -> 18.sp else -> 18.sp }, ) ) - val drawable = ResourcesCompat.getDrawable( - context.resources, - R.drawable.ic_add, - null, - )!! - - Image( - modifier = GlanceModifier.size( - when (size) { - MinimalWidget.largeMode -> 32.dp - MinimalWidget.smallMode -> 24.dp - else -> 28.dp - } - ), - provider = ImageProvider(drawable.toBitmap()), - colorFilter = ColorFilter.tint(GlanceTheme.colors.onSurface), - contentDescription = null, - ) - } - } - if ( - stateBudget === WidgetReceiver.StateBudget.NOT_SET || - stateBudget === WidgetReceiver.StateBudget.END_PERIOD - ) { - CanvasText( - modifier = GlanceModifier.padding(0.dp, 0.dp, 8.dp, 0.dp), - text = if (stateBudget === WidgetReceiver.StateBudget.NOT_SET) { - context.resources.getString( - R.string.budget_not_set - ) - } else { - context.resources.getString( - R.string.finish_period_title - ) - }, - style = TextStyle( - color = GlanceTheme.colors.onSurface, - fontWeight = FontWeight.Bold, - fontSize = when (size) { - MinimalWidget.largeMode -> 24.sp - MinimalWidget.smallMode -> 18.sp - else -> 18.sp - }, - ) - ) - - Row( - modifier = GlanceModifier.padding( - 0.dp, - when (size) { - MinimalWidget.largeMode -> 4.dp - MinimalWidget.smallMode -> 0.dp - else -> 2.dp - }, - 0.dp, - 0.dp, - ), - verticalAlignment = Alignment.CenterVertically, - ) { - CanvasText( + Row( modifier = GlanceModifier.padding( - 0.dp, 0.dp, when (size) { - MinimalWidget.largeMode -> 6.dp - MinimalWidget.smallMode -> 2.dp - else -> 4.dp + MinimalWidget.largeMode -> 4.dp + MinimalWidget.smallMode -> 0.dp + else -> 2.dp }, 0.dp, + 0.dp, ), - text = context.resources.getString( - R.string.set_period_title - ), - style = TextStyle( - color = GlanceTheme.colors.primary, - fontWeight = FontWeight.Bold, - fontSize = when (size) { - MinimalWidget.largeMode -> 16.sp - MinimalWidget.smallMode -> 12.sp - else -> 14.sp - }, + verticalAlignment = Alignment.CenterVertically, + ) { + CanvasText( + modifier = GlanceModifier.padding( + 0.dp, + 0.dp, + when (size) { + MinimalWidget.largeMode -> 6.dp + MinimalWidget.smallMode -> 2.dp + else -> 4.dp + }, + 0.dp, + ), + text = context.resources.getString( + R.string.set_period_title + ), + style = TextStyle( + color = GlanceTheme.colors.primary, + fontWeight = FontWeight.Bold, + fontSize = when (size) { + MinimalWidget.largeMode -> 16.sp + MinimalWidget.smallMode -> 12.sp + else -> 14.sp + }, + ) ) - ) - val drawable = ResourcesCompat.getDrawable( - context.resources, - R.drawable.ic_arrow_forward, - null, - )!! + val drawable = ResourcesCompat.getDrawable( + context.resources, + R.drawable.ic_arrow_forward, + null, + )!! - Image( - modifier = GlanceModifier.size( - when (size) { - MinimalWidget.largeMode -> 22.dp - MinimalWidget.smallMode -> 14.dp - else -> 20.dp - } - ), - provider = ImageProvider(drawable.toBitmap()), - colorFilter = ColorFilter.tint(GlanceTheme.colors.primary), - contentDescription = null, - ) + Image( + modifier = GlanceModifier.size( + when (size) { + MinimalWidget.largeMode -> 22.dp + MinimalWidget.smallMode -> 14.dp + else -> 20.dp + } + ), + provider = ImageProvider(drawable.toBitmap()), + colorFilter = ColorFilter.tint(GlanceTheme.colors.primary), + contentDescription = null, + ) + } } } } - } - if (BuildConfig.DEBUG) { - Box( - modifier = GlanceModifier.fillMaxWidth(), - contentAlignment = Alignment.Center, - ) { - CanvasText( - modifier = GlanceModifier.padding(top = 8.dp), - text = "${size.width}x${size.height}", style = TextStyle( - color = GlanceTheme.colors.onSurfaceVariant, - fontWeight = FontWeight.Bold, - fontSize = 10.sp, + if (BuildConfig.DEBUG) { + Box( + modifier = GlanceModifier.fillMaxWidth(), + contentAlignment = Alignment.Center, + ) { + CanvasText( + modifier = GlanceModifier.padding(top = 8.dp), + text = "${size.width}x${size.height}", style = TextStyle( + color = GlanceTheme.colors.onSurfaceVariant, + fontWeight = FontWeight.Bold, + fontSize = 10.sp, + ) ) - ) + } } - } - Box( - modifier = GlanceModifier - .cornerRadius(48.dp) - .fillMaxSize() - .clickable(actionStartActivity(intent)) - ) {} + Box( + modifier = GlanceModifier + .cornerRadius(48.dp) + .fillMaxSize() + .clickable(actionStartActivity(intent)) + ) {} + } +} + +@OptIn(ExperimentalGlancePreviewApi::class) +@Preview(400, 300) +@Composable +@GlanceComposable +private fun Preview() { + GlanceTheme { + MinimalWidgetContent() + } } \ No newline at end of file