mirror of
https://gitlab.futo.org/keyboard/latinime.git
synced 2024-09-28 14:54:30 +01:00
Replace SuggestionStripView with ActionBar
This commit is contained in:
parent
69f6c29860
commit
138d3a7886
@ -128,6 +128,9 @@ dependencies {
|
||||
|
||||
implementation 'com.google.code.findbugs:jsr305:3.0.2'
|
||||
|
||||
debugImplementation 'androidx.compose.ui:ui-tooling'
|
||||
debugImplementation 'androidx.compose.ui:ui-test-manifest'
|
||||
|
||||
testImplementation 'junit:junit:4.13.2'
|
||||
androidTestImplementation "org.mockito:mockito-core:1.9.5"
|
||||
androidTestImplementation 'com.google.dexmaker:dexmaker:1.2'
|
||||
|
13
java/res/drawable/chevron_right.xml
Normal file
13
java/res/drawable/chevron_right.xml
Normal file
@ -0,0 +1,13 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="25.5dp"
|
||||
android:height="25.5dp"
|
||||
android:viewportWidth="25.5"
|
||||
android:viewportHeight="25.5">
|
||||
<path
|
||||
android:pathData="M9.75,18.75L15.75,12.75L9.75,6.75"
|
||||
android:strokeLineJoin="round"
|
||||
android:strokeWidth="1.5"
|
||||
android:fillColor="#00000000"
|
||||
android:strokeColor="#FFFFFF"
|
||||
android:strokeLineCap="round"/>
|
||||
</vector>
|
39
java/res/drawable/mic_fill.xml
Normal file
39
java/res/drawable/mic_fill.xml
Normal file
@ -0,0 +1,39 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="19.5dp"
|
||||
android:height="19.5dp"
|
||||
android:viewportWidth="19.5"
|
||||
android:viewportHeight="19.5">
|
||||
<path
|
||||
android:pathData="M9.75,1.5C8.507,1.5 7.5,2.507 7.5,3.75L7.5,9.75C7.5,10.993 8.507,12 9.75,12C10.993,12 12,10.993 12,9.75L12,3.75C12,2.507 10.993,1.5 9.75,1.5ZZ"
|
||||
android:strokeLineJoin="round"
|
||||
android:fillColor="#FFFFFF"
|
||||
android:strokeLineCap="round"/>
|
||||
<path
|
||||
android:pathData="M9.75,1.5C8.507,1.5 7.5,2.507 7.5,3.75L7.5,9.75C7.5,10.993 8.507,12 9.75,12C10.993,12 12,10.993 12,9.75L12,3.75C12,2.507 10.993,1.5 9.75,1.5ZZ"
|
||||
android:strokeLineJoin="round"
|
||||
android:strokeWidth="1.5"
|
||||
android:fillColor="#00000000"
|
||||
android:strokeColor="#FFFFFF"
|
||||
android:strokeLineCap="round"/>
|
||||
<path
|
||||
android:pathData="M15,8.25L15,9.75C15,12.649 12.649,15 9.75,15C6.851,15 4.5,12.649 4.5,9.75L4.5,8.25"
|
||||
android:strokeLineJoin="round"
|
||||
android:strokeWidth="1.5"
|
||||
android:fillColor="#00000000"
|
||||
android:strokeColor="#FFFFFF"
|
||||
android:strokeLineCap="round"/>
|
||||
<path
|
||||
android:pathData="M9.75,15L9.75,18"
|
||||
android:strokeLineJoin="round"
|
||||
android:strokeWidth="1.5"
|
||||
android:fillColor="#00000000"
|
||||
android:strokeColor="#FFFFFF"
|
||||
android:strokeLineCap="round"/>
|
||||
<path
|
||||
android:pathData="M6.75,18L12.75,18"
|
||||
android:strokeLineJoin="round"
|
||||
android:strokeWidth="1.5"
|
||||
android:fillColor="#00000000"
|
||||
android:strokeColor="#FFFFFF"
|
||||
android:strokeLineCap="round"/>
|
||||
</vector>
|
15
java/res/drawable/top_suggestion.xml
Normal file
15
java/res/drawable/top_suggestion.xml
Normal file
@ -0,0 +1,15 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="14.4dp"
|
||||
android:height="3dp"
|
||||
android:viewportWidth="14.4"
|
||||
android:viewportHeight="3">
|
||||
<path
|
||||
android:pathData="M0,1.5a1.5,1.5 0,1 0,3 0a1.5,1.5 0,1 0,-3 0z"
|
||||
android:fillColor="#FFFFFF"/>
|
||||
<path
|
||||
android:pathData="M5.7,1.5a1.5,1.5 0,1 0,3 0a1.5,1.5 0,1 0,-3 0z"
|
||||
android:fillColor="#FFFFFF"/>
|
||||
<path
|
||||
android:pathData="M11.4,1.5a1.5,1.5 0,1 0,3 0a1.5,1.5 0,1 0,-3 0z"
|
||||
android:fillColor="#FFFFFF"/>
|
||||
</vector>
|
@ -24,17 +24,6 @@
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="bottom"
|
||||
android:orientation="vertical" >
|
||||
|
||||
<!-- To ensure that key preview popup is correctly placed when the current system locale is
|
||||
one of RTL locales, layoutDirection="ltr" is needed in the SDK version 17+. -->
|
||||
<org.futo.inputmethod.latin.suggestions.SuggestionStripView
|
||||
android:id="@+id/suggestion_strip_view"
|
||||
android:layoutDirection="ltr"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="@dimen/config_suggestions_strip_height"
|
||||
android:gravity="center_vertical"
|
||||
style="?attr/suggestionStripViewStyle" />
|
||||
|
||||
<!-- To ensure that key preview popup is correctly placed when the current system locale is
|
||||
one of RTL locales, layoutDirection="ltr" is needed in the SDK version 17+. -->
|
||||
<org.futo.inputmethod.keyboard.MainKeyboardView
|
||||
|
@ -31,8 +31,6 @@ import org.futo.inputmethod.latin.suggestions.SuggestionStripView;
|
||||
public final class InputView extends FrameLayout {
|
||||
private final Rect mInputViewRect = new Rect();
|
||||
private MainKeyboardView mMainKeyboardView;
|
||||
private KeyboardTopPaddingForwarder mKeyboardTopPaddingForwarder;
|
||||
private MoreSuggestionsViewCanceler mMoreSuggestionsViewCanceler;
|
||||
private MotionEventForwarder<?, ?> mActiveForwarder;
|
||||
|
||||
public InputView(final Context context, final AttributeSet attrs) {
|
||||
@ -41,17 +39,11 @@ public final class InputView extends FrameLayout {
|
||||
|
||||
@Override
|
||||
protected void onFinishInflate() {
|
||||
final SuggestionStripView suggestionStripView =
|
||||
(SuggestionStripView)findViewById(R.id.suggestion_strip_view);
|
||||
mMainKeyboardView = (MainKeyboardView)findViewById(R.id.keyboard_view);
|
||||
mKeyboardTopPaddingForwarder = new KeyboardTopPaddingForwarder(
|
||||
mMainKeyboardView, suggestionStripView);
|
||||
mMoreSuggestionsViewCanceler = new MoreSuggestionsViewCanceler(
|
||||
mMainKeyboardView, suggestionStripView);
|
||||
}
|
||||
|
||||
public void setKeyboardTopPadding(final int keyboardTopPadding) {
|
||||
mKeyboardTopPaddingForwarder.setKeyboardTopPadding(keyboardTopPadding);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -73,20 +65,6 @@ public final class InputView extends FrameLayout {
|
||||
final int x = (int)me.getX(index) + rect.left;
|
||||
final int y = (int)me.getY(index) + rect.top;
|
||||
|
||||
// The touch events that hit the top padding of keyboard should be forwarded to
|
||||
// {@link SuggestionStripView}.
|
||||
if (mKeyboardTopPaddingForwarder.onInterceptTouchEvent(x, y, me)) {
|
||||
mActiveForwarder = mKeyboardTopPaddingForwarder;
|
||||
return true;
|
||||
}
|
||||
|
||||
// To cancel {@link MoreSuggestionsView}, we should intercept a touch event to
|
||||
// {@link MainKeyboardView} and dismiss the {@link MoreSuggestionsView}.
|
||||
if (mMoreSuggestionsViewCanceler.onInterceptTouchEvent(x, y, me)) {
|
||||
mActiveForwarder = mMoreSuggestionsViewCanceler;
|
||||
return true;
|
||||
}
|
||||
|
||||
mActiveForwarder = null;
|
||||
return false;
|
||||
}
|
||||
|
@ -13,11 +13,7 @@ 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.Text
|
||||
import androidx.compose.runtime.LaunchedEffect
|
||||
import androidx.compose.runtime.key
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.layout.onSizeChanged
|
||||
import androidx.compose.ui.platform.ComposeView
|
||||
@ -37,9 +33,13 @@ import androidx.savedstate.SavedStateRegistryController
|
||||
import androidx.savedstate.SavedStateRegistryOwner
|
||||
import androidx.savedstate.findViewTreeSavedStateRegistryOwner
|
||||
import androidx.savedstate.setViewTreeSavedStateRegistryOwner
|
||||
import org.futo.inputmethod.latin.uix.ActionBar
|
||||
|
||||
class LatinIME : InputMethodService(), LifecycleOwner, ViewModelStoreOwner, SavedStateRegistryOwner {
|
||||
private val latinIMELegacy = LatinIMELegacy(this as InputMethodService)
|
||||
class LatinIME : InputMethodService(), LifecycleOwner, ViewModelStoreOwner, SavedStateRegistryOwner, LatinIMELegacy.SuggestionStripController {
|
||||
private val latinIMELegacy = LatinIMELegacy(
|
||||
this as InputMethodService,
|
||||
this as LatinIMELegacy.SuggestionStripController
|
||||
)
|
||||
|
||||
private val mSavedStateRegistryController = SavedStateRegistryController.create(this)
|
||||
|
||||
@ -115,6 +115,8 @@ class LatinIME : InputMethodService(), LifecycleOwner, ViewModelStoreOwner, Save
|
||||
return composeView!!
|
||||
}
|
||||
|
||||
private var shouldShowSuggestionStrip: Boolean = true
|
||||
private var suggestedWords: SuggestedWords? = null
|
||||
private fun setContent() {
|
||||
composeView?.setContent {
|
||||
Column {
|
||||
@ -123,6 +125,12 @@ class LatinIME : InputMethodService(), LifecycleOwner, ViewModelStoreOwner, Save
|
||||
touchableHeight = it.height
|
||||
}, color = MaterialTheme.colorScheme.surface) {
|
||||
Column {
|
||||
if(shouldShowSuggestionStrip) {
|
||||
ActionBar(
|
||||
suggestedWords,
|
||||
latinIMELegacy
|
||||
)
|
||||
}
|
||||
key(legacyInputView) {
|
||||
AndroidView(factory = {
|
||||
legacyInputView!!
|
||||
@ -276,4 +284,18 @@ class LatinIME : InputMethodService(), LifecycleOwner, ViewModelStoreOwner, Save
|
||||
override fun onKeyUp(keyCode: Int, event: KeyEvent?): Boolean {
|
||||
return latinIMELegacy.onKeyUp(keyCode, event) || super.onKeyUp(keyCode, event)
|
||||
}
|
||||
|
||||
override fun updateVisibility(shouldShowSuggestionsStrip: Boolean, fullscreenMode: Boolean) {
|
||||
this.shouldShowSuggestionStrip = shouldShowSuggestionsStrip
|
||||
setContent()
|
||||
}
|
||||
|
||||
override fun setSuggestions(suggestedWords: SuggestedWords?, rtlSubtype: Boolean) {
|
||||
this.suggestedWords = suggestedWords
|
||||
setContent()
|
||||
}
|
||||
|
||||
override fun maybeShowImportantNoticeTitle(): Boolean {
|
||||
return false
|
||||
}
|
||||
}
|
@ -119,6 +119,14 @@ public class LatinIMELegacy implements KeyboardActionListener,
|
||||
DictionaryFacilitator.DictionaryInitializationListener,
|
||||
PermissionsManager.PermissionsResultCallback {
|
||||
|
||||
public interface SuggestionStripController {
|
||||
public void updateVisibility(boolean shouldShowSuggestionsStrip, boolean fullscreenMode);
|
||||
|
||||
public void setSuggestions(SuggestedWords suggestedWords, boolean rtlSubtype);
|
||||
|
||||
public boolean maybeShowImportantNoticeTitle();
|
||||
}
|
||||
|
||||
private final InputMethodService mInputMethodService;
|
||||
|
||||
static final String TAG = LatinIMELegacy.class.getSimpleName();
|
||||
@ -160,7 +168,7 @@ public class LatinIMELegacy implements KeyboardActionListener,
|
||||
private View mInputView;
|
||||
private View mComposeInputView;
|
||||
private InsetsUpdater mInsetsUpdater;
|
||||
private SuggestionStripView mSuggestionStripView;
|
||||
private final SuggestionStripController mSuggestionStripController;
|
||||
|
||||
private RichInputMethodManager mRichImm;
|
||||
@UsedForTesting final KeyboardSwitcher mKeyboardSwitcher;
|
||||
@ -586,9 +594,10 @@ public class LatinIMELegacy implements KeyboardActionListener,
|
||||
JniUtils.loadNativeLibrary();
|
||||
}
|
||||
|
||||
public LatinIMELegacy(InputMethodService inputMethodService) {
|
||||
public LatinIMELegacy(InputMethodService inputMethodService, SuggestionStripController suggestionStripController) {
|
||||
super();
|
||||
mInputMethodService = inputMethodService;
|
||||
mSuggestionStripController = suggestionStripController;
|
||||
mSettings = Settings.getInstance();
|
||||
mKeyboardSwitcher = KeyboardSwitcher.getInstance();
|
||||
mStatsUtilsManager = StatsUtilsManager.getInstance();
|
||||
@ -846,10 +855,6 @@ public class LatinIMELegacy implements KeyboardActionListener,
|
||||
|
||||
public void setInputView(final View view) {
|
||||
mInputView = view;
|
||||
mSuggestionStripView = (SuggestionStripView)view.findViewById(R.id.suggestion_strip_view);
|
||||
if (hasSuggestionStripView()) {
|
||||
mSuggestionStripView.setListener(this, view);
|
||||
}
|
||||
}
|
||||
|
||||
public void setCandidatesView(final View view) {
|
||||
@ -1495,7 +1500,7 @@ public class LatinIMELegacy implements KeyboardActionListener,
|
||||
}
|
||||
|
||||
public boolean hasSuggestionStripView() {
|
||||
return null != mSuggestionStripView;
|
||||
return null != mSuggestionStripController;
|
||||
}
|
||||
|
||||
private void setSuggestedWords(final SuggestedWords suggestedWords) {
|
||||
@ -1520,7 +1525,7 @@ public class LatinIMELegacy implements KeyboardActionListener,
|
||||
|| currentSettingsValues.isApplicationSpecifiedCompletionsOn();
|
||||
final boolean shouldShowSuggestionsStrip = shouldShowSuggestionsStripUnlessPassword
|
||||
&& !currentSettingsValues.mInputAttributes.mIsPasswordField;
|
||||
mSuggestionStripView.updateVisibility(shouldShowSuggestionsStrip, mInputMethodService.isFullscreenMode());
|
||||
mSuggestionStripController.updateVisibility(shouldShowSuggestionsStrip, mInputMethodService.isFullscreenMode());
|
||||
if (!shouldShowSuggestionsStrip) {
|
||||
return;
|
||||
}
|
||||
@ -1536,7 +1541,7 @@ public class LatinIMELegacy implements KeyboardActionListener,
|
||||
final boolean noSuggestionsToOverrideImportantNotice = noSuggestionsFromDictionaries
|
||||
|| isBeginningOfSentencePrediction;
|
||||
if (shouldShowImportantNotice && noSuggestionsToOverrideImportantNotice) {
|
||||
if (mSuggestionStripView.maybeShowImportantNoticeTitle()) {
|
||||
if (mSuggestionStripController.maybeShowImportantNoticeTitle()) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
@ -1545,7 +1550,7 @@ public class LatinIMELegacy implements KeyboardActionListener,
|
||||
|| currentSettingsValues.isApplicationSpecifiedCompletionsOn()
|
||||
// We should clear the contextual strip if there is no suggestion from dictionaries.
|
||||
|| noSuggestionsFromDictionaries) {
|
||||
mSuggestionStripView.setSuggestions(suggestedWords,
|
||||
mSuggestionStripController.setSuggestions(suggestedWords,
|
||||
mRichImm.getCurrentSubtype().isRtlSubtype());
|
||||
}
|
||||
}
|
||||
|
402
java/src/org/futo/inputmethod/latin/uix/ActionBar.kt
Normal file
402
java/src/org/futo/inputmethod/latin/uix/ActionBar.kt
Normal file
@ -0,0 +1,402 @@
|
||||
package org.futo.inputmethod.latin.uix
|
||||
|
||||
import androidx.compose.foundation.Canvas
|
||||
import androidx.compose.foundation.background
|
||||
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
|
||||
import androidx.compose.foundation.layout.fillMaxHeight
|
||||
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.material3.ButtonColors
|
||||
import androidx.compose.material3.ButtonDefaults
|
||||
import androidx.compose.material3.Divider
|
||||
import androidx.compose.material3.Icon
|
||||
import androidx.compose.material3.IconButton
|
||||
import androidx.compose.material3.LocalTextStyle
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.material3.Surface
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.material3.TextButton
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.LaunchedEffect
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Alignment.Companion.CenterVertically
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.draw.alpha
|
||||
import androidx.compose.ui.draw.drawBehind
|
||||
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.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.res.painterResource
|
||||
import androidx.compose.ui.text.AnnotatedString
|
||||
import androidx.compose.ui.text.ExperimentalTextApi
|
||||
import androidx.compose.ui.text.TextStyle
|
||||
import androidx.compose.ui.text.drawText
|
||||
import androidx.compose.ui.text.font.FontFamily
|
||||
import androidx.compose.ui.text.font.FontWeight
|
||||
import androidx.compose.ui.text.rememberTextMeasurer
|
||||
import androidx.compose.ui.text.style.TextAlign
|
||||
import androidx.compose.ui.text.style.TextOverflow
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import androidx.compose.ui.unit.Constraints
|
||||
import androidx.compose.ui.unit.Dp
|
||||
import androidx.compose.ui.unit.IntSize
|
||||
import androidx.compose.ui.unit.LayoutDirection
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.compose.ui.unit.sp
|
||||
import org.futo.inputmethod.latin.R
|
||||
import org.futo.inputmethod.latin.SuggestedWords
|
||||
import org.futo.inputmethod.latin.SuggestedWords.SuggestedWordInfo
|
||||
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 java.lang.Float.max
|
||||
import java.lang.IndexOutOfBoundsException
|
||||
import java.lang.Integer.min
|
||||
import kotlin.math.ceil
|
||||
import kotlin.math.roundToInt
|
||||
|
||||
/*
|
||||
* The UIX Action Bar is intended to replace the previous top bar of the AOSP keyboard.
|
||||
* Its goal is to function similar to the old top bar by showing predictions, but also modernize
|
||||
* it with actions and new features.
|
||||
*
|
||||
* Example bar:
|
||||
* [>] word1 | word2 | word3 [mic]
|
||||
*
|
||||
* The [>] button expands the action bar, replacing word predictions with actions the user can take.
|
||||
* Actions have little icons which perform an action. Some examples:
|
||||
* - Microphone: opens the voice input menu
|
||||
* - Undo/Redo
|
||||
* - Text editing: switches to the text editing menu
|
||||
* - Settings: opens the keyboard settings menu
|
||||
* - Report problem: opens the report menu
|
||||
*
|
||||
* Generally there are a few kinds of actions:
|
||||
* - Take an action on the text being typed (undo/redo)
|
||||
* - Switch from the keyboard UI to something else (voice input, text editing)
|
||||
* - Open an app (settings, report)
|
||||
*
|
||||
* The UIX effort is to modernize the AOSP Keyboard by replacing and extending
|
||||
* parts of it with UI written in Android Compose, while keeping most of the
|
||||
* battle-tested original keyboard code the same
|
||||
*
|
||||
* TODO: Will need to make RTL languages work
|
||||
*/
|
||||
|
||||
val exampleSuggestionsList = arrayListOf(
|
||||
SuggestedWordInfo("verylongword123", "", 100, 1, null, 0, 0),
|
||||
SuggestedWordInfo("world understanding of patience", "", 99, 1, null, 0, 0),
|
||||
SuggestedWordInfo("b", "", 98, 1, null, 0, 0),
|
||||
SuggestedWordInfo("extra1", "", 97, 1, null, 0, 0),
|
||||
SuggestedWordInfo("extra2", "", 96, 1, null, 0, 0),
|
||||
SuggestedWordInfo("extra3", "", 95, 1, null, 0, 0)
|
||||
)
|
||||
|
||||
val exampleSuggestedWords = SuggestedWords(
|
||||
exampleSuggestionsList,
|
||||
exampleSuggestionsList,
|
||||
exampleSuggestionsList[0],
|
||||
true,
|
||||
true,
|
||||
false,
|
||||
0,
|
||||
0
|
||||
)
|
||||
|
||||
val exampleSuggestedWordsEmpty = SuggestedWords(
|
||||
arrayListOf(),
|
||||
arrayListOf(),
|
||||
exampleSuggestionsList[0],
|
||||
true,
|
||||
true,
|
||||
false,
|
||||
0,
|
||||
0
|
||||
)
|
||||
|
||||
val suggestionStylePrimary = TextStyle(
|
||||
fontFamily = FontFamily.SansSerif,
|
||||
fontWeight = FontWeight.Medium,
|
||||
fontSize = 18.sp,
|
||||
lineHeight = 26.sp,
|
||||
letterSpacing = 0.5.sp,
|
||||
//textAlign = TextAlign.Center
|
||||
)
|
||||
|
||||
val suggestionStyleAlternative = TextStyle(
|
||||
fontFamily = FontFamily.SansSerif,
|
||||
fontWeight = FontWeight.Normal,
|
||||
fontSize = 18.sp,
|
||||
lineHeight = 26.sp,
|
||||
letterSpacing = 0.5.sp,
|
||||
//textAlign = TextAlign.Center
|
||||
)
|
||||
|
||||
|
||||
@OptIn(ExperimentalTextApi::class)
|
||||
@Composable fun RowScope.SuggestionItem(words: SuggestedWords, idx: Int, onClick: () -> Unit) {
|
||||
val word = try {
|
||||
words.getWord(idx)
|
||||
} catch(e: IndexOutOfBoundsException) {
|
||||
null
|
||||
}
|
||||
|
||||
val topSuggestionIcon = painterResource(id = R.drawable.top_suggestion)
|
||||
val textButtonModifier = when (idx) {
|
||||
0 -> Modifier.drawBehind {
|
||||
with(topSuggestionIcon) {
|
||||
val iconSize = topSuggestionIcon.intrinsicSize
|
||||
translate(
|
||||
left = (size.width - iconSize.width) / 2.0f,
|
||||
top = size.height - iconSize.height * 2.0f
|
||||
) {
|
||||
draw(topSuggestionIcon.intrinsicSize)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
else -> Modifier
|
||||
}
|
||||
|
||||
val textModifier = when (idx) {
|
||||
0 -> Modifier
|
||||
else -> Modifier.alpha(0.75f)
|
||||
}
|
||||
|
||||
val textStyle = when (idx) {
|
||||
0 -> suggestionStylePrimary
|
||||
else -> suggestionStyleAlternative
|
||||
}.copy(color = MaterialTheme.colorScheme.onPrimary)
|
||||
|
||||
TextButton(
|
||||
onClick = onClick,
|
||||
modifier = textButtonModifier
|
||||
.weight(1.0f)
|
||||
.fillMaxHeight(),
|
||||
shape = RectangleShape,
|
||||
colors = ButtonDefaults.textButtonColors(contentColor = MaterialTheme.colorScheme.onSurface),
|
||||
enabled = word != null
|
||||
) {
|
||||
if(word != null) {
|
||||
val measurer = rememberTextMeasurer()
|
||||
|
||||
Canvas(modifier = textModifier.fillMaxSize()) {
|
||||
val measurement = measurer.measure(
|
||||
text = AnnotatedString(word),
|
||||
style = textStyle,
|
||||
overflow = TextOverflow.Visible,
|
||||
softWrap = false,
|
||||
maxLines = 1,
|
||||
constraints = Constraints(
|
||||
maxWidth = Int.MAX_VALUE,
|
||||
maxHeight = ceil(this.size.height).roundToInt()
|
||||
),
|
||||
layoutDirection = LayoutDirection.Ltr,
|
||||
density = this
|
||||
)
|
||||
|
||||
val scale = Math.min(1.0f, size.width / measurement.size.width)
|
||||
|
||||
translate(left = (scale * (size.width - measurement.size.width)) / 2.0f) {
|
||||
scale(scaleX = scale, scaleY = 1.0f) {
|
||||
drawText(
|
||||
measurement
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
/*
|
||||
Text(
|
||||
word,
|
||||
modifier = textModifier,
|
||||
style = textStyle,
|
||||
overflow = TextOverflow.Visible,
|
||||
softWrap = false,
|
||||
maxLines = 1
|
||||
)
|
||||
*/
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Composable fun RowScope.SuggestionSeparator() {
|
||||
Box(
|
||||
modifier = Modifier
|
||||
.fillMaxHeight(0.66f)
|
||||
.align(CenterVertically)
|
||||
.background(color = MaterialTheme.colorScheme.outline)
|
||||
.width((1f / LocalDensity.current.density).dp)
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
|
||||
// Show the most probable in the middle, then left, then right
|
||||
val ORDER_OF_SUGGESTIONS = listOf(1, 0, 2)
|
||||
|
||||
@Composable
|
||||
fun RowScope.SuggestionItems(words: SuggestedWords, onClick: (i: Int) -> Unit) {
|
||||
val maxSuggestions = min(ORDER_OF_SUGGESTIONS.size, words.size())
|
||||
|
||||
if(maxSuggestions == 0) {
|
||||
Spacer(modifier = Modifier.weight(1.0f))
|
||||
return
|
||||
}
|
||||
|
||||
for (i in 0 until maxSuggestions) {
|
||||
val remapped = ORDER_OF_SUGGESTIONS[i]
|
||||
|
||||
SuggestionItem(words, remapped) { onClick(remapped) }
|
||||
|
||||
if (i < maxSuggestions - 1) SuggestionSeparator()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Composable
|
||||
fun RowScope.ActionItem() {
|
||||
val col = MaterialTheme.colorScheme.secondary
|
||||
IconButton(onClick = { /*TODO*/ }, 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),
|
||||
cornerRadius = CornerRadius(radius, radius)
|
||||
)
|
||||
}
|
||||
.width(50.dp)
|
||||
.fillMaxHeight()) {
|
||||
Icon(
|
||||
painter = painterResource(id = R.drawable.mic_fill),
|
||||
contentDescription = "Voice Input"
|
||||
)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun RowScope.ActionItems() {
|
||||
|
||||
ActionItem()
|
||||
ActionItem()
|
||||
ActionItem()
|
||||
|
||||
|
||||
Spacer(modifier = Modifier.weight(1.0f))
|
||||
}
|
||||
|
||||
class ExampleListener : SuggestionStripView.Listener {
|
||||
override fun showImportantNoticeContents() {
|
||||
}
|
||||
|
||||
override fun pickSuggestionManually(word: SuggestedWordInfo?) {
|
||||
}
|
||||
|
||||
override fun onCodeInput(primaryCode: Int, x: Int, y: Int, isKeyRepeat: Boolean) {
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Composable
|
||||
@Preview
|
||||
fun ActionBar(
|
||||
words: SuggestedWords? = exampleSuggestedWords,
|
||||
suggestionStripListener: SuggestionStripView.Listener = ExampleListener()
|
||||
) {
|
||||
val isActionsOpen = remember { mutableStateOf(false) }
|
||||
val actionsForcedOpenByUser = remember { mutableStateOf(false) }
|
||||
|
||||
//LaunchedEffect(words?.isEmpty) {
|
||||
// isActionsOpen.value = actionsForcedOpenByUser.value || words == null || words.isEmpty
|
||||
//}
|
||||
|
||||
LaunchedEffect(actionsForcedOpenByUser.value) {
|
||||
isActionsOpen.value = actionsForcedOpenByUser.value //|| (words == null || words.isEmpty)
|
||||
}
|
||||
|
||||
WhisperVoiceInputTheme {
|
||||
Surface(modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.height(40.dp), color = MaterialTheme.colorScheme.surface)
|
||||
{
|
||||
Row {
|
||||
val moreActionsColor = MaterialTheme.colorScheme.primary
|
||||
|
||||
val moreActionsFill = if(isActionsOpen.value) {
|
||||
MaterialTheme.colorScheme.primary
|
||||
} else {
|
||||
MaterialTheme.colorScheme.surface
|
||||
}
|
||||
IconButton(
|
||||
onClick = { actionsForcedOpenByUser.value = !actionsForcedOpenByUser.value },
|
||||
modifier = Modifier
|
||||
.width(42.dp)
|
||||
.rotate(
|
||||
if (isActionsOpen.value) {
|
||||
180.0f
|
||||
} else {
|
||||
0.0f
|
||||
}
|
||||
)
|
||||
.fillMaxHeight()
|
||||
.drawBehind {
|
||||
drawCircle(color = moreActionsColor, radius = size.width / 3.0f + 1.0f)
|
||||
drawCircle(color = moreActionsFill, radius = size.width / 3.0f - 2.0f)
|
||||
}
|
||||
) {
|
||||
Icon(
|
||||
painter = painterResource(id = R.drawable.chevron_right),
|
||||
contentDescription = "Open Actions"
|
||||
)
|
||||
}
|
||||
|
||||
if(isActionsOpen.value) {
|
||||
ActionItems()
|
||||
} else if(words != null) {
|
||||
SuggestionItems(words) {
|
||||
suggestionStripListener.pickSuggestionManually(
|
||||
words.getInfo(it)
|
||||
)
|
||||
}
|
||||
} else {
|
||||
Spacer(modifier = Modifier.weight(1.0f))
|
||||
}
|
||||
|
||||
|
||||
// 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"
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
292
java/src/org/futo/inputmethod/latin/uix/theme/Color.kt
Normal file
292
java/src/org/futo/inputmethod/latin/uix/theme/Color.kt
Normal file
@ -0,0 +1,292 @@
|
||||
@file:Suppress("unused")
|
||||
|
||||
package org.futo.inputmethod.latin.uix.theme
|
||||
|
||||
import androidx.compose.ui.graphics.Color
|
||||
|
||||
// Colors from Tailwind - https://tailwindcss.com/docs/customizing-colors
|
||||
|
||||
val Slate50 = Color(0xfff8fafc)
|
||||
val Slate100 = Color(0xfff1f5f9)
|
||||
val Slate200 = Color(0xffe2e8f0)
|
||||
val Slate300 = Color(0xffcbd5e1)
|
||||
val Slate400 = Color(0xff94a3b8)
|
||||
val Slate500 = Color(0xff64748b)
|
||||
val Slate600 = Color(0xff475569)
|
||||
val Slate700 = Color(0xff334155)
|
||||
val Slate800 = Color(0xff1e293b)
|
||||
val Slate900 = Color(0xff0f172a)
|
||||
val Slate950 = Color(0xff020617)
|
||||
|
||||
|
||||
val Gray50 = Color(0xfff9fafb)
|
||||
val Gray100 = Color(0xfff3f4f6)
|
||||
val Gray200 = Color(0xffe5e7eb)
|
||||
val Gray300 = Color(0xffd1d5db)
|
||||
val Gray400 = Color(0xff9ca3af)
|
||||
val Gray500 = Color(0xff6b7280)
|
||||
val Gray600 = Color(0xff4b5563)
|
||||
val Gray700 = Color(0xff374151)
|
||||
val Gray800 = Color(0xff1f2937)
|
||||
val Gray900 = Color(0xff111827)
|
||||
val Gray950 = Color(0xff030712)
|
||||
|
||||
|
||||
val Zinc50 = Color(0xfffafafa)
|
||||
val Zinc100 = Color(0xfff4f4f5)
|
||||
val Zinc200 = Color(0xffe4e4e7)
|
||||
val Zinc300 = Color(0xffd4d4d8)
|
||||
val Zinc400 = Color(0xffa1a1aa)
|
||||
val Zinc500 = Color(0xff71717a)
|
||||
val Zinc600 = Color(0xff52525b)
|
||||
val Zinc700 = Color(0xff3f3f46)
|
||||
val Zinc800 = Color(0xff27272a)
|
||||
val Zinc900 = Color(0xff18181b)
|
||||
val Zinc950 = Color(0xff09090b)
|
||||
|
||||
|
||||
val Neutral50 = Color(0xfffafafa)
|
||||
val Neutral100 = Color(0xfff5f5f5)
|
||||
val Neutral200 = Color(0xffe5e5e5)
|
||||
val Neutral300 = Color(0xffd4d4d4)
|
||||
val Neutral400 = Color(0xffa3a3a3)
|
||||
val Neutral500 = Color(0xff737373)
|
||||
val Neutral600 = Color(0xff525252)
|
||||
val Neutral700 = Color(0xff404040)
|
||||
val Neutral800 = Color(0xff262626)
|
||||
val Neutral900 = Color(0xff171717)
|
||||
val Neutral950 = Color(0xff0a0a0a)
|
||||
|
||||
|
||||
val Stone50 = Color(0xfffafaf9)
|
||||
val Stone100 = Color(0xfff5f5f4)
|
||||
val Stone200 = Color(0xffe7e5e4)
|
||||
val Stone300 = Color(0xffd6d3d1)
|
||||
val Stone400 = Color(0xffa8a29e)
|
||||
val Stone500 = Color(0xff78716c)
|
||||
val Stone600 = Color(0xff57534e)
|
||||
val Stone700 = Color(0xff44403c)
|
||||
val Stone800 = Color(0xff292524)
|
||||
val Stone900 = Color(0xff1c1917)
|
||||
val Stone950 = Color(0xff0c0a09)
|
||||
|
||||
|
||||
val Red50 = Color(0xfffef2f2)
|
||||
val Red100 = Color(0xfffee2e2)
|
||||
val Red200 = Color(0xfffecaca)
|
||||
val Red300 = Color(0xfffca5a5)
|
||||
val Red400 = Color(0xfff87171)
|
||||
val Red500 = Color(0xffef4444)
|
||||
val Red600 = Color(0xffdc2626)
|
||||
val Red700 = Color(0xffb91c1c)
|
||||
val Red800 = Color(0xff991b1b)
|
||||
val Red900 = Color(0xff7f1d1d)
|
||||
val Red950 = Color(0xff450a0a)
|
||||
|
||||
|
||||
val Orange50 = Color(0xfffff7ed)
|
||||
val Orange100 = Color(0xffffedd5)
|
||||
val Orange200 = Color(0xfffed7aa)
|
||||
val Orange300 = Color(0xfffdba74)
|
||||
val Orange400 = Color(0xfffb923c)
|
||||
val Orange500 = Color(0xfff97316)
|
||||
val Orange600 = Color(0xffea580c)
|
||||
val Orange700 = Color(0xffc2410c)
|
||||
val Orange800 = Color(0xff9a3412)
|
||||
val Orange900 = Color(0xff7c2d12)
|
||||
val Orange950 = Color(0xff431407)
|
||||
|
||||
|
||||
val Amber50 = Color(0xfffffbeb)
|
||||
val Amber100 = Color(0xfffef3c7)
|
||||
val Amber200 = Color(0xfffde68a)
|
||||
val Amber300 = Color(0xfffcd34d)
|
||||
val Amber400 = Color(0xfffbbf24)
|
||||
val Amber500 = Color(0xfff59e0b)
|
||||
val Amber600 = Color(0xffd97706)
|
||||
val Amber700 = Color(0xffb45309)
|
||||
val Amber800 = Color(0xff92400e)
|
||||
val Amber900 = Color(0xff78350f)
|
||||
val Amber950 = Color(0xff451a03)
|
||||
|
||||
|
||||
val Yellow50 = Color(0xfffefce8)
|
||||
val Yellow100 = Color(0xfffef9c3)
|
||||
val Yellow200 = Color(0xfffef08a)
|
||||
val Yellow300 = Color(0xfffde047)
|
||||
val Yellow400 = Color(0xfffacc15)
|
||||
val Yellow500 = Color(0xffeab308)
|
||||
val Yellow600 = Color(0xffca8a04)
|
||||
val Yellow700 = Color(0xffa16207)
|
||||
val Yellow800 = Color(0xff854d0e)
|
||||
val Yellow900 = Color(0xff713f12)
|
||||
val Yellow950 = Color(0xff422006)
|
||||
|
||||
|
||||
val Lime50 = Color(0xfff7fee7)
|
||||
val Lime100 = Color(0xffecfccb)
|
||||
val Lime200 = Color(0xffd9f99d)
|
||||
val Lime300 = Color(0xffbef264)
|
||||
val Lime400 = Color(0xffa3e635)
|
||||
val Lime500 = Color(0xff84cc16)
|
||||
val Lime600 = Color(0xff65a30d)
|
||||
val Lime700 = Color(0xff4d7c0f)
|
||||
val Lime800 = Color(0xff3f6212)
|
||||
val Lime900 = Color(0xff365314)
|
||||
val Lime950 = Color(0xff1a2e05)
|
||||
|
||||
|
||||
val Green50 = Color(0xfff0fdf4)
|
||||
val Green100 = Color(0xffdcfce7)
|
||||
val Green200 = Color(0xffbbf7d0)
|
||||
val Green300 = Color(0xff86efac)
|
||||
val Green400 = Color(0xff4ade80)
|
||||
val Green500 = Color(0xff22c55e)
|
||||
val Green600 = Color(0xff16a34a)
|
||||
val Green700 = Color(0xff15803d)
|
||||
val Green800 = Color(0xff166534)
|
||||
val Green900 = Color(0xff14532d)
|
||||
val Green950 = Color(0xff052e16)
|
||||
|
||||
|
||||
val Emerald50 = Color(0xffecfdf5)
|
||||
val Emerald100 = Color(0xffd1fae5)
|
||||
val Emerald200 = Color(0xffa7f3d0)
|
||||
val Emerald300 = Color(0xff6ee7b7)
|
||||
val Emerald400 = Color(0xff34d399)
|
||||
val Emerald500 = Color(0xff10b981)
|
||||
val Emerald600 = Color(0xff059669)
|
||||
val Emerald700 = Color(0xff047857)
|
||||
val Emerald800 = Color(0xff065f46)
|
||||
val Emerald900 = Color(0xff064e3b)
|
||||
val Emerald950 = Color(0xff022c22)
|
||||
|
||||
|
||||
val Teal50 = Color(0xfff0fdfa)
|
||||
val Teal100 = Color(0xffccfbf1)
|
||||
val Teal200 = Color(0xff99f6e4)
|
||||
val Teal300 = Color(0xff5eead4)
|
||||
val Teal400 = Color(0xff2dd4bf)
|
||||
val Teal500 = Color(0xff14b8a6)
|
||||
val Teal600 = Color(0xff0d9488)
|
||||
val Teal700 = Color(0xff0f766e)
|
||||
val Teal800 = Color(0xff115e59)
|
||||
val Teal900 = Color(0xff134e4a)
|
||||
val Teal950 = Color(0xff042f2e)
|
||||
|
||||
|
||||
val Cyan50 = Color(0xffecfeff)
|
||||
val Cyan100 = Color(0xffcffafe)
|
||||
val Cyan200 = Color(0xffa5f3fc)
|
||||
val Cyan300 = Color(0xff67e8f9)
|
||||
val Cyan400 = Color(0xff22d3ee)
|
||||
val Cyan500 = Color(0xff06b6d4)
|
||||
val Cyan600 = Color(0xff0891b2)
|
||||
val Cyan700 = Color(0xff0e7490)
|
||||
val Cyan800 = Color(0xff155e75)
|
||||
val Cyan900 = Color(0xff164e63)
|
||||
val Cyan950 = Color(0xff083344)
|
||||
|
||||
|
||||
val Sky50 = Color(0xfff0f9ff)
|
||||
val Sky100 = Color(0xffe0f2fe)
|
||||
val Sky200 = Color(0xffbae6fd)
|
||||
val Sky300 = Color(0xff7dd3fc)
|
||||
val Sky400 = Color(0xff38bdf8)
|
||||
val Sky500 = Color(0xff0ea5e9)
|
||||
val Sky600 = Color(0xff0284c7)
|
||||
val Sky700 = Color(0xff0369a1)
|
||||
val Sky800 = Color(0xff075985)
|
||||
val Sky900 = Color(0xff0c4a6e)
|
||||
val Sky950 = Color(0xff082f49)
|
||||
|
||||
|
||||
val Blue50 = Color(0xffeff6ff)
|
||||
val Blue100 = Color(0xffdbeafe)
|
||||
val Blue200 = Color(0xffbfdbfe)
|
||||
val Blue300 = Color(0xff93c5fd)
|
||||
val Blue400 = Color(0xff60a5fa)
|
||||
val Blue500 = Color(0xff3b82f6)
|
||||
val Blue600 = Color(0xff2563eb)
|
||||
val Blue700 = Color(0xff1d4ed8)
|
||||
val Blue800 = Color(0xff1e40af)
|
||||
val Blue900 = Color(0xff1e3a8a)
|
||||
val Blue950 = Color(0xff172554)
|
||||
|
||||
|
||||
val Indigo50 = Color(0xffeef2ff)
|
||||
val Indigo100 = Color(0xffe0e7ff)
|
||||
val Indigo200 = Color(0xffc7d2fe)
|
||||
val Indigo300 = Color(0xffa5b4fc)
|
||||
val Indigo400 = Color(0xff818cf8)
|
||||
val Indigo500 = Color(0xff6366f1)
|
||||
val Indigo600 = Color(0xff4f46e5)
|
||||
val Indigo700 = Color(0xff4338ca)
|
||||
val Indigo800 = Color(0xff3730a3)
|
||||
val Indigo900 = Color(0xff312e81)
|
||||
val Indigo950 = Color(0xff1e1b4b)
|
||||
|
||||
|
||||
val Violet50 = Color(0xfff5f3ff)
|
||||
val Violet100 = Color(0xffede9fe)
|
||||
val Violet200 = Color(0xffddd6fe)
|
||||
val Violet300 = Color(0xffc4b5fd)
|
||||
val Violet400 = Color(0xffa78bfa)
|
||||
val Violet500 = Color(0xff8b5cf6)
|
||||
val Violet600 = Color(0xff7c3aed)
|
||||
val Violet700 = Color(0xff6d28d9)
|
||||
val Violet800 = Color(0xff5b21b6)
|
||||
val Violet900 = Color(0xff4c1d95)
|
||||
val Violet950 = Color(0xff2e1065)
|
||||
|
||||
|
||||
val Purple50 = Color(0xfffaf5ff)
|
||||
val Purple100 = Color(0xfff3e8ff)
|
||||
val Purple200 = Color(0xffe9d5ff)
|
||||
val Purple300 = Color(0xffd8b4fe)
|
||||
val Purple400 = Color(0xffc084fc)
|
||||
val Purple500 = Color(0xffa855f7)
|
||||
val Purple600 = Color(0xff9333ea)
|
||||
val Purple700 = Color(0xff7e22ce)
|
||||
val Purple800 = Color(0xff6b21a8)
|
||||
val Purple900 = Color(0xff581c87)
|
||||
val Purple950 = Color(0xff3b0764)
|
||||
|
||||
|
||||
val Fuchsia50 = Color(0xfffdf4ff)
|
||||
val Fuchsia100 = Color(0xfffae8ff)
|
||||
val Fuchsia200 = Color(0xfff5d0fe)
|
||||
val Fuchsia300 = Color(0xfff0abfc)
|
||||
val Fuchsia400 = Color(0xffe879f9)
|
||||
val Fuchsia500 = Color(0xffd946ef)
|
||||
val Fuchsia600 = Color(0xffc026d3)
|
||||
val Fuchsia700 = Color(0xffa21caf)
|
||||
val Fuchsia800 = Color(0xff86198f)
|
||||
val Fuchsia900 = Color(0xff701a75)
|
||||
val Fuchsia950 = Color(0xff4a044e)
|
||||
|
||||
|
||||
val Pink50 = Color(0xfffdf2f8)
|
||||
val Pink100 = Color(0xfffce7f3)
|
||||
val Pink200 = Color(0xfffbcfe8)
|
||||
val Pink300 = Color(0xfff9a8d4)
|
||||
val Pink400 = Color(0xfff472b6)
|
||||
val Pink500 = Color(0xffec4899)
|
||||
val Pink600 = Color(0xffdb2777)
|
||||
val Pink700 = Color(0xffbe185d)
|
||||
val Pink800 = Color(0xff9d174d)
|
||||
val Pink900 = Color(0xff831843)
|
||||
val Pink950 = Color(0xff500724)
|
||||
|
||||
|
||||
val Rose50 = Color(0xfffff1f2)
|
||||
val Rose100 = Color(0xffffe4e6)
|
||||
val Rose200 = Color(0xfffecdd3)
|
||||
val Rose300 = Color(0xfffda4af)
|
||||
val Rose400 = Color(0xfffb7185)
|
||||
val Rose500 = Color(0xfff43f5e)
|
||||
val Rose600 = Color(0xffe11d48)
|
||||
val Rose700 = Color(0xffbe123c)
|
||||
val Rose800 = Color(0xff9f1239)
|
||||
val Rose900 = Color(0xff881337)
|
||||
val Rose950 = Color(0xff4c0519)
|
77
java/src/org/futo/inputmethod/latin/uix/theme/Theme.kt
Normal file
77
java/src/org/futo/inputmethod/latin/uix/theme/Theme.kt
Normal file
@ -0,0 +1,77 @@
|
||||
package org.futo.inputmethod.latin.uix.theme
|
||||
|
||||
import android.app.Activity
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.material3.darkColorScheme
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.SideEffect
|
||||
import androidx.compose.ui.graphics.toArgb
|
||||
import androidx.compose.ui.platform.LocalView
|
||||
import androidx.core.view.WindowCompat
|
||||
|
||||
private val DarkColorScheme = darkColorScheme(
|
||||
primary = Slate600,
|
||||
onPrimary = Slate50,
|
||||
|
||||
primaryContainer = Slate700,
|
||||
onPrimaryContainer = Slate50,
|
||||
|
||||
secondary = Slate700,
|
||||
onSecondary = Slate50,
|
||||
|
||||
secondaryContainer = Slate600,
|
||||
onSecondaryContainer = Slate50,
|
||||
|
||||
tertiary = Stone700,
|
||||
onTertiary = Stone50,
|
||||
|
||||
tertiaryContainer = Stone600,
|
||||
onTertiaryContainer = Stone50,
|
||||
|
||||
background = Slate900,
|
||||
onBackground = Slate50,
|
||||
|
||||
surface = Slate800,
|
||||
onSurface = Slate50,
|
||||
|
||||
outline = Slate300,
|
||||
|
||||
surfaceVariant = Slate800,
|
||||
onSurfaceVariant = Slate300
|
||||
)
|
||||
|
||||
@Composable
|
||||
fun WhisperVoiceInputTheme(content: @Composable () -> Unit) {
|
||||
/*
|
||||
val colorScheme = when {
|
||||
dynamicColor && Build.VERSION.SDK_INT >= Build.VERSION_CODES.S -> {
|
||||
val context = LocalContext.current
|
||||
if (darkTheme) dynamicDarkColorScheme(context) else dynamicLightColorScheme(context)
|
||||
}
|
||||
|
||||
darkTheme -> DarkColorScheme
|
||||
else -> LightColorScheme
|
||||
}
|
||||
*/
|
||||
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
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
MaterialTheme(
|
||||
colorScheme = colorScheme,
|
||||
typography = Typography,
|
||||
content = content
|
||||
)
|
||||
}
|
34
java/src/org/futo/inputmethod/latin/uix/theme/Type.kt
Normal file
34
java/src/org/futo/inputmethod/latin/uix/theme/Type.kt
Normal file
@ -0,0 +1,34 @@
|
||||
package org.futo.inputmethod.latin.uix.theme
|
||||
|
||||
import androidx.compose.material3.Typography
|
||||
import androidx.compose.ui.text.TextStyle
|
||||
import androidx.compose.ui.text.font.FontFamily
|
||||
import androidx.compose.ui.text.font.FontWeight
|
||||
import androidx.compose.ui.unit.sp
|
||||
|
||||
// Set of Material typography styles to start with
|
||||
val Typography = Typography(
|
||||
bodyLarge = TextStyle(
|
||||
fontFamily = FontFamily.SansSerif,
|
||||
fontWeight = FontWeight.Light,
|
||||
fontSize = 20.sp,
|
||||
lineHeight = 26.sp,
|
||||
letterSpacing = 0.5.sp
|
||||
),
|
||||
/* Other default text styles to override
|
||||
titleLarge = TextStyle(
|
||||
fontFamily = FontFamily.Default,
|
||||
fontWeight = FontWeight.Normal,
|
||||
fontSize = 22.sp,
|
||||
lineHeight = 28.sp,
|
||||
letterSpacing = 0.sp
|
||||
),
|
||||
*/
|
||||
labelSmall = TextStyle(
|
||||
fontFamily = FontFamily.Default,
|
||||
fontWeight = FontWeight.Medium,
|
||||
fontSize = 11.sp,
|
||||
lineHeight = 16.sp,
|
||||
letterSpacing = 0.5.sp
|
||||
)
|
||||
)
|
@ -18,7 +18,7 @@ package org.futo.inputmethod.latin;
|
||||
|
||||
public class LatinIMELegacyForTests extends LatinIMELegacy {
|
||||
public LatinIMELegacyForTests() {
|
||||
super(mInputMethodService);
|
||||
super(mInputMethodService, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
Loading…
Reference in New Issue
Block a user