From 8ef9da2307a4d314f13b1d6a035c31edf6ecd2c4 Mon Sep 17 00:00:00 2001 From: ElenaDiachenko Date: Mon, 4 Mar 2024 20:58:58 +0200 Subject: [PATCH 01/52] fix/androidManifest_generating --- packages/app-harness/renative.json | 13 +++++++++++-- packages/sdk-android/src/manifestParser.ts | 16 +++++++++++++++- 2 files changed, 26 insertions(+), 3 deletions(-) diff --git a/packages/app-harness/renative.json b/packages/app-harness/renative.json index f3a80bd476..c5e3ae7e5c 100644 --- a/packages/app-harness/renative.json +++ b/packages/app-harness/renative.json @@ -97,6 +97,11 @@ "tag": "manifest", "android:name": "", "children": [ + { + "tag": "uses-permission ", + "android:name": "android.permission.WRITE_EXTERNAL_STORAGE", + "children": [] + }, { "tag": "application", "android:name": ".MainApplication", @@ -105,7 +110,8 @@ "tag": "activity", "android:name": "com.ahmedadeltito.photoeditor.PhotoEditorActivity", "children": [] - } + }, + { "tag": "activity", "android:name": "com.yalantis.ucrop.UCropActivity" } ] } ] @@ -151,7 +157,10 @@ "templateXcode": { "AppDelegate_h": { "appDelegateExtensions": ["UNUserNotificationCenterDelegate"], - "appDelegateImports": ["", ""] + "appDelegateImports": [ + "", + "" + ] }, "AppDelegate_mm": { "appDelegateImports": [""], diff --git a/packages/sdk-android/src/manifestParser.ts b/packages/sdk-android/src/manifestParser.ts index 280db670a3..f5e6d7166d 100644 --- a/packages/sdk-android/src/manifestParser.ts +++ b/packages/sdk-android/src/manifestParser.ts @@ -114,7 +114,7 @@ const _mergeNodeParameters = ( const key = k as NodeKey; const val = nodeParamsExt[key]; - if (val && !SYSTEM_TAGS.includes(k)) { + if (val !== 'undefined' && !SYSTEM_TAGS.includes(k)) { //TODO: fix this (node as Record)[key] = val; } @@ -240,6 +240,20 @@ export const parseAndroidManifestSync = (c: Context) => { _mergeNodeChildren(baseManifestFile, manifestObj.children); } }); + + // PARSE renative.json plugins + parsePlugins( + c, + platform, + (_, pluginPlat) => { + const androidManifest = getFlavouredProp(c, pluginPlat, 'templateAndroid')?.AndroidManifest_xml; + if (androidManifest?.children) { + _mergeNodeChildren(baseManifestFile, androidManifest.children); + } + }, + true, + true + ); //TODO: Should be mark as deprecated // appConfigs/base/plugins.json PLUGIN CONFIG OVERRIDES From 5e35e7061b6fc4deee75aa7351ab46ad1cb4b48e Mon Sep 17 00:00:00 2001 From: Mihai Blaga Date: Mon, 4 Mar 2024 19:59:55 +0100 Subject: [PATCH 02/52] added UT for getAllSuitableTasks --- .../core/src/tasks/__tests__/index.test.ts | 200 ++++++++++++++++++ 1 file changed, 200 insertions(+) create mode 100644 packages/core/src/tasks/__tests__/index.test.ts diff --git a/packages/core/src/tasks/__tests__/index.test.ts b/packages/core/src/tasks/__tests__/index.test.ts new file mode 100644 index 0000000000..a4cd1fd85b --- /dev/null +++ b/packages/core/src/tasks/__tests__/index.test.ts @@ -0,0 +1,200 @@ +import { getAllSuitableTasks } from '..'; +import { createRnvApi, createRnvContext, getContext } from '@rnv/core'; +import { getRegisteredEngines } from '../../engines'; +// import { inquirerPrompt } from '../../api'; + +jest.mock('../../engines'); +jest.mock('chalk'); +jest.mock('../../logger'); +jest.mock('../../api'); + +beforeEach(() => { + createRnvContext(); + createRnvApi(); +}); + +afterEach(() => { + jest.resetAllMocks(); +}); + +const mockEngineRegistration = [ + { + tasks: { + run: { + description: 'Run your app in browser', + task: 'run', + options: [ + { + shortcut: 'i', + value: 'value', + description: 'Show full debug Info', + key: 'info', + }, + { + shortcut: 'H', + value: 'value', + isRequired: true, + description: 'custom Host ip', + key: 'host', + }, + ], + platforms: [], + }, + build: { + description: 'Build project binary', + task: 'build', + options: [ + { + shortcut: 'i', + value: 'value', + description: 'Show full debug Info', + key: 'info', + }, + { + description: 'CI/CD flag so it wont ask questions', + key: 'ci', + }, + ], + platforms: [], + }, + configure: { + description: 'Configure current project', + task: 'configure', + options: [ + { + shortcut: 'i', + value: 'value', + description: 'Show full debug Info', + key: 'info', + }, + ], + platforms: [], + }, + }, + config: { + $schema: '../../.rnv/schema/rnv.engine.json', + id: 'engine-rn-web', + overview: 'React native based engine with web transpiler provided by react-native-web', + plugins: { + react: 'source:rnv', + 'react-art': 'source:rnv', + 'react-dom': 'source:rnv', + 'react-native': 'source:rnv', + 'react-native-web': 'source:rnv', + }, + npm: { + devDependencies: {}, + }, + platforms: { + tizen: { + npm: { + dependencies: { + raf: '3.4.1', + }, + }, + }, + web: {}, + webtv: {}, + webos: {}, + tizenwatch: {}, + tizenmobile: {}, + chromecast: {}, + kaios: {}, + }, + engineExtension: 'ext', + }, + projectDirName: '', + serverDirName: '', + runtimeExtraProps: {}, + platforms: { + web: { + defaultPort: 8080, + isWebHosted: true, + extensions: ['engine-rn-web.jsx'], + }, + chromecast: { + defaultPort: 8095, + isWebHosted: true, + extensions: ['engine-rn-web.jsx'], + }, + }, + rootPath: 'renative/packages/engine-rn-web', + originalTemplatePlatformsDir: 'renative/packages/engine-rn-web/templates/platforms', + originalTemplatePlatformProjectDir: 'renative/packages/engine-rn-web/templates/platforms', + }, +]; + +const tasksExpected = { + run: { + value: 'run', + command: 'run', + name: 'run (Run your app in browser)', + asArray: ['run'], + description: 'Run your app in browser', + params: [ + { shortcut: 'i', value: 'value', description: 'Show full debug Info', key: 'info' }, + { shortcut: 'H', value: 'value', isRequired: true, description: 'custom Host ip', key: 'host' }, + ], + providers: ['engine-rn-web'], + }, + build: { + value: 'build', + command: 'build', + name: 'build (Build project binary)', + asArray: ['build'], + description: 'Build project binary', + params: [ + { shortcut: 'i', value: 'value', description: 'Show full debug Info', key: 'info' }, + { description: 'CI/CD flag so it wont ask questions', key: 'ci' }, + ], + providers: ['engine-rn-web'], + }, + configure: { + value: 'configure', + command: 'configure', + name: 'configure (Configure current project)', + asArray: ['configure'], + description: 'Configure current project', + params: [{ shortcut: 'i', value: 'value', description: 'Show full debug Info', key: 'info' }], + providers: ['engine-rn-web'], + }, +}; + +describe('Get suitable tasks', () => { + it('should return empty when no engines are registered', () => { + // GIVEN + const c = getContext(); + jest.mocked(getRegisteredEngines).mockReturnValue([]); + // WHEN + const result = getAllSuitableTasks(c); + // THEN + expect(result).toEqual({}); + }); + + it('should return all tasks when all engines are registered', () => { + // GIVEN + const c = getContext(); + jest.mocked(getRegisteredEngines).mockReturnValue(mockEngineRegistration); + // WHEN + const result = getAllSuitableTasks(c); + // THEN + expect(result).toEqual(tasksExpected); + }); +}); + +// TODO JS loop, will be added in the next PR +// describe('findSuitableTask', () => { +// it('should return undefined when specificTask is not provided and c.command is not set', async () => { +// // GIVEN +// const c = getContext(); +// jest.mocked(getRegisteredEngines).mockReturnValue(mockEngineRegistration); +// jest.mocked(inquirerPrompt).mockReturnValue(new Promise((resolve) => resolve({ selectedTask: 'run' }))); +// jest.mocked(getEngineSubTasks).mockReturnValue([mockEngineRegistration[0].tasks.run]); + +// // WHEN +// const result = await findSuitableTask(c); + +// // THEN +// expect(result).toBeUndefined(); +// }); +// }); From 85967bf9d127863bc9b758ab10d9adbd4fe86ee4 Mon Sep 17 00:00:00 2001 From: ElenaDiachenko Date: Mon, 4 Mar 2024 22:15:39 +0200 Subject: [PATCH 03/52] rename templateAndroid properties --- packages/app-harness/renative.json | 4 +- .../fragments/templateAndroidBase.ts | 4 +- packages/sdk-android/src/kotlinParser.ts | 50 +++++++++---------- packages/template-starter/renative.json | 2 +- 4 files changed, 30 insertions(+), 30 deletions(-) diff --git a/packages/app-harness/renative.json b/packages/app-harness/renative.json index c5e3ae7e5c..cf9750b567 100644 --- a/packages/app-harness/renative.json +++ b/packages/app-harness/renative.json @@ -9,7 +9,7 @@ "react-native-splash-screen": { "android": { "templateAndroid": { - "MainActivity_java": { + "MainActivity_kt": { "createMethods": ["SplashScreen.show(this)"], "imports": ["org.devio.rn.splashscreen.SplashScreen"] } @@ -37,7 +37,7 @@ "TestNativeModule": { "android": { "templateAndroid": { - "MainApplication_java": { + "MainApplication_kt": { "packages": ["MyAppPackage"] } }, diff --git a/packages/core/src/schema/platforms/fragments/templateAndroidBase.ts b/packages/core/src/schema/platforms/fragments/templateAndroidBase.ts index d11f47e887..9484a4e0e9 100644 --- a/packages/core/src/schema/platforms/fragments/templateAndroidBase.ts +++ b/packages/core/src/schema/platforms/fragments/templateAndroidBase.ts @@ -91,7 +91,7 @@ export const TemplateAndroidBaseFragment = { ), }) ), - MainActivity_java: z.optional( + MainActivity_kt: z.optional( z.object({ onCreate: z .string({}) @@ -104,7 +104,7 @@ export const TemplateAndroidBaseFragment = { resultMethods: z.array(z.string()).optional(), }) ), - MainApplication_java: z.optional( + MainApplication_kt: z.optional( z .object({ imports: z.array(z.string()).optional(), diff --git a/packages/sdk-android/src/kotlinParser.ts b/packages/sdk-android/src/kotlinParser.ts index 1a29b03cc5..1d2f35e07d 100644 --- a/packages/sdk-android/src/kotlinParser.ts +++ b/packages/sdk-android/src/kotlinParser.ts @@ -6,7 +6,7 @@ import { getConfigProp, writeCleanFile, } from '@rnv/core'; -import { mkdirSync } from 'fs'; +// import { mkdirSync } from 'fs'; import path from 'path'; import { Context } from './types'; import { getBuildFilePath, getEntryFile, getAppId, addSystemInjects } from '@rnv/sdk-utils'; @@ -16,32 +16,32 @@ import { getBuildFilePath, getEntryFile, getAppId, addSystemInjects } from '@rnv // androidwear: '"assets://index.androidwear.bundle"', // }; -export const parseFlipperSync = (c: Context, scheme: 'debug' | 'release') => { - const appFolder = getAppFolder(c); - const { platform } = c; +// export const parseFlipperSync = (c: Context, scheme: 'debug' | 'release') => { +// const appFolder = getAppFolder(c); +// const { platform } = c; - const appId = getAppId(c, c.platform); - // console.log('appId', appId); - const javaPackageArray = appId?.split('.') || []; +// const appId = getAppId(c, c.platform); +// // console.log('appId', appId); +// const javaPackageArray = appId?.split('.') || []; - const javaPackagePath = `app/src/${scheme}/java/${javaPackageArray.join('/')}`; - mkdirSync(path.join(appFolder, javaPackagePath), { recursive: true }); +// const javaPackagePath = `app/src/${scheme}/java/${javaPackageArray.join('/')}`; +// mkdirSync(path.join(appFolder, javaPackagePath), { recursive: true }); - const templatePath = `app/src/${scheme}/java/rnv_template/ReactNativeFlipper.kt`; - const applicationPath = `${javaPackagePath}/ReactNativeFlipper.java`; +// const templatePath = `app/src/${scheme}/java/rnv_template/ReactNativeFlipper.kt`; +// const applicationPath = `${javaPackagePath}/ReactNativeFlipper.java`; - const injects: OverridesOptions = [{ pattern: '{{APPLICATION_ID}}', override: getAppId(c, platform) }]; +// const injects: OverridesOptions = [{ pattern: '{{APPLICATION_ID}}', override: getAppId(c, platform) }]; - addSystemInjects(c, injects); +// addSystemInjects(c, injects); - writeCleanFile( - getBuildFilePath(c, platform, templatePath), - path.join(appFolder, applicationPath), - injects, - undefined, - c - ); -}; +// writeCleanFile( +// getBuildFilePath(c, platform, templatePath), +// path.join(appFolder, applicationPath), +// injects, +// undefined, +// c +// ); +// }; export const parseMainApplicationSync = (c: Context) => { const appFolder = getAppFolder(c); @@ -121,7 +121,7 @@ export const parseMainActivitySync = (c: RnvContext) => { const templateAndroid = getConfigProp(c, platform, 'templateAndroid', {}); - const mainActivity = templateAndroid?.MainActivity_java; + const mainActivity = templateAndroid?.MainActivity_kt; c.payload.pluginConfigAndroid.injectActivityOnCreate = mainActivity?.onCreate || 'super.onCreate(savedInstanceState)'; @@ -203,7 +203,7 @@ export const injectPluginKotlinSync = ( pkg: string | undefined ) => { const templ = plugin.templateAndroid; - const mainActivity = templ?.MainActivity_java; + const mainActivity = templ?.MainActivity_kt; if (mainActivity?.imports) { mainActivity.imports.forEach((activityImport) => { // Avoid duplicate imports @@ -232,7 +232,7 @@ export const injectPluginKotlinSync = ( _injectPackage(c, plugin, pkg); - const mainApplication = templ?.MainApplication_java; + const mainApplication = templ?.MainApplication_kt; if (mainApplication?.packages) { mainApplication.packages.forEach((v) => { @@ -264,7 +264,7 @@ const _injectPackage = (c: RnvContext, plugin: RenativeConfigPluginPlatform, pkg c.payload.pluginConfigAndroid.pluginApplicationImports += `import ${pkg}\n`; } let packageParams = ''; - const mainApplication = plugin.templateAndroid?.MainApplication_java; + const mainApplication = plugin.templateAndroid?.MainApplication_kt; if (mainApplication?.packageParams) { packageParams = mainApplication.packageParams.join(','); } diff --git a/packages/template-starter/renative.json b/packages/template-starter/renative.json index 5a9ddca580..d43474ce40 100644 --- a/packages/template-starter/renative.json +++ b/packages/template-starter/renative.json @@ -95,7 +95,7 @@ "org.gradle.parallel": true, "org.gradle.configureondemand": true }, - "MainActivity_java": { + "MainActivity_kt": { "onCreate": "super.onCreate(null)" } } From 46e5763f068c2ef15870ced941f6d43e40a216b0 Mon Sep 17 00:00:00 2001 From: ElenaDiachenko Date: Wed, 6 Mar 2024 13:04:07 +0200 Subject: [PATCH 04/52] fix app header, add Logger --- packages/app-harness/src/app/index.tsx | 5 ++++- packages/app-harness/src/components/Logger/index.tsx | 3 +++ .../src/components/NewModuleButton/index.native.tsx | 5 +++-- .../app-harness/src/components/NewModuleButton/index.tsx | 3 ++- .../src/components/Notifications/index.ios.mobile.ts | 5 +++-- packages/app-harness/src/components/Notifications/index.ts | 6 ++++-- .../app-harness/src/components/Permissions/index.mobile.ts | 3 ++- packages/app-harness/src/components/Permissions/index.ts | 4 +++- packages/app-harness/src/components/SplashScreen/index.ts | 6 ++++-- 9 files changed, 28 insertions(+), 12 deletions(-) create mode 100644 packages/app-harness/src/components/Logger/index.tsx diff --git a/packages/app-harness/src/app/index.tsx b/packages/app-harness/src/app/index.tsx index dc8019169f..5bbb4f1851 100644 --- a/packages/app-harness/src/app/index.tsx +++ b/packages/app-harness/src/app/index.tsx @@ -1,5 +1,6 @@ import React, { useEffect, useState } from 'react'; import { Button, Image, ScrollView, Text, View } from 'react-native'; +import { Api } from '@rnv/renative'; import { OrientationLocker, PORTRAIT, LANDSCAPE } from '../components/OrientationLocker'; import { NewModuleButton } from '../components/NewModuleButton'; import { SplashScreen } from '../components/SplashScreen'; @@ -35,7 +36,9 @@ const App = () => { ReNative Harness - v1.0.0-rc.12, platform: macos, formFactor: desktop + + {`v1.0.0-rc.12, platform: ${Api.platform}, factor: ${Api.formFactor}, engine: ${Api.engine}`} + diff --git a/packages/app-harness/src/components/Logger/index.tsx b/packages/app-harness/src/components/Logger/index.tsx new file mode 100644 index 0000000000..5d6e45cc8d --- /dev/null +++ b/packages/app-harness/src/components/Logger/index.tsx @@ -0,0 +1,3 @@ +export const logDebug = (msg: any) => { + console.log(msg); +}; diff --git a/packages/app-harness/src/components/NewModuleButton/index.native.tsx b/packages/app-harness/src/components/NewModuleButton/index.native.tsx index fa23fe672a..3af4009d73 100644 --- a/packages/app-harness/src/components/NewModuleButton/index.native.tsx +++ b/packages/app-harness/src/components/NewModuleButton/index.native.tsx @@ -1,13 +1,14 @@ import React from 'react'; import { NativeModules, Button } from 'react-native'; +import { logDebug } from '../Logger'; export const NewModuleButton = () => { const { TestNativeModule } = NativeModules; const callback = (error: any, result: string) => { if (error) { - console.log(error); + logDebug(error); } else { - console.log(result); + logDebug(result); } }; const onPress = () => { diff --git a/packages/app-harness/src/components/NewModuleButton/index.tsx b/packages/app-harness/src/components/NewModuleButton/index.tsx index 683662e543..e19223d9a9 100644 --- a/packages/app-harness/src/components/NewModuleButton/index.tsx +++ b/packages/app-harness/src/components/NewModuleButton/index.tsx @@ -1,9 +1,10 @@ import React from 'react'; import { Button } from 'react-native'; +import { logDebug } from '../Logger'; export const NewModuleButton = () => { const onPress = () => { - console.log('NativeModules not supported in web'); + logDebug('NativeModules not supported in web'); }; return