mirror of
https://gitlab.futo.org/keyboard/latinime.git
synced 2024-09-28 14:54:30 +01:00
Update settings categories. Add option for customizing long-press key layout. Draw icon key hints
The texts for more keys have been updated: * morekeys_a should now include only letters relevant to the active language * morekeys_misc_a should include misc letters (accents, etc) not specifically needed for typing in the language The above still needs to be applied to most other languages. Only QWERTY has been updated with the new morekeys system. Other layouts still need to be updated.
This commit is contained in:
parent
4cba419737
commit
dd0ba32804
6
java/res/drawable/icon_spellcheck.xml
Normal file
6
java/res/drawable/icon_spellcheck.xml
Normal file
@ -0,0 +1,6 @@
|
||||
<vector xmlns:aapt="http://schemas.android.com/aapt" xmlns:android="http://schemas.android.com/apk/res/android" android:height="24dp" android:viewportHeight="25" android:viewportWidth="24" android:width="23.04dp">
|
||||
|
||||
<path android:fillColor="#00000000" android:pathData="M5.212,14.909V7.636C5.212,6.736 5.569,5.873 6.206,5.236C6.842,4.6 7.706,4.242 8.606,4.242C9.506,4.242 10.369,4.6 11.006,5.236C11.642,5.873 12,6.736 12,7.636V14.909M5.212,10.06H12M10.06,17.818L12.969,20.727L19.757,13.939" android:strokeLineCap="round" android:strokeLineJoin="round" android:strokeWidth="1.52381" android:strokeColor="#ffffff">
|
||||
</path>
|
||||
|
||||
</vector>
|
25
java/res/drawable/keyboard.xml
Normal file
25
java/res/drawable/keyboard.xml
Normal file
@ -0,0 +1,25 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android" android:height="13.935484dp" android:viewportHeight="36" android:viewportWidth="62" android:width="24dp">
|
||||
|
||||
<path android:fillColor="#FFFFFF" android:pathData="M2,0L7.538,0A2,2 0,0 1,9.538 2L9.538,7.6A2,2 0,0 1,7.538 9.6L2,9.6A2,2 0,0 1,0 7.6L0,2A2,2 0,0 1,2 0z"/>
|
||||
|
||||
<path android:fillColor="#FFFFFF" android:pathData="M2,13.2L7.538,13.2A2,2 0,0 1,9.538 15.2L9.538,20.8A2,2 0,0 1,7.538 22.8L2,22.8A2,2 0,0 1,0 20.8L0,15.2A2,2 0,0 1,2 13.2z"/>
|
||||
|
||||
<path android:fillColor="#FFFFFF" android:pathData="M15.115,0L20.653,0A2,2 0,0 1,22.653 2L22.653,7.6A2,2 0,0 1,20.653 9.6L15.115,9.6A2,2 0,0 1,13.115 7.6L13.115,2A2,2 0,0 1,15.115 0z"/>
|
||||
|
||||
<path android:fillColor="#FFFFFF" android:pathData="M15.115,13.2L20.653,13.2A2,2 0,0 1,22.653 15.2L22.653,20.8A2,2 0,0 1,20.653 22.8L15.115,22.8A2,2 0,0 1,13.115 20.8L13.115,15.2A2,2 0,0 1,15.115 13.2z"/>
|
||||
|
||||
<path android:fillColor="#FFFFFF" android:pathData="M28.231,0L33.769,0A2,2 0,0 1,35.769 2L35.769,7.6A2,2 0,0 1,33.769 9.6L28.231,9.6A2,2 0,0 1,26.231 7.6L26.231,2A2,2 0,0 1,28.231 0z"/>
|
||||
|
||||
<path android:fillColor="#FFFFFF" android:pathData="M28.231,13.2L33.769,13.2A2,2 0,0 1,35.769 15.2L35.769,20.8A2,2 0,0 1,33.769 22.8L28.231,22.8A2,2 0,0 1,26.231 20.8L26.231,15.2A2,2 0,0 1,28.231 13.2z"/>
|
||||
|
||||
<path android:fillColor="#FFFFFF" android:pathData="M12.731,26.4L49.269,26.4A2,2 0,0 1,51.269 28.4L51.269,34A2,2 0,0 1,49.269 36L12.731,36A2,2 0,0 1,10.731 34L10.731,28.4A2,2 0,0 1,12.731 26.4z"/>
|
||||
|
||||
<path android:fillColor="#FFFFFF" android:pathData="M41.346,0L46.884,0A2,2 0,0 1,48.884 2L48.884,7.6A2,2 0,0 1,46.884 9.6L41.346,9.6A2,2 0,0 1,39.346 7.6L39.346,2A2,2 0,0 1,41.346 0z"/>
|
||||
|
||||
<path android:fillColor="#FFFFFF" android:pathData="M41.346,13.2L46.884,13.2A2,2 0,0 1,48.884 15.2L48.884,20.8A2,2 0,0 1,46.884 22.8L41.346,22.8A2,2 0,0 1,39.346 20.8L39.346,15.2A2,2 0,0 1,41.346 13.2z"/>
|
||||
|
||||
<path android:fillColor="#FFFFFF" android:pathData="M54.462,0L60,0A2,2 0,0 1,62 2L62,7.6A2,2 0,0 1,60 9.6L54.462,9.6A2,2 0,0 1,52.462 7.6L52.462,2A2,2 0,0 1,54.462 0z"/>
|
||||
|
||||
<path android:fillColor="#FFFFFF" android:pathData="M54.462,13.2L60,13.2A2,2 0,0 1,62 15.2L62,20.8A2,2 0,0 1,60 22.8L54.462,22.8A2,2 0,0 1,52.462 20.8L52.462,15.2A2,2 0,0 1,54.462 13.2z"/>
|
||||
|
||||
</vector>
|
5
java/res/drawable/swipe_icon.xml
Normal file
5
java/res/drawable/swipe_icon.xml
Normal file
@ -0,0 +1,5 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android" android:height="24dp" android:viewportHeight="34" android:viewportWidth="32" android:width="22.588236dp">
|
||||
|
||||
<path android:fillColor="#00000000" android:pathData="M15.789,16.001V6.91a1.82,1.82 0,0 0,-3.104 -1.286,1.82 1.82,0 0,0 -0.533,1.286v10.303l-1.782,-1.782a2.262,2.262 0,0 0,-2.763 -0.339,1.814 1.814,0 0,0 -0.65,2.451c2.277,4.048 3.605,6.362 3.983,6.943l0.238,0.363a7.268,7.268 0,0 0,6.075 3.273h-0.252,2.424a7.269,7.269 0,0 0,7.272 -7.273v-5.454a1.819,1.819 0,1 0,-3.636 0m-7.272,0v-2.424a1.817,1.817 0,1 1,3.636 0v3.03m0,-1.818a1.817,1.817 0,1 1,3.636 0v1.818M5.535,8.236c0.93,-0.68 1.93,-1.26 2.982,-1.73m10.908,-0.859c1.6,0.429 3.1,1.093 4.466,1.954" android:strokeColor="#FFFFFF" android:strokeWidth="2"/>
|
||||
|
||||
</vector>
|
7
java/res/drawable/text_prediction.xml
Normal file
7
java/res/drawable/text_prediction.xml
Normal file
@ -0,0 +1,7 @@
|
||||
<vector xmlns:aapt="http://schemas.android.com/aapt" xmlns:android="http://schemas.android.com/apk/res/android" android:height="24dp" android:viewportHeight="30" android:viewportWidth="30" android:width="24dp">
|
||||
|
||||
<path android:fillColor="#00000000" android:pathData="M5.304,24.699H24.698M10.152,19.85V10.153C10.152,8.867 10.663,7.634 11.572,6.725C12.482,5.816 13.715,5.305 15.001,5.305C16.287,5.305 17.52,5.816 18.429,6.725C19.338,7.634 19.849,8.867 19.849,10.153V19.85M10.152,12.577H19.849" android:strokeLineCap="round" android:strokeLineJoin="round" android:strokeWidth="1.90476" android:strokeColor="#ffffff">
|
||||
|
||||
</path>
|
||||
|
||||
</vector>
|
39
java/res/drawable/themes.xml
Normal file
39
java/res/drawable/themes.xml
Normal file
@ -0,0 +1,39 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:aapt="http://schemas.android.com/aapt"
|
||||
android:width="32dp"
|
||||
android:height="32dp"
|
||||
android:viewportWidth="32"
|
||||
android:viewportHeight="32">
|
||||
<path
|
||||
android:pathData="M16.001,26.91C13.108,26.91 10.333,25.761 8.287,23.715C6.241,21.669 5.092,18.894 5.092,16.001C5.092,13.108 6.241,10.333 8.287,8.287C10.333,6.241 13.108,5.092 16.001,5.092C22.025,5.092 26.91,9.434 26.91,14.789C26.91,16.074 26.335,17.308 25.312,18.217C24.289,19.126 22.902,19.637 21.455,19.637H18.425C17.884,19.628 17.356,19.801 16.925,20.127C16.493,20.453 16.183,20.914 16.044,21.437C15.904,21.959 15.944,22.513 16.156,23.011C16.368,23.508 16.74,23.921 17.213,24.183C17.455,24.406 17.621,24.7 17.688,25.022C17.754,25.345 17.718,25.68 17.584,25.981C17.451,26.282 17.226,26.533 16.942,26.7C16.658,26.867 16.329,26.94 16.001,26.91Z"
|
||||
android:strokeLineJoin="round"
|
||||
android:strokeWidth="1.90476"
|
||||
android:fillColor="#00000000"
|
||||
android:strokeColor="#ffffff"
|
||||
android:strokeLineCap="round">
|
||||
</path>
|
||||
<path
|
||||
android:pathData="M10.546,14.183C10.546,14.504 10.674,14.813 10.901,15.04C11.129,15.267 11.437,15.395 11.759,15.395C12.08,15.395 12.388,15.267 12.616,15.04C12.843,14.813 12.971,14.504 12.971,14.183C12.971,13.861 12.843,13.553 12.616,13.326C12.388,13.098 12.08,12.971 11.759,12.971C11.437,12.971 11.129,13.098 10.901,13.326C10.674,13.553 10.546,13.861 10.546,14.183Z"
|
||||
android:strokeLineJoin="round"
|
||||
android:strokeWidth="1.90476"
|
||||
android:fillColor="#00000000"
|
||||
android:strokeColor="#ffffff"
|
||||
android:strokeLineCap="round">
|
||||
</path>
|
||||
<path
|
||||
android:pathData="M15.395,10.546C15.395,10.868 15.523,11.176 15.75,11.403C15.977,11.631 16.285,11.759 16.607,11.759C16.928,11.759 17.237,11.631 17.464,11.403C17.691,11.176 17.819,10.868 17.819,10.546C17.819,10.225 17.691,9.917 17.464,9.689C17.237,9.462 16.928,9.334 16.607,9.334C16.285,9.334 15.977,9.462 15.75,9.689C15.523,9.917 15.395,10.225 15.395,10.546Z"
|
||||
android:strokeLineJoin="round"
|
||||
android:strokeWidth="1.90476"
|
||||
android:fillColor="#00000000"
|
||||
android:strokeColor="#ffffff"
|
||||
android:strokeLineCap="round">
|
||||
</path>
|
||||
<path
|
||||
android:pathData="M20.243,14.183C20.243,14.504 20.371,14.813 20.598,15.04C20.826,15.267 21.134,15.395 21.455,15.395C21.777,15.395 22.085,15.267 22.313,15.04C22.54,14.813 22.668,14.504 22.668,14.183C22.668,13.861 22.54,13.553 22.313,13.326C22.085,13.098 21.777,12.971 21.455,12.971C21.134,12.971 20.826,13.098 20.598,13.326C20.371,13.553 20.243,13.861 20.243,14.183Z"
|
||||
android:strokeLineJoin="round"
|
||||
android:strokeWidth="1.90476"
|
||||
android:fillColor="#00000000"
|
||||
android:strokeColor="#ffffff"
|
||||
android:strokeLineCap="round">
|
||||
</path>
|
||||
</vector>
|
@ -42,7 +42,7 @@
|
||||
<key-style
|
||||
latin:styleName="baseForShiftKeyStyle"
|
||||
latin:keyActionFlags="noKeyPreview"
|
||||
latin:keyLabelFlags="preserveCase"
|
||||
latin:keyLabelFlags="preserveCase|disableKeyHintLabel"
|
||||
latin:moreKeys="!noPanelAutoMoreKey!, |!code/key_capslock" />
|
||||
<switch>
|
||||
<case
|
||||
@ -75,6 +75,7 @@
|
||||
latin:styleName="deleteKeyStyle"
|
||||
latin:keySpec="!icon/delete_key|!code/key_delete"
|
||||
latin:keyActionFlags="isRepeatable|noKeyPreview"
|
||||
latin:keyLabelFlags="disableKeyHintLabel"
|
||||
latin:backgroundType="functional" />
|
||||
<!-- emojiKeyStyle must be defined before including @xml/key_syles_enter. -->
|
||||
<key-style
|
||||
@ -89,6 +90,7 @@
|
||||
latin:styleName="spaceKeyStyle"
|
||||
latin:keySpec="!icon/space_key|!code/key_space"
|
||||
latin:backgroundType="spacebar"
|
||||
latin:keyLabelFlags="disableKeyHintLabel"
|
||||
latin:keyActionFlags="noKeyPreview|enableLongPress" />
|
||||
<!-- U+200C: ZERO WIDTH NON-JOINER
|
||||
U+200D: ZERO WIDTH JOINER -->
|
||||
|
@ -217,7 +217,7 @@
|
||||
<key-style
|
||||
latin:styleName="defaultEnterKeyStyle"
|
||||
latin:keySpec="!icon/enter_key|!code/key_enter"
|
||||
latin:keyLabelFlags="preserveCase|autoXScale|followKeyLabelRatio|followFunctionalTextColor"
|
||||
latin:keyLabelFlags="preserveCase|autoXScale|followKeyLabelRatio|followFunctionalTextColor|disableKeyHintLabel"
|
||||
latin:keyActionFlags="noKeyPreview"
|
||||
latin:backgroundType="action"
|
||||
latin:parentStyle="navigateMoreKeysStyle" />
|
||||
@ -227,7 +227,7 @@
|
||||
<key-style
|
||||
latin:styleName="defaultEnterKeyStyle"
|
||||
latin:keySpec="!icon/enter_key|!code/key_enter"
|
||||
latin:keyLabelFlags="preserveCase|autoXScale|followKeyLabelRatio|followFunctionalTextColor"
|
||||
latin:keyLabelFlags="preserveCase|autoXScale|followKeyLabelRatio|followFunctionalTextColor|disableKeyHintLabel"
|
||||
latin:keyActionFlags="noKeyPreview"
|
||||
latin:backgroundType="action"
|
||||
latin:parentStyle="navigateMoreKeysStyle" />
|
||||
|
@ -23,27 +23,17 @@
|
||||
>
|
||||
<Key
|
||||
latin:keySpec="!text/keyspec_q"
|
||||
latin:keyHintLabel="1"
|
||||
latin:additionalMoreKeys="1,\\%"
|
||||
latin:moreKeys="!text/morekeys_q" />
|
||||
latin:moreKeys="!text/morekeys_q,!text/qwertysyms_q,!text/number_1,!text/actions_q" />
|
||||
<Key
|
||||
latin:keySpec="!text/keyspec_w"
|
||||
latin:keyHintLabel="2"
|
||||
latin:additionalMoreKeys="2,\\\\"
|
||||
latin:moreKeys="!text/morekeys_w" />
|
||||
latin:moreKeys="!text/morekeys_w,!text/qwertysyms_w,!text/number_2,!text/actions_w" />
|
||||
<Key
|
||||
latin:keySpec="e"
|
||||
latin:keyHintLabel="3"
|
||||
latin:additionalMoreKeys="3,|"
|
||||
latin:moreKeys="!text/morekeys_e" />
|
||||
latin:moreKeys="!text/morekeys_e,!text/morekeys_misc_e,!text/qwertysyms_e,!text/number_3,!text/actions_e" />
|
||||
<Key
|
||||
latin:keySpec="r"
|
||||
latin:keyHintLabel="4"
|
||||
latin:additionalMoreKeys="4,="
|
||||
latin:moreKeys="!text/morekeys_r" />
|
||||
latin:moreKeys="!text/morekeys_r,!text/qwertysyms_r,!text/number_4,!text/actions_r" />
|
||||
<Key
|
||||
latin:keySpec="t"
|
||||
latin:keyHintLabel="5"
|
||||
latin:additionalMoreKeys="5,!text/keyspec_left_square_bracket"
|
||||
latin:moreKeys="!text/morekeys_t" />
|
||||
latin:moreKeys="!text/morekeys_t,!text/qwertysyms_t,!text/number_5,!text/actions_t" />
|
||||
</merge>
|
||||
|
@ -23,26 +23,17 @@
|
||||
>
|
||||
<Key
|
||||
latin:keySpec="!text/keyspec_y"
|
||||
latin:keyHintLabel="6"
|
||||
latin:additionalMoreKeys="6,!text/keyspec_right_square_bracket"
|
||||
latin:moreKeys="!text/morekeys_y" />
|
||||
latin:moreKeys="!text/morekeys_y,!text/qwertysyms_y,!text/number_6,!text/actions_y" />
|
||||
<Key
|
||||
latin:keySpec="u"
|
||||
latin:keyHintLabel="7"
|
||||
latin:additionalMoreKeys="7,!text/keyspec_less_than"
|
||||
latin:moreKeys="!text/morekeys_u" />
|
||||
latin:moreKeys="!text/morekeys_u,!text/morekeys_misc_u,!text/qwertysyms_u,!text/number_7,!text/actions_u" />
|
||||
<Key
|
||||
latin:keySpec="i"
|
||||
latin:keyHintLabel="8"
|
||||
latin:additionalMoreKeys="8,!text/keyspec_greater_than"
|
||||
latin:moreKeys="!text/morekeys_i" />
|
||||
latin:moreKeys="!text/morekeys_i,!text/morekeys_misc_i,!text/qwertysyms_i,!text/number_8,!text/actions_i" />
|
||||
<Key
|
||||
latin:keySpec="o"
|
||||
latin:keyHintLabel="9"
|
||||
latin:additionalMoreKeys="9,!text/keyspec_left_curly_bracket"
|
||||
latin:moreKeys="!text/morekeys_o" />
|
||||
latin:moreKeys="!text/morekeys_o,!text/morekeys_misc_o,!text/qwertysyms_o,!text/number_9,!text/actions_o" />
|
||||
<Key
|
||||
latin:keySpec="p"
|
||||
latin:keyHintLabel="0"
|
||||
latin:additionalMoreKeys="0,!text/keyspec_right_curly_bracket" />
|
||||
latin:moreKeys="!text/morekeys_p,!text/qwertysyms_p,!text/number_0,!text/actions_p" />
|
||||
</merge>
|
||||
|
@ -23,26 +23,17 @@
|
||||
>
|
||||
<Key
|
||||
latin:keySpec="a"
|
||||
latin:keyHintLabel="\@"
|
||||
latin:additionalMoreKeys="\\@,!icon/action_select_all|!code/action_select_all"
|
||||
latin:moreKeys="!text/morekeys_a" />
|
||||
latin:moreKeys="!text/morekeys_a,!text/morekeys_misc_a,!text/qwertysyms_a,!text/actions_a" />
|
||||
<Key
|
||||
latin:keySpec="s"
|
||||
latin:keyHintLabel="#"
|
||||
latin:additionalMoreKeys="#"
|
||||
latin:moreKeys="!text/morekeys_s" />
|
||||
latin:moreKeys="!text/morekeys_s,!text/morekeys_misc_s,!text/qwertysyms_s,!text/actions_s" />
|
||||
<Key
|
||||
latin:keySpec="d"
|
||||
latin:keyHintLabel="$"
|
||||
latin:additionalMoreKeys="$,€,£,¥,¢"
|
||||
latin:moreKeys="!text/morekeys_d" />
|
||||
latin:moreKeys="!text/morekeys_d,!text/qwertysyms_d,!text/actions_d" />
|
||||
<Key
|
||||
latin:keySpec="f"
|
||||
latin:keyHintLabel="%"
|
||||
latin:additionalMoreKeys="%" />
|
||||
latin:moreKeys="!text/morekeys_f,!text/qwertysyms_f,!text/actions_f" />
|
||||
<Key
|
||||
latin:keySpec="g"
|
||||
latin:keyHintLabel="&"
|
||||
latin:additionalMoreKeys="&,|"
|
||||
latin:moreKeys="!text/morekeys_g" />
|
||||
latin:moreKeys="!text/morekeys_g,!text/qwertysyms_g,!text/actions_g" />
|
||||
</merge>
|
||||
|
@ -23,22 +23,14 @@
|
||||
>
|
||||
<Key
|
||||
latin:keySpec="h"
|
||||
latin:keyHintLabel="-"
|
||||
latin:additionalMoreKeys="-,–,—,_"
|
||||
latin:moreKeys="!text/morekeys_h" />
|
||||
latin:moreKeys="!text/morekeys_h,!text/qwertysyms_h,!text/actions_h" />
|
||||
<Key
|
||||
latin:keySpec="j"
|
||||
latin:keyHintLabel="+"
|
||||
latin:additionalMoreKeys="+,="
|
||||
latin:moreKeys="!text/morekeys_j" />
|
||||
latin:moreKeys="!text/morekeys_j,!text/qwertysyms_j,!text/actions_j" />
|
||||
<Key
|
||||
latin:keySpec="k"
|
||||
latin:keyHintLabel="("
|
||||
latin:additionalMoreKeys="(,[,{,<"
|
||||
latin:moreKeys="!text/morekeys_k" />
|
||||
latin:moreKeys="!text/morekeys_k,!text/qwertysyms_k,!text/actions_k" />
|
||||
<Key
|
||||
latin:keySpec="l"
|
||||
latin:keyHintLabel=")"
|
||||
latin:additionalMoreKeys="),],},>"
|
||||
latin:moreKeys="!text/morekeys_l" />
|
||||
latin:moreKeys="!text/morekeys_l,!text/qwertysyms_l,!text/actions_l" />
|
||||
</merge>
|
||||
|
@ -23,22 +23,14 @@
|
||||
>
|
||||
<Key
|
||||
latin:keySpec="z"
|
||||
latin:keyHintLabel="*"
|
||||
latin:additionalMoreKeys="*,!icon/action_undo|!code/action_undo"
|
||||
latin:moreKeys="!text/morekeys_z" />
|
||||
latin:moreKeys="!text/morekeys_z,!text/qwertysyms_z,!text/actions_z" />
|
||||
<Key
|
||||
latin:keySpec="!text/keyspec_x"
|
||||
latin:keyHintLabel="""
|
||||
latin:additionalMoreKeys="",!icon/action_cut|!code/action_cut"
|
||||
latin:moreKeys="!text/morekeys_x" />
|
||||
latin:moreKeys="!text/morekeys_x,!text/qwertysyms_x,!text/actions_x" />
|
||||
<Key
|
||||
latin:keySpec="c"
|
||||
latin:keyHintLabel="'"
|
||||
latin:additionalMoreKeys="',!icon/action_copy|!code/action_copy"
|
||||
latin:moreKeys="!text/morekeys_c" />
|
||||
latin:moreKeys="!text/morekeys_c,!text/morekeys_misc_c,!text/qwertysyms_c,!text/actions_c" />
|
||||
<Key
|
||||
latin:keySpec="v"
|
||||
latin:keyHintLabel=":"
|
||||
latin:additionalMoreKeys=":,!icon/action_paste|!code/action_paste"
|
||||
latin:moreKeys="!text/morekeys_v" />
|
||||
latin:moreKeys="!text/morekeys_v,!text/qwertysyms_v,!text/actions_v" />
|
||||
</merge>
|
||||
|
@ -23,15 +23,11 @@
|
||||
>
|
||||
<Key
|
||||
latin:keySpec="b"
|
||||
latin:keyHintLabel=";"
|
||||
latin:additionalMoreKeys=";" />
|
||||
latin:moreKeys="!text/morekeys_b,!text/qwertysyms_b,!text/actions_b" />
|
||||
<Key
|
||||
latin:keySpec="n"
|
||||
latin:keyHintLabel="!"
|
||||
latin:additionalMoreKeys="!"
|
||||
latin:moreKeys="!text/morekeys_n" />
|
||||
latin:moreKeys="!text/morekeys_n,!text/morekeys_misc_n,!text/qwertysyms_n,!text/actions_n" />
|
||||
<Key
|
||||
latin:keySpec="m"
|
||||
latin:keyHintLabel="\?"
|
||||
latin:additionalMoreKeys="\?,/" />
|
||||
latin:moreKeys="!text/morekeys_m,!text/qwertysyms_m,!text/actions_m" />
|
||||
</merge>
|
||||
|
@ -60,6 +60,7 @@ public class Key implements Comparable<Key> {
|
||||
private final String mLabel;
|
||||
/** Hint label to display on the key in conjunction with the label */
|
||||
private final String mHintLabel;
|
||||
private final String mHintIconId;
|
||||
/** Flags of the label */
|
||||
private final int mLabelFlags;
|
||||
private static final int LABEL_FLAGS_ALIGN_HINT_LABEL_TO_BOTTOM = 0x02;
|
||||
@ -215,6 +216,7 @@ public class Key implements Comparable<Key> {
|
||||
mHorizontalGap = horizontalGap;
|
||||
mVerticalGap = verticalGap;
|
||||
mHintLabel = hintLabel;
|
||||
mHintIconId = ICON_UNDEFINED;
|
||||
mLabelFlags = labelFlags;
|
||||
mBackgroundType = backgroundType;
|
||||
// TODO: Pass keyActionFlags as an argument.
|
||||
@ -287,7 +289,8 @@ public class Key implements Comparable<Key> {
|
||||
final boolean needsToUpcase = needsToUpcase(mLabelFlags, params.mId.mElementId);
|
||||
final Locale localeForUpcasing = params.mId.getLocale();
|
||||
int actionFlags = style.getFlags(keyAttr, R.styleable.Keyboard_Key_keyActionFlags);
|
||||
String[] moreKeys = style.getStringArray(keyAttr, R.styleable.Keyboard_Key_moreKeys);
|
||||
|
||||
String[] moreKeys = style.getStringArray(keyAttr, R.styleable.Keyboard_Key_moreKeys, s -> params.mId.mLongPressKeySettings.reorderMoreKeys(s));
|
||||
|
||||
// Get maximum column order number and set a relevant mode value.
|
||||
int moreKeysColumnAndFlags = MORE_KEYS_MODE_MAX_COLUMN_WITH_AUTO_ORDER
|
||||
@ -320,7 +323,7 @@ public class Key implements Comparable<Key> {
|
||||
additionalMoreKeys = null;
|
||||
} else {
|
||||
additionalMoreKeys = style.getStringArray(keyAttr,
|
||||
R.styleable.Keyboard_Key_additionalMoreKeys);
|
||||
R.styleable.Keyboard_Key_additionalMoreKeys, null);
|
||||
}
|
||||
moreKeys = MoreKeySpec.insertAdditionalMoreKeys(moreKeys, additionalMoreKeys);
|
||||
|
||||
@ -357,28 +360,31 @@ public class Key implements Comparable<Key> {
|
||||
? StringUtils.toTitleCaseOfKeyLabel(label, localeForUpcasing)
|
||||
: label;
|
||||
}
|
||||
|
||||
if ((mLabelFlags & LABEL_FLAGS_DISABLE_HINT_LABEL) != 0) {
|
||||
mHintLabel = null;
|
||||
mHintIconId = null;
|
||||
} else {
|
||||
String hintLabel = style.getString(
|
||||
keyAttr, R.styleable.Keyboard_Key_keyHintLabel);
|
||||
|
||||
if(params.mId.mNumberRow && hintLabel != null && hintLabel.matches("\\d+")) {
|
||||
hintLabel = "";
|
||||
}
|
||||
String hintLabel = null;
|
||||
String hintIcon = null;
|
||||
|
||||
if(moreKeys != null && moreKeys.length > 0) {
|
||||
String hintLabelCandidate = moreKeys[0];
|
||||
if(hintLabelCandidate.startsWith("\\")) hintLabelCandidate = hintLabelCandidate.substring(1);
|
||||
|
||||
if(hintLabelCandidate.length() == 1) {
|
||||
hintLabel = hintLabelCandidate;
|
||||
hintLabel = needsToUpcase
|
||||
? StringUtils.toTitleCaseOfKeyLabel(hintLabelCandidate, localeForUpcasing)
|
||||
: hintLabelCandidate;
|
||||
} else if(hintLabelCandidate.contains("!icon/")) {
|
||||
hintIcon = KeySpecParser.getIconId(hintLabelCandidate);
|
||||
}
|
||||
}
|
||||
mHintLabel = needsToUpcase
|
||||
? StringUtils.toTitleCaseOfKeyLabel(hintLabel, localeForUpcasing)
|
||||
: hintLabel;
|
||||
|
||||
mHintLabel = hintLabel;
|
||||
mHintIconId = hintIcon;
|
||||
}
|
||||
|
||||
String outputText = KeySpecParser.getOutputText(keySpec);
|
||||
if (needsToUpcase) {
|
||||
outputText = StringUtils.toTitleCaseOfKeyLabel(outputText, localeForUpcasing);
|
||||
@ -412,7 +418,7 @@ public class Key implements Comparable<Key> {
|
||||
: code;
|
||||
}
|
||||
final int altCodeInAttr = KeySpecParser.parseCode(
|
||||
style.getString(keyAttr, R.styleable.Keyboard_Key_altCode), CODE_UNSPECIFIED);
|
||||
style.getString(keyAttr, R.styleable.Keyboard_Key_altCode, null), CODE_UNSPECIFIED);
|
||||
final int altCode = needsToUpcase
|
||||
? StringUtils.toTitleCaseOfKeyCode(altCodeInAttr, localeForUpcasing)
|
||||
: altCodeInAttr;
|
||||
@ -435,6 +441,7 @@ public class Key implements Comparable<Key> {
|
||||
mCode = key.mCode;
|
||||
mLabel = key.mLabel;
|
||||
mHintLabel = key.mHintLabel;
|
||||
mHintIconId = key.mHintIconId;
|
||||
mLabelFlags = key.mLabelFlags;
|
||||
mIconId = key.mIconId;
|
||||
mWidth = key.mWidth;
|
||||
@ -487,6 +494,7 @@ public class Key implements Comparable<Key> {
|
||||
key.mCode,
|
||||
key.mLabel,
|
||||
key.mHintLabel,
|
||||
key.mHintIconId,
|
||||
key.mIconId,
|
||||
key.mBackgroundType,
|
||||
Arrays.hashCode(key.mMoreKeys),
|
||||
@ -514,6 +522,7 @@ public class Key implements Comparable<Key> {
|
||||
&& o.mCode == mCode
|
||||
&& TextUtils.equals(o.mLabel, mLabel)
|
||||
&& TextUtils.equals(o.mHintLabel, mHintLabel)
|
||||
&& TextUtils.equals(o.mHintIconId, mHintIconId)
|
||||
&& o.mIconId == mIconId
|
||||
&& o.mBackgroundType == mBackgroundType
|
||||
&& Arrays.equals(o.mMoreKeys, mMoreKeys)
|
||||
@ -588,6 +597,11 @@ public class Key implements Comparable<Key> {
|
||||
return mHintLabel;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public String getHintIconId() {
|
||||
return mHintIconId;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public MoreKeySpec[] getMoreKeys() {
|
||||
return mMoreKeys;
|
||||
@ -840,6 +854,19 @@ public class Key implements Comparable<Key> {
|
||||
return icon;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public Drawable getHintIcon(final KeyboardIconsSet iconSet, final int alpha) {
|
||||
final OptionalAttributes attrs = mOptionalAttributes;
|
||||
final String iconId = getHintIconId();
|
||||
if(iconId == null) return null;
|
||||
|
||||
final Drawable icon = iconSet.getIconDrawable(iconId);
|
||||
if (icon != null) {
|
||||
icon.setAlpha(alpha);
|
||||
}
|
||||
return icon;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public Drawable getPreviewIcon(final KeyboardIconsSet iconSet) {
|
||||
return iconSet.getIconDrawable(getIconId());
|
||||
|
@ -24,6 +24,7 @@ import android.view.inputmethod.EditorInfo;
|
||||
|
||||
import org.futo.inputmethod.compat.EditorInfoCompatUtils;
|
||||
import org.futo.inputmethod.latin.RichInputMethodSubtype;
|
||||
import org.futo.inputmethod.latin.settings.LongPressKeySettings;
|
||||
import org.futo.inputmethod.latin.utils.InputTypeUtils;
|
||||
|
||||
import java.util.Arrays;
|
||||
@ -84,6 +85,7 @@ public final class KeyboardId {
|
||||
public final boolean mHasShortcutKey;
|
||||
public final boolean mIsSplitLayout;
|
||||
public final boolean mNumberRow;
|
||||
public final LongPressKeySettings mLongPressKeySettings;
|
||||
|
||||
private final int mHashCode;
|
||||
|
||||
@ -102,6 +104,7 @@ public final class KeyboardId {
|
||||
mHasShortcutKey = params.mVoiceInputKeyEnabled;
|
||||
mIsSplitLayout = params.mIsSplitLayoutEnabled;
|
||||
mNumberRow = params.mNumberRow || params.mIsPasswordField;
|
||||
mLongPressKeySettings = params.mLongPressKeySettings;
|
||||
|
||||
mHashCode = computeHashCode(this);
|
||||
}
|
||||
@ -124,7 +127,8 @@ public final class KeyboardId {
|
||||
id.navigatePrevious(),
|
||||
id.mSubtype,
|
||||
id.mIsSplitLayout,
|
||||
id.mNumberRow
|
||||
id.mNumberRow,
|
||||
id.mLongPressKeySettings.hashCode()
|
||||
});
|
||||
}
|
||||
|
||||
@ -147,7 +151,8 @@ public final class KeyboardId {
|
||||
&& other.navigatePrevious() == navigatePrevious()
|
||||
&& other.mSubtype.equals(mSubtype)
|
||||
&& other.mIsSplitLayout == mIsSplitLayout
|
||||
&& other.mNumberRow == mNumberRow;
|
||||
&& other.mNumberRow == mNumberRow
|
||||
&& other.mLongPressKeySettings.equals(mLongPressKeySettings);
|
||||
}
|
||||
|
||||
private static boolean isAlphabetKeyboard(final int elementId) {
|
||||
|
@ -39,7 +39,7 @@ import org.futo.inputmethod.keyboard.internal.UniqueKeysCache;
|
||||
import org.futo.inputmethod.latin.InputAttributes;
|
||||
import org.futo.inputmethod.latin.R;
|
||||
import org.futo.inputmethod.latin.RichInputMethodSubtype;
|
||||
import org.futo.inputmethod.latin.define.DebugFlags;
|
||||
import org.futo.inputmethod.latin.settings.LongPressKeySettings;
|
||||
import org.futo.inputmethod.latin.utils.InputTypeUtils;
|
||||
import org.futo.inputmethod.latin.utils.ScriptUtils;
|
||||
import org.futo.inputmethod.latin.utils.SubtypeLocaleUtils;
|
||||
@ -136,6 +136,8 @@ public final class KeyboardLayoutSet {
|
||||
new SparseArray<>();
|
||||
|
||||
boolean mNumberRow;
|
||||
|
||||
LongPressKeySettings mLongPressKeySettings;
|
||||
}
|
||||
|
||||
public static void onSystemLocaleChanged() {
|
||||
@ -272,6 +274,8 @@ public final class KeyboardLayoutSet {
|
||||
mResources = context.getResources();
|
||||
final Params params = mParams;
|
||||
|
||||
params.mLongPressKeySettings = new LongPressKeySettings(context);
|
||||
|
||||
final EditorInfo editorInfo = (ei != null) ? ei : EMPTY_EDITOR_INFO;
|
||||
params.mMode = getKeyboardMode(editorInfo);
|
||||
// TODO: Consolidate those with {@link InputAttributes}.
|
||||
|
@ -142,9 +142,15 @@ public class KeyboardView extends View {
|
||||
R.styleable.Keyboard_Key, defStyle, R.style.KeyboardView);
|
||||
|
||||
assert(context instanceof ContextThemeWrapper);
|
||||
assert(((ContextThemeWrapper) context).getBaseContext() instanceof DynamicThemeProviderOwner);
|
||||
|
||||
mDrawableProvider = ((DynamicThemeProviderOwner) ((ContextThemeWrapper) context).getBaseContext()).getDrawableProvider();
|
||||
if(((ContextThemeWrapper) context).getBaseContext() instanceof DynamicThemeProviderOwner) {
|
||||
mDrawableProvider = ((DynamicThemeProviderOwner) ((ContextThemeWrapper) context).getBaseContext()).getDrawableProvider();
|
||||
} else if(context instanceof DynamicThemeProviderOwner) {
|
||||
mDrawableProvider = ((DynamicThemeProviderOwner) context).getDrawableProvider();
|
||||
} else {
|
||||
throw new IllegalStateException("Failed to obtain DynamicThemeProvider");
|
||||
}
|
||||
|
||||
|
||||
boolean isMoreKeys = keyAttr.getBoolean(R.styleable.Keyboard_Key_isMoreKey, false);
|
||||
boolean isMoreKeysAction = keyAttr.getBoolean(R.styleable.Keyboard_Key_isAction, false);
|
||||
@ -419,6 +425,8 @@ public class KeyboardView extends View {
|
||||
final Keyboard keyboard = getKeyboard();
|
||||
final Drawable icon = (keyboard == null) ? null
|
||||
: key.getIcon(keyboard.mIconsSet, params.mAnimAlpha);
|
||||
final Drawable hintIcon = (keyboard == null) ? null
|
||||
: key.getHintIcon(keyboard.mIconsSet, params.mAnimAlpha);
|
||||
float labelX = centerX;
|
||||
float labelBaseline = centerY;
|
||||
final String label = key.getLabel();
|
||||
@ -510,6 +518,17 @@ public class KeyboardView extends View {
|
||||
final float adjustmentY = params.mHintLabelVerticalAdjustment * labelCharHeight;
|
||||
canvas.drawText(
|
||||
hintLabel, 0, hintLabel.length(), hintX, hintBaseline + adjustmentY, paint);
|
||||
} else if(hintIcon != null) {
|
||||
final float size = key.selectHintTextSize(params);
|
||||
|
||||
int iconWidth = (int)size;
|
||||
int iconHeight = (int)size;
|
||||
|
||||
int hintX = keyWidth - iconWidth - (int)mKeyHintLetterPadding;
|
||||
int hintY = (int)mKeyHintLetterPadding;
|
||||
|
||||
hintIcon.setTint(key.selectHintTextColor(params));
|
||||
drawIcon(canvas, hintIcon, hintX, hintY, iconWidth, iconHeight);
|
||||
}
|
||||
|
||||
// Draw key icon.
|
||||
|
@ -18,14 +18,16 @@ package org.futo.inputmethod.keyboard.internal;
|
||||
|
||||
import android.content.res.TypedArray;
|
||||
|
||||
import java.util.function.Function;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
public abstract class KeyStyle {
|
||||
private final KeyboardTextsSet mTextsSet;
|
||||
|
||||
public abstract @Nullable String[] getStringArray(TypedArray a, int index);
|
||||
public abstract @Nullable String getString(TypedArray a, int index);
|
||||
public abstract @Nullable String[] getStringArray(TypedArray a, int index, Function<String, String> stringMutator);
|
||||
public abstract @Nullable String getString(TypedArray a, int index, Function<String, String> stringMutator);
|
||||
public abstract int getInt(TypedArray a, int index, int defaultValue);
|
||||
public abstract int getFlags(TypedArray a, int index);
|
||||
|
||||
@ -34,17 +36,23 @@ public abstract class KeyStyle {
|
||||
}
|
||||
|
||||
@Nullable
|
||||
protected String parseString(final TypedArray a, final int index) {
|
||||
protected String parseString(final TypedArray a, final int index, Function<String, String> stringMutator) {
|
||||
if (a.hasValue(index)) {
|
||||
return mTextsSet.resolveTextReference(a.getString(index));
|
||||
String s = a.getString(index);
|
||||
if(stringMutator != null) s = stringMutator.apply(s);
|
||||
|
||||
return mTextsSet.resolveTextReference(s);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
protected String[] parseStringArray(final TypedArray a, final int index) {
|
||||
protected String[] parseStringArray(final TypedArray a, final int index, Function<String, String> stringMutator) {
|
||||
if (a.hasValue(index)) {
|
||||
final String text = mTextsSet.resolveTextReference(a.getString(index));
|
||||
String s = a.getString(index);
|
||||
if(stringMutator != null) s = stringMutator.apply(s);
|
||||
|
||||
final String text = mTextsSet.resolveTextReference(s);
|
||||
return MoreKeySpec.splitKeySpecs(text);
|
||||
}
|
||||
return null;
|
||||
|
@ -28,6 +28,7 @@ import org.xmlpull.v1.XmlPullParserException;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.function.Function;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import javax.annotation.Nullable;
|
||||
@ -59,14 +60,14 @@ public final class KeyStylesSet {
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
public String[] getStringArray(final TypedArray a, final int index) {
|
||||
return parseStringArray(a, index);
|
||||
public String[] getStringArray(final TypedArray a, final int index, Function<String, String> stringMutator) {
|
||||
return parseStringArray(a, index, stringMutator);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
public String getString(final TypedArray a, final int index) {
|
||||
return parseString(a, index);
|
||||
public String getString(final TypedArray a, final int index, Function<String, String> stringMutator) {
|
||||
return parseString(a, index, stringMutator);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -95,9 +96,9 @@ public final class KeyStylesSet {
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
public String[] getStringArray(final TypedArray a, final int index) {
|
||||
public String[] getStringArray(final TypedArray a, final int index, Function<String, String> stringMutator) {
|
||||
if (a.hasValue(index)) {
|
||||
return parseStringArray(a, index);
|
||||
return parseStringArray(a, index, stringMutator);
|
||||
}
|
||||
final Object value = mStyleAttributes.get(index);
|
||||
if (value != null) {
|
||||
@ -105,21 +106,21 @@ public final class KeyStylesSet {
|
||||
return Arrays.copyOf(array, array.length);
|
||||
}
|
||||
final KeyStyle parentStyle = mStyles.get(mParentStyleName);
|
||||
return parentStyle.getStringArray(a, index);
|
||||
return parentStyle.getStringArray(a, index, stringMutator);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
public String getString(final TypedArray a, final int index) {
|
||||
public String getString(final TypedArray a, final int index, Function<String, String> stringMutator) {
|
||||
if (a.hasValue(index)) {
|
||||
return parseString(a, index);
|
||||
return parseString(a, index, stringMutator);
|
||||
}
|
||||
final Object value = mStyleAttributes.get(index);
|
||||
if (value != null) {
|
||||
return (String)value;
|
||||
}
|
||||
final KeyStyle parentStyle = mStyles.get(mParentStyleName);
|
||||
return parentStyle.getString(a, index);
|
||||
return parentStyle.getString(a, index, stringMutator);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -159,7 +160,7 @@ public final class KeyStylesSet {
|
||||
|
||||
private void readString(final TypedArray a, final int index) {
|
||||
if (a.hasValue(index)) {
|
||||
mStyleAttributes.put(index, parseString(a, index));
|
||||
mStyleAttributes.put(index, parseString(a, index, null));
|
||||
}
|
||||
}
|
||||
|
||||
@ -179,7 +180,7 @@ public final class KeyStylesSet {
|
||||
|
||||
private void readStringArray(final TypedArray a, final int index) {
|
||||
if (a.hasValue(index)) {
|
||||
mStyleAttributes.put(index, parseStringArray(a, index));
|
||||
mStyleAttributes.put(index, parseStringArray(a, index, null));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -512,7 +512,7 @@ public class KeyboardBuilder<KP extends KeyboardParams> {
|
||||
final TypedArray keyAttr = mResources.obtainAttributes(
|
||||
Xml.asAttributeSet(parser), R.styleable.Keyboard_Key);
|
||||
final KeyStyle keyStyle = mParams.mKeyStyles.getKeyStyle(keyAttr, parser);
|
||||
final String keySpec = keyStyle.getString(keyAttr, R.styleable.Keyboard_Key_keySpec);
|
||||
final String keySpec = keyStyle.getString(keyAttr, R.styleable.Keyboard_Key_keySpec, null);
|
||||
if (TextUtils.isEmpty(keySpec)) {
|
||||
throw new ParseException("Empty keySpec", parser);
|
||||
}
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,104 @@
|
||||
package org.futo.inputmethod.latin.settings
|
||||
|
||||
import android.content.Context
|
||||
import androidx.datastore.preferences.core.stringPreferencesKey
|
||||
import org.futo.inputmethod.keyboard.internal.MoreKeySpec
|
||||
import org.futo.inputmethod.latin.uix.SettingsKey
|
||||
import org.futo.inputmethod.latin.uix.getSettingBlocking
|
||||
|
||||
enum class LongPressKey {
|
||||
Numbers,
|
||||
LanguageKeys,
|
||||
Symbols,
|
||||
QuickActions,
|
||||
MiscLetters
|
||||
}
|
||||
|
||||
fun LongPressKey.name(context: Context): String {
|
||||
return when(this) {
|
||||
LongPressKey.Numbers -> "Numbers"
|
||||
LongPressKey.LanguageKeys -> "Language keys"
|
||||
LongPressKey.Symbols -> "Symbols"
|
||||
LongPressKey.QuickActions -> "Quick actions"
|
||||
LongPressKey.MiscLetters -> "Misc. letters from common languages"
|
||||
}
|
||||
}
|
||||
fun LongPressKey.description(context: Context): String {
|
||||
return when(this) {
|
||||
LongPressKey.Numbers -> "e.g. [1] on [q]"
|
||||
LongPressKey.LanguageKeys -> "e.g. [á] on [a] in Spanish"
|
||||
LongPressKey.Symbols -> "e.g. [@] on [a]"
|
||||
LongPressKey.QuickActions -> "e.g. [Copy] on [c]"
|
||||
LongPressKey.MiscLetters -> "e.g. [ß] on [s] in all Latin script languages"
|
||||
}
|
||||
}
|
||||
|
||||
private fun getKind(moreKey: String): LongPressKey? {
|
||||
val moreKeyStripped = moreKey.replace("!text/", "")
|
||||
|
||||
return if(moreKeyStripped.startsWith("morekeys_misc_")) {
|
||||
LongPressKey.MiscLetters
|
||||
} else if(moreKeyStripped.startsWith("actions_")) {
|
||||
LongPressKey.QuickActions
|
||||
} else if(moreKeyStripped.startsWith("qwertysyms_")) {
|
||||
LongPressKey.Symbols
|
||||
} else if(moreKeyStripped.startsWith("number_")) {
|
||||
LongPressKey.Numbers
|
||||
} else if(moreKeyStripped.startsWith("morekeys_")) {
|
||||
LongPressKey.LanguageKeys
|
||||
} else {
|
||||
null
|
||||
}
|
||||
}
|
||||
|
||||
val LongPressKeyLayoutSetting = SettingsKey(
|
||||
stringPreferencesKey("longPressKeyOrdering"),
|
||||
"${LongPressKey.Numbers.ordinal},${LongPressKey.LanguageKeys.ordinal},${LongPressKey.Symbols.ordinal},${LongPressKey.QuickActions.ordinal},${LongPressKey.MiscLetters.ordinal}"
|
||||
)
|
||||
|
||||
fun String.toLongPressKeyLayoutItems(): List<LongPressKey> {
|
||||
return this.split(",").mapNotNull {
|
||||
val id = it.toIntOrNull() ?: return@mapNotNull null
|
||||
|
||||
LongPressKey.entries[id]
|
||||
}
|
||||
}
|
||||
|
||||
fun List<LongPressKey>.toEncodedString(): String {
|
||||
return this.joinToString(separator = ",") {
|
||||
"${it.ordinal}"
|
||||
}
|
||||
}
|
||||
|
||||
class LongPressKeySettings(val context: Context) {
|
||||
private val currentSetting = context.getSettingBlocking(LongPressKeyLayoutSetting).toLongPressKeyLayoutItems()
|
||||
|
||||
fun reorderMoreKeys(moreKeys: String): String {
|
||||
val keys = MoreKeySpec.splitKeySpecs(moreKeys)?.toList() ?: listOf(moreKeys)
|
||||
|
||||
val finalKeys = mutableListOf<String>()
|
||||
|
||||
// Add non configurable keys first
|
||||
keys.forEach { key ->
|
||||
if(getKind(key) == null) {
|
||||
finalKeys.add(key)
|
||||
}
|
||||
}
|
||||
|
||||
// Add the necessary configurable keys in the correct order.
|
||||
// Key kinds not enabled are not added
|
||||
currentSetting.forEach { kind ->
|
||||
keys.forEach { key ->
|
||||
if(getKind(key) == kind) {
|
||||
finalKeys.add(key)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return finalKeys.joinToString(separator = ",")
|
||||
}
|
||||
|
||||
override operator fun equals(other: Any?): Boolean {
|
||||
return other is LongPressKeySettings && (other.currentSetting.joinToString(",") == currentSetting.joinToString(","))
|
||||
}
|
||||
}
|
@ -22,7 +22,7 @@ import androidx.compose.ui.viewinterop.AndroidView
|
||||
import org.futo.inputmethod.latin.R
|
||||
|
||||
@Composable
|
||||
fun AndroidTextInput() {
|
||||
fun AndroidTextInput(allowPredictions: Boolean = true) {
|
||||
val context = LocalContext.current
|
||||
val bgColor = MaterialTheme.colorScheme.background
|
||||
val fgColor = MaterialTheme.colorScheme.onBackground
|
||||
@ -30,9 +30,14 @@ fun AndroidTextInput() {
|
||||
if(!LocalInspectionMode.current) {
|
||||
val editText = remember {
|
||||
EditText(context).apply {
|
||||
inputType = EditorInfo.TYPE_CLASS_TEXT
|
||||
isSingleLine = false
|
||||
this.
|
||||
if(allowPredictions) {
|
||||
inputType = EditorInfo.TYPE_CLASS_TEXT
|
||||
isSingleLine = false
|
||||
} else {
|
||||
inputType = EditorInfo.TYPE_CLASS_TEXT or EditorInfo.TYPE_TEXT_FLAG_AUTO_COMPLETE
|
||||
isSingleLine = true
|
||||
}
|
||||
|
||||
|
||||
setHint(R.string.try_typing)
|
||||
setBackgroundColor(bgColor.toArgb())
|
||||
|
@ -327,7 +327,7 @@ class UixManager(private val latinIME: LatinIME) {
|
||||
persistentStates[action] = action.persistentState?.let { it(keyboardManagerForAction) }
|
||||
}
|
||||
|
||||
currWindowActionWindow = action.windowImpl?.let { it(keyboardManagerForAction, persistentStates[action]) }
|
||||
currWindowActionWindow = (action.windowImpl!!)(keyboardManagerForAction, persistentStates[action])
|
||||
|
||||
if(action.keepScreenAwake) {
|
||||
latinIME.window.window?.addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON)
|
||||
|
@ -465,11 +465,11 @@ fun SettingSliderSharedPrefsInt(
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun ScrollableList(content: @Composable () -> Unit) {
|
||||
fun ScrollableList(modifier: Modifier = Modifier, content: @Composable () -> Unit) {
|
||||
val scrollState = rememberScrollState()
|
||||
|
||||
Column(
|
||||
modifier = Modifier
|
||||
modifier = modifier
|
||||
.fillMaxSize()
|
||||
.verticalScroll(scrollState)
|
||||
) {
|
||||
|
@ -30,11 +30,15 @@ import kotlinx.coroutines.Job
|
||||
import kotlinx.coroutines.delay
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.runBlocking
|
||||
import org.futo.inputmethod.latin.uix.BasicThemeProvider
|
||||
import org.futo.inputmethod.latin.uix.DynamicThemeProvider
|
||||
import org.futo.inputmethod.latin.uix.DynamicThemeProviderOwner
|
||||
import org.futo.inputmethod.latin.uix.ImportResourceActivity
|
||||
import org.futo.inputmethod.latin.uix.THEME_KEY
|
||||
import org.futo.inputmethod.latin.uix.USE_SYSTEM_VOICE_INPUT
|
||||
import org.futo.inputmethod.latin.uix.deferGetSetting
|
||||
import org.futo.inputmethod.latin.uix.getSetting
|
||||
import org.futo.inputmethod.latin.uix.getSettingFlow
|
||||
import org.futo.inputmethod.latin.uix.theme.StatusBarColorSetter
|
||||
import org.futo.inputmethod.latin.uix.theme.ThemeOption
|
||||
import org.futo.inputmethod.latin.uix.theme.ThemeOptions
|
||||
@ -76,7 +80,7 @@ public const val IMPORT_GGUF_MODEL_REQUEST = 71067309
|
||||
public const val EXPORT_GGUF_MODEL_REQUEST = 80595439
|
||||
|
||||
|
||||
class SettingsActivity : ComponentActivity() {
|
||||
class SettingsActivity : ComponentActivity(), DynamicThemeProviderOwner {
|
||||
private val themeOption: MutableState<ThemeOption?> = mutableStateOf(null)
|
||||
|
||||
private val inputMethodEnabled = mutableStateOf(false)
|
||||
@ -181,6 +185,23 @@ class SettingsActivity : ComponentActivity() {
|
||||
checkForUpdateAndSaveToPreferences(applicationContext)
|
||||
}
|
||||
|
||||
lifecycleScope.launch {
|
||||
getSettingFlow(THEME_KEY).collect {
|
||||
val themeOptionFromSettings = ThemeOptions[it]
|
||||
val themeOption = when {
|
||||
themeOptionFromSettings == null -> VoiceInputTheme
|
||||
!themeOptionFromSettings.available(this@SettingsActivity) -> VoiceInputTheme
|
||||
else -> themeOptionFromSettings
|
||||
}
|
||||
|
||||
this@SettingsActivity.themeOption.value = themeOption
|
||||
this@SettingsActivity.themeProvider = BasicThemeProvider(
|
||||
context = this@SettingsActivity,
|
||||
overrideColorScheme = themeOption.obtainColors(this@SettingsActivity)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
deferGetSetting(THEME_KEY) {
|
||||
val themeOptionFromSettings = ThemeOptions[it]
|
||||
val themeOption = when {
|
||||
@ -252,4 +273,10 @@ class SettingsActivity : ComponentActivity() {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Provides theme for keyboard preview
|
||||
private var themeProvider: BasicThemeProvider? = null
|
||||
override fun getDrawableProvider(): DynamicThemeProvider {
|
||||
return themeProvider!!
|
||||
}
|
||||
}
|
@ -24,9 +24,9 @@ import org.futo.inputmethod.latin.uix.settings.pages.PaymentScreen
|
||||
import org.futo.inputmethod.latin.uix.settings.pages.PaymentThankYouScreen
|
||||
import org.futo.inputmethod.latin.uix.settings.pages.PredictiveTextScreen
|
||||
import org.futo.inputmethod.latin.uix.settings.pages.ThemeScreen
|
||||
import org.futo.inputmethod.latin.uix.settings.pages.TypingScreen
|
||||
import org.futo.inputmethod.latin.uix.settings.pages.VoiceInputScreen
|
||||
import org.futo.inputmethod.latin.uix.settings.pages.addModelManagerNavigation
|
||||
import org.futo.inputmethod.latin.uix.settings.pages.addTypingNavigation
|
||||
import org.futo.inputmethod.latin.uix.urlDecode
|
||||
import org.futo.inputmethod.latin.uix.urlEncode
|
||||
|
||||
@ -54,7 +54,7 @@ fun SettingsNavigator(
|
||||
composable("addLanguage") { AddLanguageScreen(navController) }
|
||||
composable("predictiveText") { PredictiveTextScreen(navController) }
|
||||
composable("advancedparams") { AdvancedParametersScreen(navController) }
|
||||
composable("typing") { TypingScreen(navController) }
|
||||
addTypingNavigation(navController)
|
||||
composable("voiceInput") { VoiceInputScreen(navController) }
|
||||
composable("themes") { ThemeScreen(navController) }
|
||||
composable("help") { HelpScreen(navController) }
|
||||
|
@ -64,32 +64,43 @@ fun HomeScreen(navController: NavHostController = rememberNavController()) {
|
||||
)
|
||||
|
||||
NavigationItem(
|
||||
title = "Predictive Text",
|
||||
title = "Keyboard & Typing",
|
||||
style = NavigationItemStyle.HomeSecondary,
|
||||
navigate = { navController.navigate("predictiveText") },
|
||||
icon = painterResource(id = R.drawable.shift)
|
||||
navigate = { navController.navigate("typing") },
|
||||
icon = painterResource(id = R.drawable.keyboard)
|
||||
)
|
||||
|
||||
NavigationItem(
|
||||
title = "Typing Preferences",
|
||||
style = NavigationItemStyle.HomeSecondary,
|
||||
navigate = { navController.navigate("typing") },
|
||||
icon = painterResource(id = R.drawable.delete)
|
||||
title = "Text Prediction",
|
||||
style = NavigationItemStyle.HomeTertiary,
|
||||
navigate = { navController.navigate("predictiveText") },
|
||||
icon = painterResource(id = R.drawable.text_prediction)
|
||||
)
|
||||
|
||||
NavigationItem(
|
||||
title = "Voice Input",
|
||||
style = NavigationItemStyle.HomeSecondary,
|
||||
style = NavigationItemStyle.HomePrimary,
|
||||
subtitle = if(useDataStoreValueBlocking(USE_SYSTEM_VOICE_INPUT)) { "Built-in voice input is disabled!" } else { null },
|
||||
navigate = { navController.navigate("voiceInput") },
|
||||
icon = painterResource(id = R.drawable.mic_fill)
|
||||
)
|
||||
|
||||
NavigationItem(
|
||||
title = stringResource(R.string.edit_personal_dictionary),
|
||||
style = NavigationItemStyle.HomeSecondary,
|
||||
icon = painterResource(id = R.drawable.book),
|
||||
navigate = {
|
||||
val intent = Intent("android.settings.USER_DICTIONARY_SETTINGS")
|
||||
intent.flags = Intent.FLAG_ACTIVITY_NEW_TASK
|
||||
context.startActivity(intent)
|
||||
}
|
||||
)
|
||||
|
||||
NavigationItem(
|
||||
title = "Theme",
|
||||
style = NavigationItemStyle.HomeTertiary,
|
||||
navigate = { navController.navigate("themes") },
|
||||
icon = painterResource(id = R.drawable.eye)
|
||||
icon = painterResource(id = R.drawable.themes)
|
||||
)
|
||||
|
||||
if(!isPaid) {
|
||||
@ -103,7 +114,7 @@ fun HomeScreen(navController: NavHostController = rememberNavController()) {
|
||||
|
||||
NavigationItem(
|
||||
title = "Help & Feedback",
|
||||
style = NavigationItemStyle.HomePrimary,
|
||||
style = NavigationItemStyle.HomeSecondary,
|
||||
navigate = { navController.navigate("help") },
|
||||
icon = painterResource(id = R.drawable.help_circle)
|
||||
)
|
||||
@ -111,7 +122,7 @@ fun HomeScreen(navController: NavHostController = rememberNavController()) {
|
||||
if(isDeveloper || LocalInspectionMode.current) {
|
||||
NavigationItem(
|
||||
title = "Developer Settings",
|
||||
style = NavigationItemStyle.HomeSecondary,
|
||||
style = NavigationItemStyle.HomeTertiary,
|
||||
navigate = { navController.navigate("developer") },
|
||||
icon = painterResource(id = R.drawable.code)
|
||||
)
|
||||
|
@ -1,46 +1,436 @@
|
||||
package org.futo.inputmethod.latin.uix.settings.pages
|
||||
|
||||
import android.content.Context
|
||||
import android.preference.PreferenceManager
|
||||
import androidx.compose.foundation.ExperimentalFoundationApi
|
||||
import androidx.compose.foundation.gestures.detectDragGestures
|
||||
import androidx.compose.foundation.layout.Box
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.width
|
||||
import androidx.compose.foundation.lazy.LazyItemScope
|
||||
import androidx.compose.foundation.lazy.LazyListScope
|
||||
import androidx.compose.foundation.lazy.items
|
||||
import androidx.compose.foundation.lazy.itemsIndexed
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.filled.Add
|
||||
import androidx.compose.material.icons.filled.Clear
|
||||
import androidx.compose.material.icons.filled.Menu
|
||||
import androidx.compose.material3.Button
|
||||
import androidx.compose.material3.Icon
|
||||
import androidx.compose.material3.IconButton
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.LaunchedEffect
|
||||
import androidx.compose.runtime.mutableFloatStateOf
|
||||
import androidx.compose.runtime.mutableIntStateOf
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.graphics.graphicsLayer
|
||||
import androidx.compose.ui.input.pointer.pointerInput
|
||||
import androidx.compose.ui.layout.onSizeChanged
|
||||
import androidx.compose.ui.platform.LocalContext
|
||||
import androidx.compose.ui.res.booleanResource
|
||||
import androidx.compose.ui.res.painterResource
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.text.style.TextAlign
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.compose.ui.zIndex
|
||||
import androidx.core.content.edit
|
||||
import androidx.datastore.preferences.core.intPreferencesKey
|
||||
import androidx.navigation.NavGraphBuilder
|
||||
import androidx.navigation.NavHostController
|
||||
import androidx.navigation.compose.composable
|
||||
import androidx.navigation.compose.rememberNavController
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.withContext
|
||||
import org.futo.inputmethod.latin.R
|
||||
import org.futo.inputmethod.latin.settings.LongPressKey
|
||||
import org.futo.inputmethod.latin.settings.LongPressKeyLayoutSetting
|
||||
import org.futo.inputmethod.latin.settings.Settings
|
||||
import org.futo.inputmethod.latin.settings.Settings.PREF_VIBRATION_DURATION_SETTINGS
|
||||
import org.futo.inputmethod.latin.settings.description
|
||||
import org.futo.inputmethod.latin.settings.name
|
||||
import org.futo.inputmethod.latin.settings.toEncodedString
|
||||
import org.futo.inputmethod.latin.settings.toLongPressKeyLayoutItems
|
||||
import org.futo.inputmethod.latin.uix.AndroidTextInput
|
||||
import org.futo.inputmethod.latin.uix.KeyHintsSetting
|
||||
import org.futo.inputmethod.latin.uix.KeyboardBottomOffsetSetting
|
||||
import org.futo.inputmethod.latin.uix.KeyboardHeightMultiplierSetting
|
||||
import org.futo.inputmethod.latin.uix.SHOW_EMOJI_SUGGESTIONS
|
||||
import org.futo.inputmethod.latin.uix.SettingsKey
|
||||
import org.futo.inputmethod.latin.uix.actions.AllActions
|
||||
import org.futo.inputmethod.latin.uix.actions.ClipboardHistoryAction
|
||||
import org.futo.inputmethod.latin.uix.actions.ClipboardHistoryEnabled
|
||||
import org.futo.inputmethod.latin.uix.actions.CopyAction
|
||||
import org.futo.inputmethod.latin.uix.actions.CutAction
|
||||
import org.futo.inputmethod.latin.uix.actions.EmojiAction
|
||||
import org.futo.inputmethod.latin.uix.actions.PasteAction
|
||||
import org.futo.inputmethod.latin.uix.actions.RedoAction
|
||||
import org.futo.inputmethod.latin.uix.actions.SelectAllAction
|
||||
import org.futo.inputmethod.latin.uix.actions.SwitchLanguageAction
|
||||
import org.futo.inputmethod.latin.uix.actions.TextEditAction
|
||||
import org.futo.inputmethod.latin.uix.actions.UndoAction
|
||||
import org.futo.inputmethod.latin.uix.actions.VoiceInputAction
|
||||
import org.futo.inputmethod.latin.uix.getSettingBlocking
|
||||
import org.futo.inputmethod.latin.uix.settings.DataStoreItem
|
||||
import org.futo.inputmethod.latin.uix.settings.DropDownPicker
|
||||
import org.futo.inputmethod.latin.uix.settings.NavigationItem
|
||||
import org.futo.inputmethod.latin.uix.settings.NavigationItemStyle
|
||||
import org.futo.inputmethod.latin.uix.settings.ScreenTitle
|
||||
import org.futo.inputmethod.latin.uix.settings.ScrollableList
|
||||
import org.futo.inputmethod.latin.uix.settings.SettingItem
|
||||
import org.futo.inputmethod.latin.uix.settings.SettingListLazy
|
||||
import org.futo.inputmethod.latin.uix.settings.SettingSlider
|
||||
import org.futo.inputmethod.latin.uix.settings.SettingSliderSharedPrefsInt
|
||||
import org.futo.inputmethod.latin.uix.settings.SettingToggleDataStore
|
||||
import org.futo.inputmethod.latin.uix.settings.SettingToggleSharedPrefs
|
||||
import org.futo.inputmethod.latin.uix.settings.useDataStore
|
||||
import org.futo.inputmethod.latin.uix.settings.useSharedPrefsBool
|
||||
import org.futo.inputmethod.latin.uix.settings.useSharedPrefsInt
|
||||
import kotlin.math.absoluteValue
|
||||
import kotlin.math.roundToInt
|
||||
import kotlin.math.sign
|
||||
|
||||
val vibrationDurationSetting = SettingsKey(
|
||||
intPreferencesKey("vibration_duration"),
|
||||
-1
|
||||
)
|
||||
|
||||
@Preview
|
||||
fun NavGraphBuilder.addTypingNavigation(
|
||||
navController: NavHostController
|
||||
) {
|
||||
composable("typing") { TypingScreen(navController) }
|
||||
composable("resize") { ResizeScreen(navController) }
|
||||
composable("longPress") { LongPressScreen(navController) }
|
||||
composable("actionKey") { ActionKeyScreen(navController) }
|
||||
}
|
||||
|
||||
@Preview(showBackground = true)
|
||||
@Composable
|
||||
fun ResizeScreen(navController: NavHostController = rememberNavController()) {
|
||||
val context = LocalContext.current
|
||||
Box {
|
||||
ScrollableList {
|
||||
ScreenTitle("Resize Keyboard", showBack = true, navController)
|
||||
|
||||
SettingSlider(
|
||||
title = "Keyboard Height",
|
||||
setting = KeyboardHeightMultiplierSetting,
|
||||
range = 0.33f..1.75f, transform = { it },
|
||||
indicator = { "${(it * 100.0f).roundToInt()}%" },
|
||||
steps = 16
|
||||
)
|
||||
SettingSlider(
|
||||
title = "Keyboard Offset",
|
||||
setting = KeyboardBottomOffsetSetting,
|
||||
range = 0.0f..50.0f,
|
||||
hardRange = 0.0f..250.0f,
|
||||
transform = { it },
|
||||
indicator = { "${String.format("%.1f", it)} dp" },
|
||||
steps = 9
|
||||
)
|
||||
|
||||
AndroidTextInput(allowPredictions = false)
|
||||
}
|
||||
|
||||
/*
|
||||
AndroidView(factory = {
|
||||
val ctx = ContextThemeWrapper(context, R.style.KeyboardTheme_LXX_Light)
|
||||
|
||||
val inputView = LayoutInflater.from(ctx).inflate(
|
||||
R.layout.input_view, null, false
|
||||
) as InputView
|
||||
|
||||
val settingsValues = Settings.getInstance().current
|
||||
|
||||
val builder = KeyboardLayoutSet.Builder(ctx, null)
|
||||
val res: Resources = ctx.resources
|
||||
|
||||
val currentSubtype = RichInputMethodSubtype(Subtypes.getActiveSubtype(ctx))
|
||||
|
||||
val keyboardWidth = ResourceUtils.getDefaultKeyboardWidth(res)
|
||||
val keyboardHeight = ResourceUtils.getKeyboardHeight(res, settingsValues)
|
||||
builder.setKeyboardGeometry(keyboardWidth, keyboardHeight)
|
||||
builder.setSubtype(currentSubtype)
|
||||
builder.setVoiceInputKeyEnabled(settingsValues.mShowsVoiceInputKey)
|
||||
builder.setBottomActionKey(settingsValues.mShowsActionKey, settingsValues.mActionKeyId)
|
||||
builder.setSplitLayoutEnabledByUser(
|
||||
ProductionFlags.IS_SPLIT_KEYBOARD_SUPPORTED
|
||||
&& settingsValues.mIsSplitKeyboardEnabled
|
||||
)
|
||||
builder.setNumberRow(settingsValues.mIsNumberRowEnabled)
|
||||
|
||||
|
||||
val keyboardLayoutSet = builder.build()
|
||||
|
||||
val keyboardView = inputView.findViewById<View>(R.id.keyboard_view) as MainKeyboardView
|
||||
|
||||
keyboardView.setKeyboard(keyboardLayoutSet.getKeyboard(KeyboardId.ELEMENT_ALPHABET))
|
||||
/*
|
||||
mMainKeyboardFrame = mCurrentInputView!!.findViewById<View>(R.id.main_keyboard_frame)
|
||||
mKeyboardView =
|
||||
mCurrentInputView!!.findViewById<View>(R.id.keyboard_view) as MainKeyboardView
|
||||
*/
|
||||
inputView
|
||||
}, modifier = Modifier.align(Alignment.BottomCenter))
|
||||
*/
|
||||
}
|
||||
}
|
||||
|
||||
@OptIn(ExperimentalFoundationApi::class)
|
||||
@Composable
|
||||
private fun LazyItemScope.DraggableSettingItem(idx: Int, item: LongPressKey, moveItem: (LongPressKey, Int) -> Unit, disable: (LongPressKey) -> Unit, dragIcon: @Composable () -> Unit) {
|
||||
val context = LocalContext.current
|
||||
val dragging = remember { mutableStateOf(false) }
|
||||
val offset = remember { mutableFloatStateOf(0.0f) }
|
||||
val height = remember { mutableIntStateOf(1) }
|
||||
|
||||
SettingItem(
|
||||
title = "${idx+1}. " + item.name(context),
|
||||
subtitle = item.description(context),
|
||||
icon = dragIcon,
|
||||
modifier = Modifier
|
||||
.onSizeChanged { size -> height.intValue = size.height }
|
||||
.pointerInput(Unit) {
|
||||
detectDragGestures(
|
||||
onDragStart = {
|
||||
dragging.value = true
|
||||
offset.floatValue = 0.0f
|
||||
},
|
||||
onDragEnd = {
|
||||
dragging.value = false
|
||||
offset.floatValue = 0.0f
|
||||
},
|
||||
onDragCancel = {
|
||||
dragging.value = false
|
||||
offset.floatValue = 0.0f
|
||||
},
|
||||
onDrag = { change, dragAmount ->
|
||||
offset.floatValue += dragAmount.y
|
||||
if (offset.floatValue.absoluteValue > height.intValue) {
|
||||
val direction = offset.floatValue.sign.toInt()
|
||||
moveItem(
|
||||
item,
|
||||
direction
|
||||
)
|
||||
offset.floatValue -= height.intValue * direction
|
||||
}
|
||||
|
||||
}
|
||||
)
|
||||
}
|
||||
.let { modifier ->
|
||||
if (!dragging.value) {
|
||||
modifier.animateItemPlacement()
|
||||
} else {
|
||||
modifier
|
||||
.zIndex(10.0f)
|
||||
.graphicsLayer {
|
||||
clip = false
|
||||
translationX = 0.0f
|
||||
translationY = offset.floatValue
|
||||
}
|
||||
}
|
||||
}
|
||||
) {
|
||||
IconButton(onClick = { disable(item) }) {
|
||||
Icon(Icons.Default.Clear, contentDescription = "Remove")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@OptIn(ExperimentalFoundationApi::class)
|
||||
fun LazyListScope.longPressKeyLayoutEditor(context: Context, setting: DataStoreItem<String>) {
|
||||
item {
|
||||
ScreenTitle(title = "Layout of long-press keys")
|
||||
}
|
||||
|
||||
item {
|
||||
Button(onClick = {
|
||||
setting.setValue(LongPressKeyLayoutSetting.default)
|
||||
}) {
|
||||
Text("Reset to default")
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
val dragIcon: @Composable () -> Unit = {
|
||||
Icon(Icons.Default.Menu, contentDescription = null, tint = MaterialTheme.colorScheme.onBackground.copy(alpha = 0.75f))
|
||||
}
|
||||
|
||||
|
||||
val items = setting.value.toLongPressKeyLayoutItems()
|
||||
|
||||
|
||||
val moveItem: (item: LongPressKey, direction: Int) -> Unit = { item, direction ->
|
||||
val oldItems = context.getSettingBlocking(LongPressKeyLayoutSetting).toLongPressKeyLayoutItems()
|
||||
val oldIdx = oldItems.indexOf(item)
|
||||
|
||||
val insertIdx = (oldIdx + direction).coerceAtLeast(0).coerceAtMost(oldItems.size - 1)
|
||||
|
||||
val newItems = oldItems.filter { it != item }.toMutableList().apply {
|
||||
add(insertIdx, item)
|
||||
}.toEncodedString()
|
||||
|
||||
setting.setValue(newItems)
|
||||
}
|
||||
|
||||
val disable: (item : LongPressKey) -> Unit = { item ->
|
||||
val oldItems = context.getSettingBlocking(LongPressKeyLayoutSetting).toLongPressKeyLayoutItems()
|
||||
|
||||
val newItems = oldItems.filter { it != item }.toEncodedString()
|
||||
|
||||
setting.setValue(newItems)
|
||||
|
||||
}
|
||||
|
||||
val enable: (item : LongPressKey) -> Unit = { item ->
|
||||
val oldItems = context.getSettingBlocking(LongPressKeyLayoutSetting).toLongPressKeyLayoutItems()
|
||||
|
||||
val newItems = oldItems.filter { it != item }.toMutableList().apply {
|
||||
add(item)
|
||||
}.toEncodedString()
|
||||
|
||||
setting.setValue(newItems)
|
||||
}
|
||||
|
||||
item {
|
||||
Text("Active", modifier = Modifier.fillMaxWidth(), textAlign = TextAlign.Center)
|
||||
}
|
||||
itemsIndexed(items, key = { i, v -> v.ordinal }) { i, v ->
|
||||
DraggableSettingItem(idx = i, item = v, moveItem = moveItem, disable = disable, dragIcon = dragIcon)
|
||||
}
|
||||
|
||||
item {
|
||||
Text("Inactive", modifier = Modifier.fillMaxWidth(), textAlign = TextAlign.Center)
|
||||
}
|
||||
items(LongPressKey.entries.filter { !items.contains(it) }, key = { it.ordinal }) {
|
||||
SettingItem(
|
||||
title = it.name(context),
|
||||
subtitle = it.description(context),
|
||||
modifier = Modifier.animateItemPlacement()
|
||||
) {
|
||||
IconButton(onClick = { enable(it) }) {
|
||||
Icon(Icons.Default.Add, contentDescription = "Add")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Preview(showBackground = true)
|
||||
@Composable
|
||||
fun LongPressScreen(navController: NavHostController = rememberNavController()) {
|
||||
val context = LocalContext.current
|
||||
val setting = useDataStore(LongPressKeyLayoutSetting, blocking = true)
|
||||
SettingListLazy {
|
||||
item {
|
||||
ScreenTitle("Long-Press Keys", showBack = true, navController)
|
||||
}
|
||||
|
||||
item {
|
||||
SettingToggleDataStore(
|
||||
title = "Show hints",
|
||||
subtitle = "Display a small hint on each key, showing the primary long-press key",
|
||||
setting = KeyHintsSetting
|
||||
)
|
||||
}
|
||||
|
||||
/*
|
||||
SettingToggleDataStore(
|
||||
title = "Spacebar language switcher",
|
||||
subtitle = "Show the language switching menu when long-pressing the space",
|
||||
setting = KeyHintsSetting
|
||||
)*/
|
||||
|
||||
longPressKeyLayoutEditor(
|
||||
context = context,
|
||||
setting = setting,
|
||||
)
|
||||
|
||||
item {
|
||||
SettingSliderSharedPrefsInt(
|
||||
title = "Long Press Duration",
|
||||
subtitle = "How long a key needs to be pressed to be considered a long-press",
|
||||
key = Settings.PREF_KEY_LONGPRESS_TIMEOUT,
|
||||
default = 300,
|
||||
range = 100.0f..700.0f,
|
||||
hardRange = 25.0f..1200.0f,
|
||||
transform = { it.roundToInt() },
|
||||
indicator = { "$it ms" },
|
||||
steps = 23
|
||||
)
|
||||
}
|
||||
|
||||
/*
|
||||
SettingRadio(
|
||||
title = "Spacebar behavior",
|
||||
options = listOf(0, 1, 2),
|
||||
optionNames = listOf(
|
||||
"Swiping moves cursor, long-pressing switches language",
|
||||
"Swiping changes language, long-pressing moves cursor",
|
||||
"Swiping and long-pressing only moves cursor"
|
||||
),
|
||||
setting =
|
||||
)*/
|
||||
}
|
||||
}
|
||||
|
||||
@Preview(showBackground = true)
|
||||
@Composable
|
||||
fun ActionKeyScreen(navController: NavHostController = rememberNavController()) {
|
||||
val context = LocalContext.current
|
||||
val isActionKeyActive = useSharedPrefsBool(key = Settings.PREF_SHOW_ACTION_KEY, default = true)
|
||||
val emojiKey = useSharedPrefsInt(key = Settings.PREF_ACTION_KEY_ID, default = 0)
|
||||
|
||||
val permittedOptions = listOf(
|
||||
EmojiAction,
|
||||
SwitchLanguageAction,
|
||||
VoiceInputAction,
|
||||
ClipboardHistoryAction,
|
||||
TextEditAction,
|
||||
UndoAction,
|
||||
RedoAction,
|
||||
CutAction,
|
||||
CopyAction,
|
||||
PasteAction,
|
||||
SelectAllAction,
|
||||
)
|
||||
|
||||
ScrollableList {
|
||||
ScreenTitle("Action Key", showBack = true, navController)
|
||||
|
||||
|
||||
SettingToggleSharedPrefs(
|
||||
title = "Action key enabled",
|
||||
subtitle = "Show the action key on the bottom row",
|
||||
key = Settings.PREF_SHOW_ACTION_KEY,
|
||||
default = true
|
||||
)
|
||||
|
||||
if(isActionKeyActive.value) {
|
||||
SettingItem(title = "Action key") {
|
||||
DropDownPicker(
|
||||
label = "",
|
||||
options = permittedOptions,
|
||||
selection = AllActions[emojiKey.value],
|
||||
onSet = {
|
||||
emojiKey.setValue(AllActions.indexOf(it))
|
||||
},
|
||||
getDisplayName = {
|
||||
context.getString(it.name)
|
||||
},
|
||||
modifier = Modifier.width(180.dp)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@Preview(showBackground = true)
|
||||
@Composable
|
||||
fun TypingScreen(navController: NavHostController = rememberNavController()) {
|
||||
val context = LocalContext.current
|
||||
@ -56,71 +446,103 @@ fun TypingScreen(navController: NavHostController = rememberNavController()) {
|
||||
}
|
||||
|
||||
ScrollableList {
|
||||
ScreenTitle("Typing Preferences", showBack = true, navController)
|
||||
ScreenTitle("Keyboard", showBack = true, navController)
|
||||
|
||||
|
||||
NavigationItem(
|
||||
title = "Resize Keyboard",
|
||||
subtitle = "Change the height and offset of the keyboard",
|
||||
style = NavigationItemStyle.Misc,
|
||||
navigate = { navController.navigate("resize") },
|
||||
icon = painterResource(id = R.drawable.maximize)
|
||||
)
|
||||
|
||||
SettingToggleSharedPrefs(
|
||||
title = "Show Number Row",
|
||||
subtitle = "When active, the number row is shown on top of the keyboard at all times",
|
||||
key = Settings.PREF_ENABLE_NUMBER_ROW,
|
||||
default = false,
|
||||
icon = { Text("123", style = TextBodyRegularMlStyle, color = MaterialTheme.colorScheme.onBackground.copy(alpha = 0.75f)) }
|
||||
)
|
||||
|
||||
NavigationItem(
|
||||
title = "Long-Press Letters & Symbols",
|
||||
subtitle = "Configure long-press duration and how to order letters/symbols.",
|
||||
style = NavigationItemStyle.Misc,
|
||||
navigate = { navController.navigate("longPress") },
|
||||
icon = painterResource(id = R.drawable.arrow_up)
|
||||
)
|
||||
|
||||
NavigationItem(
|
||||
title = "Action Key",
|
||||
subtitle = "Change the action key into an emoji key, language switch key, or disable it altogether.",
|
||||
style = NavigationItemStyle.Misc,
|
||||
navigate = { navController.navigate("actionKey") },
|
||||
icon = painterResource(id = R.drawable.smile)
|
||||
)
|
||||
|
||||
NavigationItem(
|
||||
title = "Additional Layouts",
|
||||
subtitle = "Configure additional layouts in the languages screen",
|
||||
style = NavigationItemStyle.Misc,
|
||||
navigate = { navController.navigate("languages") },
|
||||
icon = painterResource(id = R.drawable.keyboard)
|
||||
)
|
||||
|
||||
ScreenTitle(title = "Typing preferences")
|
||||
|
||||
SettingToggleSharedPrefs(
|
||||
title = "Swipe Typing (alpha)",
|
||||
subtitle = "Allow swiping from key to key to write words.",
|
||||
key = Settings.PREF_GESTURE_INPUT,
|
||||
default = true,
|
||||
icon = {
|
||||
Icon(painterResource(id = R.drawable.swipe_icon), contentDescription = null,
|
||||
tint = MaterialTheme.colorScheme.onBackground.copy(alpha = 0.75f))
|
||||
}
|
||||
)
|
||||
|
||||
SettingToggleDataStore(
|
||||
title = "Emoji Suggestions",
|
||||
subtitle = "Suggest emojis while you're typing",
|
||||
setting = SHOW_EMOJI_SUGGESTIONS
|
||||
setting = SHOW_EMOJI_SUGGESTIONS,
|
||||
icon = {
|
||||
Icon(painterResource(id = R.drawable.smile), contentDescription = null,
|
||||
tint = MaterialTheme.colorScheme.onBackground.copy(alpha = 0.75f))
|
||||
}
|
||||
)
|
||||
|
||||
SettingToggleSharedPrefs(
|
||||
title = "Swipe typing",
|
||||
key = Settings.PREF_GESTURE_INPUT,
|
||||
default = true
|
||||
title = stringResource(R.string.auto_correction),
|
||||
subtitle = stringResource(R.string.auto_correction_summary),
|
||||
key = Settings.PREF_AUTO_CORRECTION,
|
||||
default = true,
|
||||
icon = {
|
||||
Icon(painterResource(id = R.drawable.icon_spellcheck), contentDescription = null,
|
||||
tint = MaterialTheme.colorScheme.onBackground.copy(alpha = 0.75f))
|
||||
}
|
||||
)
|
||||
|
||||
SettingToggleSharedPrefs(
|
||||
title = "Number row",
|
||||
key = Settings.PREF_ENABLE_NUMBER_ROW,
|
||||
default = false
|
||||
)
|
||||
|
||||
SettingToggleDataStore(
|
||||
title = "Clipboard History",
|
||||
setting = ClipboardHistoryEnabled
|
||||
)
|
||||
|
||||
SettingToggleSharedPrefs(
|
||||
title = "Action key enabled",
|
||||
subtitle = "Show the action key on the bottom row",
|
||||
key = Settings.PREF_SHOW_ACTION_KEY,
|
||||
default = true
|
||||
)
|
||||
|
||||
val emojiKey = useSharedPrefsInt(key = Settings.PREF_ACTION_KEY_ID, default = 0)
|
||||
SettingItem(title = "Action key") {
|
||||
DropDownPicker(
|
||||
label = "",
|
||||
options = AllActions,
|
||||
selection = AllActions[emojiKey.value],
|
||||
onSet = {
|
||||
emojiKey.setValue(AllActions.indexOf(it))
|
||||
},
|
||||
getDisplayName = {
|
||||
context.getString(it.name)
|
||||
},
|
||||
modifier = Modifier.width(180.dp)
|
||||
)
|
||||
}
|
||||
|
||||
SettingToggleSharedPrefs(
|
||||
title = stringResource(R.string.auto_cap),
|
||||
subtitle = stringResource(R.string.auto_cap_summary),
|
||||
key = Settings.PREF_AUTO_CAP,
|
||||
default = true
|
||||
default = true,
|
||||
icon = {
|
||||
Text("Aa", style = TextBodyRegularMlStyle, color = MaterialTheme.colorScheme.onBackground.copy(alpha = 0.75f))
|
||||
}
|
||||
)
|
||||
|
||||
SettingToggleSharedPrefs(
|
||||
title = stringResource(R.string.use_double_space_period),
|
||||
subtitle = stringResource(R.string.use_double_space_period_summary),
|
||||
key = Settings.PREF_KEY_USE_DOUBLE_SPACE_PERIOD,
|
||||
default = true
|
||||
)
|
||||
SettingToggleSharedPrefs(
|
||||
title = stringResource(R.string.vibrate_on_keypress),
|
||||
key = Settings.PREF_VIBRATE_ON,
|
||||
default = booleanResource(R.bool.config_default_vibration_enabled)
|
||||
default = true,
|
||||
icon = {
|
||||
Text(".", style = TextBodyRegularMlStyle, color = MaterialTheme.colorScheme.onBackground.copy(alpha = 0.75f))
|
||||
}
|
||||
)
|
||||
|
||||
SettingToggleSharedPrefs(
|
||||
title = stringResource(R.string.sound_on_keypress),
|
||||
key = Settings.PREF_SOUND_ON,
|
||||
@ -132,6 +554,12 @@ fun TypingScreen(navController: NavHostController = rememberNavController()) {
|
||||
default = booleanResource(R.bool.config_default_key_preview_popup)
|
||||
)
|
||||
|
||||
SettingToggleSharedPrefs(
|
||||
title = stringResource(R.string.vibrate_on_keypress),
|
||||
key = Settings.PREF_VIBRATE_ON,
|
||||
default = booleanResource(R.bool.config_default_vibration_enabled)
|
||||
)
|
||||
|
||||
SettingSlider(
|
||||
title = "Vibration",
|
||||
setting = vibrationDurationSetting,
|
||||
@ -147,15 +575,10 @@ fun TypingScreen(navController: NavHostController = rememberNavController()) {
|
||||
}
|
||||
)
|
||||
|
||||
SettingSliderSharedPrefsInt(
|
||||
title = "Long Press Duration",
|
||||
key = Settings.PREF_KEY_LONGPRESS_TIMEOUT,
|
||||
default = 300,
|
||||
range = 100.0f .. 700.0f,
|
||||
hardRange = 25.0f .. 1200.0f,
|
||||
transform = { it.roundToInt() },
|
||||
indicator = { "$it ms" },
|
||||
steps = 23
|
||||
SettingToggleDataStore(
|
||||
title = "Clipboard History",
|
||||
setting = ClipboardHistoryEnabled
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -282,39 +282,6 @@ fun ThemePicker(onSelected: (ThemeOption) -> Unit) {
|
||||
)
|
||||
}
|
||||
}
|
||||
item(span = { GridItemSpan(maxCurrentLineSpan) }) {
|
||||
CompositionLocalProvider(LocalLayoutDirection provides originalDirection) {
|
||||
SettingToggleDataStore(
|
||||
title = "Show symbol hints",
|
||||
setting = KeyHintsSetting
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
item(span = { GridItemSpan(maxCurrentLineSpan) }) {
|
||||
CompositionLocalProvider(LocalLayoutDirection provides originalDirection) {
|
||||
SettingSlider(
|
||||
title = "Keyboard Height",
|
||||
setting = KeyboardHeightMultiplierSetting,
|
||||
range = 0.33f..1.75f, transform = { it },
|
||||
indicator = { "${(it * 100.0f).roundToInt()}%" },
|
||||
steps = 16
|
||||
)
|
||||
}
|
||||
}
|
||||
item(span = { GridItemSpan(maxCurrentLineSpan) }) {
|
||||
CompositionLocalProvider(LocalLayoutDirection provides originalDirection) {
|
||||
SettingSlider(
|
||||
title = "Keyboard Offset",
|
||||
setting = KeyboardBottomOffsetSetting,
|
||||
range = 0.0f..50.0f,
|
||||
hardRange = 0.0f..250.0f,
|
||||
transform = { it },
|
||||
indicator = { "${String.format("%.1f", it)} dp" },
|
||||
steps = 9
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -136,6 +136,7 @@ val dismissedMigrateUpdateNotice = SettingsKey(
|
||||
@Composable
|
||||
@Preview
|
||||
fun ConditionalMigrateUpdateNotice() {
|
||||
if(LocalInspectionMode.current) { return }
|
||||
val context = LocalContext.current
|
||||
val value = useDataStore(dismissedMigrateUpdateNotice, blocking = true)
|
||||
if(!value.value) {
|
||||
|
@ -1,28 +1,84 @@
|
||||
{
|
||||
"locale": "DEFAULT",
|
||||
"morekeys": {
|
||||
"a": [],
|
||||
"q": [],
|
||||
"w": [],
|
||||
"e": [],
|
||||
"i": [],
|
||||
"o": [],
|
||||
"u": [],
|
||||
"s": [],
|
||||
"n": [],
|
||||
"c": [],
|
||||
"y": [],
|
||||
"d": [],
|
||||
"r": [],
|
||||
"t": [],
|
||||
"z": [],
|
||||
"k": [],
|
||||
"l": [],
|
||||
"y": [],
|
||||
"u": [],
|
||||
"i": [],
|
||||
"o": [],
|
||||
"p": [],
|
||||
"a": [],
|
||||
"s": [],
|
||||
"d": [],
|
||||
"f": [],
|
||||
"g": [],
|
||||
"v": [],
|
||||
"h": [],
|
||||
"j": [],
|
||||
"w": [],
|
||||
"q": [],
|
||||
"k": [],
|
||||
"l": [],
|
||||
"z": [],
|
||||
"x": [],
|
||||
"c": [],
|
||||
"v": [],
|
||||
"b": [],
|
||||
"n": [],
|
||||
"m": [],
|
||||
|
||||
"misc_a": [
|
||||
"à",
|
||||
"á",
|
||||
"â",
|
||||
"ä",
|
||||
"æ",
|
||||
"ã",
|
||||
"å",
|
||||
"ā"
|
||||
],
|
||||
"misc_e": [
|
||||
"é",
|
||||
"è",
|
||||
"ê",
|
||||
"ë",
|
||||
"ē"
|
||||
],
|
||||
"misc_i": [
|
||||
"í",
|
||||
"î",
|
||||
"ï",
|
||||
"ī",
|
||||
"ì"
|
||||
],
|
||||
"misc_o": [
|
||||
"ó",
|
||||
"ô",
|
||||
"ö",
|
||||
"ò",
|
||||
"œ",
|
||||
"ø",
|
||||
"ō",
|
||||
"õ"
|
||||
],
|
||||
"misc_u": [
|
||||
"ú",
|
||||
"û",
|
||||
"ü",
|
||||
"ù",
|
||||
"ū"
|
||||
],
|
||||
"misc_s": [
|
||||
"ß"
|
||||
],
|
||||
"misc_n": [
|
||||
"ñ"
|
||||
],
|
||||
"misc_c": [
|
||||
"ç"
|
||||
],
|
||||
|
||||
"nordic_row2_10": [],
|
||||
"nordic_row2_11": [],
|
||||
"east_slavic_row2_2": [],
|
||||
@ -55,6 +111,7 @@
|
||||
"₱"
|
||||
],
|
||||
"punctuation": [
|
||||
"/",
|
||||
"?",
|
||||
"!",
|
||||
"\u203d",
|
||||
@ -65,6 +122,7 @@
|
||||
"="
|
||||
],
|
||||
"tablet_punctuation": [
|
||||
"/",
|
||||
"?",
|
||||
"!",
|
||||
"\u203d",
|
||||
@ -314,6 +372,119 @@
|
||||
"double_lqm_rqm": "„,“,”",
|
||||
"double_9qm_lqm": "”,„,“",
|
||||
"double_9qm_rqm": "“,„,”",
|
||||
"double_rqm_9qm": "“,”,„"
|
||||
"double_rqm_9qm": "“,”,„",
|
||||
|
||||
"number_1": "1",
|
||||
"number_2": "2",
|
||||
"number_3": "3",
|
||||
"number_4": "4",
|
||||
"number_5": "5",
|
||||
"number_6": "6",
|
||||
"number_7": "7",
|
||||
"number_8": "8",
|
||||
"number_9": "9",
|
||||
"number_0": "0"
|
||||
},
|
||||
|
||||
"actions": {
|
||||
"1": [],
|
||||
"2": [],
|
||||
"3": [],
|
||||
"4": [],
|
||||
"5": [],
|
||||
"6": [],
|
||||
"7": [],
|
||||
"8": [],
|
||||
"9": [],
|
||||
"0": [],
|
||||
|
||||
"q": [],
|
||||
"w": [],
|
||||
"e": [],
|
||||
"r": [],
|
||||
"t": [],
|
||||
"y": [
|
||||
"!icon/action_redo|!code/action_redo"
|
||||
],
|
||||
"u": [],
|
||||
"i": [],
|
||||
"o": [],
|
||||
"p": [],
|
||||
|
||||
"a": [
|
||||
"!icon/action_select_all|!code/action_select_all"
|
||||
],
|
||||
"s": [],
|
||||
"d": [],
|
||||
"f": [],
|
||||
"g": [],
|
||||
"h": [],
|
||||
"j": [],
|
||||
"k": [],
|
||||
"l": [],
|
||||
|
||||
"z": [
|
||||
"!icon/action_undo|!code/action_undo"
|
||||
],
|
||||
"x": [
|
||||
"!icon/action_cut|!code/action_cut"
|
||||
],
|
||||
"c": [
|
||||
"!icon/action_copy|!code/action_copy"
|
||||
],
|
||||
"v": [
|
||||
"!icon/action_paste|!code/action_paste"
|
||||
],
|
||||
"b": [],
|
||||
"n": [],
|
||||
"m": []
|
||||
},
|
||||
|
||||
"qwertysyms": {
|
||||
"1": "!",
|
||||
"2": "@",
|
||||
"3": "#",
|
||||
"4": "$",
|
||||
"5": "%",
|
||||
"6": "^",
|
||||
"7": "&",
|
||||
"8": "*",
|
||||
"9": "(",
|
||||
"0": ")",
|
||||
|
||||
"q": "\\%",
|
||||
"w": "\\\\",
|
||||
"e": "|",
|
||||
"r": "=",
|
||||
"t": "[",
|
||||
"y": "]",
|
||||
"u": "<",
|
||||
"i": ">",
|
||||
"o": "{",
|
||||
"p": "}",
|
||||
|
||||
"a": "@",
|
||||
"s": "#",
|
||||
"d": [
|
||||
"$",
|
||||
"€",
|
||||
"£",
|
||||
"¥",
|
||||
"¢"
|
||||
],
|
||||
"f": "\\%",
|
||||
"g": ["&", "|"],
|
||||
"h": ["-", "–", "—", "_"],
|
||||
"j": ["+", "="],
|
||||
"k": ["(", "[", "{", "<"],
|
||||
"l": [")", "]", "}", ">" ],
|
||||
|
||||
"z": "*",
|
||||
"x": "\"",
|
||||
"c": "'",
|
||||
"v": ":",
|
||||
"b": ";",
|
||||
"n": "!",
|
||||
"m": ["?", "/"]
|
||||
}
|
||||
}
|
@ -1,57 +1,6 @@
|
||||
{
|
||||
"locale": "en",
|
||||
"morekeys": {
|
||||
"a": [
|
||||
"à",
|
||||
"á",
|
||||
"â",
|
||||
"ä",
|
||||
"æ",
|
||||
"ã",
|
||||
"å",
|
||||
"ā"
|
||||
],
|
||||
"e": [
|
||||
"é",
|
||||
"è",
|
||||
"ê",
|
||||
"ë",
|
||||
"ē"
|
||||
],
|
||||
"i": [
|
||||
"í",
|
||||
"î",
|
||||
"ï",
|
||||
"ī",
|
||||
"ì"
|
||||
],
|
||||
"o": [
|
||||
"ó",
|
||||
"ô",
|
||||
"ö",
|
||||
"ò",
|
||||
"œ",
|
||||
"ø",
|
||||
"ō",
|
||||
"õ"
|
||||
],
|
||||
"u": [
|
||||
"ú",
|
||||
"û",
|
||||
"ü",
|
||||
"ù",
|
||||
"ū"
|
||||
],
|
||||
"s": [
|
||||
"ß"
|
||||
],
|
||||
"n": [
|
||||
"ñ"
|
||||
],
|
||||
"c": [
|
||||
"ç"
|
||||
]
|
||||
},
|
||||
"morekeys": {},
|
||||
"keyspec": {},
|
||||
"label": {},
|
||||
"keylabel": {},
|
||||
|
@ -16,10 +16,13 @@ def transform_to_texts(locale_data):
|
||||
|
||||
texts["locale"] = locale_data["locale"]
|
||||
|
||||
prefixes = ['morekeys_', 'keyspec_', 'label_', 'keylabel_', 'keyhintlabel_', 'additional_morekeys_']
|
||||
prefixes = ['morekeys_', 'keyspec_', 'label_', 'keylabel_', 'keyhintlabel_', 'additional_morekeys_', 'qwertysyms_', 'actions_']
|
||||
|
||||
for prefix in prefixes:
|
||||
for k, v in locale_data[prefix.rstrip("_")].items():
|
||||
key = prefix.rstrip("_")
|
||||
if key not in locale_data: continue
|
||||
|
||||
for k, v in locale_data[key].items():
|
||||
if isinstance(v, list):
|
||||
texts[prefix + k] = ",".join(v)
|
||||
else:
|
||||
|
Loading…
Reference in New Issue
Block a user