### Development Setup Commands Source: https://github.com/tencent-tds/kuiklyui/blob/main/miniApp-js/README.md Commands for setting up the development environment, including installing dependencies, rebuilding libraries, and compiling bundles. ```bash ### 1. 安装依赖 cd miniApp-js npm install ### 2. 复制 Kotlin/JS 库 npm run rebuild-libs ### 3. 编译业务 Bundle npm run build-bundles HelloWorldPage,000 ### 4. 构建miniApp-js npm run build ``` -------------------------------- ### Run Demo Project Dev Server Source: https://github.com/tencent-tds/kuiklyui/blob/main/docs/QuickStart/hello-world.md Execute this command to start the development server for the demo project. Ensure npm packages are installed first. ```shell # 运行 demo 项目 dev server 服务器,没有安装 npm 包则先 npm install 安装一下依赖 npm run serve ``` -------------------------------- ### Switch with On State and Change Listener Source: https://github.com/tencent-tds/kuiklyui/blob/main/docs/API/components/switch.md Configures a Switch to be initially on and sets up a listener to log the switch's state changes. This example is part of a demo page setup. ```kotlin @Page("demo_page") internal class TestPage : BasePager() { override fun body(): ViewBuilder { return { attr { allCenter() } Switch { attr { isOn(true) } event { switchOnChanged { KLog.i("Switch", "switchOnChanged $it") } } } } } } ``` -------------------------------- ### Example Implementation and Registration (C++) Source: https://github.com/tencent-tds/kuiklyui/blob/main/docs/QuickStart/harmony.md A C++ example demonstrating how to implement and register both V2 and V3 image adapters. It shows how to process `imageParams` in V3. ```APIDOC ## C++ Implementation Example ### Header Inclusion ```c++ #include ``` ### Adapter Implementation (V2) ```c++ // entry/src/main/cpp/napi_init.cpp static int32_t MyImageAdapterV2(const void *context, const char *src, KRSetImageCallback callback) { // Custom image loading logic... // ... return 0; // Indicate not handled } ``` ### Adapter Implementation (V3) ```c++ // entry/src/main/cpp/napi_init.cpp static int32_t MyImageAdapterV3(const void *context, const char *src, KRAnyData *imageParams, KRSetImageCallback callback) { std::map paramsMap; if (imageParams != nullptr && KRAnyDataIsMap(imageParams)) { auto visitor = [](const char* key, KRAnyData value, void* userData) { auto* map = static_cast*>(userData); if (KRAnyDataIsString(value)) { const char* str = KRAnyDataGetString(value); if (str) (*map)[key] = str; } else if (KRAnyDataIsInt(value)) { int32_t intVal; KRAnyDataGetInt(value, &intVal); (*map)[key] = std::to_string(intVal); } else if (KRAnyDataIsLong(value)) { int64_t longVal; KRAnyDataGetLong(value, &longVal); (*map)[key] = std::to_string(longVal); } else if (KRAnyDataIsFloat(value)) { float floatVal; KRAnyDataGetFloat(value, &floatVal); (*map)[key] = std::to_string(floatVal); } else if (KRAnyDataIsBool(value)) { bool boolVal; KRAnyDataGetBool(value, &boolVal); (*map)[key] = boolVal ? "true" : "false"; } }; KRAnyDataVisitMap(imageParams, visitor, ¶msMap); } if (paramsMap.count("test") > 0) { auto value = paramsMap["test"]; KR_LOG_INFO << "imageParams testxxx value: " << value; } // Custom image loading logic... // ... return 0; // Indicate not handled } ``` ### Adapter Registration ```c++ // entry/src/main/cpp/napi_init.cpp static napi_value InitKuikly(napi_env env, napi_callback_info info) { // Register either V2 or V3 adapter (V3 takes precedence) KRRegisterImageAdapterV2(MyImageAdapterV2); // OR KRRegisterImageAdapterV3(MyImageAdapterV3); // ... other initialization return nullptr; } ``` ``` -------------------------------- ### Install cJSON using Vcpkg Source: https://github.com/tencent-tds/kuiklyui/blob/main/core-render-ohos/src/main/cpp/thirdparty/cJSON/README.md Steps to clone the vcpkg repository, bootstrap it, integrate it with your system, and install cJSON. ```bash git clone https://github.com/Microsoft/vcpkg.git cd vcpkg ./bootstrap-vcpkg.sh ./vcpkg integrate install vcpkg install cjson ``` -------------------------------- ### Install cJSON with Makefile Source: https://github.com/tencent-tds/kuiklyui/blob/main/core-render-ohos/src/main/cpp/thirdparty/cJSON/README.md Instructions for installing cJSON using the Makefile, with options to specify installation prefix and destination directory. ```bash make PREFIX=/usr DESTDIR=temp install ``` -------------------------------- ### Full Example: Text Selection Functionality Source: https://github.com/tencent-tds/kuiklyui/blob/main/docs/API/components/text-selection.md This example demonstrates how to implement text selection in a UI. It includes a button to get selected text and uses `longPress` to initiate word selection. ```kotlin @Page("TextSelectionExamplePage") internal class TextSelectionExamplePage : BasePager() { private var selectedText by observable("") private var selectableContainer: ViewRef? = null override fun body(): ViewBuilder { val ctx = this return { attr { flexDirectionColumn() } View { attr { padding(top = 12f, bottom = 12f, left = 16f, right = 16f) } event { click { ctx.selectableContainer?.view?.getSelection { result -> ctx.selectedText = result.joinToString(" | ") } } } Text { attr { text("获取选中内容: ${ctx.selectedText}") } } } View { ref { ctx.selectableContainer = it } attr { padding(all = 16f) selectable(SelectableOption.ENABLE) selectionColor(Color(0xFF2196F3)) } event { longPress { if (it.state == "start") { ctx.selectableContainer?.view ?.createSelection(it.x, it.y, SelectionType.WORD) } } selectEnd { frame -> KLog.i("TextSelection", "selectEnd: $frame") } } Text { attr { fontSize(15f) text("Kuikly是一个跨平台的UI框架,支持iOS、Android、鸿蒙等多端。") } } Text { attr { fontSize(15f) text("文本选择功能允许用户跨多个文本组件进行连续选择。") } } } } } } ``` -------------------------------- ### Example Touch Begin Event Log Source: https://github.com/tencent-tds/kuiklyui/blob/main/openspec/specs/profiler-context-events/spec.md An example of a touch context event logged when a user presses their finger on the screen and the profiler is enabled. ```json {"type":"touch_context","eventType":"touchBegin","timestampMs":1776678700583,"pointerCount":1} ``` -------------------------------- ### APNG Component Usage Example Source: https://github.com/tencent-tds/kuiklyui/blob/main/docs/API/components/apng.md Demonstrates how to use the APNG component to display an animated image with specified size and source URL. Includes event handling for animation start. ```kotlin @Page("demo_page") internal class TestPage : BasePager() { override fun body(): ViewBuilder { return { attr { allCenter() } APNG { attr { size(200f, 200f) src("https://vfiles.gtimg.cn/wuji_dashboard/xy/componenthub/5vcy152h.png?test=4") } event { animationStart { KLog.i("APNG", "start play animation") } } } } } } ``` -------------------------------- ### Switch Usage Example Source: https://github.com/tencent-tds/kuiklyui/blob/main/docs/API/components/switch.md Example demonstrating how to use the Switch component with its properties and events. ```APIDOC ```kotlin Switch { attr { isOn(true) // Example of enabling glass effect (iOS 26+) enableGlassEffect(true) onColor(Color(0xFF34C759)) unOnColor(Color(0xFF8E8E93)) thumbColor(Color.WHITE) } event { switchOnChanged { isOn -> KLog.i("Switch", "Switch state changed: $isOn") } } } ``` ``` -------------------------------- ### Example C Test File Structure Source: https://github.com/tencent-tds/kuiklyui/blob/main/core-render-ohos/src/main/cpp/thirdparty/cJSON/tests/unity/docs/UnityGettingStartedGuide.md This is a typical structure for a C test file using Unity. It includes necessary headers, optional setUp and tearDown functions, test functions, and a main function to execute the tests. ```c #include "unity.h" #include "file_to_test.h" void setUp(void) { // set stuff up here } void tearDown(void) { // clean stuff up here } void test_function_should_doBlahAndBlah(void) { //test stuff } void test_function_should_doAlsoDoBlah(void) { //more test stuff } int main(void) { UNITY_BEGIN(); RUN_TEST(test_function_should_doBlahAndBlah); RUN_TEST(test_function_should_doAlsoDoBlah); return UNITY_END(); } ``` -------------------------------- ### Example app.json Configuration Source: https://github.com/tencent-tds/kuiklyui/blob/main/miniApp/example/KuiklyWorkWithMiniapp/KuiklyUI集成指引.md A sample app.json configuration for a mini-program, defining the list of pages, window properties, and global components. ```json { "pages": [ "pages/index/index", "pages/list/list", "pages/router/index", "pages/settings/index" ], "window": { "navigationBarTextStyle": "black", "navigationBarTitleText": "我的应用", "navigationBarBackgroundColor": "#F8F8F8", "backgroundColor": "#F8F8F8" }, "usingComponents": {} } ``` -------------------------------- ### APNG Component Usage Example Source: https://github.com/tencent-tds/kuiklyui/blob/main/docs/API/components/apng.md Example demonstrating how to use the APNG component with its attributes and event handlers. ```APIDOC ## APNG Component Usage Example ### Description This example shows how to integrate the APNG component into your application, setting its size and source path, and handling animation start events. ### Method N/A (Component Usage) ### Endpoint N/A (Component Usage) ### Parameters #### Path Parameters N/A #### Query Parameters N/A #### Request Body N/A ### Request Example ```kotlin @Page("demo_page") internal class TestPage : BasePager() { override fun body(): ViewBuilder { return { attr { allCenter() } APNG { attr { size(200f, 200f) src("https://vfiles.gtimg.cn/wuji_dashboard/xy/componenthub/5vcy152h.png?test=4") } event { animationStart { KLog.i("APNG", "start play animation") } } } } } } ``` ### Response #### Success Response (200) N/A (Component Usage) #### Response Example N/A (Component Usage) ``` -------------------------------- ### Run Shared Project Dev Server Source: https://github.com/tencent-tds/kuiklyui/blob/main/docs/QuickStart/h5.md Starts the dev server for the shared project. Ensure npm packages are installed before running. ```shell # 运行 shared 项目 dev server 服务器,没有安装 npm 包则先 npm install 安装一下依赖 npm run serve ``` -------------------------------- ### AI Analysis Command Examples Source: https://github.com/tencent-tds/kuiklyui/blob/main/docs/Compose/recomposition-performance.md These examples demonstrate how to invoke the AI analysis skill for recomposition issues. You can specify the platform and package name for analysis on a device or provide local file paths for report and frames data. ```bash Use kuikly-recomposition-analyzer to analyze recomposition issues on the android emulator for com.tencent.news.core ``` ```bash Use kuikly-recomposition-analyzer to analyze these two files: - report: /tmp/profiler_report.json - frames: /tmp/profiler_frames.jsonl ``` -------------------------------- ### System Compatibility Check Source: https://github.com/tencent-tds/kuiklyui/blob/main/docs/API/components/liquid-glass.md Example demonstrating how to check for system support before applying the LiquidGlass component, with a fallback for unsupported versions. ```APIDOC ## Notes ### 1. System Compatibility When using the standalone liquid glass component, ensure system version checks are in place for iOS 26+ and provide a fallback for unsupported versions. ```kotlin import com.tencent.kuikly.core.utils.PlatformUtils // Recommended practice: Check system support if (PlatformUtils.isLiquidGlassSupported()) { LiquidGlass { // Liquid glass implementation } } else { View { attr { backgroundColor(Color.GRAY) // Fallback } // Same child components } } ``` ``` -------------------------------- ### Configure and Start RecompositionProfiler Source: https://github.com/tencent-tds/kuiklyui/blob/main/openspec/specs/ai-integration/spec.md Configure profiler settings like hotspot threshold and enable the overlay panel. The profiler starts, and by default, logs and writes to files. ```kotlin RecompositionProfiler.configure { hotspotThreshold = 5 enableOverlay = true // 需要可视面板时开启 } RecompositionProfiler.start() ``` -------------------------------- ### Implement Custom Image Adapter V2 Source: https://github.com/tencent-tds/kuiklyui/blob/main/docs/QuickStart/harmony.md Example implementation of the KRImageAdapterV2. This version does not process additional image parameters. ```cpp // entry/src/main/cpp/napi_init.cpp #include // V2 实现(不需要 imageParams) static int32_t MyImageAdapterV2(const void *context, const char *src, KRSetImageCallback callback) { // 自定义图片加载逻辑 // ... return 0; } ``` -------------------------------- ### Custom Module Implementation Source: https://github.com/tencent-tds/kuiklyui/blob/main/miniApp-js/README.md Example of creating a custom module in JavaScript, including its method handling. ```javascript // src/modules/MyCustomModule.js export class MyCustomModule { static MODULE_NAME = 'MyCustomModule'; call(method, params, callback) { switch (method) { case 'myMethod': // 处理方法调用 return; default: return null; } } } ``` -------------------------------- ### Integrate cJSON with Meson Source: https://github.com/tencent-tds/kuiklyui/blob/main/core-render-ohos/src/main/cpp/thirdparty/cJSON/README.md Example of how to include cJSON as a dependency in a Meson build system configuration. ```meson project('c-json-example', 'c') cjson = dependency('libcjson') example = executable( 'example', 'example.c', dependencies: [cjson], ) ``` -------------------------------- ### Run H5App Project Debug Server Source: https://github.com/tencent-tds/kuiklyui/blob/main/docs/DevGuide/h5-dev.md Starts the debug version of the H5App development server. For Kotlin 2.0+, use 'jsBrowserDevelopmentRun'. If compilation fails due to iOS module issues, consult the 'Quick Start - Environment Setup' guide. ```shell # Run h5App Debug version server ./gradlew :h5App:jsBrowserRun -t # Kotlin 2.0+ # ./gradlew :h5App:jsBrowserDevelopmentRun -t # Copy assets to webpack dev server ./gradlew :h5App:copyAssetsToWebpackDevServer ``` -------------------------------- ### Run H5App Project Debug Version Source: https://github.com/tencent-tds/kuiklyui/blob/main/docs/QuickStart/h5.md Starts the H5App project server in Debug mode. For Kotlin 2.0+, use 'jsBrowserDevelopmentRun'. If encountering iOS module compilation failures on Windows, consult the 'Environment Setup' guide. ```shell # 运行 h5App 服务器 Debug 版 ./gradlew :h5App:jsBrowserRun -t kotlin 2.0 以上运行: ./gradlew :h5App:jsBrowserDevelopmentRun -t ``` -------------------------------- ### Basic Navigation Setup in Compose Source: https://github.com/tencent-tds/kuiklyui/blob/main/docs/Compose/navigation.md Sets up a NavHost with two composable destinations: 'home' and 'detail'. Use rememberNavController() to create and manage the NavHostController. The startDestination is set to 'home'. ```kotlin import androidx.compose.runtime.Composable import androidx.navigation.compose.NavHost import androidx.navigation.compose.composable import androidx.navigation.compose.rememberNavController import androidx.compose.material3.Button import androidx.compose.material3.Text @Composable fun NavigationExample() { val navController = rememberNavController() NavHost( navController = navController, startDestination = "home" ) { composable("home") { HomeScreen(navController) } composable("detail") { DetailScreen(navController) } } } @Composable fun HomeScreen(navController: NavHostController) { Button(onClick = { navController.navigate("detail") }) { Text("Go to Detail") } } ``` -------------------------------- ### Example Project Structure Source: https://github.com/tencent-tds/kuiklyui/blob/main/miniApp/example/KuiklyWorkWithMiniapp/KuiklyUI集成指引.md Illustrates a typical project structure for a mini-program using KuiklyUI, showing the placement of core libraries, business logic, and page directories. ```plaintext my-miniapp/ ├── lib/ │ └── miniApp.js ├── business/ │ └── nativevue2.js ├── base.wxml ├── comp.js / comp.json / comp.wxml ├── custom-wrapper.js / .json / .wxml ├── utils.wxs ├── pages/ │ ├── index/ # 原生首页 │ │ ├── index.js │ │ ├── index.json │ │ ├── index.wxml │ │ └── index.wxss │ ├── list/ # 原生列表页 │ ├── router/ # KuiklyUI 路由页 │ │ ├── index.js │ │ ├── index.json │ │ └── index.wxml │ └── settings/ # KuiklyUI 设置页 │ ├── index.js │ ├── index.json │ └── index.wxml ├── app.js ├── app.json └── project.config.json ``` -------------------------------- ### Kotlin: CustomButtonPage Example Source: https://github.com/tencent-tds/kuiklyui/blob/main/miniApp/example/KuiklyWorkWithMiniapp/Kuikly自定义组件集成微信小程序内置组件指南.md Demonstrates using the CustomButton component to trigger WeChat Mini Program's open-type functionalities like getting the phone number or opening settings. ```kotlin package com.example.kuiklyworkwithminiapp import com.example.kuiklyworkwithminiapp.components.CustomButton import com.tencent.kuikly.core.annotations.Page import com.tencent.kuikly.core.nvi.serialization.json.JSONObject import com.tencent.kuikly.core.log.KLog @Page("customButton", supportInLocal = true) internal class CustomButtonPage : BasePager() { override fun body(): ViewBuilder { return { View { attr { width(200f) height(200f) margin(60f) } // 获取手机号按钮 CustomButton { attr { width(150f) height(40f) borderRadius(10f) backgroundColor(Color.YELLOW) titleAttr { text("getPhoneNumber") } openType("getPhoneNumber") // 设置 open-type } event { onGetPhoneNumber { // 监听获取手机号事件 val callbackData = it as JSONObject val data = callbackData.optString("data") val dataObj = JSONObject(data) KLog.d("onGetPhoneNumber", dataObj.toString()) } } } // 打开设置按钮 CustomButton { attr { titleAttr { text("openSetting") } openType("openSetting") } } } } } } ``` -------------------------------- ### 构建鸿蒙平台产物 (SO) Source: https://github.com/tencent-tds/kuiklyui/blob/main/docs/DevGuide/compile_skills.md 使用 Gradle 命令构建鸿蒙平台的 SO 库。所有模块将统一编译成一个 SO 文件。如果使用了定制化的 Gradle 配置,需要指定对应的 settings 文件。 ```bash ./gradlew :shared:linkOhosArm64 ``` ```bash ./gradlew -c settings.ohos.gradle.kts :shared:linkOhosArm64 ``` -------------------------------- ### Build cJSON with CMake (Linux Distribution Packaging) Source: https://github.com/tencent-tds/kuiklyui/blob/main/core-render-ohos/src/main/cpp/thirdparty/cJSON/README.md Example CMake build command for packaging cJSON for a Linux distribution, enabling cJSON_Utils and disabling tests, with a custom installation prefix. ```bash mkdir build cd build cmake .. -DENABLE_CJSON_UTILS=On -DENABLE_CJSON_TEST=Off -DCMAKE_INSTALL_PREFIX=/usr make make DESTDIR=$pkgdir install ``` -------------------------------- ### Complete Package.swift for shared and resources Source: https://github.com/tencent-tds/kuiklyui/blob/main/docs/QuickStart/iOS.md This example shows a complete Package.swift file for a Swift Package that includes both the 'shared.xcframework' binary target and a 'SharedResource' target for managing resources. ```swift // swift-tools-version: 5.7 import PackageDescription let package = Package( name: "shared", platforms: [.iOS(.v13)], products: [ .library( name: "shared", targets: ["shared"]), .library(name: "SharedResource", targets: ["SharedResource"]) ], targets: [ .binaryTarget( name: "shared", path: "Frameworks/shared.xcframework", ), .target( name: "SharedResource", resources: [ .copy("KuiklyResources") ], ), ], ) ``` -------------------------------- ### Get and Use Module Outside Pager/ComposeView Source: https://github.com/tencent-tds/kuiklyui/blob/main/docs/DevGuide/module.md Access the current Pager instance via PagerManager to acquire a Module in contexts other than Pagers or ComposeViews. This example demonstrates setting a value using MemoryCacheModule. ```kotlin class Test { fun setValue(v: Int) { val cacheModule = PagerManager.getCurrentPager() .acquireModule(MemoryCacheModule.MODULE_NAME) cacheModule.setObject("test", v) } } ``` -------------------------------- ### Run Shared Project Dev Server and Build Debug JS Bundle Source: https://github.com/tencent-tds/kuiklyui/blob/main/docs/DevGuide/h5-dev.md Starts the development server for the shared project and builds a debug version of the JS bundle. Ensure npm packages are installed before running. ```shell # Run shared project dev server, install npm packages if needed npm run serve # Build shared project Debug version ./gradlew :shared:packLocalJsBundleDebug ``` -------------------------------- ### Using Strong-typed Modules (Login + Storage) Source: https://github.com/tencent-tds/kuiklyui/blob/main/docs/DevGuide/miniapp-wx-apis.md Demonstrates how to acquire and use strongly-typed modules like WXApiModule and WXStorageModule for common operations such as user login and local storage. ```APIDOC ## Using Strong-typed Modules (Login + Storage) All Modules are accessed via ``acquireModule(T.MODULE_NAME)`` to get a singleton instance, and then methods are called directly. Unified callback conventions: - ``onSuccess: (JSONObject?) -> Unit`` - Call successful, parameter is the ``res`` from the wx API callback. - ``onFail: (JSONObject?) -> Unit`` - Call failed, parameter is the ``err`` from the wx API callback (includes ``errMsg``). ### Example ```kotlin import com.tencent.kuikly.core.wx.module.WXApiModule import com.tencent.kuikly.core.wx.module.WXStorageModule import com.tencent.kuikly.core.wx.module.WXUIModule // Login acquireModule(WXApiModule.MODULE_NAME).login( onSuccess = { res -> val code = res?.optString("code") // Use code to exchange openid + session_key with your backend // ... // Store locally acquireModule(WXStorageModule.MODULE_NAME) .setStorageSync("login_code", code ?: "") }, onFail = { err -> acquireModule(WXUIModule.MODULE_NAME) .showToast(title = "Login failed", icon = "error") } ) ``` ``` -------------------------------- ### Implement Custom Image Adapter V3 with Parameters Source: https://github.com/tencent-tds/kuiklyui/blob/main/docs/QuickStart/harmony.md Example implementation of KRImageAdapterV3, demonstrating how to parse and use the `imageParams` for custom loading logic. It shows two methods for accessing parameters: iterating through all key-value pairs or fetching specific values. ```cpp // entry/src/main/cpp/napi_init.cpp #include // V3 实现(需要 imageParams) static int32_t MyImageAdapterV3(const void *context, const char *src, KRAnyData *imageParams, KRSetImageCallback callback) { // 获取imageParams,跨端侧传入的是:{"test":"abc"} std::map paramsMap; // 方式1:使用 KRAnyDataVisitMap 遍历所有参数(推荐) if (imageParams != nullptr && KRAnyDataIsMap(imageParams)) { // 定义 lambda 作为访问器 auto visitor = [](const char* key, KRAnyData value, void* userData) { auto* map = static_cast*>(userData); // 根据类型转换成字符串存储 if (KRAnyDataIsString(value)) { const char* str = KRAnyDataGetString(value); if (str) { (*map)[key] = str; } } else if (KRAnyDataIsInt(value)) { int32_t intVal; KRAnyDataGetInt(value, &intVal); (*map)[key] = std::to_string(intVal); } else if (KRAnyDataIsLong(value)) { int64_t longVal; KRAnyDataGetLong(value, &longVal); (*map)[key] = std::to_string(longVal); } else if (KRAnyDataIsFloat(value)) { float floatVal; KRAnyDataGetFloat(value, &floatVal); (*map)[key] = std::to_string(floatVal); } else if (KRAnyDataIsBool(value)) { bool boolVal; KRAnyDataGetBool(value, &boolVal); (*map)[key] = boolVal ? "true" : "false"; } }; // 遍历所有键值对 KRAnyDataVisitMap(imageParams, visitor, ¶msMap); } // 业务逻辑... if (paramsMap.count("test") > 0) { auto value = paramsMap["test"]; KR_LOG_INFO << "imageParams testxxx value: " << value; } // 方式2:获取特定的参数值(如果只需要某个字段) if (imageParams != nullptr && KRAnyDataIsMap(imageParams)) { KRAnyData testValue = nullptr; if (KRAnyDataGetMapValue(imageParams, "test", &testValue) == KRANYDATA_SUCCESS && testValue != nullptr) { if (KRAnyDataIsString(testValue)) { const char *str = KRAnyDataGetString(testValue); KR_LOG_INFO << "imageParams test value: " << str; } } } // 自定义图片加载逻辑 // ... return 0; } ``` -------------------------------- ### Access Business Extension Parameters Source: https://github.com/tencent-tds/kuiklyui/blob/main/docs/DevGuide/page-data.md Retrieve custom business parameters passed from the Native side via `PagerData.params`. Use `optInt`, `optString`, etc., for safe access. This example shows how to get an integer parameter named 'test'. ```kotlin internal class HelloWorldPage : Pager() { ... override fun body(): ViewBuilder { ... } override fun created() { super.created() val test = pagerData.params.optInt("test") // 获取业务参数 } } ``` -------------------------------- ### Run H5 Demo Server and Build Shared Project Source: https://github.com/tencent-tds/kuiklyui/blob/main/docs/QuickStart/common.md Commands to start the H5 demo project's development server and build the shared project's JavaScript bundle for debugging. ```shell # Run demo project dev server, install npm packages if needed npm run serve # Build the shared project's Debug JavaScript bundle ./gradlew :shared:packLocalJsBundleDebug ``` -------------------------------- ### Open New Page Instance Source: https://github.com/tencent-tds/kuiklyui/blob/main/docs/DevGuide/multi-page.md Demonstrates opening a new instance of the same page. This snippet initializes a simple counter page. ```kotlin @Page("foo") internal class FooPage : BasePager() { private var digit by observable(0) private val routerModule by lazy(LazyThreadSafetyMode.NONE) { acquireModule(RouterModule.MODULE_NAME) } override fun body(): ViewBuilder { val ctx = this return { attr { allCenter() } Text { attr { text(ctx.digit.toString()) fontSize(100f) } event { click { ++ctx.digit } } } Text { attr { text("open") } event { click { ctx.routerModule.openPage("foo") } } } } } } ``` -------------------------------- ### Run HarmonyOS Demo Build Script (Windows) Source: https://github.com/tencent-tds/kuiklyui/blob/main/README.md Execute this script in the KuiklyUI root directory on Windows to build the HarmonyOS cross-platform product. Alternatively, use the manual Gradle command. ```cmd 2.0_ohos_demo_build.bat ``` ```cmd set KUIKLY_AGP_VERSION=7.4.2 set KUIKLY_KOTLIN_VERSION=2.0.21-KBA-010 gradlew.bat -c settings.2.0.ohos.gradle.kts :demo:linkSharedDebugSharedOhosArm64 ``` -------------------------------- ### Profiler Lifecycle Listener Callback on Start Source: https://github.com/tencent-tds/kuiklyui/blob/main/openspec/specs/recomposition-profiler-api/spec.md Callback invoked when the RecompositionProfiler starts. The listener is responsible for registering its CompositionObserver. ```kotlin override fun onProfilerStarted(tracker: CompositionObserver) { // Register CompositionObserver } ``` -------------------------------- ### Install iOS Dependencies Source: https://github.com/tencent-tds/kuiklyui/blob/main/README.md Navigate to the iosApp directory and run this command to install or update CocoaPods dependencies for the iOS application. ```bash pod install --repo-update ``` -------------------------------- ### Install Package Config Files Source: https://github.com/tencent-tds/kuiklyui/blob/main/core-render-ohos/src/main/cpp/thirdparty/cJSON/CMakeLists.txt Installs the generated cJSON package configuration files to the appropriate CMake directory for external projects to use. ```cmake install(FILES ${PROJECT_BINARY_DIR}/cJSONConfig.cmake ${PROJECT_BINARY_DIR}/cJSONConfigVersion.cmake DESTINATION "${CMAKE_INSTALL_FULL_LIBDIR}/cmake/cJSON") ``` -------------------------------- ### Implement NAPI Initialization Entry Point Source: https://github.com/tencent-tds/kuiklyui/blob/main/docs/QuickStart/harmony.md Implement the InitKuikly function, which serves as the NAPI initialization entry point. This function calls into the shared library to initialize Kuikly and returns a handler. ```c++ // entry/src/main/cpp/napi_init.cpp #include "libshared_api.h" #include "napi/native_api.h" static napi_value InitKuikly(napi_env env, napi_callback_info info) { // symbols入口名和kuikly工程的配置有关,具体查看产物的头文件 auto api = libshared_symbols(); int handler = api->kotlin.root.initKuikly(); napi_value result; napi_create_int32(env, handler, &result); return result; } EXTERN_C_START static napi_value Init(napi_env env, napi_value exports) { napi_property_descriptor desc[] = { {"initKuikly", nullptr, InitKuikly, nullptr, nullptr, nullptr, napi_default, nullptr}, }; napi_define_properties(env, exports, sizeof(desc) / sizeof(desc[0]), desc); return exports; } EXTERN_C_END ``` -------------------------------- ### Kuikly Image Loading Example Source: https://github.com/tencent-tds/kuiklyui/blob/main/docs/DevGuide/attr.md Illustrates how to display an image by setting its source URL and size using `attr` within an `Image` component. ```kotlin @Page("HelloWorldPage") internal class HelloWorldPage : Pager() { override fun body(): ViewBuilder { val ctx = this return { attr { allCenter() } Text { attr { text("Hello Kuikly") fontSize(20f) fontWeightBold() } } Image { attr { size(50f, 50f) src("https://vfiles.gtimg.cn/wupload/xy/componenthub/TbyiIqBP.jpeg") } } } } } ``` -------------------------------- ### Animation Context Event Format (Start) Source: https://github.com/tencent-tds/kuiklyui/blob/main/openspec/specs/runtime-context/spec.md JSON structure for the start event of an animation context. Records the animation type, duration, and label. ```json {"type":"animation_context","timestampMs":1775188247602,"event":"start","animationType":"animateColorAsState","durationMs":300,"label":"background-color"} ``` -------------------------------- ### Start KuiklyRenderActivity to Navigate to a Page Source: https://github.com/tencent-tds/kuiklyui/blob/main/docs/QuickStart/android.md Start the KuiklyRenderActivity to navigate to a specific Kuikly page. Pass the page name and any necessary data as parameters. ```kotlin KuiklyRenderActivity.start(context, "test", JSONObject()) ``` -------------------------------- ### Kotlin Mini App Integration Source: https://github.com/tencent-tds/kuiklyui/blob/main/docs/QuickStart/Miniapp.md This Kotlin code sets up the main entry point for a mini-app. It handles app lifecycle events like launch, show, and hide, and configures the page rendering mechanism using MiniDocument and KuiklyWebRenderViewDelegator. ```kotlin import com.tencent.kuikly.core.render.web.collection.FastMutableMap import com.tencent.kuikly.core.render.web.ktx.SizeI import com.tencent.kuikly.core.render.web.runtime.miniapp.MiniDocument import com.tencent.kuikly.core.render.web.runtime.miniapp.core.App import com.tencent.kuikly.core.render.web.runtime.miniapp.core.NativeApi const val TAG = "Main" fun main() { App.onShow { console.log(TAG, "app show") } App.onLaunch { console.log(TAG, "app launch") } App.onHide { console.log(TAG, "app hide") } } /** * Mini program page entry, use renderView delegate method to initialize and create renderView */ @JsName(name = "renderView") @JsExport @ExperimentalJsExport fun renderView(json: dynamic) { // Write to global render function val renderParams = FastMutableMap(json) // View size var size: SizeI? = null if (json.width != null && json.height != null) { size = SizeI(json.width.unsafeCast(), json.height.unsafeCast()) } MiniDocument.initPage(renderParams) { pageId: Int, pageName: String, paramsMap: FastMutableMap -> val systemInfo = NativeApi.plat.getSystemInfoSync() val isAndroid = systemInfo.platform == "android" val params = paramsMap["param"].unsafeCast>() params["is_wx_mp"] = "true" paramsMap["platform"] = if (isAndroid) "android" else "iOS" paramsMap["isIOS"] = !isAndroid paramsMap["isIphoneX"] = !isAndroid && systemInfo.safeArea.top > 30 KuiklyWebRenderViewDelegator().delegate.onAttach( pageId, pageName, paramsMap, size, ) } } /** * Register callback methods on the mini program App object, needs to be called in the app.js of the mini program */ @JsName(name = "initApp") @JsExport @ExperimentalJsExport fun initApp(options: dynamic = js("{}")) { App.initApp(options) } ``` -------------------------------- ### Project Structure Overview Source: https://github.com/tencent-tds/kuiklyui/blob/main/miniApp-js/README.md Overview of the directory structure for the Kuikly MiniApp JS project. ```bash miniApp-js/ ├── dist/ # 小程序运行目录(用微信开发者工具打开此目录) │ ├── app.js # 小程序入口 │ ├── app.json # 小程序配置 │ ├── app.wxss # 全局样式 │ ├── base.wxml # 基础模板 │ ├── lib/ # 构建输出的渲染库 │ ├── business/ # 业务代码 bundle │ ├── assets/ # 静态资源 │ └── pages/ # 页面目录 ├── src/ # 源代码目录 │ ├── index.js # 主入口 │ ├── KuiklyMiniAppRenderViewDelegator.js # 渲染代理 │ ├── components/ # 自定义组件 │ ├── modules/ # 自定义模块 │ ├── libs/ # Kotlin/JS 库(需复制) │ └── bundles/ # 业务 bundle(需复制) ├── scripts/ # 构建脚本 ├── package.json └── webpack.config.js ``` -------------------------------- ### ActionSheet Usage Example Source: https://github.com/tencent-tds/kuiklyui/blob/main/docs/API/components/action-sheet.md Demonstrates how to use the ActionSheet component with its attributes and events. This example shows how to control the visibility of the ActionSheet and handle button clicks. ```APIDOC ## ActionSheet ### Description Provides a set of actions for users to choose from, mimicking the iOS UIActionSheet style and supporting custom dialog UI for bottom sheet scenarios. ### Attributes - **showActionSheet** (Boolean) - Required - Controls whether the ActionSheet is displayed. It does not occupy layout space when not displayed. - **descriptionOfActions** (String) - Optional - A short description of the actions available in the ActionSheet. - **actionButtons** (String...) - Required - Defines the action buttons, including an optional cancel button and a variable number of action titles. - **actionButtonsCustomAttr** (TextAttr.() -> Unit) - Optional - Allows customization of the text attributes for the cancel button and other action buttons. - **customContentView** (ViewContainer<*, *>.() -> Unit) - Optional - Replaces the default foreground view UI with a custom one. - **customBackgroundView** (ViewContainer<*, *>.() -> Unit) - Optional - Replaces the default background view UI with a custom one. The custom background view should be set to full screen size. - **inWindow** (Boolean) - Optional - Makes the ActionSheet display in full screen (defaults to false). ### Events - **clickActionButton** - Callback when an action button is clicked. The index of the clicked button is provided. - **clickBackgroundMask** - Callback when the background mask is clicked. Useful for closing the dialog in custom foreground UI scenarios. The callback parameter is [ClickParams](./basic-attr-event.md#click事件). - **alertDidExit** - Callback when the ActionSheet has completely exited (not displayed and animation finished). ### Example ```kotlin @Page("demo_page") internal class TestPage : BasePager() { private var showActionSheet by observable(true) override fun body(): ViewBuilder { val ctx = this return { ActionSheet { attr { showActionSheet(ctx.showActionSheet) descriptionOfActions("A short description of the actions") actionButtons("Cancel", "Action0", "Action1", "Action2", "Action3", "Action4") } event { clickActionButton { index -> ctx.showActionSheet = false } } } } } } ``` ``` -------------------------------- ### 发布 KLib 到 Maven 仓库 Source: https://github.com/tencent-tds/kuiklyui/blob/main/docs/DevGuide/compile_skills.md 使用 Gradle 命令将指定的模块(包含 KLib)发布到已配置的 Maven 仓库。 ```bash ./gradlew xxx:publish ``` -------------------------------- ### Example Scroll Context Event Log Source: https://github.com/tencent-tds/kuiklyui/blob/main/openspec/specs/profiler-context-events/spec.md An example of a scroll context event logged when a LazyColumn scrolls and the first visible item index changes, with the profiler enabled. ```json {"type":"scroll_context","listId":"feedsList","firstVisibleItemFrom":3,"firstVisibleItemTo":5,"visibleItemCount":7,"timestampMs":1776678700650} ``` -------------------------------- ### 在鸿蒙IDE中设置断点 Source: https://github.com/tencent-tds/kuiklyui/blob/main/docs/DevGuide/ohos-debug.md 通过命令行在鸿蒙IDE的LLDB窗口设置断点,指定文件和行号。 ```shell (lldb) breakpoint set --file foo.kt --line 12 ``` -------------------------------- ### Generated User Data Class Example Source: https://github.com/tencent-tds/kuiklyui/blob/main/docs/DevGuide/protobuf.md Example of a Kotlin data class generated by the Wire protocol buffer compiler. Note that this is auto-generated code and should not be edited directly. ```kotlin // Code generated by Wire protocol buffer compiler, do not edit. // Source: User in sample.proto @file:Suppress("DEPRECATION") ... /** * 用户信息 */ public class User( @field:WireField(...) public val id: Long = 0L, @field:WireField(...) public val name: String = "", @field:WireField(...) public val age: Int = 0, @field:WireField(...) public val gender: Gender = Gender.NOT_SPECIFIED, unknownFields: ByteString = ByteString.EMPTY, ) : Message(ADAPTER, unknownFields) { ... public companion object { @JvmField public val ADAPTER: ProtoAdapter = object : ProtoAdapter(...) {...} } } ``` -------------------------------- ### Run HarmonyOS Demo Build Script (Mac) Source: https://github.com/tencent-tds/kuiklyui/blob/main/README.md Execute this script in the KuiklyUI root directory on macOS to compile the HarmonyOS cross-platform product. ```bash ./2.0_ohos_demo_build.sh ``` -------------------------------- ### Example of TEST_PROTECT and TEST_ABORT Usage Source: https://github.com/tencent-tds/kuiklyui/blob/main/core-render-ohos/src/main/cpp/thirdparty/cJSON/tests/unity/README.md This example demonstrates how TEST_PROTECT and TEST_ABORT work together. If MyTest calls TEST_ABORT, control returns to TEST_PROTECT with a zero return value. ```c main() { if (TEST_PROTECT()) { MyTest(); } } ``` -------------------------------- ### Frame Animation Example (Height) Source: https://github.com/tencent-tds/kuiklyui/blob/main/docs/DevGuide/animation-property.md Animate component position (x, y) and size (width, height) using frame animations. This example animates the height of a component. The animation is controlled by a responsive variable bound to an animation curve. ```kotlin @Page("2") internal class TestPage : BasePager() { private var frameHeight by observable(100f) override fun body(): ViewBuilder { val ctx = this return { attr { allCenter() } View { attr { size(100f, ctx.frameHeight) backgroundColor(Color.GREEN) animate(Animation.linear(0.5f), ctx.frameHeight) } } } } override fun viewDidLayout() { super.viewDidLayout() frameHeight = 200f // 启动动画 } } ``` -------------------------------- ### Implementing Long Press Event Source: https://github.com/tencent-tds/kuiklyui/blob/main/docs/API/components/basic-attr-event.md Use the `longPress` event to trigger a callback when a component is long-pressed. The callback receives `LongPressParams` with coordinates and state (start, move, end). Listen for the 'start' state if only interested in the press initiation. ```kotlin internal class LongPresskEventPage : BasePager() { override fun body(): ViewBuilder { return { attr { allCenter() } View { attr { size(100f, 100f) } event { longPress { longPressParams -> val x = longPressParams.x val y = longPressParams.y val state = longPressParams.state // start | move | end } } } } } } ``` -------------------------------- ### Gradle 常见错误:制品缺少目标架构 Source: https://github.com/tencent-tds/kuiklyui/blob/main/docs/DevGuide/compile_skills.md 当 KMP 工程依赖的制品不包含目标平台所需的架构时,会导致 Sync 失败。例如,`kotlinx-coroutines-core:1.8.1` 不包含 Ohos 平台制品。 ```text :shared:ohosArm64Main: Could not resolve org.jetbrains.kotlinx:kotlinx-coroutines-core:1.8.1. Required by: project :shared ``` -------------------------------- ### Broken PointerInput Example with Unit Key Source: https://github.com/tencent-tds/kuiklyui/blob/main/docs/Compose/faq.md This example demonstrates a common mistake where pointerInput uses `Unit` as its key. This causes the closure to capture the initial state, leading to outdated values being used in gesture detection, such as always printing 0 for a counter. ```kotlin @Composable fun BrokenExample() { var count by remember { mutableStateOf(0) } Box( modifier = Modifier .size(100.dp) .background(Color.Blue) .pointerInput(Unit) { // ❌ key 为 Unit detectTapGestures { println("点击时 count = $count") // 永远打印 0 } } ) { Text("点击我,count = $count") } Button(onClick = { count++ }) { Text("增加 count (当前 = $count)") } } ``` -------------------------------- ### 构建 iOS 平台产物 (Framework) Source: https://github.com/tencent-tds/kuiklyui/blob/main/docs/DevGuide/compile_skills.md 使用 Gradle 命令构建 iOS 平台的发行版 XCFramework。所有模块将统一编译成一个 Framework。 ```bash ./gradlew :shared:podPublishReleaseXCFramework ``` -------------------------------- ### Profiler Control Source: https://github.com/tencent-tds/kuiklyui/blob/main/openspec/specs/recomposition-profiler-api/spec.md APIs to start, stop, and check the status of the Recomposition Profiler. ```APIDOC ## Profiler Control ### `RecompositionProfiler.start()` Starts the recomposition profiling. ### `RecompositionProfiler.stop()` Stops the recomposition profiling and releases resources. ### `RecompositionProfiler.isEnabled` Returns `true` if the profiler is currently enabled, `false` otherwise. ``` -------------------------------- ### Broken LazyColumn PointerInput Example with Unit Key Source: https://github.com/tencent-tds/kuiklyui/blob/main/docs/Compose/faq.md This example illustrates click event issues in LazyColumn due to `pointerInput(Unit)`. When list items are reused, the `pointerInput` closure retains the old item's data, causing incorrect actions like navigating to the wrong page or printing the wrong item name. ```kotlin @Composable fun BrokenListExample(items: List) { LazyColumn { items(items, key = { it.id }) { Row( modifier = Modifier .fillMaxWidth() .pointerInput(Unit) { // ❌ key 为 Unit,复用时闭包不更新 detectTapGestures { println("点击了: ${item.name}") // 可能打印旧 item 的 name navigateTo(item.id) // 可能跳转到错误的页面 } } ) { Text(item.name) } } } } ``` -------------------------------- ### Basic Usage Source: https://github.com/tencent-tds/kuiklyui/blob/main/docs/API/components/liquid-glass.md Demonstrates the fundamental implementation of the LiquidGlass component with basic attributes and a Text child. ```APIDOC ## Basic Usage ```kotlin import com.tencent.kuikly.core.views.LiquidGlass LiquidGlass { attr { height(60f) borderRadius(30f) } Text { attr { text("液态玻璃效果") } } } ``` ```