Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
181 commits
Select commit Hold shift + click to select a range
31acfb1
chore: update README badges [skip ci]
github-actions[bot] Aug 20, 2026
25d8f8b
chore: update README badges [skip ci]
github-actions[bot] Aug 21, 2026
2ab06ff
chore: update README badges [skip ci]
github-actions[bot] Aug 22, 2026
a1de8f2
fix(manifest): restore SYSTEM_ALERT_WINDOW permission for floating mo…
LeanBitLab Aug 22, 2026
96a4969
feat(floating): implement live real-time resizing for floating keyboa…
LeanBitLab Aug 22, 2026
73c1b9b
fix(floating): dynamically scale toolbar & expand key and resolve liv…
LeanBitLab Aug 22, 2026
790fe2e
fix(floating): prevent live view cropping during keyboard expansion
LeanBitLab Aug 22, 2026
e0ccde5
fix(floating): preserve square toolbar key aspect ratio and synchroni…
LeanBitLab Aug 22, 2026
cba3695
fix(floating): scale pinned keys and expand key proportionally with f…
LeanBitLab Aug 22, 2026
cb0c020
fix(floating): dynamically scale functional key icons with floating k…
LeanBitLab Aug 22, 2026
95e8ff3
fix(floating): dynamically scale suggestion strip height and toolbar …
LeanBitLab Aug 22, 2026
8a0b2ec
fix(floating): trigger toolbar button rebuild and dynamic auto-span o…
LeanBitLab Aug 22, 2026
c652700
fix(theme): soften spacebar contrast and reduce pill height in border…
LeanBitLab Aug 22, 2026
c257ead
fix(theme): fix emoji tab strip dark mode desync and navbar theme syn…
LeanBitLab Aug 22, 2026
661c422
feat(settings): add comprehensive voice customization and optimizatio…
LeanBitLab Aug 22, 2026
e7d8648
refactor(settings): sort voice settings logically by priority
LeanBitLab Aug 22, 2026
e93df1d
chore(release): bump version to v4.1.3 (4103)
LeanBitLab Aug 22, 2026
c3f7ac4
fix(voice): replace system DownloadManager with robust in-app streami…
LeanBitLab Aug 22, 2026
58a1bd8
docs: mention Voice Plugin v1.0.1 release in v4.1.3 release notes
LeanBitLab Aug 22, 2026
3d62fa9
chore: update README badges [skip ci]
github-actions[bot] Aug 23, 2026
ca0354a
fix(translation): fallback to built-in AI when plugin returns unmodif…
LeanBitLab Aug 23, 2026
e7bfca5
feat(mlkit): add com.google.mlkit:translate to standardfull flavor
LeanBitLab Aug 23, 2026
4df4289
feat(translation): add Translation Mode preference and in-app Offline…
LeanBitLab Aug 23, 2026
d7bf1f7
fix(translation): wrap plugin model methods in try-catch to prevent A…
LeanBitLab Aug 23, 2026
b5b521e
feat(settings): move translation settings to dedicated Plugins sectio…
LeanBitLab Aug 23, 2026
055c99a
style(libraries): standardize card and category styling to match gest…
LeanBitLab Aug 23, 2026
fde873f
feat(settings): separate Translation settings into dedicated section …
LeanBitLab Aug 23, 2026
b5a33c7
feat(settings): create dedicated TranslationSettingsScreen matching O…
LeanBitLab Aug 23, 2026
586617d
style(voice): standardize VoiceSettingsScreen layout and card contain…
LeanBitLab Aug 23, 2026
95b1c65
style(voice): add icons to VoiceSettingsScreen rows matching Translat…
LeanBitLab Aug 23, 2026
a90d54f
style(voice): redesign VoiceModelDownloadDialog to match TranslationM…
LeanBitLab Aug 23, 2026
47579b6
style(voice): standardize Voice Plugin preference row and PreferenceD…
LeanBitLab Aug 23, 2026
89653a6
style(dictionary): restyle DictionaryScreen with standardized Cards, …
LeanBitLab Aug 23, 2026
69b71bc
fix(ui): guard against 0 and invalid icon resource IDs in Preference …
LeanBitLab Aug 23, 2026
64b49dc
feat(models): modernize Dictionary Dialog and add HandwritingModelDow…
LeanBitLab Aug 23, 2026
ac5d717
fix(ui): polish Personal Dictionary learning card, add dialog title a…
LeanBitLab Aug 23, 2026
2d73914
feat(settings): add dedicated HandwritingSettingsScreen matching Tran…
LeanBitLab Aug 23, 2026
13e4602
feat(voice): add automated GitHub release version checking and update…
LeanBitLab Aug 23, 2026
2ef0916
refactor(settings): move Dictionaries into Languages and layouts, ren…
LeanBitLab Aug 23, 2026
a735de9
fix(dict): resolve personal dictionary auto-learning bypass and accur…
LeanBitLab Aug 23, 2026
92bc516
feat(textexpander): add %clipboard_clean% placeholder to strip Wikipe…
LeanBitLab Aug 23, 2026
47b6541
feat(textexpander): add versatile composable modifiers pipeline and r…
LeanBitLab Aug 23, 2026
8ef9d2a
fix(input): prevent emoticons like :) and :( from triggering bogus in…
LeanBitLab Aug 23, 2026
6a8be7b
fix(emoji): strictly enforce mInlineEmojiSearch setting in updateInli…
LeanBitLab Aug 23, 2026
1b1c42c
chore(release): bump version to v4.1.4 (4104) with synchronized relea…
LeanBitLab Aug 23, 2026
07f4d45
docs(release): enrich v4.1.4 release notes with Translation and UI st…
LeanBitLab Aug 23, 2026
9e8faef
docs(release): simplify and streamline v4.1.4 release notes and in-ap…
LeanBitLab Aug 23, 2026
b2e0b13
docs: update README and FEATURES.md with offline translation and vers…
LeanBitLab Aug 23, 2026
2d38f5c
docs(readme): replace side-by-side tip with browser APK installation …
LeanBitLab Aug 23, 2026
51d8865
docs(readme): move Screenshots section above Flavor Comparison
LeanBitLab Aug 23, 2026
c790302
fix: enforce offline-only translation mode and show model download toast
LeanBitLab Aug 23, 2026
c8b2929
chore: update README badges [skip ci]
github-actions[bot] Aug 24, 2026
cc22d77
feat(settings): enable offline translation models management across a…
LeanBitLab Aug 24, 2026
e1f6e01
fix(translation): use PluginClassLoader for plugin-first loading and …
LeanBitLab Aug 24, 2026
f0fbbff
fix(translation): supply PluginContext with AssetManager resource loa…
LeanBitLab Aug 24, 2026
1a164b4
feat(handwriting): enable handwriting plugin across standard and all …
LeanBitLab Aug 24, 2026
2b5f338
fix(handwriting): enable handwriting toolbar key on standard flavor a…
LeanBitLab Aug 24, 2026
fecdb66
fix(plugins): extract native libraries (.so) from plugin APK and pass…
LeanBitLab Aug 24, 2026
99eda79
fix(plugins): preload native libraries with System.load and implement…
LeanBitLab Aug 24, 2026
59e17b7
fix(lifecycle): prevent SystemBroadcastReceiver from killing process …
LeanBitLab Aug 24, 2026
a2adf94
fix(handwriting): load digitalink native library into PluginClassLoad…
LeanBitLab Aug 24, 2026
4c0228c
fix(handwriting): set read-only permission on companion dex for Andro…
LeanBitLab Aug 24, 2026
6eac76c
fix(handwriting): isolate native libraries in timestamped directories…
LeanBitLab Aug 24, 2026
2eecc49
feat(handwriting): add automatic ABI detection and multi-arch downloa…
LeanBitLab Aug 24, 2026
c02829e
feat(translation): add ABI auto-detection and remove obsolete ML Kit …
LeanBitLab Aug 24, 2026
b62b212
fix(translation): ensure WorkManager is initialized and provide Confi…
LeanBitLab Aug 24, 2026
f1d37e6
fix(translation): let PluginClassLoader load translate_jni native lib…
LeanBitLab Aug 24, 2026
5cbd5d3
fix(translation): pass host applicationContext directly to provider.i…
LeanBitLab Aug 24, 2026
91f3757
fix(translation): use MergedPluginContext with unified host and plugi…
LeanBitLab Aug 24, 2026
73e84da
feat(work): implement PluginWorkerFactory to delegate WorkManager wor…
LeanBitLab Aug 24, 2026
dfe4770
fix(translation): add detailed exception logging in TranslationModelD…
LeanBitLab Aug 24, 2026
4de85d9
feat(translation): introduce TranslationModelDownloadListener to guar…
LeanBitLab Aug 24, 2026
57ca9cc
feat(translation): pass error message to TranslationModelDownloadList…
LeanBitLab Aug 24, 2026
92e7fde
fix(translation): support dual onComplete signatures on TranslationMo…
LeanBitLab Aug 24, 2026
478a327
feat: add browser-delegated model download and in-app model importer …
LeanBitLab Aug 24, 2026
c9487cf
fix(handwriting): install model to both languageTag and base language…
LeanBitLab Aug 24, 2026
27d1295
feat(handwriting): extract complete 3-pack (recospec, model, fst) fro…
LeanBitLab Aug 24, 2026
612df29
feat(handwriting): add multi-URL browser downloader, multi-file impor…
LeanBitLab Aug 24, 2026
142891d
fix(handwriting): add background downloader for standard flavor, stri…
LeanBitLab Aug 24, 2026
4fbac05
feat(handwriting): unify import into single top header button with au…
LeanBitLab Aug 24, 2026
431a973
feat(settings): sort loaded models to top in translation and handwrit…
LeanBitLab Aug 24, 2026
9201df3
fix(plugins): show translation settings in all flavors and guard agai…
LeanBitLab Aug 24, 2026
c3038ee
build(proguard): add keep rules for handwriting, voice, workmanager a…
LeanBitLab Aug 24, 2026
402909d
fix(settings): hide translation engine selector on offline flavors
LeanBitLab Aug 24, 2026
1f00c02
feat(plugins): redirect plugin downloads to browser releases on offli…
LeanBitLab Aug 24, 2026
9440b5a
feat(toolbar): unhide handwriting, translation, and clipboard search …
LeanBitLab Aug 24, 2026
bb076a8
feat(offlinelite): enable translation toolbar key via TranslationLoad…
LeanBitLab Aug 24, 2026
e709715
style(settings): show active/not installed status for offline voice i…
LeanBitLab Aug 24, 2026
569c665
fix(handwriting): isolate regional language models, require full comp…
LeanBitLab Aug 24, 2026
62bb17e
perf(handwriting): optimize dialog load time and align offline downlo…
LeanBitLab Aug 24, 2026
06ccf73
style(handwriting): remove redundant close button from offline downlo…
LeanBitLab Aug 24, 2026
5602748
fix(toolbar): calibrate minSpannedKeyWidth threshold to prevent over-…
LeanBitLab Aug 24, 2026
4dffdbb
docs(release): synchronize v4.1.4 release notes, fastlane changelog, …
LeanBitLab Aug 24, 2026
da9b44a
docs(release): simplify and streamline v4.1.4 release notes and in-ap…
LeanBitLab Aug 24, 2026
074f05c
style(updates): replace emoji bullets with standard bullet points in …
LeanBitLab Aug 24, 2026
b378079
docs(release): update flavor comparison matrix in v4.1.4 release notes
LeanBitLab Aug 24, 2026
96c2fc6
docs(release): clarify optional internet usage and file import across…
LeanBitLab Aug 24, 2026
5f725e8
docs(release): sync release notes, fastlane changelog, and in-app upd…
LeanBitLab Aug 24, 2026
7704ef5
docs: update README and FEATURES.md with universal plugin support and…
LeanBitLab Aug 24, 2026
2afdf4d
docs(release): highlight ML Kit core removal and plugin isolation in …
LeanBitLab Aug 24, 2026
c80919d
docs: update Standard Full APK size to ~11 MB following ML Kit plugin…
LeanBitLab Aug 24, 2026
e70e56a
fix(voice): reorder AudioRecord teardown and guard against native cli…
LeanBitLab Aug 24, 2026
68d96e4
feat(translation): support direct in-app model download for online fl…
LeanBitLab Aug 24, 2026
6537799
fix(proguard): keep androidx.work runtime and ListenableWorker for pl…
LeanBitLab Aug 24, 2026
8fcce37
chore: update README badges [skip ci]
github-actions[bot] Aug 25, 2026
0d3447c
chore: update README badges [skip ci]
github-actions[bot] Aug 26, 2026
c9c92b6
fix(translation): resolve plugin ClassLoader lifecycle and native mod…
LeanBitLab Aug 25, 2026
f02287f
fix(keyboard): ensure Enter and Action keys fill rectangular tile in …
LeanBitLab Aug 25, 2026
ecdecfd
feat(layout): introduce balanced default text edit layout and retain …
LeanBitLab Aug 25, 2026
ca6ddab
feat(layout): apply ergonomic D-Pad arrangement with central Select k…
LeanBitLab Aug 25, 2026
653b538
chore(release): bump version to 4.1.5 (4105)
LeanBitLab Aug 25, 2026
1441de4
fix(translation): remove hardcoded English model bypass and allow dow…
LeanBitLab Aug 25, 2026
d1362d7
fix(translation): detect input source script and supply explicit sour…
LeanBitLab Aug 25, 2026
8acbfd0
refactor(settings): migrate AboutScreen Hidden Features dialog to Com…
LeanBitLab Aug 25, 2026
3c6b5e1
refactor(settings): align SubtypeScreen with Material 3 Card-based de…
LeanBitLab Aug 25, 2026
d1e6127
refactor(settings): wrap personal dictionary and blocked word list it…
LeanBitLab Aug 25, 2026
5314726
refactor(settings): wrap ColorsScreen color items in Material 3 Cards
LeanBitLab Aug 25, 2026
84cccbe
fix(settings): fix missing imports and variable scoping in SubtypeScr…
LeanBitLab Aug 25, 2026
46d0956
fix(suggestion): optimize next-word suggestion readiness and cache li…
LeanBitLab Aug 25, 2026
4095de5
fix(ime): proactively request predictions on initial focus to resolve…
LeanBitLab Aug 25, 2026
28ee2e3
feat(dict): add gated debug telemetry for next-word score auditing
LeanBitLab Aug 25, 2026
3f6e5b0
fix(debug): enable DEBUG_ENABLED on BuildConfig.DEBUG builds
LeanBitLab Aug 25, 2026
a349213
feat(dict): log ScoreAudit at INFO level for device logcat visibility
LeanBitLab Aug 25, 2026
7c93207
fix(dict): cap personalization boost to MAX_PERSONALIZATION_BOOST = 4…
LeanBitLab Aug 25, 2026
ab39ae3
feat(dict): add early beam pruning with BEAM_DELTA = 60 and strict te…
LeanBitLab Aug 25, 2026
9b9245c
feat(dict): add SuggestTrace and per-dictionary ScoreAudit instrument…
LeanBitLab Aug 25, 2026
0399f21
feat(settings): add Suggestion Balance master slider and scoring weights
LeanBitLab Aug 26, 2026
176b028
docs(release): update and synchronize v4.1.5 release notes and change…
LeanBitLab Aug 26, 2026
39a8672
docs(release): update standardfull primary focus to Convenience (Reco…
LeanBitLab Aug 26, 2026
d3a4ae5
chore: update README badges [skip ci]
github-actions[bot] Aug 27, 2026
68f4f05
feat(dicts): unbundle dictionaries across all flavors and optimize si…
LeanBitLab Aug 26, 2026
50ac071
feat(ai): modularize offline AI engine into dynamic plugin reducing A…
LeanBitLab Aug 26, 2026
5b98c38
fix(ai): resolve chicken-and-egg verification bug in OfflineAiLoader
LeanBitLab Aug 26, 2026
a1a6eac
feat(ui): refine welcome wizard for all flavors and move offline AI i…
LeanBitLab Aug 27, 2026
cb3454b
fix(translation): ensure persistent translation model detection and h…
LeanBitLab Aug 27, 2026
7571c8e
feat(settings): open GitHub releases in browser on offline builds for…
LeanBitLab Aug 27, 2026
2414bd9
fix(translation): cache and reuse PluginClassLoader to prevent native…
LeanBitLab Aug 27, 2026
8dc09ba
feat(toolbar): enable dictionary missing toolbar button and simplifie…
LeanBitLab Aug 27, 2026
d2b479d
docs(release): add offline settings backup advisory for offline AI pl…
LeanBitLab Aug 27, 2026
6f7377d
docs(release): refine offline settings backup recommendation in relea…
LeanBitLab Aug 27, 2026
73fb7f8
docs(release): add Offline Lite advisory and upcoming merger details …
LeanBitLab Aug 27, 2026
0101ec1
docs(release): refine Offline Lite note to only mention upcoming rele…
LeanBitLab Aug 27, 2026
3971aef
docs: update README and FEATURES.md with Offline AI plugin details, u…
LeanBitLab Aug 27, 2026
cc0e7cc
docs: enrich setup guides for Voice, Translation, Handwriting, and Of…
LeanBitLab Aug 27, 2026
3ea793f
docs: adjust standard flavor APK sizes to ~10.8 MB
LeanBitLab Aug 27, 2026
50303fc
fix(translation): standardize translation target language codes and r…
LeanBitLab Aug 27, 2026
b770ef2
fix(handwriting): support all language tag case variants and redirect…
LeanBitLab Aug 27, 2026
020c69f
feat(handwriting): support all regional language variants across all …
LeanBitLab Aug 27, 2026
ffddabb
fix(autocorrect): fix auto-capitalization pollution, over-aggressive …
LeanBitLab Aug 27, 2026
fe73d63
feat(gesture): improve gesture typing accuracy with session boost, hi…
LeanBitLab Aug 27, 2026
ef10631
feat(handwriting): modernize handwriting canvas with Bezier smoothing…
LeanBitLab Aug 27, 2026
3b1d404
fix(floating): dismiss floating keyboard on finish input view and win…
LeanBitLab Aug 27, 2026
6a1e810
fix(floating): dismiss floating keyboard on finish input or null edit…
LeanBitLab Aug 27, 2026
93ee132
feat(floating): add 'Remember floating mode' setting to reopen in flo…
LeanBitLab Aug 27, 2026
2524c0c
fix(handwriting): resolve infinite recomposition and UI blocking in h…
LeanBitLab Aug 27, 2026
58da244
fix(handwriting): resolve model tag directly in getEffectiveLanguage …
LeanBitLab Aug 27, 2026
6bf0a59
feat(flavors): unify offline and offlinelite flavors with minSdk 21 a…
LeanBitLab Aug 28, 2026
108bdd7
feat(plugins): dynamically guard plugins and toolbar actions based on…
LeanBitLab Aug 28, 2026
80de5c5
chore(release): bump version to v4.1.7 (versionCode 4107)
LeanBitLab Aug 28, 2026
ffd2c0d
fix(handwriting): automatically reset and reload recognizer on model …
LeanBitLab Aug 28, 2026
7246a0f
fix(handwriting): isolate imported models strictly to target tag with…
LeanBitLab Aug 28, 2026
ef8154f
fix(handwriting): support sibling language variant fallback when regi…
LeanBitLab Aug 28, 2026
7152b0b
feat(handwriting): implement universal canonical tag indexing and hie…
LeanBitLab Aug 28, 2026
111e96d
fix(handwriting): format BCP-47 tag in detectLanguageTag and save can…
LeanBitLab Aug 28, 2026
037ab65
ci(workflow): remove assembleOfflineliteRelease from release workflow
LeanBitLab Aug 28, 2026
cf49ce0
ci(workflow): refine release APK pattern and fix repository name in w…
LeanBitLab Aug 28, 2026
112c150
chore: update README badges [skip ci]
github-actions[bot] Aug 28, 2026
5a39296
chore: update README badges [skip ci]
github-actions[bot] Aug 29, 2026
082edad
fix(translation): check active provider's token in translateAsync AI …
foegra Aug 29, 2026
807944c
Merge pull request #460 from foegra/fix/translate-ai-provider-key-check
LeanBitLab Aug 29, 2026
d88c180
fix(translation): suppress plugin fallback toast when translation eng…
LeanBitLab Aug 29, 2026
afa3523
fix(translation): harden translation prompt and output sanitizer to p…
LeanBitLab Aug 29, 2026
9fd10cc
feat(settings): add language selection dialog for handwriting and tra…
LeanBitLab Aug 29, 2026
2fef4da
style(settings): harmonize import dialogs, button actions, and langua…
LeanBitLab Aug 29, 2026
e9fa0cb
feat(sound): add custom click sound system with downloadable presets …
LeanBitLab Aug 29, 2026
c810aa3
feat(sound): bundle 6 built-in sound presets into assets with zero-la…
LeanBitLab Aug 30, 2026
dee249c
feat(sound): add 6 additional built-in sound presets (12 total presets)
LeanBitLab Aug 30, 2026
cbfaf21
chore(release): bump version to v4.1.8 (4108) with synchronized relea…
LeanBitLab Aug 30, 2026
3a43e51
Merge LeanBitLab/LeanType v4.1.8 into dev
AsafMah Sep 3, 2026
b6103ed
Merge dev invariant gate after upstream v4.1.8 sync
AsafMah Sep 3, 2026
12a4922
docs(changelog): record upstream v4.1.8 sync (#149)
AsafMah Sep 3, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,9 @@ and this project uses [Semantic Versioning](https://semver.org/spec/v2.0.0.html)

## [Unreleased]

### Upstream
- Merged **LeanBitLab/LeanType v4.1.8** (pinned at `3717aa80`, covering v4.1.3–v4.1.8, 178 commits) — adds sound packs, plugin/model management improvements, floating-keyboard fixes, next-word suggestion fixes, and Android compatibility updates. LeanTypeDual retains its distinct `applicationId` and version, four privacy flavors, bundled offline AI and dictionaries, Java fallback gesture engine, and two-thumb typing. (#149)

### Added
- **Side-by-side experimental build** — an `experimental` build type (`com.asafmah.leantypedual.exp`, shown as "LeanTypeDual EXP") that installs alongside the normal build instead of replacing it, so input experiments can be compared against a working daily driver. (#141)

Expand Down
39 changes: 35 additions & 4 deletions app/proguard-rules.pro
Original file line number Diff line number Diff line change
Expand Up @@ -38,27 +38,58 @@
-dontwarn com.google.api.client.**
-dontwarn java.lang.management.**
-dontwarn org.joda.time.**
-dontwarn com.google.ai.client.generativeai.**
-dontwarn de.kherud.llama.**
-dontwarn org.nehuatl.llamacpp.**

# Keep offline voice plugin AIDL interface and parcelable classes
# Keep offline voice plugin AIDL interface, parcelables, and host managers
-keep class com.leanbitlab.leantype.voice.** { *; }
-keep interface com.leanbitlab.leantype.voice.** { *; }
-keep class helium314.keyboard.latin.voice.** { *; }

# Keep handwriting plugin interface and classes to prevent signature optimization or inlining
-keep interface helium314.keyboard.latin.handwriting.HandwritingRecognizer {
<methods>;
}
-keep interface helium314.keyboard.latin.handwriting.ModelDownloadListener {
<methods>;
}
-keep class helium314.keyboard.latin.handwriting.** { *; }
-keep interface helium314.keyboard.latin.handwriting.** { *; }

# Keep translation plugin interface to prevent parameter removal/signature optimization
-keep interface helium314.keyboard.latin.translation.ITranslationProvider {
<methods>;
}
-keep interface helium314.keyboard.latin.translation.TranslationModelDownloadListener {
<methods>;
}
-keep class helium314.keyboard.latin.translation.** { *; }
-keep interface helium314.keyboard.latin.translation.** { *; }

# Keep offline AI plugin interface to prevent parameter removal/signature optimization
-keep interface helium314.keyboard.latin.ai.IOfflineAiProvider {
<methods>;
}
-keep class helium314.keyboard.latin.ai.** { *; }
-keep interface helium314.keyboard.latin.ai.** { *; }

# Keep WorkManager plugin factory & runtime for dynamically loaded plugins
-keep class helium314.keyboard.latin.work.** { *; }
-keep interface helium314.keyboard.latin.work.** { *; }
-keep class androidx.work.** { *; }
-keep interface androidx.work.** { *; }
-keep class * extends androidx.work.ListenableWorker {
public <init>(android.content.Context, androidx.work.WorkerParameters);
}
-keepnames class com.google.mlkit.** extends androidx.work.ListenableWorker
-dontwarn androidx.work.**

# Keep ML Kit, GMS Tasks, and Firebase components for handwriting plugin dynamic linkage
# Keep ML Kit, DataTransport, GMS Tasks, and Firebase components for plugin dynamic linkage
-keep class com.google.mlkit.** { *; }
-keep class com.google.android.gms.tasks.** { *; }
-keep class com.google.firebase.components.** { *; }
-keep class com.google.android.datatransport.** { *; }
-keep class com.google.android.gms.** { *; }
-keep class com.google.firebase.** { *; }

# Keep Kotlin standard library for dynamically loaded plugins
# ponytail: keep kotlin stdlib classes to prevent NoSuchMethodError in plugin loading
Expand Down
1 change: 1 addition & 0 deletions app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ SPDX-License-Identifier: Apache-2.0 AND GPL-3.0-only
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" android:maxSdkVersion="32" />
<uses-permission android:name="android.permission.READ_MEDIA_IMAGES" />
<uses-permission android:name="android.permission.RECORD_AUDIO" />
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />
<uses-feature android:name="android.hardware.microphone" android:required="false" />

<queries>
Expand Down
10 changes: 5 additions & 5 deletions app/src/main/assets/layouts/editing/editing.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,23 +8,23 @@
],
[
{ "code": -32, "label": "Cut", "type": "function", "width": 0.2 },
{ "code": -25, "label": "", "width": 0.2 },
{ "code": -10015, "label": "«", "width": 0.2 },
{ "code": -23, "label": "↑", "width": 0.2 },
{ "code": -26, "label": "", "width": 0.2 },
{ "code": -7, "label": "delete", "type": "function", "width": 0.2 }
{ "code": -10016, "label": "»", "width": 0.2 },
{ "code": 32, "label": "space", "width": 0.2 }
],
[
{ "code": -31, "label": "Copy", "type": "function", "width": 0.2 },
{ "code": -21, "label": "←", "width": 0.2 },
{ "code": -306, "label": "Select", "type": "function", "width": 0.2 },
{ "code": -22, "label": "→", "width": 0.2 },
{ "code": -10015, "label": "«", "width": 0.2 }
{ "code": -7, "label": "delete", "type": "function", "width": 0.2 }
],
[
{ "code": -33, "label": "Paste", "type": "function", "width": 0.2 },
{ "code": -27, "label": "⇱", "width": 0.2 },
{ "code": -24, "label": "↓", "width": 0.2 },
{ "code": -28, "label": "⇲", "width": 0.2 },
{ "code": -10016, "label": "»", "width": 0.2 }
{ "label": "action", "width": 0.2 }
]
]
30 changes: 30 additions & 0 deletions app/src/main/assets/layouts/editing/editing_classic.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
[
[
{ "code": -131, "label": "Undo", "type": "function", "width": 0.2 },
{ "code": -132, "label": "Redo", "type": "function", "width": 0.2 },
{ "code": -35, "label": "All", "type": "function", "width": 0.2 },
{ "code": -34, "label": "Word", "type": "function", "width": 0.2 },
{ "code": -201, "label": "✕", "type": "function", "width": 0.2 }
],
[
{ "code": -32, "label": "Cut", "type": "function", "width": 0.2 },
{ "code": -25, "label": "⤒", "width": 0.2 },
{ "code": -23, "label": "↑", "width": 0.2 },
{ "code": -26, "label": "⤓", "width": 0.2 },
{ "code": -7, "label": "delete", "type": "function", "width": 0.2 }
],
[
{ "code": -31, "label": "Copy", "type": "function", "width": 0.2 },
{ "code": -21, "label": "←", "width": 0.2 },
{ "code": -306, "label": "Select", "type": "function", "width": 0.2 },
{ "code": -22, "label": "→", "width": 0.2 },
{ "code": -10015, "label": "«", "width": 0.2 }
],
[
{ "code": -33, "label": "Paste", "type": "function", "width": 0.2 },
{ "code": -27, "label": "⇱", "width": 0.2 },
{ "code": -24, "label": "↓", "width": 0.2 },
{ "code": -28, "label": "⇲", "width": 0.2 },
{ "code": -10016, "label": "»", "width": 0.2 }
]
]
Binary file added app/src/main/assets/sounds/arcade_8bit/delete.ogg
Binary file not shown.
Binary file added app/src/main/assets/sounds/arcade_8bit/enter.ogg
Binary file not shown.
Binary file added app/src/main/assets/sounds/arcade_8bit/space.ogg
Binary file not shown.
Binary file not shown.
Binary file added app/src/main/assets/sounds/ios/delete.ogg
Binary file not shown.
Binary file added app/src/main/assets/sounds/ios/enter.ogg
Binary file not shown.
Binary file added app/src/main/assets/sounds/ios/space.ogg
Binary file not shown.
Binary file added app/src/main/assets/sounds/ios/standard.ogg
Binary file not shown.
Binary file added app/src/main/assets/sounds/laser_scifi/delete.ogg
Binary file not shown.
Binary file added app/src/main/assets/sounds/laser_scifi/enter.ogg
Binary file not shown.
Binary file added app/src/main/assets/sounds/laser_scifi/space.ogg
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file added app/src/main/assets/sounds/marimba_tone/enter.ogg
Binary file not shown.
Binary file added app/src/main/assets/sounds/marimba_tone/space.ogg
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file added app/src/main/assets/sounds/modern_tick/delete.ogg
Binary file not shown.
Binary file added app/src/main/assets/sounds/modern_tick/enter.ogg
Binary file not shown.
Binary file added app/src/main/assets/sounds/modern_tick/space.ogg
Binary file not shown.
Binary file not shown.
Binary file added app/src/main/assets/sounds/pop_bubble/delete.ogg
Binary file not shown.
Binary file added app/src/main/assets/sounds/pop_bubble/enter.ogg
Binary file not shown.
Binary file added app/src/main/assets/sounds/pop_bubble/space.ogg
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file added app/src/main/assets/sounds/soft_pudding/enter.ogg
Binary file not shown.
Binary file added app/src/main/assets/sounds/soft_pudding/space.ogg
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file added app/src/main/assets/sounds/wood_minimal/enter.ogg
Binary file not shown.
Binary file added app/src/main/assets/sounds/wood_minimal/space.ogg
Binary file not shown.
Binary file not shown.
Original file line number Diff line number Diff line change
Expand Up @@ -305,6 +305,11 @@ public ArrayList<SuggestedWordInfo> getSuggestions(final ComposedData composedDa
session.mInputOutputWeightOfLangModelVsSpatialModel[0];
}
final int count = session.mOutputSuggestionCount[0];
if (helium314.keyboard.latin.define.DebugFlags.DEBUG_ENABLED && composedData.mTypedWord.isEmpty()) {
Log.i("ScoreAudit", "BinaryDict.getSuggestions type=" + mDictType + " outputCount=" + count
+ " prevWordCount=" + ngramContext.getPrevWordCount()
+ " isBOS=" + ngramContext.isBeginningOfSentenceContext());
}
final ArrayList<SuggestedWordInfo> suggestions = new ArrayList<>();
for (int j = 0; j < count; ++j) {
final int start = j * DICTIONARY_MAX_WORD_LENGTH;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,9 @@ data class VoiceSessionConfig(
val enablePartial: Boolean,
val maxSegmentMs: Int,
val hybridTimeoutMs: Int,
val hybridFallbackToVosk: Boolean
val hybridFallbackToVosk: Boolean,
val cpuThreads: Int = 4,
val customPrompt: String? = null
) : Parcelable

object VoiceConstants {
Expand Down Expand Up @@ -81,6 +83,10 @@ object VoiceConstants {
const val PREF_VOICE_LANGUAGE = "voice_language"
const val VOICE_LANG_FOLLOW_KEYBOARD = "follow_keyboard"
const val VOICE_LANG_AUTO = "auto"
const val PREF_VOICE_CPU_THREADS = "voice_cpu_threads"
const val PREF_VOICE_CUSTOM_PROMPT = "voice_custom_prompt"
const val PREF_VOICE_MIC_SENSITIVITY = "voice_mic_sensitivity"
const val PREF_VOICE_MAX_DURATION_SECONDS = "voice_max_duration_seconds"
const val PREF_USE_DEBUG_VOICE_STUB = "use_debug_voice_stub"
const val VOICE_PLUGIN_PACKAGE = "com.leanbitlab.leantype.voice.offline"
}
Original file line number Diff line number Diff line change
Expand Up @@ -739,6 +739,9 @@ public void reloadKeyboard() {
if (mCurrentInputView == null)
return;
mEmojiPalettesView.clearKeyboardCache();
if (mSuggestionStripView != null) {
mSuggestionStripView.onFloatingKeyboardScaleChanged();
}
reloadMainKeyboard();
}

Expand Down
11 changes: 8 additions & 3 deletions app/src/main/java/helium314/keyboard/keyboard/KeyboardTheme.kt
Original file line number Diff line number Diff line change
Expand Up @@ -535,9 +535,14 @@ private constructor(val themeId: Int, @JvmField val mStyleId: Int) {
}
COLOR_KEYS ->
return brightenOrDarken(determineUserColor(colors, context, COLOR_BACKGROUND, isNight), isNight)
COLOR_FUNCTIONAL_KEYS ->
return brightenOrDarken(determineUserColor(colors, context, COLOR_KEYS, isNight), true)
COLOR_SPACEBAR -> return determineUserColor(colors, context, COLOR_KEYS, isNight)
COLOR_SPACEBAR -> {
val keyColor = determineUserColor(colors, context, COLOR_KEYS, isNight)
if (!context.prefs().getBoolean(Settings.PREF_THEME_KEY_BORDERS, Defaults.PREF_THEME_KEY_BORDERS)) {
val background = determineUserColor(colors, context, COLOR_BACKGROUND, isNight)
return androidx.core.graphics.ColorUtils.blendARGB(background, keyColor, 0.45f)
}
return keyColor
}
COLOR_SPACEBAR_TEXT -> {
val spacebar = determineUserColor(colors, context, COLOR_SPACEBAR, isNight)
val hintText = determineUserColor(colors, context, COLOR_HINT_TEXT, isNight)
Expand Down
34 changes: 31 additions & 3 deletions app/src/main/java/helium314/keyboard/keyboard/KeyboardView.java
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@
import helium314.keyboard.latin.settings.SettingsValues;
import helium314.keyboard.latin.suggestions.MoreSuggestions;
import helium314.keyboard.latin.suggestions.MoreSuggestionsView;
import helium314.keyboard.latin.utils.ResourceUtils;
import helium314.keyboard.latin.utils.TypefaceUtils;

import java.util.HashSet;
Expand Down Expand Up @@ -324,7 +325,17 @@ private void onDrawKeyboard(@NonNull final Canvas canvas) {
final SettingsValues sv = Settings.getValues();
mShowsHints = sv.mShowsHints;
final float scale = sv.mKeyboardHeightScale;
mIconScaleFactor = scale < 0.8f ? scale + 0.2f : 1f;
final float floatingScale = ResourceUtils.getFloatingKeyboardScale();
final int floatingWidth = ResourceUtils.getFloatingKeyboardWidth();
final int defaultWidth = ResourceUtils.getDefaultKeyboardWidth(getContext());
if (floatingScale > 0.0f || floatingWidth > 0) {
final float heightScale = scale * (floatingScale > 0.0f ? floatingScale : 1.0f);
final float widthScale = (floatingWidth > 0 && defaultWidth > 0) ? ((float) floatingWidth / defaultWidth) : 1.0f;
final float effectiveKeyScale = Math.min(heightScale, widthScale);
mIconScaleFactor = Math.max(0.4f, Math.min(effectiveKeyScale, 1.5f));
} else {
mIconScaleFactor = scale < 0.8f ? scale + 0.2f : 1f;
}
final Paint paint = mPaint;
final Drawable background = getBackground();
// Calculate clip region and set.
Expand Down Expand Up @@ -392,11 +403,14 @@ private void onDrawKey(@NonNull final Key key, @NonNull final Canvas canvas,
protected void onDrawKeyBackground(@NonNull final Key key, @NonNull final Canvas canvas,
@NonNull final Drawable background) {
int customColor = 0;
if (KeyboardActionListenerImpl.sPersistentTextEditModeActive) {
final boolean isTextEditMode = KeyboardActionListenerImpl.sPersistentTextEditModeActive
|| (getKeyboard() != null && getKeyboard().mId.mElementId == KeyboardId.ELEMENT_TEXT_EDIT);
if (isTextEditMode) {
switch (key.getCode()) {
case KeyCode.UNDO:
case KeyCode.REDO:
case KeyCode.DELETE:
case KeyCode.FORWARD_DELETE:
customColor = mColors.get(ColorType.EDIT_MODE_DELETE_BACKGROUND);
break;
case KeyCode.CLIPBOARD_SELECT_ALL:
Expand Down Expand Up @@ -425,6 +439,11 @@ protected void onDrawKeyBackground(@NonNull final Key key, @NonNull final Canvas
case KeyCode.WORD_RIGHT:
customColor = mColors.get(ColorType.EDIT_MODE_JUMP_BACKGROUND);
break;
default:
if (key.hasActionKeyBackground()) {
customColor = mColors.get(ColorType.ACTION_KEY_BACKGROUND);
}
break;
}
}

Expand All @@ -437,12 +456,19 @@ protected void onDrawKeyBackground(@NonNull final Key key, @NonNull final Canvas
final int keyHeight = key.getHeight();
final int bgWidth, bgHeight, bgX, bgY;
if (key.needsToKeepBackgroundAspectRatio(mDefaultKeyLabelFlags)
&& !isTextEditMode
// HACK: To disable expanding normal/functional key background.
&& !key.hasCustomActionLabel()) {
bgWidth = (int) (drawBackground.getIntrinsicWidth() * mIconScaleFactor);
bgHeight = (int) (drawBackground.getIntrinsicHeight() * mIconScaleFactor);
bgX = (keyWidth - bgWidth) / 2;
bgY = (keyHeight - bgHeight) / 2;
} else if (!mColors.getHasKeyBorders() && key.getBackgroundType() == Key.BACKGROUND_TYPE_SPACEBAR) {
final int verticalInset = (int) (keyHeight * 0.16f);
bgWidth = keyWidth + padding.left + padding.right;
bgHeight = Math.max(1, keyHeight + padding.top + padding.bottom - (verticalInset * 2));
bgY = -padding.top + verticalInset;
bgX = -padding.left;
} else {
bgWidth = keyWidth + padding.left + padding.right;
bgHeight = keyHeight + padding.top + padding.bottom;
Expand Down Expand Up @@ -535,7 +561,9 @@ protected void onDrawKeyTopVisuals(@NonNull final Key key, @NonNull final Canvas
}
if (key.needsAutoXScale() || (StringUtilsKt.isEmoji(label) && Settings.getValues().mEmojiKeyFit)) {
final int width;
if (key.needsToKeepBackgroundAspectRatio(mDefaultKeyLabelFlags)) {
final boolean isTextEditMode = KeyboardActionListenerImpl.sPersistentTextEditModeActive
|| (keyboard != null && keyboard.mId.mElementId == KeyboardId.ELEMENT_TEXT_EDIT);
if (key.needsToKeepBackgroundAspectRatio(mDefaultKeyLabelFlags) && !isTextEditMode) {
// make sure the text stays inside bounds of background drawable
Drawable bg = key.selectBackgroundDrawable(mKeyBackground, mFunctionalKeyBackground,
mSpacebarBackground, mActionKeyBackground);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -218,7 +218,7 @@ private void updateState(@NonNull RecyclerView recyclerView, long categoryId) {
private static SingleDictionaryFacilitator sDictionaryFacilitator;

private boolean initialized = false;
private final Colors mColors;
private Colors mColors;
private final EmojiLayoutParams mEmojiLayoutParams;
private LinearLayout mTabStrip;
private EmojiCategoryPageIndicatorView mEmojiCategoryPageIndicatorView;
Expand Down Expand Up @@ -884,6 +884,7 @@ public void startEmojiPalettes(final KeyVisualAttributes keyVisualAttr,
mEditorInfo = editorInfo; // Saved
mKeyboardActionListener = keyboardActionListener;
initialize();
updateColors();
setupBottomRowKeyboard(editorInfo, keyboardActionListener);
final KeyDrawParams params = new KeyDrawParams();
params.updateParams(mEmojiLayoutParams.getBottomRowKeyboardHeight(), keyVisualAttr);
Expand Down Expand Up @@ -1174,7 +1175,7 @@ private void setCurrentCategoryId(final int categoryId, final boolean initial) {

if (old instanceof ImageView) {
Settings.getValues().mColors.setColor((ImageView) old, ColorType.EMOJI_CATEGORY);
old.setBackgroundColor(android.graphics.Color.WHITE);
old.setBackground(null);
Settings.getValues().mColors.setBackground((ImageView) old, ColorType.STRIP_BACKGROUND);
}
if (current instanceof ImageView) {
Expand All @@ -1185,6 +1186,33 @@ private void setCurrentCategoryId(final int categoryId, final boolean initial) {
}
}

public void updateColors() {
mColors = Settings.getValues().mColors;
if (mTabStrip != null) {
mColors.setBackground(mTabStrip, ColorType.STRIP_BACKGROUND);
for (int i = 0; i < mTabStrip.getChildCount(); i++) {
final View child = mTabStrip.getChildAt(i);
if (child instanceof ImageView) {
final Object tag = child.getTag();
final long categoryId = tag instanceof Long ? (Long) tag : -1;
if (categoryId == mEmojiCategory.getCurrentCategoryId()) {
child.setBackgroundResource(R.drawable.toolbar_key_background);
mColors.setColor(child.getBackground(), ColorType.TOOL_BAR_EXPAND_KEY_BACKGROUND);
} else {
child.setBackground(null);
mColors.setBackground(child, ColorType.STRIP_BACKGROUND);
}
mColors.setColor((ImageView) child, ColorType.EMOJI_CATEGORY);
}
}
}
if (mEmojiCategoryPageIndicatorView != null) {
mEmojiCategoryPageIndicatorView.setColors(
mColors.get(ColorType.EMOJI_CATEGORY_SELECTED),
mColors.get(ColorType.STRIP_BACKGROUND));
}
}

private boolean isAnimationsDisabled() {
return android.provider.Settings.Global.getFloat(getContext().getContentResolver(),
android.provider.Settings.Global.ANIMATOR_DURATION_SCALE, 1.0f) == 0.0f;
Expand All @@ -1196,6 +1224,7 @@ public void clearKeyboardCache() {
}

mEmojiCategory.clearKeyboardCache();
updateColors();
mPager.getAdapter().notifyDataSetChanged();
closeDictionaryFacilitator();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ private GestureStrokeRecognitionParams() {
mDynamicDistanceThresholdFrom = 6.0f; // keyWidth
mDynamicDistanceThresholdTo = 0.35f; // keyWidth
// The following parameters' change will affect the result of regression test.
mSamplingMinimumDistance = 1.0f / 6.0f; // keyWidth
mSamplingMinimumDistance = 1.0f / 8.0f; // keyWidth
mRecognitionMinimumTime = 100; // msec
mRecognitionSpeedThreshold = 5.5f; // keyWidth/sec
}
Expand Down
Loading
Loading