已合并
docs: Supplement the autolinking sample. #1570
xiedairong创建于 2025年9月17日
docs: Supplement the autolinking sample. #1570
已合并
共 72 个文件变更+1641-0
| @@ -0,0 +1,12 @@ | |||
| 1 | +/node_modules | ||
| 2 | +/oh_modules | ||
| 3 | +/local.properties | ||
| 4 | +/.idea | ||
| 5 | +**/build | ||
| 6 | +/.hvigor | ||
| 7 | +.cxx | ||
| 8 | +/.clangd | ||
| 9 | +/.clang-format | ||
| 10 | +/.clang-tidy | ||
| 11 | +**/.test | ||
| 12 | +/.appanalyzer | ||
| @@ -0,0 +1,10 @@ | |||
| 1 | +{ | ||
| 2 | + "app": { | ||
| 3 | + "bundleName": "com.example.autolink", | ||
| 4 | + "vendor": "example", | ||
| 5 | + "versionCode": 1000000, | ||
| 6 | + "versionName": "1.0.0", | ||
| 7 | + "icon": "$media:app_icon", | ||
| 8 | + "label": "$string:app_name" | ||
| 9 | + } | ||
| 10 | +} | ||
| @@ -0,0 +1,8 @@ | |||
| 1 | +{ | ||
| 2 | + "string": [ | ||
| 3 | + { | ||
| 4 | + "name": "app_name", | ||
| 5 | + "value": "harmony" | ||
| 6 | + } | ||
| 7 | + ] | ||
| 8 | +} | ||
| @@ -0,0 +1,40 @@ | |||
| 1 | +{ | ||
| 2 | + "app": { | ||
| 3 | + "signingConfigs": [], | ||
| 4 | + "products": [ | ||
| 5 | + { | ||
| 6 | + "name": "default", | ||
| 7 | + "signingConfig": "default", | ||
| 8 | + "compatibleSdkVersion": "5.0.1(13)", | ||
| 9 | + "runtimeOS": "HarmonyOS", | ||
| 10 | + } | ||
| 11 | + ], | ||
| 12 | + "buildModeSet": [ | ||
| 13 | + { | ||
| 14 | + "name": "debug", | ||
| 15 | + }, | ||
| 16 | + { | ||
| 17 | + "name": "release" | ||
| 18 | + } | ||
| 19 | + ] | ||
| 20 | + }, | ||
| 21 | + "modules": [ | ||
| 22 | + { | ||
| 23 | + "name": "entry", | ||
| 24 | + "srcPath": "./entry", | ||
| 25 | + "targets": [ | ||
| 26 | + { | ||
| 27 | + "name": "default", | ||
| 28 | + "applyToProducts": [ | ||
| 29 | + "default" | ||
| 30 | + ] | ||
| 31 | + } | ||
| 32 | + ] | ||
| 33 | + }, | ||
| 34 | + // If you need to recompile library.har, you can uncomment this section. | ||
| 35 | + // { | ||
| 36 | + // "name": "library", | ||
| 37 | + // "srcPath": "../third-party-library-sample/harmony/library", | ||
| 38 | + // } | ||
| 39 | + ] | ||
| 40 | +} | ||
| @@ -0,0 +1,8 @@ | |||
| 1 | +/node_modules | ||
| 2 | +/oh_modules | ||
| 3 | +/.preview | ||
| 4 | +/build | ||
| 5 | +/.cxx | ||
| 6 | +/.test | ||
| 7 | +/src/main/cpp/generated | ||
| 8 | +/src/main/resources/rawfile/bundle.harmony.js | ||
| @@ -0,0 +1,22 @@ | |||
| 1 | +{ | ||
| 2 | + "apiType": "stageMode", | ||
| 3 | + "buildOption": { | ||
| 4 | + "arkOptions": { | ||
| 5 | + // "apPath": "./modules.ap" /* Profile used for profile-guided optimization (PGO), a compiler optimization technique to improve app runtime performance. */ | ||
| 6 | + }, | ||
| 7 | + "externalNativeOptions": { | ||
| 8 | + "path": "./src/main/cpp/CMakeLists.txt", | ||
| 9 | + "arguments": "", | ||
| 10 | + "cppFlags": "", | ||
| 11 | + } | ||
| 12 | + | ||
| 13 | + }, | ||
| 14 | + "targets": [ | ||
| 15 | + { | ||
| 16 | + "name": "default" | ||
| 17 | + }, | ||
| 18 | + { | ||
| 19 | + "name": "ohosTest", | ||
| 20 | + } | ||
| 21 | + ] | ||
| 22 | +} | ||
| @@ -0,0 +1,20 @@ | |||
| 1 | +/** | ||
| 2 | + * Copyright (c) 2025 Huawei Technologies Co., Ltd. | ||
| 3 | + * | ||
| 4 | + * This source code is licensed under the MIT license found in the | ||
| 5 | + * LICENSE-MIT file in the root directory of this source tree. | ||
| 6 | + */ | ||
| 7 | + | ||
| 8 | +import { hapTasks } from '@ohos/hvigor-ohos-plugin'; | ||
| 9 | +import { createRNOHModulePlugin } from "@rnoh/hvigor-plugin" | ||
| 10 | + | ||
| 11 | +export default { | ||
| 12 | + system: hapTasks, /* Built-in plugin of Hvigor. It cannot be modified. */ | ||
| 13 | + plugins: [ | ||
| 14 | + createRNOHModulePlugin({ | ||
| 15 | + nodeModulesPath: "../ReactProject/node_modules", | ||
| 16 | + codegen: null, | ||
| 17 | + autolinking: {} | ||
| 18 | + }), | ||
| 19 | + ] | ||
| 20 | +} | ||
| @@ -0,0 +1,10 @@ | |||
| 1 | +{ | ||
| 2 | + "license": "", | ||
| 3 | + "devDependencies": {}, | ||
| 4 | + "author": "", | ||
| 5 | + "name": "entry", | ||
| 6 | + "description": "Please describe the basic information.", | ||
| 7 | + "main": "", | ||
| 8 | + "version": "1.0.0", | ||
| 9 | + "dependencies": {} | ||
| 10 | +} | ||
| @@ -0,0 +1,39 @@ | |||
| 1 | +# Copyright (c) 2025 Huawei Technologies Co., Ltd. | ||
| 2 | +# | ||
| 3 | +# This source code is licensed under the MIT license found in the | ||
| 4 | +# LICENSE-MIT file in the root directory of this source tree. | ||
| 5 | + | ||
| 6 | +project(rnapp) | ||
| 7 | +cmake_minimum_required(VERSION 3.4.1) | ||
| 8 | +set(CMAKE_SKIP_BUILD_RPATH TRUE) | ||
| 9 | +set(RNOH_APP_DIR "${CMAKE_CURRENT_SOURCE_DIR}") | ||
| 10 | +set(OH_MODULES_DIR "${CMAKE_CURRENT_SOURCE_DIR}/../../../../oh_modules") | ||
| 11 | +set(RNOH_CPP_DIR "${OH_MODULES_DIR}/@rnoh/react-native-openharmony/src/main/cpp") | ||
| 12 | +file(REAL_PATH "${RNOH_CPP_DIR}" RNOH_CPP_DIR) | ||
| 13 | +set(RNOH_GENERATED_DIR "${CMAKE_CURRENT_SOURCE_DIR}/generated") | ||
| 14 | +set(LOG_VERBOSITY_LEVEL 1) | ||
| 15 | +set(CMAKE_ASM_FLAGS "-Wno-error=unused-command-line-argument -Qunused-arguments") | ||
| 16 | +set(CMAKE_CXX_FLAGS "-fstack-protector-strong -Wl,-z,relro,-z,now,-z,noexecstack -fPIE -pie") | ||
| 17 | +set(WITH_HITRACE_SYSTRACE 1) # for other CMakeLists.txt files to use | ||
| 18 | +add_compile_definitions(WITH_HITRACE_SYSTRACE) | ||
| 19 | + | ||
| 20 | +include("${CMAKE_CURRENT_SOURCE_DIR}/autolinking.cmake") | ||
| 21 | +add_subdirectory("${RNOH_CPP_DIR}" ./rn) | ||
| 22 | + | ||
| 23 | +# RNOH_BEGIN: manual_package_linking_1 | ||
| 24 | +# RNOH_END: manual_package_linking_1 | ||
| 25 | + | ||
| 26 | +file(GLOB GENERATED_CPP_FILES "./generated/*.cpp") | ||
| 27 | + | ||
| 28 | +add_library(rnoh_app SHARED | ||
| 29 | + ${GENERATED_CPP_FILES} | ||
| 30 | + "./PackageProvider.cpp" | ||
| 31 | + "${RNOH_CPP_DIR}/RNOHAppNapiBridge.cpp" | ||
| 32 | +) | ||
| 33 | + | ||
| 34 | +target_link_libraries(rnoh_app PUBLIC rnoh) | ||
| 35 | + | ||
| 36 | +autolink_libraries(rnoh_app) | ||
| 37 | + | ||
| 38 | +# RNOH_BEGIN: manual_package_linking_2 | ||
| 39 | +# RNOH_END: manual_package_linking_2 | ||
| @@ -0,0 +1,17 @@ | |||
| 1 | +/** | ||
| 2 | + * Copyright (c) 2025 Huawei Technologies Co., Ltd. | ||
| 3 | + * | ||
| 4 | + * This source code is licensed under the MIT license found in the | ||
| 5 | + * LICENSE-MIT file in the root directory of this source tree. | ||
| 6 | + */ | ||
| 7 | + | ||
| 8 | +#include "RNOH/PackageProvider.h" | ||
| 9 | +#include "RNOHPackagesFactory.h" | ||
| 10 | + | ||
| 11 | +using namespace rnoh; | ||
| 12 | + | ||
| 13 | +std::vector<std::shared_ptr<Package>> PackageProvider::getPackages( | ||
| 14 | + Package::Context ctx) { | ||
| 15 | + auto packages = createRNOHPackages(ctx); // <= autolinking | ||
| 16 | + return packages; | ||
| 17 | +} | ||
| @@ -0,0 +1,14 @@ | |||
| 1 | +/** | ||
| 2 | + * Copyright (c) 2025 Huawei Technologies Co., Ltd. | ||
| 3 | + * | ||
| 4 | + * This source code is licensed under the MIT license found in the | ||
| 5 | + * LICENSE file in the root directory of this source tree. | ||
| 6 | + */ | ||
| 7 | +import type { RNPackageContext, RNOHPackage } from '@rnoh/react-native-openharmony'; | ||
| 8 | +import { createRNOHPackages as createRNOHPackagesAutolinking } from "./RNOHPackagesFactory" | ||
| 9 | + | ||
| 10 | +export function getRNOHPackages(ctx: RNPackageContext): RNOHPackage[] { | ||
| 11 | + return [ | ||
| 12 | + ...createRNOHPackagesAutolinking(ctx) | ||
| 13 | + ] | ||
| 14 | +} | ||
| @@ -0,0 +1,18 @@ | |||
| 1 | +/** | ||
| 2 | + * Copyright (c) 2025 Huawei Technologies Co., Ltd. | ||
| 3 | + * | ||
| 4 | + * This source code is licensed under the MIT license found in the | ||
| 5 | + * LICENSE-MIT file in the root directory of this source tree. | ||
| 6 | + */ | ||
| 7 | + | ||
| 8 | +import { RNAbility } from '@rnoh/react-native-openharmony'; | ||
| 9 | + | ||
| 10 | +export default class EntryAbility extends RNAbility { | ||
| 11 | + getPagePath() { | ||
| 12 | + return 'pages/Index'; | ||
| 13 | + } | ||
| 14 | + | ||
| 15 | + override getRNOHWorkerScriptUrl() { | ||
| 16 | + return "entry/ets/workers/RNOHWorker.ets" | ||
| 17 | + } | ||
| 18 | +} | ||
| @@ -0,0 +1,79 @@ | |||
| 1 | +/** | ||
| 2 | + * Copyright (c) 2025 Huawei Technologies Co., Ltd. | ||
| 3 | + * | ||
| 4 | + * This source code is licensed under the MIT license found in the | ||
| 5 | + * LICENSE-MIT file in the root directory of this source tree. | ||
| 6 | + */ | ||
| 7 | + | ||
| 8 | +import { | ||
| 9 | + AnyJSBundleProvider, | ||
| 10 | + ComponentBuilderContext, | ||
| 11 | + FileJSBundleProvider, | ||
| 12 | + MetroJSBundleProvider, | ||
| 13 | + ResourceJSBundleProvider, | ||
| 14 | + RNApp, | ||
| 15 | + RNOHErrorDialog, | ||
| 16 | + RNOHLogger, | ||
| 17 | + TraceJSBundleProviderDecorator, | ||
| 18 | + RNOHCoreContext | ||
| 19 | +} from '@rnoh/react-native-openharmony'; | ||
| 20 | +import { getRNOHPackages } from '../PackageProvider'; | ||
| 21 | + | ||
| 22 | +@Builder | ||
| 23 | +export function buildCustomRNComponent(ctx: ComponentBuilderContext) {} | ||
| 24 | + | ||
| 25 | +const wrappedCustomRNComponentBuilder = wrapBuilder(buildCustomRNComponent); | ||
| 26 | + | ||
| 27 | +@Entry | ||
| 28 | +@Component | ||
| 29 | +struct Index { | ||
| 30 | + @StorageLink('RNOHCoreContext') private rnohCoreContext: RNOHCoreContext | undefined = undefined; | ||
| 31 | + @State shouldShow: boolean = false; | ||
| 32 | + private logger!: RNOHLogger; | ||
| 33 | + | ||
| 34 | + aboutToAppear() { | ||
| 35 | + this.logger = this.rnohCoreContext!.logger.clone("Index"); | ||
| 36 | + const stopTracing = this.logger.clone("aboutToAppear").startTracing(); | ||
| 37 | + this.shouldShow = true; | ||
| 38 | + stopTracing(); | ||
| 39 | + } | ||
| 40 | + | ||
| 41 | + onBackPress(): boolean | undefined { | ||
| 42 | + // NOTE: this is required since `Ability`'s `onBackPressed` function always | ||
| 43 | + // terminates or puts the app in the background, but we want Ark to ignore it completely | ||
| 44 | + // when handled by RN | ||
| 45 | + this.rnohCoreContext!.dispatchBackPress(); | ||
| 46 | + return true; | ||
| 47 | + } | ||
| 48 | + | ||
| 49 | + build() { | ||
| 50 | + Column() { | ||
| 51 | + if (this.rnohCoreContext && this.shouldShow) { | ||
| 52 | + if (this.rnohCoreContext?.isDebugModeEnabled) { | ||
| 53 | + RNOHErrorDialog({ ctx: this.rnohCoreContext }); | ||
| 54 | + } | ||
| 55 | + RNApp({ | ||
| 56 | + rnInstanceConfig: { | ||
| 57 | + createRNPackages: getRNOHPackages, | ||
| 58 | + }, | ||
| 59 | + initialProps: { "foo": "bar" } as Record<string, string>, | ||
| 60 | + appKey: "app_name", | ||
| 61 | + wrappedCustomRNComponentBuilder: wrappedCustomRNComponentBuilder, | ||
| 62 | + jsBundleProvider: new TraceJSBundleProviderDecorator( | ||
| 63 | + new AnyJSBundleProvider([ | ||
| 64 | + new MetroJSBundleProvider(), | ||
| 65 | + // NOTE: to load the bundle from file, place it in | ||
| 66 | + // `/data/app/el2/100/base/com.rnoh.tester/files/bundle.harmony.js` | ||
| 67 | + // on your device. The path mismatch is due to app sandboxing on OpenHarmony | ||
| 68 | + new FileJSBundleProvider('/data/storage/el2/base/files/bundle.harmony.js'), | ||
| 69 | + new ResourceJSBundleProvider(this.rnohCoreContext.uiAbilityContext.resourceManager, 'hermes_bundle.hbc'), | ||
| 70 | + new ResourceJSBundleProvider(this.rnohCoreContext.uiAbilityContext.resourceManager, 'bundle.harmony.js') | ||
| 71 | + ]), | ||
| 72 | + this.rnohCoreContext.logger), | ||
| 73 | + }) | ||
| 74 | + } | ||
| 75 | + } | ||
| 76 | + .height('100%') | ||
| 77 | + .width('100%') | ||
| 78 | + } | ||
| 79 | +} | ||
| @@ -0,0 +1,23 @@ | |||
| 1 | +/** | ||
| 2 | + * Copyright (c) 2025 Huawei Technologies Co., Ltd. | ||
| 3 | + * | ||
| 4 | + * This source code is licensed under the MIT license found in the | ||
| 5 | + * LICENSE file in the root directory of this source tree. | ||
| 6 | + */ | ||
| 7 | + | ||
| 8 | + /** | ||
| 9 | + * Importing some ets files in the following way results in runtime errors e.g. | ||
| 10 | + * import { setupRNOHWorker } from "@rnoh/react-native-openharmony" | ||
| 11 | + * | ||
| 12 | + * It looks like this is ArkTS problem and it may be fixed in the future. | ||
| 13 | + * For the time being, use direct imports. | ||
| 14 | + */ | ||
| 15 | +import { setupRNOHWorker } from "@rnoh/react-native-openharmony/src/main/ets/setupRNOHWorker" | ||
| 16 | +import { getRNOHPackages } from "../PackageProvider" | ||
| 17 | + | ||
| 18 | +setupRNOHWorker({ | ||
| 19 | + createWorkerRNInstanceConfig: (_rnInstanceName) => { | ||
| 20 | + return { thirdPartyPackagesFactory: getRNOHPackages } | ||
| 21 | + } | ||
| 22 | +}) | ||
| 23 | + | ||
| @@ -0,0 +1,50 @@ | |||
| 1 | +{ | ||
| 2 | + "module": { | ||
| 3 | + "name": "entry", | ||
| 4 | + "type": "entry", | ||
| 5 | + "description": "$string:module_desc", | ||
| 6 | + "mainElement": "EntryAbility", | ||
| 7 | + "deviceTypes": [ | ||
| 8 | + "phone", | ||
| 9 | + "tablet", | ||
| 10 | + "2in1" | ||
| 11 | + ], | ||
| 12 | + "metadata": [ | ||
| 13 | + { | ||
| 14 | + "name": "half_leading", | ||
| 15 | + "value": "true" | ||
| 16 | + }, | ||
| 17 | + { | ||
| 18 | + "name": "can_preview_text", | ||
| 19 | + "value": "true", | ||
| 20 | + } | ||
| 21 | + ], | ||
| 22 | + "libIsolation": false, | ||
| 23 | + "deliveryWithInstall": true, | ||
| 24 | + "installationFree": false, | ||
| 25 | + "pages": "$profile:main_pages", | ||
| 26 | + "abilities": [ | ||
| 27 | + { | ||
| 28 | + "name": "EntryAbility", | ||
| 29 | + "srcEntry": "./ets/entryability/EntryAbility.ets", | ||
| 30 | + "description": "$string:EntryAbility_desc", | ||
| 31 | + "icon": "$media:layered_image", | ||
| 32 | + "label": "$string:EntryAbility_label", | ||
| 33 | + // "orientation": "auto_rotation", | ||
| 34 | + "startWindowIcon": "$media:startIcon", | ||
| 35 | + "startWindowBackground": "$color:start_window_background", | ||
| 36 | + "exported": true, | ||
| 37 | + "skills": [ | ||
| 38 | + { | ||
| 39 | + "entities": [ | ||
| 40 | + "entity.system.home" | ||
| 41 | + ], | ||
| 42 | + "actions": [ | ||
| 43 | + "action.system.home" | ||
| 44 | + ] | ||
| 45 | + } | ||
| 46 | + ] | ||
| 47 | + }, | ||
| 48 | + ] | ||
| 49 | + } | ||
| 50 | +} | ||
| @@ -0,0 +1,8 @@ | |||
| 1 | +{ | ||
| 2 | + "color": [ | ||
| 3 | + { | ||
| 4 | + "name": "start_window_background", | ||
| 5 | + "value": "#FFFFFF" | ||
| 6 | + } | ||
| 7 | + ] | ||
| 8 | +} | ||
Adocs/Samples/AutolinkingSample/NativeProject/entry/src/main/resources/base/element/string.json+16-0
| @@ -0,0 +1,16 @@ | |||
| 1 | +{ | ||
| 2 | + "string": [ | ||
| 3 | + { | ||
| 4 | + "name": "module_desc", | ||
| 5 | + "value": "module description" | ||
| 6 | + }, | ||
| 7 | + { | ||
| 8 | + "name": "EntryAbility_desc", | ||
| 9 | + "value": "description" | ||
| 10 | + }, | ||
| 11 | + { | ||
| 12 | + "name": "EntryAbility_label", | ||
| 13 | + "value": "AutolinkingSample" | ||
| 14 | + } | ||
| 15 | + ] | ||
| 16 | +} | ||
Adocs/Samples/AutolinkingSample/NativeProject/entry/src/main/resources/base/media/background.png+0-0
Adocs/Samples/AutolinkingSample/NativeProject/entry/src/main/resources/base/media/foreground.png+0-0
Adocs/Samples/AutolinkingSample/NativeProject/entry/src/main/resources/base/media/layered_image.json+7-0
| @@ -0,0 +1,7 @@ | |||
| 1 | +{ | ||
| 2 | + "layered-image": | ||
| 3 | + { | ||
| 4 | + "background" : "$media:background", | ||
| 5 | + "foreground" : "$media:foreground" | ||
| 6 | + } | ||
| 7 | +} | ||
Adocs/Samples/AutolinkingSample/NativeProject/entry/src/main/resources/base/profile/main_pages.json+5-0
| @@ -0,0 +1,5 @@ | |||
| 1 | +{ | ||
| 2 | + "src": [ | ||
| 3 | + "pages/Index" | ||
| 4 | + ] | ||
| 5 | +} | ||
Adocs/Samples/AutolinkingSample/NativeProject/entry/src/main/resources/en_US/element/string.json+16-0
| @@ -0,0 +1,16 @@ | |||
| 1 | +{ | ||
| 2 | + "string": [ | ||
| 3 | + { | ||
| 4 | + "name": "module_desc", | ||
| 5 | + "value": "module description" | ||
| 6 | + }, | ||
| 7 | + { | ||
| 8 | + "name": "EntryAbility_desc", | ||
| 9 | + "value": "description" | ||
| 10 | + }, | ||
| 11 | + { | ||
| 12 | + "name": "EntryAbility_label", | ||
| 13 | + "value": "AutolinkingSample" | ||
| 14 | + } | ||
| 15 | + ] | ||
| 16 | +} | ||
Adocs/Samples/AutolinkingSample/NativeProject/entry/src/main/resources/zh_CN/element/string.json+16-0
| @@ -0,0 +1,16 @@ | |||
| 1 | +{ | ||
| 2 | + "string": [ | ||
| 3 | + { | ||
| 4 | + "name": "module_desc", | ||
| 5 | + "value": "模块描述" | ||
| 6 | + }, | ||
| 7 | + { | ||
| 8 | + "name": "EntryAbility_desc", | ||
| 9 | + "value": "description" | ||
| 10 | + }, | ||
| 11 | + { | ||
| 12 | + "name": "EntryAbility_label", | ||
| 13 | + "value": "FabricComponentSample" | ||
| 14 | + } | ||
| 15 | + ] | ||
| 16 | +} | ||
| @@ -0,0 +1,22 @@ | |||
| 1 | +{ | ||
| 2 | + "modelVersion": "5.0.0", | ||
| 3 | + "dependencies": { | ||
| 4 | + "@rnoh/hvigor-plugin": "file:../../ReactProject/node_modules/@react-native-oh/react-native-harmony-cli/harmony/rnoh-hvigor-plugin-0.77.22.tgz" | ||
| 5 | + }, | ||
| 6 | + "execution": { | ||
| 7 | + // "analyze": "default", /* Define the build analyze mode. Value: [ "default" | "verbose" | false ]. Default: "default" */ | ||
| 8 | + // "daemon": true, /* Enable daemon compilation. Value: [ true | false ]. Default: true */ | ||
| 9 | + // "incremental": true, /* Enable incremental compilation. Value: [ true | false ]. Default: true */ | ||
| 10 | + // "parallel": true, /* Enable parallel compilation. Value: [ true | false ]. Default: true */ | ||
| 11 | + // "typeCheck": false, /* Enable typeCheck. Value: [ true | false ]. Default: false */ | ||
| 12 | + }, | ||
| 13 | + "logging": { | ||
| 14 | + // "level": "info" /* Define the log level. Value: [ "debug" | "info" | "warn" | "error" ]. Default: "info" */ | ||
| 15 | + }, | ||
| 16 | + "debugging": { | ||
| 17 | + // "stacktrace": false /* Disable stacktrace compilation. Value: [ true | false ]. Default: false */ | ||
| 18 | + }, | ||
| 19 | + "nodeOptions": { | ||
| 20 | + // "maxOldSpaceSize": 4096 /* Enable nodeOptions maxOldSpaceSize compilation. Unit M. Used for the daemon process */ | ||
| 21 | + } | ||
| 22 | +} | ||
| @@ -0,0 +1,23 @@ | |||
| 1 | +/** | ||
| 2 | + * Copyright (c) 2025 Huawei Technologies Co., Ltd. | ||
| 3 | + * | ||
| 4 | + * This source code is licensed under the MIT license found in the | ||
| 5 | + * LICENSE-MIT file in the root directory of this source tree. | ||
| 6 | + */ | ||
| 7 | + | ||
| 8 | +import { appTasks } from '@ohos/hvigor-ohos-plugin'; | ||
| 9 | +import { createRNOHProjectPlugin } from '@rnoh/hvigor-plugin'; | ||
| 10 | + | ||
| 11 | +export default { | ||
| 12 | + system: appTasks, /* Built-in plugin of Hvigor. It cannot be modified. */ | ||
| 13 | + plugins: [ | ||
| 14 | + createRNOHProjectPlugin({ | ||
| 15 | + nodeModulesPath: "../ReactProject/node_modules", | ||
| 16 | + bundler: { | ||
| 17 | + config: "../ReactProject/metro.config.js", | ||
| 18 | + bundleOutput: "./entry/src/main/resources/rawfile/bundle.harmony.js", | ||
| 19 | + assetsDest: "./entry/src/main/resources/rawfile/assets", | ||
| 20 | + } | ||
| 21 | + }) | ||
| 22 | + ] | ||
| 23 | +} | ||
| @@ -0,0 +1,19 @@ | |||
| 1 | +{ | ||
| 2 | + modelVersion: "5.0.0", | ||
| 3 | + name: "harmony", | ||
| 4 | + version: "1.0.0", | ||
| 5 | + description: "Please describe the basic information.", | ||
| 6 | + main: "", | ||
| 7 | + author: "", | ||
| 8 | + license: "", | ||
| 9 | + dependencies: { | ||
| 10 | + "@rnoh/react-native-openharmony": "file:../ReactProject/node_modules/@react-native-oh/react-native-harmony/react_native_openharmony.har", | ||
| 11 | + }, | ||
| 12 | + devDependencies: { | ||
| 13 | + "@ohos/hypium": "1.0.16", | ||
| 14 | + "@ohos/hamock": "1.0.0", | ||
| 15 | + }, | ||
| 16 | + overrides: { | ||
| 17 | + "@rnoh/react-native-openharmony": "file:../ReactProject/node_modules/@react-native-oh/react-native-harmony/react_native_openharmony.har", | ||
| 18 | + }, | ||
| 19 | +} | ||
| @@ -0,0 +1,28 @@ | |||
| 1 | +# Description | ||
| 2 | +This is the demo project for RNOH Autolinking. | ||
| 3 | + | ||
| 4 | + | ||
| 5 | +# Directory Structure | ||
| 6 | + | ||
| 7 | +```md | ||
| 8 | +AutolinkingSample | ||
| 9 | +├── NativeProject harmony工程 | ||
| 10 | +├── react-native-oh RNOH前端及手脚架 | ||
| 11 | +├── ReactProject 前端工程 | ||
| 12 | +├── screenshots 效果图 | ||
| 13 | +├── third-party-library-sample RN三方件示例 | ||
| 14 | +└── README.md | ||
| 15 | +``` | ||
| 16 | + | ||
| 17 | + | ||
| 18 | +# Environment Setup | ||
| 19 | + | ||
| 20 | +1. Save `react-native-oh-react-native-harmony-0.77.xx.tgz` and `react-native-oh-react-native-harmony-cli-0.77.xx.tgz` to the `react-native-oh` folder. | ||
| 21 | +1. Run **npm pack** in `third-party-library-sample` to generate a .tgz file. | ||
| 22 | +1. Modify the `@react-native-oh/react-native-harmony` and `@react-native-oh/react-native-harmony-cli` dependency path of `ReactProject/package.json`. | ||
| 23 | +1. Modify the `@rnoh/hvigor-plugin` dependency path of `NativeProject/hvigor/hvigor-config.json5`; | ||
| 24 | +1. Run **npm i** in `ReactProject` to install the dependency. | ||
| 25 | +1. Open `NativeProject` in DevEco Studio and run **Sync and Refresh Project**. | ||
| 26 | +1. Click File > Project Structure > Signing Configs, log in and complete the signing. | ||
| 27 | +1. Run **npm start** in `ReactProject` to start Metro. | ||
| 28 | +1. Click **run** in the upper right corner to start the project. | ||
| @@ -0,0 +1,46 @@ | |||
| 1 | +# 说明 | ||
| 2 | + | ||
| 3 | +这是RNOH Autolinking的demo工程 | ||
| 4 | + | ||
| 5 | +## 目录结构 | ||
| 6 | + | ||
| 7 | +```md | ||
| 8 | +AutolinkingSample | ||
| 9 | +├── NativeProject harmony工程 | ||
| 10 | +├── react-native-oh RNOH前端及手脚架 | ||
| 11 | +├── ReactProject 前端工程 | ||
| 12 | +├── screenshots 效果图 | ||
| 13 | +├── third-party-library-sample RN三方件示例 | ||
| 14 | +└── README.md | ||
| 15 | +``` | ||
| 16 | + | ||
| 17 | +## 环境搭建 | ||
| 18 | + | ||
| 19 | +1. 将 `react-native-oh-react-native-harmony-0.77.xx.tgz` 和 `react-native-oh-react-native-harmony-cli-0.77.xx.tgz` 放置在 `react-native-oh` 目录下; | ||
| 20 | +1. 在 `third-party-library-sample` 中运行 **npm pack** 进行打包; | ||
| 21 | +1. 修改 `ReactProject/package.json` 中 `@react-native-oh/react-native-harmony` 和 `@react-native-oh/react-native-harmony-cli` 的版本号; | ||
| 22 | +1. 修改 `NativeProject/hvigor/hvigor-config.json5` 中 `@rnoh/hvigor-plugin` 的版本号; | ||
| 23 | +1. 在 `ReactProject` 目录下执行 **npm i** 安装依赖; | ||
| 24 | +1. 用 DevEco Studio 打开 `NativeProject`,执行 **Sync and Refresh Project**; | ||
| 25 | +1. 点击 File > Project Structure > Signing Configs,登录并完成签名; | ||
| 26 | +1. 在 `ReactProject` 目录下执行 **npm start** 启动Metro; | ||
| 27 | +1. 点击 DevEco Studio 右上角的 **run** 启动项目; | ||
| 28 | + | ||
| 29 | +> NOTE: 安装时项目默认使用最新的RNOH依赖,如需安装特定版本请查阅[RNOH版本演进规划和分支策略](https://gitcode.com/openharmony-sig/ohos_react_native/wiki/RNOH版本演进规划和分支策略.md)获取版本号。 | ||
| 30 | +> | ||
| 31 | +> npm依赖安装: `npm i @react-native-oh/react-native-harmony@0.77.xx` `npm i --save-dev @react-native-oh/react-native-harmony-cli@0.77.xx` | ||
| 32 | +> | ||
| 33 | +> ohpm依赖安装:`ohpm i @rnoh/react-native-openharmony@0.77.xx` | ||
| 34 | + | ||
| 35 | +## 效果预览 | ||
| 36 | + | ||
| 37 | +启动后页面效果如下: | ||
| 38 | + | ||
| 39 | + | ||
| 40 | + | ||
| 41 | +1. 点击【点击滚到顶】按钮,弹窗会滚到顶部; | ||
| 42 | +1. 弹窗会滚到顶部后向下拉,会根据滚动位置决定最终停留在中间还是回到顶部; | ||
| 43 | +1. 点击【选项1/2/3】,选项右侧会显示选中状态; | ||
| 44 | +1. 点击【确定】按钮,会在VSCode控制台打印对应选项的value,如:`{"target": 14, "value": [1]}`; | ||
| 45 | +1. 点击【现在是单选】按钮,按钮文案会改成【现在是多选】,继续点击【选项1/2/3】,可以让多个选项切换到选中状态; | ||
| 46 | +1. 点击【确定】按钮,会在VSCode控制台打印对应选项的value,如:`{"target": 14, "value": [1,2]}`; | ||
| @@ -0,0 +1,11 @@ | |||
| 1 | +/** | ||
| 2 | + * Copyright (c) 2025 Huawei Technologies Co., Ltd. | ||
| 3 | + * | ||
| 4 | + * This source code is licensed under the MIT license found in the | ||
| 5 | + * LICENSE-MIT file in the root directory of this source tree. | ||
| 6 | + */ | ||
| 7 | + | ||
| 8 | +module.exports = { | ||
| 9 | + root: true, | ||
| 10 | + extends: '@react-native', | ||
| 11 | +}; | ||
| @@ -0,0 +1,66 @@ | |||
| 1 | +# OSX | ||
| 2 | +# | ||
| 3 | +.DS_Store | ||
| 4 | + | ||
| 5 | +# Xcode | ||
| 6 | +# | ||
| 7 | +build/ | ||
| 8 | +*.pbxuser | ||
| 9 | +!default.pbxuser | ||
| 10 | +*.mode1v3 | ||
| 11 | +!default.mode1v3 | ||
| 12 | +*.mode2v3 | ||
| 13 | +!default.mode2v3 | ||
| 14 | +*.perspectivev3 | ||
| 15 | +!default.perspectivev3 | ||
| 16 | +xcuserdata | ||
| 17 | +*.xccheckout | ||
| 18 | +*.moved-aside | ||
| 19 | +DerivedData | ||
| 20 | +*.hmap | ||
| 21 | +*.ipa | ||
| 22 | +*.xcuserstate | ||
| 23 | +ios/.xcode.env.local | ||
| 24 | + | ||
| 25 | +# Android/IntelliJ | ||
| 26 | +# | ||
| 27 | +build/ | ||
| 28 | +.idea | ||
| 29 | +.gradle | ||
| 30 | +local.properties | ||
| 31 | +*.iml | ||
| 32 | +*.hprof | ||
| 33 | +.cxx/ | ||
| 34 | +*.keystore | ||
| 35 | +!debug.keystore | ||
| 36 | + | ||
| 37 | +# node.js | ||
| 38 | +# | ||
| 39 | +node_modules/ | ||
| 40 | +npm-debug.log | ||
| 41 | +yarn-error.log | ||
| 42 | + | ||
| 43 | +# fastlane | ||
| 44 | +# | ||
| 45 | +# It is recommended to not store the screenshots in the git repo. Instead, use fastlane to re-generate the | ||
| 46 | +# screenshots whenever they are needed. | ||
| 47 | +# For more information about the recommended setup visit: | ||
| 48 | +# https://docs.fastlane.tools/best-practices/source-control/ | ||
| 49 | + | ||
| 50 | +**/fastlane/report.xml | ||
| 51 | +**/fastlane/Preview.html | ||
| 52 | +**/fastlane/screenshots | ||
| 53 | +**/fastlane/test_output | ||
| 54 | + | ||
| 55 | +# Bundle artifact | ||
| 56 | +*.jsbundle | ||
| 57 | + | ||
| 58 | +# Ruby / CocoaPods | ||
| 59 | +/ios/Pods/ | ||
| 60 | +/vendor/bundle/ | ||
| 61 | + | ||
| 62 | +# Temporary files created by Metro to check the health of the file watcher | ||
| 63 | +.metro-health-check* | ||
| 64 | + | ||
| 65 | +# testing | ||
| 66 | +/coverage | ||
| @@ -0,0 +1,14 @@ | |||
| 1 | +/** | ||
| 2 | + * Copyright (c) 2025 Huawei Technologies Co., Ltd. | ||
| 3 | + * | ||
| 4 | + * This source code is licensed under the MIT license found in the | ||
| 5 | + * LICENSE-MIT file in the root directory of this source tree. | ||
| 6 | + */ | ||
| 7 | + | ||
| 8 | +module.exports = { | ||
| 9 | + arrowParens: 'avoid', | ||
| 10 | + bracketSameLine: true, | ||
| 11 | + bracketSpacing: false, | ||
| 12 | + singleQuote: true, | ||
| 13 | + trailingComma: 'all', | ||
| 14 | +}; | ||
| @@ -0,0 +1 @@ | |||
| 1 | +{} | ||
| @@ -0,0 +1,72 @@ | |||
| 1 | +/** | ||
| 2 | + * Copyright (c) 2025 Huawei Technologies Co., Ltd. | ||
| 3 | + * | ||
| 4 | + * This source code is licensed under the MIT license found in the | ||
| 5 | + * LICENSE-MIT file in the root directory of this source tree. | ||
| 6 | + */ | ||
| 7 | + | ||
| 8 | + | ||
| 9 | +import React, { useEffect, useRef, useState } from 'react'; | ||
| 10 | +import { StyleSheet, Text, View, Pressable, UIManager, findNodeHandle, Dimensions } from 'react-native'; | ||
| 11 | +import { QDGestureFloat, SampleAnyThreadTurboModule, SampleTurboModule } from 'third-party-library'; | ||
| 12 | +import SelectBoxApp from './src/SelectBoxApp' | ||
| 13 | + | ||
| 14 | +const ScreenHeight = Dimensions.get('window').height; | ||
| 15 | + | ||
| 16 | +const App = () => { | ||
| 17 | + const floatRef = useRef(null) | ||
| 18 | + const [addResult, setAddResult] = useState(0) | ||
| 19 | + const [powerResult, setPowerResult] = useState(0) | ||
| 20 | + useEffect(() => { | ||
| 21 | + const result1 = SampleTurboModule.add(2, 4); | ||
| 22 | + setAddResult(result1); | ||
| 23 | + SampleAnyThreadTurboModule.power(2, 4).then(result2 => { | ||
| 24 | + setPowerResult(result2); | ||
| 25 | + }); | ||
| 26 | + }, []) | ||
| 27 | + return ( | ||
| 28 | + <View style={styles.container}> | ||
| 29 | + <QDGestureFloat | ||
| 30 | + ref={floatRef} | ||
| 31 | + style={styles.container} | ||
| 32 | + stopPercent={0.5} | ||
| 33 | + stopPercentMax={0.75} | ||
| 34 | + onScroll={(event) => { | ||
| 35 | + console.log(event.nativeEvent.offsetY) | ||
| 36 | + }} | ||
| 37 | + > | ||
| 38 | + <View style={{ width: '100%', height: 1000, backgroundColor: 'yellow' }}> | ||
| 39 | + <Pressable onPress={() => { | ||
| 40 | + if (floatRef.current) { | ||
| 41 | + // RN向原生发送消息 | ||
| 42 | + UIManager.dispatchViewManagerCommand( | ||
| 43 | + findNodeHandle(floatRef.current), | ||
| 44 | + 'scrollTo', | ||
| 45 | + [ScreenHeight, true] | ||
| 46 | + ); | ||
| 47 | + } | ||
| 48 | + }}> | ||
| 49 | + <Text style={{ fontSize: 50, color: 'red' }}>点击滚到顶</Text> | ||
| 50 | + </Pressable> | ||
| 51 | + <Text style={{ backgroundColor: 'white' }}>2 + 4 = {addResult}, 2 ^ 4 = {powerResult}</Text> | ||
| 52 | + <SelectBoxApp /> | ||
| 53 | + </View> | ||
| 54 | + </QDGestureFloat> | ||
| 55 | + </View> | ||
| 56 | + ) | ||
| 57 | +} | ||
| 58 | + | ||
| 59 | +const styles = StyleSheet.create({ | ||
| 60 | + container: { | ||
| 61 | + flex: 1, | ||
| 62 | + }, | ||
| 63 | + title: { | ||
| 64 | + backgroundColor: 'green', | ||
| 65 | + color: 'white', | ||
| 66 | + fontSize: 20, | ||
| 67 | + padding: 8, | ||
| 68 | + textAlign: 'center' | ||
| 69 | + } | ||
| 70 | +}); | ||
| 71 | + | ||
| 72 | +export default App; | ||
| @@ -0,0 +1,9 @@ | |||
| 1 | +source 'https://rubygems.org' | ||
| 2 | + | ||
| 3 | +# You may use http://rbenv.org/ or https://rvm.io/ to install and use this version | ||
| 4 | +ruby ">= 2.6.10" | ||
| 5 | + | ||
| 6 | +# Cocoapods 1.15 introduced a bug which break the build. We will remove the upper | ||
| 7 | +# bound in the template on Cocoapods with next React Native release. | ||
| 8 | +gem 'cocoapods', '>= 1.13', '< 1.15' | ||
| 9 | +gem 'activesupport', '>= 6.1.7.5', '< 7.1.0' | ||
| @@ -0,0 +1,4 @@ | |||
| 1 | +{ | ||
| 2 | + "name": "app_name", | ||
| 3 | + "displayName": "tester" | ||
| 4 | +} | ||
| @@ -0,0 +1,10 @@ | |||
| 1 | +/** | ||
| 2 | + * Copyright (c) 2025 Huawei Technologies Co., Ltd. | ||
| 3 | + * | ||
| 4 | + * This source code is licensed under the MIT license found in the | ||
| 5 | + * LICENSE-MIT file in the root directory of this source tree. | ||
| 6 | + */ | ||
| 7 | + | ||
| 8 | +module.exports = { | ||
| 9 | + presets: ['module:@react-native/babel-preset'], | ||
| 10 | +}; | ||
| @@ -0,0 +1,14 @@ | |||
| 1 | +/** | ||
| 2 | + * Copyright (c) 2025 Huawei Technologies Co., Ltd. | ||
| 3 | + * | ||
| 4 | + * This source code is licensed under the MIT license found in the | ||
| 5 | + * LICENSE-MIT file in the root directory of this source tree. | ||
| 6 | + * | ||
| 7 | + * @format | ||
| 8 | + */ | ||
| 9 | + | ||
| 10 | +import { AppRegistry } from 'react-native'; | ||
| 11 | +import { name as appName } from './app.json'; | ||
| 12 | +import App from './App'; | ||
| 13 | + | ||
| 14 | +AppRegistry.registerComponent(appName, () => App); | ||
| @@ -0,0 +1,10 @@ | |||
| 1 | +/** | ||
| 2 | + * Copyright (c) 2025 Huawei Technologies Co., Ltd. | ||
| 3 | + * | ||
| 4 | + * This source code is licensed under the MIT license found in the | ||
| 5 | + * LICENSE-MIT file in the root directory of this source tree. | ||
| 6 | + */ | ||
| 7 | + | ||
| 8 | +module.exports = { | ||
| 9 | + preset: 'react-native', | ||
| 10 | +}; | ||
| @@ -0,0 +1,29 @@ | |||
| 1 | +/** | ||
| 2 | + * Copyright (c) 2025 Huawei Technologies Co., Ltd. | ||
| 3 | + * | ||
| 4 | + * This source code is licensed under the MIT license found in the | ||
| 5 | + * LICENSE-MIT file in the root directory of this source tree. | ||
| 6 | + */ | ||
| 7 | + | ||
| 8 | +const { mergeConfig, getDefaultConfig } = require('@react-native/metro-config'); | ||
| 9 | +const { createHarmonyMetroConfig } = require('@react-native-oh/react-native-harmony/metro.config'); | ||
| 10 | + | ||
| 11 | +/** | ||
| 12 | + * @type {import("metro-config").ConfigT} | ||
| 13 | + */ | ||
| 14 | +const config = { | ||
| 15 | + // 清理metro缓存 | ||
| 16 | + // resetCache: true, | ||
| 17 | + transformer: { | ||
| 18 | + getTransformOptions: async () => ({ | ||
| 19 | + transform: { | ||
| 20 | + experimentalImportSupport: false, | ||
| 21 | + inlineRequires: true, | ||
| 22 | + }, | ||
| 23 | + }), | ||
| 24 | + }, | ||
| 25 | +}; | ||
| 26 | + | ||
| 27 | +module.exports = mergeConfig(getDefaultConfig(__dirname), createHarmonyMetroConfig({ | ||
| 28 | + reactNativeHarmonyPackageName: '@react-native-oh/react-native-harmony', | ||
| 29 | +}), config); | ||
| @@ -0,0 +1,39 @@ | |||
| 1 | +{ | ||
| 2 | + "name": "ReactProject", | ||
| 3 | + "version": "0.0.1", | ||
| 4 | + "private": true, | ||
| 5 | + "scripts": { | ||
| 6 | + "lint": "eslint .", | ||
| 7 | + "start": "react-native start --reset-cache --client-logs", | ||
| 8 | + "dev": "react-native bundle-harmony --dev false --bundle-output ../NativeProject/entry/src/main/resources/rawfile/bundle.harmony.js" | ||
| 9 | + }, | ||
| 10 | + "dependencies": { | ||
| 11 | + "react": "18.3.1", | ||
| 12 | + "react-native": "0.77.1", | ||
| 13 | + "@react-native-oh/react-native-harmony": "file:../react-native-oh/react-native-oh-react-native-harmony-0.77.22.tgz", | ||
| 14 | + "react-native-performance": "^5.1.2", | ||
| 15 | + "third-party-library": "file:../third-party-library-sample/third-party-library-sample-1.0.0.tgz" | ||
| 16 | + }, | ||
| 17 | + "devDependencies": { | ||
| 18 | + "@react-native-community/cli": "15.0.1", | ||
| 19 | + "@react-native-oh/react-native-harmony-cli": "file:../react-native-oh/react-native-oh-react-native-harmony-cli-0.77.22.tgz", | ||
| 20 | + "@react-native/babel-preset": "0.77.1", | ||
| 21 | + "@babel/core": "^7.20.0", | ||
| 22 | + "@babel/preset-env": "^7.20.0", | ||
| 23 | + "@babel/runtime": "^7.20.0", | ||
| 24 | + "@react-native/eslint-config": "0.77.1", | ||
| 25 | + "@react-native/typescript-config": "0.77.1", | ||
| 26 | + "@react-native/metro-config": "0.77.1", | ||
| 27 | + "@types/react": "^18.0.24", | ||
| 28 | + "@types/react-test-renderer": "^18.0.0", | ||
| 29 | + "babel-jest": "^29.2.1", | ||
| 30 | + "eslint": "^8.19.0", | ||
| 31 | + "jest": "^29.2.1", | ||
| 32 | + "prettier": "^2.4.1", | ||
| 33 | + "react-test-renderer": "18.2.0", | ||
| 34 | + "typescript": "5.0.4" | ||
| 35 | + }, | ||
| 36 | + "engines": { | ||
| 37 | + "node": ">=16" | ||
| 38 | + } | ||
| 39 | +} | ||
| @@ -0,0 +1,86 @@ | |||
| 1 | +/** | ||
| 2 | + * Copyright (c) 2025 Huawei Technologies Co., Ltd. | ||
| 3 | + * | ||
| 4 | + * This source code is licensed under the MIT license found in the | ||
| 5 | + * LICENSE-MIT file in the root directory of this source tree. | ||
| 6 | + */ | ||
| 7 | + | ||
| 8 | + | ||
| 9 | +import React, { useRef, useState } from 'react'; | ||
| 10 | +import { | ||
| 11 | + Text, | ||
| 12 | + StyleSheet, | ||
| 13 | + Pressable, | ||
| 14 | + UIManager, | ||
| 15 | + findNodeHandle, | ||
| 16 | + View, | ||
| 17 | +} from 'react-native'; | ||
| 18 | +import { SelectBox } from 'third-party-library'; | ||
| 19 | + | ||
| 20 | +const DATA = [ | ||
| 21 | + { | ||
| 22 | + id: 0, | ||
| 23 | + text: '选项1', | ||
| 24 | + }, | ||
| 25 | + { | ||
| 26 | + id: 1, | ||
| 27 | + text: '选项2', | ||
| 28 | + }, | ||
| 29 | + { | ||
| 30 | + id: 2, | ||
| 31 | + text: '选项3', | ||
| 32 | + }, | ||
| 33 | +]; | ||
| 34 | + | ||
| 35 | +const App = () => { | ||
| 36 | + const [value, setValue] = useState([]) | ||
| 37 | + const [mutil, setMutil] = useState(false) | ||
| 38 | + const boxRef = useRef(null) | ||
| 39 | + | ||
| 40 | + return ( | ||
| 41 | + <View style={styles.container}> | ||
| 42 | + <Pressable onPress={() => { | ||
| 43 | + if (boxRef.current) { | ||
| 44 | + // RN向原生发送消息 | ||
| 45 | + UIManager.dispatchViewManagerCommand( | ||
| 46 | + findNodeHandle(boxRef.current), | ||
| 47 | + 'emitNativeEvent', | ||
| 48 | + [!mutil] | ||
| 49 | + ); | ||
| 50 | + setMutil(!mutil) | ||
| 51 | + } | ||
| 52 | + }}> | ||
| 53 | + <Text style={styles.title}>{`现在是${mutil ? '多选' : '单选'}`}</Text> | ||
| 54 | + </Pressable> | ||
| 55 | + <SelectBox | ||
| 56 | + ref={boxRef} | ||
| 57 | + style={{ | ||
| 58 | + flex: 1 | ||
| 59 | + }} | ||
| 60 | + value={value} | ||
| 61 | + data={DATA} | ||
| 62 | + onChange={(event: any) => { | ||
| 63 | + setValue(event.nativeEvent.value) | ||
| 64 | + console.log(event.nativeEvent) | ||
| 65 | + }} | ||
| 66 | + /> | ||
| 67 | + </View> | ||
| 68 | + ); | ||
| 69 | +}; | ||
| 70 | + | ||
| 71 | +const styles = StyleSheet.create({ | ||
| 72 | + container: { | ||
| 73 | + backgroundColor: 'white', | ||
| 74 | + height: 250, | ||
| 75 | + justifyContent: 'center', | ||
| 76 | + }, | ||
| 77 | + title: { | ||
| 78 | + backgroundColor: 'green', | ||
| 79 | + color: 'white', | ||
| 80 | + fontSize: 20, | ||
| 81 | + padding: 8, | ||
| 82 | + textAlign: 'center' | ||
| 83 | + } | ||
| 84 | +}); | ||
| 85 | + | ||
| 86 | +export default App; | ||
| @@ -0,0 +1,3 @@ | |||
| 1 | +{ | ||
| 2 | + "extends": "@react-native/typescript-config/tsconfig.json" | ||
| 3 | +} | ||
The file is empty
| @@ -0,0 +1,4 @@ | |||
| 1 | +*.tgz | ||
| 2 | +node_modules | ||
| 3 | +harmony/library/src/main/cpp/generated | ||
| 4 | +harmony/library/src/main/ets/generated | ||
Binary files do not support preview
| @@ -0,0 +1,6 @@ | |||
| 1 | +/node_modules | ||
| 2 | +/oh_modules | ||
| 3 | +/.preview | ||
| 4 | +/build | ||
| 5 | +/.cxx | ||
| 6 | +/.test | ||
| @@ -0,0 +1,17 @@ | |||
| 1 | +/** | ||
| 2 | + * Use these variables when you tailor your ArkTS code. They must be of the const type. | ||
| 3 | + */ | ||
| 4 | +export const HAR_VERSION = '1.0.0'; | ||
| 5 | +export const BUILD_MODE_NAME = 'debug'; | ||
| 6 | +export const DEBUG = true; | ||
| 7 | +export const TARGET_NAME = 'default'; | ||
| 8 | + | ||
| 9 | +/** | ||
| 10 | + * BuildProfile Class is used only for compatibility purposes. | ||
| 11 | + */ | ||
| 12 | +export default class BuildProfile { | ||
| 13 | + static readonly HAR_VERSION = HAR_VERSION; | ||
| 14 | + static readonly BUILD_MODE_NAME = BUILD_MODE_NAME; | ||
| 15 | + static readonly DEBUG = DEBUG; | ||
| 16 | + static readonly TARGET_NAME = TARGET_NAME; | ||
| 17 | +} | ||
| @@ -0,0 +1,8 @@ | |||
| 1 | +/** | ||
| 2 | + * Copyright (c) 2025 Huawei Technologies Co., Ltd. | ||
| 3 | + * | ||
| 4 | + * This source code is licensed under the MIT license found in the | ||
| 5 | + * LICENSE file in the root directory of this source tree. | ||
| 6 | + */ | ||
| 7 | + | ||
| 8 | +export { ThirdPartyLibrarySamplePackage as default } from './src/main/ets/ThirdPartyLibrarySamplePackage'; | ||
| @@ -0,0 +1,11 @@ | |||
| 1 | +{ | ||
| 2 | + "apiType": "stageMode", | ||
| 3 | + "targets": [ | ||
| 4 | + { | ||
| 5 | + "name": "default" | ||
| 6 | + }, | ||
| 7 | + { | ||
| 8 | + "name": "ohosTest" | ||
| 9 | + } | ||
| 10 | + ] | ||
| 11 | +} | ||
| @@ -0,0 +1,13 @@ | |||
| 1 | +/** | ||
| 2 | + * Copyright (c) 2025 Huawei Technologies Co., Ltd. | ||
| 3 | + * | ||
| 4 | + * This source code is licensed under the MIT license found in the | ||
| 5 | + * LICENSE-MIT file in the root directory of this source tree. | ||
| 6 | + */ | ||
| 7 | + | ||
| 8 | +import { harTasks } from '@ohos/hvigor-ohos-plugin'; | ||
| 9 | + | ||
| 10 | +export default { | ||
| 11 | + system: harTasks, /* Built-in plugin of Hvigor. It cannot be modified. */ | ||
| 12 | + plugins: [] /* Custom plugin to extend the functionality of Hvigor. */ | ||
| 13 | +} | ||
| @@ -0,0 +1,11 @@ | |||
| 1 | +{ | ||
| 2 | + "name": "@rnoh/third-party-library-sample", | ||
| 3 | + "version": "1.0.0", | ||
| 4 | + "description": "Please describe the basic information.", | ||
| 5 | + "main": "Index.ets", | ||
| 6 | + "author": "", | ||
| 7 | + "license": "Apache-2.0", | ||
| 8 | + "dependencies": { | ||
| 9 | + "@rnoh/react-native-openharmony": "../ReactProject/node_modules/@react-native-oh/react-native-harmony/react_native_openharmony.har" | ||
| 10 | + } | ||
| 11 | +} | ||
| @@ -0,0 +1,18 @@ | |||
| 1 | +# Copyright (c) 2025 Huawei Technologies Co., Ltd. | ||
| 2 | +# | ||
| 3 | +# This source code is licensed under the MIT license found in the | ||
| 4 | +# LICENSE-MIT file in the root directory of this source tree. | ||
| 5 | + | ||
| 6 | +cmake_minimum_required(VERSION 3.4.1) | ||
| 7 | +set(CMAKE_VERBOSE_MAKEFILE on) | ||
| 8 | + | ||
| 9 | +set(third_party_library_sample_generated_dir "${CMAKE_CURRENT_SOURCE_DIR}/generated") | ||
| 10 | +file(GLOB_RECURSE third_party_library_sample_generated_SRC "${third_party_library_sample_generated_dir}/**/*.cpp") | ||
| 11 | + | ||
| 12 | +file(GLOB third_party_library_sample_SRC CONFIGURE_DEPENDS *.cpp) | ||
| 13 | + | ||
| 14 | +add_library(third_party_library SHARED ${third_party_library_sample_SRC} ${third_party_library_sample_generated_SRC}) | ||
| 15 | +target_include_directories(third_party_library PUBLIC | ||
| 16 | + ${CMAKE_CURRENT_SOURCE_DIR} | ||
| 17 | + ${third_party_library_sample_generated_dir}) | ||
| 18 | +target_link_libraries(third_party_library PUBLIC rnoh) | ||
| @@ -0,0 +1,91 @@ | |||
| 1 | +/** | ||
| 2 | + * Copyright (c) 2025 Huawei Technologies Co., Ltd. | ||
| 3 | + * | ||
| 4 | + * This source code is licensed under the MIT license found in the | ||
| 5 | + * LICENSE-MIT file in the root directory of this source tree. | ||
| 6 | + */ | ||
| 7 | + | ||
| 8 | +#pragma once | ||
| 9 | + | ||
| 10 | +#include "QDGestureFloatComponentInstance.h" | ||
| 11 | + | ||
| 12 | +namespace rnoh { | ||
| 13 | + | ||
| 14 | +QDGestureFloatComponentInstance::QDGestureFloatComponentInstance( | ||
| 15 | + Context context) | ||
| 16 | + : Super(std::move(context)) { | ||
| 17 | + m_scrollNode.setScrollNodeDelegate(this); | ||
| 18 | + getLocalRootArkUINode().insertChild(m_scrollNode, 0); | ||
| 19 | + m_scrollNode.insertChild(m_scrollContentNode); | ||
| 20 | + m_scrollContentNode.insertChild(m_transparentNode, 0); | ||
| 21 | + m_scrollContentNode.insertChild(m_contentNode, 1); | ||
| 22 | + | ||
| 23 | + m_scrollNode.setScrollBarDisplayMode( | ||
| 24 | + ArkUI_ScrollBarDisplayMode::ARKUI_SCROLL_BAR_DISPLAY_MODE_OFF); | ||
| 25 | +} | ||
| 26 | + | ||
| 27 | +facebook::react::Point rnoh::QDGestureFloatComponentInstance::getCurrentOffset() | ||
| 28 | + const { | ||
| 29 | + auto offset = m_scrollNode.getScrollOffset(); | ||
| 30 | + offset.y -= m_height; | ||
| 31 | + return offset; | ||
| 32 | +} | ||
| 33 | + | ||
| 34 | +StackNode& QDGestureFloatComponentInstance::getLocalRootArkUINode() { | ||
| 35 | + return m_scrollContainerNode; | ||
| 36 | +} | ||
| 37 | + | ||
| 38 | +void QDGestureFloatComponentInstance::onPropsChanged( | ||
| 39 | + SharedConcreteProps const& props) { | ||
| 40 | + if (props->stopPercent) { | ||
| 41 | + m_stopPercent = props->stopPercent; | ||
| 42 | + } | ||
| 43 | + if (props->stopPercentMax) { | ||
| 44 | + m_stopPercentMax = props->stopPercentMax; | ||
| 45 | + } | ||
| 46 | +}; | ||
| 47 | + | ||
| 48 | +void QDGestureFloatComponentInstance::onChildInserted( | ||
| 49 | + ComponentInstance::Shared const& childComponentInstance, | ||
| 50 | + std::size_t index) { | ||
| 51 | + CppComponentInstance::onChildInserted(childComponentInstance, index); | ||
| 52 | + m_contentNode.insertChild( | ||
| 53 | + childComponentInstance->getLocalRootArkUINode(), index); | ||
| 54 | + if (!m_isInit) { | ||
| 55 | + auto layoutMetrics = getLayoutMetrics(); | ||
| 56 | + m_width = layoutMetrics.frame.size.width; | ||
| 57 | + m_height = layoutMetrics.frame.size.height; | ||
| 58 | + m_transparentNode.setSize(facebook::react::Size{m_width, m_height}); | ||
| 59 | + m_scrollNode.scrollTo(0, m_height * m_stopPercent, false); | ||
| 60 | + } | ||
| 61 | +} | ||
| 62 | + | ||
| 63 | +void QDGestureFloatComponentInstance::onChildRemoved( | ||
| 64 | + ComponentInstance::Shared const& childComponentInstance) { | ||
| 65 | + CppComponentInstance::onChildRemoved(childComponentInstance); | ||
| 66 | + m_contentNode.removeChild(childComponentInstance->getLocalRootArkUINode()); | ||
| 67 | +} | ||
| 68 | + | ||
| 69 | +void QDGestureFloatComponentInstance::onScroll() { | ||
| 70 | + auto offsetY = m_scrollNode.getScrollOffset().y; | ||
| 71 | + facebook::react::QDGestureFloatEventEmitter::OnScroll event = {offsetY}; | ||
| 72 | + m_eventEmitter->onScroll(event); | ||
| 73 | +} | ||
| 74 | + | ||
| 75 | +void QDGestureFloatComponentInstance::onScrollStop() { | ||
| 76 | + auto y = m_scrollNode.getScrollOffset().y; | ||
| 77 | + if (y <= m_height && y > m_height * m_stopPercentMax) { | ||
| 78 | + m_scrollNode.scrollTo(0, m_height, true); | ||
| 79 | + } else if ( | ||
| 80 | + y < m_height * m_stopPercent || | ||
| 81 | + (y <= m_height && y > m_height * m_stopPercent)) { | ||
| 82 | + m_scrollNode.scrollTo(0, m_height * m_stopPercent, true); | ||
| 83 | + } | ||
| 84 | +} | ||
| 85 | + | ||
| 86 | +void QDGestureFloatComponentInstance::onScrollToCommand( | ||
| 87 | + float offsetY, | ||
| 88 | + bool animated) { | ||
| 89 | + m_scrollNode.scrollTo(0, offsetY, animated); | ||
| 90 | +} | ||
| 91 | +} // namespace rnoh | ||
| @@ -0,0 +1,60 @@ | |||
| 1 | +/** | ||
| 2 | + * Copyright (c) 2025 Huawei Technologies Co., Ltd. | ||
| 3 | + * | ||
| 4 | + * This source code is licensed under the MIT license found in the | ||
| 5 | + * LICENSE-MIT file in the root directory of this source tree. | ||
| 6 | + */ | ||
| 7 | + | ||
| 8 | +#pragma once | ||
| 9 | + | ||
| 10 | +#include "RNOH/arkui/ColumnNode.h" | ||
| 11 | +#include "RNOH/arkui/ScrollNode.h" | ||
| 12 | +#include "RNOH/arkui/StackNode.h" | ||
| 13 | +#include "RNOH/generated/components/BaseQDGestureFloatComponentInstance.h" | ||
| 14 | + | ||
| 15 | +namespace rnoh { | ||
| 16 | +class QDGestureFloatComponentInstance | ||
| 17 | + : public BaseQDGestureFloatComponentInstance, | ||
| 18 | + ScrollNodeDelegate { | ||
| 19 | + using Super = BaseQDGestureFloatComponentInstance; | ||
| 20 | + | ||
| 21 | + private: | ||
| 22 | + // 根容器 | ||
| 23 | + StackNode m_scrollContainerNode; | ||
| 24 | + // scroll 组件 | ||
| 25 | + ScrollNode m_scrollNode; | ||
| 26 | + // scroll 内容 | ||
| 27 | + ColumnNode m_scrollContentNode; | ||
| 28 | + // 上方透明区域 | ||
| 29 | + StackNode m_transparentNode; | ||
| 30 | + // 内容区域 | ||
| 31 | + StackNode m_contentNode; | ||
| 32 | + | ||
| 33 | + // 组件宽高 | ||
| 34 | + float m_width; | ||
| 35 | + float m_height; | ||
| 36 | + bool m_isInit = false; | ||
| 37 | + // 停止百分比、吸顶百分比 | ||
| 38 | + float m_stopPercent = 0.75f; | ||
| 39 | + float m_stopPercentMax = 0.85f; | ||
| 40 | + | ||
| 41 | + public: | ||
| 42 | + explicit QDGestureFloatComponentInstance(Context context); | ||
| 43 | + | ||
| 44 | + StackNode& getLocalRootArkUINode(); | ||
| 45 | + | ||
| 46 | + void onPropsChanged(SharedConcreteProps const& props); | ||
| 47 | + | ||
| 48 | + void onChildInserted( | ||
| 49 | + ComponentInstance::Shared const& childComponentInstance, | ||
| 50 | + std::size_t index) override; | ||
| 51 | + void onChildRemoved( | ||
| 52 | + ComponentInstance::Shared const& childComponentInstance) override; | ||
| 53 | + | ||
| 54 | + facebook::react::Point getCurrentOffset() const override; | ||
| 55 | + | ||
| 56 | + void onScroll() override; | ||
| 57 | + void onScrollStop() override; | ||
| 58 | + void onScrollToCommand(float offsetY, bool animated) override; | ||
| 59 | +}; | ||
| 60 | +} // namespace rnoh | ||
| @@ -0,0 +1,25 @@ | |||
| 1 | +/** | ||
| 2 | + * Copyright (c) 2025 Huawei Technologies Co., Ltd. | ||
| 3 | + * | ||
| 4 | + * This source code is licensed under the MIT license found in the | ||
| 5 | + * LICENSE-MIT file in the root directory of this source tree. | ||
| 6 | + */ | ||
| 7 | + | ||
| 8 | +#include "ThirdPartyLibrarySamplePackage.h" | ||
| 9 | +#include "QDGestureFloatComponentInstance.h" | ||
| 10 | +#include "RNOH/RNInstanceCAPI.h" | ||
| 11 | +#include "RNOH/generated/BaseThirdPartyLibrarySamplePackage.h" | ||
| 12 | +#include "RNOHCorePackage/ComponentBinders/ViewComponentJSIBinder.h" | ||
| 13 | +#include "RNOHCorePackage/ComponentBinders/ViewComponentNapiBinder.h" | ||
| 14 | + | ||
| 15 | +using namespace facebook; | ||
| 16 | + | ||
| 17 | +namespace rnoh { | ||
| 18 | +ComponentInstance::Shared ThirdPartyLibrarySamplePackage::createComponentInstance( | ||
| 19 | + const ComponentInstance::Context& ctx) { | ||
| 20 | + if (ctx.componentName == "QDGestureFloat") { | ||
| 21 | + return std::make_shared<QDGestureFloatComponentInstance>(std::move(ctx)); | ||
| 22 | + } | ||
| 23 | + return nullptr; | ||
| 24 | +}; | ||
| 25 | +} // namespace rnoh | ||
| @@ -0,0 +1,25 @@ | |||
| 1 | +/** | ||
| 2 | + * Copyright (c) 2025 Huawei Technologies Co., Ltd. | ||
| 3 | + * | ||
| 4 | + * This source code is licensed under the MIT license found in the | ||
| 5 | + * LICENSE-MIT file in the root directory of this source tree. | ||
| 6 | + */ | ||
| 7 | + | ||
| 8 | +#pragma once | ||
| 9 | + | ||
| 10 | +#include "RNOH/Package.h" | ||
| 11 | +#include "RNOH/generated/BaseThirdPartyLibrarySamplePackage.h" | ||
| 12 | + | ||
| 13 | +namespace rnoh { | ||
| 14 | +class ThirdPartyLibrarySamplePackage | ||
| 15 | + : public BaseThirdPartyLibrarySamplePackage { | ||
| 16 | + using Super = BaseThirdPartyLibrarySamplePackage; | ||
| 17 | + | ||
| 18 | + public: | ||
| 19 | + explicit ThirdPartyLibrarySamplePackage(Package::Context ctx) | ||
| 20 | + : BaseThirdPartyLibrarySamplePackage(ctx) {} | ||
| 21 | + | ||
| 22 | + ComponentInstance::Shared createComponentInstance( | ||
| 23 | + const ComponentInstance::Context& ctx) override; | ||
| 24 | +}; | ||
| 25 | +} // namespace rnoh | ||
| @@ -0,0 +1,20 @@ | |||
| 1 | +/** | ||
| 2 | + * Copyright (c) 2025 Huawei Technologies Co., Ltd. | ||
| 3 | + * | ||
| 4 | + * This source code is licensed under the MIT license found in the | ||
| 5 | + * LICENSE-MIT file in the root directory of this source tree. | ||
| 6 | + */ | ||
| 7 | + | ||
| 8 | +import { AnyThreadTurboModule } from "@rnoh/react-native-openharmony"; | ||
| 9 | +import { TM } from "./generated/ts" | ||
| 10 | + | ||
| 11 | +export class SampleAnyThreadTurboModule extends AnyThreadTurboModule implements TM.SampleAnyThreadTurboModule.Spec { | ||
| 12 | + public static readonly NAME = TM.SampleAnyThreadTurboModule.NAME; | ||
| 13 | + | ||
| 14 | + power(a: number, b: number): Promise<number> { | ||
| 15 | + this.ctx.logger.info("AutoLinkSample.AnyThreadTurboModule.power"); | ||
| 16 | + return new Promise(resolve => { | ||
| 17 | + setTimeout(() => resolve(Math.pow(a, b)), 3000) | ||
| 18 | + }) | ||
| 19 | + } | ||
| 20 | +} | ||
| @@ -0,0 +1,18 @@ | |||
| 1 | +/** | ||
| 2 | + * Copyright (c) 2025 Huawei Technologies Co., Ltd. | ||
| 3 | + * | ||
| 4 | + * This source code is licensed under the MIT license found in the | ||
| 5 | + * LICENSE-MIT file in the root directory of this source tree. | ||
| 6 | + */ | ||
| 7 | + | ||
| 8 | +import { EtsUITurboModule } from '@rnoh/react-native-openharmony/ets'; | ||
补充copyright ![]() ![]() | |||
| 9 | +import { TM } from "./generated/ts" | ||
| 10 | + | ||
| 11 | +export class SampleTurboModule extends EtsUITurboModule implements TM.SampleTurboModule.Spec { | ||
| 12 | + public static readonly NAME = TM.SampleTurboModule.NAME; | ||
| 13 | + | ||
| 14 | + add(a: number, b: number): number { | ||
| 15 | + this.ctx.logger.info("AutoLinkSample.SampleTurboModule.add"); | ||
| 16 | + return a + b; | ||
| 17 | + } | ||
| 18 | +} | ||
Adocs/Samples/AutolinkingSample/third-party-library-sample/harmony/library/src/main/ets/SelectBox.ets+132-0
| @@ -0,0 +1,132 @@ | |||
| 1 | +/** | ||
| 2 | + * Copyright (c) 2025 Huawei Technologies Co., Ltd. | ||
| 3 | + * | ||
| 4 | + * This source code is licensed under the MIT license found in the | ||
| 5 | + * LICENSE-MIT file in the root directory of this source tree. | ||
| 6 | + */ | ||
| 7 | + | ||
| 8 | +import { RNOHContext, RNViewBase } from '@rnoh/react-native-openharmony'; | ||
| 9 | +import { RNC } from "./generated"; | ||
| 10 | + | ||
| 11 | +let nextKey = 0; | ||
| 12 | + | ||
| 13 | +@Observed | ||
| 14 | +class SelectItems { | ||
| 15 | + key: number; | ||
| 16 | + id: number; | ||
| 17 | + text: string; | ||
| 18 | + selected: boolean; | ||
| 19 | + | ||
| 20 | + constructor(id: number, text: string, selected: boolean) { | ||
| 21 | + this.key = nextKey++; | ||
| 22 | + this.id = id; | ||
| 23 | + this.text = text; | ||
| 24 | + this.selected = selected; | ||
| 25 | + } | ||
| 26 | +} | ||
| 27 | + | ||
| 28 | +@Component | ||
| 29 | +export struct SelectBox { | ||
| 30 | + public static readonly NAME = RNC.SelectBox.NAME; | ||
| 31 | + public ctx!: RNOHContext; | ||
| 32 | + public tag: number = 0; | ||
| 33 | + @State descriptorWrapper: RNC.SelectBox.DescriptorWrapper = {} as RNC.SelectBox.DescriptorWrapper; | ||
| 34 | + @State data: SelectItems[] = []; | ||
| 35 | + @State mutil: boolean = false; | ||
| 36 | + private eventEmitter: RNC.SelectBox.EventEmitter | undefined = undefined; | ||
| 37 | + private cleanUpCallbacks: (() => void)[] = []; | ||
| 38 | + | ||
| 39 | + aboutToAppear() { | ||
| 40 | + this.eventEmitter = new RNC.SelectBox.EventEmitter(this.ctx.rnInstance, this.tag); | ||
| 41 | + this.onDescriptorWrapperChange(this.ctx.descriptorRegistry.findDescriptorWrapperByTag<RNC.SelectBox.DescriptorWrapper>(this.tag)!); | ||
| 42 | + this.cleanUpCallbacks.push(this.ctx.descriptorRegistry.subscribeToDescriptorChanges(this.tag, | ||
| 43 | + (descriptor) => { | ||
| 44 | + this.onDescriptorWrapperChange(new RNC.SelectBox.DescriptorWrapper(descriptor)); | ||
| 45 | + } | ||
| 46 | + )) | ||
| 47 | + this.cleanUpCallbacks.push(new RNC.SelectBox.CommandReceiver(this.ctx.componentCommandReceiver, | ||
| 48 | + this.tag).subscribe("emitNativeEvent", (argv) => { | ||
| 49 | + console.log(`收到 RN 传来的消息 ================ ${JSON.stringify(argv)}`); | ||
| 50 | + this.mutil = argv[0] || false; | ||
| 51 | + })) | ||
| 52 | + } | ||
| 53 | + | ||
| 54 | + private onDescriptorWrapperChange(descriptorWrapper: RNC.SelectBox.DescriptorWrapper) { | ||
| 55 | + this.descriptorWrapper = descriptorWrapper; | ||
| 56 | + this.data = []; | ||
| 57 | + const data = this.descriptorWrapper.props.data; | ||
| 58 | + const value = this.descriptorWrapper.props.value; | ||
| 59 | + for (const item of data) { | ||
| 60 | + this.data.push( | ||
| 61 | + new SelectItems(item.id, item.text, value.includes(item.id)) | ||
| 62 | + ) | ||
| 63 | + } | ||
| 64 | + } | ||
| 65 | + | ||
| 66 | + aboutToDisappear() { | ||
| 67 | + this.cleanUpCallbacks.forEach(cb => cb()); | ||
| 68 | + } | ||
| 69 | + | ||
| 70 | + build() { | ||
| 71 | + RNViewBase({ ctx: this.ctx, tag: this.tag }) { | ||
| 72 | + Column() { | ||
| 73 | + ForEach(this.data, (item: SelectItems) => { | ||
| 74 | + SelectItem({ | ||
| 75 | + item: item, | ||
| 76 | + onSelect: (idx: number) => { | ||
| 77 | + for (const tmp of this.data) { | ||
| 78 | + if (tmp.id === idx) { | ||
| 79 | + tmp.selected = !tmp.selected; | ||
| 80 | + } else if (!this.mutil) { | ||
| 81 | + tmp.selected = false; | ||
| 82 | + } | ||
| 83 | + } | ||
| 84 | + } | ||
| 85 | + }) | ||
| 86 | + }, (item: SelectItems) => item.key.toString()) | ||
| 87 | + Button("确定") | ||
| 88 | + .onClick(() => { | ||
| 89 | + const value = this.data | ||
| 90 | + .filter((item: SelectItems) => item.selected) | ||
| 91 | + .map((item: SelectItems) => item.id) | ||
| 92 | + // 发送事件方式[1] | ||
| 93 | + // this.ctx.rnInstance.emitComponentEvent(this.tag, "change", { value }) | ||
| 94 | + // 发送事件方式[2] | ||
| 95 | + this.eventEmitter!.emit("change", { | ||
| 96 | + value, | ||
| 97 | + }) | ||
| 98 | + }) | ||
| 99 | + } | ||
| 100 | + .height("100%") | ||
| 101 | + } | ||
| 102 | + } | ||
| 103 | +} | ||
| 104 | + | ||
| 105 | +@Component | ||
| 106 | +struct SelectItem { | ||
| 107 | + @ObjectLink item: SelectItems; | ||
| 108 | + onSelect?: (id: number) => void; | ||
| 109 | + | ||
| 110 | + build() { | ||
| 111 | + Row() { | ||
| 112 | + Text(this.item.text) | ||
| 113 | + .fontColor('#0F294D') | ||
| 114 | + .fontSize(18) | ||
| 115 | + .layoutWeight(1) | ||
| 116 | + | ||
| 117 | + Text('选中') | ||
| 118 | + .fontColor('#FF287DFA') | ||
| 119 | + .fontSize(20) | ||
| 120 | + .visibility(this.item.selected ? Visibility.Visible : Visibility.Hidden) | ||
| 121 | + } | ||
| 122 | + .padding({ | ||
| 123 | + top: 24, | ||
| 124 | + left: 24, | ||
| 125 | + right: 24 | ||
| 126 | + }) | ||
| 127 | + .width("100%") | ||
| 128 | + .onClick(() => { | ||
| 129 | + this.onSelect?.(this.item.id) | ||
| 130 | + }) | ||
| 131 | + } | ||
| 132 | +} | ||
| @@ -0,0 +1,50 @@ | |||
| 1 | +/** | ||
| 2 | + * Copyright (c) 2025 Huawei Technologies Co., Ltd. | ||
| 3 | + * | ||
| 4 | + * This source code is licensed under the MIT license found in the | ||
| 5 | + * LICENSE-MIT file in the root directory of this source tree. | ||
| 6 | + */ | ||
| 7 | + | ||
| 8 | +import { | ||
补充copyright ![]() ![]() | |||
| 9 | + RNOHPackage, | ||
| 10 | + UITurboModuleContext, | ||
| 11 | + ComponentBuilderContext, | ||
| 12 | + AnyThreadTurboModuleContext, | ||
| 13 | + AnyThreadTurboModule, | ||
| 14 | + UITurboModule, | ||
| 15 | +} from '@rnoh/react-native-openharmony'; | ||
| 16 | +import type { | ||
| 17 | + DescriptorWrapperFactoryByDescriptorTypeCtx, | ||
| 18 | + DescriptorWrapperFactoryByDescriptorType | ||
| 19 | +} from '@rnoh/react-native-openharmony/ts'; | ||
| 20 | +import { RNC } from "./generated/ts"; | ||
| 21 | +import { SelectBox } from './SelectBox'; | ||
| 22 | +import { SampleTurboModule } from './SampleTurboModule'; | ||
| 23 | +import { SampleAnyThreadTurboModule } from './SampleAnyThreadTurboModule'; | ||
| 24 | + | ||
| 25 | +@Builder | ||
| 26 | +function buildSelectBox(ctx: ComponentBuilderContext) { | ||
| 27 | + SelectBox({ ctx: ctx.rnComponentContext, tag: ctx.tag, }) | ||
| 28 | +} | ||
| 29 | + | ||
| 30 | +export class ThirdPartyLibrarySamplePackage extends RNOHPackage { | ||
| 31 | + createDescriptorWrapperFactoryByDescriptorType(ctx: DescriptorWrapperFactoryByDescriptorTypeCtx): DescriptorWrapperFactoryByDescriptorType { | ||
| 32 | + const result: DescriptorWrapperFactoryByDescriptorType = {} | ||
| 33 | + result[RNC.SelectBox.NAME] = (ctx) => new RNC.SelectBox.DescriptorWrapper(ctx.descriptor) | ||
| 34 | + return result | ||
| 35 | + } | ||
| 36 | + | ||
| 37 | + override getUITurboModuleFactoryByNameMap(): Map<string, (ctx: UITurboModuleContext) => UITurboModule | null> { | ||
| 38 | + return new Map<string, ((ctx: UITurboModuleContext) => UITurboModule)>() | ||
| 39 | + .set(SampleTurboModule.NAME, (ctx) => new SampleTurboModule(ctx)) | ||
| 40 | + } | ||
| 41 | + | ||
| 42 | + override getAnyThreadTurboModuleFactoryByNameMap(): Map<string, (ctx: AnyThreadTurboModuleContext) => AnyThreadTurboModule | null> { | ||
| 43 | + return new Map<string, ((ctx: AnyThreadTurboModuleContext) => AnyThreadTurboModule)>() | ||
| 44 | + .set(SampleAnyThreadTurboModule.NAME, (ctx) => new SampleAnyThreadTurboModule(ctx)) | ||
| 45 | + } | ||
| 46 | + | ||
| 47 | + createWrappedCustomRNComponentBuilderByComponentNameMap(): Map<string, WrappedBuilder<[ComponentBuilderContext]>> { | ||
| 48 | + return new Map().set(SelectBox.NAME, wrapBuilder(buildSelectBox)) | ||
| 49 | + } | ||
| 50 | +} | ||
Adocs/Samples/AutolinkingSample/third-party-library-sample/harmony/library/src/main/module.json5+11-0
| @@ -0,0 +1,11 @@ | |||
| 1 | +{ | ||
| 2 | + "module": { | ||
| 3 | + "name": "library", | ||
| 4 | + "type": "har", | ||
| 5 | + "deviceTypes": [ | ||
| 6 | + "default", | ||
| 7 | + "tablet", | ||
| 8 | + "2in1" | ||
| 9 | + ] | ||
| 10 | + } | ||
| 11 | +} | ||
| @@ -0,0 +1,8 @@ | |||
| 1 | +{ | ||
| 2 | + "string": [ | ||
| 3 | + { | ||
| 4 | + "name": "page_show", | ||
| 5 | + "value": "page from package" | ||
| 6 | + } | ||
| 7 | + ] | ||
| 8 | +} | ||
| @@ -0,0 +1,15 @@ | |||
| 1 | +/** | ||
| 2 | + * Copyright (c) 2025 Huawei Technologies Co., Ltd. | ||
| 3 | + * | ||
| 4 | + * This source code is licensed under the MIT license found in the | ||
| 5 | + * LICENSE file in the root directory of this source tree. | ||
| 6 | + */ | ||
| 7 | +import NativeSampleTurboModule from "./src/specs/turbo-modules/SampleTurboModule"; | ||
| 8 | +import NativeSampleAnyThreadTurboModule from "./src/specs/turbo-modules/SampleAnyThreadTurboModule"; | ||
| 9 | +import SelectBoxNativeComponent from "./src/specs/arkts-components/SelectBox"; | ||
| 10 | +import QDGestureFloatNativeComponent from "./src/specs/cpp-components/QDGestureFloatNativeComponent" | ||
| 11 | + | ||
| 12 | +export const SampleTurboModule = NativeSampleTurboModule; | ||
| 13 | +export const SampleAnyThreadTurboModule = NativeSampleAnyThreadTurboModule; | ||
| 14 | +export const SelectBox = SelectBoxNativeComponent; | ||
| 15 | +export const QDGestureFloat = QDGestureFloatNativeComponent; | ||
| @@ -0,0 +1,30 @@ | |||
| 1 | +{ | ||
| 2 | + "name": "third-party-library-sample", | ||
| 3 | + "version": "1.0.0", | ||
| 4 | + "description": "Third party library sample package of autolinking in harmony", | ||
| 5 | + "main": "index.ts", | ||
| 6 | + "scripts": { | ||
| 7 | + "codegen-lib": "react-native codegen-lib-harmony --no-safety-check --npm-package-name third-party-library-sample --cpp-output-path ./harmony/library/src/main/cpp/generated --ets-output-path ./harmony/library/src/main/ets/generated --cpp-components-spec-paths ./src/specs/cpp-components --turbo-modules-spec-paths ./src/specs/turbo-modules --arkts-components-spec-paths ./src/specs/arkts-components" | ||
| 8 | + }, | ||
| 9 | + "keywords": [], | ||
| 10 | + "author": "", | ||
| 11 | + "license": "ISC", | ||
| 12 | + "harmony": { | ||
| 13 | + "alias": "third-party-library-sample", | ||
| 14 | + "autolinking": { | ||
| 15 | + "cmakeLibraryTargetName": "third_party_library" | ||
| 16 | + } | ||
| 17 | + }, | ||
| 18 | + "files": [ | ||
| 19 | + "index.ts", | ||
| 20 | + "src/*", | ||
| 21 | + "harmony/*" | ||
| 22 | + ], | ||
| 23 | + "devDependencies": { | ||
| 24 | + "@react-native-community/cli": "15.0.1", | ||
| 25 | + "@react-native-oh/react-native-harmony-cli": "file:../react-native-oh/react-native-oh-react-native-harmony-cli-0.77.22.tgz", | ||
| 26 | + "react": "18.3.1", | ||
| 27 | + "react-native": "0.77.1" | ||
| 28 | + }, | ||
| 29 | + "dependencies": {} | ||
| 30 | +} | ||
Adocs/Samples/AutolinkingSample/third-party-library-sample/src/specs/arkts-components/SelectBox.ts+45-0
| @@ -0,0 +1,45 @@ | |||
| 1 | +/** | ||
| 2 | + * Copyright (c) 2025 Huawei Technologies Co., Ltd. | ||
| 3 | + * | ||
| 4 | + * This source code is licensed under the MIT license found in the | ||
| 5 | + * LICENSE-MIT file in the root directory of this source tree. | ||
| 6 | + */ | ||
| 7 | + | ||
| 8 | +import React from 'react'; | ||
| 9 | +import type { ViewProps } from "react-native/Libraries/Components/View/ViewPropTypes"; | ||
| 10 | +import type { HostComponent } from "react-native"; | ||
| 11 | +import codegenNativeComponent from "react-native/Libraries/Utilities/codegenNativeComponent"; | ||
| 12 | +import codegenNativeCommands from 'react-native/Libraries/Utilities/codegenNativeCommands'; | ||
| 13 | +import type { Int32, DirectEventHandler } from 'react-native/Libraries/Types/CodegenTypes'; | ||
| 14 | + | ||
| 15 | +export interface SelectItems { | ||
| 16 | + id: Int32; | ||
| 17 | + text: string; | ||
| 18 | +} | ||
| 19 | + | ||
| 20 | +export interface Res { | ||
| 21 | + value: Int32[]; | ||
| 22 | +} | ||
| 23 | + | ||
| 24 | +export interface NativeProps extends ViewProps, Res { | ||
| 25 | + data: SelectItems[]; | ||
| 26 | + onChange: DirectEventHandler<Res>; | ||
| 27 | + // 添加其它 props | ||
| 28 | +} | ||
| 29 | + | ||
| 30 | +type NativeType = HostComponent<NativeProps>; | ||
| 31 | + | ||
| 32 | +interface NativeCommands { | ||
| 33 | + emitNativeEvent: ( | ||
| 34 | + viewRef: React.ElementRef<NativeType>, | ||
| 35 | + mutil: boolean, | ||
| 36 | + ) => void; | ||
| 37 | +} | ||
| 38 | + | ||
| 39 | +export const Commands: NativeCommands = codegenNativeCommands<NativeCommands>({ | ||
| 40 | + supportedCommands: ['emitNativeEvent'], | ||
| 41 | +}); | ||
| 42 | + | ||
| 43 | +export default codegenNativeComponent<NativeProps>( | ||
| 44 | + "SelectBox" | ||
| 45 | +) as HostComponent<NativeProps>; | ||
| @@ -0,0 +1,43 @@ | |||
| 1 | +/** | ||
| 2 | + * Copyright (c) 2025 Huawei Technologies Co., Ltd. | ||
| 3 | + * | ||
| 4 | + * This source code is licensed under the MIT license found in the | ||
| 5 | + * LICENSE-MIT file in the root directory of this source tree. | ||
| 6 | + */ | ||
| 7 | + | ||
| 8 | +import { ViewProps, HostComponent, ProcessedColorValue } from 'react-native'; | ||
| 9 | +import type { ColorValue } from "react-native/Libraries/StyleSheet/StyleSheet"; | ||
| 10 | +import codegenNativeComponent from 'react-native/Libraries/Utilities/codegenNativeComponent'; | ||
| 11 | +import codegenNativeCommands from 'react-native/Libraries/Utilities/codegenNativeCommands'; | ||
| 12 | +import type { | ||
| 13 | + Float, | ||
| 14 | + DirectEventHandler, | ||
| 15 | +} from 'react-native/Libraries/Types/CodegenTypes'; | ||
| 16 | + | ||
| 17 | +export interface ScrollEvent { | ||
| 18 | + offsetY: Float; | ||
| 19 | +} | ||
| 20 | + | ||
| 21 | +export interface NativeProps extends ViewProps { | ||
| 22 | + stopPercent?: Float, | ||
| 23 | + stopPercentMax?: Float, | ||
| 24 | + onScroll?: DirectEventHandler<ScrollEvent>; | ||
| 25 | +} | ||
| 26 | + | ||
| 27 | +type NativeType = HostComponent<NativeProps>; | ||
| 28 | + | ||
| 29 | +interface NativeCommands { | ||
| 30 | + scrollTo: ( | ||
| 31 | + viewRef: React.ElementRef<NativeType>, | ||
| 32 | + offsetY: Float, | ||
| 33 | + animated: boolean, | ||
| 34 | + ) => void; | ||
| 35 | +} | ||
| 36 | + | ||
| 37 | +export const Commands: NativeCommands = codegenNativeCommands<NativeCommands>({ | ||
| 38 | + supportedCommands: ['scrollTo'], | ||
| 39 | +}); | ||
| 40 | + | ||
| 41 | +export default codegenNativeComponent<NativeProps>( | ||
| 42 | + 'QDGestureFloat', | ||
| 43 | +) as HostComponent<NativeProps>; | ||
| @@ -0,0 +1,14 @@ | |||
| 1 | +/** | ||
| 2 | + * Copyright (c) 2025 Huawei Technologies Co., Ltd. | ||
| 3 | + * | ||
| 4 | + * This source code is licensed under the MIT license found in the | ||
| 5 | + * LICENSE file in the root directory of this source tree. | ||
| 6 | + */ | ||
| 7 | +import { TurboModuleRegistry } from 'react-native'; | ||
| 8 | +import type { TurboModule } from 'react-native/Libraries/TurboModule/RCTExport'; | ||
| 9 | + | ||
| 10 | +export interface Spec extends TurboModule { | ||
| 11 | + power(a: number, b: number): Promise<number>; | ||
| 12 | +} | ||
| 13 | + | ||
| 14 | +export default TurboModuleRegistry.get<Spec>('SampleAnyThreadTurboModule')!; | ||
| @@ -0,0 +1,14 @@ | |||
| 1 | +/** | ||
| 2 | + * Copyright (c) 2025 Huawei Technologies Co., Ltd. | ||
| 3 | + * | ||
| 4 | + * This source code is licensed under the MIT license found in the | ||
| 5 | + * LICENSE file in the root directory of this source tree. | ||
| 6 | + */ | ||
| 7 | +import { TurboModuleRegistry } from 'react-native'; | ||
| 8 | +import type { TurboModule } from 'react-native/Libraries/TurboModule/RCTExport'; | ||
| 9 | + | ||
| 10 | +export interface Spec extends TurboModule { | ||
| 11 | + add(a: number, b: number): number; | ||
| 12 | +} | ||
| 13 | + | ||
| 14 | +export default TurboModuleRegistry.get<Spec>('SampleTurboModule')!; | ||


补充copyright