Compare commits

..

282 Commits

Author SHA1 Message Date
Patrick Goldinger
166734757f Release v0.3.15 2022-04-10 13:57:55 +02:00
Patrick Goldinger
97f401371f Fix crash in key reset logic (#1771) 2022-04-10 12:26:21 +02:00
Patrick Goldinger
b012e5377b Release v0.3.15-rc02 2022-04-09 19:19:54 +02:00
florisboard-bot
3b18dc33d8 Update translations from Crowdin 2022-04-09 19:07:29 +02:00
Patrick Goldinger
d798f01576 Merge pull request #1769 from florisboard/fix-key-visuals-and-popups-getting-stuck
Fix key visuals and popups getting stuck
2022-04-09 17:35:55 +02:00
Patrick Goldinger
55281bd7d6 Merge pull request #1768 from florisboard/add-guardedbylock-and-fix-glide-issues
Add guardedbylock and fix glide issues
2022-04-09 17:34:59 +02:00
Patrick Goldinger
88e9bde0a9 Fix popup stays active when using multitouch (#1450) 2022-04-09 17:26:11 +02:00
Patrick Goldinger
54d5a16761 Fix keys can get stuck with active visuals (#1446) 2022-04-09 16:43:53 +02:00
Patrick Goldinger
701da50479 Add GuardedByLock to prevent crash (#1632) 2022-04-09 16:02:06 +02:00
Patrick Goldinger
b43b6aa2d0 Remove unnecessary classes and methods in common 2022-04-09 13:07:37 +02:00
Patrick Goldinger
4279e9d100 Fix Unicode non-spacing marks for Thai (#1759) 2022-04-08 20:06:36 +02:00
M-Koushan
e5bd979880 Add German (Gboard) layout (#1737) & Fix Persian layout issue (#1746) 2022-04-08 18:48:00 +02:00
Patrick Goldinger
9a48169bf3 Fix delete key swipe right deleting left words (#1765) 2022-04-08 17:42:47 +02:00
Patrick Goldinger
99cfd99815 Merge pull request #1763 from florisboard/fix-extracted-input-ui-issues
Fix extracted input UI issues
2022-04-08 17:23:19 +02:00
Hayleia
e8f082d885 Fix Korean composition of medial+final and final+final (#1757) 2022-04-07 20:33:45 +02:00
Patrick Goldinger
b63f475a8c Fix NPE crash in extracted input UI (#1758) 2022-04-07 20:12:20 +02:00
Patrick Goldinger
e183f10969 Improve devtools overlay UI and remove unnecessary code 2022-04-06 23:57:57 +02:00
Patrick Goldinger
c1e624b9a0 Fix input view + extracted input UI layouting issues (#1760) 2022-04-06 22:51:51 +02:00
Patrick Goldinger
2d87d0e4d3 Release v0.3.15-rc01 2022-04-05 23:59:07 +02:00
florisboard-bot
bcf1bffc24 Update translations from Crowdin 2022-04-05 23:45:52 +02:00
Patrick Goldinger
f388e8811e Add support for videos on clipboard history (#1721) 2022-04-05 23:42:12 +02:00
Patrick Goldinger
7ededa6293 Merge pull request #1756 from florisboard/quick-glide-fixes
Fix glide typing state and drawing bugs
2022-04-05 22:21:49 +02:00
Patrick Goldinger
7d9e1cf2b5 Fix glide trail not drawing if popups disabled (#1704) 2022-04-05 22:12:52 +02:00
Patrick Goldinger
299f581609 Fix glide not initializing if disabled on app start (#1703) 2022-04-05 21:33:46 +02:00
Patrick Goldinger
c38d4ed90b Merge pull request #1749 from florisboard/re-add-other-default-themes
Re-implement other default themes
2022-04-05 19:43:52 +02:00
Patrick Goldinger
647bc659d7 Decrease visual key height for borderless themes 2022-04-05 19:25:20 +02:00
Patrick Goldinger
61eb09e611 Re-add Pure Night and all borderless themes (#1702) 2022-04-05 19:08:28 +02:00
Patrick Goldinger
1a4118d29a Fix space bar ignoring "No action" setting (#1706) 2022-04-04 23:04:43 +02:00
Denys Honsiorovskyi
48655b3771 Ukrainian popup mappings improvements (#1739)
* Ukrainian popup mappings improvements

* Make all letters relevant not to override default symbols

* Update extension.json

* Remove extra domains: they look ugly
2022-04-04 22:41:53 +02:00
pjtsearch
17649c44bf Fix փ missing in Armenian layouts (#1741)
Co-authored-by: PJTSearch <pjtsignups@gmail.com>
2022-04-04 22:34:31 +02:00
Patrick Goldinger
7cbb19ddcb Add support for Chinese (Simplified) (zh-CN) 2022-04-04 20:04:25 +02:00
Patrick Goldinger
e13ac7c689 Add support for locale display language in devtools 2022-04-04 20:03:58 +02:00
Patrick Goldinger
941733cdc0 Merge pull request #1734 from florisboard/add-extracted-landscape-input-layout
Add support for ExtractedLandscapeInput
2022-04-03 15:16:44 +02:00
Patrick Goldinger
a25289a856 Fix ExtractedLandscapeInput UI themeing 2022-04-02 20:46:59 +02:00
Patrick Goldinger
7bcfeca872 Improve ExtractedLandscapeInput UI and fix compatibility
... with Samsung devices.
2022-04-02 20:01:45 +02:00
Patrick Goldinger
240ebc499a Improve debug summarization of EditorInfo 2022-04-02 17:09:10 +02:00
Patrick Goldinger
831882f419 Add base for ExtractedLandscapeInput 2022-04-01 20:24:08 +02:00
Patrick Goldinger
e0e5259b4c Remove deprecated shift and caps flag from KeyboardState 2022-04-01 18:37:04 +02:00
Patrick Goldinger
33cd2b5d01 Release v0.3.15-beta02 2022-03-31 20:35:03 +02:00
florisboard-bot
d3dda86966 Update translations from Crowdin 2022-03-31 20:21:27 +02:00
Patrick Goldinger
59aa5cdb33 Fix Restore screen too restrictive about media type (#1707) 2022-03-31 20:08:31 +02:00
Patrick Goldinger
d26e820492 Possible fix for setup screen system observer failing (#1731) 2022-03-31 19:49:33 +02:00
Patrick Goldinger
b8b1b04c7e Decrease vertical padding usage in setup screen (#1364) 2022-03-31 19:48:56 +02:00
Patrick Goldinger
26b4acc894 Add limit to clipboard history text item preview (#1730) 2022-03-31 19:19:40 +02:00
Patrick Goldinger
12c4220544 Merge pull request #1720 from florisboard/improve-theme-logic-and-ui
Improve theme logic, appearance and stylesheet editor UI
2022-03-31 18:55:43 +02:00
Patrick Goldinger
5fc4f5ba60 Improve wording of code param in stylesheet editor 2022-03-31 01:39:07 +02:00
Patrick Goldinger
03ea9bcb76 Add key code recording tool in stylesheet editor 2022-03-31 01:03:59 +02:00
Patrick Goldinger
a04c44df98 Improve common Android Toast extension funs 2022-03-30 22:06:55 +02:00
Patrick Goldinger
b1431c7e51 Add key code preview box in stylesheet rule dialog 2022-03-29 01:32:46 +02:00
Patrick Goldinger
c09719ffd6 Fix emoji key (and popup) font color ignoring current theme 2022-03-28 19:49:39 +02:00
Patrick Goldinger
16149d95a1 Fix key shape clipping contents (#1710) 2022-03-28 19:39:37 +02:00
Patrick Goldinger
658e43da9c Move fontSizeMultiplier() to AppPrefs directly 2022-03-28 19:29:56 +02:00
M-Koushan
66ddb451ab Add additional Persian keyboard layout (#1683)
* Adding new layout Persian2

* Fix whitespace issues and charactersMod missing

* Fix issues in fa2.json

Co-authored-by: M-Koushan <koushan405@gmail.com>
Co-authored-by: Patrick Goldinger <patrick@patrickgold.dev>
2022-03-27 13:09:31 +02:00
Patrick Goldinger
f135513f3e Add support for A12 VibratiorManager 2022-03-26 20:00:52 +01:00
Patrick Goldinger
322dfa717b Fix language names not titlecase for some locales (#1686) 2022-03-26 11:26:56 +01:00
Patrick Goldinger
bfe7852bdf Release v0.3.15-beta01 2022-03-25 19:54:49 +01:00
florisboard-bot
45fe2f311e Update translations from Crowdin 2022-03-25 19:43:46 +01:00
blucin
f73daa2b00 Add ColemakDH keyboard layout (#1401)
* Added ColemakDH layout

* Adjust ColemakDH to new Flex extension format

Co-authored-by: Patrick Goldinger <patrick@patrickgold.dev>
2022-03-25 19:39:22 +01:00
Nijat Ismayilzada
4e8ff9ec14 Add Azerbaijani keyboard layout (#1639)
* Add Azerbaijani keyboard layout

* Add subtype preset for Azerbaijani

Co-authored-by: Patrick Goldinger <patrick@patrickgold.dev>
2022-03-25 19:24:18 +01:00
Amir Yalon
a96fc84fc1 Add Hebrew SI-1452 niqqud and some punctuation marks (#1413)
Based on information from https://en.wikipedia.org/wiki/Hebrew_keyboard

Combining characters don’t display well on their own. In the source code, they are avoided altogether by using JSON
escape codes like `\u05c2`, while in labels a placeholder letter is used. The letter ס was chosen because it is hollow,
and the letter ש must be used for its dots because other letters take the HEBREW POINT SHIN DOT on the wrong side when
combined.
2022-03-25 17:55:34 +01:00
Patrick Goldinger
e62ddc37dd Disable forceDarkAllowed in IME base theme (#1694) 2022-03-25 17:25:12 +01:00
Patrick Goldinger
06cfa34a4b Remove popups from telpad layout (#1044) 2022-03-25 16:51:08 +01:00
Patrick Goldinger
ef849dfefd Add alphabetic letters to phone digits in telpad layout (#355) 2022-03-25 16:51:08 +01:00
pjtsearch
091d43520e Add Armenian keyboard layouts (#1654)
* feat: Add Western Armenian layouts, popup mapping, and currency

* feat: Add Eastern Armenian layouts, popup mapping, and currency

* fix: Fix Armenian popup mapping

* fix: Add yev to Armenian popup mapping

* fix: Fix Western Armenian language tag

Co-authored-by: Patrick Goldinger <patrick@patrickgold.dev>

* fix: Differentiate Western layout name

Co-authored-by: Patrick Goldinger <patrick@patrickgold.dev>

* fix: Differentiate Eastern layout name

Co-authored-by: Patrick Goldinger <patrick@patrickgold.dev>

Co-authored-by: PJTSearch <pjtsignups@gmail.com>
Co-authored-by: Patrick Goldinger <patrick@patrickgold.dev>
2022-03-25 00:07:29 +01:00
Patrick Goldinger
95b6b1bbf9 Fix keyboard ignoring number row height in symbols (#1658) 2022-03-24 22:33:39 +01:00
Patrick Goldinger
021014e870 Change layout direction of Smartbar and Emoji to forced LTR (#1673) 2022-03-24 22:10:20 +01:00
Kostas Giapis
aaa4fbae7a Fix main popup for "ﺍ" ‎(#1571) 2022-03-24 21:57:56 +01:00
Patrick Goldinger
78b645d820 Fix media and clipboard ignoring number row in height calc (#1672) 2022-03-24 20:37:42 +01:00
GoRaN
61bd6752e3 Fix TLDs of Arabic and Urdu-Phonetic (#1680) 2022-03-24 19:18:57 +01:00
Patrick Goldinger
e4e10f5c72 Fix Arabic combining characters not displaying correctly (#1679) 2022-03-24 07:43:18 +01:00
Patrick Goldinger
1c6a719aa5 Release v0.3.14 2022-03-22 20:03:11 +01:00
Patrick Goldinger
693051b699 Fix popup UI controller remember keys causing unintended resets 2022-03-22 18:29:10 +01:00
Patrick Goldinger
91865a0e14 Update CONTRIBUTING.md (#1506) 2022-03-21 22:47:39 +01:00
Patrick Goldinger
ebd45375f6 Release v0.3.14-rc04 2022-03-20 22:53:41 +01:00
Patrick Goldinger
1c9f24c533 Fix numeric and numeric advanced popup width (#1044) 2022-03-20 22:31:51 +01:00
Patrick Goldinger
d6daa87ce6 Fix currency key in symbols not having popups (#1671) 2022-03-20 22:04:59 +01:00
Patrick Goldinger
99eaee1477 Fix clipboard crash when item still has old URI format (#1660) 2022-03-20 12:24:15 +01:00
Patrick Goldinger
47824a8e5f Release v0.3.14-rc03 2022-03-19 20:04:48 +01:00
florisboard-bot
83f45f9c5d Update translations from Crowdin 2022-03-19 19:56:20 +01:00
Patrick Goldinger
5e36f57e82 Fix theme properties share values between different rules (#1626) 2022-03-19 19:48:52 +01:00
Patrick Goldinger
ec65d9e6f8 Merge pull request #1666 from florisboard/fix-clipboard-and-input-logic-crashes
Fix clipboard and input logic crashes
2022-03-19 13:11:03 +01:00
Patrick Goldinger
e3ede1160e Fix ConcurrentModificationException in glide typing (#887, #1632) 2022-03-19 12:53:25 +01:00
Patrick Goldinger
a72d570065 Fix ArrayIndexOutOfBounds in glide typing (#801, #927, #1398) 2022-03-19 11:51:22 +01:00
Patrick Goldinger
db2227cc04 Fix StringIndexOutOfBoundsException (#1140, #1301, #1519, #1662) 2022-03-19 11:44:41 +01:00
Patrick Goldinger
1a77f94af9 Fix clipboard history UI crashing if data file not existing (#1660) 2022-03-19 11:15:52 +01:00
Patrick Goldinger
5bba116e01 Release v0.3.14-rc02 2022-03-18 19:51:41 +01:00
florisboard-bot
5c177cc225 Update translations from Crowdin 2022-03-18 19:37:29 +01:00
Patrick Goldinger
1d0826f854 Update in-app notes about feature availability and welcome screen 2022-03-18 19:33:29 +01:00
Patrick Goldinger
85fdd3876a Merge pull request #1653 from florisboard/fix-clipboard-issues
Fix clipboard issues / Re-add clipboard image support
2022-03-18 19:00:25 +01:00
Patrick Goldinger
59def39114 Fix duplicate primary clip callback adding duplicates (#1555)
This is a mitigation of a bug when a target app quickly adds the same clip twice, to prevent unnecessary duplicates.
2022-03-18 18:53:26 +01:00
Patrick Goldinger
463644c1d2 Improve image scaling in clipboard history view 2022-03-18 17:47:56 +01:00
Patrick Goldinger
117654c95c Fix clipboard history text clip deletion crash 2022-03-18 17:39:20 +01:00
Patrick Goldinger
21e97d6933 Improve clipboard image source display name retrieval logic 2022-03-18 17:18:52 +01:00
Patrick Goldinger
36d9f91009 Fix copy image crash when source does not provide display name 2022-03-18 16:54:16 +01:00
Patrick Goldinger
07c15f0782 Clipboard image provider now supports OpenableColumns 2022-03-18 00:56:34 +01:00
Patrick Goldinger
97d3223122 Re-implement clipboard image support (#1642) 2022-03-17 23:49:31 +01:00
Patrick Goldinger
2e12d756df Fix clipboard adding empty string silently when actually failing (#1647) 2022-03-17 00:04:40 +01:00
Patrick Goldinger
1ca1763138 Remove Handler utils 2022-03-16 23:49:28 +01:00
Patrick Goldinger
93f6ba3f69 Update home screen text displayed 2022-03-15 23:50:56 +01:00
Patrick Goldinger
83fd9a27a8 Fix SnyggStringValueSpec not having meaningful error message (#1643) 2022-03-14 21:54:40 +01:00
Patrick Goldinger
4c8587fa1e Fix Corner Percent Shape allowing percentages over 100 (#1643) 2022-03-14 21:52:12 +01:00
Patrick Goldinger
92f4ef12d9 Fix auto-backup not working on certain devices and with ADB 2022-03-13 23:19:25 +01:00
James
db401e0b69 Fix selectedText not checking for null when performing a copy (#1637) 2022-03-13 22:58:00 +01:00
GoRaN
ca5706b638 Fix kurmanji kurdish letter ş (#1638)
Fix kurmanji letter ş
2022-03-13 16:07:03 +01:00
Patrick Goldinger
63d132ad3c Fix editable color strings contain Unicode Ctrl Chars (#1636) 2022-03-12 20:09:57 +01:00
Patrick Goldinger
97456645e4 Update README.md and ROADMAP.md 2022-03-12 14:45:09 +01:00
Patrick Goldinger
81f949a1ee Release v0.3.14-rc01 2022-03-11 19:57:21 +01:00
florisboard-bot
438ca8c7ad Update translations from Crowdin 2022-03-11 19:42:26 +01:00
Patrick Goldinger
51bd2cc5cd Add note for glide typing preview (#1627) 2022-03-11 19:29:24 +01:00
Patrick Goldinger
864ee749ca Fix Smartbar Settings preference enable state bug 2022-03-11 19:02:47 +01:00
Patrick Goldinger
ba40307f0f Fix long titles and summaries in Settings (#998) 2022-03-11 19:00:56 +01:00
Patrick Goldinger
ae091bdae8 Fix floris_user_dictionary not included in auto-backup 2022-03-11 17:56:19 +01:00
Patrick Goldinger
e98b12f3c5 Merge pull request #1629 from florisboard/localization-fixes
Add support for RTL preference/keyboard UI layout and other minor fixes
2022-03-11 17:29:43 +01:00
Patrick Goldinger
ae49342ae7 Fix Emoji RTL issues 2022-03-11 17:23:26 +01:00
Patrick Goldinger
85ad815ae7 Fix parentheses for RTL languages (#422, #1624) 2022-03-10 22:46:02 +01:00
Patrick Goldinger
948e9bb75f Fix RTL layout issues in theme editor / extension editor 2022-03-10 20:55:11 +01:00
Patrick Goldinger
898dc25cb6 Fix one-handed mode and emoji in RTL layout direction 2022-03-10 00:17:29 +01:00
Patrick Goldinger
33f2336676 Add base support for localization and RTL in keyboard UI 2022-03-09 23:59:21 +01:00
Patrick Goldinger
e64ab1e75d Add support for RTL layout inside new preference UI 2022-03-08 19:55:07 +01:00
Patrick Goldinger
d46e95ceac Disable bundle language split for GPlay releases
This is only necessary for GPLay bundles because both F-Droid and
GitHub releases are a simple APK, which does split at all.
2022-03-08 19:09:23 +01:00
Patrick Goldinger
dd25420e03 Add Japanese (ja) as available language 2022-03-08 19:03:58 +01:00
Patrick Goldinger
b29519a784 Release v0.3.14-beta14 2022-03-06 20:33:01 +01:00
Patrick Goldinger
2d62398186 Adjust home screen message 2022-03-06 20:01:53 +01:00
florisboard-bot
573e55f1c4 Update translations from Crowdin 2022-03-06 19:59:33 +01:00
blueberry-robin
523eabee17 Update Urdu phonetic layout (#1619)
2 fixes for wrong layout in the Urdu phonetic keyboard. One was a wrong(duplicate) HTML code causing 2 different keys to output the same character. The other was a wrong label on a key resulting in 1 key label appearing twice and giving 2 different outputs.
2022-03-06 19:28:38 +01:00
GoRaN
913872e4cd Fix Kurdish language not changing app language (#1620)
* Fix Kurdish language not changing app language manually + some correct and improvement to kurdish layouts

* Add language mappings for Kurdish languages (ckb and ku)

Co-authored-by: Patrick Goldinger <patrick@patrickgold.dev>
2022-03-06 19:27:18 +01:00
Patrick Goldinger
c12a802e5e Possible fix for overflow button now showing (#1615) 2022-03-06 18:40:19 +01:00
Patrick Goldinger
3129617402 Merge pull request #1614 from florisboard/reimplement-composers
Reimplement composers into new extension system
2022-03-06 16:15:52 +01:00
Patrick Goldinger
dc2d130b13 Reduce noise of Appender and WithRules composer code 2022-03-06 16:00:10 +01:00
Patrick Goldinger
e9b140a9fe Reimplement composers into new extension system (#1478) 2022-03-06 16:00:10 +01:00
Patrick Goldinger
4189955554 Merge pull request #1618 from florisboard/smartbar-beta14-overhaul
Smartbar overhaul for 0.3.14-beta14
2022-03-06 15:58:52 +01:00
Patrick Goldinger
51f0843a2f Fix Smartbar primary actions auto-collapse for selection (#870) 2022-03-05 19:31:32 +01:00
Patrick Goldinger
2496ada14b Rework and simplify Smartbar themeing 2022-03-05 13:35:11 +01:00
Patrick Goldinger
544e3857fc Add ability to switch Smartbar layouts (#1548) 2022-03-04 20:03:54 +01:00
Patrick Goldinger
f3d076b51e Re-arrange Smartbar settings screen and change terminology a bit 2022-03-04 18:30:16 +01:00
Patrick Goldinger
40efbd0f65 Fix cursor movement for RTL text inside preview field (#1575) 2022-03-04 17:03:07 +01:00
Patrick Goldinger
8d667297c2 Add clear clipboard history confirmation (#1606) 2022-03-03 23:14:10 +01:00
Patrick Goldinger
dbb3f97abd Merge pull request #1608 from florisboard/improve-emoji-implementation
Improve emoji implementation
2022-03-03 20:33:15 +01:00
Patrick Goldinger
627919e34f Fix EmojiCompat IllegalStateException crash (#1610) 2022-03-03 20:25:58 +01:00
Patrick Goldinger
9f67789337 Add ability to specify preferred emoji skin tone (#132) 2022-03-01 01:48:53 +01:00
Patrick Goldinger
96d830e5c4 Add ability to specify emoji history max size 2022-03-01 01:03:24 +01:00
Patrick Goldinger
80ca97388c Fix Emoji font size having "unspecified" as default value (#1607) 2022-03-01 00:11:59 +01:00
Patrick Goldinger
afa021f67d Upgrade AGP to 7.1.2, JC to 1.1.1, and other dependencies 2022-02-28 23:58:21 +01:00
Patrick Goldinger
e14f54cac1 Release v0.3.14-beta13 2022-02-27 23:37:46 +01:00
florisboard-bot
21c1915233 Update translations from Crowdin 2022-02-27 23:20:35 +01:00
Patrick Goldinger
5af80a2270 Fix positioning of emoji variations popup 2022-02-27 23:18:55 +01:00
Patrick Goldinger
8a1a3d3bb4 Improve emoji palette view performance 2022-02-27 23:04:57 +01:00
Patrick Goldinger
a2f15606c7 Fix EmojiCompat load state not correctly checked 2022-02-27 19:11:47 +01:00
Patrick Goldinger
01e2ee7835 Fix crash dialog PendingIntent notification bug 2022-02-26 19:45:01 +01:00
Patrick Goldinger
7adc045752 Merge pull request #1589 from florisboard/reimplement-basic-emoji-palette
Re-implement basic emoji palette view
2022-02-25 18:04:56 +01:00
Patrick Goldinger
266af61e3a Fix font size multiplier ignored in emoji view 2022-02-25 17:56:58 +01:00
Patrick Goldinger
a814190012 Improve and fix themeing of emoji popup palette 2022-02-23 18:05:28 +01:00
Patrick Goldinger
109c323369 Fix emoji palette height not properly adapting 2022-02-23 01:01:39 +01:00
Patrick Goldinger
654e160503 Fix bug that variant emojis weren't checked for availability 2022-02-23 00:51:25 +01:00
Patrick Goldinger
3aa6d7ccbe Add emoji history for recently used emojis (#268, #944) 2022-02-23 00:21:12 +01:00
Patrick Goldinger
5d447d7a8f Improve emoji display and add support for emoji compat drawing 2022-02-22 22:53:26 +01:00
Patrick Goldinger
25bfd61814 Add emoji variations popup in emoji palette 2022-02-22 22:10:30 +01:00
Patrick Goldinger
b4caa66377 Add emoji2 library / Improve emoji UI a lot 2022-02-22 01:40:37 +01:00
Patrick Goldinger
e5dde63efc Improve tabs display in emoji palette view 2022-02-21 23:45:55 +01:00
Patrick Goldinger
78f64adbbf Add base buttons (switch to text and delete) in emoji 2022-02-21 20:34:50 +01:00
Patrick Goldinger
3f39bc8768 Add input event processor for base emojis 2022-02-21 00:54:32 +01:00
Patrick Goldinger
d2274c4d9e Add base skeleton for emoji frontend palette and backend mapping 2022-02-21 00:25:28 +01:00
Patrick Goldinger
8674a04a5c Release v0.3.14-beta12 2022-02-14 21:38:40 +01:00
florisboard-bot
2f14529902 Update translations from Crowdin 2022-02-14 21:25:00 +01:00
Patrick Goldinger
1d74a17b98 Merge pull request #1569 from florisboard/prefs-rework-polishing-1
Preference Rework Polishing Part 1
2022-02-14 21:18:45 +01:00
Patrick Goldinger
52435d9837 Add option to specify language name display type (#1568) 2022-02-14 20:14:12 +01:00
Patrick Goldinger
b6fbbe5a91 Fix transparent colors not drawing with a checkered background 2022-02-14 00:44:22 +01:00
Patrick Goldinger
3f85e1167c Fix blank screen on initial app launch after install (#1537) 2022-02-14 00:20:46 +01:00
Patrick Goldinger
9c05096184 Rework internal implementation of window insets within Settings UI 2022-02-13 21:24:23 +01:00
Patrick Goldinger
ef3bc015b0 Add "display kbd after dialog" option to fine-tune editor options 2022-02-13 20:19:46 +01:00
Patrick Goldinger
75fd600448 Remove ExternalContentUtils.kt 2022-02-13 19:21:09 +01:00
Patrick Goldinger
2f01e7770f Fix behavior and visual display for URLs where no scheme is specified 2022-02-13 19:17:44 +01:00
Patrick Goldinger
12b6edf872 Add missing icon for Smartbar and Advanced screen (#1428) 2022-02-13 18:27:11 +01:00
Patrick Goldinger
6053f2d16b Fix Scrollbar overlaps with text on welcome screen (#1427) 2022-02-13 17:51:47 +01:00
Patrick Goldinger
636c5f4df4 Add "System default (AMOLED)" option for Settings UI theme (#1539) 2022-02-13 17:40:23 +01:00
Patrick Goldinger
bb0bd478cf Fix crash in devtools system settings viewer (#1387) 2022-02-13 15:50:22 +01:00
Patrick Goldinger
79eb080811 Upgrade AGP to 7.1.1 / Upgrade other dependencies 2022-02-13 15:37:47 +01:00
Patrick Goldinger
b5b82836bc Fix NPE due to incorrect variable usage in restore screen (#1567) 2022-02-13 15:06:09 +01:00
Patrick Goldinger
cef0f2b53d Merge pull request #1565 from florisboard/improve-theme-engine-and-add-border
Improve theme editor/stylesheets and implement boder color/width
2022-02-13 14:57:33 +01:00
Patrick Goldinger
dbf031469f Fix follow system and time not updating (#1557) 2022-02-13 14:50:49 +01:00
Patrick Goldinger
5b87c933da Split FlorisImeTheme and BaseStyle into separate files 2022-02-13 12:37:17 +01:00
Patrick Goldinger
adc4b9a372 Improve ordering of value types in stylesheet property editor dialog
Value was changed from explicit inherit > var > *encoders to *encoders > var > explicit inherit. This speeds up the selection process, as users naturally read top to bottom and inherit is almost never used by a user anyways.
2022-02-11 19:58:47 +01:00
Patrick Goldinger
0ff8f7776e Improve float number display in theme editor (remove .0 suffix) 2022-02-11 19:49:28 +01:00
Patrick Goldinger
c04fdeb491 Fix alpha color value in HEX8 mode missing leading zero 2022-02-11 19:28:01 +01:00
Patrick Goldinger
295d8e5326 Implement border-color and border-width for stylesheets (#1105) 2022-02-11 18:59:56 +01:00
Patrick Goldinger
b032ac64f7 Add ability to show/hide keyboard UI on Android 8.1 and lower 2022-02-11 00:22:57 +01:00
Patrick Goldinger
8ebe99d2c9 Merge pull request #1562 from florisboard/reimplement-user-dictionary-manager-ui
Re-implement user-dictionary settings UI
2022-02-10 23:16:49 +01:00
Patrick Goldinger
f0b027557b Fix state issues within the user dictionary UI 2022-02-10 23:03:13 +01:00
Patrick Goldinger
462030bcd7 Re-implement user-dictionary settings UI (#1544) 2022-02-10 22:51:02 +01:00
Patrick Goldinger
888af9d28d Release v0.3.14-beta11 2022-02-08 19:43:54 +01:00
Patrick Goldinger
ea159527f3 Restrict variable name input validation and fix behavior bugs 2022-02-08 19:33:03 +01:00
Patrick Goldinger
0dc0f53a91 Fix missing elevation theme-attribute causing crash on Android 9 (#1553) 2022-02-08 19:11:20 +01:00
Patrick Goldinger
d5aac7ac14 Release v0.3.14-beta10 2022-02-07 21:09:41 +01:00
florisboard-bot
9f58088545 Update translations from Crowdin 2022-02-07 20:24:27 +01:00
Patrick Goldinger
b684f1759d Add option to select text via delete key (#705, #1534) 2022-02-06 23:21:49 +01:00
Patrick Goldinger
aa7a264d6c Add ability to hide language name on the space bar (#371, #1025) 2022-02-06 22:50:05 +01:00
Patrick Goldinger
6ac537c517 Fix spacebar switches to full keyboard in number-only fields (#1248)
Additionally also fixed it for phone and phone2 layouts.
2022-02-06 22:22:45 +01:00
Patrick Goldinger
2386ae7749 Merge pull request #1538 from florisboard/improve-theme-editor-ui
Improve theme editor UI
2022-02-06 22:12:40 +01:00
Patrick Goldinger
7d559acfae Improve redundancy definition of shape in SnyggShapeValue 2022-02-06 21:21:54 +01:00
Patrick Goldinger
7783b9b218 Add shadow elevation to theme and UI 2022-02-06 20:08:36 +01:00
Patrick Goldinger
548f7d7b1e Move SnyggValueIcon to own source file 2022-02-06 19:10:25 +01:00
Patrick Goldinger
4629c07812 Fix manual color string editing disregarding display colors as option 2022-02-06 12:16:43 +01:00
Patrick Goldinger
3b2b7da841 Add fine tune editor dialog / Add "Display colors as" option 2022-02-05 13:59:14 +01:00
Patrick Goldinger
25ef53510a Improve Snygg shape UI and naming implementation 2022-02-05 12:04:03 +01:00
Patrick Goldinger
0064f248d3 Move theme property translations to own file 2022-02-05 11:32:32 +01:00
Patrick Goldinger
0c721696f2 Improve default theme variable usage 2022-02-04 16:08:06 +01:00
Patrick Goldinger
131ab6214d Remove term "component" from title strings 2022-02-04 14:44:18 +01:00
Patrick Goldinger
70bc7a1236 Add translation for var references in basic and advanced mode
... in stylesheet editor
2022-02-04 14:35:26 +01:00
Patrick Goldinger
6c88716a2a Add Snygg circle shape value 2022-02-04 14:29:47 +01:00
Patrick Goldinger
ff3c37e360 Add ability to style color of glide trail
(property `foreground` is the color of glide trail)
2022-02-04 00:21:06 +01:00
Patrick Goldinger
58bab443c4 Add ability to modify color values manually 2022-02-03 23:32:26 +01:00
Patrick Goldinger
a8b0a6d555 Upgrade dependencies / Upgrade Kotlin to 1.6.10 2022-02-03 20:40:34 +01:00
Patrick Goldinger
0a430b4b0a Release v0.3.14-beta09 2022-02-02 23:46:47 +01:00
Patrick Goldinger
8b76c5ce3b Update README.md 2022-02-02 23:29:11 +01:00
florisboard-bot
c81f5f7015 Update translations from Crowdin 2022-02-02 23:25:36 +01:00
GoRaN
cf6b186269 Update kurdish.json (#1410)
* Update kurdish.json

Update and correct some characters place with there codes.

* Update kurdish.json
2022-02-02 23:08:27 +01:00
Patrick Goldinger
bd25ddb92e Merge pull request #1524 from svvvst/master
Add Rusyn Language Language Set, Layout, Popups
2022-02-02 23:05:03 +01:00
Patrick Goldinger
62bdd31af3 Fix rue popup mapping missing from extension manifest 2022-02-02 22:59:06 +01:00
Patrick Goldinger
d4af89bf99 Merge pull request #1513 from florisboard/add-theme-editor-ui
Add extension editor UI / theme editor UI
2022-02-02 22:51:21 +01:00
Patrick Goldinger
1c38a42c0b Fix system nav bar not using background var reference in default themes
This is done to avoid confusion why the system nav bar color does not change with the background.
2022-02-02 22:28:56 +01:00
Patrick Goldinger
6d1ebb74fb Adjust feedback and beta info test in Settings UI 2022-02-02 22:26:29 +01:00
Patrick Goldinger
9673e6de5c Clean-up old theme strings 2022-02-02 22:14:20 +01:00
Patrick Goldinger
ab709e2c69 Add create extension ability / Fix a lot of state and validation bugs 2022-02-02 21:57:29 +01:00
Patrick Goldinger
9144708cf0 Fix autofill chip not applying correct style (#1507) 2022-02-01 22:25:02 +01:00
Patrick Goldinger
38136de39d Add save extension function to extension editor 2022-01-31 22:21:23 +01:00
Patrick Goldinger
beb800a76e Add ability to modify shape property values in stylesheet editor 2022-01-31 21:40:23 +01:00
Patrick Goldinger
aab738526a Add ability to add new component from existing in extension editor 2022-01-31 00:48:03 +01:00
Patrick Goldinger
86bdad61a4 Add (semi-)live-preview to stylesheet editor
Semi-live only because you must apply a property value before the change reflects on the keyboard UI. THis is also done because instantly updating the stylesheet when using the color picker would create lag.
2022-01-30 23:18:52 +01:00
Patrick Goldinger
e4c56cab03 Fix bugs and fine-tune appearance across extension editor 2022-01-30 20:12:46 +01:00
Patrick Goldinger
cef1c4e3f6 Add hint to text field and trim input in component meta dialog 2022-01-30 18:29:30 +01:00
Patrick Goldinger
b2721c9faa Add input validation to component meta editor dialog 2022-01-30 18:07:26 +01:00
Patrick Goldinger
ab4ae62ffe Improve SnyggRule backend 2022-01-30 15:43:44 +01:00
Patrick Goldinger
74244bab74 Add empty component screen in extension editor 2022-01-29 14:51:51 +01:00
svvvst
57112ae692 Added missing character to layout. 2022-01-28 14:04:15 -04:00
svvvst
fd1314ccba Fixed layout. 2022-01-28 14:03:24 -04:00
svvvst
45d99df104 Added missing character. 2022-01-28 14:02:36 -04:00
Patrick Goldinger
17b87f6543 Remove old theme related strings 2022-01-28 17:40:00 +01:00
Patrick Goldinger
d62e82569d Add ability to modify component meta data in stylesheet editor 2022-01-28 17:28:05 +01:00
Patrick Goldinger
dc5e00cc07 Fix KeyCode range being too restrictive 2022-01-27 23:51:45 +01:00
Patrick Goldinger
6402511d38 Eradicate nasty bug in SnyggRule comparator and equality logic
This bug caused some rules to be magically hidden, because they were either
incorrectly resolved as equal or the comparator returned `=` even though the
codes, groups or modes did not match at all.
2022-01-27 23:49:20 +01:00
Patrick Goldinger
83c1f70077 Implement property apply in stylesheet editor 2022-01-27 19:07:15 +01:00
Patrick Goldinger
f3375f48ef Update AGP to 7.1.0 and Gradle to 7.2 2022-01-27 00:12:01 +01:00
Patrick Goldinger
e1b911086b Fix minor theming issues in stylesheet editor 2022-01-26 23:38:25 +01:00
Patrick Goldinger
b60c0cef51 Improve property set button layout in stylesheet editor 2022-01-26 23:14:01 +01:00
Patrick Goldinger
0c42185700 Add sp size property value field in stylesheet editor 2022-01-26 22:52:46 +01:00
Patrick Goldinger
ee3c779b17 Add custom design for text field in stylesheet editor 2022-01-26 22:08:52 +01:00
Patrick Goldinger
b5e6655c84 Add color picker to property editor in stylesheet editor 2022-01-26 19:38:29 +01:00
Patrick Goldinger
e1b45b9193 Add property value for vars and type selector in stylesheet editor 2022-01-24 20:38:16 +01:00
svvvst
588713bd55 Add Rusyn 2022-01-24 15:23:16 -04:00
svvvst
43ad452174 Add rusyn layouts 2022-01-24 15:21:56 -04:00
svvvst
2cf9146536 Add Rusyn popup mapping 2022-01-24 15:15:37 -04:00
svvvst
f81331baed Add Rusyn language keyboard 2022-01-24 15:14:25 -04:00
Patrick Goldinger
9c9c3b9428 Add skeleton for property editor in stylesheet editor 2022-01-24 01:09:59 +01:00
Patrick Goldinger
4b64d81c21 Extract EditRuleDialog in own file 2022-01-23 23:15:03 +01:00
Patrick Goldinger
e826f600f0 Rework stylesheet editor to use lazy list, avoiding layout freeze 2022-01-23 23:04:36 +01:00
Patrick Goldinger
0f845a9784 Add modes and finish rule mod functionality in stylesheet editor 2022-01-23 21:53:04 +01:00
Patrick Goldinger
a2805bedca Add codes modifier UI in rule editor for stylesheet editor 2022-01-23 13:30:07 +01:00
Patrick Goldinger
d860bbfb90 Add rule dialog in stylesheet editor 2022-01-22 20:47:28 +01:00
Patrick Goldinger
70e2d34410 Add variables box in stylesheet editor 2022-01-21 20:36:44 +01:00
Patrick Goldinger
1c49a11824 Add property preview in stylesheet editor 2022-01-21 19:57:29 +01:00
Patrick Goldinger
cd2a0000c0 Add rule and properties view in stylesheet editor 2022-01-21 00:50:18 +01:00
Patrick Goldinger
1304e49eb4 Add strings for all rule and property names in stylesheet editor 2022-01-20 23:55:43 +01:00
svvvst
9658cecb88 Create rue.json 2022-01-20 00:32:53 -04:00
svvvst
4c23d5bafc Create rusyn.json
Custom Rusyn keyboard layout.
2022-01-19 21:00:39 -04:00
Patrick Goldinger
82238c8c1a Add base skeleton for stylesheet editing 2022-01-20 00:35:13 +01:00
Patrick Goldinger
ead74e1c26 Fix issues with loosing state on rotating screen in extension editor 2022-01-19 23:43:46 +01:00
Patrick Goldinger
d58371be81 Add basic component creator screen 2022-01-19 00:48:53 +01:00
Patrick Goldinger
844d194533 Add stub screens for dependencies and files 2022-01-18 22:55:40 +01:00
Patrick Goldinger
84abc929d0 Improve meta data editor screen for extension editor 2022-01-18 21:27:33 +01:00
Patrick Goldinger
7497470875 Add discard changes dialog / Improve action screen code 2022-01-18 01:34:19 +01:00
Patrick Goldinger
cc5df41daa Rework and refactor UI code base for extension editor 2022-01-17 23:49:14 +01:00
Patrick Goldinger
d87b290a32 Add meta data manager in extension editor 2022-01-17 01:51:16 +01:00
Patrick Goldinger
a0f859ad03 Add basic skeleton for in-app extension editing 2022-01-16 23:49:01 +01:00
Patrick Goldinger
c86892ec0b Merge pull request #1498 from florisboard/add-backup-and-restore-feature
Add backup and restore feature
2022-01-12 22:33:24 +01:00
Patrick Goldinger
c85fea0799 Enable encrypted backup for app data (#272, #1324) 2022-01-12 22:32:38 +01:00
Patrick Goldinger
765e34a01d Improve restore metadata UI 2022-01-11 00:29:19 +01:00
Patrick Goldinger
96e7f2eeac Add restore data functionality 2022-01-10 23:00:00 +01:00
Patrick Goldinger
23dddfd16e Add restore screen UI and general B&R code improvements
B&R..Backup&Restore

Restore action itself does nothing atm
2022-01-08 20:31:39 +01:00
Patrick Goldinger
e2318d0af1 Add ability to share generated backup through share menu 2022-01-07 17:38:22 +01:00
Patrick Goldinger
ef3b840dce Add backup data screen (local file sys only)
Also add skeleton for restore data screen
2022-01-07 02:51:43 +01:00
Patrick Goldinger
9b9c5fa70e Change unhandled stacktraces dir to prevent backup interference
Old location:
`files/{timestamp}.stacktrace`

New location:
`no_backup/unhandled_stacktraces/{timestamp}.stacktrace`

Additionally clean up some "magics" and improve code in the crash utility.
2022-01-06 23:00:08 +01:00
Patrick Goldinger
6f0216cf9f Raise targetSdk from API 30 to 31 2022-01-06 00:59:06 +01:00
337 changed files with 22859 additions and 11183 deletions

View File

@@ -2,127 +2,104 @@
First off, thanks for considering contributing to FlorisBoard!
There are several ways to contribute to FlorisBoard. This document
provides some general guidelines for each type of contribution.
There are several ways to contribute to FlorisBoard. This document provides some general guidelines for each type of
contribution.
## Giving general feedback
NEW! You can now [give general feedback](https://github.com/florisboard/florisboard/discussions/new?category=feedback)
directly here on GitHub. This is the preferred way to give feedback, as
it allows not only for me to read and respond to feedback, but for everyone
in this community.
directly here on GitHub. This is the preferred way to give feedback, as it allows not only for me to read and respond to
feedback, but for everyone in this community.
Optionally you can also use the review function within Google Play or email me
at [florisboard@patrickgold.dev](mailto:florisboard@patrickgold.dev). I
love to hear from you! Note, that the amount of feedback emails I get
is overwhelmingly high - so if I don't answer or answer really late, I
apologize - I guarantee though that I read through every email and that
I will use every feedback to improve FlorisBoard :)
at [florisboard@patrickgold.dev](mailto:florisboard@patrickgold.dev). I love to hear from you! Note, that the amount of
feedback emails I get is overwhelmingly high - so if I don't answer or answer really late, I apologize - I guarantee
though that I read through every email and that I will use every feedback to improve FlorisBoard :)
## Translations
To make FlorisBoard accessible in as many languages as possible, the
platform [Crowdin](https://crowdin.florisboard.patrickgold.dev) is used
to crowdsource and manage translations. This is the only source of
translations from now on - **PRs that add/update translations are no
longer accepted.** The list of languages in Crowdin covers the top 20
languages, but feel free to email me at
[florisboard@patrickgold.dev](mailto:florisboard@patrickgold.dev) to
request a language and I'll add it.
platform [Crowdin](https://crowdin.florisboard.patrickgold.dev) is used to crowdsource and manage translations. This is
the only source of translations from now on - **PRs that add/update translations are no longer accepted.** The list of
languages in Crowdin covers the top 20 languages, but feel free to email me at
[florisboard@patrickgold.dev](mailto:florisboard@patrickgold.dev) to request a language and I'll add it.
## Adding a new feature or making large changes
If you intend to add a new feature or to make large changes, please
discuss this first through a proposal on GitHub. Discussing your idea
enables both you and the dev team that we are on the same page before
you start on working on your change. If you have any questions, feel
free to ask for help at any time!
If you intend to add a new feature or to make large changes, please discuss this first through a proposal on GitHub.
Discussing your idea enables both you and the dev team that we are on the same page before you start on working on your
change. If you have any questions, feel free to ask for help at any time!
## Adding a new keyboard layout
Adding a layout to FlorisBoard is very simple and does not require any
coding skills, although you should understand the basics of the JSON
syntax (it is very easy though by just looking at some other layout files).
There are two main steps in adding new layouts, though the config step can
be skipped if you only add a layout without a new default language support.
### The config file ([`app/src/main/assets/ime/config.json`](app/src/main/assets/ime/config.json))
This file is very important, as it defines all default currency sets as
well as all default subtypes available in the Settings Subtype UI. Note
that you don't have to modify this file if you add a layout for an already
pre-configured language.
- `currencySets`: This is a list of all currency sets, which can be chosen
for each subtype. If you consider adding a new one, make sure that the
first currency symbol matches the name of the currency set and also
ensure that you have exactly 6 currency symbols. This is important as the
symbol layouts have exactly 6 slots available to fill these defined
currency symbols in.
- `defaultSubtyes`: This is a list of all pre-made subtypes. Each time the
user selects a language in the `Subtype Add`-dialog, all options configured
here will get pre-selected. The language tag must adhere to the IETF BCP
47 code ([ISO 639-1 language code](https://en.wikipedia.org/wiki/List_of_ISO_639-1_codes)
and [ISO 3166-1 region code](https://en.wikipedia.org/wiki/ISO_3166-1_alpha-2#Officially_assigned_code_elements)).
For example, Dutch as spoken in Belgium is `nl-be`. Use a unique value
for `id` to avoid possible crashes caused by duplicate ids.
Adding a layout to FlorisBoard is very simple and does not require any coding skills, although you should understand the
basics of the JSON syntax (it is very easy though by just looking at some other layout files). Most of the time is
enough to look at the existing layout files, but the following attempts to help you in creating layouts from scratch.
### Adding the layout
Since v0.3.10-beta05 it is possible to add custom layouts for all types.
Since v0.3.14-beta06 it is possible to add custom layouts for all types using the new extension format, Flex.
To add a new layout, head to [`app/src/main/assets/ime/text`](app/src/main/assets/ime/text) and then select
the correct sub-directory for the type of layout you want to add. In most cases
this will be `characters` to add a layout like QWERTY etc.
Keyboard layout assets are grouped in [`app/src/main/assets/ime/keyboard`](app/src/main/assets/ime/keyboard) and are
further sub-grouped into the following:
For the `code` field of each key, make sure to use the UTF-8 code. An
useful tool for finding the correct code is [unicode-table.com](https://unicode-table.com/en/).
From there, you search for your letter and then use the HTML code, but without the `&#;`
- `org.florisboard.composers`: Defines standard composers for interpreting input, currently supports basic typing and
Korean input. Most of the time you won't need to add new composers, so if you don't know what they are always
assume `appender` (the default composer which does not alter input in any way) is in use.
- `org.florisboard.currencysets`: Lists all currency sets, which can be chosen for each subtype. If you consider adding
a new one, make sure that the first currency symbol matches the name of the currency set and also ensure that you have
exactly 6 currency symbols. This is important as the symbol layouts have exactly 6 slots available to fill these
defined currency symbols in.
- `org.florisboard.layouts`: Contains the actual layout files for all layout types.
- `org.florisboard.localization`: Contains all popup mappings and subtype presets (formally the `config.json` file). The
subtype presets are a list of all pre-made subtypes. Each time the user selects a language in the `Subtype Add`
-dialog, all options configured here will get selected if found in the presets. The language tag must adhere to the
IETF BCP 47 code ([ISO 639-1 language code](https://en.wikipedia.org/wiki/List_of_ISO_639-1_codes)
and [ISO 3166-1 region code](https://en.wikipedia.org/wiki/ISO_3166-1_alpha-2#Officially_assigned_code_elements)). For
example, Dutch as spoken in Belgium is `nl-be`.
To add a new layout, head to above directory and add the necessary files to each extension group.
For the `code` field of each key, make sure to use the UTF-8 code. An useful tool for finding the correct code
is [unicode-table.com](https://unicode-table.com/en/). From there, you search for your letter and then use the HTML
code, but without the `&#;`
For internal codes of functional or UI keys, see
[`app/src/main/java/dev/patrickgold/florisboard/ime/text/key/KeyCode.kt`](app/src/main/java/dev/patrickgold/florisboard/ime/text/key/KeyCode.kt).
[`app/src/main/java/dev/patrickgold/florisboard/ime/text/key/KeyCode.kt`](app/src/main/java/dev/patrickgold/florisboard/ime/text/key/KeyCode.kt)
.
The label is equally important and should always match up with the defined
code. If `code` and `label` don't match up, FlorisBoard won't crash but
it will most likely lead to confusion in the key processing logic.
The label is equally important and should always match up with the defined code. If `code` and `label` don't match up,
FlorisBoard won't crash but it will most likely lead to confusion in the key processing logic.
Any accents or diacritics that should be exposed via long press can be
added at [`app/src/main/assets/ime/text/characters/extended_popups/<languageTag_name_here>.json`](app/src/main/assets/ime/text/characters/extended_popups).
For each key, you can add 1 main and several relevant accents. The main
accent should be used for accents which are important for the language
you add. The main field is used for determining if a hint or an accent
should take priority, so please make sure to leave main empty and just
use relevant for accents which are not-so important.
Any accents or diacritics that should be exposed via long press can be added
at [`app/src/main/assets/ime/keyboard/org.florisboard.localization/popupMappings/<languageTag>.json`](app/src/main/assets/ime/keyboard/org.florisboard.localization/popupMappings)
. For each key, you can add 1 main and several relevant accents. The main accent should be used for accents which are
important for the language you add. The main field is used for determining if a hint or an accent should take priority,
so please make sure to leave main empty and just use relevant for accents which are not-so important.
For popups of non-`characters` layout, simply add the popup directly to
each key via the `popup` field.
For popups of non-`characters` layout, simply add the popup directly to each key via the `popup` field.
## Adding a new dictionary for a language
Currently the suggestions implementation is highly experimental and will
get a major if not complete rework, so dictionaries are currently not
accepted.
Currently the suggestions implementation is highly experimental and not available until 0.4.0, so dictionaries are
currently not accepted.
## Bug reporting
This kind of contribution is the most important, as it tells where
FlorisBoard has flaws and thus should be improved to maximize stability
and user experience. To make this process as smooth as possible, please
use the pre-made [issue template](.github/ISSUE_TEMPLATE/bug_report.md)
for bug reporting. This makes it easy for us to understand what the bug
is and how to solve it.
This kind of contribution is the most important, as it tells where FlorisBoard has flaws and thus should be improved to
maximize stability and user experience. To make this process as smooth as possible, please use the
pre-made [issue template](.github/ISSUE_TEMPLATE/bug_report.md)
for bug reporting. This makes it easy for us to understand what the bug is and how to solve it.
### Capturing error logs
Logs are captured by FlorisBoard's crash handler, which gives you the
ability to copy it to the clipboard and paste it in GitHub. This is the
preferred way to capture logs.
Logs are captured by FlorisBoard's crash handler, which gives you the ability to copy it to the clipboard and paste it
in GitHub. This is the preferred way to capture logs.
Alternatively, you can also use ADB (Android Debug Bridge) to capture
the error log. This is recommended for experienced users only.
Alternatively, you can also use ADB (Android Debug Bridge) to capture the error log. This is recommended for experienced
users only.
## Donating
If none of the above options are feasible for you but you still want to
show your support, you can also buy me a coffee, so I can stay up all night
and chase away bugs or add new cool stuff :)
If none of the above options are feasible for you but you still want to show your support, you can also buy me a coffee,
so I can stay up all night and chase away bugs or add new cool stuff :)
See the `Sponsors` button for available options!

View File

@@ -18,10 +18,10 @@ fully respecting your privacy. Currently in early-beta state.
</tr>
<tr>
<td valign="top">
<p><i>Major versions only, 1 release per 1-3 months</i><br><br>Updates are more polished, new features are matured and tested through to ensure a stable experience.</p>
<p><i>Major versions only, 1 release per 1-5 months</i><br><br>Updates are more polished, new features are matured and tested through to ensure a stable experience.</p>
</td>
<td valign="top">
<p><i>Beta versions, 1-2 releases per week</i><br><br>Updates contain new features that may not be fully matured yet and bugs are more likely to occur. Allows you to give early feedback.</p>
<p><i>Beta versions, up to 1-2 releases per week</i><br><br>Updates contain new features that may not be fully matured yet and bugs are more likely to occur. Allows you to give early feedback.</p>
</td>
</tr>
<tr>
@@ -57,12 +57,14 @@ fully respecting your privacy. Currently in early-beta state.
Beginning with v0.4.0 FlorisBoard will follow [SemVer](https://semver.org/#summary) versioning scheme and enter the public beta on Google Play.
## Highlighted features
- Spell checking service
- Word suggestions (currently English only and may not work on all devices)
- Glide typing (currently English only)
- Advanced theming support and customization
- Integrated clipboard manager / history
- Emoji keyboard (although lacking some features)
- Advanced theming support and customization
- Integrated extension support (still evolving)
- Emoji keyboard
- Spell checking service
- Glide typing (currently English only)
Word suggestions are not included in the current releases and are a major goal for the v0.4.0 milestone.
Feature roadmap: See [ROADMAP.md](ROADMAP.md)
@@ -78,18 +80,18 @@ Please refer to this [page](https://github.com/florisboard/florisboard/wiki/List
to get more information on this topic.
## Used libraries, components and icons
* [Google Flexbox Layout for Android](https://github.com/google/flexbox-layout)
by [google](https://github.com/google)
* [AndroidX libraries](https://github.com/androidx/androidx) by
[Android Jetpack](https://github.com/androidx)
* [Accompanist Compose UI libraries](https://github.com/google/accompanist/) by
[Google](https://github.com/google)
* [Google Material icons](https://github.com/google/material-design-icons) by
[google](https://github.com/google)
[Google](https://github.com/google)
* [JetPref preference library](https://github.com/patrickgold/jetpref) by
[patrickgold](https://github.com/patrickgold)
* [KotlinX coroutines library](https://github.com/Kotlin/kotlinx.coroutines) by
[Kotlin](https://github.com/Kotlin)
* [KotlinX serialization library](https://github.com/Kotlin/kotlinx.serialization) by
[Kotlin](https://github.com/Kotlin)
* [ColorPicker preference](https://github.com/jaredrummler/ColorPicker) by
[Jared Rummler](https://github.com/jaredrummler)
* [Timber](https://github.com/JakeWharton/timber) by
[JakeWharton](https://github.com/JakeWharton)
* [expandable-fab](https://github.com/nambicompany/expandable-fab) by
[Nambi](https://github.com/nambicompany)
* [ICU4C](https://github.com/unicode-org/icu) by
[The Unicode Consortium](https://github.com/unicode-org)
* [Nuspell](https://github.com/nuspell/nuspell) by
@@ -97,7 +99,7 @@ to get more information on this topic.
## License
```
Copyright 2020 Patrick Goldinger
Copyright 2020-2022 Patrick Goldinger
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.

View File

@@ -1,89 +1,91 @@
# FlorisBoard's feature roadmap & milestones
This feature roadmap intents to provide transparency to what I want to add
to FlorisBoard in the foreseeable future. Note that there are no ETAs for any
version milestones down below, experience says these won't hold anyways.
This feature roadmap intents to provide transparency to what I want to add to FlorisBoard in the foreseeable future.
Note that there are no ETAs for any version milestones down below, experience says these won't hold anyways.
I try my best to release regularly, though some features take a lot longer
than others and thus releases can be spaced out a bit on the stable track.
If you are interested in following the development more closely, make sure to
follow along the beta track releases! These are generally more unstable but
you get new stuff faster and can provide early feedback, which helps a lot!
I try my best to release regularly, though some features take a lot longer than others and thus releases can be spaced
out a bit on the stable track. If you are interested in following the development more closely, make sure to follow
along the beta track releases! These are generally more unstable but you get new stuff faster and can provide early
feedback, which helps a lot!
## 0.3.x
Releases in this section still follow the old versioning scheme, meaning the
patch number is a feature upgrade. As this naming convention is more confusing
than useful, beginning with v0.4.0 development a new release/development cycle will be
introduced.
### 0.3.14 (currently in progress, much is already implemented and working well)
Releases in this section still follow the old versioning scheme, meaning the patch number is a feature upgrade. As this
naming convention is more confusing than useful, beginning with v0.4.0 development a new release/development cycle will
be introduced.
### 0.3.14 (almost completed, release candidate phase)
- Re-write of the Preference core
- Reduce redundancy in key/default value definitions
- Avoid having to manually add redundant code for adding a new pref
- Goes hand-in-hand with the Settings UI re-write
- Reduce redundancy in key/default value definitions
- Avoid having to manually add redundant code for adding a new pref
- Goes hand-in-hand with the Settings UI re-write
- Re-write of the Settings UI with Jetpack Compose
- Also re-structure UI into a more list-like panel
- Adjust theme colors of Settings a bit to make it more modern
- Preview the keyboard at any time from within the Settings
- Settings language different than device language
- Also re-structure UI into a more list-like panel
- Adjust theme colors of Settings a bit to make it more modern
- Preview the keyboard at any time from within the Settings
- Settings language different than device language
- Re-write the Setup UI in Jetpack Compose
- Simplify screen based on previously discussed ideas and mock-ups
- Improve backend setup logic
- Implement base-UI for extensions and further continue development
of existing Flex (FlorisBoard extension) format
- Allows for a continuous experience of customizing FlorisBoard in different areas
- Planned what will use Flex:
- Themes
- Layouts (Characters, symbols, numeric, ...)
- Composers for non-Latin script languages
- Word suggestion dictionaries (in 0.4.0)
- Spell check dictionaries
- User dictionaries (not in 0.3.14)
- Other features that require only data and no logic (not in 0.3.14)
- Simplify screen based on previously discussed ideas and mock-ups
- Improve backend setup logic
- Implement base-UI for extensions and further continue development of existing Flex (FlorisBoard extension) format
- Allows for a continuous experience of customizing FlorisBoard in different areas
- Planned what will use Flex:
- Themes
- Layouts (Characters, symbols, numeric, ...)
- Composers for non-Latin script languages
- Word suggestion dictionaries (in 0.4.0)
- Spell check dictionaries
- User dictionaries (not in 0.3.14)
- Other features that require only data and no logic (not in 0.3.14)
- Maybe full backup of preferences? Not 100% confirmed though and may be pushed back
- Theme rework part I:
- Custom key corner radius
- Custom key border color (not shadow!!)
- Re-work theme internals so they use Flex extension format and FlexCSS
- Improvement of the Smartbar
- Allow to have multiple Smartbars
- Better candidate view (in prep for 0.4.0)
- Allow to have multiple Smartbars
- Better candidate view (in prep for 0.4.0)
### 0.3.15
- Hotfix release for possible bugs in the preference rework, may be skipped and 0.4.0 is directly released.
### 0.3.15 & 0.3.16
- Hotfix releases for possible bugs in the preference rework, may be skipped.
## 0.4.0
- Re-adding word suggestions (at least for Latin-based languages at first)
- Importing the dictionaries as well as management relies on the Flex extension core and UI in Kotlin
- Actually parsing and generating suggestions happens in C++ to avoid another OOM catastrophe like in 0.3.9/10
- The actual format of the dictionary and word list source is not decided yet
- Importing the dictionaries as well as management relies on the Flex extension core and UI in Kotlin
- Actually parsing and generating suggestions happens in C++ to avoid another OOM catastrophe like in 0.3.9/10
- The actual format of the dictionary and word list source is not decided yet
- Community repository on GitHub for theme sharing across users (may be 0.5.0)
With this release the versioning scheme changes: the second number now indicates new features,
changes in the third "patch" number now indicates bug fixes for the stable track. The development
cycle for each 0.x release will have `-alphaXX`, `-betaXX` and `-rcXX` (release candidate) releases on the beta
track for interested people to follow along the development. The first release to follow the new scheme will be `0.4.0-alpha01`
on the beta track.
With this release the versioning scheme changes: the second number now indicates new features, changes in the third "
patch" number now indicates bug fixes and minor feature additions for the stable track. The development cycle for each
0.x release will have `-alphaXX`, `-betaXX` and `-rcXX` (release candidate) releases on the beta track for interested
people to follow along the development. The first release to follow the new scheme will be `0.4.0-alpha01` on the beta
track.
## 0.5.0
- Complete rework of the Emoji panel
- Recently used / Emoji history
- Emoji search
- Emoji suggestions when using :emoji_name: syntax
- Kaomoji panel implementation (the third tab which currently has "not yet implemented")
- Recently used / Emoji history (already implemented with 0.3.14)
- Emoji search
- Emoji suggestions when using :emoji_name: syntax
- Kaomoji panel implementation (the third tab which currently has "not yet implemented")
- Smartbar customization improvements
- Quick actions customization (order and which buttons to show)
- Prepare FlorisBoard repository and app store presence for public beta release
on Google Play (will go live with stable 0.5.0!!)
- Quick actions customization (order and which buttons to show)
- Prepare FlorisBoard repository and app store presence for public beta release on Google Play (will go live with stable
0.5.0!!)
- Rework branding images and texts of FlorisBoard for the app stores
- Focus on stability and experience improvements of the app and keyboard
## 0.6.0
- Full on-board layout editor which allows users to create their own layouts
without writing a JSON file
- Full on-board layout editor which allows users to create their own layouts without writing a JSON file
- Import/Export of custom layout files packed in Flex extensions
## Backlog / Features that MAY be added, even in versions not mentioned above if the feature implementation fits perfectly with another feature
- Theme rework part II
- Adaptive themes v2
- Voice-to-text with Mozilla's open-source voice service

View File

@@ -30,9 +30,9 @@ android {
defaultConfig {
applicationId = "dev.patrickgold.florisboard"
minSdk = 23
targetSdk = 30
versionCode = 64
versionName = "0.3.14"
targetSdk = 31
versionCode = 80
versionName = "0.3.15"
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
@@ -70,12 +70,21 @@ android {
}
}
bundle {
language {
// We disable language split because FlorisBoard does not use
// runtime Google Play Service APIs and thus cannot dynamically
// request to download the language resources for a specific locale.
enableSplit = false
}
}
buildFeatures {
compose = true
}
composeOptions {
kotlinCompilerExtensionVersion = "1.1.0-rc01"
kotlinCompilerExtensionVersion = "1.1.1"
}
externalNativeBuild {
@@ -90,7 +99,7 @@ android {
versionNameSuffix = "-debug"
isDebuggable = true
isJniDebuggable = true
isJniDebuggable = false
ndk {
// For running FlorisBoard on the emulator
@@ -106,7 +115,7 @@ android {
create("beta") // Needed because by default the "beta" BuildType does not exist
named("beta").configure {
applicationIdSuffix = ".beta"
versionNameSuffix = "-beta08"
versionNameSuffix = ""
proguardFiles.add(getDefaultProguardFile("proguard-android-optimize.txt"))
resValue("mipmap", "floris_app_icon", "@mipmap/ic_app_icon_beta")
@@ -133,10 +142,6 @@ android {
it.useJUnitPlatform()
}
}
lint {
isAbortOnError = false
}
}
tasks.withType<Test> {
@@ -148,26 +153,31 @@ dependencies {
implementation("androidx.activity:activity-ktx:1.4.0")
implementation("androidx.autofill:autofill:1.1.0")
implementation("androidx.collection:collection-ktx:1.2.0")
implementation("androidx.compose.material:material:1.1.0-rc01")
implementation("androidx.compose.runtime:runtime-livedata:1.1.0-rc01")
implementation("androidx.compose.ui:ui:1.1.0-rc01")
implementation("androidx.compose.ui:ui-tooling-preview:1.1.0-rc01")
implementation("androidx.compose.material:material:1.1.1")
implementation("androidx.compose.runtime:runtime-livedata:1.1.1")
implementation("androidx.compose.ui:ui:1.1.1")
implementation("androidx.compose.ui:ui-tooling-preview:1.1.1")
implementation("androidx.core:core-ktx:1.7.0")
implementation("androidx.core:core-splashscreen:1.0.0-alpha02")
implementation("androidx.navigation:navigation-compose:2.4.0-rc01")
implementation("com.google.accompanist:accompanist-systemuicontroller:0.20.2")
implementation("dev.patrickgold.jetpref:jetpref-datastore-model:0.1.0-beta02")
implementation("dev.patrickgold.jetpref:jetpref-datastore-ui:0.1.0-beta02")
implementation("dev.patrickgold.jetpref:jetpref-material-ui:0.1.0-beta02")
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-android:1.5.2")
implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:1.3.1")
implementation("androidx.room:room-runtime:2.4.0")
kapt("androidx.room:room-compiler:2.4.0")
implementation("androidx.core:core-splashscreen:1.0.0-beta01")
implementation("androidx.emoji2:emoji2:1.1.0")
implementation("androidx.emoji2:emoji2-views:1.1.0")
implementation("androidx.navigation:navigation-compose:2.4.1")
implementation("com.google.accompanist:accompanist-flowlayout:0.23.0")
implementation("com.google.accompanist:accompanist-insets:0.23.0")
implementation("com.google.accompanist:accompanist-systemuicontroller:0.23.0")
implementation("dev.patrickgold.jetpref:jetpref-datastore-model:0.1.0-beta08")
implementation("dev.patrickgold.jetpref:jetpref-datastore-ui:0.1.0-beta08")
implementation("dev.patrickgold.jetpref:jetpref-material-ui:0.1.0-beta08")
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-android:1.6.0")
implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:1.3.2")
implementation("androidx.room:room-runtime:2.4.2")
kapt("androidx.room:room-compiler:2.4.2")
testImplementation("io.kotest:kotest-runner-junit5:4.6.3")
testImplementation("io.kotest:kotest-assertions-core:4.6.3")
testImplementation("io.kotest:kotest-property:4.6.3")
testImplementation("io.kotest.extensions:kotest-extensions-robolectric:0.4.0")
testImplementation("io.kotest:kotest-runner-junit5:5.1.0")
testImplementation("io.kotest:kotest-assertions-core:5.1.0")
testImplementation("io.kotest:kotest-property:5.1.0")
testImplementation("io.kotest.extensions:kotest-extensions-robolectric:0.5.0")
testImplementation("nl.jqno.equalsverifier:equalsverifier:3.8.3")
androidTestImplementation("androidx.test.ext", "junit", "1.1.2")
androidTestImplementation("androidx.test.espresso", "espresso-core", "3.3.0")

View File

@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (C) 2020 Patrick Goldinger
<!-- Copyright (C) 2020-2022 Patrick Goldinger
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@@ -36,12 +36,15 @@
<application
android:name="dev.patrickgold.florisboard.FlorisApplication"
android:allowBackup="false"
android:allowBackup="true"
android:dataExtractionRules="@xml/backup_rules"
android:fullBackupContent="@xml/backup_rules"
android:icon="@mipmap/floris_app_icon"
android:label="@string/floris_app_name"
android:roundIcon="@mipmap/floris_app_icon_round"
android:supportsRtl="true"
android:theme="@style/FlorisAppTheme">
android:theme="@style/FlorisAppTheme"
tools:targetApi="s">
<!-- IME service -->
<service
@@ -125,13 +128,25 @@
android:label="@string/crash_dialog__title"
android:theme="@style/CrashDialogTheme"/>
<!-- Clipboard Media File Provider -->
<provider
android:name="dev.patrickgold.florisboard.ime.clipboard.provider.FlorisContentProvider"
android:authorities="${applicationId}.provider.clip"
android:name="dev.patrickgold.florisboard.ime.clipboard.provider.ClipboardMediaProvider"
android:authorities="${applicationId}.provider.clipboard"
android:grantUriPermissions="true"
android:exported="false">
</provider>
<!-- Default file provider to share files from the "files" or "cache" dir -->
<provider
android:name="androidx.core.content.FileProvider"
android:authorities="${applicationId}.provider.file"
android:grantUriPermissions="true"
android:exported="false">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/file_paths"/>
</provider>
</application>
</manifest>

View File

@@ -1,11 +1,19 @@
{
"package": "dev.patrickgold.florisboard",
"$": "ime.extension.keyboard",
"meta": {
"id": "org.florisboard.composers",
"version": "0.1.0",
"title": "Default composers",
"description": "Default composers which are always available.",
"maintainers": [ "patrickgold <patrick@patrickgold.dev>" ],
"license": "apache-2.0"
},
"composers": [
{ "$": "appender" },
{ "$": "hangul-unicode" },
{ "$": "kana-unicode" },
{ "$": "with-rules",
"name": "basic-telex",
"id": "basic-telex",
"label": "Basic Telex",
"rules": {
"aw": "ă", "aa": "â", "dd": "đ", "ee": "ê", "oo": "ô", "ow": "ơ", "uw": "ư", "w": "ư",
@@ -50,8 +58,5 @@
"ỳz": "y", "ỷz": "y", "ỹz": "y", "ýz": "y", "ỵz": "y"
}
}
],
"currencySets": [],
"defaultSubtypes": [
]
}

View File

@@ -9,6 +9,18 @@
"license": "apache-2.0"
},
"currencySets": [
{
"id": "armenian_dram",
"label": "Armenian dram (֏)",
"slots": [
{ "code": 1423, "label": "֏" },
{ "code": 36, "label": "$" },
{ "code": 8364, "label": "€" },
{ "code": 162, "label": "¢" },
{ "code": 163, "label": "£" },
{ "code": 165, "label": "¥" }
]
},
{
"id": "azerbaijani_manat",
"label": "Azerbaijani manat (₼)",

View File

@@ -17,6 +17,26 @@
"direction": "rtl",
"modifier": "org.florisboard.layouts:arabic"
},
{
"id": "western_armenian",
"label": "Armenian (Western)",
"authors": [ "PJTSearch" ],
"direction": "ltr",
"modifier": "org.florisboard.layouts:armenian"
},
{
"id": "eastern_armenian",
"label": "Armenian (Eastern)",
"authors": [ "PJTSearch" ],
"direction": "ltr",
"modifier": "org.florisboard.layouts:armenian"
},
{
"id": "azerbaijani",
"label": "Azerbaijani",
"authors": [ "nijatismayilzada" ],
"direction": "ltr"
},
{
"id": "azerty",
"label": "AZERTY",
@@ -72,6 +92,12 @@
"authors": [ "patrickgold" ],
"direction": "ltr"
},
{
"id": "colemak_dh",
"label": "ColemakDH",
"authors": [ "blucin" ],
"direction": "ltr"
},
{
"id": "danish",
"label": "Danish (QWERTY)",
@@ -109,6 +135,12 @@
"authors": [ "mahmoudk1000" ],
"direction": "ltr"
},
{
"id": "german2",
"label": "German (GBoard)",
"authors": [ "M-Koushan" ],
"direction": "rtl"
},
{
"id": "greek",
"label": "Ελληνικά",
@@ -223,6 +255,13 @@
"direction": "rtl",
"modifier": "org.florisboard.layouts:persian"
},
{
"id": "persian2",
"label": "Persian2",
"authors": [ "M-Koushan" ],
"direction": "rtl",
"modifier": "org.florisboard.layouts:persian2"
},
{
"id": "qwerty",
"label": "QWERTY",
@@ -235,6 +274,18 @@
"authors": [ "patrickgold" ],
"direction": "ltr"
},
{
"id": "rusyn",
"label": "Rusyn",
"authors": [ "svvvst" ],
"direction": "ltr"
},
{
"id": "rusyn_us",
"label": "Rusyn (Phonetic)",
"authors": [ "svvvst" ],
"direction": "ltr"
},
{
"id": "sangaline",
"label": "Sangaline",
@@ -334,6 +385,12 @@
"authors": [ "patrickgold" ],
"direction": "ltr"
},
{
"id": "armenian",
"label": "Armenian",
"authors": [ "PJTSearch" ],
"direction": "ltr"
},
{
"id": "arabic",
"label": "Arabic",
@@ -375,6 +432,12 @@
"label": "Persian",
"authors": [ "PHELAT" ],
"direction": "rtl"
},
{
"id": "persian2",
"label": "Persian2",
"authors": [ "M-Koushan" ],
"direction": "rtl"
}
],
"extension": [
@@ -528,6 +591,13 @@
}
],
"symbols": [
{
"id": "armenian",
"label": "Armenian",
"authors": [ "PJTSearch" ],
"direction": "ltr",
"modifier": "org.florisboard.layouts:armenian"
},
{
"id": "cjk",
"label": "CJK",
@@ -580,6 +650,12 @@
"authors": [ "patrickgold" ],
"direction": "ltr"
},
{
"id": "armenian",
"label": "Armenian",
"authors": [ "PJTSearch" ],
"direction": "ltr"
},
{
"id": "cjk",
"label": "CJK",

View File

@@ -0,0 +1,46 @@
[
[
{ "$": "auto_text_key", "code": 113, "label": "q" },
{ "$": "auto_text_key", "code": 252, "label": "ü" },
{ "$": "auto_text_key", "code": 101, "label": "e" },
{ "$": "auto_text_key", "code": 114, "label": "r" },
{ "$": "auto_text_key", "code": 116, "label": "t" },
{ "$": "auto_text_key", "code": 121, "label": "y" },
{ "$": "auto_text_key", "code": 117, "label": "u" },
{ "$": "case_selector",
"lower": { "code": 105, "label": "i" },
"upper": { "code": 304, "label": "İ" }
},
{ "$": "auto_text_key", "code": 111, "label": "o" },
{ "$": "auto_text_key", "code": 112, "label": "p" },
{ "$": "auto_text_key", "code": 246, "label": "ö" },
{ "$": "auto_text_key", "code": 287, "label": "ğ" }
],
[
{ "$": "auto_text_key", "code": 97, "label": "a" },
{ "$": "auto_text_key", "code": 115, "label": "s" },
{ "$": "auto_text_key", "code": 100, "label": "d" },
{ "$": "auto_text_key", "code": 102, "label": "f" },
{ "$": "auto_text_key", "code": 103, "label": "g" },
{ "$": "auto_text_key", "code": 104, "label": "h" },
{ "$": "auto_text_key", "code": 106, "label": "j" },
{ "$": "auto_text_key", "code": 107, "label": "k" },
{ "$": "auto_text_key", "code": 108, "label": "l" },
{ "$": "case_selector",
"lower": { "code": 305, "label": "ı" },
"upper": { "code": 73, "label": "I" }
},
{ "$": "auto_text_key", "code": 601, "label": "ə" }
],
[
{ "$": "auto_text_key", "code": 122, "label": "z" },
{ "$": "auto_text_key", "code": 120, "label": "x" },
{ "$": "auto_text_key", "code": 99, "label": "c" },
{ "$": "auto_text_key", "code": 118, "label": "v" },
{ "$": "auto_text_key", "code": 98, "label": "b" },
{ "$": "auto_text_key", "code": 110, "label": "n" },
{ "$": "auto_text_key", "code": 109, "label": "m" },
{ "$": "auto_text_key", "code": 231, "label": "ç" },
{ "$": "auto_text_key", "code": 351, "label": "ş" }
]
]

View File

@@ -0,0 +1,46 @@
[
[
{ "$": "auto_text_key", "code": 113, "label": "q" },
{ "$": "auto_text_key", "code": 119, "label": "w" },
{ "$": "auto_text_key", "code": 102, "label": "f" },
{ "$": "auto_text_key", "code": 112, "label": "p" },
{ "$": "auto_text_key", "code": 98, "label": "b" },
{ "$": "auto_text_key", "code": 106, "label": "j" },
{ "$": "auto_text_key", "code": 108, "label": "l" },
{ "$": "auto_text_key", "code": 117, "label": "u" },
{ "$": "auto_text_key", "code": 121, "label": "y" },
{ "$": "case_selector",
"lower": { "code": 59, "label": ";", "popup": {
"relevant": [
{ "code": 58, "label": ":" }
]
} },
"upper": { "code": 58, "label": ":", "popup": {
"relevant": [
{ "code": 59, "label": ";" }
]
} }
}
],
[
{ "$": "auto_text_key", "code": 97, "label": "a" },
{ "$": "auto_text_key", "code": 114, "label": "r" },
{ "$": "auto_text_key", "code": 115, "label": "s" },
{ "$": "auto_text_key", "code": 116, "label": "t" },
{ "$": "auto_text_key", "code": 103, "label": "g" },
{ "$": "auto_text_key", "code": 109, "label": "m" },
{ "$": "auto_text_key", "code": 110, "label": "n" },
{ "$": "auto_text_key", "code": 101, "label": "e" },
{ "$": "auto_text_key", "code": 105, "label": "i" },
{ "$": "auto_text_key", "code": 111, "label": "o" }
],
[
{ "$": "auto_text_key", "code": 120, "label": "x" },
{ "$": "auto_text_key", "code": 99, "label": "c" },
{ "$": "auto_text_key", "code": 100, "label": "d" },
{ "$": "auto_text_key", "code": 118, "label": "v" },
{ "$": "auto_text_key", "code": 122, "label": "z" },
{ "$": "auto_text_key", "code": 107, "label": "k" },
{ "$": "auto_text_key", "code": 104, "label": "h" }
]
]

View File

@@ -0,0 +1,48 @@
[
[
{ "$": "auto_text_key", "code": 1393, "label": "ձ" },
{ "$": "auto_text_key", "code": 1397, "label": "յ" },
{ "$": "auto_text_key", "code": 1413, "label": "օ" },
{ "$": "auto_text_key", "code": 1404, "label": "ռ" },
{ "$": "auto_text_key", "code": 1386, "label": "ժ" },
{ "$": "auto_text_key", "code": 1401, "label": "չ" },
{ "$": "auto_text_key", "code": 1403, "label": "ջ" },
{ "$": "auto_text_key", "code": 1411, "label": "փ" },
{ "$": "auto_text_key", "code": 1394, "label": "ղ" },
{ "$": "auto_text_key", "code": 1390, "label": "ծ" }
],
[
{ "$": "auto_text_key", "code": 1389, "label": "խ" },
{ "$": "auto_text_key", "code": 1410, "label": "ւ" },
{ "$": "auto_text_key", "code": 1383, "label": "է" },
{ "$": "auto_text_key", "code": 1408, "label": "ր" },
{ "$": "auto_text_key", "code": 1407, "label": "տ" },
{ "$": "auto_text_key", "code": 1381, "label": "ե" },
{ "$": "auto_text_key", "code": 1384, "label": "ը" },
{ "$": "auto_text_key", "code": 1387, "label": "ի" },
{ "$": "auto_text_key", "code": 1400, "label": "ո" },
{ "$": "auto_text_key", "code": 1402, "label": "պ" }
],
[
{ "$": "auto_text_key", "code": 1377, "label": "ա" },
{ "$": "auto_text_key", "code": 1405, "label": "ս" },
{ "$": "auto_text_key", "code": 1380, "label": "դ" },
{ "$": "auto_text_key", "code": 1414, "label": "ֆ" },
{ "$": "auto_text_key", "code": 1412, "label": "ք" },
{ "$": "auto_text_key", "code": 1392, "label": "հ" },
{ "$": "auto_text_key", "code": 1395, "label": "ճ" },
{ "$": "auto_text_key", "code": 1391, "label": "կ" },
{ "$": "auto_text_key", "code": 1388, "label": "լ" },
{ "$": "auto_text_key", "code": 1385, "label": "թ" }
],
[
{ "$": "auto_text_key", "code": 1382, "label": "զ" },
{ "$": "auto_text_key", "code": 1409, "label": "ց" },
{ "$": "auto_text_key", "code": 1379, "label": "գ" },
{ "$": "auto_text_key", "code": 1406, "label": "վ" },
{ "$": "auto_text_key", "code": 1378, "label": "բ" },
{ "$": "auto_text_key", "code": 1398, "label": "ն" },
{ "$": "auto_text_key", "code": 1396, "label": "մ" },
{ "$": "auto_text_key", "code": 1399, "label": "շ" }
]
]

View File

@@ -0,0 +1,37 @@
[
[
{ "$": "auto_text_key", "code": 113, "label": "q" },
{ "$": "auto_text_key", "code": 119, "label": "w" },
{ "$": "auto_text_key", "code": 101, "label": "e" },
{ "$": "auto_text_key", "code": 114, "label": "r" },
{ "$": "auto_text_key", "code": 116, "label": "t" },
{ "$": "auto_text_key", "code": 122, "label": "z" },
{ "$": "auto_text_key", "code": 117, "label": "u" },
{ "$": "auto_text_key", "code": 105, "label": "i" },
{ "$": "auto_text_key", "code": 111, "label": "o" },
{ "$": "auto_text_key", "code": 112, "label": "p" },
{ "$": "auto_text_key", "code": 252, "label": "ü" }
],
[
{ "$": "auto_text_key", "code": 97, "label": "a" },
{ "$": "auto_text_key", "code": 115, "label": "s" },
{ "$": "auto_text_key", "code": 100, "label": "d" },
{ "$": "auto_text_key", "code": 102, "label": "f" },
{ "$": "auto_text_key", "code": 103, "label": "g" },
{ "$": "auto_text_key", "code": 104, "label": "h" },
{ "$": "auto_text_key", "code": 106, "label": "j" },
{ "$": "auto_text_key", "code": 107, "label": "k" },
{ "$": "auto_text_key", "code": 108, "label": "l" },
{ "$": "auto_text_key", "code": 246, "label": "ö" },
{ "$": "auto_text_key", "code": 228, "label": "ä" }
],
[
{ "$": "auto_text_key", "code": 121, "label": "y" },
{ "$": "auto_text_key", "code": 120, "label": "x" },
{ "$": "auto_text_key", "code": 99, "label": "c" },
{ "$": "auto_text_key", "code": 118, "label": "v" },
{ "$": "auto_text_key", "code": 98, "label": "b" },
{ "$": "auto_text_key", "code": 110, "label": "n" },
{ "$": "auto_text_key", "code": 109, "label": "m" }
]
]

View File

@@ -2,44 +2,85 @@
[
{ "code": 39, "label": "'", "popup": {
"relevant": [
{ "code": 1474, "label": "ש\u05c2" },
{ "code": 1467, "label": "ס\u05bb" },
{ "code": 1523, "label": "׳" },
{ "code": 1524, "label": "״" },
{ "code": 34, "label": "\"" },
{ "code": 96, "label": "`" }
]
} },
{ "code": 45, "label": "-", "popup": {
"relevant": [
{ "code": 1470, "label": "־" },
{ "code": 1473, "label": "ש\u05c1" },
{ "code": 95, "label": "_" }
]
} },
{ "code": 1511, "label": "ק" },
{ "code": 1511, "label": "ק", "popup": {
"relevant": [
{ "code": 1464, "label": "ס\u05b8" },
{ "code": 1459, "label": "ס\u05b3" }
]
} },
{ "code": 1512, "label": "ר" },
{ "code": 1488, "label": "א" },
{ "code": 1496, "label": "ט" },
{ "code": 1493, "label": "ו" },
{ "code": 1493, "label": "ו", "popup": {
"relevant": [
{ "code": 1465, "label": "ס\u05b9" }
]
} },
{ "code": 1503, "label": "ן" },
{ "code": 1501, "label": "ם" },
{ "code": 1508, "label": "פ" }
{ "code": 1508, "label": "פ", "popup": {
"relevant": [
{ "code": 1463, "label": "ס\u05b7" },
{ "code": 1458, "label": "ס\u05b2" }
]
} }
],
[
{ "code": 1513, "label": "ש" },
{ "code": 1491, "label": "ד" },
{ "code": 1513, "label": "ש", "popup": {
"relevant": [
{ "code": 1456, "label": "ס\u05b0" }
]
} },
{ "code": 1491, "label": "ד", "popup": {
"relevant": [
{ "code": 1468, "label": "ס\u05bc" }
]
} },
{ "code": 1490, "label": "ג" },
{ "code": 1499, "label": "כ" },
{ "code": 1506, "label": "ע" },
{ "code": 1497, "label": "י" },
{ "code": 1495, "label": "ח" },
{ "code": 1495, "label": "ח", "popup": {
"relevant": [
{ "code": 1460, "label": "ס\u05b4" }
]
} },
{ "code": 1500, "label": "ל" },
{ "code": 1498, "label": "ך" },
{ "code": 1507, "label": "ף" }
],
[
{ "code": 1494, "label": "ז" },
{ "code": 1505, "label": "ס" },
{ "code": 1505, "label": "ס", "popup": {
"relevant": [
{ "code": 1462, "label": "ס\u05b6" },
{ "code": 1457, "label": "ס\u05b1" }
]
} },
{ "code": 1489, "label": "ב" },
{ "code": 1492, "label": "ה" },
{ "code": 1504, "label": "נ" },
{ "code": 1502, "label": "מ" },
{ "code": 1510, "label": "צ" },
{ "code": 1510, "label": "צ", "popup": {
"relevant": [
{ "code": 1461, "label": "ס\u05b5" }
]
} },
{ "code": 1514, "label": "ת" },
{ "code": 1509, "label": "ץ" }
]

View File

@@ -1,13 +1,13 @@
[
[
[
{ "code": 1602, "label": "ق", "popup": {
"main": { "code": 1647, "label": "ٯ" }
} },
{ "code": 1608, "label": "و", "popup": {
"main": { "code": -255, "label": "وو" }
} },
{ "code": 1749, "label": "", "popup": {
"main": { "code": 1577, "label": "ة" }
{ "code": 1749, "label": "ە", "popup": {
"main": { "code": 1577, "label": "ة" }
} },
{ "code": 1585, "label": "ر", "popup": {
"main": { "code": 1685, "label": "ڕ" }
@@ -15,50 +15,49 @@
{ "code": 1578, "label": "ت", "popup": {
"main": { "code": 1591, "label": "ط" }
} },
{ "code": 1740, "label": "ی", "popup": {
"main": { "code": 1742, "label": "ێ" }
} },
{ "code": 1740, "label": "ی" },
{ "code": 1742, "label": "ێ" },
{ "code": 1574, "label": "ﺋ", "popup": {
"main": { "code": 1569, "label": "ء" }
} },
{ "code": 1593, "label": "ع", "popup": {
"main": { "code": 1594, "label": "غ" }
} },
{ "code": 1734, "label": "ۆ" },
{ "code": 1662, "label": "پ", "popup": {
"main": { "code": 1579, "label": "ث" }
} }
],
[
{"code": 1575, "label": "ا"},
{ "code": 1587, "label": "س" },
{ "code": 1588, "label": "ش" },
{ "code": 1583, "label": "د", "popup": {
"main": {"code": 1584, "label": "ذ" }
],
[
{ "code": 1575, "label": "ا"},
{ "code": 1587, "label": "س" },
{ "code": 1588, "label": "ش" },
{ "code": 1583, "label": "د", "popup": {
"main": {"code": 1584, "label": "ذ" }
} },
{ "code": 1601, "label": "ف" , "popup": {
"main": {"code": 1700, "label": "ڤ" }
} },
{ "code": 1601, "label": "ف" , "popup": {
"main": {"code": 1700, "label": "ڤ" }
} },
{ "code": 1607, "label": "ھ" },
{ "code": 1688, "label": "ژ", "popup": {
"main": { "code": 1600, "label": "" }
} },
{ "code": 1604, "label": "ل", "popup": {
"main": { "code": 1717, "label": "ڵ" }
} },
{ "code": 1705, "label": "ک" },
{ "code": 1711, "label": "گ" }
],
[
{ "code": 1586, "label": "ز", "popup": {
"main": {"code": 1592, "label": "ظ" }
} },
{ "code": 1582, "label": "خ" },
{ "code": 1580, "label": "ج" },
{ "code": 1670, "label": "چ" },
{ "code": 1581, "label": "ح" },
{ "code": 1576, "label": "ب" },
{ "code": 1606, "label": "ن" },
{ "code": 1605, "label": "م" }
{ "code": 1726, "label": "ھ" },
{ "code": 1688, "label": "ژ", "popup": {
"main": { "code": 1600, "label": "━" }
} },
{ "code": 1604, "label": "ل", "popup": {
"main": { "code": 1717, "label": "ڵ" }
} },
{ "code": 1705, "label": "ک" },
{ "code": 1711, "label": "گ" , "popup": {
"main": { "code": 1594, "label": "غ" }
} }
],
[
{ "code": 1586, "label": "ز", "popup": {
"main": {"code": 1592, "label": "ظ" }
} },
{ "code": 1582, "label": "خ" },
{ "code": 1580, "label": "ج" },
{ "code": 1670, "label": "چ" },
{ "code": 1581, "label": "ح" },
{ "code": 1593, "label": "ع" },
{ "code": 1576, "label": "ب" },
{ "code": 1606, "label": "ن" },
{ "code": 1605, "label": "م" }
]
]
]

View File

@@ -60,7 +60,7 @@
{ "code": 1605, "label": "م" },
{ "code": 1567, "label": "؟" },
{ "code": 1548, "label": "،" },
{ "code": 46, "label": "." }
{ "code": 58, "label": ":" }
]
]

View File

@@ -0,0 +1,36 @@
[
[
{ "code": 1589, "label": "ص" },
{ "code": 1602, "label": "ق" },
{ "code": 1601, "label": "ف" },
{ "code": 1594, "label": "غ" },
{ "code": 1593, "label": "ع" },
{ "code": 1607, "label": "ه" },
{ "code": 1582, "label": "خ" },
{ "code": 1581, "label": "ح" },
{ "code": 1580, "label": "ج" },
{ "code": 1670, "label": "چ" }
],
[
{ "code": 1588, "label": "ش" },
{ "code": 1587, "label": "س" },
{ "code": 1740, "label": "ی" },
{ "code": 1576, "label": "ب" },
{ "code": 1604, "label": "ل" },
{ "code": 1575, "label": "ا" },
{ "code": 1578, "label": "ت" },
{ "code": 1606, "label": "ن" },
{ "code": 1605, "label": "م" },
{ "code": 1705, "label": "ک" }
],
[
{ "code": 8204, "label": "half_space" },
{ "code": 1591, "label": "ط" },
{ "code": 1586, "label": "ز" },
{ "code": 1585, "label": "ر" },
{ "code": 1584, "label": "ذ" },
{ "code": 1583, "label": "د" },
{ "code": 1608, "label": "و" },
{ "code": 1711, "label": "گ" }
]
]

View File

@@ -0,0 +1,47 @@
[
[
{ "$": "auto_text_key", "code": 1081, "label": "й" },
{ "$": "auto_text_key", "code": 1094, "label": "ц" },
{ "$": "auto_text_key", "code": 1091, "label": "у" },
{ "$": "auto_text_key", "code": 1082, "label": "к" },
{ "$": "auto_text_key", "code": 1077, "label": "е" },
{ "$": "auto_text_key", "code": 1085, "label": "н" },
{ "$": "auto_text_key", "code": 1075, "label": "г" },
{ "$": "auto_text_key", "code": 1096, "label": "ш" },
{ "$": "auto_text_key", "code": 1097, "label": "щ" },
{ "$": "auto_text_key", "code": 1079, "label": "з" },
{ "$": "auto_text_key", "code": 1093, "label": "х" },
{ "$": "auto_text_key", "code": 1031, "label": "ї" }
],
[
{ "$": "auto_text_key", "code": 1092 , "label": "ф" },
{ "$": "auto_text_key", "code": 1110 , "label": "і" },
{ "$": "auto_text_key", "code": 1074 , "label": "в" },
{ "$": "auto_text_key", "code": 1072 , "label": "а" },
{ "$": "auto_text_key", "code": 1087 , "label": "п" },
{ "$": "auto_text_key", "code": 1088 , "label": "р" },
{ "$": "auto_text_key", "code": 1086 , "label": "о" },
{ "$": "auto_text_key", "code": 1083 , "label": "л" },
{ "$": "auto_text_key", "code": 1076 , "label": "д" },
{ "$": "auto_text_key", "code": 1078 , "label": "ж" },
{ "$": "auto_text_key", "code": 1108 , "label": "є" },
{ "$": "auto_text_key", "code": 1067 , "label": "ы" }
],
[
{ "$": "auto_text_key", "code": 1169 , "label": "ґ" },
{ "$": "auto_text_key", "code": 1103 , "label": "я" },
{ "$": "auto_text_key", "code": 1095 , "label": "ч" },
{ "$": "auto_text_key", "code": 1089 , "label": "с" },
{ "$": "auto_text_key", "code": 1084 , "label": "м" },
{ "$": "auto_text_key", "code": 1080 , "label": "и" },
{ "$": "auto_text_key", "code": 1090 , "label": "т" },
{ "$": "auto_text_key", "code": 1100 , "label": "ь" },
{ "$": "auto_text_key", "code": 1073 , "label": "б" },
{ "$": "auto_text_key", "code": 1102 , "label": "ю" },
{ "$": "auto_text_key", "code": 1025 , "label": "ё" }
]
]

View File

@@ -0,0 +1,46 @@
[
[
{ "$": "auto_text_key", "code": 1094, "label": "ц" },
{ "$": "auto_text_key", "code": 1108 , "label": "є" },
{ "$": "auto_text_key", "code": 1077, "label": "е" },
{ "$": "auto_text_key", "code": 1088 , "label": "р" },
{ "$": "auto_text_key", "code": 1090 , "label": "т" },
{ "$": "auto_text_key", "code": 1081, "label": "й" },
{ "$": "auto_text_key", "code": 1091, "label": "у" },
{ "$": "auto_text_key", "code": 1102 , "label": "ю" },
{ "$": "auto_text_key", "code": 1110 , "label": "і" },
{ "$": "auto_text_key", "code": 1031, "label": "ї" },
{ "$": "auto_text_key", "code": 1086 , "label": "о" },
{ "$": "auto_text_key", "code": 1025 , "label": "ё" },
{ "$": "auto_text_key", "code": 1087 , "label": "п" }
],
[
{ "$": "auto_text_key", "code": 1103 , "label": "я" },
{ "$": "auto_text_key", "code": 1072 , "label": "а" },
{ "$": "auto_text_key", "code": 1089 , "label": "с" },
{ "$": "auto_text_key", "code": 1076 , "label": "д" },
{ "$": "auto_text_key", "code": 1092 , "label": "ф" },
{ "$": "auto_text_key", "code": 1169 , "label": "ґ" },
{ "$": "auto_text_key", "code": 1067 , "label": "ы" },
{ "$": "auto_text_key", "code": 1075, "label": "г" },
{ "$": "auto_text_key", "code": 1078 , "label": "ж" },
{ "$": "auto_text_key", "code": 1082, "label": "к" },
{ "$": "auto_text_key", "code": 1083 , "label": "л" },
{ "$": "auto_text_key", "code": 1096, "label": "ш" },
{ "$": "auto_text_key", "code": 1097, "label": "щ" }
],
[
{ "$": "auto_text_key", "code": 1079, "label": "з" },
{ "$": "auto_text_key", "code": 1093, "label": "х" },
{ "$": "auto_text_key", "code": 1095 , "label": "ч" },
{ "$": "auto_text_key", "code": 1074 , "label": "в" },
{ "$": "auto_text_key", "code": 1073 , "label": "б" },
{ "$": "auto_text_key", "code": 1085, "label": "н" },
{ "$": "auto_text_key", "code": 1084 , "label": "м" },
{ "$": "auto_text_key", "code": 1080 , "label": "и" },
{ "$": "auto_text_key", "code": 1100 , "label": "ь" }
]
]

View File

@@ -4,7 +4,7 @@
{ "code": 1608, "label": "و" },
{ "code": 1593, "label": "ع" },
{ "code": 1585, "label": "ر" },
{ "code": 1587, "label": "ت" },
{ "code": 1578, "label": "ت" },
{ "code": 1746, "label": "ے" },
{ "code": 1569, "label": "ء" },
{ "code": 1740, "label": "ی" },
@@ -27,7 +27,7 @@
{ "code": 1588, "label": "ش" },
{ "code": 1670, "label": "چ" },
{ "code": 1591, "label": "ط" },
{ "code": 1576, "label": "پ" },
{ "code": 1576, "label": "ب" },
{ "code": 1606, "label": "ن" },
{ "code": 1605, "label": "م" }
]

View File

@@ -0,0 +1,49 @@
[
[
{ "$": "auto_text_key", "code": 1393, "label": "ձ" },
{ "$": "auto_text_key", "code": 1397, "label": "յ" },
{ "$": "auto_text_key", "code": 1413, "label": "օ" },
{ "$": "auto_text_key", "code": 1404, "label": "ռ" },
{ "$": "auto_text_key", "code": 1386, "label": "ժ" },
{ "$": "auto_text_key", "code": 1401, "label": "չ" },
{ "$": "auto_text_key", "code": 1403, "label": "ջ" },
{ "$": "auto_text_key", "code": 1411, "label": "փ" },
{ "$": "auto_text_key", "code": 1394, "label": "ղ" },
{ "$": "auto_text_key", "code": 1390, "label": "ծ" }
],
[
{ "$": "auto_text_key", "code": 1389, "label": "խ" },
{ "$": "auto_text_key", "code": 1406, "label": "վ" },
{ "$": "auto_text_key", "code": 1383, "label": "է" },
{ "$": "auto_text_key", "code": 1408, "label": "ր" },
{ "$": "auto_text_key", "code": 1380, "label": "դ" },
{ "$": "auto_text_key", "code": 1381, "label": "ե" },
{ "$": "auto_text_key", "code": 1384, "label": "ը" },
{ "$": "auto_text_key", "code": 1387, "label": "ի" },
{ "$": "auto_text_key", "code": 1400, "label": "ո" },
{ "$": "auto_text_key", "code": 1378, "label": "բ" }
],
[
{ "$": "auto_text_key", "code": 1377, "label": "ա" },
{ "$": "auto_text_key", "code": 1405, "label": "ս" },
{ "$": "auto_text_key", "code": 1407, "label": "տ" },
{ "$": "auto_text_key", "code": 1414, "label": "ֆ" },
{ "$": "auto_text_key", "code": 1391, "label": "կ" },
{ "$": "auto_text_key", "code": 1392, "label": "հ" },
{ "$": "auto_text_key", "code": 1395, "label": "ճ" },
{ "$": "auto_text_key", "code": 1412, "label": "ք" },
{ "$": "auto_text_key", "code": 1388, "label": "լ" },
{ "$": "auto_text_key", "code": 1385, "label": "թ" }
],
[
{ "$": "auto_text_key", "code": 1382, "label": "զ" },
{ "$": "auto_text_key", "code": 1409, "label": "ց" },
{ "$": "auto_text_key", "code": 1379, "label": "գ" },
{ "$": "auto_text_key", "code": 1410, "label": "ւ" },
{ "$": "auto_text_key", "code": 1402, "label": "պ" },
{ "$": "auto_text_key", "code": 1398, "label": "ն" },
{ "$": "auto_text_key", "code": 1396, "label": "մ" },
{ "$": "auto_text_key", "code": 1399, "label": "շ" }
]
]

View File

@@ -0,0 +1,20 @@
[
[
{ "code": -11, "label": "shift", "type": "modifier" },
{ "code": 0, "type": "placeholder" },
{ "code": -7, "label": "delete", "type": "enter_editing" }
],
[
{ "code": -202, "label": "view_symbols", "type": "system_gui" },
{ "$": "variation_selector",
"default": { "code": 44, "label": ",", "groupId": 1 },
"email": { "code": 64, "label": "@", "groupId": 1 },
"uri": { "code": 47, "label": "/", "groupId": 1 }
},
{ "code": -227, "label": "language_switch", "type": "system_gui" },
{ "code": -212, "label": "ime_ui_mode_media", "type": "system_gui" },
{ "code": 32, "label": "space" },
{ "code": 1417, "label": "։", "groupId": 2 },
{ "code": 10, "label": "enter", "groupId": 3, "type": "enter_editing" }
]
]

View File

@@ -0,0 +1,19 @@
[
[
{ "code": 0, "type": "placeholder" },
{ "code": -7, "label": "delete", "type": "enter_editing" }
],
[
{ "code": -202, "label": "view_symbols", "type": "system_gui" },
{ "code": -227, "label": "language_switch", "type": "system_gui" },
{ "code": -212, "label": "ime_ui_mode_media", "type": "system_gui" },
{ "$": "variation_selector",
"default": { "code": 1548, "label": "،", "groupId": 1 },
"email": { "code": 64, "label": "@", "groupId": 1 },
"uri": { "code": 47, "label": "/", "groupId": 1 }
},
{ "code": 32, "label": "space" },
{ "code": 46, "label": ".", "groupId": 2 },
{ "code": 10, "label": "enter", "groupId": 3, "type": "enter_editing" }
]
]

View File

@@ -1,8 +1,14 @@
[
[
{ "code": 40, "label": "(" },
{ "$": "layout_direction_selector",
"ltr": { "code": 40, "label": "(" },
"rtl": { "code": 41, "label": "(" }
},
{ "code": 47, "label": "/" },
{ "code": 41, "label": ")" },
{ "$": "layout_direction_selector",
"ltr": { "code": 41, "label": ")" },
"rtl": { "code": 40, "label": ")" }
},
{ "code": 45, "label": "-" }
],
[

View File

@@ -0,0 +1,92 @@
[
[
{ "code": 64, "label": "@" },
{ "code": 35, "label": "#", "popup": {
"main": { "code": 8470, "label": "№" }
} },
{ "code": -801, "label": "currency_slot_1", "popup": {
"main": { "code": -802, "label": "currency_slot_2" },
"relevant": [
{ "code": -806, "label": "currency_slot_6" },
{ "code": -803, "label": "currency_slot_3" },
{ "code": -804, "label": "currency_slot_4" },
{ "code": -805, "label": "currency_slot_5" }
]
} },
{ "code": 37, "label": "%", "popup": {
"main": { "code": 8240, "label": "‰" },
"relevant": [
{ "code": 8453, "label": "℅" }
]
} },
{ "code": 38, "label": "&" },
{ "code": 45, "label": "-", "popup": {
"main": { "code": 95, "label": "_" },
"relevant": [
{ "code": 8212, "label": "—" },
{ "code": 8211, "label": "" },
{ "code": 183, "label": "·" }
]
} },
{ "code": 43, "label": "+", "popup": {
"main": { "code": 177, "label": "±" }
} },
{ "code": 40, "label": "(", "popup": {
"main": { "code": 60, "label": "<" },
"relevant": [
{ "code": 91, "label": "[" },
{ "code": 123, "label": "{" }
]
} },
{ "code": 41, "label": ")", "popup": {
"main": { "code": 62, "label": ">" },
"relevant": [
{ "code": 93, "label": "]" },
{ "code": 125, "label": "}" }
]
} },
{ "code": 47, "label": "/" }
],
[
{ "code": 42, "label": "*", "popup": {
"main": { "code": 8224, "label": "†" },
"relevant": [
{ "code": 9733, "label": "★" },
{ "code": 8225, "label": "‡" }
]
} },
{ "code": 171, "label": "«", "popup": {
"main": { "code": 34, "label": "\"" },
"relevant": [
{ "code": 8221, "label": "”" },
{ "code": 8222, "label": "„" },
{ "code": 8220, "label": "“" },
{ "code": 8249, "label": "" }
]
} },
{ "code": 187, "label": "»", "popup": {
"main": { "code": 39, "label": "'" },
"relevant": [
{ "code": 8217, "label": "" },
{ "code": 8218, "label": "" },
{ "code": 8216, "label": "" },
{ "code": 8250, "label": "" }
]
} },
{ "code": 1373, "label": "՝", "popup": {
"main": { "code": 58, "label": ":" }
} },
{ "code": 46, "label": "." },
{ "code": 1372, "label": "՜", "popup": {
"main": { "code": 33, "label": "!" }
} },
{ "code": 1374, "label": "՞", "popup": {
"main": { "code": 63, "label": "?" },
"relevant": [
{ "code": 191, "label": "¿" },
{ "code": 8253, "label": "‽" }
]
} },
{ "code": 1371, "label": "՛" }
]
]

View File

@@ -32,22 +32,42 @@
{ "code": 43, "label": "+", "popup": {
"main": { "code": 177, "label": "±" }
} },
{ "code": 40, "label": "(", "popup": {
"main": { "code":64830, "label": "" },
"relevant": [
{ "code": 91, "label": "[" },
{ "code": 60, "label": "<" },
{ "code": 123, "label": "{" }
]
} },
{ "code": 41, "label": ")", "popup": {
"main": { "code":64831, "label": "﴿" },
"relevant": [
{ "code": 93, "label": "]" },
{ "code": 62, "label": ">" },
{ "code": 125, "label": "}" }
]
} },
{ "$": "layout_direction_selector",
"ltr": { "code": 40, "label": "(", "popup": {
"main": { "code":64830, "label": "" },
"relevant": [
{ "code": 91, "label": "[" },
{ "code": 60, "label": "<" },
{ "code": 123, "label": "{" }
]
} },
"rtl": { "code": 41, "label": "(", "popup": {
"main": { "code":64830, "label": "" },
"relevant": [
{ "code": 93, "label": "[" },
{ "code": 62, "label": "<" },
{ "code": 125, "label": "{" }
]
} }
},
{ "$": "layout_direction_selector",
"ltr": { "code": 41, "label": ")", "popup": {
"main": { "code":64831, "label": "﴿" },
"relevant": [
{ "code": 93, "label": "]" },
{ "code": 62, "label": ">" },
{ "code": 125, "label": "}" }
]
} },
"rtl": { "code": 40, "label": ")", "popup": {
"main": { "code":64831, "label": "﴿" },
"relevant": [
{ "code": 91, "label": "]" },
{ "code": 60, "label": ">" },
{ "code": 123, "label": "}" }
]
} }
},
{ "code": 47, "label": "/" }
],
[

View File

@@ -2,12 +2,24 @@
[
{ "code": 8230, "label": "…" },
{ "code": 95, "label": "_" },
{ "code": 91, "label": "[" },
{ "code": 93, "label": "]" },
{ "$": "layout_direction_selector",
"ltr": { "code": 91, "label": "[" },
"rtl": { "code": 93, "label": "[" }
},
{ "$": "layout_direction_selector",
"ltr": { "code": 93, "label": "]" },
"rtl": { "code": 91, "label": "]" }
},
{ "code": 94, "label": "^" },
{ "code": 33, "label": "!" },
{ "code": 60, "label": "<" },
{ "code": 62, "label": ">" },
{ "$": "layout_direction_selector",
"ltr": { "code": 60, "label": "<" },
"rtl": { "code": 62, "label": "<" }
},
{ "$": "layout_direction_selector",
"ltr": { "code": 62, "label": ">" },
"rtl": { "code": 60, "label": ">" }
},
{ "code": 61, "label": "=" },
{ "code": 38, "label": "&" },
{ "code": 383, "label": "ſ" }
@@ -15,12 +27,24 @@
[
{ "code": 92, "label": "\\" },
{ "code": 47, "label": "/" },
{ "code": 123, "label": "{" },
{ "code": 125, "label": "}" },
{ "$": "layout_direction_selector",
"ltr": { "code": 123, "label": "{" },
"rtl": { "code": 125, "label": "{" }
},
{ "$": "layout_direction_selector",
"ltr": { "code": 125, "label": "}" },
"rtl": { "code": 123, "label": "}" }
},
{ "code": 42, "label": "*" },
{ "code": 63, "label": "?" },
{ "code": 40, "label": "(" },
{ "code": 41, "label": ")" },
{ "$": "layout_direction_selector",
"ltr": { "code": 40, "label": "(" },
"rtl": { "code": 41, "label": "(" }
},
{ "$": "layout_direction_selector",
"ltr": { "code": 41, "label": ")" },
"rtl": { "code": 40, "label": ")" }
},
{ "code": 45, "label": "-" },
{ "code": 58, "label": ":" },
{ "code": 64, "label": "@" }

View File

@@ -32,22 +32,42 @@
{ "code": 43, "label": "+", "popup": {
"main": { "code": 177, "label": "±" }
} },
{ "code": 40, "label": "(", "popup": {
"main": { "code":64830, "label": "" },
"relevant": [
{ "code": 91, "label": "[" },
{ "code": 60, "label": "<" },
{ "code": 123, "label": "{" }
]
} },
{ "code": 41, "label": ")", "popup": {
"main": { "code":64831, "label": "﴿" },
"relevant": [
{ "code": 93, "label": "]" },
{ "code": 62, "label": ">" },
{ "code": 125, "label": "}" }
]
} },
{ "$": "layout_direction_selector",
"ltr": { "code": 40, "label": "(", "popup": {
"main": { "code":64830, "label": "" },
"relevant": [
{ "code": 91, "label": "[" },
{ "code": 60, "label": "<" },
{ "code": 123, "label": "{" }
]
} },
"rtl": { "code": 41, "label": "(", "popup": {
"main": { "code":64830, "label": "" },
"relevant": [
{ "code": 93, "label": "[" },
{ "code": 62, "label": "<" },
{ "code": 125, "label": "{" }
]
} }
},
{ "$": "layout_direction_selector",
"ltr": { "code": 41, "label": ")", "popup": {
"main": { "code":64831, "label": "﴿" },
"relevant": [
{ "code": 93, "label": "]" },
{ "code": 62, "label": ">" },
{ "code": 125, "label": "}" }
]
} },
"rtl": { "code": 40, "label": ")", "popup": {
"main": { "code":64831, "label": "﴿" },
"relevant": [
{ "code": 91, "label": "]" },
{ "code": 60, "label": ">" },
{ "code": 123, "label": "}" }
]
} }
},
{ "code": 1643, "label": "٫", "popup": {
"main": { "code": 1644, "label": "٬" },
"relevant": [

View File

@@ -31,20 +31,38 @@
{ "code": 43, "label": "+", "popup": {
"main": { "code": 177, "label": "±" }
} },
{ "code": 40, "label": "(", "popup": {
"main": { "code": 60, "label": "<" },
"relevant": [
{ "code": 91, "label": "[" },
{ "code": 123, "label": "{" }
]
} },
{ "code": 41, "label": ")", "popup": {
"main": { "code": 62, "label": ">" },
"relevant": [
{ "code": 93, "label": "]" },
{ "code": 125, "label": "}" }
]
} },
{ "$": "layout_direction_selector",
"ltr": { "code": 40, "label": "(", "popup": {
"main": { "code": 60, "label": "<" },
"relevant": [
{ "code": 91, "label": "[" },
{ "code": 123, "label": "{" }
]
} },
"rtl": { "code": 41, "label": "(", "popup": {
"main": { "code": 62, "label": "<" },
"relevant": [
{ "code": 93, "label": "[" },
{ "code": 125, "label": "{" }
]
} }
},
{ "$": "layout_direction_selector",
"ltr": { "code": 41, "label": ")", "popup": {
"main": { "code": 62, "label": ">" },
"relevant": [
{ "code": 93, "label": "]" },
{ "code": 125, "label": "}" }
]
} },
"rtl": { "code": 40, "label": ")", "popup": {
"main": { "code": 60, "label": ">" },
"relevant": [
{ "code": 91, "label": "]" },
{ "code": 123, "label": "}" }
]
} }
},
{ "code": 47, "label": "/" }
],
[

View File

@@ -43,20 +43,38 @@
{ "code": 43, "label": "+", "popup": {
"main": { "code": 177, "label": "±" }
} },
{ "code": 40, "label": "(", "popup": {
"main": { "code": 60, "label": "<" },
"relevant": [
{ "code": 91, "label": "[" },
{ "code": 123, "label": "{" }
]
} },
{ "code": 41, "label": ")", "popup": {
"main": { "code": 62, "label": ">" },
"relevant": [
{ "code": 93, "label": "]" },
{ "code": 125, "label": "}" }
]
} },
{ "$": "layout_direction_selector",
"ltr": { "code": 40, "label": "(", "popup": {
"main": { "code": 60, "label": "<" },
"relevant": [
{ "code": 91, "label": "[" },
{ "code": 123, "label": "{" }
]
} },
"rtl": { "code": 41, "label": "(", "popup": {
"main": { "code": 62, "label": "<" },
"relevant": [
{ "code": 93, "label": "[" },
{ "code": 125, "label": "{" }
]
} }
},
{ "$": "layout_direction_selector",
"ltr": { "code": 41, "label": ")", "popup": {
"main": { "code": 62, "label": ">" },
"relevant": [
{ "code": 93, "label": "]" },
{ "code": 125, "label": "}" }
]
} },
"rtl": { "code": 40, "label": ")", "popup": {
"main": { "code": 60, "label": ">" },
"relevant": [
{ "code": 91, "label": "]" },
{ "code": 123, "label": "}" }
]
} }
},
{ "code": 47, "label": "/" }
],
[

View File

@@ -56,12 +56,22 @@
{ "code": 8776, "label": "≈" }
]
} },
{ "code": 123, "label": "{", "popup": {
"main": { "code": 40, "label": "(" }
} },
{ "code": 125, "label": "}", "popup": {
"main": { "code": 41, "label": ")" }
} },
{ "$": "layout_direction_selector",
"ltr": { "code": 123, "label": "{", "popup": {
"main": { "code": 40, "label": "(" }
} },
"rtl": { "code": 125, "label": "{", "popup": {
"main": { "code": 41, "label": "(" }
} }
},
{ "$": "layout_direction_selector",
"ltr": { "code": 125, "label": "}", "popup": {
"main": { "code": 41, "label": ")" }
} },
"rtl": { "code": 123, "label": "}", "popup": {
"main": { "code": 40, "label": ")" }
} }
},
{ "code": 92, "label": "\\" }
],
[
@@ -70,7 +80,13 @@
{ "code": 174, "label": "®" },
{ "code": 8482, "label": "™" },
{ "code": 10003, "label": "✓" },
{ "code": 91, "label": "[" },
{ "code": 93, "label": "]" }
{ "$": "layout_direction_selector",
"ltr": { "code": 91, "label": "[" },
"rtl": { "code": 93, "label": "[" }
},
{ "$": "layout_direction_selector",
"ltr": { "code": 93, "label": "]" },
"rtl": { "code": 91, "label": "]" }
}
]
]

View File

@@ -56,12 +56,22 @@
{ "code": 8776, "label": "≈" }
]
} },
{ "code": 123, "label": "{", "popup": {
"main": { "code": 40, "label": "(" }
} },
{ "code": 125, "label": "}", "popup": {
"main": { "code": 41, "label": ")" }
} },
{ "$": "layout_direction_selector",
"ltr": { "code": 123, "label": "{", "popup": {
"main": { "code": 40, "label": "(" }
} },
"rtl": { "code": 125, "label": "{", "popup": {
"main": { "code": 41, "label": "(" }
} }
},
{ "$": "layout_direction_selector",
"ltr": { "code": 125, "label": "}", "popup": {
"main": { "code": 41, "label": ")" }
} },
"rtl": { "code": 123, "label": "}", "popup": {
"main": { "code": 40, "label": ")" }
} }
},
{ "code": 92, "label": "\\" }
],
[
@@ -70,7 +80,13 @@
{ "code": 174, "label": "®" },
{ "code": 8482, "label": "™" },
{ "code": 10003, "label": "✓" },
{ "code": 91, "label": "[" },
{ "code": 93, "label": "]" }
{ "$": "layout_direction_selector",
"ltr": { "code": 91, "label": "[" },
"rtl": { "code": 93, "label": "[" }
},
{ "$": "layout_direction_selector",
"ltr": { "code": 93, "label": "]" },
"rtl": { "code": 91, "label": "]" }
}
]
]

View File

@@ -56,12 +56,22 @@
{ "code": 8776, "label": "≈" }
]
} },
{ "code": 123, "label": "{", "popup": {
"main": { "code": 40, "label": "(" }
} },
{ "code": 125, "label": "}", "popup": {
"main": { "code": 41, "label": ")" }
} },
{ "$": "layout_direction_selector",
"ltr": { "code": 123, "label": "{", "popup": {
"main": { "code": 40, "label": "(" }
} },
"rtl": { "code": 125, "label": "{", "popup": {
"main": { "code": 41, "label": "(" }
} }
},
{ "$": "layout_direction_selector",
"ltr": { "code": 125, "label": "}", "popup": {
"main": { "code": 41, "label": ")" }
} },
"rtl": { "code": 123, "label": "}", "popup": {
"main": { "code": 40, "label": ")" }
} }
},
{ "code": 92, "label": "\\" }
],
[
@@ -70,7 +80,13 @@
{ "code": 174, "label": "®" },
{ "code": 8482, "label": "™" },
{ "code": 10003, "label": "✓" },
{ "code": 91, "label": "[" },
{ "code": 93, "label": "]" }
{ "$": "layout_direction_selector",
"ltr": { "code": 91, "label": "[" },
"rtl": { "code": 93, "label": "[" }
},
{ "$": "layout_direction_selector",
"ltr": { "code": 93, "label": "]" },
"rtl": { "code": 91, "label": "]" }
}
]
]

View File

@@ -6,24 +6,44 @@
],
[
{ "code": -201, "label": "view_characters", "type": "system_gui" },
{ "code": 60, "label": "<", "popup": {
"relevant": [
{ "code": 171, "label": "«" },
{ "code": 8804, "label": "" },
{ "code": 8249, "label": "" },
{ "code":10216, "label": "" }
]
} },
{ "$": "layout_direction_selector",
"ltr": { "code": 60, "label": "<", "popup": {
"relevant": [
{ "code": 171, "label": "«" },
{ "code": 8804, "label": "" },
{ "code": 8249, "label": "" },
{ "code":10216, "label": "⟨" }
]
} },
"rtl": { "code": 62, "label": "<", "popup": {
"relevant": [
{ "code": 187, "label": "«" },
{ "code": 8805, "label": "≤" },
{ "code": 8250, "label": "" },
{ "code":10217, "label": "⟨" }
]
} }
},
{ "code": -205, "label": "view_numeric_advanced", "type": "system_gui" },
{ "code": 32, "label": "space" },
{ "code": 62, "label": ">", "popup": {
"relevant": [
{ "code":10217, "label": "⟩" },
{ "code": 8250, "label": "" },
{ "code": 8805, "label": "" },
{ "code": 187, "label": "»" }
]
} },
{ "$": "layout_direction_selector",
"ltr": { "code": 62, "label": ">", "popup": {
"relevant": [
{ "code":10217, "label": "" },
{ "code": 8250, "label": "" },
{ "code": 8805, "label": "" },
{ "code": 187, "label": "»" }
]
} },
"rtl": { "code": 60, "label": ">", "popup": {
"relevant": [
{ "code":10216, "label": "⟩" },
{ "code": 8249, "label": "" },
{ "code": 8804, "label": "≥" },
{ "code": 171, "label": "»" }
]
} }
},
{ "code": 10, "label": "enter", "groupId": 3, "type": "enter_editing" }
]
]

View File

@@ -0,0 +1,17 @@
[
[
{ "code": -203, "label": "view_symbols2", "type": "system_gui" },
{ "code": 0, "type": "placeholder" },
{ "code": -7, "label": "delete", "type": "enter_editing" }
],
[
{ "code": -201, "label": "view_characters", "type": "system_gui" },
{ "code": 44, "label": "," },
{ "code": -205, "label": "view_numeric_advanced", "type": "system_gui" },
{ "code": 32, "label": "space" },
{ "code": 1417, "label": "։", "popup": {
"main": { "code": 46, "label": "." }
} },
{ "code": 10, "label": "enter", "groupId": 3, "type": "enter_editing" }
]
]

View File

@@ -70,6 +70,10 @@
"id": "fa",
"authors": [ "PHELAT" ]
},
{
"id": "fa2",
"authors": [ "M-Koushan" ]
},
{
"id": "fi",
"authors": [ "patrickgold" ]
@@ -90,6 +94,10 @@
"id": "hu",
"authors": [ "zoli111, gabik65" ]
},
{
"id": "hy",
"authors": [ "PJTSearch" ]
},
{
"id": "is",
"authors": [ "patrickgold" ]
@@ -150,6 +158,10 @@
"id": "ru",
"authors": [ "williamtheaker", "33kk" ]
},
{
"id": "rue",
"authors": [ "svvvst" ]
},
{
"id": "sk",
"authors": [ "stefan-misik", "majso" ]
@@ -168,7 +180,11 @@
},
{
"id": "uk",
"authors": [ "williamtheaker", "33kk" ]
"authors": [ "williamtheaker", "33kk", "honsiorovskyi" ]
},
{
"id": "uk-cyr-ext",
"authors": [ "williamtheaker", "33kk", "honsiorovskyi" ]
},
{
"id": "ur-PK",
@@ -419,6 +435,18 @@
"numericRow": "org.florisboard.layouts:persian"
}
},
{
"languageTag": "fa-FA",
"composer": "org.florisboard.composers:appender",
"currencySet": "org.florisboard.currencysets:rial",
"popupMapping": "org.florisboard.localization:fa2",
"preferred": {
"characters": "org.florisboard.layouts:persian2",
"symbols": "org.florisboard.layouts:persian",
"symbols2": "org.florisboard.layouts:persian",
"numericRow": "org.florisboard.layouts:persian"
}
},
{
"languageTag": "ar",
"composer": "org.florisboard.composers:appender",
@@ -431,6 +459,15 @@
"numericRow": "org.florisboard.layouts:eastern_arabic"
}
},
{
"languageTag": "az",
"composer": "org.florisboard.composers:appender",
"currencySet": "org.florisboard.currencysets:azerbaijani_manat",
"popupMapping": "org.florisboard.localization:tr",
"preferred": {
"characters": "org.florisboard.layouts:azerbaijani"
}
},
{
"languageTag": "hu",
"composer": "org.florisboard.composers:appender",
@@ -458,6 +495,26 @@
"characters": "org.florisboard.layouts:qwertz"
}
},
{
"languageTag": "hy",
"composer": "org.florisboard.composers:appender",
"currencySet": "org.florisboard.currencysets:armenian_dram",
"popupMapping": "org.florisboard.localization:hy",
"preferred": {
"characters": "org.florisboard.layouts:western_armenian",
"symbols": "org.florisboard.layouts:armenian"
}
},
{
"languageTag": "hy",
"composer": "org.florisboard.composers:appender",
"currencySet": "org.florisboard.currencysets:armenian_dram",
"popupMapping": "org.florisboard.localization:hy",
"preferred": {
"characters": "org.florisboard.layouts:eastern_armenian",
"symbols": "org.florisboard.layouts:armenian"
}
},
{
"languageTag": "ru",
"composer": "org.florisboard.composers:appender",
@@ -467,6 +524,15 @@
"characters": "org.florisboard.layouts:jcuken_russian"
}
},
{
"languageTag": "rue",
"composer": "org.florisboard.composers:appender",
"currencySet": "org.florisboard.currencysets:euro",
"popupMapping": "org.florisboard.localization:rue",
"preferred": {
"characters": "org.florisboard.layouts:rusyn"
}
},
{
"languageTag": "uk",
"composer": "org.florisboard.composers:appender",

View File

@@ -90,7 +90,7 @@
},
"uri": {
"~right": {
"main": { "code": -255, "label": ".ir"},
"main": { "code": -255, "label": ".sa"},
"relevant": [
{ "code": -255, "label": ".gov" },
{ "code": -255, "label": ".edu" },

View File

@@ -18,8 +18,14 @@
{ "code": 64, "label": "@" },
{ "code": 59, "label": ";" },
{ "code": 47, "label": "/" },
{ "code": 40, "label": "(" },
{ "code": 41, "label": ")" },
{ "$": "layout_direction_selector",
"ltr": { "code": 40, "label": "(" },
"rtl": { "code": 41, "label": "(" }
},
{ "$": "layout_direction_selector",
"ltr": { "code": 41, "label": ")" },
"rtl": { "code": 40, "label": ")" }
},
{ "code": 35, "label": "#" },
{ "code": 33, "label": "!" },
{ "code": 63, "label": "?" }

View File

@@ -91,8 +91,14 @@
{ "code": 64, "label": "@" },
{ "code": 59, "label": ";" },
{ "code": 47, "label": "/" },
{ "code": 40, "label": "(" },
{ "code": 41, "label": ")" },
{ "$": "layout_direction_selector",
"ltr": { "code": 40, "label": "(" },
"rtl": { "code": 41, "label": "(" }
},
{ "$": "layout_direction_selector",
"ltr": { "code": 41, "label": ")" },
"rtl": { "code": 40, "label": ")" }
},
{ "code": 35, "label": "#" },
{ "code": 33, "label": "!" },
{ "code": 63, "label": "?" }

View File

@@ -88,8 +88,14 @@
{ "code": 64, "label": "@" },
{ "code": 59, "label": ";" },
{ "code": 47, "label": "/" },
{ "code": 40, "label": "(" },
{ "code": 41, "label": ")" },
{ "$": "layout_direction_selector",
"ltr": { "code": 40, "label": "(" },
"rtl": { "code": 41, "label": "(" }
},
{ "$": "layout_direction_selector",
"ltr": { "code": 41, "label": ")" },
"rtl": { "code": 40, "label": ")" }
},
{ "code": 35, "label": "#" },
{ "code": 33, "label": "!" },
{ "code": 63, "label": "?" }

View File

@@ -106,8 +106,14 @@
{ "code": 64, "label": "@" },
{ "code": 59, "label": ";" },
{ "code": 47, "label": "/" },
{ "code": 40, "label": "(" },
{ "code": 41, "label": ")" },
{ "$": "layout_direction_selector",
"ltr": { "code": 40, "label": "(" },
"rtl": { "code": 41, "label": "(" }
},
{ "$": "layout_direction_selector",
"ltr": { "code": 41, "label": ")" },
"rtl": { "code": 40, "label": ")" }
},
{ "code": 35, "label": "#" },
{ "code": 33, "label": "!" },
{ "code": 63, "label": "?" }

View File

@@ -85,8 +85,14 @@
{ "code": 64, "label": "@" },
{ "code": 59, "label": ";" },
{ "code": 47, "label": "/" },
{ "code": 40, "label": "(" },
{ "code": 41, "label": ")" },
{ "$": "layout_direction_selector",
"ltr": { "code": 40, "label": "(" },
"rtl": { "code": 41, "label": "(" }
},
{ "$": "layout_direction_selector",
"ltr": { "code": 41, "label": ")" },
"rtl": { "code": 40, "label": ")" }
},
{ "code": 35, "label": "#" },
{ "code": 33, "label": "!" },
{ "code": 63, "label": "?" }

View File

@@ -52,8 +52,14 @@
{ "code": 64, "label": "@" },
{ "code": 59, "label": ";" },
{ "code": 47, "label": "/" },
{ "code": 40, "label": "(" },
{ "code": 41, "label": ")" },
{ "$": "layout_direction_selector",
"ltr": { "code": 40, "label": "(" },
"rtl": { "code": 41, "label": "(" }
},
{ "$": "layout_direction_selector",
"ltr": { "code": 41, "label": ")" },
"rtl": { "code": 40, "label": ")" }
},
{ "code": 35, "label": "#" },
{ "code": 33, "label": "!" },
{ "code": 63, "label": "?" }

View File

@@ -80,8 +80,14 @@
{ "code": 64, "label": "@" },
{ "code": 59, "label": ";" },
{ "code": 47, "label": "/" },
{ "code": 40, "label": "(" },
{ "code": 41, "label": ")" },
{ "$": "layout_direction_selector",
"ltr": { "code": 40, "label": "(" },
"rtl": { "code": 41, "label": "(" }
},
{ "$": "layout_direction_selector",
"ltr": { "code": 41, "label": ")" },
"rtl": { "code": 40, "label": ")" }
},
{ "code": 35, "label": "#" },
{ "code": 33, "label": "!" },
{ "code": 63, "label": "?" }

View File

@@ -63,8 +63,14 @@
{ "code": 64, "label": "@" },
{ "code": 59, "label": ";" },
{ "code": 47, "label": "/" },
{ "code": 40, "label": "(" },
{ "code": 41, "label": ")" },
{ "$": "layout_direction_selector",
"ltr": { "code": 40, "label": "(" },
"rtl": { "code": 41, "label": "(" }
},
{ "$": "layout_direction_selector",
"ltr": { "code": 41, "label": ")" },
"rtl": { "code": 40, "label": ")" }
},
{ "code": 35, "label": "#" },
{ "code": 33, "label": "!" },
{ "code": 63, "label": "?" }

View File

@@ -88,8 +88,14 @@
{ "code": 64, "label": "@" },
{ "code": 59, "label": ";" },
{ "code": 47, "label": "/" },
{ "code": 40, "label": "(" },
{ "code": 41, "label": ")" },
{ "$": "layout_direction_selector",
"ltr": { "code": 40, "label": "(" },
"rtl": { "code": 41, "label": "(" }
},
{ "$": "layout_direction_selector",
"ltr": { "code": 41, "label": ")" },
"rtl": { "code": 40, "label": ")" }
},
{ "code": 35, "label": "#" },
{ "code": 33, "label": "!" },
{ "code": 63, "label": "?" }

View File

@@ -8,12 +8,12 @@
]
},
"ا": {
"main": { "code": 1570, "label": "آ"},
"relevant": [
{ "code": 1649, "label": "ٱ" },
{ "code": 1569, "label": "ء" },
{ "code": 1571, "label": "أ" },
{ "code": 1573, "label": "إ" },
{ "code": 1570, "label": "آ" }
{ "code": 1573, "label": "إ" }
]
},
"ه": {

View File

@@ -0,0 +1,99 @@
{
"all": {
"ص": {
"relevant": [
{ "code": 1590, "label": "ض" }
]
},
"half_space": {
"relevant": [
{ "code": 1622, "label": "ٖ" },
{ "code": 1648, "label": "ٰ" },
{ "code": 1619, "label": "ٓ" },
{ "code": 1615, "label": "ُ" },
{ "code": 1616, "label": "ِ" },
{ "code": 1614, "label": "َ" },
{ "code": 1600, "label": "ـ" },
{ "code": 1621, "label": "ٕ" },
{ "code": 1618, "label": "ْ" },
{ "code": 1617, "label": "ّ" },
{ "code": 1612, "label": "ٌ" },
{ "code": 1613, "label": "ٍ" },
{ "code": 1620, "label": "ٔ" }
]
},
"ی": {
"relevant": [
{ "code": 1574, "label": "ئ" },
{ "code": 1610, "label": "ي" },
{ "code": 1746, "label": "ے" }
]
},
"ا": {
"main": { "code": 1570, "label": "آ"},
"relevant": [
{ "code": 1649, "label": "ٱ" },
{ "code": 1569, "label": "ء" },
{ "code": 1571, "label": "أ" },
{ "code": 1573, "label": "إ" }
]
},
"ه": {
"relevant": [
{ "code": 1729, "label": "ہ" },
{ "code": 1728, "label": "ۀ" },
{ "code": 1726, "label": "ھ" }
]
},
"ت": {
"relevant": [
{ "code": 1579, "label": "ث" }
]
},
"ک": {
"relevant": [
{ "code": 1706, "label": "ڪ"}
]
},
"ط": {
"relevant": [
{ "code": 1592, "label": "ظ" }
]
},
"ز": {
"relevant": [
{ "code": 1688, "label": "ژ" }
]
},
"و": {
"relevant": [
{ "code": 1572, "label": "ؤ" }
]
},
"گ": {
"relevant": [
{ "code": 1662, "label": "پ" }
]
},
"~right": {
"main": { "code": 1567, "label": "؟"},
"relevant": [
{ "code": 1563, "label": "؛" },
{ "code": 58, "label": ":"},
{ "code": 33, "label": "!" }
]
}
},
"uri": {
"~right": {
"main": { "code": -255, "label": ".ir"},
"relevant": [
{ "code": -255, "label": ".gov" },
{ "code": -255, "label": ".org" },
{ "code": -255, "label": ".edu" },
{ "code": -255, "label": ".com" },
{ "code": -255, "label": ".net" }
]
}
}
}

View File

@@ -91,8 +91,14 @@
{ "code": 64, "label": "@" },
{ "code": 59, "label": ";" },
{ "code": 47, "label": "/" },
{ "code": 40, "label": "(" },
{ "code": 41, "label": ")" },
{ "$": "layout_direction_selector",
"ltr": { "code": 40, "label": "(" },
"rtl": { "code": 41, "label": "(" }
},
{ "$": "layout_direction_selector",
"ltr": { "code": 41, "label": ")" },
"rtl": { "code": 40, "label": ")" }
},
{ "code": 35, "label": "#" },
{ "code": 33, "label": "!" },
{ "code": 63, "label": "?" }

View File

@@ -111,8 +111,14 @@
{ "code": 64, "label": "@" },
{ "code": 59, "label": ";" },
{ "code": 47, "label": "/" },
{ "code": 40, "label": "(" },
{ "code": 41, "label": ")" },
{ "$": "layout_direction_selector",
"ltr": { "code": 40, "label": "(" },
"rtl": { "code": 41, "label": "(" }
},
{ "$": "layout_direction_selector",
"ltr": { "code": 41, "label": ")" },
"rtl": { "code": 40, "label": ")" }
},
{ "code": 35, "label": "#" },
{ "code": 33, "label": "!" },
{ "code": 63, "label": "?" }

View File

@@ -94,8 +94,14 @@
{ "code": 64, "label": "@" },
{ "code": 59, "label": ";" },
{ "code": 47, "label": "/" },
{ "code": 40, "label": "(" },
{ "code": 41, "label": ")" },
{ "$": "layout_direction_selector",
"ltr": { "code": 40, "label": "(" },
"rtl": { "code": 41, "label": "(" }
},
{ "$": "layout_direction_selector",
"ltr": { "code": 41, "label": ")" },
"rtl": { "code": 40, "label": ")" }
},
{ "code": 35, "label": "#" },
{ "code": 33, "label": "!" },
{ "code": 63, "label": "?" }

View File

@@ -34,8 +34,14 @@
{ "code": 64, "label": "@" },
{ "code": 59, "label": ";" },
{ "code": 47, "label": "/" },
{ "code": 40, "label": "(" },
{ "code": 41, "label": ")" },
{ "$": "layout_direction_selector",
"ltr": { "code": 40, "label": "(" },
"rtl": { "code": 41, "label": "(" }
},
{ "$": "layout_direction_selector",
"ltr": { "code": 41, "label": ")" },
"rtl": { "code": 40, "label": ")" }
},
{ "code": 35, "label": "#" },
{ "code": 33, "label": "!" },
{ "code": 63, "label": "?" }

View File

@@ -42,8 +42,14 @@
{ "code": 64, "label": "@" },
{ "code": 59, "label": ";" },
{ "code": 47, "label": "/" },
{ "code": 40, "label": "(" },
{ "code": 41, "label": ")" },
{ "$": "layout_direction_selector",
"ltr": { "code": 40, "label": "(" },
"rtl": { "code": 41, "label": "(" }
},
{ "$": "layout_direction_selector",
"ltr": { "code": 41, "label": ")" },
"rtl": { "code": 40, "label": ")" }
},
{ "code": 35, "label": "#" },
{ "code": 33, "label": "!" },
{ "code": 63, "label": "?" }

View File

@@ -0,0 +1,41 @@
{
"all": {
"ե": {
"main": { "$": "auto_text_key", "code": 1415, "label": "և" }
},
"~right": {
"main": { "code": 44, "label": "," },
"relevant": [
{ "code": 38, "label": "&" },
{ "code": 37, "label": "%" },
{ "code": 43, "label": "+" },
{ "code": 171, "label": "«" },
{ "code": 187, "label": "»" },
{ "code": 45, "label": "-" },
{ "code": 1373, "label": "՝" },
{ "code": 1371, "label": "՛" },
{ "code": 64, "label": "@" },
{ "code": 46, "label": "." },
{ "code": 47, "label": "/" },
{ "code": 40, "label": "(" },
{ "code": 41, "label": ")" },
{ "code": 35, "label": "#" },
{ "code": 1372, "label": "՜" },
{ "code": 1374, "label": "՞" },
{ "code": 1415, "label": "և" }
]
}
},
"uri": {
"~right": {
"main": { "code": -255, "label": ".com" },
"relevant": [
{ "code": -255, "label": ".gov" },
{ "code": -255, "label": ".edu" },
{ "code": -255, "label": ".gr" },
{ "code": -255, "label": ".org" },
{ "code": -255, "label": ".net" }
]
}
}
}

View File

@@ -83,8 +83,14 @@
{ "code": 64, "label": "@" },
{ "code": 59, "label": ";" },
{ "code": 47, "label": "/" },
{ "code": 40, "label": "(" },
{ "code": 41, "label": ")" },
{ "$": "layout_direction_selector",
"ltr": { "code": 40, "label": "(" },
"rtl": { "code": 41, "label": "(" }
},
{ "$": "layout_direction_selector",
"ltr": { "code": 41, "label": ")" },
"rtl": { "code": 40, "label": ")" }
},
{ "code": 35, "label": "#" },
{ "code": 33, "label": "!" },
{ "code": 63, "label": "?" }

View File

@@ -76,8 +76,14 @@
{ "code": 64, "label": "@" },
{ "code": 59, "label": ";" },
{ "code": 47, "label": "/" },
{ "code": 40, "label": "(" },
{ "code": 41, "label": ")" },
{ "$": "layout_direction_selector",
"ltr": { "code": 40, "label": "(" },
"rtl": { "code": 41, "label": "(" }
},
{ "$": "layout_direction_selector",
"ltr": { "code": 41, "label": ")" },
"rtl": { "code": 40, "label": ")" }
},
{ "code": 35, "label": "#" },
{ "code": 33, "label": "!" },
{ "code": 63, "label": "?" }

View File

@@ -13,8 +13,14 @@
{ "code": 64, "label": "@" },
{ "code": 59, "label": ";" },
{ "code": 47, "label": "/" },
{ "code": 40, "label": "(" },
{ "code": 41, "label": ")" },
{ "$": "layout_direction_selector",
"ltr": { "code": 40, "label": "(" },
"rtl": { "code": 41, "label": "(" }
},
{ "$": "layout_direction_selector",
"ltr": { "code": 41, "label": ")" },
"rtl": { "code": 40, "label": ")" }
},
{ "code": 35, "label": "#" },
{ "code": 33, "label": "!" },
{ "code": 63, "label": "?" }

View File

@@ -48,8 +48,14 @@
{ "code": 64, "label": "@" },
{ "code": 59, "label": ";" },
{ "code": 47, "label": "/" },
{ "code": 40, "label": "(" },
{ "code": 41, "label": ")" },
{ "$": "layout_direction_selector",
"ltr": { "code": 40, "label": "(" },
"rtl": { "code": 41, "label": "(" }
},
{ "$": "layout_direction_selector",
"ltr": { "code": 41, "label": ")" },
"rtl": { "code": 40, "label": ")" }
},
{ "code": 35, "label": "#" },
{ "code": 33, "label": "!" },
{ "code": 63, "label": "?" }

View File

@@ -63,7 +63,7 @@
]
},
"s": {
"main": { "$": "auto_text_key", "code": 219, "label": "ș" },
"main": { "$": "auto_text_key", "code": 351, "label": "ş" },
"relevant": [
{ "$": "auto_text_key", "code": 347, "label": "ś" },
{ "$": "auto_text_key", "code": 349, "label": "ŝ" },
@@ -102,8 +102,14 @@
{ "code": 64, "label": "@" },
{ "code": 59, "label": ";" },
{ "code": 47, "label": "/" },
{ "code": 40, "label": "(" },
{ "code": 41, "label": ")" },
{ "$": "layout_direction_selector",
"ltr": { "code": 40, "label": "(" },
"rtl": { "code": 41, "label": "(" }
},
{ "$": "layout_direction_selector",
"ltr": { "code": 41, "label": ")" },
"rtl": { "code": 40, "label": ")" }
},
{ "code": 35, "label": "#" },
{ "code": 33, "label": "!" },
{ "code": 63, "label": "?" }

View File

@@ -140,8 +140,14 @@
{ "code": 64, "label": "@" },
{ "code": 59, "label": ";" },
{ "code": 47, "label": "/" },
{ "code": 40, "label": "(" },
{ "code": 41, "label": ")" },
{ "$": "layout_direction_selector",
"ltr": { "code": 40, "label": "(" },
"rtl": { "code": 41, "label": "(" }
},
{ "$": "layout_direction_selector",
"ltr": { "code": 41, "label": ")" },
"rtl": { "code": 40, "label": ")" }
},
{ "code": 35, "label": "#" },
{ "code": 33, "label": "!" },
{ "code": 63, "label": "?" }

View File

@@ -80,8 +80,14 @@
{ "code": 64, "label": "@" },
{ "code": 59, "label": ";" },
{ "code": 47, "label": "/" },
{ "code": 40, "label": "(" },
{ "code": 41, "label": ")" },
{ "$": "layout_direction_selector",
"ltr": { "code": 40, "label": "(" },
"rtl": { "code": 41, "label": "(" }
},
{ "$": "layout_direction_selector",
"ltr": { "code": 41, "label": ")" },
"rtl": { "code": 40, "label": ")" }
},
{ "code": 35, "label": "#" },
{ "code": 33, "label": "!" },
{ "code": 63, "label": "?" }

View File

@@ -72,8 +72,14 @@
{ "code": 64, "label": "@" },
{ "code": 59, "label": ";" },
{ "code": 47, "label": "/" },
{ "code": 40, "label": "(" },
{ "code": 41, "label": ")" },
{ "$": "layout_direction_selector",
"ltr": { "code": 40, "label": "(" },
"rtl": { "code": 41, "label": "(" }
},
{ "$": "layout_direction_selector",
"ltr": { "code": 41, "label": ")" },
"rtl": { "code": 40, "label": ")" }
},
{ "code": 35, "label": "#" },
{ "code": 33, "label": "!" },
{ "code": 63, "label": "?" }

View File

@@ -82,8 +82,14 @@
{ "code": 64, "label": "@" },
{ "code": 59, "label": ";" },
{ "code": 47, "label": "/" },
{ "code": 40, "label": "(" },
{ "code": 41, "label": ")" },
{ "$": "layout_direction_selector",
"ltr": { "code": 40, "label": "(" },
"rtl": { "code": 41, "label": "(" }
},
{ "$": "layout_direction_selector",
"ltr": { "code": 41, "label": ")" },
"rtl": { "code": 40, "label": ")" }
},
{ "code": 35, "label": "#" },
{ "code": 33, "label": "!" },
{ "code": 63, "label": "?" }

View File

@@ -60,8 +60,14 @@
{ "code": 64, "label": "@" },
{ "code": 59, "label": ";" },
{ "code": 47, "label": "/" },
{ "code": 40, "label": "(" },
{ "code": 41, "label": ")" },
{ "$": "layout_direction_selector",
"ltr": { "code": 40, "label": "(" },
"rtl": { "code": 41, "label": "(" }
},
{ "$": "layout_direction_selector",
"ltr": { "code": 41, "label": ")" },
"rtl": { "code": 40, "label": ")" }
},
{ "code": 35, "label": "#" },
{ "code": 33, "label": "!" },
{ "code": 63, "label": "?" }

View File

@@ -81,8 +81,14 @@
{ "code": 64, "label": "@" },
{ "code": 59, "label": ";" },
{ "code": 47, "label": "/" },
{ "code": 40, "label": "(" },
{ "code": 41, "label": ")" },
{ "$": "layout_direction_selector",
"ltr": { "code": 40, "label": "(" },
"rtl": { "code": 41, "label": "(" }
},
{ "$": "layout_direction_selector",
"ltr": { "code": 41, "label": ")" },
"rtl": { "code": 40, "label": ")" }
},
{ "code": 35, "label": "#" },
{ "code": 33, "label": "!" },
{ "code": 63, "label": "?" }

View File

@@ -81,8 +81,14 @@
{ "code": 64, "label": "@" },
{ "code": 59, "label": ";" },
{ "code": 47, "label": "/" },
{ "code": 40, "label": "(" },
{ "code": 41, "label": ")" },
{ "$": "layout_direction_selector",
"ltr": { "code": 40, "label": "(" },
"rtl": { "code": 41, "label": "(" }
},
{ "$": "layout_direction_selector",
"ltr": { "code": 41, "label": ")" },
"rtl": { "code": 40, "label": ")" }
},
{ "code": 35, "label": "#" },
{ "code": 33, "label": "!" },
{ "code": 63, "label": "?" }

View File

@@ -52,8 +52,14 @@
{ "code": 64, "label": "@" },
{ "code": 59, "label": ";" },
{ "code": 47, "label": "/" },
{ "code": 40, "label": "(" },
{ "code": 41, "label": ")" },
{ "$": "layout_direction_selector",
"ltr": { "code": 40, "label": "(" },
"rtl": { "code": 41, "label": "(" }
},
{ "$": "layout_direction_selector",
"ltr": { "code": 41, "label": ")" },
"rtl": { "code": 40, "label": ")" }
},
{ "code": 35, "label": "#" },
{ "code": 33, "label": "!" },
{ "code": 63, "label": "?" }

View File

@@ -23,8 +23,14 @@
{ "code": 64, "label": "@" },
{ "code": 59, "label": ";" },
{ "code": 47, "label": "/" },
{ "code": 40, "label": "(" },
{ "code": 41, "label": ")" },
{ "$": "layout_direction_selector",
"ltr": { "code": 40, "label": "(" },
"rtl": { "code": 41, "label": "(" }
},
{ "$": "layout_direction_selector",
"ltr": { "code": 41, "label": ")" },
"rtl": { "code": 40, "label": ")" }
},
{ "code": 35, "label": "#" },
{ "code": 33, "label": "!" },
{ "code": 63, "label": "?" }

View File

@@ -0,0 +1,69 @@
{
"all": {
"е": {
"main": { "$": "auto_text_key", "code": 234, "label": "ê" },
"relevant": [{ "$": "auto_text_key", "code": 1105, "label": "ё" }]
},
"у": {
"main": { "$": "auto_text_key", "code": 1263, "label": "ӯ" },
"relevant": [
{ "$": "auto_text_key", "code": 1118, "label": "ў" },
{ "$": "auto_text_key", "code": 1265, "label": "ӱ" },
{ "$": "auto_text_key", "code": 375, "label": "ŷ" }
]
},
"г": {
"main": { "$": "auto_text_key", "code": 1169, "label": "ґ" }
},
"і": {
"main": { "$": "auto_text_key", "code": 1123, "label": "î" },
"relevant": [
{ "$": "auto_text_key", "code": 1123, "label": "ѣ" },
{ "$": "auto_text_key", "code": 1111, "label": "ї" }
]
},
"о": {
"main": { "$": "auto_text_key", "code": 333, "label": "ō" },
"relevant": [{ "$": "auto_text_key", "code": 244, "label": "ô" }]
},
"ь": {
"main": { "$": "auto_text_key", "code": 1098, "label": "ъ" }
},
"~right": {
"main": { "code": 44, "label": "," },
"relevant": [
{ "code": 38, "label": "&" },
{ "code": 37, "label": "%" },
{ "code": 43, "label": "+" },
{ "code": 34, "label": "\"" },
{ "code": 45, "label": "-" },
{ "code": 58, "label": ":" },
{ "code": 39, "label": "'" },
{ "code": 64, "label": "@" },
{ "code": 59, "label": ";" },
{ "code": 47, "label": "/" },
{ "$": "layout_direction_selector",
"ltr": { "code": 40, "label": "(" },
"rtl": { "code": 41, "label": "(" }
},
{ "$": "layout_direction_selector",
"ltr": { "code": 41, "label": ")" },
"rtl": { "code": 40, "label": ")" }
},
{ "code": 35, "label": "#" },
{ "code": 33, "label": "!" },
{ "code": 63, "label": "?" }
]
}
},
"uri": {
"~right": {
"main": { "code": -255, "label": ".com" },
"relevant": [
{ "code": -255, "label": ".edu" },
{ "code": -255, "label": ".org" },
{ "code": -255, "label": ".net" }
]
}
}
}

View File

@@ -89,8 +89,14 @@
{ "code": 64, "label": "@" },
{ "code": 59, "label": ";" },
{ "code": 47, "label": "/" },
{ "code": 40, "label": "(" },
{ "code": 41, "label": ")" },
{ "$": "layout_direction_selector",
"ltr": { "code": 40, "label": "(" },
"rtl": { "code": 41, "label": "(" }
},
{ "$": "layout_direction_selector",
"ltr": { "code": 41, "label": ")" },
"rtl": { "code": 40, "label": ")" }
},
{ "code": 35, "label": "#" },
{ "code": 33, "label": "!" },
{ "code": 63, "label": "?" }

View File

@@ -32,8 +32,14 @@
{ "code": 64, "label": "@" },
{ "code": 59, "label": ";" },
{ "code": 47, "label": "/" },
{ "code": 40, "label": "(" },
{ "code": 41, "label": ")" },
{ "$": "layout_direction_selector",
"ltr": { "code": 40, "label": "(" },
"rtl": { "code": 41, "label": "(" }
},
{ "$": "layout_direction_selector",
"ltr": { "code": 41, "label": ")" },
"rtl": { "code": 40, "label": ")" }
},
{ "code": 35, "label": "#" },
{ "code": 33, "label": "!" },
{ "code": 63, "label": "?" }

View File

@@ -133,8 +133,14 @@
{ "code": 64, "label": "@" },
{ "code": 59, "label": ";" },
{ "code": 47, "label": "/" },
{ "code": 40, "label": "(" },
{ "code": 41, "label": ")" },
{ "$": "layout_direction_selector",
"ltr": { "code": 40, "label": "(" },
"rtl": { "code": 41, "label": "(" }
},
{ "$": "layout_direction_selector",
"ltr": { "code": 41, "label": ")" },
"rtl": { "code": 40, "label": ")" }
},
{ "code": 35, "label": "#" },
{ "code": 33, "label": "!" },
{ "code": 63, "label": "?" }

View File

@@ -40,8 +40,14 @@
{ "code": 64, "label": "@" },
{ "code": 59, "label": ";" },
{ "code": 47, "label": "/" },
{ "code": 40, "label": "(" },
{ "code": 41, "label": ")" },
{ "$": "layout_direction_selector",
"ltr": { "code": 40, "label": "(" },
"rtl": { "code": 41, "label": "(" }
},
{ "$": "layout_direction_selector",
"ltr": { "code": 41, "label": ")" },
"rtl": { "code": 40, "label": ")" }
},
{ "code": 35, "label": "#" },
{ "code": 33, "label": "!" },
{ "code": 63, "label": "?" }

View File

@@ -0,0 +1,74 @@
{
"all": {
"е": {
"relevant": [
{ "$": "auto_text_key", "code": 1105, "label": "ё" }
]
},
"у": {
"relevant": [
{ "$": "auto_text_key", "code": 1118, "label": "ў" }
]
},
"г": {
"relevant": [
{ "$": "auto_text_key", "code": 1169, "label": "ґ" }
]
},
"і": {
"relevant": [
{ "$": "auto_text_key", "code": 1111, "label": "ї" },
{ "$": "auto_text_key", "code": 1099, "label": "ы" }
]
},
"є": {
"relevant": [
{ "$": "auto_text_key", "code": 8212, "label": "—" },
{ "$": "auto_text_key", "code": 1101, "label": "э" }
]
},
"ь": {
"relevant": [
{ "$": "auto_text_key", "code": 700, "label": "ʼ" },
{ "$": "auto_text_key", "code": 39, "label": "'" },
{ "$": "auto_text_key", "code": 1098, "label": "ъ" }
]
},
"~right": {
"main": { "code": 44, "label": "," },
"relevant": [
{ "code": 38, "label": "&" },
{ "code": 37, "label": "%" },
{ "code": 43, "label": "+" },
{ "code": 34, "label": "\"" },
{ "code": 45, "label": "-" },
{ "code": 58, "label": ":" },
{ "code": 39, "label": "'" },
{ "code": 64, "label": "@" },
{ "code": 59, "label": ";" },
{ "code": 47, "label": "/" },
{ "$": "layout_direction_selector",
"ltr": { "code": 40, "label": "(" },
"rtl": { "code": 41, "label": "(" }
},
{ "$": "layout_direction_selector",
"ltr": { "code": 41, "label": ")" },
"rtl": { "code": 40, "label": ")" }
},
{ "code": 35, "label": "#" },
{ "code": 33, "label": "!" },
{ "code": 63, "label": "?" }
]
}
},
"uri": {
"~right": {
"main": { "code": -255, "label": ".com" },
"relevant": [
{ "code": -255, "label": ".ua" },
{ "code": -255, "label": ".org" },
{ "code": -255, "label": ".net" }
]
}
}
}

View File

@@ -1,10 +1,26 @@
{
"all": {
"г": {
"relevant": [
{ "$": "auto_text_key", "code": 1169, "label": "ґ" }
]
},
"і": {
"relevant": [
{ "$": "auto_text_key", "code": 1111, "label": "ї" }
]
},
"є": {
"relevant": [
{ "$": "auto_text_key", "code": 8212, "label": "—" }
]
},
"ь": {
"relevant": [
{ "$": "auto_text_key", "code": 700, "label": "ʼ" },
{ "$": "auto_text_key", "code": 39, "label": "'" }
]
},
"~right": {
"main": { "code": 44, "label": "," },
"relevant": [
@@ -18,8 +34,14 @@
{ "code": 64, "label": "@" },
{ "code": 59, "label": ";" },
{ "code": 47, "label": "/" },
{ "code": 40, "label": "(" },
{ "code": 41, "label": ")" },
{ "$": "layout_direction_selector",
"ltr": { "code": 40, "label": "(" },
"rtl": { "code": 41, "label": "(" }
},
{ "$": "layout_direction_selector",
"ltr": { "code": 41, "label": ")" },
"rtl": { "code": 40, "label": ")" }
},
{ "code": 35, "label": "#" },
{ "code": 33, "label": "!" },
{ "code": 63, "label": "?" }
@@ -31,7 +53,6 @@
"main": { "code": -255, "label": ".com" },
"relevant": [
{ "code": -255, "label": ".ua" },
{ "code": -255, "label": ".edu" },
{ "code": -255, "label": ".org" },
{ "code": -255, "label": ".net" }
]

View File

@@ -183,7 +183,7 @@
},
"uri": {
"~right": {
"main": { "code": -255, "label": ".ir"},
"main": { "code": -255, "label": ".pk"},
"relevant": [
{ "code": -255, "label": ".gov" },
{ "code": -255, "label": ".edu" },

View File

@@ -40,8 +40,14 @@
{ "code": 64, "label": "@" },
{ "code": 59, "label": ";" },
{ "code": 47, "label": "/" },
{ "code": 40, "label": "(" },
{ "code": 41, "label": ")" },
{ "$": "layout_direction_selector",
"ltr": { "code": 40, "label": "(" },
"rtl": { "code": 41, "label": "(" }
},
{ "$": "layout_direction_selector",
"ltr": { "code": 41, "label": ")" },
"rtl": { "code": 40, "label": ")" }
},
{ "code": 35, "label": "#" },
{ "code": 33, "label": "!" },
{ "code": 63, "label": "?" }

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -1,74 +0,0 @@
{
"$type": "dev.patrickgold.florisboard.ime.theme.Theme",
"name": "floris_black",
"label": "Floris Black",
"authors": [ "serebit" ],
"isNightTheme": true,
"attributes": {
"window": {
"colorPrimary": "#388E3C",
"colorPrimaryDark": "#306D32",
"colorAccent": "#FF9800",
"navigationBarColor": "@keyboard/background",
"navigationBarLight": "false",
"semiTransparentColor": "#20FFFFFF",
"textColor": "#EEEEEE"
},
"keyboard": {
"background": "#000000"
},
"key": {
"background": "#212121",
"backgroundPressed": "#3D3D3D",
"foreground": "@window/textColor",
"foregroundPressed": "@window/textColor",
"showBorder": "true"
},
"key:enter": {
"background": "@window/colorPrimary",
"backgroundPressed": "@window/colorPrimaryDark",
"foreground": "@window/textColor",
"foregroundPressed": "@window/textColor"
},
"key:shift:capslock": {
"foreground": "@window/colorAccent",
"foregroundPressed": "@window/colorAccent"
},
"media": {
"foreground": "@window/textColor",
"foregroundAlt": "#BDBDBD"
},
"oneHanded": {
"background": "#000000",
"foreground": "@window/textColor"
},
"popup": {
"background": "#424242",
"backgroundActive": "#707070",
"foreground": "@window/textColor"
},
"privateMode": {
"background": "#7800BF",
"foreground": "@window/textColor"
},
"smartbar": {
"background": "transparent",
"foreground": "@window/textColor",
"foregroundAlt": "#73FFFFFF"
},
"smartbarButton": {
"background": "@key/background",
"foreground": "@key/foreground"
},
"extractEditLayout": {
"background": "#282828",
"foreground": "@window/textColor",
"foregroundAlt": "#73FFFFFF"
},
"extractActionButton": {
"background": "@smartbarButton/background",
"foreground": "@smartbarButton/foreground"
},
"glideTrail": {"foreground": "#20388E3C"}
}
}

View File

@@ -1,77 +0,0 @@
{
"$type": "dev.patrickgold.florisboard.ime.theme.Theme",
"name": "floris_black_borderless",
"label": "Floris Black Borderless",
"authors": [ "serebit" ],
"isNightTheme": true,
"attributes": {
"window": {
"colorPrimary": "#388E3C",
"colorPrimaryDark": "#306D32",
"colorAccent": "#FF9800",
"navigationBarColor": "@keyboard/background",
"navigationBarLight": "false",
"semiTransparentColor": "#20FFFFFF",
"textColor": "#EEEEEE"
},
"keyboard": {
"background": "#000000"
},
"key": {
"background": "transparent",
"backgroundPressed": "#7F616161",
"foreground": "@window/textColor",
"foregroundPressed": "@window/textColor",
"showBorder": "false"
},
"key:enter": {
"background": "@window/colorPrimary",
"backgroundPressed": "@window/colorPrimaryDark",
"foreground": "@window/textColor",
"foregroundPressed": "@window/textColor"
},
"key:shift:capslock": {
"foreground": "@window/colorAccent",
"foregroundPressed": "@window/colorAccent"
},
"key:space": {
"background": "#46616161"
},
"media": {
"foreground": "@window/textColor",
"foregroundAlt": "#BDBDBD"
},
"oneHanded": {
"background": "#000000",
"foreground": "@window/textColor"
},
"popup": {
"background": "#363636",
"backgroundActive": "#5F5F5F",
"foreground": "@window/textColor"
},
"privateMode": {
"background": "#7800BF",
"foreground": "@window/textColor"
},
"smartbar": {
"background": "transparent",
"foreground": "@window/textColor",
"foregroundAlt": "#73FFFFFF"
},
"smartbarButton": {
"background": "#212121",
"foreground": "@window/textColor"
},
"extractEditLayout": {
"background": "#282828",
"foreground": "@window/textColor",
"foregroundAlt": "#73FFFFFF"
},
"extractActionButton": {
"background": "@smartbarButton/background",
"foreground": "@smartbarButton/foreground"
},
"glideTrail": {"foreground": "#20388E3C"}
}
}

View File

@@ -1,74 +0,0 @@
{
"$type": "dev.patrickgold.florisboard.ime.theme.Theme",
"name": "floris_day",
"label": "Floris Day",
"authors": [ "patrickgold" ],
"isNightTheme": false,
"attributes": {
"window": {
"colorPrimary": "#4CAF50",
"colorPrimaryDark": "#388E3C",
"colorAccent": "#FF9800",
"navigationBarColor": "@keyboard/background",
"navigationBarLight": "true",
"semiTransparentColor": "#20000000",
"textColor": "#000000"
},
"keyboard": {
"background": "#E0E0E0"
},
"key": {
"background": "#FFFFFF",
"backgroundPressed": "#F5F5F5",
"foreground": "@window/textColor",
"foregroundPressed": "@window/textColor",
"showBorder": "true"
},
"key:enter": {
"background": "@window/colorPrimary",
"backgroundPressed": "@window/colorPrimaryDark",
"foreground": "#FFFFFF",
"foregroundPressed": "#FFFFFF"
},
"key:shift:capslock": {
"foreground": "@window/colorAccent",
"foregroundPressed": "@window/colorAccent"
},
"media": {
"foreground": "@window/textColor",
"foregroundAlt": "#757575"
},
"oneHanded": {
"background": "#E8F5E9",
"foreground": "#424242"
},
"popup": {
"background": "#EEEEEE",
"backgroundActive": "#BDBDBD",
"foreground": "@window/textColor"
},
"privateMode": {
"background": "#A000FF",
"foreground": "#FFFFFF"
},
"smartbar": {
"background": "transparent",
"foreground": "@window/textColor",
"foregroundAlt": "#8A8A8A"
},
"smartbarButton": {
"background": "@key/background",
"foreground": "@key/foreground"
},
"extractEditLayout": {
"background": "#E8E8E8",
"foreground": "@window/textColor",
"foregroundAlt": "#8A8A8A"
},
"extractActionButton": {
"background": "@smartbarButton/background",
"foreground": "@smartbarButton/foreground"
},
"glideTrail": {"foreground": "#204CAF50"}
}
}

View File

@@ -1,78 +0,0 @@
{
"$type": "dev.patrickgold.florisboard.ime.theme.Theme",
"name": "floris_day_borderless",
"label": "Floris Day Borderless",
"authors": [ "patrickgold" ],
"isNightTheme": false,
"attributes": {
"window": {
"colorPrimary": "#4CAF50",
"colorPrimaryDark": "#388E3C",
"colorAccent": "#FF9800",
"navigationBarColor": "@keyboard/background",
"navigationBarLight": "true",
"semiTransparentColor": "#20000000",
"textColor": "#000000"
},
"keyboard": {
"background": "#E0E0E0"
},
"key": {
"background": "transparent",
"backgroundPressed": "#7FF5F5F5",
"foreground": "@window/textColor",
"foregroundPressed": "@window/textColor",
"showBorder": "false"
},
"key:enter": {
"background": "@window/colorPrimary",
"backgroundPressed": "@window/colorPrimaryDark",
"foreground": "#FFFFFF",
"foregroundPressed": "#FFFFFF"
},
"key:shift:capslock": {
"foreground": "@window/colorAccent",
"foregroundPressed": "@window/colorAccent"
},
"key:space": {
"background": "#7FF5F5F5",
"backgroundPressed": "#FFF5F5F5"
},
"media": {
"foreground": "@window/textColor",
"foregroundAlt": "#757575"
},
"oneHanded": {
"background": "#E8F5E9",
"foreground": "#424242"
},
"popup": {
"background": "#EEEEEE",
"backgroundActive": "#BDBDBD",
"foreground": "@window/textColor"
},
"privateMode": {
"background": "#A000FF",
"foreground": "#FFFFFF"
},
"smartbar": {
"background": "transparent",
"foreground": "@window/textColor",
"foregroundAlt": "#8A8A8A"
},
"smartbarButton": {
"background": "#FFFFFF",
"foreground": "@window/textColor"
},
"extractEditLayout": {
"background": "#E8E8E8",
"foreground": "@window/textColor",
"foregroundAlt": "#8A8A8A"
},
"extractActionButton": {
"background": "@smartbarButton/background",
"foreground": "@smartbarButton/foreground"
},
"glideTrail": {"foreground": "#204CAF50"}
}
}

View File

@@ -1,74 +0,0 @@
{
"$type": "dev.patrickgold.florisboard.ime.theme.Theme",
"name": "floris_night",
"label": "Floris Night",
"authors": [ "patrickgold" ],
"isNightTheme": true,
"attributes": {
"window": {
"colorPrimary": "#4CAF50",
"colorPrimaryDark": "#388E3C",
"colorAccent": "#FF9800",
"navigationBarColor": "@keyboard/background",
"navigationBarLight": "false",
"semiTransparentColor": "#20FFFFFF",
"textColor": "#FFFFFF"
},
"keyboard": {
"background": "#212121"
},
"key": {
"background": "#424242",
"backgroundPressed": "#616161",
"foreground": "@window/textColor",
"foregroundPressed": "@window/textColor",
"showBorder": "true"
},
"key:enter": {
"background": "@window/colorPrimary",
"backgroundPressed": "@window/colorPrimaryDark",
"foreground": "#FFFFFF",
"foregroundPressed": "#FFFFFF"
},
"key:shift:capslock": {
"foreground": "@window/colorAccent",
"foregroundPressed": "@window/colorAccent"
},
"media": {
"foreground": "@window/textColor",
"foregroundAlt": "#BDBDBD"
},
"oneHanded": {
"background": "#1B5E20",
"foreground": "#EEEEEE"
},
"popup": {
"background": "#757575",
"backgroundActive": "#BDBDBD",
"foreground": "@window/textColor"
},
"privateMode": {
"background": "#A000FF",
"foreground": "#FFFFFF"
},
"smartbar": {
"background": "transparent",
"foreground": "@window/textColor",
"foregroundAlt": "#73FFFFFF"
},
"smartbarButton": {
"background": "@key/background",
"foreground": "@key/foreground"
},
"extractEditLayout": {
"background": "#282828",
"foreground": "@window/textColor",
"foregroundAlt": "#73FFFFFF"
},
"extractActionButton": {
"background": "@smartbarButton/background",
"foreground": "@smartbarButton/foreground"
},
"glideTrail": {"foreground": "#204CAF50"}
}
}

View File

@@ -1,78 +0,0 @@
{
"$type": "dev.patrickgold.florisboard.ime.theme.Theme",
"name": "floris_night_borderless",
"label": "Floris Night Borderless",
"authors": [ "patrickgold" ],
"isNightTheme": true,
"attributes": {
"window": {
"colorPrimary": "#4CAF50",
"colorPrimaryDark": "#388E3C",
"colorAccent": "#FF9800",
"navigationBarColor": "@keyboard/background",
"navigationBarLight": "false",
"semiTransparentColor": "#20FFFFFF",
"textColor": "#FFFFFF"
},
"keyboard": {
"background": "#212121"
},
"key": {
"background": "transparent",
"backgroundPressed": "#7F616161",
"foreground": "@window/textColor",
"foregroundPressed": "@window/textColor",
"showBorder": "false"
},
"key:enter": {
"background": "@window/colorPrimary",
"backgroundPressed": "@window/colorPrimaryDark",
"foreground": "#FFFFFF",
"foregroundPressed": "#FFFFFF"
},
"key:shift:capslock": {
"foreground": "@window/colorAccent",
"foregroundPressed": "@window/colorAccent"
},
"key:space": {
"background": "#2F616161",
"backgroundPressed": "#7F616161"
},
"media": {
"foreground": "@window/textColor",
"foregroundAlt": "#BDBDBD"
},
"oneHanded": {
"background": "#1B5E20",
"foreground": "#EEEEEE"
},
"popup": {
"background": "#757575",
"backgroundActive": "#BDBDBD",
"foreground": "@window/textColor"
},
"privateMode": {
"background": "#A000FF",
"foreground": "#FFFFFF"
},
"smartbar": {
"background": "transparent",
"foreground": "@window/textColor",
"foregroundAlt": "#73FFFFFF"
},
"smartbarButton": {
"background": "#424242",
"foreground": "@window/textColor"
},
"extractEditLayout": {
"background": "#282828",
"foreground": "@window/textColor",
"foregroundAlt": "#73FFFFFF"
},
"extractActionButton": {
"background": "@smartbarButton/background",
"foreground": "@smartbarButton/foreground"
},
"glideTrail": {"foreground": "#204CAF50"}
}
}

View File

@@ -17,6 +17,14 @@
"isBorderless": false,
"isMaterialYouAware": false
},
{
"id": "floris_day_borderless",
"label": "Floris Day (Borderless)",
"authors": [ "patrickgold" ],
"isNight": false,
"isBorderless": true,
"isMaterialYouAware": false
},
{
"id": "floris_night",
"label": "Floris Night",
@@ -24,6 +32,30 @@
"isNight": true,
"isBorderless": false,
"isMaterialYouAware": false
},
{
"id": "floris_night_borderless",
"label": "Floris Night (Borderless)",
"authors": [ "patrickgold" ],
"isNight": true,
"isBorderless": true,
"isMaterialYouAware": false
},
{
"id": "floris_pure_night",
"label": "Floris Pure Night",
"authors": [ "serebit" ],
"isNight": true,
"isBorderless": false,
"isMaterialYouAware": false
},
{
"id": "floris_pure_night_borderless",
"label": "Floris Pure Night (Borderless)",
"authors": [ "serebit" ],
"isNight": true,
"isBorderless": true,
"isMaterialYouAware": false
}
]
}

View File

@@ -8,10 +8,12 @@
"--surface": "#ffffff",
"--surface-variant": "#f5f5f5",
"--on-primary": "#000000",
"--on-secondary": "#000000",
"--on-background": "#000000",
"--on-surface": "#000000"
"--on-background": "#121212",
"--on-surface": "#000000",
"--on-surface-variant": "#5f5f5f",
"--shape": "rounded-corner(8dp, 8dp, 8dp, 8dp)",
"--shape-variant": "rounded-corner(12dp, 12dp, 12dp, 12dp)"
},
"keyboard": {
@@ -22,7 +24,8 @@
"background": "var(--surface)",
"foreground": "var(--on-surface)",
"font-size": "22sp",
"shape": "rounded-corner(20%, 20%, 20%, 20%)"
"shape": "var(--shape)",
"shadow-elevation": "2dp"
},
"key:pressed": {
"background": "var(--surface-variant)",
@@ -30,36 +33,91 @@
},
"key[code={c:enter}]": {
"background": "var(--primary)",
"foreground": "#ffffff"
"foreground": "var(--on-surface)"
},
"key[code={c:enter}]:pressed": {
"background": "var(--primary-variant)",
"foreground": "#ffffff"
"foreground": "var(--on-surface)"
},
"key[code={c:shift}][mode={m:capslock}]": {
"foreground": "var(--secondary)"
},
"key[code={c:space}]": {
"background": "var(--surface)",
"foreground": "#909090",
"foreground": "var(--on-surface-variant)",
"font-size": "12sp"
},
"key-hint": {
"background": "transparent",
"foreground": "#b8b8b8",
"foreground": "var(--on-surface-variant)",
"font-size": "12sp"
},
"key-popup": {
"background": "#eeeeee",
"foreground": "var(--on-surface)",
"font-size": "22sp",
"shape": "rounded-corner(20%, 20%, 20%, 20%)"
"shape": "var(--shape)",
"shadow-elevation": "2dp"
},
"key-popup:focus": {
"background": "#bdbdbd",
"foreground": "var(--on-surface)"
},
"smartbar-primary-actions-toggle": {
"background": "var(--surface)",
"foreground": "var(--on-surface)",
"shape": "circle()",
"shadow-elevation": "2dp"
},
"smartbar-secondary-actions-toggle": {
"background": "transparent",
"foreground": "var(--on-surface-variant)",
"shape": "circle()"
},
"smartbar-quick-action": {
"background": "transparent",
"foreground": "var(--on-background)",
"shape": "circle()"
},
"smartbar-key": {
"background": "transparent",
"foreground": "var(--on-background)",
"font-size": "18sp",
"shape": "var(--shape)"
},
"smartbar-key:pressed": {
"background": "var(--surface)",
"foreground": "var(--on-surface)"
},
"smartbar-key:disabled": {
"background": "transparent",
"foreground": "#12121248"
},
"smartbar-candidate-word": {
"background": "transparent",
"foreground": "var(--on-background)",
"font-size": "14sp",
"shape": "rectangle()"
},
"smartbar-candidate-word:pressed": {
"background": "var(--surface)",
"foreground": "var(--on-background)"
},
"smartbar-candidate-clip": {
"background": "transparent",
"foreground": "var(--on-background)",
"font-size": "14sp",
"shape": "rounded-corner(8%, 8%, 8%, 8%)"
},
"smartbar-candidate-clip:pressed": {
"background": "var(--surface)",
"foreground": "var(--on-background)"
},
"smartbar-candidate-spacer": {
"foreground": "var(--surface)"
},
"clipboard-header": {
"background": "transparent",
"foreground": "var(--on-surface)",
@@ -69,13 +127,60 @@
"background": "var(--surface)",
"foreground": "var(--on-surface)",
"font-size": "14sp",
"shape": "rounded-corner(12dp, 12dp, 12dp, 12dp)"
"shape": "var(--shape-variant)",
"shadow-elevation": "2dp"
},
"clipboard-item-popup": {
"background": "var(--surface)",
"background": "var(--surface-variant)",
"foreground": "var(--on-surface)",
"font-size": "14sp",
"shape": "rounded-corner(12dp, 12dp, 12dp, 12dp)"
"shape": "var(--shape-variant)",
"shadow-elevation": "2dp"
},
"emoji-key": {
"background": "transparent",
"foreground": "var(--on-background)",
"font-size": "22sp",
"shape": "var(--shape)"
},
"emoji-key:pressed": {
"background": "var(--surface)",
"foreground": "var(--on-surface)"
},
"emoji-key-popup": {
"background": "#eeeeee",
"foreground": "var(--on-surface)",
"font-size": "22sp",
"shape": "var(--shape)",
"shadow-elevation": "2dp"
},
"emoji-tab": {
"foreground": "var(--on-background)"
},
"emoji-tab:focus": {
"foreground": "var(--primary)"
},
"extracted-landscape-input-layout": {
"background": "var(--background)"
},
"extracted-landscape-input-field": {
"background": "transparent",
"foreground": "var(--on-background)",
"font-size": "16sp",
"shape": "rounded-corner(12dp, 12dp, 12dp, 12dp)",
"border-color": "var(--secondary)",
"border-width": "2dp"
},
"extracted-landscape-input-action": {
"background": "var(--primary)",
"foreground": "var(--on-surface)",
"shape": "rounded-corner(4dp, 4dp, 4dp, 4dp)"
},
"glide-trail": {
"foreground": "var(--primary)"
},
"one-handed-panel": {
@@ -83,76 +188,7 @@
"foreground": "#424242"
},
"smartbar-primary-row": {
"background": "transparent"
},
"smartbar-primary-action-row-toggle": {
"background": "var(--surface)",
"foreground": "var(--on-surface)",
"shape": "rounded-corner(50%, 50%, 50%, 50%)"
},
"smartbar-primary-secondary-row-toggle": {
"background": "transparent",
"foreground": "#121212",
"shape": "rounded-corner(50%, 50%, 50%, 50%)"
},
"smartbar-secondary-row": {
"background": "var(--background)"
},
"smartbar-action-row": {
"background": "transparent"
},
"smartbar-action-button": {
"background": "transparent",
"foreground": "#121212",
"shape": "rounded-corner(50%, 50%, 50%, 50%)"
},
"smartbar-candidate-row": {
"background": "transparent"
},
"smartbar-candidate-word": {
"background": "transparent",
"foreground": "#121212",
"font-size": "14sp",
"shape": "rectangle()"
},
"smartbar-candidate-word:pressed": {
"background": "var(--surface)",
"foreground": "#121212"
},
"smartbar-candidate-clip": {
"background": "transparent",
"foreground": "#121212",
"font-size": "14sp",
"shape": "rounded-corner(8%, 8%, 8%, 8%)"
},
"smartbar-candidate-clip:pressed": {
"background": "var(--surface)",
"foreground": "#121212"
},
"smartbar-candidate-spacer": {
"foreground": "#ffffff40"
},
"smartbar-key": {
"background": "transparent",
"foreground": "#121212",
"font-size": "18sp",
"shape": "rounded-corner(20%, 20%, 20%, 20%)"
},
"smartbar-key:pressed": {
"background": "var(--surface)",
"foreground": "#121212"
},
"smartbar-key:disabled": {
"background": "transparent",
"foreground": "#12121248"
},
"system-nav-bar": {
"background": "#e0e0e0"
"background": "var(--background)"
}
}

View File

@@ -0,0 +1,192 @@
{
"@defines": {
"--primary": "#4caf50",
"--primary-variant": "#388e3c",
"--secondary": "#ff9800",
"--secondary-variant": "#e65100",
"--background": "#e0e0e0",
"--surface": "#f0f0f0",
"--surface-variant": "#ffffff",
"--on-background": "#121212",
"--on-surface": "#000000",
"--on-surface-variant": "#5f5f5f",
"--shape": "rounded-corner(8dp, 8dp, 8dp, 8dp)",
"--shape-variant": "rounded-corner(12dp, 12dp, 12dp, 12dp)"
},
"keyboard": {
"background": "var(--background)"
},
"key": {
"background": "transparent",
"foreground": "var(--on-surface)",
"font-size": "22sp",
"shape": "var(--shape)"
},
"key:pressed": {
"background": "var(--surface)",
"foreground": "var(--on-surface)"
},
"key[code={c:enter}]": {
"background": "var(--primary)",
"foreground": "var(--on-surface)"
},
"key[code={c:enter}]:pressed": {
"background": "var(--primary-variant)",
"foreground": "var(--on-surface)"
},
"key[code={c:shift}][mode={m:capslock}]": {
"foreground": "var(--secondary)"
},
"key[code={c:space}]": {
"background": "var(--surface)",
"foreground": "var(--on-surface-variant)",
"font-size": "12sp"
},
"key-hint": {
"background": "transparent",
"foreground": "var(--on-surface-variant)",
"font-size": "12sp"
},
"key-popup": {
"background": "#eeeeee",
"foreground": "var(--on-surface)",
"font-size": "22sp",
"shape": "var(--shape)",
"shadow-elevation": "2dp"
},
"key-popup:focus": {
"background": "#bdbdbd",
"foreground": "var(--on-surface)"
},
"smartbar-primary-actions-toggle": {
"background": "var(--surface)",
"foreground": "var(--on-surface)",
"shape": "circle()"
},
"smartbar-secondary-actions-toggle": {
"background": "transparent",
"foreground": "var(--on-surface-variant)",
"shape": "circle()"
},
"smartbar-quick-action": {
"background": "transparent",
"foreground": "var(--on-background)",
"shape": "circle()"
},
"smartbar-key": {
"background": "transparent",
"foreground": "var(--on-background)",
"font-size": "18sp",
"shape": "var(--shape)"
},
"smartbar-key:pressed": {
"background": "var(--surface)",
"foreground": "var(--on-surface)"
},
"smartbar-key:disabled": {
"background": "transparent",
"foreground": "#12121248"
},
"smartbar-candidate-word": {
"background": "transparent",
"foreground": "var(--on-background)",
"font-size": "14sp",
"shape": "rectangle()"
},
"smartbar-candidate-word:pressed": {
"background": "var(--surface)",
"foreground": "var(--on-background)"
},
"smartbar-candidate-clip": {
"background": "transparent",
"foreground": "var(--on-background)",
"font-size": "14sp",
"shape": "rounded-corner(8%, 8%, 8%, 8%)"
},
"smartbar-candidate-clip:pressed": {
"background": "var(--surface)",
"foreground": "var(--on-background)"
},
"smartbar-candidate-spacer": {
"foreground": "var(--surface)"
},
"clipboard-header": {
"background": "transparent",
"foreground": "var(--on-surface)",
"font-size": "16sp"
},
"clipboard-item": {
"background": "var(--surface)",
"foreground": "var(--on-surface)",
"font-size": "14sp",
"shape": "var(--shape-variant)",
"shadow-elevation": "2dp"
},
"clipboard-item-popup": {
"background": "var(--surface-variant)",
"foreground": "var(--on-surface)",
"font-size": "14sp",
"shape": "var(--shape-variant)",
"shadow-elevation": "2dp"
},
"emoji-key": {
"background": "transparent",
"foreground": "var(--on-background)",
"font-size": "22sp",
"shape": "var(--shape)"
},
"emoji-key:pressed": {
"background": "var(--surface)",
"foreground": "var(--on-surface)"
},
"emoji-key-popup": {
"background": "#eeeeee",
"foreground": "var(--on-surface)",
"font-size": "22sp",
"shape": "var(--shape)",
"shadow-elevation": "2dp"
},
"emoji-tab": {
"foreground": "var(--on-background)"
},
"emoji-tab:focus": {
"foreground": "var(--primary)"
},
"extracted-landscape-input-layout": {
"background": "var(--background)"
},
"extracted-landscape-input-field": {
"background": "transparent",
"foreground": "var(--on-background)",
"font-size": "16sp",
"shape": "rounded-corner(12dp, 12dp, 12dp, 12dp)",
"border-color": "var(--secondary)",
"border-width": "2dp"
},
"extracted-landscape-input-action": {
"background": "var(--primary)",
"foreground": "var(--on-surface)",
"shape": "rounded-corner(4dp, 4dp, 4dp, 4dp)"
},
"glide-trail": {
"foreground": "var(--primary)"
},
"one-handed-panel": {
"background": "#e8f5e9",
"foreground": "#424242"
},
"system-nav-bar": {
"background": "var(--background)"
}
}

View File

@@ -8,10 +8,12 @@
"--surface": "#424242",
"--surface-variant": "#616161",
"--on-primary": "#ffffff",
"--on-secondary": "#ffffff",
"--on-background": "#ffffff",
"--on-surface": "#ffffff"
"--on-background": "#dcdcdc",
"--on-surface": "#ffffff",
"--on-surface-variant": "#a0a0a0",
"--shape": "rounded-corner(8dp, 8dp, 8dp, 8dp)",
"--shape-variant": "rounded-corner(12dp, 12dp, 12dp, 12dp)"
},
"keyboard": {
@@ -22,7 +24,8 @@
"background": "var(--surface)",
"foreground": "var(--on-surface)",
"font-size": "22sp",
"shape": "rounded-corner(20%, 20%, 20%, 20%)"
"shape": "var(--shape)",
"shadow-elevation": "2dp"
},
"key:pressed": {
"background": "var(--surface-variant)",
@@ -41,25 +44,80 @@
},
"key[code={c:space}]": {
"background": "var(--surface)",
"foreground": "#909090",
"foreground": "var(--on-surface-variant)",
"font-size": "12sp"
},
"key-hint": {
"background": "transparent",
"foreground": "#b8b8b8",
"foreground": "var(--on-surface-variant)",
"font-size": "12sp"
},
"key-popup": {
"background": "#757575",
"foreground": "var(--on-surface)",
"font-size": "22sp",
"shape": "rounded-corner(20%, 20%, 20%, 20%)"
"shape": "var(--shape)",
"shadow-elevation": "2dp"
},
"key-popup:focus": {
"background": "#bdbdbd",
"foreground": "var(--on-surface)"
},
"smartbar-primary-actions-toggle": {
"background": "var(--surface)",
"foreground": "var(--on-surface)",
"shape": "circle()",
"shadow-elevation": "2dp"
},
"smartbar-secondary-actions-toggle": {
"background": "transparent",
"foreground": "var(--on-surface-variant)",
"shape": "circle()"
},
"smartbar-quick-action": {
"background": "transparent",
"foreground": "var(--on-background)",
"shape": "circle()"
},
"smartbar-key": {
"background": "transparent",
"foreground": "var(--on-background)",
"font-size": "18sp",
"shape": "var(--shape)"
},
"smartbar-key:pressed": {
"background": "var(--surface)",
"foreground": "var(--on-surface)"
},
"smartbar-key:disabled": {
"background": "transparent",
"foreground": "#dcdcdc48"
},
"smartbar-candidate-word": {
"background": "transparent",
"foreground": "var(--on-background)",
"font-size": "14sp",
"shape": "rectangle()"
},
"smartbar-candidate-word:pressed": {
"background": "var(--surface)",
"foreground": "var(--on-background)"
},
"smartbar-candidate-clip": {
"background": "transparent",
"foreground": "var(--on-background)",
"font-size": "14sp",
"shape": "rounded-corner(8%, 8%, 8%, 8%)"
},
"smartbar-candidate-clip:pressed": {
"background": "var(--surface)",
"foreground": "var(--on-background)"
},
"smartbar-candidate-spacer": {
"foreground": "var(--surface)"
},
"clipboard-header": {
"background": "transparent",
"foreground": "var(--on-surface)",
@@ -69,13 +127,60 @@
"background": "var(--surface)",
"foreground": "var(--on-surface)",
"font-size": "14sp",
"shape": "rounded-corner(12dp, 12dp, 12dp, 12dp)"
"shape": "var(--shape-variant)",
"shadow-elevation": "2dp"
},
"clipboard-item-popup": {
"background": "#757575",
"background": "var(--surface-variant)",
"foreground": "var(--on-surface)",
"font-size": "14sp",
"shape": "rounded-corner(12dp, 12dp, 12dp, 12dp)"
"shape": "var(--shape-variant)",
"shadow-elevation": "2dp"
},
"emoji-key": {
"background": "transparent",
"foreground": "var(--on-background)",
"font-size": "22sp",
"shape": "var(--shape)"
},
"emoji-key:pressed": {
"background": "var(--surface)",
"foreground": "var(--on-surface)"
},
"emoji-key-popup": {
"background": "#757575",
"foreground": "var(--on-surface)",
"font-size": "22sp",
"shape": "var(--shape)",
"shadow-elevation": "2dp"
},
"emoji-tab": {
"foreground": "var(--on-background)"
},
"emoji-tab:focus": {
"foreground": "var(--primary)"
},
"extracted-landscape-input-layout": {
"background": "var(--background)"
},
"extracted-landscape-input-field": {
"background": "transparent",
"foreground": "var(--on-background)",
"font-size": "16sp",
"shape": "rounded-corner(12dp, 12dp, 12dp, 12dp)",
"border-color": "var(--secondary)",
"border-width": "2dp"
},
"extracted-landscape-input-action": {
"background": "var(--primary)",
"foreground": "var(--on-surface)",
"shape": "rounded-corner(4dp, 4dp, 4dp, 4dp)"
},
"glide-trail": {
"foreground": "var(--primary)"
},
"one-handed-panel": {
@@ -83,76 +188,7 @@
"foreground": "#eeeeee"
},
"smartbar-primary-row": {
"background": "transparent"
},
"smartbar-primary-action-row-toggle": {
"background": "var(--surface)",
"foreground": "var(--on-surface)",
"shape": "rounded-corner(50%, 50%, 50%, 50%)"
},
"smartbar-primary-secondary-row-toggle": {
"background": "transparent",
"foreground": "#909090",
"shape": "rounded-corner(50%, 50%, 50%, 50%)"
},
"smartbar-secondary-row": {
"background": "var(--background)"
},
"smartbar-action-row": {
"background": "transparent"
},
"smartbar-action-button": {
"background": "transparent",
"foreground": "#dcdcdc",
"shape": "rounded-corner(50%, 50%, 50%, 50%)"
},
"smartbar-candidate-row": {
"background": "transparent"
},
"smartbar-candidate-word": {
"background": "transparent",
"foreground": "#dcdcdc",
"font-size": "14sp",
"shape": "rectangle()"
},
"smartbar-candidate-word:pressed": {
"background": "var(--surface)",
"foreground": "#dcdcdc"
},
"smartbar-candidate-clip": {
"background": "transparent",
"foreground": "#dcdcdc",
"font-size": "14sp",
"shape": "rounded-corner(8%, 8%, 8%, 8%)"
},
"smartbar-candidate-clip:pressed": {
"background": "var(--surface)",
"foreground": "#dcdcdc"
},
"smartbar-candidate-spacer": {
"foreground": "#ffffff40"
},
"smartbar-key": {
"background": "transparent",
"foreground": "#dcdcdc",
"font-size": "18sp",
"shape": "rounded-corner(20%, 20%, 20%, 20%)"
},
"smartbar-key:pressed": {
"background": "var(--surface)",
"foreground": "#dcdcdc"
},
"smartbar-key:disabled": {
"background": "transparent",
"foreground": "var(--surface)"
},
"system-nav-bar": {
"background": "#212121"
"background": "var(--background)"
}
}

View File

@@ -0,0 +1,192 @@
{
"@defines": {
"--primary": "#4caf50",
"--primary-variant": "#388e3c",
"--secondary": "#f57c00",
"--secondary-variant": "#e65100",
"--background": "#212121",
"--surface": "#424242",
"--surface-variant": "#616161",
"--on-background": "#dcdcdc",
"--on-surface": "#ffffff",
"--on-surface-variant": "#a0a0a0",
"--shape": "rounded-corner(8dp, 8dp, 8dp, 8dp)",
"--shape-variant": "rounded-corner(12dp, 12dp, 12dp, 12dp)"
},
"keyboard": {
"background": "var(--background)"
},
"key": {
"background": "transparent",
"foreground": "var(--on-surface)",
"font-size": "22sp",
"shape": "var(--shape)"
},
"key:pressed": {
"background": "var(--surface)",
"foreground": "var(--on-surface)"
},
"key[code={c:enter}]": {
"background": "var(--primary)",
"foreground": "var(--on-surface)"
},
"key[code={c:enter}]:pressed": {
"background": "var(--primary-variant)",
"foreground": "var(--on-surface)"
},
"key[code={c:shift}][mode={m:capslock}]": {
"foreground": "var(--secondary)"
},
"key[code={c:space}]": {
"background": "var(--surface)",
"foreground": "var(--on-surface-variant)",
"font-size": "12sp"
},
"key-hint": {
"background": "transparent",
"foreground": "var(--on-surface-variant)",
"font-size": "12sp"
},
"key-popup": {
"background": "#757575",
"foreground": "var(--on-surface)",
"font-size": "22sp",
"shape": "var(--shape)",
"shadow-elevation": "2dp"
},
"key-popup:focus": {
"background": "#bdbdbd",
"foreground": "var(--on-surface)"
},
"smartbar-primary-actions-toggle": {
"background": "var(--surface)",
"foreground": "var(--on-surface)",
"shape": "circle()"
},
"smartbar-secondary-actions-toggle": {
"background": "transparent",
"foreground": "var(--on-surface-variant)",
"shape": "circle()"
},
"smartbar-quick-action": {
"background": "transparent",
"foreground": "var(--on-background)",
"shape": "circle()"
},
"smartbar-key": {
"background": "transparent",
"foreground": "var(--on-background)",
"font-size": "18sp",
"shape": "var(--shape)"
},
"smartbar-key:pressed": {
"background": "var(--surface)",
"foreground": "var(--on-surface)"
},
"smartbar-key:disabled": {
"background": "transparent",
"foreground": "#dcdcdc48"
},
"smartbar-candidate-word": {
"background": "transparent",
"foreground": "var(--on-background)",
"font-size": "14sp",
"shape": "rectangle()"
},
"smartbar-candidate-word:pressed": {
"background": "var(--surface)",
"foreground": "var(--on-background)"
},
"smartbar-candidate-clip": {
"background": "transparent",
"foreground": "var(--on-background)",
"font-size": "14sp",
"shape": "rounded-corner(8%, 8%, 8%, 8%)"
},
"smartbar-candidate-clip:pressed": {
"background": "var(--surface)",
"foreground": "var(--on-background)"
},
"smartbar-candidate-spacer": {
"foreground": "var(--surface)"
},
"clipboard-header": {
"background": "transparent",
"foreground": "var(--on-surface)",
"font-size": "16sp"
},
"clipboard-item": {
"background": "var(--surface)",
"foreground": "var(--on-surface)",
"font-size": "14sp",
"shape": "var(--shape-variant)",
"shadow-elevation": "2dp"
},
"clipboard-item-popup": {
"background": "var(--surface-variant)",
"foreground": "var(--on-surface)",
"font-size": "14sp",
"shape": "var(--shape-variant)",
"shadow-elevation": "2dp"
},
"emoji-key": {
"background": "transparent",
"foreground": "var(--on-background)",
"font-size": "22sp",
"shape": "var(--shape)"
},
"emoji-key:pressed": {
"background": "var(--surface)",
"foreground": "var(--on-surface)"
},
"emoji-key-popup": {
"background": "#757575",
"foreground": "var(--on-surface)",
"font-size": "22sp",
"shape": "var(--shape)",
"shadow-elevation": "2dp"
},
"emoji-tab": {
"foreground": "var(--on-background)"
},
"emoji-tab:focus": {
"foreground": "var(--primary)"
},
"extracted-landscape-input-layout": {
"background": "var(--background)"
},
"extracted-landscape-input-field": {
"background": "transparent",
"foreground": "var(--on-background)",
"font-size": "16sp",
"shape": "rounded-corner(12dp, 12dp, 12dp, 12dp)",
"border-color": "var(--secondary)",
"border-width": "2dp"
},
"extracted-landscape-input-action": {
"background": "var(--primary)",
"foreground": "var(--on-surface)",
"shape": "rounded-corner(4dp, 4dp, 4dp, 4dp)"
},
"glide-trail": {
"foreground": "var(--primary)"
},
"one-handed-panel": {
"background": "#1b5e20",
"foreground": "#eeeeee"
},
"system-nav-bar": {
"background": "var(--background)"
}
}

View File

@@ -0,0 +1,194 @@
{
"@defines": {
"--primary": "#388e3c",
"--primary-variant": "#306d32",
"--secondary": "#ff9800",
"--secondary-variant": "#804c00",
"--background": "#000000",
"--surface": "#212121",
"--surface-variant": "#3d3d3d",
"--on-background": "#eeeeee",
"--on-surface": "#eeeeee",
"--on-surface-variant": "#ffffff73",
"--shape": "rounded-corner(8dp, 8dp, 8dp, 8dp)",
"--shape-variant": "rounded-corner(12dp, 12dp, 12dp, 12dp)"
},
"keyboard": {
"background": "var(--background)"
},
"key": {
"background": "var(--surface)",
"foreground": "var(--on-surface)",
"font-size": "22sp",
"shape": "var(--shape)",
"shadow-elevation": "2dp"
},
"key:pressed": {
"background": "var(--surface-variant)",
"foreground": "var(--on-surface)"
},
"key[code={c:enter}]": {
"background": "var(--primary)",
"foreground": "var(--on-surface)"
},
"key[code={c:enter}]:pressed": {
"background": "var(--primary-variant)",
"foreground": "var(--on-surface)"
},
"key[code={c:shift}][mode={m:capslock}]": {
"foreground": "var(--secondary)"
},
"key[code={c:space}]": {
"background": "var(--surface)",
"foreground": "var(--on-surface-variant)",
"font-size": "12sp"
},
"key-hint": {
"background": "transparent",
"foreground": "var(--on-surface-variant)",
"font-size": "12sp"
},
"key-popup": {
"background": "#424242",
"foreground": "var(--on-surface)",
"font-size": "22sp",
"shape": "var(--shape)",
"shadow-elevation": "2dp"
},
"key-popup:focus": {
"background": "#707070",
"foreground": "var(--on-surface)"
},
"smartbar-primary-actions-toggle": {
"background": "var(--surface)",
"foreground": "var(--on-surface)",
"shape": "circle()",
"shadow-elevation": "2dp"
},
"smartbar-secondary-actions-toggle": {
"background": "transparent",
"foreground": "var(--on-surface-variant)",
"shape": "circle()"
},
"smartbar-quick-action": {
"background": "transparent",
"foreground": "var(--on-background)",
"shape": "circle()"
},
"smartbar-key": {
"background": "transparent",
"foreground": "var(--on-background)",
"font-size": "18sp",
"shape": "var(--shape)"
},
"smartbar-key:pressed": {
"background": "var(--surface)",
"foreground": "var(--on-surface)"
},
"smartbar-key:disabled": {
"background": "transparent",
"foreground": "#dcdcdc48"
},
"smartbar-candidate-word": {
"background": "transparent",
"foreground": "var(--on-background)",
"font-size": "14sp",
"shape": "rectangle()"
},
"smartbar-candidate-word:pressed": {
"background": "var(--surface)",
"foreground": "var(--on-background)"
},
"smartbar-candidate-clip": {
"background": "transparent",
"foreground": "var(--on-background)",
"font-size": "14sp",
"shape": "rounded-corner(8%, 8%, 8%, 8%)"
},
"smartbar-candidate-clip:pressed": {
"background": "var(--surface)",
"foreground": "var(--on-background)"
},
"smartbar-candidate-spacer": {
"foreground": "var(--surface)"
},
"clipboard-header": {
"background": "transparent",
"foreground": "var(--on-surface)",
"font-size": "16sp"
},
"clipboard-item": {
"background": "var(--surface)",
"foreground": "var(--on-surface)",
"font-size": "14sp",
"shape": "var(--shape-variant)",
"shadow-elevation": "2dp"
},
"clipboard-item-popup": {
"background": "var(--surface-variant)",
"foreground": "var(--on-surface)",
"font-size": "14sp",
"shape": "var(--shape-variant)",
"shadow-elevation": "2dp"
},
"emoji-key": {
"background": "transparent",
"foreground": "var(--on-background)",
"font-size": "22sp",
"shape": "var(--shape)"
},
"emoji-key:pressed": {
"background": "var(--surface)",
"foreground": "var(--on-surface)"
},
"emoji-key-popup": {
"background": "#757575",
"foreground": "var(--on-surface)",
"font-size": "22sp",
"shape": "var(--shape)",
"shadow-elevation": "2dp"
},
"emoji-tab": {
"foreground": "var(--on-background)"
},
"emoji-tab:focus": {
"foreground": "var(--primary)"
},
"extracted-landscape-input-layout": {
"background": "var(--background)"
},
"extracted-landscape-input-field": {
"background": "transparent",
"foreground": "var(--on-background)",
"font-size": "16sp",
"shape": "rounded-corner(12dp, 12dp, 12dp, 12dp)",
"border-color": "var(--secondary-variant)",
"border-width": "1dp"
},
"extracted-landscape-input-action": {
"background": "var(--surface)",
"foreground": "var(--on-surface)",
"shape": "rounded-corner(4dp, 4dp, 4dp, 4dp)"
},
"glide-trail": {
"foreground": "var(--primary-variant)"
},
"one-handed-panel": {
"background": "#000000",
"foreground": "#eeeeee"
},
"system-nav-bar": {
"background": "var(--background)"
}
}

View File

@@ -0,0 +1,193 @@
{
"@defines": {
"--primary": "#388e3c",
"--primary-variant": "#306d32",
"--secondary": "#ff9800",
"--secondary-variant": "#804c00",
"--background": "#000000",
"--surface": "#212121",
"--surface-variant": "#3d3d3d",
"--on-background": "#eeeeee",
"--on-surface": "#eeeeee",
"--on-surface-variant": "#ffffff73",
"--shape": "rounded-corner(8dp, 8dp, 8dp, 8dp)",
"--shape-variant": "rounded-corner(12dp, 12dp, 12dp, 12dp)"
},
"keyboard": {
"background": "var(--background)"
},
"key": {
"background": "transparent",
"foreground": "var(--on-surface)",
"font-size": "22sp",
"shape": "var(--shape)"
},
"key:pressed": {
"background": "#6161617f",
"foreground": "var(--on-surface)"
},
"key[code={c:enter}]": {
"background": "var(--primary)",
"foreground": "var(--on-surface)"
},
"key[code={c:enter}]:pressed": {
"background": "var(--primary-variant)",
"foreground": "var(--on-surface)"
},
"key[code={c:shift}][mode={m:capslock}]": {
"foreground": "var(--secondary)"
},
"key[code={c:space}]": {
"background": "#61616146",
"foreground": "var(--on-surface-variant)",
"font-size": "12sp"
},
"key-hint": {
"background": "transparent",
"foreground": "var(--on-surface-variant)",
"font-size": "12sp"
},
"key-popup": {
"background": "#363636",
"foreground": "var(--on-surface)",
"font-size": "22sp",
"shape": "var(--shape)",
"shadow-elevation": "2dp"
},
"key-popup:focus": {
"background": "#5F5F5F",
"foreground": "var(--on-surface)"
},
"smartbar-primary-actions-toggle": {
"background": "var(--surface)",
"foreground": "var(--on-surface)",
"shape": "circle()",
"shadow-elevation": "2dp"
},
"smartbar-secondary-actions-toggle": {
"background": "transparent",
"foreground": "var(--on-surface-variant)",
"shape": "circle()"
},
"smartbar-quick-action": {
"background": "transparent",
"foreground": "var(--on-background)",
"shape": "circle()"
},
"smartbar-key": {
"background": "transparent",
"foreground": "var(--on-background)",
"font-size": "18sp",
"shape": "var(--shape)"
},
"smartbar-key:pressed": {
"background": "var(--surface)",
"foreground": "var(--on-surface)"
},
"smartbar-key:disabled": {
"background": "transparent",
"foreground": "#dcdcdc48"
},
"smartbar-candidate-word": {
"background": "transparent",
"foreground": "var(--on-background)",
"font-size": "14sp",
"shape": "rectangle()"
},
"smartbar-candidate-word:pressed": {
"background": "var(--surface)",
"foreground": "var(--on-background)"
},
"smartbar-candidate-clip": {
"background": "transparent",
"foreground": "var(--on-background)",
"font-size": "14sp",
"shape": "rounded-corner(8%, 8%, 8%, 8%)"
},
"smartbar-candidate-clip:pressed": {
"background": "var(--surface)",
"foreground": "var(--on-background)"
},
"smartbar-candidate-spacer": {
"foreground": "var(--surface)"
},
"clipboard-header": {
"background": "transparent",
"foreground": "var(--on-surface)",
"font-size": "16sp"
},
"clipboard-item": {
"background": "var(--surface)",
"foreground": "var(--on-surface)",
"font-size": "14sp",
"shape": "var(--shape-variant)",
"shadow-elevation": "2dp"
},
"clipboard-item-popup": {
"background": "var(--surface-variant)",
"foreground": "var(--on-surface)",
"font-size": "14sp",
"shape": "var(--shape-variant)",
"shadow-elevation": "2dp"
},
"emoji-key": {
"background": "transparent",
"foreground": "var(--on-background)",
"font-size": "22sp",
"shape": "var(--shape)"
},
"emoji-key:pressed": {
"background": "var(--surface)",
"foreground": "var(--on-surface)"
},
"emoji-key-popup": {
"background": "#757575",
"foreground": "var(--on-surface)",
"font-size": "22sp",
"shape": "var(--shape)",
"shadow-elevation": "2dp"
},
"emoji-tab": {
"foreground": "var(--on-background)"
},
"emoji-tab:focus": {
"foreground": "var(--primary)"
},
"extracted-landscape-input-layout": {
"background": "var(--background)"
},
"extracted-landscape-input-field": {
"background": "transparent",
"foreground": "var(--on-background)",
"font-size": "16sp",
"shape": "rounded-corner(12dp, 12dp, 12dp, 12dp)",
"border-color": "var(--secondary-variant)",
"border-width": "1dp"
},
"extracted-landscape-input-action": {
"background": "var(--surface)",
"foreground": "var(--on-surface)",
"shape": "rounded-corner(4dp, 4dp, 4dp, 4dp)"
},
"glide-trail": {
"foreground": "var(--primary-variant)"
},
"one-handed-panel": {
"background": "#000000",
"foreground": "#eeeeee"
},
"system-nav-bar": {
"background": "var(--background)"
}
}

View File

@@ -24,29 +24,28 @@ import android.content.IntentFilter
import androidx.core.os.UserManagerCompat
import dev.patrickgold.florisboard.app.prefs.florisPreferenceModel
import dev.patrickgold.florisboard.common.NativeStr
import dev.patrickgold.florisboard.common.android.AndroidVersion
import dev.patrickgold.florisboard.common.toNativeStr
import dev.patrickgold.florisboard.crashutility.CrashUtility
import dev.patrickgold.florisboard.debug.Flog
import dev.patrickgold.florisboard.debug.LogTopic
import dev.patrickgold.florisboard.debug.flogError
import dev.patrickgold.florisboard.debug.flogInfo
import dev.patrickgold.florisboard.ime.clipboard.ClipboardManager
import dev.patrickgold.florisboard.ime.core.SubtypeManager
import dev.patrickgold.florisboard.ime.dictionary.DictionaryManager
import dev.patrickgold.florisboard.ime.keyboard.KeyboardManager
import dev.patrickgold.florisboard.ime.nlp.NlpManager
import dev.patrickgold.florisboard.ime.spelling.SpellingManager
import dev.patrickgold.florisboard.ime.spelling.SpellingService
import dev.patrickgold.florisboard.ime.text.gestures.GlideTypingManager
import dev.patrickgold.florisboard.ime.theme.ThemeManager
import dev.patrickgold.florisboard.res.AssetManager
import dev.patrickgold.florisboard.res.ext.ExtensionManager
import dev.patrickgold.florisboard.common.android.AndroidVersion
import dev.patrickgold.florisboard.ime.clipboard.ClipboardManager
import dev.patrickgold.florisboard.ime.nlp.NlpManager
import dev.patrickgold.florisboard.ime.text.gestures.GlideTypingManager
import dev.patrickgold.florisboard.res.cache.CacheManager
import dev.patrickgold.florisboard.res.ext.ExtensionManager
import dev.patrickgold.florisboard.res.io.deleteContentsRecursively
import dev.patrickgold.jetpref.datastore.JetPrefManager
import dev.patrickgold.jetpref.datastore.JetPref
import java.io.File
import kotlin.Exception
@Suppress("unused")
class FlorisApplication : Application() {
@@ -80,7 +79,7 @@ class FlorisApplication : Application() {
override fun onCreate() {
super.onCreate()
try {
JetPrefManager.init(saveIntervalMs = 1_000)
JetPref.configure(saveIntervalMs = 500)
Flog.install(
context = this,
isFloggingEnabled = BuildConfig.DEBUG,
@@ -93,12 +92,12 @@ class FlorisApplication : Application() {
if (AndroidVersion.ATLEAST_API24_N && !UserManagerCompat.isUserUnlocked(this)) {
val context = createDeviceProtectedStorageContext()
initICU(context)
prefs.initializeForContext(context)
prefs.initializeBlocking(context)
registerReceiver(BootComplete(), IntentFilter(Intent.ACTION_USER_UNLOCKED))
} else {
initICU(this)
cacheDir?.deleteContentsRecursively()
prefs.initializeForContext(this)
prefs.initializeBlocking(this)
clipboardManager.value.initializeForContext(this)
}
@@ -141,7 +140,7 @@ class FlorisApplication : Application() {
flogError { e.toString() }
}
cacheDir?.deleteContentsRecursively()
prefs.initializeForContext(this@FlorisApplication)
prefs.initializeBlocking(this@FlorisApplication)
clipboardManager.value.initializeForContext(this@FlorisApplication)
}
}

View File

@@ -16,56 +16,71 @@
package dev.patrickgold.florisboard
import android.content.Context
import android.content.Intent
import android.content.res.Configuration
import android.inputmethodservice.ExtractEditText
import android.os.Build
import android.os.Bundle
import android.util.Size
import android.util.TypedValue
import android.view.Gravity
import android.view.View
import android.view.ViewGroup
import android.view.WindowManager
import android.view.inputmethod.EditorInfo
import android.view.inputmethod.ExtractedText
import android.view.inputmethod.InlineSuggestionsRequest
import android.view.inputmethod.InlineSuggestionsResponse
import android.view.inputmethod.InputMethodManager
import android.widget.FrameLayout
import android.widget.LinearLayout
import android.widget.inline.InlinePresentationSpec
import androidx.annotation.RequiresApi
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.BoxScope
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.fillMaxHeight
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.heightIn
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.wrapContentHeight
import androidx.compose.material.ButtonDefaults
import androidx.compose.runtime.Composable
import androidx.compose.runtime.CompositionLocalProvider
import androidx.compose.runtime.SideEffect
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.ExperimentalComposeUiApi
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.toArgb
import androidx.compose.ui.input.pointer.pointerInteropFilter
import androidx.compose.ui.layout.onGloballyPositioned
import androidx.compose.ui.platform.AbstractComposeView
import androidx.compose.ui.platform.ComposeView
import androidx.compose.ui.platform.LocalConfiguration
import androidx.compose.ui.platform.LocalDensity
import androidx.compose.ui.platform.LocalLayoutDirection
import androidx.compose.ui.unit.IntSize
import androidx.compose.ui.unit.LayoutDirection
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import androidx.compose.ui.viewinterop.AndroidView
import androidx.core.view.WindowCompat
import dev.patrickgold.florisboard.app.FlorisAppActivity
import dev.patrickgold.florisboard.app.prefs.florisPreferenceModel
import dev.patrickgold.florisboard.app.res.ProvideLocalizedResources
import dev.patrickgold.florisboard.app.ui.components.FlorisButton
import dev.patrickgold.florisboard.app.ui.components.SystemUiIme
import dev.patrickgold.florisboard.app.ui.devtools.DevtoolsOverlay
import dev.patrickgold.florisboard.common.ViewUtils
import dev.patrickgold.florisboard.common.android.AndroidInternalR
import dev.patrickgold.florisboard.common.android.AndroidVersion
import dev.patrickgold.florisboard.common.android.isOrientationLandscape
import dev.patrickgold.florisboard.common.android.isOrientationPortrait
import dev.patrickgold.florisboard.common.android.launchActivity
import dev.patrickgold.florisboard.common.android.setLocale
import dev.patrickgold.florisboard.common.android.systemServiceOrNull
import dev.patrickgold.florisboard.common.observeAsTransformingState
import dev.patrickgold.florisboard.debug.LogTopic
@@ -79,15 +94,22 @@ import dev.patrickgold.florisboard.ime.keyboard.FlorisImeSizing
import dev.patrickgold.florisboard.ime.keyboard.InputFeedbackController
import dev.patrickgold.florisboard.ime.keyboard.LocalInputFeedbackController
import dev.patrickgold.florisboard.ime.keyboard.ProvideKeyboardRowBaseHeight
import dev.patrickgold.florisboard.ime.landscapeinput.LandscapeInputUiMode
import dev.patrickgold.florisboard.ime.lifecycle.LifecycleInputMethodService
import dev.patrickgold.florisboard.ime.media.MediaInputLayout
import dev.patrickgold.florisboard.ime.onehanded.OneHandedMode
import dev.patrickgold.florisboard.ime.onehanded.OneHandedPanel
import dev.patrickgold.florisboard.ime.text.TextInputLayout
import dev.patrickgold.florisboard.ime.text.smartbar.SecondaryRowPlacement
import dev.patrickgold.florisboard.ime.theme.FlorisImeTheme
import dev.patrickgold.florisboard.ime.theme.FlorisImeUi
import dev.patrickgold.florisboard.ime.theme.ThemeManager
import dev.patrickgold.florisboard.snygg.ui.SnyggSurface
import dev.patrickgold.florisboard.snygg.ui.shape
import dev.patrickgold.florisboard.snygg.ui.snyggBackground
import dev.patrickgold.florisboard.snygg.ui.snyggBorder
import dev.patrickgold.florisboard.snygg.ui.snyggShadow
import dev.patrickgold.florisboard.snygg.ui.solidColor
import dev.patrickgold.florisboard.snygg.ui.spSize
import dev.patrickgold.jetpref.datastore.model.observeAsState
import java.lang.ref.WeakReference
@@ -103,10 +125,6 @@ private var FlorisImeServiceReference = WeakReference<FlorisImeService?>(null)
/**
* Core class responsible for linking together all managers and UI compose-ables to provide an IME service. Sets
* up the window and context to be lifecycle-aware, so LiveData and Jetpack Compose can be used without issues.
*
* This is a new implementation for the keyboard service class and is replacing the old core class bit by bit.
* The main objective for the new class is to hold as few state as possible and delegate tasks to context-bound
* manager classes.
*/
class FlorisImeService : LifecycleInputMethodService(), EditorInstance.WordHistoryChangedListener {
companion object {
@@ -135,12 +153,25 @@ class FlorisImeService : LifecycleInputMethodService(), EditorInstance.WordHisto
}
fun showUi() {
val ims = FlorisImeServiceReference.get() ?: return
if (AndroidVersion.ATLEAST_API28_P) {
FlorisImeServiceReference.get()?.requestShowSelf(0)
ims.requestShowSelf(0)
} else {
@Suppress("DEPRECATION")
ims.systemServiceOrNull(InputMethodManager::class)
?.showSoftInputFromInputMethod(ims.currentInputBinding.connectionToken, 0)
}
}
fun hideUi() {
val ims = FlorisImeServiceReference.get() ?: return
if (AndroidVersion.ATLEAST_API28_P) {
ims.requestHideSelf(0)
} else {
@Suppress("DEPRECATION")
ims.systemServiceOrNull(InputMethodManager::class)
?.hideSoftInputFromInputMethod(ims.currentInputBinding.connectionToken, 0)
}
FlorisImeServiceReference.get()?.requestHideSelf(0)
}
@@ -186,6 +217,8 @@ class FlorisImeService : LifecycleInputMethodService(), EditorInstance.WordHisto
private val prefs by florisPreferenceModel()
private val keyboardManager by keyboardManager()
private val nlpManager by nlpManager()
private val subtypeManager by subtypeManager()
private val themeManager by themeManager()
private val activeEditorInstance by lazy { EditorInstance(this) }
private val activeState get() = keyboardManager.activeState
@@ -193,15 +226,27 @@ class FlorisImeService : LifecycleInputMethodService(), EditorInstance.WordHisto
private var inputViewSize by mutableStateOf(IntSize.Zero)
private val inputFeedbackController by lazy { InputFeedbackController.new(this) }
private var isWindowShown: Boolean = false
private var isFullscreenUiMode by mutableStateOf(false)
private var isExtractUiShown by mutableStateOf(false)
private var resourcesContext by mutableStateOf(this as Context)
init {
setTheme(R.style.FlorisImeTheme)
}
override fun onCreate() {
super.onCreate()
FlorisImeServiceReference = WeakReference(this)
activeEditorInstance.wordHistoryChangedListener = this
subtypeManager.activeSubtype.observe(this) { subtype ->
val config = Configuration(resources.configuration)
config.setLocale(subtype.primaryLocale)
resourcesContext = createConfigurationContext(config)
}
}
override fun onCreateInputView(): View {
super.onCreateInputView()
super.installViewTreeOwners()
val composeView = ComposeInputView()
inputWindowView = composeView
return composeView
@@ -212,6 +257,24 @@ class FlorisImeService : LifecycleInputMethodService(), EditorInstance.WordHisto
return null
}
override fun onCreateExtractTextView(): View {
super.installViewTreeOwners()
// Consider adding a fallback to the default extract edit layout if user reports come
// that this causes a crash, especially if the device manufacturer of the user device
// is a known one to break AOSP standards...
val defaultExtractView = super.onCreateExtractTextView()
if (defaultExtractView == null || defaultExtractView !is ViewGroup) {
return ComposeExtractedLandscapeInputView(null)
}
val extractEditText = defaultExtractView.findViewById<ExtractEditText>(android.R.id.inputExtractEditText)
(extractEditText?.parent as? ViewGroup)?.removeView(extractEditText)
defaultExtractView.apply {
removeAllViews()
addView(ComposeExtractedLandscapeInputView(extractEditText))
}
return defaultExtractView
}
override fun onDestroy() {
super.onDestroy()
FlorisImeServiceReference = WeakReference(null)
@@ -302,6 +365,7 @@ class FlorisImeService : LifecycleInputMethodService(), EditorInstance.WordHisto
flogInfo(LogTopic.IMS_EVENTS)
}
isWindowShown = true
themeManager.updateActiveTheme()
}
override fun onWindowHidden() {
@@ -315,8 +379,17 @@ class FlorisImeService : LifecycleInputMethodService(), EditorInstance.WordHisto
isWindowShown = false
}
override fun onEvaluateFullscreenMode(): Boolean {
return when (prefs.keyboard.landscapeInputUiMode.get()) {
LandscapeInputUiMode.DYNAMICALLY_SHOW -> super.onEvaluateFullscreenMode()
LandscapeInputUiMode.NEVER_SHOW -> false
LandscapeInputUiMode.ALWAYS_SHOW -> true
}
}
override fun updateFullscreenMode() {
super.updateFullscreenMode()
isFullscreenUiMode = isFullscreenMode
updateSoftInputWindowLayoutParameters()
}
@@ -325,13 +398,30 @@ class FlorisImeService : LifecycleInputMethodService(), EditorInstance.WordHisto
activeEditorInstance.updateText(token, text)
}
override fun onUpdateExtractingVisibility(ei: EditorInfo?) {
if (ei != null) {
activeState.update(ei)
activeEditorInstance.editorInfo = ei
}
when (prefs.keyboard.landscapeInputUiMode.get()) {
LandscapeInputUiMode.DYNAMICALLY_SHOW -> super.onUpdateExtractingVisibility(ei)
LandscapeInputUiMode.NEVER_SHOW -> isExtractViewShown = false
LandscapeInputUiMode.ALWAYS_SHOW -> isExtractViewShown = true
}
}
override fun setExtractViewShown(shown: Boolean) {
super.setExtractViewShown(shown)
isExtractUiShown = shown
}
@RequiresApi(Build.VERSION_CODES.R)
override fun onCreateInlineSuggestionsRequest(uiExtras: Bundle): InlineSuggestionsRequest? {
return if (prefs.smartbar.enabled.get() && prefs.suggestion.api30InlineSuggestionsEnabled.get()) {
flogInfo(LogTopic.IMS_EVENTS) {
"Creating inline suggestions request because Smartbar and inline suggestions are enabled."
}
val stylesBundle = ThemeManager.createInlineSuggestionUiStyleBundle(this)
val stylesBundle = themeManager.createInlineSuggestionUiStyleBundle(this)
val spec = InlinePresentationSpec.Builder(InlineSuggestionUiSmallestSize, InlineSuggestionUiBiggestSize)
.setStyle(stylesBundle)
.build()
@@ -372,9 +462,9 @@ class FlorisImeService : LifecycleInputMethodService(), EditorInstance.WordHisto
val visibleTopY = inputWindowView.height - inputViewSize.height
val needAdditionalOverlay =
prefs.smartbar.enabled.get() &&
prefs.smartbar.secondaryRowEnabled.get() &&
prefs.smartbar.secondaryRowExpanded.get() &&
prefs.smartbar.secondaryRowPlacement.get() == SecondaryRowPlacement.OVERLAY_APP_UI &&
prefs.smartbar.secondaryActionsEnabled.get() &&
prefs.smartbar.secondaryActionsExpanded.get() &&
prefs.smartbar.secondaryActionsPlacement.get() == SecondaryRowPlacement.OVERLAY_APP_UI &&
keyboardManager.activeState.imeUiMode == ImeUiMode.TEXT
outInsets.contentTopInsets = visibleTopY
@@ -394,7 +484,7 @@ class FlorisImeService : LifecycleInputMethodService(), EditorInstance.WordHisto
val w = window?.window ?: return
WindowCompat.setDecorFitsSystemWindows(w, true)
ViewUtils.updateLayoutHeightOf(w, WindowManager.LayoutParams.MATCH_PARENT)
val layoutHeight = if (isFullscreenMode) {
val layoutHeight = if (isFullscreenUiMode) {
WindowManager.LayoutParams.WRAP_CONTENT
} else {
WindowManager.LayoutParams.MATCH_PARENT
@@ -406,18 +496,39 @@ class FlorisImeService : LifecycleInputMethodService(), EditorInstance.WordHisto
ViewUtils.updateLayoutHeightOf(inputWindowView, layoutHeight)
}
override fun getTextForImeAction(imeOptions: Int): String? {
return try {
when (imeOptions and EditorInfo.IME_MASK_ACTION) {
EditorInfo.IME_ACTION_NONE -> null
EditorInfo.IME_ACTION_GO -> resourcesContext.getString(AndroidInternalR.string.ime_action_go)
EditorInfo.IME_ACTION_SEARCH -> resourcesContext.getString(AndroidInternalR.string.ime_action_search)
EditorInfo.IME_ACTION_SEND -> resourcesContext.getString(AndroidInternalR.string.ime_action_send)
EditorInfo.IME_ACTION_NEXT -> resourcesContext.getString(AndroidInternalR.string.ime_action_next)
EditorInfo.IME_ACTION_DONE -> resourcesContext.getString(AndroidInternalR.string.ime_action_done)
EditorInfo.IME_ACTION_PREVIOUS -> resourcesContext.getString(AndroidInternalR.string.ime_action_previous)
else -> resourcesContext.getString(AndroidInternalR.string.ime_action_default)
}
} catch (_: Throwable) {
super.getTextForImeAction(imeOptions)?.toString()
}
}
@Composable
private fun ImeUiWrapper() {
ProvideLocalizedResources(this) {
ProvideLocalizedResources(resourcesContext) {
ProvideKeyboardRowBaseHeight {
CompositionLocalProvider(
LocalInputFeedbackController provides inputFeedbackController,
LocalLayoutDirection provides LayoutDirection.Ltr,
) {
CompositionLocalProvider(LocalInputFeedbackController provides inputFeedbackController) {
FlorisImeTheme {
// Outer box is necessary as an "outer window"
Box(modifier = Modifier.fillMaxSize()) {
DevtoolsUi()
Column(modifier = Modifier.fillMaxWidth()) {
if (!(isFullscreenUiMode && isExtractUiShown)) {
Box(
modifier = Modifier
.fillMaxWidth()
.weight(1f),
) {
DevtoolsUi()
}
}
ImeUi()
}
SystemUiIme()
@@ -429,80 +540,81 @@ class FlorisImeService : LifecycleInputMethodService(), EditorInstance.WordHisto
@OptIn(ExperimentalComposeUiApi::class)
@Composable
private fun BoxScope.ImeUi() {
val keyboardStyle = FlorisImeTheme.style.get(FlorisImeUi.Keyboard)
SnyggSurface(
modifier = Modifier
.fillMaxWidth()
.wrapContentHeight()
.align(Alignment.BottomStart)
.onGloballyPositioned { coords -> inputViewSize = coords.size }
// Do not remove below line or touch input may get stuck
.pointerInteropFilter { false },
background = keyboardStyle.background,
) {
val configuration = LocalConfiguration.current
val bottomOffset by if (configuration.isOrientationPortrait()) {
prefs.keyboard.bottomOffsetPortrait
} else {
prefs.keyboard.bottomOffsetLandscape
}.observeAsTransformingState { it.dp }
Row(
private fun ImeUi() {
val activeState by keyboardManager.observeActiveState()
val keyboardStyle = FlorisImeTheme.style.get(
element = FlorisImeUi.Keyboard,
mode = activeState.inputMode.value,
)
val layoutDirection = LocalLayoutDirection.current
SideEffect {
keyboardManager.activeState.layoutDirection = layoutDirection
}
CompositionLocalProvider(LocalLayoutDirection provides LayoutDirection.Ltr) {
SnyggSurface(
modifier = Modifier
.fillMaxWidth()
.wrapContentHeight()
// FIXME: removing this fixes the Smartbar sizing but breaks one-handed-mode
//.height(IntrinsicSize.Min)
.padding(bottom = bottomOffset),
.onGloballyPositioned { coords -> inputViewSize = coords.size }
// Do not remove below line or touch input may get stuck
.pointerInteropFilter { false },
style = keyboardStyle,
) {
val oneHandedMode by prefs.keyboard.oneHandedMode.observeAsState()
val oneHandedModeScaleFactor by prefs.keyboard.oneHandedModeScaleFactor.observeAsState()
val keyboardWeight = when {
oneHandedMode == OneHandedMode.OFF || configuration.isOrientationLandscape() -> 1f
else -> oneHandedModeScaleFactor / 100f
}
if (oneHandedMode == OneHandedMode.END && configuration.isOrientationPortrait()) {
OneHandedPanel(
panelSide = OneHandedMode.START,
weight = 1f - keyboardWeight,
)
}
Box(
val configuration = LocalConfiguration.current
val bottomOffset by if (configuration.isOrientationPortrait()) {
prefs.keyboard.bottomOffsetPortrait
} else {
prefs.keyboard.bottomOffsetLandscape
}.observeAsTransformingState { it.dp }
Row(
modifier = Modifier
.weight(keyboardWeight)
.wrapContentHeight(),
.fillMaxWidth()
.wrapContentHeight()
// FIXME: removing this fixes the Smartbar sizing but breaks one-handed-mode
//.height(IntrinsicSize.Min)
.padding(bottom = bottomOffset),
) {
val activeState by keyboardManager.observeActiveState()
when (activeState.imeUiMode) {
ImeUiMode.TEXT -> TextInputLayout()
ImeUiMode.MEDIA -> {}
ImeUiMode.CLIPBOARD -> ClipboardInputLayout()
val oneHandedMode by prefs.keyboard.oneHandedMode.observeAsState()
val oneHandedModeScaleFactor by prefs.keyboard.oneHandedModeScaleFactor.observeAsState()
val keyboardWeight = when {
oneHandedMode == OneHandedMode.OFF || configuration.isOrientationLandscape() -> 1f
else -> oneHandedModeScaleFactor / 100f
}
if (oneHandedMode == OneHandedMode.END && configuration.isOrientationPortrait()) {
OneHandedPanel(
panelSide = OneHandedMode.START,
weight = 1f - keyboardWeight,
)
}
CompositionLocalProvider(LocalLayoutDirection provides layoutDirection) {
Box(
modifier = Modifier
.weight(keyboardWeight)
.wrapContentHeight(),
) {
when (activeState.imeUiMode) {
ImeUiMode.TEXT -> TextInputLayout()
ImeUiMode.MEDIA -> MediaInputLayout()
ImeUiMode.CLIPBOARD -> ClipboardInputLayout()
}
}
}
if (oneHandedMode == OneHandedMode.START && configuration.isOrientationPortrait()) {
OneHandedPanel(
panelSide = OneHandedMode.END,
weight = 1f - keyboardWeight,
)
}
}
if (oneHandedMode == OneHandedMode.START && configuration.isOrientationPortrait()) {
OneHandedPanel(
panelSide = OneHandedMode.END,
weight = 1f - keyboardWeight,
)
}
}
}
}
@Composable
private fun BoxScope.DevtoolsUi() = with(LocalDensity.current) {
private fun DevtoolsUi() {
val devtoolsEnabled by prefs.devtools.enabled.observeAsState()
if (devtoolsEnabled) {
val maxHeight = inputWindowView?.measuredHeight?.let { windowHeight ->
windowHeight - inputViewSize.height - FlorisImeSizing.Static.smartbarHeightPx
} ?: inputViewSize.height
DevtoolsOverlay(
modifier = Modifier
.fillMaxWidth()
.wrapContentHeight()
.heightIn(max = maxHeight.toDp())
.align(Alignment.TopStart),
)
DevtoolsOverlay(modifier = Modifier.fillMaxSize())
}
}
@@ -526,4 +638,111 @@ class FlorisImeService : LifecycleInputMethodService(), EditorInstance.WordHisto
updateSoftInputWindowLayoutParameters()
}
}
private inner class ComposeExtractedLandscapeInputView(eet: ExtractEditText?) : FrameLayout(this) {
val composeView: ComposeView
val extractEditText: ExtractEditText
init {
isHapticFeedbackEnabled = true
layoutParams = LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT)
extractEditText = (eet ?: ExtractEditText(context)).also {
it.id = android.R.id.inputExtractEditText
it.layoutParams = LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT)
it.background = null
it.gravity = Gravity.TOP
it.isVerticalScrollBarEnabled = true
}
addView(extractEditText)
composeView = ComposeView(context).also { it.setContent { Content() } }
addView(composeView)
}
@Composable
fun Content() {
ProvideLocalizedResources(resourcesContext, forceLayoutDirection = LayoutDirection.Ltr) {
FlorisImeTheme {
val layoutStyle = FlorisImeTheme.style.get(FlorisImeUi.ExtractedLandscapeInputLayout)
val fieldStyle = FlorisImeTheme.style.get(FlorisImeUi.ExtractedLandscapeInputField)
val actionStyle = FlorisImeTheme.style.get(FlorisImeUi.ExtractedLandscapeInputAction)
val activeState by keyboardManager.observeActiveState()
Box(
modifier = Modifier
.snyggBackground(layoutStyle, FlorisImeTheme.fallbackSurfaceColor()),
) {
Row(
modifier = Modifier.fillMaxSize(),
verticalAlignment = Alignment.CenterVertically,
) {
val fieldColor = fieldStyle.foreground.solidColor(FlorisImeTheme.fallbackContentColor())
AndroidView(
modifier = Modifier
.padding(8.dp)
.fillMaxHeight()
.weight(1f)
.snyggShadow(fieldStyle)
.snyggBorder(fieldStyle)
.snyggBackground(fieldStyle),
factory = { extractEditText },
update = { view ->
view.background = null
view.backgroundTintList = null
view.foregroundTintList = null
view.setTextColor(fieldColor.toArgb())
view.setHintTextColor(fieldColor.copy(fieldColor.alpha * 0.6f).toArgb())
view.setTextSize(
TypedValue.COMPLEX_UNIT_SP,
fieldStyle.fontSize.spSize(default = 16.sp).value,
)
},
)
FlorisButton(
onClick = {
val ei = activeEditorInstance.editorInfo
if (ei != null) {
if (ei.actionId != 0) {
activeEditorInstance.inputConnection?.performEditorAction(ei.actionId)
} else {
activeEditorInstance.performEnterAction(activeState.imeOptions.enterAction)
}
}
},
modifier = Modifier.padding(horizontal = 8.dp),
text = activeEditorInstance.editorInfo?.actionLabel?.toString()
?: getTextForImeAction(activeState.imeOptions.enterAction.toInt())
?: "ACTION",
shape = actionStyle.shape.shape(),
colors = ButtonDefaults.buttonColors(
backgroundColor = actionStyle.background.solidColor(FlorisImeTheme.fallbackContentColor()),
contentColor = actionStyle.foreground.solidColor(FlorisImeTheme.fallbackSurfaceColor()),
),
)
}
}
}
}
}
override fun getAccessibilityClassName(): CharSequence {
return javaClass.name
}
override fun onAttachedToWindow() {
removeView(extractEditText)
super.onAttachedToWindow()
try {
(parent as LinearLayout).let { extractEditLayout ->
extractEditLayout.layoutParams = LayoutParams(
LinearLayout.LayoutParams.MATCH_PARENT,
LinearLayout.LayoutParams.MATCH_PARENT,
).also { it.setMargins(0, 0, 0, 0) }
extractEditLayout.setPadding(0, 0, 0, 0)
}
} catch (e: Throwable) {
flogError { e.message.toString() }
}
}
}
}

View File

@@ -19,8 +19,6 @@ package dev.patrickgold.florisboard.app
import android.content.Context
import android.content.res.Configuration
import android.os.Bundle
import android.view.View
import android.view.ViewTreeObserver
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.compose.animation.ExperimentalAnimationApi
@@ -39,6 +37,9 @@ import androidx.core.splashscreen.SplashScreen.Companion.installSplashScreen
import androidx.core.view.WindowCompat
import androidx.navigation.NavController
import androidx.navigation.compose.rememberNavController
import com.google.accompanist.insets.ProvideWindowInsets
import com.google.accompanist.insets.navigationBarsWithImePadding
import com.google.accompanist.insets.statusBarsPadding
import dev.patrickgold.florisboard.R
import dev.patrickgold.florisboard.app.prefs.florisPreferenceModel
import dev.patrickgold.florisboard.app.res.ProvideLocalizedResources
@@ -59,9 +60,10 @@ import dev.patrickgold.jetpref.datastore.ui.ProvideDefaultDialogPrefStrings
enum class AppTheme(val id: String) {
AUTO("auto"),
AUTO_AMOLED("auto_amoled"),
LIGHT("light"),
DARK("dark"),
AMOLED_DARK("amoled_dark"),
AMOLED_DARK("amoled_dark");
}
val LocalNavController = staticCompositionLocalOf<NavController> {
@@ -97,35 +99,20 @@ class FlorisAppActivity : ComponentActivity() {
}
AppVersionUtils.updateVersionOnInstallAndLastUse(this, prefs)
WindowCompat.setDecorFitsSystemWindows(window, true)
WindowCompat.setDecorFitsSystemWindows(window, false)
setContent {
ProvideLocalizedResources(resourcesContext) {
FlorisAppTheme(theme = appTheme) {
Surface(color = MaterialTheme.colors.background) {
SystemUiApp()
if (isDatastoreReady) {
ProvideWindowInsets(windowInsetsAnimationsEnabled = false) {
Surface(color = MaterialTheme.colors.background) {
SystemUiApp()
AppContent()
}
}
}
}
}
// PreDraw observer for SplashScreen
val content = findViewById<View>(android.R.id.content)
content.viewTreeObserver.addOnPreDrawListener(
object : ViewTreeObserver.OnPreDrawListener {
override fun onPreDraw(): Boolean {
return if (isDatastoreReady) {
content.viewTreeObserver.removeOnPreDrawListener(this)
true
} else {
false
}
}
}
)
}
override fun onPause() {
@@ -144,12 +131,6 @@ class FlorisAppActivity : ComponentActivity() {
}
}
override fun onDestroy() {
super.onDestroy()
prefs.forceSyncToDisk()
}
@OptIn(ExperimentalAnimationApi::class)
@Composable
private fun AppContent() {
@@ -165,7 +146,11 @@ class FlorisAppActivity : ComponentActivity() {
dismissLabel = stringRes(R.string.action__cancel),
neutralLabel = stringRes(R.string.action__default),
) {
Column {
Column(
modifier = Modifier
.statusBarsPadding()
.navigationBarsWithImePadding(),
) {
Routes.AppNavHost(
modifier = Modifier.weight(1.0f),
navController = navController,

View File

@@ -16,11 +16,20 @@
package dev.patrickgold.florisboard.app.prefs
import android.os.Build
import androidx.annotation.RequiresApi
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.ui.platform.LocalConfiguration
import dev.patrickgold.florisboard.app.AppTheme
import dev.patrickgold.florisboard.app.ui.settings.theme.DisplayColorsAs
import dev.patrickgold.florisboard.app.ui.settings.theme.DisplayKbdAfterDialogs
import dev.patrickgold.florisboard.common.android.isOrientationPortrait
import dev.patrickgold.florisboard.common.observeAsTransformingState
import dev.patrickgold.florisboard.ime.core.DisplayLanguageNamesIn
import dev.patrickgold.florisboard.ime.core.Subtype
import dev.patrickgold.florisboard.ime.landscapeinput.LandscapeInputUiMode
import dev.patrickgold.florisboard.ime.media.emoji.EmojiHairStyle
import dev.patrickgold.florisboard.ime.media.emoji.EmojiRecentlyUsedHelper
import dev.patrickgold.florisboard.ime.media.emoji.EmojiSkinTone
import dev.patrickgold.florisboard.ime.onehanded.OneHandedMode
import dev.patrickgold.florisboard.ime.spelling.SpellingLanguageMode
import dev.patrickgold.florisboard.ime.text.gestures.SwipeAction
@@ -29,15 +38,17 @@ import dev.patrickgold.florisboard.ime.text.key.KeyHintMode
import dev.patrickgold.florisboard.ime.text.key.UtilityKeyAction
import dev.patrickgold.florisboard.ime.text.smartbar.CandidatesDisplayMode
import dev.patrickgold.florisboard.ime.text.smartbar.SecondaryRowPlacement
import dev.patrickgold.florisboard.ime.text.smartbar.SmartbarRowType
import dev.patrickgold.florisboard.ime.theme.ThemeMode
import dev.patrickgold.florisboard.ime.theme.extCoreTheme
import dev.patrickgold.florisboard.res.ext.ExtensionComponentName
import dev.patrickgold.florisboard.snygg.SnyggLevel
import dev.patrickgold.florisboard.util.VersionName
import dev.patrickgold.jetpref.datastore.JetPref
import dev.patrickgold.jetpref.datastore.model.PreferenceModel
import dev.patrickgold.jetpref.datastore.preferenceModel
import java.time.LocalTime
import dev.patrickgold.jetpref.datastore.model.observeAsState
fun florisPreferenceModel() = preferenceModel(AppPrefs::class, ::AppPrefs)
fun florisPreferenceModel() = JetPref.getOrCreatePreferenceModel(AppPrefs::class, ::AppPrefs)
class AppPrefs : PreferenceModel("florisboard-app-prefs") {
val advanced = Advanced()
@@ -304,7 +315,7 @@ class AppPrefs : PreferenceModel("florisboard-app-prefs") {
val internal = Internal()
inner class Internal {
val homeIsBetaToolboxCollapsed = boolean(
key = "internal__home_is_beta_toolbox_collapsed_beta08",
key = "internal__home_is_beta_toolbox_collapsed_0314release",
default = false,
)
val isImeSetUp = boolean(
@@ -355,6 +366,10 @@ class AppPrefs : PreferenceModel("florisboard-app-prefs") {
key = "keyboard__utility_key_action",
default = UtilityKeyAction.DYNAMIC_SWITCH_LANGUAGE_EMOJIS,
)
val spaceBarLanguageDisplayEnabled = boolean(
key = "keyboard__space_bar_language_display_enabled",
default = true,
)
val fontSizeMultiplierPortrait = int(
key = "keyboard__font_size_multiplier_portrait",
default = 100,
@@ -429,10 +444,32 @@ class AppPrefs : PreferenceModel("florisboard-app-prefs") {
mergeHintPopups = mergeHintPopupsEnabled.get(),
)
}
@Composable
fun fontSizeMultiplier(): Float {
val configuration = LocalConfiguration.current
val oneHandedMode by oneHandedMode.observeAsState()
val oneHandedModeFactor by oneHandedModeScaleFactor.observeAsTransformingState { it / 100.0f }
val fontSizeMultiplierBase by if (configuration.isOrientationPortrait()) {
fontSizeMultiplierPortrait
} else {
fontSizeMultiplierLandscape
}.observeAsTransformingState { it / 100.0f }
val fontSizeMultiplier = fontSizeMultiplierBase * if (oneHandedMode != OneHandedMode.OFF && configuration.isOrientationPortrait()) {
oneHandedModeFactor
} else {
1.0f
}
return fontSizeMultiplier
}
}
val localization = Localization()
inner class Localization {
val displayLanguageNamesIn = enum(
key = "localization__display_language_names_in",
default = DisplayLanguageNamesIn.NATIVE_LOCALE,
)
val activeSubtypeId = long(
key = "localization__active_subtype_id",
default = Subtype.DEFAULT.id,
@@ -443,42 +480,71 @@ class AppPrefs : PreferenceModel("florisboard-app-prefs") {
)
}
val media = Media()
inner class Media {
val emojiRecentlyUsed = custom(
key = "media__emoji_recently_used",
default = emptyList(),
serializer = EmojiRecentlyUsedHelper.Serializer,
)
val emojiRecentlyUsedMaxSize = int(
key = "media__emoji_recently_used_max_size",
default = 90,
)
val emojiPreferredSkinTone = enum(
key = "media__emoji_preferred_skin_tone",
default = EmojiSkinTone.DEFAULT,
)
val emojiPreferredHairStyle = enum(
key = "media__emoji_preferred_hair_style",
default = EmojiHairStyle.DEFAULT,
)
}
val smartbar = Smartbar()
inner class Smartbar {
val enabled = boolean(
key = "smartbar__enabled",
default = true,
)
val primaryRowFlipToggles = boolean(
key = "smartbar__primary_row_flip_toggles",
val flipToggles = boolean(
key = "smartbar__flip_toggles",
default = false,
)
val secondaryRowEnabled = boolean(
key = "smartbar__secondary_row_enabled",
val primaryActionsExpanded = boolean(
key = "smartbar__primary_actions_expanded",
default = false,
)
val primaryActionsRowType = enum(
key = "smartbar__primary_actions_row_type",
default = SmartbarRowType.QUICK_ACTIONS,
)
val primaryActionsAutoExpandCollapse = boolean(
key = "smartbar__primary_actions_auto_expand_collapse",
default = true,
)
val secondaryRowExpanded = boolean(
key = "smartbar__secondary_row_expanded",
val primaryActionsExpandWithAnimation = boolean(
key = "smartbar__primary_actions_expand_with_animation",
default = true,
)
val secondaryActionsEnabled = boolean(
key = "smartbar__secondary_actions_enabled",
default = true,
)
val secondaryActionsExpanded = boolean(
key = "smartbar__secondary_actions_expanded",
default = false,
)
val secondaryRowPlacement = enum(
key = "smartbar__secondary_row_placement",
val secondaryActionsPlacement = enum(
key = "smartbar__secondary_actions_placement",
default = SecondaryRowPlacement.ABOVE_PRIMARY,
)
val actionRowExpanded = boolean(
key = "smartbar__action_row_expanded",
default = false,
val secondaryActionsRowType = enum(
key = "smartbar__secondary_actions_row_type",
default = SmartbarRowType.CLIPBOARD_CURSOR_TOOLS,
)
val actionRowExpandWithAnimation = boolean(
key = "smartbar__action_row_expand_with_animation",
default = true,
)
val actionRowAutoExpandCollapse = boolean(
key = "smartbar__action_row_auto_expand_collapse",
default = true,
)
val actions = string(
key = "smartbar__actions",
val quickActions = string(
key = "smartbar__quick_actions",
default = "[]",
)
}
@@ -555,15 +621,25 @@ class AppPrefs : PreferenceModel("florisboard-app-prefs") {
default = extCoreTheme("floris_night"),
serializer = ExtensionComponentName.Serializer,
)
@RequiresApi(Build.VERSION_CODES.O)
val sunriseTime = localTime(
key = "theme__sunrise_time",
default = LocalTime.of(6, 0),
//val sunriseTime = localTime(
// key = "theme__sunrise_time",
// default = LocalTime.of(6, 0),
//)
//val sunsetTime = localTime(
// key = "theme__sunset_time",
// default = LocalTime.of(18, 0),
//)
val editorDisplayColorsAs = enum(
key = "theme__editor_display_colors_as",
default = DisplayColorsAs.HEX8,
)
@RequiresApi(Build.VERSION_CODES.O)
val sunsetTime = localTime(
key = "theme__sunset_time",
default = LocalTime.of(18, 0),
val editorDisplayKbdAfterDialogs = enum(
key = "theme__editor_display_kbd_after_dialogs",
default = DisplayKbdAfterDialogs.REMEMBER,
)
val editorLevel = enum(
key = "theme__editor_level",
default = SnyggLevel.ADVANCED,
)
}
}

View File

@@ -17,12 +17,15 @@
package dev.patrickgold.florisboard.app.res
import android.content.Context
import android.view.View
import androidx.annotation.PluralsRes
import androidx.annotation.StringRes
import androidx.compose.runtime.Composable
import androidx.compose.runtime.CompositionLocalProvider
import androidx.compose.runtime.staticCompositionLocalOf
import androidx.compose.ui.platform.LocalLayoutDirection
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.unit.LayoutDirection
import dev.patrickgold.florisboard.R
import dev.patrickgold.florisboard.common.kotlin.CurlyArg
import dev.patrickgold.florisboard.common.kotlin.curlyFormat
@@ -38,10 +41,17 @@ private val LocalAppNameString = staticCompositionLocalOf {
@Composable
fun ProvideLocalizedResources(
resourcesContext: Context,
forceLayoutDirection: LayoutDirection? = null,
content: @Composable () -> Unit,
) {
val layoutDirection = forceLayoutDirection ?: when (resourcesContext.resources.configuration.layoutDirection) {
View.LAYOUT_DIRECTION_LTR -> LayoutDirection.Ltr
View.LAYOUT_DIRECTION_RTL -> LayoutDirection.Rtl
else -> error("Given configuration specifies invalid layout direction!")
}
CompositionLocalProvider(
LocalResourcesContext provides resourcesContext,
LocalLayoutDirection provides layoutDirection,
LocalAppNameString provides stringResource(R.string.floris_app_name),
) {
content()

View File

@@ -24,6 +24,7 @@ import androidx.navigation.compose.composable
import dev.patrickgold.florisboard.app.ui.devtools.AndroidLocalesScreen
import dev.patrickgold.florisboard.app.ui.devtools.AndroidSettingsScreen
import dev.patrickgold.florisboard.app.ui.devtools.DevtoolsScreen
import dev.patrickgold.florisboard.app.ui.ext.ExtensionEditScreen
import dev.patrickgold.florisboard.app.ui.ext.ExtensionExportScreen
import dev.patrickgold.florisboard.app.ui.ext.ExtensionImportScreen
import dev.patrickgold.florisboard.app.ui.ext.ExtensionImportScreenType
@@ -33,14 +34,19 @@ import dev.patrickgold.florisboard.app.ui.settings.about.AboutScreen
import dev.patrickgold.florisboard.app.ui.settings.about.ProjectLicenseScreen
import dev.patrickgold.florisboard.app.ui.settings.about.ThirdPartyLicensesScreen
import dev.patrickgold.florisboard.app.ui.settings.advanced.AdvancedScreen
import dev.patrickgold.florisboard.app.ui.settings.advanced.BackupScreen
import dev.patrickgold.florisboard.app.ui.settings.advanced.RestoreScreen
import dev.patrickgold.florisboard.app.ui.settings.clipboard.ClipboardScreen
import dev.patrickgold.florisboard.app.ui.settings.dictionary.DictionaryScreen
import dev.patrickgold.florisboard.app.ui.settings.dictionary.UserDictionaryScreen
import dev.patrickgold.florisboard.app.ui.settings.dictionary.UserDictionaryType
import dev.patrickgold.florisboard.app.ui.settings.gestures.GesturesScreen
import dev.patrickgold.florisboard.app.ui.settings.keyboard.InputFeedbackScreen
import dev.patrickgold.florisboard.app.ui.settings.keyboard.KeyboardScreen
import dev.patrickgold.florisboard.app.ui.settings.localization.LocalizationScreen
import dev.patrickgold.florisboard.app.ui.settings.localization.SelectLocaleScreen
import dev.patrickgold.florisboard.app.ui.settings.localization.SubtypeEditorScreen
import dev.patrickgold.florisboard.app.ui.settings.media.MediaScreen
import dev.patrickgold.florisboard.app.ui.settings.smartbar.SmartbarScreen
import dev.patrickgold.florisboard.app.ui.settings.spelling.ImportSpellingArchiveScreen
import dev.patrickgold.florisboard.app.ui.settings.spelling.ManageSpellingDictsScreen
@@ -91,12 +97,18 @@ object Routes {
const val ImportSpellingAffDic = "settings/spelling/import-aff-dic"
const val Dictionary = "settings/dictionary"
const val UserDictionary = "settings/dictionary/user-dictionary/{type}"
fun UserDictionary(type: UserDictionaryType) = UserDictionary.curlyFormat("type" to type.id)
const val Gestures = "settings/gestures"
const val Clipboard = "settings/clipboard"
const val Media = "settings/media"
const val Advanced = "settings/advanced"
const val Backup = "settings/advanced/backup"
const val Restore = "settings/advanced/restore"
const val About = "settings/about"
const val ProjectLicense = "settings/about/project-license"
@@ -112,6 +124,11 @@ object Routes {
}
object Ext {
const val Edit = "ext/edit/{id}?create={serial_type}"
fun Edit(id: String, serialType: String? = null): String {
return Edit.curlyFormat("id" to id, "serial_type" to (serialType ?: ""))
}
const val Export = "ext/export/{id}"
fun Export(id: String) = Export.curlyFormat("id" to id)
@@ -171,12 +188,22 @@ object Routes {
composable(Settings.ImportSpellingArchive) { ImportSpellingArchiveScreen() }
composable(Settings.Dictionary) { DictionaryScreen() }
composable(Settings.UserDictionary) { navBackStack ->
val type = navBackStack.arguments?.getString("type")?.let { typeId ->
UserDictionaryType.values().firstOrNull { it.id == typeId }
}
UserDictionaryScreen(type!!)
}
composable(Settings.Gestures) { GesturesScreen() }
composable(Settings.Clipboard) { ClipboardScreen() }
composable(Settings.Media) { MediaScreen() }
composable(Settings.Advanced) { AdvancedScreen() }
composable(Settings.Backup) { BackupScreen() }
composable(Settings.Restore) { RestoreScreen() }
composable(Settings.About) { AboutScreen() }
composable(Settings.ProjectLicense) { ProjectLicenseScreen() }
@@ -189,11 +216,18 @@ object Routes {
AndroidSettingsScreen(name)
}
composable(Ext.Edit) { navBackStack ->
val extensionId = navBackStack.arguments?.getString("id")
val serialType = navBackStack.arguments?.getString("serial_type")
ExtensionEditScreen(
id = extensionId.toString(),
createSerialType = serialType.takeIf { it != null && it.isNotBlank() },
)
}
composable(Ext.Export) { navBackStack ->
val extensionId = navBackStack.arguments?.getString("id")
ExtensionExportScreen(id = extensionId.toString())
}
composable(Ext.Import) { navBackStack ->
val type = navBackStack.arguments?.getString("type")?.let { typeId ->
ExtensionImportScreenType.values().firstOrNull { it.id == typeId }
@@ -201,7 +235,6 @@ object Routes {
val uuid = navBackStack.arguments?.getString("uuid")?.takeIf { it != "null" }
ExtensionImportScreen(type, uuid)
}
composable(Ext.View) { navBackStack ->
val extensionId = navBackStack.arguments?.getString("id")
ExtensionViewScreen(id = extensionId.toString())

View File

@@ -0,0 +1,46 @@
/*
* Copyright (C) 2022 Patrick Goldinger
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package dev.patrickgold.florisboard.app.ui.components
import androidx.compose.runtime.Composable
import androidx.compose.runtime.DisposableEffect
import androidx.compose.runtime.NonRestartableComposable
import androidx.compose.ui.platform.LocalLifecycleOwner
import androidx.lifecycle.Lifecycle
import androidx.lifecycle.LifecycleEventObserver
@Composable
@NonRestartableComposable
fun DisposableLifecycleEffect(
lifecycle: Lifecycle = LocalLifecycleOwner.current.lifecycle,
onResume: () -> Unit,
onPause: () -> Unit,
) {
DisposableEffect(lifecycle) {
val observer = LifecycleEventObserver { _, event ->
when (event) {
Lifecycle.Event.ON_RESUME -> onResume()
Lifecycle.Event.ON_PAUSE -> onPause()
else -> { }
}
}
lifecycle.addObserver(observer)
onDispose {
lifecycle.removeObserver(observer)
}
}
}

View File

@@ -0,0 +1,41 @@
/*
* Copyright (C) 2022 Patrick Goldinger
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package dev.patrickgold.florisboard.app.ui.components
import androidx.compose.runtime.saveable.Saver
import androidx.compose.ui.unit.Dp
import androidx.compose.ui.unit.TextUnit
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.isUnspecified
import androidx.compose.ui.unit.sp
infix fun TextUnit.safeTimes(other: Float): TextUnit {
return if (this.isUnspecified) 0.sp else this.times(other)
}
infix fun TextUnit.safeTimes(other: Double): TextUnit {
return if (this.isUnspecified) this else this.times(other)
}
infix fun TextUnit.safeTimes(other: Int): TextUnit {
return if (this.isUnspecified) this else this.times(other)
}
val DpSizeSaver = Saver<Dp, Float>(
save = { it.value },
restore = { it.dp },
)

View File

@@ -25,19 +25,32 @@ import androidx.compose.animation.fadeIn
import androidx.compose.animation.fadeOut
import androidx.compose.animation.shrinkHorizontally
import androidx.compose.animation.shrinkVertically
import androidx.compose.ui.Alignment
fun EnterTransition.Companion.verticalTween(duration: Int): EnterTransition {
return fadeIn(tween(duration)) + expandVertically(tween(duration))
fun EnterTransition.Companion.verticalTween(
duration: Int,
expandFrom: Alignment.Vertical = Alignment.Bottom,
): EnterTransition {
return fadeIn(tween(duration)) + expandVertically(tween(duration), expandFrom)
}
fun ExitTransition.Companion.verticalTween(duration: Int): ExitTransition {
return fadeOut(tween(duration)) + shrinkVertically(tween(duration))
fun ExitTransition.Companion.verticalTween(
duration: Int,
shrinkTowards: Alignment.Vertical = Alignment.Bottom,
): ExitTransition {
return fadeOut(tween(duration)) + shrinkVertically(tween(duration), shrinkTowards)
}
fun EnterTransition.Companion.horizontalTween(duration: Int): EnterTransition {
return fadeIn(tween(duration)) + expandHorizontally(tween(duration))
fun EnterTransition.Companion.horizontalTween(
duration: Int,
expandFrom: Alignment.Horizontal = Alignment.End,
): EnterTransition {
return fadeIn(tween(duration)) + expandHorizontally(tween(duration), expandFrom)
}
fun ExitTransition.Companion.horizontalTween(duration: Int): ExitTransition {
return fadeOut(tween(duration)) + shrinkHorizontally(tween(duration))
fun ExitTransition.Companion.horizontalTween(
duration: Int,
shrinkTowards: Alignment.Horizontal = Alignment.End,
): ExitTransition {
return fadeOut(tween(duration)) + shrinkHorizontally(tween(duration), shrinkTowards)
}

Some files were not shown because too many files have changed in this diff Show More