getTurboModule(
27 | const std::string name,
28 | const JavaTurboModule::InitParams ¶ms) override;
29 |
30 | /**
31 | * Test-only method. Allows user to verify whether a TurboModule can be
32 | * created by instances of this class.
33 | */
34 | bool canCreateTurboModule(std::string name);
35 | };
36 |
37 | } // namespace react
38 | } // namespace facebook
39 |
--------------------------------------------------------------------------------
/debug/packages/mobile/android/app/src/main/java/com/rxninputexample/newarchitecture/components/MainComponentsRegistry.java:
--------------------------------------------------------------------------------
1 | package com.rxninputexample.newarchitecture.components;
2 |
3 | import com.facebook.jni.HybridData;
4 | import com.facebook.proguard.annotations.DoNotStrip;
5 | import com.facebook.react.fabric.ComponentFactory;
6 | import com.facebook.soloader.SoLoader;
7 |
8 | /**
9 | * Class responsible to load the custom Fabric Components. This class has native methods and needs a
10 | * corresponding C++ implementation/header file to work correctly (already placed inside the jni/
11 | * folder for you).
12 | *
13 | * Please note that this class is used ONLY if you opt-in for the New Architecture (see the
14 | * `newArchEnabled` property). Is ignored otherwise.
15 | */
16 | @DoNotStrip
17 | public class MainComponentsRegistry {
18 | static {
19 | SoLoader.loadLibrary("fabricjni");
20 | }
21 |
22 | @DoNotStrip private final HybridData mHybridData;
23 |
24 | @DoNotStrip
25 | private native HybridData initHybrid(ComponentFactory componentFactory);
26 |
27 | @DoNotStrip
28 | private MainComponentsRegistry(ComponentFactory componentFactory) {
29 | mHybridData = initHybrid(componentFactory);
30 | }
31 |
32 | @DoNotStrip
33 | public static MainComponentsRegistry register(ComponentFactory componentFactory) {
34 | return new MainComponentsRegistry(componentFactory);
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/website/src/hooks/useMediaQuery.ts:
--------------------------------------------------------------------------------
1 | import {useEffect, useState} from 'react';
2 |
3 | function useMediaQuery(query: string): boolean {
4 | query = query.replaceAll('@media', '').trim();
5 |
6 | const getMatches = (query: string): boolean => {
7 | // Prevents SSR issues
8 | if (typeof window !== 'undefined') {
9 | return window.matchMedia(query).matches;
10 | }
11 | return false;
12 | };
13 |
14 | const [matches, setMatches] = useState(getMatches(query));
15 |
16 | function handleChange() {
17 | setMatches(getMatches(query));
18 | }
19 |
20 | useEffect(() => {
21 | if (typeof window == 'undefined') {
22 | return;
23 | }
24 |
25 | const matchMedia = window.matchMedia(query);
26 |
27 | // Triggered at the first client-side load and if query changes
28 | handleChange();
29 |
30 | // Listen matchMedia
31 | if (matchMedia.addListener) {
32 | matchMedia.addListener(handleChange);
33 | } else {
34 | matchMedia.addEventListener('change', handleChange);
35 | }
36 |
37 | return () => {
38 | if (matchMedia.removeListener) {
39 | matchMedia.removeListener(handleChange);
40 | } else {
41 | matchMedia.removeEventListener('change', handleChange);
42 | }
43 | };
44 | }, [query]);
45 |
46 | return matches;
47 | }
48 |
49 | export default useMediaQuery;
50 |
--------------------------------------------------------------------------------
/src/Input/index.ts:
--------------------------------------------------------------------------------
1 | import type getAxis from './getAxis';
2 | import type getAxisRaw from './getAxisRaw';
3 | import type isMouseButtonDown from './isMouseButtonDown';
4 | import type isMouseButtonUp from './isMouseButtonUp';
5 |
6 | export interface InputFunctions {
7 | isMouseButtonDown: typeof isMouseButtonDown;
8 | isMouseButtonUp: typeof isMouseButtonUp;
9 | getAxis: typeof getAxis;
10 | getAxisRaw: typeof getAxisRaw;
11 | }
12 |
13 | export interface InputVariables {
14 | /**
15 | * Returns if touch inputs are present, which maybe supported by device but that's not in use at moment.
16 | *
17 | * Can change on desktop web browsers, when toggle mobile simulation tools.
18 | *
19 | * @hook useTouchPresent
20 | * @event TouchListener.on('changeTouchPresence')
21 | * @returns boolean
22 | */
23 | touchPresent: boolean;
24 |
25 | /**
26 | * Returns if a mouse device is detected / connected.
27 | *
28 | * @hook useMousePresent
29 | * @event MouseListener.on('changeMousePresence')
30 | * @returns boolean
31 | */
32 | mousePresent: boolean;
33 |
34 | /**
35 | * The current mouse position in pixel coordinates. (X and Y)
36 | *
37 | * @hook useMousePosition
38 | * @event MouseListener.on('changeMousePosition')
39 | * @returns object
40 | */
41 | mousePosition: { x: number; y: number };
42 | }
43 |
44 | const Input = {} as InputFunctions & InputVariables;
45 |
46 | export default Input;
47 |
--------------------------------------------------------------------------------
/website/src/components/Layout/index.tsx:
--------------------------------------------------------------------------------
1 | import React, { useState, useEffect } from 'react';
2 | import useMediaQuery from '../../hooks/useMediaQuery';
3 | import iSelectedPage from '../../interfaces/SelectedPage';
4 | import BreakPoints from '../../styles/theme/BreakPoints';
5 | import MobileMenu from './MobileMenu';
6 | import TopBar from './TopBar';
7 |
8 | interface iProps {
9 | children?: JSX.Element;
10 | SelectedPage?: iSelectedPage;
11 | }
12 |
13 | const Layout = ({ children, SelectedPage }: iProps) => {
14 | const isDesktop = useMediaQuery(BreakPoints.up('sm'));
15 | const [mobileMenuOpen, setMobileMenuOpen] = useState(false);
16 |
17 | useEffect(() => {
18 | if (typeof window !== 'undefined') {
19 | if (mobileMenuOpen) {
20 | document.documentElement.style.overflow = 'hidden';
21 | } else {
22 | document.documentElement.style.overflow = 'auto';
23 | }
24 | }
25 | }, [mobileMenuOpen]);
26 |
27 | useEffect(() => {
28 | if (isDesktop) {
29 | setMobileMenuOpen(false);
30 | }
31 | }, [isDesktop]);
32 |
33 | return (
34 | <>
35 | {mobileMenuOpen && }
36 |
37 | {children}
38 | >
39 | );
40 | };
41 |
42 | export { LayoutContent } from './styles';
43 |
44 | export default Layout;
45 |
--------------------------------------------------------------------------------
/website/src/components/MdxComponents/styled.tsx:
--------------------------------------------------------------------------------
1 | import styled from 'styled-components';
2 | import BreakPoints from '../../styles/theme/BreakPoints';
3 | import Colors from '../../styles/theme/Colors';
4 |
5 | export const H1 = styled.h1`
6 | font-size: 1.8rem;
7 | margin-top: 1.5rem;
8 | margin-bottom: 1.5rem;
9 | `;
10 |
11 | export const P = styled.p`
12 | color: ${Colors.BLUEBLOUSE};
13 | margin-top: 2rem;
14 | margin-bottom: 2rem;
15 | font-size: 1.1rem;
16 |
17 | & > code {
18 | ${BreakPoints.down('md')} {
19 | display: block;
20 | }
21 | margin-left: 0.2rem;
22 | padding: 0.5rem;
23 | background-color: rgba(0, 0, 0, 0.2);
24 | border-radius: 0.4rem;
25 | color: ${Colors.ZIMABLUE};
26 | font-size: 0.9rem;
27 | overflow: auto !important;
28 | }
29 | `;
30 |
31 | export const A = styled.a`
32 | cursor: pointer;
33 | color: ${Colors.ZIMABLUE};
34 | border-bottom: solid 1px ${Colors.ZIMABLUE};
35 | `;
36 |
37 | export const Code = styled.div`
38 | min-width: 10rem;
39 | padding-bottom: 1rem;
40 | padding-top: 1rem;
41 | padding-left: 1rem;
42 | padding-right: 1rem;
43 | margin-top: 0.25rem;
44 | margin-bottom: 0.25rem;
45 | background-color: rgba(0, 0, 0, 0.2) !important;
46 | border-radius: 0.4rem;
47 | font-size: 0.9rem;
48 |
49 | overflow: auto;
50 |
51 | .inserted-sign {
52 | background-color: rgba(0, 200, 0, 0.06);
53 | }
54 | `;
55 |
--------------------------------------------------------------------------------
/debug/packages/mobile/android/app/_BUCK:
--------------------------------------------------------------------------------
1 | # To learn about Buck see [Docs](https://buckbuild.com/).
2 | # To run your application with Buck:
3 | # - install Buck
4 | # - `npm start` - to start the packager
5 | # - `cd android`
6 | # - `keytool -genkey -v -keystore keystores/debug.keystore -storepass android -alias androiddebugkey -keypass android -dname "CN=Android Debug,O=Android,C=US"`
7 | # - `./gradlew :app:copyDownloadableDepsToLibs` - make all Gradle compile dependencies available to Buck
8 | # - `buck install -r android/app` - compile, install and run application
9 | #
10 |
11 | load(":build_defs.bzl", "create_aar_targets", "create_jar_targets")
12 |
13 | lib_deps = []
14 |
15 | create_aar_targets(glob(["libs/*.aar"]))
16 |
17 | create_jar_targets(glob(["libs/*.jar"]))
18 |
19 | android_library(
20 | name = "all-libs",
21 | exported_deps = lib_deps,
22 | )
23 |
24 | android_library(
25 | name = "app-code",
26 | srcs = glob([
27 | "src/main/java/**/*.java",
28 | ]),
29 | deps = [
30 | ":all-libs",
31 | ":build_config",
32 | ":res",
33 | ],
34 | )
35 |
36 | android_build_config(
37 | name = "build_config",
38 | package = "com.rxninputexample",
39 | )
40 |
41 | android_resource(
42 | name = "res",
43 | package = "com.rxninputexample",
44 | res = "src/main/res",
45 | )
46 |
47 | android_binary(
48 | name = "app",
49 | keystore = "//android/keystores:debug",
50 | manifest = "src/main/AndroidManifest.xml",
51 | package_type = "debug",
52 | deps = [
53 | ":app-code",
54 | ],
55 | )
56 |
--------------------------------------------------------------------------------
/android/build.gradle:
--------------------------------------------------------------------------------
1 | buildscript {
2 | if (project == rootProject) {
3 | repositories {
4 | google()
5 | mavenCentral()
6 | jcenter()
7 | }
8 |
9 | dependencies {
10 | classpath 'com.android.tools.build:gradle:3.5.3'
11 | }
12 | }
13 | }
14 |
15 | apply plugin: 'com.android.library'
16 |
17 | def safeExtGet(prop, fallback) {
18 | rootProject.ext.has(prop) ? rootProject.ext.get(prop) : fallback
19 | }
20 |
21 | android {
22 | compileSdkVersion safeExtGet('RXNInput_compileSdkVersion', 29)
23 | defaultConfig {
24 | minSdkVersion safeExtGet('RXNInput_minSdkVersion', 16)
25 | targetSdkVersion safeExtGet('RXNInput_targetSdkVersion', 29)
26 | versionCode 1
27 | versionName "1.0"
28 |
29 | }
30 |
31 | buildTypes {
32 | release {
33 | minifyEnabled false
34 | }
35 | }
36 | lintOptions {
37 | disable 'GradleCompatible'
38 | }
39 | compileOptions {
40 | sourceCompatibility JavaVersion.VERSION_1_8
41 | targetCompatibility JavaVersion.VERSION_1_8
42 | }
43 | }
44 |
45 | repositories {
46 | mavenLocal()
47 | maven {
48 | // All of React Native (JS, Obj-C sources, Android binaries) is installed from npm
49 | url("$rootDir/../node_modules/react-native/android")
50 | }
51 | google()
52 | mavenCentral()
53 | jcenter()
54 | }
55 |
56 | dependencies {
57 | //noinspection GradleDynamicVersion
58 | implementation "com.facebook.react:react-native:+" // From node_modules
59 | }
60 |
--------------------------------------------------------------------------------
/debug/packages/mobile/android/app/src/main/jni/MainApplicationTurboModuleManagerDelegate.cpp:
--------------------------------------------------------------------------------
1 | #include "MainApplicationTurboModuleManagerDelegate.h"
2 | #include "MainApplicationModuleProvider.h"
3 |
4 | namespace facebook {
5 | namespace react {
6 |
7 | jni::local_ref
8 | MainApplicationTurboModuleManagerDelegate::initHybrid(
9 | jni::alias_ref) {
10 | return makeCxxInstance();
11 | }
12 |
13 | void MainApplicationTurboModuleManagerDelegate::registerNatives() {
14 | registerHybrid({
15 | makeNativeMethod(
16 | "initHybrid", MainApplicationTurboModuleManagerDelegate::initHybrid),
17 | makeNativeMethod(
18 | "canCreateTurboModule",
19 | MainApplicationTurboModuleManagerDelegate::canCreateTurboModule),
20 | });
21 | }
22 |
23 | std::shared_ptr
24 | MainApplicationTurboModuleManagerDelegate::getTurboModule(
25 | const std::string name,
26 | const std::shared_ptr jsInvoker) {
27 | // Not implemented yet: provide pure-C++ NativeModules here.
28 | return nullptr;
29 | }
30 |
31 | std::shared_ptr
32 | MainApplicationTurboModuleManagerDelegate::getTurboModule(
33 | const std::string name,
34 | const JavaTurboModule::InitParams ¶ms) {
35 | return MainApplicationModuleProvider(name, params);
36 | }
37 |
38 | bool MainApplicationTurboModuleManagerDelegate::canCreateTurboModule(
39 | std::string name) {
40 | return getTurboModule(name, nullptr) != nullptr ||
41 | getTurboModule(name, {.moduleName = name}) != nullptr;
42 | }
43 |
44 | } // namespace react
45 | } // namespace facebook
46 |
--------------------------------------------------------------------------------
/website/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "rxn-input-website",
3 | "version": "0.1.0",
4 | "private": true,
5 | "homepage": "https://luffos.github.io/rxn-input/",
6 | "description": "RXNInput Official Website",
7 | "scripts": {
8 | "predev": "node ./scripts/preGenFiles.js",
9 | "dev": "next dev",
10 | "prebuild": "node ./scripts/preGenFiles.js",
11 | "build": "next build && next export",
12 | "prestart": "node ./scripts/preGenFiles.js",
13 | "start": "next start",
14 | "prelint": "node ./scripts/preGenFiles.js",
15 | "lint": "next lint"
16 | },
17 | "dependencies": {
18 | "@fontsource/lato": "^4.5.10",
19 | "@mdx-js/loader": "^2.1.4",
20 | "@mdx-js/react": "^2.1.5",
21 | "@next/mdx": "^12.3.1",
22 | "@svgr/webpack": "^6.4.0",
23 | "chokidar": "^3.5.3",
24 | "glob": "^8.0.3",
25 | "gray-matter": "^4.0.3",
26 | "next": "12.3.1",
27 | "next-mdx-remote": "^4.1.0",
28 | "prism-react-renderer": "^1.3.5",
29 | "react": "18.2.0",
30 | "react-animated-components": "^4.0.0",
31 | "react-dom": "18.2.0",
32 | "remark-gfm": "^3.0.1",
33 | "styled-components": "^5.3.6",
34 | "uuid": "^9.0.0"
35 | },
36 | "devDependencies": {
37 | "@types/node": "18.8.3",
38 | "@types/react": "18.0.21",
39 | "@types/react-dom": "18.0.6",
40 | "@types/styled-components": "^5.1.26",
41 | "@typescript-eslint/eslint-plugin": "^5.41.0",
42 | "babel-plugin-styled-components": "^2.0.7",
43 | "eslint": "8.25.0",
44 | "eslint-config-next": "12.3.1",
45 | "eslint-config-prettier": "^8.5.0",
46 | "prettier": "^2.7.1",
47 | "typescript": "4.8.4"
48 | }
49 | }
50 |
--------------------------------------------------------------------------------
/src/listeners/KeyListener/index.web.ts:
--------------------------------------------------------------------------------
1 | import { EmitterSubscription, NativeEventEmitter, NativeModules } from 'react-native';
2 | import type { KeyListener as _KeyListener } from '.';
3 | import { ErrorMessages } from '../../ErrorMessages';
4 |
5 | const eventEmitter = new NativeEventEmitter(NativeModules.RXNInput);
6 |
7 | window.addEventListener('keydown', (e) => {
8 | eventEmitter.emit('keydown', e);
9 | });
10 |
11 | window.addEventListener('keyup', (e) => {
12 | eventEmitter.emit('keyup', e);
13 | });
14 |
15 | const KeyListener: typeof _KeyListener = {
16 | addListener: (event, callback) => {
17 | if (event.toLowerCase() === 'keydown' || event.toLowerCase() === 'keyup') {
18 | return eventEmitter.addListener(event.toLowerCase(), (e: KeyboardEvent) =>
19 | callback({
20 | keyCode: '',
21 | key: e.key,
22 | shiftKey: e.shiftKey,
23 | altKey: e.altKey,
24 | ctrlKey: e.ctrlKey,
25 | metaKey: e.metaKey,
26 | capsLock: e.getModifierState('CapsLock'),
27 | numLock: e.getModifierState('NumLock'),
28 | scrollLock: e.getModifierState('ScrollLock'),
29 | device: undefined,
30 | original: e,
31 | })
32 | );
33 | }
34 |
35 | throw Error(ErrorMessages.InvalidEvent);
36 | },
37 | removeListener: (listener: any) => {
38 | if (listener) {
39 | (listener as EmitterSubscription).remove();
40 | }
41 | },
42 | clearAllListeners: () => {
43 | eventEmitter.removeAllListeners('keyup');
44 | eventEmitter.removeAllListeners('keydown');
45 | },
46 | };
47 |
48 | const KeyEvent = {};
49 |
50 | export { KeyEvent, KeyListener };
51 |
--------------------------------------------------------------------------------
/debug/packages/mobile/android/app/src/main/jni/Android.mk:
--------------------------------------------------------------------------------
1 | THIS_DIR := $(call my-dir)
2 |
3 | include $(REACT_ANDROID_DIR)/Android-prebuilt.mk
4 |
5 | # If you wish to add a custom TurboModule or Fabric component in your app you
6 | # will have to include the following autogenerated makefile.
7 | # include $(GENERATED_SRC_DIR)/codegen/jni/Android.mk
8 | include $(CLEAR_VARS)
9 |
10 | LOCAL_PATH := $(THIS_DIR)
11 |
12 | # You can customize the name of your application .so file here.
13 | LOCAL_MODULE := rxninputexample_appmodules
14 |
15 | LOCAL_C_INCLUDES := $(LOCAL_PATH)
16 | LOCAL_SRC_FILES := $(wildcard $(LOCAL_PATH)/*.cpp)
17 | LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH)
18 |
19 | # If you wish to add a custom TurboModule or Fabric component in your app you
20 | # will have to uncomment those lines to include the generated source
21 | # files from the codegen (placed in $(GENERATED_SRC_DIR)/codegen/jni)
22 | #
23 | # LOCAL_C_INCLUDES += $(GENERATED_SRC_DIR)/codegen/jni
24 | # LOCAL_SRC_FILES += $(wildcard $(GENERATED_SRC_DIR)/codegen/jni/*.cpp)
25 | # LOCAL_EXPORT_C_INCLUDES += $(GENERATED_SRC_DIR)/codegen/jni
26 |
27 | # Here you should add any native library you wish to depend on.
28 | LOCAL_SHARED_LIBRARIES := \
29 | libfabricjni \
30 | libfbjni \
31 | libfolly_runtime \
32 | libglog \
33 | libjsi \
34 | libreact_codegen_rncore \
35 | libreact_debug \
36 | libreact_nativemodule_core \
37 | libreact_render_componentregistry \
38 | libreact_render_core \
39 | libreact_render_debug \
40 | libreact_render_graphics \
41 | librrc_view \
42 | libruntimeexecutor \
43 | libturbomodulejsijni \
44 | libyoga
45 |
46 | LOCAL_CFLAGS := -DLOG_TAG=\"ReactNative\" -fexceptions -frtti -std=c++17 -Wall
47 |
48 | include $(BUILD_SHARED_LIBRARY)
49 |
--------------------------------------------------------------------------------
/website/src/components/MdxComponents/index.tsx:
--------------------------------------------------------------------------------
1 | /* eslint-disable @typescript-eslint/no-explicit-any */
2 | /* eslint-disable react/jsx-key */
3 | import type { Components } from '@mdx-js/react/lib';
4 | import { P, A, H1, Code } from './styled';
5 | import Link from 'next/link';
6 |
7 | import Highlight, { defaultProps } from 'prism-react-renderer';
8 | import theme from 'prism-react-renderer/themes/dracula';
9 | import React from 'react';
10 |
11 | const resolveHref = (href: string) => {
12 | return href;
13 | };
14 |
15 | const MdxComponents: Components = {
16 | h1: ({ children }) => {children} ,
17 | p: ({ children }) => {children}
,
18 | code: ({ children, className }) => (
19 |
20 | {({ className, style, tokens, getLineProps, getTokenProps }) => (
21 |
22 | {tokens.map((line, i) => (
23 |
24 | {line.map((token, key) => {
25 | if (token.empty || token.content == '') {
26 | return ;
27 | }
28 | return ;
29 | })}
30 |
31 | ))}
32 |
33 | )}
34 |
35 | ),
36 | a: ({ children, href }) => (
37 |
38 | {children}
39 |
40 | ),
41 | };
42 |
43 | export default MdxComponents;
44 |
--------------------------------------------------------------------------------
/debug/packages/mobile/metro.config.js:
--------------------------------------------------------------------------------
1 | const path = require('path');
2 | const exclusionList = require('metro-config/src/defaults/exclusionList');
3 | const {
4 | getMetroTools,
5 | getMetroAndroidAssetsResolutionFix,
6 | } = require('react-native-monorepo-tools');
7 |
8 | const {getDefaultConfig} = require('metro-config');
9 |
10 | const moduleRoot = path.resolve(__dirname, '../../..');
11 |
12 | const monorepoMetroTools = getMetroTools();
13 |
14 | const androidAssetsResolutionFix = getMetroAndroidAssetsResolutionFix();
15 |
16 | module.exports = (async () => {
17 | const {
18 | resolver: {sourceExts, assetExts},
19 | } = await getDefaultConfig();
20 | return {
21 | transformer: {
22 | // Apply the Android assets resolution fix to the public path...
23 | publicPath: androidAssetsResolutionFix.publicPath,
24 | getTransformOptions: async () => ({
25 | transform: {
26 | experimentalImportSupport: false,
27 | inlineRequires: false,
28 | },
29 | }),
30 | },
31 | server: {
32 | // ...and to the server middleware.
33 | enhanceMiddleware: middleware => {
34 | return androidAssetsResolutionFix.applyMiddleware(middleware);
35 | },
36 | },
37 | // Add additional Yarn workspace package roots to the module map.
38 | // This allows importing importing from all the project's packages.
39 | watchFolders: [moduleRoot, ...monorepoMetroTools.watchFolders],
40 | resolver: {
41 | assetExts: assetExts,
42 | sourceExts: [...sourceExts],
43 | // Ensure we resolve nohoist libraries from this directory.
44 | blockList: exclusionList(monorepoMetroTools.blockList),
45 | extraNodeModules: monorepoMetroTools.extraNodeModules,
46 | },
47 | };
48 | })();
49 |
--------------------------------------------------------------------------------
/debug/packages/mobile/ios/RXNInputExample/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | en
7 | CFBundleDisplayName
8 | RXNInputExample
9 | CFBundleExecutable
10 | $(EXECUTABLE_NAME)
11 | CFBundleIdentifier
12 | $(PRODUCT_BUNDLE_IDENTIFIER)
13 | CFBundleInfoDictionaryVersion
14 | 6.0
15 | CFBundleName
16 | $(PRODUCT_NAME)
17 | CFBundlePackageType
18 | APPL
19 | CFBundleShortVersionString
20 | 1.0
21 | CFBundleSignature
22 | ????
23 | CFBundleVersion
24 | 1
25 | LSRequiresIPhoneOS
26 |
27 | NSAppTransportSecurity
28 |
29 | NSExceptionDomains
30 |
31 | localhost
32 |
33 | NSExceptionAllowsInsecureHTTPLoads
34 |
35 |
36 |
37 |
38 | NSLocationWhenInUseUsageDescription
39 |
40 | UILaunchStoryboardName
41 | LaunchScreen
42 | UIRequiredDeviceCapabilities
43 |
44 | armv7
45 |
46 | UISupportedInterfaceOrientations
47 |
48 | UIInterfaceOrientationPortrait
49 | UIInterfaceOrientationLandscapeLeft
50 | UIInterfaceOrientationLandscapeRight
51 |
52 | UIViewControllerBasedStatusBarAppearance
53 |
54 |
55 |
56 |
--------------------------------------------------------------------------------
/website/src/components/Layout/MobileMenu/index.tsx:
--------------------------------------------------------------------------------
1 | import React, { memo } from 'react';
2 | import { MobileMenuBackground, MobileMenuBox, MobileMenuWrapper } from './styles';
3 | import CloseSVG from '../../../assets/close-icon.svg';
4 | import Link from 'next/link';
5 | import GitHubSVG from '../../../assets/github-icon.svg';
6 | import { FadeIn } from 'react-animated-components';
7 | import iSelectedPage from '../../../interfaces/SelectedPage';
8 | //import iSelectedPage from '../../../interfaces/SelectedPage';
9 |
10 | interface iProps {
11 | SelectedPage?: iSelectedPage;
12 | setMobileMenuOpen: React.Dispatch>;
13 | }
14 |
15 | const MobileMenu = ({ SelectedPage, setMobileMenuOpen }: iProps) => {
16 | return (
17 |
18 |
19 | setMobileMenuOpen(false)} />
20 |
21 |
22 | setMobileMenuOpen(false)} className="closeWrapper">
23 |
24 |
25 |
47 |
48 |
49 | );
50 | };
51 |
52 | export default memo(MobileMenu);
53 |
--------------------------------------------------------------------------------
/debug/packages/mobile/android/gradle.properties:
--------------------------------------------------------------------------------
1 | # Project-wide Gradle settings.
2 |
3 | # IDE (e.g. Android Studio) users:
4 | # Gradle settings configured through the IDE *will override*
5 | # any settings specified in this file.
6 |
7 | # For more details on how to configure your build environment visit
8 | # http://www.gradle.org/docs/current/userguide/build_environment.html
9 |
10 | # Specifies the JVM arguments used for the daemon process.
11 | # The setting is particularly useful for tweaking memory settings.
12 | # Default value: -Xmx512m -XX:MaxMetaspaceSize=256m
13 | org.gradle.jvmargs=-Xmx2048m -XX:MaxMetaspaceSize=512m
14 |
15 | # When configured, Gradle will run in incubating parallel mode.
16 | # This option should only be used with decoupled projects. More details, visit
17 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
18 | # org.gradle.parallel=true
19 |
20 | # AndroidX package structure to make it clearer which packages are bundled with the
21 | # Android operating system, and which are packaged with your app's APK
22 | # https://developer.android.com/topic/libraries/support-library/androidx-rn
23 | android.useAndroidX=true
24 | # Automatically convert third-party libraries to use AndroidX
25 | android.enableJetifier=true
26 |
27 | # Version of flipper SDK to use with React Native
28 | FLIPPER_VERSION=0.125.0
29 |
30 | # Use this property to specify which architecture you want to build.
31 | # You can also override it from the CLI using
32 | # ./gradlew -PreactNativeArchitectures=x86_64
33 | reactNativeArchitectures=armeabi-v7a,arm64-v8a,x86,x86_64
34 |
35 | # Use this property to enable support to the new architecture.
36 | # This will allow you to use TurboModules and the Fabric render in
37 | # your application. You should enable this flag either if you want
38 | # to write custom TurboModules/Fabric components OR use libraries that
39 | # are providing them.
40 | newArchEnabled=false
41 |
--------------------------------------------------------------------------------
/debug/packages/mobile/android/build.gradle:
--------------------------------------------------------------------------------
1 | import org.apache.tools.ant.taskdefs.condition.Os
2 |
3 | // Top-level build file where you can add configuration options common to all sub-projects/modules.
4 |
5 | buildscript {
6 | ext {
7 | buildToolsVersion = "31.0.0"
8 | minSdkVersion = 21
9 | compileSdkVersion = 31
10 | targetSdkVersion = 31
11 |
12 | if (System.properties['os.arch'] == "aarch64") {
13 | // For M1 Users we need to use the NDK 24 which added support for aarch64
14 | ndkVersion = "24.0.8215888"
15 | } else {
16 | // Otherwise we default to the side-by-side NDK version from AGP.
17 | ndkVersion = "21.4.7075529"
18 | }
19 | }
20 | repositories {
21 | google()
22 | mavenCentral()
23 | }
24 | dependencies {
25 | classpath("com.android.tools.build:gradle:7.1.1")
26 | classpath("com.facebook.react:react-native-gradle-plugin")
27 | classpath("de.undercouch:gradle-download-task:5.0.1")
28 | // NOTE: Do not place your application dependencies here; they belong
29 | // in the individual module build.gradle files
30 | }
31 | }
32 |
33 | allprojects {
34 | repositories {
35 | maven {
36 | // All of React Native (JS, Obj-C sources, Android binaries) is installed from npm
37 | url("$rootDir/../node_modules/react-native/android")
38 | }
39 | maven {
40 | // Android JSC is installed from npm
41 | url("$rootDir/../node_modules/jsc-android/dist")
42 | }
43 | mavenCentral {
44 | // We don't want to fetch react-native from Maven Central as there are
45 | // older versions over there.
46 | content {
47 | excludeGroup "com.facebook.react"
48 | }
49 | }
50 | google()
51 | maven { url 'https://www.jitpack.io' }
52 | }
53 | }
54 |
--------------------------------------------------------------------------------
/debug/packages/mobile/android/app/src/main/res/drawable/rn_edit_text_material.xml:
--------------------------------------------------------------------------------
1 |
2 |
16 |
21 |
22 |
23 |
32 |
33 |
34 |
35 |
36 |
37 |
--------------------------------------------------------------------------------
/debug/packages/mobile/android/app/src/main/java/com/rxninputexample/newarchitecture/modules/MainApplicationTurboModuleManagerDelegate.java:
--------------------------------------------------------------------------------
1 | package com.rxninputexample.newarchitecture.modules;
2 |
3 | import com.facebook.jni.HybridData;
4 | import com.facebook.react.ReactPackage;
5 | import com.facebook.react.ReactPackageTurboModuleManagerDelegate;
6 | import com.facebook.react.bridge.ReactApplicationContext;
7 | import com.facebook.soloader.SoLoader;
8 | import java.util.List;
9 |
10 | /**
11 | * Class responsible to load the TurboModules. This class has native methods and needs a
12 | * corresponding C++ implementation/header file to work correctly (already placed inside the jni/
13 | * folder for you).
14 | *
15 | * Please note that this class is used ONLY if you opt-in for the New Architecture (see the
16 | * `newArchEnabled` property). Is ignored otherwise.
17 | */
18 | public class MainApplicationTurboModuleManagerDelegate
19 | extends ReactPackageTurboModuleManagerDelegate {
20 |
21 | private static volatile boolean sIsSoLibraryLoaded;
22 |
23 | protected MainApplicationTurboModuleManagerDelegate(
24 | ReactApplicationContext reactApplicationContext, List packages) {
25 | super(reactApplicationContext, packages);
26 | }
27 |
28 | protected native HybridData initHybrid();
29 |
30 | native boolean canCreateTurboModule(String moduleName);
31 |
32 | public static class Builder extends ReactPackageTurboModuleManagerDelegate.Builder {
33 | protected MainApplicationTurboModuleManagerDelegate build(
34 | ReactApplicationContext context, List packages) {
35 | return new MainApplicationTurboModuleManagerDelegate(context, packages);
36 | }
37 | }
38 |
39 | @Override
40 | protected synchronized void maybeLoadOtherSoLibraries() {
41 | if (!sIsSoLibraryLoaded) {
42 | // If you change the name of your application .so file in the Android.mk file,
43 | // make sure you update the name here as well.
44 | SoLoader.loadLibrary("rxninputexample_appmodules");
45 | sIsSoLibraryLoaded = true;
46 | }
47 | }
48 | }
49 |
--------------------------------------------------------------------------------
/debug/packages/mobile/ios/RXNInputExampleTests/RXNInputExampleTests.m:
--------------------------------------------------------------------------------
1 | #import
2 | #import
3 |
4 | #import
5 | #import
6 |
7 | #define TIMEOUT_SECONDS 600
8 | #define TEXT_TO_LOOK_FOR @"Welcome to React"
9 |
10 | @interface RXNInputExampleTests : XCTestCase
11 |
12 | @end
13 |
14 | @implementation RXNInputExampleTests
15 |
16 | - (BOOL)findSubviewInView:(UIView *)view matching:(BOOL (^)(UIView *view))test
17 | {
18 | if (test(view)) {
19 | return YES;
20 | }
21 | for (UIView *subview in [view subviews]) {
22 | if ([self findSubviewInView:subview matching:test]) {
23 | return YES;
24 | }
25 | }
26 | return NO;
27 | }
28 |
29 | - (void)testRendersWelcomeScreen
30 | {
31 | UIViewController *vc = [[[RCTSharedApplication() delegate] window] rootViewController];
32 | NSDate *date = [NSDate dateWithTimeIntervalSinceNow:TIMEOUT_SECONDS];
33 | BOOL foundElement = NO;
34 |
35 | __block NSString *redboxError = nil;
36 | #ifdef DEBUG
37 | RCTSetLogFunction(
38 | ^(RCTLogLevel level, RCTLogSource source, NSString *fileName, NSNumber *lineNumber, NSString *message) {
39 | if (level >= RCTLogLevelError) {
40 | redboxError = message;
41 | }
42 | });
43 | #endif
44 |
45 | while ([date timeIntervalSinceNow] > 0 && !foundElement && !redboxError) {
46 | [[NSRunLoop mainRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate dateWithTimeIntervalSinceNow:0.1]];
47 | [[NSRunLoop mainRunLoop] runMode:NSRunLoopCommonModes beforeDate:[NSDate dateWithTimeIntervalSinceNow:0.1]];
48 |
49 | foundElement = [self findSubviewInView:vc.view
50 | matching:^BOOL(UIView *view) {
51 | if ([view.accessibilityLabel isEqualToString:TEXT_TO_LOOK_FOR]) {
52 | return YES;
53 | }
54 | return NO;
55 | }];
56 | }
57 |
58 | #ifdef DEBUG
59 | RCTSetLogFunction(RCTDefaultLogFunction);
60 | #endif
61 |
62 | XCTAssertNil(redboxError, @"RedBox error: %@", redboxError);
63 | XCTAssertTrue(foundElement, @"Couldn't find element with text '%@' in %d seconds", TEXT_TO_LOOK_FOR, TIMEOUT_SECONDS);
64 | }
65 |
66 | @end
67 |
--------------------------------------------------------------------------------
/debug/packages/mobile/android/app/src/main/jni/MainComponentsRegistry.cpp:
--------------------------------------------------------------------------------
1 | #include "MainComponentsRegistry.h"
2 |
3 | #include
4 | #include
5 | #include
6 | #include
7 |
8 | namespace facebook {
9 | namespace react {
10 |
11 | MainComponentsRegistry::MainComponentsRegistry(ComponentFactory *delegate) {}
12 |
13 | std::shared_ptr
14 | MainComponentsRegistry::sharedProviderRegistry() {
15 | auto providerRegistry = CoreComponentsRegistry::sharedProviderRegistry();
16 |
17 | // Custom Fabric Components go here. You can register custom
18 | // components coming from your App or from 3rd party libraries here.
19 | //
20 | // providerRegistry->add(concreteComponentDescriptorProvider<
21 | // AocViewerComponentDescriptor>());
22 | return providerRegistry;
23 | }
24 |
25 | jni::local_ref
26 | MainComponentsRegistry::initHybrid(
27 | jni::alias_ref,
28 | ComponentFactory *delegate) {
29 | auto instance = makeCxxInstance(delegate);
30 |
31 | auto buildRegistryFunction =
32 | [](EventDispatcher::Weak const &eventDispatcher,
33 | ContextContainer::Shared const &contextContainer)
34 | -> ComponentDescriptorRegistry::Shared {
35 | auto registry = MainComponentsRegistry::sharedProviderRegistry()
36 | ->createComponentDescriptorRegistry(
37 | {eventDispatcher, contextContainer});
38 |
39 | auto mutableRegistry =
40 | std::const_pointer_cast(registry);
41 |
42 | mutableRegistry->setFallbackComponentDescriptor(
43 | std::make_shared(
44 | ComponentDescriptorParameters{
45 | eventDispatcher, contextContainer, nullptr}));
46 |
47 | return registry;
48 | };
49 |
50 | delegate->buildRegistryFunction = buildRegistryFunction;
51 | return instance;
52 | }
53 |
54 | void MainComponentsRegistry::registerNatives() {
55 | registerHybrid({
56 | makeNativeMethod("initHybrid", MainComponentsRegistry::initHybrid),
57 | });
58 | }
59 |
60 | } // namespace react
61 | } // namespace facebook
62 |
--------------------------------------------------------------------------------
/debug/packages/mobile/android/app/src/main/java/com/rxninputexample/MainActivity.java:
--------------------------------------------------------------------------------
1 | package com.rxninputexample;
2 |
3 | import android.view.KeyEvent;
4 |
5 | import com.facebook.react.ReactActivity;
6 | import com.facebook.react.ReactActivityDelegate;
7 | import com.facebook.react.ReactRootView;
8 | import com.rxninput.RXNInputModule;
9 |
10 | public class MainActivity extends ReactActivity {
11 |
12 | @Override
13 | public boolean onKeyDown(int keyCode, KeyEvent event) {
14 | RXNInputModule.onKeyDownEvent(keyCode, event);
15 | super.onKeyDown(keyCode, event);
16 | return true;
17 | }
18 |
19 | @Override
20 | public boolean onKeyUp(int keyCode, KeyEvent event) {
21 | RXNInputModule.onKeyUpEvent(keyCode, event);
22 | super.onKeyUp(keyCode, event);
23 | return true;
24 | }
25 |
26 |
27 | /**
28 | * Returns the name of the main component registered from JavaScript. This is used to schedule
29 | * rendering of the component.
30 | */
31 | @Override
32 | protected String getMainComponentName() {
33 | return "RXNInputExample";
34 | }
35 |
36 | /**
37 | * Returns the instance of the {@link ReactActivityDelegate}. There the RootView is created and
38 | * you can specify the renderer you wish to use - the new renderer (Fabric) or the old renderer
39 | * (Paper).
40 | */
41 | @Override
42 | protected ReactActivityDelegate createReactActivityDelegate() {
43 | return new MainActivityDelegate(this, getMainComponentName());
44 | }
45 |
46 | public static class MainActivityDelegate extends ReactActivityDelegate {
47 | public MainActivityDelegate(ReactActivity activity, String mainComponentName) {
48 | super(activity, mainComponentName);
49 | }
50 |
51 | @Override
52 | protected ReactRootView createRootView() {
53 | ReactRootView reactRootView = new ReactRootView(getContext());
54 | // If you opted-in for the New Architecture, we enable the Fabric Renderer.
55 | reactRootView.setIsFabric(BuildConfig.IS_NEW_ARCHITECTURE_ENABLED);
56 | return reactRootView;
57 | }
58 |
59 | @Override
60 | protected boolean isConcurrentRootEnabled() {
61 | // If you opted-in for the New Architecture, we enable Concurrent Root (i.e. React 18).
62 | // More on this on https://reactjs.org/blog/2022/03/29/react-v18.html
63 | return BuildConfig.IS_NEW_ARCHITECTURE_ENABLED;
64 | }
65 | }
66 | }
67 |
--------------------------------------------------------------------------------
/website/src/components/DocsNavigator/index.tsx:
--------------------------------------------------------------------------------
1 | /* eslint-disable @typescript-eslint/no-unused-vars */
2 | /* eslint-disable @typescript-eslint/no-explicit-any */
3 | import { memo, useCallback } from 'react';
4 | import Colors from '../../styles/theme/Colors';
5 | import { MainUl } from './styled';
6 | import Link from 'next/link';
7 |
8 | import DocsData from '../../content/docs/data.json';
9 | import { Router, useRouter } from 'next/router';
10 |
11 | const DocsNavigator = () => {
12 | const router = useRouter();
13 |
14 | const getSlugLink = (slugs: Array) => {
15 | // Remove /vx.x.x/ from url
16 | return slugs
17 | .slice(-1)[0]
18 | .split('docs/')
19 | .pop()
20 | ?.replace(/v(\d+\.)?(\d+\.)?(\*|\d+)\//g, '');
21 | };
22 |
23 | const isCurrentDoc = useCallback(
24 | (slugs: Array) => {
25 | const transform = (str: string) => str.split('docs/')?.pop()?.split('/docs')?.pop()?.replace(/\/+$/, '');
26 |
27 | return slugs.find((i: any) => transform(i) == transform(router.asPath)) ? true : false;
28 | },
29 | [router]
30 | );
31 |
32 | return (
33 |
34 | {(() => {
35 | const d: Array
= [];
36 | Object.keys(DocsData).forEach((version) => {
37 | if (version != 'v1.0.0') return;
38 |
39 | Object.keys((DocsData as any)[version]).map((folder, index) => {
40 | d.push(
41 |
42 | {
44 | e.currentTarget.parentElement?.toggleAttribute('data-navclosed');
45 | }}
46 | >
47 | {folder}
48 |
49 |
50 | {Object.keys((DocsData as any)[version][folder]).map((docName, index) => {
51 | return (
52 |
53 |
54 | {docName}
55 |
56 |
57 | );
58 | })}
59 |
60 | );
61 | });
62 | });
63 | return d;
64 | })()}
65 |
66 | );
67 | };
68 |
69 | export default memo(DocsNavigator);
70 |
--------------------------------------------------------------------------------
/website/src/components/Layout/TopBar/index.tsx:
--------------------------------------------------------------------------------
1 | import Link from 'next/link';
2 | import React, { memo, useState } from 'react';
3 | import LogoSVG from '../../../assets/Logo.svg';
4 | import GitHubSVG from '../../../assets/github-icon.svg';
5 | import KebabSVG from '../../../assets/kebab-icon.svg';
6 | import { ContentWrapper, InnerWrapper, MobileKebab, RItems, Wrapper } from './styles';
7 | import useMediaQuery from '../../../hooks/useMediaQuery';
8 | import BreakPoints from '../../../styles/theme/BreakPoints';
9 | import useEffectOnce from '../../../hooks/useEffectOnce';
10 | import iSelectedPage from '../../../interfaces/SelectedPage';
11 | import useScrollPosition from '../../../hooks/useScrollPosition';
12 |
13 | interface iProps {
14 | SelectedPage?: iSelectedPage;
15 | setMobileMenuOpen: React.Dispatch>;
16 | }
17 |
18 | const TopBar = ({ SelectedPage, setMobileMenuOpen }: iProps) => {
19 | const [canShowKebab, setCanShowKebab] = useState(false);
20 | const showKebab = useMediaQuery(BreakPoints.down('md'));
21 | const scrollPosition = useScrollPosition();
22 |
23 | useEffectOnce(() => {
24 | setCanShowKebab(true);
25 | });
26 |
27 | return (
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 | DOCUMENTATION
42 |
43 |
44 |
45 |
46 |
47 |
48 | EXAMPLES
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 | {canShowKebab && showKebab && (
60 | setMobileMenuOpen(true)}>
61 |
62 |
63 | )}
64 |
65 |
66 |
67 | );
68 | };
69 |
70 | export default memo(TopBar);
71 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "rxn-input",
3 | "version": "0.0.1",
4 | "license": "MIT",
5 | "author": "Luffos",
6 | "description": "🎮 🖱️ ⌨️ Cross-Platform Input Handler for React Native and React Native Web.",
7 | "keywords": [
8 | "react",
9 | "typescript",
10 | "react-native",
11 | "input",
12 | "react-native-web",
13 | "rxn",
14 | "gamepad",
15 | "keyboard",
16 | "mouse"
17 | ],
18 | "homepage": "https://github.com/Luffos/rxn-input#readme",
19 | "bugs": {
20 | "url": "https://github.com/Luffos/rxn-input/issues"
21 | },
22 | "repository": {
23 | "type": "git",
24 | "url": "git+https://github.com/Luffos/rxn-input.git"
25 | },
26 | "main": "dist/index.js",
27 | "source": "src/index",
28 | "types": "dist/index.d.ts",
29 | "react-native": "dist/index.js",
30 | "files": [
31 | "android",
32 | "ios",
33 | "rxn-input.podspec",
34 | "!lib/typescript/example",
35 | "!android/build",
36 | "!ios/build",
37 | "!**/__tests__",
38 | "!**/__fixtures__",
39 | "!**/__mocks__",
40 | "dist"
41 | ],
42 | "scripts": {
43 | "lint": "eslint . --ext .ts,.tsx",
44 | "mobile:android": "cd ./debug/packages/mobile & yarn android",
45 | "mobile:ios": "cd ./debug/packages/mobile & yarn ios",
46 | "mobile:start": "cd ./debug/packages/mobile & yarn start",
47 | "test": "jest",
48 | "web:start": "cd ./debug/packages/web & yarn start",
49 | "build": "rimraf ./dist && tsc --build",
50 | "build-watch": "watch \"npm run build\" ./src --interval 1 --wait 0.1",
51 | "prepack": "npm run build"
52 | },
53 | "jest": {
54 | "moduleFileExtensions": [
55 | "ts",
56 | "tsx",
57 | "js",
58 | "jsx",
59 | "json",
60 | "node"
61 | ],
62 | "preset": "react-native"
63 | },
64 | "resolutions": {
65 | "@types/react": "^17"
66 | },
67 | "dependencies": {
68 | "react": "17.0.2",
69 | "react-native": "0.68.2"
70 | },
71 | "devDependencies": {
72 | "@babel/core": "^7.19.6",
73 | "@babel/runtime": "^7.19.0",
74 | "@react-native-community/eslint-config": "^2.0.0",
75 | "@types/jest": "^29.0.3",
76 | "@types/react-native": "^0.67.3",
77 | "@types/react-test-renderer": "^17.0.1",
78 | "@typescript-eslint/eslint-plugin": "^5.39.0",
79 | "@typescript-eslint/parser": "^5.17.0",
80 | "babel-jest": "^26.6.3",
81 | "eslint": "^7.32.0",
82 | "jest": "^29.0.3",
83 | "metro-react-native-babel-preset": "^0.73.1",
84 | "react-test-renderer": "17.0.2",
85 | "typescript": "^4.8.4"
86 | },
87 | "rnpm": {
88 | "android": {
89 | "packageInstance": "new RXNInputPackage()"
90 | }
91 | }
92 | }
93 |
--------------------------------------------------------------------------------
/website/src/pages/index.tsx:
--------------------------------------------------------------------------------
1 | import { useState, useLayoutEffect } from 'react';
2 | import type { NextPage } from 'next';
3 | import Layout, { LayoutContent } from '../components/Layout';
4 | import { Title, SubTitle, DevicesWrapper, Section1Content, GetStartedButton, Section1Background, Section1 } from '../styles/pages/index.styles';
5 | import DeviceSVG from '../assets/Devices.svg';
6 | import Head from 'next/head';
7 | import useMediaQuery from '../hooks/useMediaQuery';
8 | import BreakPoints from '../styles/theme/BreakPoints';
9 | import Link from 'next/link';
10 |
11 | const Home: NextPage = () => {
12 | const downLg = useMediaQuery(BreakPoints.down('lg'));
13 |
14 | const [showSection1, setShowSection1] = useState(false);
15 |
16 | useLayoutEffect(() => {
17 | setShowSection1(true);
18 | }, []);
19 |
20 | return (
21 | <>
22 |
23 | RXN Input - Cross Platform Input Handler for React and React Native.
24 |
25 |
26 |
27 |
28 | {showSection1 && (
29 |
30 |
31 |
32 |
33 |
34 |
35 | Cross-Platform Input Handler
36 |
37 | for React and React Native
38 |
39 |
40 | Mouse, Touches, Keyboard and Gamepad
41 |
42 | {!downLg && (
43 |
44 |
45 | Get started
46 |
47 |
48 | )}
49 |
50 |
51 |
52 |
53 | {downLg && (
54 |
55 |
56 | Get started
57 |
58 |
59 | )}
60 |
61 |
62 |
63 | )}
64 |
65 |
66 | >
67 | );
68 | };
69 |
70 | export default Home;
71 |
--------------------------------------------------------------------------------
/android/gradlew.bat:
--------------------------------------------------------------------------------
1 | @rem
2 | @rem Copyright 2015 the original author or authors.
3 | @rem
4 | @rem Licensed under the Apache License, Version 2.0 (the "License");
5 | @rem you may not use this file except in compliance with the License.
6 | @rem You may obtain a copy of the License at
7 | @rem
8 | @rem https://www.apache.org/licenses/LICENSE-2.0
9 | @rem
10 | @rem Unless required by applicable law or agreed to in writing, software
11 | @rem distributed under the License is distributed on an "AS IS" BASIS,
12 | @rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | @rem See the License for the specific language governing permissions and
14 | @rem limitations under the License.
15 | @rem
16 |
17 | @if "%DEBUG%" == "" @echo off
18 | @rem ##########################################################################
19 | @rem
20 | @rem Gradle startup script for Windows
21 | @rem
22 | @rem ##########################################################################
23 |
24 | @rem Set local scope for the variables with windows NT shell
25 | if "%OS%"=="Windows_NT" setlocal
26 |
27 | set DIRNAME=%~dp0
28 | if "%DIRNAME%" == "" set DIRNAME=.
29 | set APP_BASE_NAME=%~n0
30 | set APP_HOME=%DIRNAME%
31 |
32 | @rem Resolve any "." and ".." in APP_HOME to make it shorter.
33 | for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
34 |
35 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
36 | set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
37 |
38 | @rem Find java.exe
39 | if defined JAVA_HOME goto findJavaFromJavaHome
40 |
41 | set JAVA_EXE=java.exe
42 | %JAVA_EXE% -version >NUL 2>&1
43 | if "%ERRORLEVEL%" == "0" goto execute
44 |
45 | echo.
46 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
47 | echo.
48 | echo Please set the JAVA_HOME variable in your environment to match the
49 | echo location of your Java installation.
50 |
51 | goto fail
52 |
53 | :findJavaFromJavaHome
54 | set JAVA_HOME=%JAVA_HOME:"=%
55 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe
56 |
57 | if exist "%JAVA_EXE%" goto execute
58 |
59 | echo.
60 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
61 | echo.
62 | echo Please set the JAVA_HOME variable in your environment to match the
63 | echo location of your Java installation.
64 |
65 | goto fail
66 |
67 | :execute
68 | @rem Setup the command line
69 |
70 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
71 |
72 |
73 | @rem Execute Gradle
74 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %*
75 |
76 | :end
77 | @rem End local scope for the variables with windows NT shell
78 | if "%ERRORLEVEL%"=="0" goto mainEnd
79 |
80 | :fail
81 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
82 | rem the _cmd.exe /c_ return code!
83 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
84 | exit /b 1
85 |
86 | :mainEnd
87 | if "%OS%"=="Windows_NT" endlocal
88 |
89 | :omega
90 |
--------------------------------------------------------------------------------
/debug/packages/mobile/android/gradlew.bat:
--------------------------------------------------------------------------------
1 | @rem
2 | @rem Copyright 2015 the original author or authors.
3 | @rem
4 | @rem Licensed under the Apache License, Version 2.0 (the "License");
5 | @rem you may not use this file except in compliance with the License.
6 | @rem You may obtain a copy of the License at
7 | @rem
8 | @rem https://www.apache.org/licenses/LICENSE-2.0
9 | @rem
10 | @rem Unless required by applicable law or agreed to in writing, software
11 | @rem distributed under the License is distributed on an "AS IS" BASIS,
12 | @rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | @rem See the License for the specific language governing permissions and
14 | @rem limitations under the License.
15 | @rem
16 |
17 | @if "%DEBUG%" == "" @echo off
18 | @rem ##########################################################################
19 | @rem
20 | @rem Gradle startup script for Windows
21 | @rem
22 | @rem ##########################################################################
23 |
24 | @rem Set local scope for the variables with windows NT shell
25 | if "%OS%"=="Windows_NT" setlocal
26 |
27 | set DIRNAME=%~dp0
28 | if "%DIRNAME%" == "" set DIRNAME=.
29 | set APP_BASE_NAME=%~n0
30 | set APP_HOME=%DIRNAME%
31 |
32 | @rem Resolve any "." and ".." in APP_HOME to make it shorter.
33 | for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
34 |
35 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
36 | set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
37 |
38 | @rem Find java.exe
39 | if defined JAVA_HOME goto findJavaFromJavaHome
40 |
41 | set JAVA_EXE=java.exe
42 | %JAVA_EXE% -version >NUL 2>&1
43 | if "%ERRORLEVEL%" == "0" goto execute
44 |
45 | echo.
46 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
47 | echo.
48 | echo Please set the JAVA_HOME variable in your environment to match the
49 | echo location of your Java installation.
50 |
51 | goto fail
52 |
53 | :findJavaFromJavaHome
54 | set JAVA_HOME=%JAVA_HOME:"=%
55 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe
56 |
57 | if exist "%JAVA_EXE%" goto execute
58 |
59 | echo.
60 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
61 | echo.
62 | echo Please set the JAVA_HOME variable in your environment to match the
63 | echo location of your Java installation.
64 |
65 | goto fail
66 |
67 | :execute
68 | @rem Setup the command line
69 |
70 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
71 |
72 |
73 | @rem Execute Gradle
74 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %*
75 |
76 | :end
77 | @rem End local scope for the variables with windows NT shell
78 | if "%ERRORLEVEL%"=="0" goto mainEnd
79 |
80 | :fail
81 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
82 | rem the _cmd.exe /c_ return code!
83 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
84 | exit /b 1
85 |
86 | :mainEnd
87 | if "%OS%"=="Windows_NT" endlocal
88 |
89 | :omega
90 |
--------------------------------------------------------------------------------
/website/src/pages/docs/[[...slug]].tsx:
--------------------------------------------------------------------------------
1 | /* eslint-disable @typescript-eslint/no-unused-vars */
2 | /* eslint-disable @typescript-eslint/no-explicit-any */
3 | import { GetStaticPaths } from 'next';
4 | import Head from 'next/head';
5 | import React from 'react';
6 | import Layout, { LayoutContent } from '../../components/Layout';
7 | import getDocBySlug from '../../helpers/getDocBySlug';
8 | import { serialize } from 'next-mdx-remote/serialize';
9 | import { MDXRemote } from 'next-mdx-remote';
10 | import MdxComponents from '../../components/MdxComponents';
11 | import DocsNavigator from '../../components/DocsNavigator';
12 | import remarkGfm from 'remark-gfm';
13 |
14 | import DocsData from '../../content/docs/data.json';
15 | import useMediaQuery from '../../hooks/useMediaQuery';
16 | import BreakPoints from '../../styles/theme/BreakPoints';
17 | import Sizes from '../../styles/theme/Sizes';
18 |
19 | export default function Docs({ url, doc, source }: any) {
20 | const isMobile = useMediaQuery(BreakPoints.down('md'));
21 |
22 | return (
23 | <>
24 |
25 | RXN Input - Documentation
26 |
27 |
28 |
29 |
30 | {!isMobile && (
31 |
32 |
33 |
34 | )}
35 |
42 |
{doc.frontmatter.title}
43 |
44 |
45 |
46 |
47 | >
48 | );
49 | }
50 |
51 | export const getStaticProps = async ({ params }: any) => {
52 | const doc = getDocBySlug(DocsData, params?.slug) as any;
53 | const mdxSource = await serialize(doc?.body, { parseFrontmatter: true, mdxOptions: { remarkPlugins: [remarkGfm] } });
54 |
55 | return {
56 | props: {
57 | url: params?.slug ? Array.from(params.slug).join('/') : '/',
58 | doc: doc,
59 | source: mdxSource,
60 | },
61 | };
62 | };
63 |
64 | export const getStaticPaths: GetStaticPaths<{ slug: Array | undefined }> = async () => {
65 | const paths: Array<{ params: { slug: Array | undefined } }> = [];
66 |
67 | Object.keys(DocsData).forEach((version) => {
68 | Object.keys((DocsData as any)[version]).forEach((folder) => {
69 | Object.keys((DocsData as any)[version][folder]).forEach((docName) => {
70 | (DocsData as any)[version][folder][docName].slugs.forEach((slug: string) => {
71 | paths.push({ params: { slug: slug.split('/').slice(1)[0] == '' ? undefined : slug.split('/').slice(1) } });
72 | });
73 | });
74 | });
75 | });
76 |
77 | return {
78 | paths: paths,
79 | fallback: false,
80 | };
81 | };
82 |
--------------------------------------------------------------------------------
/debug/packages/web/craco.config.js:
--------------------------------------------------------------------------------
1 | /* eslint-disable no-unused-vars */
2 | const webpack = require("webpack");
3 | const path = require('path')
4 |
5 | const {
6 | when,
7 | whenDev,
8 | whenProd,
9 | whenTest,
10 | ESLINT_MODES,
11 | POSTCSS_MODES,
12 | getLoader,
13 | loaderByName,
14 | getPlugin,
15 | pluginByName
16 | } = require("@craco/craco");
17 |
18 | const {
19 | getWebpackTools
20 | } = require("react-native-monorepo-tools");
21 |
22 | const monorepoWebpackTools = getWebpackTools();
23 |
24 | const findWebpackPlugin = (webpackConfig, pluginName) =>
25 | webpackConfig.resolve.plugins.find(
26 | ({
27 | constructor
28 | }) => constructor && constructor.name === pluginName,
29 | );
30 |
31 | const enableTypescriptImportsFromExternalPaths = (
32 | webpackConfig,
33 | newIncludePaths,
34 | ) => {
35 | const oneOfRule = webpackConfig.module.rules.find(rule => rule.oneOf);
36 | if (oneOfRule) {
37 | const tsxRule = oneOfRule.oneOf.find(
38 | rule => rule.test && rule.test.toString().includes('tsx'),
39 | );
40 |
41 | if (tsxRule) {
42 | tsxRule.include = Array.isArray(tsxRule.include) ?
43 | [...tsxRule.include, ...newIncludePaths] :
44 | [tsxRule.include, ...newIncludePaths];
45 | }
46 | }
47 | };
48 |
49 | const addPathsToModuleScopePlugin = (webpackConfig, paths) => {
50 | const moduleScopePlugin = findWebpackPlugin(
51 | webpackConfig,
52 | 'ModuleScopePlugin',
53 | );
54 | if (!moduleScopePlugin) {
55 | throw new Error(`Expected to find plugin "ModuleScopePlugin", but didn't.`);
56 | }
57 | moduleScopePlugin.appSrcs = [...moduleScopePlugin.appSrcs, ...paths];
58 | };
59 |
60 | const enableImportsFromExternalPaths = (webpackConfig, paths) => {
61 | enableTypescriptImportsFromExternalPaths(webpackConfig, paths);
62 | addPathsToModuleScopePlugin(webpackConfig, paths);
63 | };
64 |
65 | const pak = require('../../../package.json');
66 |
67 | module.exports = function({
68 | env
69 | }) {
70 | return {
71 | babel: {
72 | plugins: [
73 | ["module-resolver", {
74 | "extensions": ['.tsx', '.ts', '.js', '.json'],
75 | "alias": {
76 | [pak.name]: path.join(__dirname, '../../..', pak.source),
77 | "^react-native$": "react-native-web"
78 | }
79 | }]
80 | ],
81 | },
82 | webpack: {
83 | configure: (webpackConfig) => {
84 |
85 | enableImportsFromExternalPaths(webpackConfig, [
86 | path.resolve(__dirname, '../../../'),
87 | ]);
88 |
89 | // Allow importing from external workspaces.
90 | monorepoWebpackTools.enableWorkspacesResolution(webpackConfig);
91 | // Ensure nohoisted libraries are resolved from this workspace.
92 | monorepoWebpackTools.addNohoistAliases(webpackConfig);
93 |
94 | return webpackConfig;
95 | },
96 | plugins: {
97 | add: [
98 | // Inject the "__DEV__" global variable.
99 | new webpack.DefinePlugin({
100 | __DEV__: process.env.NODE_ENV !== "production",
101 | }),
102 | ],
103 | remove: ["ManifestPlugin", "WorkboxWebpackPlugin", "WebpackManifestPlugin"]
104 | }
105 | },
106 | }
107 | };
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 | See Official Website
10 |
11 | ---------------------------------------------
12 |
13 |
14 |
15 |
16 |
17 | ### BETA, DO NOT USE IN PRODUCTION! ⚠️
18 |
19 | ## Support:
20 |
21 | | | Android | IOS | Web (react-native-web) | Windows (react-native-windows) | Expo |
22 | |----------------|:-------:|:---:|:----------------------:|:---------------------------------------:|:------:|
23 | | Mouse 🖱️ | 🚧 | 🚧 | 🚧 | 🚧 | ❌ |
24 | | Keyboard ⌨️ | ✅ | 🚧 | ✅ | 🚧 | ❌ |
25 | | Gamepad 🎮 | 🚧 | 🚧 | 🚧 | 🚧 | ❌ |
26 | | MIDI 🎹 | 🚧 | 🚧 | 🚧 | 🚧 | ❌ |
27 |
28 | Inspired by [react-native-keyevent](https://github.com/kevinejohn/react-native-keyevent) and [Unity](https://unity.com).
29 |
30 | ## Install
31 |
32 | Using NPM
33 | ```sh
34 | npm install rxn-input
35 | ```
36 |
37 | Using Yarn
38 | ```sh
39 | yarn add rxn-input
40 | ```
41 |
42 | ## Setup
43 |
44 |
54 |
55 | 🌐 Using this module for Web? Don't forget to setup [react-native-web](https://github.com/necolas/react-native-web)
56 |
57 | ## Usage
58 |
59 | See on [Documentation](https://luffos.github.io/rxn-input/docs)
60 |
61 | ## Contributors
62 |
63 |
64 |
65 |
66 |
67 | ## 📄 License
68 | MIT - Feel free for modify, edit, copy, fork and share
69 |
--------------------------------------------------------------------------------
/website/src/components/Layout/MobileMenu/styles.ts:
--------------------------------------------------------------------------------
1 | import styled from 'styled-components';
2 | import BreakPoints from '../../../styles/theme/BreakPoints';
3 | import Colors from '../../../styles/theme/Colors';
4 |
5 | export const MobileMenuWrapper = styled.div`
6 | display: none;
7 |
8 | position: fixed;
9 | z-index: 9999905;
10 | overflow: hidden;
11 | width: 100%;
12 | height: 100%;
13 | top: 0;
14 | left: 0;
15 |
16 | ${BreakPoints.down('md')} {
17 | display: block;
18 | }
19 | `;
20 |
21 | export const MobileMenuBackground = styled.div`
22 | position: fixed;
23 | z-index: 9999903;
24 | flex: 1;
25 | top: 0;
26 | left: 0;
27 | width: 100%;
28 | height: 100%;
29 | background: linear-gradient(
30 | 180deg,
31 | rgba(1, 10, 43, 0.3) 0%,
32 | rgba(7, 3, 34, 0.2) 100%
33 | );
34 | backdrop-filter: blur(2px);
35 | `;
36 |
37 | export const MobileMenuBox = styled.div`
38 | position: fixed;
39 | z-index: 9999904;
40 | color: white;
41 | width: 200px;
42 | height: 250px;
43 | right: 8px;
44 | top: 8px;
45 | background: linear-gradient(180deg, rgba(5, 2, 24, 0.9) 0%, #0b091f 100%);
46 | backdrop-filter: blur(10px);
47 | border: 2px solid rgba(148, 163, 184, 0.12);
48 | border-radius: 24px 0px 24px 12px;
49 | & .closeWrapper {
50 | cursor: pointer;
51 | display: flex;
52 | justify-content: center;
53 | align-items: center;
54 | width: 30px;
55 | height: 30px;
56 | margin-left: 8px;
57 | margin-right: 8px;
58 | margin-top: 18px;
59 | margin-left: auto;
60 | & > svg > path {
61 | transition: fill 0.1s ease-in-out;
62 | }
63 | &:hover > svg > path {
64 | fill: ${Colors.CLOUDLESS};
65 | }
66 | }
67 | & > ul {
68 | width: 100%;
69 | margin: 0;
70 | margin-top: 8px;
71 | padding: 0;
72 | list-style: none;
73 | text-align: center;
74 | & > li {
75 | margin: 0;
76 | padding: 0;
77 | display: flex;
78 | justify-content: center;
79 | align-items: center;
80 | & > a:hover {
81 | & > p {
82 | color: white;
83 | }
84 | & > svg > path {
85 | fill: white;
86 | }
87 | }
88 | & > a:not(.github):hover {
89 | & > p {
90 | color: ${Colors.ZIMABLUE};
91 | }
92 | & > svg > path {
93 | fill: ${Colors.ZIMABLUE};
94 | }
95 | }
96 | & > a {
97 | width: fit-content;
98 | display: flex;
99 | justify-content: center;
100 | align-items: center;
101 | flex-direction: row;
102 | &[data-currentpage='true'] {
103 | & > p {
104 | color: ${Colors.ZIMABLUE};
105 | }
106 | }
107 | & > p {
108 | user-select: none;
109 | font-size: 16px;
110 | letter-spacing: 0.01rem;
111 | display: inline;
112 | color: ${Colors.BLUEBLOUSE};
113 | font-weight: 600;
114 | transition: color 0.1s ease-in-out;
115 | }
116 | & > svg {
117 | margin-left: 8px;
118 | width: 22px;
119 | height: 22px;
120 | & > path {
121 | transition: fill 0.1s ease-in-out;
122 | }
123 | }
124 | }
125 | }
126 | }
127 | `;
128 |
--------------------------------------------------------------------------------
/debug/packages/mobile/android/app/src/main/java/com/rxninputexample/MainApplication.java:
--------------------------------------------------------------------------------
1 | package com.rxninputexample;
2 |
3 | import android.app.Application;
4 | import android.content.Context;
5 | import com.facebook.react.PackageList;
6 | import com.facebook.react.ReactApplication;
7 | import com.facebook.react.ReactInstanceManager;
8 | import com.facebook.react.ReactNativeHost;
9 | import com.facebook.react.ReactPackage;
10 | import com.facebook.react.config.ReactFeatureFlags;
11 | import com.facebook.soloader.SoLoader;
12 | import com.rxninputexample.newarchitecture.MainApplicationReactNativeHost;
13 | import java.lang.reflect.InvocationTargetException;
14 | import java.util.List;
15 | import com.rxninput.RXNInputPackage;
16 |
17 | public class MainApplication extends Application implements ReactApplication {
18 |
19 | private final ReactNativeHost mReactNativeHost =
20 | new ReactNativeHost(this) {
21 | @Override
22 | public boolean getUseDeveloperSupport() {
23 | return BuildConfig.DEBUG;
24 | }
25 |
26 | @Override
27 | protected List getPackages() {
28 | @SuppressWarnings("UnnecessaryLocalVariable")
29 | List packages = new PackageList(this).getPackages();
30 | // Packages that cannot be autolinked yet can be added manually here, for example:
31 | packages.add(new RXNInputPackage());
32 | return packages;
33 | }
34 |
35 | @Override
36 | protected String getJSMainModuleName() {
37 | return "index";
38 | }
39 | };
40 |
41 | private final ReactNativeHost mNewArchitectureNativeHost =
42 | new MainApplicationReactNativeHost(this);
43 |
44 | @Override
45 | public ReactNativeHost getReactNativeHost() {
46 | if (BuildConfig.IS_NEW_ARCHITECTURE_ENABLED) {
47 | return mNewArchitectureNativeHost;
48 | } else {
49 | return mReactNativeHost;
50 | }
51 | }
52 |
53 | @Override
54 | public void onCreate() {
55 | super.onCreate();
56 | // If you opted-in for the New Architecture, we enable the TurboModule system
57 | ReactFeatureFlags.useTurboModules = BuildConfig.IS_NEW_ARCHITECTURE_ENABLED;
58 | SoLoader.init(this, /* native exopackage */ false);
59 | initializeFlipper(this, getReactNativeHost().getReactInstanceManager());
60 | }
61 |
62 | /**
63 | * Loads Flipper in React Native templates. Call this in the onCreate method with something like
64 | * initializeFlipper(this, getReactNativeHost().getReactInstanceManager());
65 | *
66 | * @param context
67 | * @param reactInstanceManager
68 | */
69 | private static void initializeFlipper(
70 | Context context, ReactInstanceManager reactInstanceManager) {
71 | if (BuildConfig.DEBUG) {
72 | try {
73 | /*
74 | We use reflection here to pick up the class that initializes Flipper,
75 | since Flipper library is not available in release mode
76 | */
77 | Class> aClass = Class.forName("com.rxninputexample.ReactNativeFlipper");
78 | aClass
79 | .getMethod("initializeFlipper", Context.class, ReactInstanceManager.class)
80 | .invoke(null, context, reactInstanceManager);
81 | } catch (ClassNotFoundException e) {
82 | e.printStackTrace();
83 | } catch (NoSuchMethodException e) {
84 | e.printStackTrace();
85 | } catch (IllegalAccessException e) {
86 | e.printStackTrace();
87 | } catch (InvocationTargetException e) {
88 | e.printStackTrace();
89 | }
90 | }
91 | }
92 | }
93 |
--------------------------------------------------------------------------------
/debug/packages/mobile/android/app/src/debug/java/com/rxninputexample/ReactNativeFlipper.java:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (c) Meta Platforms, Inc. and affiliates.
3 | *
4 | * This source code is licensed under the MIT license found in the LICENSE file in the root
5 | * directory of this source tree.
6 | */
7 | package com.rxninputexample;
8 |
9 | import android.content.Context;
10 | import com.facebook.flipper.android.AndroidFlipperClient;
11 | import com.facebook.flipper.android.utils.FlipperUtils;
12 | import com.facebook.flipper.core.FlipperClient;
13 | import com.facebook.flipper.plugins.crashreporter.CrashReporterPlugin;
14 | import com.facebook.flipper.plugins.databases.DatabasesFlipperPlugin;
15 | import com.facebook.flipper.plugins.fresco.FrescoFlipperPlugin;
16 | import com.facebook.flipper.plugins.inspector.DescriptorMapping;
17 | import com.facebook.flipper.plugins.inspector.InspectorFlipperPlugin;
18 | import com.facebook.flipper.plugins.network.FlipperOkhttpInterceptor;
19 | import com.facebook.flipper.plugins.network.NetworkFlipperPlugin;
20 | import com.facebook.flipper.plugins.react.ReactFlipperPlugin;
21 | import com.facebook.flipper.plugins.sharedpreferences.SharedPreferencesFlipperPlugin;
22 | import com.facebook.react.ReactInstanceEventListener;
23 | import com.facebook.react.ReactInstanceManager;
24 | import com.facebook.react.bridge.ReactContext;
25 | import com.facebook.react.modules.network.NetworkingModule;
26 | import okhttp3.OkHttpClient;
27 |
28 | public class ReactNativeFlipper {
29 | public static void initializeFlipper(Context context, ReactInstanceManager reactInstanceManager) {
30 | if (FlipperUtils.shouldEnableFlipper(context)) {
31 | final FlipperClient client = AndroidFlipperClient.getInstance(context);
32 |
33 | client.addPlugin(new InspectorFlipperPlugin(context, DescriptorMapping.withDefaults()));
34 | client.addPlugin(new ReactFlipperPlugin());
35 | client.addPlugin(new DatabasesFlipperPlugin(context));
36 | client.addPlugin(new SharedPreferencesFlipperPlugin(context));
37 | client.addPlugin(CrashReporterPlugin.getInstance());
38 |
39 | NetworkFlipperPlugin networkFlipperPlugin = new NetworkFlipperPlugin();
40 | NetworkingModule.setCustomClientBuilder(
41 | new NetworkingModule.CustomClientBuilder() {
42 | @Override
43 | public void apply(OkHttpClient.Builder builder) {
44 | builder.addNetworkInterceptor(new FlipperOkhttpInterceptor(networkFlipperPlugin));
45 | }
46 | });
47 | client.addPlugin(networkFlipperPlugin);
48 | client.start();
49 |
50 | // Fresco Plugin needs to ensure that ImagePipelineFactory is initialized
51 | // Hence we run if after all native modules have been initialized
52 | ReactContext reactContext = reactInstanceManager.getCurrentReactContext();
53 | if (reactContext == null) {
54 | reactInstanceManager.addReactInstanceEventListener(
55 | new ReactInstanceEventListener() {
56 | @Override
57 | public void onReactContextInitialized(ReactContext reactContext) {
58 | reactInstanceManager.removeReactInstanceEventListener(this);
59 | reactContext.runOnNativeModulesQueueThread(
60 | new Runnable() {
61 | @Override
62 | public void run() {
63 | client.addPlugin(new FrescoFlipperPlugin());
64 | }
65 | });
66 | }
67 | });
68 | } else {
69 | client.addPlugin(new FrescoFlipperPlugin());
70 | }
71 | }
72 | }
73 | }
74 |
--------------------------------------------------------------------------------
/debug/packages/mobile/ios/RXNInputExample.xcodeproj/xcshareddata/xcschemes/RXNInputExample.xcscheme:
--------------------------------------------------------------------------------
1 |
2 |
5 |
8 |
9 |
15 |
21 |
22 |
23 |
24 |
25 |
30 |
31 |
33 |
39 |
40 |
41 |
42 |
43 |
53 |
55 |
61 |
62 |
63 |
64 |
70 |
72 |
78 |
79 |
80 |
81 |
83 |
84 |
87 |
88 |
89 |
--------------------------------------------------------------------------------
/android/src/main/java/com/rxninput/RXNInputModule.java:
--------------------------------------------------------------------------------
1 | package com.rxninput;
2 |
3 | import android.view.InputDevice;
4 | import android.view.KeyEvent;
5 |
6 | import androidx.annotation.NonNull;
7 |
8 | import com.facebook.react.bridge.ReactApplicationContext;
9 | import com.facebook.react.bridge.ReactContext;
10 | import com.facebook.react.bridge.ReactContextBaseJavaModule;
11 | import com.facebook.react.bridge.WritableMap;
12 | import com.facebook.react.bridge.WritableNativeMap;
13 | import com.facebook.react.module.annotations.ReactModule;
14 | import com.facebook.react.modules.core.DeviceEventManagerModule;
15 |
16 | @ReactModule(name = RXNInputModule.NAME)
17 | public class RXNInputModule extends ReactContextBaseJavaModule {
18 | public static final String NAME = "RXNInput";
19 |
20 | private static ReactContext mReactContext;
21 | private static DeviceEventManagerModule.RCTDeviceEventEmitter mJSModule = null;
22 |
23 | private static RXNInputModule instance = null;
24 |
25 | public static RXNInputModule initModule(ReactApplicationContext reactContext) {
26 | instance = new RXNInputModule(reactContext);
27 | return instance;
28 | }
29 |
30 | protected RXNInputModule(ReactApplicationContext reactContext) {
31 | super(reactContext);
32 | mReactContext = reactContext;
33 | }
34 |
35 | @Override
36 | @NonNull
37 | public String getName() {
38 | return NAME;
39 | }
40 |
41 | private WritableMap createMap(int keyCode, KeyEvent keyEvent) {
42 | WritableMap map = new WritableNativeMap();
43 |
44 | map.putString("keyCode", "");
45 |
46 | String key = String.valueOf((char) keyEvent.getUnicodeChar());
47 |
48 | if (key.matches("^[a-zA-Z0-9]*$")) {
49 | map.putString("key", key);
50 | } else {
51 | map.putString("key", KeyEvent.keyCodeToString(keyCode));
52 | }
53 |
54 | map.putBoolean("shiftKey", keyEvent.isShiftPressed());
55 | map.putBoolean("altKey", keyEvent.isAltPressed());
56 | map.putBoolean("ctrlKey", keyEvent.isCtrlPressed());
57 | map.putBoolean("metaKey", keyEvent.isMetaPressed());
58 | map.putBoolean("capsLock", keyEvent.isCapsLockOn());
59 | map.putBoolean("numLock", keyEvent.isNumLockOn());
60 | map.putBoolean("scrollLock", keyEvent.isScrollLockOn());
61 |
62 | InputDevice device = keyEvent.getDevice();
63 |
64 | WritableMap deviceMap = new WritableNativeMap();
65 | deviceMap.putInt("id", device.getId());
66 | deviceMap.putString("name", device.getName());
67 | deviceMap.putString("descriptor", device.getDescriptor());
68 | deviceMap.putBoolean("isVirtual", device.isVirtual());
69 |
70 | map.putMap("device", deviceMap);
71 |
72 | WritableMap originalMap = new WritableNativeMap();
73 | originalMap.putInt("KeyCode", keyEvent.getKeyCode());
74 | originalMap.putString("keyCodeString", KeyEvent.keyCodeToString(keyCode));
75 | originalMap.putInt("Action", keyEvent.getAction());
76 | originalMap.putInt("Flags", keyEvent.getFlags());
77 | originalMap.putInt("UnicodeChar", keyEvent.getUnicodeChar());
78 | originalMap.putInt("DiplayLabel", keyEvent.getDisplayLabel());
79 | originalMap.putInt("RepeatCount", keyEvent.getRepeatCount());
80 |
81 | map.putMap("original", originalMap);
82 |
83 |
84 | return map;
85 | }
86 |
87 | public static void onKeyDownEvent(int keyCode, KeyEvent keyEvent) {
88 | if (mJSModule == null) {
89 | mJSModule = mReactContext.getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter.class);
90 | }
91 |
92 | mJSModule.emit("keydown", instance.createMap(keyCode, keyEvent));
93 | }
94 |
95 | public static void onKeyUpEvent(int keyCode, KeyEvent keyEvent) {
96 | if (mJSModule == null) {
97 | mJSModule = mReactContext.getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter.class);
98 | }
99 | mJSModule.emit("keyup", instance.createMap(keyCode, keyEvent));
100 | }
101 |
102 | }
103 |
--------------------------------------------------------------------------------
/website/src/styles/pages/index.styles.ts:
--------------------------------------------------------------------------------
1 | import styled from 'styled-components';
2 | import BreakPoints from '../theme/BreakPoints';
3 | import Colors from '../theme/Colors';
4 | import Sizes from '../theme/Sizes';
5 |
6 | export const Section1 = styled.div`
7 | @keyframes fadeIn {
8 | 0% {
9 | opacity: 0;
10 | }
11 | 100% {
12 | opacity: 1;
13 | }
14 | }
15 |
16 | animation: fadeIn 5s;
17 | `;
18 |
19 | export const Section1Content = styled.div`
20 | display: flex;
21 | flex-direction: row;
22 |
23 | ${BreakPoints.down('lg')} {
24 | flex-direction: column;
25 | }
26 | `;
27 |
28 | export const Section1Background = styled.div`
29 | position: absolute;
30 | width: 100%;
31 | max-width: ${Sizes.maxWidth};
32 | height: 250px;
33 | filter: blur(8rem);
34 | background: radial-gradient(50% 41.03% at 50% 58.97%, rgba(0, 131, 255, 0) 50%, rgb(0, 131, 255) 28.65%, rgba(0, 25, 245, 0.62) 81.25%, rgba(0, 131, 255, 0) 99.99%);
35 | left: 50%;
36 | margin-top: 20px;
37 | opacity: 0.8;
38 | transform: translateX(-50%);
39 | z-index: 0;
40 | `;
41 |
42 | export const Title = styled.h1`
43 | margin: 0px;
44 | padding: 0;
45 | font-size: 3rem;
46 |
47 | ${BreakPoints.down('lg')} {
48 | margin-left: auto;
49 | margin-right: auto;
50 | align-self: center;
51 | text-align: center;
52 | }
53 |
54 | ${BreakPoints.down('md')} {
55 | font-size: 2rem;
56 | }
57 |
58 | ${BreakPoints.down('sm')} {
59 | font-size: 1.4rem;
60 | }
61 | `;
62 |
63 | export const SubTitle = styled.h2`
64 | margin: 0;
65 | margin-top: 1.5rem;
66 | padding: 0;
67 | font-size: 1.8rem;
68 | color: ${Colors.ZIMABLUE};
69 |
70 | ${BreakPoints.down('lg')} {
71 | margin-left: auto;
72 | margin-right: auto;
73 | align-self: center;
74 | text-align: center;
75 | }
76 |
77 | ${BreakPoints.down('md')} {
78 | font-size: 1.2rem;
79 | }
80 |
81 | ${BreakPoints.down('sm')} {
82 | font-size: 0.9rem;
83 | }
84 |
85 | & > span {
86 | color: ${Colors.BLUEBLOUSE};
87 | }
88 | `;
89 |
90 | export const DevicesWrapper = styled.div`
91 | margin-left: auto;
92 | margin-top: -2.5rem;
93 | width: 500px;
94 | height: 500px;
95 | display: flex;
96 | justify-content: center;
97 |
98 | ${BreakPoints.down('lg')} {
99 | margin-top: 4rem;
100 | margin-left: auto;
101 | margin-right: auto;
102 | margin-top: 0rem;
103 | width: 400px;
104 | height: 300px;
105 |
106 | & > svg {
107 | align-self: end;
108 | }
109 | }
110 |
111 | ${BreakPoints.down('md')} {
112 | margin-top: 0rem;
113 | width: 300px;
114 | height: 260px;
115 | }
116 |
117 | ${BreakPoints.down('sm')} {
118 | margin-top: 0.5rem;
119 | width: 240px;
120 | height: 240px;
121 |
122 | & > svg {
123 | align-self: end;
124 | }
125 | }
126 | `;
127 |
128 | export const GetStartedButton = styled.div`
129 | margin-top: 2rem;
130 | display: flex;
131 | justify-content: center;
132 | align-items: center;
133 | cursor: pointer;
134 | user-select: none;
135 | color: white;
136 | font-weight: 600;
137 | font-size: 1.5rem;
138 | letter-spacing: 0.08rem;
139 | width: 16rem;
140 | height: 4rem;
141 | background: linear-gradient(180deg, rgba(16, 117, 255, 0.9) 0%, rgba(9, 115, 223, 0.9) 0.01%, rgba(18, 21, 93, 0.9) 100%);
142 | border: 0.1rem solid #0b4ea8;
143 | border-radius: 1rem;
144 | transition: 0.1s filter linear;
145 | &:hover {
146 | filter: brightness(140%);
147 | }
148 |
149 | ${BreakPoints.down('lg')} {
150 | margin-top: 1rem;
151 | margin-left: auto;
152 | margin-right: auto;
153 | }
154 |
155 | ${BreakPoints.down('md')} {
156 | margin-top: 0rem;
157 | width: 14rem;
158 | height: 3.5rem;
159 | font-size: 1rem;
160 | }
161 |
162 | ${BreakPoints.down('sm')} {
163 | margin-top: 0rem;
164 | width: 12rem;
165 | height: 3rem;
166 | font-size: 0.9rem;
167 | }
168 | `;
169 |
--------------------------------------------------------------------------------
/website/scripts/.webpack/plugins/DocsDataPlugin.js:
--------------------------------------------------------------------------------
1 | const path = require('path');
2 | const fs = require('fs');
3 | const glob = require('glob');
4 | const chokidar = require('chokidar');
5 | const { v4: uuidv4 } = require('uuid');
6 | const matter = require('gray-matter');
7 |
8 | const docsPath = './src/content/docs';
9 | let docsSchema = JSON.parse(fs.readFileSync(`${docsPath}/schema.json`, { encoding: `utf-8` }));
10 |
11 | let pluginAlreadyLoaded = false;
12 | let isProduction = String(process?.env?.NODE_ENV).toLowerCase() === 'production';
13 | let lastBuildHash = '';
14 |
15 | class DocsDataPlugin {
16 | apply(compiler) {
17 | compiler.hooks.emit.tapAsync('DocsDataPlugin', (compilation, callback) => {
18 | if (pluginAlreadyLoaded) return callback();
19 | pluginAlreadyLoaded = true;
20 |
21 | buildData();
22 |
23 | if (!isProduction) {
24 | chokidar.watch(`${docsPath}/schema.json`, { ignoreInitial: true }).on('all', (event, path, stats) => {
25 | buildData();
26 | });
27 |
28 | chokidar.watch(`${docsPath}/**/*.mdx`, { ignoreInitial: true }).on('all', (event, path, stats) => {
29 | buildData();
30 | });
31 | }
32 |
33 | callback();
34 | });
35 | }
36 |
37 | preBuild(){
38 | buildData()
39 | }
40 | }
41 |
42 | const handleDocFile = (data, version, folder, docPath, contextIndex) => {
43 | try {
44 | const docFileName = docPath.replace(/^.*[\\\/]/, '').replace(/\.[^/.]+$/, '');
45 |
46 | const body = fs.readFileSync(docPath, 'utf-8');
47 |
48 | data[version][folder][docFileName] = {
49 | slugs: generateSlugs(data, version, folder, docPath, docFileName, contextIndex),
50 | body: body,
51 | version: version,
52 | frontmatter: matter(body).data,
53 | };
54 | } catch (error) {
55 | console.log(`error! ${version}/${folder}/${docPath}`, error);
56 | }
57 | };
58 |
59 | const buildData = () => {
60 | const buildHash = uuidv4();
61 | lastBuildHash = buildHash;
62 |
63 | docsSchema = JSON.parse(fs.readFileSync(`${docsPath}/schema.json`, { encoding: `utf-8` }));
64 | const data = {};
65 |
66 | Object.keys(docsSchema).forEach((version) => {
67 | data[version] = {};
68 |
69 | Object.keys(docsSchema[version]).forEach((folder) => {
70 | data[version][folder] = {};
71 |
72 | if (docsSchema[version][folder] == `asc`) {
73 | return glob.sync(`${docsPath}/${version}/${folder}/*.mdx`).map((docFile, index) => handleDocFile(data, version, folder, docFile, index));
74 | }
75 |
76 | if (Array.isArray(docsSchema[version][folder])) {
77 | docsSchema[version][folder].map((docFile, index) => handleDocFile(data, version, folder, `${docsPath}/${version}/${folder}/${docFile}`, index));
78 | }
79 | });
80 | });
81 |
82 | if (lastBuildHash !== buildHash) return;
83 |
84 | fs.writeFileSync(`${docsPath}/data.json`, JSON.stringify(data, null, 2), 'utf-8');
85 | };
86 |
87 | const generateSlugs = (data, version, folder, docPath, docFileName, contextIndex) => {
88 | let slugs = [];
89 |
90 | // is last version, first folder and first doc 👇
91 | if (
92 | folder == Object.entries(Object.entries(docsSchema).slice(-1)[0].pop())[0][0] &&
93 | Object.entries(Object.entries(docsSchema).slice(-1)[0].pop())[0][1][0] == docFileName + '.mdx'
94 | ) {
95 | slugs.push('docs/');
96 | }
97 |
98 | // is last version ( dont't need /docs/VERSION/... ) 👇
99 | if (version == Object.keys(docsSchema).slice(-1)[0]) {
100 | //is first doc ( and last version) 👇
101 | if (contextIndex == 0) {
102 | slugs.push(`docs/${folder}`);
103 | }
104 |
105 | slugs.push(`docs/${folder}/${docFileName}`);
106 | }
107 |
108 | //is first doc 👇
109 | if (contextIndex == 0) {
110 | slugs.push(`docs/${version}/${folder}`);
111 | }
112 |
113 | // default
114 | slugs.push(`docs/${version}/${folder}/${docFileName}`);
115 |
116 | // transform
117 | slugs = slugs.map((element) => {
118 | return element.replace(/ /g, '-').toLowerCase();
119 | });
120 |
121 | return slugs;
122 | };
123 |
124 | module.exports = DocsDataPlugin;
125 |
--------------------------------------------------------------------------------
/debug/packages/mobile/ios/RXNInputExample/LaunchScreen.storyboard:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
--------------------------------------------------------------------------------
/website/src/components/Layout/TopBar/styles.ts:
--------------------------------------------------------------------------------
1 | import styled from 'styled-components';
2 | import BreakPoints from '../../../styles/theme/BreakPoints';
3 | import Colors from '../../../styles/theme/Colors';
4 | import Sizes from '../../../styles/theme/Sizes';
5 | import zIndex from '../../../styles/theme/zIndex';
6 |
7 | export const Wrapper = styled.div`
8 | position: fixed;
9 | top: 0;
10 | flex: none;
11 | align-items: center;
12 | justify-content: center;
13 | box-sizing: border-box;
14 | z-index: ${zIndex.TopBar-1};
15 | width: 100%;
16 |
17 | &[data-scrolled='true'] {
18 | background: linear-gradient(#0b091f 0%, rgba(8, 6, 31, 0.4) 100%);
19 | transition: background 0.2s ease-in-out;
20 | backdrop-filter: blur(0.3rem);
21 | border-bottom: solid rgba(255, 255, 255, 0.01) 1px;
22 | box-shadow: 0rem 0rem 1rem rgba(8, 6, 31, 0.85);
23 | }
24 | `;
25 |
26 | export const InnerWrapper = styled.div`
27 | display: contents;
28 | `;
29 |
30 | export const ContentWrapper = styled.div`
31 | position: relative;
32 | z-index: ${zIndex.TopBar};
33 | box-sizing: border-box;
34 | display: flex;
35 | flex-direction: row;
36 | align-items: center;
37 | margin-left: auto;
38 | margin-right: auto;
39 | margin-bottom: auto;
40 | width: 100vw;
41 | max-width: ${Sizes.maxWidth};
42 | padding-left: 2rem;
43 | padding-right: 2rem;
44 |
45 | ${BreakPoints.down('md')} {
46 | margin-top: 1rem;
47 | margin-bottom: 1rem;
48 | padding-left: 1rem;
49 | padding-right: 1rem;
50 | }
51 |
52 | .logoWrapper {
53 | display: inline-flex;
54 | vertical-align: middle;
55 | justify-content: center;
56 | align-items: center;
57 | width: 180px;
58 | height: 30px;
59 |
60 | &:hover {
61 | & > svg {
62 | filter: brightness(140%);
63 | }
64 | }
65 |
66 | & > svg {
67 | pointer-events: none;
68 | position: relative;
69 | transition: 0.1s filter linear;
70 | }
71 | }
72 | `;
73 |
74 | export const RItems = styled.ul`
75 | display: flex;
76 | justify-content: center;
77 | flex-direction: row;
78 | list-style: none;
79 | padding: 0;
80 | margin-left: auto;
81 |
82 | ${BreakPoints.down('md')} {
83 | display: none;
84 | }
85 |
86 | li,
87 | a,
88 | p {
89 | margin: 0;
90 | padding: 0;
91 | }
92 |
93 | li {
94 | display: flex;
95 | justify-content: center;
96 | align-items: center;
97 | }
98 |
99 | li:not(:first-child) {
100 | margin-left: 3.5rem;
101 | }
102 |
103 | a[data-currentpage='true'] {
104 | & > p {
105 | color: ${Colors.ZIMABLUE};
106 |
107 | &::after {
108 | background: ${Colors.ZIMABLUE};
109 | }
110 | }
111 | }
112 |
113 | a {
114 | display: flex;
115 | flex-direction: column;
116 |
117 | &:hover {
118 | & > p {
119 | color: ${Colors.ZIMABLUE};
120 |
121 | &::after {
122 | background: ${Colors.ZIMABLUE};
123 | }
124 | }
125 | }
126 |
127 | & > p {
128 | transition: color 0.1s ease-in-out;
129 | color: ${Colors.BLUEBLOUSE};
130 | font-size: 0.85rem;
131 | font-weight: 600;
132 | letter-spacing: 0.01rem;
133 |
134 | &::after {
135 | margin-left: auto;
136 | margin-right: auto;
137 | margin-top: 0.6rem;
138 | display: block;
139 | white-space: pre;
140 | border-radius: 2rem;
141 | content: ' ';
142 | width: 1rem;
143 | height: 0.4rem;
144 | background: ${Colors.BLUEBLOUSE};
145 | }
146 | }
147 | }
148 |
149 | .gitHubWrapper {
150 | display: inline-flex;
151 | vertical-align: middle;
152 | justify-content: center;
153 | align-items: center;
154 | width: 30px;
155 | height: 30px;
156 |
157 | & > svg > path {
158 | cursor: pointer;
159 | transition: fill 0.1s ease-in-out;
160 | }
161 | &:hover > svg > path {
162 | fill: #d9e8fb;
163 | }
164 | }
165 | `;
166 |
167 | export const MobileKebab = styled.div`
168 | cursor: pointer;
169 | display: none;
170 | margin-left: auto;
171 | padding-left: 0.2rem;
172 | padding-right: 0.2rem;
173 |
174 | & > svg > path {
175 | transition: fill 0.1s ease-in-out;
176 | }
177 |
178 | &:hover > svg > path {
179 | fill: #d9e8fb;
180 | }
181 |
182 | ${BreakPoints.down('md')} {
183 | display: block;
184 | }
185 | `;
186 |
--------------------------------------------------------------------------------
/debug/packages/mobile/ios/RXNInputExample/AppDelegate.mm:
--------------------------------------------------------------------------------
1 | #import "AppDelegate.h"
2 |
3 | #import
4 | #import
5 | #import
6 |
7 | #import
8 |
9 | #if RCT_NEW_ARCH_ENABLED
10 | #import
11 | #import
12 | #import
13 | #import
14 | #import
15 | #import
16 |
17 | #import
18 |
19 | static NSString *const kRNConcurrentRoot = @"concurrentRoot";
20 |
21 | @interface AppDelegate () {
22 | RCTTurboModuleManager *_turboModuleManager;
23 | RCTSurfacePresenterBridgeAdapter *_bridgeAdapter;
24 | std::shared_ptr _reactNativeConfig;
25 | facebook::react::ContextContainer::Shared _contextContainer;
26 | }
27 | @end
28 | #endif
29 |
30 | @implementation AppDelegate
31 |
32 | - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
33 | {
34 | RCTAppSetupPrepareApp(application);
35 |
36 | RCTBridge *bridge = [[RCTBridge alloc] initWithDelegate:self launchOptions:launchOptions];
37 |
38 | #if RCT_NEW_ARCH_ENABLED
39 | _contextContainer = std::make_shared();
40 | _reactNativeConfig = std::make_shared();
41 | _contextContainer->insert("ReactNativeConfig", _reactNativeConfig);
42 | _bridgeAdapter = [[RCTSurfacePresenterBridgeAdapter alloc] initWithBridge:bridge contextContainer:_contextContainer];
43 | bridge.surfacePresenter = _bridgeAdapter.surfacePresenter;
44 | #endif
45 |
46 | NSDictionary *initProps = [self prepareInitialProps];
47 | UIView *rootView = RCTAppSetupDefaultRootView(bridge, @"RXNInputExample", initProps);
48 |
49 | if (@available(iOS 13.0, *)) {
50 | rootView.backgroundColor = [UIColor systemBackgroundColor];
51 | } else {
52 | rootView.backgroundColor = [UIColor whiteColor];
53 | }
54 |
55 | self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];
56 | UIViewController *rootViewController = [UIViewController new];
57 | rootViewController.view = rootView;
58 | self.window.rootViewController = rootViewController;
59 | [self.window makeKeyAndVisible];
60 | return YES;
61 | }
62 |
63 | /// This method controls whether the `concurrentRoot`feature of React18 is turned on or off.
64 | ///
65 | /// @see: https://reactjs.org/blog/2022/03/29/react-v18.html
66 | /// @note: This requires to be rendering on Fabric (i.e. on the New Architecture).
67 | /// @return: `true` if the `concurrentRoot` feture is enabled. Otherwise, it returns `false`.
68 | - (BOOL)concurrentRootEnabled
69 | {
70 | // Switch this bool to turn on and off the concurrent root
71 | return true;
72 | }
73 |
74 | - (NSDictionary *)prepareInitialProps
75 | {
76 | NSMutableDictionary *initProps = [NSMutableDictionary new];
77 |
78 | #ifdef RCT_NEW_ARCH_ENABLED
79 | initProps[kRNConcurrentRoot] = @([self concurrentRootEnabled]);
80 | #endif
81 |
82 | return initProps;
83 | }
84 |
85 | - (NSURL *)sourceURLForBridge:(RCTBridge *)bridge
86 | {
87 | #if DEBUG
88 | return [[RCTBundleURLProvider sharedSettings] jsBundleURLForBundleRoot:@"index"];
89 | #else
90 | return [[NSBundle mainBundle] URLForResource:@"main" withExtension:@"jsbundle"];
91 | #endif
92 | }
93 |
94 | #if RCT_NEW_ARCH_ENABLED
95 |
96 | #pragma mark - RCTCxxBridgeDelegate
97 |
98 | - (std::unique_ptr)jsExecutorFactoryForBridge:(RCTBridge *)bridge
99 | {
100 | _turboModuleManager = [[RCTTurboModuleManager alloc] initWithBridge:bridge
101 | delegate:self
102 | jsInvoker:bridge.jsCallInvoker];
103 | return RCTAppSetupDefaultJsExecutorFactory(bridge, _turboModuleManager);
104 | }
105 |
106 | #pragma mark RCTTurboModuleManagerDelegate
107 |
108 | - (Class)getModuleClassFromName:(const char *)name
109 | {
110 | return RCTCoreModulesClassProvider(name);
111 | }
112 |
113 | - (std::shared_ptr)getTurboModule:(const std::string &)name
114 | jsInvoker:(std::shared_ptr)jsInvoker
115 | {
116 | return nullptr;
117 | }
118 |
119 | - (std::shared_ptr)getTurboModule:(const std::string &)name
120 | initParams:
121 | (const facebook::react::ObjCTurboModule::InitParams &)params
122 | {
123 | return nullptr;
124 | }
125 |
126 | - (id)getModuleInstanceFromClass:(Class)moduleClass
127 | {
128 | return RCTAppSetupDefaultModuleFromClass(moduleClass);
129 | }
130 |
131 | #endif
132 |
133 | @end
134 |
--------------------------------------------------------------------------------
/debug/packages/mobile/android/app/src/main/java/com/rxninputexample/newarchitecture/MainApplicationReactNativeHost.java:
--------------------------------------------------------------------------------
1 | package com.rxninputexample.newarchitecture;
2 |
3 | import android.app.Application;
4 | import androidx.annotation.NonNull;
5 | import com.facebook.react.PackageList;
6 | import com.facebook.react.ReactInstanceManager;
7 | import com.facebook.react.ReactNativeHost;
8 | import com.facebook.react.ReactPackage;
9 | import com.facebook.react.ReactPackageTurboModuleManagerDelegate;
10 | import com.facebook.react.bridge.JSIModulePackage;
11 | import com.facebook.react.bridge.JSIModuleProvider;
12 | import com.facebook.react.bridge.JSIModuleSpec;
13 | import com.facebook.react.bridge.JSIModuleType;
14 | import com.facebook.react.bridge.JavaScriptContextHolder;
15 | import com.facebook.react.bridge.ReactApplicationContext;
16 | import com.facebook.react.bridge.UIManager;
17 | import com.facebook.react.fabric.ComponentFactory;
18 | import com.facebook.react.fabric.CoreComponentsRegistry;
19 | import com.facebook.react.fabric.FabricJSIModuleProvider;
20 | import com.facebook.react.fabric.ReactNativeConfig;
21 | import com.facebook.react.uimanager.ViewManagerRegistry;
22 | import com.rxninputexample.BuildConfig;
23 | import com.rxninputexample.newarchitecture.components.MainComponentsRegistry;
24 | import com.rxninputexample.newarchitecture.modules.MainApplicationTurboModuleManagerDelegate;
25 | import java.util.ArrayList;
26 | import java.util.List;
27 |
28 | /**
29 | * A {@link ReactNativeHost} that helps you load everything needed for the New Architecture, both
30 | * TurboModule delegates and the Fabric Renderer.
31 | *
32 | * Please note that this class is used ONLY if you opt-in for the New Architecture (see the
33 | * `newArchEnabled` property). Is ignored otherwise.
34 | */
35 | public class MainApplicationReactNativeHost extends ReactNativeHost {
36 | public MainApplicationReactNativeHost(Application application) {
37 | super(application);
38 | }
39 |
40 | @Override
41 | public boolean getUseDeveloperSupport() {
42 | return BuildConfig.DEBUG;
43 | }
44 |
45 | @Override
46 | protected List getPackages() {
47 | List packages = new PackageList(this).getPackages();
48 | // Packages that cannot be autolinked yet can be added manually here, for example:
49 | // packages.add(new MyReactNativePackage());
50 | // TurboModules must also be loaded here providing a valid TurboReactPackage implementation:
51 | // packages.add(new TurboReactPackage() { ... });
52 | // If you have custom Fabric Components, their ViewManagers should also be loaded here
53 | // inside a ReactPackage.
54 | return packages;
55 | }
56 |
57 | @Override
58 | protected String getJSMainModuleName() {
59 | return "index";
60 | }
61 |
62 | @NonNull
63 | @Override
64 | protected ReactPackageTurboModuleManagerDelegate.Builder
65 | getReactPackageTurboModuleManagerDelegateBuilder() {
66 | // Here we provide the ReactPackageTurboModuleManagerDelegate Builder. This is necessary
67 | // for the new architecture and to use TurboModules correctly.
68 | return new MainApplicationTurboModuleManagerDelegate.Builder();
69 | }
70 |
71 | @Override
72 | protected JSIModulePackage getJSIModulePackage() {
73 | return new JSIModulePackage() {
74 | @Override
75 | public List getJSIModules(
76 | final ReactApplicationContext reactApplicationContext,
77 | final JavaScriptContextHolder jsContext) {
78 | final List specs = new ArrayList<>();
79 |
80 | // Here we provide a new JSIModuleSpec that will be responsible of providing the
81 | // custom Fabric Components.
82 | specs.add(
83 | new JSIModuleSpec() {
84 | @Override
85 | public JSIModuleType getJSIModuleType() {
86 | return JSIModuleType.UIManager;
87 | }
88 |
89 | @Override
90 | public JSIModuleProvider getJSIModuleProvider() {
91 | final ComponentFactory componentFactory = new ComponentFactory();
92 | CoreComponentsRegistry.register(componentFactory);
93 |
94 | // Here we register a Components Registry.
95 | // The one that is generated with the template contains no components
96 | // and just provides you the one from React Native core.
97 | MainComponentsRegistry.register(componentFactory);
98 |
99 | final ReactInstanceManager reactInstanceManager = getReactInstanceManager();
100 |
101 | ViewManagerRegistry viewManagerRegistry =
102 | new ViewManagerRegistry(
103 | reactInstanceManager.getOrCreateViewManagers(reactApplicationContext));
104 |
105 | return new FabricJSIModuleProvider(
106 | reactApplicationContext,
107 | componentFactory,
108 | ReactNativeConfig.DEFAULT_CONFIG,
109 | viewManagerRegistry);
110 | }
111 | });
112 | return specs;
113 | }
114 | };
115 | }
116 | }
117 |
--------------------------------------------------------------------------------
/website/src/assets/Logo.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
--------------------------------------------------------------------------------
/android/gradlew:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env sh
2 |
3 | #
4 | # Copyright 2015 the original author or authors.
5 | #
6 | # Licensed under the Apache License, Version 2.0 (the "License");
7 | # you may not use this file except in compliance with the License.
8 | # You may obtain a copy of the License at
9 | #
10 | # https://www.apache.org/licenses/LICENSE-2.0
11 | #
12 | # Unless required by applicable law or agreed to in writing, software
13 | # distributed under the License is distributed on an "AS IS" BASIS,
14 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 | # See the License for the specific language governing permissions and
16 | # limitations under the License.
17 | #
18 |
19 | ##############################################################################
20 | ##
21 | ## Gradle start up script for UN*X
22 | ##
23 | ##############################################################################
24 |
25 | # Attempt to set APP_HOME
26 | # Resolve links: $0 may be a link
27 | PRG="$0"
28 | # Need this for relative symlinks.
29 | while [ -h "$PRG" ] ; do
30 | ls=`ls -ld "$PRG"`
31 | link=`expr "$ls" : '.*-> \(.*\)$'`
32 | if expr "$link" : '/.*' > /dev/null; then
33 | PRG="$link"
34 | else
35 | PRG=`dirname "$PRG"`"/$link"
36 | fi
37 | done
38 | SAVED="`pwd`"
39 | cd "`dirname \"$PRG\"`/" >/dev/null
40 | APP_HOME="`pwd -P`"
41 | cd "$SAVED" >/dev/null
42 |
43 | APP_NAME="Gradle"
44 | APP_BASE_NAME=`basename "$0"`
45 |
46 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
47 | DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
48 |
49 | # Use the maximum available, or set MAX_FD != -1 to use that value.
50 | MAX_FD="maximum"
51 |
52 | warn () {
53 | echo "$*"
54 | }
55 |
56 | die () {
57 | echo
58 | echo "$*"
59 | echo
60 | exit 1
61 | }
62 |
63 | # OS specific support (must be 'true' or 'false').
64 | cygwin=false
65 | msys=false
66 | darwin=false
67 | nonstop=false
68 | case "`uname`" in
69 | CYGWIN* )
70 | cygwin=true
71 | ;;
72 | Darwin* )
73 | darwin=true
74 | ;;
75 | MSYS* | MINGW* )
76 | msys=true
77 | ;;
78 | NONSTOP* )
79 | nonstop=true
80 | ;;
81 | esac
82 |
83 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
84 |
85 |
86 | # Determine the Java command to use to start the JVM.
87 | if [ -n "$JAVA_HOME" ] ; then
88 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
89 | # IBM's JDK on AIX uses strange locations for the executables
90 | JAVACMD="$JAVA_HOME/jre/sh/java"
91 | else
92 | JAVACMD="$JAVA_HOME/bin/java"
93 | fi
94 | if [ ! -x "$JAVACMD" ] ; then
95 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
96 |
97 | Please set the JAVA_HOME variable in your environment to match the
98 | location of your Java installation."
99 | fi
100 | else
101 | JAVACMD="java"
102 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
103 |
104 | Please set the JAVA_HOME variable in your environment to match the
105 | location of your Java installation."
106 | fi
107 |
108 | # Increase the maximum file descriptors if we can.
109 | if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
110 | MAX_FD_LIMIT=`ulimit -H -n`
111 | if [ $? -eq 0 ] ; then
112 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
113 | MAX_FD="$MAX_FD_LIMIT"
114 | fi
115 | ulimit -n $MAX_FD
116 | if [ $? -ne 0 ] ; then
117 | warn "Could not set maximum file descriptor limit: $MAX_FD"
118 | fi
119 | else
120 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
121 | fi
122 | fi
123 |
124 | # For Darwin, add options to specify how the application appears in the dock
125 | if $darwin; then
126 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
127 | fi
128 |
129 | # For Cygwin or MSYS, switch paths to Windows format before running java
130 | if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then
131 | APP_HOME=`cygpath --path --mixed "$APP_HOME"`
132 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
133 |
134 | JAVACMD=`cygpath --unix "$JAVACMD"`
135 |
136 | # We build the pattern for arguments to be converted via cygpath
137 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
138 | SEP=""
139 | for dir in $ROOTDIRSRAW ; do
140 | ROOTDIRS="$ROOTDIRS$SEP$dir"
141 | SEP="|"
142 | done
143 | OURCYGPATTERN="(^($ROOTDIRS))"
144 | # Add a user-defined pattern to the cygpath arguments
145 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then
146 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
147 | fi
148 | # Now convert the arguments - kludge to limit ourselves to /bin/sh
149 | i=0
150 | for arg in "$@" ; do
151 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
152 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
153 |
154 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
155 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
156 | else
157 | eval `echo args$i`="\"$arg\""
158 | fi
159 | i=`expr $i + 1`
160 | done
161 | case $i in
162 | 0) set -- ;;
163 | 1) set -- "$args0" ;;
164 | 2) set -- "$args0" "$args1" ;;
165 | 3) set -- "$args0" "$args1" "$args2" ;;
166 | 4) set -- "$args0" "$args1" "$args2" "$args3" ;;
167 | 5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
168 | 6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
169 | 7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
170 | 8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
171 | 9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
172 | esac
173 | fi
174 |
175 | # Escape application args
176 | save () {
177 | for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
178 | echo " "
179 | }
180 | APP_ARGS=`save "$@"`
181 |
182 | # Collect all arguments for the java command, following the shell quoting and substitution rules
183 | eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
184 |
185 | exec "$JAVACMD" "$@"
186 |
--------------------------------------------------------------------------------
/debug/packages/mobile/android/gradlew:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 |
3 | #
4 | # Copyright © 2015-2021 the original authors.
5 | #
6 | # Licensed under the Apache License, Version 2.0 (the "License");
7 | # you may not use this file except in compliance with the License.
8 | # You may obtain a copy of the License at
9 | #
10 | # https://www.apache.org/licenses/LICENSE-2.0
11 | #
12 | # Unless required by applicable law or agreed to in writing, software
13 | # distributed under the License is distributed on an "AS IS" BASIS,
14 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 | # See the License for the specific language governing permissions and
16 | # limitations under the License.
17 | #
18 |
19 | ##############################################################################
20 | #
21 | # Gradle start up script for POSIX generated by Gradle.
22 | #
23 | # Important for running:
24 | #
25 | # (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is
26 | # noncompliant, but you have some other compliant shell such as ksh or
27 | # bash, then to run this script, type that shell name before the whole
28 | # command line, like:
29 | #
30 | # ksh Gradle
31 | #
32 | # Busybox and similar reduced shells will NOT work, because this script
33 | # requires all of these POSIX shell features:
34 | # * functions;
35 | # * expansions «$var», «${var}», «${var:-default}», «${var+SET}»,
36 | # «${var#prefix}», «${var%suffix}», and «$( cmd )»;
37 | # * compound commands having a testable exit status, especially «case»;
38 | # * various built-in commands including «command», «set», and «ulimit».
39 | #
40 | # Important for patching:
41 | #
42 | # (2) This script targets any POSIX shell, so it avoids extensions provided
43 | # by Bash, Ksh, etc; in particular arrays are avoided.
44 | #
45 | # The "traditional" practice of packing multiple parameters into a
46 | # space-separated string is a well documented source of bugs and security
47 | # problems, so this is (mostly) avoided, by progressively accumulating
48 | # options in "$@", and eventually passing that to Java.
49 | #
50 | # Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS,
51 | # and GRADLE_OPTS) rely on word-splitting, this is performed explicitly;
52 | # see the in-line comments for details.
53 | #
54 | # There are tweaks for specific operating systems such as AIX, CygWin,
55 | # Darwin, MinGW, and NonStop.
56 | #
57 | # (3) This script is generated from the Groovy template
58 | # https://github.com/gradle/gradle/blob/master/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
59 | # within the Gradle project.
60 | #
61 | # You can find Gradle at https://github.com/gradle/gradle/.
62 | #
63 | ##############################################################################
64 |
65 | # Attempt to set APP_HOME
66 |
67 | # Resolve links: $0 may be a link
68 | app_path=$0
69 |
70 | # Need this for daisy-chained symlinks.
71 | while
72 | APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path
73 | [ -h "$app_path" ]
74 | do
75 | ls=$( ls -ld "$app_path" )
76 | link=${ls#*' -> '}
77 | case $link in #(
78 | /*) app_path=$link ;; #(
79 | *) app_path=$APP_HOME$link ;;
80 | esac
81 | done
82 |
83 | APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit
84 |
85 | APP_NAME="Gradle"
86 | APP_BASE_NAME=${0##*/}
87 |
88 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
89 | DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
90 |
91 | # Use the maximum available, or set MAX_FD != -1 to use that value.
92 | MAX_FD=maximum
93 |
94 | warn () {
95 | echo "$*"
96 | } >&2
97 |
98 | die () {
99 | echo
100 | echo "$*"
101 | echo
102 | exit 1
103 | } >&2
104 |
105 | # OS specific support (must be 'true' or 'false').
106 | cygwin=false
107 | msys=false
108 | darwin=false
109 | nonstop=false
110 | case "$( uname )" in #(
111 | CYGWIN* ) cygwin=true ;; #(
112 | Darwin* ) darwin=true ;; #(
113 | MSYS* | MINGW* ) msys=true ;; #(
114 | NONSTOP* ) nonstop=true ;;
115 | esac
116 |
117 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
118 |
119 |
120 | # Determine the Java command to use to start the JVM.
121 | if [ -n "$JAVA_HOME" ] ; then
122 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
123 | # IBM's JDK on AIX uses strange locations for the executables
124 | JAVACMD=$JAVA_HOME/jre/sh/java
125 | else
126 | JAVACMD=$JAVA_HOME/bin/java
127 | fi
128 | if [ ! -x "$JAVACMD" ] ; then
129 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
130 |
131 | Please set the JAVA_HOME variable in your environment to match the
132 | location of your Java installation."
133 | fi
134 | else
135 | JAVACMD=java
136 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
137 |
138 | Please set the JAVA_HOME variable in your environment to match the
139 | location of your Java installation."
140 | fi
141 |
142 | # Increase the maximum file descriptors if we can.
143 | if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then
144 | case $MAX_FD in #(
145 | max*)
146 | MAX_FD=$( ulimit -H -n ) ||
147 | warn "Could not query maximum file descriptor limit"
148 | esac
149 | case $MAX_FD in #(
150 | '' | soft) :;; #(
151 | *)
152 | ulimit -n "$MAX_FD" ||
153 | warn "Could not set maximum file descriptor limit to $MAX_FD"
154 | esac
155 | fi
156 |
157 | # Collect all arguments for the java command, stacking in reverse order:
158 | # * args from the command line
159 | # * the main class name
160 | # * -classpath
161 | # * -D...appname settings
162 | # * --module-path (only if needed)
163 | # * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables.
164 |
165 | # For Cygwin or MSYS, switch paths to Windows format before running java
166 | if "$cygwin" || "$msys" ; then
167 | APP_HOME=$( cygpath --path --mixed "$APP_HOME" )
168 | CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" )
169 |
170 | JAVACMD=$( cygpath --unix "$JAVACMD" )
171 |
172 | # Now convert the arguments - kludge to limit ourselves to /bin/sh
173 | for arg do
174 | if
175 | case $arg in #(
176 | -*) false ;; # don't mess with options #(
177 | /?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath
178 | [ -e "$t" ] ;; #(
179 | *) false ;;
180 | esac
181 | then
182 | arg=$( cygpath --path --ignore --mixed "$arg" )
183 | fi
184 | # Roll the args list around exactly as many times as the number of
185 | # args, so each arg winds up back in the position where it started, but
186 | # possibly modified.
187 | #
188 | # NB: a `for` loop captures its iteration list before it begins, so
189 | # changing the positional parameters here affects neither the number of
190 | # iterations, nor the values presented in `arg`.
191 | shift # remove old arg
192 | set -- "$@" "$arg" # push replacement arg
193 | done
194 | fi
195 |
196 | # Collect all arguments for the java command;
197 | # * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of
198 | # shell script including quotes and variable substitutions, so put them in
199 | # double quotes to make sure that they get re-expanded; and
200 | # * put everything else in single quotes, so that it's not re-expanded.
201 |
202 | set -- \
203 | "-Dorg.gradle.appname=$APP_BASE_NAME" \
204 | -classpath "$CLASSPATH" \
205 | org.gradle.wrapper.GradleWrapperMain \
206 | "$@"
207 |
208 | # Use "xargs" to parse quoted args.
209 | #
210 | # With -n1 it outputs one arg per line, with the quotes and backslashes removed.
211 | #
212 | # In Bash we could simply go:
213 | #
214 | # readarray ARGS < <( xargs -n1 <<<"$var" ) &&
215 | # set -- "${ARGS[@]}" "$@"
216 | #
217 | # but POSIX shell has neither arrays nor command substitution, so instead we
218 | # post-process each arg (as a line of input to sed) to backslash-escape any
219 | # character that might be a shell metacharacter, then use eval to reverse
220 | # that process (while maintaining the separation between arguments), and wrap
221 | # the whole thing up as a single "set" statement.
222 | #
223 | # This will of course break if any of these variables contains a newline or
224 | # an unmatched quote.
225 | #
226 |
227 | eval "set -- $(
228 | printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" |
229 | xargs -n1 |
230 | sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' |
231 | tr '\n' ' '
232 | )" '"$@"'
233 |
234 | exec "$JAVACMD" "$@"
235 |
--------------------------------------------------------------------------------