From 5ce9e09f7dd8985a3279570a1c5be8dbf0f80bea Mon Sep 17 00:00:00 2001 From: Helium314 Date: Thu, 15 Feb 2024 11:13:42 +0100 Subject: [PATCH 01/40] update readme and description --- README.md | 5 +++++ .../java/helium314/keyboard/latin/inputlogic/InputLogic.java | 3 +-- fastlane/metadata/android/en-US/full_description.txt | 2 ++ 3 files changed, 8 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 3b9447d7f..01ee3e243 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,6 @@ # HeliBoard HeliBoard is a privacy-conscious and customizable open-source keyboard, based on AOSP / OpenBoard. +Does not use internet permission, and thus is 100% offline. ## Table of Contents @@ -40,6 +41,10 @@ HeliBoard is a privacy-conscious and customizable open-source keyboard, based on * __No suggestions for some language__: Check [dictionaries repo](https://codeberg.org/Helium314/aosp-dictionaries) whether a dictionary is available. If there is one, download it and add it in the language settings for this language. * __No suggestions in some app / text field__: This app respects the [no suggestions flag](https://developer.android.com/reference/android/text/InputType#TYPE_TEXT_FLAG_NO_SUGGESTIONS) set by some input fields, i.e. the developer does not want you to see suggestions here. Best do in issue report for that app if you think this behavior is wrong. Alternatively you can enable the _always show suggestions_ setting that overrides the _no suggestions_ flag. * __How to enable glide typing__: There is no glide typing built into this app, but you can load compatible libraries: Go to advanced settings -> _load gesture typing library_ and point to a file. You can extract the file from GApps packages ("_swypelibs_"), or download one [here](https://github.com/erkserkserks/openboard/tree/master/app/src/main/jniLibs). Make sure to use the correct version (app will tell you in the dialog to load the library). +* __What is the _nouserlib_ version?__: The normal version (_release_) allows the user to provide a library for glide typing. Running code that isn't supplied with the app is _dynamic code loading_, which is a security risk. Android Studio warns about this: + > Dynamically loading code from locations other than the application's library directory or the Android platform's built-in library directories is dangerous, as there is an increased risk that the code could have been tampered with. Applications should use loadLibrary when possible, which provides increased assurance that libraries are loaded from one of these safer locations. Application developers should use the features of their development environment to place application native libraries into the lib directory of their compiled APKs. + + The app checks the SHA256 checksum of the library and warns the user if it doesn't match with known library versions. A mismatch indicates the library was modified, but may also occur if the user intentionally provides a different library than expected (e.g. a self-built variant). * (_to be expanded_...) ## Hidden Functionality diff --git a/app/src/main/java/helium314/keyboard/latin/inputlogic/InputLogic.java b/app/src/main/java/helium314/keyboard/latin/inputlogic/InputLogic.java index 4829f0992..1f548cbf7 100644 --- a/app/src/main/java/helium314/keyboard/latin/inputlogic/InputLogic.java +++ b/app/src/main/java/helium314/keyboard/latin/inputlogic/InputLogic.java @@ -1253,13 +1253,12 @@ private void handleBackspaceEvent(final Event event, final InputTransaction inpu // TODO: Add a new StatsUtils method onBackspaceWhenNoText() return; } - final int lengthToDelete = - Character.isSupplementaryCodePoint(codePointBeforeCursor) ? 2 : 1; if (StringUtils.mightBeEmoji(codePointBeforeCursor)) { // emoji length varies, so we'd need to find out length to delete correctly // the solution is not optimal, but a reasonable workaround for issues when trying to delete emojis sendDownUpKeyEvent(KeyEvent.KEYCODE_DEL); } else { + final int lengthToDelete = Character.isSupplementaryCodePoint(codePointBeforeCursor) ? 2 : 1; mConnection.deleteTextBeforeCursor(lengthToDelete); int totalDeletedLength = lengthToDelete; if (mDeleteCount > Constants.DELETE_ACCELERATE_AT) { diff --git a/fastlane/metadata/android/en-US/full_description.txt b/fastlane/metadata/android/en-US/full_description.txt index d3ad0bde2..7cd968c0e 100644 --- a/fastlane/metadata/android/en-US/full_description.txt +++ b/fastlane/metadata/android/en-US/full_description.txt @@ -1,6 +1,8 @@ HeliBoard is a privacy-conscious open-source keyboard, based on AOSP / OpenBoard. +Does not use internet permission, and thus is 100% offline. Features: + - Add your own dictionaries for suggestions and spell check - Customizable themes and background - Customizable layouts From 27259ac376799d8729389edb47a7c79eea9e0915 Mon Sep 17 00:00:00 2001 From: Helium314 Date: Thu, 15 Feb 2024 11:53:01 +0100 Subject: [PATCH 02/40] update readme and pr template --- .github/PULL_REQUEST_TEMPLATE.md | 4 ++-- README.md | 3 ++- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md index e5e704f8a..f18e2fc8e 100644 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -1,6 +1,6 @@ diff --git a/README.md b/README.md index 01ee3e243..ee8a8b35e 100644 --- a/README.md +++ b/README.md @@ -30,6 +30,7 @@ Does not use internet permission, and thus is 100% offline. * library not included in the app, as there is no compatible open source library available * can be extracted from GApps packages ("_swypelibs_"), or downloaded [here](https://github.com/erkserkserks/openboard/tree/master/app/src/main/jniLibs) * if you are concerned about security implications of loading user-provides libraries, please use the _nouserlib_ build variant, which removes this option. If HeliBoard is installed as system app, and _swypelibs_ are available for the system, they will be used. + * If the app is installed as a system app and _swypelibs_ are available, glide typing will be available independent of the version. * Clipboard history * One-handed mode * Split keyboard (if the screen is large enough) @@ -117,7 +118,7 @@ In addition to previous elements, HeliBoard must stick to [F-Droid inclusion gui ### Adding Layouts -See [layouts.md](layouts.md) for how to add new layouts to the app. +See [layouts.md](layouts.md#adding-new-layouts--languages) for how to add new layouts to the app. ### Update Emojis From a0324b54d7ecd734161eea03216b82ea3f16d38e Mon Sep 17 00:00:00 2001 From: Helium314 Date: Thu, 15 Feb 2024 11:57:30 +0100 Subject: [PATCH 03/40] Update layouts.md --- layouts.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/layouts.md b/layouts.md index 2c93c0c61..cdd8a7dc3 100644 --- a/layouts.md +++ b/layouts.md @@ -32,7 +32,8 @@ If you want different key label and use text, set the label to [label]|[text], e * You need a layout file in one of the formats above, and add it to [layouts](app/src/main/assets/layouts) * Popup keys in the layout will be in the "Layout" popup key group. * Add a layout entry to [method.xml](app/src/main/res/xml/method.xml) - * `KeyboardLayoutSet` must be set to the name of your layout file (without file ending) + * `KeyboardLayoutSet` in `android:imeSubtypeExtraValue` must be set to the name of your layout file (without file ending) + * `android:subtypeId` must be set to a value that is unique in this file (please use the same length as for other layouts) * If you add a layout to an existing language, add a string with the layout name to use instead of `subtype_generic`. `%s` will be replaced with the language * If you add a new language, you might want to provide a [language_key_texts](/app/src/main/assets/language_key_texts) file * `[popup_keys]` section contains popup keys that are similar to the letter (like `a` and `ä` or `य` and `य़`) From b34ac45312ea74af71528b69a35aed6b98677b17 Mon Sep 17 00:00:00 2001 From: Helium314 Date: Thu, 15 Feb 2024 12:39:31 +0100 Subject: [PATCH 04/40] Update layouts.md --- layouts.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/layouts.md b/layouts.md index cdd8a7dc3..ecde9b3ed 100644 --- a/layouts.md +++ b/layouts.md @@ -30,11 +30,11 @@ If you want different key label and use text, set the label to [label]|[text], e ## Adding new layouts / languages * You need a layout file in one of the formats above, and add it to [layouts](app/src/main/assets/layouts) - * Popup keys in the layout will be in the "Layout" popup key group. -* Add a layout entry to [method.xml](app/src/main/res/xml/method.xml) + * Popup keys in the layout will be in the "_Layout_" popup key group. +* Add a layout entry to [`method.xml`](app/src/main/res/xml/method.xml) * `KeyboardLayoutSet` in `android:imeSubtypeExtraValue` must be set to the name of your layout file (without file ending) * `android:subtypeId` must be set to a value that is unique in this file (please use the same length as for other layouts) - * If you add a layout to an existing language, add a string with the layout name to use instead of `subtype_generic`. `%s` will be replaced with the language + * If you add a layout to an existing language, add a string with the layout name to use instead of `subtype_generic`. The new string should be added to default [`strings.xml`](/app/src/main/res/values/strings.xml), and optionally to other languages. `%s` will be replaced with the language. * If you add a new language, you might want to provide a [language_key_texts](/app/src/main/assets/language_key_texts) file * `[popup_keys]` section contains popup keys that are similar to the letter (like `a` and `ä` or `य` and `य़`) * Such forms should _not_ be in the layout. They will apply to all layouts of that language, even custom ones. From 759cb48e1ea8850a9e51a4d928473a617a96f1c6 Mon Sep 17 00:00:00 2001 From: Helium314 Date: Thu, 15 Feb 2024 16:32:25 +0100 Subject: [PATCH 05/40] update readme and do some more logging --- README.md | 2 +- .../main/java/helium314/keyboard/latin/utils/SubtypeSettings.kt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index ee8a8b35e..af5467922 100644 --- a/README.md +++ b/README.md @@ -18,7 +18,6 @@ Does not use internet permission, and thus is 100% offline. # Features * Add dictionaries for suggestions and spell check * build your own, or get them [here](https://codeberg.org/Helium314/aosp-dictionaries#dictionaries), or in the [experimental](https://codeberg.org/Helium314/aosp-dictionaries#experimental-dictionaries) section (quality may vary) - * add them in language settings (click on the language, then on `+` next to _dictionary_), or open the file in a file explorer * additional dictionaries for emojis or scientific symbols can be used to provide suggestions ("emoji search") * note that for Korean layouts, suggestions only work using [this dictionary](https://github.com/openboard-team/openboard/commit/83fca9533c03b9fecc009fc632577226bbd6301f), the tools in the dictionary repository are not able to create working dictionaries * Customize keyboard themes (style, colors and background image) @@ -38,6 +37,7 @@ Does not use internet permission, and thus is 100% offline. * Backup and restore your learned word / history data ## FAQ / Common Issues +* __Add a dictionary__: First download the dictionary file, e.g. from [here](https://codeberg.org/Helium314/aosp-dictionaries#dictionaries). Then go to language settings, click on the language, then on `+` next to _dictionary_ the _add_ and select the file. Alternatively you can open a `.dict` file in a file explorer with HeliBoard and then select the language. Note that the latter method does not work with all file explorers. * __Emoji search__: You can get addon dictionaries for emoji suggestions in the [dictionaries repo](https://codeberg.org/Helium314/aosp-dictionaries). An actual search funtion does not exist. * __No suggestions for some language__: Check [dictionaries repo](https://codeberg.org/Helium314/aosp-dictionaries) whether a dictionary is available. If there is one, download it and add it in the language settings for this language. * __No suggestions in some app / text field__: This app respects the [no suggestions flag](https://developer.android.com/reference/android/text/InputType#TYPE_TEXT_FLAG_NO_SUGGESTIONS) set by some input fields, i.e. the developer does not want you to see suggestions here. Best do in issue report for that app if you think this behavior is wrong. Alternatively you can enable the _always show suggestions_ setting that overrides the _no suggestions_ flag. diff --git a/app/src/main/java/helium314/keyboard/latin/utils/SubtypeSettings.kt b/app/src/main/java/helium314/keyboard/latin/utils/SubtypeSettings.kt index 8f46d0951..67c392865 100644 --- a/app/src/main/java/helium314/keyboard/latin/utils/SubtypeSettings.kt +++ b/app/src/main/java/helium314/keyboard/latin/utils/SubtypeSettings.kt @@ -195,7 +195,7 @@ private fun getDefaultEnabledSubtypes(): List { /** string for for identifying a subtype, does not contain all necessary information to actually create it */ private fun InputMethodSubtype.prefString(): String { if (DebugFlags.DEBUG_ENABLED && Build.VERSION.SDK_INT >= Build.VERSION_CODES.N && locale().toLanguageTag() == "und") { - Log.e(TAG, "unknown language, should not happen ${locale}, $languageTag, $this") + Log.e(TAG, "unknown language, should not happen ${locale}, $languageTag, $extraValue, ${hashCode()}, $nameResId") } return locale().toLanguageTag() + LOCALE_LAYOUT_SEPARATOR + SubtypeLocaleUtils.getKeyboardLayoutSetName(this) } From 2646c0ae10c1add57219388cfae96dbdbcabf91b Mon Sep 17 00:00:00 2001 From: FineFindus <63370021+FineFindus@users.noreply.github.com> Date: Thu, 15 Feb 2024 18:33:50 +0100 Subject: [PATCH 06/40] chore: fix typos in feature_request template (#491) --- .github/ISSUE_TEMPLATE/feature_request.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/ISSUE_TEMPLATE/feature_request.md b/.github/ISSUE_TEMPLATE/feature_request.md index fe494b034..1d164acbc 100644 --- a/.github/ISSUE_TEMPLATE/feature_request.md +++ b/.github/ISSUE_TEMPLATE/feature_request.md @@ -6,8 +6,8 @@ labels: enhancement From f177bb984bde672d092aded08efb0591d0ab85b8 Mon Sep 17 00:00:00 2001 From: src Date: Thu, 15 Feb 2024 20:00:32 -0800 Subject: [PATCH 07/40] Fix typo in README.md (#493) --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index af5467922..02b38579b 100644 --- a/README.md +++ b/README.md @@ -38,7 +38,7 @@ Does not use internet permission, and thus is 100% offline. ## FAQ / Common Issues * __Add a dictionary__: First download the dictionary file, e.g. from [here](https://codeberg.org/Helium314/aosp-dictionaries#dictionaries). Then go to language settings, click on the language, then on `+` next to _dictionary_ the _add_ and select the file. Alternatively you can open a `.dict` file in a file explorer with HeliBoard and then select the language. Note that the latter method does not work with all file explorers. -* __Emoji search__: You can get addon dictionaries for emoji suggestions in the [dictionaries repo](https://codeberg.org/Helium314/aosp-dictionaries). An actual search funtion does not exist. +* __Emoji search__: You can get addon dictionaries for emoji suggestions in the [dictionaries repo](https://codeberg.org/Helium314/aosp-dictionaries). An actual search function does not exist yet. * __No suggestions for some language__: Check [dictionaries repo](https://codeberg.org/Helium314/aosp-dictionaries) whether a dictionary is available. If there is one, download it and add it in the language settings for this language. * __No suggestions in some app / text field__: This app respects the [no suggestions flag](https://developer.android.com/reference/android/text/InputType#TYPE_TEXT_FLAG_NO_SUGGESTIONS) set by some input fields, i.e. the developer does not want you to see suggestions here. Best do in issue report for that app if you think this behavior is wrong. Alternatively you can enable the _always show suggestions_ setting that overrides the _no suggestions_ flag. * __How to enable glide typing__: There is no glide typing built into this app, but you can load compatible libraries: Go to advanced settings -> _load gesture typing library_ and point to a file. You can extract the file from GApps packages ("_swypelibs_"), or download one [here](https://github.com/erkserkserks/openboard/tree/master/app/src/main/jniLibs). Make sure to use the correct version (app will tell you in the dialog to load the library). From 8ff7810df94c6a08668a4fd92b360390720320e2 Mon Sep 17 00:00:00 2001 From: Helium314 Date: Sat, 17 Feb 2024 07:42:18 +0100 Subject: [PATCH 08/40] update readmes --- README.md | 2 +- layouts.md | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 02b38579b..89222697b 100644 --- a/README.md +++ b/README.md @@ -41,7 +41,7 @@ Does not use internet permission, and thus is 100% offline. * __Emoji search__: You can get addon dictionaries for emoji suggestions in the [dictionaries repo](https://codeberg.org/Helium314/aosp-dictionaries). An actual search function does not exist yet. * __No suggestions for some language__: Check [dictionaries repo](https://codeberg.org/Helium314/aosp-dictionaries) whether a dictionary is available. If there is one, download it and add it in the language settings for this language. * __No suggestions in some app / text field__: This app respects the [no suggestions flag](https://developer.android.com/reference/android/text/InputType#TYPE_TEXT_FLAG_NO_SUGGESTIONS) set by some input fields, i.e. the developer does not want you to see suggestions here. Best do in issue report for that app if you think this behavior is wrong. Alternatively you can enable the _always show suggestions_ setting that overrides the _no suggestions_ flag. -* __How to enable glide typing__: There is no glide typing built into this app, but you can load compatible libraries: Go to advanced settings -> _load gesture typing library_ and point to a file. You can extract the file from GApps packages ("_swypelibs_"), or download one [here](https://github.com/erkserkserks/openboard/tree/master/app/src/main/jniLibs). Make sure to use the correct version (app will tell you in the dialog to load the library). +* __How to enable glide typing__: There is no glide typing built into this app, but you can load compatible libraries: Go to advanced settings -> _load gesture typing library_ and point to a file (setting not available in _nouserlib_ version). You can extract the file from GApps packages ("_swypelibs_"), or download one [here](https://github.com/erkserkserks/openboard/tree/master/app/src/main/jniLibs). Make sure to use the correct version (app will tell you in the dialog to load the library). * __What is the _nouserlib_ version?__: The normal version (_release_) allows the user to provide a library for glide typing. Running code that isn't supplied with the app is _dynamic code loading_, which is a security risk. Android Studio warns about this: > Dynamically loading code from locations other than the application's library directory or the Android platform's built-in library directories is dangerous, as there is an increased risk that the code could have been tampered with. Applications should use loadLibrary when possible, which provides increased assurance that libraries are loaded from one of these safer locations. Application developers should use the features of their development environment to place application native libraries into the lib directory of their compiled APKs. diff --git a/layouts.md b/layouts.md index ecde9b3ed..e7ba3ea7c 100644 --- a/layouts.md +++ b/layouts.md @@ -22,10 +22,10 @@ If you want different key label and use text, set the label to [label]|[text], e ## Json format * Allows more flexibility than the simple format, e.g. changing keys depending on input type, shift state or layout direction -* You can use character layouts from FlorisBoard +* You can use character layouts from [FlorisBoard](https://github.com/florisboard/florisboard/blob/master/CONTRIBUTING.md#adding-the-layout) * There is no need for specifying a code, it will be determined from the label automatically - * Specify it if you want key label and code to be different -* You can add a _labelFlag_ to a key for some specific effects, see [here](app/src/main/res/values/attrs.xml) in the section _keyLabelFlags_ for names and numeric values + * You can still specify it, but it's only necessary if you want key label and code to be different +* You can add the numeric value of a _labelFlag_ to a key for some specific effects, see [here](app/src/main/res/values/attrs.xml) in the section _keyLabelFlags_ for names and numeric values. * More details on the formal will be provided. For now you can check other layouts, often you just need to copy lines and change the labels. ## Adding new layouts / languages From b1eb33f6e2d5eb631121af3494b11c1151d50157 Mon Sep 17 00:00:00 2001 From: Helium314 Date: Sat, 17 Feb 2024 17:07:18 +0100 Subject: [PATCH 09/40] add more locales to spellchecker.xml --- app/src/main/res/xml/spellchecker.xml | 276 +++++++++++++------------- 1 file changed, 140 insertions(+), 136 deletions(-) diff --git a/app/src/main/res/xml/spellchecker.xml b/app/src/main/res/xml/spellchecker.xml index 213f499cb..2f642303a 100644 --- a/app/src/main/res/xml/spellchecker.xml +++ b/app/src/main/res/xml/spellchecker.xml @@ -12,140 +12,144 @@ android:label="@string/spell_checker_service_name" android:settingsActivity="helium314.keyboard.latin.spellcheck.SpellCheckerSettingsActivity"> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + android:label="@string/subtype_generic" + android:subtypeLocale="ar" /> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + From fd95b4dc879c146c1b1558e7ccfc0d9e8c1b5597 Mon Sep 17 00:00:00 2001 From: Helium314 Date: Mon, 19 Feb 2024 14:10:49 +0100 Subject: [PATCH 10/40] add list of known dictionaries for more convenient links --- README.md | 4 + .../main/assets/dictionaries_in_dict_repo.csv | 85 +++++++++++++++++++ .../keyboard/latin/common/LocaleUtils.kt | 2 +- .../latin/settings/LanguageSettingsDialog.kt | 35 +++++++- .../keyboard/latin/utils/DictionaryUtils.kt | 3 + app/src/main/res/values/strings.xml | 2 + settings.gradle | 1 + tools/make-dict-list/README.md | 5 ++ tools/make-dict-list/build.gradle | 18 ++++ .../main/kotlin/tools/dict/MakeDictList.kt | 63 ++++++++++++++ 10 files changed, 215 insertions(+), 3 deletions(-) create mode 100644 app/src/main/assets/dictionaries_in_dict_repo.csv create mode 100644 tools/make-dict-list/README.md create mode 100644 tools/make-dict-list/build.gradle create mode 100644 tools/make-dict-list/src/main/kotlin/tools/dict/MakeDictList.kt diff --git a/README.md b/README.md index 89222697b..d655ce192 100644 --- a/README.md +++ b/README.md @@ -124,6 +124,10 @@ See [layouts.md](layouts.md#adding-new-layouts--languages) for how to add new la See make-emoji-keys tool [README](tools/make-emoji-keys/README.md). +### Update List of Existing Dictionaries + +See make-dict-list tool [README](tools/make-dict-list/README.md). + # License HeliBoard (as a fork of OpenBoard) is licensed under GNU General Public License v3.0. diff --git a/app/src/main/assets/dictionaries_in_dict_repo.csv b/app/src/main/assets/dictionaries_in_dict_repo.csv new file mode 100644 index 000000000..581fd5cfb --- /dev/null +++ b/app/src/main/assets/dictionaries_in_dict_repo.csv @@ -0,0 +1,85 @@ +main,ar, +main,hy, +main,as, +main,bn, +main,by, +main,bg, +main,ca, +main,hr, +main,cs, +main,da, +main,nl, +main,en_AU, +main,en_GB, +main,en_US, +emoji,en, +main,eo, +main,fi, +emoji,fr, +main,fr, +main,gl, +main,ka, +main,de, +main,gom, +main,el, +main,gu, +main,he, +main,iw, +main,hi, +main,hi_ZZ, +main,hu, +main,it, +main,kn, +main,ks, +main,lv, +main,lt, +main,lb, +main,mai, +main,ml, +main,mr, +main,nb, +main,or, +main,pl, +main,pt_BR, +main,pt_PT, +main,pa, +main,ro, +emoji,ru, +main,ru, +main,sa, +main,sat, +main,sr_ZZ, +main,sr, +main,sd, +main,sl, +main,es, +main,sv, +main,ta, +main,te, +main,tok, +main,tcy, +main,tr, +main,uk, +main,ur, +main,af,exp +main,ar,exp +main,bn,exp +main,bg,exp +main,cs,exp +main,en_GB,exp +main,en_US,exp +symbols,en,exp +symbols,fr,exp +main,fr,exp +main,de_AT,exp +main,de,exp +main,id,exp +main,it,exp +main,kab,exp +addon,ml_ZZ,exp +main,ru,exp +main,sk,exp +main,es,exp +main,uk,exp +main,vi,exp + diff --git a/app/src/main/java/helium314/keyboard/latin/common/LocaleUtils.kt b/app/src/main/java/helium314/keyboard/latin/common/LocaleUtils.kt index 72fae76af..067b973ec 100644 --- a/app/src/main/java/helium314/keyboard/latin/common/LocaleUtils.kt +++ b/app/src/main/java/helium314/keyboard/latin/common/LocaleUtils.kt @@ -91,7 +91,7 @@ object LocaleUtils { * @param tested the locale to test. * @return a constant that measures how well the tested locale matches the reference locale. */ - private fun getMatchLevel(reference: Locale, tested: Locale): Int { + fun getMatchLevel(reference: Locale, tested: Locale): Int { if (reference == tested) return LOCALE_FULL_MATCH if (reference.toString().isEmpty()) return LOCALE_ANY_MATCH if (reference.language != tested.language) return LOCALE_NO_MATCH diff --git a/app/src/main/java/helium314/keyboard/latin/settings/LanguageSettingsDialog.kt b/app/src/main/java/helium314/keyboard/latin/settings/LanguageSettingsDialog.kt index 2d9805101..6f0ff0c52 100644 --- a/app/src/main/java/helium314/keyboard/latin/settings/LanguageSettingsDialog.kt +++ b/app/src/main/java/helium314/keyboard/latin/settings/LanguageSettingsDialog.kt @@ -268,10 +268,41 @@ class LanguageSettingsDialog( binding.secondaryLocales.addView(rowBinding.root) } + private fun createDictionaryText(locale: Locale, context: Context): String { + val link = "" + context.getString(R.string.dictionary_link_text) + "" + val message = context.getString(R.string.add_dictionary, link) + val knownDicts = mutableListOf() + context.assets.open("dictionaries_in_dict_repo.csv").reader().forEachLine { + if (it.isBlank()) return@forEachLine + val (type, localeString, experimental) = it.split(",") + // we use a locale string here because that's in the dictionaries repo + // ideally the repo would switch to language tag, but not sure how this is handled in the dictionary header + // further, the dicts in the dictionaries repo should be compatible with other AOSP-based keyboards + val dictLocale = localeString.constructLocale() + if (LocaleUtils.getMatchLevel(locale, dictLocale) < 3) return@forEachLine + val rawDictString = "$type: ${dictLocale.getDisplayName(context.resources.configuration.locale())}" + val dictString = if (experimental.isEmpty()) rawDictString + else context.getString(R.string.available_dictionary_experimental, rawDictString) + val dictBaseUrl = DICTIONARY_URL + DICTIONARY_DOWNLOAD_SUFFIX + + if (experimental.isEmpty()) DICTIONARY_NORMAL_SUFFIX else DICTIONARY_EXPERIMENTAL_SUFFIX + val dictLink = dictBaseUrl + type + "_" + localeString.lowercase() + ".dict" + val fullText = "
  • $dictString
  • " + knownDicts.add(fullText) + } + if (knownDicts.isEmpty()) return message + return """ +

    $message

    + ${context.getString(R.string.dictionary_available)} +
      + ${knownDicts.joinToString("\n")} +
    + """.trimIndent() + } + private fun fillDictionariesView() { binding.addDictionary.setOnClickListener { - val link = "" + context.getString(R.string.dictionary_link_text) + "" - val message = SpannableStringUtils.fromHtml(context.getString(R.string.add_dictionary, link)) + val messageRawText = createDictionaryText(mainLocale, context) + val message = SpannableStringUtils.fromHtml(messageRawText) val dialog = Builder(context) .setTitle(R.string.add_new_dictionary_title) .setMessage(message) diff --git a/app/src/main/java/helium314/keyboard/latin/utils/DictionaryUtils.kt b/app/src/main/java/helium314/keyboard/latin/utils/DictionaryUtils.kt index 9c063e2d9..4f28f43b9 100644 --- a/app/src/main/java/helium314/keyboard/latin/utils/DictionaryUtils.kt +++ b/app/src/main/java/helium314/keyboard/latin/utils/DictionaryUtils.kt @@ -85,3 +85,6 @@ private fun hasAnythingOtherThanExtractedMainDictionary(dir: File) = dir.listFiles()?.any { it.name != DictionaryInfoUtils.getExtractedMainDictFilename() } != false const val DICTIONARY_URL = "https://codeberg.org/Helium314/aosp-dictionaries" +const val DICTIONARY_DOWNLOAD_SUFFIX = "/src/branch/main/" +const val DICTIONARY_NORMAL_SUFFIX = "dictionaries/" +const val DICTIONARY_EXPERIMENTAL_SUFFIX = "dictionaries_experimental/" diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 7aa226847..1f02a9447 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -547,6 +547,8 @@ New dictionary: "Select a dictionary to add. Dictionaries in .dict format can be downloaded %s." "here" + + "%s (experimental)" "Error: Selected file is not a valid dictionary file" diff --git a/settings.gradle b/settings.gradle index 8335aa9f5..287debfb1 100755 --- a/settings.gradle +++ b/settings.gradle @@ -1,2 +1,3 @@ include ':app' include ':tools:make-emoji-keys' +include ':tools:make-dict-list' diff --git a/tools/make-dict-list/README.md b/tools/make-dict-list/README.md new file mode 100644 index 000000000..8927e592c --- /dev/null +++ b/tools/make-dict-list/README.md @@ -0,0 +1,5 @@ +# make-dict-list + +This module takes care of generating a list of dictionaries available in the [dictionaries repository](https://codeberg.org/Helium314/aosp-dictionaries) for convenient linking when adding dictionaries in HeliBoard. + +To use it, simply run `./gradlew tools:make-dict-list:makeDictList` diff --git a/tools/make-dict-list/build.gradle b/tools/make-dict-list/build.gradle new file mode 100644 index 000000000..40b2dc986 --- /dev/null +++ b/tools/make-dict-list/build.gradle @@ -0,0 +1,18 @@ +apply plugin: "java" +apply plugin: 'kotlin' + +ext { + javaMainClass = "tools.dict.MakeDictList" +} + +java { + sourceCompatibility = JavaVersion.VERSION_17 + targetCompatibility = JavaVersion.VERSION_17 +} + +tasks.register('makeDictList', JavaExec) { + args project.rootProject.project('app').projectDir.path + File.separator + 'src' + + File.separator + 'main' + File.separator + 'assets' + classpath = sourceSets.main.runtimeClasspath + main = javaMainClass +} diff --git a/tools/make-dict-list/src/main/kotlin/tools/dict/MakeDictList.kt b/tools/make-dict-list/src/main/kotlin/tools/dict/MakeDictList.kt new file mode 100644 index 000000000..7ca864ee6 --- /dev/null +++ b/tools/make-dict-list/src/main/kotlin/tools/dict/MakeDictList.kt @@ -0,0 +1,63 @@ +package tools.dict + +import java.io.File +import java.net.URL + +class MakeDictList { + + companion object { + + @JvmStatic fun main(args: Array) { + val readmeUrl = "https://codeberg.org/Helium314/aosp-dictionaries/raw/branch/main/README.md" + val readmeText = URL(readmeUrl).readText() + val fileText = doIt(readmeText) + val targetDir = args[0] + + File(targetDir).mkdirs() + File("$targetDir/dictionaries_in_dict_repo.csv").writeText(fileText) + } + + } +} + +/** + * extract dictionary list from README.md + * output format: ,, + * is empty if dictionary is not experimental, no other check done + * requires README.md to have dicts in correct "# Dictionaries" or "# Experimental dictionaries" sections + */ +private fun doIt(readme: String): String { + // output format: ,, + // experimental is empty if dictionary is not experimental, no other check done + var mode = MODE_NOTHING + val outLines = mutableListOf() + readme.split("\n").forEach { line -> + if (line.startsWith("#")) { + mode = if (line.trim() == "# Dictionaries") + MODE_NORMAL + else if (line.trim() == "# Experimental dictionaries") + MODE_EXPERIMENTAL + else + MODE_NOTHING + return@forEach + } + if (mode == MODE_NOTHING || !line.startsWith("*")) return@forEach + val dictName = line.substringAfter("]").substringAfter("(").substringBefore(")") + .substringAfterLast("/").substringBefore(".dict") + val type = dictName.substringBefore("_") + val rawLocale = dictName.substringAfter("_") + val locale = if ("_" !in rawLocale) rawLocale + else { + val split = rawLocale.split("_").toMutableList() + if (!split[1].startsWith("#")) + split[1] = split[1].uppercase() + split.joinToString("_") + } + outLines.add("$type,$locale,${if (mode == MODE_EXPERIMENTAL) "exp" else ""}") + } + return outLines.joinToString("\n") + "\n" +} + +private const val MODE_NOTHING = 0 +private const val MODE_NORMAL = 1 +private const val MODE_EXPERIMENTAL = 2 From d3da4478b4a1bfb1905acb757c1f7dbc39dc3b5e Mon Sep 17 00:00:00 2001 From: Helium314 Date: Mon, 19 Feb 2024 14:33:51 +0100 Subject: [PATCH 11/40] disable onCheckedChangeListener while setting switch state, fixes #505 --- .../helium314/keyboard/latin/utils/PopupKeysUtils.kt | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/app/src/main/java/helium314/keyboard/latin/utils/PopupKeysUtils.kt b/app/src/main/java/helium314/keyboard/latin/utils/PopupKeysUtils.kt index f2e4298cc..b524c0b32 100644 --- a/app/src/main/java/helium314/keyboard/latin/utils/PopupKeysUtils.kt +++ b/app/src/main/java/helium314/keyboard/latin/utils/PopupKeysUtils.kt @@ -126,17 +126,18 @@ fun reorderPopupKeysDialog(context: Context, key: String, defaultSetting: String } val bgColor = ContextCompat.getColor(context, R.color.sliding_items_background) val adapter = object : ListAdapter, RecyclerView.ViewHolder>(callback) { - override fun onCreateViewHolder(p0: ViewGroup, p1: Int): RecyclerView.ViewHolder { + override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder { val b = LayoutInflater.from(context).inflate(R.layout.popup_keys_list_item, rv, false) b.setBackgroundColor(bgColor) return object : RecyclerView.ViewHolder(b) { } } - override fun onBindViewHolder(p0: RecyclerView.ViewHolder, p1: Int) { - val (text, wasChecked) = orderedItems[p1] + override fun onBindViewHolder(viewHolder: RecyclerView.ViewHolder, position: Int) { + val (text, wasChecked) = orderedItems[position] val displayTextId = context.resources.getIdentifier(text.lowercase(), "string", context.packageName) val displayText = if (displayTextId == 0) text else context.getString(displayTextId) - p0.itemView.findViewById(R.id.popup_keys_type)?.text = displayText - val switch = p0.itemView.findViewById(R.id.popup_keys_switch) + viewHolder.itemView.findViewById(R.id.popup_keys_type)?.text = displayText + val switch = viewHolder.itemView.findViewById(R.id.popup_keys_switch) + switch?.setOnCheckedChangeListener(null) switch?.isChecked = wasChecked switch?.isEnabled = !(key.contains(Settings.PREF_POPUP_KEYS_ORDER) && text == POPUP_KEYS_LAYOUT) // layout can't be disabled switch?.setOnCheckedChangeListener { _, isChecked -> From 060f98af1397da5b433155623ef50e1bf1118b6d Mon Sep 17 00:00:00 2001 From: Michael Keck Date: Tue, 20 Feb 2024 07:31:26 +0100 Subject: [PATCH 12/40] CI: Enable for main branch and PRs + update actions (#485) * CI: Run on all branches and pull requests * CI: Update actions * CI: Only run on the main branch + all PRs * CI: Use official gradle action It promises to handle CI caching better than the setup-java action. https://github.com/gradle/actions/blob/9e899d11ad247ec76be7a60bc1cf9d3abbb9e7f1/setup-gradle/README.md --- .github/workflows/android-build.yml | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/.github/workflows/android-build.yml b/.github/workflows/android-build.yml index 7eaa9413a..ad2f5e8d2 100644 --- a/.github/workflows/android-build.yml +++ b/.github/workflows/android-build.yml @@ -2,9 +2,8 @@ name: Build on: push: - branches: [ new ] + branches: [ main ] pull_request: - branches: [ new ] jobs: build: @@ -15,11 +14,12 @@ jobs: - uses: actions/checkout@v4 - name: Set up JDK - uses: actions/setup-java@v3 + uses: actions/setup-java@v4 with: java-version: '17' distribution: 'temurin' - cache: gradle + + - uses: gradle/actions/setup-gradle@v3 - name: Grant execute permission for gradlew run: chmod +x gradlew @@ -28,13 +28,13 @@ jobs: run: ./gradlew assembleDebug - name: Upload APK - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: name: HeliBoard-debug path: app/build/outputs/apk/debug/*-debug*.apk - name: Archive reports for failed job - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: name: reports path: '*/build/reports' From 71cfe3fbef657af0fca75d0f7d0e424a0cbb2c71 Mon Sep 17 00:00:00 2001 From: Helium314 Date: Tue, 20 Feb 2024 08:12:57 +0100 Subject: [PATCH 13/40] update translations from weblate --- app/src/main/res/values-ar/strings.xml | 78 ++++++++- app/src/main/res/values-be/strings.xml | 73 +++++++-- app/src/main/res/values-de/strings.xml | 175 +++++++++++++++++++- app/src/main/res/values-fr/strings.xml | 53 +++--- app/src/main/res/values-gl/strings.xml | 206 +++++++++++++++++++++++- app/src/main/res/values-it/strings.xml | 161 +++++++++++++++++- app/src/main/res/values-kab/strings.xml | 32 +++- app/src/main/res/values-pl/strings.xml | 175 +++++++++++++++++++- app/src/main/res/values-ru/strings.xml | 144 +++++++++++++++-- app/src/main/res/values-uk/strings.xml | 29 ++-- 10 files changed, 1030 insertions(+), 96 deletions(-) diff --git a/app/src/main/res/values-ar/strings.xml b/app/src/main/res/values-ar/strings.xml index fec3a629d..1c494f849 100644 --- a/app/src/main/res/values-ar/strings.xml +++ b/app/src/main/res/values-ar/strings.xml @@ -3,8 +3,7 @@ Copyright (C) 2008 The Android Open Source Project modified SPDX-License-Identifier: Apache-2.0 AND GPL-3.0-only ---> - +--> "بحث في أسماء جهات الاتصال" "يستخدم المدقق الإملائي إدخالات من قائمة جهات الاتصال" "اهتزاز عند ضغط مفتاح" @@ -171,4 +170,79 @@ "بحث" "توقف" "انتظر" + الألوان + صف الأرقام + %s (تجريبي) + اللغة + استخدمه على أي حال + النمط + دائري + صف الأرقام باللغة المحلية + إظهار كافة الألوان + إضافة كلمة + بنّي + سحابي + غابة + رمل + مخصص + أزرق رمادي + خلفية لوحة المفاتيح + نص الأزرار + اختيار تلقائي للون + انقر للمعانية + الإصدار + غلق + المظهر + خلفية الأزرار + الإدخال الحَرَكي + حفظ السِجِلّ + رخصة مفتوحة المصدر + نص زر المسافة البيضاء + الرابط إلى جت هب + النسخ الاحتياطي والإسترجاع + الوزن: + عن + خلفية زر المسافة البيضاء + مسافة التقسيم + تغيير اللغة + التصحيح التلقائي المتقدم + إظهار الاقتراحات دائما + حفظ + استرجاع + الكتابة متعددة اللغات + تحميل المكتبة + حذف المكتبة + تحميل مكتبة الإدخال الحرَكي + الرموز + الحافظة + يسار + يمين + أعلى + أسفل + اللغة (أولوية) + مسح الحافظة + الإدخال الصوتي + اختر كلمة + وضع اليد الواحدة + تقليص المسافة ما بين الأزرار + تحميل ملف + المزيد من الرموز + إضافة تخطيط مخصص + تعذرت قراءة الملف + تخصيص تخطيط الرموز + القواميس + إعداد لوحة المفاتيح + القواميس المدمَجَة + إضافة قاموس عبر ملف + هنا + اختر اللغة + استبدل القاموس + إضافة إلى %s + لا تظهره مرة أخرى + فاتح + داكن + أسود + ألوان ديناميكية + محيط + وردي \ No newline at end of file diff --git a/app/src/main/res/values-be/strings.xml b/app/src/main/res/values-be/strings.xml index deefb5e32..ba31d97dc 100644 --- a/app/src/main/res/values-be/strings.xml +++ b/app/src/main/res/values-be/strings.xml @@ -3,8 +3,7 @@ Copyright (C) 2008 The Android Open Source Project modified SPDX-License-Identifier: Apache-2.0 AND GPL-3.0-only ---> - +--> "Шукаць імёны кантактаў" "Модуль праверкі правапісу выкарыстоўвае запісы са спісу кантактаў" "Вібрацыя пры націску клавіш" @@ -17,7 +16,7 @@ "Дадатковыя" "Тэма" "Уключыць раздзеленую клавіятуру" - "Перакл. да інш. спос. ув." + Пераключаць метады ўводу "Кнопка пераключэння мовы" "%s мс" "Стандартныя сістэмныя" @@ -43,7 +42,7 @@ "Вельмі агрэсіўна" "Падказкi для наступнага слова" "Выкарыстоўваць папярэдняе слова, каб атрымлiваць падказкi" - "Уключыць набор жэстамі" + Уключыць ўвод жэстамі "Уводзьце слова, перасоўваючы палец па літарах" "Паказаць след жэста" "Дынамічны плаваючы прагляд" @@ -53,16 +52,16 @@ "Англійская (Вялікабрытанія)" "Англійская (ЗША)" "Іспанская (ЗША)" - "Хінгліш" - "Сербская (Лацініца)" + хінгліш + сербская (Лацініца) Англійская (Вялікабрытанія) (%s) Англійская (ЗША) (%s) Іспанская (ЗША) (%s) - Хінгліш (%s) - Сербская (%s) + хінгліш (%s) + сербская (%s) %s (Традыцыйная) %s (Кампактная) - "Стандартная (Лацініца)" + стандартная (лацініца) "Лацініца (QWERTY)" "Лацініца (QWERTZ)" "Лацініца (AZERTY)" @@ -130,9 +129,9 @@ Налады праверкі правапісу HeliBoard Клавіша эмодзі Налады HeliBoard - Увод + Ўвод Дадатковыя клавішы - Праграма праверкі правапісу HeliBoard + Праверка правапісу HeliBoard Уключыць гісторыю буфера абмену Калі выключана, клавіша буфера абмену будзе ўстаўляць змесціва буфера абмену, калі яно ёсць Час захоўвання гісторыі буфера абмену @@ -174,9 +173,9 @@ Акцэнт Даведка Версія - Паглядзець на GitHub - Ліцэнзія з адкрытым зыходным кодам - GNU General Public License v3.0 + Паглядзець на GitHub + Ліцэнзія з адкрытым зыходным кодам + GNU General Public License v3.0 Закрыць "Выкарыстоўваць мовы сістэмы" Націсніце на мову, каб адкрыць наладкі @@ -193,7 +192,7 @@ Лічбавы рад Паказваць ключавыя падказкі Паказваць падказкі пры доўгім націску - Змяняць метад уводу з дапамогай клавішы прабел + Змяніць метад ўводу з дапамогай клавішы прабел Доўгі націск клавішы прабел адкрые меню выбару метаду ўводу Алфавіт (Colemak Mod-DH) Выкарыстоўваць тэму сістэмы @@ -218,4 +217,46 @@ "Адпр." "Паўза" "Чакаць" - + Заўсёды паказваць прапановы + Галасавы ўвод + Дадаць словы ў асабісты слоўнік + Мовы і раскладкі + Вам спатрэбіцца бібліятэка для «%s». Несумяшчальныя бібліятэкі могуць выйсці з ладу пры выкарыстанні жэставага ўводу. +\n +\nПапярэджанне: загрузка знешняга кода можа пагражаць бяспецы. Выкарыстоўвайце толькі бібліятэку з крыніцы, якой давяраеце. + Выдаліць бібліятэку + Невядомы файл бібліятэкі. Вы ўпэўненыя, што атрымалі яго з надзейнай крыніцы, і гэта для «%s»? + Паказаць варыянты, вызначаныя ў мовах клавіятуры (па змаўчанні) + Дадаць распаўсюджаныя варыянты + Дадаць ўсе даступныя варыянты + Больш аўтакарэкцыі + Адлегласць падзелу + Ігнараваць запыты іншых праграм на адключэнне прапаноў + Пераключыць мову + Папярэджанне: Адключэнне гэтай налады прывядзе да выдалення атрыманых дадзеных + Загрузіць бібліятэку + Паказаць больш літар з дыякрытычнымі знакамі пры ўтрыманні + Аўтавыпраўленне, нават калі гэта відавочна не запытана ў полі ўводу + Пераключаць абодва + Уверх + Паказаць функцыянальныя падказкі + Выберыце файл у сумяшчальным фармаце. Інфармацыя пра фарматы даступна %s. + Мова (прыярытэт) + Немагчыма прачытаць файл + Мова + Направа + Буфер абмену + Ўніз + Выберыце клавішы панэлі інструментаў + У левы канец + Выберыце слова + Налева + Дадаць уласную раскладку + Сімвалы + У правы канец + Ачысціць буфер абмену + Загрузіць файл + Вышыня ніжняй водступу + Рэжым адной рукой + Раскладка + \ No newline at end of file diff --git a/app/src/main/res/values-de/strings.xml b/app/src/main/res/values-de/strings.xml index b99fd51fb..5ba450120 100644 --- a/app/src/main/res/values-de/strings.xml +++ b/app/src/main/res/values-de/strings.xml @@ -3,14 +3,13 @@ Copyright (C) 2008 The Android Open Source Project modified SPDX-License-Identifier: Apache-2.0 AND GPL-3.0-only ---> - +--> "Kontakte erkennen" "Rechtschreibprüfung kann Einträge aus meiner Kontaktliste verwenden" "Bei Tastendruck vibrieren" "Ton bei Tastendruck" "Bei Tastendruck Pop-up" - "Einstellungen" + Präferenzen "Gesteneingabe" "Textkorrektur" "Erweitert" @@ -27,9 +26,9 @@ "Doppeltippen auf Leertaste fügt Punkt und Leerzeichen ein" "Autom. Groß-/Kleinschreibung" "Das erste Wort jedes Satzes großschreiben" - "Mein Wörterbuch" - "Erweiterte Wörterbücher" - "Allgemeines Wörterbuch" + Persönliches Wörterbuch + Zusatzwörterbücher + Hauptwörterbuch "Änderungsvorschläge" "Vorgeschlagene Wörter während des Tippens anzeigen" "Anstößige Wörter sperren" @@ -42,7 +41,7 @@ "Sehr stark" "Vorschläge für nächstes Wort" "Anhand des vorherigen Wortes Vorschläge machen" - "Bewegungseingabe aktivieren" + Gesteneingabe aktivieren "Durch Bewegen der Finger über die Buchstaben ein Wort eingeben" "Spur der Touch-Geste anzeigen" "Dyn. unverankerter Vorschlag" @@ -121,7 +120,7 @@ " ABCDEFGHIJKLMNOPQRSTUVWXYZ" "Systemsprachen verwenden" "Eingabemethode wählen" - Zwischenablage-Verlauf + Verlauf der Zwischenablage Korrekturen Vorschläge HeliBoard Rechtschreibprüfungs-Einstellungen @@ -171,4 +170,164 @@ "Suchen" "Pause" "Warten" + Immer Vorschläge anzeigen + Farben anpassen (Nacht) + Internes Hauptwörterbuch + Dunkel + Nur Hauptfarben anzeigen + Hoch + Spracheingabe + Dynamische Farben + Aussehen + Funktionale Hinweise anzeigen + Datei in einem kompatiblen Format auswählen. Information zu den Formaten ist verfügbar %s. + Tastenhintergrund + Fehler beim Wiederherstellen der Sicherung: %s + Farben + Funktionstastenhintergrund + %s (Sebeolsik 390) + Persönliches Wörterbuch des Gerätes verwenden um gelernte Wörter zu speichern + Dieses Wort ist bereits im %s Benutzer-Wörterbuch vorhanden. Bitte geben Sie ein anderes ein. + Abgerundet + Sicherung + Schwarz + %s (Sebeolsik Final) + Schokolade + Soll das vom Benutzer hinzugefügte Wörterbuch \"%s\" wirklich entfernt werden? + Wolkig + Von Leertaste nach oben wischen um die Sprache zu ändern + GNU General Public License v3.0 + Tag + Fehler: Skript ist kompatibel mit dieser Tastatur + Beschreibung der versteckten Features + Sprache (Priorität) + Wörter zum persönlichen Wörterbuch hinzufügen + Hintergrundbild festlegen + Tippen um das Rohlayout zu bearbeiten + Pink + Sprachen & Layouts + Datei kann nicht gelesen werden + hier + Fehler: Ausgewählte Datei ist keine gültige Wörterbuchdatei + gerätegeschützter Speicher + Farbe der Navigationsleiste + trotzdem benutzen + Wald + Sie benötigen die Bibliothek für \'%s\'. Inkompatible Bibliotheken können zu Abstürzen bei der Gesteneingabe führen. +\n +\nWarnung: Das Laden von externem Code kann ein Sicherheitsrisiko darstellen. Verwenden Sie nur Bibliotheken aus Quellen den Sie vertrauen. + Wörterbuch zum Hinzufügen auswählen. Wörterbücher im .dict-Format können heruntergeladen werden %s. + Bibliothek löschen + Sprache + Rechts + Fehler beim Laden der Wörterbuchdatei + Bevorzuge lokalisierte gegenüber lateinischen Zahlen + Unbekannte Bibliotheksdatei. Sind Sie sicher, dass Sie es von einer vertrauenswürdigen Quelle erhalten haben und es ist für \'%s\'? + Blau-Grau + Beschriftung Leertaste + Hell + Wort hinzufügen + Textfarbe Wortvorschlag + Für Vorschau klicken + In den Tastatursprachen definierte Varianten anzeigen (Standard) + Gemeinsame Varianten hinzufügen + Layout für weitere Symbole anpassen + Benutzerdefiniert + Wörterbuch ersetzen + Hinzufügen zu %s + Tastaturhintergrund + Zwischenablage + Indigo + Akzent + Auf GitHub ansehen + Zahlenreihe + Alphabet (Bépo) + Wiederherstellen + Symbollayout anpassen + Popup-Tastenreihenfolge wählen + Version + Hinweis-Quelle wählen + Native Bibliothek bereitstellen um Gesteneingabe zu aktivieren + Mehr Symbole + Versuche URLs und ähnliches als einzelnes Wort zu erkennen + Sprache auswählen + Tastenbeschriftung + Gesteneingabe-Bibliothek laden + Hintergrund der Leertaste + Dunkler + Bild für den Tag- oder Nachtmodus festlegen? + Farbe automatisch wählen + Über + Runter + Symbolleistentasten wählen + Open-Source-Lizenz + Ozean + Sicherungsfehler: %s + Hinweise anzeigen, wenn langes Drücken einer Taste zusätzliche Funktionen auslöst + Sand + Sichern und wiederherstellen + Ganz links + Stil + Wort auswählen + Funktionen anzeigen, die möglicherweise unbemerkt bleiben + Farben (Nacht) + Links + Alle Farben zeigen + Benutzerdefinierte Layout %s wirklich löschen? + Wörterbücher + Benutzerdefiniertes Layout hinzu + Farben für Text und Hintergrund wählen + Tasten-Hinweistext + Tastatur konfigurieren + Symbole + Wörterbuch aus Datei hinzufügen + Benutzerdefiniert (Nacht) + Braun + Das vom Benutzer hinzugefügte Wörterbuch \"%1$s\" wirklich ersetzen? +\n +\nAktuelles Wörterbuch: +\n%2$s +\n +\nNeues Wörterbuch: +\n%3$s + URL-Erkennung + Violette + Ganz rechts + Nummernzeile lokalisieren + Alle verfügbaren Varianten hinzufügen + Mehr Autokorrektur + Teilungsabstand + Zu welcher Sprache soll das Wörterbuch \"%1$s\" für %2$s hinzugefügt werden? + Schriftstärke: + Ignoriere andere App-Anfragen um Vorschläge zu deaktivieren + Layout-Name festlegen + Sprache wechseln + Zwischenablage löschen + Nacht + Enge Tastenlücken + Nicht noch einmal zeigen + Die ausgewählte Datei ist für %1$s , es wurde jedoch %2$s erwartet. Trotzdem für %2$s verwenden? + Warnung: Deaktivieren dieser Einstellung löscht gelernte Daten + Bibliothek laden + Datei laden + Schließen + Randabstand unten + Vorhandenes Layout kopieren + Eingabe durch Gesten + Sprache antippen um Einstellungen zu öffnen + Mehr Buchstaben mit diakritischen Zeichen im Popup anzeigen + Einhandmodus + Layoutfehler: %s + Farben anpassen + Mehrsprachiges Tippen + Speichern oder laden aus Datei. Warnung: Die Wiederherstellung überschreibt vorhandene Daten + Protokoll speichern + Layout + Autokorrektur, auch wenn dies vom Eingabefeld nicht explizit angefordert wird + Holo weiß + Beides wechseln + Sprachwechsel mit Leertaste + ► Durch langes Drücken der Zwischenablagetaste (die optionale Taste in der Vorschlagsleiste) wird der Inhalt der Systemzwischenablage eingefügt. <br> <br> ► Durch langes Drücken von Tasten in der Symbolleiste der Vorschlagsleiste werden diese an die Vorschlagsleiste angeheftet. <br> <br> ► Halten Sie die Komma-Taste gedrückt, um auf die Zwischenablageansicht, die Emoji-Ansicht, den Einhandmodus, die Einstellungen oder den Sprachwechsel zuzugreifen: <br> • Die Emoji-Ansicht und der Sprachwechsel verschwinden, wenn Sie über die entsprechende Taste verfügen ermöglicht; <br> • Bei einigen Layouts ist es nicht die Komma-Taste, sondern die Taste an derselben Position (z. B. ist es „q“ für das Dvorak-Layout). <br> <br> ► Wenn der Inkognito-Modus aktiviert ist, werden keine Wörter gelernt und keine Emojis zu den letzten hinzugefügt. <br> <br> ► Drücken Sie auf das Inkognito-Symbol, um auf die Symbolleiste zuzugreifen. <br> <br> ► Schiebetasteneingabe: Wischen Sie von der Umschalttaste zu einer anderen Taste, um einen einzelnen Großbuchstaben einzugeben: <br> • Dies funktioniert auch für die Taste „?123“, um ein einzelnes Symbol über die Symboltastatur einzugeben, und für zugehörige Schlüssel. <br> <br> ► Drücken Sie lange auf einen Vorschlag in der Vorschlagsleiste, um weitere Vorschläge anzuzeigen, und klicken Sie auf die Schaltfläche „Löschen“, um diesen Vorschlag zu entfernen. <br> <br> ► Wischen Sie von einem Vorschlag nach oben, um weitere Vorschläge zu öffnen, und lassen Sie den Vorschlag los, um ihn auszuwählen. <br> <br> ► Drücken Sie lange auf einen Eintrag im Verlauf der Zwischenablage, um ihn anzuheften (belassen Sie ihn in der Zwischenablage, bis Sie die Anheftung aufheben). <br> <br> ► Sie können Wörterbücher hinzufügen, indem Sie sie in einem Datei-Explorer öffnen: <br> • Dies funktioniert nur mit <i>content-uris</i> und nicht mit <i>file-uris</i> Dies bedeutet, dass es mit einigen Datei-Explorern möglicherweise nicht funktioniert. <br> <br> <i>Debug-Modus / Debug-APK</i> <br> <br> • Drücken Sie lange auf einen Vorschlag, um das Quellwörterbuch anzuzeigen.<br> <br> • Wenn Sie Debug-APK verwenden, können Sie dies tun Suchen Sie in den erweiterten Einstellungen nach den Debug-Einstellungen. Der Nutzen ist jedoch begrenzt, mit Ausnahme der Speicherung von Wörterbüchern im Protokoll. <br> <br> • Im Falle eines Anwendungsabsturzes werden Sie beim Öffnen der Einstellungen gefragt, ob Sie die Absturzprotokolle wünschen. <br> <br> • Bei mehrsprachiger Eingabe zeigt die Leertaste einen Konfidenzwert an, der zur Bestimmung der aktuell verwendeten Sprache verwendet wird. <br> <br> • Vorschläge werden oben einige kleine Zahlen haben, die eine interne Bewertung und ein Quellwörterbuch anzeigen (kann deaktiviert werden). ► Für Benutzer, die manuelle Backups mit Root-Zugriff durchführen: Ab Android 7 befindet sich die gemeinsame Einstellungsdatei nicht am Standardspeicherort, da die App %s verwendet. <br> Dies ist notwendig, damit die Einstellungen gelesen werden können, bevor das Gerät entsperrt wird, z.B. beim Booten. <br> Die Datei befindet sich in /data/user_de/0/package_id/shared_prefs/, dies kann jedoch vom Gerät und der Android-Version abhängen. + "Ohne Wörterbuch erhalten Sie nur Vorschläge für Text, den Sie zuvor eingegeben haben.<br> +\n Sie können Wörterbücher %1$s herunterladen oder überprüfen, ob ein Wörterbuch für \"%2$s\" direkt heruntergeladen werden kann %3$s." \ No newline at end of file diff --git a/app/src/main/res/values-fr/strings.xml b/app/src/main/res/values-fr/strings.xml index adca305e6..6a6a2005c 100644 --- a/app/src/main/res/values-fr/strings.xml +++ b/app/src/main/res/values-fr/strings.xml @@ -3,8 +3,7 @@ Copyright (C) 2008 The Android Open Source Project modified SPDX-License-Identifier: Apache-2.0 AND GPL-3.0-only ---> - +--> "Rechercher les noms de contacts" "Le correcteur orthographique utilise les noms des contacts." "Vibrer à chaque touche" @@ -273,9 +272,9 @@ Nouveau dictionnaire: Couleur d\'accentuation Saisie gestuelle À propos - Lien vers GitHub + Lien vers GitHub Sauvegarder le journal - Licence Open-source + Licence Open-source Forcer le mode incognito Style Arrondi @@ -313,27 +312,27 @@ Nouveau dictionnaire: Montre les caractéristiques qui peuvent passer inaperçues stockage protégé de l\'appareil - ► Un appui long sur la touche presse-papiers (celle qui est optionnelle dans la bande de suggestions) permet de coller le contenu du presse-papiers. <br> <br> - ► Un appui long sur les touches de la barre d\'outils permet de les épingler à la bande de suggestions. <br> <br> - ► Appuyez longuement sur la virgule pour accéder à l\'affichage du presse-papiers, des emojis, au mode à une main, aux paramètres ou au changement de langue : <br> - \t• l\'affichage des emojis et le changement de langue disparaîtront si les touches correspondantes sont affichées ; <br> - \t• pour certaines dispositions, ce n\'est pas sur la touche virgule mais sur la touche à la même position (par exemple, c\'est `q` pour la disposition Dvorak). <br> <br> - ► Lorsque le mode incognito est activé, aucun mot n\'est appris et aucun emojis n\'est ajouté à la catégorie récent. <br> <br> - ► Appuyez sur l\'icône incognito pour ouvrir la barre d\'outils. <br> <br> - ► Saisie par balayage des touches : passez de la touche Maj à une autre touche pour taper un seul caractère en majuscule : <br> - \t• fonctionne également avec la touche `?123` qui permet de taper un seul symbole à partir du clavier des symboles, ainsi que pour les touches associées. <br> <br> - ► Un appui long sur une suggestion dans la bande de suggestions permet d\'afficher d\'autres suggestions et un bouton de suppression qui permet de supprimer cette suggestion. <br> <br> - ► Balayez vers le haut à partir d\'une suggestion pour ouvrir d\'autres suggestions, puis relâchez la pression sur la suggestion pour la sélectionner. <br> <br> - ► Appuyez longuement sur une entrée dans l\'historique du presse-papiers pour l\'épingler (elle reste dans le presse-papiers jusqu\'à ce que vous la désépingliez). <br> <br> - ► Vous pouvez ajouter des dictionnaires en les ouvrant dans un explorateur de fichiers : <br> - \t• ne fonctionne qu\'avec <i>content-uris</i> et non avec <i>file-uris</i>, ce qui signifie que cela peut ne pas fonctionner avec certains explorateurs de fichiers. <br> <br> + ► Un appui long sur la touche presse-papiers (celle qui est optionnelle dans la bande de suggestions) permet de coller le contenu du presse-papiers. <br> <br> + ► Un appui long sur les touches de la barre d\'outils permet de les épingler à la bande de suggestions. <br> <br> + ► Appuyez longuement sur la virgule pour accéder à l\'affichage du presse-papiers, des emojis, au mode à une main, aux paramètres ou au changement de langue : <br> + \t• l\'affichage des emojis et le changement de langue disparaîtront si les touches correspondantes sont affichées ; <br> + \t• pour certaines dispositions, ce n\'est pas sur la touche virgule mais sur la touche à la même position (par exemple, c\'est `q` pour la disposition Dvorak). <br> <br> + ► Lorsque le mode incognito est activé, aucun mot n\'est appris et aucun emojis n\'est ajouté à la catégorie récent. <br> <br> + ► Appuyez sur l\'icône incognito pour ouvrir la barre d\'outils. <br> <br> + ► Saisie par balayage des touches : passez de la touche Maj à une autre touche pour taper un seul caractère en majuscule : <br> + \t• fonctionne également avec la touche `?123` qui permet de taper un seul symbole à partir du clavier des symboles, ainsi que pour les touches associées. <br> <br> + ► Un appui long sur une suggestion dans la bande de suggestions permet d\'afficher d\'autres suggestions et un bouton de suppression qui permet de supprimer cette suggestion. <br> <br> + ► Balayez vers le haut à partir d\'une suggestion pour ouvrir d\'autres suggestions, puis relâchez la pression sur la suggestion pour la sélectionner. <br> <br> + ► Appuyez longuement sur une entrée dans l\'historique du presse-papiers pour l\'épingler (elle reste dans le presse-papiers jusqu\'à ce que vous la désépingliez). <br> <br> + ► Vous pouvez ajouter des dictionnaires en les ouvrant dans un explorateur de fichiers : <br> + \t• ne fonctionne qu\'avec <i>content-uris</i> et non avec <i>file-uris</i>, ce qui signifie que cela peut ne pas fonctionner avec certains explorateurs de fichiers. <br> <br> <i> Mode debug / APK de debogage </i> <br> <br> - \t• Un appui-long sur une suggestion montre la source du dictionnaire.<br> <br> - \t• Lorsque vous utilisez l\'APK de débogage, vous trouverez les paramètres de débogage dans les préférences avancées, bien qu\'ils ne soient pas très utiles, sauf pour transférer les dictionnaires dans le journal de débogage. <br> <br> - \t• Lorsque l\'application se bloque, un message vous demande où vous souhaitez enregistrer les journaux d\'incidents lorsque vous ouvrez les paramètres. <br> <br> - \t• Lors de la saisie multilingue, la barre d\'espace affiche une valeur de fiabilité utilisée pour déterminer la langue en cours d\'utilisation. <br> <br> - \t• Les suggestions seront accompagnées de petits chiffres indiquant un score interne et la source du dictionnaire (peut être désactivé). <br> <br> - ► Pour les utilisateurs effectuant des sauvegardes manuelles avec un accès root : à partir d\'Android 7, le fichier de préférences partagées ne se trouve pas dans l\'emplacement par défaut car l\'application utilise le %s. <br> + \t• Un appui-long sur une suggestion montre la source du dictionnaire.<br> <br> + \t• Lorsque vous utilisez l\'APK de débogage, vous trouverez les paramètres de débogage dans les préférences avancées, bien qu\'ils ne soient pas très utiles, sauf pour transférer les dictionnaires dans le journal de débogage. <br> <br> + \t• Lorsque l\'application se bloque, un message vous demande où vous souhaitez enregistrer les journaux d\'incidents lorsque vous ouvrez les paramètres. <br> <br> + \t• Lors de la saisie multilingue, la barre d\'espace affiche une valeur de fiabilité utilisée pour déterminer la langue en cours d\'utilisation. <br> <br> + \t• Les suggestions seront accompagnées de petits chiffres indiquant un score interne et la source du dictionnaire (peut être désactivé). <br> <br> + ► Pour les utilisateurs effectuant des sauvegardes manuelles avec un accès root : à partir d\'Android 7, le fichier de préférences partagées ne se trouve pas dans l\'emplacement par défaut car l\'application utilise le %s. <br> Cela est nécessaire pour que les paramètres puissent être lus avant que l\'appareil ne soit déverrouillé, par exemple au démarrage. <br> Le fichier se trouve dans <i>/data/user_de/0/package_id/shared_prefs/</i>, mais cela peut dépendre de l\'appareil et de la version d\'Android. "Améliore les suggestions en fonction des messages et des données saisies" @@ -345,4 +344,8 @@ Nouveau dictionnaire: "Rech." "Pause" "Attente" - + Alphabet (Bépo) + %s (expérimental) + Version + Impossible de lire le fichier + \ No newline at end of file diff --git a/app/src/main/res/values-gl/strings.xml b/app/src/main/res/values-gl/strings.xml index fc32f906b..5c00cdde8 100644 --- a/app/src/main/res/values-gl/strings.xml +++ b/app/src/main/res/values-gl/strings.xml @@ -1,10 +1,9 @@ - + - +--> "Verificar nomes de contactos" "O corrector ortográfico utiliza entradas da lista de contactos" "Vibrar ao premer as teclas" @@ -132,4 +131,203 @@ "Buscar" "Pausa" "Espera" - + %s min + %s (Akkhor) + %s (Sebeolsik 390) + %s (experimental) + Tamaño: + Engadir unha palabra + Estilo + Redondeado + Cores + Cores (noite) + Bordo da tecla + Modo Auto para día/noite + A aparencia seguirá os axustes do sistema + Cor da barra de navegación + Claro + Branco Holo + Escuro + Máis escuro + Cores dinámicas + Gris azulado + Marrón + Chocolate + Nubrado + Rosa + Area + Violeta + Persoal + Persoal (claro) + Axustar cores + Elexir cor automáticamente + Mostrar só cores principais + Mostrar todas as cores + Preme para vista previa + Elixe as cores do texto e fondo + Fodo do teclado + Texto da tecla + Suxestión da tecla + Texto da suxestión + Fondo da tecla + Fondo da barra de espazo + Texto da barra de espazo + Destacado + Entrada do xesto + Acerca de + Versión + Ver en GitHub + Gardar rexistro + Licenza Código-Aberto + Licenza GNU General Public v3.0 + Toca no idioma para abrir os axustes + Aparencia + Descrición de ferramentas ocultas + almacenaxe protexida do dispositivo + Entrada + Teclas adicionais + Historial do portapapeis + Correccións + Suxestións + Experimental + Varios + Distancia de separación + Cambiar de Idioma + Cambiar os dous + Tecla Emoji + Sen límite + Aviso: ao desactivar este axuste vas eliminar os datos aprendidos + Engadir palabras ao dicionario persoal + Usar un dicionario persoal no dispositivo para gardar palabras aprendidas + Mostrar sempre suxestións + Ignorar as solicitudes de outras app para desactivar as suxestións + Auto-corrección estendida + Auto-correxir incluso se non fose solicitado explícitamente polo campo de entrada + Confianza na auto-corrección + Activar historial do portapapeis + Se o desactivas, a tecla de portapapeis pegará o contido que exista no portapapeis + Período de retención do historial + Borrar ao desprazar + Fai un xesto de desprazamento desde a tecla eliminar e elimina anacos grandes de texto dunha pasada + Desprázate na barra espazadora para mover o cursor + Desprazamento na barra + Deprázate hacia arriba na barra espazadora para cambiar de idioma + Cambio de idioma na barra + Copia de apoio e restablecer + Garda ou restablecer desde un ficheiro. Aviso: o restablecemento sobrescribe os datos + Fallo na copia: %s + Erro ao restablecer: %s + Copia de apoio + Restablecer + Escritura varios idiomas + Cargar biblioteca de xestos ao escribir + Proporcionar unha biblioteca nativa para activar escritura por xestos + Ficheiro de biblioteca descoñecido. Tes a certeza de que procede dunha fonte de confianza e é valida para \'%s\'? + Cargar biblioteca + Eliminar biblioteca + Espazo após puntuación + Engadir un espazo automáticamente despois de escribir un signo de puntuación + Mostrar máis letras co signos diacríticos nas emerxentes + Mostrar variantes definidas nos idiomas do teclado (por defecto) + Engadir variantes comúns + Engadir todas as variables dispoñibles + Detección de URL + Forzar modo incógnito + Desactiva a aprendizaxe de novas palabras + Máis teclas + Idiomas e Disposicións + Número de fila + Mostrar sempre o número de fila + Traducir número de fila + Mostrar suxestións de teclas + Mostrar suxestións ao manter presa + Elexir fonte da suxestión + Elixe a orde das teclas na emerxente + Fila de números + Idioma + Idioma (prioridade) + Disposición + Símbolos + Elixe teclas barra ferramentas + Portapapeis + Limpar portapapeis + Escribir por voz + Elexir palabra + Modo dunha sóa man + Só esquerda + Só dereita + Esquerda + Dereita + Arriba + Abaixo + Mostrar suxestión de funcións + Mostra suxestión a manter presa unha tecla que teña funcións adicionais + Cambiar o método de escritura coa tecla espazo + Manter presa a tecla espazo para abrir o menú de selección de método de entrada + Espazo reducido entre teclas + Escala de altura do teclado + Escala do espazo inferior do teclado + %s (Sebeolsik Final) + Alfabeto (Colemak Mod-DH) + Alfabeto (Bépo) + Engadir disposición persoal + Elixe un ficheiro cun formato compatible. Tes información sobre os formatos en %s. + Cargar ficheiro + Non se puido ler o ficheiro + Copiar disposición existente + Dar nome á disposición + Queres eliminar a disposición persoal %s? + Erro na disposición: %s + Toca para editar a disposición + Personaliza os símbolos da disposición + Personaliza máis símbolos na disposición + Máis símbolos + Establece imaxe de fondo + Establecer para o modo diurno ou nocturno? + Día + Noite + Configurar o teclado + Dicionarios + Dicionario interno principal + Engadir dicionario desde ficheiro + A que idioma deberiamos engadir o dicionario \"%1$s\" de %2$s? + Elexir idioma + Engadir a %s + Substituír dicionario + Tes certeza de querer substituír o dicionario engadido \"%s\"? + Non volver mostrar + Elixe o dicionario a engadir. Os dicionarios en formato .dict están dispoñibles en %s. + Erro: o ficheiro seleccionado non é un dicionario válido + Erro: o script non é compatible con este teclado + Usar igualmente + Erro ao cargar o ficheiro do dicionario + Esta palabra xa está presente no dicionario %s da usuaria. Por favor escribe outra. + Negro + Índigo + Océano + Axustes de HeliBoard + Preferir números traducidos sobre os latinos + Tes certeza de querer substituír o dicionario engadido \"%1$s\"? +\n +\nDicionario actual: +\n%2$s +\n +\nNovo dicionario: +\n%3$s + aquí + Axustar cores (noite) + Fondo da tecla función + O ficheiro seleccionado é para %1$s, mais agardábase %2$s. Usar igualmente para %2$s? + Alfabeto (Workman) + Revisor de Ortografía + Axustes do revisor de Ortografía de HeliBoard + Vas precisar a biblioteca para \'%s\': As bibliotecas incompatibles podería estragar a app ao escribir. +\n +\nAviso: a carga de código externo é un risco de seguridade. Usa só bibliotecas de fontes de confianza. + Intentar detectar URLs e equivalentes como unha soa palabra + Bosque + "Sen un dicionario, só terás suxestións procedentes de texto que escribises con anterioridade.<br> +\n Podes descargar dicionarios %1$s, ou comprobar se podes decargar directamente %3$s un dicionario para \"%2$s\"." + Pechar + Mostar características que igual non coñeces + \ No newline at end of file diff --git a/app/src/main/res/values-it/strings.xml b/app/src/main/res/values-it/strings.xml index 94275bb64..84290029b 100644 --- a/app/src/main/res/values-it/strings.xml +++ b/app/src/main/res/values-it/strings.xml @@ -3,8 +3,7 @@ Copyright (C) 2008 The Android Open Source Project modified SPDX-License-Identifier: Apache-2.0 AND GPL-3.0-only ---> - +--> "Cerca in nomi contatti" "La funzione di controllo ortografico usa voci dell\'elenco contatti" "Vibrazione tasti" @@ -171,4 +170,162 @@ "Cerca" "Pausa" "Attendi" + Mostrare sempre i suggerimenti + In alto + Input vocale + Mostra suggerimenti funzionali + Selezionare un file in un formato compatibile. Le informazioni sui formati sono disponibili %s. + Errore nel ripristinare il backup: %s + Utilizzare il dizionario personale del dispositivo per memorizzare le parole apprese + Backup + Passare il dito verso l\'alto sulla barra spaziatrice per cambiare la lingua + Lingua (priorità) + Aggiungi parole al dizionario personale + Toccare per modificare il layout grezzo + Lingue & Layout + Impossibile leggere file + È necessaria la libreria per \'%s\'. Le librerie incompatibili potrebbero bloccarsi quando si utilizza la digitazione gestuale. +\n +\nAttenzione: il caricamento di codice esterno può essere un rischio per la sicurezza. Utilizzare solo librerie di provenienza affidabile. + Elimina libreria + Lingua + Destra + Preferire i numeri localizzati a quelli latini + Barra spaziatrice per lo scorrimento della lingua + File di libreria sconosciuto. Si è sicuri di averlo ottenuto da una fonte affidabile e che sia per \'%s\'? + Mostra le varianti definite nelle lingue della tastiera (impostazione predefinita) + Aggiungere varianti comuni + Appunti + Riga numerica + Ripristino + Selezionare l\'ordine dei tasti a comparsa + Selezionare la fonte del suggerimento + Fornire una libreria nativa per abilitare la digitazione gestuale + Cerca di rilevare URL e simili come una singola parola + Caricare la libreria di digitazione gestuale + In basso + Selezionare i tasti della barra degli strumenti + Errore backup: %s + Mostra i suggerimenti se premendo a lungo un tasto si attivano funzionalità aggiuntive + Backup e ripristino + A sinistra + Seleziona parola + Sinistra + Veramente eliminare layout personalizzato %s? + Aggiungi layout personalizzato + Simboli + Rilevamento URL + A destra + Localizzare la riga dei numeri + Aggiungere tutte le varianti disponibili + Più autocorrezione + Distanza divisione + Ignorare la richiesta di altre applicazioni di disabilitare i suggerimenti + Imposta nome layout + Cambia lingua + Pulisci appunti + Ridurre spazio tra i tasti + Attenzione: La disattivazione di questa impostazione cancella i dati appresi + Carica libreria + Carica file + Copia layout esistente + Mostra più lettere con diacritici nel popup + Modalità ad una mano + Errore layout: %s + Digitazione multilingue + Salva o carica da file. Attenzione: il ripristino sovrascrive i dati esistenti + Layout + Correzione automatica anche quando non è esplicitamente richiesta dal campo di input + Cambia entrambi + %s (tipo tastiera Sebeolsik 390) + %s (Tipo tastiera Sebeolsik Final) + Diurna + Imposta un\'immagine di sfondo + Personalizza più simboli del layout + Alphabet (tipo tastiera Bépo) + Personalizza i simboli del layout + Più simboli + Imposta immagine per modalità diurna o notturna? + Dizionari + Configura la tastiera + Notturna + Spaziatura dal bordo in basso + Regola i colori (notte) + Scuro + Mostra solo i colori principali + Colori dinamici + Aspetto + Sfondo tasti + Colori + Sfondo tasto funzione + Questa parola è già presente nel dizionario utente %s. Si prega di digitarne un\'altra. + Arrotondato + Nero + Cioccolato + Rimuovere davvero il dizionario \"%s\" aggiunto dall\'utente? + Nuvoloso + GNU General Public License v3.0 + Errore: script non compatibile con questa tastiera + Descrizione delle funzionalità nascoste + Rosa + qui + Errore: Il file selezionato non è un file dizionario valido + dispositivo di archiviazione protetto + Colore barra di navigazione + Utilizza ancora + Foresta + Selezionare un dizionario da aggiungere. I dizionari in formato .dict possono essere scaricati %s. + Errore nel caricamento del file del dizionario + Blu grigio + testo barra spaziatrice + Chiaro + Aggiungi una parola + Testo riga suggerimenti + Clicca per l\'anteprima + Definito dall\'utente + Sostituisci dizionario + Aggiungi a %s + Sfondo della tastiera + Indaco + Visualizza su GitHub + Versione + Seleziona la lingua + Tasti chiave + Sfondo barra spaziatrice + Più scuro + Scegli colore automaticamente + Informazioni + Licenza Open-source + Oceano + Sabbia + Stile + Mostra le funzionalità che potrebbero passare inosservate + Colori (notte) + Mostra tutti i colori + Selezionare i colori per il testo e gli sfondi + Tasti suggerimento + Definito dall\'utente (notte) + Marrone + Sostituire davvero il dizionario aggiunto dall\'utente \"%1$s\"? +\n +\nDizionario attuale: +\n%2$s +\n +\nNuovo dizionario: +\n%3$s + Violetto + A quale lingua deve essere aggiunto il dizionario \"%1$s\" per %2$s? + Peso: + "Senza un dizionario, si otterranno solo suggerimenti per il testo immesso in precedenza.<br> +\n È possibile scaricare i dizionari %1$s, oppure verificare se un dizionario per \"%2$s\" può essere scaricato direttamente %3$s." + Non mostrare ancora + Il file selezionato è per %1$s, ma %2$s era previsto. Lo si usa ancora per %2$s? + Chiudi + Input gestuale + Toccare la lingua per aprire le impostazioni + Regola i colori + Salva log + Holo bianco + Dizionario interno principale + Aggiungi dizionario da file \ No newline at end of file diff --git a/app/src/main/res/values-kab/strings.xml b/app/src/main/res/values-kab/strings.xml index a3555f8bf..fbaa1e3b2 100644 --- a/app/src/main/res/values-kab/strings.xml +++ b/app/src/main/res/values-kab/strings.xml @@ -3,8 +3,7 @@ Copyright (C) The Android Open Source Project modified SPDX-License-Identifier: Apache-2.0 AND GPL-3.0-only ---> - +--> Imenyafen Iɣewwaren n HeliBoard Wiyyaḍ @@ -22,4 +21,33 @@ IH Kkes Aru yiwen n wawal + Nadi + Anegzum: + " ABCČDḌEƐFGǦƔHḤIJKLMNPQRṚSṢTṬUWXYZẒ" + Axuxi + Smiren + Aqehwi + Lexla + Lqem + Mdel + Seṛǧu + Aceɛlal + Aberkan + Ɣef + Iɣewwaren leqqayen + Asentel + Anekcum + Isumar + Abeddel n tutlayt + Tiqfilt n imujiyen + Amezwer n unagraw + Tutlayt + Asettef + Sefsex + Amezwer + sya + Udem + Azen + Uḍfir + Immed \ No newline at end of file diff --git a/app/src/main/res/values-pl/strings.xml b/app/src/main/res/values-pl/strings.xml index 5c2ba17ea..839db25f0 100644 --- a/app/src/main/res/values-pl/strings.xml +++ b/app/src/main/res/values-pl/strings.xml @@ -3,10 +3,9 @@ Copyright (C) 2008 The Android Open Source Project modified SPDX-License-Identifier: Apache-2.0 AND GPL-3.0-only ---> - +--> "Przeszukaj kontakty" - "Sprawdzanie pisowni bierze pod uwagę wpisy z listy kontaktów." + Sprawdzanie pisowni bierze pod uwagę wpisy z listy kontaktów "Wibracja przy naciśnięciu" "Dźwięk przy naciśnięciu" "Powiększ po naciśnięciu" @@ -93,9 +92,9 @@ Przełącz się na aplikację %s Następnie wybierz „%s” jako aktywną metodę wprowadzania tekstu. "Przełącz metody wprowadzania" - Gratulacje, Wszystko gotowe! + Gratulacje, wszystko gotowe! Teraz możesz pisać we wszystkich swoich ulubionych aplikacjach, używając aplikacji %s. - "Zakończone" + Zakończ "Pokaż ikonę aplikacji" "Wyświetlaj ikonę aplikacji w programie uruchamiającym" "Słowniki dodatkowe" @@ -121,13 +120,13 @@ "Więcej języków…" " ABCDEFGHIJKLMNOPQRSTUVWXYZ" Korekty - Różnorodne + Różne %smin. Bez limitu Wyłącz naukę nowych słów Więcej klawiszy Rząd numeryczny - Klawisz Emoji + Klawisz emotikonów Sprawdzanie pisowni HeliBoard Ustawienia sprawdzania pisowni HeliBoard Historia schowka @@ -172,4 +171,164 @@ "Szukaj" "Pauza" "Czekaj" - + Zawsze pokazuj sugestie + Dostosuj kolory (tryb nocny) + Główny słownik wewnętrzny + Ciemne + Pokaż tylko główne kolory + W górę + Pisanie głosowe + Dynamiczne kolory + Pokaż wskazówki na klawiszach funkcyjnych + Wybierz plik w kompatybilnym formacie. Informacje o formatach dostępne są %s. + Tło klawiszy + Błąd podczas przywracania kopii zapasowej: %s + Kolory + Tło klawiszy funkcyjnych + %s (Sebeolsik 390) + Używaj słownika osobistego do przechowywania nauczonych słów + To słowo znajduje się już w słowniku: %s. Wpisz inne. + Zaokrąglony + Kopia + Czarne + %s (Sebeolsik Final) + Czekoladowe + Na pewno usunąć słownik \"%s\" dodany przez użytkownika? + Pochmurne + Przesuń w górę po klawiszu spacji, aby zmienić język + GNU General Public License v3.0 + Dzienny + Błąd: skrypt nie jest kompatybilny z tą klawiaturą + Opis ukrytych funkcji + Język (dodatkowy) + Dodawaj słowa do słownika osobistego + Ustaw obraz jako tło klawiatury + Dotknij, aby edytować układ + Różowe + Języki i układy + Nie można odczytać pliku + stąd + Błąd: wybrany plik nie jest prawidłowym plikiem słownika + chronionej pamięci urządzenia + Koloruj pasek nawigacyjny + Tak + Leśne + Będziesz potrzebować biblioteki dla \\\'%s\\\'. Niekompatybilne biblioteki mogą powodować awarie podczas pisania gestami. +\n +\nUwaga: dodawanie zewnętrznego kodu może stanowić zagrożenie bezpieczeństwa. Korzystaj z biblioteki pochodzącej tylko z zaufanego źródła. + Wybierz słownik do dodania. Słowniki w formacie .dict można pobrać %s. + Usuń bibliotekę + Język (główny) + W prawo + Błąd podczas dodawania słownika + Preferuj liczby lokalne zamiast łacińskich + Spacja zmienia język + Nieznany plik biblioteki. Czy na pewno pochodzi z zaufanego źródła i jest przeznaczony dla \\\'%s\\\'? + ► Długie naciśnięcie klawisza schowka (opcjonalnego na pasku sugestii) spowoduje wklejenie zawartości schowka systemowego. <br> <br> ► Długie naciśnięcie przycisków na pasku narzędzi spowoduje przypięcie ich do paska sugestii. <br> <br> ► Przytrzymaj klawisz przecinka, aby uzyskać dostęp do schowka, emotikonów, trybu jednej ręki, ustawień lub zmiany języka: <br> \t•Przyciski emotikonów i zmiany języka znikną, jeśli masz włączone odpowiednie klawisze; <br> \t• W niektórych układach nie jest to klawisz przecinka, tylko inny w tym samym miejscu (np. w układzie Dvorak jest to \'q\'). <br> <br> ► Gdy tryb incognito jest włączony, słowa nie będą pamiętane, a emotikony nie zostaną dodane do ostatnio używanych. <br> <br> ► Dotknij ikonkę incognito, aby uzyskać dostęp do paska narzędzi. <br> <br> ► Pisanie za pomocą przesuwania po klawiszu: przesuń palcem od klawisza Shift do innego klawisza, aby wpisać pojedynczą wielką literę: <br> \t• Działa to również w przypadku klawisza \\\'?123\\\' do wpisywania pojedynczego symbolu z klawiatury symboli oraz podobnych klawiszy. <br> <br> ► Przytrzymaj sugestię na pasku sugestii, aby wyświetlić więcej sugestii oraz przycisk usuwania, aby ją usunąć. <br> <br> ► Przesuń palcem w górę na sugestii, aby wyświetlić więcej sugestii i puść, aby wybrać sugestię. <br> <br> ► Przytrzymaj wpis w schowku, aby go przypiąć (pozostanie w schowku do czasu odpięcia). <br> <br> ► Możesz dodać słowniki otwierając je w eksploratorze plików: <br> \t• Działa to tylko z <i>content-uris</i> nie z <i>file-uris</i>, co oznacza, że może nie działać z niektórymi eksploratorami plików. <br> <br> <i>Tryb debugowania / aplikacja w wersji debug</i> <br> <br> \t• Przytrzymaj sugestię, aby wyświetlić słownik źródłowy.<br> <br> \t• Korzystając z aplikacji w wersji debug, w ustawieniach zaawansowanych znajdziesz ustawienia debugowania, choć ich użyteczność jest ograniczona, z wyjątkiem dodawania słowników do dziennika zdarzeń. <br> <br> \t• W przypadku awarii aplikacji, po otwarciu ustawień zostaniesz zapytany, czy chcesz zapisać dzienniki awarii. <br> <br> \t• Podczas pisywania wielojęzycznego spacja wyświetli wartość służącą do określenia aktualnie używanego języka. <br> <br> \t• Sugestie będą miały na górze cyferki pokazujące wewnętrzne numery i słownik źródłowy (można to wyłączyć). ► Do użytkowników wykonujących ręczne kopie zapasowe z dostępem do roota: od Androida 7 udostępniony plik ustawień nie znajduje się w domyślnej lokalizacji, ponieważ aplikacja korzysta z %s. <br> Jest to konieczne, aby można było odczytać ustawienia przed odblokowaniem urządzenia, np. podczas uruchamiania. <br> Plik zwykle znajduje się w /data/user_de/0/package_id/shared_prefs/, ale może to zależeć od urządzenia i wersji Androida. + Niebiesko-szare + Tekst spacji + Jasne + Dodaj słowo + Tekst paska sugestii + Dotknij, aby wyświetlić podgląd + Pokaż warianty zdefiniowane w językach klawiatury (domyślnie) + Pokaż popularne warianty + Dostosuj układ większej liczby symboli + Własne + Zastąp słownik + Dodaj do %s + Tło klawiatury + Schowek + Indygo + Akcent + Zobacz na GitHubie + Rząd numeryczny + Alfabet (Bépo) + Przywracanie + Dostosuj układ symboli + Wybierz kolejność klawiszy w wyskakującym okienku + Wersja + Wybierz źródło wskazówek + Dodaj natywną bibliotekę, aby umożliwić pisanie gestami + Więcej symboli + Próbuj wykrywać adresy URL i podobne jako pojedyncze słowo + Wybierz język + Tekst klawiszy + Dodaj bibliotekę pisania gestami + Tło spacji + Bardzo ciemne + Ustawić obraz na tryb dzienny czy nocny? + Wybierz kolor automatycznie + O aplikacji + W dół + Wybierz klawisze paska narzędzi + Licencje open source + Niebieskie + Błąd podczas tworzenia kopii zapasowej: %s + Wyświetlaj wskazówki, jeśli długie naciśnięcie klawisza uruchamia dodatkową funkcję + Piaskowe + Kopia i przywracanie + Na początek + Styl + Zaznacz słowo + Pokaż funkcje, które mogą zostać niezauważone + Kolory (tryb nocny) + W lewo + Pokaż wszystkie kolory + Na pewno chcesz usunąć układ %s? + Słowniki + Dodaj własny układ + Wybierz kolory tekstu i tła + Tekst wskazówek + Skonfiguruj klawiaturę + Symbole + Dodaj słownik z pliku + Własne (tryb nocny) + Brązowe + Na pewno zastąpić słownik \"%1$s\" dodany przez użytkownika? +\n +\nObecny słownik: +\n%2$s +\n +\nNowy słownik: +\n%3$s + Wykrywaj adresy URL + Fiołkowe + Na koniec + Lokalny rząd numeryczny + Pokaż wszystkie dostępne warianty + Zaawansowana autokorekta + Szerokość podziału + Do którego języka dodać słownik \"%1$s\" przeznaczony dla: %2$s? + Wartość: + Ignoruj prośby innych aplikacji o wyłączenie sugestii + Nazwij układ + "Bez słownika będziesz otrzymywać jedynie sugestie dotyczące tekstu, który został wpisany wcześniej.<br> +\n Słowniki możesz pobrać %1$s lub sprawdź, czy słownik \"%2$s\" można pobrać bezpośrednio %3$s." + Zmień język + Wyczyść schowek + Nocny + Mniejszy odstęp między klawiszami + Nie pokazuj ponownie + Wybrano słownik %1$s, a nie %2$s. Na pewno chcesz użyć tego słownika dla języka: %2$s? + Uwaga: wyłączenie tego ustawienia spowoduje usunięcie nauczonych podpowiedzi + Dodaj bibliotekę + Dodaj plik + Zamknij + Wysokość dolnego odstępu + Skopiuj istniejący układ + Gest + Dotknij język, aby wyświetlić opcje + Pokaż więcej liter ze znakami diakrytycznymi w wyskakującym okienku + Tryb jednej ręki + Błąd układu: %s + Dostosuj kolory + Pisanie wielojęzyczne + Zapisz lub przywróć z pliku. Uwaga: przywrócenie spowoduje zastąpienie istniejących danych + Zapisz dziennik zdarzeń + Układ + Włącza autokorektę, nawet jeśli nie jest to wyraźnie wymagane przez pole wprowadzania + Białe Holo + Zmień oba + %s (eksperymentalny) + \ No newline at end of file diff --git a/app/src/main/res/values-ru/strings.xml b/app/src/main/res/values-ru/strings.xml index 22e075a4f..8f9966f39 100644 --- a/app/src/main/res/values-ru/strings.xml +++ b/app/src/main/res/values-ru/strings.xml @@ -3,8 +3,7 @@ Copyright (C) 2008 The Android Open Source Project modified SPDX-License-Identifier: Apache-2.0 AND GPL-3.0-only ---> - +--> "Поиск в контактах" "Использовать имена контактов при проверке правописания" "Виброотклик клавиш" @@ -14,7 +13,7 @@ Оформление "Непрерывный ввод" "Исправление текста" - "Дополнительные настройки" + Дополнительные "Тема" "Включить разделённую клавиатуру" "Смена способов ввода" @@ -25,7 +24,7 @@ "Подсказывать исправления на основе имен из списка контактов" "Пользовательские словари" "Точки автоматически" - "Вводить точку с пробелом двойным нажатием пробела." + Вводить точку с пробелом двойным нажатием пробела "Заглавные автоматически" "Писать первое слово предложения с прописной буквы" "Личный словарь" @@ -53,16 +52,16 @@ Английский (Великобритания) Английский (США) Испанский (США) - Хинглиш - Сербский (латиница) + хинглиш + сербский (латиница) Английский (Великобритания, %s) Английский (США, %s) Испанский (США, %s) - Хинглиш (%s) - Сербский (%s) + хинглиш (%s) + сербский (%s) %s (классическая) %s (Компактная) - Стандартная (Латиница) + стандартная (латиница) Латиница (QWERTY) Латиница (QWERTZ) Латиница (AZERTY) @@ -118,7 +117,7 @@ Изменение слова "В пользовательском словаре пока ничего нет. Добавлять слова можно с помощью кнопки \"Добавить (+)\"." Для всех языков - Другой язык + Другие языки… " АБВГДЕЁЖЗИЙКЛМНОПРСТУФХЦЧШЩЪЫЬЭЮЯ" Ряд с цифрами Всегда показывать ряд с цифрами @@ -151,7 +150,7 @@ Включить журнал буфера обмена Проверка правописания HeliBoard Настройки проверки правописания - %sмин. + %s мин Настройки HeliBoard Без ограничения Время хранения журнала буфера обмена @@ -160,7 +159,7 @@ Контуры клавиш Использовать тему системы Стиль темы - Rounded + Закругленная Цвета темы Цвета темы (тёмная тема) Внешний вид будет следовать настройкам системы @@ -199,9 +198,9 @@ Акцент Справка Версия - Посмотреть на GitHub - Лицензия с открытым исходным кодом - GNU General Public License v3.0 + Посмотреть на GitHub + Лицензия с открытым исходным кодом + GNU General Public License v3.0 Закрыть Языки системы Нажмите на язык, чтобы открыть настройки @@ -218,5 +217,116 @@ "Отправить" "Поиск" "Пауза" - "Пауза" - + Ждать + Всегда показывать предложения + Внутренний основной словарь + Показывать только основные цвета + Голосовой ввод + Динамические цвета + Показать функциональные подсказки + Выберите файл в совместимом формате. Информация о форматах доступна %s. + %s (Себольсик 390) + Использовать личный словарь устройства для хранения выученных слов + %s (Себольсик Финальная) + Шоколад + Облачная + День + Язык (приоритет) + Добавить слова в личный словарь + Установить фоновое изображение + Нажмите, чтобы отредактировать базовую раскладку + Розовая + Языки и раскладки + хранилище, защищенное устройством + Лес + Вам понадобится библиотека для «%s». Несовместимые библиотеки могут привести к сбою при использовании набора текста с помощью жестов. +\n +\nВнимание: загрузка внешнего кода может представлять угрозу безопасности. Используйте библиотеку только из источника, которому вы доверяете. + Удалить библиотеку + Язык + Предпочитать локализованные латинские цифры + Неизвестный файл библиотеки. Вы уверены, что получили его из надёжного источника и оно предназначено для «%s»? + Серо-голубой + Добавить слово + Текст полосы предложений + Показать варианты, определенные для языков клавиатуры (по умолчанию) + Добавить распространённые варианты + Заменить словарь + Добавить в %s + Буфер обмена + Индиго + Ряд с цифрами + Алфавит (Бепо) + Выберите порядок всплывающих клавиш + Выберите источник подсказки + Выберите язык + Установить изображение для дневного или ночного режима? + Выбор клавиш панели инструментов + Океан + Показывать подсказки, если длительное нажатие клавиши запускает дополнительные функции + Песок + Выберите слово + Показывать все цвета + Действительно удалить пользовательскую раскладку %s? + Словари + Добавить собственную раскладку + Настройка клавиатуры + Символы + Добавить словарь из файла + Коричневый + Виолетта + Локализация ряда с цифрами + Добавить все доступные варианты + Больше автокоррекции + Расстояние разделения + К какому языку следует добавить словарь \"%1$s\" для %2$s? + Игнорировать запросы других приложений об отключении предложений + Переключить язык + Очистить буфер обмена + Ночь + Больше не показывать + Предупреждение: Отключение этого параметра приведёт к удалению изученных данных + Загрузить библиотеку + Высота нижнего отступа + Ввод жестами + Показывать больше букв с диакритическими знаками при удержании + Режим одной руки + Сохранить лог + Раскладка + Автокоррекция, даже если это явно не запрошено в поле ввода + Holo Белая + Переключать оба + Вверх + Удалить пользовательский словарь \"%s\"? + Не получается прочитать файл + здесь + Выберите для добавления словаря. Словари в формате .dict можно скачать %s. + Вправо + Ошибка загрузки файла словаря + Редактировать раскладку дополнительных символов + Редактировать раскладку символов + Больше символов + Вниз + В конец влево + Влево + Заменить пользовательский словарь \"%1$s\"? +\n +\nТекущий словарь: +\n%2$s +\n +\nНовый словарь: +\n%3$s + В конец вправо + Высота: + Задать имя раскладки + Загрузить файл + Скопировать текущую раскладку + Ошибка раскладки: %s + Это слово уже присутствует в пользовательском словаре %s. Пожалуйста, введите другое. + Ошибка: скрипт несовместим с этой клавиатурой + Всё ещё используется + Выбранный файл предназначен для %1$s, но ожидался %2$s. Всё ещё используете его для %2$s? + Ошибка: выбранный файл не является корректным словарем + Без словаря вы будете получать предложения только для введенного ранее текста.<br> +\nВы можете загрузить словари %1$s или проверить, можно ли загрузить словарь для \"%2$s\" напрямую %3$s. + \ No newline at end of file diff --git a/app/src/main/res/values-uk/strings.xml b/app/src/main/res/values-uk/strings.xml index fc07dc120..65c85f36b 100644 --- a/app/src/main/res/values-uk/strings.xml +++ b/app/src/main/res/values-uk/strings.xml @@ -3,8 +3,7 @@ Copyright (C) 2008 The Android Open Source Project modified SPDX-License-Identifier: Apache-2.0 AND GPL-3.0-only ---> - +--> "Шукати імена контактів" "Для перевірки правопису використовувати список контактів" "Вібр. при натисканні клавіш" @@ -14,7 +13,7 @@ "Зовнішній вигляд" "Введення тексту жестами" "Виправлення тексту" - "Додатково" + Додаткові "Тема" "Увімкнути розділену клавіатуру" "Інші методи введення" @@ -53,16 +52,16 @@ "Англійська (Велика Британія)" "Англійська (США)" "Іспанська (США)" - "Хінґліш" - "Сербська (латиниця)" + гінґліш + сербська (латиниця) Англійська (Британія) (%s) Англійська (США) (%s) Іспанська (США) (%s) - Гінґліш (%s) - Сербська (%s) + гінґліш (%s) + сербська (%s) %s (Традиційна) %s (Компактна) - "Стандартна (латиниця)" + стандартна (латиниця) "Латиниця (QWERTY)" "Латиниця (QWERTZ)" "Латиниця (AZERTY)" @@ -165,9 +164,9 @@ Акцент Довідка Версія - Подивитися на GitHub - Ліцензія з відкритим кодом - GNU General Public License v3.0 + Подивитися на GitHub + Ліцензія з відкритим кодом + GNU General Public License v3.0 Використовувати мови системи Закрити Натисніть мову, щоб відкрити налаштування @@ -219,4 +218,10 @@ "Пошук" "Пауза" "Ждати" - + Мови та розкладки + Додати слова до особистого словника + Відстань розділення + Переключити мову + Попередження: Вимкнення цього параметра призведе до видалення отриманих даних + Переключити обидва + \ No newline at end of file From 2dfc82431998ee28cba61810823bb080d43695b4 Mon Sep 17 00:00:00 2001 From: Helium314 Date: Tue, 20 Feb 2024 08:44:12 +0100 Subject: [PATCH 14/40] allow customizing more layouts (number, phone, numpad, ...) --- .../keyboard_parser/KeyboardParser.kt | 41 +++++++++++----- .../main/java/helium314/keyboard/latin/App.kt | 8 ++++ .../settings/AdvancedSettingsFragment.kt | 48 ++++++++++++++----- .../settings/AppearanceSettingsFragment.kt | 5 +- .../keyboard/latin/settings/Settings.java | 18 ++----- .../keyboard/latin/utils/CustomLayoutUtils.kt | 10 ++-- .../helium314/keyboard/latin/utils/Ktx.kt | 7 +++ .../keyboard/latin/utils/PopupKeysUtils.kt | 15 +++--- app/src/main/res/values-af/strings.xml | 1 - app/src/main/res/values-am/strings.xml | 1 - app/src/main/res/values-ar/strings.xml | 4 +- app/src/main/res/values-as/strings.xml | 1 - app/src/main/res/values-az/strings.xml | 1 - app/src/main/res/values-b+sr+Latn/strings.xml | 1 - app/src/main/res/values-be/strings.xml | 1 - app/src/main/res/values-bg/strings.xml | 1 - app/src/main/res/values-bn/strings.xml | 1 - app/src/main/res/values-bs/strings.xml | 1 - app/src/main/res/values-ca/strings.xml | 1 - app/src/main/res/values-cs/strings.xml | 1 - app/src/main/res/values-da/strings.xml | 1 - app/src/main/res/values-de/strings.xml | 5 +- app/src/main/res/values-el/strings.xml | 1 - app/src/main/res/values-en-rAU/strings.xml | 1 - app/src/main/res/values-en-rCA/strings.xml | 1 - app/src/main/res/values-en-rGB/strings.xml | 1 - app/src/main/res/values-en-rIN/strings.xml | 1 - app/src/main/res/values-en-rXC/strings.xml | 1 - app/src/main/res/values-es-rUS/strings.xml | 1 - app/src/main/res/values-es/strings.xml | 1 - app/src/main/res/values-et/strings.xml | 1 - app/src/main/res/values-eu/strings.xml | 1 - app/src/main/res/values-fa/strings.xml | 1 - app/src/main/res/values-fi/strings.xml | 1 - app/src/main/res/values-fr-rCA/strings.xml | 1 - app/src/main/res/values-fr/strings.xml | 5 +- app/src/main/res/values-gl/strings.xml | 5 +- app/src/main/res/values-gu/strings.xml | 1 - app/src/main/res/values-hi/strings.xml | 1 - app/src/main/res/values-hr/strings.xml | 1 - app/src/main/res/values-hu/strings.xml | 1 - app/src/main/res/values-hy/strings.xml | 1 - app/src/main/res/values-in/strings.xml | 1 - app/src/main/res/values-is/strings.xml | 1 - app/src/main/res/values-it/strings.xml | 5 +- app/src/main/res/values-iw/strings.xml | 1 - app/src/main/res/values-ja/strings.xml | 1 - app/src/main/res/values-ka/strings.xml | 1 - app/src/main/res/values-kab/strings.xml | 1 - app/src/main/res/values-kk/strings.xml | 1 - app/src/main/res/values-km/strings.xml | 1 - app/src/main/res/values-kn/strings.xml | 1 - app/src/main/res/values-ko/strings.xml | 1 - app/src/main/res/values-ky/strings.xml | 1 - app/src/main/res/values-lo/strings.xml | 1 - app/src/main/res/values-lt/strings.xml | 1 - app/src/main/res/values-lv/strings.xml | 1 - app/src/main/res/values-mk/strings.xml | 1 - app/src/main/res/values-ml/strings.xml | 1 - app/src/main/res/values-mn/strings.xml | 1 - app/src/main/res/values-mr/strings.xml | 1 - app/src/main/res/values-ms/strings.xml | 1 - app/src/main/res/values-my/strings.xml | 1 - app/src/main/res/values-nb/strings.xml | 1 - app/src/main/res/values-ne/strings.xml | 1 - app/src/main/res/values-nl/strings.xml | 1 - app/src/main/res/values-pa-rPK/strings.xml | 1 - app/src/main/res/values-pa/strings.xml | 1 - app/src/main/res/values-pl/strings.xml | 5 +- app/src/main/res/values-pt-rBR/strings.xml | 1 - app/src/main/res/values-pt-rPT/strings.xml | 1 - app/src/main/res/values-pt/strings.xml | 1 - app/src/main/res/values-ro/strings.xml | 1 - app/src/main/res/values-ru/strings.xml | 5 +- app/src/main/res/values-si/strings.xml | 1 - app/src/main/res/values-sk/strings.xml | 1 - app/src/main/res/values-sl/strings.xml | 1 - app/src/main/res/values-sq/strings.xml | 1 - app/src/main/res/values-sr/strings.xml | 1 - app/src/main/res/values-sv/strings.xml | 1 - app/src/main/res/values-sw/strings.xml | 1 - app/src/main/res/values-ta/strings.xml | 1 - app/src/main/res/values-te/strings.xml | 1 - app/src/main/res/values-th/strings.xml | 1 - app/src/main/res/values-tl/strings.xml | 1 - app/src/main/res/values-tr/strings.xml | 1 - app/src/main/res/values-uk/strings.xml | 1 - app/src/main/res/values-ur/strings.xml | 1 - app/src/main/res/values-uz/strings.xml | 1 - app/src/main/res/values-vi/strings.xml | 1 - app/src/main/res/values-zh-rCN/strings.xml | 1 - app/src/main/res/values-zh-rHK/strings.xml | 1 - app/src/main/res/values-zh-rTW/strings.xml | 1 - app/src/main/res/values-zu/strings.xml | 1 - app/src/main/res/values/strings.xml | 39 +++++++-------- .../main/res/xml/prefs_screen_advanced.xml | 9 ++-- 96 files changed, 128 insertions(+), 185 deletions(-) diff --git a/app/src/main/java/helium314/keyboard/keyboard/internal/keyboard_parser/KeyboardParser.kt b/app/src/main/java/helium314/keyboard/keyboard/internal/keyboard_parser/KeyboardParser.kt index 015db6284..ef457f0b7 100644 --- a/app/src/main/java/helium314/keyboard/keyboard/internal/keyboard_parser/KeyboardParser.kt +++ b/app/src/main/java/helium314/keyboard/keyboard/internal/keyboard_parser/KeyboardParser.kt @@ -27,6 +27,8 @@ import helium314.keyboard.latin.utils.CUSTOM_LAYOUT_PREFIX import helium314.keyboard.latin.utils.InputTypeUtils import helium314.keyboard.latin.utils.POPUP_KEYS_LAYOUT import helium314.keyboard.latin.utils.POPUP_KEYS_NUMBER +import helium314.keyboard.latin.utils.ScriptUtils +import helium314.keyboard.latin.utils.ScriptUtils.script import helium314.keyboard.latin.utils.getLayoutFile import helium314.keyboard.latin.utils.runInLocale import helium314.keyboard.latin.utils.sumOf @@ -185,7 +187,7 @@ abstract class KeyboardParser(private val params: KeyboardParams, private val co } private fun addSymbolPopupKeys(baseKeys: MutableList>) { - val layoutName = Settings.readSymbolsLayoutName(context, params.mId.locale) + val layoutName = getLayoutFileName(params, context, overrideElementId = KeyboardId.ELEMENT_SYMBOLS) val layout = if (layoutName.startsWith(CUSTOM_LAYOUT_PREFIX)) { val parser = if (layoutName.endsWith("json")) JsonKeyboardParser(params, context) else SimpleKeyboardParser(params, context, false) @@ -766,17 +768,25 @@ abstract class KeyboardParser(private val params: KeyboardParams, private val co private fun Context.readAssetsFile(name: String) = assets.open(name).reader().readText() - private fun getLayoutFileName(params: KeyboardParams, context: Context) = when (params.mId.mElementId) { - KeyboardId.ELEMENT_SYMBOLS -> Settings.readSymbolsLayoutName(context, params.mId.locale) - KeyboardId.ELEMENT_SYMBOLS_SHIFTED -> Settings.readShiftedSymbolsLayoutName(context) - KeyboardId.ELEMENT_NUMPAD -> if (context.resources.configuration.orientation == Configuration.ORIENTATION_LANDSCAPE) - "numpad_landscape" + private fun getLayoutFileName(params: KeyboardParams, context: Context, overrideElementId: Int? = null): String { + var checkForCustom = true + val layoutName = when (overrideElementId ?: params.mId.mElementId) { + KeyboardId.ELEMENT_SYMBOLS -> if (params.mId.locale.script() == ScriptUtils.SCRIPT_ARABIC) LAYOUT_SYMBOLS_ARABIC else LAYOUT_SYMBOLS + KeyboardId.ELEMENT_SYMBOLS_SHIFTED -> LAYOUT_SYMBOLS_SHIFTED + KeyboardId.ELEMENT_NUMPAD -> if (context.resources.configuration.orientation == Configuration.ORIENTATION_LANDSCAPE) + LAYOUT_NUMPAD_LANDSCAPE else - "numpad" - KeyboardId.ELEMENT_NUMBER -> "number" - KeyboardId.ELEMENT_PHONE -> "phone" - KeyboardId.ELEMENT_PHONE_SYMBOLS -> "phone_symbols" - else -> params.mId.mSubtype.keyboardLayoutSetName.substringBeforeLast("+") + LAYOUT_NUMPAD + KeyboardId.ELEMENT_NUMBER -> LAYOUT_NUMBER + KeyboardId.ELEMENT_PHONE -> LAYOUT_PHONE + KeyboardId.ELEMENT_PHONE_SYMBOLS -> LAYOUT_PHONE_SYMBOLS + else -> { + checkForCustom = false // "custom" is already in keyboardLayoutSetName + params.mId.mSubtype.keyboardLayoutSetName.substringBeforeLast("+") + } + } + return if (checkForCustom) Settings.readLayoutName(layoutName, context) + else layoutName } // todo: @@ -862,3 +872,12 @@ private const val POPUP_EYS_NAVIGATE_EMOJI_PREVIOUS = "!fixedColumnOrder!3,!need private const val POPUP_EYS_NAVIGATE_EMOJI = "!icon/clipboard_action_key|!code/key_clipboard,!icon/emoji_action_key|!code/key_emoji" private const val POPUP_EYS_NAVIGATE_EMOJI_NEXT = "!fixedColumnOrder!3,!needsDividers!,!icon/clipboard_action_key|!code/key_clipboard,!icon/emoji_action_key|!code/key_emoji,!icon/next_key|!code/key_action_next" private const val POPUP_EYS_NAVIGATE_EMOJI_PREVIOUS_NEXT = "!fixedColumnOrder!4,!needsDividers!,!icon/previous_key|!code/key_action_previous,!icon/clipboard_action_key|!code/key_clipboard,!icon/emoji_action_key|!code/key_emoji,!icon/next_key|!code/key_action_next" + +const val LAYOUT_SYMBOLS = "symbols" +const val LAYOUT_SYMBOLS_SHIFTED = "symbols_shifted" +const val LAYOUT_SYMBOLS_ARABIC = "symbols_arabic" +const val LAYOUT_NUMPAD = "numpad" +const val LAYOUT_NUMPAD_LANDSCAPE = "numpad_landscape" +const val LAYOUT_NUMBER = "number" +const val LAYOUT_PHONE = "phone" +const val LAYOUT_PHONE_SYMBOLS = "phone_symbols" diff --git a/app/src/main/java/helium314/keyboard/latin/App.kt b/app/src/main/java/helium314/keyboard/latin/App.kt index e9af21340..819863aa9 100644 --- a/app/src/main/java/helium314/keyboard/latin/App.kt +++ b/app/src/main/java/helium314/keyboard/latin/App.kt @@ -8,6 +8,7 @@ import androidx.preference.PreferenceManager import helium314.keyboard.latin.common.LocaleUtils.constructLocale import helium314.keyboard.latin.settings.Settings import helium314.keyboard.latin.settings.USER_DICTIONARY_SUFFIX +import helium314.keyboard.latin.utils.CUSTOM_LAYOUT_PREFIX import helium314.keyboard.latin.utils.DeviceProtectedUtils import helium314.keyboard.latin.utils.DictionaryInfoUtils import helium314.keyboard.latin.utils.upgradeToolbarPref @@ -48,6 +49,13 @@ fun checkVersionUpgrade(context: Context) { } if (oldVersion == 0) // new install or restoring settings from old app name upgradesWhenComingFromOldAppName(context) + if (oldVersion == 1000) { // upgrade old custom layouts name + val layoutsDir = Settings.getLayoutsDir(context) + val oldShiftSymbolsFile = File(layoutsDir, "${CUSTOM_LAYOUT_PREFIX}shift_symbols") + if (oldShiftSymbolsFile.exists()) { + oldShiftSymbolsFile.renameTo(File(layoutsDir, "${CUSTOM_LAYOUT_PREFIX}symbols_shifted")) + } + } prefs.edit { putInt(Settings.PREF_VERSION_CODE, BuildConfig.VERSION_CODE) } } diff --git a/app/src/main/java/helium314/keyboard/latin/settings/AdvancedSettingsFragment.kt b/app/src/main/java/helium314/keyboard/latin/settings/AdvancedSettingsFragment.kt index 3eca1462b..a95f836cf 100644 --- a/app/src/main/java/helium314/keyboard/latin/settings/AdvancedSettingsFragment.kt +++ b/app/src/main/java/helium314/keyboard/latin/settings/AdvancedSettingsFragment.kt @@ -20,11 +20,18 @@ import androidx.preference.Preference import androidx.preference.PreferenceManager import kotlinx.serialization.encodeToString import kotlinx.serialization.json.Json -import helium314.keyboard.compat.locale import helium314.keyboard.dictionarypack.DictionaryPackConstants import helium314.keyboard.latin.utils.ChecksumCalculator import helium314.keyboard.keyboard.KeyboardLayoutSet import helium314.keyboard.keyboard.KeyboardSwitcher +import helium314.keyboard.keyboard.internal.keyboard_parser.LAYOUT_NUMBER +import helium314.keyboard.keyboard.internal.keyboard_parser.LAYOUT_NUMPAD +import helium314.keyboard.keyboard.internal.keyboard_parser.LAYOUT_NUMPAD_LANDSCAPE +import helium314.keyboard.keyboard.internal.keyboard_parser.LAYOUT_PHONE +import helium314.keyboard.keyboard.internal.keyboard_parser.LAYOUT_PHONE_SYMBOLS +import helium314.keyboard.keyboard.internal.keyboard_parser.LAYOUT_SYMBOLS +import helium314.keyboard.keyboard.internal.keyboard_parser.LAYOUT_SYMBOLS_ARABIC +import helium314.keyboard.keyboard.internal.keyboard_parser.LAYOUT_SYMBOLS_SHIFTED import helium314.keyboard.latin.AudioAndHapticFeedbackManager import helium314.keyboard.latin.BuildConfig import helium314.keyboard.latin.R @@ -38,6 +45,7 @@ import helium314.keyboard.latin.utils.CUSTOM_LAYOUT_PREFIX import helium314.keyboard.latin.utils.DeviceProtectedUtils import helium314.keyboard.latin.utils.JniUtils import helium314.keyboard.latin.utils.editCustomLayout +import helium314.keyboard.latin.utils.getStringResourceOrName import helium314.keyboard.latin.utils.infoDialog import helium314.keyboard.latin.utils.reloadEnabledSubtypes import helium314.keyboard.latin.utils.updateAdditionalSubtypes @@ -127,18 +135,8 @@ class AdvancedSettingsFragment : SubScreenFragment() { findPreference("backup_restore")?.setOnPreferenceClickListener { showBackupRestoreDialog() } findPreference("custom_background_image")?.setOnPreferenceClickListener { onClickLoadImage() } - findPreference("custom_symbols_layout")?.setOnPreferenceClickListener { - val layoutName = Settings.readSymbolsLayoutName(context, context.resources.configuration.locale()).takeIf { it.startsWith(CUSTOM_LAYOUT_PREFIX) } - val oldLayout = if (layoutName != null) null - else context.assets.open("layouts${File.separator}symbols.txt").reader().readText() - editCustomLayout(layoutName ?: "${CUSTOM_LAYOUT_PREFIX}symbols.txt", context, oldLayout, true) - true - } - findPreference("custom_shift_symbols_layout")?.setOnPreferenceClickListener { - val layoutName = Settings.readShiftedSymbolsLayoutName(context).takeIf { it.startsWith(CUSTOM_LAYOUT_PREFIX) } - val oldLayout = if (layoutName != null) null - else context.assets.open("layouts${File.separator}symbols_shifted.txt").reader().readText() - editCustomLayout(layoutName ?: "${CUSTOM_LAYOUT_PREFIX}shift_symbols.txt", context, oldLayout, true) + findPreference("custom_symbols_number_layouts")?.setOnPreferenceClickListener { + showCustomizeLayoutsDialog() true } } @@ -156,6 +154,30 @@ class AdvancedSettingsFragment : SubScreenFragment() { } } + private fun showCustomizeLayoutsDialog() { + val layouts = listOf(LAYOUT_SYMBOLS, LAYOUT_SYMBOLS_SHIFTED, LAYOUT_SYMBOLS_ARABIC, LAYOUT_NUMBER, LAYOUT_NUMPAD, LAYOUT_NUMPAD_LANDSCAPE, LAYOUT_PHONE, LAYOUT_PHONE_SYMBOLS) + val layoutNames = layouts.map { it.getStringResourceOrName("layout_", requireContext()) }.toTypedArray() + AlertDialog.Builder(requireContext()) + .setTitle(R.string.customize_symbols_number_layouts) + .setItems(layoutNames) { di, i -> + di.dismiss() + customizeLayout(layouts[i]) + } + .setNegativeButton(android.R.string.cancel, null) + .show() + } + + private fun customizeLayout(layout: String) { + val customLayoutName = Settings.readLayoutName(layout, context).takeIf { it.startsWith(CUSTOM_LAYOUT_PREFIX) } + val originalLayout = if (customLayoutName != null) null + else { + requireContext().assets.list("layouts")?.firstOrNull { it.startsWith("$layout.") } + ?.let { requireContext().assets.open("layouts" + File.separator + it).reader().readText() } + } + val displayName = layout.getStringResourceOrName("layout", requireContext()) + editCustomLayout(customLayoutName ?: "$CUSTOM_LAYOUT_PREFIX$layout.txt", requireContext(), originalLayout, displayName) + } + @SuppressLint("ApplySharedPref") private fun onClickLoadLibrary(): Boolean { // get architecture for telling user which file to use diff --git a/app/src/main/java/helium314/keyboard/latin/settings/AppearanceSettingsFragment.kt b/app/src/main/java/helium314/keyboard/latin/settings/AppearanceSettingsFragment.kt index c6c3155f8..1e8ef22e5 100644 --- a/app/src/main/java/helium314/keyboard/latin/settings/AppearanceSettingsFragment.kt +++ b/app/src/main/java/helium314/keyboard/latin/settings/AppearanceSettingsFragment.kt @@ -12,6 +12,7 @@ import androidx.preference.TwoStatePreference import helium314.keyboard.keyboard.KeyboardSwitcher import helium314.keyboard.keyboard.KeyboardTheme import helium314.keyboard.latin.R +import helium314.keyboard.latin.utils.getStringResourceOrName import java.lang.Float.max import java.lang.Float.min import java.util.* @@ -166,9 +167,7 @@ class AppearanceSettingsFragment : SubScreenFragment() { } private fun Array.getNamesFromResourcesIfAvailable(prefix: String) = - map { val resId = resources.getIdentifier("$prefix$it", "string", requireContext().packageName) - if (resId == 0) it else getString(resId) - }.toTypedArray() + map { it.getStringResourceOrName(prefix, requireContext()) }.toTypedArray() companion object { private const val PERCENTAGE_FLOAT = 100.0f diff --git a/app/src/main/java/helium314/keyboard/latin/settings/Settings.java b/app/src/main/java/helium314/keyboard/latin/settings/Settings.java index d0bc8a5d7..340aa66d4 100644 --- a/app/src/main/java/helium314/keyboard/latin/settings/Settings.java +++ b/app/src/main/java/helium314/keyboard/latin/settings/Settings.java @@ -528,26 +528,16 @@ public static int readMorePopupKeysPref(final SharedPreferences prefs) { }; } - public static String readSymbolsLayoutName(final Context context, final Locale locale) { + /** @return custom layout name if there is one for the given layout, else returns "layout" */ + public static String readLayoutName(final String layout, final Context context) { String[] layouts = getLayoutsDir(context).list(); if (layouts != null) { for (String name : layouts) { - if (name.startsWith(CustomLayoutUtilsKt.CUSTOM_LAYOUT_PREFIX + "symbols")) + if (name.startsWith(CustomLayoutUtilsKt.CUSTOM_LAYOUT_PREFIX + layout + ".")) return name; } } - return ScriptUtils.script(locale).equals(ScriptUtils.SCRIPT_ARABIC) ? "symbols_arabic" : "symbols"; - } - - public static String readShiftedSymbolsLayoutName(final Context context) { - String[] layouts = getLayoutsDir(context).list(); - if (layouts != null) { - for (String name : layouts) { - if (name.startsWith(CustomLayoutUtilsKt.CUSTOM_LAYOUT_PREFIX + "shift_symbols")) - return name; - } - } - return "symbols_shifted"; + return layout; } public static File getLayoutsDir(final Context context) { diff --git a/app/src/main/java/helium314/keyboard/latin/utils/CustomLayoutUtils.kt b/app/src/main/java/helium314/keyboard/latin/utils/CustomLayoutUtils.kt index c7a636241..b3b367a97 100644 --- a/app/src/main/java/helium314/keyboard/latin/utils/CustomLayoutUtils.kt +++ b/app/src/main/java/helium314/keyboard/latin/utils/CustomLayoutUtils.kt @@ -135,7 +135,7 @@ fun removeCustomLayoutFile(layoutName: String, context: Context) { getLayoutFile(layoutName, context).delete() } -fun editCustomLayout(layoutName: String, context: Context, startContent: String? = null, isSymbols: Boolean = false) { +fun editCustomLayout(layoutName: String, context: Context, startContent: String? = null, displayName: CharSequence? = null) { val file = getLayoutFile(layoutName, context) val editText = EditText(context).apply { setText(startContent ?: file.readText()) @@ -149,6 +149,7 @@ fun editCustomLayout(layoutName: String, context: Context, startContent: String? if (isJson == null) { editCustomLayout(layoutName, context, content) // todo: this actually always returns the "simple layout" error, even on a json layout with a single small error + // -> check in inverse expected order (set depending in current file name) infoDialog(context, context.getString(R.string.layout_error, Log.getLog(10).lastOrNull { it.tag == TAG }?.message)) } else { val wasJson = file.name.substringAfterLast(".") == "json" @@ -160,17 +161,16 @@ fun editCustomLayout(layoutName: String, context: Context, startContent: String? } } .setNegativeButton(android.R.string.cancel, null) - if (isSymbols) { - val name = if (layoutName.contains("shift")) context.getString(R.string.shift_symbols) else context.getString(R.string.popup_keys_symbols) + if (displayName != null) { if (file.exists()) { builder.setNeutralButton(R.string.delete) { _, _ -> - confirmDialog(context, context.getString(R.string.delete_layout, name), context.getString(R.string.delete)) { + confirmDialog(context, context.getString(R.string.delete_layout, displayName), context.getString(R.string.delete)) { file.delete() KeyboardSwitcher.getInstance().forceUpdateKeyboardTheme(context) } } } - builder.setTitle(name) + builder.setTitle(displayName) } builder.show() } diff --git a/app/src/main/java/helium314/keyboard/latin/utils/Ktx.kt b/app/src/main/java/helium314/keyboard/latin/utils/Ktx.kt index 7da0aee43..01467e0d6 100644 --- a/app/src/main/java/helium314/keyboard/latin/utils/Ktx.kt +++ b/app/src/main/java/helium314/keyboard/latin/utils/Ktx.kt @@ -1,5 +1,7 @@ package helium314.keyboard.latin.utils +import android.content.Context + // generic extension functions // adapted from Kotlin source: https://github.com/JetBrains/kotlin/blob/7a7d392b3470b38d42f80c896b7270678d0f95c3/libraries/stdlib/common/src/generated/_Collections.kt#L3004 @@ -10,3 +12,8 @@ inline fun Iterable.sumOf(selector: (T) -> Float): Float { } return sum } + +fun CharSequence.getStringResourceOrName(prefix: String, context: Context): CharSequence { + val resId = context.resources.getIdentifier(prefix + this, "string", context.packageName) + return if (resId == 0) this else context.getString(resId) +} diff --git a/app/src/main/java/helium314/keyboard/latin/utils/PopupKeysUtils.kt b/app/src/main/java/helium314/keyboard/latin/utils/PopupKeysUtils.kt index b524c0b32..123d4c3dd 100644 --- a/app/src/main/java/helium314/keyboard/latin/utils/PopupKeysUtils.kt +++ b/app/src/main/java/helium314/keyboard/latin/utils/PopupKeysUtils.kt @@ -133,29 +133,28 @@ fun reorderPopupKeysDialog(context: Context, key: String, defaultSetting: String } override fun onBindViewHolder(viewHolder: RecyclerView.ViewHolder, position: Int) { val (text, wasChecked) = orderedItems[position] - val displayTextId = context.resources.getIdentifier(text.lowercase(), "string", context.packageName) - val displayText = if (displayTextId == 0) text else context.getString(displayTextId) + val displayText = text.lowercase().getStringResourceOrName("", context) viewHolder.itemView.findViewById(R.id.popup_keys_type)?.text = displayText val switch = viewHolder.itemView.findViewById(R.id.popup_keys_switch) switch?.setOnCheckedChangeListener(null) switch?.isChecked = wasChecked switch?.isEnabled = !(key.contains(Settings.PREF_POPUP_KEYS_ORDER) && text == POPUP_KEYS_LAYOUT) // layout can't be disabled switch?.setOnCheckedChangeListener { _, isChecked -> - val position = orderedItems.indexOfFirst { it.first == text } - orderedItems[position] = text to isChecked + val pos = orderedItems.indexOfFirst { it.first == text } + orderedItems[pos] = text to isChecked } } } rv.adapter = adapter ItemTouchHelper(object : ItemTouchHelper.SimpleCallback(ItemTouchHelper.UP or ItemTouchHelper.DOWN, 0) { - override fun onMove(p0: RecyclerView, p1: RecyclerView.ViewHolder, p2: RecyclerView.ViewHolder): Boolean { - val pos1 = p1.absoluteAdapterPosition - val pos2 = p2.absoluteAdapterPosition + override fun onMove(rv: RecyclerView, viewHolder: RecyclerView.ViewHolder, target: RecyclerView.ViewHolder): Boolean { + val pos1 = viewHolder.absoluteAdapterPosition + val pos2 = target.absoluteAdapterPosition Collections.swap(orderedItems, pos1, pos2) adapter.notifyItemMoved(pos1, pos2) return true } - override fun onSwiped(p0: RecyclerView.ViewHolder, p1: Int) { } + override fun onSwiped(rv: RecyclerView.ViewHolder, direction: Int) { } }).attachToRecyclerView(rv) adapter.submitList(orderedItems) AlertDialog.Builder(context) diff --git a/app/src/main/res/values-af/strings.xml b/app/src/main/res/values-af/strings.xml index c0f248f51..22a265f25 100644 --- a/app/src/main/res/values-af/strings.xml +++ b/app/src/main/res/values-af/strings.xml @@ -102,7 +102,6 @@ "Woordeboek beskikbaar" "Kan nie aan woordeboekdiens koppel nie" "Geen woordeboeke beskikbaar nie" - "Verfris" "Laas opgedateer" "Hoofwoordeboek" "Instellings" diff --git a/app/src/main/res/values-am/strings.xml b/app/src/main/res/values-am/strings.xml index 437af0aee..5b7bef05f 100644 --- a/app/src/main/res/values-am/strings.xml +++ b/app/src/main/res/values-am/strings.xml @@ -102,7 +102,6 @@ "መዝገበ-ቃላት ይገኛል" "ወደ መዝገበ-ቃላት አገልገሎት ማገናኘት ላይ ችግር" "ምንም መዝገበ-ቃላት የሉም" - "አድስ" "ለመጨረሻ ጊዜ የተዘመነው" "ዋና መዝገበ-ቃላት" "ቅንብሮች" diff --git a/app/src/main/res/values-ar/strings.xml b/app/src/main/res/values-ar/strings.xml index 1c494f849..155354342 100644 --- a/app/src/main/res/values-ar/strings.xml +++ b/app/src/main/res/values-ar/strings.xml @@ -101,7 +101,6 @@ "القاموس متاح" "مشكلة في الاتصال بخدمة القاموس" "لا تتوفر أي قواميس" - "تحديث" "تاريخ آخر تحديث" "القاموس الرئيسي" "إعدادات" @@ -226,10 +225,9 @@ وضع اليد الواحدة تقليص المسافة ما بين الأزرار تحميل ملف - المزيد من الرموز + المزيد من الرموز إضافة تخطيط مخصص تعذرت قراءة الملف - تخصيص تخطيط الرموز القواميس إعداد لوحة المفاتيح القواميس المدمَجَة diff --git a/app/src/main/res/values-as/strings.xml b/app/src/main/res/values-as/strings.xml index 022ded004..a71cf5c05 100644 --- a/app/src/main/res/values-as/strings.xml +++ b/app/src/main/res/values-as/strings.xml @@ -71,7 +71,6 @@ "অভিধান উপলব্ধ" "অভিধান সেৱাৰ লগত সংযোগ কৰোঁতে সমস্যাৰ সৃষ্টি হৈছে" "কোনো অভিধান নাই" - "ৰিফ্ৰেশ্ব কৰক" "অন্তিমবাৰ আপডে’ট কৰা হৈছিল" "মুখ্য অভিধান" "ছেটিংসমূহ" diff --git a/app/src/main/res/values-az/strings.xml b/app/src/main/res/values-az/strings.xml index 4768980a8..fb22fff0b 100644 --- a/app/src/main/res/values-az/strings.xml +++ b/app/src/main/res/values-az/strings.xml @@ -102,7 +102,6 @@ "Lüğət mövcuddur" "Lüğət xidmətinə bağlantı problemi" "Lüğət mövcud deyil" - "Təzələ" "Son yeniləmə" "Əsas lüğət" "Ayarlar" diff --git a/app/src/main/res/values-b+sr+Latn/strings.xml b/app/src/main/res/values-b+sr+Latn/strings.xml index 7bc2d0463..933379074 100644 --- a/app/src/main/res/values-b+sr+Latn/strings.xml +++ b/app/src/main/res/values-b+sr+Latn/strings.xml @@ -102,7 +102,6 @@ "Rečnik je dostupan" "Problem pri povezivanju s uslugom rečnika" "Nema dostupnih rečnika" - "Osveži" "Poslednje ažuriranje" "Glavni rečnik" "Podešavanja" diff --git a/app/src/main/res/values-be/strings.xml b/app/src/main/res/values-be/strings.xml index ba31d97dc..86007d073 100644 --- a/app/src/main/res/values-be/strings.xml +++ b/app/src/main/res/values-be/strings.xml @@ -102,7 +102,6 @@ "Даступны слоўнік" "Праблема падключэння да слоўніка" "Слоўнікаў няма" - "Абнавіць" "Апошняе абнаўленне" "Асноўны слоўнік" "Налады" diff --git a/app/src/main/res/values-bg/strings.xml b/app/src/main/res/values-bg/strings.xml index a23d0fb64..d00c91add 100644 --- a/app/src/main/res/values-bg/strings.xml +++ b/app/src/main/res/values-bg/strings.xml @@ -102,7 +102,6 @@ "Речникът е налице" "Няма връзка с речниците" "Няма налични речници" - "Опресняване" "Последна актуализация:" "Основен речник" "Настройки" diff --git a/app/src/main/res/values-bn/strings.xml b/app/src/main/res/values-bn/strings.xml index 45f733830..cdb212939 100644 --- a/app/src/main/res/values-bn/strings.xml +++ b/app/src/main/res/values-bn/strings.xml @@ -204,7 +204,6 @@ অভিধান উপলব্ধ অভিধান পরিষেবার সাথে সংযুক্ত হতে সমস্যা হচ্ছে কোনো অভিধান উপলব্ধ নয় - "রিফ্রেশ" সর্বশেষ আপডেট মূল অভিধান সেটিংস diff --git a/app/src/main/res/values-bs/strings.xml b/app/src/main/res/values-bs/strings.xml index c95caa32a..e750a1320 100644 --- a/app/src/main/res/values-bs/strings.xml +++ b/app/src/main/res/values-bs/strings.xml @@ -103,7 +103,6 @@ "Rječnik je dostupan" "Problem prilikom povezivanja na uslugu rječnika" "Nema dostupnih rječnika" - "Osvježi" "Posljednji put ažurirano" "Glavni rječnik" "Postavke" diff --git a/app/src/main/res/values-ca/strings.xml b/app/src/main/res/values-ca/strings.xml index 3e8809560..fba7d4d98 100644 --- a/app/src/main/res/values-ca/strings.xml +++ b/app/src/main/res/values-ca/strings.xml @@ -102,7 +102,6 @@ "Diccionari disponible" "Error en connectar amb el diccionari" "Cap diccion. dispon." - "Actualitza" "Última actualització" "Diccionari principal" "Configuració" diff --git a/app/src/main/res/values-cs/strings.xml b/app/src/main/res/values-cs/strings.xml index 8f8e1ab5f..af86638e8 100644 --- a/app/src/main/res/values-cs/strings.xml +++ b/app/src/main/res/values-cs/strings.xml @@ -103,7 +103,6 @@ "Slovník k dispozici" "Chyba přip. k slovníku" "Žádné slovníky" - "Aktualizovat" "Poslední aktualizace" "Hlavní slovník" "Nastavení" diff --git a/app/src/main/res/values-da/strings.xml b/app/src/main/res/values-da/strings.xml index 80ef0cf27..474578443 100644 --- a/app/src/main/res/values-da/strings.xml +++ b/app/src/main/res/values-da/strings.xml @@ -102,7 +102,6 @@ "Ordbog er tilgængelig" "Ingen ordbogstjeneste" "Ingen tilg. ordbøger" - "Opdater" "Sidst opdateret" "Hovedordbog" "Indstillinger" diff --git a/app/src/main/res/values-de/strings.xml b/app/src/main/res/values-de/strings.xml index 5ba450120..301c39984 100644 --- a/app/src/main/res/values-de/strings.xml +++ b/app/src/main/res/values-de/strings.xml @@ -101,7 +101,6 @@ "Wörterbuch verfügbar" "Kein Wörterbuchdienst" "Keine Wörterbücher" - "Aktualisieren" "Zuletzt aktualisiert" "Allgemeines Wörterbuch" "Einstellungen" @@ -231,7 +230,6 @@ Für Vorschau klicken In den Tastatursprachen definierte Varianten anzeigen (Standard) Gemeinsame Varianten hinzufügen - Layout für weitere Symbole anpassen Benutzerdefiniert Wörterbuch ersetzen Hinzufügen zu %s @@ -243,12 +241,11 @@ Zahlenreihe Alphabet (Bépo) Wiederherstellen - Symbollayout anpassen Popup-Tastenreihenfolge wählen Version Hinweis-Quelle wählen Native Bibliothek bereitstellen um Gesteneingabe zu aktivieren - Mehr Symbole + Mehr Symbole Versuche URLs und ähnliches als einzelnes Wort zu erkennen Sprache auswählen Tastenbeschriftung diff --git a/app/src/main/res/values-el/strings.xml b/app/src/main/res/values-el/strings.xml index 1794f86db..6d2ca3c13 100644 --- a/app/src/main/res/values-el/strings.xml +++ b/app/src/main/res/values-el/strings.xml @@ -102,7 +102,6 @@ "Διαθέσιμο λεξικό" "Πρόβλ. σύνδ. στο λεξικό." "Δεν υπάρχουν λεξικά" - "Ανανέωση" "Τελευταία ενημέρωση" "Κύριο λεξικό" "Ρυθμίσεις" diff --git a/app/src/main/res/values-en-rAU/strings.xml b/app/src/main/res/values-en-rAU/strings.xml index c3f02c6f7..926bc0514 100644 --- a/app/src/main/res/values-en-rAU/strings.xml +++ b/app/src/main/res/values-en-rAU/strings.xml @@ -102,7 +102,6 @@ "Dictionary available" "Problem connecting to dictionary service" "No dictionaries available" - "Refresh" "Last updated" "Main dictionary" "Settings" diff --git a/app/src/main/res/values-en-rCA/strings.xml b/app/src/main/res/values-en-rCA/strings.xml index c3f02c6f7..926bc0514 100644 --- a/app/src/main/res/values-en-rCA/strings.xml +++ b/app/src/main/res/values-en-rCA/strings.xml @@ -102,7 +102,6 @@ "Dictionary available" "Problem connecting to dictionary service" "No dictionaries available" - "Refresh" "Last updated" "Main dictionary" "Settings" diff --git a/app/src/main/res/values-en-rGB/strings.xml b/app/src/main/res/values-en-rGB/strings.xml index 79c3658c7..309b97524 100644 --- a/app/src/main/res/values-en-rGB/strings.xml +++ b/app/src/main/res/values-en-rGB/strings.xml @@ -102,7 +102,6 @@ "Dictionary available" "Problem connecting to dictionary service" "No dictionaries available" - "Refresh" "Last updated" "Main dictionary" "Settings" diff --git a/app/src/main/res/values-en-rIN/strings.xml b/app/src/main/res/values-en-rIN/strings.xml index ce3cb6e9a..002cd7e90 100644 --- a/app/src/main/res/values-en-rIN/strings.xml +++ b/app/src/main/res/values-en-rIN/strings.xml @@ -102,7 +102,6 @@ "Dictionary available" "Problem connecting to dictionary service" "No dictionaries available" - "Refresh" "Last updated" "Main dictionary" "Settings" diff --git a/app/src/main/res/values-en-rXC/strings.xml b/app/src/main/res/values-en-rXC/strings.xml index d67c5f24e..549bb00e4 100644 --- a/app/src/main/res/values-en-rXC/strings.xml +++ b/app/src/main/res/values-en-rXC/strings.xml @@ -102,7 +102,6 @@ "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‏‎‏‎‏‏‏‏‏‏‏‏‎‏‏‏‎‎‏‎‎‎‏‏‎‎‏‎‎‏‏‏‎‏‏‎‎‏‏‏‏‎‏‏‎‎‎‎‎‏‏‎‎‏‏‏‏‏‏‏‏‎‏‎‎‏‏‎‎‏‎‎‏‎‏‎Dictionary available‎‏‎‎‏‎" "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‏‎‏‎‏‏‏‏‏‏‏‏‏‎‏‎‎‎‎‎‏‎‎‎‎‏‎‎‏‏‏‏‎‏‎‏‎‏‏‎‏‏‏‏‏‏‎‎‏‏‎‏‎‎‏‏‏‏‏‏‏‎‏‏‎‎‎‏‏‏‏‎‎‎‎‎‎Problem connecting to dictionary service‎‏‎‎‏‎" "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‏‎‏‎‏‏‏‏‏‏‏‏‏‎‏‏‏‎‏‎‎‎‎‏‏‏‎‎‎‏‎‎‏‏‎‎‏‎‎‎‏‎‎‎‎‎‏‎‎‏‎‎‎‎‎‏‏‎‎‎‏‏‏‎‎‎‎‎‏‏‏‎‏‏‏‎‎No dictionaries available‎‏‎‎‏‎" - "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‏‎‏‎‏‏‏‏‏‏‏‏‏‏‏‎‎‏‎‏‎‏‎‎‏‏‎‏‎‏‏‎‏‎‏‏‏‏‏‎‎‏‎‏‏‏‏‏‏‎‏‏‏‎‎‎‎‏‎‎‎‏‎‎‏‎‎‏‎‎‎‏‏‏‎‏‎‎Refresh‎‏‎‎‏‎" "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‏‎‏‎‏‏‏‏‏‏‏‏‏‎‏‎‎‎‎‎‏‏‏‏‏‏‎‏‎‎‏‎‎‎‏‎‏‏‎‏‏‏‏‏‏‎‎‎‏‏‎‎‎‎‎‏‎‎‏‏‏‏‏‎‎‎‎‎‎‏‎‎‏‏‎‎‎Last updated‎‏‎‎‏‎" "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‏‎‏‎‏‏‏‏‏‏‏‏‎‎‏‎‎‏‏‎‏‎‎‏‏‎‎‎‏‎‏‎‎‏‏‏‏‎‏‏‎‎‏‎‎‏‏‏‏‎‎‏‏‎‏‎‎‏‏‏‏‎‎‎‎‎‏‎‏‏‎‏‏‎‎Main dictionary‎‏‎‎‏‎" "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‏‎‏‎‏‏‏‏‏‏‏‏‏‎‏‎‏‎‎‏‏‏‏‎‎‏‏‎‎‏‎‏‎‎‏‎‎‏‎‏‏‎‎‏‏‎‏‏‏‎‎‎‏‏‏‎‏‏‏‎‎‏‎‎‎‏‎‏‏‏‎‏‏‎‎‎‎Settings‎‏‎‎‏‎" diff --git a/app/src/main/res/values-es-rUS/strings.xml b/app/src/main/res/values-es-rUS/strings.xml index d7f598bc0..e6d789ed2 100644 --- a/app/src/main/res/values-es-rUS/strings.xml +++ b/app/src/main/res/values-es-rUS/strings.xml @@ -102,7 +102,6 @@ "Diccionario disponible" "Err. conex. con dic." "No hay diccionarios." - "Actualizar" "Última actualización" "Diccionario principal" "Configuración" diff --git a/app/src/main/res/values-es/strings.xml b/app/src/main/res/values-es/strings.xml index be807d7bb..f6d3ee122 100644 --- a/app/src/main/res/values-es/strings.xml +++ b/app/src/main/res/values-es/strings.xml @@ -102,7 +102,6 @@ "Diccionario disponible" "Error al conectar" "No hay diccionarios" - "Actualizar" "Última actualización" "Diccionario principal" "Ajustes" diff --git a/app/src/main/res/values-et/strings.xml b/app/src/main/res/values-et/strings.xml index df8b06ba9..91f3255e7 100644 --- a/app/src/main/res/values-et/strings.xml +++ b/app/src/main/res/values-et/strings.xml @@ -102,7 +102,6 @@ "Sõnastik on saadaval" "Probleem sõnastikuga ühendumisel" "Sõnastikke pole" - "Värskenda" "Viimati värskendatud" "Peamine sõnastik" "Seaded" diff --git a/app/src/main/res/values-eu/strings.xml b/app/src/main/res/values-eu/strings.xml index 90828b816..45acd065e 100644 --- a/app/src/main/res/values-eu/strings.xml +++ b/app/src/main/res/values-eu/strings.xml @@ -102,7 +102,6 @@ "Hiztegia erabilgarri" "Arazoa gertatu da hiztegi-zerbitzuarekin konektatzean" "Ez dago hiztegirik erabilgarri" - "Freskatu" "Azken eguneratzea" "Hiztegi nagusia" "Ezarpenak" diff --git a/app/src/main/res/values-fa/strings.xml b/app/src/main/res/values-fa/strings.xml index 80adb0a95..e46a5d4b3 100644 --- a/app/src/main/res/values-fa/strings.xml +++ b/app/src/main/res/values-fa/strings.xml @@ -102,7 +102,6 @@ "واژه‌نامه موجود است" "مشکل اتصال به سرویس واژه‌نامه" "هیچ فرهنگ لغتی موجود نیست" - "بازخوانی" "آخرین به‌روزرسانی" "واژه‌نامه اصلی" "تنظیمات" diff --git a/app/src/main/res/values-fi/strings.xml b/app/src/main/res/values-fi/strings.xml index 429e51a11..65cdf22de 100644 --- a/app/src/main/res/values-fi/strings.xml +++ b/app/src/main/res/values-fi/strings.xml @@ -102,7 +102,6 @@ "Sanakirja saatavilla" "Ei yhteyttä sanak." "Ei sanak. saatavilla" - "Päivitä" "Päivitetty viimeksi" "Pääsanakirja" "Asetukset" diff --git a/app/src/main/res/values-fr-rCA/strings.xml b/app/src/main/res/values-fr-rCA/strings.xml index 99c81ad2c..905d93b16 100644 --- a/app/src/main/res/values-fr-rCA/strings.xml +++ b/app/src/main/res/values-fr-rCA/strings.xml @@ -102,7 +102,6 @@ "Dictionnaire disponible" "Pas de service dico." "Aucun dictionnaire" - "Actualiser" "Dernière mise à jour" "Dictionnaire principal" "Paramètres" diff --git a/app/src/main/res/values-fr/strings.xml b/app/src/main/res/values-fr/strings.xml index 6a6a2005c..63f7b58f7 100644 --- a/app/src/main/res/values-fr/strings.xml +++ b/app/src/main/res/values-fr/strings.xml @@ -91,9 +91,7 @@ Souhaitez-vous réellement supprimer la disposition personnalisée %s? Erreur de disposition : %s Appuyez pour modifier la disposition d\'origine - Personnaliser la dispostion des symboles - Personnaliser davantage la disposition des symboles - Plus de symboles + Plus de symboles Définir une image d\'arrière-plan Définir l\'image pour le mode jour ou nuit ? Jour @@ -150,7 +148,6 @@ Nouveau dictionnaire: "Dictionnaire disponible" "Pas de service dico." "Aucun dictionnaire" - "Actualiser" "Dernière mise à jour" "Dictionnaire principal" "Supprimer" diff --git a/app/src/main/res/values-gl/strings.xml b/app/src/main/res/values-gl/strings.xml index 5c00cdde8..72d778f42 100644 --- a/app/src/main/res/values-gl/strings.xml +++ b/app/src/main/res/values-gl/strings.xml @@ -101,7 +101,6 @@ "Dicionario dispoñible" "Erro ao conectar" "Non hai dicionarios" - "Actualizar" "Última actualización" "Dicionario principal" "Configuración" @@ -279,9 +278,7 @@ Queres eliminar a disposición persoal %s? Erro na disposición: %s Toca para editar a disposición - Personaliza os símbolos da disposición - Personaliza máis símbolos na disposición - Máis símbolos + Máis símbolos Establece imaxe de fondo Establecer para o modo diurno ou nocturno? Día diff --git a/app/src/main/res/values-gu/strings.xml b/app/src/main/res/values-gu/strings.xml index da806891d..bca265c8f 100644 --- a/app/src/main/res/values-gu/strings.xml +++ b/app/src/main/res/values-gu/strings.xml @@ -102,7 +102,6 @@ "શબ્દકોશ ઉપલબ્ધ છે" "શબ્દકોશ સેવા સાથે કનેક્ટ થવામાં સમસ્યા" "કોઈ શબ્દકોશ ઉપલબ્ધ નથી" - "તાજું કરો" "છેલ્લે અપડેટ કર્યું" "મુખ્ય શબ્દકોશ" "સેટિંગ્સ" diff --git a/app/src/main/res/values-hi/strings.xml b/app/src/main/res/values-hi/strings.xml index 9da1c1ddc..e8ec9529a 100644 --- a/app/src/main/res/values-hi/strings.xml +++ b/app/src/main/res/values-hi/strings.xml @@ -102,7 +102,6 @@ "शब्दकोश उपलब्‍ध" "शब्दकोश सेवा से कनेक्ट करने में समस्या" "डिक्‍शनरी अनुपलब्‍ध" - "रीफ़्रेश करें" "आख़री बार अपडेट किया गया" "मुख्‍य डिक्‍शनरी" "सेटिंग" diff --git a/app/src/main/res/values-hr/strings.xml b/app/src/main/res/values-hr/strings.xml index 1ddf2929b..6e152b7a5 100644 --- a/app/src/main/res/values-hr/strings.xml +++ b/app/src/main/res/values-hr/strings.xml @@ -102,7 +102,6 @@ "Dostupan je rječnik" "Nema usluge rječnika" "Rječnici nedostupni" - "Osvježavanje" "Zadnje ažuriranje" "Glavni rječnik" "Postavke" diff --git a/app/src/main/res/values-hu/strings.xml b/app/src/main/res/values-hu/strings.xml index 06c6e4081..62794a23d 100644 --- a/app/src/main/res/values-hu/strings.xml +++ b/app/src/main/res/values-hu/strings.xml @@ -102,7 +102,6 @@ "Van rendelkezésre álló szótár" "Csatlakozási hiba" "Nincs szótár" - "Frissítés" "Legutóbb frissítve" "Fő szótár" "Beállítások" diff --git a/app/src/main/res/values-hy/strings.xml b/app/src/main/res/values-hy/strings.xml index f8bad4c7b..68e699dcd 100644 --- a/app/src/main/res/values-hy/strings.xml +++ b/app/src/main/res/values-hy/strings.xml @@ -102,7 +102,6 @@ "Բառարանն առկա է" "Բառարանային ծառայությանը միացման խնդիր կա" "Բառարաններ չկան" - "Թարմացնել" "Վերջին անգամ թարմացվել է" "Հիմնական բառարան" "Կարգավորումներ" diff --git a/app/src/main/res/values-in/strings.xml b/app/src/main/res/values-in/strings.xml index f233e9f5d..311530e88 100644 --- a/app/src/main/res/values-in/strings.xml +++ b/app/src/main/res/values-in/strings.xml @@ -102,7 +102,6 @@ "Kamus yang tersedia" "Problem koneksi kamus" "Tidak tersedia kamus" - "Segarkan" "Terakhir diperbarui" "Kamus utama" "Setelan" diff --git a/app/src/main/res/values-is/strings.xml b/app/src/main/res/values-is/strings.xml index 19573d906..a3af390c8 100644 --- a/app/src/main/res/values-is/strings.xml +++ b/app/src/main/res/values-is/strings.xml @@ -102,7 +102,6 @@ "Orðabók í boði" "Vandamál við að tengjast orðabókarþjónustu" "Engar orðabækur" - "Endurnýja" "Síðast uppfært" "Aðalorðabók" "Stillingar" diff --git a/app/src/main/res/values-it/strings.xml b/app/src/main/res/values-it/strings.xml index 84290029b..be3a589d2 100644 --- a/app/src/main/res/values-it/strings.xml +++ b/app/src/main/res/values-it/strings.xml @@ -101,7 +101,6 @@ "Dizionario disponibile" "Conness. diz. imposs" "Nessun dizionario" - "Aggiorna" "Ultimo aggiornamento" "Dizionario principale" "Impostazioni" @@ -241,10 +240,8 @@ %s (Tipo tastiera Sebeolsik Final) Diurna Imposta un\'immagine di sfondo - Personalizza più simboli del layout Alphabet (tipo tastiera Bépo) - Personalizza i simboli del layout - Più simboli + Più simboli Imposta immagine per modalità diurna o notturna? Dizionari Configura la tastiera diff --git a/app/src/main/res/values-iw/strings.xml b/app/src/main/res/values-iw/strings.xml index 7bc36fca9..ef2612bdc 100644 --- a/app/src/main/res/values-iw/strings.xml +++ b/app/src/main/res/values-iw/strings.xml @@ -102,7 +102,6 @@ "מילון זמין" "בעיה בהתחברות לשירות המילון" "אין מילונים זמינים" - "רענן" "עודכן לאחרונה" "מילון ראשי" "הגדרות" diff --git a/app/src/main/res/values-ja/strings.xml b/app/src/main/res/values-ja/strings.xml index 311fed8b3..5f2721f6d 100644 --- a/app/src/main/res/values-ja/strings.xml +++ b/app/src/main/res/values-ja/strings.xml @@ -102,7 +102,6 @@ "辞書を利用できます" "辞書に接続できません" "辞書はありません" - "更新" "最終更新" "メイン辞書" "設定" diff --git a/app/src/main/res/values-ka/strings.xml b/app/src/main/res/values-ka/strings.xml index 72901b6d2..9a6e842c9 100644 --- a/app/src/main/res/values-ka/strings.xml +++ b/app/src/main/res/values-ka/strings.xml @@ -102,7 +102,6 @@ "ხელმისაწვდომია ლექსიკონი" "ლექსიკონის სერვისთან დაკავშირებით პრობლემა წარმოიშვა" "ლექსიკონები მიუწვდომელია" - "განახლება" "ბოლო განახლება" "მთავარი ლექსიკონი" "პარამეტრები" diff --git a/app/src/main/res/values-kab/strings.xml b/app/src/main/res/values-kab/strings.xml index fbaa1e3b2..3b5214d45 100644 --- a/app/src/main/res/values-kab/strings.xml +++ b/app/src/main/res/values-kab/strings.xml @@ -25,7 +25,6 @@ Anegzum: " ABCČDḌEƐFGǦƔHḤIJKLMNPQRṚSṢTṬUWXYZẒ" Axuxi - Smiren Aqehwi Lexla Lqem diff --git a/app/src/main/res/values-kk/strings.xml b/app/src/main/res/values-kk/strings.xml index 01a4fa220..5b64d0458 100644 --- a/app/src/main/res/values-kk/strings.xml +++ b/app/src/main/res/values-kk/strings.xml @@ -102,7 +102,6 @@ "Сөздік қолжетімді" "Сөздік қызметіне қосылу мәселесі" "Сөздіктер қолжетімсіз" - "Жаңарту" "Соңғы жаңартылған" "Негізгі сөздік" "Параметрлер" diff --git a/app/src/main/res/values-km/strings.xml b/app/src/main/res/values-km/strings.xml index e34a9a017..104fde57b 100644 --- a/app/src/main/res/values-km/strings.xml +++ b/app/src/main/res/values-km/strings.xml @@ -102,7 +102,6 @@ "វចនានុក្រម​​​អាច​ប្រើ​បាន" "មាន​បញ្ហា​ក្នុង​ការ​​ភ្ជាប់​ទៅ​​សេវា​កម្ម​វចនានុក្រម" "គ្មាន​វចនានុក្រម" - "ផ្ទុក​ឡើងវិញ" "បាន​ធ្វើ​បច្ចុប្បន្នភាព​ចុងក្រោយ" "វចនានុក្រម​ចម្បង" "ការ​កំណត់" diff --git a/app/src/main/res/values-kn/strings.xml b/app/src/main/res/values-kn/strings.xml index 7fe1aa1c5..b11a78830 100644 --- a/app/src/main/res/values-kn/strings.xml +++ b/app/src/main/res/values-kn/strings.xml @@ -102,7 +102,6 @@ "ನಿಘಂಟು ಲಭ್ಯವಿದೆ" "ನಿಘಂಟು ಸೇವೆಗೆ ಸಂಪರ್ಕಗೊಳಿಸುವಾಗ ಸಮಸ್ಯೆ" "ನಿಘಂಟುಗಳು ಲಭ್ಯವಿಲ್ಲ" - "ರಿಫ್ರೆಶ್ ಮಾಡಿ" "ಕೊನೆಯದಾಗಿ ನವೀಕರಿಸಿರುವುದು" "ಮುಖ್ಯ ನಿಘಂಟು" "ಸೆಟ್ಟಿಂಗ್‌ಗಳು" diff --git a/app/src/main/res/values-ko/strings.xml b/app/src/main/res/values-ko/strings.xml index 0e76c9528..81b1a42d0 100644 --- a/app/src/main/res/values-ko/strings.xml +++ b/app/src/main/res/values-ko/strings.xml @@ -102,7 +102,6 @@ "사전 사용 가능" "사전 서비스에 연결하는 중에 문제가 발생했습니다." "사용할 수 있는 사전이 없습니다." - "새로고침" "최종 업데이트" "기본 사전" "설정" diff --git a/app/src/main/res/values-ky/strings.xml b/app/src/main/res/values-ky/strings.xml index 5c1d1c97d..6e93b9b80 100644 --- a/app/src/main/res/values-ky/strings.xml +++ b/app/src/main/res/values-ky/strings.xml @@ -102,7 +102,6 @@ "Сөздүк бар" "Сөздүк кызматына туташуу көйгөйү" "Сөздүктөр жок" - "Жаңылоо" "Акыркы жолу жаңыртылган" "Негизги сөздүк" "Жөндөөлөр" diff --git a/app/src/main/res/values-lo/strings.xml b/app/src/main/res/values-lo/strings.xml index 9a1e96943..4e9766af6 100644 --- a/app/src/main/res/values-lo/strings.xml +++ b/app/src/main/res/values-lo/strings.xml @@ -102,7 +102,6 @@ "ມີວັດຈະນານຸກົມ" "ມີປັນຫາໃນການເຊື່ອມຕໍ່ກັບບໍລິການວັດຈະນານຸກົມ" "ບໍ່ມີວັດຈະນານຸກົມ" - "ດຶງຂໍ້ມູນໃຫມ່" "ອັບເດດຫຼ້າສຸດ" "ວັດຈະນານຸກົມຫຼັກ" "ການຕັ້ງຄ່າ" diff --git a/app/src/main/res/values-lt/strings.xml b/app/src/main/res/values-lt/strings.xml index 6cae388d6..7da5235fa 100644 --- a/app/src/main/res/values-lt/strings.xml +++ b/app/src/main/res/values-lt/strings.xml @@ -102,7 +102,6 @@ "Galimas žodynas" "Prisijung. problema" "Nėra galimų žodynų" - "Atnaujinti" "Paskutinį kartą atnaujinta" "Pagrindinis žodynas" "Nustatymai" diff --git a/app/src/main/res/values-lv/strings.xml b/app/src/main/res/values-lv/strings.xml index cd46f2464..1ac066eee 100644 --- a/app/src/main/res/values-lv/strings.xml +++ b/app/src/main/res/values-lv/strings.xml @@ -102,7 +102,6 @@ "Vārdnīca ir pieejama" "Nevar savien. ar vārdnīcas pakalp." "Vārdn. nav pieejamas" - "Atsvaidzināt" "Pēdējo reizi atjaunināts" "Galvenā vārdnīca" "Iestatījumi" diff --git a/app/src/main/res/values-mk/strings.xml b/app/src/main/res/values-mk/strings.xml index 4182bb503..86fa5154e 100644 --- a/app/src/main/res/values-mk/strings.xml +++ b/app/src/main/res/values-mk/strings.xml @@ -102,7 +102,6 @@ "Речникот е достапен" "Проблем при поврзувањето со услугата речник" "Нема достапен речник" - "Освежи" "Последен пат ажурирано" "Главен речник" "Поставки" diff --git a/app/src/main/res/values-ml/strings.xml b/app/src/main/res/values-ml/strings.xml index d5913bf55..32b7bf8cb 100644 --- a/app/src/main/res/values-ml/strings.xml +++ b/app/src/main/res/values-ml/strings.xml @@ -102,7 +102,6 @@ "നിഘണ്ടു ലഭ്യമാണ്" "നിഘണ്ടു സേവനത്തിൽ കണക്റ്റുചെയ്യുന്നതിൽ പ്രശ്‌നം" "നിഘണ്ടുക്കളൊന്നും ലഭ്യമല്ല" - "പുതുക്കുക" "അവസാനം അപ്ഡേറ്റുചെയ്തത്" "പ്രധാന നിഘണ്ടു" "ക്രമീകരണം" diff --git a/app/src/main/res/values-mn/strings.xml b/app/src/main/res/values-mn/strings.xml index 8181d5e22..3d7485355 100644 --- a/app/src/main/res/values-mn/strings.xml +++ b/app/src/main/res/values-mn/strings.xml @@ -102,7 +102,6 @@ "Толь бичиг байна" "Толь бичгийн үйлчилгээнд холбогдоход алдаа гарлаа" "Толь бичиг байхгүй" - "Дахин шинэчлэх" "Сүүлд шинэчлэгдсэн" "Үндсэн толь бичиг" "Тохиргоо" diff --git a/app/src/main/res/values-mr/strings.xml b/app/src/main/res/values-mr/strings.xml index 50d62a7d9..d5f2f7587 100644 --- a/app/src/main/res/values-mr/strings.xml +++ b/app/src/main/res/values-mr/strings.xml @@ -102,7 +102,6 @@ "शब्दकोश उपलब्ध" "शब्दकोश सेवेस कनेक्ट करताना समस्या" "कोणतेही शब्दकोश उपलब्ध नाहीत" - "रिफ्रेश करा" "अंतिम अपडेट" "मु्ख्य शब्दकोश" "सेटिंग्ज" diff --git a/app/src/main/res/values-ms/strings.xml b/app/src/main/res/values-ms/strings.xml index adec8bd55..84e9a5f60 100644 --- a/app/src/main/res/values-ms/strings.xml +++ b/app/src/main/res/values-ms/strings.xml @@ -102,7 +102,6 @@ "Kamus tersedia" "Masalah menyambung kepada perkhidmatan kamus" "Tiada kamus tersedia" - "Muatkan semula" "Kali terakhir dikemas kini" "Kamus utama" "Tetapan" diff --git a/app/src/main/res/values-my/strings.xml b/app/src/main/res/values-my/strings.xml index 9d1d54833..8018e55d4 100644 --- a/app/src/main/res/values-my/strings.xml +++ b/app/src/main/res/values-my/strings.xml @@ -102,7 +102,6 @@ "အဘိဓါန်ရရှိနိုင်" "အဘိဓါန်ဝန်ဆောင်မှုသို့ ချိတ်ဆက်ရန် ပြဿနာရှိနေသည်" "အဘိဓါန်မရှိ" - "ပြန်လည်ဆန်းသစ်ရန်" "နောက်ဆုံး အသစ်မွမ်းမံမှု" "အဓိက အဘိဓါန်" "ဆက်တင်များ" diff --git a/app/src/main/res/values-nb/strings.xml b/app/src/main/res/values-nb/strings.xml index cd9d0ad0b..bb8cf9ac5 100644 --- a/app/src/main/res/values-nb/strings.xml +++ b/app/src/main/res/values-nb/strings.xml @@ -102,7 +102,6 @@ "Ordliste tilgjengelig" "Kan ikke koble til ordlistetjenesten" "Fant ingen ordlister" - "Last inn på nytt" "Sist oppdatert" "Hovedordliste" "Innstillinger" diff --git a/app/src/main/res/values-ne/strings.xml b/app/src/main/res/values-ne/strings.xml index 4f644f72e..e3c408335 100644 --- a/app/src/main/res/values-ne/strings.xml +++ b/app/src/main/res/values-ne/strings.xml @@ -102,7 +102,6 @@ "उपलब्ध शब्दकोश" "शब्दकोश सेवासँग जोड्न समस्या" "शब्दकोशहरू उपलब्ध छैनन्" - "पुनः ताजा गर्नुहोस्" "पछिल्लो अद्यावधिक" "मुख्य शब्दकोश" "सेटिङहरू" diff --git a/app/src/main/res/values-nl/strings.xml b/app/src/main/res/values-nl/strings.xml index 830262d09..2e850af9a 100644 --- a/app/src/main/res/values-nl/strings.xml +++ b/app/src/main/res/values-nl/strings.xml @@ -102,7 +102,6 @@ "Woordenboek beschikbaar" "Verbindingsprobleem woordenboekservice" "Geen woordenboeken" - "Vernieuwen" "Laatst bijgewerkt" "Algemeen woordenboek" "Instellingen" diff --git a/app/src/main/res/values-pa-rPK/strings.xml b/app/src/main/res/values-pa-rPK/strings.xml index a5d67571a..01de26ef2 100644 --- a/app/src/main/res/values-pa-rPK/strings.xml +++ b/app/src/main/res/values-pa-rPK/strings.xml @@ -41,7 +41,6 @@ پورا ہویا بولی سیٹنگاں - تازہ کرو شورٹکٹ: دو خالی تھاں ڈنڈی سنکیت نال اینپُٹ کرن diff --git a/app/src/main/res/values-pa/strings.xml b/app/src/main/res/values-pa/strings.xml index 0af127490..4515157c7 100644 --- a/app/src/main/res/values-pa/strings.xml +++ b/app/src/main/res/values-pa/strings.xml @@ -102,7 +102,6 @@ "ਸ਼ਬਦਕੋਸ਼ ਉਪਲਬਧ" "ਸ਼ਬਦਕੋਸ਼ ਸੇਵਾ ਕਨੈਕਟ ਕਰਨ ਵਿੱਚ ਸਮੱਸਿਆ" "ਕੋਈ ਸ਼ਬਦਕੋਸ਼ ਉਪਲਬਧ ਨਹੀਂ" - "ਤਾਜ਼ਾ" "ਆਖਰੀ ਵਾਰ ਅੱਪਡੇਟ ਕੀਤਾ" "ਮੁੱਖ ਸ਼ਬਦਕੋਸ਼" "ਸੈਟਿੰਗਾਂ" diff --git a/app/src/main/res/values-pl/strings.xml b/app/src/main/res/values-pl/strings.xml index 839db25f0..ef319d4a2 100644 --- a/app/src/main/res/values-pl/strings.xml +++ b/app/src/main/res/values-pl/strings.xml @@ -102,7 +102,6 @@ "Słownik dostępny" "Problem z połączeniem z usługą słownika" "Brak słowników" - "Odśwież" "Ostatnia aktualizacja" "Słownik główny" "Ustawienia" @@ -233,7 +232,6 @@ Dotknij, aby wyświetlić podgląd Pokaż warianty zdefiniowane w językach klawiatury (domyślnie) Pokaż popularne warianty - Dostosuj układ większej liczby symboli Własne Zastąp słownik Dodaj do %s @@ -245,12 +243,11 @@ Rząd numeryczny Alfabet (Bépo) Przywracanie - Dostosuj układ symboli Wybierz kolejność klawiszy w wyskakującym okienku Wersja Wybierz źródło wskazówek Dodaj natywną bibliotekę, aby umożliwić pisanie gestami - Więcej symboli + Więcej symboli Próbuj wykrywać adresy URL i podobne jako pojedyncze słowo Wybierz język Tekst klawiszy diff --git a/app/src/main/res/values-pt-rBR/strings.xml b/app/src/main/res/values-pt-rBR/strings.xml index efe29b87f..c85bec13e 100644 --- a/app/src/main/res/values-pt-rBR/strings.xml +++ b/app/src/main/res/values-pt-rBR/strings.xml @@ -83,7 +83,6 @@ Adicionar dicionários Erro ao contatar o serviço de dicionário Nenhum dicionário disponível - Atualizar Última atualização Configurações Apagar diff --git a/app/src/main/res/values-pt-rPT/strings.xml b/app/src/main/res/values-pt-rPT/strings.xml index 1aef1c485..6eed9f557 100644 --- a/app/src/main/res/values-pt-rPT/strings.xml +++ b/app/src/main/res/values-pt-rPT/strings.xml @@ -103,7 +103,6 @@ "Dicionário disponível" "Problema ao ligar ao serviço de dicionário" "Nenhum dicionário" - "Atualizar" "Última atualização" "Dicionário principal" "Definições" diff --git a/app/src/main/res/values-pt/strings.xml b/app/src/main/res/values-pt/strings.xml index d972ac8a6..e48cfec4e 100644 --- a/app/src/main/res/values-pt/strings.xml +++ b/app/src/main/res/values-pt/strings.xml @@ -102,7 +102,6 @@ "Dicionário disponível" "Prob. conexão dic." "Nenhum dicionário disponível" - "Atualizar" "Última atualização" "Dicionário principal" "Configurações" diff --git a/app/src/main/res/values-ro/strings.xml b/app/src/main/res/values-ro/strings.xml index 9545d7a1b..9014c0cc3 100644 --- a/app/src/main/res/values-ro/strings.xml +++ b/app/src/main/res/values-ro/strings.xml @@ -102,7 +102,6 @@ "Dicționar disponibil" "Eroare conectare la serviciu dicționar" "Niciun dicționar" - "Actualizați" "Data ultimei modificări" "Dicționar principal" "Setări" diff --git a/app/src/main/res/values-ru/strings.xml b/app/src/main/res/values-ru/strings.xml index 8f9966f39..6f7d70647 100644 --- a/app/src/main/res/values-ru/strings.xml +++ b/app/src/main/res/values-ru/strings.xml @@ -102,7 +102,6 @@ Доступен словарь Сбой подключения Словарей нет - Обновить Последнее обновление Основной словарь Настройки @@ -303,9 +302,7 @@ Выберите для добавления словаря. Словари в формате .dict можно скачать %s. Вправо Ошибка загрузки файла словаря - Редактировать раскладку дополнительных символов - Редактировать раскладку символов - Больше символов + Больше символов Вниз В конец влево Влево diff --git a/app/src/main/res/values-si/strings.xml b/app/src/main/res/values-si/strings.xml index 6c45cf9fd..da05f3801 100644 --- a/app/src/main/res/values-si/strings.xml +++ b/app/src/main/res/values-si/strings.xml @@ -102,7 +102,6 @@ "ශබ්දකෝෂය ලබාගත හැක" "ශබ්දකෝෂ සේවාව වෙත සම්බන්ධ වීමට ගැටලුවක්ද" "ශබ්ද කෝෂ ලබාගත නොහැක" - "නැවුම් කරන්න" "අවසන් වරට යාවත්කාලීන කළේ" "ප්‍රධාන ශබ්ද කෝෂය" "සැකසීම්" diff --git a/app/src/main/res/values-sk/strings.xml b/app/src/main/res/values-sk/strings.xml index ec9ae1019..07ec33690 100644 --- a/app/src/main/res/values-sk/strings.xml +++ b/app/src/main/res/values-sk/strings.xml @@ -102,7 +102,6 @@ "K dispozícii je slovník" "Probl. s prip. k sl." "Slovníky sú nedostupné" - "Obnoviť" "Posledná aktualizácia" "Hlavný slovník" "Nastavenia" diff --git a/app/src/main/res/values-sl/strings.xml b/app/src/main/res/values-sl/strings.xml index f04ad58a8..a8b80944c 100644 --- a/app/src/main/res/values-sl/strings.xml +++ b/app/src/main/res/values-sl/strings.xml @@ -102,7 +102,6 @@ "Slovar je na voljo" "Težava s povezavo" "Ni slovarjev" - "Osveži" "Nazadnje posodobljeno" "Glavni slovar" "Nastavitve" diff --git a/app/src/main/res/values-sq/strings.xml b/app/src/main/res/values-sq/strings.xml index 475b9002d..a07129fd8 100644 --- a/app/src/main/res/values-sq/strings.xml +++ b/app/src/main/res/values-sq/strings.xml @@ -102,7 +102,6 @@ "Fjalor i përdorshëm" "Problem në lidhjen me shërbimin e fjalorit" "Nuk mund të përdoret asnjë fjalor" - "Rifresko" "Përditësimi i fundit" "Fjalori kryesor" "Cilësimet" diff --git a/app/src/main/res/values-sr/strings.xml b/app/src/main/res/values-sr/strings.xml index bd547a6d8..43a0024dd 100644 --- a/app/src/main/res/values-sr/strings.xml +++ b/app/src/main/res/values-sr/strings.xml @@ -102,7 +102,6 @@ "Речник је доступан" "Проблем при повезивању с услугом речника" "Нема доступних речника" - "Освежи" "Последње ажурирање" "Главни речник" "Подешавања" diff --git a/app/src/main/res/values-sv/strings.xml b/app/src/main/res/values-sv/strings.xml index 45aa75e1c..794a9de99 100644 --- a/app/src/main/res/values-sv/strings.xml +++ b/app/src/main/res/values-sv/strings.xml @@ -102,7 +102,6 @@ "En ordlista är tillgänglig" "Problem med att ansluta till ordlistetjänsten" "Inga ordlistor finns" - "Uppdatera" "Informationen uppdaterades senast" "Huvudordlista" "Inställningar" diff --git a/app/src/main/res/values-sw/strings.xml b/app/src/main/res/values-sw/strings.xml index 17d5c8d7b..0e93b083e 100644 --- a/app/src/main/res/values-sw/strings.xml +++ b/app/src/main/res/values-sw/strings.xml @@ -102,7 +102,6 @@ "Kamusi inapatikana" "Tatizo wakati wa kuunganisha kwenye huduma ya kamusi" "Hakuna kamusi inayopatikana" - "Onyesha upya" "Ilibadilishwa mwisho" "Kamusi kuu" "Mipangilio" diff --git a/app/src/main/res/values-ta/strings.xml b/app/src/main/res/values-ta/strings.xml index 5ba357cb9..fe0fb6a3f 100644 --- a/app/src/main/res/values-ta/strings.xml +++ b/app/src/main/res/values-ta/strings.xml @@ -102,7 +102,6 @@ "அகராதி கிடைக்கிறது" "அகராதி சேவையில் இணைப்பதில் பிரச்சனை ஏற்பட்டது" "அகராதிகள் எதுவும் இல்லை" - "புதுப்பி" "இறுதியாகப் புதுப்பித்தது" "முதன்மை அகராதி" "அமைப்பு" diff --git a/app/src/main/res/values-te/strings.xml b/app/src/main/res/values-te/strings.xml index 52cf797f8..12d67d8c8 100644 --- a/app/src/main/res/values-te/strings.xml +++ b/app/src/main/res/values-te/strings.xml @@ -102,7 +102,6 @@ "నిఘంటువు అందుబాటులో ఉంది" "నిఘంటువు సేవకు కనెక్ట్ చేయడంలో సమస్య" "నిఘంటువులు ఏవీ అందుబాటులో లేవు" - "రీఫ్రెష్ చేయండి" "చివరిగా నవీకరించబడినది" "ప్రధాన నిఘంటువు" "సెట్టింగ్‌లు" diff --git a/app/src/main/res/values-th/strings.xml b/app/src/main/res/values-th/strings.xml index 5ec9beb72..a7bbb6d06 100644 --- a/app/src/main/res/values-th/strings.xml +++ b/app/src/main/res/values-th/strings.xml @@ -102,7 +102,6 @@ "มีพจนานุกรมให้ใช้งาน" "พบปัญหาขณะเชื่อมต่อ" "ไม่มีพจนานุกรม" - "รีเฟรช" "ปรับปรุงแก้ไขครั้งล่าสุด" "พจนานุกรมหลัก" "การตั้งค่า" diff --git a/app/src/main/res/values-tl/strings.xml b/app/src/main/res/values-tl/strings.xml index b3ee96c7a..8bbebf17b 100644 --- a/app/src/main/res/values-tl/strings.xml +++ b/app/src/main/res/values-tl/strings.xml @@ -102,7 +102,6 @@ "Available ang diksyunaryo" "Di makakonekta sa serbisyong diksyunaryo" "Walang mga diksyunaryo" - "I-refresh" "Huling na-update" "Pangunahing diksyunaryo" "Mga Setting" diff --git a/app/src/main/res/values-tr/strings.xml b/app/src/main/res/values-tr/strings.xml index 80240f3ca..b747e36de 100644 --- a/app/src/main/res/values-tr/strings.xml +++ b/app/src/main/res/values-tr/strings.xml @@ -102,7 +102,6 @@ "Sözlük mevcut" "Sözlük hizmetine bağlantı sorunu" "Kullanılabilir sözlük yok" - "Yenile" "Son güncelleme tarihi" "Ana sözlük" "Ayarlar" diff --git a/app/src/main/res/values-uk/strings.xml b/app/src/main/res/values-uk/strings.xml index 65c85f36b..5dfc4b979 100644 --- a/app/src/main/res/values-uk/strings.xml +++ b/app/src/main/res/values-uk/strings.xml @@ -102,7 +102,6 @@ Словник доступний "Нема з’єднання зі службою словника" Словники недоступні - Оновити Останнє оновлення Основний словник Налаштування diff --git a/app/src/main/res/values-ur/strings.xml b/app/src/main/res/values-ur/strings.xml index c18caf851..528cd40d7 100644 --- a/app/src/main/res/values-ur/strings.xml +++ b/app/src/main/res/values-ur/strings.xml @@ -102,7 +102,6 @@ "لغت دستیاب ہے" "لغت سروس سے مربوط ہونے میں مسئلہ" "کوئی لغت دستیاب نہیں" - "ریفریش کریں" "آخری بار اپ ڈیٹ کردہ" "مرکزی لغت" "ترتیبات" diff --git a/app/src/main/res/values-uz/strings.xml b/app/src/main/res/values-uz/strings.xml index 9aafed9e3..8bb7a17b3 100644 --- a/app/src/main/res/values-uz/strings.xml +++ b/app/src/main/res/values-uz/strings.xml @@ -102,7 +102,6 @@ "Lug‘at mavjud" "Ulanib bo‘lmadi" "Lug‘at mavjud emas" - "Yangilash" "So‘nggi marta yangilandi" "Asosiy lug‘at" "Sozlamalar" diff --git a/app/src/main/res/values-vi/strings.xml b/app/src/main/res/values-vi/strings.xml index 728b64ccd..e5c123914 100644 --- a/app/src/main/res/values-vi/strings.xml +++ b/app/src/main/res/values-vi/strings.xml @@ -102,7 +102,6 @@ "Từ điển có sẵn" "Lỗi kết nối DV từ điển" "Không có từ điển nào" - "Làm mới" "Cập nhật lần cuối" "Từ điển chính" "Cài đặt" diff --git a/app/src/main/res/values-zh-rCN/strings.xml b/app/src/main/res/values-zh-rCN/strings.xml index cb8b48dfa..7d133cecd 100644 --- a/app/src/main/res/values-zh-rCN/strings.xml +++ b/app/src/main/res/values-zh-rCN/strings.xml @@ -102,7 +102,6 @@ "字典可供下载" "连接到字典服务时发生问题" "没有可供下载的字典" - "刷新" "上次更新时间" "主字典" "设置" diff --git a/app/src/main/res/values-zh-rHK/strings.xml b/app/src/main/res/values-zh-rHK/strings.xml index 154c0e399..c648ba2db 100644 --- a/app/src/main/res/values-zh-rHK/strings.xml +++ b/app/src/main/res/values-zh-rHK/strings.xml @@ -102,7 +102,6 @@ "可使用字典" "連線至字典服務時發生問題" "沒有可用的字典" - "重新整理" "上次更新日期" "主要字典" "設定" diff --git a/app/src/main/res/values-zh-rTW/strings.xml b/app/src/main/res/values-zh-rTW/strings.xml index 42eee1915..7c21fccf7 100644 --- a/app/src/main/res/values-zh-rTW/strings.xml +++ b/app/src/main/res/values-zh-rTW/strings.xml @@ -102,7 +102,6 @@ "可用的字典" "連線至字典服務時發生問題" "沒有可用的字典" - "重新整理" "上次更新時間:" "主要字典" "設定" diff --git a/app/src/main/res/values-zu/strings.xml b/app/src/main/res/values-zu/strings.xml index 313593723..b0b4f738f 100644 --- a/app/src/main/res/values-zu/strings.xml +++ b/app/src/main/res/values-zu/strings.xml @@ -102,7 +102,6 @@ "Isichazamazwi siyatholakala" "Inkinga yokuxhumanisa kusevisi yesichazamazwi" "Azikho izachazimazwi ezitholakalayo" - "Qala kabusha" "Igcine ukulungiswa" "Isichazamazwi sakho esisemqoka" "Izilungiselelo" diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 1f02a9447..c3ded5980 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -442,12 +442,26 @@ disposition rather than other common dispositions for Latin languages. [CHAR LIM Layout error: %s Tap to edit raw layout - - Customize symbols layout - - Customize more symbols layout - - More symbols + + Customize symbols and number layouts + + Layouts (except symbols) expose internal settings which may still change. If that happens, the custom layout may not work properly any more. + + Symbols + + Symbols (Arabic) + + More symbols + + Phone + + Phone symbols + + Numbers + + Numpad + + Numpad (landscape) Set background image @@ -565,8 +579,6 @@ New dictionary: Problem connecting to dictionary service No dictionaries available - - Refresh Last updated @@ -576,40 +588,29 @@ New dictionary: Version %1$s - Add - Add to dictionary - Shortcut: Weight: - Language: - Type a word - Optional shortcut - Edit word - You don\'t have any words in the user dictionary. To add a word, tap the Add (+) button. - For all languages - More languages… - \u0020ABCDEFGHIJKLMNOPQRSTUVWXYZ This word is already present in the %s user dictionary. Please type another one. diff --git a/app/src/main/res/xml/prefs_screen_advanced.xml b/app/src/main/res/xml/prefs_screen_advanced.xml index 1d49e0cd5..48d43d811 100644 --- a/app/src/main/res/xml/prefs_screen_advanced.xml +++ b/app/src/main/res/xml/prefs_screen_advanced.xml @@ -96,12 +96,9 @@ android:title="@string/customize_background_image" /> - - + android:key="custom_symbols_number_layouts" + android:title="@string/customize_symbols_number_layouts" + android:summary="@string/customize_symbols_number_layouts_summary" /> Date: Tue, 20 Feb 2024 10:33:47 +0100 Subject: [PATCH 15/40] avoid loading uris from content resolver on main thread because uris might point to network locations, which triggers an exception main thread is still blocked by loading, this is purely to get around the crash (files are small, and usually stored locally) --- .../keyboard/latin/common/FileUtils.java | 35 +++- .../keyboard/latin/settings/AboutFragment.kt | 7 +- .../settings/AdvancedSettingsFragment.kt | 164 ++++++++++-------- .../latin/settings/SettingsFragment.java | 2 +- .../keyboard/latin/utils/CustomLayoutUtils.kt | 7 +- .../latin/utils/NewDictionaryAdder.kt | 3 +- 6 files changed, 139 insertions(+), 79 deletions(-) diff --git a/app/src/main/java/helium314/keyboard/latin/common/FileUtils.java b/app/src/main/java/helium314/keyboard/latin/common/FileUtils.java index 71ba4213d..a69d76170 100644 --- a/app/src/main/java/helium314/keyboard/latin/common/FileUtils.java +++ b/app/src/main/java/helium314/keyboard/latin/common/FileUtils.java @@ -6,12 +6,18 @@ package helium314.keyboard.latin.common; +import android.content.Context; +import android.net.Uri; + import java.io.File; import java.io.FileOutputStream; import java.io.FilenameFilter; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; +import java.util.concurrent.CountDownLatch; + +import helium314.keyboard.latin.utils.ExecutorUtils; /** * A simple class to help with removing directories recursively. @@ -47,7 +53,32 @@ public static boolean deleteFilteredFiles(final File dir, final FilenameFilter f return hasDeletedAllFiles; } - public static void copyStreamToNewFile(InputStream in, File outfile) throws IOException { + /** + * copy data to file on different thread to avoid NetworkOnMainThreadException + * still effectively blocking, as we only use small files which are mostly stored locally + */ + public static void copyContentUriToNewFile(final Uri uri, final Context context, final File outfile) throws IOException { + final boolean[] allOk = new boolean[] { true }; + final CountDownLatch wait = new CountDownLatch(1); + ExecutorUtils.getBackgroundExecutor(ExecutorUtils.KEYBOARD).execute(() -> { + try { + copyStreamToNewFile(context.getContentResolver().openInputStream(uri), outfile); + } catch (IOException e) { + allOk[0] = false; + } finally { + wait.countDown(); + } + }); + try { + wait.await(); + } catch (InterruptedException e) { + allOk[0] = false; + } + if (!allOk[0]) + throw new IOException("could not copy from uri"); + } + + public static void copyStreamToNewFile(final InputStream in, final File outfile) throws IOException { File parentFile = outfile.getParentFile(); if (parentFile == null || (!parentFile.exists() && !parentFile.mkdirs())) { throw new IOException("could not create parent folder"); @@ -57,7 +88,7 @@ public static void copyStreamToNewFile(InputStream in, File outfile) throws IOEx out.close(); } - public static void copyStreamToOtherStream(InputStream in, OutputStream out) throws IOException { + public static void copyStreamToOtherStream(final InputStream in, final OutputStream out) throws IOException { byte[] buf = new byte[1024]; int len; while ((len = in.read(buf)) > 0) { diff --git a/app/src/main/java/helium314/keyboard/latin/settings/AboutFragment.kt b/app/src/main/java/helium314/keyboard/latin/settings/AboutFragment.kt index e05d8e0fd..51f9ca982 100644 --- a/app/src/main/java/helium314/keyboard/latin/settings/AboutFragment.kt +++ b/app/src/main/java/helium314/keyboard/latin/settings/AboutFragment.kt @@ -17,6 +17,7 @@ import androidx.appcompat.app.AlertDialog import androidx.preference.Preference import helium314.keyboard.latin.BuildConfig import helium314.keyboard.latin.R +import helium314.keyboard.latin.utils.ExecutorUtils import helium314.keyboard.latin.utils.Log import helium314.keyboard.latin.utils.SpannableStringUtils @@ -46,8 +47,10 @@ class AboutFragment : SubScreenFragment() { private val logFilePicker = registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { result -> if (result.resultCode != Activity.RESULT_OK) return@registerForActivityResult val uri = result.data?.data ?: return@registerForActivityResult - activity?.contentResolver?.openOutputStream(uri)?.use { os -> - os.bufferedWriter().use { it.write(Log.getLog().joinToString("\n")) } + ExecutorUtils.getBackgroundExecutor(ExecutorUtils.KEYBOARD).execute { + activity?.contentResolver?.openOutputStream(uri)?.use { os -> + os.bufferedWriter().use { it.write(Log.getLog().joinToString("\n")) } + } } } diff --git a/app/src/main/java/helium314/keyboard/latin/settings/AdvancedSettingsFragment.kt b/app/src/main/java/helium314/keyboard/latin/settings/AdvancedSettingsFragment.kt index a95f836cf..1512420ff 100644 --- a/app/src/main/java/helium314/keyboard/latin/settings/AdvancedSettingsFragment.kt +++ b/app/src/main/java/helium314/keyboard/latin/settings/AdvancedSettingsFragment.kt @@ -43,6 +43,7 @@ import helium314.keyboard.latin.settings.SeekBarDialogPreference.ValueProxy import helium314.keyboard.latin.utils.AdditionalSubtypeUtils import helium314.keyboard.latin.utils.CUSTOM_LAYOUT_PREFIX import helium314.keyboard.latin.utils.DeviceProtectedUtils +import helium314.keyboard.latin.utils.ExecutorUtils import helium314.keyboard.latin.utils.JniUtils import helium314.keyboard.latin.utils.editCustomLayout import helium314.keyboard.latin.utils.getStringResourceOrName @@ -54,6 +55,7 @@ import java.io.FileInputStream import java.io.FileOutputStream import java.io.IOException import java.io.OutputStream +import java.util.concurrent.CountDownLatch import java.util.zip.ZipEntry import java.util.zip.ZipInputStream import java.util.zip.ZipOutputStream @@ -207,12 +209,15 @@ class AdvancedSettingsFragment : SubScreenFragment() { private fun copyLibrary(uri: Uri) { val tmpfile = File(requireContext().filesDir.absolutePath + File.separator + "tmplib") try { - val inputStream = requireContext().contentResolver.openInputStream(uri) + val otherTemporaryFile = File(requireContext().filesDir.absolutePath + File.separator + "tmpfile") + FileUtils.copyContentUriToNewFile(uri, requireContext(), otherTemporaryFile) + val inputStream = FileInputStream(otherTemporaryFile) val outputStream = FileOutputStream(tmpfile) outputStream.use { tmpfile.setReadOnly() // as per recommendations in https://developer.android.com/about/versions/14/behavior-changes-14#safer-dynamic-code-loading FileUtils.copyStreamToOtherStream(inputStream, it) } + otherTemporaryFile.delete() val checksum = ChecksumCalculator.checksum(tmpfile.inputStream()) ?: "" if (checksum == JniUtils.expectedDefaultChecksum()) { @@ -269,7 +274,7 @@ class AdvancedSettingsFragment : SubScreenFragment() { private fun loadImage(uri: Uri, night: Boolean) { val imageFile = Settings.getCustomBackgroundFile(requireContext(), night) - FileUtils.copyStreamToNewFile(requireContext().contentResolver.openInputStream(uri), imageFile) + FileUtils.copyContentUriToNewFile(uri, requireContext(), imageFile) try { BitmapFactory.decodeFile(imageFile.absolutePath) } catch (_: Exception) { @@ -334,91 +339,110 @@ class AdvancedSettingsFragment : SubScreenFragment() { if (backupFilePatterns.any { path.matches(it) }) protectedFiles.add(file) } - try { - activity?.contentResolver?.openOutputStream(uri)?.use { os -> - // write files to zip - val zipStream = ZipOutputStream(os) - files.forEach { - val fileStream = FileInputStream(it).buffered() - zipStream.putNextEntry(ZipEntry(it.path.replace(filesPath, ""))) - fileStream.copyTo(zipStream, 1024) - fileStream.close() + var error: String? = "" + val wait = CountDownLatch(1) + ExecutorUtils.getBackgroundExecutor(ExecutorUtils.KEYBOARD).execute { + try { + activity?.contentResolver?.openOutputStream(uri)?.use { os -> + // write files to zip + val zipStream = ZipOutputStream(os) + files.forEach { + val fileStream = FileInputStream(it).buffered() + zipStream.putNextEntry(ZipEntry(it.path.replace(filesPath, ""))) + fileStream.copyTo(zipStream, 1024) + fileStream.close() + zipStream.closeEntry() + } + protectedFiles.forEach { + val fileStream = FileInputStream(it).buffered() + zipStream.putNextEntry(ZipEntry(it.path.replace(protectedFilesDir.path, "unprotected"))) + fileStream.copyTo(zipStream, 1024) + fileStream.close() + zipStream.closeEntry() + } + zipStream.putNextEntry(ZipEntry(PREFS_FILE_NAME)) + settingsToJsonStream(sharedPreferences.all, zipStream) zipStream.closeEntry() - } - protectedFiles.forEach { - val fileStream = FileInputStream(it).buffered() - zipStream.putNextEntry(ZipEntry(it.path.replace(protectedFilesDir.path, "unprotected"))) - fileStream.copyTo(zipStream, 1024) - fileStream.close() + zipStream.putNextEntry(ZipEntry(PROTECTED_PREFS_FILE_NAME)) + settingsToJsonStream(PreferenceManager.getDefaultSharedPreferences(requireContext()).all, zipStream) zipStream.closeEntry() + zipStream.close() } - zipStream.putNextEntry(ZipEntry(PREFS_FILE_NAME)) - settingsToJsonStream(sharedPreferences.all, zipStream) - zipStream.closeEntry() - zipStream.putNextEntry(ZipEntry(PROTECTED_PREFS_FILE_NAME)) - settingsToJsonStream(PreferenceManager.getDefaultSharedPreferences(requireContext()).all, zipStream) - zipStream.closeEntry() - zipStream.close() + } catch (t: Throwable) { + error = t.message + Log.w(TAG, "error during backup", t) + } finally { + wait.countDown() } - } catch (t: Throwable) { + } + wait.await() + if (!error.isNullOrBlank()) { // inform about every error - Log.w(TAG, "error during backup", t) - infoDialog(requireContext(), requireContext().getString(R.string.backup_error, t.message)) + infoDialog(requireContext(), requireContext().getString(R.string.backup_error, error)) } } private fun restore(uri: Uri) { - try { - activity?.contentResolver?.openInputStream(uri)?.use { inputStream -> - ZipInputStream(inputStream).use { zip -> - var entry: ZipEntry? = zip.nextEntry - val filesDir = requireContext().filesDir?.path ?: return - val deviceProtectedFilesDir = DeviceProtectedUtils.getFilesDir(requireContext()).path - Settings.getInstance().stopListener() - while (entry != null) { - if (entry.name.startsWith("unprotected${File.separator}")) { - val adjustedName = entry.name.substringAfter("unprotected${File.separator}") - if (backupFilePatterns.any { adjustedName.matches(it) }) { - val targetFileName = upgradeFileNames(adjustedName) - val file = File(deviceProtectedFilesDir, targetFileName) + var error: String? = "" + val wait = CountDownLatch(1) + ExecutorUtils.getBackgroundExecutor(ExecutorUtils.KEYBOARD).execute { + try { + activity?.contentResolver?.openInputStream(uri)?.use { inputStream -> + ZipInputStream(inputStream).use { zip -> + var entry: ZipEntry? = zip.nextEntry + val filesDir = requireContext().filesDir?.path ?: return@execute + val deviceProtectedFilesDir = DeviceProtectedUtils.getFilesDir(requireContext()).path + Settings.getInstance().stopListener() + while (entry != null) { + if (entry.name.startsWith("unprotected${File.separator}")) { + val adjustedName = entry.name.substringAfter("unprotected${File.separator}") + if (backupFilePatterns.any { adjustedName.matches(it) }) { + val targetFileName = upgradeFileNames(adjustedName) + val file = File(deviceProtectedFilesDir, targetFileName) + FileUtils.copyStreamToNewFile(zip, file) + } + } else if (backupFilePatterns.any { entry!!.name.matches(it) }) { + val targetFileName = upgradeFileNames(entry.name) + val file = File(filesDir, targetFileName) FileUtils.copyStreamToNewFile(zip, file) + } else if (entry.name == PREFS_FILE_NAME) { + val prefLines = String(zip.readBytes()).split("\n") + sharedPreferences.edit().clear().apply() + readJsonLinesToSettings(prefLines, sharedPreferences) + } else if (entry.name == PROTECTED_PREFS_FILE_NAME) { + val prefLines = String(zip.readBytes()).split("\n") + val protectedPrefs = PreferenceManager.getDefaultSharedPreferences(requireContext()) + protectedPrefs.edit().clear().apply() + readJsonLinesToSettings(prefLines, protectedPrefs) } - } else if (backupFilePatterns.any { entry!!.name.matches(it) }) { - val targetFileName = upgradeFileNames(entry.name) - val file = File(filesDir, targetFileName) - FileUtils.copyStreamToNewFile(zip, file) - } else if (entry.name == PREFS_FILE_NAME) { - val prefLines = String(zip.readBytes()).split("\n") - sharedPreferences.edit().clear().apply() - readJsonLinesToSettings(prefLines, sharedPreferences) - } else if (entry.name == PROTECTED_PREFS_FILE_NAME) { - val prefLines = String(zip.readBytes()).split("\n") - val protectedPrefs = PreferenceManager.getDefaultSharedPreferences(requireContext()) - protectedPrefs.edit().clear().apply() - readJsonLinesToSettings(prefLines, protectedPrefs) + zip.closeEntry() + entry = zip.nextEntry } - zip.closeEntry() - entry = zip.nextEntry } } + } catch (t: Throwable) { + error = t.message + Log.w(TAG, "error during restore", t) + } finally { + wait.countDown() } - } catch (t: Throwable) { + } + wait.await() + if (!error.isNullOrBlank()) { // inform about every error - Log.w(TAG, "error during restore", t) - infoDialog(requireContext(), requireContext().getString(R.string.restore_error, t.message)) - } finally { - checkVersionUpgrade(requireContext()) - Settings.getInstance().startListener() - val additionalSubtypes = Settings.readPrefAdditionalSubtypes(sharedPreferences, resources); - updateAdditionalSubtypes(AdditionalSubtypeUtils.createAdditionalSubtypesArray(additionalSubtypes)); - reloadEnabledSubtypes(requireContext()) - val newDictBroadcast = Intent(DictionaryPackConstants.NEW_DICTIONARY_INTENT_ACTION) - activity?.sendBroadcast(newDictBroadcast) - // reload current prefs screen - preferenceScreen.removeAll() - setupPreferences() - KeyboardSwitcher.getInstance().forceUpdateKeyboardTheme(requireContext()) + infoDialog(requireContext(), requireContext().getString(R.string.restore_error, error)) } + checkVersionUpgrade(requireContext()) + Settings.getInstance().startListener() + val additionalSubtypes = Settings.readPrefAdditionalSubtypes(sharedPreferences, resources); + updateAdditionalSubtypes(AdditionalSubtypeUtils.createAdditionalSubtypesArray(additionalSubtypes)); + reloadEnabledSubtypes(requireContext()) + val newDictBroadcast = Intent(DictionaryPackConstants.NEW_DICTIONARY_INTENT_ACTION) + activity?.sendBroadcast(newDictBroadcast) + // reload current prefs screen + preferenceScreen.removeAll() + setupPreferences() + KeyboardSwitcher.getInstance().forceUpdateKeyboardTheme(requireContext()) } // todo (later): remove this when new package name has been in use for long enough, this is only for migrating from old openboard name diff --git a/app/src/main/java/helium314/keyboard/latin/settings/SettingsFragment.java b/app/src/main/java/helium314/keyboard/latin/settings/SettingsFragment.java index 7e8c6b633..dc984b85a 100644 --- a/app/src/main/java/helium314/keyboard/latin/settings/SettingsFragment.java +++ b/app/src/main/java/helium314/keyboard/latin/settings/SettingsFragment.java @@ -128,7 +128,7 @@ private void askAboutCrashReports() { if (intent.getResultCode() != Activity.RESULT_OK || intent.getData() == null) return; final Uri uri = intent.getData().getData(); if (uri != null) - saveCrashReport(uri); + ExecutorUtils.getBackgroundExecutor(ExecutorUtils.KEYBOARD).execute(() -> saveCrashReport(uri)); }); private void saveCrashReport(final Uri uri) { diff --git a/app/src/main/java/helium314/keyboard/latin/utils/CustomLayoutUtils.kt b/app/src/main/java/helium314/keyboard/latin/utils/CustomLayoutUtils.kt index b3b367a97..cfa863104 100644 --- a/app/src/main/java/helium314/keyboard/latin/utils/CustomLayoutUtils.kt +++ b/app/src/main/java/helium314/keyboard/latin/utils/CustomLayoutUtils.kt @@ -18,6 +18,7 @@ import helium314.keyboard.keyboard.internal.keyboard_parser.POPUP_KEYS_NORMAL import helium314.keyboard.keyboard.internal.keyboard_parser.SimpleKeyboardParser import helium314.keyboard.keyboard.internal.keyboard_parser.addLocaleKeyTextsToParams import helium314.keyboard.latin.R +import helium314.keyboard.latin.common.FileUtils import helium314.keyboard.latin.settings.Settings import java.io.File import java.io.IOException @@ -28,8 +29,10 @@ fun loadCustomLayout(uri: Uri?, languageTag: String, context: Context, onAdded: return infoDialog(context, context.getString(R.string.layout_error, "layout file not found")) val layoutContent: String try { - val i = context.contentResolver.openInputStream(uri) - layoutContent = i?.use { it.reader().readText() } ?: throw IOException() + val tmpFile = File(context.filesDir.absolutePath + File.separator + "tmpfile") + FileUtils.copyContentUriToNewFile(uri, context, tmpFile) + layoutContent = tmpFile.readText() + tmpFile.delete() } catch (e: IOException) { return infoDialog(context, context.getString(R.string.layout_error, "cannot read layout file")) } diff --git a/app/src/main/java/helium314/keyboard/latin/utils/NewDictionaryAdder.kt b/app/src/main/java/helium314/keyboard/latin/utils/NewDictionaryAdder.kt index a2fa2370a..c7343c9fa 100644 --- a/app/src/main/java/helium314/keyboard/latin/utils/NewDictionaryAdder.kt +++ b/app/src/main/java/helium314/keyboard/latin/utils/NewDictionaryAdder.kt @@ -30,8 +30,7 @@ class NewDictionaryAdder(private val context: Context, private val onAdded: ((Bo cachedDictionaryFile.delete() try { - val i = context.contentResolver.openInputStream(uri) - FileUtils.copyStreamToNewFile(i, cachedDictionaryFile) + FileUtils.copyContentUriToNewFile(uri, context, cachedDictionaryFile) } catch (e: IOException) { return onDictionaryLoadingError(R.string.dictionary_load_error) } From 6c6799e97ed0382cad7b9284eff5e8491f522815 Mon Sep 17 00:00:00 2001 From: Helium314 Date: Tue, 20 Feb 2024 11:05:34 +0100 Subject: [PATCH 16/40] clarify that changing layout is only possible if "use system languages" is disabled --- README.md | 3 ++- .../latin/settings/LanguageSettingsDialog.kt | 18 +++++++++++------- 2 files changed, 13 insertions(+), 8 deletions(-) diff --git a/README.md b/README.md index d655ce192..e1c2302b6 100644 --- a/README.md +++ b/README.md @@ -23,7 +23,7 @@ Does not use internet permission, and thus is 100% offline. * Customize keyboard themes (style, colors and background image) * can follow the system's day/night setting on Android 10+ (and on some versions of Android 9) * can follow dynamic colors for Android 12+ -* Customize keyboard [layouts](layouts.md) +* Customize keyboard [layouts](layouts.md) (only when disabling _use system languages_) * Multilingual typing * Glide typing (_only with closed source library_) * library not included in the app, as there is no compatible open source library available @@ -39,6 +39,7 @@ Does not use internet permission, and thus is 100% offline. ## FAQ / Common Issues * __Add a dictionary__: First download the dictionary file, e.g. from [here](https://codeberg.org/Helium314/aosp-dictionaries#dictionaries). Then go to language settings, click on the language, then on `+` next to _dictionary_ the _add_ and select the file. Alternatively you can open a `.dict` file in a file explorer with HeliBoard and then select the language. Note that the latter method does not work with all file explorers. * __Emoji search__: You can get addon dictionaries for emoji suggestions in the [dictionaries repo](https://codeberg.org/Helium314/aosp-dictionaries). An actual search function does not exist yet. +* __Cannot switch choose layout__: This is only possible when _use system languages_ is disabled. * __No suggestions for some language__: Check [dictionaries repo](https://codeberg.org/Helium314/aosp-dictionaries) whether a dictionary is available. If there is one, download it and add it in the language settings for this language. * __No suggestions in some app / text field__: This app respects the [no suggestions flag](https://developer.android.com/reference/android/text/InputType#TYPE_TEXT_FLAG_NO_SUGGESTIONS) set by some input fields, i.e. the developer does not want you to see suggestions here. Best do in issue report for that app if you think this behavior is wrong. Alternatively you can enable the _always show suggestions_ setting that overrides the _no suggestions_ flag. * __How to enable glide typing__: There is no glide typing built into this app, but you can load compatible libraries: Go to advanced settings -> _load gesture typing library_ and point to a file (setting not available in _nouserlib_ version). You can extract the file from GApps packages ("_swypelibs_"), or download one [here](https://github.com/erkserkserks/openboard/tree/master/app/src/main/jniLibs). Make sure to use the correct version (app will tell you in the dialog to load the library). diff --git a/app/src/main/java/helium314/keyboard/latin/settings/LanguageSettingsDialog.kt b/app/src/main/java/helium314/keyboard/latin/settings/LanguageSettingsDialog.kt index 6f0ff0c52..6bf45af4e 100644 --- a/app/src/main/java/helium314/keyboard/latin/settings/LanguageSettingsDialog.kt +++ b/app/src/main/java/helium314/keyboard/latin/settings/LanguageSettingsDialog.kt @@ -39,7 +39,7 @@ class LanguageSettingsDialog( private val onlySystemLocales: Boolean, private val reloadSetting: () -> Unit ) : AlertDialog(context), LanguageSettingsFragment.Listener { - private val prefs = DeviceProtectedUtils.getSharedPreferences(context)!! + private val prefs = DeviceProtectedUtils.getSharedPreferences(context) private val binding = LocaleSettingsDialogBinding.inflate(LayoutInflater.from(context)) private val mainLocale = infos.first().subtype.locale() private var hasInternalDictForLanguage = false @@ -53,6 +53,10 @@ class LanguageSettingsDialog( } if (onlySystemLocales) + // don't allow setting subtypes, because + // a. subtypes are set purely based on system locales (in SubtypeSettings) + // b. extra handling needed if user disables all subtypes for a locale + // todo (later): fix above and allow it binding.subtypes.isGone = true else fillSubtypesView() @@ -147,7 +151,7 @@ class LanguageSettingsDialog( .setTitle(R.string.keyboard_layout_set) .setItems(displayNames.toTypedArray()) { di, i -> di.dismiss() - val fileName = context.assets.list("layouts")!!.firstOrNull { it.startsWith(layouts[i]) } ?: return@setItems + val fileName = context.assets.list("layouts")?.firstOrNull { it.startsWith(layouts[i]) } ?: return@setItems loadCustomLayout(context.assets.open("layouts${File.separator}$fileName").reader().readText(), displayNames[i], mainLocale.toLanguageTag(), context) { addSubtype(it) } } @@ -161,11 +165,11 @@ class LanguageSettingsDialog( private fun addSubtypeToView(subtype: SubtypeInfo) { val row = LayoutInflater.from(context).inflate(R.layout.language_list_item, listView) - val layoutSetName: String? = subtype.subtype.getExtraValueOf(KEYBOARD_LAYOUT_SET) + val layoutSetName = subtype.subtype.getExtraValueOf(KEYBOARD_LAYOUT_SET) ?: "qwerty" row.findViewById(R.id.language_name).text = SubtypeLocaleUtils.getKeyboardLayoutSetDisplayName(subtype.subtype) ?: SubtypeLocaleUtils.getSubtypeDisplayNameInSystemLocale(subtype.subtype) - if (layoutSetName?.startsWith(CUSTOM_LAYOUT_PREFIX) == true) { + if (layoutSetName.startsWith(CUSTOM_LAYOUT_PREFIX)) { row.findViewById(R.id.language_details).setText(R.string.edit_layout) row.findViewById(R.id.language_text).setOnClickListener { editCustomLayout(layoutSetName, context) } } else { @@ -191,18 +195,18 @@ class LanguageSettingsDialog( row.findViewById(R.id.delete_button).apply { isVisible = true setOnClickListener { - val isCustom = layoutSetName?.startsWith(CUSTOM_LAYOUT_PREFIX) == true + val isCustom = layoutSetName.startsWith(CUSTOM_LAYOUT_PREFIX) fun delete() { binding.subtypes.removeView(row) infos.remove(subtype) if (isCustom) - removeCustomLayoutFile(layoutSetName!!, context) + removeCustomLayoutFile(layoutSetName, context) removeAdditionalSubtype(prefs, context.resources, subtype.subtype) removeEnabledSubtype(prefs, subtype.subtype) reloadSetting() } if (isCustom) { - confirmDialog(context, context.getString(R.string.delete_layout, getLayoutDisplayName(layoutSetName!!)), context.getString(R.string.delete)) { delete() } + confirmDialog(context, context.getString(R.string.delete_layout, getLayoutDisplayName(layoutSetName)), context.getString(R.string.delete)) { delete() } } else { delete() } From 056ba3731a8f5ee653f59ff025d618b177598d7a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?M=C3=A6x=C3=A6m=C3=A6t?= Date: Tue, 27 Feb 2024 13:18:26 +0300 Subject: [PATCH 17/40] Kaitag language support (#519) --- .../main/assets/language_key_texts/xdq.txt | 16 ++++++++++ app/src/main/assets/layouts/kaitag.txt | 32 +++++++++++++++++++ .../keyboard/latin/common/LocaleUtils.kt | 2 +- .../keyboard/latin/utils/ScriptUtils.kt | 2 +- app/src/main/res/values-en-rAU/strings.xml | 2 ++ app/src/main/res/values-en-rCA/strings.xml | 2 ++ app/src/main/res/values-en-rGB/strings.xml | 2 ++ app/src/main/res/values-en-rIN/strings.xml | 2 ++ app/src/main/res/values-ru/strings.xml | 2 ++ app/src/main/res/values/donottranslate.xml | 3 ++ app/src/main/res/values/strings.xml | 4 +++ app/src/main/res/xml/method.xml | 9 ++++++ 12 files changed, 76 insertions(+), 2 deletions(-) create mode 100644 app/src/main/assets/language_key_texts/xdq.txt create mode 100644 app/src/main/assets/layouts/kaitag.txt diff --git a/app/src/main/assets/language_key_texts/xdq.txt b/app/src/main/assets/language_key_texts/xdq.txt new file mode 100644 index 000000000..697b2f937 --- /dev/null +++ b/app/src/main/assets/language_key_texts/xdq.txt @@ -0,0 +1,16 @@ +[popup_keys] +у у́ ю +е е́ э ё +ш щ +а а́ +п ф +о о́ +и и́ ы +ъ ӏ +я я́ +ь ӏ +' ’ ‚ ‘ +" ” „ “ + +[labels] +alphabet: АБВ diff --git a/app/src/main/assets/layouts/kaitag.txt b/app/src/main/assets/layouts/kaitag.txt new file mode 100644 index 000000000..51dcff3ea --- /dev/null +++ b/app/src/main/assets/layouts/kaitag.txt @@ -0,0 +1,32 @@ +й +ц +у +к +е +н +г +ш +ҡ +з +х № + +ҳ +ғ +в +а +п +р +о +л +д +ж / +ъ ~ + +я +ч +с +м +и +т +ь +б < > diff --git a/app/src/main/java/helium314/keyboard/latin/common/LocaleUtils.kt b/app/src/main/java/helium314/keyboard/latin/common/LocaleUtils.kt index 067b973ec..6eca45a38 100644 --- a/app/src/main/java/helium314/keyboard/latin/common/LocaleUtils.kt +++ b/app/src/main/java/helium314/keyboard/latin/common/LocaleUtils.kt @@ -181,7 +181,7 @@ object LocaleUtils { fun getLocaleDisplayNameInSystemLocale(locale: Locale, context: Context): String { val languageTag = locale.toLanguageTag() if (languageTag == SubtypeLocaleUtils.NO_LANGUAGE) return context.getString(R.string.subtype_no_language) - if (locale.script() != locale.language.constructLocale().script()) { + if (locale.script() != locale.language.constructLocale().script() || locale.language == "xdq") { val resId = context.resources.getIdentifier("subtype_${languageTag.replace("-", "_")}", "string", context.packageName) if (resId != 0) return context.getString(resId) } diff --git a/app/src/main/java/helium314/keyboard/latin/utils/ScriptUtils.kt b/app/src/main/java/helium314/keyboard/latin/utils/ScriptUtils.kt index c1925cda4..f60e0e047 100644 --- a/app/src/main/java/helium314/keyboard/latin/utils/ScriptUtils.kt +++ b/app/src/main/java/helium314/keyboard/latin/utils/ScriptUtils.kt @@ -165,7 +165,7 @@ object ScriptUtils { "ar", "ur", "fa" -> SCRIPT_ARABIC "hy" -> SCRIPT_ARMENIAN "bn" -> SCRIPT_BENGALI - "sr", "mk", "ru", "uk", "mn", "be", "kk", "ky", "bg" -> SCRIPT_CYRILLIC + "sr", "mk", "ru", "uk", "mn", "be", "kk", "ky", "bg", "xdq" -> SCRIPT_CYRILLIC "ka" -> SCRIPT_GEORGIAN "el" -> SCRIPT_GREEK "iw" -> SCRIPT_HEBREW diff --git a/app/src/main/res/values-en-rAU/strings.xml b/app/src/main/res/values-en-rAU/strings.xml index 926bc0514..f14000bcf 100644 --- a/app/src/main/res/values-en-rAU/strings.xml +++ b/app/src/main/res/values-en-rAU/strings.xml @@ -53,11 +53,13 @@ "English (US)" "Spanish (US)" "Hinglish" + "Kaitag" "Serbian (Latin)" "English (UK) (%s)" "English (US) (%s)" "Spanish (US) (%s)" "Hinglish (%s)" + "Kaitag (%s)" "Serbian (%s)" "%s (Traditional)" "%s (Compact)" diff --git a/app/src/main/res/values-en-rCA/strings.xml b/app/src/main/res/values-en-rCA/strings.xml index 926bc0514..f14000bcf 100644 --- a/app/src/main/res/values-en-rCA/strings.xml +++ b/app/src/main/res/values-en-rCA/strings.xml @@ -53,11 +53,13 @@ "English (US)" "Spanish (US)" "Hinglish" + "Kaitag" "Serbian (Latin)" "English (UK) (%s)" "English (US) (%s)" "Spanish (US) (%s)" "Hinglish (%s)" + "Kaitag (%s)" "Serbian (%s)" "%s (Traditional)" "%s (Compact)" diff --git a/app/src/main/res/values-en-rGB/strings.xml b/app/src/main/res/values-en-rGB/strings.xml index 309b97524..c03a8bdc6 100644 --- a/app/src/main/res/values-en-rGB/strings.xml +++ b/app/src/main/res/values-en-rGB/strings.xml @@ -53,11 +53,13 @@ "English (US)" "Spanish (US)" "Hinglish" + "Kaitag" "Serbian (Latin)" English (UK) (%s) English (US) (%s) Spanish (US) (%s) Hinglish (%s) + Kaitag (%s) Serbian (%s) %s (Traditional) %s (Compact) diff --git a/app/src/main/res/values-en-rIN/strings.xml b/app/src/main/res/values-en-rIN/strings.xml index 002cd7e90..322799645 100644 --- a/app/src/main/res/values-en-rIN/strings.xml +++ b/app/src/main/res/values-en-rIN/strings.xml @@ -53,11 +53,13 @@ "English (US)" "Spanish (US)" "Hinglish" + "Kaitag" "Serbian (Latin)" "English (UK) (%s)" "English (US) (%s)" "Spanish (US) (%s)" "Hinglish (%s)" + "Kaitag (%s)" "Serbian (%s)" "%s (Traditional)" "%s (Compact)" diff --git a/app/src/main/res/values-ru/strings.xml b/app/src/main/res/values-ru/strings.xml index 6f7d70647..501ffd450 100644 --- a/app/src/main/res/values-ru/strings.xml +++ b/app/src/main/res/values-ru/strings.xml @@ -53,11 +53,13 @@ Английский (США) Испанский (США) хинглиш + Кайтагский сербский (латиница) Английский (Великобритания, %s) Английский (США, %s) Испанский (США, %s) хинглиш (%s) + Кайтагский (%s) сербский (%s) %s (классическая) %s (Компактная) diff --git a/app/src/main/res/values/donottranslate.xml b/app/src/main/res/values/donottranslate.xml index 68e5f47eb..958226be8 100644 --- a/app/src/main/res/values/donottranslate.xml +++ b/app/src/main/res/values/donottranslate.xml @@ -14,15 +14,18 @@ en-GB es-US hi-Latn + xdq sr-Latn hi-Latn + xdq sr-Latn Hinglish + Хайдаҡьан Srpski diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index c3ded5980..d7f111157 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -277,6 +277,7 @@ Spanish (US) Hinglish + Kaitag Serbian (Latin) @@ -297,6 +298,9 @@ Hinglish (%s) + Kaitag (%s) + Serbian (%s) diff --git a/app/src/main/res/xml/method.xml b/app/src/main/res/xml/method.xml index ffadf2905..d7e53ea1e 100644 --- a/app/src/main/res/xml/method.xml +++ b/app/src/main/res/xml/method.xml @@ -615,6 +615,15 @@ android:imeSubtypeExtraValue="KeyboardLayoutSet=russian,EmojiCapable" android:isAsciiCapable="false" /> + Date: Tue, 27 Feb 2024 11:19:10 +0100 Subject: [PATCH 18/40] remove native build id for reproducible builds --- app/src/main/jni/Android.mk | 3 +++ 1 file changed, 3 insertions(+) diff --git a/app/src/main/jni/Android.mk b/app/src/main/jni/Android.mk index 34f525250..de21410c8 100755 --- a/app/src/main/jni/Android.mk +++ b/app/src/main/jni/Android.mk @@ -92,6 +92,9 @@ LOCAL_SDK_VERSION := 14 LOCAL_NDK_STL_VARIANT := c++_static LOCAL_LDFLAGS += -ldl +# Avoid issues with reproducible builds, see https://gitlab.com/fdroid/rfp/-/issues/2662 +LOCAL_LDFLAGS += -Wl,--build-id=none + include $(BUILD_SHARED_LIBRARY) #################### Clean up the tmp vars include $(LOCAL_PATH)/CleanupNativeFileList.mk From c9d9ef5c63bf8e7ee7623d9409369e1857469d19 Mon Sep 17 00:00:00 2001 From: Helium314 Date: Tue, 27 Feb 2024 11:29:44 +0100 Subject: [PATCH 19/40] udpate readmes --- README.md | 1 + layouts.md | 2 ++ 2 files changed, 3 insertions(+) diff --git a/README.md b/README.md index e1c2302b6..aa966ef70 100644 --- a/README.md +++ b/README.md @@ -88,6 +88,7 @@ Note that issues that that ignore part of the issue template will likely get tre ## Translation Translations can be added using [Weblate](https://translate.codeberg.org/projects/heliboard/). You will need an account to update translations and add languages. Add the language you want to translate to in Languages -> Manage translated languages in the top menu bar. +Updating translations in a PR will not be accepted, as it may cause conflicts with Weblate tranlations. ## Dictionary Creation There will not be any further dictionaries bundled in this app. However, you can add dictionaries to the [dictionaries repository](https://codeberg.org/Helium314/aosp-dictionaries). diff --git a/layouts.md b/layouts.md index e7ba3ea7c..67603c797 100644 --- a/layouts.md +++ b/layouts.md @@ -44,3 +44,5 @@ If you want different key label and use text, set the label to [label]|[text], e * `[labels]` may contain non-default labels for the following keys `symbol`, `alphabet`, `shift_symbol`, `shift_symbol_tablet`, `comma`, `period`, `question` * `[number_row]` may contain a custom number row (1-9 and 0 separated by space). You should also add the language to `numberRowLocales` in [`PreferencesSettingsFragment`](app/src/main/java/helium314/keyboard/latin/settings/PreferencesSettingsFragment.java) so the user can opt into having a localized number row. * `[extra_keys]` are typically keys shown in the default layout of the language. This is currently only used for latin layouts to avoid duplicating layouts for just adding few keys on the right side. The layout name need to end with `+`, but the `+` is removed when looking up the actual layout. +* If you add a new language for which Android does not have a display name, it will be displayed using the language tag + * Avoiding this currently is more complicated than necessary: add the language tag to [LocaleUtils.getLocaleDisplayNameInSystemLocale](/app/src/main/java/helium314/keyboard/latin/common/LocaleUtils.kt#L181) to have an exception, and add a string named `subtype_` to [`strings.xml`](/app/src/main/res/values/strings.xml). Further you may need to add a `subtype_in_root_locale_` to [donottranslate.xml](/app/src/main/res/values/donottranslate.xml), and add the language tag to `subtype_locale_exception_keys` and `subtype_locale_displayed_in_root_locale`. From 777737db72fa6cbd13ca94ea0e1a1523bef8378a Mon Sep 17 00:00:00 2001 From: Helium314 Date: Tue, 27 Feb 2024 16:55:46 +0100 Subject: [PATCH 20/40] add todo section to readme --- README.md | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/README.md b/README.md index aa966ef70..c5ad21f4a 100644 --- a/README.md +++ b/README.md @@ -12,6 +12,7 @@ Does not use internet permission, and thus is 100% offline. * [Translation](#translation) * [Dictionary Creation](#dictionary-creation) * [Code Contribution](#code-contribution) +- [To-do](#to-do) - [License](#license) - [Credits](#credits) @@ -130,6 +131,22 @@ See make-emoji-keys tool [README](tools/make-emoji-keys/README.md). See make-dict-list tool [README](tools/make-dict-list/README.md). +# To-do +Planned features and improvements +* Customizable functional key layout + * Will likely result in having the same functional key layout for alphabet and symbols layouts + * Requires adjusting names and codes for compatibility with FlorisBoard layouts +* Support for "special keys" like _alt_ and _ctrl_ (#479) +* Less complicated addition of languages (e.g. #519) +* Additional and customizable key swipe functionality + * Some functionality will not be possible when using glide typing +* Ability to enter all emojis independent of Android version (optional, #297) +* (limited) support for customizing _all_ internally used colors +* Add and enable emoji dictionaries by default (if available for language) +* Clearer / more intuitive arrangement of settings + * Maybe hide some less used settings by default (similar to color customization) +* Bug fixes + # License HeliBoard (as a fork of OpenBoard) is licensed under GNU General Public License v3.0. From b30ac99b09118a6483ecaa149ef07e9bd158a19e Mon Sep 17 00:00:00 2001 From: Helium314 Date: Tue, 27 Feb 2024 20:31:00 +0100 Subject: [PATCH 21/40] prepare for adding AllColors --- .../helium314/keyboard/latin/common/Colors.kt | 44 +++++++++++++++++++ 1 file changed, 44 insertions(+) diff --git a/app/src/main/java/helium314/keyboard/latin/common/Colors.kt b/app/src/main/java/helium314/keyboard/latin/common/Colors.kt index 09eaaa494..19c644dbc 100644 --- a/app/src/main/java/helium314/keyboard/latin/common/Colors.kt +++ b/app/src/main/java/helium314/keyboard/latin/common/Colors.kt @@ -33,6 +33,7 @@ import helium314.keyboard.latin.utils.brightenOrDarken import helium314.keyboard.latin.utils.darken import helium314.keyboard.latin.utils.isBrightColor import helium314.keyboard.latin.utils.isDarkColor +import java.util.EnumMap interface Colors { // these theme parameters should no be in here, but are still used @@ -537,6 +538,49 @@ class DefaultColors ( } } +// todo: allow users to use this class +// the colorMap should be stored in settings +// reading should consider that colors might be added and removed, i.e. no "simple" serialization +// color settings should add another menu option for "all colors" +// just show all ColorTypes with current value read from the map (default to black, same as in get) +// no string name, as it is not stable +class AllColors(private val colorMap: EnumMap, override val themeStyle: String, override val hasKeyBorders: Boolean) : Colors { + private var keyboardBackground: Drawable? = null + private val stateListMap = EnumMap(ColorType::class.java) + private var backgroundSetupDone = false + override fun get(color: ColorType): Int = colorMap[color] ?: Color.BLACK + + override fun setColor(drawable: Drawable, color: ColorType) { + val colorStateList = stateListMap.getOrPut(color) { stateList(brightenOrDarken(get(color), true), get(color)) } + DrawableCompat.setTintMode(drawable, PorterDuff.Mode.MULTIPLY) + DrawableCompat.setTintList(drawable, colorStateList) + } + + override fun setColor(view: ImageView, color: ColorType) { + setColor(view.drawable, color) + } + + override fun setBackground(view: View, color: ColorType) { + if (view.background == null) + view.setBackgroundColor(Color.WHITE) // set white to make the color filters work + when (color) { + ONE_HANDED_MODE_BUTTON -> setColor(view.background, BACKGROUND) // button has no separate background color + MAIN_BACKGROUND -> { + if (keyboardBackground != null) { + if (!backgroundSetupDone) { + keyboardBackground = BitmapDrawable(view.context.resources, keyboardBackground!!.toBitmap(view.width, view.height)) + backgroundSetupDone = true + } + view.background = keyboardBackground + } else { + setColor(view.background, color) + } + } + else -> setColor(view.background, color) + } + } +} + private fun colorFilter(color: Int, mode: BlendModeCompat = BlendModeCompat.MODULATE): ColorFilter { // using !! for the color filter because null is only returned for unsupported blend modes, which are not used return BlendModeColorFilterCompat.createBlendModeColorFilterCompat(color, mode)!! From 7b0ee924ae0f349476600fc93cfbe076ffca9b41 Mon Sep 17 00:00:00 2001 From: Helium314 Date: Sat, 2 Mar 2024 18:52:55 +0100 Subject: [PATCH 22/40] use less specific key codes --- .../accessibility/KeyCodeDescriptionMapper.kt | 2 +- .../java/helium314/keyboard/keyboard/Key.java | 5 +- .../keyboard/keyboard/PointerTracker.java | 2 +- .../clipboard/ClipboardHistoryView.kt | 2 +- .../keyboard/emoji/EmojiPalettesView.java | 2 +- .../keyboard/internal/KeyboardBuilder.kt | 1 + .../keyboard/internal/KeyboardCodesSet.java | 14 +- .../keyboard/internal/KeyboardState.java | 135 ++++++------------ .../keyboard_parser/KeyboardParser.kt | 25 ++-- .../keyboard/latin/common/Constants.java | 19 ++- .../keyboard/latin/inputlogic/InputLogic.java | 12 +- .../res/values-sw600dp/functional-keys.xml | 2 +- app/src/main/res/values/functional-keys.xml | 2 +- 13 files changed, 87 insertions(+), 136 deletions(-) diff --git a/app/src/main/java/helium314/keyboard/accessibility/KeyCodeDescriptionMapper.kt b/app/src/main/java/helium314/keyboard/accessibility/KeyCodeDescriptionMapper.kt index 382d894dc..338c77250 100644 --- a/app/src/main/java/helium314/keyboard/accessibility/KeyCodeDescriptionMapper.kt +++ b/app/src/main/java/helium314/keyboard/accessibility/KeyCodeDescriptionMapper.kt @@ -57,7 +57,7 @@ internal class KeyCodeDescriptionMapper private constructor() { */ fun getDescriptionForKey(context: Context, keyboard: Keyboard?, key: Key, shouldObscure: Boolean): String? { val code = key.code - if (code == Constants.CODE_SWITCH_ALPHA_SYMBOL) { + if (code == Constants.CODE_SWITCH_ALPHA_SYMBOL || code == Constants.CODE_SWITCH_SYMBOL || code == Constants.CODE_SWITCH_ALPHA) { val description = getDescriptionForSwitchAlphaSymbol(context, keyboard) if (description != null) { return description diff --git a/app/src/main/java/helium314/keyboard/keyboard/Key.java b/app/src/main/java/helium314/keyboard/keyboard/Key.java index 6ab00c667..fd8cffdff 100644 --- a/app/src/main/java/helium314/keyboard/keyboard/Key.java +++ b/app/src/main/java/helium314/keyboard/keyboard/Key.java @@ -26,10 +26,11 @@ import java.util.Locale; import static helium314.keyboard.keyboard.internal.KeyboardIconsSet.ICON_UNDEFINED; -import static helium314.keyboard.latin.common.Constants.CODE_ALPHA_FROM_NUMPAD; import static helium314.keyboard.latin.common.Constants.CODE_OUTPUT_TEXT; import static helium314.keyboard.latin.common.Constants.CODE_SHIFT; +import static helium314.keyboard.latin.common.Constants.CODE_SWITCH_ALPHA; import static helium314.keyboard.latin.common.Constants.CODE_SWITCH_ALPHA_SYMBOL; +import static helium314.keyboard.latin.common.Constants.CODE_SWITCH_SYMBOL; import static helium314.keyboard.latin.common.Constants.CODE_UNSPECIFIED; import androidx.annotation.NonNull; @@ -517,7 +518,7 @@ public final boolean isShift() { } public final boolean isModifier() { - return mCode == CODE_SHIFT || mCode == CODE_SWITCH_ALPHA_SYMBOL || mCode == CODE_ALPHA_FROM_NUMPAD; + return mCode == CODE_SHIFT || mCode == CODE_SWITCH_ALPHA_SYMBOL || mCode == CODE_SWITCH_ALPHA || mCode == CODE_SWITCH_SYMBOL; } public final boolean isRepeatable() { diff --git a/app/src/main/java/helium314/keyboard/keyboard/PointerTracker.java b/app/src/main/java/helium314/keyboard/keyboard/PointerTracker.java index b47295a69..a9a86ed7f 100644 --- a/app/src/main/java/helium314/keyboard/keyboard/PointerTracker.java +++ b/app/src/main/java/helium314/keyboard/keyboard/PointerTracker.java @@ -1114,7 +1114,7 @@ public void onLongPressed() { } } if (code == Constants.CODE_SWITCH_ALPHA_SYMBOL) { - sListener.onCodeInput(Constants.CODE_NUMPAD, Constants.NOT_A_COORDINATE, Constants.NOT_A_COORDINATE, false); + sListener.onCodeInput(Constants.CODE_SWITCH_NUMPAD, Constants.NOT_A_COORDINATE, Constants.NOT_A_COORDINATE, false); return; } diff --git a/app/src/main/java/helium314/keyboard/keyboard/clipboard/ClipboardHistoryView.kt b/app/src/main/java/helium314/keyboard/keyboard/clipboard/ClipboardHistoryView.kt index 0f0c21ba8..a225f280f 100644 --- a/app/src/main/java/helium314/keyboard/keyboard/clipboard/ClipboardHistoryView.kt +++ b/app/src/main/java/helium314/keyboard/keyboard/clipboard/ClipboardHistoryView.kt @@ -102,7 +102,7 @@ class ClipboardHistoryView @JvmOverloads constructor( } alphabetKey = findViewById(R.id.key_alphabet) alphabetKey.setBackgroundResource(functionalKeyBackgroundId) - alphabetKey.tag = Constants.CODE_ALPHA_FROM_CLIPBOARD + alphabetKey.tag = Constants.CODE_SWITCH_ALPHA alphabetKey.setOnTouchListener(this) alphabetKey.setOnClickListener(this) deleteKey = findViewById(R.id.key_delete) diff --git a/app/src/main/java/helium314/keyboard/keyboard/emoji/EmojiPalettesView.java b/app/src/main/java/helium314/keyboard/keyboard/emoji/EmojiPalettesView.java index 783ac3c72..6435b25b9 100644 --- a/app/src/main/java/helium314/keyboard/keyboard/emoji/EmojiPalettesView.java +++ b/app/src/main/java/helium314/keyboard/keyboard/emoji/EmojiPalettesView.java @@ -237,7 +237,7 @@ public void onScrolled(@NonNull @NotNull RecyclerView recyclerView, int dx, int // {@link #startEmojiPalettes(String,int,float,Typeface)}. mAlphabetKeyLeft = findViewById(R.id.key_alphabet); mAlphabetKeyLeft.setBackgroundResource(mFunctionalKeyBackgroundId); - mAlphabetKeyLeft.setTag(Constants.CODE_ALPHA_FROM_EMOJI); + mAlphabetKeyLeft.setTag(Constants.CODE_SWITCH_ALPHA); mAlphabetKeyLeft.setOnTouchListener(this); mAlphabetKeyLeft.setOnClickListener(this); mSpacebar = findViewById(R.id.key_space); diff --git a/app/src/main/java/helium314/keyboard/keyboard/internal/KeyboardBuilder.kt b/app/src/main/java/helium314/keyboard/keyboard/internal/KeyboardBuilder.kt index cdeaed546..5caebb7f9 100644 --- a/app/src/main/java/helium314/keyboard/keyboard/internal/KeyboardBuilder.kt +++ b/app/src/main/java/helium314/keyboard/keyboard/internal/KeyboardBuilder.kt @@ -207,6 +207,7 @@ open class KeyboardBuilder(protected val mContext: Context, } // reduce width of symbol and action key if in the row, and add this width to space to keep other key size constant + // todo: this assumes fixed layout for symbols keys, which will change soon! private fun reduceSymbolAndActionKeyWidth(row: ArrayList) { val spaceKey = row.first { it.mCode == Constants.CODE_SPACE } val symbolKey = row.firstOrNull { it.mCode == Constants.CODE_SWITCH_ALPHA_SYMBOL } diff --git a/app/src/main/java/helium314/keyboard/keyboard/internal/KeyboardCodesSet.java b/app/src/main/java/helium314/keyboard/keyboard/internal/KeyboardCodesSet.java index 27fc16e1a..e10f48f5d 100644 --- a/app/src/main/java/helium314/keyboard/keyboard/internal/KeyboardCodesSet.java +++ b/app/src/main/java/helium314/keyboard/keyboard/internal/KeyboardCodesSet.java @@ -32,6 +32,8 @@ public static int getCode(final String name) { "key_shift", "key_capslock", "key_switch_alpha_symbol", + "key_switch_alpha", + "key_switch_symbol", "key_output_text", "key_delete", "key_settings", @@ -41,13 +43,9 @@ public static int getCode(final String name) { "key_shift_enter", "key_language_switch", "key_emoji", - "key_alpha_from_emoji", "key_unspecified", "key_clipboard", - "key_alpha_from_clipboard", "key_numpad", - "key_alphaNumpad", - "key_symbolNumpad", "key_start_onehanded", "key_stop_onehanded", "key_switch_onehanded" @@ -60,6 +58,8 @@ public static int getCode(final String name) { Constants.CODE_SHIFT, Constants.CODE_CAPSLOCK, Constants.CODE_SWITCH_ALPHA_SYMBOL, + Constants.CODE_SWITCH_ALPHA, + Constants.CODE_SWITCH_SYMBOL, Constants.CODE_OUTPUT_TEXT, Constants.CODE_DELETE, Constants.CODE_SETTINGS, @@ -69,13 +69,9 @@ public static int getCode(final String name) { Constants.CODE_SHIFT_ENTER, Constants.CODE_LANGUAGE_SWITCH, Constants.CODE_EMOJI, - Constants.CODE_ALPHA_FROM_EMOJI, Constants.CODE_UNSPECIFIED, Constants.CODE_CLIPBOARD, - Constants.CODE_ALPHA_FROM_CLIPBOARD, - Constants.CODE_NUMPAD, - Constants.CODE_ALPHA_FROM_NUMPAD, - Constants.CODE_SYMBOL_FROM_NUMPAD, + Constants.CODE_SWITCH_NUMPAD, Constants.CODE_START_ONE_HANDED_MODE, Constants.CODE_STOP_ONE_HANDED_MODE, Constants.CODE_SWITCH_ONE_HANDED_MODE diff --git a/app/src/main/java/helium314/keyboard/keyboard/internal/KeyboardState.java b/app/src/main/java/helium314/keyboard/keyboard/internal/KeyboardState.java index 4f2fc295b..a7f222cba 100644 --- a/app/src/main/java/helium314/keyboard/keyboard/internal/KeyboardState.java +++ b/app/src/main/java/helium314/keyboard/keyboard/internal/KeyboardState.java @@ -67,7 +67,6 @@ public interface SwitchActions { private final ShiftKeyState mShiftKeyState = new ShiftKeyState("Shift"); private final ModifierKeyState mSymbolKeyState = new ModifierKeyState("Symbol"); - private final ModifierKeyState mAlphaNumpadKeyState = new ModifierKeyState("AlphaNumpad"); private final AlphabetShiftState mAlphabetShiftState = new AlphabetShiftState(); // TODO: Merge {@link #mSwitchState}, {@link #mIsAlphabetMode}, {@link #mAlphabetShiftState}, @@ -76,12 +75,12 @@ public interface SwitchActions { private static final int SWITCH_STATE_ALPHA = 0; private static final int SWITCH_STATE_SYMBOL_BEGIN = 1; private static final int SWITCH_STATE_SYMBOL = 2; - private static final int SWITCH_STATE_MOMENTARY_ALPHA_AND_SYMBOL = 3; - private static final int SWITCH_STATE_MOMENTARY_SYMBOL_AND_MORE = 4; - private static final int SWITCH_STATE_MOMENTARY_ALPHA_SHIFT = 5; + private static final int SWITCH_STATE_NUMPAD = 3; + private static final int SWITCH_STATE_MOMENTARY_ALPHA_AND_SYMBOL = 4; + private static final int SWITCH_STATE_MOMENTARY_SYMBOL_AND_MORE = 5; + private static final int SWITCH_STATE_MOMENTARY_ALPHA_SHIFT = 6; + private static final int SWITCH_STATE_MOMENTARY_FROM_NUMPAD = 7; private int mSwitchState = SWITCH_STATE_ALPHA; - private static final int SWITCH_STATE_NUMPAD = 6; - private static final int SWITCH_STATE_MOMENTARY_NUMPAD_AND_ALPHA = 7; private static final int MODE_ALPHABET = 0; private static final int MODE_SYMBOLS = 1; @@ -290,23 +289,6 @@ private void toggleAlphabetAndSymbols(final int autoCapsFlags, final int recapit } } - private void toggleNumpadAndAlphabet(final int autoCapsFlags, final int recapitalizeMode) { - if (DEBUG_INTERNAL_ACTION) { - Log.d(TAG, "toggleNumpadAndAlphabet: " - + stateToString(autoCapsFlags, recapitalizeMode)); - } - if (mMode == MODE_NUMPAD) { - mPrevMainKeyboardWasShiftLocked = mAlphabetShiftState.isShiftLocked(); - setAlphabetKeyboard(autoCapsFlags, recapitalizeMode); - if (mPrevMainKeyboardWasShiftLocked) { - setShiftLocked(true); - } - mPrevMainKeyboardWasShiftLocked = false; - } else { - setNumpadKeyboard(); - } - } - // TODO: Remove this method. Come up with a more comprehensive way to reset the keyboard layout // when a keyboard layout set doesn't get reloaded in LatinIME.onStartInputViewInternal(). private void resetKeyboardStateToAlphabet(final int autoCapsFlags, final int recapitalizeMode) { @@ -439,9 +421,13 @@ public void onPressKey(final int code, final boolean isSinglePointer, final int } else if (code == Constants.CODE_CAPSLOCK) { // Nothing to do here. See {@link #onReleaseKey(int,boolean)}. } else if (code == Constants.CODE_SWITCH_ALPHA_SYMBOL) { - onPressSymbol(autoCapsFlags, recapitalizeMode); - } else if (code == Constants.CODE_ALPHA_FROM_NUMPAD) { - onPressAlphaNumpad(autoCapsFlags, recapitalizeMode); + onPressAlphaSymbol(autoCapsFlags, recapitalizeMode); + } else if (code == Constants.CODE_SWITCH_SYMBOL) { + // don't start sliding, causes issues with fully customizable layouts + // (also does not allow chording, but can be fixed later) + } else if (code == Constants.CODE_SWITCH_ALPHA) { + // don't start sliding, causes issues with fully customizable layouts + // (also does not allow chording, but can be fixed later) } else { mShiftKeyState.onOtherKeyPressed(); mSymbolKeyState.onOtherKeyPressed(); @@ -476,21 +462,21 @@ public void onReleaseKey(final int code, final boolean withSliding, final int au } else if (code == Constants.CODE_CAPSLOCK) { setShiftLocked(!mAlphabetShiftState.isShiftLocked()); } else if (code == Constants.CODE_SWITCH_ALPHA_SYMBOL) { + onReleaseAlphaSymbol(withSliding, autoCapsFlags, recapitalizeMode); + } else if (code == Constants.CODE_SWITCH_SYMBOL) { onReleaseSymbol(withSliding, autoCapsFlags, recapitalizeMode); - } else if (code == Constants.CODE_ALPHA_FROM_NUMPAD) { - onReleaseAlphaNumpad(withSliding, autoCapsFlags, recapitalizeMode); + } else if (code == Constants.CODE_SWITCH_ALPHA) { + onReleaseAlpha(withSliding, autoCapsFlags, recapitalizeMode); } } - private void onPressSymbol(final int autoCapsFlags, - final int recapitalizeMode) { + private void onPressAlphaSymbol(final int autoCapsFlags, final int recapitalizeMode) { toggleAlphabetAndSymbols(autoCapsFlags, recapitalizeMode); mSymbolKeyState.onPress(); mSwitchState = SWITCH_STATE_MOMENTARY_ALPHA_AND_SYMBOL; } - private void onReleaseSymbol(final boolean withSliding, final int autoCapsFlags, - final int recapitalizeMode) { + private void onReleaseAlphaSymbol(final boolean withSliding, final int autoCapsFlags, final int recapitalizeMode) { if (mSymbolKeyState.isChording()) { // Switch back to the previous keyboard mode if the user chords the mode change key and // another key, then releases the mode change key. @@ -504,27 +490,18 @@ private void onReleaseSymbol(final boolean withSliding, final int autoCapsFlags, mSymbolKeyState.onRelease(); } - private void onPressAlphaNumpad(final int autoCapsFlags, - final int recapitalizeMode) { - toggleNumpadAndAlphabet(autoCapsFlags, recapitalizeMode); - mAlphaNumpadKeyState.onPress(); - mSwitchState = SWITCH_STATE_MOMENTARY_NUMPAD_AND_ALPHA; + private void onReleaseSymbol(final boolean withSliding, final int autoCapsFlags, final int recapitalizeMode) { + final int oldMode = mMode; + setSymbolsKeyboard(); + if (withSliding && oldMode == MODE_NUMPAD) + mSwitchState = SWITCH_STATE_MOMENTARY_FROM_NUMPAD; } - private void onReleaseAlphaNumpad(final boolean withSliding, final int autoCapsFlags, - final int recapitalizeMode) { - if (mAlphaNumpadKeyState.isChording()) { - // Switch back to the previous keyboard mode if the user chords the mode change key and - // another key, then releases the mode change key. - toggleNumpadAndAlphabet(autoCapsFlags, recapitalizeMode); - } else if (!withSliding) { - // If the mode change key is being released without sliding, we should remember - // caps lock mode and reset alphabet shift state. - mPrevMainKeyboardWasShiftLocked = mAlphabetShiftState.isShiftLocked(); - mAlphabetShiftState.setShiftLocked(false); - - } - mAlphaNumpadKeyState.onRelease(); + private void onReleaseAlpha(final boolean withSliding, final int autoCapsFlags, final int recapitalizeMode) { + final int oldMode = mMode; + setAlphabetKeyboard(autoCapsFlags, recapitalizeMode); + if (withSliding && oldMode == MODE_NUMPAD) + mSwitchState = SWITCH_STATE_MOMENTARY_FROM_NUMPAD; } public void onUpdateShiftState(final int autoCapsFlags, final int recapitalizeMode) { @@ -701,18 +678,10 @@ public void onFinishSlidingInput(final int autoCapsFlags, final int recapitalize } // Switch back to the previous keyboard mode if the user cancels sliding input. switch (mSwitchState) { - case SWITCH_STATE_MOMENTARY_ALPHA_AND_SYMBOL: - toggleAlphabetAndSymbols(autoCapsFlags, recapitalizeMode); - break; - case SWITCH_STATE_MOMENTARY_SYMBOL_AND_MORE: - toggleShiftInSymbols(); - break; - case SWITCH_STATE_MOMENTARY_ALPHA_SHIFT: - setAlphabetKeyboard(autoCapsFlags, recapitalizeMode); - break; - case SWITCH_STATE_MOMENTARY_NUMPAD_AND_ALPHA: - toggleNumpadAndAlphabet(autoCapsFlags, recapitalizeMode); - break; + case SWITCH_STATE_MOMENTARY_ALPHA_AND_SYMBOL -> toggleAlphabetAndSymbols(autoCapsFlags, recapitalizeMode); + case SWITCH_STATE_MOMENTARY_SYMBOL_AND_MORE -> toggleShiftInSymbols(); + case SWITCH_STATE_MOMENTARY_ALPHA_SHIFT -> setAlphabetKeyboard(autoCapsFlags, recapitalizeMode); + case SWITCH_STATE_MOMENTARY_FROM_NUMPAD -> setNumpadKeyboard(); } } @@ -738,16 +707,6 @@ public void onEvent(final Event event, final int autoCapsFlags, final int recapi } } break; - case SWITCH_STATE_MOMENTARY_NUMPAD_AND_ALPHA: - if (code == Constants.CODE_ALPHA_FROM_NUMPAD) { - // Detected only the mode change key has been pressed, and then released. - if (mMode == MODE_NUMPAD) { - mSwitchState = SWITCH_STATE_NUMPAD; - } else { - mSwitchState = SWITCH_STATE_ALPHA; - } - } - break; case SWITCH_STATE_MOMENTARY_SYMBOL_AND_MORE: if (code == Constants.CODE_SHIFT) { // Detected only the shift key has been pressed on symbol layout, and then @@ -793,7 +752,7 @@ public void onEvent(final Event event, final int autoCapsFlags, final int recapi updateAlphabetShiftState(autoCapsFlags, recapitalizeMode); } else if (code == Constants.CODE_EMOJI) { setEmojiKeyboard(); - } else if (code == Constants.CODE_ALPHA_FROM_EMOJI) { + } else if (code == Constants.CODE_SWITCH_ALPHA) { setAlphabetKeyboard(autoCapsFlags, recapitalizeMode); } else if (code == Constants.CODE_CLIPBOARD) { // Note: Printing clipboard content is handled in @@ -801,11 +760,9 @@ public void onEvent(final Event event, final int autoCapsFlags, final int recapi if (Settings.getInstance().getCurrent().mClipboardHistoryEnabled) { setClipboardKeyboard(); } - } else if (code == Constants.CODE_ALPHA_FROM_CLIPBOARD) { - setAlphabetKeyboard(autoCapsFlags, recapitalizeMode); - } else if (code == Constants.CODE_NUMPAD) { + } else if (code == Constants.CODE_SWITCH_NUMPAD) { setNumpadKeyboard(); - } else if (code == Constants.CODE_SYMBOL_FROM_NUMPAD) { + } else if (code == Constants.CODE_SWITCH_SYMBOL) { setSymbolsKeyboard(); } else if (code == Constants.CODE_START_ONE_HANDED_MODE) { setOneHandedModeEnabled(true); @@ -826,17 +783,17 @@ static String shiftModeToString(final int shiftMode) { } private static String switchStateToString(final int switchState) { - switch (switchState) { - case SWITCH_STATE_ALPHA: return "ALPHA"; - case SWITCH_STATE_SYMBOL_BEGIN: return "SYMBOL-BEGIN"; - case SWITCH_STATE_SYMBOL: return "SYMBOL"; - case SWITCH_STATE_MOMENTARY_ALPHA_AND_SYMBOL: return "MOMENTARY-ALPHA-SYMBOL"; - case SWITCH_STATE_MOMENTARY_SYMBOL_AND_MORE: return "MOMENTARY-SYMBOL-MORE"; - case SWITCH_STATE_MOMENTARY_ALPHA_SHIFT: return "MOMENTARY-ALPHA_SHIFT"; - case SWITCH_STATE_NUMPAD: return "NUMPAD"; - case SWITCH_STATE_MOMENTARY_NUMPAD_AND_ALPHA: return "MOMENTARY-NUMPAD-ALPHA"; - default: return null; - } + return switch (switchState) { + case SWITCH_STATE_ALPHA -> "ALPHA"; + case SWITCH_STATE_SYMBOL_BEGIN -> "SYMBOL-BEGIN"; + case SWITCH_STATE_SYMBOL -> "SYMBOL"; + case SWITCH_STATE_MOMENTARY_ALPHA_AND_SYMBOL -> "MOMENTARY-ALPHA-SYMBOL"; + case SWITCH_STATE_MOMENTARY_SYMBOL_AND_MORE -> "MOMENTARY-SYMBOL-MORE"; + case SWITCH_STATE_MOMENTARY_ALPHA_SHIFT -> "MOMENTARY-ALPHA_SHIFT"; + case SWITCH_STATE_NUMPAD -> "NUMPAD"; + case SWITCH_STATE_MOMENTARY_FROM_NUMPAD -> "MOMENTARY-FROM-NUMPAD"; + default -> null; + }; } @Override diff --git a/app/src/main/java/helium314/keyboard/keyboard/internal/keyboard_parser/KeyboardParser.kt b/app/src/main/java/helium314/keyboard/keyboard/internal/keyboard_parser/KeyboardParser.kt index ef457f0b7..4c7675eb3 100644 --- a/app/src/main/java/helium314/keyboard/keyboard/internal/keyboard_parser/KeyboardParser.kt +++ b/app/src/main/java/helium314/keyboard/keyboard/internal/keyboard_parser/KeyboardParser.kt @@ -413,9 +413,18 @@ abstract class KeyboardParser(private val params: KeyboardParams, private val co // for comma and period: label will override default, popupKeys will be appended val width = relativeWidth ?: params.mDefaultRelativeKeyWidth return when (key) { + FunctionalKey.SYMBOL_ALPHA -> KeyParams( + if (params.mId.isAlphabetKeyboard) getToSymbolLabel() else params.mLocaleKeyboardInfos.labelAlphabet, + Constants.CODE_SWITCH_ALPHA_SYMBOL, + params, + width, + Key.LABEL_FLAGS_PRESERVE_CASE or Key.LABEL_FLAGS_FOLLOW_FUNCTIONAL_TEXT_COLOR, + Key.BACKGROUND_TYPE_FUNCTIONAL, + null + ) FunctionalKey.SYMBOL -> KeyParams( getToSymbolLabel(), - getToSymbolCode(), + Constants.CODE_SWITCH_SYMBOL, params, width, Key.LABEL_FLAGS_PRESERVE_CASE or Key.LABEL_FLAGS_FOLLOW_FUNCTIONAL_TEXT_COLOR, @@ -424,7 +433,7 @@ abstract class KeyboardParser(private val params: KeyboardParams, private val co ) FunctionalKey.ALPHA -> KeyParams( params.mLocaleKeyboardInfos.labelAlphabet, - getToAlphaCode(), + Constants.CODE_SWITCH_ALPHA, params, width, Key.LABEL_FLAGS_PRESERVE_CASE or Key.LABEL_FLAGS_FOLLOW_FUNCTIONAL_TEXT_COLOR, @@ -660,16 +669,6 @@ abstract class KeyboardParser(private val params: KeyboardParams, private val co params.mLocaleKeyboardInfos.labelAlphabet else params.mLocaleKeyboardInfos.labelSymbol - private fun getToSymbolCode() = - if (params.mId.mElementId == KeyboardId.ELEMENT_NUMPAD) - Constants.CODE_SYMBOL_FROM_NUMPAD - else Constants.CODE_SWITCH_ALPHA_SYMBOL - - private fun getToAlphaCode() = - if (params.mId.mElementId == KeyboardId.ELEMENT_NUMPAD) - Constants.CODE_ALPHA_FROM_NUMPAD - else Constants.CODE_SWITCH_ALPHA_SYMBOL - private fun getShiftLabel(): String { val elementId = params.mId.mElementId if (elementId == KeyboardId.ELEMENT_SYMBOLS_SHIFTED) @@ -820,7 +819,7 @@ abstract class KeyboardParser(private val params: KeyboardParams, private val co } protected enum class FunctionalKey { - EMOJI, LANGUAGE_SWITCH, COM, EMOJI_COM, ACTION, DELETE, PERIOD, COMMA, SPACE, SHIFT, NUMPAD, SYMBOL, ALPHA, ZWNJ + EMOJI, LANGUAGE_SWITCH, COM, EMOJI_COM, ACTION, DELETE, PERIOD, COMMA, SPACE, SHIFT, NUMPAD, SYMBOL, ALPHA, SYMBOL_ALPHA, ZWNJ } } diff --git a/app/src/main/java/helium314/keyboard/latin/common/Constants.java b/app/src/main/java/helium314/keyboard/latin/common/Constants.java index 75b4bb26b..b8a619c56 100644 --- a/app/src/main/java/helium314/keyboard/latin/common/Constants.java +++ b/app/src/main/java/helium314/keyboard/latin/common/Constants.java @@ -196,6 +196,7 @@ public static boolean isValidCoordinate(final int coordinate) { * These should be aligned with constants in * {@link helium314.keyboard.keyboard.internal.KeyboardCodesSet}. */ + // todo: switch to using KeyCode for internal values? for FlorisBoard modifier key(code) compatibility public static final int CODE_SHIFT = -1; public static final int CODE_CAPSLOCK = -2; public static final int CODE_SWITCH_ALPHA_SYMBOL = -3; @@ -210,14 +211,12 @@ public static boolean isValidCoordinate(final int coordinate) { public static final int CODE_CLIPBOARD = -12; public static final int CODE_SHIFT_ENTER = -13; public static final int CODE_SYMBOL_SHIFT = -14; - public static final int CODE_ALPHA_FROM_EMOJI = -15; - public static final int CODE_ALPHA_FROM_CLIPBOARD = -16; public static final int CODE_START_ONE_HANDED_MODE = -17; public static final int CODE_STOP_ONE_HANDED_MODE = -18; public static final int CODE_SWITCH_ONE_HANDED_MODE = -19; - public static final int CODE_NUMPAD = -20; - public static final int CODE_ALPHA_FROM_NUMPAD = -21; - public static final int CODE_SYMBOL_FROM_NUMPAD = -22; + public static final int CODE_SWITCH_NUMPAD = -20; + public static final int CODE_SWITCH_ALPHA = -21; + public static final int CODE_SWITCH_SYMBOL = -22; public static final int CODE_SELECT_ALL = -23; public static final int CODE_COPY = -24; public static final int CODE_LEFT = -25; @@ -243,7 +242,9 @@ public static String printableCode(final int code) { switch (code) { case CODE_SHIFT: return "shift"; case CODE_CAPSLOCK: return "capslock"; - case CODE_SWITCH_ALPHA_SYMBOL: return "symbol"; + case CODE_SWITCH_ALPHA_SYMBOL: return "alpha_symbol"; + case CODE_SWITCH_ALPHA: return "alpha"; + case CODE_SWITCH_SYMBOL: return "symbol"; case CODE_OUTPUT_TEXT: return "text"; case CODE_DELETE: return "delete"; case CODE_SETTINGS: return "settings"; @@ -254,8 +255,6 @@ public static String printableCode(final int code) { case CODE_EMOJI: return "emoji"; case CODE_CLIPBOARD: return "clipboard"; case CODE_SHIFT_ENTER: return "shiftEnter"; - case CODE_ALPHA_FROM_EMOJI: return "alpha"; - case CODE_ALPHA_FROM_CLIPBOARD: return "alpha"; case CODE_UNSPECIFIED: return "unspec"; case CODE_TAB: return "tab"; case CODE_ENTER: return "enter"; @@ -263,9 +262,7 @@ public static String printableCode(final int code) { case CODE_START_ONE_HANDED_MODE: return "startOneHandedMode"; case CODE_STOP_ONE_HANDED_MODE: return "stopOneHandedMode"; case CODE_SWITCH_ONE_HANDED_MODE: return "switchOneHandedMode"; - case CODE_NUMPAD: return "numpad"; - case CODE_ALPHA_FROM_NUMPAD: return "alphaNumpad"; - case CODE_SYMBOL_FROM_NUMPAD: return "symbolNumpad"; + case CODE_SWITCH_NUMPAD: return "numpad"; default: if (code < CODE_SPACE) return String.format("\\u%02X", code); if (code < 0x100) return String.format("%c", code); diff --git a/app/src/main/java/helium314/keyboard/latin/inputlogic/InputLogic.java b/app/src/main/java/helium314/keyboard/latin/inputlogic/InputLogic.java index 1f548cbf7..42c843664 100644 --- a/app/src/main/java/helium314/keyboard/latin/inputlogic/InputLogic.java +++ b/app/src/main/java/helium314/keyboard/latin/inputlogic/InputLogic.java @@ -488,7 +488,9 @@ public InputTransaction onCodeInput(final SettingsValues settingsValues, } if (!inputTransaction.didAutoCorrect() && processedEvent.getMKeyCode() != Constants.CODE_SHIFT && processedEvent.getMKeyCode() != Constants.CODE_CAPSLOCK - && processedEvent.getMKeyCode() != Constants.CODE_SWITCH_ALPHA_SYMBOL) + && processedEvent.getMKeyCode() != Constants.CODE_SWITCH_ALPHA_SYMBOL + && processedEvent.getMKeyCode() != Constants.CODE_SWITCH_ALPHA + && processedEvent.getMKeyCode() != Constants.CODE_SWITCH_SYMBOL) mLastComposedWord.deactivate(); if (Constants.CODE_DELETE != processedEvent.getMKeyCode()) { mEnteredText = null; @@ -744,12 +746,10 @@ private void handleFunctionalEvent(final Event event, final InputTransaction inp case Constants.CODE_CAPSLOCK: case Constants.CODE_SYMBOL_SHIFT: case Constants.CODE_SWITCH_ALPHA_SYMBOL: + case Constants.CODE_SWITCH_ALPHA: + case Constants.CODE_SWITCH_SYMBOL: + case Constants.CODE_SWITCH_NUMPAD: case Constants.CODE_EMOJI: - case Constants.CODE_ALPHA_FROM_EMOJI: - case Constants.CODE_ALPHA_FROM_CLIPBOARD: - case Constants.CODE_NUMPAD: - case Constants.CODE_ALPHA_FROM_NUMPAD: - case Constants.CODE_SYMBOL_FROM_NUMPAD: case Constants.CODE_START_ONE_HANDED_MODE: case Constants.CODE_STOP_ONE_HANDED_MODE: case Constants.CODE_SWITCH_ONE_HANDED_MODE: diff --git a/app/src/main/res/values-sw600dp/functional-keys.xml b/app/src/main/res/values-sw600dp/functional-keys.xml index f44de015f..a5296108a 100644 --- a/app/src/main/res/values-sw600dp/functional-keys.xml +++ b/app/src/main/res/values-sw600dp/functional-keys.xml @@ -4,5 +4,5 @@ ;action 10% shift 10%; shift" ";delete 10%" - "symbol, comma, space, period, emoji_com" + "symbol_alpha, comma, space, period, emoji_com" diff --git a/app/src/main/res/values/functional-keys.xml b/app/src/main/res/values/functional-keys.xml index 285039d6b..6fe085de4 100644 --- a/app/src/main/res/values/functional-keys.xml +++ b/app/src/main/res/values/functional-keys.xml @@ -18,5 +18,5 @@ split into two groups. Space bar will be adjusted in code for language and emoji keys, and other keys in symbol layouts --> - "symbol 15%, comma, space, period, action 15%" + "symbol_alpha 15%, comma, space, period, action 15%" From a34b3f4cdd759353f0f9100171d371930d2ff541 Mon Sep 17 00:00:00 2001 From: Helium314 Date: Sat, 2 Mar 2024 21:02:48 +0100 Subject: [PATCH 23/40] switch internal codes for functional keys to the same as florisboard for better compatibility of layouts also convert labels --- .../accessibility/KeyCodeDescriptionMapper.kt | 27 ++--- .../helium314/keyboard/event/CombinerChain.kt | 3 +- .../keyboard/event/DeadKeyCombiner.kt | 3 +- .../keyboard/event/HangulCombiner.kt | 7 +- .../event/HardwareKeyboardEventDecoder.kt | 5 +- .../java/helium314/keyboard/keyboard/Key.java | 57 +++++----- .../helium314/keyboard/keyboard/Keyboard.java | 3 +- .../keyboard/keyboard/MainKeyboardView.java | 5 +- .../keyboard/keyboard/PointerTracker.java | 20 ++-- .../keyboard/PopupKeysKeyboardView.java | 5 +- .../clipboard/ClipboardHistoryView.kt | 9 +- .../keyboard/emoji/EmojiPalettesView.java | 15 +-- .../keyboard/internal/CodesArrayParser.java | 3 +- .../keyboard/internal/KeySpecParser.java | 14 ++- .../keyboard/internal/KeyboardBuilder.kt | 3 +- .../keyboard/internal/KeyboardCodesSet.java | 43 ++++---- .../keyboard/internal/KeyboardParams.java | 3 +- .../keyboard/internal/KeyboardState.java | 46 ++++---- .../keyboard/internal/PopupKeySpec.java | 11 +- .../keyboard/internal/TimerHandler.java | 3 +- .../internal/keyboard_parser/EmojiParser.kt | 5 +- .../keyboard_parser/JsonKeyboardParser.kt | 3 +- .../keyboard_parser/KeyboardParser.kt | 7 +- .../keyboard_parser/LocaleKeyboardInfos.kt | 4 +- .../keyboard_parser/floris/KeyCode.kt | 88 +++++++++++---- .../keyboard_parser/floris/KeyData.kt | 96 ----------------- .../keyboard_parser/floris/TextKeyData.kt | 102 +++++++++++++++++- .../latin/AudioAndHapticFeedbackManager.java | 3 +- .../keyboard/latin/KeyboardWrapperView.kt | 7 +- .../helium314/keyboard/latin/LatinIME.java | 21 ++-- .../latin/PunctuationSuggestions.java | 3 +- .../keyboard/latin/WordComposer.java | 5 +- .../keyboard/latin/common/Constants.java | 83 ++++---------- .../keyboard/latin/common/StringUtils.java | 3 +- .../keyboard/latin/inputlogic/InputLogic.java | 79 +++++++------- .../latin/suggestions/MoreSuggestions.java | 3 +- .../suggestions/SuggestionStripView.java | 3 +- .../keyboard/latin/utils/ToolbarUtils.kt | 36 +++---- .../helium314/keyboard/KeySpecParserTest.kt | 5 +- .../keyboard/latin/InputLogicTest.kt | 17 +-- 40 files changed, 448 insertions(+), 410 deletions(-) diff --git a/app/src/main/java/helium314/keyboard/accessibility/KeyCodeDescriptionMapper.kt b/app/src/main/java/helium314/keyboard/accessibility/KeyCodeDescriptionMapper.kt index 338c77250..9a5fba56f 100644 --- a/app/src/main/java/helium314/keyboard/accessibility/KeyCodeDescriptionMapper.kt +++ b/app/src/main/java/helium314/keyboard/accessibility/KeyCodeDescriptionMapper.kt @@ -14,6 +14,7 @@ import android.view.inputmethod.EditorInfo import helium314.keyboard.keyboard.Key import helium314.keyboard.keyboard.Keyboard import helium314.keyboard.keyboard.KeyboardId +import helium314.keyboard.keyboard.internal.keyboard_parser.floris.KeyCode import helium314.keyboard.latin.R import helium314.keyboard.latin.common.Constants import helium314.keyboard.latin.common.StringUtils @@ -23,17 +24,17 @@ internal class KeyCodeDescriptionMapper private constructor() { private val mKeyCodeMap = SparseIntArray().apply { // Special non-character codes defined in Keyboard put(Constants.CODE_SPACE, R.string.spoken_description_space) - put(Constants.CODE_DELETE, R.string.spoken_description_delete) + put(KeyCode.DELETE, R.string.spoken_description_delete) put(Constants.CODE_ENTER, R.string.spoken_description_return) - put(Constants.CODE_SETTINGS, R.string.spoken_description_settings) - put(Constants.CODE_SHIFT, R.string.spoken_description_shift) - put(Constants.CODE_SHORTCUT, R.string.spoken_description_mic) - put(Constants.CODE_SWITCH_ALPHA_SYMBOL, R.string.spoken_description_to_symbol) + put(KeyCode.SETTINGS, R.string.spoken_description_settings) + put(KeyCode.SHIFT, R.string.spoken_description_shift) + put(KeyCode.VOICE_INPUT, R.string.spoken_description_mic) + put(KeyCode.ALPHA_SYMBOL, R.string.spoken_description_to_symbol) put(Constants.CODE_TAB, R.string.spoken_description_tab) - put(Constants.CODE_LANGUAGE_SWITCH, R.string.spoken_description_language_switch) - put(Constants.CODE_ACTION_NEXT, R.string.spoken_description_action_next) - put(Constants.CODE_ACTION_PREVIOUS, R.string.spoken_description_action_previous) - put(Constants.CODE_EMOJI, R.string.spoken_description_emoji) + put(KeyCode.LANGUAGE_SWITCH, R.string.spoken_description_language_switch) + put(KeyCode.ACTION_NEXT, R.string.spoken_description_action_next) + put(KeyCode.ACTION_PREVIOUS, R.string.spoken_description_action_previous) + put(KeyCode.EMOJI, R.string.spoken_description_emoji) // Because the upper-case and lower-case mappings of the following letters is depending on // the locale, the upper case descriptions should be defined here. The lower case // descriptions are handled in {@link #getSpokenLetterDescriptionId(Context,int)}. @@ -57,13 +58,13 @@ internal class KeyCodeDescriptionMapper private constructor() { */ fun getDescriptionForKey(context: Context, keyboard: Keyboard?, key: Key, shouldObscure: Boolean): String? { val code = key.code - if (code == Constants.CODE_SWITCH_ALPHA_SYMBOL || code == Constants.CODE_SWITCH_SYMBOL || code == Constants.CODE_SWITCH_ALPHA) { + if (code == KeyCode.ALPHA_SYMBOL || code == KeyCode.SYMBOL || code == KeyCode.ALPHA) { val description = getDescriptionForSwitchAlphaSymbol(context, keyboard) if (description != null) { return description } } - if (code == Constants.CODE_SHIFT) { + if (code == KeyCode.SHIFT) { return getDescriptionForShiftKey(context, keyboard) } if (code == Constants.CODE_ENTER) { @@ -71,11 +72,11 @@ internal class KeyCodeDescriptionMapper private constructor() { // regular enter cases, taking care of all modes. return getDescriptionForActionKey(context, keyboard, key) } - if (code == Constants.CODE_OUTPUT_TEXT) { + if (code == KeyCode.MULTIPLE_CODE_POINTS) { return key.outputText ?: context.getString(R.string.spoken_description_unknown) } // Just attempt to speak the description. - if (code != Constants.CODE_UNSPECIFIED) { + if (code != KeyCode.NOT_SPECIFIED) { // If the key description should be obscured, now is the time to do it. val isDefinedNonCtrl = (Character.isDefined(code) && !Character.isISOControl(code)) diff --git a/app/src/main/java/helium314/keyboard/event/CombinerChain.kt b/app/src/main/java/helium314/keyboard/event/CombinerChain.kt index 7089b86dd..7862f9ee2 100644 --- a/app/src/main/java/helium314/keyboard/event/CombinerChain.kt +++ b/app/src/main/java/helium314/keyboard/event/CombinerChain.kt @@ -8,6 +8,7 @@ package helium314.keyboard.event import android.text.SpannableStringBuilder import android.text.TextUtils +import helium314.keyboard.keyboard.internal.keyboard_parser.floris.KeyCode import helium314.keyboard.latin.common.Constants import java.util.* @@ -104,7 +105,7 @@ class CombinerChain(initialText: String) { */ fun applyProcessedEvent(event: Event?) { if (null != event) { // TODO: figure out the generic way of doing this - if (Constants.CODE_DELETE == event.mKeyCode) { + if (KeyCode.DELETE == event.mKeyCode) { val length = mCombinedText.length if (length > 0) { val lastCodePoint = mCombinedText.codePointBefore(length) diff --git a/app/src/main/java/helium314/keyboard/event/DeadKeyCombiner.kt b/app/src/main/java/helium314/keyboard/event/DeadKeyCombiner.kt index fd149f9a3..2de633668 100644 --- a/app/src/main/java/helium314/keyboard/event/DeadKeyCombiner.kt +++ b/app/src/main/java/helium314/keyboard/event/DeadKeyCombiner.kt @@ -8,6 +8,7 @@ package helium314.keyboard.event import android.text.TextUtils import android.util.SparseIntArray +import helium314.keyboard.keyboard.internal.keyboard_parser.floris.KeyCode import helium314.keyboard.latin.common.Constants import java.text.Normalizer import java.util.* @@ -211,7 +212,7 @@ class DeadKeyCombiner : Combiner { return resultEvent } if (event.isFunctionalKeyEvent) { - if (Constants.CODE_DELETE == event.mKeyCode) { // Remove the last code point + if (KeyCode.DELETE == event.mKeyCode) { // Remove the last code point val trimIndex = mDeadSequence.length - Character.charCount( mDeadSequence.codePointBefore(mDeadSequence.length)) mDeadSequence.setLength(trimIndex) diff --git a/app/src/main/java/helium314/keyboard/event/HangulCombiner.kt b/app/src/main/java/helium314/keyboard/event/HangulCombiner.kt index a73043237..411c46995 100644 --- a/app/src/main/java/helium314/keyboard/event/HangulCombiner.kt +++ b/app/src/main/java/helium314/keyboard/event/HangulCombiner.kt @@ -2,6 +2,7 @@ package helium314.keyboard.event +import helium314.keyboard.keyboard.internal.keyboard_parser.floris.KeyCode import helium314.keyboard.latin.common.Constants import java.lang.StringBuilder import java.util.ArrayList @@ -14,13 +15,13 @@ class HangulCombiner : Combiner { private val syllable: HangulSyllable? get() = history.lastOrNull() override fun processEvent(previousEvents: ArrayList?, event: Event): Event { - if (event.mKeyCode == Constants.CODE_SHIFT) return event + if (event.mKeyCode == KeyCode.SHIFT) return event if (Character.isWhitespace(event.mCodePoint)) { val text = combiningStateFeedback reset() return createEventChainFromSequence(text, event) } else if (event.isFunctionalKeyEvent) { - if(event.mKeyCode == Constants.CODE_DELETE) { + if(event.mKeyCode == KeyCode.DELETE) { return when { history.size == 1 && composingWord.isEmpty() || history.isEmpty() && composingWord.length == 1 -> { reset() @@ -327,7 +328,7 @@ class HangulCombiner : Combiner { 0x11ba to 0x11ba to 0x11bb // ㅆ ) private fun createEventChainFromSequence(text: CharSequence, originalEvent: Event): Event { - return Event.createSoftwareTextEvent(text, Constants.CODE_OUTPUT_TEXT, originalEvent) + return Event.createSoftwareTextEvent(text, KeyCode.MULTIPLE_CODE_POINTS, originalEvent) } } diff --git a/app/src/main/java/helium314/keyboard/event/HardwareKeyboardEventDecoder.kt b/app/src/main/java/helium314/keyboard/event/HardwareKeyboardEventDecoder.kt index 165ed8458..31c64f22a 100644 --- a/app/src/main/java/helium314/keyboard/event/HardwareKeyboardEventDecoder.kt +++ b/app/src/main/java/helium314/keyboard/event/HardwareKeyboardEventDecoder.kt @@ -8,6 +8,7 @@ package helium314.keyboard.event import android.view.KeyCharacterMap import android.view.KeyEvent +import helium314.keyboard.keyboard.internal.keyboard_parser.floris.KeyCode import helium314.keyboard.latin.common.Constants /** @@ -30,7 +31,7 @@ class HardwareKeyboardEventDecoder(val mDeviceId: Int) : HardwareEventDecoder { val keyCode = keyEvent.keyCode val isKeyRepeat = 0 != keyEvent.repeatCount if (KeyEvent.KEYCODE_DEL == keyCode) { - return Event.createHardwareKeypressEvent(Event.NOT_A_CODE_POINT, Constants.CODE_DELETE, null /* next */, isKeyRepeat) + return Event.createHardwareKeypressEvent(Event.NOT_A_CODE_POINT, KeyCode.DELETE, null /* next */, isKeyRepeat) } if (keyEvent.isPrintingKey || KeyEvent.KEYCODE_SPACE == keyCode || KeyEvent.KEYCODE_ENTER == keyCode) { if (0 != codePointAndFlags and KeyCharacterMap.COMBINING_ACCENT) { // A dead key. @@ -44,7 +45,7 @@ class HardwareKeyboardEventDecoder(val mDeviceId: Int) : HardwareEventDecoder { // Latin IME decide what to do with it. if (keyEvent.isShiftPressed) { Event.createHardwareKeypressEvent(Event.NOT_A_CODE_POINT, - Constants.CODE_SHIFT_ENTER, null /* next */, isKeyRepeat) + KeyCode.SHIFT_ENTER, null /* next */, isKeyRepeat) } else Event.createHardwareKeypressEvent(Constants.CODE_ENTER, keyCode, null /* next */, isKeyRepeat) } else Event.createHardwareKeypressEvent(codePointAndFlags, keyCode, null /* next */, isKeyRepeat) diff --git a/app/src/main/java/helium314/keyboard/keyboard/Key.java b/app/src/main/java/helium314/keyboard/keyboard/Key.java index fd8cffdff..f71ca481d 100644 --- a/app/src/main/java/helium314/keyboard/keyboard/Key.java +++ b/app/src/main/java/helium314/keyboard/keyboard/Key.java @@ -17,6 +17,7 @@ import helium314.keyboard.keyboard.internal.KeyboardIconsSet; import helium314.keyboard.keyboard.internal.KeyboardParams; import helium314.keyboard.keyboard.internal.PopupKeySpec; +import helium314.keyboard.keyboard.internal.keyboard_parser.floris.KeyCode; import helium314.keyboard.keyboard.internal.keyboard_parser.floris.PopupSet; import helium314.keyboard.latin.common.Constants; import helium314.keyboard.latin.common.StringUtils; @@ -26,12 +27,6 @@ import java.util.Locale; import static helium314.keyboard.keyboard.internal.KeyboardIconsSet.ICON_UNDEFINED; -import static helium314.keyboard.latin.common.Constants.CODE_OUTPUT_TEXT; -import static helium314.keyboard.latin.common.Constants.CODE_SHIFT; -import static helium314.keyboard.latin.common.Constants.CODE_SWITCH_ALPHA; -import static helium314.keyboard.latin.common.Constants.CODE_SWITCH_ALPHA_SYMBOL; -import static helium314.keyboard.latin.common.Constants.CODE_SWITCH_SYMBOL; -import static helium314.keyboard.latin.common.Constants.CODE_UNSPECIFIED; import androidx.annotation.NonNull; import androidx.annotation.Nullable; @@ -178,7 +173,7 @@ private OptionalAttributes(final String outputText, final int altCode, @Nullable public static OptionalAttributes newInstance(final String outputText, final int altCode, final int disabledIconId, final int visualInsetsLeft, final int visualInsetsRight) { - if (outputText == null && altCode == CODE_UNSPECIFIED + if (outputText == null && altCode == KeyCode.NOT_SPECIFIED && disabledIconId == ICON_UNDEFINED && visualInsetsLeft == 0 && visualInsetsRight == 0) { return null; @@ -214,10 +209,10 @@ public Key(@Nullable final String label, final int iconId, final int code, mPopupKeys = null; mPopupKeysColumnAndFlags = 0; mLabel = label; - mOptionalAttributes = OptionalAttributes.newInstance(outputText, CODE_UNSPECIFIED, + mOptionalAttributes = OptionalAttributes.newInstance(outputText, KeyCode.NOT_SPECIFIED, ICON_UNDEFINED, 0 /* visualInsetsLeft */, 0 /* visualInsetsRight */); mCode = code; - mEnabled = (code != CODE_UNSPECIFIED); + mEnabled = (code != KeyCode.NOT_SPECIFIED); mIconId = iconId; // Horizontal gap is divided equally to both sides of the key. mX = x + mHorizontalGap / 2; @@ -267,7 +262,7 @@ protected Key(@NonNull final Key key, @Nullable final PopupKeySpec[] popupKeys, public Key(@NonNull final Key key, @Nullable final PopupKeySpec[] popupKeys, @Nullable final String labelHint, final int backgroundType, final int code, @Nullable final String outputText) { // Final attributes. - mCode = outputText == null ? code : CODE_OUTPUT_TEXT; + mCode = outputText == null ? code : KeyCode.MULTIPLE_CODE_POINTS; mLabel = outputText == null ? StringUtils.newSingleCodePointString(code) : outputText; mHintLabel = labelHint; mLabelFlags = key.mLabelFlags; @@ -284,7 +279,7 @@ public Key(@NonNull final Key key, @Nullable final PopupKeySpec[] popupKeys, mBackgroundType = backgroundType; mActionFlags = key.mActionFlags; mKeyVisualAttributes = key.mKeyVisualAttributes; - mOptionalAttributes = outputText == null ? null : Key.OptionalAttributes.newInstance(outputText, CODE_UNSPECIFIED, ICON_UNDEFINED, 0, 0); + mOptionalAttributes = outputText == null ? null : Key.OptionalAttributes.newInstance(outputText, KeyCode.NOT_SPECIFIED, ICON_UNDEFINED, 0, 0); mHashCode = key.mHashCode; // Key state. mPressed = key.mPressed; @@ -442,7 +437,7 @@ public String toString() { public String toShortString() { final int code = getCode(); - if (code == Constants.CODE_OUTPUT_TEXT) { + if (code == KeyCode.MULTIPLE_CODE_POINTS) { return getOutputText(); } return Constants.printableCode(code); @@ -514,11 +509,11 @@ public final boolean isActionKey() { } public final boolean isShift() { - return mCode == CODE_SHIFT; + return mCode == KeyCode.SHIFT; } public final boolean isModifier() { - return mCode == CODE_SHIFT || mCode == CODE_SWITCH_ALPHA_SYMBOL || mCode == CODE_SWITCH_ALPHA || mCode == CODE_SWITCH_SYMBOL; + return mCode == KeyCode.SHIFT || mCode == KeyCode.ALPHA_SYMBOL || mCode == KeyCode.ALPHA || mCode == KeyCode.SYMBOL; } public final boolean isRepeatable() { @@ -704,7 +699,7 @@ public final String getOutputText() { public final int getAltCode() { final OptionalAttributes attrs = mOptionalAttributes; - return (attrs != null) ? attrs.mAltCode : CODE_UNSPECIFIED; + return (attrs != null) ? attrs.mAltCode : KeyCode.NOT_SPECIFIED; } public int getIconId() { @@ -948,7 +943,7 @@ private Spacer(KeyParams keyParams) { */ protected Spacer(final KeyboardParams params, final int x, final int y, final int width, final int height) { - super(null /* label */, ICON_UNDEFINED, CODE_UNSPECIFIED, null /* outputText */, + super(null /* label */, ICON_UNDEFINED, KeyCode.NOT_SPECIFIED, null /* outputText */, null /* hintLabel */, 0 /* labelFlags */, BACKGROUND_TYPE_EMPTY, x, y, width, height, params.mHorizontalGap, params.mVerticalGap); } @@ -1116,7 +1111,7 @@ public KeyParams( outputText = StringUtils.toTitleCaseOfKeyLabel(outputText, localeForUpcasing); } // Choose the first letter of the label as primary code if not specified. - if (code == CODE_UNSPECIFIED && TextUtils.isEmpty(outputText) && !TextUtils.isEmpty(mLabel)) { + if (code == KeyCode.NOT_SPECIFIED && TextUtils.isEmpty(outputText) && !TextUtils.isEmpty(mLabel)) { if (StringUtils.codePointCount(mLabel) == 1) { // Use the first letter of the hint label if shiftedLetterActivated flag is // specified. @@ -1130,14 +1125,14 @@ public KeyParams( // In some locale and case, the character might be represented by multiple code // points, such as upper case Eszett of German alphabet. outputText = mLabel; - mCode = CODE_OUTPUT_TEXT; + mCode = KeyCode.MULTIPLE_CODE_POINTS; } - } else if (code == CODE_UNSPECIFIED && outputText != null) { + } else if (code == KeyCode.NOT_SPECIFIED && outputText != null) { if (StringUtils.codePointCount(outputText) == 1) { mCode = outputText.codePointAt(0); outputText = null; } else { - mCode = CODE_OUTPUT_TEXT; + mCode = KeyCode.MULTIPLE_CODE_POINTS; } } else { mCode = needsToUpcase ? StringUtils.toTitleCaseOfKeyCode(code, localeForUpcasing) : code; @@ -1145,23 +1140,23 @@ public KeyParams( // action flags don't need to be specified, they can be deduced from the key if (backgroundType == BACKGROUND_TYPE_SPACEBAR - || mCode == Constants.CODE_LANGUAGE_SWITCH - || (mCode == CODE_SWITCH_ALPHA_SYMBOL && !params.mId.isAlphabetKeyboard()) + || mCode == KeyCode.LANGUAGE_SWITCH + || (mCode == KeyCode.ALPHA_SYMBOL && !params.mId.isAlphabetKeyboard()) ) actionFlags |= ACTION_FLAGS_ENABLE_LONG_PRESS; - if (mCode <= Constants.CODE_SPACE && mCode != CODE_OUTPUT_TEXT) + if (mCode <= Constants.CODE_SPACE && mCode != KeyCode.MULTIPLE_CODE_POINTS) actionFlags |= ACTION_FLAGS_NO_KEY_PREVIEW; - if (mCode == Constants.CODE_DELETE) + if (mCode == KeyCode.DELETE) actionFlags |= ACTION_FLAGS_IS_REPEATABLE; - if (mCode == Constants.CODE_SETTINGS || mCode == Constants.CODE_LANGUAGE_SWITCH) + if (mCode == KeyCode.SETTINGS || mCode == KeyCode.LANGUAGE_SWITCH) actionFlags |= ACTION_FLAGS_ALT_CODE_WHILE_TYPING; mActionFlags = actionFlags; final int altCodeInAttr; // settings and language switch keys have alt code space, all others nothing - if (mCode == Constants.CODE_SETTINGS || mCode == Constants.CODE_LANGUAGE_SWITCH) + if (mCode == KeyCode.SETTINGS || mCode == KeyCode.LANGUAGE_SWITCH) altCodeInAttr = Constants.CODE_SPACE; else - altCodeInAttr = CODE_UNSPECIFIED; + altCodeInAttr = KeyCode.NOT_SPECIFIED; final int altCode = needsToUpcase ? StringUtils.toTitleCaseOfKeyCode(altCodeInAttr, localeForUpcasing) : altCodeInAttr; @@ -1206,11 +1201,11 @@ public KeyParams(@Nullable final String label, final int code, @Nullable final S } mLabel = label; - mOptionalAttributes = code == Constants.CODE_OUTPUT_TEXT - ? OptionalAttributes.newInstance(label, CODE_UNSPECIFIED, ICON_UNDEFINED, 0, 0) + mOptionalAttributes = code == KeyCode.MULTIPLE_CODE_POINTS + ? OptionalAttributes.newInstance(label, KeyCode.NOT_SPECIFIED, ICON_UNDEFINED, 0, 0) : null; mCode = code; - mEnabled = (code != CODE_UNSPECIFIED); + mEnabled = (code != KeyCode.NOT_SPECIFIED); mIconId = KeyboardIconsSet.ICON_UNDEFINED; mKeyVisualAttributes = null; } @@ -1220,7 +1215,7 @@ private KeyParams(final KeyboardParams params) { isSpacer = true; // this is only for spacer! mKeyboardParams = params; - mCode = CODE_UNSPECIFIED; + mCode = KeyCode.NOT_SPECIFIED; mLabel = null; mHintLabel = null; mKeyVisualAttributes = null; diff --git a/app/src/main/java/helium314/keyboard/keyboard/Keyboard.java b/app/src/main/java/helium314/keyboard/keyboard/Keyboard.java index 15e11ad5a..802370cf0 100644 --- a/app/src/main/java/helium314/keyboard/keyboard/Keyboard.java +++ b/app/src/main/java/helium314/keyboard/keyboard/Keyboard.java @@ -16,6 +16,7 @@ import helium314.keyboard.keyboard.internal.KeyVisualAttributes; import helium314.keyboard.keyboard.internal.KeyboardIconsSet; import helium314.keyboard.keyboard.internal.KeyboardParams; +import helium314.keyboard.keyboard.internal.keyboard_parser.floris.KeyCode; import helium314.keyboard.latin.common.Constants; import helium314.keyboard.latin.common.CoordinateUtils; @@ -180,7 +181,7 @@ public List getSortedKeys() { @Nullable public Key getKey(final int code) { - if (code == Constants.CODE_UNSPECIFIED) { + if (code == KeyCode.NOT_SPECIFIED) { return null; } synchronized (mKeyCache) { diff --git a/app/src/main/java/helium314/keyboard/keyboard/MainKeyboardView.java b/app/src/main/java/helium314/keyboard/keyboard/MainKeyboardView.java index 6dfb4fedd..59926cccf 100644 --- a/app/src/main/java/helium314/keyboard/keyboard/MainKeyboardView.java +++ b/app/src/main/java/helium314/keyboard/keyboard/MainKeyboardView.java @@ -42,6 +42,7 @@ import helium314.keyboard.keyboard.internal.NonDistinctMultitouchHelper; import helium314.keyboard.keyboard.internal.SlidingKeyInputDrawingPreview; import helium314.keyboard.keyboard.internal.TimerHandler; +import helium314.keyboard.keyboard.internal.keyboard_parser.floris.KeyCode; import helium314.keyboard.latin.R; import helium314.keyboard.latin.RichInputMethodSubtype; import helium314.keyboard.latin.SuggestedWords; @@ -688,7 +689,7 @@ public void updateShortcutKey(final boolean available) { if (keyboard == null) { return; } - final Key shortcutKey = keyboard.getKey(Constants.CODE_SHORTCUT); + final Key shortcutKey = keyboard.getKey(KeyCode.VOICE_INPUT); if (shortcutKey == null) { return; } @@ -741,7 +742,7 @@ protected void onDrawKeyTopVisuals(@NonNull final Key key, @NonNull final Canvas if (key.isLongPressEnabled() && mHasMultipleEnabledIMEsOrSubtypes) { drawKeyPopupHint(key, canvas, paint, params); } - } else if (code == Constants.CODE_LANGUAGE_SWITCH) { + } else if (code == KeyCode.LANGUAGE_SWITCH) { drawKeyPopupHint(key, canvas, paint, params); } } diff --git a/app/src/main/java/helium314/keyboard/keyboard/PointerTracker.java b/app/src/main/java/helium314/keyboard/keyboard/PointerTracker.java index a9a86ed7f..4857adcdd 100644 --- a/app/src/main/java/helium314/keyboard/keyboard/PointerTracker.java +++ b/app/src/main/java/helium314/keyboard/keyboard/PointerTracker.java @@ -11,6 +11,8 @@ import android.content.res.Resources; import android.content.res.TypedArray; import android.os.SystemClock; + +import helium314.keyboard.keyboard.internal.keyboard_parser.floris.KeyCode; import helium314.keyboard.latin.utils.Log; import android.view.MotionEvent; import android.view.inputmethod.InputMethodSubtype; @@ -284,7 +286,7 @@ private void callListenerOnCodeInput(final Key key, final int primaryCode, final final boolean altersCode = key.altCodeWhileTyping() && sTimerProxy.isTypingState(); final int code = altersCode ? key.getAltCode() : primaryCode; if (DEBUG_LISTENER) { - final String output = code == Constants.CODE_OUTPUT_TEXT + final String output = code == KeyCode.MULTIPLE_CODE_POINTS ? key.getOutputText() : Constants.printableCode(code); Log.d(TAG, String.format(Locale.US, "[%d] onCodeInput: %4d %4d %s%s%s%s", mPointerId, x, y, output, ignoreModifierKey ? " ignoreModifier" : "", @@ -296,9 +298,9 @@ private void callListenerOnCodeInput(final Key key, final int primaryCode, final // Even if the key is disabled, it should respond if it is in the altCodeWhileTyping state. if (key.isEnabled() || altersCode) { sTypingTimeRecorder.onCodeInput(code, eventTime); - if (code == Constants.CODE_OUTPUT_TEXT) { + if (code == KeyCode.MULTIPLE_CODE_POINTS) { sListener.onTextInput(key.getOutputText()); - } else if (code != Constants.CODE_UNSPECIFIED) { + } else if (code != KeyCode.NOT_SPECIFIED) { if (mKeyboard.hasProximityCharsCorrection(code)) { sListener.onCodeInput(code, x, y, isKeyRepeat); } else { @@ -935,7 +937,7 @@ private void onMoveEventInternal(final int x, final int y, final long eventTime) return; } - if (oldKey != null && oldKey.getCode() == Constants.CODE_DELETE && sv.mDeleteSwipeEnabled) { + if (oldKey != null && oldKey.getCode() == KeyCode.DELETE && sv.mDeleteSwipeEnabled) { // Delete slider int steps = (x - mStartX) / sPointerStep; if (abs(steps) > 2 || (mCursorMoved && steps != 0)) { @@ -1023,7 +1025,7 @@ private void onUpEventInternal(final int x, final int y, final long eventTime) { // Release the last pressed key. setReleasedKeyGraphics(currentKey, true); - if(mCursorMoved && currentKey.getCode() == Constants.CODE_DELETE) { + if(mCursorMoved && currentKey.getCode() == KeyCode.DELETE) { sListener.onUpWithDeletePointerActive(); } @@ -1103,7 +1105,7 @@ public void onLongPressed() { return; } final int code = key.getCode(); - if (code == Constants.CODE_LANGUAGE_SWITCH + if (code == KeyCode.LANGUAGE_SWITCH || (code == Constants.CODE_SPACE && Settings.getInstance().getCurrent().mSpaceForLangChange) ) { // Long pressing the space key invokes IME switcher dialog. @@ -1113,8 +1115,8 @@ public void onLongPressed() { return; } } - if (code == Constants.CODE_SWITCH_ALPHA_SYMBOL) { - sListener.onCodeInput(Constants.CODE_SWITCH_NUMPAD, Constants.NOT_A_COORDINATE, Constants.NOT_A_COORDINATE, false); + if (code == KeyCode.ALPHA_SYMBOL) { + sListener.onCodeInput(KeyCode.NUMPAD, Constants.NOT_A_COORDINATE, Constants.NOT_A_COORDINATE, false); return; } @@ -1207,7 +1209,7 @@ private void startLongPressTimer(final Key key) { } private int getLongPressTimeout(final int code) { - if (code == Constants.CODE_SHIFT) { + if (code == KeyCode.SHIFT) { return sParams.mLongPressShiftLockTimeout; } final int longpressTimeout = Settings.getInstance().getCurrent().mKeyLongpressTimeout; diff --git a/app/src/main/java/helium314/keyboard/keyboard/PopupKeysKeyboardView.java b/app/src/main/java/helium314/keyboard/keyboard/PopupKeysKeyboardView.java index 8da446e53..ad642ff48 100644 --- a/app/src/main/java/helium314/keyboard/keyboard/PopupKeysKeyboardView.java +++ b/app/src/main/java/helium314/keyboard/keyboard/PopupKeysKeyboardView.java @@ -22,6 +22,7 @@ import helium314.keyboard.accessibility.PopupKeysKeyboardAccessibilityDelegate; import helium314.keyboard.keyboard.emoji.OnKeyEventListener; import helium314.keyboard.keyboard.internal.KeyDrawParams; +import helium314.keyboard.keyboard.internal.keyboard_parser.floris.KeyCode; import helium314.keyboard.latin.R; import helium314.keyboard.latin.common.Constants; import helium314.keyboard.latin.common.CoordinateUtils; @@ -205,9 +206,9 @@ public void onUpEvent(final int x, final int y, final int pointerId, final long protected void onKeyInput(final Key key, final int x, final int y) { if (mListener != null) { final int code = key.getCode(); - if (code == Constants.CODE_OUTPUT_TEXT) { + if (code == KeyCode.MULTIPLE_CODE_POINTS) { mListener.onTextInput(mCurrentKey.getOutputText()); - } else if (code != Constants.CODE_UNSPECIFIED) { + } else if (code != KeyCode.NOT_SPECIFIED) { if (getKeyboard().hasProximityCharsCorrection(code)) { mListener.onCodeInput(code, x, y, false /* isKeyRepeat */); } else { diff --git a/app/src/main/java/helium314/keyboard/keyboard/clipboard/ClipboardHistoryView.kt b/app/src/main/java/helium314/keyboard/keyboard/clipboard/ClipboardHistoryView.kt index a225f280f..b958d7ae6 100644 --- a/app/src/main/java/helium314/keyboard/keyboard/clipboard/ClipboardHistoryView.kt +++ b/app/src/main/java/helium314/keyboard/keyboard/clipboard/ClipboardHistoryView.kt @@ -18,6 +18,7 @@ import helium314.keyboard.keyboard.KeyboardSwitcher import helium314.keyboard.keyboard.internal.KeyDrawParams import helium314.keyboard.keyboard.internal.KeyVisualAttributes import helium314.keyboard.keyboard.internal.KeyboardIconsSet +import helium314.keyboard.keyboard.internal.keyboard_parser.floris.KeyCode import helium314.keyboard.latin.ClipboardHistoryManager import helium314.keyboard.latin.R import helium314.keyboard.latin.common.ColorType @@ -102,12 +103,12 @@ class ClipboardHistoryView @JvmOverloads constructor( } alphabetKey = findViewById(R.id.key_alphabet) alphabetKey.setBackgroundResource(functionalKeyBackgroundId) - alphabetKey.tag = Constants.CODE_SWITCH_ALPHA + alphabetKey.tag = KeyCode.ALPHA alphabetKey.setOnTouchListener(this) alphabetKey.setOnClickListener(this) deleteKey = findViewById(R.id.key_delete) deleteKey.setBackgroundResource(functionalKeyBackgroundId) - deleteKey.tag = Constants.CODE_DELETE + deleteKey.tag = KeyCode.DELETE deleteKey.setOnTouchListener(this) deleteKey.setOnClickListener(this) spacebar = findViewById(R.id.key_space) @@ -240,13 +241,13 @@ class ClipboardHistoryView @JvmOverloads constructor( } override fun onKeyDown(clipId: Long) { - keyboardActionListener?.onPressKey(Constants.CODE_UNSPECIFIED, 0, true) + keyboardActionListener?.onPressKey(KeyCode.NOT_SPECIFIED, 0, true) } override fun onKeyUp(clipId: Long) { val clipContent = clipboardHistoryManager?.getHistoryEntryContent(clipId) keyboardActionListener?.onTextInput(clipContent?.content.toString()) - keyboardActionListener?.onReleaseKey(Constants.CODE_UNSPECIFIED, false) + keyboardActionListener?.onReleaseKey(KeyCode.NOT_SPECIFIED, false) } override fun onClipboardHistoryEntryAdded(at: Int) { diff --git a/app/src/main/java/helium314/keyboard/keyboard/emoji/EmojiPalettesView.java b/app/src/main/java/helium314/keyboard/keyboard/emoji/EmojiPalettesView.java index 6435b25b9..b93137599 100644 --- a/app/src/main/java/helium314/keyboard/keyboard/emoji/EmojiPalettesView.java +++ b/app/src/main/java/helium314/keyboard/keyboard/emoji/EmojiPalettesView.java @@ -32,6 +32,7 @@ import helium314.keyboard.keyboard.internal.KeyDrawParams; import helium314.keyboard.keyboard.internal.KeyVisualAttributes; import helium314.keyboard.keyboard.internal.KeyboardIconsSet; +import helium314.keyboard.keyboard.internal.keyboard_parser.floris.KeyCode; import helium314.keyboard.latin.AudioAndHapticFeedbackManager; import helium314.keyboard.latin.R; import helium314.keyboard.latin.RichInputMethodSubtype; @@ -225,7 +226,7 @@ public void onScrolled(@NonNull @NotNull RecyclerView recyclerView, int dx, int mDeleteKey = findViewById(R.id.key_delete); mDeleteKey.setBackgroundResource(mFunctionalKeyBackgroundId); mColors.setColor(mDeleteKey, ColorType.KEY_ICON); - mDeleteKey.setTag(Constants.CODE_DELETE); + mDeleteKey.setTag(KeyCode.DELETE); mDeleteKey.setOnTouchListener(mDeleteKeyOnTouchListener); // {@link #mAlphabetKeyLeft} and spaceKey depend on @@ -237,7 +238,7 @@ public void onScrolled(@NonNull @NotNull RecyclerView recyclerView, int dx, int // {@link #startEmojiPalettes(String,int,float,Typeface)}. mAlphabetKeyLeft = findViewById(R.id.key_alphabet); mAlphabetKeyLeft.setBackgroundResource(mFunctionalKeyBackgroundId); - mAlphabetKeyLeft.setTag(Constants.CODE_SWITCH_ALPHA); + mAlphabetKeyLeft.setTag(KeyCode.ALPHA); mAlphabetKeyLeft.setOnTouchListener(this); mAlphabetKeyLeft.setOnClickListener(this); mSpacebar = findViewById(R.id.key_space); @@ -297,7 +298,7 @@ public boolean onTouch(final View v, final MotionEvent event) { public void onClick(View v) { final Object tag = v.getTag(); if (tag instanceof Long) { - AudioAndHapticFeedbackManager.getInstance().performHapticAndAudioFeedback(Constants.CODE_UNSPECIFIED, this); + AudioAndHapticFeedbackManager.getInstance().performHapticAndAudioFeedback(KeyCode.NOT_SPECIFIED, this); final int categoryId = ((Long) tag).intValue(); if (categoryId != mEmojiCategory.getCurrentCategoryId()) { setCurrentCategoryAndPageId(categoryId, 0, false); @@ -333,7 +334,7 @@ public void onPressKey(final Key key) { public void onReleaseKey(final Key key) { mEmojiPalettesAdapter.addRecentKey(key); final int code = key.getCode(); - if (code == Constants.CODE_OUTPUT_TEXT) { + if (code == KeyCode.MULTIPLE_CODE_POINTS) { mKeyboardActionListener.onTextInput(key.getOutputText()); } else { mKeyboardActionListener.onCodeInput(code, NOT_A_COORDINATE, NOT_A_COORDINATE, false); @@ -453,13 +454,13 @@ public boolean onTouch(final View v, final MotionEvent event) { } private void onTouchDown(final View v) { - mKeyboardActionListener.onPressKey(Constants.CODE_DELETE, 0, true); + mKeyboardActionListener.onPressKey(KeyCode.DELETE, 0, true); v.setPressed(true /* pressed */); } private void onTouchUp(final View v) { - mKeyboardActionListener.onCodeInput(Constants.CODE_DELETE, NOT_A_COORDINATE, NOT_A_COORDINATE, false); - mKeyboardActionListener.onReleaseKey(Constants.CODE_DELETE, false); + mKeyboardActionListener.onCodeInput(KeyCode.DELETE, NOT_A_COORDINATE, NOT_A_COORDINATE, false); + mKeyboardActionListener.onReleaseKey(KeyCode.DELETE, false); v.setPressed(false /* pressed */); } diff --git a/app/src/main/java/helium314/keyboard/keyboard/internal/CodesArrayParser.java b/app/src/main/java/helium314/keyboard/keyboard/internal/CodesArrayParser.java index 7d8475b19..7cd1a6873 100644 --- a/app/src/main/java/helium314/keyboard/keyboard/internal/CodesArrayParser.java +++ b/app/src/main/java/helium314/keyboard/keyboard/internal/CodesArrayParser.java @@ -8,6 +8,7 @@ import android.text.TextUtils; +import helium314.keyboard.keyboard.internal.keyboard_parser.floris.KeyCode; import helium314.keyboard.latin.common.Constants; import helium314.keyboard.latin.common.StringUtils; @@ -79,7 +80,7 @@ public static int parseCode(final String codesArraySpec) { if (codeSpec.indexOf(COMMA) < 0) { return Integer.parseInt(codeSpec, BASE_HEX); } - return Constants.CODE_OUTPUT_TEXT; + return KeyCode.MULTIPLE_CODE_POINTS; } public static String parseOutputText(final String codesArraySpec) { diff --git a/app/src/main/java/helium314/keyboard/keyboard/internal/KeySpecParser.java b/app/src/main/java/helium314/keyboard/keyboard/internal/KeySpecParser.java index 062be8c1d..9eb0b82e4 100644 --- a/app/src/main/java/helium314/keyboard/keyboard/internal/KeySpecParser.java +++ b/app/src/main/java/helium314/keyboard/keyboard/internal/KeySpecParser.java @@ -6,13 +6,11 @@ package helium314.keyboard.keyboard.internal; +import helium314.keyboard.keyboard.internal.keyboard_parser.floris.KeyCode; import helium314.keyboard.latin.common.Constants; import helium314.keyboard.latin.common.StringUtils; import helium314.keyboard.latin.define.DebugFlags; -import static helium314.keyboard.latin.common.Constants.CODE_OUTPUT_TEXT; -import static helium314.keyboard.latin.common.Constants.CODE_UNSPECIFIED; - import androidx.annotation.NonNull; import androidx.annotation.Nullable; @@ -184,12 +182,12 @@ public static String getOutputText(@Nullable final String keySpec) { public static int getCode(@Nullable final String keySpec) { if (keySpec == null) { // TODO: Throw {@link KeySpecParserError} once Key.keyLabel attribute becomes mandatory. - return CODE_UNSPECIFIED; + return KeyCode.NOT_SPECIFIED; } final int labelEnd = indexOfLabelEnd(keySpec); if (hasCode(keySpec, labelEnd)) { checkDoubleLabelEnd(keySpec, labelEnd); - return parseCode(getAfterLabelEnd(keySpec, labelEnd), CODE_UNSPECIFIED); + return parseCode(getAfterLabelEnd(keySpec, labelEnd), KeyCode.NOT_SPECIFIED); } final String outputText = getOutputTextInternal(keySpec, labelEnd); if (outputText != null) { @@ -198,16 +196,16 @@ public static int getCode(@Nullable final String keySpec) { if (StringUtils.codePointCount(outputText) == 1) { return outputText.codePointAt(0); } - return CODE_OUTPUT_TEXT; + return KeyCode.MULTIPLE_CODE_POINTS; } final String label = getLabel(keySpec); if (label == null) { if (DebugFlags.DEBUG_ENABLED) throw new KeySpecParserError("Empty label: " + keySpec); - else return CODE_OUTPUT_TEXT; + else return KeyCode.MULTIPLE_CODE_POINTS; } // Code is automatically generated for one letter label. - return (StringUtils.codePointCount(label) == 1) ? label.codePointAt(0) : CODE_OUTPUT_TEXT; + return (StringUtils.codePointCount(label) == 1) ? label.codePointAt(0) : KeyCode.MULTIPLE_CODE_POINTS; } public static int parseCode(@Nullable final String text, final int defaultCode) { diff --git a/app/src/main/java/helium314/keyboard/keyboard/internal/KeyboardBuilder.kt b/app/src/main/java/helium314/keyboard/keyboard/internal/KeyboardBuilder.kt index 5caebb7f9..448e2f204 100644 --- a/app/src/main/java/helium314/keyboard/keyboard/internal/KeyboardBuilder.kt +++ b/app/src/main/java/helium314/keyboard/keyboard/internal/KeyboardBuilder.kt @@ -16,6 +16,7 @@ import helium314.keyboard.keyboard.KeyboardId import helium314.keyboard.keyboard.internal.keyboard_parser.EmojiParser import helium314.keyboard.keyboard.internal.keyboard_parser.KeyboardParser import helium314.keyboard.keyboard.internal.keyboard_parser.addLocaleKeyTextsToParams +import helium314.keyboard.keyboard.internal.keyboard_parser.floris.KeyCode import helium314.keyboard.latin.R import helium314.keyboard.latin.common.Constants import helium314.keyboard.latin.define.DebugFlags @@ -210,7 +211,7 @@ open class KeyboardBuilder(protected val mContext: Context, // todo: this assumes fixed layout for symbols keys, which will change soon! private fun reduceSymbolAndActionKeyWidth(row: ArrayList) { val spaceKey = row.first { it.mCode == Constants.CODE_SPACE } - val symbolKey = row.firstOrNull { it.mCode == Constants.CODE_SWITCH_ALPHA_SYMBOL } + val symbolKey = row.firstOrNull { it.mCode == KeyCode.ALPHA_SYMBOL } val symbolKeyWidth = symbolKey?.mRelativeWidth ?: 0f if (symbolKeyWidth > mParams.mDefaultRelativeKeyWidth) { val widthToChange = symbolKey!!.mRelativeWidth - mParams.mDefaultRelativeKeyWidth diff --git a/app/src/main/java/helium314/keyboard/keyboard/internal/KeyboardCodesSet.java b/app/src/main/java/helium314/keyboard/keyboard/internal/KeyboardCodesSet.java index e10f48f5d..5a0809e3b 100644 --- a/app/src/main/java/helium314/keyboard/keyboard/internal/KeyboardCodesSet.java +++ b/app/src/main/java/helium314/keyboard/keyboard/internal/KeyboardCodesSet.java @@ -6,6 +6,7 @@ package helium314.keyboard.keyboard.internal; +import helium314.keyboard.keyboard.internal.keyboard_parser.floris.KeyCode; import helium314.keyboard.latin.common.Constants; import java.util.HashMap; @@ -37,7 +38,7 @@ public static int getCode(final String name) { "key_output_text", "key_delete", "key_settings", - "key_shortcut", + "key_voice_input", "key_action_next", "key_action_previous", "key_shift_enter", @@ -55,26 +56,26 @@ public static int getCode(final String name) { Constants.CODE_TAB, Constants.CODE_ENTER, Constants.CODE_SPACE, - Constants.CODE_SHIFT, - Constants.CODE_CAPSLOCK, - Constants.CODE_SWITCH_ALPHA_SYMBOL, - Constants.CODE_SWITCH_ALPHA, - Constants.CODE_SWITCH_SYMBOL, - Constants.CODE_OUTPUT_TEXT, - Constants.CODE_DELETE, - Constants.CODE_SETTINGS, - Constants.CODE_SHORTCUT, - Constants.CODE_ACTION_NEXT, - Constants.CODE_ACTION_PREVIOUS, - Constants.CODE_SHIFT_ENTER, - Constants.CODE_LANGUAGE_SWITCH, - Constants.CODE_EMOJI, - Constants.CODE_UNSPECIFIED, - Constants.CODE_CLIPBOARD, - Constants.CODE_SWITCH_NUMPAD, - Constants.CODE_START_ONE_HANDED_MODE, - Constants.CODE_STOP_ONE_HANDED_MODE, - Constants.CODE_SWITCH_ONE_HANDED_MODE + KeyCode.SHIFT, + KeyCode.CAPS_LOCK, + KeyCode.ALPHA_SYMBOL, + KeyCode.ALPHA, + KeyCode.SYMBOL, + KeyCode.MULTIPLE_CODE_POINTS, + KeyCode.DELETE, + KeyCode.SETTINGS, + KeyCode.VOICE_INPUT, + KeyCode.ACTION_NEXT, + KeyCode.ACTION_PREVIOUS, + KeyCode.SHIFT_ENTER, + KeyCode.LANGUAGE_SWITCH, + KeyCode.EMOJI, + KeyCode.NOT_SPECIFIED, + KeyCode.CLIPBOARD, + KeyCode.NUMPAD, + KeyCode.START_ONE_HANDED_MODE, + KeyCode.STOP_ONE_HANDED_MODE, + KeyCode.SWITCH_ONE_HANDED_MODE }; static { diff --git a/app/src/main/java/helium314/keyboard/keyboard/internal/KeyboardParams.java b/app/src/main/java/helium314/keyboard/keyboard/internal/KeyboardParams.java index 3d5480dad..11739ed92 100644 --- a/app/src/main/java/helium314/keyboard/keyboard/internal/KeyboardParams.java +++ b/app/src/main/java/helium314/keyboard/keyboard/internal/KeyboardParams.java @@ -17,6 +17,7 @@ import helium314.keyboard.keyboard.Key; import helium314.keyboard.keyboard.KeyboardId; import helium314.keyboard.keyboard.internal.keyboard_parser.LocaleKeyboardInfos; +import helium314.keyboard.keyboard.internal.keyboard_parser.floris.KeyCode; import helium314.keyboard.latin.R; import helium314.keyboard.latin.common.Constants; import helium314.keyboard.latin.settings.Settings; @@ -134,7 +135,7 @@ public void onAddKey(@NonNull final Key newKey) { return; } updateHistogram(key); - if (key.getCode() == Constants.CODE_SHIFT) { + if (key.getCode() == KeyCode.SHIFT) { mShiftKeys.add(key); } if (key.altCodeWhileTyping()) { diff --git a/app/src/main/java/helium314/keyboard/keyboard/internal/KeyboardState.java b/app/src/main/java/helium314/keyboard/keyboard/internal/KeyboardState.java index a7f222cba..c6579e58a 100644 --- a/app/src/main/java/helium314/keyboard/keyboard/internal/KeyboardState.java +++ b/app/src/main/java/helium314/keyboard/keyboard/internal/KeyboardState.java @@ -7,6 +7,8 @@ package helium314.keyboard.keyboard.internal; import android.text.TextUtils; + +import helium314.keyboard.keyboard.internal.keyboard_parser.floris.KeyCode; import helium314.keyboard.latin.utils.Log; import androidx.annotation.NonNull; @@ -411,21 +413,21 @@ public void onPressKey(final int code, final boolean isSinglePointer, final int + " single=" + isSinglePointer + " " + stateToString(autoCapsFlags, recapitalizeMode)); } - if (code != Constants.CODE_SHIFT) { + if (code != KeyCode.SHIFT) { // Because the double tap shift key timer is to detect two consecutive shift key press, // it should be canceled when a non-shift key is pressed. mSwitchActions.cancelDoubleTapShiftKeyTimer(); } - if (code == Constants.CODE_SHIFT) { + if (code == KeyCode.SHIFT) { onPressShift(); - } else if (code == Constants.CODE_CAPSLOCK) { + } else if (code == KeyCode.CAPS_LOCK) { // Nothing to do here. See {@link #onReleaseKey(int,boolean)}. - } else if (code == Constants.CODE_SWITCH_ALPHA_SYMBOL) { + } else if (code == KeyCode.ALPHA_SYMBOL) { onPressAlphaSymbol(autoCapsFlags, recapitalizeMode); - } else if (code == Constants.CODE_SWITCH_SYMBOL) { + } else if (code == KeyCode.SYMBOL) { // don't start sliding, causes issues with fully customizable layouts // (also does not allow chording, but can be fixed later) - } else if (code == Constants.CODE_SWITCH_ALPHA) { + } else if (code == KeyCode.ALPHA) { // don't start sliding, causes issues with fully customizable layouts // (also does not allow chording, but can be fixed later) } else { @@ -457,15 +459,15 @@ public void onReleaseKey(final int code, final boolean withSliding, final int au + " sliding=" + withSliding + " " + stateToString(autoCapsFlags, recapitalizeMode)); } - if (code == Constants.CODE_SHIFT) { + if (code == KeyCode.SHIFT) { onReleaseShift(withSliding, autoCapsFlags, recapitalizeMode); - } else if (code == Constants.CODE_CAPSLOCK) { + } else if (code == KeyCode.CAPS_LOCK) { setShiftLocked(!mAlphabetShiftState.isShiftLocked()); - } else if (code == Constants.CODE_SWITCH_ALPHA_SYMBOL) { + } else if (code == KeyCode.ALPHA_SYMBOL) { onReleaseAlphaSymbol(withSliding, autoCapsFlags, recapitalizeMode); - } else if (code == Constants.CODE_SWITCH_SYMBOL) { + } else if (code == KeyCode.SYMBOL) { onReleaseSymbol(withSliding, autoCapsFlags, recapitalizeMode); - } else if (code == Constants.CODE_SWITCH_ALPHA) { + } else if (code == KeyCode.ALPHA) { onReleaseAlpha(withSliding, autoCapsFlags, recapitalizeMode); } } @@ -698,7 +700,7 @@ public void onEvent(final Event event, final int autoCapsFlags, final int recapi switch (mSwitchState) { case SWITCH_STATE_MOMENTARY_ALPHA_AND_SYMBOL: - if (code == Constants.CODE_SWITCH_ALPHA_SYMBOL) { + if (code == KeyCode.ALPHA_SYMBOL) { // Detected only the mode change key has been pressed, and then released. if (mMode == MODE_ALPHABET) { mSwitchState = SWITCH_STATE_ALPHA; @@ -708,7 +710,7 @@ public void onEvent(final Event event, final int autoCapsFlags, final int recapi } break; case SWITCH_STATE_MOMENTARY_SYMBOL_AND_MORE: - if (code == Constants.CODE_SHIFT) { + if (code == KeyCode.SHIFT) { // Detected only the shift key has been pressed on symbol layout, and then // released. mSwitchState = SWITCH_STATE_SYMBOL_BEGIN; @@ -727,7 +729,7 @@ public void onEvent(final Event event, final int autoCapsFlags, final int recapi break; } if (!isSpaceOrEnter(code) && (Constants.isLetterCode(code) - || code == Constants.CODE_OUTPUT_TEXT)) { + || code == KeyCode.MULTIPLE_CODE_POINTS)) { mSwitchState = SWITCH_STATE_SYMBOL; } // Switch back to alpha keyboard mode if user types one or more non-space/enter @@ -750,25 +752,25 @@ public void onEvent(final Event event, final int autoCapsFlags, final int recapi // If the code is a letter, update keyboard shift state. if (Constants.isLetterCode(code)) { updateAlphabetShiftState(autoCapsFlags, recapitalizeMode); - } else if (code == Constants.CODE_EMOJI) { + } else if (code == KeyCode.EMOJI) { setEmojiKeyboard(); - } else if (code == Constants.CODE_SWITCH_ALPHA) { + } else if (code == KeyCode.ALPHA) { setAlphabetKeyboard(autoCapsFlags, recapitalizeMode); - } else if (code == Constants.CODE_CLIPBOARD) { + } else if (code == KeyCode.CLIPBOARD) { // Note: Printing clipboard content is handled in // {@link InputLogic#handleFunctionalEvent(Event,InputTransaction,int,LatinIME.UIHandler)}. if (Settings.getInstance().getCurrent().mClipboardHistoryEnabled) { setClipboardKeyboard(); } - } else if (code == Constants.CODE_SWITCH_NUMPAD) { + } else if (code == KeyCode.NUMPAD) { setNumpadKeyboard(); - } else if (code == Constants.CODE_SWITCH_SYMBOL) { + } else if (code == KeyCode.SYMBOL) { setSymbolsKeyboard(); - } else if (code == Constants.CODE_START_ONE_HANDED_MODE) { + } else if (code == KeyCode.START_ONE_HANDED_MODE) { setOneHandedModeEnabled(true); - } else if (code == Constants.CODE_STOP_ONE_HANDED_MODE) { + } else if (code == KeyCode.STOP_ONE_HANDED_MODE) { setOneHandedModeEnabled(false); - } else if (code == Constants.CODE_SWITCH_ONE_HANDED_MODE) { + } else if (code == KeyCode.SWITCH_ONE_HANDED_MODE) { switchOneHandedMode(); } } diff --git a/app/src/main/java/helium314/keyboard/keyboard/internal/PopupKeySpec.java b/app/src/main/java/helium314/keyboard/keyboard/internal/PopupKeySpec.java index 3b58ac0b5..9f88f78c6 100644 --- a/app/src/main/java/helium314/keyboard/keyboard/internal/PopupKeySpec.java +++ b/app/src/main/java/helium314/keyboard/keyboard/internal/PopupKeySpec.java @@ -13,6 +13,7 @@ import androidx.annotation.Nullable; import helium314.keyboard.keyboard.Key; +import helium314.keyboard.keyboard.internal.keyboard_parser.floris.KeyCode; import helium314.keyboard.latin.common.CollectionUtils; import helium314.keyboard.latin.common.Constants; import helium314.keyboard.latin.common.StringUtils; @@ -51,10 +52,10 @@ public PopupKeySpec(@NonNull final String popupKeySpec, boolean needsToUpperCase final int codeInSpec = KeySpecParser.getCode(popupKeySpec); final int code = needsToUpperCase ? StringUtils.toTitleCaseOfKeyCode(codeInSpec, locale) : codeInSpec; - if (code == Constants.CODE_UNSPECIFIED) { + if (code == KeyCode.NOT_SPECIFIED) { // Some letter, for example German Eszett (U+00DF: "ß"), has multiple characters // upper case representation ("SS"). - mCode = Constants.CODE_OUTPUT_TEXT; + mCode = KeyCode.MULTIPLE_CODE_POINTS; mOutputText = mLabel; } else { mCode = code; @@ -103,7 +104,7 @@ public boolean equals(final Object o) { public String toString() { final String label = (mIconId == KeyboardIconsSet.ICON_UNDEFINED ? mLabel : KeyboardIconsSet.PREFIX_ICON + KeyboardIconsSet.getIconName(mIconId)); - final String output = (mCode == Constants.CODE_OUTPUT_TEXT ? mOutputText + final String output = (mCode == KeyCode.MULTIPLE_CODE_POINTS ? mOutputText : Constants.printableCode(mCode)); if (StringUtils.codePointCount(label) == 1 && label.codePointAt(0) == mCode) { return output; @@ -119,7 +120,7 @@ public void addLetter(@NonNull final Key key) { final int code = key.getCode(); if (code > 32) { mCodes.put(code, 0); - } else if (code == Constants.CODE_OUTPUT_TEXT) { + } else if (code == KeyCode.MULTIPLE_CODE_POINTS) { mTexts.add(key.getOutputText()); } } @@ -128,7 +129,7 @@ public boolean contains(@NonNull final PopupKeySpec popupKey) { final int code = popupKey.mCode; if (mCodes.indexOfKey(code) >= 0) { return true; - } else return code == Constants.CODE_OUTPUT_TEXT && mTexts.contains(popupKey.mOutputText); + } else return code == KeyCode.MULTIPLE_CODE_POINTS && mTexts.contains(popupKey.mOutputText); } } diff --git a/app/src/main/java/helium314/keyboard/keyboard/internal/TimerHandler.java b/app/src/main/java/helium314/keyboard/keyboard/internal/TimerHandler.java index 4ad111c02..e47a42361 100644 --- a/app/src/main/java/helium314/keyboard/keyboard/internal/TimerHandler.java +++ b/app/src/main/java/helium314/keyboard/keyboard/internal/TimerHandler.java @@ -14,6 +14,7 @@ import helium314.keyboard.keyboard.Key; import helium314.keyboard.keyboard.PointerTracker; +import helium314.keyboard.keyboard.internal.keyboard_parser.floris.KeyCode; import helium314.keyboard.latin.common.Constants; import helium314.keyboard.latin.utils.LeakGuardHandlerWrapper; @@ -104,7 +105,7 @@ public void startLongPressTimerOf(@NonNull final PointerTracker tracker, final i } // Use a separate message id for long pressing shift key, because long press shift key // timers should be canceled when other key is pressed. - final int messageId = (key.getCode() == Constants.CODE_SHIFT) + final int messageId = (key.getCode() == KeyCode.SHIFT) ? MSG_LONGPRESS_SHIFT_KEY : MSG_LONGPRESS_KEY; sendMessageDelayed(obtainMessage(messageId, tracker), delay); } diff --git a/app/src/main/java/helium314/keyboard/keyboard/internal/keyboard_parser/EmojiParser.kt b/app/src/main/java/helium314/keyboard/keyboard/internal/keyboard_parser/EmojiParser.kt index 092d9c9ba..ad4f1022a 100644 --- a/app/src/main/java/helium314/keyboard/keyboard/internal/keyboard_parser/EmojiParser.kt +++ b/app/src/main/java/helium314/keyboard/keyboard/internal/keyboard_parser/EmojiParser.kt @@ -7,6 +7,7 @@ import helium314.keyboard.keyboard.Key import helium314.keyboard.keyboard.Key.KeyParams import helium314.keyboard.keyboard.KeyboardId import helium314.keyboard.keyboard.internal.KeyboardParams +import helium314.keyboard.keyboard.internal.keyboard_parser.floris.KeyCode import helium314.keyboard.latin.R import helium314.keyboard.latin.common.Constants import helium314.keyboard.latin.common.StringUtils @@ -66,7 +67,7 @@ class EmojiParser(private val params: KeyboardParams, private val context: Conte val specAndSdk = spec.split("||") if (specAndSdk.getOrNull(1)?.toIntOrNull()?.let { it > Build.VERSION.SDK_INT } == true) return null if ("," !in specAndSdk.first()) { - val code = specAndSdk.first().toIntOrNull(16) ?: return specAndSdk.first() to Constants.CODE_OUTPUT_TEXT // text emojis + val code = specAndSdk.first().toIntOrNull(16) ?: return specAndSdk.first() to KeyCode.MULTIPLE_CODE_POINTS // text emojis val label = StringUtils.newSingleCodePointString(code) return label to code } @@ -75,7 +76,7 @@ class EmojiParser(private val params: KeyboardParams, private val context: Conte val cp = codePointString.toInt(16) labelBuilder.appendCodePoint(cp) } - return labelBuilder.toString() to Constants.CODE_OUTPUT_TEXT + return labelBuilder.toString() to KeyCode.MULTIPLE_CODE_POINTS } private fun parseEmojiKey(spec: String, popupKeysString: String? = null): KeyParams? { diff --git a/app/src/main/java/helium314/keyboard/keyboard/internal/keyboard_parser/JsonKeyboardParser.kt b/app/src/main/java/helium314/keyboard/keyboard/internal/keyboard_parser/JsonKeyboardParser.kt index dc1721943..a5c0493f1 100644 --- a/app/src/main/java/helium314/keyboard/keyboard/internal/keyboard_parser/JsonKeyboardParser.kt +++ b/app/src/main/java/helium314/keyboard/keyboard/internal/keyboard_parser/JsonKeyboardParser.kt @@ -11,6 +11,7 @@ import helium314.keyboard.keyboard.internal.keyboard_parser.floris.AutoTextKeyDa import helium314.keyboard.keyboard.internal.keyboard_parser.floris.CaseSelector import helium314.keyboard.keyboard.internal.keyboard_parser.floris.CharWidthSelector import helium314.keyboard.keyboard.internal.keyboard_parser.floris.KanaSelector +import helium314.keyboard.keyboard.internal.keyboard_parser.floris.KeyCode.convertFloris import helium314.keyboard.keyboard.internal.keyboard_parser.floris.KeyData import helium314.keyboard.keyboard.internal.keyboard_parser.floris.LayoutDirectionSelector import helium314.keyboard.keyboard.internal.keyboard_parser.floris.MultiTextKeyData @@ -34,7 +35,7 @@ class JsonKeyboardParser(private val params: KeyboardParams, private val context // initially 200 ms parse (debug build on S4 mini) // after a few parses it's optimized and 20-30 ms // whole load is 50-70 ms vs 30-55 with simple parser -> it's ok - return florisKeyData.mapTo(mutableListOf()) { it.mapNotNull { it.compute(params) } } + return florisKeyData.mapTo(mutableListOf()) { it.mapNotNull { it.compute(params)?.convertFloris() } } } } diff --git a/app/src/main/java/helium314/keyboard/keyboard/internal/keyboard_parser/KeyboardParser.kt b/app/src/main/java/helium314/keyboard/keyboard/internal/keyboard_parser/KeyboardParser.kt index 4c7675eb3..9a0ad2d1f 100644 --- a/app/src/main/java/helium314/keyboard/keyboard/internal/keyboard_parser/KeyboardParser.kt +++ b/app/src/main/java/helium314/keyboard/keyboard/internal/keyboard_parser/KeyboardParser.kt @@ -12,6 +12,7 @@ import helium314.keyboard.keyboard.KeyboardId import helium314.keyboard.keyboard.KeyboardTheme import helium314.keyboard.keyboard.internal.KeyboardIconsSet import helium314.keyboard.keyboard.internal.KeyboardParams +import helium314.keyboard.keyboard.internal.keyboard_parser.floris.KeyCode import helium314.keyboard.keyboard.internal.keyboard_parser.floris.KeyData import helium314.keyboard.keyboard.internal.keyboard_parser.floris.KeyType import helium314.keyboard.keyboard.internal.keyboard_parser.floris.SimplePopups @@ -415,7 +416,7 @@ abstract class KeyboardParser(private val params: KeyboardParams, private val co return when (key) { FunctionalKey.SYMBOL_ALPHA -> KeyParams( if (params.mId.isAlphabetKeyboard) getToSymbolLabel() else params.mLocaleKeyboardInfos.labelAlphabet, - Constants.CODE_SWITCH_ALPHA_SYMBOL, + KeyCode.ALPHA_SYMBOL, params, width, Key.LABEL_FLAGS_PRESERVE_CASE or Key.LABEL_FLAGS_FOLLOW_FUNCTIONAL_TEXT_COLOR, @@ -424,7 +425,7 @@ abstract class KeyboardParser(private val params: KeyboardParams, private val co ) FunctionalKey.SYMBOL -> KeyParams( getToSymbolLabel(), - Constants.CODE_SWITCH_SYMBOL, + KeyCode.SYMBOL, params, width, Key.LABEL_FLAGS_PRESERVE_CASE or Key.LABEL_FLAGS_FOLLOW_FUNCTIONAL_TEXT_COLOR, @@ -433,7 +434,7 @@ abstract class KeyboardParser(private val params: KeyboardParams, private val co ) FunctionalKey.ALPHA -> KeyParams( params.mLocaleKeyboardInfos.labelAlphabet, - Constants.CODE_SWITCH_ALPHA, + KeyCode.ALPHA, params, width, Key.LABEL_FLAGS_PRESERVE_CASE or Key.LABEL_FLAGS_FOLLOW_FUNCTIONAL_TEXT_COLOR, diff --git a/app/src/main/java/helium314/keyboard/keyboard/internal/keyboard_parser/LocaleKeyboardInfos.kt b/app/src/main/java/helium314/keyboard/keyboard/internal/keyboard_parser/LocaleKeyboardInfos.kt index d0a53ad9c..2593c0255 100644 --- a/app/src/main/java/helium314/keyboard/keyboard/internal/keyboard_parser/LocaleKeyboardInfos.kt +++ b/app/src/main/java/helium314/keyboard/keyboard/internal/keyboard_parser/LocaleKeyboardInfos.kt @@ -324,8 +324,8 @@ private val euro = "€" to arrayOf("£", "¥", "$", "¢", "₱") private val dram = "֏" to arrayOf("€", "₽", "$", "£", "¥") private val rupee = "₹" to arrayOf("£", "€", "$", "¢", "¥", "₱") private val pound = "£" to arrayOf("€", "¥", "$", "¢", "₱") -private val ruble = "₽" to arrayOf("€", "$", "£", "¥") -private val lira = "₺" to arrayOf("€", "$", "£", "¥") +private val ruble = "₽" to arrayOf("€", "$", "£", "¥", "₱") +private val lira = "₺" to arrayOf("€", "$", "£", "¥", "₱") private val dollar = "$" to arrayOf("£", "¢", "€", "¥", "₱") private val euroCountries = "AD|AT|BE|BG|HR|CY|CZ|DA|EE|FI|FR|DE|GR|HU|IE|IT|XK|LV|LT|LU|MT|MO|ME|NL|PL|PT|RO|SM|SK|SI|ES|VA".toRegex() private val euroLocales = "bg|ca|cs|da|de|el|en|es|et|eu|fi|fr|ga|gl|hr|hu|it|lb|lt|lv|mt|nl|pl|pt|ro|sk|sl|sq|sr|sv".toRegex() diff --git a/app/src/main/java/helium314/keyboard/keyboard/internal/keyboard_parser/floris/KeyCode.kt b/app/src/main/java/helium314/keyboard/keyboard/internal/keyboard_parser/floris/KeyCode.kt index e94a63278..a56a8a8ff 100644 --- a/app/src/main/java/helium314/keyboard/keyboard/internal/keyboard_parser/floris/KeyCode.kt +++ b/app/src/main/java/helium314/keyboard/keyboard/internal/keyboard_parser/floris/KeyCode.kt @@ -5,28 +5,21 @@ */ package helium314.keyboard.keyboard.internal.keyboard_parser.floris -// taken from FlorisBoard, not actually used +// taken from FlorisBoard and modified object KeyCode { object Spec { const val CHARACTERS_MIN = 1 const val CHARACTERS_MAX = 65535 val CHARACTERS = CHARACTERS_MIN..CHARACTERS_MAX - const val INTERNAL_MIN = -9999 - const val INTERNAL_MAX = -1 - val INTERNAL = INTERNAL_MIN..INTERNAL_MAX + const val INTERNAL_FLORIS_MIN = -9999 + const val INTERNAL_FLORIS_MAX = -1 + val INTERNAL_FLORIS = INTERNAL_FLORIS_MIN..INTERNAL_FLORIS_MAX + val INTERNAL_HELI = -19999..-10000 // for keys exclusive to this app } const val UNSPECIFIED = 0 - const val PHONE_WAIT = 59 // ; - const val PHONE_PAUSE = 44 // , - - const val SPACE = 32 - const val ESCAPE = 27 - const val ENTER = 10 - const val TAB = 9 - const val CTRL = -1 const val CTRL_LOCK = -2 const val ALT = -3 @@ -52,7 +45,7 @@ object KeyCode { const val CLIPBOARD_COPY = -31 const val CLIPBOARD_CUT = -32 const val CLIPBOARD_PASTE = -33 - const val CLIPBOARD_SELECT = -34 + const val CLIPBOARD_SELECT_WORD = -34 // CLIPBOARD_SELECT const val CLIPBOARD_SELECT_ALL = -35 const val CLIPBOARD_CLEAR_HISTORY = -36 const val CLIPBOARD_CLEAR_FULL_HISTORY = -37 @@ -66,17 +59,17 @@ object KeyCode { const val UNDO = -131 const val REDO = -132 - const val VIEW_CHARACTERS = -201 - const val VIEW_SYMBOLS = -202 + const val ALPHA = -201 // VIEW_CHARACTERS + const val SYMBOL = -202 // VIEW_SYMBOLS const val VIEW_SYMBOLS2 = -203 const val VIEW_NUMERIC = -204 - const val VIEW_NUMERIC_ADVANCED = -205 + const val NUMPAD = -205 // VIEW_NUMERIC_ADVANCED const val VIEW_PHONE = -206 const val VIEW_PHONE2 = -207 const val IME_UI_MODE_TEXT = -211 - const val IME_UI_MODE_MEDIA = -212 - const val IME_UI_MODE_CLIPBOARD = -213 + const val EMOJI = -212 // IME_UI_MODE_MEDIA + const val CLIPBOARD = -213 // IME_UI_MODE_CLIPBOARD const val SYSTEM_INPUT_METHOD_PICKER = -221 const val SYSTEM_PREV_INPUT_METHOD = -222 @@ -125,4 +118,63 @@ object KeyCode { const val HALF_SPACE = 8204 const val CJK_SPACE = 12288 + + // heliboard only codes + const val ALPHA_SYMBOL = -10001 + const val START_ONE_HANDED_MODE = -10002 + const val STOP_ONE_HANDED_MODE = -10003 + const val SWITCH_ONE_HANDED_MODE = -10004 + const val SHIFT_ENTER = -10005 + const val ACTION_NEXT = -10006 + const val ACTION_PREVIOUS = -10007 + const val SYMBOL_SHIFT = -10008 // todo: check, maybe can be removed + // Code value representing the code is not specified. + const val NOT_SPECIFIED = -10009 // todo: not sure if there is need to have the "old" unspecified keyCode different, just test it and maybe merge + + /** to make sure a FlorisBoard code works when reading a JSON layout */ + private fun Int.checkOrConvertCode(): Int = when (this) { + // todo: should work, but not yet + // CURRENCY_SLOT_1, CURRENCY_SLOT_2, CURRENCY_SLOT_3, CURRENCY_SLOT_4, CURRENCY_SLOT_5, CURRENCY_SLOT_6, + + // working + VOICE_INPUT, LANGUAGE_SWITCH, SETTINGS, DELETE, ALPHA, SYMBOL, EMOJI, CLIPBOARD, + UNDO, REDO, ARROW_DOWN, ARROW_UP, ARROW_RIGHT, ARROW_LEFT, CLIPBOARD_COPY, CLIPBOARD_SELECT_ALL, + CLIPBOARD_SELECT_WORD, TOGGLE_INCOGNITO_MODE, TOGGLE_AUTOCORRECT, MOVE_START_OF_LINE, MOVE_END_OF_LINE, + SHIFT, CAPS_LOCK, MULTIPLE_CODE_POINTS, UNSPECIFIED, + + // heliboard only + ALPHA_SYMBOL, START_ONE_HANDED_MODE, STOP_ONE_HANDED_MODE, SWITCH_ONE_HANDED_MODE, SHIFT_ENTER, + ACTION_NEXT, ACTION_PREVIOUS, SYMBOL_SHIFT, NOT_SPECIFIED + -> this + + // conversion + IME_UI_MODE_TEXT -> ALPHA + + else -> throw IllegalStateException("key code $this not yet supported") + } + + /** to make sure a FlorisBoard label works when reading a JSON layout */ + private fun String.convertFlorisLabel(): String = when (this) { + "view_characters" -> "alpha" + "view_symbols" -> "symbol" + "view_numeric_advanced" -> "numpad" + "view_phone" -> "alpha" + "view_phone2" -> "symbols" + "ime_ui_mode_media" -> "emoji" + "ime_ui_mode_clipboard" -> "clipboard" + "ime_ui_mode_text" -> "alpha" + "currency_slot_1" -> "$$$" + "currency_slot_2" -> "$$$1" + "currency_slot_3" -> "$$$2" + "currency_slot_4" -> "$$$3" + "currency_slot_5" -> "$$$4" + "currency_slot_6" -> "$$$5" + else -> this + } + + fun KeyData.convertFloris() = when (this) { + is TextKeyData -> { TextKeyData(type, code.checkOrConvertCode(), label.convertFlorisLabel(), groupId, popup, labelFlags) } + is AutoTextKeyData -> { AutoTextKeyData(type, code.checkOrConvertCode(), label.convertFlorisLabel(), groupId, popup, labelFlags) } + is MultiTextKeyData -> { MultiTextKeyData(type, codePoints, label.convertFlorisLabel(), groupId, popup, labelFlags) } + } } diff --git a/app/src/main/java/helium314/keyboard/keyboard/internal/keyboard_parser/floris/KeyData.kt b/app/src/main/java/helium314/keyboard/keyboard/internal/keyboard_parser/floris/KeyData.kt index 3711d7994..7c1897df7 100644 --- a/app/src/main/java/helium314/keyboard/keyboard/internal/keyboard_parser/floris/KeyData.kt +++ b/app/src/main/java/helium314/keyboard/keyboard/internal/keyboard_parser/floris/KeyData.kt @@ -7,11 +7,8 @@ package helium314.keyboard.keyboard.internal.keyboard_parser.floris import kotlinx.serialization.SerialName import kotlinx.serialization.Serializable -import helium314.keyboard.keyboard.Key -import helium314.keyboard.keyboard.Key.KeyParams import helium314.keyboard.keyboard.KeyboardId import helium314.keyboard.keyboard.internal.KeyboardParams -import helium314.keyboard.keyboard.internal.keyboard_parser.rtlLabel import helium314.keyboard.latin.common.StringUtils // taken from FlorisBoard, small modifications @@ -58,99 +55,6 @@ interface AbstractKeyData { } } -/** - * Interface describing a basic key which can carry a character, an emoji, a special function etc. while being as - * abstract as possible. - * - * @property type The type of the key. - * @property code The Unicode code point of this key, or a special code from [KeyCode]. - * @property label The label of the key. This should always be a representative string for [code]. - * @property groupId The group which this key belongs to (currently only allows [GROUP_DEFAULT]). - * @property popup The popups for ths key. Can also dynamically be provided via popup extensions. - */ -interface KeyData : AbstractKeyData { - val type: KeyType - val code: Int - val label: String - val groupId: Int - val popup: PopupSet // not nullable because can't add number otherwise - val labelFlags: Int - - // groups (currently) not supported - companion object { - /** - * Constant for the default group. If not otherwise specified, any key is automatically - * assigned to this group. - */ - const val GROUP_DEFAULT: Int = 0 - - /** - * Constant for the Left modifier key group. Any key belonging to this group will get the - * popups specified for "~left" in the popup mapping. - */ - const val GROUP_LEFT: Int = 1 - - /** - * Constant for the right modifier key group. Any key belonging to this group will get the - * popups specified for "~right" in the popup mapping. - */ - const val GROUP_RIGHT: Int = 2 - - /** - * Constant for the enter modifier key group. Any key belonging to this group will get the - * popups specified for "~enter" in the popup mapping. - */ - const val GROUP_ENTER: Int = 3 - - /** - * Constant for the enter modifier key group. Any key belonging to this group will get the - * popups specified for "~kana" in the popup mapping. - */ - const val GROUP_KANA: Int = 97 - } - - // make it non-nullable for simplicity, and to reflect current implementations - override fun compute(params: KeyboardParams): KeyData - - fun isSpaceKey(): Boolean { - return type == KeyType.CHARACTER && (code == KeyCode.SPACE || code == KeyCode.CJK_SPACE - || code == KeyCode.HALF_SPACE || code == KeyCode.KESHIDA) - } - - fun toKeyParams(params: KeyboardParams, width: Float = params.mDefaultRelativeKeyWidth, additionalLabelFlags: Int = 0): KeyParams { - // numeric keys are assigned a higher width in number layouts - require(type == KeyType.CHARACTER || type == KeyType.NUMERIC) { "only KeyType CHARACTER or NUMERIC is supported" } - // allow GROUP_ENTER negative codes so original florisboard number layouts can be used, bu actually it's ignored - require(groupId == GROUP_DEFAULT || groupId == GROUP_ENTER) { "currently only GROUP_DEFAULT or GROUP_ENTER is supported" } - // allow some negative codes so original florisboard number layouts can be used, those codes are actually ignored - require(code >= 0 || code == -7 || code == -201 || code == -202) { "functional code $code not (yet) supported" } - require(code != KeyCode.UNSPECIFIED || label.isNotEmpty()) { "key has no code and no label" } - - return if (code == KeyCode.UNSPECIFIED || code == KeyCode.MULTIPLE_CODE_POINTS) { - // code will be determined from label if possible (i.e. label is single code point) - // but also longer labels should work without issues, also for MultiTextKeyData - KeyParams( - label.rtlLabel(params), // todo (when supported): convert special labels to keySpec - params, - width, - labelFlags or additionalLabelFlags, - Key.BACKGROUND_TYPE_NORMAL, // todo (when supported): determine type - popup, - ) - } else { - KeyParams( - label.ifEmpty { StringUtils.newSingleCodePointString(code) }, - code, // todo (when supported): convert codes < 0, because florisboard layouts should still be usable - params, - width, - labelFlags or additionalLabelFlags, - Key.BACKGROUND_TYPE_NORMAL, - popup, - ) - } - } -} - /** * Allows to select an [AbstractKeyData] based on the current caps state. Note that this type of selector only really * makes sense in a text context, though technically speaking it can be used anywhere, so this implementation allows diff --git a/app/src/main/java/helium314/keyboard/keyboard/internal/keyboard_parser/floris/TextKeyData.kt b/app/src/main/java/helium314/keyboard/keyboard/internal/keyboard_parser/floris/TextKeyData.kt index 4da2a9591..be1655109 100644 --- a/app/src/main/java/helium314/keyboard/keyboard/internal/keyboard_parser/floris/TextKeyData.kt +++ b/app/src/main/java/helium314/keyboard/keyboard/internal/keyboard_parser/floris/TextKeyData.kt @@ -10,11 +10,107 @@ import kotlinx.serialization.Serializable import kotlinx.serialization.Transient import helium314.keyboard.keyboard.Key import helium314.keyboard.keyboard.internal.KeyboardParams +import helium314.keyboard.keyboard.internal.keyboard_parser.rtlLabel +import helium314.keyboard.latin.common.Constants +import helium314.keyboard.latin.common.StringUtils // taken from FlorisBoard, small modifications (see also KeyData) // internal keys removed (currently no plan to support them) // added String.toTextKey // currency key handling (see todo below...) + +/** + * Interface describing a basic key which can carry a character, an emoji, a special function etc. while being as + * abstract as possible. + * + * @property type The type of the key. + * @property code The Unicode code point of this key, or a special code from [KeyCode]. + * @property label The label of the key. This should always be a representative string for [code]. + * @property groupId The group which this key belongs to (currently only allows [GROUP_DEFAULT]). + * @property popup The popups for ths key. Can also dynamically be provided via popup extensions. + */ +sealed interface KeyData : AbstractKeyData { + val type: KeyType + val code: Int + val label: String + val groupId: Int + val popup: PopupSet // not nullable because can't add number otherwise + val labelFlags: Int + + // groups (currently) not supported + companion object { + /** + * Constant for the default group. If not otherwise specified, any key is automatically + * assigned to this group. + */ + const val GROUP_DEFAULT: Int = 0 + + /** + * Constant for the Left modifier key group. Any key belonging to this group will get the + * popups specified for "~left" in the popup mapping. + */ + const val GROUP_LEFT: Int = 1 + + /** + * Constant for the right modifier key group. Any key belonging to this group will get the + * popups specified for "~right" in the popup mapping. + */ + const val GROUP_RIGHT: Int = 2 + + /** + * Constant for the enter modifier key group. Any key belonging to this group will get the + * popups specified for "~enter" in the popup mapping. + */ + const val GROUP_ENTER: Int = 3 + + /** + * Constant for the enter modifier key group. Any key belonging to this group will get the + * popups specified for "~kana" in the popup mapping. + */ + const val GROUP_KANA: Int = 97 + } + + // make it non-nullable for simplicity, and to reflect current implementations + override fun compute(params: KeyboardParams): KeyData + + fun isSpaceKey(): Boolean { + return type == KeyType.CHARACTER && (code == Constants.CODE_SPACE || code == KeyCode.CJK_SPACE + || code == KeyCode.HALF_SPACE || code == KeyCode.KESHIDA) + } + + fun toKeyParams(params: KeyboardParams, width: Float = params.mDefaultRelativeKeyWidth, additionalLabelFlags: Int = 0): Key.KeyParams { + // todo: remove checks here, do only when reading json layouts + // numeric keys are assigned a higher width in number layouts + require(type == KeyType.CHARACTER || type == KeyType.NUMERIC) { "only KeyType CHARACTER or NUMERIC is supported" } + // allow GROUP_ENTER negative codes so original florisboard number layouts can be used, bu actually it's ignored + require(groupId == GROUP_DEFAULT || groupId == GROUP_ENTER) { "currently only GROUP_DEFAULT or GROUP_ENTER is supported" } + require(code != KeyCode.UNSPECIFIED || label.isNotEmpty()) { "key has no code and no label" } + + return if (code == KeyCode.UNSPECIFIED || code == KeyCode.MULTIPLE_CODE_POINTS) { + // code will be determined from label if possible (i.e. label is single code point) + // but also longer labels should work without issues, also for MultiTextKeyData + Key.KeyParams( + label.rtlLabel(params), // todo (when supported): convert special labels to keySpec + params, + width, + labelFlags or additionalLabelFlags, + Key.BACKGROUND_TYPE_NORMAL, // todo (when supported): determine type + popup, + ) + } else { + Key.KeyParams( + label.ifEmpty { StringUtils.newSingleCodePointString(code) }, + code, + params, + width, + labelFlags or additionalLabelFlags, + Key.BACKGROUND_TYPE_NORMAL, + popup, + ) + } + } +} + /** * Data class which describes a single key and its attributes. * @@ -47,7 +143,7 @@ class TextKeyData( return params.mLocaleKeyboardInfos.currencyKey .let { it.first.toTextKey(it.second.toList(), labelFlags = Key.LABEL_FLAGS_FOLLOW_KEY_LETTER_RATIO) } // the flag is to match old parser, but why for main currency key, but not for others? val n = label.substringAfter("$$$").toIntOrNull() - if (n != null && n <= 4 && n > 0) + if (n != null && n <= 5 && n > 0) return params.mLocaleKeyboardInfos.currencyKey.second[n - 1].toTextKey() } return this @@ -55,7 +151,7 @@ class TextKeyData( override fun asString(isForDisplay: Boolean): String { return buildString { - if (isForDisplay || code == KeyCode.URI_COMPONENT_TLD || code < KeyCode.SPACE) { + if (isForDisplay || code == KeyCode.URI_COMPONENT_TLD || code < Constants.CODE_SPACE) { if (Unicode.isNonSpacingMark(code) && !label.startsWith("◌")) { append("◌") } @@ -95,7 +191,7 @@ class AutoTextKeyData( override fun asString(isForDisplay: Boolean): String { return buildString { - if (isForDisplay || code == KeyCode.URI_COMPONENT_TLD || code < KeyCode.SPACE) { + if (isForDisplay || code == KeyCode.URI_COMPONENT_TLD || code < Constants.CODE_SPACE) { if (Unicode.isNonSpacingMark(code) && !label.startsWith("◌")) { append("◌") } diff --git a/app/src/main/java/helium314/keyboard/latin/AudioAndHapticFeedbackManager.java b/app/src/main/java/helium314/keyboard/latin/AudioAndHapticFeedbackManager.java index e21341ea4..873d080f0 100644 --- a/app/src/main/java/helium314/keyboard/latin/AudioAndHapticFeedbackManager.java +++ b/app/src/main/java/helium314/keyboard/latin/AudioAndHapticFeedbackManager.java @@ -12,6 +12,7 @@ import android.view.HapticFeedbackConstants; import android.view.View; +import helium314.keyboard.keyboard.internal.keyboard_parser.floris.KeyCode; import helium314.keyboard.latin.common.Constants; import helium314.keyboard.latin.settings.SettingsValues; @@ -82,7 +83,7 @@ public void performAudioFeedback(final int code) { } final int sound; switch (code) { - case Constants.CODE_DELETE: + case KeyCode.DELETE: sound = AudioManager.FX_KEYPRESS_DELETE; break; case Constants.CODE_ENTER: diff --git a/app/src/main/java/helium314/keyboard/latin/KeyboardWrapperView.kt b/app/src/main/java/helium314/keyboard/latin/KeyboardWrapperView.kt index a769e5643..d750752f8 100644 --- a/app/src/main/java/helium314/keyboard/latin/KeyboardWrapperView.kt +++ b/app/src/main/java/helium314/keyboard/latin/KeyboardWrapperView.kt @@ -13,6 +13,7 @@ import android.widget.FrameLayout import android.widget.ImageButton import helium314.keyboard.keyboard.KeyboardActionListener import helium314.keyboard.keyboard.KeyboardSwitcher +import helium314.keyboard.keyboard.internal.keyboard_parser.floris.KeyCode import helium314.keyboard.latin.common.ColorType import helium314.keyboard.latin.common.Constants import helium314.keyboard.latin.settings.Settings @@ -83,7 +84,7 @@ class KeyboardWrapperView @JvmOverloads constructor( if (newScale == oldScale) return@setOnTouchListener true Settings.getInstance().writeOneHandedModeScale(newScale) oneHandedModeEnabled = false // intentionally putting wrong value, so KeyboardSwitcher.setOneHandedModeEnabled does actually reload - keyboardActionListener?.onCodeInput(Constants.CODE_START_ONE_HANDED_MODE, + keyboardActionListener?.onCodeInput(KeyCode.START_ONE_HANDED_MODE, Constants.NOT_A_COORDINATE, Constants.NOT_A_COORDINATE, false) } else -> x = 0f @@ -118,11 +119,11 @@ class KeyboardWrapperView @JvmOverloads constructor( override fun onClick(view: View) { if (view === stopOneHandedModeBtn) { - keyboardActionListener?.onCodeInput(Constants.CODE_STOP_ONE_HANDED_MODE, + keyboardActionListener?.onCodeInput(KeyCode.STOP_ONE_HANDED_MODE, Constants.NOT_A_COORDINATE, Constants.NOT_A_COORDINATE, false /* isKeyRepeat */) } else if (view === switchOneHandedModeBtn) { - keyboardActionListener?.onCodeInput(Constants.CODE_SWITCH_ONE_HANDED_MODE, + keyboardActionListener?.onCodeInput(KeyCode.SWITCH_ONE_HANDED_MODE, Constants.NOT_A_COORDINATE, Constants.NOT_A_COORDINATE, false /* isKeyRepeat */) } diff --git a/app/src/main/java/helium314/keyboard/latin/LatinIME.java b/app/src/main/java/helium314/keyboard/latin/LatinIME.java index 776299c20..bb20ad997 100644 --- a/app/src/main/java/helium314/keyboard/latin/LatinIME.java +++ b/app/src/main/java/helium314/keyboard/latin/LatinIME.java @@ -42,6 +42,7 @@ import helium314.keyboard.accessibility.AccessibilityUtils; import helium314.keyboard.compat.ConfigurationCompatKt; import helium314.keyboard.compat.EditorInfoCompatUtils; +import helium314.keyboard.keyboard.internal.keyboard_parser.floris.KeyCode; import helium314.keyboard.latin.common.InsetsOutlineProvider; import helium314.keyboard.dictionarypack.DictionaryPackConstants; import helium314.keyboard.event.Event; @@ -1402,7 +1403,7 @@ public void onMovePointer(int steps) { // some apps don't return any text via input connection, and the cursor can't be moved // we fall back to virtually pressing the left/right key one or more times instead while (steps != 0) { - onCodeInput(Constants.CODE_LEFT, Constants.NOT_A_COORDINATE, Constants.NOT_A_COORDINATE, false); + onCodeInput(KeyCode.ARROW_LEFT, Constants.NOT_A_COORDINATE, Constants.NOT_A_COORDINATE, false); ++steps; } return; @@ -1412,7 +1413,7 @@ public void onMovePointer(int steps) { moveSteps = Math.min(availableCharacters, steps); if (moveSteps == 0) { while (steps != 0) { - onCodeInput(Constants.CODE_RIGHT, Constants.NOT_A_COORDINATE, Constants.NOT_A_COORDINATE, false); + onCodeInput(KeyCode.ARROW_RIGHT, Constants.NOT_A_COORDINATE, Constants.NOT_A_COORDINATE, false); --steps; } return; @@ -1446,7 +1447,7 @@ public void onMoveDeletePointer(int steps) { public void onUpWithDeletePointerActive() { if (mInputLogic.mConnection.hasSelection()) { mInputLogic.finishInput(); - onCodeInput(Constants.CODE_DELETE, Constants.NOT_A_COORDINATE, Constants.NOT_A_COORDINATE, false); + onCodeInput(KeyCode.DELETE, Constants.NOT_A_COORDINATE, Constants.NOT_A_COORDINATE, false); } } @@ -1527,12 +1528,12 @@ public void switchInputMethodAndSubtype(final InputMethodInfo imi, final InputMe // TODO: Instead of checking for alphabetic keyboard here, separate keycodes for // alphabetic shift and shift while in symbol layout and get rid of this method. private int getCodePointForKeyboard(final int codePoint) { - if (Constants.CODE_SHIFT == codePoint) { + if (KeyCode.SHIFT == codePoint) { final Keyboard currentKeyboard = mKeyboardSwitcher.getKeyboard(); if (null != currentKeyboard && currentKeyboard.mId.isAlphabetKeyboard()) { return codePoint; } - return Constants.CODE_SYMBOL_SHIFT; + return KeyCode.SYMBOL_SHIFT; } return codePoint; } @@ -1542,8 +1543,8 @@ private int getCodePointForKeyboard(final int codePoint) { public void onCodeInput(final int codePoint, final int x, final int y, final boolean isKeyRepeat) { if (codePoint < 0) { switch (codePoint) { - case Constants.CODE_TOGGLE_AUTOCORRECT -> {mSettings.toggleAutoCorrect(); return; } - case Constants.CODE_TOGGLE_INCOGNITO -> {mSettings.toggleAlwaysIncognitoMode(); return; } + case KeyCode.TOGGLE_AUTOCORRECT -> {mSettings.toggleAutoCorrect(); return; } + case KeyCode.TOGGLE_INCOGNITO_MODE -> {mSettings.toggleAlwaysIncognitoMode(); return; } } } // TODO: this processing does not belong inside LatinIME, the caller should be doing this. @@ -1562,7 +1563,7 @@ public void onCodeInput(final int codePoint, final int x, final int y, final boo // This method is public for testability of LatinIME, but also in the future it should // completely replace #onCodeInput. public void onEvent(@NonNull final Event event) { - if (Constants.CODE_SHORTCUT == event.getMKeyCode()) { + if (KeyCode.VOICE_INPUT == event.getMKeyCode()) { mRichImm.switchToShortcutIme(this); } final InputTransaction completeInputTransaction = @@ -1595,7 +1596,7 @@ public static Event createSoftwareKeypressEvent(final int keyCodeOrCodePoint, fi @Override public void onTextInput(final String rawText) { // TODO: have the keyboard pass the correct key code when we need it. - final Event event = Event.createSoftwareTextEvent(rawText, Constants.CODE_OUTPUT_TEXT); + final Event event = Event.createSoftwareTextEvent(rawText, KeyCode.MULTIPLE_CODE_POINTS); final InputTransaction completeInputTransaction = mInputLogic.onTextInput(mSettings.getCurrent(), event, mKeyboardSwitcher.getKeyboardShiftMode(), mHandler); @@ -1802,7 +1803,7 @@ private void hapticAndAudioFeedback(final int code, final int repeatCount) { return; } if (repeatCount > 0) { - if (code == Constants.CODE_DELETE && !mInputLogic.mConnection.canDeleteCharacters()) { + if (code == KeyCode.DELETE && !mInputLogic.mConnection.canDeleteCharacters()) { // No need to feedback when repeat delete key will have no effect. return; } diff --git a/app/src/main/java/helium314/keyboard/latin/PunctuationSuggestions.java b/app/src/main/java/helium314/keyboard/latin/PunctuationSuggestions.java index b4ade7c14..241af9a5e 100644 --- a/app/src/main/java/helium314/keyboard/latin/PunctuationSuggestions.java +++ b/app/src/main/java/helium314/keyboard/latin/PunctuationSuggestions.java @@ -9,6 +9,7 @@ import androidx.annotation.Nullable; import helium314.keyboard.keyboard.internal.KeySpecParser; +import helium314.keyboard.keyboard.internal.keyboard_parser.floris.KeyCode; import helium314.keyboard.latin.common.Constants; import helium314.keyboard.latin.common.StringUtils; @@ -62,7 +63,7 @@ public static PunctuationSuggestions newPunctuationSuggestions( public String getWord(final int index) { final String keySpec = super.getWord(index); final int code = KeySpecParser.getCode(keySpec); - return (code == Constants.CODE_OUTPUT_TEXT) + return (code == KeyCode.MULTIPLE_CODE_POINTS) ? KeySpecParser.getOutputText(keySpec) : StringUtils.newSingleCodePointString(code); } diff --git a/app/src/main/java/helium314/keyboard/latin/WordComposer.java b/app/src/main/java/helium314/keyboard/latin/WordComposer.java index 286cb38a0..343dc6d8e 100644 --- a/app/src/main/java/helium314/keyboard/latin/WordComposer.java +++ b/app/src/main/java/helium314/keyboard/latin/WordComposer.java @@ -12,6 +12,7 @@ import helium314.keyboard.event.Event; import helium314.keyboard.keyboard.Keyboard; import helium314.keyboard.keyboard.KeyboardSwitcher; +import helium314.keyboard.keyboard.internal.keyboard_parser.floris.KeyCode; import helium314.keyboard.latin.SuggestedWords.SuggestedWordInfo; import helium314.keyboard.latin.common.ComposedData; import helium314.keyboard.latin.common.Constants; @@ -176,7 +177,7 @@ public void applyProcessedEvent(final Event event) { applyProcessedEvent(event, false); } - // specifically for that Constants.CODE_OUTPUT_TEXT Hangul event: try keeping cursor position + // specifically for that KeyCode.MULTIPLE_CODE_POINTS Hangul event: try keeping cursor position // because typically nothing changes, todo: if really nothing changes maybe there is a better way to do it public void applyProcessedEvent(final Event event, final boolean keepCursorPosition) { mCombinerChain.applyProcessedEvent(event); @@ -191,7 +192,7 @@ public void applyProcessedEvent(final Event event, final boolean keepCursorPosit if (0 == mCodePointSize) { mIsOnlyFirstCharCapitalized = false; } - if (Constants.CODE_DELETE != event.getMKeyCode()) { + if (KeyCode.DELETE != event.getMKeyCode()) { if (newIndex < MAX_WORD_LENGTH) { // In the batch input mode, the {@code mInputPointers} holds batch input points and // shouldn't be overridden by the "typed key" coordinates diff --git a/app/src/main/java/helium314/keyboard/latin/common/Constants.java b/app/src/main/java/helium314/keyboard/latin/common/Constants.java index b8a619c56..e697cd0b2 100644 --- a/app/src/main/java/helium314/keyboard/latin/common/Constants.java +++ b/app/src/main/java/helium314/keyboard/latin/common/Constants.java @@ -8,6 +8,7 @@ import androidx.annotation.NonNull; +import helium314.keyboard.keyboard.internal.keyboard_parser.floris.KeyCode; import helium314.keyboard.latin.BuildConfig; public final class Constants { @@ -191,48 +192,6 @@ public static boolean isValidCoordinate(final int coordinate) { public static final String REGEXP_PERIOD = "\\."; public static final String STRING_SPACE = " "; - /** - * Special keys code. Must be negative. - * These should be aligned with constants in - * {@link helium314.keyboard.keyboard.internal.KeyboardCodesSet}. - */ - // todo: switch to using KeyCode for internal values? for FlorisBoard modifier key(code) compatibility - public static final int CODE_SHIFT = -1; - public static final int CODE_CAPSLOCK = -2; - public static final int CODE_SWITCH_ALPHA_SYMBOL = -3; - public static final int CODE_OUTPUT_TEXT = -4; - public static final int CODE_DELETE = -5; - public static final int CODE_SETTINGS = -6; - public static final int CODE_SHORTCUT = -7; - public static final int CODE_ACTION_NEXT = -8; - public static final int CODE_ACTION_PREVIOUS = -9; - public static final int CODE_LANGUAGE_SWITCH = -10; - public static final int CODE_EMOJI = -11; - public static final int CODE_CLIPBOARD = -12; - public static final int CODE_SHIFT_ENTER = -13; - public static final int CODE_SYMBOL_SHIFT = -14; - public static final int CODE_START_ONE_HANDED_MODE = -17; - public static final int CODE_STOP_ONE_HANDED_MODE = -18; - public static final int CODE_SWITCH_ONE_HANDED_MODE = -19; - public static final int CODE_SWITCH_NUMPAD = -20; - public static final int CODE_SWITCH_ALPHA = -21; - public static final int CODE_SWITCH_SYMBOL = -22; - public static final int CODE_SELECT_ALL = -23; - public static final int CODE_COPY = -24; - public static final int CODE_LEFT = -25; - public static final int CODE_RIGHT = -26; - public static final int CODE_UP = -27; - public static final int CODE_DOWN = -28; - public static final int CODE_UNDO = -29; - public static final int CODE_REDO = -30; - public static final int CODE_TOGGLE_AUTOCORRECT = -31; - public static final int CODE_TOGGLE_INCOGNITO = -32; - public static final int CODE_HOME = -33; - public static final int CODE_END = -34; - public static final int CODE_SELECT_WORD = -35; - // Code value representing the code is not specified. - public static final int CODE_UNSPECIFIED = -200; - public static boolean isLetterCode(final int code) { return code >= CODE_SPACE; } @@ -240,29 +199,29 @@ public static boolean isLetterCode(final int code) { @NonNull public static String printableCode(final int code) { switch (code) { - case CODE_SHIFT: return "shift"; - case CODE_CAPSLOCK: return "capslock"; - case CODE_SWITCH_ALPHA_SYMBOL: return "alpha_symbol"; - case CODE_SWITCH_ALPHA: return "alpha"; - case CODE_SWITCH_SYMBOL: return "symbol"; - case CODE_OUTPUT_TEXT: return "text"; - case CODE_DELETE: return "delete"; - case CODE_SETTINGS: return "settings"; - case CODE_SHORTCUT: return "shortcut"; - case CODE_ACTION_NEXT: return "actionNext"; - case CODE_ACTION_PREVIOUS: return "actionPrevious"; - case CODE_LANGUAGE_SWITCH: return "languageSwitch"; - case CODE_EMOJI: return "emoji"; - case CODE_CLIPBOARD: return "clipboard"; - case CODE_SHIFT_ENTER: return "shiftEnter"; - case CODE_UNSPECIFIED: return "unspec"; + case KeyCode.SHIFT: return "shift"; + case KeyCode.CAPS_LOCK: return "capslock"; + case KeyCode.ALPHA_SYMBOL: return "alpha_symbol"; + case KeyCode.ALPHA: return "alpha"; + case KeyCode.SYMBOL: return "symbol"; + case KeyCode.MULTIPLE_CODE_POINTS: return "text"; + case KeyCode.DELETE: return "delete"; + case KeyCode.SETTINGS: return "settings"; + case KeyCode.VOICE_INPUT: return "shortcut"; + case KeyCode.ACTION_NEXT: return "actionNext"; + case KeyCode.ACTION_PREVIOUS: return "actionPrevious"; + case KeyCode.LANGUAGE_SWITCH: return "languageSwitch"; + case KeyCode.EMOJI: return "emoji"; + case KeyCode.CLIPBOARD: return "clipboard"; + case KeyCode.SHIFT_ENTER: return "shiftEnter"; + case KeyCode.NOT_SPECIFIED: return "unspec"; case CODE_TAB: return "tab"; case CODE_ENTER: return "enter"; case CODE_SPACE: return "space"; - case CODE_START_ONE_HANDED_MODE: return "startOneHandedMode"; - case CODE_STOP_ONE_HANDED_MODE: return "stopOneHandedMode"; - case CODE_SWITCH_ONE_HANDED_MODE: return "switchOneHandedMode"; - case CODE_SWITCH_NUMPAD: return "numpad"; + case KeyCode.START_ONE_HANDED_MODE: return "startOneHandedMode"; + case KeyCode.STOP_ONE_HANDED_MODE: return "stopOneHandedMode"; + case KeyCode.SWITCH_ONE_HANDED_MODE: return "switchOneHandedMode"; + case KeyCode.NUMPAD: return "numpad"; default: if (code < CODE_SPACE) return String.format("\\u%02X", code); if (code < 0x100) return String.format("%c", code); diff --git a/app/src/main/java/helium314/keyboard/latin/common/StringUtils.java b/app/src/main/java/helium314/keyboard/latin/common/StringUtils.java index 87bfa9039..36da83ac2 100644 --- a/app/src/main/java/helium314/keyboard/latin/common/StringUtils.java +++ b/app/src/main/java/helium314/keyboard/latin/common/StringUtils.java @@ -9,6 +9,7 @@ import androidx.annotation.NonNull; import androidx.annotation.Nullable; +import helium314.keyboard.keyboard.internal.keyboard_parser.floris.KeyCode; import helium314.keyboard.latin.utils.ScriptUtils; import java.util.ArrayList; @@ -586,7 +587,7 @@ public static int toTitleCaseOfKeyCode(final int code, @NonNull final Locale loc final String label = newSingleCodePointString(code); final String titleCaseLabel = toTitleCaseOfKeyLabel(label, locale); return codePointCount(titleCaseLabel) == 1 - ? titleCaseLabel.codePointAt(0) : Constants.CODE_UNSPECIFIED; + ? titleCaseLabel.codePointAt(0) : KeyCode.NOT_SPECIFIED; } public static int getTrailingSingleQuotesCount(@NonNull final CharSequence charSequence) { diff --git a/app/src/main/java/helium314/keyboard/latin/inputlogic/InputLogic.java b/app/src/main/java/helium314/keyboard/latin/inputlogic/InputLogic.java index 42c843664..c45174ba2 100644 --- a/app/src/main/java/helium314/keyboard/latin/inputlogic/InputLogic.java +++ b/app/src/main/java/helium314/keyboard/latin/inputlogic/InputLogic.java @@ -25,6 +25,7 @@ import helium314.keyboard.event.InputTransaction; import helium314.keyboard.keyboard.Keyboard; import helium314.keyboard.keyboard.KeyboardSwitcher; +import helium314.keyboard.keyboard.internal.keyboard_parser.floris.KeyCode; import helium314.keyboard.latin.Dictionary; import helium314.keyboard.latin.DictionaryFacilitator; import helium314.keyboard.latin.LastComposedWord; @@ -450,7 +451,7 @@ public InputTransaction onCodeInput(final SettingsValues settingsValues, final InputTransaction inputTransaction = new InputTransaction(settingsValues, processedEvent, SystemClock.uptimeMillis(), mSpaceState, getActualCapsMode(settingsValues, keyboardShiftMode)); - if (processedEvent.getMKeyCode() != Constants.CODE_DELETE + if (processedEvent.getMKeyCode() != KeyCode.DELETE || inputTransaction.getMTimestamp() > mLastKeyTime + Constants.LONG_PRESS_MILLISECONDS) { mDeleteCount = 0; } @@ -482,17 +483,17 @@ public InputTransaction onCodeInput(final SettingsValues settingsValues, // the backspace key. if (!mConnection.hasSlowInputConnection() && !mWordComposer.isComposingWord() && (settingsValues.isWordCodePoint(processedEvent.getMCodePoint()) - || processedEvent.getMKeyCode() == Constants.CODE_DELETE) + || processedEvent.getMKeyCode() == KeyCode.DELETE) ) { mWordBeingCorrectedByCursor = getWordAtCursor(settingsValues, currentKeyboardScript); } - if (!inputTransaction.didAutoCorrect() && processedEvent.getMKeyCode() != Constants.CODE_SHIFT - && processedEvent.getMKeyCode() != Constants.CODE_CAPSLOCK - && processedEvent.getMKeyCode() != Constants.CODE_SWITCH_ALPHA_SYMBOL - && processedEvent.getMKeyCode() != Constants.CODE_SWITCH_ALPHA - && processedEvent.getMKeyCode() != Constants.CODE_SWITCH_SYMBOL) + if (!inputTransaction.didAutoCorrect() && processedEvent.getMKeyCode() != KeyCode.SHIFT + && processedEvent.getMKeyCode() != KeyCode.CAPS_LOCK + && processedEvent.getMKeyCode() != KeyCode.ALPHA_SYMBOL + && processedEvent.getMKeyCode() != KeyCode.ALPHA + && processedEvent.getMKeyCode() != KeyCode.SYMBOL) mLastComposedWord.deactivate(); - if (Constants.CODE_DELETE != processedEvent.getMKeyCode()) { + if (KeyCode.DELETE != processedEvent.getMKeyCode()) { mEnteredText = null; } mConnection.endBatchEdit(); @@ -649,12 +650,12 @@ private void handleConsumedEvent(final Event event, final InputTransaction input private void handleFunctionalEvent(final Event event, final InputTransaction inputTransaction, final String currentKeyboardScript, final LatinIME.UIHandler handler) { switch (event.getMKeyCode()) { - case Constants.CODE_DELETE: + case KeyCode.DELETE: handleBackspaceEvent(event, inputTransaction, currentKeyboardScript); // Backspace is a functional key, but it affects the contents of the editor. inputTransaction.setDidAffectContents(); break; - case Constants.CODE_SHIFT: + case KeyCode.SHIFT: performRecapitalization(inputTransaction.getMSettingsValues()); inputTransaction.requireShiftUpdate(InputTransaction.SHIFT_UPDATE_NOW); if (mSuggestedWords.isPrediction()) { @@ -666,19 +667,19 @@ private void handleFunctionalEvent(final Event event, final InputTransaction inp && inputTransaction.getMSettingsValues().isUsuallyFollowedBySpace(mConnection.getCodePointBeforeCursor())) mSpaceState = SpaceState.NONE; break; - case Constants.CODE_SETTINGS: + case KeyCode.SETTINGS: onSettingsKeyPressed(); break; - case Constants.CODE_ACTION_NEXT: + case KeyCode.ACTION_NEXT: performEditorAction(EditorInfo.IME_ACTION_NEXT); break; - case Constants.CODE_ACTION_PREVIOUS: + case KeyCode.ACTION_PREVIOUS: performEditorAction(EditorInfo.IME_ACTION_PREVIOUS); break; - case Constants.CODE_LANGUAGE_SWITCH: + case KeyCode.LANGUAGE_SWITCH: handleLanguageSwitchKey(); break; - case Constants.CODE_CLIPBOARD: + case KeyCode.CLIPBOARD: // Note: If clipboard history is enabled, switching to clipboard keyboard // is being handled in {@link KeyboardState#onEvent(Event,int)}. // If disabled, current clipboard content is committed. @@ -691,7 +692,7 @@ private void handleFunctionalEvent(final Event event, final InputTransaction inp } } break; - case Constants.CODE_SHIFT_ENTER: + case KeyCode.SHIFT_ENTER: final Event tmpEvent = Event.createSoftwareKeypressEvent(Constants.CODE_ENTER, event.getMKeyCode(), event.getMX(), event.getMY(), event.isKeyRepeat()); handleNonSpecialCharacterEvent(tmpEvent, inputTransaction, handler); @@ -699,60 +700,60 @@ private void handleFunctionalEvent(final Event event, final InputTransaction inp // line, so that does affect the contents of the editor. inputTransaction.setDidAffectContents(); break; - case Constants.CODE_OUTPUT_TEXT: + case KeyCode.MULTIPLE_CODE_POINTS: // added in the hangul branch, createEventChainFromSequence // this introduces issues like space being added behind cursor, or input deleting // a word, but the keepCursorPosition applyProcessedEvent seems to help here mWordComposer.applyProcessedEvent(event, true); break; - case Constants.CODE_SELECT_ALL: + case KeyCode.CLIPBOARD_SELECT_ALL: mConnection.selectAll(); break; - case Constants.CODE_SELECT_WORD: + case KeyCode.CLIPBOARD_SELECT_WORD: mConnection.selectWord(inputTransaction.getMSettingsValues().mSpacingAndPunctuations, currentKeyboardScript); break; - case Constants.CODE_COPY: + case KeyCode.CLIPBOARD_COPY: mConnection.copyText(); break; - case Constants.CODE_LEFT: + case KeyCode.ARROW_LEFT: sendDownUpKeyEvent(KeyEvent.KEYCODE_DPAD_LEFT); break; - case Constants.CODE_RIGHT: + case KeyCode.ARROW_RIGHT: sendDownUpKeyEvent(KeyEvent.KEYCODE_DPAD_RIGHT); break; - case Constants.CODE_UP: + case KeyCode.ARROW_UP: sendDownUpKeyEvent(KeyEvent.KEYCODE_DPAD_UP); break; - case Constants.CODE_DOWN: + case KeyCode.ARROW_DOWN: sendDownUpKeyEvent(KeyEvent.KEYCODE_DPAD_DOWN); break; - case Constants.CODE_UNDO: + case KeyCode.UNDO: sendDownUpKeyEventWithMetaState(KeyEvent.KEYCODE_Z, KeyEvent.META_CTRL_ON); break; - case Constants.CODE_REDO: + case KeyCode.REDO: sendDownUpKeyEventWithMetaState(KeyEvent.KEYCODE_Z, KeyEvent.META_CTRL_ON | KeyEvent.META_SHIFT_ON); break; - case Constants.CODE_HOME: + case KeyCode.MOVE_START_OF_LINE: sendDownUpKeyEvent(KeyEvent.KEYCODE_MOVE_HOME); break; - case Constants.CODE_END: + case KeyCode.MOVE_END_OF_LINE: sendDownUpKeyEvent(KeyEvent.KEYCODE_MOVE_END); break; - case Constants.CODE_SHORTCUT: + case KeyCode.VOICE_INPUT: // switching to shortcut IME, shift state, keyboard,... is handled by LatinIME, // {@link KeyboardSwitcher#onEvent(Event)}, or {@link #onPressKey(int,int,boolean)} and {@link #onReleaseKey(int,boolean)}. // We need to switch to the shortcut IME. This is handled by LatinIME since the // input logic has no business with IME switching. - case Constants.CODE_CAPSLOCK: - case Constants.CODE_SYMBOL_SHIFT: - case Constants.CODE_SWITCH_ALPHA_SYMBOL: - case Constants.CODE_SWITCH_ALPHA: - case Constants.CODE_SWITCH_SYMBOL: - case Constants.CODE_SWITCH_NUMPAD: - case Constants.CODE_EMOJI: - case Constants.CODE_START_ONE_HANDED_MODE: - case Constants.CODE_STOP_ONE_HANDED_MODE: - case Constants.CODE_SWITCH_ONE_HANDED_MODE: + case KeyCode.CAPS_LOCK: + case KeyCode.SYMBOL_SHIFT: + case KeyCode.ALPHA_SYMBOL: + case KeyCode.ALPHA: + case KeyCode.SYMBOL: + case KeyCode.NUMPAD: + case KeyCode.EMOJI: + case KeyCode.START_ONE_HANDED_MODE: + case KeyCode.STOP_ONE_HANDED_MODE: + case KeyCode.SWITCH_ONE_HANDED_MODE: break; default: throw new RuntimeException("Unknown key code : " + event.getMKeyCode()); diff --git a/app/src/main/java/helium314/keyboard/latin/suggestions/MoreSuggestions.java b/app/src/main/java/helium314/keyboard/latin/suggestions/MoreSuggestions.java index ec7d5ba9a..b5ea28357 100644 --- a/app/src/main/java/helium314/keyboard/latin/suggestions/MoreSuggestions.java +++ b/app/src/main/java/helium314/keyboard/latin/suggestions/MoreSuggestions.java @@ -16,6 +16,7 @@ import helium314.keyboard.keyboard.internal.KeyboardBuilder; import helium314.keyboard.keyboard.internal.KeyboardIconsSet; import helium314.keyboard.keyboard.internal.KeyboardParams; +import helium314.keyboard.keyboard.internal.keyboard_parser.floris.KeyCode; import helium314.keyboard.latin.R; import helium314.keyboard.latin.SuggestedWords; import helium314.keyboard.latin.common.Constants; @@ -230,7 +231,7 @@ static final class MoreSuggestionKey extends Key { public MoreSuggestionKey(final String word, final String info, final int index, final MoreSuggestionsParam params) { - super(word /* label */, KeyboardIconsSet.ICON_UNDEFINED, Constants.CODE_OUTPUT_TEXT, + super(word /* label */, KeyboardIconsSet.ICON_UNDEFINED, KeyCode.MULTIPLE_CODE_POINTS, word /* outputText */, info, 0 /* labelFlags */, Key.BACKGROUND_TYPE_NORMAL, params.getX(index), params.getY(index), params.getWidth(index), params.mDefaultRowHeight, params.mHorizontalGap, params.mVerticalGap); diff --git a/app/src/main/java/helium314/keyboard/latin/suggestions/SuggestionStripView.java b/app/src/main/java/helium314/keyboard/latin/suggestions/SuggestionStripView.java index eb908a444..33ba1d8a2 100644 --- a/app/src/main/java/helium314/keyboard/latin/suggestions/SuggestionStripView.java +++ b/app/src/main/java/helium314/keyboard/latin/suggestions/SuggestionStripView.java @@ -45,6 +45,7 @@ import helium314.keyboard.keyboard.Keyboard; import helium314.keyboard.keyboard.MainKeyboardView; import helium314.keyboard.keyboard.PopupKeysPanel; +import helium314.keyboard.keyboard.internal.keyboard_parser.floris.KeyCode; import helium314.keyboard.latin.AudioAndHapticFeedbackManager; import helium314.keyboard.latin.Dictionary; import helium314.keyboard.latin.R; @@ -645,7 +646,7 @@ public boolean onTouchEvent(final MotionEvent me) { @Override public void onClick(final View view) { - AudioAndHapticFeedbackManager.getInstance().performHapticAndAudioFeedback(Constants.CODE_UNSPECIFIED, this); + AudioAndHapticFeedbackManager.getInstance().performHapticAndAudioFeedback(KeyCode.NOT_SPECIFIED, this); final Object tag = view.getTag(); if (tag instanceof ToolbarKey) { final Integer code = getCodeForToolbarKey((ToolbarKey) tag); diff --git a/app/src/main/java/helium314/keyboard/latin/utils/ToolbarUtils.kt b/app/src/main/java/helium314/keyboard/latin/utils/ToolbarUtils.kt index c52386df7..b5b578f6a 100644 --- a/app/src/main/java/helium314/keyboard/latin/utils/ToolbarUtils.kt +++ b/app/src/main/java/helium314/keyboard/latin/utils/ToolbarUtils.kt @@ -7,8 +7,8 @@ import android.content.res.TypedArray import android.widget.ImageButton import android.widget.ImageView import androidx.core.content.edit +import helium314.keyboard.keyboard.internal.keyboard_parser.floris.KeyCode import helium314.keyboard.latin.R -import helium314.keyboard.latin.common.Constants.* import helium314.keyboard.latin.settings.Settings import helium314.keyboard.latin.utils.ToolbarKey.* @@ -35,23 +35,23 @@ fun createToolbarKey(context: Context, keyboardAttr: TypedArray, key: ToolbarKey } fun getCodeForToolbarKey(key: ToolbarKey) = when (key) { - VOICE -> CODE_SHORTCUT - SETTINGS -> CODE_SETTINGS - CLIPBOARD -> CODE_CLIPBOARD - SELECT_ALL -> CODE_SELECT_ALL - COPY -> CODE_COPY - ONE_HANDED -> if (Settings.getInstance().current.mOneHandedModeEnabled) CODE_STOP_ONE_HANDED_MODE else CODE_START_ONE_HANDED_MODE - LEFT -> CODE_LEFT - RIGHT -> CODE_RIGHT - UP -> CODE_UP - DOWN -> CODE_DOWN - UNDO -> CODE_UNDO - REDO -> CODE_REDO - INCOGNITO -> CODE_TOGGLE_INCOGNITO - AUTOCORRECT -> CODE_TOGGLE_AUTOCORRECT - FULL_LEFT -> CODE_HOME - FULL_RIGHT -> CODE_END - SELECT_WORD -> CODE_SELECT_WORD + VOICE -> KeyCode.VOICE_INPUT + SETTINGS -> KeyCode.SETTINGS + CLIPBOARD -> KeyCode.CLIPBOARD + SELECT_ALL -> KeyCode.CLIPBOARD_SELECT_ALL + COPY -> KeyCode.CLIPBOARD_COPY + ONE_HANDED -> if (Settings.getInstance().current.mOneHandedModeEnabled) KeyCode.STOP_ONE_HANDED_MODE else KeyCode.START_ONE_HANDED_MODE + LEFT -> KeyCode.ARROW_LEFT + RIGHT -> KeyCode.ARROW_RIGHT + UP -> KeyCode.ARROW_UP + DOWN -> KeyCode.ARROW_DOWN + UNDO -> KeyCode.UNDO + REDO -> KeyCode.REDO + INCOGNITO -> KeyCode.TOGGLE_INCOGNITO_MODE + AUTOCORRECT -> KeyCode.TOGGLE_AUTOCORRECT + FULL_LEFT -> KeyCode.MOVE_START_OF_LINE + FULL_RIGHT -> KeyCode.MOVE_END_OF_LINE + SELECT_WORD -> KeyCode.CLIPBOARD_SELECT_WORD CLEAR_CLIPBOARD -> null // not managed via code input } diff --git a/app/src/test/java/helium314/keyboard/KeySpecParserTest.kt b/app/src/test/java/helium314/keyboard/KeySpecParserTest.kt index 807c9b6b9..1c0fc1ba1 100644 --- a/app/src/test/java/helium314/keyboard/KeySpecParserTest.kt +++ b/app/src/test/java/helium314/keyboard/KeySpecParserTest.kt @@ -1,6 +1,7 @@ package helium314.keyboard import helium314.keyboard.keyboard.internal.KeySpecParser +import helium314.keyboard.keyboard.internal.keyboard_parser.floris.KeyCode import helium314.keyboard.latin.common.Constants import org.junit.Assert.assertEquals import org.junit.Test @@ -19,9 +20,9 @@ class KeySpecParserTest { @Test fun code() { assertEquals('a'.code, KeySpecParser.getCode("a")) assertEquals('b'.code, KeySpecParser.getCode("a|b")) - assertEquals(Constants.CODE_OUTPUT_TEXT, KeySpecParser.getCode("hey|there")) + assertEquals(KeyCode.MULTIPLE_CODE_POINTS, KeySpecParser.getCode("hey|there")) assertEquals('c'.code, KeySpecParser.getCode("a|b|c")) - assertEquals(Constants.CODE_OUTPUT_TEXT, KeySpecParser.getCode("a\\|b")) + assertEquals(KeyCode.MULTIPLE_CODE_POINTS, KeySpecParser.getCode("a\\|b")) assertEquals('c'.code, KeySpecParser.getCode("a\\|b|c")) assertEquals('d'.code, KeySpecParser.getCode("a\\|b|c|d")) } diff --git a/app/src/test/java/helium314/keyboard/latin/InputLogicTest.kt b/app/src/test/java/helium314/keyboard/latin/InputLogicTest.kt index b1e84da9f..c3b145f69 100644 --- a/app/src/test/java/helium314/keyboard/latin/InputLogicTest.kt +++ b/app/src/test/java/helium314/keyboard/latin/InputLogicTest.kt @@ -14,6 +14,7 @@ import helium314.keyboard.ShadowLocaleManagerCompat import helium314.keyboard.event.Event import helium314.keyboard.keyboard.KeyboardSwitcher import helium314.keyboard.keyboard.MainKeyboardView +import helium314.keyboard.keyboard.internal.keyboard_parser.floris.KeyCode import helium314.keyboard.latin.ShadowFacilitator2.Companion.lastAddedWord import helium314.keyboard.latin.SuggestedWords.SuggestedWordInfo import helium314.keyboard.latin.common.Constants @@ -81,7 +82,7 @@ class InputLogicTest { @Test fun delete() { reset() setText("hello there ") - functionalKeyPress(Constants.CODE_DELETE) + functionalKeyPress(KeyCode.DELETE) assertEquals("hello there", text) assertEquals("there", composingText) } @@ -90,7 +91,7 @@ class InputLogicTest { reset() setText("hello you there") setCursorPosition(8) // after o in you - functionalKeyPress(Constants.CODE_DELETE) + functionalKeyPress(KeyCode.DELETE) assertEquals("hello yu there", text) // todo: do we really want an empty composing text in this case? // setting whole word composing will delete text behind cursor @@ -245,7 +246,7 @@ class InputLogicTest { DeviceProtectedUtils.getSharedPreferences(latinIME).edit { putBoolean(Settings.PREF_AUTOSPACE_AFTER_PUNCTUATION, true) } input("bla") input('.') - functionalKeyPress(Constants.CODE_SHIFT) // should remove the phantom space (in addition to normal effect) + functionalKeyPress(KeyCode.SHIFT) // should remove the phantom space (in addition to normal effect) input('c') assertEquals("bla.c", text) assertEquals("bla.c", composingText) @@ -326,9 +327,9 @@ class InputLogicTest { setInputType(InputType.TYPE_CLASS_TEXT or InputType.TYPE_TEXT_VARIATION_URI) setText("http://example.com/here") setCursorPosition(18) // after .com - functionalKeyPress(Constants.CODE_DELETE) - functionalKeyPress(Constants.CODE_DELETE) - functionalKeyPress(Constants.CODE_DELETE) // delete com + functionalKeyPress(KeyCode.DELETE) + functionalKeyPress(KeyCode.DELETE) + functionalKeyPress(KeyCode.DELETE) // delete com // todo: do we really want no composing text? // probably not... try not to break composing assertEquals("", composingText) @@ -341,8 +342,8 @@ class InputLogicTest { DeviceProtectedUtils.getSharedPreferences(latinIME).edit { putBoolean(Settings.PREF_URL_DETECTION, true) } setText("http://example.com/here") setCursorPosition(18) // after .com - functionalKeyPress(Constants.CODE_DELETE) - functionalKeyPress(Constants.CODE_DELETE) // delete om + functionalKeyPress(KeyCode.DELETE) + functionalKeyPress(KeyCode.DELETE) // delete om // todo: this is a weird difference to deleting the full TLD (see urlProperlySelected) // what do we want here? (probably consistency) assertEquals("example.c/here", composingText) From fe5aa2c33c432e5612b263e40471707364ac38d4 Mon Sep 17 00:00:00 2001 From: Helium314 Date: Sat, 2 Mar 2024 21:07:27 +0100 Subject: [PATCH 24/40] remove unused SYMBOL_SHIFT key --- .../internal/keyboard_parser/floris/KeyCode.kt | 5 ++--- .../java/helium314/keyboard/latin/LatinIME.java | 15 +-------------- .../keyboard/latin/inputlogic/InputLogic.java | 1 - 3 files changed, 3 insertions(+), 18 deletions(-) diff --git a/app/src/main/java/helium314/keyboard/keyboard/internal/keyboard_parser/floris/KeyCode.kt b/app/src/main/java/helium314/keyboard/keyboard/internal/keyboard_parser/floris/KeyCode.kt index a56a8a8ff..f85290a3a 100644 --- a/app/src/main/java/helium314/keyboard/keyboard/internal/keyboard_parser/floris/KeyCode.kt +++ b/app/src/main/java/helium314/keyboard/keyboard/internal/keyboard_parser/floris/KeyCode.kt @@ -127,9 +127,8 @@ object KeyCode { const val SHIFT_ENTER = -10005 const val ACTION_NEXT = -10006 const val ACTION_PREVIOUS = -10007 - const val SYMBOL_SHIFT = -10008 // todo: check, maybe can be removed // Code value representing the code is not specified. - const val NOT_SPECIFIED = -10009 // todo: not sure if there is need to have the "old" unspecified keyCode different, just test it and maybe merge + const val NOT_SPECIFIED = -10008 // todo: not sure if there is need to have the "old" unspecified keyCode different, just test it and maybe merge /** to make sure a FlorisBoard code works when reading a JSON layout */ private fun Int.checkOrConvertCode(): Int = when (this) { @@ -144,7 +143,7 @@ object KeyCode { // heliboard only ALPHA_SYMBOL, START_ONE_HANDED_MODE, STOP_ONE_HANDED_MODE, SWITCH_ONE_HANDED_MODE, SHIFT_ENTER, - ACTION_NEXT, ACTION_PREVIOUS, SYMBOL_SHIFT, NOT_SPECIFIED + ACTION_NEXT, ACTION_PREVIOUS, NOT_SPECIFIED -> this // conversion diff --git a/app/src/main/java/helium314/keyboard/latin/LatinIME.java b/app/src/main/java/helium314/keyboard/latin/LatinIME.java index bb20ad997..844f48049 100644 --- a/app/src/main/java/helium314/keyboard/latin/LatinIME.java +++ b/app/src/main/java/helium314/keyboard/latin/LatinIME.java @@ -1525,19 +1525,6 @@ public void switchInputMethodAndSubtype(final InputMethodInfo imi, final InputMe } } - // TODO: Instead of checking for alphabetic keyboard here, separate keycodes for - // alphabetic shift and shift while in symbol layout and get rid of this method. - private int getCodePointForKeyboard(final int codePoint) { - if (KeyCode.SHIFT == codePoint) { - final Keyboard currentKeyboard = mKeyboardSwitcher.getKeyboard(); - if (null != currentKeyboard && currentKeyboard.mId.isAlphabetKeyboard()) { - return codePoint; - } - return KeyCode.SYMBOL_SHIFT; - } - return codePoint; - } - // Implementation of {@link KeyboardActionListener}. @Override public void onCodeInput(final int codePoint, final int x, final int y, final boolean isKeyRepeat) { @@ -1556,7 +1543,7 @@ public void onCodeInput(final int codePoint, final int x, final int y, final boo // this transformation, it should be done already before calling onEvent. final int keyX = mainKeyboardView.getKeyX(x); final int keyY = mainKeyboardView.getKeyY(y); - final Event event = createSoftwareKeypressEvent(getCodePointForKeyboard(codePoint), keyX, keyY, isKeyRepeat); + final Event event = createSoftwareKeypressEvent(codePoint, keyX, keyY, isKeyRepeat); onEvent(event); } diff --git a/app/src/main/java/helium314/keyboard/latin/inputlogic/InputLogic.java b/app/src/main/java/helium314/keyboard/latin/inputlogic/InputLogic.java index c45174ba2..6d5147222 100644 --- a/app/src/main/java/helium314/keyboard/latin/inputlogic/InputLogic.java +++ b/app/src/main/java/helium314/keyboard/latin/inputlogic/InputLogic.java @@ -745,7 +745,6 @@ private void handleFunctionalEvent(final Event event, final InputTransaction inp // We need to switch to the shortcut IME. This is handled by LatinIME since the // input logic has no business with IME switching. case KeyCode.CAPS_LOCK: - case KeyCode.SYMBOL_SHIFT: case KeyCode.ALPHA_SYMBOL: case KeyCode.ALPHA: case KeyCode.SYMBOL: From 4b52f2d51df847a2a4604ba6e47fd95f7759c5fc Mon Sep 17 00:00:00 2001 From: Helium314 Date: Sun, 3 Mar 2024 14:48:03 +0100 Subject: [PATCH 25/40] properly determine length of emojis when deleting fixes issue described in https://github.com/Helium314/HeliBoard/issues/426#issuecomment-1944132643, but not the initial problem --- .../keyboard/latin/RichInputConnection.java | 8 ++++ .../keyboard/latin/common/Constants.java | 2 + .../keyboard/latin/common/StringUtils.kt | 23 +++++++++++ .../keyboard/latin/inputlogic/InputLogic.java | 41 ++++++++----------- .../keyboard/latin/StringUtilsTest.kt | 14 +++++++ 5 files changed, 65 insertions(+), 23 deletions(-) diff --git a/app/src/main/java/helium314/keyboard/latin/RichInputConnection.java b/app/src/main/java/helium314/keyboard/latin/RichInputConnection.java index b863ef1ba..f4a58015b 100644 --- a/app/src/main/java/helium314/keyboard/latin/RichInputConnection.java +++ b/app/src/main/java/helium314/keyboard/latin/RichInputConnection.java @@ -1046,6 +1046,14 @@ public boolean spaceBeforeCursor() { return mCommittedTextBeforeComposingText.indexOf(" ") != -1; } + public int getCharCountToDeleteBeforeCursor() { + final int lastCodePoint = getCodePointBeforeCursor(); + if (!Character.isSupplementaryCodePoint(lastCodePoint)) return 1; + if (!StringUtils.mightBeEmoji(lastCodePoint)) return 2; + final String text = mCommittedTextBeforeComposingText.toString() + mComposingText; + return StringUtilsKt.getFullEmojiAtEnd(text).length(); + } + public boolean hasLetterBeforeLastSpaceBeforeCursor() { return StringUtilsKt.hasLetterBeforeLastSpaceBeforeCursor(mCommittedTextBeforeComposingText); } diff --git a/app/src/main/java/helium314/keyboard/latin/common/Constants.java b/app/src/main/java/helium314/keyboard/latin/common/Constants.java index e697cd0b2..e660745e1 100644 --- a/app/src/main/java/helium314/keyboard/latin/common/Constants.java +++ b/app/src/main/java/helium314/keyboard/latin/common/Constants.java @@ -191,6 +191,8 @@ public static boolean isValidCoordinate(final int coordinate) { public static final String REGEXP_PERIOD = "\\."; public static final String STRING_SPACE = " "; + public static final int CODE_ZWNJ = '\u200C'; + public static final int CODE_ZWJ = '\u200D'; public static boolean isLetterCode(final int code) { return code >= CODE_SPACE; diff --git a/app/src/main/java/helium314/keyboard/latin/common/StringUtils.kt b/app/src/main/java/helium314/keyboard/latin/common/StringUtils.kt index b5131d5fe..c017afa13 100644 --- a/app/src/main/java/helium314/keyboard/latin/common/StringUtils.kt +++ b/app/src/main/java/helium314/keyboard/latin/common/StringUtils.kt @@ -53,6 +53,29 @@ fun hasLetterBeforeLastSpaceBeforeCursor(s: CharSequence): Boolean { return letter } +/** get the complete emoji at end of [s], considering that emojis can be joined with ZWJ resulting in different emojis */ +fun getFullEmojiAtEnd(s: CharSequence): String { + val text = if (s is String) s else s.toString() + var offset = text.length + while (offset > 0) { + val codepoint = text.codePointBefore(offset) + // stop if codepoint can't be emoji + if (!mightBeEmoji(codepoint)) return "" + offset -= Character.charCount(codepoint) + if (offset > 0 && text[offset - 1].code == Constants.CODE_ZWJ) { + // continue if ZWJ + offset -= 1 + continue + } + // check the whole text after offset + val textToCheck = text.substring(offset) + if (isEmoji(textToCheck)) { + return textToCheck + } + } + return "" +} + /** split the string on the first of consecutive space only, further consecutive spaces are added to the next split */ fun String.splitOnFirstSpacesOnly(): List { val out = mutableListOf() diff --git a/app/src/main/java/helium314/keyboard/latin/inputlogic/InputLogic.java b/app/src/main/java/helium314/keyboard/latin/inputlogic/InputLogic.java index 6d5147222..b15ab9afb 100644 --- a/app/src/main/java/helium314/keyboard/latin/inputlogic/InputLogic.java +++ b/app/src/main/java/helium314/keyboard/latin/inputlogic/InputLogic.java @@ -1253,31 +1253,26 @@ private void handleBackspaceEvent(final Event event, final InputTransaction inpu // TODO: Add a new StatsUtils method onBackspaceWhenNoText() return; } - if (StringUtils.mightBeEmoji(codePointBeforeCursor)) { - // emoji length varies, so we'd need to find out length to delete correctly - // the solution is not optimal, but a reasonable workaround for issues when trying to delete emojis - sendDownUpKeyEvent(KeyEvent.KEYCODE_DEL); - } else { - final int lengthToDelete = Character.isSupplementaryCodePoint(codePointBeforeCursor) ? 2 : 1; - mConnection.deleteTextBeforeCursor(lengthToDelete); - int totalDeletedLength = lengthToDelete; - if (mDeleteCount > Constants.DELETE_ACCELERATE_AT) { - // If this is an accelerated (i.e., double) deletion, then we need to - // consider unlearning here because we may have already reached - // the previous word, and will lose it after next deletion. - hasUnlearnedWordBeingDeleted |= unlearnWordBeingDeleted( - inputTransaction.getMSettingsValues(), currentKeyboardScript); - final int codePointBeforeCursorToDeleteAgain = - mConnection.getCodePointBeforeCursor(); - if (codePointBeforeCursorToDeleteAgain != Constants.NOT_A_CODE) { - final int lengthToDeleteAgain = Character.isSupplementaryCodePoint( - codePointBeforeCursorToDeleteAgain) ? 2 : 1; - mConnection.deleteTextBeforeCursor(lengthToDeleteAgain); - totalDeletedLength += lengthToDeleteAgain; - } + final int lengthToDelete = Character.isSupplementaryCodePoint(codePointBeforeCursor) + ? mConnection.getCharCountToDeleteBeforeCursor() : 1; + mConnection.deleteTextBeforeCursor(lengthToDelete); + int totalDeletedLength = lengthToDelete; + if (mDeleteCount > Constants.DELETE_ACCELERATE_AT) { + // If this is an accelerated (i.e., double) deletion, then we need to + // consider unlearning here because we may have already reached + // the previous word, and will lose it after next deletion. + hasUnlearnedWordBeingDeleted |= unlearnWordBeingDeleted( + inputTransaction.getMSettingsValues(), currentKeyboardScript); + final int codePointBeforeCursorToDeleteAgain = + mConnection.getCodePointBeforeCursor(); + if (codePointBeforeCursorToDeleteAgain != Constants.NOT_A_CODE) { + final int lengthToDeleteAgain = Character.isSupplementaryCodePoint(codePointBeforeCursorToDeleteAgain) + ? mConnection.getCharCountToDeleteBeforeCursor() : 1; + mConnection.deleteTextBeforeCursor(lengthToDeleteAgain); + totalDeletedLength += lengthToDeleteAgain; } - StatsUtils.onBackspacePressed(totalDeletedLength); } + StatsUtils.onBackspacePressed(totalDeletedLength); } } if (!hasUnlearnedWordBeingDeleted) { diff --git a/app/src/test/java/helium314/keyboard/latin/StringUtilsTest.kt b/app/src/test/java/helium314/keyboard/latin/StringUtilsTest.kt index 20e7fe2ed..cb5f0d9b9 100644 --- a/app/src/test/java/helium314/keyboard/latin/StringUtilsTest.kt +++ b/app/src/test/java/helium314/keyboard/latin/StringUtilsTest.kt @@ -2,6 +2,8 @@ package helium314.keyboard.latin import helium314.keyboard.latin.common.StringUtils +import helium314.keyboard.latin.common.getFullEmojiAtEnd +import org.junit.Assert.assertEquals import org.junit.Test // todo: actually this test could/should be significantly expanded... @@ -39,6 +41,18 @@ class StringUtilsTest { assert(StringUtils.isInsideDoubleQuoteOrAfterDigit("hello \"yes\", \"h")) } + @Test fun detectEmojisAtEnd() { + assertEquals("\uD83C\uDF83", getFullEmojiAtEnd("\uD83C\uDF83")) + assertEquals("ℹ️", getFullEmojiAtEnd("ℹ️")) + assertEquals("ℹ️", getFullEmojiAtEnd("ℹ️ℹ️")) + assertEquals("\uD83D\uDE22", getFullEmojiAtEnd("x\uD83D\uDE22")) + assertEquals("", getFullEmojiAtEnd("x\uD83D\uDE22 ")) + assertEquals("\uD83C\uDFF4\u200D☠️", getFullEmojiAtEnd("ok \uD83C\uDFF4\u200D☠️")) + assertEquals("\uD83C\uDFF3️\u200D\uD83C\uDF08", getFullEmojiAtEnd("\uD83C\uDFF3️\u200D\uD83C\uDF08")) + assertEquals("\uD83C\uDFF3️\u200D\uD83C\uDF08", getFullEmojiAtEnd("\uD83C\uDFF4\u200D☠️\uD83C\uDFF3️\u200D\uD83C\uDF08")) + assertEquals("\uD83C\uDFF3️\u200D⚧️", getFullEmojiAtEnd("hello there🏳️‍⚧️")) + } + // todo: add tests for emoji detection? // could help towards fully fixing https://github.com/Helium314/HeliBoard/issues/22 // though this might be tricky, as some emojis will show as one on new Android versions, and From b263b96b96a749b8a09773a4cf275f0cd55d3cae Mon Sep 17 00:00:00 2001 From: Helium314 Date: Sun, 3 Mar 2024 15:13:11 +0100 Subject: [PATCH 26/40] always load recent emoji keys right after creating recents keyboard, fixes #527 --- .../java/helium314/keyboard/keyboard/emoji/EmojiCategory.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/app/src/main/java/helium314/keyboard/keyboard/emoji/EmojiCategory.java b/app/src/main/java/helium314/keyboard/keyboard/emoji/EmojiCategory.java index e82064142..f89440c61 100644 --- a/app/src/main/java/helium314/keyboard/keyboard/emoji/EmojiCategory.java +++ b/app/src/main/java/helium314/keyboard/keyboard/emoji/EmojiCategory.java @@ -153,8 +153,6 @@ public void initialize() { addShownCategoryId(EmojiCategory.ID_EMOTICONS); DynamicGridKeyboard recentsKbd = getKeyboard(EmojiCategory.ID_RECENTS, 0); - recentsKbd.loadRecentKeys(mCategoryKeyboardMap.values()); - mCurrentCategoryId = Settings.readLastShownEmojiCategoryId(mPrefs, defaultCategoryId); mCurrentCategoryPageId = Settings.readLastShownEmojiCategoryPageId(mPrefs, 0); if (!isShownCategoryId(mCurrentCategoryId)) { @@ -305,6 +303,7 @@ public DynamicGridKeyboard getKeyboard(final int categoryId, final int id) { mLayoutSet.getKeyboard(KeyboardId.ELEMENT_EMOJI_RECENTS), mMaxRecentsKeyCount, categoryId, currentWidth); mCategoryKeyboardMap.put(categoryKeyboardMapKey, kbd); + kbd.loadRecentKeys(mCategoryKeyboardMap.values()); return kbd; } From 1874e11d308c9908c8c340a8719af90c4901eade Mon Sep 17 00:00:00 2001 From: Helium314 Date: Mon, 4 Mar 2024 22:10:47 +0100 Subject: [PATCH 27/40] update readme --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index c5ad21f4a..0ec3ed0c9 100644 --- a/README.md +++ b/README.md @@ -44,6 +44,7 @@ Does not use internet permission, and thus is 100% offline. * __No suggestions for some language__: Check [dictionaries repo](https://codeberg.org/Helium314/aosp-dictionaries) whether a dictionary is available. If there is one, download it and add it in the language settings for this language. * __No suggestions in some app / text field__: This app respects the [no suggestions flag](https://developer.android.com/reference/android/text/InputType#TYPE_TEXT_FLAG_NO_SUGGESTIONS) set by some input fields, i.e. the developer does not want you to see suggestions here. Best do in issue report for that app if you think this behavior is wrong. Alternatively you can enable the _always show suggestions_ setting that overrides the _no suggestions_ flag. * __How to enable glide typing__: There is no glide typing built into this app, but you can load compatible libraries: Go to advanced settings -> _load gesture typing library_ and point to a file (setting not available in _nouserlib_ version). You can extract the file from GApps packages ("_swypelibs_"), or download one [here](https://github.com/erkserkserks/openboard/tree/master/app/src/main/jniLibs). Make sure to use the correct version (app will tell you in the dialog to load the library). + * __Glide typing is not working after loading a library__: Possibly the download was corrupted, or you downloaded the wrong file. If you get a "_unknown file_" confirmation popup, it is likely you are not using the correct file (or you might be using a different version of the library). * __What is the _nouserlib_ version?__: The normal version (_release_) allows the user to provide a library for glide typing. Running code that isn't supplied with the app is _dynamic code loading_, which is a security risk. Android Studio warns about this: > Dynamically loading code from locations other than the application's library directory or the Android platform's built-in library directories is dangerous, as there is an increased risk that the code could have been tampered with. Applications should use loadLibrary when possible, which provides increased assurance that libraries are loaded from one of these safer locations. Application developers should use the features of their development environment to place application native libraries into the lib directory of their compiled APKs. From a0c7b28b912efa07c13f032eebb6579be51859db Mon Sep 17 00:00:00 2001 From: Helium314 Date: Wed, 6 Mar 2024 20:55:47 +0100 Subject: [PATCH 28/40] use TypedValueCompat for dp <-> px conversion --- .../java/helium314/keyboard/keyboard/PointerTracker.java | 3 ++- .../keyboard/latin/settings/AppearanceSettingsFragment.kt | 5 +++-- .../keyboard/latin/settings/LanguageSettingsDialog.kt | 2 +- .../helium314/keyboard/latin/settings/SettingsValues.java | 3 ++- .../helium314/keyboard/latin/setup/SetupWizardActivity.java | 6 ++---- .../helium314/keyboard/latin/utils/CustomLayoutUtils.kt | 2 +- .../java/helium314/keyboard/latin/utils/PopupKeysUtils.kt | 2 +- .../java/helium314/keyboard/latin/utils/ResourceUtils.java | 6 ++++++ 8 files changed, 18 insertions(+), 11 deletions(-) diff --git a/app/src/main/java/helium314/keyboard/keyboard/PointerTracker.java b/app/src/main/java/helium314/keyboard/keyboard/PointerTracker.java index 4857adcdd..98279a6b4 100644 --- a/app/src/main/java/helium314/keyboard/keyboard/PointerTracker.java +++ b/app/src/main/java/helium314/keyboard/keyboard/PointerTracker.java @@ -19,6 +19,7 @@ import androidx.annotation.NonNull; import androidx.annotation.Nullable; +import androidx.core.util.TypedValueCompat; import helium314.keyboard.keyboard.internal.BatchInputArbiter; import helium314.keyboard.keyboard.internal.BatchInputArbiter.BatchInputArbiterListener; @@ -84,7 +85,7 @@ public PointerTrackerParams(final TypedArray mainKeyboardViewAttr) { // Parameters for pointer handling. private static PointerTrackerParams sParams; - private static final int sPointerStep = (int)(10.0 * Resources.getSystem().getDisplayMetrics().density); + private static final int sPointerStep = (int)TypedValueCompat.dpToPx(10, Resources.getSystem().getDisplayMetrics()); private static GestureStrokeRecognitionParams sGestureStrokeRecognitionParams; private static GestureStrokeDrawingParams sGestureStrokeDrawingParams; private static boolean sNeedsPhantomSuddenMoveEventHack; diff --git a/app/src/main/java/helium314/keyboard/latin/settings/AppearanceSettingsFragment.kt b/app/src/main/java/helium314/keyboard/latin/settings/AppearanceSettingsFragment.kt index 1e8ef22e5..f066847d6 100644 --- a/app/src/main/java/helium314/keyboard/latin/settings/AppearanceSettingsFragment.kt +++ b/app/src/main/java/helium314/keyboard/latin/settings/AppearanceSettingsFragment.kt @@ -6,6 +6,7 @@ import android.content.SharedPreferences import android.content.res.Configuration import android.os.Build import android.os.Bundle +import androidx.core.util.TypedValueCompat import androidx.preference.ListPreference import androidx.preference.Preference import androidx.preference.TwoStatePreference @@ -80,8 +81,8 @@ class AppearanceSettingsFragment : SubScreenFragment() { } } val metrics = requireContext().resources.displayMetrics - val widthDp = metrics.widthPixels / metrics.density - val heightDp = metrics.heightPixels / metrics.density + val widthDp = TypedValueCompat.pxToDp(metrics.widthPixels.toFloat(), metrics) + val heightDp = TypedValueCompat.pxToDp(metrics.heightPixels.toFloat(), metrics) if ((min(widthDp, heightDp) < 600 && max(widthDp, heightDp) < 720)) { removePreference(Settings.PREF_ENABLE_SPLIT_KEYBOARD) removePreference(Settings.PREF_SPLIT_SPACER_SCALE) diff --git a/app/src/main/java/helium314/keyboard/latin/settings/LanguageSettingsDialog.kt b/app/src/main/java/helium314/keyboard/latin/settings/LanguageSettingsDialog.kt index 6bf45af4e..b0a317569 100644 --- a/app/src/main/java/helium314/keyboard/latin/settings/LanguageSettingsDialog.kt +++ b/app/src/main/java/helium314/keyboard/latin/settings/LanguageSettingsDialog.kt @@ -326,7 +326,7 @@ class LanguageSettingsDialog( val attrs = context.obtainStyledAttributes(R.style.PreferenceSubtitleText, intArrayOf(android.R.attr.textSize)) setTextSize(TypedValue.COMPLEX_UNIT_PX, attrs.getDimension(0, 20f)) attrs.recycle() - setPadding((context.resources.displayMetrics.scaledDensity * 16).toInt(), 0, 0, 0) + setPadding(ResourceUtils.toPx(16, context.resources), 0, 0, 0) isEnabled = userDicts.none { it.name == "${DictionaryInfoUtils.MAIN_DICT_PREFIX}${USER_DICTIONARY_SUFFIX}" } }) } diff --git a/app/src/main/java/helium314/keyboard/latin/settings/SettingsValues.java b/app/src/main/java/helium314/keyboard/latin/settings/SettingsValues.java index 17df0d7ea..e328204de 100644 --- a/app/src/main/java/helium314/keyboard/latin/settings/SettingsValues.java +++ b/app/src/main/java/helium314/keyboard/latin/settings/SettingsValues.java @@ -15,6 +15,7 @@ import androidx.annotation.NonNull; import androidx.annotation.Nullable; +import androidx.core.util.TypedValueCompat; import helium314.keyboard.compat.ConfigurationCompatKt; import helium314.keyboard.keyboard.internal.keyboard_parser.LocaleKeyboardInfosKt; @@ -167,7 +168,7 @@ public SettingsValues(final Context context, final SharedPreferences prefs, fina mBigramPredictionEnabled = readBigramPredictionEnabled(prefs, res); mDoubleSpacePeriodTimeout = res.getInteger(R.integer.config_double_space_period_timeout); mHasHardwareKeyboard = Settings.readHasHardwareKeyboard(res.getConfiguration()); - final float displayWidthDp = res.getDisplayMetrics().widthPixels / res.getDisplayMetrics().density; + final float displayWidthDp = TypedValueCompat.pxToDp(res.getDisplayMetrics().widthPixels, res.getDisplayMetrics()); mIsSplitKeyboardEnabled = prefs.getBoolean(Settings.PREF_ENABLE_SPLIT_KEYBOARD, false) && displayWidthDp > 600; // require display width of 600 dp for split // determine spacerWidth from display width and scale setting mSplitKeyboardSpacerRelativeWidth = mIsSplitKeyboardEnabled diff --git a/app/src/main/java/helium314/keyboard/latin/setup/SetupWizardActivity.java b/app/src/main/java/helium314/keyboard/latin/setup/SetupWizardActivity.java index 73351d414..6bab89934 100644 --- a/app/src/main/java/helium314/keyboard/latin/setup/SetupWizardActivity.java +++ b/app/src/main/java/helium314/keyboard/latin/setup/SetupWizardActivity.java @@ -6,8 +6,6 @@ package helium314.keyboard.latin.setup; -import static android.util.TypedValue.COMPLEX_UNIT_DIP; - import android.content.Intent; import android.content.res.ColorStateList; import android.content.res.Resources; @@ -15,7 +13,6 @@ import android.os.Bundle; import android.os.Message; import android.provider.Settings; -import android.util.TypedValue; import android.view.View; import android.view.inputmethod.InputMethodManager; import android.widget.TextView; @@ -33,6 +30,7 @@ import helium314.keyboard.latin.utils.ActivityThemeUtils; import helium314.keyboard.latin.utils.JniUtils; import helium314.keyboard.latin.utils.LeakGuardHandlerWrapper; +import helium314.keyboard.latin.utils.ResourceUtils; import helium314.keyboard.latin.utils.UncachedInputMethodManagerUtils; import java.util.ArrayList; @@ -387,7 +385,7 @@ public SetupStep(final int stepNo, final String applicationName, final TextView final int paddingEnd = mActionLabel.getPaddingEnd(); mActionLabel.setPaddingRelative(paddingEnd, 0, paddingEnd, 0); } else { - final int size = (int) TypedValue.applyDimension(COMPLEX_UNIT_DIP, 24f, res.getDisplayMetrics()); + final int size = ResourceUtils.toPx(24, res); actionIconDrawable.setBounds(0,0, size, size); mActionLabel.setCompoundDrawablesRelative(actionIconDrawable, null, null, null); } diff --git a/app/src/main/java/helium314/keyboard/latin/utils/CustomLayoutUtils.kt b/app/src/main/java/helium314/keyboard/latin/utils/CustomLayoutUtils.kt index cfa863104..994a8e85c 100644 --- a/app/src/main/java/helium314/keyboard/latin/utils/CustomLayoutUtils.kt +++ b/app/src/main/java/helium314/keyboard/latin/utils/CustomLayoutUtils.kt @@ -58,7 +58,7 @@ fun loadCustomLayout(layoutContent: String, layoutName: String, languageTag: Str .setView(EditText(context).apply { setText(name) doAfterTextChanged { name = it.toString() } - val padding = (8 * context.resources.displayMetrics.density).toInt() + val padding = ResourceUtils.toPx(8, context.resources) setPadding(3 * padding, padding, 3 * padding, padding) inputType = InputType.TYPE_CLASS_TEXT or InputType.TYPE_TEXT_VARIATION_NORMAL }) diff --git a/app/src/main/java/helium314/keyboard/latin/utils/PopupKeysUtils.kt b/app/src/main/java/helium314/keyboard/latin/utils/PopupKeysUtils.kt index 123d4c3dd..208f32dea 100644 --- a/app/src/main/java/helium314/keyboard/latin/utils/PopupKeysUtils.kt +++ b/app/src/main/java/helium314/keyboard/latin/utils/PopupKeysUtils.kt @@ -117,7 +117,7 @@ fun reorderPopupKeysDialog(context: Context, key: String, defaultSetting: String both.first() to both.last().toBoolean() } val rv = RecyclerView(context) - val padding = (8 * context.resources.displayMetrics.density).toInt() + val padding = ResourceUtils.toPx(8, context.resources) rv.setPadding(3 * padding, padding, padding, padding) rv.layoutManager = LinearLayoutManager(context, LinearLayoutManager.VERTICAL, false) val callback = object : DiffUtil.ItemCallback>() { diff --git a/app/src/main/java/helium314/keyboard/latin/utils/ResourceUtils.java b/app/src/main/java/helium314/keyboard/latin/utils/ResourceUtils.java index 5e19459f1..564736601 100644 --- a/app/src/main/java/helium314/keyboard/latin/utils/ResourceUtils.java +++ b/app/src/main/java/helium314/keyboard/latin/utils/ResourceUtils.java @@ -14,6 +14,8 @@ import android.util.DisplayMetrics; import android.util.TypedValue; +import androidx.core.util.TypedValueCompat; + import helium314.keyboard.latin.R; import helium314.keyboard.latin.settings.SettingsValues; @@ -259,4 +261,8 @@ public static boolean isDimensionValue(final TypedValue v) { public static boolean isNight(final Resources res) { return (res.getConfiguration().uiMode & Configuration.UI_MODE_NIGHT_MASK) == Configuration.UI_MODE_NIGHT_YES; } + + public static int toPx(final int dp, final Resources res) { + return (int) TypedValueCompat.dpToPx(dp, res.getDisplayMetrics()); + } } From 273cd87c2bc4e9b8b2f746e32a211609a827bf9f Mon Sep 17 00:00:00 2001 From: Helium314 Date: Wed, 6 Mar 2024 21:18:09 +0100 Subject: [PATCH 29/40] add separate turkis layout fixes #339 fixes #508 --- app/src/main/assets/language_key_texts/tr.txt | 10 +----- app/src/main/assets/layouts/turkish.txt | 34 +++++++++++++++++++ app/src/main/res/xml/method.xml | 4 +-- 3 files changed, 37 insertions(+), 11 deletions(-) create mode 100644 app/src/main/assets/layouts/turkish.txt diff --git a/app/src/main/assets/language_key_texts/tr.txt b/app/src/main/assets/language_key_texts/tr.txt index 8ad9c50a7..73459f8d8 100644 --- a/app/src/main/assets/language_key_texts/tr.txt +++ b/app/src/main/assets/language_key_texts/tr.txt @@ -1,7 +1,7 @@ [popup_keys] a â ä á e ə é -i ı î ï ì í į ī +ı i î ï ì í į ī o ö ô œ ò ó õ ø ō u ü û ù ú ū s ş ß ś š @@ -10,11 +10,3 @@ n ň ñ c ç ć č y ý z ž - -[extra_keys] -1: ğ -1: ü -2: ş -2: î -3: ö -3: ç diff --git a/app/src/main/assets/layouts/turkish.txt b/app/src/main/assets/layouts/turkish.txt new file mode 100644 index 000000000..2da3d0d48 --- /dev/null +++ b/app/src/main/assets/layouts/turkish.txt @@ -0,0 +1,34 @@ +q +w +e +r +t +y +u +ı +o +p +ğ +ü + +a +s +d +f +g +h +j +k +l +ş +i + +z +x +c +v +b +n +m +ö +ç diff --git a/app/src/main/res/xml/method.xml b/app/src/main/res/xml/method.xml index d7e53ea1e..f0f35ae07 100644 --- a/app/src/main/res/xml/method.xml +++ b/app/src/main/res/xml/method.xml @@ -94,7 +94,7 @@ te_IN: Telugu (India)/telugu th: Thai/thai tl: Tagalog/qwerty+ - tr: Turkish/qwerty + tr: Turkish/turkish ur_PK: Urdu Pakistan uk: Ukrainian/ukrainian uz_UZ: Uzbek (Uzbekistan)/uzbek # This is a preliminary keyboard layout. @@ -925,7 +925,7 @@ android:imeSubtypeLocale="tr" android:languageTag="tr" android:imeSubtypeMode="keyboard" - android:imeSubtypeExtraValue="KeyboardLayoutSet=qwerty+,AsciiCapable,SupportTouchPositionCorrection,EmojiCapable" + android:imeSubtypeExtraValue="KeyboardLayoutSet=turkish,AsciiCapable,SupportTouchPositionCorrection,EmojiCapable" android:isAsciiCapable="true" /> Date: Wed, 6 Mar 2024 21:19:22 +0100 Subject: [PATCH 30/40] fix minor issues when copying custom layout from existing layout --- .../latin/settings/LanguageSettingsDialog.kt | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/app/src/main/java/helium314/keyboard/latin/settings/LanguageSettingsDialog.kt b/app/src/main/java/helium314/keyboard/latin/settings/LanguageSettingsDialog.kt index b0a317569..0902020ef 100644 --- a/app/src/main/java/helium314/keyboard/latin/settings/LanguageSettingsDialog.kt +++ b/app/src/main/java/helium314/keyboard/latin/settings/LanguageSettingsDialog.kt @@ -136,17 +136,20 @@ class LanguageSettingsDialog( private fun copyLayout() { val layouts = mutableListOf() val displayNames = mutableListOf() - if (infos.first().subtype.isAsciiCapable) { - layouts.addAll(context.resources.getStringArray(R.array.predefined_layouts)) - layouts.forEach { displayNames.add(SubtypeLocaleUtils.getKeyboardLayoutSetDisplayName(it) ?: it) } - } infos.forEach { val layoutSetName = it.subtype.getExtraValueOf(KEYBOARD_LAYOUT_SET) - if (layoutSetName?.startsWith(CUSTOM_LAYOUT_PREFIX) == false) { // don't allow copying custom layout (at least for now) + if (layoutSetName?.startsWith(CUSTOM_LAYOUT_PREFIX) == false // don't allow copying custom layout (at least for now) + && !layoutSetName.endsWith("+")) { // don't allow copying layouts only defined via extra keys layouts.add(layoutSetName) displayNames.add(SubtypeLocaleUtils.getSubtypeDisplayNameInSystemLocale(it.subtype)) } } + if (infos.first().subtype.isAsciiCapable) { + context.resources.getStringArray(R.array.predefined_layouts).forEach { + layouts.add(it) + displayNames.add(SubtypeLocaleUtils.getKeyboardLayoutSetDisplayName(it) ?: it) + } + } Builder(context) .setTitle(R.string.keyboard_layout_set) .setItems(displayNames.toTypedArray()) { di, i -> From 2a13ae186a7fee142c20939255f90de8f994f5f4 Mon Sep 17 00:00:00 2001 From: Helium314 Date: Wed, 6 Mar 2024 21:29:11 +0100 Subject: [PATCH 31/40] avoid immediate switch to other app when language key switches both layouts and keyboard apps --- app/src/main/java/helium314/keyboard/latin/LatinIME.java | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/app/src/main/java/helium314/keyboard/latin/LatinIME.java b/app/src/main/java/helium314/keyboard/latin/LatinIME.java index 844f48049..64d2382c7 100644 --- a/app/src/main/java/helium314/keyboard/latin/LatinIME.java +++ b/app/src/main/java/helium314/keyboard/latin/LatinIME.java @@ -526,7 +526,7 @@ public void onFinishInput() { final class SubtypeState { private InputMethodSubtype mLastActiveSubtype; - private boolean mCurrentSubtypeHasBeenUsed; + private boolean mCurrentSubtypeHasBeenUsed = true; // starting with true avoids immediate switch public void setCurrentSubtypeHasBeenUsed() { mCurrentSubtypeHasBeenUsed = true; @@ -1477,13 +1477,10 @@ public void switchToNextSubtype() { } if (shouldSwitchToOtherInputMethods()) { final InputMethodSubtype nextSubtype = mRichImm.getNextSubtypeInThisIme(false); - // todo (later): this will switch IME if we are at the end of the list, but ideally we - // want to switch IME only if all internal subtypes are unused - // -> need to store used/unused subtypes in mSubtypeState if (nextSubtype != null) { switchToSubtype(nextSubtype); return; - } else if (switchInputMethod()){ + } else if (switchInputMethod()) { return; } } From aa94c84d5238344b992509e4727712cbfa481fb9 Mon Sep 17 00:00:00 2001 From: Helium314 Date: Wed, 6 Mar 2024 22:07:38 +0100 Subject: [PATCH 32/40] rename subtype settings and clean up when renaming in shared prefs --- .../main/java/helium314/keyboard/latin/App.kt | 18 +++++++++++++++++- .../keyboard/latin/settings/Settings.java | 7 +++---- .../keyboard/latin/utils/SubtypeSettings.kt | 18 +++++++++--------- 3 files changed, 29 insertions(+), 14 deletions(-) diff --git a/app/src/main/java/helium314/keyboard/latin/App.kt b/app/src/main/java/helium314/keyboard/latin/App.kt index 819863aa9..ffe8ff7da 100644 --- a/app/src/main/java/helium314/keyboard/latin/App.kt +++ b/app/src/main/java/helium314/keyboard/latin/App.kt @@ -49,12 +49,28 @@ fun checkVersionUpgrade(context: Context) { } if (oldVersion == 0) // new install or restoring settings from old app name upgradesWhenComingFromOldAppName(context) - if (oldVersion == 1000) { // upgrade old custom layouts name + if (oldVersion <= 1000) { // upgrade old custom layouts name val layoutsDir = Settings.getLayoutsDir(context) val oldShiftSymbolsFile = File(layoutsDir, "${CUSTOM_LAYOUT_PREFIX}shift_symbols") if (oldShiftSymbolsFile.exists()) { oldShiftSymbolsFile.renameTo(File(layoutsDir, "${CUSTOM_LAYOUT_PREFIX}symbols_shifted")) } + + // rename subtype setting, and clean old subtypes that might remain in some cases + val subtypesPref = prefs.getString("enabled_input_styles", "")!! + .split(";").filter { it.isNotEmpty() } + .map { + val localeAndLayout = it.split(":").toMutableList() + localeAndLayout[0] = localeAndLayout[0].constructLocale().toLanguageTag() + localeAndLayout.joinToString(":") + }.toSet().joinToString(";") + val selectedSubtype = prefs.getString("selected_input_style", "") + prefs.edit { + remove("enabled_input_styles") + putString(Settings.PREF_ENABLED_SUBTYPES, subtypesPref) + remove("selected_input_style") + putString(Settings.PREF_SELECTED_SUBTYPE, selectedSubtype) + } } prefs.edit { putInt(Settings.PREF_VERSION_CODE, BuildConfig.VERSION_CODE) } } diff --git a/app/src/main/java/helium314/keyboard/latin/settings/Settings.java b/app/src/main/java/helium314/keyboard/latin/settings/Settings.java index 340aa66d4..583d83cc0 100644 --- a/app/src/main/java/helium314/keyboard/latin/settings/Settings.java +++ b/app/src/main/java/helium314/keyboard/latin/settings/Settings.java @@ -41,7 +41,6 @@ import helium314.keyboard.latin.utils.Log; import helium314.keyboard.latin.utils.ResourceUtils; import helium314.keyboard.latin.utils.RunInLocaleKt; -import helium314.keyboard.latin.utils.ScriptUtils; import helium314.keyboard.latin.utils.StatsUtils; import helium314.keyboard.latin.utils.SubtypeSettingsKt; import helium314.keyboard.latin.utils.ToolbarKey; @@ -139,8 +138,8 @@ public final class Settings implements SharedPreferences.OnSharedPreferenceChang public static final String PREF_ADD_TO_PERSONAL_DICTIONARY = "add_to_personal_dictionary"; public static final String PREF_NAVBAR_COLOR = "navbar_color"; public static final String PREF_NARROW_KEY_GAPS = "narrow_key_gaps"; - public static final String PREF_ENABLED_INPUT_STYLES = "enabled_input_styles"; - public static final String PREF_SELECTED_INPUT_STYLE = "selected_input_style"; + public static final String PREF_ENABLED_SUBTYPES = "enabled_subtypes"; + public static final String PREF_SELECTED_SUBTYPE = "selected_subtype"; public static final String PREF_USE_SYSTEM_LOCALES = "use_system_locales"; public static final String PREF_URL_DETECTION = "url_detection"; public static final String PREF_DONT_SHOW_MISSING_DICTIONARY_DIALOG = "dont_show_missing_dict_dialog"; @@ -179,7 +178,7 @@ public final class Settings implements SharedPreferences.OnSharedPreferenceChang add(PREF_EMOJI_RECENT_KEYS); add(PREF_DONT_SHOW_MISSING_DICTIONARY_DIALOG); add(PREF_SHOW_ALL_COLORS); - add(PREF_SELECTED_INPUT_STYLE); + add(PREF_SELECTED_SUBTYPE); }}; public static Settings getInstance() { diff --git a/app/src/main/java/helium314/keyboard/latin/utils/SubtypeSettings.kt b/app/src/main/java/helium314/keyboard/latin/utils/SubtypeSettings.kt index 67c392865..2b6c7b786 100644 --- a/app/src/main/java/helium314/keyboard/latin/utils/SubtypeSettings.kt +++ b/app/src/main/java/helium314/keyboard/latin/utils/SubtypeSettings.kt @@ -57,9 +57,9 @@ fun getMatchingLayoutSetNameForLocale(locale: Locale): String { fun addEnabledSubtype(prefs: SharedPreferences, newSubtype: InputMethodSubtype) { require(initialized) val subtypeString = newSubtype.prefString() - val oldSubtypeStrings = prefs.getString(Settings.PREF_ENABLED_INPUT_STYLES, "")!!.split(SUBTYPE_SEPARATOR) + val oldSubtypeStrings = prefs.getString(Settings.PREF_ENABLED_SUBTYPES, "")!!.split(SUBTYPE_SEPARATOR) val newString = (oldSubtypeStrings + subtypeString).filter { it.isNotBlank() }.toSortedSet().joinToString(SUBTYPE_SEPARATOR) - prefs.edit { putString(Settings.PREF_ENABLED_INPUT_STYLES, newString) } + prefs.edit { putString(Settings.PREF_ENABLED_SUBTYPES, newString) } if (newSubtype !in enabledSubtypes) { enabledSubtypes.add(newSubtype) @@ -94,7 +94,7 @@ fun removeAdditionalSubtype(prefs: SharedPreferences, resources: Resources, subt fun getSelectedSubtype(prefs: SharedPreferences): InputMethodSubtype { require(initialized) - val localeAndLayout = prefs.getString(Settings.PREF_SELECTED_INPUT_STYLE, "")!!.toLocaleAndLayout() + val localeAndLayout = prefs.getString(Settings.PREF_SELECTED_SUBTYPE, "")!!.toLocaleAndLayout() val subtypes = if (prefs.getBoolean(Settings.PREF_USE_SYSTEM_LOCALES, true)) getDefaultEnabledSubtypes() else enabledSubtypes val subtype = subtypes.firstOrNull { localeAndLayout.first == it.locale() && localeAndLayout.second == SubtypeLocaleUtils.getKeyboardLayoutSetName(it) } @@ -113,9 +113,9 @@ fun getSelectedSubtype(prefs: SharedPreferences): InputMethodSubtype { fun setSelectedSubtype(prefs: SharedPreferences, subtype: InputMethodSubtype) { val subtypeString = subtype.prefString() - if (subtype.locale().toLanguageTag().isEmpty() || prefs.getString(Settings.PREF_SELECTED_INPUT_STYLE, "") == subtypeString) + if (subtype.locale().toLanguageTag().isEmpty() || prefs.getString(Settings.PREF_SELECTED_SUBTYPE, "") == subtypeString) return - prefs.edit { putString(Settings.PREF_SELECTED_INPUT_STYLE, subtypeString) } + prefs.edit { putString(Settings.PREF_SELECTED_SUBTYPE, subtypeString) } } fun isAdditionalSubtype(subtype: InputMethodSubtype): Boolean { @@ -267,7 +267,7 @@ private fun loadAdditionalSubtypes(context: Context) { // requires loadResourceSubtypes to be called before private fun loadEnabledSubtypes(context: Context) { val prefs = DeviceProtectedUtils.getSharedPreferences(context) - val subtypeStrings = prefs.getString(Settings.PREF_ENABLED_INPUT_STYLES, "")!! + val subtypeStrings = prefs.getString(Settings.PREF_ENABLED_SUBTYPES, "")!! .split(SUBTYPE_SEPARATOR).filter { it.isNotEmpty() }.map { it.toLocaleAndLayout() } for (localeAndLayout in subtypeStrings) { @@ -299,12 +299,12 @@ private fun loadEnabledSubtypes(context: Context) { } private fun removeEnabledSubtype(prefs: SharedPreferences, subtypeString: String) { - val oldSubtypeString = prefs.getString(Settings.PREF_ENABLED_INPUT_STYLES, "")!! + val oldSubtypeString = prefs.getString(Settings.PREF_ENABLED_SUBTYPES, "")!! val newString = (oldSubtypeString.split(SUBTYPE_SEPARATOR) - subtypeString).joinToString(SUBTYPE_SEPARATOR) if (newString == oldSubtypeString) return // already removed - prefs.edit { putString(Settings.PREF_ENABLED_INPUT_STYLES, newString) } - if (subtypeString == prefs.getString(Settings.PREF_SELECTED_INPUT_STYLE, "")) { + prefs.edit { putString(Settings.PREF_ENABLED_SUBTYPES, newString) } + if (subtypeString == prefs.getString(Settings.PREF_SELECTED_SUBTYPE, "")) { // switch subtype if the currently used one has been disabled try { val nextSubtype = RichInputMethodManager.getInstance().getNextSubtypeInThisIme(true) From 0f250d72bb614e2b63e2fe299d308980f10f6720 Mon Sep 17 00:00:00 2001 From: Helium314 Date: Sun, 10 Mar 2024 05:29:05 +0100 Subject: [PATCH 33/40] allow storing AllColors in prefs (still not used) --- .../helium314/keyboard/latin/common/Colors.kt | 23 ++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) diff --git a/app/src/main/java/helium314/keyboard/latin/common/Colors.kt b/app/src/main/java/helium314/keyboard/latin/common/Colors.kt index 19c644dbc..07931bc30 100644 --- a/app/src/main/java/helium314/keyboard/latin/common/Colors.kt +++ b/app/src/main/java/helium314/keyboard/latin/common/Colors.kt @@ -3,6 +3,7 @@ package helium314.keyboard.latin.common import android.content.Context +import android.content.SharedPreferences import android.content.res.ColorStateList import android.content.res.Configuration import android.content.res.TypedArray @@ -18,6 +19,7 @@ import android.widget.ImageView import androidx.annotation.ColorInt import androidx.annotation.RequiresApi import androidx.core.content.ContextCompat +import androidx.core.content.edit import androidx.core.graphics.BlendModeColorFilterCompat import androidx.core.graphics.BlendModeCompat import androidx.core.graphics.ColorUtils @@ -540,7 +542,7 @@ class DefaultColors ( // todo: allow users to use this class // the colorMap should be stored in settings -// reading should consider that colors might be added and removed, i.e. no "simple" serialization +// settings read and write untested // color settings should add another menu option for "all colors" // just show all ColorTypes with current value read from the map (default to black, same as in get) // no string name, as it is not stable @@ -581,6 +583,25 @@ class AllColors(private val colorMap: EnumMap, override val them } } +fun readAllColorsMap(prefs: SharedPreferences): EnumMap { + val s = prefs.getString("all_colors", "") ?: "" + val c = EnumMap(ColorType::class.java) + s.split(";").forEach { + val ct = try { + ColorType.valueOf(it.substringBefore(",").uppercase()) + } catch (_: Exception) { // todo: which one? + return@forEach + } + val i = it.substringAfter(",").toIntOrNull() ?: return@forEach + c[ct] = i + } + return c +} + +fun writeAllColorsMap(c: EnumMap, prefs: SharedPreferences) { + prefs.edit { putString("all_colors", c.map { "${it.key},${it.value}" }.joinToString(";")) } +} + private fun colorFilter(color: Int, mode: BlendModeCompat = BlendModeCompat.MODULATE): ColorFilter { // using !! for the color filter because null is only returned for unsupported blend modes, which are not used return BlendModeColorFilterCompat.createBlendModeColorFilterCompat(color, mode)!! From 8d13a66a00479db35898052b3d30821d5fa1510b Mon Sep 17 00:00:00 2001 From: Helium314 Date: Sun, 10 Mar 2024 06:10:59 +0100 Subject: [PATCH 34/40] adjust colors so pressed toolbar keys change background color --- .../helium314/keyboard/latin/common/Colors.kt | 34 +++++++++++-------- 1 file changed, 20 insertions(+), 14 deletions(-) diff --git a/app/src/main/java/helium314/keyboard/latin/common/Colors.kt b/app/src/main/java/helium314/keyboard/latin/common/Colors.kt index 07931bc30..60d53304d 100644 --- a/app/src/main/java/helium314/keyboard/latin/common/Colors.kt +++ b/app/src/main/java/helium314/keyboard/latin/common/Colors.kt @@ -400,15 +400,6 @@ class DefaultColors ( private var backgroundSetupDone = false init { - if (themeStyle == STYLE_HOLO && keyboardBackground == null) { - val darkerBackground = adjustLuminosityAndKeepAlpha(background, -0.2f) - navBar = darkerBackground - keyboardBackground = GradientDrawable(GradientDrawable.Orientation.TOP_BOTTOM, intArrayOf(background, darkerBackground)) - backgroundSetupDone = true - } else { - navBar = background - } - if (isDarkColor(background)) { adjustedBackground = brighten(background) doubleAdjustedBackground = brighten(adjustedBackground) @@ -418,15 +409,30 @@ class DefaultColors ( } adjustedBackgroundStateList = stateList(doubleAdjustedBackground, adjustedBackground) - val stripBackground = if (keyboardBackground == null && !hasKeyBorders) { - if (isDarkColor(background)) 0x16ffffff else 0x11000000 + val stripBackground: Int + val pressedStripElementBackground: Int + if (keyboardBackground != null || (themeStyle == STYLE_HOLO && hasKeyBorders)) { + stripBackground = Color.TRANSPARENT + pressedStripElementBackground = if (isDarkColor(background)) 0x22ffffff // assume background is similar to the background color + else 0x11000000 + } else if (hasKeyBorders) { + stripBackground = background + pressedStripElementBackground = adjustedBackground } else { - Color.TRANSPARENT + stripBackground = adjustedBackground + pressedStripElementBackground = doubleAdjustedBackground } - val pressedStripElementBackground = if (keyboardBackground == null) adjustedBackground - else if (isDarkColor(background)) 0x22ffffff else 0x11000000 stripBackgroundList = stateList(pressedStripElementBackground, stripBackground) + if (themeStyle == STYLE_HOLO && keyboardBackground == null) { + val darkerBackground = adjustLuminosityAndKeepAlpha(background, -0.2f) + navBar = darkerBackground + keyboardBackground = GradientDrawable(GradientDrawable.Orientation.TOP_BOTTOM, intArrayOf(background, darkerBackground)) + backgroundSetupDone = true + } else { + navBar = background + } + adjustedBackgroundFilter = colorFilter(adjustedBackground) if (hasKeyBorders) { backgroundStateList = stateList(brightenOrDarken(background, true), background) From 9e375e9926ada1c0378f30db016ffc411e082fa2 Mon Sep 17 00:00:00 2001 From: Helium314 Date: Sun, 10 Mar 2024 08:25:08 +0100 Subject: [PATCH 35/40] adjust build workflow --- .github/workflows/android-build.yml | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/.github/workflows/android-build.yml b/.github/workflows/android-build.yml index ad2f5e8d2..e869cd3e2 100644 --- a/.github/workflows/android-build.yml +++ b/.github/workflows/android-build.yml @@ -1,9 +1,14 @@ -name: Build +name: Build debug on: push: - branches: [ main ] + # don't run on main. I noticed I often don't push commits to avoid unnecessary workflow runs + branches-ignore: [ main ] + paths: + - 'app/**' pull_request: + paths: + - 'app/**' jobs: build: From 7d004c1c793695d3864ac1a20ac01cf49eb565b1 Mon Sep 17 00:00:00 2001 From: Helium314 Date: Sun, 10 Mar 2024 13:26:58 +0100 Subject: [PATCH 36/40] add python script for updating translations and running the makeDictList task --- .../android/en-US/changelogs/1001.txt | 1 + release.py | 74 +++++++++++++++++++ 2 files changed, 75 insertions(+) create mode 100644 fastlane/metadata/android/en-US/changelogs/1001.txt create mode 100755 release.py diff --git a/fastlane/metadata/android/en-US/changelogs/1001.txt b/fastlane/metadata/android/en-US/changelogs/1001.txt new file mode 100644 index 000000000..8d1c8b69c --- /dev/null +++ b/fastlane/metadata/android/en-US/changelogs/1001.txt @@ -0,0 +1 @@ + diff --git a/release.py b/release.py new file mode 100755 index 000000000..30942008e --- /dev/null +++ b/release.py @@ -0,0 +1,74 @@ +#!/bin/python + +import os +import subprocess +import zipfile +from urllib.request import urlretrieve + + +# git diff should be empty, and there should be no errors +def check_git(): + result = subprocess.run(["git", "diff", "--name-only"], capture_output=True) + if result.returncode != 0 or len(result.stdout) != 0: + raise ValueError("uncommitted changes") + + +# download and update translations +def update_translations(): + url = "https://translate.codeberg.org/download/heliboard/?format=zip" + zip_file_name = "translations.zip" + urlretrieve(url, zip_file_name) + # extract all in heliboard/heliboard/app/src/main/res + with zipfile.ZipFile(zip_file_name, "r") as f: + for file in f.filelist: + if not file.filename.startswith("heliboard/heliboard/app/src/main/res"): + continue + file.filename = file.filename.replace("heliboard/heliboard/", "") + f.extract(file) + os.remove(zip_file_name) + + +# git diff to make sure default strings are the same +def check_default_values_diff(): + result = subprocess.run(["git", "diff", "--name-only", "app/src/main/res/values"], capture_output=True) + if result.returncode != 0 or len(result.stdout) != 0: + raise ValueError("default strings changed after translation import, something is wrong") + + +# run that task +def update_dict_list(): +# gradle = "gradlew" # Linux +# gradle = "gradlew.bat" # Windows + gradle = "../../builder/realgradle.sh" # weird path for historic reasons + result = subprocess.run([gradle, ":tools:make-dict-list:makeDictList"]) + assert result.returncode == 0 + + +# check whether there is a changelog file for current version and print result and version code +def check_changelog(): + changelog_dir = "fastlane/metadata/android/en-US/changelogs" + assert os.path.isdir(changelog_dir) + filenames = list(os.scandir(changelog_dir)) + filenames.sort() + changelog_version = filenames[-1].replace(".txt", "") + with open("app/build.gradle") as f: + for line in f: + line = line.lstrip() + if line.startswith("versionCode"): + if changelog_version == line.split(" ")[1]: + print("changelog for", changelog_version, "exists") + else: + print("changelog for", changelog_version, "does not exist") + break + + +def main(): + check_git() + update_translations() + check_default_values_diff() + update_dict_list() + check_changelog() + + +if __name__ == "__main__": + main() From ec4d0558e7f4eab1714c6b49d6c7088c0a87d4e3 Mon Sep 17 00:00:00 2001 From: Helium314 Date: Sun, 10 Mar 2024 19:08:18 +0100 Subject: [PATCH 37/40] store clipboard history entries in companion object fixes #548 --- .../helium314/keyboard/latin/ClipboardHistoryManager.kt | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/app/src/main/java/helium314/keyboard/latin/ClipboardHistoryManager.kt b/app/src/main/java/helium314/keyboard/latin/ClipboardHistoryManager.kt index ea4ea3c30..9c383094d 100644 --- a/app/src/main/java/helium314/keyboard/latin/ClipboardHistoryManager.kt +++ b/app/src/main/java/helium314/keyboard/latin/ClipboardHistoryManager.kt @@ -17,7 +17,6 @@ class ClipboardHistoryManager( ) : ClipboardManager.OnPrimaryClipChangedListener { private lateinit var clipboardManager: ClipboardManager - private val historyEntries: MutableList = ArrayList() private var onHistoryChangeListener: OnHistoryChangeListener? = null fun onCreate() { @@ -149,4 +148,9 @@ class ClipboardHistoryManager( fun onClipboardHistoryEntriesRemoved(pos: Int, count: Int) fun onClipboardHistoryEntryMoved(from: Int, to: Int) } + + companion object { + // store pinned clips in companion object so they survive a keyboard switch (which destroys the current instance) + private val historyEntries: MutableList = ArrayList() + } } From 3feac6d96611da7a5dcbbb03a553d641e988ff59 Mon Sep 17 00:00:00 2001 From: Helium314 Date: Sun, 10 Mar 2024 19:41:46 +0100 Subject: [PATCH 38/40] don't hide voice input key for TYPE_TEXT_VARIATION_URI see #544 URL fields are frequently used as search fields --- app/src/main/java/helium314/keyboard/latin/InputAttributes.java | 1 - 1 file changed, 1 deletion(-) diff --git a/app/src/main/java/helium314/keyboard/latin/InputAttributes.java b/app/src/main/java/helium314/keyboard/latin/InputAttributes.java index 8eb8462c4..ce231aa8f 100644 --- a/app/src/main/java/helium314/keyboard/latin/InputAttributes.java +++ b/app/src/main/java/helium314/keyboard/latin/InputAttributes.java @@ -99,7 +99,6 @@ public InputAttributes(final EditorInfo editorInfo, final boolean isFullscreenMo final boolean noMicrophone = mIsPasswordField || InputTypeUtils.isEmailVariation(variation) - || InputType.TYPE_TEXT_VARIATION_URI == variation || hasNoMicrophoneKeyOption() || !RichInputMethodManager.getInstance().hasShortcutIme(); mShouldShowVoiceInputKey = !noMicrophone; From 3b8b44b34b4c03a098e42de1aeec311ae94601c0 Mon Sep 17 00:00:00 2001 From: Helium314 Date: Sun, 10 Mar 2024 20:10:23 +0100 Subject: [PATCH 39/40] fix issue when specifying codes in json layouts --- .../keyboard/internal/keyboard_parser/floris/KeyCode.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/src/main/java/helium314/keyboard/keyboard/internal/keyboard_parser/floris/KeyCode.kt b/app/src/main/java/helium314/keyboard/keyboard/internal/keyboard_parser/floris/KeyCode.kt index f85290a3a..bba5d4025 100644 --- a/app/src/main/java/helium314/keyboard/keyboard/internal/keyboard_parser/floris/KeyCode.kt +++ b/app/src/main/java/helium314/keyboard/keyboard/internal/keyboard_parser/floris/KeyCode.kt @@ -131,7 +131,7 @@ object KeyCode { const val NOT_SPECIFIED = -10008 // todo: not sure if there is need to have the "old" unspecified keyCode different, just test it and maybe merge /** to make sure a FlorisBoard code works when reading a JSON layout */ - private fun Int.checkOrConvertCode(): Int = when (this) { + private fun Int.checkOrConvertCode(): Int = if (this > 0) this else when (this) { // todo: should work, but not yet // CURRENCY_SLOT_1, CURRENCY_SLOT_2, CURRENCY_SLOT_3, CURRENCY_SLOT_4, CURRENCY_SLOT_5, CURRENCY_SLOT_6, From 1ffa4766af395918365f465839f58c9a08729230 Mon Sep 17 00:00:00 2001 From: Helium314 Date: Mon, 11 Mar 2024 19:08:40 +0100 Subject: [PATCH 40/40] update readmes --- README.md | 18 +++++++++--------- layouts.md | 2 ++ 2 files changed, 11 insertions(+), 9 deletions(-) diff --git a/README.md b/README.md index 0ec3ed0c9..b22b38e28 100644 --- a/README.md +++ b/README.md @@ -24,16 +24,16 @@ Does not use internet permission, and thus is 100% offline. * Customize keyboard themes (style, colors and background image) * can follow the system's day/night setting on Android 10+ (and on some versions of Android 9) * can follow dynamic colors for Android 12+ -* Customize keyboard [layouts](layouts.md) (only when disabling _use system languages_) +* Customize keyboard [layouts](layouts.md) (only available when disabling _use system languages_) * Multilingual typing -* Glide typing (_only with closed source library_) +* Glide typing (_only with closed source library_ ☹️) * library not included in the app, as there is no compatible open source library available * can be extracted from GApps packages ("_swypelibs_"), or downloaded [here](https://github.com/erkserkserks/openboard/tree/master/app/src/main/jniLibs) * if you are concerned about security implications of loading user-provides libraries, please use the _nouserlib_ build variant, which removes this option. If HeliBoard is installed as system app, and _swypelibs_ are available for the system, they will be used. * If the app is installed as a system app and _swypelibs_ are available, glide typing will be available independent of the version. * Clipboard history * One-handed mode -* Split keyboard (if the screen is large enough) +* Split keyboard (only available if the screen is large enough) * Number pad * Backup and restore your learned word / history data @@ -43,13 +43,14 @@ Does not use internet permission, and thus is 100% offline. * __Cannot switch choose layout__: This is only possible when _use system languages_ is disabled. * __No suggestions for some language__: Check [dictionaries repo](https://codeberg.org/Helium314/aosp-dictionaries) whether a dictionary is available. If there is one, download it and add it in the language settings for this language. * __No suggestions in some app / text field__: This app respects the [no suggestions flag](https://developer.android.com/reference/android/text/InputType#TYPE_TEXT_FLAG_NO_SUGGESTIONS) set by some input fields, i.e. the developer does not want you to see suggestions here. Best do in issue report for that app if you think this behavior is wrong. Alternatively you can enable the _always show suggestions_ setting that overrides the _no suggestions_ flag. +* __Multilingual typing__: Enable in _Languages & Layouts_, select the main language and tap the `+` button next to _multilingual typing_ to add a language. Note that the selection is limited to languages with the same script as the main language, and to languages that have a dictionary (see above for how to add). * __How to enable glide typing__: There is no glide typing built into this app, but you can load compatible libraries: Go to advanced settings -> _load gesture typing library_ and point to a file (setting not available in _nouserlib_ version). You can extract the file from GApps packages ("_swypelibs_"), or download one [here](https://github.com/erkserkserks/openboard/tree/master/app/src/main/jniLibs). Make sure to use the correct version (app will tell you in the dialog to load the library). * __Glide typing is not working after loading a library__: Possibly the download was corrupted, or you downloaded the wrong file. If you get a "_unknown file_" confirmation popup, it is likely you are not using the correct file (or you might be using a different version of the library). * __What is the _nouserlib_ version?__: The normal version (_release_) allows the user to provide a library for glide typing. Running code that isn't supplied with the app is _dynamic code loading_, which is a security risk. Android Studio warns about this: > Dynamically loading code from locations other than the application's library directory or the Android platform's built-in library directories is dangerous, as there is an increased risk that the code could have been tampered with. Applications should use loadLibrary when possible, which provides increased assurance that libraries are loaded from one of these safer locations. Application developers should use the features of their development environment to place application native libraries into the lib directory of their compiled APKs. The app checks the SHA256 checksum of the library and warns the user if it doesn't match with known library versions. A mismatch indicates the library was modified, but may also occur if the user intentionally provides a different library than expected (e.g. a self-built variant). -* (_to be expanded_...) +* (_to be expanded_...) ## Hidden Functionality Features that may go unnoticed, and further potentially useful information @@ -72,7 +73,7 @@ Features that may go unnoticed, and further potentially useful information * Long-press a suggestion in the suggestion strip twice to show the source dictionary. * When using debug APK, you can find Debug Settings within the Advanced Preferences, though the usefulness is limited except for dumping dictionaries into the log. * In the event of an application crash, you will be prompted whether you want the crash logs when you open the Settings. - * When using multilingual typing, space bar will show an confidence value used for determining the currenly used language. + * When using multilingual typing, space bar will show an confidence value used for determining the currently used language. * Suggestions will have some tiny numbers on top showing some internal score and source dictionary (can be disabled) * For users doing manual backups with root access: Starting at Android 7, some files and the main shared preferences file are not in the default location, because the app is using [device protected storage](https://developer.android.com/reference/android/content/Context#createDeviceProtectedStorageContext()). This is necessary so the settings and layout files can be read before the device is unlocked, e.g. at boot. The files are usually located in `/data/user_de/0//`, though the location may depend on the device and Android version. @@ -86,11 +87,11 @@ Before opening a new issue, be sure to check the following: - **Does the issue already exist?** Make sure a similar issue has not been reported by browsing [existing issues](https://github.com/Helium314/HeliBoard/issues). Please search open and closed issues. - **Is the issue still relevant?** Make sure your issue is not already fixed in the latest version of HeliBoard. - **Did you use the issue template?** It is important to make life of our kind contributors easier by avoiding issues that miss key information to their resolution. -Note that issues that that ignore part of the issue template will likely get treated with very low priority, as often they are needlessly hard to read or understand (e.g. huge screenshots, or addressing multiple topics). +Note that issues that that ignore part of the issue template will likely get treated with very low priority, as often they are needlessly hard to read or understand (e.g. huge screenshots, not providing a proper description, or addressing multiple topics). ## Translation Translations can be added using [Weblate](https://translate.codeberg.org/projects/heliboard/). You will need an account to update translations and add languages. Add the language you want to translate to in Languages -> Manage translated languages in the top menu bar. -Updating translations in a PR will not be accepted, as it may cause conflicts with Weblate tranlations. +Updating translations in a PR will not be accepted, as it may cause conflicts with Weblate translations. ## Dictionary Creation There will not be any further dictionaries bundled in this app. However, you can add dictionaries to the [dictionaries repository](https://codeberg.org/Helium314/aosp-dictionaries). @@ -136,8 +137,7 @@ See make-dict-list tool [README](tools/make-dict-list/README.md). Planned features and improvements * Customizable functional key layout * Will likely result in having the same functional key layout for alphabet and symbols layouts - * Requires adjusting names and codes for compatibility with FlorisBoard layouts -* Support for "special keys" like _alt_ and _ctrl_ (#479) +* Support for _alt_, _ctrl_, _meta_ and _fn_ (#479) * Less complicated addition of languages (e.g. #519) * Additional and customizable key swipe functionality * Some functionality will not be possible when using glide typing diff --git a/layouts.md b/layouts.md index 67603c797..e8f1c0b6f 100644 --- a/layouts.md +++ b/layouts.md @@ -23,8 +23,10 @@ If you want different key label and use text, set the label to [label]|[text], e ## Json format * Allows more flexibility than the simple format, e.g. changing keys depending on input type, shift state or layout direction * You can use character layouts from [FlorisBoard](https://github.com/florisboard/florisboard/blob/master/CONTRIBUTING.md#adding-the-layout) + * Support is not 100% there yet, notably `kana_selector` and `char_width_selector` do not work. * There is no need for specifying a code, it will be determined from the label automatically * You can still specify it, but it's only necessary if you want key label and code to be different + * Note that not all _special codes_ (negative numbers) from FlorisBoard are supported * You can add the numeric value of a _labelFlag_ to a key for some specific effects, see [here](app/src/main/res/values/attrs.xml) in the section _keyLabelFlags_ for names and numeric values. * More details on the formal will be provided. For now you can check other layouts, often you just need to copy lines and change the labels.