chore(android): Merge remote-tracking branch 'origin/master' into refactor/android/engine-package
73
HISTORY.md
|
|
@ -1,5 +1,57 @@
|
|||
# Keyman Version History
|
||||
|
||||
## 17.0.33 alpha 2023-01-23
|
||||
|
||||
* chore: Xcode 14.2 update (#8015)
|
||||
|
||||
## 17.0.32 alpha 2023-01-20
|
||||
|
||||
* fix(ios): use mobile mode for keyboard download pages (#8042)
|
||||
* docs(common/resources): Update configure step in Docker readme (#8034)
|
||||
* fix(linux): JSON File missing after installation (#8040)
|
||||
|
||||
## 17.0.31 alpha 2023-01-19
|
||||
|
||||
* chore: git tag with release@semver (#8035)
|
||||
* fix(linux): Properly set context after changing IP (#8026)
|
||||
* chore(linux): use faster zero-length string check (#8037)
|
||||
* chore(linux): log failures to `km_kbp_context_clear(context)` (#8036)
|
||||
* chore(linux): Update recommended extension (#8038)
|
||||
|
||||
## 17.0.30 alpha 2023-01-17
|
||||
|
||||
* chore(linux): Fix vertical alignment of label (#8016)
|
||||
* fix(common): update sentry release identifiers to support semver (#8031)
|
||||
|
||||
## 17.0.29 alpha 2023-01-16
|
||||
|
||||
* fix(linux): Fix crash (un-)installing shared keyboard (#8020)
|
||||
* chore(linux): Don't report KeyboardInterrupt to Sentry (#8021)
|
||||
* chore(linux): Update sample settings (#8018)
|
||||
* feat(linux): Enhance tab completion in km-package-install (#8005)
|
||||
|
||||
## 17.0.28 alpha 2023-01-12
|
||||
|
||||
* feat(linux): Display error messages in the UI (#8006)
|
||||
* bug(linux): Empty keyboard after failed installation (#8008)
|
||||
|
||||
## 17.0.27 alpha 2023-01-11
|
||||
|
||||
* chore(linux): Refactor completion script (#8002)
|
||||
|
||||
## 17.0.26 alpha 2023-01-10
|
||||
|
||||
* feat(linux): Add Back button to "Download Keyman Keyboards" dialog (#7994)
|
||||
* feat(linux): List fonts in the uninstall confirmation dialog (#7995)
|
||||
|
||||
## 17.0.25 alpha 2023-01-09
|
||||
|
||||
* chore(linux): Remove unnecessary variable (#7988)
|
||||
|
||||
## 17.0.24 alpha 2023-01-06
|
||||
|
||||
* chore(common/resources): Add Docker readme (#7980)
|
||||
|
||||
## 17.0.23 alpha 2023-01-03
|
||||
|
||||
* fix(linux): add IBUS_HAS_PREFILTER ifdef to linux/ibus-keyman/tests (#7958)
|
||||
|
|
@ -106,6 +158,27 @@
|
|||
* chore: move to 17.0-alpha (#7577)
|
||||
* chore: Move to 17.0 alpha
|
||||
|
||||
## 16.0.133 beta 2023-01-19
|
||||
|
||||
* fix(linux): Properly set context after changing IP (#8025)
|
||||
|
||||
## 16.0.132 beta 2023-01-18
|
||||
|
||||
* docs(windows): update screenshots and documentation for Keyman for Windows config (#8014)
|
||||
|
||||
## 16.0.131 beta 2023-01-16
|
||||
|
||||
* chore(linux): Don't report KeyboardInterrupt to Sentry (#8022)
|
||||
* fix(linux): Fix crash (un-)installing shared keyboard (#8019)
|
||||
|
||||
## 16.0.130 beta 2023-01-09
|
||||
|
||||
* fix(windows): kmshell -ikl install language and enable keyboard (#7856)
|
||||
|
||||
## 16.0.129 beta 2023-01-06
|
||||
|
||||
* fix(android/engine): Add utility for localized strings (#7976)
|
||||
|
||||
## 16.0.128 beta 2022-12-22
|
||||
|
||||
* fix(developer): force ES3 code generation for LMs (#7927)
|
||||
|
|
|
|||
|
|
@ -1 +1 @@
|
|||
17.0.24
|
||||
17.0.34
|
||||
|
|
|
|||
|
|
@ -36,7 +36,7 @@ display_usage ( ) {
|
|||
}
|
||||
|
||||
function makeLocalSentryRelease() {
|
||||
local SENTRY_RELEASE_VERSION="release-$VERSION_WITH_TAG"
|
||||
local SENTRY_RELEASE_VERSION="release@$VERSION_WITH_TAG"
|
||||
echo "Making a Sentry release for tag $SENTRY_RELEASE_VERSION"
|
||||
sentry-cli upload-dif -p keyman-android --include-sources
|
||||
sentry-cli releases -p keyman-android files $SENTRY_RELEASE_VERSION upload-sourcemaps ./
|
||||
|
|
|
|||
|
|
@ -55,7 +55,7 @@ public class SystemKeyboard extends InputMethodService implements OnKeyboardEven
|
|||
if (DependencyUtil.libraryExists(LibraryType.SENTRY) && !Sentry.isEnabled()) {
|
||||
Log.d(TAG, "Initializing Sentry");
|
||||
SentryAndroid.init(getApplicationContext(), options -> {
|
||||
options.setRelease("release-"+com.tavultesoft.kmapro.BuildConfig.VERSION_NAME);
|
||||
options.setRelease("release@"+com.tavultesoft.kmapro.BuildConfig.VERSION_NAME);
|
||||
options.setEnvironment(com.tavultesoft.kmapro.BuildConfig.VERSION_ENVIRONMENT);
|
||||
});
|
||||
}
|
||||
|
|
|
|||
|
|
@ -131,7 +131,7 @@ public class MainActivity extends BaseActivity implements OnKeyboardEventListene
|
|||
checkSendCrashReport();
|
||||
if (KMManager.getMaySendCrashReport()) {
|
||||
SentryAndroid.init(context, options -> {
|
||||
options.setRelease("release-" + com.tavultesoft.kmapro.BuildConfig.VERSION_NAME);
|
||||
options.setRelease("release@" + com.tavultesoft.kmapro.BuildConfig.VERSION_NAME);
|
||||
options.setEnvironment(com.tavultesoft.kmapro.BuildConfig.VERSION_ENVIRONMENT);
|
||||
});
|
||||
}
|
||||
|
|
|
|||
|
|
@ -16,10 +16,12 @@ import androidx.appcompat.app.AppCompatActivity;
|
|||
import androidx.preference.PreferenceManager;
|
||||
|
||||
import com.keyman.engine.util.ContextUtils;
|
||||
import com.keyman.engine.util.KMLog;
|
||||
|
||||
import java.util.Locale;
|
||||
|
||||
public class BaseActivity extends AppCompatActivity {
|
||||
private static final String TAG = "BaseActivity";
|
||||
static ContextWrapper localeUpdatedContext;
|
||||
|
||||
/**
|
||||
|
|
@ -49,6 +51,23 @@ public class BaseActivity extends AppCompatActivity {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Some classes aren't an AppCompatActivity and need this helper to retrieve localized Strings
|
||||
* in the updated locale.
|
||||
* @param defaultContext - the context to fallback if localUpdatedContext is null
|
||||
* @param resID - the resource ID of the string
|
||||
* @return String - localized string
|
||||
*/
|
||||
public static String getString(Context defaultContext, int resID) {
|
||||
Context context = (localeUpdatedContext != null) ? localeUpdatedContext : defaultContext;
|
||||
if (context != null) {
|
||||
return context.getString(resID);
|
||||
};
|
||||
// Shouldn't be here
|
||||
KMLog.LogError(TAG, "context null for getString()");
|
||||
return "";
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void attachBaseContext(Context newBase) {
|
||||
// Override the app locale using the BCP 47 tag from shared preferences
|
||||
|
|
|
|||
|
|
@ -1288,7 +1288,7 @@ final class KMKeyboard extends WebView {
|
|||
}
|
||||
|
||||
try {
|
||||
String hintText = context.getString(R.string.help_bubble_text);
|
||||
String hintText = BaseActivity.getString(this.context, R.string.help_bubble_text);
|
||||
|
||||
// To ensure that the localized text is properly escaped, we'll use JSON utilities. Since
|
||||
// there's no direct string encoder, we'll just wrap it in an object and unwrap it in JS.
|
||||
|
|
|
|||
|
|
@ -59,7 +59,7 @@ if builder_start_action build; then
|
|||
static readonly VERSION_TAG = \"$VERSION_TAG\";
|
||||
static readonly VERSION_WITH_TAG = \"$VERSION_WITH_TAG\";
|
||||
static readonly VERSION_ENVIRONMENT = \"$VERSION_ENVIRONMENT\";
|
||||
static readonly SENTRY_RELEASE = \"release-$VERSION_WITH_TAG\";
|
||||
static readonly SENTRY_RELEASE = \"release@$VERSION_WITH_TAG\";
|
||||
}
|
||||
}
|
||||
" > ./version.inc.ts
|
||||
|
|
|
|||
|
|
@ -49,7 +49,7 @@ int keyman_sentry_init(bool is_keyman_developer, const char *logger) {
|
|||
ILFree(pidl);
|
||||
}
|
||||
|
||||
sentry_options_set_release(options, "release-" KEYMAN_VersionWithTag); // matches git tag
|
||||
sentry_options_set_release(options, "release@" KEYMAN_VersionWithTag); // matches git tag
|
||||
sentry_options_set_environment(options, KEYMAN_Environment); // stable, beta, alpha, test, local
|
||||
|
||||
// We don't currently need to set this, because it will be same path
|
||||
|
|
|
|||
|
|
@ -341,7 +341,7 @@ begin
|
|||
|
||||
// Note: system proxy is used automatically if no proxy is defined
|
||||
|
||||
o.Release := 'release-'+CKeymanVersionInfo.VersionWithTag; // matches git tag
|
||||
o.Release := 'release@'+CKeymanVersionInfo.VersionWithTag; // matches git tag
|
||||
o.Environment := CKeymanVersionInfo.Environment; // stable, beta, alpha, test, local
|
||||
|
||||
if kscfCaptureExceptions in FFlags
|
||||
|
|
|
|||
|
|
@ -14,6 +14,11 @@ using namespace kmx;
|
|||
|
||||
#include <chrono>
|
||||
|
||||
/**
|
||||
* \def MEDIUM_BUFFER_SIZE not too big, not too small
|
||||
*/
|
||||
#define MEDIUM_BUFFER_SIZE (128 * 7)
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#define _USE_WINDOWS
|
||||
#endif
|
||||
|
|
@ -58,7 +63,7 @@ int km::kbp::kmx::DebugLog_1(const char *file, int line, const char *function, c
|
|||
return 0;
|
||||
|
||||
char windowinfo[1024];
|
||||
sprintf(windowinfo,
|
||||
snprintf(windowinfo, 1024,
|
||||
"%ld" TAB //"TickCount" TAB
|
||||
"%s:%d" TAB //"SourceFile" TAB
|
||||
"%s" TAB //"Function"
|
||||
|
|
@ -108,10 +113,10 @@ const char *km::kbp::kmx::Debug_VirtualKey(KMX_WORD vk) {
|
|||
}
|
||||
|
||||
if (vk < 256) {
|
||||
sprintf(buf, "['%s' 0x%x]", s_key_names[vk], vk);
|
||||
snprintf(buf, 256, "['%s' 0x%x]", s_key_names[vk], vk);
|
||||
}
|
||||
else {
|
||||
sprintf(buf, "[0x%x]", vk);
|
||||
snprintf(buf, 256, "[0x%x]", vk);
|
||||
}
|
||||
return buf;
|
||||
}
|
||||
|
|
@ -129,7 +134,7 @@ const char *km::kbp::kmx::Debug_UnicodeString(PKMX_WCHAR s, int x) {
|
|||
bufout[x][0] = 0;
|
||||
for (p = s, q = bufout[x]; *p && (p - s < 128); p++)
|
||||
{
|
||||
sprintf(q, "U+%4.4X ", *p);
|
||||
snprintf(q, MEDIUM_BUFFER_SIZE, "U+%4.4X ", *p);
|
||||
q = strchr(q, 0);
|
||||
}
|
||||
//WideCharToMultiByte(CP_ACP, 0, buf, -1, bufout, 128, NULL, NULL);
|
||||
|
|
@ -149,7 +154,7 @@ const char *km::kbp::kmx::Debug_UnicodeString(std::u16string s, int x) {
|
|||
bufout[x][0] = 0;
|
||||
for (q = bufout[x]; (intptr_t)(q-bufout[x]) < (128*7) && p != s.end(); p++)
|
||||
{
|
||||
sprintf(q, "U+%4.4X ", *p); q = strchr(q, 0);
|
||||
snprintf(q, MEDIUM_BUFFER_SIZE, "U+%4.4X ", *p); q = strchr(q, 0);
|
||||
}
|
||||
return bufout[x];
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ const Sentry = require("@sentry/node");
|
|||
Sentry.init({
|
||||
dsn: 'https://39b25a09410349a58fe12aaf721565af@o1005580.ingest.sentry.io/5983519', // Keyman Developer
|
||||
environment: environment.versionEnvironment,
|
||||
release: environment.versionWithTag
|
||||
release: 'release@'+environment.versionWithTag
|
||||
});
|
||||
|
||||
import express = require('express');
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@
|
|||
Sentry.init({
|
||||
dsn: 'https://39b25a09410349a58fe12aaf721565af@o1005580.ingest.sentry.io/5983519', // Keyman Developer
|
||||
environment: '$VERSION_ENVIRONMENT',
|
||||
release: 'release-$VERSION_WITH_TAG'
|
||||
release: 'release@$VERSION_WITH_TAG'
|
||||
});
|
||||
|
||||
function keymanEnableDiagnostics() {
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@
|
|||
Sentry.init({
|
||||
dsn: 'https://39b25a09410349a58fe12aaf721565af@o1005580.ingest.sentry.io/5983519', // Keyman Developer
|
||||
environment: '$Environment',
|
||||
release: 'release-$VersionWithTag'
|
||||
release: 'release@$VersionWithTag'
|
||||
});
|
||||
|
||||
function keymanEnableDiagnostics() {
|
||||
|
|
|
|||
|
|
@ -41,4 +41,4 @@ cd "$KEYMAN_ROOT/developer/src"
|
|||
|
||||
echo "Uploading symbols for developer/"
|
||||
sentry-cli upload-dif -p keyman-developer -t breakpad -t pdb . --include-sources
|
||||
sentry-cli releases -p keyman-developer files "release-$VERSION_WITH_TAG" upload-sourcemaps ./TIKE/xml ../bin/server ./kmlmc/dist
|
||||
sentry-cli releases -p keyman-developer files "release@$VERSION_WITH_TAG" upload-sourcemaps ./TIKE/xml ../bin/server ./kmlmc/dist
|
||||
|
|
|
|||
|
|
@ -2,11 +2,12 @@
|
|||
// See http://go.microsoft.com/fwlink/?LinkId=827846
|
||||
// for the documentation about the extensions.json format
|
||||
"recommendations": [
|
||||
"asabil.meson",
|
||||
"mesonbuild.mesonbuild",
|
||||
"editorconfig.editorconfig",
|
||||
"ms-python.python",
|
||||
"mads-hartmann.bash-ide-vscode",
|
||||
"timonwong.shellcheck",
|
||||
"maelvalais.autoconf"
|
||||
"maelvalais.autoconf",
|
||||
"webfreak.debug",
|
||||
]
|
||||
}
|
||||
|
|
|
|||
|
|
@ -24,14 +24,17 @@
|
|||
"valuesFormatting": "parseText"
|
||||
},
|
||||
{
|
||||
// Mount the Keyman root directory as a Shared Folder in the VM.
|
||||
// kill ibus-engine-keyman, if running
|
||||
// start: gdbserver 10.3.0.53:2345 /media/sf_Develop/keyman/keyman/linux/ibus-keyman/src/ibus-engine-keyman
|
||||
// then attach debugger in vscode
|
||||
// Replace the IP address after `gdbserver` with the IP address of the host machine.
|
||||
// Replace the IP address below with the address of the VM running gdbserver.
|
||||
"type": "gdb",
|
||||
"request": "attach",
|
||||
"name": "Attach to gdbserver",
|
||||
"executable": "./linux/ibus-keyman/src/ibus-engine-keyman",
|
||||
"target": "10.3.0.53:2345",
|
||||
"name": "Attach to gdbserver (ibus-keyman)",
|
||||
"executable": "${workspaceFolder}/linux/ibus-keyman/src/ibus-engine-keyman",
|
||||
"target": "10.3.0.52:2345",
|
||||
"remote": true,
|
||||
"cwd": "${workspaceFolder}/linux/ibus-keyman",
|
||||
"valuesFormatting": "parseText"
|
||||
|
|
|
|||
|
|
@ -143,9 +143,9 @@
|
|||
"CPPFLAGS=\"-DG_MESSAGES_DEBUG -I${workspaceFolder}/core/build/arch/debug/include/ -I${workspaceFolder}/common/include/ -I${workspaceFolder}/core/include/\"",
|
||||
"CFLAGS=\"-g -O0\"",
|
||||
"CXXFLAGS=\"-g -O0\"",
|
||||
"KEYMAN_PROC_LIBS=\"-L${workspaceFolder}/common/core/desktop/build/arch/debug/src -lkmnkbp0\"",
|
||||
"KEYMAN_PROC_CFLAGS=\"-I${workspaceFolder}/common/core/desktop/build/arch/debug/include -I${workspaceFolder}/common/core/desktop/include\"",
|
||||
"PKG_CONFIG_PATH=${workspaceFolder}/common/core/desktop/build/arch/debug/meson-private"
|
||||
"KEYMAN_PROC_LIBS=\"-L${workspaceFolder}/core/build/arch/debug/src -lkmnkbp0\"",
|
||||
"KEYMAN_PROC_CFLAGS=\"-I${workspaceFolder}/core/build/arch/debug/include -I${workspaceFolder}/core/include -I${workspaceFolder}/common/include\"",
|
||||
"PKG_CONFIG_PATH=${workspaceFolder}/core/build/arch/debug/meson-private"
|
||||
],
|
||||
"options": {
|
||||
"cwd": "${workspaceFolder}/linux/ibus-keyman"
|
||||
|
|
|
|||
117
docs/websites/README.md
Normal file
|
|
@ -0,0 +1,117 @@
|
|||
# How to Set Up a Local Web Server for the Keyman Web Pages
|
||||
|
||||
Currently, most of the Keyman websites are running via IIS. Refer to the Keyman [wiki](https://github.com/keymanapp/keyman/wiki/How-to-set-up-a-local-web-server-for-the-Keyman-web-pages) for setting that up on Windows 10.
|
||||
|
||||
To make IIS redirects compatible with the Docker sites below, see
|
||||
https://github.com/keymanapp/keyman.com/issues/337#issuecomment-1336339387
|
||||
|
||||
As the websites get migrated to Apache via Docker, follow the installation steps below:
|
||||
|
||||
## Pre-requisite Installs
|
||||
* [Docker Desktop](https://www.docker.com/products/docker-desktop/)
|
||||
|
||||
On Windows, Docker will need either:
|
||||
* Hyper-V or
|
||||
* WSL 2.0 - Install with this guide:
|
||||
https://learn.microsoft.com/en-us/windows/wsl/tutorials/wsl-containers
|
||||
* WSL will then need a Linux image (e.g. Ubuntu app) from the Microsoft Store
|
||||
|
||||
#### Other Docker Notes
|
||||
Docker tends to throttle Docker image downloads, so some developer offices may want to set up a proxy server. If the proxy server is set up, carefully edit the JSON file per in Docker Settings -> Docker Engine https://docs.docker.com/registry/recipes/mirror/#configure-the-docker-daemon and click 'Apply & Restart'. Note the example (lingnet) is for running inside the Linguistics Institute (Chiang Mai)
|
||||
|
||||
```
|
||||
"registry-mirrors": ["https://docker.io.registry.lingnet/"],
|
||||
"insecure-registries" : [
|
||||
"docker.io.registry.lingnet",
|
||||
"registry.lingnet"
|
||||
]
|
||||
```
|
||||
|
||||
## Builder BASH Script Actions
|
||||
|
||||
#### Stop the Docker container
|
||||
1. Run `./build.sh stop`
|
||||
|
||||
This stops the Docker container for the site.
|
||||
|
||||
#### Build the Docker image
|
||||
1. Run `./build.sh build`.
|
||||
|
||||
This downloads and builds the Docker images needed for the site.
|
||||
|
||||
#### Configure
|
||||
1. Run `./build.sh configure`.
|
||||
|
||||
This step is currently not needed
|
||||
|
||||
#### Start the Docker container
|
||||
1. Run `./build.sh start`.
|
||||
|
||||
This maps the local directory to the the Docker image.
|
||||
Then, it creates a link of the PHP dependencies in Docker image from /var/www/vendor/ to /var/www/html/vendor.
|
||||
The link file also appears locally.
|
||||
|
||||
After this, you can access the website at the following ports:
|
||||
|
||||
| Website | URL |
|
||||
|--------------|-----------------------|
|
||||
|help.keyman | http://localhost:8055 |
|
||||
|keymanweb.com | http://localhost:8057 |
|
||||
|
||||
#### Remove the Docker container and image
|
||||
1. Run `./build.sh clean`.
|
||||
|
||||
#### Running tests
|
||||
Checks for broken links
|
||||
1. Run `./build.sh test`
|
||||
|
||||
---------
|
||||
|
||||
## Kubernetes Deployment
|
||||
For production, the websites are deployed with Kubernetes.
|
||||
|
||||
|
||||
### How to run help.keyman.com locally with Docker Desktop's Kubernetes singlenode cluster
|
||||
|
||||
For testing Kubernetes deployment, there are yaml files under the corresponding website's repo: `/resources/kubectl`, that cover local developer testing.
|
||||
|
||||
### Pre-requisites
|
||||
On the host machine, install [Docker](https://docs.docker.com/get-docker/), then enable Kubernetes in the settings. Ensure you have built a help-keyman-app Docker image, and either tag it `docker.dallas.languagetechnology.org/keyman/help-keyman-app` or modify the `app-php` containers `image:` value to match you local copy's name.
|
||||
|
||||
### Deploying to a desktop cluster
|
||||
To deploy the dev version to the cluster do the following:
|
||||
1. Ensure your `kubectl` context is set to `docker-desktop`, though the Docker Desktop systray icon or by running:
|
||||
```bash
|
||||
$> kubectl config use-context docker-desktop
|
||||
```
|
||||
2. Create a keyman namespace if it does not already exist:
|
||||
```bash
|
||||
$> kubectl create ns keyman
|
||||
```
|
||||
3. Apply the configs for the resources and start the pod:
|
||||
```bash
|
||||
$> kubectl --namespace keyman apply \
|
||||
-f resources/kubectl/help-kubectl-dev.yaml \
|
||||
-f resources/kubectl/help-kubectl.yaml
|
||||
```
|
||||
### Testing the site and `/api/deploy` webhook endpoint
|
||||
The site can be reached on http://localhost:30080/ via web browser, and the deploy api is on http://localhost:30900/api/deploy, and can be activated like so:
|
||||
```bash
|
||||
$> curl -v --request POST \
|
||||
-H "Content-Type: application/json" \
|
||||
-H "X-Hub-Signature-256: sha256=49af8531106a369bfee369f91dadec597e8ea3992ec2802bbe655be0ece17f15" \
|
||||
--data '{"action":"push","ref":"refs/heads/staging"}' \
|
||||
http://localhost:30900/api/deploy
|
||||
```
|
||||
This simulates enough of a GitHub webhook push event to pass validation on the responder.
|
||||
|
||||
### Clean up after testing
|
||||
|
||||
To remove the k8s pod and resources, and delete everything do:
|
||||
```bash
|
||||
$> kubectl --namespace=keyman delete {pod,cm,svc,secret,pvc}/help-keyman-com
|
||||
```
|
||||
Or just delete the pod and keep the resources for further testing:
|
||||
```bash
|
||||
$> kubectl --namespace=keyman delete pod/help-keyman-com
|
||||
```
|
||||
|
|
@ -1,5 +1,5 @@
|
|||
github "marmelroy/Zip"
|
||||
github "DaveWoodCom/XCGLogger" ~> 6.1.0
|
||||
github "devicekit/DeviceKit" ~> 2.3
|
||||
github "devicekit/DeviceKit" ~> 5.0
|
||||
github "ashleymills/Reachability.swift"
|
||||
github "getsentry/sentry-cocoa" ~> 6.2.1
|
||||
github "getsentry/sentry-cocoa" ~> 6.2.1
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
github "DaveWoodCom/XCGLogger" "6.1.0"
|
||||
github "ashleymills/Reachability.swift" "v5.0.0"
|
||||
github "devicekit/DeviceKit" "2.3.0"
|
||||
github "ashleymills/Reachability.swift" "v5.1.0"
|
||||
github "devicekit/DeviceKit" "5.0.0"
|
||||
github "getsentry/sentry-cocoa" "6.2.1"
|
||||
github "marmelroy/Zip" "1.1.0"
|
||||
github "marmelroy/Zip" "2.1.2"
|
||||
|
|
|
|||
|
|
@ -1670,7 +1670,7 @@
|
|||
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
|
||||
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
||||
INFOPLIST_FILE = SystemKeyboard/Info.plist;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 12.1;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 12.2;
|
||||
LD_RUNPATH_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
"@executable_path/Frameworks",
|
||||
|
|
@ -1716,7 +1716,7 @@
|
|||
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
|
||||
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
||||
INFOPLIST_FILE = SystemKeyboard/Info.plist;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 12.1;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 12.2;
|
||||
LD_RUNPATH_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
"@executable_path/Frameworks",
|
||||
|
|
@ -1851,7 +1851,7 @@
|
|||
DYLIB_COMPATIBILITY_VERSION = 1;
|
||||
DYLIB_CURRENT_VERSION = 1;
|
||||
DYLIB_INSTALL_NAME_BASE = "@rpath";
|
||||
ENABLE_BITCODE = YES;
|
||||
ENABLE_BITCODE = NO;
|
||||
GCC_C_LANGUAGE_STANDARD = gnu11;
|
||||
GCC_DYNAMIC_NO_PIC = NO;
|
||||
GCC_OPTIMIZATION_LEVEL = 0;
|
||||
|
|
@ -1859,7 +1859,7 @@
|
|||
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
||||
INFOPLIST_FILE = KeymanEngine/Info.plist;
|
||||
INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 12.1;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 12.2;
|
||||
LD_RUNPATH_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
"@executable_path/Frameworks",
|
||||
|
|
@ -1907,14 +1907,14 @@
|
|||
DYLIB_COMPATIBILITY_VERSION = 1;
|
||||
DYLIB_CURRENT_VERSION = 1;
|
||||
DYLIB_INSTALL_NAME_BASE = "@rpath";
|
||||
ENABLE_BITCODE = YES;
|
||||
ENABLE_BITCODE = NO;
|
||||
ENABLE_NS_ASSERTIONS = NO;
|
||||
GCC_C_LANGUAGE_STANDARD = gnu11;
|
||||
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
|
||||
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
||||
INFOPLIST_FILE = KeymanEngine/Info.plist;
|
||||
INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 12.1;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 12.2;
|
||||
LD_RUNPATH_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
"@executable_path/Frameworks",
|
||||
|
|
@ -1938,7 +1938,7 @@
|
|||
isa = XCBuildConfiguration;
|
||||
baseConfigurationReference = F27FCAF6157FD95E00FBBA20 /* Keyman-lib.xcconfig */;
|
||||
buildSettings = {
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 9.0;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 12.2;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
STRIP_INSTALLED_PRODUCT = NO;
|
||||
STRIP_STYLE = all;
|
||||
|
|
@ -1951,7 +1951,7 @@
|
|||
isa = XCBuildConfiguration;
|
||||
baseConfigurationReference = F27FCAF6157FD95E00FBBA20 /* Keyman-lib.xcconfig */;
|
||||
buildSettings = {
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 9.0;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 12.2;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
SUPPORTS_MACCATALYST = NO;
|
||||
};
|
||||
|
|
@ -1980,7 +1980,7 @@
|
|||
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
|
||||
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
||||
INFOPLIST_FILE = "KeymanEngine/resources/Keyman.bundle/Contents/Resources/KeymanEngine-Info.plist";
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 12.1;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 12.2;
|
||||
LD_RUNPATH_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
"@executable_path/Frameworks",
|
||||
|
|
@ -2017,7 +2017,7 @@
|
|||
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
|
||||
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
||||
INFOPLIST_FILE = "KeymanEngine/resources/Keyman.bundle/Contents/Resources/KeymanEngine-Info.plist";
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 12.1;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 12.2;
|
||||
LD_RUNPATH_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
"@executable_path/Frameworks",
|
||||
|
|
@ -2069,7 +2069,7 @@
|
|||
GCC_WARN_UNINITIALIZED_AUTOS = YES;
|
||||
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 9.0;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 12.2;
|
||||
KEYMAN_ROOT = "$(SRCROOT)/../../..";
|
||||
SKIP_INSTALL = YES;
|
||||
SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG;
|
||||
|
|
@ -2102,7 +2102,7 @@
|
|||
DYLIB_COMPATIBILITY_VERSION = 1;
|
||||
DYLIB_CURRENT_VERSION = 1;
|
||||
DYLIB_INSTALL_NAME_BASE = "@rpath";
|
||||
ENABLE_BITCODE = YES;
|
||||
ENABLE_BITCODE = NO;
|
||||
GCC_C_LANGUAGE_STANDARD = gnu11;
|
||||
GCC_DYNAMIC_NO_PIC = NO;
|
||||
GCC_OPTIMIZATION_LEVEL = 0;
|
||||
|
|
@ -2110,7 +2110,7 @@
|
|||
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
||||
INFOPLIST_FILE = KeymanEngine/Info.plist;
|
||||
INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 12.1;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 12.2;
|
||||
LD_RUNPATH_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
"@executable_path/Frameworks",
|
||||
|
|
@ -2134,7 +2134,7 @@
|
|||
isa = XCBuildConfiguration;
|
||||
baseConfigurationReference = F27FCAF6157FD95E00FBBA20 /* Keyman-lib.xcconfig */;
|
||||
buildSettings = {
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 9.0;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 12.2;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
SUPPORTS_MACCATALYST = NO;
|
||||
};
|
||||
|
|
@ -2153,7 +2153,7 @@
|
|||
DEFINES_MODULE = YES;
|
||||
DEVELOPMENT_TEAM = 3YE4W86L3G;
|
||||
ENABLE_BITCODE = NO;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 12.1;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 12.2;
|
||||
LD_RUNPATH_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
"@executable_path/Frameworks",
|
||||
|
|
@ -2203,7 +2203,7 @@
|
|||
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
|
||||
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
||||
INFOPLIST_FILE = SystemKeyboard/Info.plist;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 12.1;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 12.2;
|
||||
LD_RUNPATH_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
"@executable_path/Frameworks",
|
||||
|
|
@ -2292,7 +2292,7 @@
|
|||
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
|
||||
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
||||
INFOPLIST_FILE = "KeymanEngine/resources/Keyman.bundle/Contents/Resources/KeymanEngine-Info.plist";
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 12.1;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 12.2;
|
||||
LD_RUNPATH_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
"@executable_path/Frameworks",
|
||||
|
|
@ -2344,7 +2344,7 @@
|
|||
GCC_WARN_UNINITIALIZED_AUTOS = YES;
|
||||
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 9.0;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 12.2;
|
||||
KEYMAN_ROOT = "$(SRCROOT)/../../..";
|
||||
SKIP_INSTALL = YES;
|
||||
SWIFT_ACTIVE_COMPILATION_CONDITIONS = "DEBUG NO_SENTRY";
|
||||
|
|
@ -2387,7 +2387,7 @@
|
|||
GCC_WARN_UNINITIALIZED_AUTOS = YES;
|
||||
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 9.0;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 12.2;
|
||||
KEYMAN_ROOT = "$(SRCROOT)/../../..";
|
||||
SKIP_INSTALL = YES;
|
||||
SWIFT_COMPILATION_MODE = wholemodule;
|
||||
|
|
@ -2408,7 +2408,7 @@
|
|||
DEFINES_MODULE = YES;
|
||||
DEVELOPMENT_TEAM = 3YE4W86L3G;
|
||||
ENABLE_BITCODE = NO;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 12.1;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 12.2;
|
||||
LD_RUNPATH_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
"@executable_path/Frameworks",
|
||||
|
|
@ -2441,7 +2441,7 @@
|
|||
DEFINES_MODULE = YES;
|
||||
DEVELOPMENT_TEAM = 3YE4W86L3G;
|
||||
ENABLE_BITCODE = NO;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 12.1;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 12.2;
|
||||
LD_RUNPATH_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
"@executable_path/Frameworks",
|
||||
|
|
|
|||
|
|
@ -35,7 +35,7 @@ public class SentryManager {
|
|||
let infoDict = Bundle(for: SentryManager.self).infoDictionary
|
||||
let versionWithTag = infoDict?["KeymanVersionWithTag"] as? String ?? ""
|
||||
let environment = infoDict?["KeymanVersionEnvironment"] as? String ?? ""
|
||||
let release = "release-\(versionWithTag)"
|
||||
let release = "release@\(versionWithTag)"
|
||||
|
||||
let options = Sentry.Options()
|
||||
options.dsn = "https://d14d2efb594e4345b8367dbb61ebceaf@o1005580.ingest.sentry.io/5983521"
|
||||
|
|
|
|||
|
|
@ -43,6 +43,16 @@ class PackageWebViewController: UIViewController, WKNavigationDelegate {
|
|||
let prefs = WKPreferences()
|
||||
prefs.javaScriptEnabled = true
|
||||
|
||||
if #available(iOS 13.0, *) {
|
||||
/**
|
||||
In iPadOS 16 and above WKWebView defaults to lying about its user-agent,
|
||||
telling the web server that it is a mac. We can avoid this with .mobile:
|
||||
*/
|
||||
let pref = WKWebpagePreferences.init()
|
||||
pref.preferredContentMode = .mobile
|
||||
config.defaultWebpagePreferences = pref
|
||||
}
|
||||
|
||||
// Inject a meta viewport tag into the head of the file if it doesn't exist
|
||||
let metaViewportInjection = """
|
||||
if(!document.querySelectorAll('meta[name=viewport]').length) {
|
||||
|
|
|
|||
|
|
@ -101,7 +101,20 @@ public class KeyboardSearchViewController: UIViewController, WKNavigationDelegat
|
|||
}
|
||||
|
||||
public override func loadView() {
|
||||
let webView = WKWebView()
|
||||
|
||||
let config = WKWebViewConfiguration()
|
||||
|
||||
if #available(iOS 13.0, *) {
|
||||
/**
|
||||
In iPadOS 16 and above WKWebView defaults to lying about its user-agent,
|
||||
telling the web server that it is a mac. We can avoid this with .mobile:
|
||||
*/
|
||||
let pref = WKWebpagePreferences.init()
|
||||
pref.preferredContentMode = .mobile
|
||||
config.defaultWebpagePreferences = pref
|
||||
}
|
||||
|
||||
let webView = WKWebView.init(frame: CGRect.zero, configuration: config)
|
||||
webView.navigationDelegate = self
|
||||
if let languageCode = languageCode {
|
||||
let baseURL = KeyboardSearchViewController.ENDPOINT_ROOT
|
||||
|
|
|
|||
|
|
@ -1123,7 +1123,7 @@
|
|||
GCC_PREFIX_HEADER = "Keyman/Keyman-Prefix.pch";
|
||||
GCC_PREPROCESSOR_DEFINITIONS = "$(inherited)";
|
||||
INFOPLIST_FILE = Keyman/Info.plist;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 12.1;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 12.2;
|
||||
LD_RUNPATH_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
"@executable_path/Frameworks",
|
||||
|
|
@ -1158,7 +1158,7 @@
|
|||
GCC_PRECOMPILE_PREFIX_HEADER = YES;
|
||||
GCC_PREFIX_HEADER = "Keyman/Keyman-Prefix.pch";
|
||||
INFOPLIST_FILE = Keyman/Info.plist;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 12.1;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 12.2;
|
||||
LD_RUNPATH_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
"@executable_path/Frameworks",
|
||||
|
|
@ -1225,7 +1225,7 @@
|
|||
GCC_WARN_UNINITIALIZED_AUTOS = YES;
|
||||
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 9.0;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 12.2;
|
||||
KEYMAN_ROOT = "$(SRCROOT)/../../..";
|
||||
ONLY_ACTIVE_ARCH = NO;
|
||||
OTHER_LDFLAGS = "";
|
||||
|
|
@ -1277,7 +1277,7 @@
|
|||
GCC_WARN_UNINITIALIZED_AUTOS = YES;
|
||||
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 9.0;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 12.2;
|
||||
KEYMAN_ROOT = "$(SRCROOT)/../../..";
|
||||
ONLY_ACTIVE_ARCH = NO;
|
||||
OTHER_CFLAGS = "-DNS_BLOCK_ASSERTIONS=1";
|
||||
|
|
@ -1312,7 +1312,7 @@
|
|||
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
||||
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||
INFOPLIST_FILE = SWKeyboard/Info.plist;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 12.1;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 12.2;
|
||||
LD_RUNPATH_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
"@executable_path/Frameworks",
|
||||
|
|
@ -1355,7 +1355,7 @@
|
|||
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
||||
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||
INFOPLIST_FILE = SWKeyboard/Info.plist;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 12.1;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 12.2;
|
||||
LD_RUNPATH_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
"@executable_path/Frameworks",
|
||||
|
|
@ -1424,7 +1424,7 @@
|
|||
GCC_WARN_UNINITIALIZED_AUTOS = YES;
|
||||
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 9.0;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 12.2;
|
||||
KEYMAN_ROOT = "$(SRCROOT)/../../..";
|
||||
ONLY_ACTIVE_ARCH = NO;
|
||||
OTHER_LDFLAGS = "";
|
||||
|
|
@ -1449,7 +1449,7 @@
|
|||
GCC_PREFIX_HEADER = "Keyman/Keyman-Prefix.pch";
|
||||
GCC_PREPROCESSOR_DEFINITIONS = "$(inherited)";
|
||||
INFOPLIST_FILE = Keyman/Info.plist;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 12.1;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 12.2;
|
||||
LD_RUNPATH_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
"@executable_path/Frameworks",
|
||||
|
|
@ -1493,7 +1493,7 @@
|
|||
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
||||
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||
INFOPLIST_FILE = SWKeyboard/Info.plist;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 12.1;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 12.2;
|
||||
LD_RUNPATH_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
"@executable_path/Frameworks",
|
||||
|
|
|
|||
|
|
@ -222,12 +222,6 @@ if [ $DO_CARTHAGE = true ]; then
|
|||
|
||||
carthage checkout || fail "Carthage dependency loading failed"
|
||||
|
||||
# Carthage sometimes picks the wrong .xcworkspace if two are available in a dependency's repo.
|
||||
# Easiest way to override it - delete the wrong one (or just its scheme)
|
||||
|
||||
# Deleted workspace - a test for proper deployment to CocoaPods. Doesn't matter here.
|
||||
rm -r ./Carthage/Checkouts/DeviceKit/CocoaPodsVerification/ || fail "Carthage dependency loading failed"
|
||||
|
||||
# --no-use-binaries: due to https://github.com/Carthage/Carthage/issues/3134,
|
||||
# which affects the sentry-cocoa dependency.
|
||||
carthage build --use-xcframeworks --no-use-binaries --platform iOS || fail "Carthage dependency loading failed"
|
||||
|
|
|
|||
|
|
@ -461,6 +461,7 @@
|
|||
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
|
||||
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
|
||||
COPY_PHASE_STRIP = NO;
|
||||
ENABLE_BITCODE = NO;
|
||||
ENABLE_STRICT_OBJC_MSGSEND = YES;
|
||||
ENABLE_TESTABILITY = YES;
|
||||
FRAMEWORK_SEARCH_PATHS = (
|
||||
|
|
@ -518,6 +519,7 @@
|
|||
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
|
||||
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
|
||||
COPY_PHASE_STRIP = NO;
|
||||
ENABLE_BITCODE = NO;
|
||||
ENABLE_NS_ASSERTIONS = NO;
|
||||
ENABLE_STRICT_OBJC_MSGSEND = YES;
|
||||
FRAMEWORK_SEARCH_PATHS = (
|
||||
|
|
@ -552,6 +554,7 @@
|
|||
CODE_SIGN_ENTITLEMENTS = KMSample2/KMSample2.entitlements;
|
||||
CODE_SIGN_IDENTITY = "iPhone Developer";
|
||||
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
|
||||
ENABLE_BITCODE = NO;
|
||||
INFOPLIST_FILE = KMSample2/Info.plist;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 12.1;
|
||||
LD_RUNPATH_SEARCH_PATHS = (
|
||||
|
|
@ -577,6 +580,7 @@
|
|||
CODE_SIGN_ENTITLEMENTS = KMSample2/KMSample2.entitlements;
|
||||
CODE_SIGN_IDENTITY = "iPhone Developer";
|
||||
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
|
||||
ENABLE_BITCODE = NO;
|
||||
INFOPLIST_FILE = KMSample2/Info.plist;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 12.1;
|
||||
LD_RUNPATH_SEARCH_PATHS = (
|
||||
|
|
@ -599,6 +603,7 @@
|
|||
CODE_SIGN_ENTITLEMENTS = SWKeyboard/SWKeyboard.entitlements;
|
||||
CODE_SIGN_IDENTITY = "iPhone Developer";
|
||||
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
|
||||
ENABLE_BITCODE = NO;
|
||||
GCC_PREPROCESSOR_DEFINITIONS = (
|
||||
"DEBUG=1",
|
||||
"$(inherited)",
|
||||
|
|
@ -628,6 +633,7 @@
|
|||
CODE_SIGN_ENTITLEMENTS = SWKeyboard/SWKeyboard.entitlements;
|
||||
CODE_SIGN_IDENTITY = "iPhone Developer";
|
||||
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
|
||||
ENABLE_BITCODE = NO;
|
||||
INFOPLIST_FILE = SWKeyboard/Info.plist;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 12.1;
|
||||
LD_RUNPATH_SEARCH_PATHS = (
|
||||
|
|
|
|||
|
|
@ -390,7 +390,7 @@
|
|||
CODE_SIGN_STYLE = Automatic;
|
||||
DEVELOPMENT_TEAM = WHE552KZN5;
|
||||
INFOPLIST_FILE = CalibrationKbd/Info.plist;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 10.0;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 11.0;
|
||||
LD_RUNPATH_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
"@executable_path/Frameworks",
|
||||
|
|
@ -411,7 +411,7 @@
|
|||
CODE_SIGN_STYLE = Automatic;
|
||||
DEVELOPMENT_TEAM = WHE552KZN5;
|
||||
INFOPLIST_FILE = CalibrationKbd/Info.plist;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 10.0;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 11.0;
|
||||
LD_RUNPATH_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
"@executable_path/Frameworks",
|
||||
|
|
@ -548,7 +548,7 @@
|
|||
CODE_SIGN_STYLE = Automatic;
|
||||
DEVELOPMENT_TEAM = WHE552KZN5;
|
||||
INFOPLIST_FILE = KeyboardCalibrator/Info.plist;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 10.0;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 11.0;
|
||||
LD_RUNPATH_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
"@executable_path/Frameworks",
|
||||
|
|
@ -569,7 +569,7 @@
|
|||
CODE_SIGN_STYLE = Automatic;
|
||||
DEVELOPMENT_TEAM = WHE552KZN5;
|
||||
INFOPLIST_FILE = KeyboardCalibrator/Info.plist;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 10.0;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 11.0;
|
||||
LD_RUNPATH_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
"@executable_path/Frameworks",
|
||||
|
|
|
|||
|
|
@ -37,11 +37,7 @@ private class CustomInputView: UIInputView {
|
|||
func setConstraints() {
|
||||
var guide: UILayoutGuide
|
||||
|
||||
if #available(iOS 11.0, *) {
|
||||
guide = self.safeAreaLayoutGuide
|
||||
} else {
|
||||
guide = self.layoutMarginsGuide
|
||||
}
|
||||
guide = self.safeAreaLayoutGuide
|
||||
|
||||
if height != 0 {
|
||||
innerView.heightAnchor.constraint(equalToConstant: height).isActive = true
|
||||
|
|
@ -49,15 +45,9 @@ private class CustomInputView: UIInputView {
|
|||
innerView.heightAnchor.constraint(equalTo: guide.heightAnchor).isActive = true
|
||||
}
|
||||
|
||||
if #available(iOS 11.0, *) {
|
||||
innerView.widthAnchor.constraint(equalTo: guide.widthAnchor).isActive = true
|
||||
innerView.leftAnchor.constraint(equalTo: guide.leftAnchor).isActive = true
|
||||
insetView.widthAnchor.constraint(equalTo: guide.widthAnchor).isActive = true
|
||||
} else {
|
||||
innerView.widthAnchor.constraint(equalTo: self.widthAnchor).isActive = true
|
||||
innerView.leftAnchor.constraint(equalTo: self.leftAnchor).isActive = true
|
||||
insetView.widthAnchor.constraint(equalTo: self.widthAnchor).isActive = true
|
||||
}
|
||||
innerView.widthAnchor.constraint(equalTo: guide.widthAnchor).isActive = true
|
||||
innerView.leftAnchor.constraint(equalTo: guide.leftAnchor).isActive = true
|
||||
insetView.widthAnchor.constraint(equalTo: guide.widthAnchor).isActive = true
|
||||
|
||||
innerView.bottomAnchor.constraint(equalTo: insetView.topAnchor).isActive = true
|
||||
|
||||
|
|
@ -172,13 +162,8 @@ class DummyInputViewController: UIInputViewController {
|
|||
self.view.addSubview(self.nextKeyboardButton)
|
||||
|
||||
var guide: UILayoutGuide
|
||||
if #available(iOS 11.0, *) {
|
||||
guide = self.view.safeAreaLayoutGuide
|
||||
self.nextKeyboardButton.isHidden = !self.needsInputModeSwitchKey || !asSystemKeyboard
|
||||
} else {
|
||||
guide = self.view.layoutMarginsGuide
|
||||
self.nextKeyboardButton.isHidden = false // Seems buggy to vary, and it matters greatly on older devices.
|
||||
}
|
||||
guide = self.view.safeAreaLayoutGuide
|
||||
self.nextKeyboardButton.isHidden = !self.needsInputModeSwitchKey || !asSystemKeyboard
|
||||
|
||||
self.nextKeyboardButton.leftAnchor.constraint(equalTo: guide.leftAnchor).isActive = true
|
||||
self.nextKeyboardButton.bottomAnchor.constraint(equalTo: guide.bottomAnchor).isActive = true
|
||||
|
|
|
|||
|
|
@ -149,11 +149,7 @@ class ViewController: UIViewController {
|
|||
|
||||
@IBAction func performCapture() {
|
||||
let rect = kbdFrame?.cgRectValue
|
||||
if #available(iOS 11.0, *) {
|
||||
capture.insetBottom = self.view.safeAreaInsets.bottom
|
||||
} else {
|
||||
capture.insetBottom = self.view.layoutMargins.bottom
|
||||
}
|
||||
capture.insetBottom = self.view.safeAreaInsets.bottom
|
||||
|
||||
// Determine correct capture mode
|
||||
switch captureMode {
|
||||
|
|
|
|||
|
|
@ -86,6 +86,7 @@ Depends:
|
|||
python3-bs4,
|
||||
python3-gi,
|
||||
python3-sentry-sdk (>= 1.1) | python3-raven,
|
||||
dbus-x11,
|
||||
${misc:Depends},
|
||||
${python3:Depends},
|
||||
Description: Keyman for Linux configuration
|
||||
|
|
|
|||
|
|
@ -123,11 +123,11 @@ static void ibus_keyman_engine_focus_out (IBusEngine *engine);
|
|||
static void ibus_keyman_engine_reset (IBusEngine *engine);
|
||||
static void ibus_keyman_engine_enable (IBusEngine *engine);
|
||||
static void ibus_keyman_engine_disable (IBusEngine *engine);
|
||||
// static void ibus_keyman_engine_set_surrounding_text
|
||||
// (IBusEngine *engine,
|
||||
// IBusText *text,
|
||||
// guint cursor_pos,
|
||||
// guint anchor_pos);
|
||||
static void ibus_keyman_engine_set_surrounding_text
|
||||
(IBusEngine *engine,
|
||||
IBusText *text,
|
||||
guint cursor_pos,
|
||||
guint anchor_pos);
|
||||
// static void ibus_keyman_engine_set_cursor_location
|
||||
// (IBusEngine *engine,
|
||||
// guint x,
|
||||
|
|
@ -201,7 +201,7 @@ ibus_keyman_engine_class_init (IBusKeymanEngineClass *klass)
|
|||
engine_class->enable = ibus_keyman_engine_enable;
|
||||
engine_class->disable = ibus_keyman_engine_disable;
|
||||
|
||||
// engine_class->set_surrounding_text = ibus_keyman_engine_set_surrounding_text;
|
||||
engine_class->set_surrounding_text = ibus_keyman_engine_set_surrounding_text;
|
||||
// engine_class->set_cursor_location = ibus_keyman_engine_set_cursor_location;
|
||||
|
||||
|
||||
|
|
@ -272,17 +272,22 @@ reset_context(IBusEngine *engine) {
|
|||
surrounding_text, context_end - context_start, cursor_pos, anchor_pos);
|
||||
|
||||
current_context_utf8 = get_current_context_text(context);
|
||||
if (!g_str_has_suffix(surrounding_text, current_context_utf8) || !g_utf8_strlen(current_context_utf8, -1)) {
|
||||
if (!(*current_context_utf8) || !g_str_has_suffix(surrounding_text, current_context_utf8)) {
|
||||
g_message("%s: setting context because it has changed from expected", __FUNCTION__);
|
||||
if (km_kbp_context_items_from_utf8(surrounding_text, &context_items) == KM_KBP_STATUS_OK) {
|
||||
enum km_kbp_status_codes status = km_kbp_context_items_from_utf8(surrounding_text, &context_items);
|
||||
if (status == KM_KBP_STATUS_OK) {
|
||||
km_kbp_context_set(context, context_items);
|
||||
km_kbp_context_items_dispose(context_items);
|
||||
} else {
|
||||
km_kbp_context_clear(context);
|
||||
g_message("%s: setting context failed with status code %d", __FUNCTION__, status);
|
||||
}
|
||||
}
|
||||
g_free(surrounding_text);
|
||||
g_free(current_context_utf8);
|
||||
} else {
|
||||
km_kbp_context_clear(context);
|
||||
g_message("%s: client does not support surrounding text", __FUNCTION__);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -978,23 +983,23 @@ ibus_keyman_engine_process_key_event(
|
|||
return TRUE;
|
||||
}
|
||||
|
||||
// static void
|
||||
// ibus_keyman_engine_set_surrounding_text (IBusEngine *engine,
|
||||
// IBusText *text,
|
||||
// guint cursor_pos,
|
||||
// guint anchor_pos)
|
||||
// {
|
||||
// gchar *surrounding_text;
|
||||
// guint context_start = cursor_pos > MAXCONTEXT_ITEMS ? cursor_pos - MAXCONTEXT_ITEMS : 0;
|
||||
// if (cursor_pos != anchor_pos){
|
||||
// g_message("%s: There is a selection", __FUNCTION__);
|
||||
// }
|
||||
// parent_class->set_surrounding_text (engine, text, cursor_pos, anchor_pos);
|
||||
// surrounding_text = g_utf8_substring(ibus_text_get_text(text), context_start, cursor_pos);
|
||||
// g_message("%s: surrounding context is:%u:%s:", __FUNCTION__, cursor_pos - context_start, surrounding_text);
|
||||
// g_free(surrounding_text);
|
||||
// reset_context(engine);
|
||||
// }
|
||||
static void
|
||||
ibus_keyman_engine_set_surrounding_text (IBusEngine *engine,
|
||||
IBusText *text,
|
||||
guint cursor_pos,
|
||||
guint anchor_pos)
|
||||
{
|
||||
// gchar *surrounding_text;
|
||||
// guint context_start = cursor_pos > MAXCONTEXT_ITEMS ? cursor_pos - MAXCONTEXT_ITEMS : 0;
|
||||
// if (cursor_pos != anchor_pos){
|
||||
// g_message("%s: There is a selection", __FUNCTION__);
|
||||
// }
|
||||
parent_class->set_surrounding_text (engine, text, cursor_pos, anchor_pos);
|
||||
// surrounding_text = g_utf8_substring(ibus_text_get_text(text), context_start, cursor_pos);
|
||||
// g_message("%s: surrounding context is:%u:%s:", __FUNCTION__, cursor_pos - context_start, surrounding_text);
|
||||
// g_free(surrounding_text);
|
||||
reset_context(engine);
|
||||
}
|
||||
|
||||
// static void ibus_keyman_engine_set_cursor_location (IBusEngine *engine,
|
||||
// guint x,
|
||||
|
|
|
|||
|
|
@ -37,6 +37,15 @@ def secure_lookup(data, key1, key2 = None):
|
|||
return None
|
||||
|
||||
|
||||
def before_send(event, hint):
|
||||
if 'exc_info' in hint:
|
||||
exc_type, exc_value, tb = hint['exc_info']
|
||||
if isinstance(exc_value, KeyboardInterrupt):
|
||||
# Ignore KeyboardInterrupt exception
|
||||
return None
|
||||
return event
|
||||
|
||||
|
||||
gettext.bindtextdomain('keyman-config', '/usr/share/locale')
|
||||
gettext.textdomain('keyman-config')
|
||||
|
||||
|
|
@ -75,8 +84,9 @@ else:
|
|||
sentry_sdk.init(
|
||||
dsn=SentryUrl,
|
||||
environment=__environment__,
|
||||
release='release-' + __versionwithtag__,
|
||||
release='release@' + __versionwithtag__,
|
||||
integrations=[sentry_logging],
|
||||
before_send=before_send
|
||||
)
|
||||
set_user({'id': hash(getpass.getuser())})
|
||||
with configure_scope() as scope:
|
||||
|
|
@ -94,7 +104,7 @@ else:
|
|||
|
||||
# Note, legacy raven API requires secret (https://github.com/keymanapp/keyman/pull/5787#discussion_r721457909)
|
||||
SentryUrl = "https://1d0edbf2d0dc411b87119b6e92e2c357:e6d5a81ee6944fc79bd9f0cbb1f2c2a4@o1005580.ingest.sentry.io/5983525"
|
||||
client = Client(SentryUrl, environment=__environment__, release='release-' + __versionwithtag__)
|
||||
client = Client(SentryUrl, environment=__environment__, release='release@' + __versionwithtag__)
|
||||
client.user_context({'id': hash(getpass.getuser())})
|
||||
client.tags_context({
|
||||
'app': os.path.basename(sys.argv[0]),
|
||||
|
|
|
|||
|
|
@ -30,13 +30,26 @@ class DownloadKmpWindow(Gtk.Dialog):
|
|||
s = Gtk.ScrolledWindow()
|
||||
self.webview = WebKit2.WebView()
|
||||
self.webview.connect("decide-policy", self._keyman_policy)
|
||||
self.webview.connect("load-changed", self._update_back_button)
|
||||
url = KeymanComUrl + "/go/linux/" + __releaseversion__ + "/download-keyboards"
|
||||
self.webview.load_uri(url)
|
||||
s.add(self.webview)
|
||||
|
||||
self.get_content_area().pack_start(s, True, True, 0)
|
||||
|
||||
self.add_button(_("_Close"), Gtk.ResponseType.CLOSE)
|
||||
hbox = Gtk.Box(spacing=6)
|
||||
self.get_content_area().pack_start(hbox, False, False, 0)
|
||||
|
||||
self.back_button = Gtk.Button.new_with_mnemonic(_("_Back"))
|
||||
self.back_button.set_tooltip_text(_("Back to search"))
|
||||
self.back_button.connect("clicked", self._on_back_clicked)
|
||||
self.back_button.set_sensitive(False)
|
||||
hbox.pack_start(self.back_button, False, False, 0)
|
||||
|
||||
close_button = Gtk.Button.new_with_mnemonic(_("_Close"))
|
||||
close_button.set_tooltip_text(_("Close dialog"))
|
||||
close_button.connect("clicked", self._on_close_clicked)
|
||||
hbox.pack_end(close_button, False, False, 0)
|
||||
|
||||
if self.parentWindow is not None:
|
||||
self.getinfo = GetInfo(self.parentWindow.incomplete_kmp)
|
||||
|
|
@ -44,6 +57,15 @@ class DownloadKmpWindow(Gtk.Dialog):
|
|||
self.resize(800, 450)
|
||||
self.show_all()
|
||||
|
||||
def _update_back_button(self, webview, load_event):
|
||||
self.back_button.set_sensitive(webview.can_go_back())
|
||||
|
||||
def _on_back_clicked(self, button):
|
||||
self.webview.go_back()
|
||||
|
||||
def _on_close_clicked(self, button):
|
||||
self.response(Gtk.ResponseType.CLOSE)
|
||||
|
||||
def _process_kmp(self, url, downloadfile: str):
|
||||
logging.info("Downloading kmp file to %s", downloadfile)
|
||||
if download_kmp_file(url, downloadfile):
|
||||
|
|
@ -52,6 +74,12 @@ class DownloadKmpWindow(Gtk.Dialog):
|
|||
self.response(Gtk.ResponseType.OK)
|
||||
self.close()
|
||||
return True
|
||||
logging.error(_("Downloading kmp file failed"))
|
||||
dialog = Gtk.MessageDialog(
|
||||
self, 0, Gtk.MessageType.ERROR,
|
||||
Gtk.ButtonsType.OK, _("Downloading keyboard file failed"))
|
||||
dialog.run()
|
||||
dialog.destroy()
|
||||
return False
|
||||
|
||||
def _keyman_policy(self, web_view, decision, decision_type):
|
||||
|
|
|
|||
|
|
@ -74,7 +74,10 @@ def get_keyboard_data(keyboardID, weekCache=False):
|
|||
os.chdir(cache_dir)
|
||||
requests_cache.install_cache(cache_name='keyman_cache', backend='sqlite', expire_after=expire_after)
|
||||
now = time.ctime(int(time.time()))
|
||||
response = requests.get(api_url)
|
||||
try:
|
||||
response = requests.get(api_url)
|
||||
except requests.exceptions.RequestException as e: # This is the correct syntax
|
||||
return None
|
||||
logging.debug('Time: {0} / Used Cache: {1}'.format(now, response.from_cache))
|
||||
os.chdir(current_dir)
|
||||
requests_cache.uninstall_cache()
|
||||
|
|
|
|||
|
|
@ -20,7 +20,6 @@ def download_and_install_package(url):
|
|||
"""
|
||||
parsedUrl = urlparse(url)
|
||||
bcp47 = _extract_bcp47(parsedUrl.query)
|
||||
severity = logging.ERROR
|
||||
|
||||
if parsedUrl.scheme == 'keyman':
|
||||
logging.info("downloading " + url)
|
||||
|
|
@ -49,7 +48,7 @@ def download_and_install_package(url):
|
|||
return
|
||||
|
||||
if packageFile and not _install_package(packageFile, bcp47):
|
||||
logging.log(severity, "Can't find file " + url)
|
||||
logging.error("Can't find file " + url)
|
||||
|
||||
|
||||
def _extract_bcp47(query):
|
||||
|
|
|
|||
|
|
@ -74,13 +74,12 @@ class InstallKmp():
|
|||
packageID, ext = os.path.splitext(os.path.basename(inputfile))
|
||||
return packageID.lower()
|
||||
|
||||
def install_kmp_shared(self, inputfile, online=False, language=None):
|
||||
def install_kmp_shared(self, inputfile, language=None):
|
||||
"""
|
||||
Install a kmp file to /usr/local/share/keyman
|
||||
|
||||
Args:
|
||||
inputfile (str): path to kmp file
|
||||
online (bool, default=False): whether to attempt to get online keyboard data
|
||||
"""
|
||||
self._check_keyman_dir(
|
||||
'/usr/local/share',
|
||||
|
|
@ -95,25 +94,25 @@ class InstallKmp():
|
|||
_("You do not have permissions to install the font files to the shared font area "
|
||||
"/usr/local/share/fonts"))
|
||||
|
||||
return self._install_kmp(inputfile, online, language, InstallLocation.Shared)
|
||||
return self._install_kmp(inputfile, language, InstallLocation.Shared)
|
||||
|
||||
def install_kmp_user(self, inputfile, online=False, language=None):
|
||||
return self._install_kmp(inputfile, online, language, InstallLocation.User)
|
||||
def install_kmp_user(self, inputfile, language=None):
|
||||
return self._install_kmp(inputfile, language, InstallLocation.User)
|
||||
|
||||
def _install_kmp(self, inputfile, online, language, area):
|
||||
def _install_kmp(self, inputfile, language, area):
|
||||
self.packageID = self._extract_package_id(inputfile)
|
||||
self.packageDir = get_keyboard_dir(area, self.packageID)
|
||||
self.kmpdocdir = get_keyman_doc_dir(area, self.packageID)
|
||||
self.kmpfontdir = get_keyman_font_dir(area, self.packageID)
|
||||
|
||||
if not self._safeMakeDirs(self.packageDir):
|
||||
return
|
||||
|
||||
if not os.path.isfile(inputfile):
|
||||
message = _("File {kmpfile} doesn't exist").format(kmpfile=inputfile)
|
||||
logging.error("install_kmp.py: %s", message)
|
||||
raise InstallError(InstallStatus.Abort, message)
|
||||
|
||||
if not self._safeMakeDirs(self.packageDir):
|
||||
return
|
||||
|
||||
extract_kmp(inputfile, self.packageDir)
|
||||
|
||||
if is_fcitx_running():
|
||||
|
|
@ -136,11 +135,10 @@ class InstallKmp():
|
|||
raise InstallError(InstallStatus.Abort, message)
|
||||
if keyboards:
|
||||
logging.info("Installing %s", secure_lookup(info, 'name', 'description'))
|
||||
if online:
|
||||
process_keyboard_data(self.packageID, self.packageDir)
|
||||
for kb in keyboards:
|
||||
if kb['id'] != self.packageID:
|
||||
process_keyboard_data(kb['id'], self.packageDir)
|
||||
process_keyboard_data(self.packageID, self.packageDir)
|
||||
for kb in keyboards:
|
||||
if kb['id'] != self.packageID:
|
||||
process_keyboard_data(kb['id'], self.packageDir)
|
||||
|
||||
if files is None:
|
||||
return self.install_keyboards(keyboards, self.packageDir, language)
|
||||
|
|
@ -309,21 +307,20 @@ def process_keyboard_data(keyboardID, packageDir) -> None:
|
|||
# raise InstallError(InstallStatus.Abort, message)
|
||||
|
||||
|
||||
def install_kmp(inputfile, online=False, sharedarea=False, language=None):
|
||||
def install_kmp(inputfile, sharedarea=False, language=None):
|
||||
"""
|
||||
Install a kmp file
|
||||
|
||||
Args:
|
||||
inputfile (str): path to kmp file
|
||||
online(bool, default=False): whether to attempt to get online keyboard data
|
||||
sharedarea(bool, default=False): whether install kmp to shared area or user directory
|
||||
language(str, default=None): language to install keyboard for
|
||||
has_ui(bool, default=True): whether we're displaying a window or running UI less from the command line
|
||||
"""
|
||||
if sharedarea:
|
||||
return_value = InstallKmp().install_kmp_shared(inputfile, online, language)
|
||||
return_value = InstallKmp().install_kmp_shared(inputfile, language)
|
||||
else:
|
||||
return_value = InstallKmp().install_kmp_user(inputfile, online, language)
|
||||
return_value = InstallKmp().install_kmp_user(inputfile, language)
|
||||
|
||||
get_keyman_config_service().keyboard_list_changed()
|
||||
return return_value
|
||||
|
|
|
|||
|
|
@ -47,10 +47,9 @@ def find_keyman_image(image_file):
|
|||
|
||||
class InstallKmpWindow(Gtk.Dialog):
|
||||
|
||||
def __init__(self, kmpfile, online=False, viewkmp=None, language=None):
|
||||
def __init__(self, kmpfile, viewkmp=None, language=None):
|
||||
logging.debug("InstallKmpWindow: kmpfile: %s", kmpfile)
|
||||
self.kmpfile = kmpfile
|
||||
self.online = online
|
||||
self.viewwindow = viewkmp
|
||||
self.accelerators = None
|
||||
self.language = language
|
||||
|
|
@ -327,7 +326,7 @@ class InstallKmpWindow(Gtk.Dialog):
|
|||
def on_install_clicked(self, button):
|
||||
logging.info("Installing keyboard")
|
||||
try:
|
||||
result = install_kmp(self.kmpfile, self.online, language=self.language)
|
||||
result = install_kmp(self.kmpfile, language=self.language)
|
||||
if result:
|
||||
# If install_kmp returns a string, it is an instruction for the end user,
|
||||
# because for fcitx they will need to take extra steps to complete
|
||||
|
|
|
|||
|
|
@ -116,6 +116,7 @@ class KeyboardDetailsView(Gtk.Dialog):
|
|||
lbl_pkg_desc = Gtk.Label()
|
||||
lbl_pkg_desc.set_text(_("Package description: "))
|
||||
lbl_pkg_desc.set_halign(Gtk.Align.END)
|
||||
lbl_pkg_desc.set_valign(Gtk.Align.START)
|
||||
grid.attach_next_to(lbl_pkg_desc, prevlabel, Gtk.PositionType.BOTTOM, 1, 1)
|
||||
prevlabel = lbl_pkg_desc
|
||||
label = Gtk.Label()
|
||||
|
|
@ -125,28 +126,26 @@ class KeyboardDetailsView(Gtk.Dialog):
|
|||
label.set_line_wrap(80)
|
||||
grid.attach_next_to(label, lbl_pkg_desc, Gtk.PositionType.RIGHT, 1, 1)
|
||||
|
||||
if secure_lookup(info, "author"):
|
||||
if secure_lookup(info, 'author', 'description'):
|
||||
lbl_pkg_auth = Gtk.Label()
|
||||
lbl_pkg_auth.set_text(_("Package author: "))
|
||||
lbl_pkg_auth.set_halign(Gtk.Align.END)
|
||||
grid.attach_next_to(lbl_pkg_auth, prevlabel, Gtk.PositionType.BOTTOM, 1, 1)
|
||||
prevlabel = lbl_pkg_auth
|
||||
label = Gtk.Label()
|
||||
if secure_lookup(info, 'author', 'description'):
|
||||
label.set_text(secure_lookup(info, 'author', 'description'))
|
||||
label.set_text(secure_lookup(info, 'author', 'description'))
|
||||
label.set_halign(Gtk.Align.START)
|
||||
label.set_selectable(True)
|
||||
grid.attach_next_to(label, lbl_pkg_auth, Gtk.PositionType.RIGHT, 1, 1)
|
||||
|
||||
if secure_lookup(info, "copyright"):
|
||||
if secure_lookup(info, 'copyright', 'description'):
|
||||
lbl_pkg_cpy = Gtk.Label()
|
||||
lbl_pkg_cpy.set_text(_("Package copyright: "))
|
||||
lbl_pkg_cpy.set_halign(Gtk.Align.END)
|
||||
grid.attach_next_to(lbl_pkg_cpy, prevlabel, Gtk.PositionType.BOTTOM, 1, 1)
|
||||
prevlabel = lbl_pkg_cpy
|
||||
label = Gtk.Label()
|
||||
if secure_lookup(info, 'copyright', 'description'):
|
||||
label.set_text(secure_lookup(info, 'copyright', 'description'))
|
||||
label.set_text(secure_lookup(info, 'copyright', 'description'))
|
||||
label.set_halign(Gtk.Align.START)
|
||||
label.set_selectable(True)
|
||||
grid.attach_next_to(label, lbl_pkg_cpy, Gtk.PositionType.RIGHT, 1, 1)
|
||||
|
|
|
|||
|
|
@ -506,7 +506,6 @@ def get_metadata(tmpdirname):
|
|||
If it does not exist then will return get_and_convert_infdata
|
||||
|
||||
Args:
|
||||
inputfile (str): path to kmp file
|
||||
tmpdirname(str): temp directory to extract kmp
|
||||
|
||||
Returns:
|
||||
|
|
|
|||
|
|
@ -37,31 +37,32 @@ def uninstall_kmp_shared(packageID):
|
|||
"""
|
||||
kbdir = get_keyboard_dir(InstallLocation.Shared, packageID)
|
||||
if not os.path.isdir(kbdir):
|
||||
logging.error("Keyboard directory for %s does not exist. Aborting", packageID)
|
||||
exit(3)
|
||||
msg = _("Keyboard directory for %s does not exist." % packageID)
|
||||
logging.error(msg)
|
||||
return msg
|
||||
|
||||
kbdocdir = get_keyman_doc_dir(InstallLocation.Shared, packageID)
|
||||
kbfontdir = get_keyman_font_dir(InstallLocation.Shared, packageID)
|
||||
|
||||
logging.info("Uninstalling shared keyboard: %s", packageID)
|
||||
if not os.access(kbdir, os.X_OK | os.W_OK): # Check for write access of keyman dir
|
||||
logging.error(
|
||||
"You do not have permissions to uninstall the keyboard files. You need to run this with `sudo`")
|
||||
exit(3)
|
||||
msg = _("You do not have permissions to uninstall the keyboard files. You need to run this with `sudo`")
|
||||
logging.error(msg)
|
||||
return msg
|
||||
if os.path.isdir(kbdocdir):
|
||||
if not os.access(kbdocdir, os.X_OK | os.W_OK): # Check for write access of keyman doc dir
|
||||
logging.error(
|
||||
"You do not have permissions to uninstall the documentation. You need to run this with `sudo`")
|
||||
exit(3)
|
||||
msg = _("You do not have permissions to uninstall the documentation. You need to run this with `sudo`")
|
||||
logging.error(msg)
|
||||
return msg
|
||||
delete_dir(kbdocdir)
|
||||
logging.info("Removed documentation directory: %s", kbdocdir)
|
||||
else:
|
||||
logging.info("No documentation directory")
|
||||
if os.path.isdir(kbfontdir):
|
||||
if not os.access(kbfontdir, os.X_OK | os.W_OK): # Check for write access of keyman fonts
|
||||
logging.error(
|
||||
"You do not have permissions to uninstall the font files. You need to run this with `sudo`")
|
||||
exit(3)
|
||||
msg = _("You do not have permissions to uninstall the font files. You need to run this with `sudo`")
|
||||
logging.error(msg)
|
||||
return msg
|
||||
delete_dir(kbfontdir)
|
||||
logging.info("Removed font directory: %s", kbfontdir)
|
||||
else:
|
||||
|
|
@ -80,6 +81,7 @@ def uninstall_kmp_shared(packageID):
|
|||
delete_dir(kbdir)
|
||||
logging.info("Removed keyman directory: %s", kbdir)
|
||||
logging.info("Finished uninstalling shared keyboard: %s", packageID)
|
||||
return ''
|
||||
|
||||
|
||||
def uninstall_keyboards_from_ibus(keyboards, packageDir):
|
||||
|
|
@ -130,8 +132,9 @@ def uninstall_kmp_user(packageID):
|
|||
"""
|
||||
kbdir = get_keyboard_dir(InstallLocation.User, packageID)
|
||||
if not os.path.isdir(kbdir):
|
||||
logging.error("Keyboard directory for %s does not exist. Aborting", packageID)
|
||||
exit(3)
|
||||
msg = _("Keyboard directory for %s does not exist." % packageID)
|
||||
logging.error(msg)
|
||||
return msg
|
||||
logging.info("Uninstalling local keyboard: %s", packageID)
|
||||
info, system, options, keyboards, files = get_metadata(kbdir)
|
||||
if keyboards:
|
||||
|
|
@ -150,6 +153,7 @@ def uninstall_kmp_user(packageID):
|
|||
delete_dir(fontdir)
|
||||
logging.info("Removed user keyman font directory: %s", fontdir)
|
||||
logging.info("Finished uninstalling local keyboard: %s", packageID)
|
||||
return ''
|
||||
|
||||
|
||||
def uninstall_kmp(packageID, sharedarea=False):
|
||||
|
|
@ -161,8 +165,9 @@ def uninstall_kmp(packageID, sharedarea=False):
|
|||
sharedarea (str): whether to uninstall from shared /usr/local or ~/.local
|
||||
"""
|
||||
if sharedarea:
|
||||
uninstall_kmp_shared(packageID)
|
||||
msg = uninstall_kmp_shared(packageID)
|
||||
else:
|
||||
uninstall_kmp_user(packageID)
|
||||
msg = uninstall_kmp_user(packageID)
|
||||
|
||||
get_keyman_config_service().keyboard_list_changed()
|
||||
return msg
|
||||
|
|
|
|||
|
|
@ -22,6 +22,7 @@ from keyman_config.get_kmp import (InstallLocation, get_keyboard_dir,
|
|||
get_keyman_dir)
|
||||
from keyman_config.install_window import InstallKmpWindow, find_keyman_image
|
||||
from keyman_config.keyboard_details import KeyboardDetailsView
|
||||
from keyman_config.kmpmetadata import get_fonts, parsemetadata
|
||||
from keyman_config.list_installed_kmp import get_installed_kmp
|
||||
from keyman_config.options import OptionsView
|
||||
from keyman_config.uninstall_kmp import uninstall_kmp
|
||||
|
|
@ -351,18 +352,40 @@ class ViewInstalledWindow(ViewInstalledWindowBase):
|
|||
model, treeiter = self.tree.get_selection().get_selected()
|
||||
if treeiter is not None:
|
||||
logging.info("Uninstall keyboard " + model[treeiter][3] + "?")
|
||||
dialog = Gtk.MessageDialog(
|
||||
self, 0, Gtk.MessageType.QUESTION,
|
||||
Gtk.ButtonsType.YES_NO, _("Uninstall keyboard package?"))
|
||||
dialog.format_secondary_text(
|
||||
_("Are you sure that you want to uninstall the {keyboard} keyboard and its fonts?")
|
||||
.format(keyboard=model[treeiter][1]))
|
||||
dialog = Gtk.MessageDialog(self, 0, Gtk.MessageType.QUESTION, Gtk.ButtonsType.YES_NO,
|
||||
_("Uninstall keyboard package?"))
|
||||
msg = _("Are you sure that you want to uninstall the {keyboard} keyboard?").format(
|
||||
keyboard=model[treeiter][1])
|
||||
kbdir = get_keyboard_dir(InstallLocation.User, model[treeiter][3])
|
||||
kmpjson = os.path.join(kbdir, "kmp.json")
|
||||
if os.path.isfile(kmpjson):
|
||||
info, system, options, keyboards, files = parsemetadata(kmpjson, False)
|
||||
fonts = get_fonts(files)
|
||||
if fonts:
|
||||
# Fonts are optional
|
||||
fontlist = ""
|
||||
for font in fonts:
|
||||
if 'description' in font:
|
||||
if fontlist != "":
|
||||
fontlist = fontlist + "\n"
|
||||
if font['description'][:5] == "Font ":
|
||||
fontdesc = font['description'][5:]
|
||||
else:
|
||||
fontdesc = font['description']
|
||||
fontlist = fontlist + fontdesc
|
||||
msg += "\n\n" + _("The following fonts will also be uninstalled:\n") + fontlist
|
||||
dialog.format_secondary_text(msg)
|
||||
response = dialog.run()
|
||||
dialog.destroy()
|
||||
if response == Gtk.ResponseType.YES:
|
||||
logging.info("Uninstalling keyboard" + model[treeiter][1])
|
||||
# can only uninstall with the gui from user area
|
||||
uninstall_kmp(model[treeiter][3])
|
||||
msg = uninstall_kmp(model[treeiter][3])
|
||||
if not msg == '':
|
||||
md = Gtk.MessageDialog(self, 0, Gtk.MessageType.ERROR,
|
||||
Gtk.ButtonsType.OK, _("Uninstalling keyboard failed.\n\nError message: ") + msg)
|
||||
md.run()
|
||||
md.destroy()
|
||||
logging.info("need to restart window after uninstalling a keyboard")
|
||||
self.restart()
|
||||
elif response == Gtk.ResponseType.NO:
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
#/usr/bin/env bash
|
||||
#!/usr/bin/env bash
|
||||
|
||||
_km-config_completions()
|
||||
{
|
||||
|
|
@ -9,14 +9,15 @@ _km-config_completions()
|
|||
opts="-h --help -v --verbose -vv --veryverbose --version -i --install"
|
||||
|
||||
if [[ ${cur} == -* ]] ; then
|
||||
COMPREPLY=( $(compgen -W "${opts}" -- ${cur}) )
|
||||
# shellcheck disable=SC2207
|
||||
COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
|
||||
return 0
|
||||
fi
|
||||
|
||||
# default IFS splits 'file://' into 'file', ':' and '//'
|
||||
if [ "${prev}" == ":" -a "${COMP_WORDS[COMP_CWORD-2]}" == "file" ]; then
|
||||
if [ "${prev}" == ":" ] && [ "${COMP_WORDS[COMP_CWORD-2]}" == "file" ]; then
|
||||
local flag=${COMP_WORDS[COMP_CWORD-3]}
|
||||
if [ $flag == "-i" -o $flag == "--install" ]; then
|
||||
if [ "$flag" == "-i" ] || [ "$flag" == "--install" ]; then
|
||||
prev=$flag
|
||||
fi
|
||||
fi
|
||||
|
|
@ -25,7 +26,8 @@ _km-config_completions()
|
|||
"-i"|"--install")
|
||||
local IFS=$'\n'
|
||||
compopt -o filenames
|
||||
COMPREPLY=( $(compgen -f -X "!"*.kmp -- $cur) $(compgen -d -- $cur) )
|
||||
# shellcheck disable=SC2207
|
||||
COMPREPLY=( $(compgen -f -X "!"*.kmp -- "$cur") $(compgen -d -- "$cur") )
|
||||
return 0
|
||||
;;
|
||||
*)
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
#/usr/bin/env bash
|
||||
#!/usr/bin/env bash
|
||||
|
||||
_km-kvk2ldml_completions()
|
||||
{
|
||||
|
|
@ -9,7 +9,8 @@ _km-kvk2ldml_completions()
|
|||
opts="-h --help -p --print -k --keys -o --output -v --verbose -vv --veryverbose --version"
|
||||
|
||||
if [[ ${cur} == -* ]] ; then
|
||||
COMPREPLY=( $(compgen -W "${opts}" -- ${cur}) )
|
||||
# shellcheck disable=SC2207
|
||||
COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
|
||||
return 0
|
||||
fi
|
||||
|
||||
|
|
@ -17,7 +18,8 @@ _km-kvk2ldml_completions()
|
|||
"-o"|"--output")
|
||||
local IFS=$'\n'
|
||||
compopt -o filenames
|
||||
COMPREPLY=( $(compgen -f -- $cur) )
|
||||
# shellcheck disable=SC2207
|
||||
COMPREPLY=( $(compgen -f -- "$cur") )
|
||||
return 0
|
||||
;;
|
||||
*)
|
||||
|
|
@ -26,7 +28,8 @@ _km-kvk2ldml_completions()
|
|||
|
||||
local IFS=$'\n'
|
||||
compopt -o filenames
|
||||
COMPREPLY=( $(compgen -f -X "!"*.kvk -- $cur) $(compgen -d -- $cur) )
|
||||
# shellcheck disable=SC2207
|
||||
COMPREPLY=( $(compgen -f -X "!"*.kvk -- "$cur") $(compgen -d -- "$cur") )
|
||||
}
|
||||
|
||||
complete -F _km-kvk2ldml_completions km-kvk2ldml
|
||||
|
|
|
|||
|
|
@ -1,17 +1,17 @@
|
|||
#/usr/bin/env bash
|
||||
#!/usr/bin/env bash
|
||||
|
||||
_km-package-get_completions()
|
||||
{
|
||||
local cur prev opts cache
|
||||
local cur opts cache pkg_install_path
|
||||
COMPREPLY=()
|
||||
cur="${COMP_WORDS[COMP_CWORD]}"
|
||||
prev="${COMP_WORDS[COMP_CWORD-1]}"
|
||||
opts="-h --help -v --verbose -vv --veryverbose --version"
|
||||
|
||||
cache=${XDG_CACHE_HOME:-~/.cache}/keyman/kmpdirlist
|
||||
|
||||
if [[ ${cur} == -* ]] ; then
|
||||
COMPREPLY=( $(compgen -W "${opts}" -- ${cur}) )
|
||||
# shellcheck disable=SC2207
|
||||
COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
|
||||
return 0
|
||||
fi
|
||||
|
||||
|
|
@ -21,15 +21,17 @@ _km-package-get_completions()
|
|||
# Unfortunately with bash completion scripts it's not possible to factor out
|
||||
# common code.
|
||||
if [[ -e ./km-package-install ]]; then
|
||||
python3 -c "from importlib.machinery import SourceFileLoader;from importlib.util import module_from_spec, spec_from_loader;loader = SourceFileLoader('km_package_install', './km-package-install');spec = spec_from_loader(loader.name, loader);mod = module_from_spec(spec);loader.exec_module(mod);mod.list_keyboards()"
|
||||
pkg_install_path='./km-package-install'
|
||||
else
|
||||
python3 -c "from importlib.machinery import SourceFileLoader;from importlib.util import module_from_spec, spec_from_loader;loader = SourceFileLoader('km_package_install', '/usr/bin/km-package-install');spec = spec_from_loader(loader.name, loader);mod = module_from_spec(spec);loader.exec_module(mod);mod.list_keyboards()"
|
||||
pkg_install_path='/usr/bin/km-package-install'
|
||||
fi
|
||||
python3 -c "from importlib.machinery import SourceFileLoader;from importlib.util import module_from_spec, spec_from_loader;loader = SourceFileLoader('km_package_install', $pkg_install_path);spec = spec_from_loader(loader.name, loader);mod = module_from_spec(spec);loader.exec_module(mod);mod.list_keyboards()"
|
||||
fi
|
||||
|
||||
if [[ -r $cache ]] ; then
|
||||
for file in `cat $cache`; do words="${words} ${file}"; done
|
||||
COMPREPLY=($(compgen -W "${words}" -- ${cur}))
|
||||
while read -r file; do words="${words} ${file}"; done < "$cache"
|
||||
# shellcheck disable=SC2207
|
||||
COMPREPLY=($(compgen -W "${words}" -- "${cur}"))
|
||||
return 0
|
||||
fi
|
||||
}
|
||||
|
|
|
|||
|
|
@ -10,6 +10,8 @@ from pkg_resources import parse_version
|
|||
from zipfile import is_zipfile
|
||||
|
||||
from keyman_config import KeymanApiUrl, __version__, secure_lookup
|
||||
from keyman_config.install_kmp import extract_kmp
|
||||
from keyman_config.kmpmetadata import get_metadata
|
||||
from keyman_config.uninstall_kmp import uninstall_kmp
|
||||
|
||||
|
||||
|
|
@ -84,6 +86,33 @@ def list_keyboards():
|
|||
write_kmpdirlist(kmpdirfile)
|
||||
|
||||
|
||||
def _list_languages_for_keyboard_impl(packageId, packageDir):
|
||||
from keyman_config.get_kmp import keyman_cache_dir
|
||||
kmpfile = os.path.join(keyman_cache_dir(), packageId)
|
||||
if not os.path.exists(kmpfile):
|
||||
kmpfile = kmpfile + '.kmp'
|
||||
if not os.path.exists(kmpfile):
|
||||
return ''
|
||||
extract_kmp(kmpfile, packageDir)
|
||||
info, system, options, keyboards, files = get_metadata(packageDir)
|
||||
if not keyboards:
|
||||
return ''
|
||||
firstKeyboard = keyboards[0]
|
||||
if not secure_lookup(firstKeyboard, 'languages') or len(firstKeyboard['languages']) <= 0:
|
||||
return ''
|
||||
result = ''
|
||||
for lang in firstKeyboard['languages']:
|
||||
if result:
|
||||
result += '\n'
|
||||
result += lang['id']
|
||||
return result
|
||||
|
||||
|
||||
def list_languages_for_keyboard(packageId, packageDir):
|
||||
result = _list_languages_for_keyboard_impl(packageId, packageDir)
|
||||
print(result)
|
||||
|
||||
|
||||
def main():
|
||||
parser = argparse.ArgumentParser(
|
||||
description='Install a Keyman keyboard package, either a local .kmp file or specify a ' +
|
||||
|
|
@ -122,9 +151,9 @@ def main():
|
|||
if os.path.exists(os.path.join(keyman_cache_dir(), 'kmpdirlist')):
|
||||
os.remove(os.path.join(keyman_cache_dir(), 'kmpdirlist'))
|
||||
|
||||
def try_install_kmp(inputfile, arg, language=None, online=False, sharedarea=False):
|
||||
def try_install_kmp(inputfile, arg, language=None, sharedarea=False):
|
||||
try:
|
||||
install_kmp(inputfile, online, sharedarea, language)
|
||||
install_kmp(inputfile, sharedarea, language)
|
||||
except InstallError as e:
|
||||
if e.status == InstallStatus.Abort:
|
||||
logging.error("km-package-install: error: Failed to install %s", arg)
|
||||
|
|
@ -144,7 +173,7 @@ def main():
|
|||
logging.error("km-package-install: Keyman kmp file %s not found.", args.file)
|
||||
logging.error("km-package-install -f <kmpfile>")
|
||||
sys.exit(2)
|
||||
try_install_kmp(args.file, "file " + args.file, args.bcp47, False, args.shared)
|
||||
try_install_kmp(args.file, "file " + args.file, args.bcp47, args.shared)
|
||||
elif args.package:
|
||||
if args.shared:
|
||||
if get_kmp_version_user(args.package):
|
||||
|
|
@ -176,7 +205,7 @@ def main():
|
|||
|
||||
kmpfile = get_kmp(args.package)
|
||||
if kmpfile:
|
||||
try_install_kmp(kmpfile, "keyboard package " + args.package, args.bcp47, True, args.shared)
|
||||
try_install_kmp(kmpfile, "keyboard package " + args.package, args.bcp47, args.shared)
|
||||
else:
|
||||
logging.error("km-package-install: error: Could not download keyboard package %s", args.package)
|
||||
sys.exit(2)
|
||||
|
|
|
|||
|
|
@ -1,20 +1,29 @@
|
|||
#/usr/bin/env bash
|
||||
#!/usr/bin/env bash
|
||||
|
||||
_km-package-install_completions()
|
||||
{
|
||||
local cur prev opts cache
|
||||
local cur prev opts cache pkg_install_path
|
||||
COMPREPLY=()
|
||||
cur="${COMP_WORDS[COMP_CWORD]}"
|
||||
prev="${COMP_WORDS[COMP_CWORD-1]}"
|
||||
opts="-h --help -v --verbose -vv --veryverbose --version -p --package -f --file -s --shared"
|
||||
opts="-h --help -v --verbose -vv --veryverbose --version -p --package -f --file -s --shared -l --bcp47"
|
||||
|
||||
cache=${XDG_CACHE_HOME:-~/.cache}/keyman/kmpdirlist
|
||||
|
||||
if [[ ${cur} == -* ]] ; then
|
||||
COMPREPLY=( $(compgen -W "${opts}" -- ${cur}) )
|
||||
# shellcheck disable=SC2207
|
||||
COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
|
||||
return 0
|
||||
fi
|
||||
|
||||
if [[ -e ./km-package-install ]]; then
|
||||
pkg_install_path='./km-package-install'
|
||||
get_kmp_path='keyman_config/get_kmp.py'
|
||||
else
|
||||
pkg_install_path='/usr/bin/km-package-install'
|
||||
get_kmp_path='/usr/lib/python3/dist-packages/keyman_config/get_kmp.py'
|
||||
fi
|
||||
|
||||
case "${prev}" in
|
||||
"-p"|"--package")
|
||||
words=""
|
||||
|
|
@ -22,23 +31,58 @@ _km-package-install_completions()
|
|||
# NOTE: identical code in `km-package-get.bash-completion`.
|
||||
# Unfortunately with bash completion scripts it's not possible to factor out
|
||||
# common code.
|
||||
if [[ -e ./km-package-install ]]; then
|
||||
python3 -c "from importlib.machinery import SourceFileLoader;from importlib.util import module_from_spec, spec_from_loader;loader = SourceFileLoader('km_package_install', './km-package-install');spec = spec_from_loader(loader.name, loader);mod = module_from_spec(spec);loader.exec_module(mod);mod.list_keyboards()"
|
||||
else
|
||||
python3 -c "from importlib.machinery import SourceFileLoader;from importlib.util import module_from_spec, spec_from_loader;loader = SourceFileLoader('km_package_install', '/usr/bin/km-package-install');spec = spec_from_loader(loader.name, loader);mod = module_from_spec(spec);loader.exec_module(mod);mod.list_keyboards()"
|
||||
fi
|
||||
|
||||
python3 -c "from importlib.machinery import SourceFileLoader;from importlib.util import module_from_spec, spec_from_loader;loader = SourceFileLoader('km_package_install', '$pkg_install_path');spec = spec_from_loader(loader.name, loader);mod = module_from_spec(spec);loader.exec_module(mod);mod.list_keyboards()"
|
||||
fi
|
||||
|
||||
if [[ -r $cache ]] ; then
|
||||
for file in `cat $cache`; do words="${words} ${file}"; done
|
||||
COMPREPLY=($(compgen -W "${words}" -- ${cur}))
|
||||
while read -r file; do words="${words} ${file}"; done < "$cache"
|
||||
# shellcheck disable=SC2207
|
||||
COMPREPLY=($(compgen -W "${words}" -- "${cur}"))
|
||||
return 0
|
||||
fi
|
||||
;;
|
||||
"-f"|"--file")
|
||||
local IFS=$'\n'
|
||||
compopt -o filenames
|
||||
COMPREPLY=( $(compgen -f -X "!"*.kmp -- $cur) $(compgen -d -- $cur) )
|
||||
# shellcheck disable=SC2207
|
||||
COMPREPLY=( $(compgen -f -X "!"*.kmp -- "$cur") $(compgen -d -- "$cur") )
|
||||
return 0
|
||||
;;
|
||||
"-l"|"--bcp47")
|
||||
local packageId=""
|
||||
local packageDir
|
||||
packageDir=$(mktemp -d)
|
||||
for ((i=0;i<$COMP_CWORD;i++)); do
|
||||
case ${COMP_WORDS[$i]} in
|
||||
"-p"|"--package")
|
||||
packageId="${COMP_WORDS[$i+1]}"
|
||||
# shellcheck disable=SC2086 # doesn't work with quotes
|
||||
if [ ! -f ${XDG_CACHE_HOME:-~/.cache}/keyman/$packageId ] && [ ! -f ${XDG_CACHE_HOME:-~/.cache}/keyman/${packageId}.kmp ]; then
|
||||
python3 -c "from importlib.machinery import SourceFileLoader;from importlib.util import module_from_spec, spec_from_loader;loader = SourceFileLoader('get_kmp', '$get_kmp_path');spec = spec_from_loader(loader.name, loader);mod = module_from_spec(spec);loader.exec_module(mod);mod.get_kmp('$packageId')"
|
||||
fi
|
||||
break
|
||||
;;
|
||||
"-f"|"--file")
|
||||
package="${COMP_WORDS[$i+1]}"
|
||||
packageId=$(basename "$package")
|
||||
# shellcheck disable=SC2086 # doesn't work with quotes
|
||||
cp "$package" ${XDG_CACHE_HOME:-~/.cache}/keyman/${packageId}
|
||||
break
|
||||
;;
|
||||
*)
|
||||
;;
|
||||
esac
|
||||
done
|
||||
if [ -z "$packageId" ]; then
|
||||
return 0
|
||||
fi
|
||||
words=""
|
||||
while read -r lang; do
|
||||
words="$words $lang"
|
||||
done < <(python3 -c "from importlib.machinery import SourceFileLoader;from importlib.util import module_from_spec, spec_from_loader;loader = SourceFileLoader('km_package_install', '$pkg_install_path');spec = spec_from_loader(loader.name, loader);mod = module_from_spec(spec);loader.exec_module(mod);mod.list_languages_for_keyboard('$packageId', '$packageDir')")
|
||||
# shellcheck disable=SC2207
|
||||
COMPREPLY=($(compgen -W "${words}" -- "${cur}"))
|
||||
return 0
|
||||
;;
|
||||
*)
|
||||
|
|
|
|||
|
|
@ -1,15 +1,15 @@
|
|||
#/usr/bin/env bash
|
||||
#!/usr/bin/env bash
|
||||
|
||||
_km-package-list-installed_completions()
|
||||
{
|
||||
local cur prev opts
|
||||
local cur opts
|
||||
COMPREPLY=()
|
||||
cur="${COMP_WORDS[COMP_CWORD]}"
|
||||
prev="${COMP_WORDS[COMP_CWORD-1]}"
|
||||
opts="-h --help -l --long -v --verbose -vv --veryverbose --version -u --user -o --os -s --shared"
|
||||
|
||||
if [[ ${cur} == -* ]] ; then
|
||||
COMPREPLY=( $(compgen -W "${opts}" -- ${cur}) )
|
||||
# shellcheck disable=SC2207
|
||||
COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
|
||||
return 0
|
||||
fi
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
#/usr/bin/env bash
|
||||
#!/usr/bin/env bash
|
||||
|
||||
_km-package-uninstall_completions()
|
||||
{
|
||||
|
|
@ -9,7 +9,8 @@ _km-package-uninstall_completions()
|
|||
opts="-h --help -s --shared -v --verbose -vv --veryverbose --version"
|
||||
|
||||
if [[ ${cur} == -* ]] ; then
|
||||
COMPREPLY=( $(compgen -W "${opts}" -- ${cur}) )
|
||||
# shellcheck disable=SC2207
|
||||
COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
|
||||
return 0
|
||||
fi
|
||||
|
||||
|
|
@ -23,12 +24,15 @@ _km-package-uninstall_completions()
|
|||
shared=""
|
||||
case "${prev}" in
|
||||
"-s"|"--shared")
|
||||
for file in $(ls -1 /usr/local/share/keyman); do kbid="`basename ${file}`"; shared="${shared} ${kbid}"; done
|
||||
COMPREPLY=($(compgen -W "${shared}" -- ${cur}))
|
||||
for file in /usr/local/share/keyman/*; do kbid="$(basename "${file}")"; shared="${shared} ${kbid}"; done
|
||||
# shellcheck disable=SC2207
|
||||
COMPREPLY=($(compgen -W "${shared}" -- "${cur}"))
|
||||
;;
|
||||
*)
|
||||
for file in $(ls -1 ${XDG_DATA_HOME:-~/.local/share}/keyman); do kbid="`basename ${file}`"; words="${words} ${kbid}"; done
|
||||
COMPREPLY=($(compgen -W "${words}" -- ${cur}))
|
||||
# shellcheck disable=SC2231 # doesn't work with quotes
|
||||
for file in ${XDG_DATA_HOME:-~/.local/share}/keyman/*; do kbid="$(basename "${file}")"; words="${words} ${kbid}"; done
|
||||
# shellcheck disable=SC2207
|
||||
COMPREPLY=($(compgen -W "${words}" -- "${cur}"))
|
||||
;;
|
||||
esac
|
||||
}
|
||||
|
|
|
|||
|
|
@ -272,7 +272,7 @@ class InstallKmpTests(unittest.TestCase):
|
|||
|
||||
# Execute
|
||||
with self.assertRaises(InstallError) as context:
|
||||
InstallKmp()._install_kmp(kmpfile, False, 'km', InstallLocation.User)
|
||||
InstallKmp()._install_kmp(kmpfile, 'km', InstallLocation.User)
|
||||
|
||||
# Verify
|
||||
self.assertTrue('foo.kmp requires Keyman 99.0 or higher' in context.exception.message)
|
||||
|
|
@ -296,7 +296,7 @@ class InstallKmpTests(unittest.TestCase):
|
|||
self._createKmpJson(packagedir, testcase['fileVersion'])
|
||||
|
||||
# Execute
|
||||
InstallKmp()._install_kmp(kmpfile, False, 'km', InstallLocation.User)
|
||||
InstallKmp()._install_kmp(kmpfile, 'km', InstallLocation.User)
|
||||
|
||||
# Verify
|
||||
self.mockInstallToIbus.assert_called_once()
|
||||
|
|
|
|||
60
linux/keyman-config/tests/test_package_install_completion.py
Normal file
|
|
@ -0,0 +1,60 @@
|
|||
#!/usr/bin/python3
|
||||
import os
|
||||
import tempfile
|
||||
import unittest
|
||||
from unittest.mock import patch, ANY
|
||||
from importlib.machinery import SourceFileLoader
|
||||
from importlib.util import module_from_spec, spec_from_loader
|
||||
|
||||
|
||||
class PackageInstallCompletionTests(unittest.TestCase):
|
||||
|
||||
def setUp(self):
|
||||
patcher1 = patch('keyman_config.install_kmp.extract_kmp')
|
||||
self.mockExtractKmp = patcher1.start()
|
||||
self.addCleanup(patcher1.stop)
|
||||
patcher2 = patch('keyman_config.kmpmetadata.get_metadata')
|
||||
self.mockGetMetadata = patcher2.start()
|
||||
self.addCleanup(patcher2.stop)
|
||||
|
||||
loader = SourceFileLoader('km_package_install', os.path.join(os.path.dirname(
|
||||
os.path.abspath(__file__)), '../km-package-install'))
|
||||
spec = spec_from_loader(loader.name, loader)
|
||||
if spec:
|
||||
self.mod = module_from_spec(spec)
|
||||
loader.exec_module(self.mod)
|
||||
|
||||
self.tempDir = tempfile.TemporaryDirectory()
|
||||
os.environ["XDG_CACHE_HOME"] = self.tempDir.name
|
||||
self.cacheDir = os.path.join(self.tempDir.name, 'keyman')
|
||||
os.makedirs(self.cacheDir)
|
||||
|
||||
def _list_languages_for_keyboard_impl(self, packageId):
|
||||
return self.mod._list_languages_for_keyboard_impl(packageId, 'someDir')
|
||||
|
||||
def test_PackageCompletionNoLanguage(self):
|
||||
open(os.path.join(self.cacheDir, 'foo'), 'w')
|
||||
self.mockGetMetadata.return_value = (None, None, None, [{}], None)
|
||||
result = self._list_languages_for_keyboard_impl('foo')
|
||||
self.assertEqual(result, "")
|
||||
|
||||
def test_PackageCompletionOneLanguage(self):
|
||||
open(os.path.join(self.cacheDir, 'khmer_angkor'), 'w')
|
||||
self.mockGetMetadata.return_value = (
|
||||
None, None, None,
|
||||
[{'languages': [{'name': 'Central Khmer (Khmer, Cambodia)', 'id': 'km'}]}],
|
||||
None)
|
||||
result = self._list_languages_for_keyboard_impl('khmer_angkor')
|
||||
self.assertEqual(result, "km")
|
||||
|
||||
def test_PackageCompletionMultipleLanguages(self):
|
||||
open(os.path.join(self.cacheDir, 'sil_euro_latin'), 'w')
|
||||
self.mockGetMetadata.return_value = (
|
||||
None, None, None,
|
||||
[{'languages': [
|
||||
{'name': 'English', 'id': 'en'},
|
||||
{'name': 'French', 'id': 'fr'},
|
||||
{'name': 'German', 'id': 'de'}]}],
|
||||
None)
|
||||
result = self._list_languages_for_keyboard_impl('sil_euro_latin')
|
||||
self.assertEqual(result, 'en\nfr\nde')
|
||||
|
|
@ -158,7 +158,7 @@ NSString* _keymanDataPath = nil;
|
|||
[[NSUserDefaults standardUserDefaults] registerDefaults:@{ @"NSApplicationCrashOnExceptions": @YES }];
|
||||
|
||||
KeymanVersionInfo keymanVersionInfo = [self versionInfo];
|
||||
NSString *releaseName = [NSString stringWithFormat:@"release-%@", keymanVersionInfo.versionWithTag];
|
||||
NSString *releaseName = [NSString stringWithFormat:@"release@%@", keymanVersionInfo.versionWithTag];
|
||||
|
||||
[SentrySDK startWithConfigureOptions:^(SentryOptions *options) {
|
||||
options.dsn = @"https://960f8b8e574c46e3be385d60ce8e1fea@o1005580.ingest.sentry.io/5983522";
|
||||
|
|
|
|||
|
|
@ -40,7 +40,7 @@ public class MainActivity extends AppCompatActivity implements OnKeyboardDownloa
|
|||
context = this;
|
||||
|
||||
SentryAndroid.init(context, options -> {
|
||||
options.setRelease("release-"+com.firstvoices.keyboards.BuildConfig.VERSION_NAME);
|
||||
options.setRelease("release@"+com.firstvoices.keyboards.BuildConfig.VERSION_NAME);
|
||||
options.setEnvironment(com.firstvoices.keyboards.BuildConfig.VERSION_ENVIRONMENT);
|
||||
});
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,4 @@
|
|||
github "marmelroy/Zip"
|
||||
github "DaveWoodCom/XCGLogger" ~> 6.1.0
|
||||
github "devicekit/DeviceKit" ~> 2.3
|
||||
github "devicekit/DeviceKit" ~> 5.0
|
||||
github "ashleymills/Reachability.swift"
|
||||
github "getsentry/sentry-cocoa" ~> 6.2.1
|
||||
|
|
|
|||
|
|
@ -1,5 +1,4 @@
|
|||
github "DaveWoodCom/XCGLogger" "6.1.0"
|
||||
github "ashleymills/Reachability.swift" "v5.0.0"
|
||||
github "devicekit/DeviceKit" "2.3.0"
|
||||
github "ashleymills/Reachability.swift" "v5.1.0"
|
||||
github "devicekit/DeviceKit" "5.0.0"
|
||||
github "getsentry/sentry-cocoa" "6.2.1"
|
||||
github "marmelroy/Zip" "2.0.0"
|
||||
|
|
|
|||
|
|
@ -57,15 +57,12 @@
|
|||
CEBD34232654D76B00EB2EA8 /* Sentry.xcframework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = CEBD34092654D5AA00EB2EA8 /* Sentry.xcframework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
|
||||
CEBD34252654D76C00EB2EA8 /* XCGLogger.xcframework in Frameworks */ = {isa = PBXBuildFile; fileRef = CEBD340A2654D5AA00EB2EA8 /* XCGLogger.xcframework */; };
|
||||
CEBD34262654D76C00EB2EA8 /* XCGLogger.xcframework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = CEBD340A2654D5AA00EB2EA8 /* XCGLogger.xcframework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
|
||||
CEBD34272654D76E00EB2EA8 /* Zip.xcframework in Frameworks */ = {isa = PBXBuildFile; fileRef = CEBD340B2654D5AA00EB2EA8 /* Zip.xcframework */; };
|
||||
CEBD34282654D76E00EB2EA8 /* Zip.xcframework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = CEBD340B2654D5AA00EB2EA8 /* Zip.xcframework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
|
||||
CEBD34472654FF3300EB2EA8 /* KeymanEngine.xcframework in Frameworks */ = {isa = PBXBuildFile; fileRef = CEBD34012654D41200EB2EA8 /* KeymanEngine.xcframework */; };
|
||||
CEDB327F265C9C58000A2009 /* DeviceKit.xcframework in Frameworks */ = {isa = PBXBuildFile; fileRef = CEBD34052654D4EB00EB2EA8 /* DeviceKit.xcframework */; };
|
||||
CEDB3280265C9C58000A2009 /* ObjcExceptionBridging.xcframework in Frameworks */ = {isa = PBXBuildFile; fileRef = CEBD34082654D5AA00EB2EA8 /* ObjcExceptionBridging.xcframework */; };
|
||||
CEDB3281265C9C58000A2009 /* Reachability.xcframework in Frameworks */ = {isa = PBXBuildFile; fileRef = CEBD340C2654D5AB00EB2EA8 /* Reachability.xcframework */; };
|
||||
CEDB3282265C9C58000A2009 /* Sentry.xcframework in Frameworks */ = {isa = PBXBuildFile; fileRef = CEBD34092654D5AA00EB2EA8 /* Sentry.xcframework */; };
|
||||
CEDB3283265C9C58000A2009 /* XCGLogger.xcframework in Frameworks */ = {isa = PBXBuildFile; fileRef = CEBD340A2654D5AA00EB2EA8 /* XCGLogger.xcframework */; };
|
||||
CEDB3284265C9C58000A2009 /* Zip.xcframework in Frameworks */ = {isa = PBXBuildFile; fileRef = CEBD340B2654D5AA00EB2EA8 /* Zip.xcframework */; };
|
||||
/* End PBXBuildFile section */
|
||||
|
||||
/* Begin PBXCopyFilesBuildPhase section */
|
||||
|
|
@ -81,7 +78,6 @@
|
|||
CEBD34232654D76B00EB2EA8 /* Sentry.xcframework in Embed Frameworks */,
|
||||
CEBD34262654D76C00EB2EA8 /* XCGLogger.xcframework in Embed Frameworks */,
|
||||
CEBD34032654D41200EB2EA8 /* KeymanEngine.xcframework in Embed Frameworks */,
|
||||
CEBD34282654D76E00EB2EA8 /* Zip.xcframework in Embed Frameworks */,
|
||||
);
|
||||
name = "Embed Frameworks";
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
|
|
@ -147,7 +143,6 @@
|
|||
CEBD34082654D5AA00EB2EA8 /* ObjcExceptionBridging.xcframework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcframework; name = ObjcExceptionBridging.xcframework; path = Carthage/Build/ObjcExceptionBridging.xcframework; sourceTree = "<group>"; };
|
||||
CEBD34092654D5AA00EB2EA8 /* Sentry.xcframework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcframework; name = Sentry.xcframework; path = Carthage/Build/Sentry.xcframework; sourceTree = "<group>"; };
|
||||
CEBD340A2654D5AA00EB2EA8 /* XCGLogger.xcframework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcframework; name = XCGLogger.xcframework; path = Carthage/Build/XCGLogger.xcframework; sourceTree = "<group>"; };
|
||||
CEBD340B2654D5AA00EB2EA8 /* Zip.xcframework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcframework; name = Zip.xcframework; path = Carthage/Build/Zip.xcframework; sourceTree = "<group>"; };
|
||||
CEBD340C2654D5AB00EB2EA8 /* Reachability.xcframework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcframework; name = Reachability.xcframework; path = Carthage/Build/Reachability.xcframework; sourceTree = "<group>"; };
|
||||
/* End PBXFileReference section */
|
||||
|
||||
|
|
@ -162,7 +157,6 @@
|
|||
CEBD341A2654D76600EB2EA8 /* DeviceKit.xcframework in Frameworks */,
|
||||
CEBD34022654D41200EB2EA8 /* KeymanEngine.xcframework in Frameworks */,
|
||||
CEBD34252654D76C00EB2EA8 /* XCGLogger.xcframework in Frameworks */,
|
||||
CEBD34272654D76E00EB2EA8 /* Zip.xcframework in Frameworks */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
|
|
@ -175,7 +169,6 @@
|
|||
CEDB3281265C9C58000A2009 /* Reachability.xcframework in Frameworks */,
|
||||
CEDB3282265C9C58000A2009 /* Sentry.xcframework in Frameworks */,
|
||||
CEDB3283265C9C58000A2009 /* XCGLogger.xcframework in Frameworks */,
|
||||
CEDB3284265C9C58000A2009 /* Zip.xcframework in Frameworks */,
|
||||
CEBD34472654FF3300EB2EA8 /* KeymanEngine.xcframework in Frameworks */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
|
|
@ -295,7 +288,6 @@
|
|||
CEBD340C2654D5AB00EB2EA8 /* Reachability.xcframework */,
|
||||
CEBD34092654D5AA00EB2EA8 /* Sentry.xcframework */,
|
||||
CEBD340A2654D5AA00EB2EA8 /* XCGLogger.xcframework */,
|
||||
CEBD340B2654D5AA00EB2EA8 /* Zip.xcframework */,
|
||||
CEBD34052654D4EB00EB2EA8 /* DeviceKit.xcframework */,
|
||||
CEBD34012654D41200EB2EA8 /* KeymanEngine.xcframework */,
|
||||
);
|
||||
|
|
@ -590,7 +582,7 @@
|
|||
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||
HEADER_SEARCH_PATHS = "";
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 9.0;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 12.2;
|
||||
MTL_ENABLE_DEBUG_INFO = YES;
|
||||
ONLY_ACTIVE_ARCH = YES;
|
||||
SDKROOT = iphoneos;
|
||||
|
|
@ -642,7 +634,7 @@
|
|||
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||
HEADER_SEARCH_PATHS = "";
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 9.0;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 12.2;
|
||||
MTL_ENABLE_DEBUG_INFO = NO;
|
||||
SDKROOT = iphoneos;
|
||||
TARGETED_DEVICE_FAMILY = "1,2";
|
||||
|
|
@ -662,7 +654,7 @@
|
|||
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
|
||||
DEVELOPMENT_TEAM = D7TR486TEH;
|
||||
INFOPLIST_FILE = FirstVoices/Info.plist;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 12.1;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 12.2;
|
||||
KEYMAN_ROOT = "$(SRCROOT)/../../..";
|
||||
LD_RUNPATH_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
|
|
@ -691,7 +683,7 @@
|
|||
CODE_SIGN_STYLE = Manual;
|
||||
DEVELOPMENT_TEAM = D7TR486TEH;
|
||||
INFOPLIST_FILE = FirstVoices/Info.plist;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 12.1;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 12.2;
|
||||
KEYMAN_ROOT = "$(SRCROOT)/../../..";
|
||||
LD_RUNPATH_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
|
|
@ -718,7 +710,7 @@
|
|||
DEVELOPMENT_TEAM = D7TR486TEH;
|
||||
HEADER_SEARCH_PATHS = "";
|
||||
INFOPLIST_FILE = SWKeyboard/Info.plist;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 12.1;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 12.2;
|
||||
KEYMAN_ROOT = "$(SRCROOT)/../../..";
|
||||
LD_RUNPATH_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
|
|
@ -749,7 +741,7 @@
|
|||
DEVELOPMENT_TEAM = D7TR486TEH;
|
||||
HEADER_SEARCH_PATHS = "";
|
||||
INFOPLIST_FILE = SWKeyboard/Info.plist;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 12.1;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 12.2;
|
||||
KEYMAN_ROOT = "$(SRCROOT)/../../..";
|
||||
LD_RUNPATH_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
|
|
|
|||
|
|
@ -165,12 +165,6 @@ if [ $DO_CARTHAGE = true ]; then
|
|||
|
||||
carthage checkout || fail "Carthage dependency loading failed"
|
||||
|
||||
# Carthage sometimes picks the wrong .xcworkspace if two are available in a dependency's repo.
|
||||
# Easiest way to override it - delete the wrong one (or just its scheme)
|
||||
|
||||
# Deleted workspace - a test for proper deployment to CocoaPods. Doesn't matter here.
|
||||
rm -r ./Carthage/Checkouts/DeviceKit/CocoaPodsVerification/ || fail "Carthage dependency loading failed"
|
||||
|
||||
# --no-use-binaries: due to https://github.com/Carthage/Carthage/issues/3134,
|
||||
# which affects the sentry-cocoa dependency.
|
||||
carthage build --use-xcframeworks --no-use-binaries --platform iOS || fail "Carthage dependency loading failed"
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@
|
|||
Sentry.init({
|
||||
dsn: 'https://92eb58e6005d47daa33c9c9e39458eb7@o1005580.ingest.sentry.io/5983518', // Keyman for Windows
|
||||
environment: '$Environment',
|
||||
release: 'release-$VersionWithTag'
|
||||
release: 'release@$VersionWithTag'
|
||||
});
|
||||
|
||||
function keymanEnableDiagnostics() {
|
||||
|
|
|
|||
|
|
@ -126,7 +126,7 @@ if [ "$action" == "commit" ]; then
|
|||
pushd "$KEYMAN_ROOT" > /dev/null
|
||||
message="auto: increment $base version to $NEWVERSION"
|
||||
branch="auto/version-$base-$NEWVERSION"
|
||||
git tag -a "release-$VERSION_WITH_TAG" -m "Keyman release $VERSION_WITH_TAG"
|
||||
git tag -a "release@$VERSION_WITH_TAG" -m "Keyman release $VERSION_WITH_TAG"
|
||||
git checkout -b "$branch"
|
||||
git add VERSION.md HISTORY.md
|
||||
|
||||
|
|
|
|||
|
|
@ -210,7 +210,7 @@ INTERMEDIATE="../intermediate"
|
|||
SOURCE="."
|
||||
NODE_SOURCE="source"
|
||||
|
||||
SENTRY_RELEASE_VERSION="release-$VERSION_WITH_TAG"
|
||||
SENTRY_RELEASE_VERSION="release@$VERSION_WITH_TAG"
|
||||
|
||||
readonly WEB_OUTPUT
|
||||
readonly EMBED_OUTPUT
|
||||
|
|
|
|||
|
|
@ -31,7 +31,7 @@ cd "$KEYMAN_ROOT/windows/src"
|
|||
|
||||
echo "Uploading symbols for desktop/"
|
||||
sentry-cli upload-dif -p keyman-windows -t breakpad -t pdb desktop --include-sources
|
||||
sentry-cli releases -p keyman-windows files "release-$VERSION_WITH_TAG" upload-sourcemaps desktop/kmshell/xml
|
||||
sentry-cli releases -p keyman-windows files "release@$VERSION_WITH_TAG" upload-sourcemaps desktop/kmshell/xml
|
||||
|
||||
echo "Uploading symbols for engine/"
|
||||
sentry-cli upload-dif -p keyman-windows -t breakpad -t pdb engine --include-sources
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ latest version of Keyman.
|
|||
|
||||
Keyman is a keyboard application that makes it easy for you to type in
|
||||
your language in all your favourite Windows programs and across the Web.
|
||||
Keyman is used by more than a million people to type in over 1000
|
||||
Keyman is used by more than a million people to type in over 2000
|
||||
languages and counting.
|
||||
|
||||
Keyman remaps your hardware keyboard to any one of hundreds of virtual
|
||||
|
|
|
|||
|
|
@ -40,18 +40,44 @@ Keyman Configuration, see: [Keyboard Task - Enable or Disable a Keyboard](../ena
|
|||
|
||||
## Setting a Hotkey
|
||||
|
||||
To set a hotkey for a Keyman keyboard, use the [Hotkeys tab](hotkeys).
|
||||
The Hotkey for selecting a keyboard will appear to the right of the keyboard name.
|
||||
If the keyboard has more than one language associated with it then the hotkey will
|
||||
appear beside the language in the keyboards details list.
|
||||
|
||||
1. Click the hotkey link beside the keyboard or language. The
|
||||
Change Hotkey dialog box will be displayed.
|
||||
|
||||

|
||||
|
||||
2. Select a default hotkey or click Custom and type the hotkey you wish
|
||||
to use.
|
||||
|
||||
**Note:** If you press a single letter or Shift plus a single letter, the
|
||||
hotkey will default to <kbd>Ctrl</kbd> + <kbd>Alt</kbd> plus the letter you pressed, in
|
||||
order to avoid conflicts with standard keyboard input.
|
||||
|
||||
**Note:** To clear a hotkey that has been set previously, click Clear Hotkey
|
||||
or press Backspace.
|
||||
|
||||
**Note:** Be aware that you can set the hotkey to replace common Windows hotkeys (
|
||||
<kbd>Ctrl</kbd> + <kbd>C</kbd>, <kbd>Ctrl</kbd> + <kbd>V</kbd>, etc). This is not
|
||||
recommended.
|
||||
|
||||
3. Click OK to save your selection.
|
||||
|
||||
The new hotkey will now be available.
|
||||
|
||||
The hotkeys can also be set for a Keyman keyboard, using the [Hotkeys tab](hotkeys).
|
||||
|
||||
## Showing Introductory Help
|
||||
|
||||
To show introductory help for a Keyman keyboard from the Keyboard
|
||||
Layouts tab of Keyman Configuration:
|
||||
|
||||
1. Find a keyboard in the keyboard list.
|
||||
1. Select the keyboard name from the keyboard list to expand options associated with it.
|
||||
|
||||
2. Click on the question mark icon
|
||||
() beside the keyboard
|
||||
name. The keyboard help documentation will be shown.
|
||||
2. Click on the help button and the help documentation will be shown.
|
||||

|
||||
|
||||
## Viewing Keyboard Details
|
||||
|
||||
|
|
@ -60,23 +86,32 @@ Keyman Configuration:
|
|||
|
||||
1. Find a keyboard in the keyboard list.
|
||||
|
||||
2. Click on the down arrow
|
||||
() beside the keyboard
|
||||
name. The keyboard information window will expand.
|
||||
2. Select the keyboard name from the keyboard list to expand options associated with it.
|
||||
The keyboard information window will expand.
|
||||

|
||||
The initial drop down has the following information if available:
|
||||
|
||||

|
||||
- Languages associated with the keyboard
|
||||
- Keyboard package name
|
||||
- Keyboard package version number
|
||||
- Copyright details
|
||||
|
||||
3. In the information window you can view keyboard details, including:
|
||||
|
||||
|
||||
3. Click on the down arrow
|
||||
, at the end of the list will reveal
|
||||
further details including:
|
||||
|
||||
- Keyboard version number
|
||||
- Keyboard filename.
|
||||
- Keyboard package name.
|
||||
- Keyboard version number.
|
||||
- Keyboard encodings.
|
||||
- Keyboard layout type.
|
||||
- On Screen Keyboard status.
|
||||
- Documentation status.
|
||||
- Copyright details.
|
||||
- Installation details.
|
||||
- Keyboard included fonts
|
||||
- Keyboard encodings
|
||||
- Keyboard layout type
|
||||
- On Screen Keyboard status
|
||||
- Documentation status
|
||||
- Keyboard Message
|
||||
|
||||

|
||||
|
||||
## Sharing a keyboard with other users and devices
|
||||
|
||||
|
|
@ -85,7 +120,7 @@ then you can share the keyboard with other devices and users using a QR
|
|||
Code.
|
||||
|
||||
1. Expand the keyboard details for the keyboard you wish to share, and
|
||||
click Share keyboard.
|
||||
click the Share keyboard button.
|
||||
|
||||
2. A popup will appear with a QR Code. This QR Code can be scanned with
|
||||
a mobile phone camera to automatically open a web page with a
|
||||
|
|
|
|||
|
|
@ -33,12 +33,17 @@ To disable a Keyman keyboard:
|
|||
|
||||
4. Select the Keyboard Layouts tab.
|
||||
|
||||
5. Untick the checkbox beside the Keyman keyboard.
|
||||
5. Select the keyboard name you want to disable to expand options associated with it.
|
||||
|
||||
6. Click OK.
|
||||
6. Click on the Disable button.
|
||||
|
||||
When a keyboard layout is disabled, its name appears in grey and its
|
||||
checkbox is unticked.
|
||||

|
||||
|
||||
7. Click OK.
|
||||
|
||||
When a keyboard layout is disabled, its name and details appear in grey and the disable
|
||||
button now says enable. The Add/remove language... button is also disabled as this option is
|
||||
not available while the keyboard is disabled.
|
||||
|
||||
## Enabling a Keyman keyboard
|
||||
|
||||
|
|
@ -57,9 +62,13 @@ To enable a Keyman keyboard:
|
|||
|
||||
4. Select the Keyboard Layouts tab.
|
||||
|
||||
5. Tick the checkbox beside the Keyman keyboard.
|
||||
5. Select the keyboard name you want to enable to expand options associated with it.
|
||||
|
||||
6. Click OK.
|
||||
6. Click on the Enable button.
|
||||
|
||||

|
||||
|
||||
7. Click OK.
|
||||
|
||||
## Related Topics
|
||||
|
||||
|
|
|
|||
|
|
@ -23,13 +23,15 @@ To uninstall a Keyman keyboard:
|
|||
|
||||

|
||||
|
||||
5. Click on the uninstall icon 
|
||||
for the keyboard you want to uninstall.
|
||||
5. Click on the keyboard name for the keyboard you want to uninstall to
|
||||
expand options associated with it.
|
||||
|
||||
6. A message box is displayed asking you to confirm this is the package
|
||||
or keyboard layout that you wish to uninstall. Click OK.
|
||||
6. Click the Uninstall button.
|
||||
|
||||
7. Click OK.
|
||||
7. A message box is displayed asking you to confirm this is the package
|
||||
or keyboard layout that you wish to uninstall.
|
||||
|
||||
8. Click OK.
|
||||
|
||||
The Keyman keyboard is now removed from Keyman.
|
||||
|
||||
|
|
|
|||
|
Before Width: | Height: | Size: 26 KiB After Width: | Height: | Size: 32 KiB |
|
Before Width: | Height: | Size: 66 KiB After Width: | Height: | Size: 73 KiB |
|
Before Width: | Height: | Size: 52 KiB After Width: | Height: | Size: 45 KiB |
|
Before Width: | Height: | Size: 22 KiB |
|
Before Width: | Height: | Size: 41 KiB After Width: | Height: | Size: 43 KiB |
|
Before Width: | Height: | Size: 8.2 KiB After Width: | Height: | Size: 9.2 KiB |
|
Before Width: | Height: | Size: 6.6 KiB After Width: | Height: | Size: 11 KiB |
BIN
windows/src/desktop/help/desktop_images/tab-add-lang.png
Normal file
|
After Width: | Height: | Size: 43 KiB |
BIN
windows/src/desktop/help/desktop_images/tab-add-popup.png
Normal file
|
After Width: | Height: | Size: 50 KiB |
|
Before Width: | Height: | Size: 43 KiB After Width: | Height: | Size: 47 KiB |
|
Before Width: | Height: | Size: 58 KiB After Width: | Height: | Size: 32 KiB |
BIN
windows/src/desktop/help/desktop_images/tab-layout-detail1.png
Normal file
|
After Width: | Height: | Size: 42 KiB |
BIN
windows/src/desktop/help/desktop_images/tab-layout-detail2.png
Normal file
|
After Width: | Height: | Size: 51 KiB |
BIN
windows/src/desktop/help/desktop_images/tab-layout-disable.png
Normal file
|
After Width: | Height: | Size: 43 KiB |
BIN
windows/src/desktop/help/desktop_images/tab-layout-enable.png
Normal file
|
After Width: | Height: | Size: 44 KiB |
BIN
windows/src/desktop/help/desktop_images/tab-layout-help.png
Normal file
|
After Width: | Height: | Size: 43 KiB |
BIN
windows/src/desktop/help/desktop_images/tab-layout-share.png
Normal file
|
After Width: | Height: | Size: 43 KiB |
|
Before Width: | Height: | Size: 51 KiB After Width: | Height: | Size: 52 KiB |
|
Before Width: | Height: | Size: 61 KiB After Width: | Height: | Size: 51 KiB |
|
Before Width: | Height: | Size: 40 KiB After Width: | Height: | Size: 44 KiB |
|
|
@ -30,7 +30,7 @@ Correctly associating your Keyman keyboard has three main benefits.
|
|||
right-to-left languages like Arabic, Hebrew, and Farsi.
|
||||
|
||||
- Applications will know how characters and symbols should be
|
||||
rendered. This is partucularly necessary for many Indian
|
||||
rendered. This is particularly necessary for many Indian
|
||||
languages.
|
||||
|
||||
- Applications will know which language tools to use when spell
|
||||
|
|
@ -49,21 +49,24 @@ Correctly associating your Keyman keyboard has three main benefits.
|
|||
|
||||

|
||||
|
||||
4. Click on the down arrow
|
||||
() beside the keyboard
|
||||
name.
|
||||
4. Select the keyboard name to expand the options
|
||||
|
||||
5. Click the Add language button on the left side under 'Languages:'
|
||||
5. Click the Add/remove language... button
|
||||
|
||||

|
||||

|
||||
|
||||
6. From the pop up window, search for the Windows langauge you would
|
||||
6. Click the Add button on the first pop-up
|
||||
|
||||

|
||||
|
||||
|
||||
7. From the pop up window, search for the Windows language you would
|
||||
like to use and click OK
|
||||
|
||||

|
||||
|
||||
7. To remove an association, hover over the language name, and click
|
||||
the  button that appears.
|
||||
8. To remove an association, click
|
||||
the  button to the left of the language.
|
||||
|
||||
## Related Topics
|
||||
|
||||
|
|
|
|||
|
|
@ -129,9 +129,11 @@ implementation
|
|||
uses
|
||||
System.Types,
|
||||
Vcl.Themes,
|
||||
Sentry.Client,
|
||||
|
||||
Keyman.Configuration.UI.MitigationForWin10_1803,
|
||||
Keyman.System.LanguageCodeUtils,
|
||||
Keyman.System.KeymanSentryClient,
|
||||
Keyman.Configuration.System.TIPMaintenance,
|
||||
Keyman.UI.UfrmProgress,
|
||||
MessageIdentifierConsts,
|
||||
|
|
@ -147,6 +149,9 @@ uses
|
|||
{ TfrmInstallKeyboardLanguage }
|
||||
|
||||
function InstallKeyboardLanguage(Owner: TForm; const KeyboardID, ISOCode: string; Silent: Boolean): Boolean;
|
||||
var
|
||||
n: Integer;
|
||||
kbd: IKeymanKeyboardInstalled;
|
||||
begin
|
||||
Result := TTIPMaintenance.DoInstall(KeyboardID, ISOCode);
|
||||
if not Result then
|
||||
|
|
@ -157,7 +162,18 @@ begin
|
|||
end
|
||||
else
|
||||
CheckForMitigationWarningFor_Win10_1803(Silent, '');
|
||||
|
||||
// Enable the keyboard
|
||||
n := kmcom.Keyboards.IndexOf(KeyboardID);
|
||||
if n < 0 then
|
||||
begin
|
||||
// The Keyboard was successully installed for the BCP47Code
|
||||
// for some reason the index look up has failed. Still pass through
|
||||
// the DoInstall reasult, however the keyboard will not be enabled.
|
||||
TKeymanSentryClient.Client.MessageEvent(Sentry.Client.SENTRY_LEVEL_ERROR, 'InstallKeyboardLanguage: KeyboardID "'+KeyboardID+'" not found, attempting to install for language "'+ISOCode+'".');
|
||||
Exit;
|
||||
end;
|
||||
kbd := kmcom.Keyboards[n];
|
||||
kbd.Loaded := True;
|
||||
kmcom.Apply;
|
||||
Result := True;
|
||||
end;
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@
|
|||
Sentry.init({
|
||||
dsn: 'https://92eb58e6005d47daa33c9c9e39458eb7@o1005580.ingest.sentry.io/5983518', // Keyman for Windows
|
||||
environment: '$Environment',
|
||||
release: 'release-$VersionWithTag'
|
||||
release: 'release@$VersionWithTag'
|
||||
});
|
||||
|
||||
function keymanEnableDiagnostics() {
|
||||
|
|
|
|||