mirror of
https://gitlab.futo.org/keyboard/latinime.git
synced 2024-09-28 14:54:30 +01:00
Implement Actions, create a theme switcher action window
This commit is contained in:
parent
ad151d7f11
commit
f91a626955
20
java/res/drawable/arrow_left.xml
Normal file
20
java/res/drawable/arrow_left.xml
Normal file
@ -0,0 +1,20 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="26dp"
|
||||
android:height="26dp"
|
||||
android:viewportWidth="26"
|
||||
android:viewportHeight="26">
|
||||
<path
|
||||
android:pathData="M20,13L6,13"
|
||||
android:strokeLineJoin="round"
|
||||
android:strokeWidth="2"
|
||||
android:fillColor="#00000000"
|
||||
android:strokeColor="#FFFFFF"
|
||||
android:strokeLineCap="round"/>
|
||||
<path
|
||||
android:pathData="M13,20L6,13L13,6"
|
||||
android:strokeLineJoin="round"
|
||||
android:strokeWidth="2"
|
||||
android:fillColor="#00000000"
|
||||
android:strokeColor="#FFFFFF"
|
||||
android:strokeLineCap="round"/>
|
||||
</vector>
|
20
java/res/drawable/eye.xml
Normal file
20
java/res/drawable/eye.xml
Normal file
@ -0,0 +1,20 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="26dp"
|
||||
android:height="26dp"
|
||||
android:viewportWidth="26"
|
||||
android:viewportHeight="26">
|
||||
<path
|
||||
android:pathData="M2,13C2,13 6,5 13,5C20,5 24,13 24,13C24,13 20,21 13,21C6,21 2,13 2,13ZZ"
|
||||
android:strokeLineJoin="round"
|
||||
android:strokeWidth="2"
|
||||
android:fillColor="#00000000"
|
||||
android:strokeColor="#FFFFFF"
|
||||
android:strokeLineCap="round"/>
|
||||
<path
|
||||
android:pathData="M10,13a3,3 0,1 0,6 0a3,3 0,1 0,-6 0z"
|
||||
android:strokeLineJoin="round"
|
||||
android:strokeWidth="2"
|
||||
android:fillColor="#00000000"
|
||||
android:strokeColor="#FFFFFF"
|
||||
android:strokeLineCap="round"/>
|
||||
</vector>
|
@ -98,13 +98,19 @@ public final class KeyboardSwitcher implements KeyboardState.SwitchActions {
|
||||
}
|
||||
}
|
||||
|
||||
private boolean themeSwitchPending = false;
|
||||
public void queueThemeSwitch() {
|
||||
themeSwitchPending = true;
|
||||
}
|
||||
|
||||
private boolean updateKeyboardThemeAndContextThemeWrapper(final Context context,
|
||||
final KeyboardTheme keyboardTheme) {
|
||||
if (mThemeContext == null || !keyboardTheme.equals(mKeyboardTheme)
|
||||
if (themeSwitchPending || mThemeContext == null || !keyboardTheme.equals(mKeyboardTheme)
|
||||
|| !mThemeContext.getResources().equals(context.getResources())) {
|
||||
mKeyboardTheme = keyboardTheme;
|
||||
mThemeContext = new ContextThemeWrapper(context, keyboardTheme.mStyleId);
|
||||
KeyboardLayoutSet.onKeyboardThemeChanged();
|
||||
themeSwitchPending = false;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
@ -35,8 +35,8 @@ import android.view.View;
|
||||
|
||||
import org.futo.inputmethod.keyboard.internal.KeyDrawParams;
|
||||
import org.futo.inputmethod.keyboard.internal.KeyVisualAttributes;
|
||||
import org.futo.inputmethod.latin.KeyboardDrawableProvider;
|
||||
import org.futo.inputmethod.latin.KeyboardDrawableProviderOwner;
|
||||
import org.futo.inputmethod.latin.DynamicThemeProvider;
|
||||
import org.futo.inputmethod.latin.DynamicThemeProviderOwner;
|
||||
import org.futo.inputmethod.latin.R;
|
||||
import org.futo.inputmethod.latin.common.Constants;
|
||||
import org.futo.inputmethod.latin.utils.TypefaceUtils;
|
||||
@ -96,7 +96,7 @@ public class KeyboardView extends View {
|
||||
private final Drawable mKeyBackground;
|
||||
private final Drawable mFunctionalKeyBackground;
|
||||
private final Drawable mSpacebarBackground;
|
||||
protected final KeyboardDrawableProvider mDrawableProvider;
|
||||
protected final DynamicThemeProvider mDrawableProvider;
|
||||
private final float mSpacebarIconWidthRatio;
|
||||
private final Rect mKeyBackgroundPadding = new Rect();
|
||||
private static final float KET_TEXT_SHADOW_RADIUS_DISABLED = -1.0f;
|
||||
@ -138,9 +138,9 @@ public class KeyboardView extends View {
|
||||
R.styleable.KeyboardView, defStyle, R.style.KeyboardView);
|
||||
|
||||
assert(context instanceof ContextThemeWrapper);
|
||||
assert(((ContextThemeWrapper) context).getBaseContext() instanceof KeyboardDrawableProviderOwner);
|
||||
assert(((ContextThemeWrapper) context).getBaseContext() instanceof DynamicThemeProviderOwner);
|
||||
|
||||
mDrawableProvider = ((KeyboardDrawableProviderOwner) ((ContextThemeWrapper) context).getBaseContext()).getDrawableProvider();
|
||||
mDrawableProvider = ((DynamicThemeProviderOwner) ((ContextThemeWrapper) context).getBaseContext()).getDrawableProvider();
|
||||
|
||||
boolean isMoreKeys = defStyle == R.attr.moreKeysKeyboardViewStyle || defStyle == R.attr.moreKeysKeyboardViewForActionStyle;
|
||||
|
||||
|
@ -28,7 +28,6 @@ import android.graphics.Paint;
|
||||
import android.graphics.Paint.Align;
|
||||
import android.graphics.Typeface;
|
||||
import android.preference.PreferenceManager;
|
||||
import android.text.TextUtils;
|
||||
import android.util.AttributeSet;
|
||||
import android.util.Log;
|
||||
import android.view.LayoutInflater;
|
||||
@ -51,7 +50,7 @@ import org.futo.inputmethod.keyboard.internal.MoreKeySpec;
|
||||
import org.futo.inputmethod.keyboard.internal.NonDistinctMultitouchHelper;
|
||||
import org.futo.inputmethod.keyboard.internal.SlidingKeyInputDrawingPreview;
|
||||
import org.futo.inputmethod.keyboard.internal.TimerHandler;
|
||||
import org.futo.inputmethod.latin.KeyboardDrawableProvider;
|
||||
import org.futo.inputmethod.latin.DynamicThemeProvider;
|
||||
import org.futo.inputmethod.latin.R;
|
||||
import org.futo.inputmethod.latin.RichInputMethodSubtype;
|
||||
import org.futo.inputmethod.latin.SuggestedWords;
|
||||
@ -61,7 +60,6 @@ import org.futo.inputmethod.latin.settings.DebugSettings;
|
||||
import org.futo.inputmethod.latin.utils.LanguageOnSpacebarUtils;
|
||||
import org.futo.inputmethod.latin.utils.TypefaceUtils;
|
||||
|
||||
import java.util.Locale;
|
||||
import java.util.WeakHashMap;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
@ -215,7 +213,7 @@ public final class MainKeyboardView extends KeyboardView implements DrawingProxy
|
||||
mBackgroundDimAlphaPaint.setAlpha(backgroundDimAlpha);
|
||||
mLanguageOnSpacebarTextRatio = mainKeyboardViewAttr.getFraction(
|
||||
R.styleable.MainKeyboardView_languageOnSpacebarTextRatio, 1, 1, 1.0f);
|
||||
mLanguageOnSpacebarTextColor = KeyboardDrawableProvider.Companion.getColorOrDefault(
|
||||
mLanguageOnSpacebarTextColor = DynamicThemeProvider.Companion.getColorOrDefault(
|
||||
R.styleable.MainKeyboardView_languageOnSpacebarTextColor, 0,
|
||||
mainKeyboardViewAttr, mDrawableProvider
|
||||
);
|
||||
@ -461,6 +459,10 @@ public final class MainKeyboardView extends KeyboardView implements DrawingProxy
|
||||
Log.w(TAG, "Cannot find android.R.id.content view to add DrawingPreviewPlacerView");
|
||||
return;
|
||||
}
|
||||
|
||||
if(mDrawingPreviewPlacerView.getParent() != null) {
|
||||
((ViewGroup)mDrawingPreviewPlacerView.getParent()).removeView(mDrawingPreviewPlacerView);
|
||||
}
|
||||
windowContentView.addView(mDrawingPreviewPlacerView);
|
||||
}
|
||||
|
||||
|
@ -26,7 +26,7 @@ import android.view.View;
|
||||
import android.view.animation.AccelerateInterpolator;
|
||||
import android.view.animation.DecelerateInterpolator;
|
||||
|
||||
import org.futo.inputmethod.latin.KeyboardDrawableProvider;
|
||||
import org.futo.inputmethod.latin.DynamicThemeProvider;
|
||||
import org.futo.inputmethod.latin.R;
|
||||
|
||||
public final class KeyPreviewDrawParams {
|
||||
@ -71,7 +71,7 @@ public final class KeyPreviewDrawParams {
|
||||
// preview background.
|
||||
private int mVisibleOffset;
|
||||
|
||||
public KeyPreviewDrawParams(final TypedArray mainKeyboardViewAttr, final KeyboardDrawableProvider provider) {
|
||||
public KeyPreviewDrawParams(final TypedArray mainKeyboardViewAttr, final DynamicThemeProvider provider) {
|
||||
mPreviewOffset = mainKeyboardViewAttr.getDimensionPixelOffset(
|
||||
R.styleable.MainKeyboardView_keyPreviewOffset, 0);
|
||||
mPreviewHeight = mainKeyboardViewAttr.getDimensionPixelSize(
|
||||
|
@ -20,7 +20,7 @@ import android.content.res.TypedArray;
|
||||
import android.graphics.Typeface;
|
||||
import android.util.SparseIntArray;
|
||||
|
||||
import org.futo.inputmethod.latin.KeyboardDrawableProvider;
|
||||
import org.futo.inputmethod.latin.DynamicThemeProvider;
|
||||
import org.futo.inputmethod.latin.R;
|
||||
import org.futo.inputmethod.latin.utils.ResourceUtils;
|
||||
|
||||
@ -87,7 +87,7 @@ public final class KeyVisualAttributes {
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static KeyVisualAttributes newInstance(@Nonnull final TypedArray keyAttr, @Nullable final KeyboardDrawableProvider provider) {
|
||||
public static KeyVisualAttributes newInstance(@Nonnull final TypedArray keyAttr, @Nullable final DynamicThemeProvider provider) {
|
||||
final int indexCount = keyAttr.getIndexCount();
|
||||
for (int i = 0; i < indexCount; i++) {
|
||||
final int attrId = keyAttr.getIndex(i);
|
||||
@ -99,7 +99,7 @@ public final class KeyVisualAttributes {
|
||||
return null;
|
||||
}
|
||||
|
||||
private KeyVisualAttributes(@Nonnull final TypedArray keyAttr, @Nullable final KeyboardDrawableProvider provider) {
|
||||
private KeyVisualAttributes(@Nonnull final TypedArray keyAttr, @Nullable final DynamicThemeProvider provider) {
|
||||
if (keyAttr.hasValue(R.styleable.Keyboard_Key_keyTypeface)) {
|
||||
mTypeface = Typeface.defaultFromStyle(
|
||||
keyAttr.getInt(R.styleable.Keyboard_Key_keyTypeface, Typeface.NORMAL));
|
||||
@ -126,23 +126,23 @@ public final class KeyVisualAttributes {
|
||||
mPreviewTextRatio = ResourceUtils.getFraction(keyAttr,
|
||||
R.styleable.Keyboard_Key_keyPreviewTextRatio);
|
||||
|
||||
mTextColor = KeyboardDrawableProvider.Companion.getColorOrDefault(
|
||||
mTextColor = DynamicThemeProvider.Companion.getColorOrDefault(
|
||||
R.styleable.Keyboard_Key_keyTextColor, 0, keyAttr, provider);
|
||||
mTextInactivatedColor = KeyboardDrawableProvider.Companion.getColorOrDefault(
|
||||
mTextInactivatedColor = DynamicThemeProvider.Companion.getColorOrDefault(
|
||||
R.styleable.Keyboard_Key_keyTextInactivatedColor, 0, keyAttr, provider);
|
||||
mTextShadowColor = KeyboardDrawableProvider.Companion.getColorOrDefault(
|
||||
mTextShadowColor = DynamicThemeProvider.Companion.getColorOrDefault(
|
||||
R.styleable.Keyboard_Key_keyTextShadowColor, 0, keyAttr, provider);
|
||||
mFunctionalTextColor = KeyboardDrawableProvider.Companion.getColorOrDefault(
|
||||
mFunctionalTextColor = DynamicThemeProvider.Companion.getColorOrDefault(
|
||||
R.styleable.Keyboard_Key_functionalTextColor, 0, keyAttr, provider);
|
||||
mHintLetterColor = KeyboardDrawableProvider.Companion.getColorOrDefault(
|
||||
mHintLetterColor = DynamicThemeProvider.Companion.getColorOrDefault(
|
||||
R.styleable.Keyboard_Key_keyHintLetterColor, 0, keyAttr, provider);
|
||||
mHintLabelColor = KeyboardDrawableProvider.Companion.getColorOrDefault(
|
||||
mHintLabelColor = DynamicThemeProvider.Companion.getColorOrDefault(
|
||||
R.styleable.Keyboard_Key_keyHintLabelColor, 0, keyAttr, provider);
|
||||
mShiftedLetterHintInactivatedColor = KeyboardDrawableProvider.Companion.getColorOrDefault(
|
||||
mShiftedLetterHintInactivatedColor = DynamicThemeProvider.Companion.getColorOrDefault(
|
||||
R.styleable.Keyboard_Key_keyShiftedLetterHintInactivatedColor, 0, keyAttr, provider);
|
||||
mShiftedLetterHintActivatedColor = KeyboardDrawableProvider.Companion.getColorOrDefault(
|
||||
mShiftedLetterHintActivatedColor = DynamicThemeProvider.Companion.getColorOrDefault(
|
||||
R.styleable.Keyboard_Key_keyShiftedLetterHintActivatedColor, 0, keyAttr, provider);
|
||||
mPreviewTextColor = KeyboardDrawableProvider.Companion.getColorOrDefault(
|
||||
mPreviewTextColor = DynamicThemeProvider.Companion.getColorOrDefault(
|
||||
R.styleable.Keyboard_Key_keyPreviewTextColor, 0, keyAttr, provider);
|
||||
|
||||
mHintLabelVerticalAdjustment = ResourceUtils.getFraction(keyAttr,
|
||||
|
@ -33,8 +33,8 @@ import org.futo.inputmethod.keyboard.Key;
|
||||
import org.futo.inputmethod.keyboard.Keyboard;
|
||||
import org.futo.inputmethod.keyboard.KeyboardId;
|
||||
import org.futo.inputmethod.keyboard.KeyboardTheme;
|
||||
import org.futo.inputmethod.latin.KeyboardDrawableProvider;
|
||||
import org.futo.inputmethod.latin.KeyboardDrawableProviderOwner;
|
||||
import org.futo.inputmethod.latin.DynamicThemeProvider;
|
||||
import org.futo.inputmethod.latin.DynamicThemeProviderOwner;
|
||||
import org.futo.inputmethod.latin.R;
|
||||
import org.futo.inputmethod.latin.common.Constants;
|
||||
import org.futo.inputmethod.latin.common.StringUtils;
|
||||
@ -153,16 +153,16 @@ public class KeyboardBuilder<KP extends KeyboardParams> {
|
||||
private boolean mTopEdge;
|
||||
private Key mRightEdgeKey = null;
|
||||
|
||||
private KeyboardDrawableProvider mProvider = null;
|
||||
private DynamicThemeProvider mProvider = null;
|
||||
|
||||
public KeyboardBuilder(final Context context, @Nonnull final KP params) {
|
||||
mContext = context;
|
||||
if(mContext instanceof KeyboardDrawableProviderOwner) {
|
||||
mProvider = ((KeyboardDrawableProviderOwner) mContext).getDrawableProvider();
|
||||
if(mContext instanceof DynamicThemeProviderOwner) {
|
||||
mProvider = ((DynamicThemeProviderOwner) mContext).getDrawableProvider();
|
||||
}else if(mContext instanceof ContextThemeWrapper) {
|
||||
Context baseContext = ((ContextThemeWrapper) mContext).getBaseContext();
|
||||
if(baseContext instanceof KeyboardDrawableProviderOwner) {
|
||||
mProvider = ((KeyboardDrawableProviderOwner) baseContext).getDrawableProvider();
|
||||
if(baseContext instanceof DynamicThemeProviderOwner) {
|
||||
mProvider = ((DynamicThemeProviderOwner) baseContext).getDrawableProvider();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -22,7 +22,7 @@ import android.graphics.drawable.Drawable;
|
||||
import android.util.Log;
|
||||
import android.util.SparseIntArray;
|
||||
|
||||
import org.futo.inputmethod.latin.KeyboardDrawableProvider;
|
||||
import org.futo.inputmethod.latin.DynamicThemeProvider;
|
||||
import org.futo.inputmethod.latin.R;
|
||||
|
||||
import java.util.HashMap;
|
||||
@ -108,12 +108,12 @@ public final class KeyboardIconsSet {
|
||||
}
|
||||
}
|
||||
|
||||
public void loadIcons(final TypedArray keyboardAttrs, @Nullable KeyboardDrawableProvider provider) {
|
||||
public void loadIcons(final TypedArray keyboardAttrs, @Nullable DynamicThemeProvider provider) {
|
||||
final int size = ATTR_ID_TO_ICON_ID.size();
|
||||
for (int index = 0; index < size; index++) {
|
||||
final int attrId = ATTR_ID_TO_ICON_ID.keyAt(index);
|
||||
try {
|
||||
final Drawable icon = KeyboardDrawableProvider.Companion.getDrawableOrDefault(attrId, keyboardAttrs, provider);
|
||||
final Drawable icon = DynamicThemeProvider.Companion.getDrawableOrDefault(attrId, keyboardAttrs, provider);
|
||||
setDefaultBounds(icon);
|
||||
final Integer iconId = ATTR_ID_TO_ICON_ID.get(attrId);
|
||||
mIcons[iconId] = icon;
|
||||
|
@ -6,13 +6,11 @@ import android.content.res.TypedArray
|
||||
import android.graphics.Color
|
||||
import android.graphics.drawable.Drawable
|
||||
import android.graphics.drawable.GradientDrawable
|
||||
import android.graphics.drawable.InsetDrawable
|
||||
import android.graphics.drawable.LayerDrawable
|
||||
import android.graphics.drawable.ShapeDrawable
|
||||
import android.graphics.drawable.StateListDrawable
|
||||
import android.graphics.drawable.shapes.RoundRectShape
|
||||
import android.inputmethodservice.InputMethodService
|
||||
import android.util.AttributeSet
|
||||
import android.util.TypedValue
|
||||
import android.view.KeyEvent
|
||||
import android.view.View
|
||||
@ -22,22 +20,34 @@ import android.view.inputmethod.InputMethodManager
|
||||
import android.view.inputmethod.InputMethodSubtype
|
||||
import androidx.annotation.ColorInt
|
||||
import androidx.appcompat.content.res.AppCompatResources
|
||||
import androidx.compose.foundation.layout.Box
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.Row
|
||||
import androidx.compose.foundation.layout.Spacer
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.height
|
||||
import androidx.compose.material3.Button
|
||||
import androidx.compose.material3.ColorScheme
|
||||
import androidx.compose.material3.Icon
|
||||
import androidx.compose.material3.IconButton
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.material3.Surface
|
||||
import androidx.compose.material3.dynamicDarkColorScheme
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.material3.dynamicLightColorScheme
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.key
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Alignment.Companion.CenterVertically
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.graphics.toArgb
|
||||
import androidx.compose.ui.layout.onSizeChanged
|
||||
import androidx.compose.ui.platform.ComposeView
|
||||
import androidx.compose.ui.platform.LocalDensity
|
||||
import androidx.compose.ui.platform.ViewCompositionStrategy
|
||||
import androidx.compose.ui.res.painterResource
|
||||
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
|
||||
@ -53,12 +63,16 @@ import androidx.savedstate.SavedStateRegistryOwner
|
||||
import androidx.savedstate.findViewTreeSavedStateRegistryOwner
|
||||
import androidx.savedstate.setViewTreeSavedStateRegistryOwner
|
||||
import com.google.android.material.color.DynamicColors
|
||||
import org.futo.inputmethod.latin.common.Constants
|
||||
import org.futo.inputmethod.latin.uix.Action
|
||||
import org.futo.inputmethod.latin.uix.ActionBar
|
||||
import org.futo.inputmethod.latin.uix.KeyboardManagerForAction
|
||||
import org.futo.inputmethod.latin.uix.theme.DarkColorScheme
|
||||
import org.futo.inputmethod.latin.uix.theme.Typography
|
||||
import org.futo.inputmethod.latin.uix.theme.UixThemeWrapper
|
||||
import kotlin.math.roundToInt
|
||||
|
||||
|
||||
interface KeyboardDrawableProvider {
|
||||
interface DynamicThemeProvider {
|
||||
val primaryKeyboardColor: Int
|
||||
|
||||
val keyboardBackground: Drawable
|
||||
@ -77,11 +91,11 @@ interface KeyboardDrawableProvider {
|
||||
|
||||
companion object {
|
||||
@ColorInt
|
||||
fun getColorOrDefault(i: Int, @ColorInt default: Int, keyAttr: TypedArray, provider: KeyboardDrawableProvider?): Int {
|
||||
fun getColorOrDefault(i: Int, @ColorInt default: Int, keyAttr: TypedArray, provider: DynamicThemeProvider?): Int {
|
||||
return (provider?.getColor(i)) ?: keyAttr.getColor(i, default)
|
||||
}
|
||||
|
||||
fun getDrawableOrDefault(i: Int, keyAttr: TypedArray, provider: KeyboardDrawableProvider?): Drawable? {
|
||||
fun getDrawableOrDefault(i: Int, keyAttr: TypedArray, provider: DynamicThemeProvider?): Drawable? {
|
||||
return (provider?.getDrawable(i)) ?: keyAttr.getDrawable(i)
|
||||
}
|
||||
}
|
||||
@ -89,7 +103,7 @@ interface KeyboardDrawableProvider {
|
||||
|
||||
// TODO: Expand the number of drawables this provides so it covers the full theme, and
|
||||
// build some system to dynamically change these colors
|
||||
class BasicThemeProvider(val context: Context) : KeyboardDrawableProvider {
|
||||
class BasicThemeProvider(val context: Context, val overrideColorScheme: ColorScheme? = null) : DynamicThemeProvider {
|
||||
override val primaryKeyboardColor: Int
|
||||
|
||||
override val keyboardBackground: Drawable
|
||||
@ -152,7 +166,9 @@ class BasicThemeProvider(val context: Context) : KeyboardDrawableProvider {
|
||||
}
|
||||
|
||||
init {
|
||||
val colorScheme = if(!DynamicColors.isDynamicColorAvailable()) {
|
||||
val colorScheme = if(overrideColorScheme != null) {
|
||||
overrideColorScheme
|
||||
}else if(!DynamicColors.isDynamicColorAvailable()) {
|
||||
DarkColorScheme
|
||||
} else {
|
||||
val dCtx = DynamicColors.wrapContextIfAvailable(context)
|
||||
@ -213,7 +229,7 @@ class BasicThemeProvider(val context: Context) : KeyboardDrawableProvider {
|
||||
)
|
||||
|
||||
addStateWithHighlightLayerOnPressed(highlight, intArrayOf(android.R.attr.state_checkable, android.R.attr.state_checked),
|
||||
coloredRoundedRectangle(secondary, dp(8.dp))
|
||||
coloredRoundedRectangle(colorScheme.secondaryContainer.toArgb(), dp(8.dp))
|
||||
)
|
||||
|
||||
addStateWithHighlightLayerOnPressed(highlight, intArrayOf(android.R.attr.state_checkable),
|
||||
@ -264,20 +280,39 @@ class BasicThemeProvider(val context: Context) : KeyboardDrawableProvider {
|
||||
|
||||
}
|
||||
|
||||
interface KeyboardDrawableProviderOwner {
|
||||
fun getDrawableProvider(): KeyboardDrawableProvider
|
||||
interface DynamicThemeProviderOwner {
|
||||
fun getDrawableProvider(): DynamicThemeProvider
|
||||
}
|
||||
|
||||
class LatinIME : InputMethodService(), LifecycleOwner, ViewModelStoreOwner, SavedStateRegistryOwner, LatinIMELegacy.SuggestionStripController, KeyboardDrawableProviderOwner {
|
||||
private var drawableProvider: KeyboardDrawableProvider? = null
|
||||
override fun getDrawableProvider(): KeyboardDrawableProvider {
|
||||
|
||||
|
||||
class LatinIME : InputMethodService(), LifecycleOwner, ViewModelStoreOwner, SavedStateRegistryOwner, LatinIMELegacy.SuggestionStripController, DynamicThemeProviderOwner,
|
||||
KeyboardManagerForAction {
|
||||
private var activeColorScheme = DarkColorScheme
|
||||
|
||||
private var drawableProvider: DynamicThemeProvider? = null
|
||||
override fun getDrawableProvider(): DynamicThemeProvider {
|
||||
if(drawableProvider == null) {
|
||||
drawableProvider = BasicThemeProvider(this)
|
||||
drawableProvider = BasicThemeProvider(this, activeColorScheme)
|
||||
}
|
||||
|
||||
return drawableProvider!!
|
||||
}
|
||||
|
||||
private fun updateDrawableProvider(colorScheme: ColorScheme) {
|
||||
activeColorScheme = colorScheme
|
||||
|
||||
// ... update drawableProvider with params
|
||||
drawableProvider = BasicThemeProvider(this, overrideColorScheme = colorScheme)
|
||||
|
||||
// ... force change keyboard view
|
||||
legacyInputView = latinIMELegacy.onCreateInputView()
|
||||
latinIMELegacy.loadKeyboard()
|
||||
setContent()
|
||||
|
||||
window.window?.navigationBarColor = drawableProvider!!.primaryKeyboardColor
|
||||
}
|
||||
|
||||
private val latinIMELegacy = LatinIMELegacy(
|
||||
this as InputMethodService,
|
||||
this as LatinIMELegacy.SuggestionStripController
|
||||
@ -305,6 +340,15 @@ class LatinIME : InputMethodService(), LifecycleOwner, ViewModelStoreOwner, Save
|
||||
|
||||
override fun onCreate() {
|
||||
super.onCreate()
|
||||
|
||||
activeColorScheme = if(!DynamicColors.isDynamicColorAvailable()) {
|
||||
DarkColorScheme
|
||||
} else {
|
||||
val dCtx = DynamicColors.wrapContextIfAvailable(this)
|
||||
|
||||
dynamicLightColorScheme(dCtx)
|
||||
}
|
||||
|
||||
mSavedStateRegistryController.performRestore(null)
|
||||
handleLifecycleEvent(Lifecycle.Event.ON_RESUME)
|
||||
|
||||
@ -359,26 +403,95 @@ class LatinIME : InputMethodService(), LifecycleOwner, ViewModelStoreOwner, Save
|
||||
return composeView!!
|
||||
}
|
||||
|
||||
private var currWindowAction: Action? = null
|
||||
private fun onActionActivated(action: Action) {
|
||||
if(action.windowImpl != null) {
|
||||
currWindowAction = action
|
||||
setContent()
|
||||
} else if(action.simplePressImpl != null) {
|
||||
action.simplePressImpl.invoke(this)
|
||||
} else {
|
||||
throw IllegalStateException("An action must have either a window implementation or a simple press implementation")
|
||||
}
|
||||
}
|
||||
|
||||
private var inputViewHeight: Int = -1
|
||||
private var shouldShowSuggestionStrip: Boolean = true
|
||||
private var suggestedWords: SuggestedWords? = null
|
||||
|
||||
@Composable
|
||||
private fun LegacyKeyboardView() {
|
||||
key(legacyInputView) {
|
||||
AndroidView(factory = {
|
||||
legacyInputView!!
|
||||
}, update = { }, modifier = Modifier.onSizeChanged {
|
||||
inputViewHeight = it.height
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun MainKeyboardViewWithActionBar() {
|
||||
Column {
|
||||
if (shouldShowSuggestionStrip) {
|
||||
ActionBar(
|
||||
suggestedWords,
|
||||
latinIMELegacy,
|
||||
onActionActivated = { onActionActivated(it) }
|
||||
)
|
||||
}
|
||||
LegacyKeyboardView()
|
||||
}
|
||||
}
|
||||
|
||||
private fun returnBackToMainKeyboardViewFromAction() {
|
||||
assert(currWindowAction != null)
|
||||
currWindowAction = null
|
||||
|
||||
setContent()
|
||||
}
|
||||
@Composable
|
||||
private fun ActionViewWithHeader(action: Action) {
|
||||
val windowImpl = action.windowImpl!!
|
||||
println("The height is $inputViewHeight, which in DP is ${ with(LocalDensity.current) { inputViewHeight.toDp() }}")
|
||||
Column {
|
||||
Surface(modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.height(40.dp), color = MaterialTheme.colorScheme.background)
|
||||
{
|
||||
Row {
|
||||
IconButton(onClick = {
|
||||
returnBackToMainKeyboardViewFromAction()
|
||||
}) {
|
||||
Icon(
|
||||
painter = painterResource(id = R.drawable.arrow_left),
|
||||
contentDescription = "Back"
|
||||
)
|
||||
}
|
||||
|
||||
Text(windowImpl.windowName(), style = Typography.titleMedium, modifier = Modifier.align(CenterVertically))
|
||||
}
|
||||
}
|
||||
|
||||
Box(modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.height(with(LocalDensity.current) { inputViewHeight.toDp() })) {
|
||||
windowImpl.WindowContents(manager = this@LatinIME)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun setContent() {
|
||||
composeView?.setContent {
|
||||
Column {
|
||||
Spacer(modifier = Modifier.weight(1.0f))
|
||||
Surface(modifier = Modifier.onSizeChanged {
|
||||
touchableHeight = it.height
|
||||
}, color = MaterialTheme.colorScheme.surface) {
|
||||
Column {
|
||||
if(shouldShowSuggestionStrip) {
|
||||
ActionBar(
|
||||
suggestedWords,
|
||||
latinIMELegacy
|
||||
)
|
||||
}
|
||||
key(legacyInputView) {
|
||||
AndroidView(factory = {
|
||||
legacyInputView!!
|
||||
}, update = { })
|
||||
UixThemeWrapper(activeColorScheme) {
|
||||
Column {
|
||||
Spacer(modifier = Modifier.weight(1.0f))
|
||||
Surface(modifier = Modifier.onSizeChanged {
|
||||
touchableHeight = it.height
|
||||
}) {
|
||||
when {
|
||||
currWindowAction != null -> ActionViewWithHeader(currWindowAction!!)
|
||||
else -> MainKeyboardViewWithActionBar()
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -500,7 +613,7 @@ class LatinIME : InputMethodService(), LifecycleOwner, ViewModelStoreOwner, Save
|
||||
|
||||
val touchLeft = 0
|
||||
val touchTop = visibleTopY
|
||||
val touchRight = legacyInputView!!.width
|
||||
val touchRight = composeView!!.width
|
||||
val touchBottom = inputHeight
|
||||
|
||||
latinIMELegacy.setInsets(outInsets!!.apply {
|
||||
@ -549,4 +662,17 @@ class LatinIME : InputMethodService(), LifecycleOwner, ViewModelStoreOwner, Save
|
||||
override fun maybeShowImportantNoticeTitle(): Boolean {
|
||||
return false
|
||||
}
|
||||
|
||||
override fun triggerSystemVoiceInput() {
|
||||
latinIMELegacy.onCodeInput(
|
||||
Constants.CODE_SHORTCUT,
|
||||
Constants.SUGGESTION_STRIP_COORDINATE,
|
||||
Constants.SUGGESTION_STRIP_COORDINATE,
|
||||
false
|
||||
);
|
||||
}
|
||||
|
||||
override fun updateTheme(newTheme: ColorScheme) {
|
||||
updateDrawableProvider(newTheme)
|
||||
}
|
||||
}
|
@ -846,6 +846,7 @@ public class LatinIMELegacy implements KeyboardActionListener,
|
||||
public View onCreateInputView() {
|
||||
StatsUtils.onCreateInputView();
|
||||
assert mDisplayContext != null;
|
||||
mKeyboardSwitcher.queueThemeSwitch();
|
||||
return mKeyboardSwitcher.onCreateInputView(mDisplayContext,
|
||||
mIsHardwareAcceleratedDrawingEnabled);
|
||||
}
|
||||
@ -1948,7 +1949,7 @@ public class LatinIMELegacy implements KeyboardActionListener,
|
||||
}
|
||||
|
||||
private void setNavigationBarVisibility(final boolean visible) {
|
||||
int color = ((KeyboardDrawableProviderOwner)getInputMethodService()).getDrawableProvider().getPrimaryKeyboardColor();
|
||||
int color = ((DynamicThemeProviderOwner)getInputMethodService()).getDrawableProvider().getPrimaryKeyboardColor();
|
||||
if (BuildCompatUtils.EFFECTIVE_SDK_INT > Build.VERSION_CODES.M) {
|
||||
// For N and later, IMEs can specify Color.TRANSPARENT to make the navigation bar
|
||||
// transparent. For other colors the system uses the default color.
|
||||
|
27
java/src/org/futo/inputmethod/latin/uix/Action.kt
Normal file
27
java/src/org/futo/inputmethod/latin/uix/Action.kt
Normal file
@ -0,0 +1,27 @@
|
||||
package org.futo.inputmethod.latin.uix
|
||||
|
||||
import androidx.annotation.DrawableRes
|
||||
import androidx.compose.material3.ColorScheme
|
||||
import androidx.compose.runtime.Composable
|
||||
|
||||
|
||||
interface KeyboardManagerForAction {
|
||||
fun triggerSystemVoiceInput()
|
||||
|
||||
fun updateTheme(newTheme: ColorScheme)
|
||||
}
|
||||
|
||||
interface ActionWindow {
|
||||
@Composable
|
||||
fun windowName(): String
|
||||
|
||||
@Composable
|
||||
fun WindowContents(manager: KeyboardManagerForAction)
|
||||
}
|
||||
|
||||
data class Action(
|
||||
@DrawableRes val icon: Int,
|
||||
val name: String, // TODO: @StringRes Int
|
||||
val windowImpl: ActionWindow?,
|
||||
val simplePressImpl: ((KeyboardManagerForAction) -> Unit)?
|
||||
)
|
@ -1,9 +1,12 @@
|
||||
package org.futo.inputmethod.latin.uix
|
||||
|
||||
import androidx.annotation.DrawableRes
|
||||
import android.os.Build
|
||||
import androidx.compose.foundation.Canvas
|
||||
import androidx.compose.foundation.background
|
||||
import androidx.compose.foundation.gestures.Orientation
|
||||
import androidx.compose.foundation.gestures.scrollable
|
||||
import androidx.compose.foundation.layout.Box
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.Row
|
||||
import androidx.compose.foundation.layout.RowScope
|
||||
import androidx.compose.foundation.layout.Spacer
|
||||
@ -12,14 +15,21 @@ import androidx.compose.foundation.layout.fillMaxSize
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.height
|
||||
import androidx.compose.foundation.layout.width
|
||||
import androidx.compose.foundation.rememberScrollState
|
||||
import androidx.compose.material3.Button
|
||||
import androidx.compose.material3.ButtonDefaults
|
||||
import androidx.compose.material3.ColorScheme
|
||||
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.Text
|
||||
import androidx.compose.material3.TextButton
|
||||
import androidx.compose.material3.darkColorScheme
|
||||
import androidx.compose.material3.dynamicDarkColorScheme
|
||||
import androidx.compose.material3.dynamicLightColorScheme
|
||||
import androidx.compose.material3.lightColorScheme
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.compose.runtime.remember
|
||||
@ -31,10 +41,11 @@ import androidx.compose.ui.draw.rotate
|
||||
import androidx.compose.ui.geometry.CornerRadius
|
||||
import androidx.compose.ui.geometry.Offset
|
||||
import androidx.compose.ui.geometry.Size
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.graphics.RectangleShape
|
||||
import androidx.compose.ui.graphics.drawscope.scale
|
||||
import androidx.compose.ui.graphics.drawscope.translate
|
||||
import androidx.compose.ui.platform.LocalDensity
|
||||
import androidx.compose.ui.platform.LocalContext
|
||||
import androidx.compose.ui.res.painterResource
|
||||
import androidx.compose.ui.text.AnnotatedString
|
||||
import androidx.compose.ui.text.ExperimentalTextApi
|
||||
@ -55,8 +66,8 @@ import org.futo.inputmethod.latin.SuggestedWords.SuggestedWordInfo
|
||||
import org.futo.inputmethod.latin.SuggestedWords.SuggestedWordInfo.KIND_TYPED
|
||||
import org.futo.inputmethod.latin.common.Constants
|
||||
import org.futo.inputmethod.latin.suggestions.SuggestionStripView
|
||||
import org.futo.inputmethod.latin.uix.theme.Typography
|
||||
import org.futo.inputmethod.latin.uix.theme.WhisperVoiceInputTheme
|
||||
import org.futo.inputmethod.latin.uix.theme.DarkColorScheme
|
||||
import org.futo.inputmethod.latin.uix.theme.UixThemeWrapper
|
||||
import java.lang.Integer.min
|
||||
import kotlin.math.ceil
|
||||
import kotlin.math.roundToInt
|
||||
@ -249,48 +260,54 @@ fun RowScope.SuggestionItems(words: SuggestedWords, onClick: (i: Int) -> Unit) {
|
||||
}
|
||||
}
|
||||
|
||||
data class Action(
|
||||
@DrawableRes val icon: Int
|
||||
// TODO: How should the actual action abstraction look?
|
||||
)
|
||||
|
||||
@Composable
|
||||
fun ActionItem() {
|
||||
fun ActionItem(action: Action, onSelect: (Action) -> Unit) {
|
||||
val col = MaterialTheme.colorScheme.secondary
|
||||
val contentCol = MaterialTheme.colorScheme.onSecondary
|
||||
IconButton(onClick = { /*TODO*/ }, modifier = Modifier
|
||||
IconButton(onClick = { onSelect(action) }, modifier = Modifier
|
||||
.drawBehind {
|
||||
val radius = size.height / 4.0f
|
||||
drawRoundRect(
|
||||
col,
|
||||
topLeft = Offset(size.width * 0.1f, size.height * 0.1f),
|
||||
size = Size(size.width * 0.8f, size.height * 0.8f),
|
||||
topLeft = Offset(size.width * 0.1f, size.height * 0.05f),
|
||||
size = Size(size.width * 0.8f, size.height * 0.9f),
|
||||
cornerRadius = CornerRadius(radius, radius)
|
||||
)
|
||||
}
|
||||
.width(50.dp)
|
||||
.width(64.dp)
|
||||
.fillMaxHeight(),
|
||||
colors = IconButtonDefaults.iconButtonColors(contentColor = contentCol)
|
||||
) {
|
||||
Icon(
|
||||
painter = painterResource(id = R.drawable.mic_fill),
|
||||
contentDescription = "Voice Input"
|
||||
painter = painterResource(id = action.icon),
|
||||
contentDescription = action.name
|
||||
)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun RowScope.ActionItems() {
|
||||
// TODO
|
||||
ActionItem()
|
||||
ActionItem()
|
||||
ActionItem()
|
||||
fun ActionItemSmall(action: Action, onSelect: (Action) -> Unit) {
|
||||
IconButton(onClick = {
|
||||
onSelect(action)
|
||||
}, modifier = Modifier
|
||||
.width(42.dp)
|
||||
.fillMaxHeight()) {
|
||||
Icon(
|
||||
painter = painterResource(id = action.icon),
|
||||
contentDescription = action.name
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun RowScope.ActionItems(onSelect: (Action) -> Unit) {
|
||||
ActionItem(VoiceInputAction, onSelect)
|
||||
ActionItem(ThemeAction, onSelect)
|
||||
|
||||
Box(modifier = Modifier
|
||||
.fillMaxHeight()
|
||||
.weight(1.0f)) {
|
||||
AutoFitText("Note: Actions not yet implemented", style = Typography.bodyMedium.copy(color = MaterialTheme.colorScheme.onBackground))
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@ -341,49 +358,31 @@ fun ExpandActionsButton(isActionsOpen: Boolean, onClick: () -> Unit) {
|
||||
fun ActionBar(
|
||||
words: SuggestedWords?,
|
||||
suggestionStripListener: SuggestionStripView.Listener,
|
||||
forceOpenActionsInitially: Boolean = false
|
||||
onActionActivated: (Action) -> Unit,
|
||||
forceOpenActionsInitially: Boolean = false,
|
||||
) {
|
||||
val isActionsOpen = remember { mutableStateOf(forceOpenActionsInitially) }
|
||||
|
||||
WhisperVoiceInputTheme {
|
||||
Surface(modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.height(40.dp), color = MaterialTheme.colorScheme.background)
|
||||
{
|
||||
Row {
|
||||
ExpandActionsButton(isActionsOpen.value) { isActionsOpen.value = !isActionsOpen.value }
|
||||
|
||||
if(isActionsOpen.value) {
|
||||
ActionItems()
|
||||
} else if(words != null) {
|
||||
SuggestionItems(words) {
|
||||
suggestionStripListener.pickSuggestionManually(
|
||||
words.getInfo(it)
|
||||
)
|
||||
}
|
||||
} else {
|
||||
Spacer(modifier = Modifier.weight(1.0f))
|
||||
}
|
||||
Surface(modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.height(40.dp), color = MaterialTheme.colorScheme.background)
|
||||
{
|
||||
Row {
|
||||
ExpandActionsButton(isActionsOpen.value) { isActionsOpen.value = !isActionsOpen.value }
|
||||
|
||||
|
||||
// TODO: For now, this calls CODE_SHORTCUT. In the future, we will want to
|
||||
// ask the main UI to hide the keyboard and show our own voice input menu
|
||||
IconButton(onClick = {
|
||||
suggestionStripListener.onCodeInput(
|
||||
Constants.CODE_SHORTCUT,
|
||||
Constants.SUGGESTION_STRIP_COORDINATE,
|
||||
Constants.SUGGESTION_STRIP_COORDINATE,
|
||||
false
|
||||
);
|
||||
}, modifier = Modifier
|
||||
.width(42.dp)
|
||||
.fillMaxHeight()) {
|
||||
Icon(
|
||||
painter = painterResource(id = R.drawable.mic_fill),
|
||||
contentDescription = "Voice Input"
|
||||
if(isActionsOpen.value) {
|
||||
ActionItems(onActionActivated)
|
||||
} else if(words != null) {
|
||||
SuggestionItems(words) {
|
||||
suggestionStripListener.pickSuggestionManually(
|
||||
words.getInfo(it)
|
||||
)
|
||||
}
|
||||
} else {
|
||||
Spacer(modifier = Modifier.weight(1.0f))
|
||||
}
|
||||
|
||||
ActionItemSmall(VoiceInputAction, onActionActivated)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -437,18 +436,74 @@ val exampleSuggestedWordsEmpty = SuggestedWords(
|
||||
|
||||
@Composable
|
||||
@Preview
|
||||
fun PreviewActionBarWithSuggestions() {
|
||||
ActionBar(words = exampleSuggestedWords, suggestionStripListener = ExampleListener())
|
||||
fun PreviewActionBarWithSuggestions(colorScheme: ColorScheme = DarkColorScheme) {
|
||||
UixThemeWrapper(colorScheme) {
|
||||
ActionBar(
|
||||
words = exampleSuggestedWords,
|
||||
onActionActivated = { },
|
||||
suggestionStripListener = ExampleListener()
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
@Preview
|
||||
fun PreviewActionBarWithEmptySuggestions() {
|
||||
ActionBar(words = exampleSuggestedWordsEmpty, suggestionStripListener = ExampleListener())
|
||||
fun PreviewActionBarWithEmptySuggestions(colorScheme: ColorScheme = DarkColorScheme) {
|
||||
UixThemeWrapper(colorScheme) {
|
||||
ActionBar(
|
||||
words = exampleSuggestedWordsEmpty,
|
||||
onActionActivated = { },
|
||||
suggestionStripListener = ExampleListener()
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
@Preview
|
||||
fun PreviewExpandedActionBar() {
|
||||
ActionBar(words = exampleSuggestedWordsEmpty, suggestionStripListener = ExampleListener(), forceOpenActionsInitially = true)
|
||||
fun PreviewExpandedActionBar(colorScheme: ColorScheme = DarkColorScheme) {
|
||||
UixThemeWrapper(colorScheme) {
|
||||
ActionBar(
|
||||
words = exampleSuggestedWordsEmpty,
|
||||
onActionActivated = { },
|
||||
suggestionStripListener = ExampleListener(),
|
||||
forceOpenActionsInitially = true
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Composable
|
||||
@Preview
|
||||
fun PreviewActionBarWithSuggestionsDynamicLight() {
|
||||
PreviewActionBarWithSuggestions(dynamicLightColorScheme(LocalContext.current))
|
||||
}
|
||||
|
||||
@Composable
|
||||
@Preview
|
||||
fun PreviewActionBarWithEmptySuggestionsDynamicLight() {
|
||||
PreviewActionBarWithEmptySuggestions(dynamicLightColorScheme(LocalContext.current))
|
||||
}
|
||||
|
||||
@Composable
|
||||
@Preview
|
||||
fun PreviewExpandedActionBarDynamicLight() {
|
||||
PreviewExpandedActionBar(dynamicLightColorScheme(LocalContext.current))
|
||||
}
|
||||
|
||||
@Composable
|
||||
@Preview
|
||||
fun PreviewActionBarWithSuggestionsDynamicDark() {
|
||||
PreviewActionBarWithSuggestions(dynamicDarkColorScheme(LocalContext.current))
|
||||
}
|
||||
|
||||
@Composable
|
||||
@Preview
|
||||
fun PreviewActionBarWithEmptySuggestionsDynamicDark() {
|
||||
PreviewActionBarWithEmptySuggestions(dynamicDarkColorScheme(LocalContext.current))
|
||||
}
|
||||
|
||||
@Composable
|
||||
@Preview
|
||||
fun PreviewExpandedActionBarDynamicDark() {
|
||||
PreviewExpandedActionBar(dynamicDarkColorScheme(LocalContext.current))
|
||||
}
|
211
java/src/org/futo/inputmethod/latin/uix/BaseActions.kt
Normal file
211
java/src/org/futo/inputmethod/latin/uix/BaseActions.kt
Normal file
@ -0,0 +1,211 @@
|
||||
@file:Suppress("LocalVariableName")
|
||||
|
||||
package org.futo.inputmethod.latin.uix
|
||||
|
||||
import android.os.Build
|
||||
import androidx.compose.foundation.gestures.Orientation
|
||||
import androidx.compose.foundation.gestures.scrollable
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.fillMaxSize
|
||||
import androidx.compose.foundation.rememberScrollState
|
||||
import androidx.compose.material3.Button
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.material3.darkColorScheme
|
||||
import androidx.compose.material3.dynamicDarkColorScheme
|
||||
import androidx.compose.material3.dynamicLightColorScheme
|
||||
import androidx.compose.material3.lightColorScheme
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.platform.LocalContext
|
||||
import org.futo.inputmethod.latin.R
|
||||
import org.futo.inputmethod.latin.uix.theme.DarkColorScheme
|
||||
|
||||
|
||||
// TODO: For now, this calls CODE_SHORTCUT. In the future, we will want to
|
||||
// make this a window
|
||||
val VoiceInputAction = Action(
|
||||
icon = R.drawable.mic_fill,
|
||||
name = "Voice Input",
|
||||
simplePressImpl = {
|
||||
it.triggerSystemVoiceInput()
|
||||
},
|
||||
windowImpl = null
|
||||
)
|
||||
|
||||
val ThemeAction = Action(
|
||||
icon = R.drawable.eye,
|
||||
name = "Theme Switcher",
|
||||
simplePressImpl = null,
|
||||
windowImpl = object : ActionWindow {
|
||||
@Composable
|
||||
override fun windowName(): String {
|
||||
return "Theme Switcher"
|
||||
}
|
||||
|
||||
@Composable
|
||||
override fun WindowContents(manager: KeyboardManagerForAction) {
|
||||
val context = LocalContext.current
|
||||
Column(modifier = Modifier.fillMaxSize().scrollable(rememberScrollState(), Orientation.Vertical)) {
|
||||
Button(onClick = {
|
||||
manager.updateTheme(DarkColorScheme)
|
||||
}) {
|
||||
Text("Default voice input theme")
|
||||
}
|
||||
|
||||
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
|
||||
Button(onClick = {
|
||||
manager.updateTheme(dynamicLightColorScheme(context))
|
||||
}) {
|
||||
Text("Dynamic light color scheme")
|
||||
}
|
||||
|
||||
Button(onClick = {
|
||||
manager.updateTheme(dynamicDarkColorScheme(context))
|
||||
}) {
|
||||
Text("Dynamic dark color scheme")
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Button(onClick = {
|
||||
val md_theme_light_primary = Color(0xFF6750A4)
|
||||
val md_theme_light_onPrimary = Color(0xFFFFFFFF)
|
||||
val md_theme_light_primaryContainer = Color(0xFFEADDFF)
|
||||
val md_theme_light_onPrimaryContainer = Color(0xFF21005D)
|
||||
val md_theme_light_secondary = Color(0xFF625B71)
|
||||
val md_theme_light_onSecondary = Color(0xFFFFFFFF)
|
||||
val md_theme_light_secondaryContainer = Color(0xFFE8DEF8)
|
||||
val md_theme_light_onSecondaryContainer = Color(0xFF1D192B)
|
||||
val md_theme_light_tertiary = Color(0xFF7D5260)
|
||||
val md_theme_light_onTertiary = Color(0xFFFFFFFF)
|
||||
val md_theme_light_tertiaryContainer = Color(0xFFFFD8E4)
|
||||
val md_theme_light_onTertiaryContainer = Color(0xFF31111D)
|
||||
val md_theme_light_error = Color(0xFFB3261E)
|
||||
val md_theme_light_onError = Color(0xFFFFFFFF)
|
||||
val md_theme_light_errorContainer = Color(0xFFF9DEDC)
|
||||
val md_theme_light_onErrorContainer = Color(0xFF410E0B)
|
||||
val md_theme_light_outline = Color(0xFF79747E)
|
||||
val md_theme_light_background = Color(0xFFFFFBFE)
|
||||
val md_theme_light_onBackground = Color(0xFF1C1B1F)
|
||||
val md_theme_light_surface = Color(0xFFFFFBFE)
|
||||
val md_theme_light_onSurface = Color(0xFF1C1B1F)
|
||||
val md_theme_light_surfaceVariant = Color(0xFFE7E0EC)
|
||||
val md_theme_light_onSurfaceVariant = Color(0xFF49454F)
|
||||
val md_theme_light_inverseSurface = Color(0xFF313033)
|
||||
val md_theme_light_inverseOnSurface = Color(0xFFF4EFF4)
|
||||
val md_theme_light_inversePrimary = Color(0xFFD0BCFF)
|
||||
val md_theme_light_shadow = Color(0xFF000000)
|
||||
val md_theme_light_surfaceTint = Color(0xFF6750A4)
|
||||
val md_theme_light_outlineVariant = Color(0xFFCAC4D0)
|
||||
val md_theme_light_scrim = Color(0xFF000000)
|
||||
|
||||
manager.updateTheme(
|
||||
lightColorScheme(
|
||||
primary = md_theme_light_primary,
|
||||
onPrimary = md_theme_light_onPrimary,
|
||||
primaryContainer = md_theme_light_primaryContainer,
|
||||
onPrimaryContainer = md_theme_light_onPrimaryContainer,
|
||||
secondary = md_theme_light_secondary,
|
||||
onSecondary = md_theme_light_onSecondary,
|
||||
secondaryContainer = md_theme_light_secondaryContainer,
|
||||
onSecondaryContainer = md_theme_light_onSecondaryContainer,
|
||||
tertiary = md_theme_light_tertiary,
|
||||
onTertiary = md_theme_light_onTertiary,
|
||||
tertiaryContainer = md_theme_light_tertiaryContainer,
|
||||
onTertiaryContainer = md_theme_light_onTertiaryContainer,
|
||||
error = md_theme_light_error,
|
||||
onError = md_theme_light_onError,
|
||||
errorContainer = md_theme_light_errorContainer,
|
||||
onErrorContainer = md_theme_light_onErrorContainer,
|
||||
outline = md_theme_light_outline,
|
||||
background = md_theme_light_background,
|
||||
onBackground = md_theme_light_onBackground,
|
||||
surface = md_theme_light_surface,
|
||||
onSurface = md_theme_light_onSurface,
|
||||
surfaceVariant = md_theme_light_surfaceVariant,
|
||||
onSurfaceVariant = md_theme_light_onSurfaceVariant,
|
||||
inverseSurface = md_theme_light_inverseSurface,
|
||||
inverseOnSurface = md_theme_light_inverseOnSurface,
|
||||
inversePrimary = md_theme_light_inversePrimary,
|
||||
surfaceTint = md_theme_light_surfaceTint,
|
||||
outlineVariant = md_theme_light_outlineVariant,
|
||||
scrim = md_theme_light_scrim,
|
||||
)
|
||||
)
|
||||
}) {
|
||||
Text("Some random light theme")
|
||||
}
|
||||
|
||||
Button(onClick = {
|
||||
val md_theme_dark_primary = Color(0xFFD0BCFF)
|
||||
val md_theme_dark_onPrimary = Color(0xFF381E72)
|
||||
val md_theme_dark_primaryContainer = Color(0xFF4F378B)
|
||||
val md_theme_dark_onPrimaryContainer = Color(0xFFEADDFF)
|
||||
val md_theme_dark_secondary = Color(0xFFCCC2DC)
|
||||
val md_theme_dark_onSecondary = Color(0xFF332D41)
|
||||
val md_theme_dark_secondaryContainer = Color(0xFF4A4458)
|
||||
val md_theme_dark_onSecondaryContainer = Color(0xFFE8DEF8)
|
||||
val md_theme_dark_tertiary = Color(0xFFEFB8C8)
|
||||
val md_theme_dark_onTertiary = Color(0xFF492532)
|
||||
val md_theme_dark_tertiaryContainer = Color(0xFF633B48)
|
||||
val md_theme_dark_onTertiaryContainer = Color(0xFFFFD8E4)
|
||||
val md_theme_dark_error = Color(0xFFF2B8B5)
|
||||
val md_theme_dark_onError = Color(0xFF601410)
|
||||
val md_theme_dark_errorContainer = Color(0xFF8C1D18)
|
||||
val md_theme_dark_onErrorContainer = Color(0xFFF9DEDC)
|
||||
val md_theme_dark_outline = Color(0xFF938F99)
|
||||
val md_theme_dark_background = Color(0xFF1C1B1F)
|
||||
val md_theme_dark_onBackground = Color(0xFFE6E1E5)
|
||||
val md_theme_dark_surface = Color(0xFF1C1B1F)
|
||||
val md_theme_dark_onSurface = Color(0xFFE6E1E5)
|
||||
val md_theme_dark_surfaceVariant = Color(0xFF49454F)
|
||||
val md_theme_dark_onSurfaceVariant = Color(0xFFCAC4D0)
|
||||
val md_theme_dark_inverseSurface = Color(0xFFE6E1E5)
|
||||
val md_theme_dark_inverseOnSurface = Color(0xFF313033)
|
||||
val md_theme_dark_inversePrimary = Color(0xFF6750A4)
|
||||
val md_theme_dark_shadow = Color(0xFF000000)
|
||||
val md_theme_dark_surfaceTint = Color(0xFFD0BCFF)
|
||||
val md_theme_dark_outlineVariant = Color(0xFF49454F)
|
||||
val md_theme_dark_scrim = Color(0xFF000000)
|
||||
|
||||
manager.updateTheme(
|
||||
darkColorScheme(
|
||||
primary = md_theme_dark_primary,
|
||||
onPrimary = md_theme_dark_onPrimary,
|
||||
primaryContainer = md_theme_dark_primaryContainer,
|
||||
onPrimaryContainer = md_theme_dark_onPrimaryContainer,
|
||||
secondary = md_theme_dark_secondary,
|
||||
onSecondary = md_theme_dark_onSecondary,
|
||||
secondaryContainer = md_theme_dark_secondaryContainer,
|
||||
onSecondaryContainer = md_theme_dark_onSecondaryContainer,
|
||||
tertiary = md_theme_dark_tertiary,
|
||||
onTertiary = md_theme_dark_onTertiary,
|
||||
tertiaryContainer = md_theme_dark_tertiaryContainer,
|
||||
onTertiaryContainer = md_theme_dark_onTertiaryContainer,
|
||||
error = md_theme_dark_error,
|
||||
onError = md_theme_dark_onError,
|
||||
errorContainer = md_theme_dark_errorContainer,
|
||||
onErrorContainer = md_theme_dark_onErrorContainer,
|
||||
outline = md_theme_dark_outline,
|
||||
background = md_theme_dark_background,
|
||||
onBackground = md_theme_dark_onBackground,
|
||||
surface = md_theme_dark_surface,
|
||||
onSurface = md_theme_dark_onSurface,
|
||||
surfaceVariant = md_theme_dark_surfaceVariant,
|
||||
onSurfaceVariant = md_theme_dark_onSurfaceVariant,
|
||||
inverseSurface = md_theme_dark_inverseSurface,
|
||||
inverseOnSurface = md_theme_dark_inverseOnSurface,
|
||||
inversePrimary = md_theme_dark_inversePrimary,
|
||||
surfaceTint = md_theme_dark_surfaceTint,
|
||||
outlineVariant = md_theme_dark_outlineVariant,
|
||||
scrim = md_theme_dark_scrim,
|
||||
)
|
||||
)
|
||||
}) {
|
||||
Text("Some random dark theme")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
)
|
@ -2,6 +2,7 @@ package org.futo.inputmethod.latin.uix.theme
|
||||
|
||||
import android.app.Activity
|
||||
import android.os.Build
|
||||
import androidx.compose.material3.ColorScheme
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.material3.darkColorScheme
|
||||
import androidx.compose.material3.dynamicDarkColorScheme
|
||||
@ -45,37 +46,10 @@ val DarkColorScheme = darkColorScheme(
|
||||
)
|
||||
|
||||
@Composable
|
||||
fun WhisperVoiceInputTheme(content: @Composable () -> Unit) {
|
||||
// TODO: Switch light or dark mode
|
||||
val colorScheme = when {
|
||||
Build.VERSION.SDK_INT >= Build.VERSION_CODES.S -> {
|
||||
val context = LocalContext.current
|
||||
dynamicLightColorScheme(context)
|
||||
}
|
||||
|
||||
else -> DarkColorScheme
|
||||
}
|
||||
|
||||
//val colorScheme = DarkColorScheme // TODO: Figure out light/dynamic if it's worth it
|
||||
|
||||
|
||||
val view = LocalView.current
|
||||
if (!view.isInEditMode) {
|
||||
SideEffect {
|
||||
if(view.context is Activity) {
|
||||
val window = (view.context as Activity).window
|
||||
window.statusBarColor = colorScheme.primary.toArgb()
|
||||
WindowCompat.getInsetsController(window, view).isAppearanceLightStatusBars =
|
||||
false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
fun UixThemeWrapper(colorScheme: ColorScheme, content: @Composable () -> Unit) {
|
||||
MaterialTheme(
|
||||
colorScheme = colorScheme,
|
||||
typography = Typography,
|
||||
content = content,
|
||||
|
||||
)
|
||||
}
|
Loading…
Reference in New Issue
Block a user