From ad151d7f11be2f4b37ae3833242e14c57e717ec7 Mon Sep 17 00:00:00 2001 From: Aleksandras Kostarevas Date: Sat, 19 Aug 2023 15:06:18 +0300 Subject: [PATCH] Update theme to use dynamic color scheme --- .../org/futo/inputmethod/latin/LatinIME.kt | 90 +++++++++++++------ .../futo/inputmethod/latin/uix/ActionBar.kt | 28 ++++-- .../futo/inputmethod/latin/uix/theme/Theme.kt | 20 +++-- 3 files changed, 95 insertions(+), 43 deletions(-) diff --git a/java/src/org/futo/inputmethod/latin/LatinIME.kt b/java/src/org/futo/inputmethod/latin/LatinIME.kt index 68c1fc9e1..195a9137d 100644 --- a/java/src/org/futo/inputmethod/latin/LatinIME.kt +++ b/java/src/org/futo/inputmethod/latin/LatinIME.kt @@ -26,6 +26,8 @@ import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Spacer import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Surface +import androidx.compose.material3.dynamicDarkColorScheme +import androidx.compose.material3.dynamicLightColorScheme import androidx.compose.runtime.key import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.toArgb @@ -35,6 +37,7 @@ import androidx.compose.ui.platform.ViewCompositionStrategy import androidx.compose.ui.unit.Dp import androidx.compose.ui.unit.dp import androidx.compose.ui.viewinterop.AndroidView +import androidx.core.graphics.toColor import androidx.lifecycle.Lifecycle import androidx.lifecycle.LifecycleOwner import androidx.lifecycle.LifecycleRegistry @@ -49,6 +52,7 @@ import androidx.savedstate.SavedStateRegistryController import androidx.savedstate.SavedStateRegistryOwner import androidx.savedstate.findViewTreeSavedStateRegistryOwner import androidx.savedstate.setViewTreeSavedStateRegistryOwner +import com.google.android.material.color.DynamicColors import org.futo.inputmethod.latin.uix.ActionBar import org.futo.inputmethod.latin.uix.theme.DarkColorScheme import kotlin.math.roundToInt @@ -148,43 +152,62 @@ class BasicThemeProvider(val context: Context) : KeyboardDrawableProvider { } init { - val primary = DarkColorScheme.primary.toArgb() - val secondary = DarkColorScheme.secondary.toArgb() - val highlight = DarkColorScheme.outline.copy(alpha = 0.33f).toArgb() - val background = DarkColorScheme.surface.toArgb() - val surface = DarkColorScheme.background.toArgb() - val outline = DarkColorScheme.outline.toArgb() + val colorScheme = if(!DynamicColors.isDynamicColorAvailable()) { + DarkColorScheme + } else { + val dCtx = DynamicColors.wrapContextIfAvailable(context) + + dynamicLightColorScheme(dCtx) + } + + + val primary = colorScheme.primary.toArgb() + val secondary = colorScheme.secondary.toArgb() + val highlight = colorScheme.outline.copy(alpha = 0.33f).toArgb() + + val background = colorScheme.surface.toArgb() + val surface = colorScheme.background.toArgb() + val outline = colorScheme.outline.toArgb() + + val onSecondary = colorScheme.onSecondary.toArgb() + val onBackground = colorScheme.onBackground.toArgb() + val onBackgroundHalf = colorScheme.onBackground.copy(alpha = 0.5f).toArgb() val transparent = Color.TRANSPARENT - colors[R.styleable.Keyboard_Key_keyTextColor] = DarkColorScheme.onBackground.toArgb() - colors[R.styleable.Keyboard_Key_keyTextInactivatedColor] = DarkColorScheme.onBackground.copy(alpha = 0.5f).toArgb() + colors[R.styleable.Keyboard_Key_keyTextColor] = onBackground + colors[R.styleable.Keyboard_Key_keyTextInactivatedColor] = onBackgroundHalf colors[R.styleable.Keyboard_Key_keyTextShadowColor] = 0 - colors[R.styleable.Keyboard_Key_functionalTextColor] = DarkColorScheme.onBackground.toArgb() - colors[R.styleable.Keyboard_Key_keyHintLetterColor] = DarkColorScheme.onBackground.copy(alpha = 0.5f).toArgb() - colors[R.styleable.Keyboard_Key_keyHintLabelColor] = DarkColorScheme.onBackground.copy(alpha = 0.5f).toArgb() - colors[R.styleable.Keyboard_Key_keyShiftedLetterHintInactivatedColor] = DarkColorScheme.onBackground.copy(alpha = 0.5f).toArgb() - colors[R.styleable.Keyboard_Key_keyShiftedLetterHintActivatedColor] = DarkColorScheme.onBackground.copy(alpha = 0.5f).toArgb() - colors[R.styleable.Keyboard_Key_keyPreviewTextColor] = DarkColorScheme.onBackground.toArgb() - colors[R.styleable.MainKeyboardView_languageOnSpacebarTextColor] = DarkColorScheme.onBackground.copy(alpha = 0.5f).toArgb() + colors[R.styleable.Keyboard_Key_functionalTextColor] = onBackground + colors[R.styleable.Keyboard_Key_keyHintLetterColor] = onBackgroundHalf + colors[R.styleable.Keyboard_Key_keyHintLabelColor] = onBackgroundHalf + colors[R.styleable.Keyboard_Key_keyShiftedLetterHintInactivatedColor] = onBackgroundHalf + colors[R.styleable.Keyboard_Key_keyShiftedLetterHintActivatedColor] = onBackgroundHalf + colors[R.styleable.Keyboard_Key_keyPreviewTextColor] = onSecondary + colors[R.styleable.MainKeyboardView_languageOnSpacebarTextColor] = onBackgroundHalf - drawables[R.styleable.Keyboard_iconDeleteKey] = AppCompatResources.getDrawable(context, R.drawable.delete)!! - drawables[R.styleable.Keyboard_iconLanguageSwitchKey] = AppCompatResources.getDrawable(context, R.drawable.globe)!! + drawables[R.styleable.Keyboard_iconDeleteKey] = AppCompatResources.getDrawable(context, R.drawable.delete)!!.apply { + setTint(onBackground) + } + drawables[R.styleable.Keyboard_iconLanguageSwitchKey] = AppCompatResources.getDrawable(context, R.drawable.globe)!!.apply { + setTint(onBackground) + } - drawables[R.styleable.Keyboard_iconShiftKey] = AppCompatResources.getDrawable(context, R.drawable.shift)!! - drawables[R.styleable.Keyboard_iconShiftKeyShifted] = AppCompatResources.getDrawable(context, R.drawable.shiftshifted)!! + drawables[R.styleable.Keyboard_iconShiftKey] = AppCompatResources.getDrawable(context, R.drawable.shift)!!.apply { + setTint(onBackground) + } + + drawables[R.styleable.Keyboard_iconShiftKeyShifted] = AppCompatResources.getDrawable(context, R.drawable.shiftshifted)!!.apply { + setTint(onBackground) + } primaryKeyboardColor = background - keyboardBackground = LayerDrawable(arrayOf( - coloredRectangle(primary), - InsetDrawable(coloredRectangle(background), - 0, 1, 0, 0) - )) + keyboardBackground = coloredRectangle(background) keyBackground = StateListDrawable().apply { addStateWithHighlightLayerOnPressed(highlight, intArrayOf(android.R.attr.state_active), - coloredRoundedRectangle(secondary, dp(8.dp)).apply { + coloredRoundedRectangle(primary, dp(8.dp)).apply { setSize(dp(64.dp).toInt(), dp(48.dp).toInt()) } ) @@ -209,12 +232,12 @@ class BasicThemeProvider(val context: Context) : KeyboardDrawableProvider { spaceBarBackground = StateListDrawable().apply { addState(intArrayOf(android.R.attr.state_pressed), LayerDrawable(arrayOf( - coloredRoundedRectangle(secondary, dp(32.dp)), + coloredRoundedRectangle(highlight, dp(32.dp)), coloredRoundedRectangle(highlight, dp(32.dp)) )) ) addState(intArrayOf(), - coloredRoundedRectangle(secondary, dp(32.dp)) + coloredRoundedRectangle(highlight, dp(32.dp)) ) } @@ -331,6 +354,8 @@ class LatinIME : InputMethodService(), LifecycleOwner, ViewModelStoreOwner, Save setContent() + latinIMELegacy.setComposeInputView(composeView) + return composeView!! } @@ -366,13 +391,20 @@ class LatinIME : InputMethodService(), LifecycleOwner, ViewModelStoreOwner, Save legacyInputView = newView setContent() - latinIMELegacy.setComposeInputView(composeView!!) + if(composeView != null) { + latinIMELegacy.setComposeInputView(composeView) + } + latinIMELegacy.setInputView(legacyInputView) } override fun setInputView(view: View?) { super.setInputView(view) - latinIMELegacy.setComposeInputView(composeView!!) + + if(composeView != null) { + latinIMELegacy.setComposeInputView(composeView) + } + latinIMELegacy.setInputView(legacyInputView) } diff --git a/java/src/org/futo/inputmethod/latin/uix/ActionBar.kt b/java/src/org/futo/inputmethod/latin/uix/ActionBar.kt index 455b6010f..cbe7331ce 100644 --- a/java/src/org/futo/inputmethod/latin/uix/ActionBar.kt +++ b/java/src/org/futo/inputmethod/latin/uix/ActionBar.kt @@ -15,6 +15,8 @@ import androidx.compose.foundation.layout.width import androidx.compose.material3.ButtonDefaults import androidx.compose.material3.Icon import androidx.compose.material3.IconButton +import androidx.compose.material3.IconButtonColors +import androidx.compose.material3.IconButtonDefaults import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Surface import androidx.compose.material3.TextButton @@ -179,7 +181,7 @@ fun RowScope.SuggestionItem(words: SuggestedWords, idx: Int, isPrimary: Boolean, val textStyle = when (isPrimary) { true -> suggestionStylePrimary false -> suggestionStyleAlternative - }.copy(color = MaterialTheme.colorScheme.onPrimary) + }.copy(color = MaterialTheme.colorScheme.onBackground) TextButton( onClick = onClick, @@ -187,7 +189,7 @@ fun RowScope.SuggestionItem(words: SuggestedWords, idx: Int, isPrimary: Boolean, .weight(1.0f) .fillMaxHeight(), shape = RectangleShape, - colors = ButtonDefaults.textButtonColors(contentColor = MaterialTheme.colorScheme.onSurface), + colors = ButtonDefaults.textButtonColors(contentColor = MaterialTheme.colorScheme.onBackground), enabled = word != null ) { if(word != null) { @@ -202,7 +204,7 @@ fun RowScope.SuggestionItem(words: SuggestedWords, idx: Int, isPrimary: Boolean, .fillMaxHeight(0.66f) .align(CenterVertically) .background(color = MaterialTheme.colorScheme.outline) - .width((1f / LocalDensity.current.density).dp) + .width(1.dp) ) } @@ -255,6 +257,7 @@ data class Action( @Composable fun ActionItem() { val col = MaterialTheme.colorScheme.secondary + val contentCol = MaterialTheme.colorScheme.onSecondary IconButton(onClick = { /*TODO*/ }, modifier = Modifier .drawBehind { val radius = size.height / 4.0f @@ -266,7 +269,9 @@ fun ActionItem() { ) } .width(50.dp) - .fillMaxHeight()) { + .fillMaxHeight(), + colors = IconButtonDefaults.iconButtonColors(contentColor = contentCol) + ) { Icon( painter = painterResource(id = R.drawable.mic_fill), contentDescription = "Voice Input" @@ -282,7 +287,9 @@ fun RowScope.ActionItems() { ActionItem() ActionItem() - Box(modifier = Modifier.fillMaxHeight().weight(1.0f)) { + Box(modifier = Modifier + .fillMaxHeight() + .weight(1.0f)) { AutoFitText("Note: Actions not yet implemented", style = Typography.bodyMedium.copy(color = MaterialTheme.colorScheme.onBackground)) } } @@ -297,6 +304,13 @@ fun ExpandActionsButton(isActionsOpen: Boolean, onClick: () -> Unit) { } else { MaterialTheme.colorScheme.background } + + val actionsContent = if(isActionsOpen) { + MaterialTheme.colorScheme.onPrimary + } else { + MaterialTheme.colorScheme.onBackground + } + IconButton( onClick = onClick, modifier = Modifier @@ -312,7 +326,9 @@ fun ExpandActionsButton(isActionsOpen: Boolean, onClick: () -> Unit) { .drawBehind { drawCircle(color = moreActionsColor, radius = size.width / 3.0f + 1.0f) drawCircle(color = moreActionsFill, radius = size.width / 3.0f - 2.0f) - } + }, + + colors = IconButtonDefaults.iconButtonColors(contentColor = actionsContent) ) { Icon( painter = painterResource(id = R.drawable.chevron_right), diff --git a/java/src/org/futo/inputmethod/latin/uix/theme/Theme.kt b/java/src/org/futo/inputmethod/latin/uix/theme/Theme.kt index 79a4184c2..08896b61f 100644 --- a/java/src/org/futo/inputmethod/latin/uix/theme/Theme.kt +++ b/java/src/org/futo/inputmethod/latin/uix/theme/Theme.kt @@ -1,11 +1,15 @@ package org.futo.inputmethod.latin.uix.theme import android.app.Activity +import android.os.Build import androidx.compose.material3.MaterialTheme import androidx.compose.material3.darkColorScheme +import androidx.compose.material3.dynamicDarkColorScheme +import androidx.compose.material3.dynamicLightColorScheme import androidx.compose.runtime.Composable import androidx.compose.runtime.SideEffect import androidx.compose.ui.graphics.toArgb +import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.platform.LocalView import androidx.core.view.WindowCompat @@ -42,18 +46,17 @@ val DarkColorScheme = darkColorScheme( @Composable fun WhisperVoiceInputTheme(content: @Composable () -> Unit) { - /* + // TODO: Switch light or dark mode val colorScheme = when { - dynamicColor && Build.VERSION.SDK_INT >= Build.VERSION_CODES.S -> { + Build.VERSION.SDK_INT >= Build.VERSION_CODES.S -> { val context = LocalContext.current - if (darkTheme) dynamicDarkColorScheme(context) else dynamicLightColorScheme(context) + dynamicLightColorScheme(context) } - darkTheme -> DarkColorScheme - else -> LightColorScheme + else -> DarkColorScheme } - */ - val colorScheme = DarkColorScheme // TODO: Figure out light/dynamic if it's worth it + + //val colorScheme = DarkColorScheme // TODO: Figure out light/dynamic if it's worth it val view = LocalView.current @@ -72,6 +75,7 @@ fun WhisperVoiceInputTheme(content: @Composable () -> Unit) { MaterialTheme( colorScheme = colorScheme, typography = Typography, - content = content + content = content, + ) } \ No newline at end of file