diff --git a/CHANGELOG.md b/CHANGELOG.md index 72f7757a..c98f44ed 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,8 +6,13 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] ### Added +- Optional key to quickly switch keyboard language ([#62]) - Added apostrophe as a pop-up character on the dot key ([#356]) +### Changed +- The space bar now shows the currently selected language ([#62]) +- Space bar cursor control now activates immediately on swipe ([#129]) + ## [1.7.0] - 2025-12-16 ### Added - Option to disable the emoji key ([#234]) @@ -116,9 +121,11 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Initial release [#47]: https://github.com/FossifyOrg/Keyboard/issues/47 +[#62]: https://github.com/FossifyOrg/Keyboard/issues/62 [#78]: https://github.com/FossifyOrg/Keyboard/issues/78 [#100]: https://github.com/FossifyOrg/Keyboard/issues/100 [#117]: https://github.com/FossifyOrg/Keyboard/issues/117 +[#129]: https://github.com/FossifyOrg/Keyboard/issues/129 [#133]: https://github.com/FossifyOrg/Keyboard/issues/133 [#134]: https://github.com/FossifyOrg/Keyboard/issues/134 [#136]: https://github.com/FossifyOrg/Keyboard/issues/136 diff --git a/app/detekt-baseline.xml b/app/detekt-baseline.xml index 7c17b114..78d5f011 100644 --- a/app/detekt-baseline.xml +++ b/app/detekt-baseline.xml @@ -8,8 +8,7 @@ ComplexCondition:MyKeyboardView.kt$MyKeyboardView$(show && keyboardViewBinding?.clipboardValue!!.alpha == 0f) || (!show && keyboardViewBinding?.clipboardValue!!.alpha == 1f) ComplexCondition:MyKeyboardView.kt$MyKeyboardView$key.label.isNotEmpty() && key.code != KEYCODE_MODE_CHANGE && key.code != KEYCODE_SYMBOLS_MODE_CHANGE && key.code != KEYCODE_SHIFT ComplexCondition:MyKeyboardView.kt$MyKeyboardView$mBuffer == null || mKeyboardChanged && (mBuffer!!.width != width || mBuffer!!.height != height) - CyclomaticComplexMethod:Context.kt$fun Context.getKeyboardLanguageText(language: Int): String - CyclomaticComplexMethod:Context.kt$fun Context.setupKeyboardDialogStuff( windowToken: IBinder, view: View, dialog: AlertDialog.Builder, titleId: Int = 0, titleText: String = "", cancelOnTouchOutside: Boolean = true, callback: ((alertDialog: AlertDialog) -> Unit)? = null ) + CyclomaticComplexMethod:ContextExt.kt$fun Context.setupKeyboardDialogStuff( windowToken: IBinder, view: View, dialog: AlertDialog.Builder, titleId: Int = 0, titleText: String = "", cancelOnTouchOutside: Boolean = true, callback: ((alertDialog: AlertDialog) -> Unit)? = null ) CyclomaticComplexMethod:MyKeyboard.kt$MyKeyboard$@SuppressLint("UseCompatLoadingForDrawables") private fun loadKeyboard(context: Context, parser: XmlResourceParser) CyclomaticComplexMethod:MyKeyboardView.kt$MyKeyboardView$@SuppressLint("UseCompatLoadingForDrawables") private fun onBufferDraw() CyclomaticComplexMethod:MyKeyboardView.kt$MyKeyboardView$override fun onTouchEvent(me: MotionEvent): Boolean @@ -54,7 +53,6 @@ MaxLineLength:ClipsActivityAdapter.kt$ClipsActivityAdapter$override fun onCreateViewHolder(parent: ViewGroup, viewType: Int) MaxLineLength:ClipsKeyboardAdapter.kt$ClipsKeyboardAdapter$layerDrawable.findDrawableByLayerId(R.id.clipboard_background_stroke).applyColorFilter(context.getStrokeColor()) MaxLineLength:Config.kt$Config$set(lastExportedClipsFolder) = prefs.edit().putString(LAST_EXPORTED_CLIPS_FOLDER, lastExportedClipsFolder).apply() - MaxLineLength:Context.kt$fun MaxLineLength:EmojisAdapter.kt$EmojisAdapter.EmojiCategoryViewHolder$inner MaxLineLength:ExportClipsDialog.kt$ExportClipsDialog$exportClipsFilename.setText("${activity.getString(R.string.app_launcher_name)}_${activity.getCurrentFormattedDateTime()}") MaxLineLength:ExportClipsDialog.kt$ExportClipsDialog$val activity: BaseSimpleActivity @@ -93,7 +91,7 @@ MaxLineLength:SimpleKeyboardIME.kt$SimpleKeyboardIME$layerDrawable.findDrawableByLayerId(R.id.clipboard_background_shape).applyColorFilter(getProperBackgroundColor()) MaxLineLength:SimpleKeyboardIME.kt$SimpleKeyboardIME$override MaxLineLength:SwitchLanguageDialog.kt$SwitchLanguageDialog$addView(radioButton, RadioGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT)) - NestedBlockDepth:Context.kt$fun Context.setupKeyboardDialogStuff( windowToken: IBinder, view: View, dialog: AlertDialog.Builder, titleId: Int = 0, titleText: String = "", cancelOnTouchOutside: Boolean = true, callback: ((alertDialog: AlertDialog) -> Unit)? = null ) + NestedBlockDepth:ContextExt.kt$fun Context.setupKeyboardDialogStuff( windowToken: IBinder, view: View, dialog: AlertDialog.Builder, titleId: Int = 0, titleText: String = "", cancelOnTouchOutside: Boolean = true, callback: ((alertDialog: AlertDialog) -> Unit)? = null ) NestedBlockDepth:MyKeyboard.kt$MyKeyboard$@SuppressLint("UseCompatLoadingForDrawables") private fun loadKeyboard(context: Context, parser: XmlResourceParser) NestedBlockDepth:MyKeyboardView.kt$MyKeyboardView$@SuppressLint("UseCompatLoadingForDrawables") private fun onBufferDraw() NestedBlockDepth:MyKeyboardView.kt$MyKeyboardView$override fun onTouchEvent(me: MotionEvent): Boolean diff --git a/app/lint-baseline.xml b/app/lint-baseline.xml index dbec9dcf..c835a2db 100644 --- a/app/lint-baseline.xml +++ b/app/lint-baseline.xml @@ -8,7 +8,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> @@ -36,29 +36,40 @@ errorLine1="distributionUrl=https\://services.gradle.org/distributions/gradle-8.13-bin.zip" errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> + + + + @@ -76,7 +87,7 @@ + + + + @@ -756,6 +778,17 @@ column="29"/> + + + + @@ -774,7 +807,7 @@ errorLine2=" ~~~~~~~~~~~~"> @@ -785,7 +818,7 @@ errorLine2=" ~~~~~~~~~~~~"> @@ -796,7 +829,7 @@ errorLine2=" ~~~~~~~~~~~~"> @@ -807,7 +840,7 @@ errorLine2=" ~~~~~~~~~~~~"> @@ -818,7 +851,7 @@ errorLine2=" ~~~~~~~~~~~~"> @@ -829,7 +862,7 @@ errorLine2=" ~~~~~~~~~~~~"> @@ -840,7 +873,7 @@ errorLine2=" ~~~~~~~~~~~~"> @@ -851,7 +884,7 @@ errorLine2=" ~~~~~~~~~~~~"> @@ -862,7 +895,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~"> @@ -873,7 +906,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~"> @@ -884,7 +917,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> @@ -895,7 +928,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> @@ -906,7 +939,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~"> @@ -917,7 +950,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~"> @@ -928,7 +961,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> @@ -939,7 +972,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> @@ -950,7 +983,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> @@ -961,7 +994,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> @@ -972,7 +1005,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> @@ -983,7 +1016,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~"> @@ -994,7 +1027,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~"> @@ -1005,7 +1038,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~"> @@ -1016,7 +1049,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> @@ -1027,7 +1060,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> @@ -1038,7 +1071,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~"> @@ -1049,7 +1082,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~"> diff --git a/app/src/main/kotlin/org/fossify/keyboard/activities/SettingsActivity.kt b/app/src/main/kotlin/org/fossify/keyboard/activities/SettingsActivity.kt index 08c0eb45..5133024c 100644 --- a/app/src/main/kotlin/org/fossify/keyboard/activities/SettingsActivity.kt +++ b/app/src/main/kotlin/org/fossify/keyboard/activities/SettingsActivity.kt @@ -60,6 +60,7 @@ class SettingsActivity : SimpleActivity() { setupKeyboardLanguage() setupKeyboardHeightMultiplier() setupShowEmojiKey() + setupShowLanguageSwitchKey() setupShowClipboardContent() setupSentencesCapitalization() setupShowNumbersRow() @@ -243,11 +244,29 @@ class SettingsActivity : SimpleActivity() { settingsShowEmojiKeyHolder.setOnClickListener { settingsShowEmojiKey.toggle() config.showEmojiKey = settingsShowEmojiKey.isChecked + if (settingsShowEmojiKey.isChecked) { + config.showLanguageSwitchKey = false + settingsShowLanguageSwitchKey.isChecked = false + } } settingsShowEmojiKey.isChecked = config.showEmojiKey } } + private fun setupShowLanguageSwitchKey() { + binding.apply { + settingsShowLanguageSwitchKeyHolder.setOnClickListener { + settingsShowLanguageSwitchKey.toggle() + config.showLanguageSwitchKey = settingsShowLanguageSwitchKey.isChecked + if (settingsShowLanguageSwitchKey.isChecked) { + config.showEmojiKey = false + settingsShowEmojiKey.isChecked = false + } + } + settingsShowLanguageSwitchKey.isChecked = config.showLanguageSwitchKey + } + } + private fun setupShowNumbersRow() { binding.apply { settingsShowNumbersRow.isChecked = config.showNumbersRow diff --git a/app/src/main/kotlin/org/fossify/keyboard/extensions/Context.kt b/app/src/main/kotlin/org/fossify/keyboard/extensions/ContextExt.kt similarity index 50% rename from app/src/main/kotlin/org/fossify/keyboard/extensions/Context.kt rename to app/src/main/kotlin/org/fossify/keyboard/extensions/ContextExt.kt index e35433ec..563c8692 100644 --- a/app/src/main/kotlin/org/fossify/keyboard/extensions/Context.kt +++ b/app/src/main/kotlin/org/fossify/keyboard/extensions/ContextExt.kt @@ -3,7 +3,6 @@ package org.fossify.keyboard.extensions import android.app.KeyguardManager import android.content.ClipboardManager import android.content.Context -import android.graphics.Color import android.inputmethodservice.InputMethodService import android.os.IBinder import android.os.UserManager @@ -21,15 +20,12 @@ import androidx.core.content.res.ResourcesCompat import com.google.android.material.dialog.MaterialAlertDialogBuilder import org.fossify.commons.databinding.DialogTitleBinding import org.fossify.commons.extensions.baseConfig -import org.fossify.commons.extensions.darkenColor import org.fossify.commons.extensions.getColoredDrawableWithColor import org.fossify.commons.extensions.getProperBackgroundColor import org.fossify.commons.extensions.getProperPrimaryColor import org.fossify.commons.extensions.getProperTextColor import org.fossify.commons.extensions.isBlackAndWhiteTheme import org.fossify.commons.extensions.isDynamicTheme -import org.fossify.commons.extensions.isSystemInDarkMode -import org.fossify.commons.extensions.lightenColor import org.fossify.commons.extensions.updateTextColors import org.fossify.commons.helpers.isNougatPlus import org.fossify.commons.models.RadioItem @@ -38,49 +34,6 @@ import org.fossify.keyboard.R import org.fossify.keyboard.databases.ClipsDatabase import org.fossify.keyboard.helpers.Config import org.fossify.keyboard.helpers.INPUT_METHOD_SUBTYPE_VOICE -import org.fossify.keyboard.helpers.LANGUAGE_ARABIC -import org.fossify.keyboard.helpers.LANGUAGE_BELARUSIAN_CYRL -import org.fossify.keyboard.helpers.LANGUAGE_BELARUSIAN_LATN -import org.fossify.keyboard.helpers.LANGUAGE_BENGALI -import org.fossify.keyboard.helpers.LANGUAGE_BULGARIAN -import org.fossify.keyboard.helpers.LANGUAGE_CENTRAL_KURDISH -import org.fossify.keyboard.helpers.LANGUAGE_CHUVASH -import org.fossify.keyboard.helpers.LANGUAGE_CZECH_QWERTY -import org.fossify.keyboard.helpers.LANGUAGE_CZECH_QWERTZ -import org.fossify.keyboard.helpers.LANGUAGE_DANISH -import org.fossify.keyboard.helpers.LANGUAGE_DUTCH -import org.fossify.keyboard.helpers.LANGUAGE_ENGLISH_ASSET -import org.fossify.keyboard.helpers.LANGUAGE_ENGLISH_COLEMAK -import org.fossify.keyboard.helpers.LANGUAGE_ENGLISH_COLEMAKDH -import org.fossify.keyboard.helpers.LANGUAGE_ENGLISH_DVORAK -import org.fossify.keyboard.helpers.LANGUAGE_ENGLISH_NIRO -import org.fossify.keyboard.helpers.LANGUAGE_ENGLISH_QWERTZ -import org.fossify.keyboard.helpers.LANGUAGE_ENGLISH_SOUL -import org.fossify.keyboard.helpers.LANGUAGE_ENGLISH_WORKMAN -import org.fossify.keyboard.helpers.LANGUAGE_ESPERANTO -import org.fossify.keyboard.helpers.LANGUAGE_FRENCH_AZERTY -import org.fossify.keyboard.helpers.LANGUAGE_FRENCH_BEPO -import org.fossify.keyboard.helpers.LANGUAGE_GERMAN -import org.fossify.keyboard.helpers.LANGUAGE_GERMAN_QWERTZ -import org.fossify.keyboard.helpers.LANGUAGE_GREEK -import org.fossify.keyboard.helpers.LANGUAGE_HEBREW -import org.fossify.keyboard.helpers.LANGUAGE_ITALIAN -import org.fossify.keyboard.helpers.LANGUAGE_KABYLE_AZERTY -import org.fossify.keyboard.helpers.LANGUAGE_LATVIAN -import org.fossify.keyboard.helpers.LANGUAGE_LITHUANIAN -import org.fossify.keyboard.helpers.LANGUAGE_NORWEGIAN -import org.fossify.keyboard.helpers.LANGUAGE_POLISH -import org.fossify.keyboard.helpers.LANGUAGE_PORTUGUESE -import org.fossify.keyboard.helpers.LANGUAGE_PORTUGUESE_HCESAR -import org.fossify.keyboard.helpers.LANGUAGE_ROMANIAN -import org.fossify.keyboard.helpers.LANGUAGE_RUSSIAN -import org.fossify.keyboard.helpers.LANGUAGE_SLOVENIAN -import org.fossify.keyboard.helpers.LANGUAGE_SPANISH -import org.fossify.keyboard.helpers.LANGUAGE_SWEDISH -import org.fossify.keyboard.helpers.LANGUAGE_TURKISH -import org.fossify.keyboard.helpers.LANGUAGE_TURKISH_Q -import org.fossify.keyboard.helpers.LANGUAGE_UKRAINIAN -import org.fossify.keyboard.helpers.LANGUAGE_VIETNAMESE_TELEX import org.fossify.keyboard.interfaces.ClipsDao val Context.config: Config get() = Config.newInstance(applicationContext.safeStorageContext) @@ -115,43 +68,6 @@ fun Context.getCurrentClip(): String? { return clipboardManager.primaryClip?.getItemAt(0)?.text?.toString() } -fun Context.getKeyboardBackgroundColor(): Int { - val color = if (isDynamicTheme()) { - resources.getColor(R.color.you_keyboard_background_color, theme) - } else { - getProperBackgroundColor().darkenColor(2) - } - - // use darker background color when key borders are enabled - if (config.showKeyBorders) { - val darkerColor = color.darkenColor(2) - return if (darkerColor == Color.WHITE) { - resources.getColor(R.color.md_grey_200, theme) - } else { - darkerColor - } - } - - return color -} - -fun Context.getStrokeColor(): Int { - return if (isDynamicTheme()) { - if (isSystemInDarkMode()) { - resources.getColor(R.color.md_grey_800, theme) - } else { - resources.getColor(R.color.md_grey_400, theme) - } - } else { - val lighterColor = safeStorageContext.getProperBackgroundColor().lightenColor() - if (lighterColor == Color.WHITE || lighterColor == Color.BLACK) { - resources.getColor(R.color.divider_grey, theme) - } else { - lighterColor - } - } -} - fun Context.getKeyboardDialogBuilder() = if (safeStorageContext.isDynamicTheme()) { MaterialAlertDialogBuilder(this, R.style.MyKeyboard_Alert) } else { @@ -273,68 +189,9 @@ fun Context.setupKeyboardDialogStuff( } } -fun Context.getKeyboardLanguagesRadioItems(): ArrayList { - val selectedLanguagesRadioItems = arrayListOf() - - for (lang in config.selectedLanguages) { - selectedLanguagesRadioItems.add(RadioItem(lang, getKeyboardLanguageText(lang))) - } - - return selectedLanguagesRadioItems - .sortedBy { it.title } - .toMutableList() as ArrayList -} - -fun Context.getKeyboardLanguageText(language: Int): String { - return when (language) { - LANGUAGE_ARABIC -> getString(R.string.translation_arabic) - LANGUAGE_BELARUSIAN_CYRL -> "${getString(R.string.translation_belarusian)} (Cyrillic)" - LANGUAGE_BELARUSIAN_LATN -> "${getString(R.string.translation_belarusian)} (Latin)" - LANGUAGE_BENGALI -> getString(R.string.translation_bengali) - LANGUAGE_BULGARIAN -> getString(R.string.translation_bulgarian) - LANGUAGE_CENTRAL_KURDISH -> getString(R.string.translation_central_kurdish) - LANGUAGE_CHUVASH -> getString(R.string.translation_chuvash) - LANGUAGE_CZECH_QWERTY -> "${getString(R.string.translation_czech)} (QWERTY)" - LANGUAGE_CZECH_QWERTZ -> "${getString(R.string.translation_czech)} (QWERTZ)" - LANGUAGE_DANISH -> getString(R.string.translation_danish) - LANGUAGE_DUTCH -> getString(R.string.translation_dutch) - LANGUAGE_ENGLISH_ASSET -> "${getString(R.string.translation_english)} (Asset)" - LANGUAGE_ENGLISH_COLEMAK -> "${getString(R.string.translation_english)} (Colemak)" - LANGUAGE_ENGLISH_COLEMAKDH -> "${getString(R.string.translation_english)} (Colemak-DH)" - LANGUAGE_ENGLISH_DVORAK -> "${getString(R.string.translation_english)} (DVORAK)" - LANGUAGE_ENGLISH_NIRO -> "${getString(R.string.translation_english)} (Niro)" - LANGUAGE_ENGLISH_QWERTZ -> "${getString(R.string.translation_english)} (QWERTZ)" - LANGUAGE_ENGLISH_SOUL -> "${getString(R.string.translation_english)} (Soul)" - LANGUAGE_ENGLISH_WORKMAN -> "${getString(R.string.translation_english)} (Workman)" - LANGUAGE_ESPERANTO -> getString(R.string.translation_esperanto) - LANGUAGE_FRENCH_AZERTY -> "${getString(R.string.translation_french)} (AZERTY)" - LANGUAGE_FRENCH_BEPO -> "${getString(R.string.translation_french)} (BEPO)" - LANGUAGE_GERMAN -> getString(R.string.translation_german) - LANGUAGE_GERMAN_QWERTZ -> "${getString(R.string.translation_german)} (QWERTZ)" - LANGUAGE_GREEK -> getString(R.string.translation_greek) - LANGUAGE_HEBREW -> getString(R.string.translation_hebrew) - LANGUAGE_ITALIAN -> getString(R.string.translation_italian) - LANGUAGE_KABYLE_AZERTY -> "${getString(R.string.translation_kabyle)} (AZERTY)" - LANGUAGE_LATVIAN -> getString(R.string.translation_latvian) - LANGUAGE_LITHUANIAN -> getString(R.string.translation_lithuanian) - LANGUAGE_NORWEGIAN -> getString(R.string.translation_norwegian) - LANGUAGE_POLISH -> getString(R.string.translation_polish) - LANGUAGE_PORTUGUESE -> getString(R.string.translation_portuguese) - LANGUAGE_PORTUGUESE_HCESAR -> "${getString(R.string.translation_portuguese)} (HCESAR)" - LANGUAGE_ROMANIAN -> getString(R.string.translation_romanian) - LANGUAGE_RUSSIAN -> getString(R.string.translation_russian) - LANGUAGE_SLOVENIAN -> getString(R.string.translation_slovenian) - LANGUAGE_SPANISH -> getString(R.string.translation_spanish) - LANGUAGE_SWEDISH -> getString(R.string.translation_swedish) - LANGUAGE_TURKISH -> getString(R.string.translation_turkish) - LANGUAGE_TURKISH_Q -> "${getString(R.string.translation_turkish)} (Q)" - LANGUAGE_UKRAINIAN -> getString(R.string.translation_ukrainian) - LANGUAGE_VIETNAMESE_TELEX -> "${getString(R.string.translation_vietnamese)} (Telex)" - else -> "${getString(R.string.translation_english)} (QWERTY)" - } -} - -fun Context.getVoiceInputMethods(imm: InputMethodManager = inputMethodManager): List> { +fun Context.getVoiceInputMethods( + imm: InputMethodManager = inputMethodManager +): List> { return imm.enabledInputMethodList.flatMap { im -> imm.getEnabledInputMethodSubtypeList(im, true) .filter { it.mode == INPUT_METHOD_SUBTYPE_VOICE } diff --git a/app/src/main/kotlin/org/fossify/keyboard/extensions/KeyboardLanguageExt.kt b/app/src/main/kotlin/org/fossify/keyboard/extensions/KeyboardLanguageExt.kt new file mode 100644 index 00000000..d7aa20cf --- /dev/null +++ b/app/src/main/kotlin/org/fossify/keyboard/extensions/KeyboardLanguageExt.kt @@ -0,0 +1,112 @@ +package org.fossify.keyboard.extensions + +import android.annotation.SuppressLint +import android.content.Context +import org.fossify.commons.models.RadioItem +import org.fossify.keyboard.R +import org.fossify.keyboard.helpers.LANGUAGE_ARABIC +import org.fossify.keyboard.helpers.LANGUAGE_BELARUSIAN_CYRL +import org.fossify.keyboard.helpers.LANGUAGE_BELARUSIAN_LATN +import org.fossify.keyboard.helpers.LANGUAGE_BENGALI +import org.fossify.keyboard.helpers.LANGUAGE_BULGARIAN +import org.fossify.keyboard.helpers.LANGUAGE_CENTRAL_KURDISH +import org.fossify.keyboard.helpers.LANGUAGE_CHUVASH +import org.fossify.keyboard.helpers.LANGUAGE_CZECH_QWERTY +import org.fossify.keyboard.helpers.LANGUAGE_CZECH_QWERTZ +import org.fossify.keyboard.helpers.LANGUAGE_DANISH +import org.fossify.keyboard.helpers.LANGUAGE_DUTCH +import org.fossify.keyboard.helpers.LANGUAGE_ENGLISH_ASSET +import org.fossify.keyboard.helpers.LANGUAGE_ENGLISH_COLEMAK +import org.fossify.keyboard.helpers.LANGUAGE_ENGLISH_COLEMAKDH +import org.fossify.keyboard.helpers.LANGUAGE_ENGLISH_DVORAK +import org.fossify.keyboard.helpers.LANGUAGE_ENGLISH_NIRO +import org.fossify.keyboard.helpers.LANGUAGE_ENGLISH_QWERTZ +import org.fossify.keyboard.helpers.LANGUAGE_ENGLISH_SOUL +import org.fossify.keyboard.helpers.LANGUAGE_ENGLISH_WORKMAN +import org.fossify.keyboard.helpers.LANGUAGE_ESPERANTO +import org.fossify.keyboard.helpers.LANGUAGE_FRENCH_AZERTY +import org.fossify.keyboard.helpers.LANGUAGE_FRENCH_BEPO +import org.fossify.keyboard.helpers.LANGUAGE_GERMAN +import org.fossify.keyboard.helpers.LANGUAGE_GERMAN_QWERTZ +import org.fossify.keyboard.helpers.LANGUAGE_GREEK +import org.fossify.keyboard.helpers.LANGUAGE_HEBREW +import org.fossify.keyboard.helpers.LANGUAGE_ITALIAN +import org.fossify.keyboard.helpers.LANGUAGE_KABYLE_AZERTY +import org.fossify.keyboard.helpers.LANGUAGE_LATVIAN +import org.fossify.keyboard.helpers.LANGUAGE_LITHUANIAN +import org.fossify.keyboard.helpers.LANGUAGE_NORWEGIAN +import org.fossify.keyboard.helpers.LANGUAGE_POLISH +import org.fossify.keyboard.helpers.LANGUAGE_PORTUGUESE +import org.fossify.keyboard.helpers.LANGUAGE_PORTUGUESE_HCESAR +import org.fossify.keyboard.helpers.LANGUAGE_ROMANIAN +import org.fossify.keyboard.helpers.LANGUAGE_RUSSIAN +import org.fossify.keyboard.helpers.LANGUAGE_SLOVENIAN +import org.fossify.keyboard.helpers.LANGUAGE_SPANISH +import org.fossify.keyboard.helpers.LANGUAGE_SWEDISH +import org.fossify.keyboard.helpers.LANGUAGE_TURKISH +import org.fossify.keyboard.helpers.LANGUAGE_TURKISH_Q +import org.fossify.keyboard.helpers.LANGUAGE_UKRAINIAN +import org.fossify.keyboard.helpers.LANGUAGE_VIETNAMESE_TELEX + +fun Context.getSelectedLanguagesSorted(): List { + return config.selectedLanguages + .map { it to getKeyboardLanguageText(it) } + .sortedBy { it.second } + .map { it.first } +} + +fun Context.getKeyboardLanguagesRadioItems(): ArrayList { + return getSelectedLanguagesSorted() + .map { RadioItem(it, getKeyboardLanguageText(it)) } + .toMutableList() as ArrayList +} + +@Suppress("CyclomaticComplexMethod") +fun Context.getKeyboardLanguageText(language: Int): String { + return when (language) { + LANGUAGE_ARABIC -> getString(R.string.translation_arabic) + LANGUAGE_BELARUSIAN_CYRL -> "${getString(R.string.translation_belarusian)} (Cyrillic)" + LANGUAGE_BELARUSIAN_LATN -> "${getString(R.string.translation_belarusian)} (Latin)" + LANGUAGE_BENGALI -> getString(R.string.translation_bengali) + LANGUAGE_BULGARIAN -> getString(R.string.translation_bulgarian) + LANGUAGE_CENTRAL_KURDISH -> getString(R.string.translation_central_kurdish) + LANGUAGE_CHUVASH -> getString(R.string.translation_chuvash) + LANGUAGE_CZECH_QWERTY -> "${getString(R.string.translation_czech)} (QWERTY)" + LANGUAGE_CZECH_QWERTZ -> "${getString(R.string.translation_czech)} (QWERTZ)" + LANGUAGE_DANISH -> getString(R.string.translation_danish) + LANGUAGE_DUTCH -> getString(R.string.translation_dutch) + LANGUAGE_ENGLISH_ASSET -> "${getString(R.string.translation_english)} (Asset)" + LANGUAGE_ENGLISH_COLEMAK -> "${getString(R.string.translation_english)} (Colemak)" + LANGUAGE_ENGLISH_COLEMAKDH -> "${getString(R.string.translation_english)} (Colemak-DH)" + LANGUAGE_ENGLISH_DVORAK -> "${getString(R.string.translation_english)} (DVORAK)" + LANGUAGE_ENGLISH_NIRO -> "${getString(R.string.translation_english)} (Niro)" + LANGUAGE_ENGLISH_QWERTZ -> "${getString(R.string.translation_english)} (QWERTZ)" + LANGUAGE_ENGLISH_SOUL -> "${getString(R.string.translation_english)} (Soul)" + LANGUAGE_ENGLISH_WORKMAN -> "${getString(R.string.translation_english)} (Workman)" + LANGUAGE_ESPERANTO -> getString(R.string.translation_esperanto) + LANGUAGE_FRENCH_AZERTY -> "${getString(R.string.translation_french)} (AZERTY)" + LANGUAGE_FRENCH_BEPO -> "${getString(R.string.translation_french)} (BEPO)" + LANGUAGE_GERMAN -> getString(R.string.translation_german) + LANGUAGE_GERMAN_QWERTZ -> "${getString(R.string.translation_german)} (QWERTZ)" + LANGUAGE_GREEK -> getString(R.string.translation_greek) + LANGUAGE_HEBREW -> getString(R.string.translation_hebrew) + LANGUAGE_ITALIAN -> getString(R.string.translation_italian) + LANGUAGE_KABYLE_AZERTY -> "${getString(R.string.translation_kabyle)} (AZERTY)" + LANGUAGE_LATVIAN -> getString(R.string.translation_latvian) + LANGUAGE_LITHUANIAN -> getString(R.string.translation_lithuanian) + LANGUAGE_NORWEGIAN -> getString(R.string.translation_norwegian) + LANGUAGE_POLISH -> getString(R.string.translation_polish) + LANGUAGE_PORTUGUESE -> getString(R.string.translation_portuguese) + LANGUAGE_PORTUGUESE_HCESAR -> "${getString(R.string.translation_portuguese)} (HCESAR)" + LANGUAGE_ROMANIAN -> getString(R.string.translation_romanian) + LANGUAGE_RUSSIAN -> getString(R.string.translation_russian) + LANGUAGE_SLOVENIAN -> getString(R.string.translation_slovenian) + LANGUAGE_SPANISH -> getString(R.string.translation_spanish) + LANGUAGE_SWEDISH -> getString(R.string.translation_swedish) + LANGUAGE_TURKISH -> getString(R.string.translation_turkish) + LANGUAGE_TURKISH_Q -> "${getString(R.string.translation_turkish)} (Q)" + LANGUAGE_UKRAINIAN -> getString(R.string.translation_ukrainian) + LANGUAGE_VIETNAMESE_TELEX -> "${getString(R.string.translation_vietnamese)} (Telex)" + else -> "${getString(R.string.translation_english)} (QWERTY)" + } +} diff --git a/app/src/main/kotlin/org/fossify/keyboard/extensions/KeyboardThemeExt.kt b/app/src/main/kotlin/org/fossify/keyboard/extensions/KeyboardThemeExt.kt new file mode 100644 index 00000000..3a0abb89 --- /dev/null +++ b/app/src/main/kotlin/org/fossify/keyboard/extensions/KeyboardThemeExt.kt @@ -0,0 +1,47 @@ +package org.fossify.keyboard.extensions + +import android.content.Context +import android.graphics.Color +import org.fossify.commons.extensions.darkenColor +import org.fossify.commons.extensions.getProperBackgroundColor +import org.fossify.commons.extensions.isDynamicTheme +import org.fossify.commons.extensions.isSystemInDarkMode +import org.fossify.commons.extensions.lightenColor +import org.fossify.keyboard.R + +fun Context.getKeyboardBackgroundColor(): Int { + val color = if (isDynamicTheme()) { + resources.getColor(R.color.you_keyboard_background_color, theme) + } else { + getProperBackgroundColor().darkenColor(2) + } + + // use darker background color when key borders are enabled + if (config.showKeyBorders) { + val darkerColor = color.darkenColor(2) + return if (darkerColor == Color.WHITE) { + resources.getColor(R.color.md_grey_200, theme) + } else { + darkerColor + } + } + + return color +} + +fun Context.getStrokeColor(): Int { + return if (isDynamicTheme()) { + if (isSystemInDarkMode()) { + resources.getColor(R.color.md_grey_800, theme) + } else { + resources.getColor(R.color.md_grey_400, theme) + } + } else { + val lighterColor = safeStorageContext.getProperBackgroundColor().lightenColor() + if (lighterColor == Color.WHITE || lighterColor == Color.BLACK) { + resources.getColor(R.color.divider_grey, theme) + } else { + lighterColor + } + } +} diff --git a/app/src/main/kotlin/org/fossify/keyboard/helpers/Config.kt b/app/src/main/kotlin/org/fossify/keyboard/helpers/Config.kt index 9d5499e4..58b8f510 100644 --- a/app/src/main/kotlin/org/fossify/keyboard/helpers/Config.kt +++ b/app/src/main/kotlin/org/fossify/keyboard/helpers/Config.kt @@ -27,6 +27,10 @@ class Config(context: Context) : BaseConfig(context) { get() = prefs.getBoolean(SHOW_EMOJI_KEY, true) set(showEmojiKey) = prefs.edit().putBoolean(SHOW_EMOJI_KEY, showEmojiKey).apply() + var showLanguageSwitchKey: Boolean + get() = prefs.getBoolean(SHOW_LANGUAGE_SWITCH_KEY, false) + set(showLanguageSwitchKey) = prefs.edit().putBoolean(SHOW_LANGUAGE_SWITCH_KEY, showLanguageSwitchKey).apply() + var showKeyBorders: Boolean get() = prefs.getBoolean(SHOW_KEY_BORDERS, true) set(showKeyBorders) = prefs.edit().putBoolean(SHOW_KEY_BORDERS, showKeyBorders).apply() diff --git a/app/src/main/kotlin/org/fossify/keyboard/helpers/Constants.kt b/app/src/main/kotlin/org/fossify/keyboard/helpers/Constants.kt index dfa1c6ea..b60629ec 100644 --- a/app/src/main/kotlin/org/fossify/keyboard/helpers/Constants.kt +++ b/app/src/main/kotlin/org/fossify/keyboard/helpers/Constants.kt @@ -16,6 +16,7 @@ const val SHOW_POPUP_ON_KEYPRESS = "show_popup_on_keypress" const val SHOW_KEY_BORDERS = "show_key_borders" const val SENTENCES_CAPITALIZATION = "sentences_capitalization" const val SHOW_EMOJI_KEY = "show_emoji_key" +const val SHOW_LANGUAGE_SWITCH_KEY = "show_language_switch_key" const val LAST_EXPORTED_CLIPS_FOLDER = "last_exported_clips_folder" const val KEYBOARD_LANGUAGE = "keyboard_language" const val HEIGHT_PERCENTAGE = "height_percentage" diff --git a/app/src/main/kotlin/org/fossify/keyboard/helpers/MyKeyboard.kt b/app/src/main/kotlin/org/fossify/keyboard/helpers/MyKeyboard.kt index 0e85f200..592e7d30 100644 --- a/app/src/main/kotlin/org/fossify/keyboard/helpers/MyKeyboard.kt +++ b/app/src/main/kotlin/org/fossify/keyboard/helpers/MyKeyboard.kt @@ -66,7 +66,7 @@ class MyKeyboard { const val KEYCODE_ENTER = -4 const val KEYCODE_DELETE = -5 const val KEYCODE_SPACE = 32 - const val KEYCODE_EMOJI = -6 + const val KEYCODE_EMOJI_OR_LANGUAGE = -6 fun getDimensionOrFraction(a: TypedArray, index: Int, base: Int, defValue: Int): Int { val value = a.peekValue(index) ?: return defValue @@ -237,7 +237,9 @@ class MyKeyboard { KEYCODE_ENTER -> context.getString(R.string.keycode_enter) KEYCODE_DELETE -> context.getString(R.string.keycode_delete) KEYCODE_SPACE -> context.getString(R.string.keycode_space) - KEYCODE_EMOJI -> context.getString(R.string.emojis) + KEYCODE_EMOJI_OR_LANGUAGE -> context.getString( + if (context.config.showEmojiKey) R.string.emojis else R.string.keyboard_language + ) else -> label } } diff --git a/app/src/main/kotlin/org/fossify/keyboard/services/SimpleKeyboardIME.kt b/app/src/main/kotlin/org/fossify/keyboard/services/SimpleKeyboardIME.kt index e46d3e74..02b2cee9 100644 --- a/app/src/main/kotlin/org/fossify/keyboard/services/SimpleKeyboardIME.kt +++ b/app/src/main/kotlin/org/fossify/keyboard/services/SimpleKeyboardIME.kt @@ -28,6 +28,7 @@ import androidx.autofill.inline.common.ImageViewStyle import androidx.autofill.inline.common.TextViewStyle import androidx.autofill.inline.common.ViewStyle import androidx.autofill.inline.v1.InlineSuggestionUi +import androidx.core.content.res.ResourcesCompat import androidx.core.graphics.drawable.toBitmap import androidx.core.view.ViewCompat import androidx.core.view.WindowCompat @@ -39,6 +40,8 @@ import org.fossify.keyboard.R import org.fossify.keyboard.databinding.KeyboardViewKeyboardBinding import org.fossify.keyboard.extensions.config import org.fossify.keyboard.extensions.getKeyboardBackgroundColor +import org.fossify.keyboard.extensions.getKeyboardLanguageText +import org.fossify.keyboard.extensions.getSelectedLanguagesSorted import org.fossify.keyboard.extensions.getStrokeColor import org.fossify.keyboard.extensions.safeStorageContext import org.fossify.keyboard.helpers.* @@ -251,8 +254,18 @@ class SimpleKeyboardIME : InputMethodService(), OnKeyboardActionListener, Shared keyboardView!!.setKeyboard(keyboard!!) } - MyKeyboard.KEYCODE_EMOJI -> { - keyboardView?.openEmojiPalette() + MyKeyboard.KEYCODE_EMOJI_OR_LANGUAGE -> { + if (config.showEmojiKey) { + keyboardView?.openEmojiPalette() + } else if (config.showLanguageSwitchKey) { + val sortedLanguages = getSelectedLanguagesSorted() + if (sortedLanguages.size > 1) { + val currentIndex = sortedLanguages.indexOf(config.keyboardLanguage) + val nextIndex = (currentIndex + 1) % sortedLanguages.size + config.keyboardLanguage = sortedLanguages[nextIndex] + reloadKeyboard() + } + } } else -> { @@ -581,30 +594,47 @@ class SimpleKeyboardIME : InputMethodService(), OnKeyboardActionListener, Shared return Icon.createWithData(byteArray, 0, byteArray.size) } - private fun adjustForEmojiButton(keyboard: MyKeyboard): MyKeyboard { - if (!config.showEmojiKey && this.keyboardMode == KEYBOARD_LETTERS) { - keyboard.mKeys?.let { keys -> - val emojiKeyIndex = keys.indexOfFirst { it.code == MyKeyboard.KEYCODE_EMOJI } - val spaceKeyIndex = keys.indexOfFirst { it.code == MyKeyboard.KEYCODE_SPACE } - - if (emojiKeyIndex != -1 && spaceKeyIndex != -1) { - val emojiKey = keys[emojiKeyIndex] - val spaceKey = keys[spaceKeyIndex] + private fun constructKeyboard(keyboardXml: Int, enterKeyType: Int): MyKeyboard { + val keyboard = MyKeyboard(this, keyboardXml, enterKeyType) + return adjustBottomRow(keyboard) + } - spaceKey.width += emojiKey.width + emojiKey.gap - spaceKey.x = emojiKey.x + // hacky, but good enough for now + private fun adjustBottomRow(keyboard: MyKeyboard): MyKeyboard { + keyboard.mKeys?.let { keys -> + val spaceKeyIndex = keys.indexOfFirst { it.code == MyKeyboard.KEYCODE_SPACE } + if (spaceKeyIndex != -1) { + val spaceKey = keys[spaceKeyIndex] + spaceKey.label = spaceKey.label.ifEmpty { + getKeyboardLanguageText(config.keyboardLanguage) + } + } - val mutableKeys = keys.toMutableList() - mutableKeys.removeAt(emojiKeyIndex) - keyboard.mKeys = mutableKeys + if (keyboardMode != KEYBOARD_LETTERS) return keyboard + val emojiKeyIndex = keys.indexOfFirst { it.code == MyKeyboard.KEYCODE_EMOJI_OR_LANGUAGE } + if (emojiKeyIndex != -1 && spaceKeyIndex != -1) { + val emojiKey = keys[emojiKeyIndex] + val spaceKey = keys[spaceKeyIndex] + emojiKey.secondaryIcon = null + when { + config.showEmojiKey -> { + // no-op + } + config.showLanguageSwitchKey -> { + emojiKey.icon = ResourcesCompat.getDrawable(resources, R.drawable.ic_language_outlined, theme) + } + else -> { + // both emoji and language keys are disabled + spaceKey.width += emojiKey.width + emojiKey.gap + spaceKey.x = emojiKey.x + + val mutableKeys = keys.toMutableList() + mutableKeys.removeAt(emojiKeyIndex) + keyboard.mKeys = mutableKeys + } } } } return keyboard } - - private fun constructKeyboard(keyboardXml: Int, enterKeyType: Int): MyKeyboard { - val keyboard = MyKeyboard(this, keyboardXml, enterKeyType) - return adjustForEmojiButton(keyboard) - } } diff --git a/app/src/main/kotlin/org/fossify/keyboard/views/MyKeyboardView.kt b/app/src/main/kotlin/org/fossify/keyboard/views/MyKeyboardView.kt index 534bc7c7..1918e787 100644 --- a/app/src/main/kotlin/org/fossify/keyboard/views/MyKeyboardView.kt +++ b/app/src/main/kotlin/org/fossify/keyboard/views/MyKeyboardView.kt @@ -64,6 +64,7 @@ import org.fossify.commons.extensions.lightenColor import org.fossify.commons.extensions.performHapticFeedback import org.fossify.commons.extensions.removeUnderlines import org.fossify.commons.extensions.toast +import org.fossify.commons.helpers.HIGHER_ALPHA import org.fossify.commons.helpers.ensureBackgroundThread import org.fossify.commons.helpers.isOreoMr1Plus import org.fossify.commons.helpers.isPiePlus @@ -95,7 +96,7 @@ import org.fossify.keyboard.helpers.LANGUAGE_VN_TELEX import org.fossify.keyboard.helpers.MAX_KEYS_PER_MINI_ROW import org.fossify.keyboard.helpers.MyKeyboard import org.fossify.keyboard.helpers.MyKeyboard.Companion.KEYCODE_DELETE -import org.fossify.keyboard.helpers.MyKeyboard.Companion.KEYCODE_EMOJI +import org.fossify.keyboard.helpers.MyKeyboard.Companion.KEYCODE_EMOJI_OR_LANGUAGE import org.fossify.keyboard.helpers.MyKeyboard.Companion.KEYCODE_ENTER import org.fossify.keyboard.helpers.MyKeyboard.Companion.KEYCODE_MODE_CHANGE import org.fossify.keyboard.helpers.MyKeyboard.Companion.KEYCODE_SHIFT @@ -140,6 +141,7 @@ class MyKeyboardView @JvmOverloads constructor( private var mLabelTextSize = 0 private var mKeyTextSize = 0 + private var mSpaceBarTextSize = 0 private var mTextColor = 0 private var mBackgroundColor = 0 @@ -190,7 +192,7 @@ class MyKeyboardView @JvmOverloads constructor( private var mRepeatKeyIndex = NOT_A_KEY private var mPopupLayout = 0 private var mAbortKey = false - private var mIsLongPressingSpace = false + private var mCursorControlActive = false private var mLastSpaceMoveX = 0 private var mPopupMaxMoveDistance = 0f private var mTopSmallNumberSize = 0f @@ -264,6 +266,7 @@ class MyKeyboardView @JvmOverloads constructor( mKeyBackground = resources.getDrawable(R.drawable.keyboard_key_selector, context.theme) mVerticalCorrection = resources.getDimension(R.dimen.vertical_correction).toInt() mLabelTextSize = resources.getDimension(R.dimen.label_text_size).toInt() + mSpaceBarTextSize = resources.getDimension(R.dimen.space_bar_text_size).toInt() mPreviewHeight = resources.getDimension(R.dimen.key_height).toInt() mSpaceMoveThreshold = resources.getDimension(R.dimen.medium_margin).toInt() @@ -305,7 +308,7 @@ class MyKeyboardView @JvmOverloads constructor( override fun handleMessage(msg: Message) { when (msg.what) { MSG_REMOVE_PREVIEW -> mPreviewText!!.visibility = INVISIBLE - MSG_REPEAT -> if (repeatKey(false)) { + MSG_REPEAT -> if (repeatKey()) { val repeat = Message.obtain(this, MSG_REPEAT) sendMessageDelayed(repeat, REPEAT_INTERVAL.toLong()) } @@ -685,19 +688,23 @@ class MyKeyboardView @JvmOverloads constructor( for (i in 0 until keyCount) { val key = keys[i] val code = key.code + val label = adjustCase(key.label)?.toString() setupKeyBackground(key, code, canvas) - val textColor = if (key.pressed) { - mTextColor.adjustAlpha(0.5f) - } else { - mTextColor + val textColor = when { + key.pressed -> mTextColor.adjustAlpha(0.5f) + code == KEYCODE_SPACE && label.orEmpty().length > 1 -> mTextColor.adjustAlpha(HIGHER_ALPHA) + else -> mTextColor } // Switch the character to uppercase if shift is pressed - val label = adjustCase(key.label)?.toString() if (label?.isNotEmpty() == true) { // For characters, use large font. For labels like "Done", use small font. - if (label.length > 1) { + if (code == KEYCODE_SPACE && key.label.length > 1) { + // Use smaller font size for current language label on space bar + paint.textSize = mSpaceBarTextSize.toFloat() + paint.typeface = Typeface.DEFAULT + } else if (label.length > 1) { paint.textSize = mLabelTextSize.toFloat() paint.typeface = Typeface.DEFAULT_BOLD } else { @@ -758,7 +765,7 @@ class MyKeyboardView @JvmOverloads constructor( val contrastColor = mPrimaryColor.getContrastColor() key.icon!!.applyColorFilter(contrastColor) key.secondaryIcon?.applyColorFilter(contrastColor.adjustAlpha(0.6f)) - } else if (code == KEYCODE_DELETE || code == KEYCODE_SHIFT || code == KEYCODE_EMOJI) { + } else if (code == KEYCODE_DELETE || code == KEYCODE_SHIFT || code == KEYCODE_EMOJI_OR_LANGUAGE) { key.icon!!.applyColorFilter(textColor) key.secondaryIcon?.applyColorFilter( if (key.pressed) { @@ -830,7 +837,7 @@ class MyKeyboardView @JvmOverloads constructor( private fun setupKeyBackground(key: MyKeyboard.Key, keyCode: Int, canvas: Canvas) { val keyBackground = when { - keyCode == KEYCODE_SPACE && key.label.isBlank() -> getSpaceKeyBackground() + keyCode == KEYCODE_SPACE && key.label.length > 1 -> getSpaceKeyBackground() keyCode == KEYCODE_ENTER -> getEnterKeyBackground() else -> mKeyBackground } @@ -1019,6 +1026,7 @@ class MyKeyboardView @JvmOverloads constructor( } val key = keys[keyIndex] + if (key.code == KEYCODE_SPACE) return // no popup for the language label if (key.icon != null) { mPreviewText!!.setCompoundDrawables(null, null, null, key.icon) } else { @@ -1169,10 +1177,25 @@ class MyKeyboardView @JvmOverloads constructor( * handle the call. */ private fun onLongPress(popupKey: MyKeyboard.Key, me: MotionEvent): Boolean { - if (popupKey.code == KEYCODE_EMOJI) { + if (popupKey.code == KEYCODE_SPACE) { + return if (!mCursorControlActive) { + setCurrentKeyPressed(false) + mRepeatKeyIndex = NOT_A_KEY + mHandler?.removeMessages(MSG_REPEAT) + vibrateIfNeeded() + SwitchLanguageDialog(this) { + mOnKeyboardActionListener?.reloadKeyboard() + } + true + } else false + } else if (popupKey.code == KEYCODE_EMOJI_OR_LANGUAGE) { setCurrentKeyPressed(false) - SwitchLanguageDialog(this) { - mOnKeyboardActionListener?.reloadKeyboard() + if (context.config.showEmojiKey) { + openEmojiPalette() + } else { + SwitchLanguageDialog(this) { + mOnKeyboardActionListener?.reloadKeyboard() + } } return true } else { @@ -1415,11 +1438,12 @@ class MyKeyboardView @JvmOverloads constructor( val msg = mHandler!!.obtainMessage(MSG_REPEAT) mHandler!!.sendMessageDelayed(msg, REPEAT_START_DELAY.toLong()) - // if the user long presses Space, move the cursor after swipine left/right + // if the user long presses space bar, move the cursor after swiping left/right if (mKeys[mCurrentKey].code == KEYCODE_SPACE) { mLastSpaceMoveX = -1 + mCursorControlActive = false } else { - repeatKey(true) + repeatKey() } // Delivering the key could have caused an abort @@ -1463,7 +1487,9 @@ class MyKeyboardView @JvmOverloads constructor( } } - if (mIsLongPressingSpace) { + // activate cursor control immediately on sufficient movement + val currentKey = mKeys.getOrNull(mCurrentKey) + if (currentKey?.code == KEYCODE_SPACE && mLastSpaceMoveX != 0) { if (mLastSpaceMoveX == -1) { mLastSpaceMoveX = mLastX } @@ -1474,16 +1500,20 @@ class MyKeyboardView @JvmOverloads constructor( mOnKeyboardActionListener?.moveCursorLeft() } mLastSpaceMoveX = mLastX + if (!mCursorControlActive) mHandler?.removeMessages(MSG_LONGPRESS) + mCursorControlActive = true } else if (diff > mSpaceMoveThreshold) { for (i in 0 until diff / mSpaceMoveThreshold) { mOnKeyboardActionListener?.moveCursorRight() } mLastSpaceMoveX = mLastX + if (!mCursorControlActive) mHandler?.removeMessages(MSG_LONGPRESS) + mCursorControlActive = true } } else if (!continueLongPress) { - // Cancel old longpress + // Cancel old long-press mHandler!!.removeMessages(MSG_LONGPRESS) - // Start new longpress if key has changed + // Start new long-press if key has changed if (keyIndex != NOT_A_KEY) { val msg = mHandler!!.obtainMessage(MSG_LONGPRESS, me) mHandler!!.sendMessageDelayed(msg, LONGPRESS_TIMEOUT.toLong()) @@ -1523,17 +1553,17 @@ class MyKeyboardView @JvmOverloads constructor( // If we're not on a repeating key (which sends on a DOWN event) if (mRepeatKeyIndex == NOT_A_KEY && !mMiniKeyboardOnScreen && !mAbortKey) { detectAndSendKey(mCurrentKey, touchX, touchY, eventTime) - } else if (currentKeyCode == KEYCODE_SPACE && !mIsLongPressingSpace) { + } else if (currentKeyCode == KEYCODE_SPACE && !mCursorControlActive) { detectAndSendKey(mCurrentKey, touchX, touchY, eventTime) } mRepeatKeyIndex = NOT_A_KEY mOnKeyboardActionListener!!.onActionUp() - mIsLongPressingSpace = false + mCursorControlActive = false } MotionEvent.ACTION_CANCEL -> { - mIsLongPressingSpace = false + mCursorControlActive = false mLastSpaceMoveX = 0 removeMessages() dismissPopupKeyboard() @@ -1548,15 +1578,9 @@ class MyKeyboardView @JvmOverloads constructor( return true } - private fun repeatKey(initialCall: Boolean): Boolean { + private fun repeatKey(): Boolean { val key = mKeys[mRepeatKeyIndex] - if (!initialCall && key.code == KEYCODE_SPACE) { - if (!mIsLongPressingSpace) { - vibrateIfNeeded() - } - - mIsLongPressingSpace = true - } else { + if (key.code != KEYCODE_SPACE) { detectAndSendKey(mCurrentKey, key.x, key.y, mLastTapTime) } return true diff --git a/app/src/main/res/drawable-v31/keyboard_space_background_material.xml b/app/src/main/res/drawable-v31/keyboard_space_background_material.xml index 64f29b9b..91b55f81 100644 --- a/app/src/main/res/drawable-v31/keyboard_space_background_material.xml +++ b/app/src/main/res/drawable-v31/keyboard_space_background_material.xml @@ -2,20 +2,20 @@ - + - + - + - + diff --git a/app/src/main/res/drawable/keyboard_enter_background.xml b/app/src/main/res/drawable/keyboard_enter_background.xml index 2be68134..23e3f1ed 100644 --- a/app/src/main/res/drawable/keyboard_enter_background.xml +++ b/app/src/main/res/drawable/keyboard_enter_background.xml @@ -2,13 +2,13 @@ + android:bottom="@dimen/medium_margin" + android:left="@dimen/tiny_margin" + android:right="@dimen/tiny_margin" + android:top="@dimen/medium_margin"> - + diff --git a/app/src/main/res/drawable/keyboard_space_background.xml b/app/src/main/res/drawable/keyboard_space_background.xml index 1953af34..6bd13adb 100644 --- a/app/src/main/res/drawable/keyboard_space_background.xml +++ b/app/src/main/res/drawable/keyboard_space_background.xml @@ -2,20 +2,20 @@ - + - + - + - + diff --git a/app/src/main/res/layout/activity_settings.xml b/app/src/main/res/layout/activity_settings.xml index 82850b41..80e300b1 100644 --- a/app/src/main/res/layout/activity_settings.xml +++ b/app/src/main/res/layout/activity_settings.xml @@ -252,6 +252,21 @@ + + + + + + 16sp 30sp 13sp + 13sp diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 10499b1d..70541f0d 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -37,6 +37,7 @@ Show numbers on a separate row Start sentences with a capital letter Show emoji key + Show language switch key Emojis Recently used