From 5ba40f7875e17e7294b64469070f0a6c8ecaa5a4 Mon Sep 17 00:00:00 2001 From: Helium314 Date: Fri, 14 Feb 2025 13:37:21 +0100 Subject: [PATCH] adjust arrangement for layouts so we can have more than one layout per type (was possible only for main) --- app/build.gradle.kts | 4 +- .../clip_bottom_row.json | 0 .../{ => emoji_bottom}/emoji_bottom_row.json | 0 .../{ => functional}/functional_keys.json | 0 .../functional_keys_tablet.json | 0 .../main/assets/layouts/{ => main}/arabic.txt | 0 .../layouts/{ => main}/arabic_hijai.txt | 0 .../assets/layouts/{ => main}/arabic_pc.txt | 0 .../layouts/{ => main}/armenian_phonetic.txt | 0 .../assets/layouts/{ => main}/azerty.json | 0 .../assets/layouts/{ => main}/belarusian.txt | 0 .../assets/layouts/{ => main}/bengali.txt | 0 .../layouts/{ => main}/bengali_akkhor.json | 0 .../layouts/{ => main}/bengali_probhat.json | 0 .../layouts/{ => main}/bengali_unijoy.json | 0 .../main/assets/layouts/{ => main}/bepo.txt | 0 .../assets/layouts/{ => main}/bulgarian.txt | 0 .../layouts/{ => main}/bulgarian_bds.txt | 0 .../layouts/{ => main}/bulgarian_bekl.txt | 0 .../assets/layouts/{ => main}/chuvash.txt | 0 .../assets/layouts/{ => main}/colemak.json | 0 .../assets/layouts/{ => main}/colemak_dh.json | 0 .../layouts/{ => main}/dargwa_urakhi.txt | 0 .../assets/layouts/{ => main}/dvorak.json | 0 .../assets/layouts/{ => main}/esperanto.txt | 0 .../main/assets/layouts/{ => main}/farsi.txt | 0 .../assets/layouts/{ => main}/georgian.json | 0 .../main/assets/layouts/{ => main}/greek.json | 0 .../assets/layouts/{ => main}/gujarati.json | 0 .../main/assets/layouts/{ => main}/halmak.txt | 0 .../assets/layouts/{ => main}/hebrew.json | 0 .../layouts/{ => main}/hebrew_1452_2.json | 0 .../main/assets/layouts/{ => main}/hindi.json | 0 .../layouts/{ => main}/hindi_compact.json | 0 .../layouts/{ => main}/hindi_phonetic.json | 0 .../{ => main}/hungarian_extended_qwertz.txt | 0 .../assets/layouts/{ => main}/kabyle.json | 0 .../main/assets/layouts/{ => main}/kaitag.txt | 0 .../assets/layouts/{ => main}/kannada.txt | 0 .../layouts/{ => main}/kannada_extended.txt | 0 .../main/assets/layouts/{ => main}/khmer.json | 0 .../assets/layouts/{ => main}/korean.json | 0 .../{ => main}/korean_sebeolsik_390.json | 0 .../{ => main}/korean_sebeolsik_final.json | 0 .../main/assets/layouts/{ => main}/lao.json | 0 .../assets/layouts/{ => main}/macedonian.txt | 0 .../assets/layouts/{ => main}/malayalam.txt | 0 .../assets/layouts/{ => main}/mansi_north.txt | 0 .../assets/layouts/{ => main}/marathi.json | 0 .../main/assets/layouts/{ => main}/mari.txt | 0 .../assets/layouts/{ => main}/mongolian.txt | 0 .../layouts/{ => main}/nepali_romanized.json | 0 .../{ => main}/nepali_traditional.json | 0 .../assets/layouts/{ => main}/pcqwerty.json | 0 .../main/assets/layouts/{ => main}/qwerty.txt | 0 .../main/assets/layouts/{ => main}/qwertz.txt | 0 .../assets/layouts/{ => main}/russian.txt | 0 .../layouts/{ => main}/russian_student.txt | 0 .../assets/layouts/{ => main}/serbian.txt | 0 .../assets/layouts/{ => main}/sinhala.json | 0 .../main/assets/layouts/{ => main}/tamil.txt | 0 .../main/assets/layouts/{ => main}/telugu.txt | 0 .../main/assets/layouts/{ => main}/thai.json | 0 .../assets/layouts/{ => main}/turkish.txt | 0 .../assets/layouts/{ => main}/ukrainian.txt | 0 .../main/assets/layouts/{ => main}/urdu.json | 0 .../main/assets/layouts/{ => main}/uzbek.json | 0 .../assets/layouts/{ => main}/workman.txt | 0 .../{ => more_symbols}/symbols_shifted.txt | 0 .../assets/layouts/{ => number}/number.json | 0 .../layouts/{ => number_row}/number_row.txt | 0 .../assets/layouts/{ => numpad}/numpad.json | 0 .../numpad_landscape.json | 0 .../assets/layouts/{ => phone}/phone.json | 0 .../{ => phone_symbols}/phone_symbols.json | 0 .../assets/layouts/{ => symbols}/symbols.txt | 0 .../layouts/{ => symbols}/symbols_arabic.txt | 0 .../keyboard/keyboard/KeyboardLayoutSet.java | 4 +- .../keyboard_parser/KeyboardParser.kt | 25 +++- .../{RawKeyboardParser.kt => LayoutParser.kt} | 124 +++++------------- .../keyboard_parser/LocaleKeyboardInfos.kt | 3 + .../main/java/helium314/keyboard/latin/App.kt | 119 ++++++++++++++++- .../keyboard/latin/RichInputMethodSubtype.kt | 1 + .../settings/AdvancedSettingsFragment.kt | 6 +- .../keyboard/latin/settings/Defaults.kt | 23 +++- .../latin/settings/LanguageSettingsDialog.kt | 4 +- .../keyboard/latin/settings/Settings.java | 6 + .../latin/settings/SettingsValues.java | 2 - .../latin/utils/AdditionalSubtypeUtils.java | 10 +- .../keyboard/latin/utils/CustomLayoutUtils.kt | 63 +++------ .../keyboard/latin/utils/LayoutType.kt | 3 + .../latin/utils/SubtypeLocaleUtils.java | 2 +- .../keyboard/latin/utils/SubtypeSettings.kt | 5 +- .../keyboard/latin/utils/SubtypeUtils.kt | 7 +- .../keyboard/settings/SettingsContainer.kt | 6 +- .../settings/screens/AdvancedScreen.kt | 7 +- app/src/main/res/xml/method.xml | 10 +- .../helium314/keyboard/KeyboardParserTest.kt | 33 +++-- 98 files changed, 260 insertions(+), 207 deletions(-) rename app/src/main/assets/layouts/{ => clipboard_bottom}/clip_bottom_row.json (100%) rename app/src/main/assets/layouts/{ => emoji_bottom}/emoji_bottom_row.json (100%) rename app/src/main/assets/layouts/{ => functional}/functional_keys.json (100%) rename app/src/main/assets/layouts/{ => functional}/functional_keys_tablet.json (100%) rename app/src/main/assets/layouts/{ => main}/arabic.txt (100%) rename app/src/main/assets/layouts/{ => main}/arabic_hijai.txt (100%) rename app/src/main/assets/layouts/{ => main}/arabic_pc.txt (100%) rename app/src/main/assets/layouts/{ => main}/armenian_phonetic.txt (100%) rename app/src/main/assets/layouts/{ => main}/azerty.json (100%) rename app/src/main/assets/layouts/{ => main}/belarusian.txt (100%) rename app/src/main/assets/layouts/{ => main}/bengali.txt (100%) rename app/src/main/assets/layouts/{ => main}/bengali_akkhor.json (100%) rename app/src/main/assets/layouts/{ => main}/bengali_probhat.json (100%) rename app/src/main/assets/layouts/{ => main}/bengali_unijoy.json (100%) rename app/src/main/assets/layouts/{ => main}/bepo.txt (100%) rename app/src/main/assets/layouts/{ => main}/bulgarian.txt (100%) rename app/src/main/assets/layouts/{ => main}/bulgarian_bds.txt (100%) rename app/src/main/assets/layouts/{ => main}/bulgarian_bekl.txt (100%) rename app/src/main/assets/layouts/{ => main}/chuvash.txt (100%) rename app/src/main/assets/layouts/{ => main}/colemak.json (100%) rename app/src/main/assets/layouts/{ => main}/colemak_dh.json (100%) rename app/src/main/assets/layouts/{ => main}/dargwa_urakhi.txt (100%) rename app/src/main/assets/layouts/{ => main}/dvorak.json (100%) rename app/src/main/assets/layouts/{ => main}/esperanto.txt (100%) rename app/src/main/assets/layouts/{ => main}/farsi.txt (100%) rename app/src/main/assets/layouts/{ => main}/georgian.json (100%) rename app/src/main/assets/layouts/{ => main}/greek.json (100%) rename app/src/main/assets/layouts/{ => main}/gujarati.json (100%) rename app/src/main/assets/layouts/{ => main}/halmak.txt (100%) rename app/src/main/assets/layouts/{ => main}/hebrew.json (100%) rename app/src/main/assets/layouts/{ => main}/hebrew_1452_2.json (100%) rename app/src/main/assets/layouts/{ => main}/hindi.json (100%) rename app/src/main/assets/layouts/{ => main}/hindi_compact.json (100%) rename app/src/main/assets/layouts/{ => main}/hindi_phonetic.json (100%) rename app/src/main/assets/layouts/{ => main}/hungarian_extended_qwertz.txt (100%) rename app/src/main/assets/layouts/{ => main}/kabyle.json (100%) rename app/src/main/assets/layouts/{ => main}/kaitag.txt (100%) rename app/src/main/assets/layouts/{ => main}/kannada.txt (100%) rename app/src/main/assets/layouts/{ => main}/kannada_extended.txt (100%) rename app/src/main/assets/layouts/{ => main}/khmer.json (100%) rename app/src/main/assets/layouts/{ => main}/korean.json (100%) rename app/src/main/assets/layouts/{ => main}/korean_sebeolsik_390.json (100%) rename app/src/main/assets/layouts/{ => main}/korean_sebeolsik_final.json (100%) rename app/src/main/assets/layouts/{ => main}/lao.json (100%) rename app/src/main/assets/layouts/{ => main}/macedonian.txt (100%) rename app/src/main/assets/layouts/{ => main}/malayalam.txt (100%) rename app/src/main/assets/layouts/{ => main}/mansi_north.txt (100%) rename app/src/main/assets/layouts/{ => main}/marathi.json (100%) rename app/src/main/assets/layouts/{ => main}/mari.txt (100%) rename app/src/main/assets/layouts/{ => main}/mongolian.txt (100%) rename app/src/main/assets/layouts/{ => main}/nepali_romanized.json (100%) rename app/src/main/assets/layouts/{ => main}/nepali_traditional.json (100%) rename app/src/main/assets/layouts/{ => main}/pcqwerty.json (100%) rename app/src/main/assets/layouts/{ => main}/qwerty.txt (100%) rename app/src/main/assets/layouts/{ => main}/qwertz.txt (100%) rename app/src/main/assets/layouts/{ => main}/russian.txt (100%) rename app/src/main/assets/layouts/{ => main}/russian_student.txt (100%) rename app/src/main/assets/layouts/{ => main}/serbian.txt (100%) rename app/src/main/assets/layouts/{ => main}/sinhala.json (100%) rename app/src/main/assets/layouts/{ => main}/tamil.txt (100%) rename app/src/main/assets/layouts/{ => main}/telugu.txt (100%) rename app/src/main/assets/layouts/{ => main}/thai.json (100%) rename app/src/main/assets/layouts/{ => main}/turkish.txt (100%) rename app/src/main/assets/layouts/{ => main}/ukrainian.txt (100%) rename app/src/main/assets/layouts/{ => main}/urdu.json (100%) rename app/src/main/assets/layouts/{ => main}/uzbek.json (100%) rename app/src/main/assets/layouts/{ => main}/workman.txt (100%) rename app/src/main/assets/layouts/{ => more_symbols}/symbols_shifted.txt (100%) rename app/src/main/assets/layouts/{ => number}/number.json (100%) rename app/src/main/assets/layouts/{ => number_row}/number_row.txt (100%) rename app/src/main/assets/layouts/{ => numpad}/numpad.json (100%) rename app/src/main/assets/layouts/{ => numpad_landscape}/numpad_landscape.json (100%) rename app/src/main/assets/layouts/{ => phone}/phone.json (100%) rename app/src/main/assets/layouts/{ => phone_symbols}/phone_symbols.json (100%) rename app/src/main/assets/layouts/{ => symbols}/symbols.txt (100%) rename app/src/main/assets/layouts/{ => symbols}/symbols_arabic.txt (100%) rename app/src/main/java/helium314/keyboard/keyboard/internal/keyboard_parser/{RawKeyboardParser.kt => LayoutParser.kt} (57%) diff --git a/app/build.gradle.kts b/app/build.gradle.kts index e1b9e2aaa..6e126c193 100755 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -13,8 +13,8 @@ android { applicationId = "helium314.keyboard" minSdk = 21 targetSdk = 34 - versionCode = 2303 - versionName = "2.3+dev2" + versionCode = 2304 + versionName = "2.3+dev3" ndk { abiFilters.clear() abiFilters.addAll(listOf("armeabi-v7a", "arm64-v8a", "x86", "x86_64")) diff --git a/app/src/main/assets/layouts/clip_bottom_row.json b/app/src/main/assets/layouts/clipboard_bottom/clip_bottom_row.json similarity index 100% rename from app/src/main/assets/layouts/clip_bottom_row.json rename to app/src/main/assets/layouts/clipboard_bottom/clip_bottom_row.json diff --git a/app/src/main/assets/layouts/emoji_bottom_row.json b/app/src/main/assets/layouts/emoji_bottom/emoji_bottom_row.json similarity index 100% rename from app/src/main/assets/layouts/emoji_bottom_row.json rename to app/src/main/assets/layouts/emoji_bottom/emoji_bottom_row.json diff --git a/app/src/main/assets/layouts/functional_keys.json b/app/src/main/assets/layouts/functional/functional_keys.json similarity index 100% rename from app/src/main/assets/layouts/functional_keys.json rename to app/src/main/assets/layouts/functional/functional_keys.json diff --git a/app/src/main/assets/layouts/functional_keys_tablet.json b/app/src/main/assets/layouts/functional/functional_keys_tablet.json similarity index 100% rename from app/src/main/assets/layouts/functional_keys_tablet.json rename to app/src/main/assets/layouts/functional/functional_keys_tablet.json diff --git a/app/src/main/assets/layouts/arabic.txt b/app/src/main/assets/layouts/main/arabic.txt similarity index 100% rename from app/src/main/assets/layouts/arabic.txt rename to app/src/main/assets/layouts/main/arabic.txt diff --git a/app/src/main/assets/layouts/arabic_hijai.txt b/app/src/main/assets/layouts/main/arabic_hijai.txt similarity index 100% rename from app/src/main/assets/layouts/arabic_hijai.txt rename to app/src/main/assets/layouts/main/arabic_hijai.txt diff --git a/app/src/main/assets/layouts/arabic_pc.txt b/app/src/main/assets/layouts/main/arabic_pc.txt similarity index 100% rename from app/src/main/assets/layouts/arabic_pc.txt rename to app/src/main/assets/layouts/main/arabic_pc.txt diff --git a/app/src/main/assets/layouts/armenian_phonetic.txt b/app/src/main/assets/layouts/main/armenian_phonetic.txt similarity index 100% rename from app/src/main/assets/layouts/armenian_phonetic.txt rename to app/src/main/assets/layouts/main/armenian_phonetic.txt diff --git a/app/src/main/assets/layouts/azerty.json b/app/src/main/assets/layouts/main/azerty.json similarity index 100% rename from app/src/main/assets/layouts/azerty.json rename to app/src/main/assets/layouts/main/azerty.json diff --git a/app/src/main/assets/layouts/belarusian.txt b/app/src/main/assets/layouts/main/belarusian.txt similarity index 100% rename from app/src/main/assets/layouts/belarusian.txt rename to app/src/main/assets/layouts/main/belarusian.txt diff --git a/app/src/main/assets/layouts/bengali.txt b/app/src/main/assets/layouts/main/bengali.txt similarity index 100% rename from app/src/main/assets/layouts/bengali.txt rename to app/src/main/assets/layouts/main/bengali.txt diff --git a/app/src/main/assets/layouts/bengali_akkhor.json b/app/src/main/assets/layouts/main/bengali_akkhor.json similarity index 100% rename from app/src/main/assets/layouts/bengali_akkhor.json rename to app/src/main/assets/layouts/main/bengali_akkhor.json diff --git a/app/src/main/assets/layouts/bengali_probhat.json b/app/src/main/assets/layouts/main/bengali_probhat.json similarity index 100% rename from app/src/main/assets/layouts/bengali_probhat.json rename to app/src/main/assets/layouts/main/bengali_probhat.json diff --git a/app/src/main/assets/layouts/bengali_unijoy.json b/app/src/main/assets/layouts/main/bengali_unijoy.json similarity index 100% rename from app/src/main/assets/layouts/bengali_unijoy.json rename to app/src/main/assets/layouts/main/bengali_unijoy.json diff --git a/app/src/main/assets/layouts/bepo.txt b/app/src/main/assets/layouts/main/bepo.txt similarity index 100% rename from app/src/main/assets/layouts/bepo.txt rename to app/src/main/assets/layouts/main/bepo.txt diff --git a/app/src/main/assets/layouts/bulgarian.txt b/app/src/main/assets/layouts/main/bulgarian.txt similarity index 100% rename from app/src/main/assets/layouts/bulgarian.txt rename to app/src/main/assets/layouts/main/bulgarian.txt diff --git a/app/src/main/assets/layouts/bulgarian_bds.txt b/app/src/main/assets/layouts/main/bulgarian_bds.txt similarity index 100% rename from app/src/main/assets/layouts/bulgarian_bds.txt rename to app/src/main/assets/layouts/main/bulgarian_bds.txt diff --git a/app/src/main/assets/layouts/bulgarian_bekl.txt b/app/src/main/assets/layouts/main/bulgarian_bekl.txt similarity index 100% rename from app/src/main/assets/layouts/bulgarian_bekl.txt rename to app/src/main/assets/layouts/main/bulgarian_bekl.txt diff --git a/app/src/main/assets/layouts/chuvash.txt b/app/src/main/assets/layouts/main/chuvash.txt similarity index 100% rename from app/src/main/assets/layouts/chuvash.txt rename to app/src/main/assets/layouts/main/chuvash.txt diff --git a/app/src/main/assets/layouts/colemak.json b/app/src/main/assets/layouts/main/colemak.json similarity index 100% rename from app/src/main/assets/layouts/colemak.json rename to app/src/main/assets/layouts/main/colemak.json diff --git a/app/src/main/assets/layouts/colemak_dh.json b/app/src/main/assets/layouts/main/colemak_dh.json similarity index 100% rename from app/src/main/assets/layouts/colemak_dh.json rename to app/src/main/assets/layouts/main/colemak_dh.json diff --git a/app/src/main/assets/layouts/dargwa_urakhi.txt b/app/src/main/assets/layouts/main/dargwa_urakhi.txt similarity index 100% rename from app/src/main/assets/layouts/dargwa_urakhi.txt rename to app/src/main/assets/layouts/main/dargwa_urakhi.txt diff --git a/app/src/main/assets/layouts/dvorak.json b/app/src/main/assets/layouts/main/dvorak.json similarity index 100% rename from app/src/main/assets/layouts/dvorak.json rename to app/src/main/assets/layouts/main/dvorak.json diff --git a/app/src/main/assets/layouts/esperanto.txt b/app/src/main/assets/layouts/main/esperanto.txt similarity index 100% rename from app/src/main/assets/layouts/esperanto.txt rename to app/src/main/assets/layouts/main/esperanto.txt diff --git a/app/src/main/assets/layouts/farsi.txt b/app/src/main/assets/layouts/main/farsi.txt similarity index 100% rename from app/src/main/assets/layouts/farsi.txt rename to app/src/main/assets/layouts/main/farsi.txt diff --git a/app/src/main/assets/layouts/georgian.json b/app/src/main/assets/layouts/main/georgian.json similarity index 100% rename from app/src/main/assets/layouts/georgian.json rename to app/src/main/assets/layouts/main/georgian.json diff --git a/app/src/main/assets/layouts/greek.json b/app/src/main/assets/layouts/main/greek.json similarity index 100% rename from app/src/main/assets/layouts/greek.json rename to app/src/main/assets/layouts/main/greek.json diff --git a/app/src/main/assets/layouts/gujarati.json b/app/src/main/assets/layouts/main/gujarati.json similarity index 100% rename from app/src/main/assets/layouts/gujarati.json rename to app/src/main/assets/layouts/main/gujarati.json diff --git a/app/src/main/assets/layouts/halmak.txt b/app/src/main/assets/layouts/main/halmak.txt similarity index 100% rename from app/src/main/assets/layouts/halmak.txt rename to app/src/main/assets/layouts/main/halmak.txt diff --git a/app/src/main/assets/layouts/hebrew.json b/app/src/main/assets/layouts/main/hebrew.json similarity index 100% rename from app/src/main/assets/layouts/hebrew.json rename to app/src/main/assets/layouts/main/hebrew.json diff --git a/app/src/main/assets/layouts/hebrew_1452_2.json b/app/src/main/assets/layouts/main/hebrew_1452_2.json similarity index 100% rename from app/src/main/assets/layouts/hebrew_1452_2.json rename to app/src/main/assets/layouts/main/hebrew_1452_2.json diff --git a/app/src/main/assets/layouts/hindi.json b/app/src/main/assets/layouts/main/hindi.json similarity index 100% rename from app/src/main/assets/layouts/hindi.json rename to app/src/main/assets/layouts/main/hindi.json diff --git a/app/src/main/assets/layouts/hindi_compact.json b/app/src/main/assets/layouts/main/hindi_compact.json similarity index 100% rename from app/src/main/assets/layouts/hindi_compact.json rename to app/src/main/assets/layouts/main/hindi_compact.json diff --git a/app/src/main/assets/layouts/hindi_phonetic.json b/app/src/main/assets/layouts/main/hindi_phonetic.json similarity index 100% rename from app/src/main/assets/layouts/hindi_phonetic.json rename to app/src/main/assets/layouts/main/hindi_phonetic.json diff --git a/app/src/main/assets/layouts/hungarian_extended_qwertz.txt b/app/src/main/assets/layouts/main/hungarian_extended_qwertz.txt similarity index 100% rename from app/src/main/assets/layouts/hungarian_extended_qwertz.txt rename to app/src/main/assets/layouts/main/hungarian_extended_qwertz.txt diff --git a/app/src/main/assets/layouts/kabyle.json b/app/src/main/assets/layouts/main/kabyle.json similarity index 100% rename from app/src/main/assets/layouts/kabyle.json rename to app/src/main/assets/layouts/main/kabyle.json diff --git a/app/src/main/assets/layouts/kaitag.txt b/app/src/main/assets/layouts/main/kaitag.txt similarity index 100% rename from app/src/main/assets/layouts/kaitag.txt rename to app/src/main/assets/layouts/main/kaitag.txt diff --git a/app/src/main/assets/layouts/kannada.txt b/app/src/main/assets/layouts/main/kannada.txt similarity index 100% rename from app/src/main/assets/layouts/kannada.txt rename to app/src/main/assets/layouts/main/kannada.txt diff --git a/app/src/main/assets/layouts/kannada_extended.txt b/app/src/main/assets/layouts/main/kannada_extended.txt similarity index 100% rename from app/src/main/assets/layouts/kannada_extended.txt rename to app/src/main/assets/layouts/main/kannada_extended.txt diff --git a/app/src/main/assets/layouts/khmer.json b/app/src/main/assets/layouts/main/khmer.json similarity index 100% rename from app/src/main/assets/layouts/khmer.json rename to app/src/main/assets/layouts/main/khmer.json diff --git a/app/src/main/assets/layouts/korean.json b/app/src/main/assets/layouts/main/korean.json similarity index 100% rename from app/src/main/assets/layouts/korean.json rename to app/src/main/assets/layouts/main/korean.json diff --git a/app/src/main/assets/layouts/korean_sebeolsik_390.json b/app/src/main/assets/layouts/main/korean_sebeolsik_390.json similarity index 100% rename from app/src/main/assets/layouts/korean_sebeolsik_390.json rename to app/src/main/assets/layouts/main/korean_sebeolsik_390.json diff --git a/app/src/main/assets/layouts/korean_sebeolsik_final.json b/app/src/main/assets/layouts/main/korean_sebeolsik_final.json similarity index 100% rename from app/src/main/assets/layouts/korean_sebeolsik_final.json rename to app/src/main/assets/layouts/main/korean_sebeolsik_final.json diff --git a/app/src/main/assets/layouts/lao.json b/app/src/main/assets/layouts/main/lao.json similarity index 100% rename from app/src/main/assets/layouts/lao.json rename to app/src/main/assets/layouts/main/lao.json diff --git a/app/src/main/assets/layouts/macedonian.txt b/app/src/main/assets/layouts/main/macedonian.txt similarity index 100% rename from app/src/main/assets/layouts/macedonian.txt rename to app/src/main/assets/layouts/main/macedonian.txt diff --git a/app/src/main/assets/layouts/malayalam.txt b/app/src/main/assets/layouts/main/malayalam.txt similarity index 100% rename from app/src/main/assets/layouts/malayalam.txt rename to app/src/main/assets/layouts/main/malayalam.txt diff --git a/app/src/main/assets/layouts/mansi_north.txt b/app/src/main/assets/layouts/main/mansi_north.txt similarity index 100% rename from app/src/main/assets/layouts/mansi_north.txt rename to app/src/main/assets/layouts/main/mansi_north.txt diff --git a/app/src/main/assets/layouts/marathi.json b/app/src/main/assets/layouts/main/marathi.json similarity index 100% rename from app/src/main/assets/layouts/marathi.json rename to app/src/main/assets/layouts/main/marathi.json diff --git a/app/src/main/assets/layouts/mari.txt b/app/src/main/assets/layouts/main/mari.txt similarity index 100% rename from app/src/main/assets/layouts/mari.txt rename to app/src/main/assets/layouts/main/mari.txt diff --git a/app/src/main/assets/layouts/mongolian.txt b/app/src/main/assets/layouts/main/mongolian.txt similarity index 100% rename from app/src/main/assets/layouts/mongolian.txt rename to app/src/main/assets/layouts/main/mongolian.txt diff --git a/app/src/main/assets/layouts/nepali_romanized.json b/app/src/main/assets/layouts/main/nepali_romanized.json similarity index 100% rename from app/src/main/assets/layouts/nepali_romanized.json rename to app/src/main/assets/layouts/main/nepali_romanized.json diff --git a/app/src/main/assets/layouts/nepali_traditional.json b/app/src/main/assets/layouts/main/nepali_traditional.json similarity index 100% rename from app/src/main/assets/layouts/nepali_traditional.json rename to app/src/main/assets/layouts/main/nepali_traditional.json diff --git a/app/src/main/assets/layouts/pcqwerty.json b/app/src/main/assets/layouts/main/pcqwerty.json similarity index 100% rename from app/src/main/assets/layouts/pcqwerty.json rename to app/src/main/assets/layouts/main/pcqwerty.json diff --git a/app/src/main/assets/layouts/qwerty.txt b/app/src/main/assets/layouts/main/qwerty.txt similarity index 100% rename from app/src/main/assets/layouts/qwerty.txt rename to app/src/main/assets/layouts/main/qwerty.txt diff --git a/app/src/main/assets/layouts/qwertz.txt b/app/src/main/assets/layouts/main/qwertz.txt similarity index 100% rename from app/src/main/assets/layouts/qwertz.txt rename to app/src/main/assets/layouts/main/qwertz.txt diff --git a/app/src/main/assets/layouts/russian.txt b/app/src/main/assets/layouts/main/russian.txt similarity index 100% rename from app/src/main/assets/layouts/russian.txt rename to app/src/main/assets/layouts/main/russian.txt diff --git a/app/src/main/assets/layouts/russian_student.txt b/app/src/main/assets/layouts/main/russian_student.txt similarity index 100% rename from app/src/main/assets/layouts/russian_student.txt rename to app/src/main/assets/layouts/main/russian_student.txt diff --git a/app/src/main/assets/layouts/serbian.txt b/app/src/main/assets/layouts/main/serbian.txt similarity index 100% rename from app/src/main/assets/layouts/serbian.txt rename to app/src/main/assets/layouts/main/serbian.txt diff --git a/app/src/main/assets/layouts/sinhala.json b/app/src/main/assets/layouts/main/sinhala.json similarity index 100% rename from app/src/main/assets/layouts/sinhala.json rename to app/src/main/assets/layouts/main/sinhala.json diff --git a/app/src/main/assets/layouts/tamil.txt b/app/src/main/assets/layouts/main/tamil.txt similarity index 100% rename from app/src/main/assets/layouts/tamil.txt rename to app/src/main/assets/layouts/main/tamil.txt diff --git a/app/src/main/assets/layouts/telugu.txt b/app/src/main/assets/layouts/main/telugu.txt similarity index 100% rename from app/src/main/assets/layouts/telugu.txt rename to app/src/main/assets/layouts/main/telugu.txt diff --git a/app/src/main/assets/layouts/thai.json b/app/src/main/assets/layouts/main/thai.json similarity index 100% rename from app/src/main/assets/layouts/thai.json rename to app/src/main/assets/layouts/main/thai.json diff --git a/app/src/main/assets/layouts/turkish.txt b/app/src/main/assets/layouts/main/turkish.txt similarity index 100% rename from app/src/main/assets/layouts/turkish.txt rename to app/src/main/assets/layouts/main/turkish.txt diff --git a/app/src/main/assets/layouts/ukrainian.txt b/app/src/main/assets/layouts/main/ukrainian.txt similarity index 100% rename from app/src/main/assets/layouts/ukrainian.txt rename to app/src/main/assets/layouts/main/ukrainian.txt diff --git a/app/src/main/assets/layouts/urdu.json b/app/src/main/assets/layouts/main/urdu.json similarity index 100% rename from app/src/main/assets/layouts/urdu.json rename to app/src/main/assets/layouts/main/urdu.json diff --git a/app/src/main/assets/layouts/uzbek.json b/app/src/main/assets/layouts/main/uzbek.json similarity index 100% rename from app/src/main/assets/layouts/uzbek.json rename to app/src/main/assets/layouts/main/uzbek.json diff --git a/app/src/main/assets/layouts/workman.txt b/app/src/main/assets/layouts/main/workman.txt similarity index 100% rename from app/src/main/assets/layouts/workman.txt rename to app/src/main/assets/layouts/main/workman.txt diff --git a/app/src/main/assets/layouts/symbols_shifted.txt b/app/src/main/assets/layouts/more_symbols/symbols_shifted.txt similarity index 100% rename from app/src/main/assets/layouts/symbols_shifted.txt rename to app/src/main/assets/layouts/more_symbols/symbols_shifted.txt diff --git a/app/src/main/assets/layouts/number.json b/app/src/main/assets/layouts/number/number.json similarity index 100% rename from app/src/main/assets/layouts/number.json rename to app/src/main/assets/layouts/number/number.json diff --git a/app/src/main/assets/layouts/number_row.txt b/app/src/main/assets/layouts/number_row/number_row.txt similarity index 100% rename from app/src/main/assets/layouts/number_row.txt rename to app/src/main/assets/layouts/number_row/number_row.txt diff --git a/app/src/main/assets/layouts/numpad.json b/app/src/main/assets/layouts/numpad/numpad.json similarity index 100% rename from app/src/main/assets/layouts/numpad.json rename to app/src/main/assets/layouts/numpad/numpad.json diff --git a/app/src/main/assets/layouts/numpad_landscape.json b/app/src/main/assets/layouts/numpad_landscape/numpad_landscape.json similarity index 100% rename from app/src/main/assets/layouts/numpad_landscape.json rename to app/src/main/assets/layouts/numpad_landscape/numpad_landscape.json diff --git a/app/src/main/assets/layouts/phone.json b/app/src/main/assets/layouts/phone/phone.json similarity index 100% rename from app/src/main/assets/layouts/phone.json rename to app/src/main/assets/layouts/phone/phone.json diff --git a/app/src/main/assets/layouts/phone_symbols.json b/app/src/main/assets/layouts/phone_symbols/phone_symbols.json similarity index 100% rename from app/src/main/assets/layouts/phone_symbols.json rename to app/src/main/assets/layouts/phone_symbols/phone_symbols.json diff --git a/app/src/main/assets/layouts/symbols.txt b/app/src/main/assets/layouts/symbols/symbols.txt similarity index 100% rename from app/src/main/assets/layouts/symbols.txt rename to app/src/main/assets/layouts/symbols/symbols.txt diff --git a/app/src/main/assets/layouts/symbols_arabic.txt b/app/src/main/assets/layouts/symbols/symbols_arabic.txt similarity index 100% rename from app/src/main/assets/layouts/symbols_arabic.txt rename to app/src/main/assets/layouts/symbols/symbols_arabic.txt diff --git a/app/src/main/java/helium314/keyboard/keyboard/KeyboardLayoutSet.java b/app/src/main/java/helium314/keyboard/keyboard/KeyboardLayoutSet.java index e527e4908..0a834fe76 100644 --- a/app/src/main/java/helium314/keyboard/keyboard/KeyboardLayoutSet.java +++ b/app/src/main/java/helium314/keyboard/keyboard/KeyboardLayoutSet.java @@ -16,9 +16,9 @@ import helium314.keyboard.keyboard.internal.KeyboardBuilder; import helium314.keyboard.keyboard.internal.KeyboardIconsSet; import helium314.keyboard.keyboard.internal.KeyboardParams; import helium314.keyboard.keyboard.internal.UniqueKeysCache; +import helium314.keyboard.keyboard.internal.keyboard_parser.LayoutParser; import helium314.keyboard.keyboard.internal.keyboard_parser.LocaleKeyboardInfos; import helium314.keyboard.keyboard.internal.keyboard_parser.LocaleKeyboardInfosKt; -import helium314.keyboard.keyboard.internal.keyboard_parser.RawKeyboardParser; import helium314.keyboard.latin.RichInputMethodManager; import helium314.keyboard.latin.RichInputMethodSubtype; import helium314.keyboard.latin.settings.Settings; @@ -104,7 +104,7 @@ public final class KeyboardLayoutSet { private static void clearKeyboardCache() { sKeyboardCache.clear(); sUniqueKeysCache.clear(); - RawKeyboardParser.INSTANCE.clearCache(); + LayoutParser.INSTANCE.clearCache(); KeyboardIconsSet.Companion.setNeedsReload(true); } 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 4d5e3c630..b0ae6711c 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 @@ -17,10 +17,9 @@ import helium314.keyboard.keyboard.internal.keyboard_parser.floris.TextKeyData import helium314.keyboard.latin.common.isEmoji import helium314.keyboard.latin.define.DebugFlags import helium314.keyboard.latin.settings.Settings +import helium314.keyboard.latin.utils.LayoutType 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.replaceFirst import helium314.keyboard.latin.utils.splitAt import helium314.keyboard.latin.utils.sumOf @@ -47,7 +46,20 @@ class KeyboardParser(private val params: KeyboardParams, private val context: Co fun parseLayout(): ArrayList> { params.readAttributes(context, null) - val baseKeys = RawKeyboardParser.parseLayout(params, context) + // todo: maybe determine layoutType earlier, and to less stuff based on elementId + val layoutType = when (params.mId.mElementId) { + KeyboardId.ELEMENT_SYMBOLS -> LayoutType.SYMBOLS + KeyboardId.ELEMENT_SYMBOLS_SHIFTED -> LayoutType.MORE_SYMBOLS + KeyboardId.ELEMENT_PHONE -> LayoutType.PHONE + KeyboardId.ELEMENT_PHONE_SYMBOLS -> LayoutType.PHONE_SYMBOLS + KeyboardId.ELEMENT_NUMBER -> LayoutType.NUMBER + KeyboardId.ELEMENT_NUMPAD -> if (Settings.getInstance().current.mDisplayOrientation == Configuration.ORIENTATION_LANDSCAPE) + LayoutType.NUMPAD_LANDSCAPE else LayoutType.NUMPAD + KeyboardId.ELEMENT_EMOJI_BOTTOM_ROW -> LayoutType.EMOJI_BOTTOM + KeyboardId.ELEMENT_CLIPBOARD_BOTTOM_ROW -> LayoutType.CLIPBOARD_BOTTOM + else -> LayoutType.MAIN + } + val baseKeys = LayoutParser.parseLayout(layoutType, params, context) val keysInRows = createRows(baseKeys) val heightRescale: Float if (params.mId.isEmojiClipBottomRow) { @@ -94,7 +106,7 @@ class KeyboardParser(private val params: KeyboardParams, private val context: Co if (!params.mAllowRedundantPopupKeys) params.baseKeys = baseKeys.flatMap { it.map { it.toKeyParams(params) } } - val allFunctionalKeys = RawKeyboardParser.parseLayout(params, context, true) + val allFunctionalKeys = LayoutParser.parseLayout(LayoutType.FUNCTIONAL, params, context) adjustBottomFunctionalRowAndBaseKeys(allFunctionalKeys, baseKeys) if (allFunctionalKeys.none { it.singleOrNull()?.isKeyPlaceholder() == true }) @@ -272,8 +284,7 @@ class KeyboardParser(private val params: KeyboardParams, private val context: Co } private fun addSymbolPopupKeys(baseKeys: MutableList>) { - val layoutName = if (params.mId.locale.script() == ScriptUtils.SCRIPT_ARABIC) LAYOUT_SYMBOLS_ARABIC else LAYOUT_SYMBOLS - val layout = RawKeyboardParser.parseLayout(layoutName, params, context) + val layout = LayoutParser.parseLayout(LayoutType.SYMBOLS, params, context) layout.forEachIndexed { i, row -> val baseRow = baseKeys.getOrNull(i) ?: return@forEachIndexed row.forEachIndexed { j, key -> @@ -283,7 +294,7 @@ class KeyboardParser(private val params: KeyboardParams, private val context: Co } private fun getNumberRow(): MutableList { - val row = RawKeyboardParser.parseLayout(LAYOUT_NUMBER_ROW, params, context).first() + val row = LayoutParser.parseLayout(LayoutType.NUMBER_ROW, params, context).first() val localizedNumbers = params.mLocaleKeyboardInfos.localizedNumberKeys if (localizedNumbers?.size != 10) return row if (Settings.getInstance().current.mLocalizedNumberRow) { diff --git a/app/src/main/java/helium314/keyboard/keyboard/internal/keyboard_parser/RawKeyboardParser.kt b/app/src/main/java/helium314/keyboard/keyboard/internal/keyboard_parser/LayoutParser.kt similarity index 57% rename from app/src/main/java/helium314/keyboard/keyboard/internal/keyboard_parser/RawKeyboardParser.kt rename to app/src/main/java/helium314/keyboard/keyboard/internal/keyboard_parser/LayoutParser.kt index 14f5ea409..09071993a 100644 --- a/app/src/main/java/helium314/keyboard/keyboard/internal/keyboard_parser/RawKeyboardParser.kt +++ b/app/src/main/java/helium314/keyboard/keyboard/internal/keyboard_parser/LayoutParser.kt @@ -2,8 +2,6 @@ package helium314.keyboard.keyboard.internal.keyboard_parser import android.content.Context -import android.content.res.Configuration -import helium314.keyboard.keyboard.KeyboardId import helium314.keyboard.keyboard.internal.KeyboardParams import helium314.keyboard.keyboard.internal.keyboard_parser.floris.AbstractKeyData import helium314.keyboard.keyboard.internal.keyboard_parser.floris.AutoTextKeyData @@ -19,45 +17,32 @@ import helium314.keyboard.keyboard.internal.keyboard_parser.floris.TextKeyData import helium314.keyboard.keyboard.internal.keyboard_parser.floris.VariationSelector import helium314.keyboard.keyboard.internal.keyboard_parser.floris.toTextKey import helium314.keyboard.latin.common.splitOnWhitespace +import helium314.keyboard.latin.settings.Defaults.default import helium314.keyboard.latin.settings.Settings import helium314.keyboard.latin.utils.CUSTOM_LAYOUT_PREFIX +import helium314.keyboard.latin.utils.LayoutType +import helium314.keyboard.latin.utils.LayoutType.Companion.folder import helium314.keyboard.latin.utils.Log -import helium314.keyboard.latin.utils.ScriptUtils -import helium314.keyboard.latin.utils.ScriptUtils.script -import helium314.keyboard.latin.utils.getCustomFunctionalLayoutName -import helium314.keyboard.latin.utils.getCustomLayoutFile import helium314.keyboard.latin.utils.getCustomLayoutFiles +import helium314.keyboard.latin.utils.prefs import kotlinx.serialization.ExperimentalSerializationApi import kotlinx.serialization.json.Json import kotlinx.serialization.modules.SerializersModule import kotlinx.serialization.modules.polymorphic -import java.io.File -object RawKeyboardParser { - private const val TAG = "RawKeyboardParser" - private val rawLayoutCache = hashMapOf MutableList>>() +object LayoutParser { + private const val TAG = "LayoutParser" + private val layoutCache = hashMapOf MutableList>>() - val symbolAndNumberLayouts = listOf(LAYOUT_SYMBOLS, LAYOUT_SYMBOLS_SHIFTED, LAYOUT_SYMBOLS_ARABIC, - LAYOUT_NUMBER, LAYOUT_NUMPAD, LAYOUT_NUMPAD_LANDSCAPE, LAYOUT_PHONE, LAYOUT_PHONE_SYMBOLS, - LAYOUT_NUMBER_ROW, LAYOUT_EMOJI_BOTTOM_ROW, LAYOUT_CLIPBOARD_BOTTOM_ROW) + fun clearCache() = layoutCache.clear() - fun clearCache() = rawLayoutCache.clear() - - fun parseLayout(params: KeyboardParams, context: Context, isFunctional: Boolean = false): MutableList> { - val layoutName = if (isFunctional) { - if (!params.mId.isAlphaOrSymbolKeyboard) return mutableListOf(mutableListOf()) - else getFunctionalLayoutName(params, context) - } else { - getLayoutName(params, context) - } - return rawLayoutCache.getOrPut(layoutName) { - createCacheLambda(layoutName, context) - }(params) - } - - fun parseLayout(layoutName: String, params: KeyboardParams, context: Context): MutableList> { - return rawLayoutCache.getOrPut(layoutName) { - createCacheLambda(layoutName, context) + fun parseLayout(layoutType: LayoutType, params: KeyboardParams, context: Context): MutableList> { + if (layoutType == LayoutType.FUNCTIONAL && !params.mId.isAlphaOrSymbolKeyboard) + return mutableListOf(mutableListOf()) // no functional keys + val layoutName = if (layoutType == LayoutType.MAIN) params.mId.mSubtype.mainLayoutName + else params.mId.mSubtype.layouts[layoutType] ?: Settings.getLayoutName(layoutType, context.prefs()) + return layoutCache.getOrPut(layoutType.name + layoutName) { + createCacheLambda(layoutType, layoutName, context) }(params) } @@ -89,25 +74,12 @@ object RawKeyboardParser { else split.first().toTextKey(split.drop(1)) } - private fun createCacheLambda(layoutName: String, context: Context): (KeyboardParams) -> MutableList> { - val layoutFileName = getLayoutFileName(layoutName, context) - val layoutText = if (layoutFileName.startsWith(CUSTOM_LAYOUT_PREFIX)) { + private fun createCacheLambda(layoutType: LayoutType, layoutName: String, context: Context): + (KeyboardParams) -> MutableList> { + val layoutFileContent = getLayoutFileContent(layoutType, layoutName.substringBefore("+"), context).trimStart() + if (layoutFileContent.startsWith("[") || (layoutName.startsWith(CUSTOM_LAYOUT_PREFIX) && layoutFileContent.startsWith("/"))) { try { - getCustomLayoutFile(layoutFileName, context).readText().trimStart() - } catch (e: Exception) { // fall back to defaults if for some reason file is broken - val name = when { - layoutName.contains("functional") -> "functional_keys.json" - layoutName.contains("number_row") -> "number_row.txt" - layoutName.contains("symbols") -> "symbols.txt" - else -> "qwerty.txt" - } - Log.e(TAG, "cannot open layout $layoutName, falling back to $name", e) - context.assets.open("layouts${File.separator}$name").reader().use { it.readText() } - } - } else context.assets.open("layouts${File.separator}$layoutFileName").reader().use { it.readText() } - if (layoutFileName.endsWith(".json") || (layoutFileName.startsWith(CUSTOM_LAYOUT_PREFIX) && layoutText.startsWith("["))) { - try { - val florisKeyData = parseJsonString(layoutText, false) + val florisKeyData = parseJsonString(layoutFileContent, false) return { params -> florisKeyData.mapTo(mutableListOf()) { row -> row.mapNotNullTo(mutableListOf()) { it.compute(params) } @@ -118,60 +90,26 @@ object RawKeyboardParser { } } // not a json, or invalid json - val simpleKeyData = parseSimpleString(layoutText) + val simpleKeyData = parseSimpleString(layoutFileContent) return { params -> simpleKeyData.mapIndexedTo(mutableListOf()) { i, row -> val newRow = row.toMutableList() - if (params.mId.isAlphabetKeyboard - && params.mId.mSubtype.mainLayoutName.endsWith("+") - && "$layoutName+" == params.mId.mSubtype.mainLayoutName - ) { + if (params.mId.isAlphabetKeyboard && layoutName.endsWith("+")) params.mLocaleKeyboardInfos.getExtraKeys(i+1)?.let { newRow.addAll(it) } - } newRow } } } - private fun getLayoutName(params: KeyboardParams, context: Context) = when (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 - LAYOUT_NUMPAD - KeyboardId.ELEMENT_NUMBER -> LAYOUT_NUMBER - KeyboardId.ELEMENT_PHONE -> LAYOUT_PHONE - KeyboardId.ELEMENT_PHONE_SYMBOLS -> LAYOUT_PHONE_SYMBOLS - KeyboardId.ELEMENT_EMOJI_BOTTOM_ROW -> LAYOUT_EMOJI_BOTTOM_ROW - KeyboardId.ELEMENT_CLIPBOARD_BOTTOM_ROW -> LAYOUT_CLIPBOARD_BOTTOM_ROW - else -> params.mId.mSubtype.mainLayoutName.substringBeforeLast("+") - } - - private fun getFunctionalLayoutName(params: KeyboardParams, context: Context): String { - if (Settings.getInstance().current.mHasCustomFunctionalLayout) { - getCustomFunctionalLayoutName(params.mId.mElementId, params.mId.mSubtype.rawSubtype, context) - ?.let { return it } - } - return if (Settings.getInstance().isTablet) "functional_keys_tablet" else "functional_keys" - } - - /** returns the file name matching the layout name, making sure the file exists (falling back to qwerty.txt) */ - private fun getLayoutFileName(layoutName: String, context: Context): String { - val customFiles = getCustomLayoutFiles(context).map { it.name } - if (layoutName.startsWith(CUSTOM_LAYOUT_PREFIX)) { - return customFiles.firstOrNull { it.startsWith(layoutName)} - ?: if (layoutName.contains("functional")) "functional_keys.json" else "qwerty.txt" // fallback to defaults - } - val assetsFiles by lazy { context.assets.list("layouts")!! } - return if (layoutName in symbolAndNumberLayouts) { - customFiles.firstOrNull { it.startsWith("$CUSTOM_LAYOUT_PREFIX$layoutName.")} - ?: assetsFiles.first { it.startsWith(layoutName) } - } else { - // can't be custom layout, so it must be in assets - val searchName = layoutName.substringBeforeLast("+") // consider there are layouts ending in "+" for adding extra keys - assetsFiles.firstOrNull { it.startsWith(searchName) } ?: "qwerty.txt" // in case it was removed - } + private fun getLayoutFileContent(layoutType: LayoutType, layoutName: String, context: Context): String { + if (layoutName.startsWith(CUSTOM_LAYOUT_PREFIX)) + getCustomLayoutFiles(layoutType, context) + .firstOrNull { it.name.startsWith(layoutName) }?.let { return it.readText() } + val layouts = context.assets.list(layoutType.folder)!! + layouts.firstOrNull { it.startsWith("$layoutName.") } + ?.let { return context.assets.open(layoutType.folder + it).reader().readText() } + val fallback = layouts.first { it.startsWith(layoutType.default) } // must exist! + return context.assets.open(layoutType.folder + fallback).reader().readText() } // allow commenting lines by starting them with "//" 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 70f696c9f..1fa28dfa4 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 @@ -195,6 +195,9 @@ fun addLocaleKeyTextsToParams(context: Context, params: KeyboardParams, popupKey } } +fun hasLocalizedNumberRow(locale: Locale, context: Context) = + getStreamForLocale(locale, context)?.bufferedReader()?.readLines()?.any { it == "[number_row]" } == true + private fun createLocaleKeyTexts(context: Context, params: KeyboardParams, popupKeysSetting: Int): LocaleKeyboardInfos { val lkt = LocaleKeyboardInfos(getStreamForLocale(params.mId.locale, context), params.mId.locale) params.mSecondaryLocales.forEach { locale -> diff --git a/app/src/main/java/helium314/keyboard/latin/App.kt b/app/src/main/java/helium314/keyboard/latin/App.kt index 776032957..1de81b046 100644 --- a/app/src/main/java/helium314/keyboard/latin/App.kt +++ b/app/src/main/java/helium314/keyboard/latin/App.kt @@ -3,7 +3,6 @@ package helium314.keyboard.latin import android.app.Application import android.content.Context -import android.content.SharedPreferences import androidx.core.content.edit import helium314.keyboard.keyboard.ColorSetting import helium314.keyboard.keyboard.KeyboardTheme @@ -15,9 +14,13 @@ import helium314.keyboard.latin.settings.Settings import helium314.keyboard.latin.settings.USER_DICTIONARY_SUFFIX import helium314.keyboard.latin.settings.colorPrefsAndResIds 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.LayoutType +import helium314.keyboard.latin.utils.LayoutType.Companion.folder import helium314.keyboard.latin.utils.ToolbarKey import helium314.keyboard.latin.utils.defaultPinnedToolbarPref +import helium314.keyboard.latin.utils.encodeBase36 import helium314.keyboard.latin.utils.getCustomLayoutFile import helium314.keyboard.latin.utils.getCustomLayoutFiles import helium314.keyboard.latin.utils.onCustomLayoutFileListChanged @@ -236,6 +239,120 @@ fun checkVersionUpgrade(context: Context) { } } writeCustomKeyCodes(prefs, combined) } + if (oldVersion <= 2303) { + File(DeviceProtectedUtils.getFilesDir(context), "layouts").listFiles()?.forEach { file -> + val folder = DeviceProtectedUtils.getFilesDir(context) + when (file.name) { + "${CUSTOM_LAYOUT_PREFIX}symbols." -> { + val dir = File(folder, LayoutType.SYMBOLS.folder) + dir.mkdirs() + val name = "$CUSTOM_LAYOUT_PREFIX${encodeBase36("symbols")}." + file.renameTo(File(dir, name)) + prefs.edit().putString(Settings.PREF_LAYOUT_PREFIX + LayoutType.SYMBOLS.name, name).apply() + } + "${CUSTOM_LAYOUT_PREFIX}symbols_shifted." -> { + val dir = File(folder, LayoutType.MORE_SYMBOLS.folder) + dir.mkdirs() + val name = "$CUSTOM_LAYOUT_PREFIX${encodeBase36("symbols_shifted")}." + file.renameTo(File(dir, name)) + prefs.edit().putString(Settings.PREF_LAYOUT_PREFIX + LayoutType.MORE_SYMBOLS.name, name).apply() + } + "${CUSTOM_LAYOUT_PREFIX}symbols_arabic." -> { + val dir = File(folder, LayoutType.SYMBOLS.folder) + dir.mkdirs() + val name = "$CUSTOM_LAYOUT_PREFIX${encodeBase36("symbols_arabic")}." + file.renameTo(File(dir, name)) + } + "${CUSTOM_LAYOUT_PREFIX}numpad." -> { + val dir = File(folder, LayoutType.NUMPAD.folder) + dir.mkdirs() + val name = "$CUSTOM_LAYOUT_PREFIX${encodeBase36("numpad")}." + file.renameTo(File(dir, name)) + prefs.edit().putString(Settings.PREF_LAYOUT_PREFIX + LayoutType.NUMPAD.name, name).apply() + } + "${CUSTOM_LAYOUT_PREFIX}numpad_landscape." -> { + val dir = File(folder, LayoutType.NUMPAD_LANDSCAPE.folder) + dir.mkdirs() + val name = "$CUSTOM_LAYOUT_PREFIX${encodeBase36("numpad_landscape")}." + file.renameTo(File(dir, name)) + prefs.edit().putString(Settings.PREF_LAYOUT_PREFIX + LayoutType.NUMPAD_LANDSCAPE.name, name).apply() + } + "${CUSTOM_LAYOUT_PREFIX}number." -> { + val dir = File(folder, LayoutType.NUMBER.folder) + dir.mkdirs() + val name = "$CUSTOM_LAYOUT_PREFIX${encodeBase36("number")}." + file.renameTo(File(dir, name)) + prefs.edit().putString(Settings.PREF_LAYOUT_PREFIX + LayoutType.NUMBER.name, name).apply() + } + "${CUSTOM_LAYOUT_PREFIX}phone." -> { + val dir = File(folder, LayoutType.PHONE.folder) + dir.mkdirs() + val name = "$CUSTOM_LAYOUT_PREFIX${encodeBase36("phone")}." + file.renameTo(File(dir, name)) + prefs.edit().putString(Settings.PREF_LAYOUT_PREFIX + LayoutType.PHONE.name, name).apply() + } + "${CUSTOM_LAYOUT_PREFIX}phone_symbols." -> { + val dir = File(folder, LayoutType.PHONE_SYMBOLS.folder) + dir.mkdirs() + val name = "$CUSTOM_LAYOUT_PREFIX${encodeBase36("phone_symbols")}." + file.renameTo(File(dir, name)) + prefs.edit().putString(Settings.PREF_LAYOUT_PREFIX + LayoutType.PHONE_SYMBOLS.name, name).apply() + } + "${CUSTOM_LAYOUT_PREFIX}number_row." -> { + val dir = File(folder, LayoutType.NUMBER_ROW.folder) + dir.mkdirs() + val name = "$CUSTOM_LAYOUT_PREFIX${encodeBase36("number_row")}." + file.renameTo(File(dir, name)) + prefs.edit().putString(Settings.PREF_LAYOUT_PREFIX + LayoutType.NUMBER_ROW.name, name).apply() + } + "${CUSTOM_LAYOUT_PREFIX}emoji_bottom_row." -> { + val dir = File(folder, LayoutType.EMOJI_BOTTOM.folder) + dir.mkdirs() + val name = "$CUSTOM_LAYOUT_PREFIX${encodeBase36("emoji_bottom_row")}." + file.renameTo(File(dir, name)) + prefs.edit().putString(Settings.PREF_LAYOUT_PREFIX + LayoutType.EMOJI_BOTTOM.name, name).apply() + } + "${CUSTOM_LAYOUT_PREFIX}clip_bottom_row." -> { + val dir = File(folder, LayoutType.CLIPBOARD_BOTTOM.folder) + dir.mkdirs() + val name = "$CUSTOM_LAYOUT_PREFIX${encodeBase36("clip_bottom_row")}." + file.renameTo(File(dir, name)) + prefs.edit().putString(Settings.PREF_LAYOUT_PREFIX + LayoutType.CLIPBOARD_BOTTOM.name, name).apply() + } + "${CUSTOM_LAYOUT_PREFIX}functional_keys." -> { + val dir = File(folder, LayoutType.FUNCTIONAL.folder) + dir.mkdirs() + val name = "$CUSTOM_LAYOUT_PREFIX${encodeBase36("functional_keys")}." + file.renameTo(File(dir, name)) + prefs.edit().putString(Settings.PREF_LAYOUT_PREFIX + LayoutType.FUNCTIONAL.name, name).apply() + } + "${CUSTOM_LAYOUT_PREFIX}functional_keys_symbols." -> { + val dir = File(folder, LayoutType.FUNCTIONAL.folder) + dir.mkdirs() + val name = "$CUSTOM_LAYOUT_PREFIX${encodeBase36("functional_keys_symbols")}." + file.renameTo(File(dir, name)) + } + "${CUSTOM_LAYOUT_PREFIX}functional_keys_symbols_shifted." -> { + val dir = File(folder, LayoutType.FUNCTIONAL.folder) + dir.mkdirs() + val name = "$CUSTOM_LAYOUT_PREFIX${encodeBase36("functional_keys_symbols_shifted")}." + file.renameTo(File(dir, name)) + } + else -> { + // main layouts + val dir = File(folder, LayoutType.MAIN.folder) + dir.mkdirs() + file.renameTo(File(dir, file.name)) + // todo: maybe rename to custom.latn.name. instead of custom.en-GB.name. for latin script? + // just make sure the subtypes are still working when the file name is different (need to upgrade PREF_ADDITIONAL_SUBTYPES) + // also consider name collision when a user has layout with the same name for 2 languages + // decode name, append number, encode name + } + } + } + if (prefs.contains(Settings.PREF_ADDITIONAL_SUBTYPES)) + prefs.edit().putString(Settings.PREF_ADDITIONAL_SUBTYPES, prefs.getString(Settings.PREF_ADDITIONAL_SUBTYPES, "")!!.replace(":", "§")).apply() + } upgradeToolbarPrefs(prefs) onCustomLayoutFileListChanged() // just to be sure prefs.edit { putInt(Settings.PREF_VERSION_CODE, BuildConfig.VERSION_CODE) } diff --git a/app/src/main/java/helium314/keyboard/latin/RichInputMethodSubtype.kt b/app/src/main/java/helium314/keyboard/latin/RichInputMethodSubtype.kt index 2cba7202a..58ee4ed89 100644 --- a/app/src/main/java/helium314/keyboard/latin/RichInputMethodSubtype.kt +++ b/app/src/main/java/helium314/keyboard/latin/RichInputMethodSubtype.kt @@ -35,6 +35,7 @@ class RichInputMethodSubtype private constructor(val rawSubtype: InputMethodSubt val mainLayoutName: String get() = layouts[LayoutType.MAIN] ?: "qwerty" + /** layout names for this subtype by LayoutType */ val layouts = LayoutType.getLayoutMap(getExtraValueOf(KEYBOARD_LAYOUT_SET) ?: "") val isCustom: Boolean get() = mainLayoutName.startsWith(CUSTOM_LAYOUT_PREFIX) 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 4b482d5e2..373b376e9 100644 --- a/app/src/main/java/helium314/keyboard/latin/settings/AdvancedSettingsFragment.kt +++ b/app/src/main/java/helium314/keyboard/latin/settings/AdvancedSettingsFragment.kt @@ -22,7 +22,6 @@ import androidx.core.content.edit import androidx.core.widget.doAfterTextChanged import androidx.preference.Preference import androidx.preference.PreferenceManager -import kotlinx.serialization.encodeToString import kotlinx.serialization.json.Json import helium314.keyboard.dictionarypack.DictionaryPackConstants import helium314.keyboard.keyboard.KeyboardActionListener @@ -37,7 +36,6 @@ 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.keyboard.internal.keyboard_parser.RawKeyboardParser import helium314.keyboard.latin.AudioAndHapticFeedbackManager import helium314.keyboard.latin.BuildConfig import helium314.keyboard.latin.R @@ -165,7 +163,7 @@ class AdvancedSettingsFragment : SubScreenFragment() { } private fun showCustomizeSymbolNumberLayoutsDialog() { - val layoutNames = RawKeyboardParser.symbolAndNumberLayouts.map { it.getStringResourceOrName("layout_", requireContext()) }.toTypedArray() +/* val layoutNames = RawKeyboardParser.symbolAndNumberLayouts.map { it.getStringResourceOrName("layout_", requireContext()) }.toTypedArray() AlertDialog.Builder(requireContext()) .setTitle(R.string.customize_symbols_number_layouts) .setItems(layoutNames) { di, i -> @@ -174,7 +172,7 @@ class AdvancedSettingsFragment : SubScreenFragment() { } .setNegativeButton(android.R.string.cancel, null) .show() - } +*/ } private fun customizeSymbolNumberLayout(layoutName: String) { val customLayoutName = getCustomLayoutFiles(requireContext()).map { it.name } diff --git a/app/src/main/java/helium314/keyboard/latin/settings/Defaults.kt b/app/src/main/java/helium314/keyboard/latin/settings/Defaults.kt index 44e502dcd..e178d1dd8 100644 --- a/app/src/main/java/helium314/keyboard/latin/settings/Defaults.kt +++ b/app/src/main/java/helium314/keyboard/latin/settings/Defaults.kt @@ -9,6 +9,7 @@ import helium314.keyboard.keyboard.KeyboardTheme import helium314.keyboard.latin.BuildConfig import helium314.keyboard.latin.utils.AdditionalSubtypeUtils import helium314.keyboard.latin.utils.JniUtils +import helium314.keyboard.latin.utils.LayoutType import helium314.keyboard.latin.utils.POPUP_KEYS_LABEL_DEFAULT import helium314.keyboard.latin.utils.POPUP_KEYS_ORDER_DEFAULT import helium314.keyboard.latin.utils.defaultClipboardToolbarPref @@ -27,6 +28,22 @@ object Defaults { PREF_POPUP_ON = dm.widthPixels >= px600 || dm.heightPixels >= px600 } + // must correspond to a file name + val LayoutType.default get() = when (this) { + LayoutType.MAIN -> "qwerty" + LayoutType.SYMBOLS -> "symbols" + LayoutType.MORE_SYMBOLS -> "symbols_shifted" + LayoutType.FUNCTIONAL -> if (Settings.getInstance().isTablet) "functional_keys_tablet" else "functional_keys" + LayoutType.NUMBER -> "number" + LayoutType.NUMBER_ROW -> "number_row" + LayoutType.NUMPAD -> "numpad" + LayoutType.NUMPAD_LANDSCAPE -> "numpad_landscape" + LayoutType.PHONE -> "phone" + LayoutType.PHONE_SYMBOLS -> "phone_symbols" + LayoutType.EMOJI_BOTTOM -> "emoji_bottom_row" + LayoutType.CLIPBOARD_BOTTOM -> "clipboard_bottom_row" + } + const val PREF_THEME_STYLE = KeyboardTheme.STYLE_MATERIAL const val PREF_ICON_STYLE = KeyboardTheme.STYLE_MATERIAL const val PREF_THEME_COLORS = KeyboardTheme.THEME_LIGHT @@ -56,8 +73,10 @@ object Defaults { const val PREF_LANGUAGE_SWITCH_KEY = "internal" const val PREF_SHOW_EMOJI_KEY = false const val PREF_VARIABLE_TOOLBAR_DIRECTION = true - const val PREF_ADDITIONAL_SUBTYPES = "de:qwerty:AsciiCapable${AdditionalSubtypeUtils.PREF_SUBTYPE_SEPARATOR}" + - "fr:qwertz:AsciiCapable${AdditionalSubtypeUtils.PREF_SUBTYPE_SEPARATOR}hu:qwerty:AsciiCapable" + private const val ls = AdditionalSubtypeUtils.LOCALE_AND_EXTRA_SEPARATOR + private const val subs = AdditionalSubtypeUtils.PREF_SUBTYPE_SEPARATOR + const val PREF_ADDITIONAL_SUBTYPES = "de${ls}qwerty${ls}AsciiCapable${subs}" + + "fr${ls}qwertz:${ls}AsciiCapable${subs}hu${ls}qwerty${ls}AsciiCapable" const val PREF_ENABLE_SPLIT_KEYBOARD = false const val PREF_ENABLE_SPLIT_KEYBOARD_LANDSCAPE = false const val PREF_SPLIT_SPACER_SCALE = SettingsValues.DEFAULT_SIZE_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 ad51ce7eb..e7caaffc5 100644 --- a/app/src/main/java/helium314/keyboard/latin/settings/LanguageSettingsDialog.kt +++ b/app/src/main/java/helium314/keyboard/latin/settings/LanguageSettingsDialog.kt @@ -137,7 +137,7 @@ class LanguageSettingsDialog( val layouts = mutableListOf() val displayNames = mutableListOf() infos.forEach { - val mainLayoutName = it.subtype.mainLayoutName() + val mainLayoutName = it.subtype.mainLayoutName() ?: "qwerty" if (!mainLayoutName.startsWith(CUSTOM_LAYOUT_PREFIX) // don't allow copying custom layout (at least for now) && !mainLayoutName.endsWith("+")) { // don't allow copying layouts only defined via extra keys layouts.add(mainLayoutName) @@ -168,7 +168,7 @@ class LanguageSettingsDialog( private fun addSubtypeToView(subtype: SubtypeInfo) { val row = LayoutInflater.from(context).inflate(R.layout.language_list_item, listView) - val layoutSetName = subtype.subtype.mainLayoutName() + val layoutSetName = subtype.subtype.mainLayoutName() ?: "qwerty" row.findViewById(R.id.language_name).text = SubtypeLocaleUtils.getKeyboardLayoutSetDisplayName(subtype.subtype) ?: subtype.subtype.displayName(context) 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 76a4f5e71..e537864d9 100644 --- a/app/src/main/java/helium314/keyboard/latin/settings/Settings.java +++ b/app/src/main/java/helium314/keyboard/latin/settings/Settings.java @@ -32,6 +32,7 @@ import helium314.keyboard.latin.common.LocaleUtils; import helium314.keyboard.latin.utils.AdditionalSubtypeUtils; import helium314.keyboard.latin.utils.DeviceProtectedUtils; import helium314.keyboard.latin.utils.KtxKt; +import helium314.keyboard.latin.utils.LayoutType; import helium314.keyboard.latin.utils.Log; import helium314.keyboard.latin.utils.ResourceUtils; import helium314.keyboard.latin.utils.RunInLocaleKt; @@ -68,6 +69,7 @@ public final class Settings implements SharedPreferences.OnSharedPreferenceChang public static final String PREF_CUSTOM_ICON_NAMES = "custom_icon_names"; public static final String PREF_TOOLBAR_CUSTOM_KEY_CODES = "toolbar_custom_key_codes"; + public static final String PREF_LAYOUT_PREFIX = "layout_"; public static final String PREF_AUTO_CAP = "auto_cap"; public static final String PREF_VIBRATE_ON = "vibrate_on"; @@ -549,6 +551,10 @@ public final class Settings implements SharedPreferences.OnSharedPreferenceChang return new File(DeviceProtectedUtils.getFilesDir(context), "custom_font"); } + public static String getLayoutName(final LayoutType type, final SharedPreferences prefs) { + return prefs.getString(PREF_LAYOUT_PREFIX + type.name(), Defaults.INSTANCE.getDefault(type)); + } + @Nullable public Typeface getCustomTypeface() { if (!sCustomTypefaceLoaded) { 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 1bd262e44..f029f1524 100644 --- a/app/src/main/java/helium314/keyboard/latin/settings/SettingsValues.java +++ b/app/src/main/java/helium314/keyboard/latin/settings/SettingsValues.java @@ -144,7 +144,6 @@ public class SettingsValues { public final SettingsValuesForSuggestion mSettingsValuesForSuggestion; public final boolean mIncognitoModeEnabled; public final boolean mLongPressSymbolsForNumpad; - public final boolean mHasCustomFunctionalLayout; public final int mEmojiMaxSdk; // User-defined colors @@ -276,7 +275,6 @@ public class SettingsValues { mLongPressSymbolsForNumpad = prefs.getBoolean(Settings.PREFS_LONG_PRESS_SYMBOLS_FOR_NUMPAD, Defaults.PREFS_LONG_PRESS_SYMBOLS_FOR_NUMPAD); mAutoShowToolbar = prefs.getBoolean(Settings.PREF_AUTO_SHOW_TOOLBAR, Defaults.PREF_AUTO_SHOW_TOOLBAR); mAutoHideToolbar = suggestionsEnabled && prefs.getBoolean(Settings.PREF_AUTO_HIDE_TOOLBAR, Defaults.PREF_AUTO_HIDE_TOOLBAR); - mHasCustomFunctionalLayout = CustomLayoutUtilsKt.hasCustomFunctionalLayout(selectedSubtype, context); mAlphaAfterEmojiInEmojiView = prefs.getBoolean(Settings.PREF_ABC_AFTER_EMOJI, Defaults.PREF_ABC_AFTER_EMOJI); mAlphaAfterClipHistoryEntry = prefs.getBoolean(Settings.PREF_ABC_AFTER_CLIP, Defaults.PREF_ABC_AFTER_CLIP); mAlphaAfterSymbolAndSpace = prefs.getBoolean(Settings.PREF_ABC_AFTER_SYMBOL_SPACE, Defaults.PREF_ABC_AFTER_SYMBOL_SPACE); diff --git a/app/src/main/java/helium314/keyboard/latin/utils/AdditionalSubtypeUtils.java b/app/src/main/java/helium314/keyboard/latin/utils/AdditionalSubtypeUtils.java index c264a0c4e..6a7cf700b 100644 --- a/app/src/main/java/helium314/keyboard/latin/utils/AdditionalSubtypeUtils.java +++ b/app/src/main/java/helium314/keyboard/latin/utils/AdditionalSubtypeUtils.java @@ -38,7 +38,7 @@ public final class AdditionalSubtypeUtils { return subtype.containsExtraValueKey(IS_ADDITIONAL_SUBTYPE); } - private static final String LOCALE_AND_LAYOUT_SEPARATOR = ":"; + public static final String LOCALE_AND_EXTRA_SEPARATOR = "§"; private static final int INDEX_OF_LANGUAGE_TAG = 0; private static final int INDEX_OF_KEYBOARD_LAYOUT = 1; private static final int INDEX_OF_EXTRA_VALUE = 2; @@ -85,10 +85,12 @@ public final class AdditionalSubtypeUtils { final String extraValue = StringUtils.removeFromCommaSplittableTextIfExists( layoutExtraValue, StringUtils.removeFromCommaSplittableTextIfExists( IS_ADDITIONAL_SUBTYPE, subtype.getExtraValue())); - final String basePrefSubtype = SubtypeUtilsKt.locale(subtype).toLanguageTag() + LOCALE_AND_LAYOUT_SEPARATOR + if (extraValue.contains(PREF_SUBTYPE_SEPARATOR) || extraValue.contains(LOCALE_AND_EXTRA_SEPARATOR)) + throw new IllegalArgumentException("extra value contains not allowed characters " + extraValue); + final String basePrefSubtype = SubtypeUtilsKt.locale(subtype).toLanguageTag() + LOCALE_AND_EXTRA_SEPARATOR + keyboardLayoutSetName; return extraValue.isEmpty() ? basePrefSubtype - : basePrefSubtype + LOCALE_AND_LAYOUT_SEPARATOR + extraValue; + : basePrefSubtype + LOCALE_AND_EXTRA_SEPARATOR + extraValue; } public static InputMethodSubtype[] createAdditionalSubtypesArray(final String prefSubtypes) { @@ -107,7 +109,7 @@ public final class AdditionalSubtypeUtils { // use string created with getPrefSubtype public static InputMethodSubtype createSubtypeFromString(final String prefSubtype) { - final String[] elems = prefSubtype.split(LOCALE_AND_LAYOUT_SEPARATOR); + final String[] elems = prefSubtype.split(LOCALE_AND_EXTRA_SEPARATOR); if (elems.length != LENGTH_WITHOUT_EXTRA_VALUE && elems.length != LENGTH_WITH_EXTRA_VALUE) { Log.w(TAG, "Unknown additional subtype specified: " + prefSubtype); 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 a3cbbcb6f..6e017d78d 100644 --- a/app/src/main/java/helium314/keyboard/latin/utils/CustomLayoutUtils.kt +++ b/app/src/main/java/helium314/keyboard/latin/utils/CustomLayoutUtils.kt @@ -14,17 +14,17 @@ import helium314.keyboard.keyboard.KeyboardId import helium314.keyboard.keyboard.KeyboardLayoutSet import helium314.keyboard.keyboard.KeyboardSwitcher import helium314.keyboard.keyboard.internal.KeyboardParams +import helium314.keyboard.keyboard.internal.keyboard_parser.LayoutParser import helium314.keyboard.keyboard.internal.keyboard_parser.POPUP_KEYS_NORMAL -import helium314.keyboard.keyboard.internal.keyboard_parser.RawKeyboardParser import helium314.keyboard.keyboard.internal.keyboard_parser.addLocaleKeyTextsToParams import helium314.keyboard.latin.R -import helium314.keyboard.latin.common.Constants import helium314.keyboard.latin.common.FileUtils -import helium314.keyboard.latin.settings.Settings +import helium314.keyboard.latin.utils.LayoutType.Companion.folder import kotlinx.serialization.SerializationException import java.io.File import java.io.IOException import java.math.BigInteger +import java.util.EnumMap fun loadCustomLayout(uri: Uri?, languageTag: String, context: Context, onAdded: (String) -> Unit) { if (uri == null) @@ -85,7 +85,7 @@ fun checkLayout(layoutContent: String, context: Context): Boolean { params.mPopupKeyTypes.add(POPUP_KEYS_LAYOUT) addLocaleKeyTextsToParams(context, params, POPUP_KEYS_NORMAL) try { - val keys = RawKeyboardParser.parseJsonString(layoutContent).map { row -> row.mapNotNull { it.compute(params)?.toKeyParams(params) } } + val keys = LayoutParser.parseJsonString(layoutContent).map { row -> row.mapNotNull { it.compute(params)?.toKeyParams(params) } } return checkKeys(keys) } catch (e: SerializationException) { Log.w(TAG, "json parsing error", e) @@ -96,13 +96,13 @@ fun checkLayout(layoutContent: String, context: Context): Boolean { return false } try { - val keys = RawKeyboardParser.parseSimpleString(layoutContent).map { row -> row.map { it.toKeyParams(params) } } + val keys = LayoutParser.parseSimpleString(layoutContent).map { row -> row.map { it.toKeyParams(params) } } return checkKeys(keys) } catch (e: Exception) { Log.w(TAG, "error parsing custom simple layout", e) } if (layoutContent.trimStart().startsWith("[") && layoutContent.trimEnd().endsWith("]")) { // layout can't be loaded, assume it's json -> load json layout again because the error message shown to the user is from the most recent error try { - RawKeyboardParser.parseJsonString(layoutContent).map { row -> row.mapNotNull { it.compute(params)?.toKeyParams(params) } } + LayoutParser.parseJsonString(layoutContent).map { row -> row.mapNotNull { it.compute(params)?.toKeyParams(params) } } } catch (e: Exception) { Log.w(TAG, "json parsing error", e) } } return false @@ -149,20 +149,28 @@ fun checkKeys(keys: List>): Boolean { } /** don't rename or delete the file without calling [onCustomLayoutFileListChanged] */ -fun getCustomLayoutFile(layoutName: String, context: Context) = +fun getCustomLayoutFile(layoutName: String, context: Context) = // todo: remove File(getCustomLayoutsDir(context), layoutName) // cache to avoid frequently listing files /** don't rename or delete files without calling [onCustomLayoutFileListChanged] */ -fun getCustomLayoutFiles(context: Context): List { +fun getCustomLayoutFiles(context: Context): List { // todo: remove, AND USE THE NEW THING FOR SUBTYPE SETTINGS customLayouts?.let { return it } val layouts = getCustomLayoutsDir(context).listFiles()?.toList() ?: emptyList() customLayouts = layouts return layouts } +fun getCustomLayoutFiles(layoutType: LayoutType, context: Context): List = + customLayoutMap.getOrPut(layoutType) { + File(DeviceProtectedUtils.getFilesDir(context), layoutType.folder).listFiles()?.toList() ?: emptyList() + } + +private val customLayoutMap = EnumMap>(LayoutType::class.java) + fun onCustomLayoutFileListChanged() { customLayouts = null + customLayoutMap.clear() } private fun getCustomLayoutsDir(context: Context) = File(DeviceProtectedUtils.getFilesDir(context), "layouts") @@ -215,45 +223,6 @@ fun editCustomLayout(layoutName: String, context: Context, startContent: String? builder.show() } -fun hasCustomFunctionalLayout(subtype: InputMethodSubtype, context: Context): Boolean { - val anyCustomFunctionalLayout = getCustomFunctionalLayoutName(KeyboardId.ELEMENT_ALPHABET, subtype, context) - ?: getCustomFunctionalLayoutName(KeyboardId.ELEMENT_SYMBOLS, subtype, context) - ?: getCustomFunctionalLayoutName(KeyboardId.ELEMENT_SYMBOLS_SHIFTED, subtype, context) - return anyCustomFunctionalLayout != null -} - -fun getCustomFunctionalLayoutName(elementId: Int, subtype: InputMethodSubtype, context: Context): String? { - val customFunctionalLayoutNames = getCustomLayoutFiles(context).filter { it.name.contains("functional") }.map { it.name.substringBeforeLast(".") + "." } - if (customFunctionalLayoutNames.isEmpty()) return null - val languageTag = subtype.locale().toLanguageTag() - val mainLayoutName = subtype.mainLayoutName() - - if (elementId == KeyboardId.ELEMENT_SYMBOLS_SHIFTED) { - findMatchingLayout(customFunctionalLayoutNames.filter { it.startsWith(CUSTOM_FUNCTIONAL_LAYOUT_SYMBOLS_SHIFTED) }, mainLayoutName, languageTag) - ?.let { return it } - } - if (elementId == KeyboardId.ELEMENT_SYMBOLS) { - findMatchingLayout(customFunctionalLayoutNames.filter { it.startsWith(CUSTOM_FUNCTIONAL_LAYOUT_SYMBOLS) }, mainLayoutName, languageTag) - ?.let { return it } - } - return findMatchingLayout(customFunctionalLayoutNames.filter { it.startsWith(CUSTOM_FUNCTIONAL_LAYOUT_NORMAL) }, mainLayoutName, languageTag) -} - -// todo (when adding custom layouts per locale or main layout): adjust mainLayoutName for custom layouts? -// remove language tag and file ending (currently name is e.g. custom.en-US.abcdfdsg3.json, and we could use abcdfdsg3 only) -// this way, custom layouts with same name could use same custom functional layouts -// currently there is no way to set the language tag or main layout name, so changes don't break backwards compatibility -private fun findMatchingLayout(layoutNames: List, mainLayoutName: String, languageTag: String): String? { - // first find layout with matching locale and main layout - return layoutNames.firstOrNull { it.endsWith(".$languageTag.$mainLayoutName.") } - // then find matching main layout - ?: layoutNames.firstOrNull { it.endsWith(".$mainLayoutName.") } - // then find matching language - ?: layoutNames.firstOrNull { it.endsWith(".$languageTag.") } - // then find "normal" functional layout (make use of the '.' separator - ?: layoutNames.firstOrNull { it.count { it == '.' } == 2 } -} - fun encodeBase36(string: String): String = BigInteger(string.toByteArray()).toString(36) fun decodeBase36(string: String) = BigInteger(string, 36).toByteArray().decodeToString() diff --git a/app/src/main/java/helium314/keyboard/latin/utils/LayoutType.kt b/app/src/main/java/helium314/keyboard/latin/utils/LayoutType.kt index ac95cb124..e639aadff 100644 --- a/app/src/main/java/helium314/keyboard/latin/utils/LayoutType.kt +++ b/app/src/main/java/helium314/keyboard/latin/utils/LayoutType.kt @@ -1,5 +1,6 @@ package helium314.keyboard.latin.utils +import java.io.File import java.util.EnumMap enum class LayoutType { @@ -17,5 +18,7 @@ enum class LayoutType { } return map } + + val LayoutType.folder get() = "layouts${File.separator}${name.lowercase()}${File.separator}" } } diff --git a/app/src/main/java/helium314/keyboard/latin/utils/SubtypeLocaleUtils.java b/app/src/main/java/helium314/keyboard/latin/utils/SubtypeLocaleUtils.java index 0856b28d7..46dfcf3b2 100644 --- a/app/src/main/java/helium314/keyboard/latin/utils/SubtypeLocaleUtils.java +++ b/app/src/main/java/helium314/keyboard/latin/utils/SubtypeLocaleUtils.java @@ -273,7 +273,7 @@ public final class SubtypeLocaleUtils { @NonNull public static String getKeyboardLayoutSetName(final InputMethodSubtype subtype) { - String keyboardLayoutSet = SubtypeUtilsKt.explicitMainLayoutName(subtype); + String keyboardLayoutSet = SubtypeUtilsKt.mainLayoutName(subtype); if (keyboardLayoutSet == null && subtype.isAsciiCapable()) { keyboardLayoutSet = QWERTY; } 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 becc230cd..5d56e78bc 100644 --- a/app/src/main/java/helium314/keyboard/latin/utils/SubtypeSettings.kt +++ b/app/src/main/java/helium314/keyboard/latin/utils/SubtypeSettings.kt @@ -13,7 +13,6 @@ import androidx.core.content.edit import helium314.keyboard.keyboard.KeyboardSwitcher import helium314.keyboard.latin.R import helium314.keyboard.latin.RichInputMethodManager -import helium314.keyboard.latin.common.Constants import helium314.keyboard.latin.common.LocaleUtils import helium314.keyboard.latin.common.LocaleUtils.constructLocale import helium314.keyboard.latin.define.DebugFlags @@ -41,7 +40,7 @@ fun getAllAvailableSubtypes(): List { fun getMatchingLayoutSetNameForLocale(locale: Locale): String { val subtypes = resourceSubtypesByLocale.values.flatten() - val name = LocaleUtils.getBestMatch(locale, subtypes) { it.locale() }?.explicitMainLayoutName() + val name = LocaleUtils.getBestMatch(locale, subtypes) { it.locale() }?.mainLayoutName() if (name != null) return name return when (locale.script()) { ScriptUtils.SCRIPT_LATIN -> "qwerty" @@ -246,7 +245,7 @@ private fun loadResourceSubtypes(resources: Resources) { private fun removeInvalidCustomSubtypes(context: Context) { val prefs = context.prefs() val additionalSubtypes = prefs.getString(Settings.PREF_ADDITIONAL_SUBTYPES, Defaults.PREF_ADDITIONAL_SUBTYPES)!!.split(";") - val customSubtypeFiles by lazy { getCustomLayoutFiles(context).map { it.name } } + val customSubtypeFiles by lazy { getCustomLayoutFiles(LayoutType.MAIN, context).map { it.name } } val subtypesToRemove = mutableListOf() additionalSubtypes.forEach { val name = it.substringAfter(":").substringBefore(":") diff --git a/app/src/main/java/helium314/keyboard/latin/utils/SubtypeUtils.kt b/app/src/main/java/helium314/keyboard/latin/utils/SubtypeUtils.kt index cfaaaebe5..c95c261aa 100644 --- a/app/src/main/java/helium314/keyboard/latin/utils/SubtypeUtils.kt +++ b/app/src/main/java/helium314/keyboard/latin/utils/SubtypeUtils.kt @@ -16,12 +16,7 @@ fun InputMethodSubtype.locale(): Locale { @Suppress("deprecation") return locale.constructLocale() } -fun InputMethodSubtype.mainLayoutName(): String { - val map = LayoutType.getLayoutMap(getExtraValueOf(KEYBOARD_LAYOUT_SET) ?: "") - return map[LayoutType.MAIN] ?: "qwerty" -} - -fun InputMethodSubtype.explicitMainLayoutName(): String? { +fun InputMethodSubtype.mainLayoutName(): String? { val map = LayoutType.getLayoutMap(getExtraValueOf(KEYBOARD_LAYOUT_SET) ?: "") return map[LayoutType.MAIN] } diff --git a/app/src/main/java/helium314/keyboard/settings/SettingsContainer.kt b/app/src/main/java/helium314/keyboard/settings/SettingsContainer.kt index eebeb189a..d475a1481 100644 --- a/app/src/main/java/helium314/keyboard/settings/SettingsContainer.kt +++ b/app/src/main/java/helium314/keyboard/settings/SettingsContainer.kt @@ -74,13 +74,11 @@ object SettingsWithoutKey { const val GITHUB = "github" const val SAVE_LOG = "save_log" const val CUSTOM_KEY_CODES = "customize_key_codes" - const val CUSTOM_SYMBOLS_NUMBER_LAYOUTS = "custom_symbols_number_layouts" - const val CUSTOM_FUNCTIONAL_LAYOUTS = "custom_functional_key_layouts" +// const val CUSTOM_SYMBOLS_NUMBER_LAYOUTS = "custom_symbols_number_layouts" +// const val CUSTOM_FUNCTIONAL_LAYOUTS = "custom_functional_key_layouts" const val BACKUP_RESTORE = "backup_restore" const val DEBUG_SETTINGS = "screen_debug" const val LOAD_GESTURE_LIB = "load_gesture_library" - const val ADJUST_COLORS = "adjust_colors" - const val ADJUST_COLORS_NIGHT = "adjust_colors_night" const val BACKGROUND_IMAGE = "background_image" const val BACKGROUND_IMAGE_LANDSCAPE = "background_image_landscape" const val CUSTOM_FONT = "custom_font" diff --git a/app/src/main/java/helium314/keyboard/settings/screens/AdvancedScreen.kt b/app/src/main/java/helium314/keyboard/settings/screens/AdvancedScreen.kt index 6c6e74dd9..500dc04d7 100644 --- a/app/src/main/java/helium314/keyboard/settings/screens/AdvancedScreen.kt +++ b/app/src/main/java/helium314/keyboard/settings/screens/AdvancedScreen.kt @@ -20,7 +20,6 @@ import androidx.compose.ui.res.stringResource import androidx.compose.ui.tooling.preview.Preview import helium314.keyboard.keyboard.KeyboardActionListener import helium314.keyboard.keyboard.KeyboardLayoutSet -import helium314.keyboard.keyboard.internal.keyboard_parser.RawKeyboardParser import helium314.keyboard.latin.BuildConfig import helium314.keyboard.latin.R import helium314.keyboard.latin.SystemBroadcastReceiver @@ -74,8 +73,6 @@ fun AdvancedSettingsScreen( Settings.PREF_ABC_AFTER_CLIP, Settings.PREF_CUSTOM_CURRENCY_KEY, Settings.PREF_MORE_POPUP_KEYS, - SettingsWithoutKey.CUSTOM_SYMBOLS_NUMBER_LAYOUTS, - SettingsWithoutKey.CUSTOM_FUNCTIONAL_LAYOUTS, SettingsWithoutKey.BACKUP_RESTORE, if (BuildConfig.DEBUG || prefs.getBoolean(DebugSettings.PREF_SHOW_DEBUG_SETTINGS, Defaults.PREF_SHOW_DEBUG_SETTINGS)) SettingsWithoutKey.DEBUG_SETTINGS else null, @@ -195,7 +192,7 @@ fun createAdvancedSettings(context: Context) = listOf( ) ListPreference(it, items, Defaults.PREF_MORE_POPUP_KEYS) { KeyboardLayoutSet.onSystemLocaleChanged() } }, - Setting(context, SettingsWithoutKey.CUSTOM_SYMBOLS_NUMBER_LAYOUTS, R.string.customize_symbols_number_layouts) { setting -> +/* Setting(context, SettingsWithoutKey.CUSTOM_SYMBOLS_NUMBER_LAYOUTS, R.string.customize_symbols_number_layouts) { setting -> LayoutEditPreference( setting = setting, items = RawKeyboardParser.symbolAndNumberLayouts, @@ -211,7 +208,7 @@ fun createAdvancedSettings(context: Context) = listOf( getItemName = { it.substringAfter(CUSTOM_LAYOUT_PREFIX).getStringResourceOrName("layout_", LocalContext.current) }, getDefaultLayout = { if (Settings.getInstance().isTablet) "functional_keys_tablet.json" else "functional_keys.json" } ) - }, + },*/ // todo: these settings are disabled for now -> remove them and use a layoutScreen instead Setting(context, SettingsWithoutKey.BACKUP_RESTORE, R.string.backup_restore_title) { BackupRestorePreference(it) }, diff --git a/app/src/main/res/xml/method.xml b/app/src/main/res/xml/method.xml index c7a2e9e3f..ee7e7178a 100644 --- a/app/src/main/res/xml/method.xml +++ b/app/src/main/res/xml/method.xml @@ -166,7 +166,7 @@ android:imeSubtypeLocale="ar" android:languageTag="ar" android:imeSubtypeMode="keyboard" - android:imeSubtypeExtraValue="KeyboardLayoutSet=MAIN:arabic,NoShiftKey,SupportTouchPositionCorrection,EmojiCapable" + android:imeSubtypeExtraValue="KeyboardLayoutSet=MAIN:arabic|SYMBOLS:symbols_arabic,NoShiftKey,SupportTouchPositionCorrection,EmojiCapable" android:isAsciiCapable="false" />