Compare commits
165 Commits
1.24.0
...
bigger-sys
Author | SHA1 | Date | |
---|---|---|---|
|
4fd6aac137 | ||
|
69ab869079 | ||
|
d96414c6c6 | ||
|
0f11a88418 | ||
|
82e0840568 | ||
|
c7ed2bcae9 | ||
|
5386541db3 | ||
|
94b2ded843 | ||
|
2684d1f041 | ||
|
78f85e52a2 | ||
|
5e3a3f894b | ||
|
3f6b6fd232 | ||
|
f17afba7be | ||
|
7e9d8c73df | ||
|
b22b49d3e6 | ||
|
7c3286078b | ||
|
e604f6fd57 | ||
|
dc3a303af1 | ||
|
ec8e78d5cc | ||
|
0549c6c8a1 | ||
|
e74b45c2d6 | ||
|
1cbaa7106c | ||
|
fe0f82436a | ||
|
5c19140609 | ||
|
47e2009da4 | ||
|
b33bcd8865 | ||
|
c41a098924 | ||
|
8cd868ba76 | ||
|
07f9c1ffaa | ||
|
9a07149efc | ||
|
0594127575 | ||
|
a9f9bbec19 | ||
|
35d1ebeab5 | ||
|
0739c6bd2c | ||
|
a1de69bcc4 | ||
|
5e5937b0f4 | ||
|
ce38a4f151 | ||
|
0e0c761a92 | ||
|
940cf0deb8 | ||
|
c2d5b14261 | ||
|
ebda7b2c3e | ||
|
39f6d294fb | ||
|
8b5d971fb5 | ||
|
8c7559d8f6 | ||
|
d7e5040873 | ||
|
b29a344cd0 | ||
|
b8e673b614 | ||
|
bae82d6ed8 | ||
|
f913051dca | ||
|
dac702ad0b | ||
|
f2f6ef0627 | ||
|
6389d58553 | ||
|
e40558677e | ||
|
ae270b36f4 | ||
|
146d520325 | ||
|
065d9520e5 | ||
|
bb60ed9b13 | ||
|
d56e4d129e | ||
|
e9f734b6cc | ||
|
63e7ac2e94 | ||
|
8c29073260 | ||
|
38deb810f9 | ||
|
d8beda411d | ||
|
d96577963e | ||
|
f369b5d90b | ||
|
f4d88cc087 | ||
|
d5676d683f | ||
|
332413ed3c | ||
|
93d8af4505 | ||
|
f74e5a9f73 | ||
|
6513c21144 | ||
|
79aec5b9bc | ||
|
be053b082c | ||
|
5ce89d1b4b | ||
|
82a9774f5a | ||
|
5d1a503210 | ||
|
d1aa59768d | ||
|
2c52e94e0b | ||
|
3adf95a4c9 | ||
|
44f39059e4 | ||
|
bbc6226839 | ||
|
c5f2c0b727 | ||
|
fb27f8d36f | ||
|
5beacf32b7 | ||
|
ad7314a016 | ||
|
bef29da3de | ||
|
a55506e607 | ||
|
b3dcd61c28 | ||
|
9257bf7392 | ||
|
95bd9312a7 | ||
|
0a86f9ab01 | ||
|
70d777253c | ||
|
d7fa5ffa9a | ||
|
b114c78bf1 | ||
|
eddf9c6c11 | ||
|
148f3dfc05 | ||
|
6725d3057b | ||
|
cf9fd3a0db | ||
|
329a35e7d3 | ||
|
b319356a08 | ||
|
73267d68fb | ||
|
3f2f3177da | ||
|
e26e1d112c | ||
|
0005eb2dd5 | ||
|
8b2c7d9337 | ||
|
409362ddb4 | ||
|
c524caa6f1 | ||
|
7caf60c93b | ||
|
49a6a30773 | ||
|
4a5a125aea | ||
|
51a41ec90a | ||
|
7e7a5e4425 | ||
|
9ff8179d49 | ||
|
1af4e45117 | ||
|
2db4ae3730 | ||
|
2aecbca9ac | ||
|
dce7e2b9d9 | ||
|
7c12aa610c | ||
|
294ebee6f1 | ||
|
bd1afd2c3c | ||
|
44f6908411 | ||
|
df04eae85f | ||
|
d7c230e173 | ||
|
478d8082f4 | ||
|
7af6adcf11 | ||
|
dd327cc812 | ||
|
d073523125 | ||
|
684d5c7b70 | ||
|
851d22da6e | ||
|
44adb55544 | ||
|
15de829138 | ||
|
c57d896d8d | ||
|
80c6f97767 | ||
|
b0cf9a52b5 | ||
|
f696452c59 | ||
|
70500ba6f8 | ||
|
474c693427 | ||
|
73060bfc00 | ||
|
60134effdc | ||
|
838fbc8ef8 | ||
|
148bed769a | ||
|
3d36ecb34d | ||
|
2d164ca64f | ||
|
d594242a53 | ||
|
bd886a24eb | ||
|
7b7202ec1b | ||
|
33653a94cb | ||
|
5b4345088d | ||
|
d5cbcb37e3 | ||
|
66b1bdc9c9 | ||
|
d771e9d2c7 | ||
|
44e2e86f19 | ||
|
92a8db5e93 | ||
|
687d88f4f7 | ||
|
b079e5cf43 | ||
|
86038ef512 | ||
|
816269aed0 | ||
|
234986817f | ||
|
f4a995e2bd | ||
|
f07fbaff3b | ||
|
3530263083 | ||
|
9b917e79b1 | ||
|
f4c11d99ed | ||
|
cf76118548 | ||
|
40498e7b4c |
1
.gitattributes
vendored
Normal file
@@ -0,0 +1 @@
|
||||
srcs/juloo.keyboard2/ComposeKeyData.java -diff
|
19
.github/workflows/check-layouts.yml
vendored
@@ -1,19 +1,26 @@
|
||||
name: Check layouts
|
||||
|
||||
# Runs 'gen_layouts.py' and checks that the generated file were uptodate.
|
||||
# This doesn't run 'check_layout.py'.
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
push:
|
||||
pull_request:
|
||||
|
||||
jobs:
|
||||
check-layouts:
|
||||
gen-layouts:
|
||||
name: Generated files
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout repo
|
||||
uses: actions/checkout@v3
|
||||
uses: actions/checkout@v4
|
||||
- run: python3 gen_layouts.py
|
||||
- name: Check that the generated layouts.xml is uptodate, run python3 gen_layouts.py otherwise
|
||||
- name: "Check that the generated 'layouts.xml' is uptodate, otherwise run 'python3 gen_layouts.py'"
|
||||
run: git diff --exit-code
|
||||
check-layouts:
|
||||
name: check_layout.output
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout repo
|
||||
uses: actions/checkout@v4
|
||||
- run: python3 check_layout.py
|
||||
- name: "Check that the generated 'check_layout.output' is uptodate, otherwise run 'python3 check_layout.py'"
|
||||
run: git diff --exit-code
|
||||
|
6
.github/workflows/check-translations.yml
vendored
@@ -10,7 +10,7 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout repo
|
||||
uses: actions/checkout@v3
|
||||
uses: actions/checkout@v4
|
||||
- run: python3 sync_translations.py
|
||||
- name: Check that strings files are uptodate, run python3 sync_translations.py otherwise
|
||||
run: git diff --exit-code
|
||||
- name: "Check that strings files are uptodate, otherwise run 'python3 sync_translations.py'"
|
||||
run: git add -N . && git diff --exit-code
|
||||
|
36
.github/workflows/make-apk.yml
vendored
@@ -9,39 +9,41 @@ jobs:
|
||||
Build-Apk:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/setup-java@v3
|
||||
- uses: actions/setup-java@v4
|
||||
with:
|
||||
distribution: 'zulu' # See 'Supported distributions' for available options
|
||||
java-version: '11'
|
||||
java-version: '17'
|
||||
- name: Checkout repo
|
||||
uses: actions/checkout@v3
|
||||
- name: Cache debug certificate
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
path: _build/debug.keystore
|
||||
key: debug-keystore
|
||||
- name: Restore debug keystore from github Secrets
|
||||
uses: actions/checkout@v4
|
||||
- name: Restore debug keystore from GitHub Secrets
|
||||
run: |
|
||||
mkdir -p _build
|
||||
cd "_build"
|
||||
# Check if exist and use the secret named DEBUG_KEYSTORE
|
||||
# The contents of the secret can be obtained -
|
||||
# from the debug.keystore.asc from you local _build folder
|
||||
# from the debug.keystore.asc from you local folder
|
||||
# (refer to CONTRIBUTING.md Using the local debug.keystore on the Github CI actions)
|
||||
if [[ ! "${{ secrets.DEBUG_KEYSTORE }}" = "" ]]; then
|
||||
echo "${{ secrets.DEBUG_KEYSTORE }}" > "debug.keystore.asc"
|
||||
if [[ -s "debug.keystore.asc" ]]; then
|
||||
echo "Restoring debug keystore from GitHub secrets"
|
||||
gpg -d --passphrase "debug0" --batch "debug.keystore.asc" > "debug.keystore"
|
||||
fi
|
||||
fi
|
||||
- name: Build
|
||||
run: make
|
||||
- name: Build debug APK
|
||||
uses: gradle/gradle-build-action@v3
|
||||
env:
|
||||
DEBUG_KEYSTORE: "debug.keystore"
|
||||
DEBUG_KEYSTORE_PASSWORD: debug0
|
||||
DEBUG_KEY_ALIAS: debug
|
||||
DEBUG_KEY_PASSWORD: debug0
|
||||
with:
|
||||
arguments: assembleDebug
|
||||
- name: Artifact naming
|
||||
run: |
|
||||
artifact="${{github.repository_owner}} ${{github.ref_name}}"
|
||||
artifact="${artifact//\//-}" # replace slashes
|
||||
echo "artifact=${artifact}" >> $GITHUB_ENV
|
||||
- name: Save debug apk
|
||||
uses: actions/upload-artifact@v3
|
||||
- name: Upload debug APK
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: "${{env.artifact}} debug_apk"
|
||||
path: _build/*.apk
|
||||
path: build/outputs/apk/debug/*.apk
|
||||
|
10
.gitignore
vendored
@@ -1,4 +1,12 @@
|
||||
*.keystore
|
||||
*.keystore.asc
|
||||
_build
|
||||
/*-keystore.conf
|
||||
*.iml
|
||||
.gradle
|
||||
/local.properties
|
||||
/.idea
|
||||
.DS_Store
|
||||
/captures
|
||||
/build
|
||||
# Directory _build is not used anymore
|
||||
/_build
|
||||
|
@@ -1,25 +1,32 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="juloo.keyboard2" android:versionCode="36" android:versionName="1.24.0" android:hardwareAccelerated="false">
|
||||
<uses-sdk android:minSdkVersion="4" android:targetSdkVersion="33"/>
|
||||
<application android:label="@string/app_name" android:allowBackup="true" android:icon="@drawable/ic_launcher" android:hardwareAccelerated="false">
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android" android:hardwareAccelerated="false">
|
||||
<uses-permission android:name="android.permission.VIBRATE"/>
|
||||
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>
|
||||
|
||||
<application android:label="@string/app_name" android:allowBackup="true" android:icon="@mipmap/ic_launcher" android:hardwareAccelerated="false">
|
||||
<service android:name="juloo.keyboard2.Keyboard2" android:label="@string/app_name" android:permission="android.permission.BIND_INPUT_METHOD" android:exported="true" android:directBootAware="true">
|
||||
<intent-filter>
|
||||
<action android:name="android.view.InputMethod"/>
|
||||
</intent-filter>
|
||||
<meta-data android:name="android.view.im" android:resource="@xml/method"/>
|
||||
</service>
|
||||
<activity android:name="juloo.keyboard2.SettingsActivity" android:icon="@drawable/ic_launcher" android:label="@string/settings_activity_label" android:theme="@style/android:Theme.DeviceDefault" android:exported="true" android:directBootAware="true">
|
||||
<activity android:name="juloo.keyboard2.SettingsActivity" android:icon="@mipmap/ic_launcher" android:label="@string/settings_activity_label" android:theme="@style/appTheme" android:exported="true" android:directBootAware="true">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN"/>
|
||||
</intent-filter>
|
||||
</activity>
|
||||
<activity android:name="juloo.keyboard2.LauncherActivity" android:icon="@drawable/ic_launcher" android:label="@string/app_name" android:theme="@style/android:Theme.DeviceDefault" android:exported="true" android:directBootAware="true">
|
||||
<activity android:name="juloo.keyboard2.LauncherActivity" android:icon="@mipmap/ic_launcher" android:theme="@style/appTheme" android:exported="true" android:directBootAware="true">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN"/>
|
||||
<category android:name="android.intent.category.LAUNCHER"/>
|
||||
</intent-filter>
|
||||
</activity>
|
||||
</application>
|
||||
<uses-permission android:name="android.permission.VIBRATE"/>
|
||||
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>
|
||||
|
||||
<!-- To query enabled input methods for voice IME detection -->
|
||||
<queries>
|
||||
<intent>
|
||||
<action android:name="android.view.InputMethod" />
|
||||
</intent>
|
||||
</queries>
|
||||
</manifest>
|
||||
|
129
CONTRIBUTING.md
@@ -4,52 +4,46 @@ Thanks for contributing :)
|
||||
|
||||
## Building the app
|
||||
|
||||
The application doesn't use Gradle and it might be hard to use some features of
|
||||
Android Studio.
|
||||
|
||||
Fortunately, there's not many dependencies:
|
||||
- OpenJDK 8
|
||||
The application uses Gradle and can be used with Android Studio, but using
|
||||
Android Studio is not required. The build dependencies are:
|
||||
- OpenJDK 17
|
||||
- Android SDK: build tools (minimum `28.0.1`), platform `30`
|
||||
- Make sure to have the `$ANDROID_HOME` environment variable set.
|
||||
|
||||
Python 3 is required to update generated files but not to build the app.
|
||||
|
||||
For Android Studio users, no more setup is needed.
|
||||
|
||||
For Nix users, the right environment can be obtained with `nix-shell ./shell.nix`.
|
||||
Instructions to install Nix are [here](https://nixos.wiki/wiki/Nix_Installation_Guide).
|
||||
|
||||
If you don't use Android Studio or Nix, you have to inform Gradle about the
|
||||
location of your Android SDK by either:
|
||||
- Setting the `ANDROID_HOME` environment variable to point to the android sdk or
|
||||
- Creating the file `local.properties` and writing
|
||||
`sdk.dir=<location_of_android_home>` into it.
|
||||
|
||||
Building the debug apk:
|
||||
|
||||
```sh
|
||||
make
|
||||
./gradlew assembleDebug
|
||||
```
|
||||
|
||||
If the build succeed, the debug apk is located in `_build/juloo.keyboard2.debug.apk`.
|
||||
Nix users can call gradle directly: `gradle assembleDebug`.
|
||||
|
||||
## Using the local debug.keystore on the Github CI actions
|
||||
|
||||
It's possible to save the local debug.keystore into a github secret, so the same keystore is utilized to build the debug apk in the CI github actions.
|
||||
Doing this, they wil have the same signature, thus the debug apk can be updated without having to uninstall it first.
|
||||
|
||||
After you sucessfully run `make`, (thus a debug.keystore exists) you can use this second command to generate a base64 stringified version of it
|
||||
|
||||
```sh
|
||||
cd _build
|
||||
gpg -c --armor --pinentry-mode loopback --passphrase debug0 --yes "debug.keystore"
|
||||
```
|
||||
|
||||
A file will be generated inside the local `_build/` folder, called `debug.keystore.asc`
|
||||
|
||||
You can copy the content of this file, and with that, paste it into a new github secret in your repo settings.
|
||||
|
||||
The secret must be named `DEBUG_KEYSTORE`
|
||||
If the build succeeds, the debug apk is located in `build/outputs/apk/debug/app-debug.apk`.
|
||||
|
||||
## Debugging on your phone
|
||||
|
||||
First [Enable adb debugging on your device](https://developer.android.com/studio/command-line/adb#Enabling).
|
||||
Then connect your phone to your computer using an USB cable or wireless
|
||||
Then connect your phone to your computer using an USB cable or via wireless
|
||||
debugging.
|
||||
|
||||
If you use Android Studio, this process will be automatic and you don't have to
|
||||
follow this guide anymore.
|
||||
|
||||
And finally, install the application with:
|
||||
```sh
|
||||
make installd
|
||||
./gradlew installDebug
|
||||
```
|
||||
|
||||
The released version of the application won't be removed, both versions will
|
||||
@@ -57,11 +51,13 @@ be installed at the same time.
|
||||
|
||||
## Debugging the application: INSTALL_FAILED_UPDATE_INCOMPATIBLE
|
||||
|
||||
`make installd` can fail with the following error message:
|
||||
`./gradlew installDebug` can fail with the following error message:
|
||||
|
||||
```
|
||||
adb: failed to install _build/juloo.keyboard2.debug.apk: Failure [INSTALL_FAILED_UPDATE_INCOMPATIBLE: Package juloo.keyboard2.debug signatures do not match previously installed version; ignoring!]
|
||||
make: *** [Makefile:20: installd] Error 1
|
||||
FAILURE: Build failed with an exception.
|
||||
* What went wrong:
|
||||
Execution failed for task ':installDebug'.
|
||||
> java.util.concurrent.ExecutionException: com.android.builder.testing.api.DeviceException: com.android.ddmlib.InstallException: INSTALL_FAILED_UPDATE_INCOMPATIBLE: Existing package juloo.keyboard2.debug signatures do not match newer version; ignoring!
|
||||
```
|
||||
|
||||
The application can't be "updated" because the temporary certificate has been
|
||||
@@ -70,36 +66,57 @@ The application must be enabled again in the settings.
|
||||
|
||||
```sh
|
||||
adb uninstall juloo.keyboard2.debug
|
||||
make installd
|
||||
./gradlew installDebug
|
||||
```
|
||||
|
||||
## Specifying a debug signing certificate on Github Actions
|
||||
|
||||
It's possible to specify the signing certificate that the automated build
|
||||
should use.
|
||||
After you successfully run `./gradlew asssembleDebug`, (thus a debug.keystore
|
||||
exists) you can use this second command to generate a base64 stringified
|
||||
version of it:
|
||||
|
||||
```sh
|
||||
gpg -c --armor --pinentry-mode loopback --passphrase debug0 --yes "debug.keystore"
|
||||
```
|
||||
|
||||
This will create the file `debug.keystore.asc`, paste its content into a new
|
||||
Github secret named `DEBUG_KEYSTORE`.
|
||||
|
||||
## Guidelines
|
||||
|
||||
### Adding a layout
|
||||
|
||||
Layouts are defined in XML, see `res/xml/latn_qwerty_us.xml`.
|
||||
Layouts are defined in XML, see `srcs/layouts/latn_qwerty_us.xml`.
|
||||
An online tool for editing layout files written by @Lixquid is available
|
||||
[here](https://unexpected-keyboard-layout-editor.lixquid.com/).
|
||||
|
||||
Makes sure to specify the `name` attribute like in `latn_qwerty_us.xml`,
|
||||
otherwise the layout won't be added to the app.
|
||||
|
||||
The layout file must be placed in the `res/xml/` directory and named according to:
|
||||
The layout file must be placed in the `srcs/layouts` directory and named
|
||||
according to:
|
||||
- script (`latn` for latin, etc..)
|
||||
- layout name (eg. the name of a standard)
|
||||
- country code (or language code if more adequate)
|
||||
|
||||
Then, run `make gen_layouts` to add the layout to the app.
|
||||
Then, run `./gradlew genLayoutsList` to add the layout to the app.
|
||||
|
||||
The last step will update the file `res/values/layouts.xml`, that you should
|
||||
not edit directly.
|
||||
|
||||
Run `make check_layouts` to check some properties about your layout. This will
|
||||
change the file `check_layout.output`, which you should commit.
|
||||
Run `./gradlew checkKeyboardLayouts` to check some properties about your
|
||||
layout. This will change the file `check_layout.output`, which you should
|
||||
commit.
|
||||
|
||||
Layouts are CC0 licensed by default. If you do not want your layout to be
|
||||
released into the public domain, add a copyright notice at the top of the file
|
||||
and a mention in `srcs/layouts/LICENSE`.
|
||||
|
||||
#### Adding a programming layout
|
||||
|
||||
A programming layout must contains every ASCII characters.
|
||||
A programming layout must contain all ASCII characters.
|
||||
The current programming layouts are: QWERTY, Dvorak and Colemak.
|
||||
|
||||
See for example, Dvorak, added in https://github.com/Julow/Unexpected-Keyboard/pull/16
|
||||
@@ -133,27 +150,41 @@ and other extra keys to show.
|
||||
|
||||
The list of language tags (generally two letters)
|
||||
and locales (generally of the form `xx_XX`)
|
||||
can be found in this stackoverflow answer: https://stackoverflow.com/a/7989085
|
||||
can be found in this [stackoverflow answer](https://stackoverflow.com/a/7989085)
|
||||
|
||||
### Translations
|
||||
### Updating translations
|
||||
|
||||
Translations are always welcome !
|
||||
The text used in the app is written in `res/values-<language_tag>/strings.xml`.
|
||||
|
||||
See for example: 1723288 (Latvian), baf867a (French).
|
||||
The app can be translated by writing `res/values-<language code>/strings.xml`
|
||||
(for example `values-fr`, `values-lv`), based on the default:
|
||||
`res/values/strings.xml` (English).
|
||||
The list of language tags can be found in this
|
||||
[stackoverflow answer](https://stackoverflow.com/a/7989085)
|
||||
|
||||
The first part before the `_` is used, for example,
|
||||
`res/values-fr/strings.xml` for French,
|
||||
`res/values-lv/strings.xml` for Latvian.
|
||||
|
||||
Commented-out lines indicate missing translations:
|
||||
|
||||
```xml
|
||||
<!-- <string name="pref_layouts_add">Add an alternate layout</string> -->
|
||||
```
|
||||
|
||||
Remove the `<!--` and `-->` parts and change the text.
|
||||
|
||||
### Adding a translation
|
||||
|
||||
The `res/values-<language_tag>/strings.xml` file must be created by copying the
|
||||
default translation in `res/values/strings.xml`, which contain the structure of
|
||||
the file and the English strings.
|
||||
|
||||
To check that `strings.xml` is formatted correctly, run
|
||||
`python sync_translations.py`. This will modify your files.
|
||||
|
||||
The store description is found in `metadata/android/<locale>/`,
|
||||
`short_description.txt` and `full_description.txt`.
|
||||
The short description must not exceed 80 characters.
|
||||
Store descriptions in `fastlane/metadata/android/` are updated automatically.
|
||||
Translating changelogs is not useful.
|
||||
|
||||
The app name might be partially translated, the "unexpected" word should remain
|
||||
untranslated.
|
||||
The app name might be partially translated, the "Unexpected" word should remain
|
||||
untranslated if possible.
|
||||
|
||||
As translations need to be updated regularly, you can subscribe to this issue
|
||||
to receive a notification when an update is needed:
|
||||
|
3
FUNDING.yml
Normal file
@@ -0,0 +1,3 @@
|
||||
github: [ Julow ]
|
||||
liberapay: Julow
|
||||
custom: [ "https://paypal.me/JulesAguillon" ]
|
139
Makefile
@@ -1,139 +0,0 @@
|
||||
# Configuration
|
||||
|
||||
PACKAGE_NAME = juloo.keyboard2
|
||||
|
||||
ANDROID_PLATFORM_VERSION = android-30
|
||||
JAVA_VERSION = 1.7
|
||||
|
||||
SRC_DIR = srcs
|
||||
RES_DIR = res
|
||||
|
||||
EXTRA_JARS =
|
||||
|
||||
# /
|
||||
|
||||
debug: _build/$(PACKAGE_NAME).debug.apk
|
||||
release: _build/$(PACKAGE_NAME).apk
|
||||
|
||||
installd: _build/$(PACKAGE_NAME).debug.apk
|
||||
adb install -r "$<"
|
||||
|
||||
clean:
|
||||
rm -rf _build/*.dex _build/class _build/gen _build/*.apk _build/*.unsigned-apk \
|
||||
_build/*.idsig _build/assets
|
||||
|
||||
rebuild_special_font: _build/special_font.ttf
|
||||
cp "$<" srcs/special_font/result.ttf
|
||||
|
||||
sync_translations:
|
||||
python sync_translations.py
|
||||
|
||||
check_layouts:
|
||||
python check_layout.py $(wildcard res/xml/*.xml) > check_layout.output
|
||||
|
||||
gen_layouts:
|
||||
python gen_layouts.py
|
||||
|
||||
# Will modify the source tree.
|
||||
runtest: rebuild_special_font sync_translations check_layouts gen_layouts
|
||||
|
||||
.PHONY: release debug installd clean rebuild_special_font check_layouts \
|
||||
sync_translations runtest gen_layouts
|
||||
|
||||
$(shell mkdir -p _build)
|
||||
|
||||
ifndef ANDROID_HOME
|
||||
$(error ANDROID_HOME not set)
|
||||
endif
|
||||
|
||||
ANDROID_BUILD_TOOLS = $(lastword $(sort $(wildcard $(ANDROID_HOME)/build-tools/*)))
|
||||
ANDROID_PLATFORM = $(ANDROID_HOME)/platforms/$(ANDROID_PLATFORM_VERSION)
|
||||
|
||||
ifeq ($(shell [ -d "$(ANDROID_PLATFORM)" ] && echo ok),)
|
||||
$(error Android platform not found. Want $(ANDROID_PLATFORM_VERSION), \
|
||||
found $(notdir $(wildcard $(ANDROID_HOME)/platforms/*)))
|
||||
endif
|
||||
|
||||
JAVAC_FLAGS = -source $(JAVA_VERSION) -target $(JAVA_VERSION) -encoding utf8
|
||||
|
||||
# Source files
|
||||
|
||||
MANIFEST_FILE = AndroidManifest.xml
|
||||
JAVA_FILES = $(shell find $(SRC_DIR) -name '*.java')
|
||||
RES_FILES = $(shell find $(RES_DIR) -type f)
|
||||
|
||||
# Debug signing
|
||||
|
||||
DEBUG_KEYSTORE = _build/debug.keystore
|
||||
DEBUG_PASSWD = debug0
|
||||
|
||||
$(DEBUG_KEYSTORE):
|
||||
echo y | keytool -genkeypair -dname "cn=d, ou=e, o=b, c=ug" \
|
||||
-alias debug -keypass $(DEBUG_PASSWD) -keystore "$@" \
|
||||
-keyalg rsa -storepass $(DEBUG_PASSWD) -validity 10000
|
||||
|
||||
_build/%.debug.apk: _build/%.debug.unsigned-apk $(DEBUG_KEYSTORE)
|
||||
$(ANDROID_BUILD_TOOLS)/apksigner sign --in "$<" --out "$@" \
|
||||
--ks $(DEBUG_KEYSTORE) --ks-key-alias debug --ks-pass "pass:$(DEBUG_PASSWD)"
|
||||
|
||||
# Debug apk
|
||||
|
||||
_build/$(PACKAGE_NAME).debug.unsigned-apk: AAPT_PACKAGE_FLAGS+=--rename-manifest-package $(PACKAGE_NAME).debug --product debug
|
||||
|
||||
# Release signing
|
||||
|
||||
# %-keystore.conf should declare KEYSTORE, KEYNAME and KEYSTOREPASS
|
||||
# it is interpreted as a shell script
|
||||
_build/%.apk: _build/%.unsigned-apk %-keystore.conf
|
||||
eval `cat $(word 2,$^)` && \
|
||||
$(ANDROID_BUILD_TOOLS)/apksigner sign --in "$<" --out "$@" \
|
||||
--ks "$$KEYSTORE" --ks-key-alias "$$KEYNAME" --ks-pass "pass:$$KEYSTOREPASS"
|
||||
|
||||
# Package
|
||||
|
||||
_build/%.unsigned-apk: _build/%.unaligned-apk
|
||||
$(ANDROID_BUILD_TOOLS)/zipalign -fp 4 "$<" "$@"
|
||||
|
||||
APK_EXTRA_FILES = classes.dex assets/special_font.ttf
|
||||
|
||||
_build/%.unaligned-apk: $(addprefix _build/,$(APK_EXTRA_FILES)) $(MANIFEST_FILE)
|
||||
$(ANDROID_BUILD_TOOLS)/aapt package -f -M $(MANIFEST_FILE) -S $(RES_DIR) \
|
||||
-I $(ANDROID_PLATFORM)/android.jar -F "$@" $(AAPT_PACKAGE_FLAGS)
|
||||
cd $(@D) && $(ANDROID_BUILD_TOOLS)/aapt add $(@F) $(APK_EXTRA_FILES)
|
||||
|
||||
# Copy the special font file into _build because aapt requires relative paths
|
||||
_build/assets/special_font.ttf: srcs/special_font/result.ttf
|
||||
mkdir -p $(@D)
|
||||
cp "$<" "$@"
|
||||
|
||||
# R.java
|
||||
|
||||
GEN_DIR = _build/gen
|
||||
R_FILE = $(GEN_DIR)/$(subst .,/,$(PACKAGE_NAME))/R.java
|
||||
|
||||
$(R_FILE): $(RES_FILES) $(MANIFEST_FILE)
|
||||
mkdir -p "$(@D)"
|
||||
$(ANDROID_BUILD_TOOLS)/aapt package -f -m -S $(RES_DIR) -J $(GEN_DIR) \
|
||||
-M $(MANIFEST_FILE) -I $(ANDROID_PLATFORM)/android.jar
|
||||
|
||||
# Compile java classes and build classes.dex
|
||||
|
||||
OBJ_DIR = _build/class
|
||||
# A$B.class files are ignored
|
||||
# CLASS_FILES = $(JAVA_FILES:$(SRC_DIR)/%.java=$(OBJ_DIR)/%.class) \
|
||||
# $(R_FILE:$(GEN_DIR)/%.java=$(OBJ_DIR)/%.class)
|
||||
|
||||
_build/classes.dex: $(JAVA_FILES) $(R_FILE)
|
||||
mkdir -p $(OBJ_DIR)
|
||||
javac -d $(OBJ_DIR) $(JAVAC_FLAGS) \
|
||||
-classpath $(ANDROID_PLATFORM)/android.jar:$(EXTRA_JARS) \
|
||||
-sourcepath $(SRC_DIR):$(GEN_DIR) \
|
||||
$^
|
||||
$(ANDROID_BUILD_TOOLS)/d8 --output $(@D) $(OBJ_DIR)/*/*/* $(subst :, ,$(EXTRA_JARS))
|
||||
|
||||
# Font file
|
||||
|
||||
FONT_GLYPHS = $(wildcard srcs/special_font/*.svg)
|
||||
|
||||
_build/special_font.ttf: srcs/special_font/build.pe $(FONT_GLYPHS)
|
||||
fontforge -lang=ff -script $< "$@" $(FONT_GLYPHS)
|
10
README.md
@@ -9,9 +9,7 @@
|
||||
|
||||
Lightweight and privacy-conscious virtual keyboard for Android.
|
||||
|
||||
| <img src="/metadata/android/en-US/images/phoneScreenshots/1.png" alt="Screenshot-1" /> | <img src="/metadata/android/en-US/images/phoneScreenshots/2.png" alt="Screenshot-2"/> | <img src="/metadata/android/en-US/images/phoneScreenshots/3.png" alt="Screenshot-3"/> |
|
||||
| --- | --- | --- |
|
||||
| <img src="/metadata/android/en-US/images/phoneScreenshots/4.png" alt="Screenshot-4" /> | <img src="/metadata/android/en-US/images/phoneScreenshots/5.png" alt="Screenshot-5" /> | <img src="/metadata/android/en-US/images/phoneScreenshots/6.png" alt="Screenshot-6" /> |
|
||||
https://github.com/Julow/Unexpected-Keyboard/assets/2310568/28f8f6fe-ac13-46f3-8c5e-d62443e16d0d
|
||||
|
||||
The main feature is that you can type more characters by swiping the keys towards the corners.
|
||||
|
||||
@@ -20,6 +18,12 @@ Now perfect for everyday use.
|
||||
|
||||
This application contains no ads, doesn't make any network requests and is Open Source.
|
||||
|
||||
Usage: to apply the symbols located in the corners of each key, slide your finger in the direction of the symbols. For example, the Settings are opened by sliding in the left down corner.
|
||||
|
||||
| <img src="/fastlane/metadata/android/en-US/images/phoneScreenshots/1.png" alt="Screenshot-1" /> | <img src="/fastlane/metadata/android/en-US/images/phoneScreenshots/2.png" alt="Screenshot-2"/> | <img src="/fastlane/metadata/android/en-US/images/phoneScreenshots/3.png" alt="Screenshot-3"/> |
|
||||
| --- | --- | --- |
|
||||
| <img src="/fastlane/metadata/android/en-US/images/phoneScreenshots/4.png" alt="Screenshot-4" /> | <img src="/fastlane/metadata/android/en-US/images/phoneScreenshots/5.png" alt="Screenshot-5" /> | <img src="/fastlane/metadata/android/en-US/images/phoneScreenshots/6.png" alt="Screenshot-6" /> |
|
||||
|
||||
## Similar apps
|
||||
* [Calculator++](https://github.com/Bubu/android-calculatorpp) - Calculator with a similar UX, swipe to corners for advanced math symbols and operators. Works up to Android 13 but maybe unmaintained.
|
||||
|
||||
|
186
build.gradle
Normal file
@@ -0,0 +1,186 @@
|
||||
plugins {
|
||||
id 'com.android.application' version '8.1.1'
|
||||
}
|
||||
|
||||
android {
|
||||
namespace 'juloo.keyboard2'
|
||||
compileSdk 33
|
||||
|
||||
defaultConfig {
|
||||
applicationId "juloo.keyboard2"
|
||||
minSdk 11
|
||||
targetSdkVersion 33
|
||||
versionCode 39
|
||||
versionName "1.27.0"
|
||||
}
|
||||
|
||||
sourceSets {
|
||||
main {
|
||||
manifest.srcFile 'AndroidManifest.xml'
|
||||
java.srcDirs = ['srcs']
|
||||
res.srcDirs = ['res', 'build/generated-resources']
|
||||
assets.srcDirs = ['assets']
|
||||
}
|
||||
}
|
||||
|
||||
signingConfigs {
|
||||
// Debug builds will always be signed. If no environment variables are set, a default
|
||||
// keystore will be initialized by the task initDebugKeystore and used. This keystore
|
||||
// can be uploaded to GitHub secrets by following instructions in CONTRIBUTING.md
|
||||
// in order to always receive correctly signed debug APKs from the CI.
|
||||
debug {
|
||||
storeFile(System.env.DEBUG_KEYSTORE ? file(System.env.DEBUG_KEYSTORE) : file("debug.keystore"))
|
||||
storePassword(System.env.DEBUG_KEYSTORE_PASSWORD ? "$System.env.DEBUG_KEYSTORE_PASSWORD" : "debug0")
|
||||
keyAlias(System.env.DEBUG_KEY_ALIAS ? "$System.env.DEBUG_KEY_ALIAS" : "debug")
|
||||
keyPassword(System.env.DEBUG_KEY_PASSWORD ? "$System.env.DEBUG_KEY_PASSWORD" : "debug0")
|
||||
}
|
||||
|
||||
release {
|
||||
if (System.env.RELEASE_KEYSTORE) {
|
||||
storeFile file(System.env.RELEASE_KEYSTORE)
|
||||
storePassword "$System.env.RELEASE_KEYSTORE_PASSWORD"
|
||||
keyAlias "$System.env.RELEASE_KEY_ALIAS"
|
||||
keyPassword "$System.env.RELEASE_KEY_PASSWORD"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
buildTypes {
|
||||
release {
|
||||
minifyEnabled true
|
||||
shrinkResources true
|
||||
debuggable false
|
||||
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt')
|
||||
resValue "string", "app_name", "@string/app_name_release"
|
||||
signingConfig signingConfigs.release
|
||||
}
|
||||
|
||||
debug {
|
||||
minifyEnabled false
|
||||
shrinkResources false
|
||||
debuggable true
|
||||
applicationIdSuffix ".debug"
|
||||
resValue "string", "app_name", "@string/app_name_debug"
|
||||
resValue "bool", "debug_logs", "true"
|
||||
signingConfig signingConfigs.debug
|
||||
}
|
||||
}
|
||||
|
||||
// Name outputs after the application ID.
|
||||
android.applicationVariants.all { variant ->
|
||||
variant.outputs.all {
|
||||
outputFileName = "${applicationId}.apk"
|
||||
}
|
||||
}
|
||||
|
||||
compileOptions {
|
||||
sourceCompatibility JavaVersion.VERSION_1_7
|
||||
targetCompatibility JavaVersion.VERSION_1_7
|
||||
}
|
||||
|
||||
lintOptions {
|
||||
// Translation are already checked by 'syncTranslations'
|
||||
disable 'MissingTranslation'
|
||||
}
|
||||
}
|
||||
|
||||
dependencies {
|
||||
}
|
||||
|
||||
tasks.register('buildKeyboardFont') {
|
||||
println "\nBuilding assets/special_font.ttf"
|
||||
mkdir "$buildDir"
|
||||
exec {
|
||||
workingDir "$projectDir/srcs/special_font"
|
||||
def svgFiles = workingDir.listFiles().findAll {
|
||||
it.isFile() && it.name.endsWith(".svg")
|
||||
}
|
||||
commandLine("fontforge", "-lang=ff", "-script", "build.pe", "$buildDir/special_font.ttf", *svgFiles)
|
||||
}
|
||||
copy {
|
||||
from "$buildDir/special_font.ttf"
|
||||
into "assets"
|
||||
}
|
||||
}
|
||||
|
||||
tasks.withType(Test).configureEach {
|
||||
dependsOn 'genLayoutsList'
|
||||
dependsOn 'checkKeyboardLayouts'
|
||||
dependsOn 'syncTranslations'
|
||||
dependsOn 'compileComposeSequences'
|
||||
}
|
||||
|
||||
tasks.register('genLayoutsList') {
|
||||
println "\nGenerating res/values/layouts.xml"
|
||||
exec {
|
||||
workingDir = projectDir
|
||||
commandLine "python", "gen_layouts.py"
|
||||
}
|
||||
}
|
||||
|
||||
tasks.register('checkKeyboardLayouts') {
|
||||
println "\nChecking layouts"
|
||||
exec {
|
||||
def layouts = new File(projectDir, "srcs/layouts").listFiles().findAll {
|
||||
it.name.endsWith(".xml")
|
||||
}
|
||||
workingDir = projectDir
|
||||
commandLine("python", "check_layout.py", *layouts)
|
||||
standardOutput = new FileOutputStream("${projectDir}/check_layout.output")
|
||||
}
|
||||
}
|
||||
|
||||
tasks.register('syncTranslations') {
|
||||
println "\nUpdating translations"
|
||||
exec {
|
||||
workingDir = projectDir
|
||||
commandLine "python", "sync_translations.py"
|
||||
}
|
||||
}
|
||||
|
||||
tasks.register('compileComposeSequences') {
|
||||
def out = "srcs/juloo.keyboard2/ComposeKeyData.java"
|
||||
println "\nGenerating ${out}"
|
||||
exec {
|
||||
def sequences = new File(projectDir, "srcs/compose").listFiles().findAll {
|
||||
it.name.endsWith(".pre") || it.name.endsWith(".json")
|
||||
}
|
||||
workingDir = projectDir
|
||||
commandLine("python", "srcs/compose/compile.py", *sequences)
|
||||
standardOutput = new FileOutputStream("${projectDir}/${out}")
|
||||
}
|
||||
}
|
||||
|
||||
tasks.named("preBuild") {
|
||||
dependsOn += "initDebugKeystore"
|
||||
dependsOn += "copyRawQwertyUS"
|
||||
dependsOn += "copyLayoutDefinitions"
|
||||
}
|
||||
|
||||
tasks.register('initDebugKeystore') {
|
||||
if (!file("debug.keystore").exists()) {
|
||||
println "Initializing default debug keystore"
|
||||
exec {
|
||||
// A shell script might be needed if this line requires input from the user
|
||||
commandLine "keytool", "-genkeypair", "-dname", "cn=d, ou=e, o=b, c=ug", "-alias", "debug", "-keypass", "debug0", "-keystore", "debug.keystore", "-keyalg", "rsa", "-storepass", "debug0", "-validity", "10000"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// latn_qwerty_us is used as a raw resource by the custom layout option.
|
||||
tasks.register('copyRawQwertyUS')
|
||||
{
|
||||
copy {
|
||||
from "srcs/layouts/latn_qwerty_us.xml"
|
||||
into "build/generated-resources/raw"
|
||||
}
|
||||
}
|
||||
|
||||
tasks.register('copyLayoutDefinitions')
|
||||
{
|
||||
copy {
|
||||
from "srcs/layouts"
|
||||
include "*.xml"
|
||||
into "build/generated-resources/xml"
|
||||
}
|
||||
}
|
@@ -1,117 +1,145 @@
|
||||
# res/xml/arab_alt.xml
|
||||
# arab_alt
|
||||
Layout includes some ASCII punctuation but not all, missing: !, ", ', +, -, /, :, ;, <, =, >, ?, [, \, ], _, |, ~
|
||||
Layout doesn't define some important keys, missing: f11_placeholder, f12_placeholder
|
||||
2 warnings
|
||||
# res/xml/arab_pc_ckb.xml
|
||||
Layout includes some ASCII punctuation but not all, missing: ", %, ', +, ,, ., :, ;, <, =, >, ?, `, |, ~
|
||||
1 warnings
|
||||
# res/xml/arab_pc_ir.xml
|
||||
Duplicate keys: (, )
|
||||
Layout includes some ASCII punctuation but not all, missing: ", %, ', ,, /, ;, <, =, >, ?, [, \, ], `, {, |, }
|
||||
# arab_hamvaj_tly
|
||||
Layout includes some ASCII punctuation but not all, missing: ", %, ', ,, /, ;, <, =, >, ?, [, \, ], _, `, {, |, }
|
||||
Layout doesn't define some important keys, missing: esc, f11_placeholder, f12_placeholder
|
||||
2 warnings
|
||||
# res/xml/arab_pc.xml
|
||||
# arab_pc
|
||||
Layout includes some ASCII punctuation but not all, missing: !, ', +, ;, ?, \, |
|
||||
1 warnings
|
||||
# res/xml/beng_national.xml
|
||||
# arab_pc_ckb
|
||||
Layout includes some ASCII punctuation but not all, missing: ", %, ', +, ,, ., :, ;, <, =, >, ?, `, |, ~
|
||||
1 warnings
|
||||
# arab_pc_hindu
|
||||
Layout includes some ASCII punctuation but not all, missing: !, ', +, ;, ?, \, |
|
||||
1 warnings
|
||||
# arab_pc_ir
|
||||
Layout includes some ASCII punctuation but not all, missing: ", %, ', ,, /, ;, <, =, >, ?, [, \, ], `, {, |, }
|
||||
1 warnings
|
||||
# armenian_ph_am
|
||||
Layout doesn't define some important keys, missing: f11_placeholder, f12_placeholder
|
||||
1 warnings
|
||||
# beng_national
|
||||
Layout includes some ASCII punctuation but not all, missing: $
|
||||
Layout doesn't define some important keys, missing: f11_placeholder, f12_placeholder
|
||||
Layout doesn't specify a script.
|
||||
3 warnings
|
||||
# res/xml/beng_provat.xml
|
||||
2 warnings
|
||||
# beng_provat
|
||||
Layout includes some ASCII punctuation but not all, missing: $, &, *, ., /, <, >, [, \, ], `, {, |, }
|
||||
Layout doesn't define some important keys, missing: f11_placeholder, f12_placeholder
|
||||
Layout doesn't specify a script.
|
||||
3 warnings
|
||||
# res/xml/cyrl_jcuken_ru.xml
|
||||
2 warnings
|
||||
# cyrl_jcuken_ru
|
||||
0 warnings
|
||||
# res/xml/cyrl_jcuken_uk.xml
|
||||
# cyrl_jcuken_uk
|
||||
0 warnings
|
||||
# res/xml/cyrl_yaverti.xml
|
||||
# cyrl_ueishsht
|
||||
0 warnings
|
||||
# cyrl_yaverti
|
||||
Layout includes some ASCII punctuation but not all, missing: ~
|
||||
1 warnings
|
||||
# res/xml/deva_alt.xml
|
||||
Layout includes some ASCII punctuation but not all, missing: #, $, %, &, ', (, ), *, +, ., /, :, <, =, >, @, [, \, ], ^, _, `, {, |, }, ~
|
||||
Layout doesn't define some important keys, missing: f11_placeholder, f12_placeholder
|
||||
# deva_alt
|
||||
Layout includes some ASCII punctuation but not all, missing: #, $, %, &, ', (, ), +, ., /, :, <, =, >, [, \, ], ^, _, `, {, |, }, ~
|
||||
Layout doesn't define some important keys, missing: esc, f11_placeholder, f12_placeholder, tab
|
||||
2 warnings
|
||||
# res/xml/deva_inscript.xml
|
||||
Duplicate keys: , ।
|
||||
# deva_inscript
|
||||
Duplicate keys: ।
|
||||
Layout includes some ASCII punctuation but not all, missing: ", $, ', ^, _, `, |
|
||||
Layout doesn't define some important keys, missing: f11_placeholder, f12_placeholder
|
||||
3 warnings
|
||||
# res/xml/grek_qwerty.xml
|
||||
# grek_qwerty
|
||||
Duplicate keys: ;
|
||||
1 warnings
|
||||
# res/xml/hang_dubeolsik_kr.xml
|
||||
# guj_phonetic_in
|
||||
Duplicate keys: ટ, ડ
|
||||
Layout doesn't define some important keys, missing: f11_placeholder, f12_placeholder
|
||||
2 warnings
|
||||
# hang_dubeolsik_kr
|
||||
0 warnings
|
||||
# res/xml/hebr_1_il.xml
|
||||
# hebr_1_il
|
||||
Layout includes some ASCII punctuation but not all, missing: (, ), <, >, [, ], {, }
|
||||
1 warnings
|
||||
# res/xml/hebr_2_il.xml
|
||||
# hebr_2_il
|
||||
Layout includes some ASCII punctuation but not all, missing: (, ), <, >, [, ], {, }
|
||||
1 warnings
|
||||
# res/xml/latn_azerty_fr.xml
|
||||
# latn_azerty_fr
|
||||
0 warnings
|
||||
# res/xml/latn_bepo_fr.xml
|
||||
# latn_bepo_fr
|
||||
Layout doesn't define some important keys, missing: f11_placeholder, f12_placeholder
|
||||
1 warnings
|
||||
# res/xml/latn_bone.xml
|
||||
# latn_bone
|
||||
Layout includes some ASCII punctuation but not all, missing: $
|
||||
Layout redefines the bottom row but some important keys are missing, missing: switch_backward
|
||||
Layout redefines the bottom row but some important keys are missing, missing: cursor_left, cursor_right, loc compose, loc end, loc home, loc page_down, loc page_up, loc switch_greekmath, loc voice_typing, switch_backward
|
||||
2 warnings
|
||||
# res/xml/latn_colemak.xml
|
||||
# latn_colemak
|
||||
Some keys contain whitespaces, unexpected: ́
|
||||
1 warnings
|
||||
# latn_dvorak
|
||||
0 warnings
|
||||
# res/xml/latn_dvorak.xml
|
||||
# latn_neo2
|
||||
0 warnings
|
||||
# res/xml/latn_neo2.xml
|
||||
Duplicate keys: -
|
||||
Layout redefines the bottom row but some important keys are missing, missing: switch_forward
|
||||
2 warnings
|
||||
# res/xml/latn_qwerty_br.xml
|
||||
# latn_qwerty_br
|
||||
0 warnings
|
||||
# res/xml/latn_qwerty_es.xml
|
||||
# latn_qwerty_cz
|
||||
Layout doesn't define some important keys, missing: f11_placeholder, f12_placeholder
|
||||
1 warnings
|
||||
# latn_qwerty_da
|
||||
0 warnings
|
||||
# res/xml/latn_qwerty_hu.xml
|
||||
# latn_qwerty_es
|
||||
0 warnings
|
||||
# res/xml/latn_qwerty_lv.xml
|
||||
# latn_qwerty_gb
|
||||
0 warnings
|
||||
# res/xml/latn_qwerty_no.xml
|
||||
# latn_qwerty_hu
|
||||
0 warnings
|
||||
# res/xml/latn_qwerty_pl.xml
|
||||
# latn_qwerty_lv
|
||||
0 warnings
|
||||
# res/xml/latn_qwerty_ro.xml
|
||||
# latn_qwerty_no
|
||||
0 warnings
|
||||
# res/xml/latn_qwerty_se.xml
|
||||
# latn_qwerty_pl
|
||||
0 warnings
|
||||
# latn_qwerty_ro
|
||||
0 warnings
|
||||
# latn_qwerty_se
|
||||
Duplicate keys: !, ', ,, -, ., ?
|
||||
1 warnings
|
||||
# res/xml/latn_qwerty_tr.xml
|
||||
# latn_qwerty_sk
|
||||
Layout doesn't define some important keys, missing: f11_placeholder, f12_placeholder
|
||||
1 warnings
|
||||
# res/xml/latn_qwerty_us.xml
|
||||
0 warnings
|
||||
# res/xml/latn_qwerty_vi.xml
|
||||
Layout includes some ASCII punctuation but not all, missing: \
|
||||
# latn_qwerty_tly
|
||||
Duplicate keys: a, c, j, q
|
||||
Layout doesn't define some important keys, missing: esc, f11_placeholder, f12_placeholder, tab
|
||||
2 warnings
|
||||
# latn_qwerty_tr
|
||||
Layout doesn't define some important keys, missing: f11_placeholder, f12_placeholder
|
||||
1 warnings
|
||||
# res/xml/latn_qwertz_cz_multifunctional.xml
|
||||
# latn_qwerty_us
|
||||
0 warnings
|
||||
# latn_qwerty_vi
|
||||
0 warnings
|
||||
# latn_qwertz
|
||||
0 warnings
|
||||
# latn_qwertz_cz
|
||||
Layout doesn't define some important keys, missing: f11_placeholder, f12_placeholder
|
||||
1 warnings
|
||||
# latn_qwertz_cz_multifunctional
|
||||
Layout includes some ASCII punctuation but not all, missing: `
|
||||
Layout doesn't define some important keys, missing: f11_placeholder, f12_placeholder
|
||||
2 warnings
|
||||
# res/xml/latn_qwertz_cz.xml
|
||||
Layout doesn't define some important keys, missing: f11_placeholder, f12_placeholder
|
||||
1 warnings
|
||||
# res/xml/latn_qwertz_de.xml
|
||||
# latn_qwertz_de
|
||||
0 warnings
|
||||
# res/xml/latn_qwertz_fr_ch.xml
|
||||
# latn_qwertz_fr_ch
|
||||
0 warnings
|
||||
# res/xml/latn_qwertz_hu.xml
|
||||
# latn_qwertz_hu
|
||||
0 warnings
|
||||
# res/xml/latn_qwertz_sk.xml
|
||||
Layout includes some ASCII punctuation but not all, missing: \, `
|
||||
# latn_qwertz_sk
|
||||
Layout includes some ASCII punctuation but not all, missing: `
|
||||
Layout doesn't define some important keys, missing: f11_placeholder, f12_placeholder
|
||||
2 warnings
|
||||
# res/xml/latn_qwertz.xml
|
||||
# shaw_imperial_en
|
||||
0 warnings
|
||||
# res/xml/urdu_phonetic_ur.xml
|
||||
# urdu_phonetic_ur
|
||||
Duplicate keys:
|
||||
Layout includes some ASCII punctuation but not all, missing: <, >, ?, `, |, ~
|
||||
Layout doesn't define some important keys, missing: f11_placeholder, f12_placeholder
|
||||
3 warnings
|
||||
Some keys contain whitespaces, unexpected:
|
||||
4 warnings
|
||||
|
@@ -1,12 +1,12 @@
|
||||
import xml.etree.ElementTree as ET
|
||||
import sys
|
||||
import sys, os
|
||||
|
||||
warning_count = 0
|
||||
|
||||
KNOWN_NOT_LAYOUT = set([
|
||||
"res/xml/number_row.xml", "res/xml/numpad.xml", "res/xml/pin.xml",
|
||||
"res/xml/bottom_row.xml", "res/xml/settings.xml", "res/xml/method.xml",
|
||||
"res/xml/greekmath.xml", "res/xml/numeric.xml" ])
|
||||
"number_row", "numpad", "pin",
|
||||
"bottom_row", "settings", "method",
|
||||
"greekmath", "numeric", "emoji_bottom_row" ])
|
||||
|
||||
def warn(msg):
|
||||
global warning_count
|
||||
@@ -34,6 +34,15 @@ def unexpected_keys(keys, symbols, msg):
|
||||
if len(unexpected) > 0:
|
||||
warn("%s, unexpected: %s" % (msg, key_list_str(unexpected)))
|
||||
|
||||
# Write to [keys] and [dup].
|
||||
def parse_row_from_et(row, keys, dup):
|
||||
for key in row:
|
||||
for attr in key.keys():
|
||||
if attr.startswith("key"):
|
||||
k = key.get(attr).removeprefix("\\")
|
||||
if k in keys: dup.add(k)
|
||||
keys.add(k)
|
||||
|
||||
def parse_layout(fname):
|
||||
keys = set()
|
||||
dup = set()
|
||||
@@ -41,12 +50,16 @@ def parse_layout(fname):
|
||||
if root.tag != "keyboard":
|
||||
return None
|
||||
for row in root:
|
||||
for key in row:
|
||||
for attr in key.keys():
|
||||
if attr.startswith("key"):
|
||||
k = key.get(attr).removeprefix("\\")
|
||||
if k in keys: dup.add(k)
|
||||
keys.add(k)
|
||||
parse_row_from_et(row, keys, dup)
|
||||
return root, keys, dup
|
||||
|
||||
def parse_row(fname):
|
||||
keys = set()
|
||||
dup = set()
|
||||
root = ET.parse(fname).getroot()
|
||||
if root.tag != "row":
|
||||
return None
|
||||
parse_row_from_et(root, keys, dup)
|
||||
return root, keys, dup
|
||||
|
||||
def check_layout(layout):
|
||||
@@ -60,19 +73,17 @@ def check_layout(layout):
|
||||
"Layout doesn't define some important keys")
|
||||
unexpected_keys(keys,
|
||||
["copy", "paste", "cut", "selectAll", "shareText",
|
||||
"pasteAsPlainText", "undo", "redo", "replaceText",
|
||||
"textAssist", "autofill" ],
|
||||
"pasteAsPlainText", "undo", "redo" ],
|
||||
"Layout contains editing keys")
|
||||
unexpected_keys(keys,
|
||||
[ "f1", "f2", "f3", "f4", "f5", "f6", "f7", "f8", "f9",
|
||||
"f10", "f11", "f12" ],
|
||||
"Layout contains function keys")
|
||||
unexpected_keys(keys, [""], "Layout contains empty strings")
|
||||
unexpected_keys(keys, ["loc"], "Special keyword cannot be a symbol")
|
||||
unexpected_keys(keys, filter(lambda k: k.strip()!=k, keys), "Some keys contain whitespaces")
|
||||
|
||||
bottom_row_keys = [
|
||||
"ctrl", "fn", "switch_numeric", "change_method", "switch_emoji",
|
||||
"config", "switch_forward", "switch_backward", "enter", "action",
|
||||
"left", "up", "right", "down", "space"
|
||||
]
|
||||
_, bottom_row_keys, _ = parse_row("res/xml/bottom_row.xml")
|
||||
|
||||
if root.get("bottom_row") == "false":
|
||||
missing_required(keys, bottom_row_keys,
|
||||
@@ -84,14 +95,15 @@ def check_layout(layout):
|
||||
if root.get("script") == None:
|
||||
warn("Layout doesn't specify a script.")
|
||||
|
||||
for fname in sys.argv[1:]:
|
||||
if fname in KNOWN_NOT_LAYOUT:
|
||||
for fname in sorted(sys.argv[1:]):
|
||||
layout_id, _ = os.path.splitext(os.path.basename(fname))
|
||||
if layout_id in KNOWN_NOT_LAYOUT:
|
||||
continue
|
||||
layout = parse_layout(fname)
|
||||
if layout == None:
|
||||
print("Not a layout file: %s" % fname)
|
||||
print("Not a layout file: %s" % layout_id)
|
||||
else:
|
||||
print("# %s" % fname)
|
||||
print("# %s" % layout_id)
|
||||
warning_count = 0
|
||||
check_layout(layout)
|
||||
print("%d warnings" % warning_count)
|
||||
|
6
fastlane/metadata/android/cs-CZ/full_description.txt
Normal file
@@ -0,0 +1,6 @@
|
||||
Hlavní funkcí je možnost psát více znaků posunutím kláves směrem k rohům.
|
||||
|
||||
Tato aplikace byla původně navržena pro programátory používající Termux.
|
||||
Nyní je ideální pro každodenní použití.
|
||||
|
||||
Tato aplikace neobsahuje žádné reklamy, nevyužívá připojení k síti a je Open Source.
|
8
fastlane/metadata/android/en-US/changelogs/37.txt
Normal file
@@ -0,0 +1,8 @@
|
||||
Improved custom layout option.
|
||||
Allow selecting voice typing app with a long press.
|
||||
The numpad can work with other numeral systems.
|
||||
New and updated layouts.
|
||||
New themes.
|
||||
Many small improvements.
|
||||
|
||||
Thanks to the contributors: @pharook, @syskill, @ojas-bhagavath, @lrvideckis, @lyubomirv, @matthiakl, @deftkHD, @V6lhost, @RZHSSNZDH, @RetrogisusDEV, @rafasaurus, @krtsgnr7230, @eandersons, @ChasmSolacer, @Validbit, @polyctena
|
7
fastlane/metadata/android/en-US/changelogs/38.txt
Normal file
@@ -0,0 +1,7 @@
|
||||
The custom vibration setting is back.
|
||||
Allow to hide the keyboard switching key.
|
||||
Fixed modifier keys in some development apps.
|
||||
Updated translations.
|
||||
Bug fixes and general improvements.
|
||||
|
||||
Many thanks to the contributors: @abb128, @marciozomb13, @RetrogisusDEV, @Sestowner, @vedamanavi, @krtsgnr7230
|
6
fastlane/metadata/android/en-US/changelogs/39.txt
Normal file
@@ -0,0 +1,6 @@
|
||||
New layouts: QWERTY (Slovak), Gujarati phonetic
|
||||
Add Linux Compose key to type a variety of characters using known combinations.
|
||||
Fixed localized numpad and number row.
|
||||
Many improvements and bug fixes.
|
||||
|
||||
Huge thanks to the contributors: @Yogesh-B, @ChasmSolacer, @matthiakl, @Sestowner, @RyanGibb, @BogdanLata, @RetrogisusDEV, @V6lhost, @ErrrorMaxx, @sdrapha, @vedamanavi
|
Before Width: | Height: | Size: 22 KiB After Width: | Height: | Size: 22 KiB |
Before Width: | Height: | Size: 22 KiB After Width: | Height: | Size: 22 KiB |
Before Width: | Height: | Size: 26 KiB After Width: | Height: | Size: 26 KiB |
Before Width: | Height: | Size: 26 KiB After Width: | Height: | Size: 26 KiB |
Before Width: | Height: | Size: 24 KiB After Width: | Height: | Size: 24 KiB |
Before Width: | Height: | Size: 62 KiB After Width: | Height: | Size: 62 KiB |
Before Width: | Height: | Size: 62 KiB After Width: | Height: | Size: 62 KiB |
Before Width: | Height: | Size: 20 KiB After Width: | Height: | Size: 20 KiB |
1
fastlane/metadata/android/en-US/video.txt
Normal file
@@ -0,0 +1 @@
|
||||
https://www.youtube.com/watch?v=rwGvWesPFX8
|
@@ -3,4 +3,4 @@ La característica principal es que hay acceso a más caractéres deslizando hac
|
||||
Esta aplicación fue originalmente diseñada para programadores que usaran Termux.
|
||||
Ahora es perfecta para uso cotidiano.
|
||||
|
||||
La misma no contiene ningún anuncio/publicidad, no realiza peticiones de red y es de Fuente Abierta.
|
||||
La misma no contiene ningún anuncio/publicidad, no realiza peticiones de red y es de Fuente Abierta.
|
6
fastlane/metadata/android/pt-BR/full_description.txt
Normal file
@@ -0,0 +1,6 @@
|
||||
A principal característica é que você pode digitar mais caracteres deslizando as teclas para os cantos.
|
||||
|
||||
O app foi criado originalmente para desenvolvedores que usam Termux.
|
||||
Agora aperfeiçoado para o uso diário.
|
||||
|
||||
Este aplicativo não contém anúncios, não faz nenhuma solicitação de rede e é Open Source.
|
1
fastlane/metadata/android/ro/title.txt
Normal file
@@ -0,0 +1 @@
|
||||
Unexpected Keyboard
|
6
fastlane/metadata/android/ru-RU/full_description.txt
Normal file
@@ -0,0 +1,6 @@
|
||||
Главная особенность клавиатуры — это возможность легко напечатать любой ASCII-символ жестами в углы клавиш.
|
||||
|
||||
Приложение изначально было разработано для использования с Termux.
|
||||
На данный момент оно также удобно в повседневном использовании.
|
||||
|
||||
Приложение не содержит рекламы, не осуществляет никаких запросов в сеть и имеет открытый исходный код.
|
1
fastlane/metadata/android/ru-RU/title.txt
Normal file
@@ -0,0 +1 @@
|
||||
Unexpected Keyboard
|
6
fastlane/metadata/android/tr-TR/full_description.txt
Normal file
@@ -0,0 +1,6 @@
|
||||
Bu uygulama özünde tuşların kenarlarından kaydırarak daha fazla karakter yazabilmek amacıyla geliştirildi.
|
||||
|
||||
Bu uygulama aslında Termux kullanıcıları için geliştirildi.
|
||||
Artık gündelik kullanım için de uygun.
|
||||
|
||||
Bu uygulama açık kaynaklıdır. Reklam içermez ve internete bağlanmaz.
|
1
fastlane/metadata/android/tr-TR/short_description.txt
Normal file
@@ -0,0 +1 @@
|
||||
Android için hafif ve güvenlik odaklı bir sanal klavye uygulaması.
|
1
fastlane/metadata/android/tr-TR/title.txt
Normal file
@@ -0,0 +1 @@
|
||||
Unexpected Keyboard
|
6
fastlane/metadata/android/uk/full_description.txt
Normal file
@@ -0,0 +1,6 @@
|
||||
Головна особливість полягає в тому, що ви можете вводити більше символів, проводячи клавіші до кутів.
|
||||
|
||||
Ця програма спочатку була розроблена для програмістів, які використовують Termux.
|
||||
Тепер ідеально підходить для щоденного використання.
|
||||
|
||||
Ця програма не містить реклами, не надсилає жодних мережевих запитів і має відкритий код.
|
1
fastlane/metadata/android/uk/short_description.txt
Normal file
@@ -0,0 +1 @@
|
||||
Легка та конфіденційна віртуальна клавіатура для Android.
|
1
fastlane/metadata/android/uk/title.txt
Normal file
@@ -0,0 +1 @@
|
||||
Unexpected Keyboard
|
1
fastlane/metadata/android/vi/title.txt
Normal file
@@ -0,0 +1 @@
|
||||
Unexpected Keyboard
|
6
fastlane/metadata/android/zh-CN/full_description.txt
Normal file
@@ -0,0 +1,6 @@
|
||||
此应用的主要功能是,通过将按键沿四角滑动,您可以输入更多字符。
|
||||
|
||||
此应用最初是为使用 Termux 的程序员而设计的。
|
||||
现在对于日常使用来说也很完美。
|
||||
|
||||
此应用没有广告,不会发送任何网络请求,而且是开源的。
|
1
fastlane/metadata/android/zh-CN/short_description.txt
Normal file
@@ -0,0 +1 @@
|
||||
适用于 Android 的轻量级、注重隐私的虚拟键盘。
|
1
fastlane/metadata/android/zh-CN/title.txt
Normal file
@@ -0,0 +1 @@
|
||||
Unexpected Keyboard
|
@@ -1,7 +1,7 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
# Generates the list of layouts in res/values/layouts.xml from the layout files
|
||||
# in res/xml. Every layouts must have a 'name' attribute to be listed.
|
||||
# in srcs/layouts. Every layouts must have a 'name' attribute to be listed.
|
||||
|
||||
import itertools as it
|
||||
import sys, os, glob
|
||||
@@ -11,11 +11,6 @@ import xml.etree.ElementTree as XML
|
||||
# are sorted alphabetically.
|
||||
FIRST_LAYOUTS = [ "latn_qwerty_us", "latn_colemak", "latn_dvorak" ]
|
||||
|
||||
# File names that are known not to be layouts. Avoid warning about them.
|
||||
KNOWN_NOT_LAYOUT = set([
|
||||
"number_row", "numpad", "pin", "bottom_row", "settings", "method",
|
||||
"greekmath", "numeric" ])
|
||||
|
||||
# Read a layout from a file. Returns [None] if [fname] is not a layout.
|
||||
def read_layout(fname):
|
||||
root = XML.parse(fname).getroot()
|
||||
@@ -28,9 +23,7 @@ def read_layouts(files):
|
||||
for layout_file in files:
|
||||
layout_id, _ = os.path.splitext(os.path.basename(layout_file))
|
||||
layout = read_layout(layout_file)
|
||||
if layout_id in KNOWN_NOT_LAYOUT:
|
||||
continue
|
||||
elif layout == None:
|
||||
if layout == None:
|
||||
print("Not a layout file: %s" % layout_file)
|
||||
elif layout["name"] == None:
|
||||
print("Layout doesn't have a name: %s" % layout_id)
|
||||
@@ -66,6 +59,6 @@ def generate_arrays(out, layouts):
|
||||
XML.indent(root)
|
||||
XML.ElementTree(element=root).write(out, encoding="unicode", xml_declaration=True)
|
||||
|
||||
layouts = sort_layouts(read_layouts(glob.glob("res/xml/*.xml")))
|
||||
layouts = sort_layouts(read_layouts(glob.glob("srcs/layouts/*.xml")))
|
||||
with open("res/values/layouts.xml", "w") as out:
|
||||
generate_arrays(out, layouts)
|
||||
|