Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

WIP! feat(react-native-global-keyevent): add config plugin #244

Draft
wants to merge 1 commit into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions packages/react-native-global-keyevent/.eslintrc.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
// @generated by expo-module-scripts
module.exports = require('expo-module-scripts/eslintrc.base.js');
47 changes: 47 additions & 0 deletions packages/react-native-global-keyevent/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
# @config-plugins/react-native-global-keyevent

Expo Config Plugin to auto-configure [`react-native-global-keyevent`](https://www.npmjs.com/package/react-native-global-keyevent) when the native code is generated (`npx expo prebuild`).

## Versioning

| `expo` | `react-native-global-keyevent` | `@config-plugins/react-native-global-keyevent` |
|--------|--------------------------------|------------------------------------------------|
| 51.0.0 | 0.1.4 | 0.1.4 |

## Expo installation

> This package cannot be used in the "Expo Go" app because [it requires custom native code](https://docs.expo.io/workflow/customizing/).

First install the package with yarn, npm, or [`npx expo install`](https://docs.expo.io/workflow/expo-cli/#expo-install).

```sh
npx expo install react-native-global-keyevent @config-plugins/react-native-global-keyevent
```

After installing this npm package, add the [config plugin](https://docs.expo.io/guides/config-plugins/) to the [`plugins`](https://docs.expo.io/versions/latest/config/app/#plugins) array of your `app.json` or `app.config.js`:

```json
{
"expo": {
"plugins": ["@config-plugins/react-native-global-keyevent"]
}
}
```

Next, rebuild your app as described in the ["Adding custom native code"](https://docs.expo.io/workflow/customizing/) guide.

## API

The plugin does not provide any props for extra customization.

#### Example

```json
{
"expo": {
"plugins": [
"@config-plugins/react-native-global-keyevent"
]
}
}
```
1 change: 1 addition & 0 deletions packages/react-native-global-keyevent/app.plugin.js
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
module.exports = require("./build/withReactNativeGlobalKeyevent");
37 changes: 37 additions & 0 deletions packages/react-native-global-keyevent/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
{
"name": "@config-plugins/react-native-global-keyevent",
"version": "0.1.4",
"description": "Config plugin for react-native-global-keyevent package",
"main": "build/withReactNativeGlobalKeyevent.js",
"types": "build/withReactNativeGlobalKeyevent.d.ts",
"sideEffects": false,
"homepage": "https://github.com/mybigday/react-native-global-keyevent",
"repository": {
"type": "git",
"url": "https://github.com/expo/config-plugins.git",
"directory": "packages/react-native-global-keyevent"
},
"scripts": {
"build": "expo-module build",
"clean": "expo-module clean",
"lint": "expo-module lint",
"test": "expo-module test",
"prepare": "expo-module prepare",
"prepublishOnly": "expo-module prepublishOnly",
"expo-module": "expo-module"
},
"keywords": [
"react",
"expo",
"config-plugins",
"prebuild",
"react-native-global-keyevent",
"expo-51"
],
"peerDependencies": {
"expo": "^51"
},
"devDependencies": {
"expo-module-scripts": "^3.5.1"
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
import {
ConfigPlugin,
createRunOncePlugin,
withMainActivity,
} from "@expo/config-plugins";
import { addImports } from "@expo/config-plugins/build/android/codeMod";
import { mergeContents } from "@expo/config-plugins/build/utils/generateCode";

const MAIN_ACTIVITY_LANGUAGES: Record<
string,
{ code: string; anchor: RegExp }
> = {
java: {
code: `
@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
GlobalKeyEventModule instance = GlobalKeyEventModule.getInstance();
if (instance != null) instance.onKeyDownEvent(keyCode, event);
return super.onKeyDown(keyCode, event);
}

@Override
public boolean onKeyUp(int keyCode, KeyEvent event) {
GlobalKeyEventModule instance = GlobalKeyEventModule.getInstance();
if (instance != null) instance.onKeyUpEvent(keyCode, event);
return super.onKeyUp(keyCode, event);
}
`,
anchor: /return "main";\n\s*};/,
},
kt: {
code: `
override fun onKeyDown(keyCode: Int, event: KeyEvent): Boolean {
val instance = GlobalKeyEventModule.getInstance();
if (instance != null) instance.onKeyDownEvent(keyCode, event);
return super.onKeyDown(keyCode, event);
}

override fun onKeyUp(keyCode: Int , event: KeyEvent): Boolean {
val instance = GlobalKeyEventModule.getInstance();
if (instance != null) instance.onKeyUpEvent(keyCode, event);
return super.onKeyUp(keyCode, event);
}
`,
anchor: /override\sfun\sgetMainComponentName\(\).*/,
},
};

const addKeyBindings = (src: string, language: string) => {
const mainActivity = MAIN_ACTIVITY_LANGUAGES[language];
if (!mainActivity) {
throw new Error(
`react-native-global-keyevent config plugin does not support MainActivity.${language} yet`,
);
}

const newSrc = [];
newSrc.push(` ${mainActivity.code}`);

return mergeContents({
tag: "react-native-global-keyevent-onKey",
src,
newSrc: newSrc.join("\n"),
anchor: mainActivity.anchor,
offset: 1,
comment: "//",
});
};

const withAndroidMainActivityKeyboardEvents: ConfigPlugin<void> = (config) => {
return withMainActivity(config, async (config) => {
const src = addImports(
config.modResults.contents,
["android.view.KeyEvent", "com.globalkeyevent.GlobalKeyEventModule"],
config.modResults.language === "java",
);

config.modResults.contents = addKeyBindings(
src,
config.modResults.language,
).contents;

return config;
});
};

/**
* Apply react-native-global-keyevent configuration for Expo SDK 51 projects.
*/
const withReactNativeGlobalKeyevent: ConfigPlugin<void> = (config) => {
config = withAndroidMainActivityKeyboardEvents(config);

// Return the modified config.
return config;
};

const pkg = {
// Prevent this plugin from being run more than once.
// This pattern enables users to safely migrate off of this
// out-of-tree `@config-plugins/react-native-global-keyevent` to a future
// upstream plugin in `react-native-global-keyevent`
name: "react-native-global-keyevent",
// Indicates that this plugin is dangerously linked to a module,
// and might not work with the latest version of that module.
version: "UNVERSIONED",
};

export default createRunOncePlugin(
withReactNativeGlobalKeyevent,
pkg.name,
pkg.version,
);
8 changes: 8 additions & 0 deletions packages/react-native-global-keyevent/tsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
{
"extends": "expo-module-scripts/tsconfig.plugin",
"compilerOptions": {
"outDir": "./build"
},
"include": ["./src"],
"exclude": ["**/__mocks__/*", "**/__tests__/*"]
}