diff --git a/ArkUIKit/AppStorage/AppScope/app.json5 b/ArkUIKit/AppStorage/AppScope/app.json5 new file mode 100644 index 0000000000000000000000000000000000000000..0d37e7c5f416e6838c0f860a30fc1fdb6b871546 --- /dev/null +++ b/ArkUIKit/AppStorage/AppScope/app.json5 @@ -0,0 +1,24 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License") + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +{ + "app": { + "bundleName": "com.samples.appstorage", + "vendor": "example", + "versionCode": 1000000, + "versionName": "1.0.0", + "icon": "$media:layered_image", + "label": "$string:app_name" + } +} diff --git a/ArkUIKit/AppStorage/AppScope/resources/base/element/string.json b/ArkUIKit/AppStorage/AppScope/resources/base/element/string.json new file mode 100644 index 0000000000000000000000000000000000000000..3812124c10b5e979077eebf9dc2eee141ec0caf6 --- /dev/null +++ b/ArkUIKit/AppStorage/AppScope/resources/base/element/string.json @@ -0,0 +1,8 @@ +{ + "string": [ + { + "name": "app_name", + "value": "AppStorage" + } + ] +} diff --git a/ArkUIKit/AppStorage/AppScope/resources/base/media/background.png b/ArkUIKit/AppStorage/AppScope/resources/base/media/background.png new file mode 100644 index 0000000000000000000000000000000000000000..923f2b3f27e915d6871871deea0420eb45ce102f Binary files /dev/null and b/ArkUIKit/AppStorage/AppScope/resources/base/media/background.png differ diff --git a/ArkUIKit/AppStorage/AppScope/resources/base/media/foreground.png b/ArkUIKit/AppStorage/AppScope/resources/base/media/foreground.png new file mode 100644 index 0000000000000000000000000000000000000000..eb9427585b36d14b12477435b6419d1f07b3e0bb Binary files /dev/null and b/ArkUIKit/AppStorage/AppScope/resources/base/media/foreground.png differ diff --git a/ArkUIKit/AppStorage/AppScope/resources/base/media/layered_image.json b/ArkUIKit/AppStorage/AppScope/resources/base/media/layered_image.json new file mode 100644 index 0000000000000000000000000000000000000000..fb49920440fb4d246c82f9ada275e26123a2136a --- /dev/null +++ b/ArkUIKit/AppStorage/AppScope/resources/base/media/layered_image.json @@ -0,0 +1,7 @@ +{ + "layered-image": + { + "background" : "$media:background", + "foreground" : "$media:foreground" + } +} \ No newline at end of file diff --git a/ArkUIKit/AppStorage/README.md b/ArkUIKit/AppStorage/README.md new file mode 100644 index 0000000000000000000000000000000000000000..8f593d5a958e641595674f521cea97e04317b21f --- /dev/null +++ b/ArkUIKit/AppStorage/README.md @@ -0,0 +1,122 @@ +# arkts-appstorage + +## 介绍 + +AppStorage是在应用启动时创建的单例,用于提供应用状态数据的中心存储。这些状态数据在应用级别可访问。AppStorage在应用运行过程中保留其属性。 + +AppStorage中保存的属性通过唯一的字符串类型属性名(key)访问,该属性可以和UI组件同步,且可以在应用业务逻辑中被访问。 + +AppStorage支持应用的主线程内多个UIAbility实例间的UI状态数据共享。 + +AppStorage中的属性通过唯一的字符串类型key值访问,支持与UI组件同步,并可在应用业务逻辑中被访问。其支持应用的主线程内多个UIAbility实例间的UI状态数据共享。 + +[AppStorage:应用全局的UI状态存储](https://gitcode.com/openharmony/docs/blob/master/zh-cn/application-dev/ui/state-management/arkts-appstorage.md)。 + +## 效果预览 + +| 首页 | CustomDialogController_CAPI页面 | OpenCustomDialog_CAPI页面 | +|----------------------------------------------------|-----------------------------------------------------|----------------------------------------------------| +| | | | + +## 使用说明 + +1. 安装编译生成的hap包,并打开应用; +2. 首页面会出现页面列表,点击此列表项进入对应页面示例界面; + +## 工程目录 + +``` +PersistentStorage +entry +└── src + ├── main + │   ├── ets + │   │   ├── entryability + │   │   │   └── EntryAbility.ets + │   │   ├── entrybackupability + │   │   │   └── EntryBackupAbility.ets + │   │   └── pages + │   │   ├── Index.ets + │   │   ├── PageEight.ets //示例8:emit接口不支持在Previewer预览器中使用 + │   │   ├── PageFive.ets //示例5:装饰Map类型变量 + │   │   ├── PageFour.ets //示例4:装饰Date类型变量 + │   │   ├── PageNine.ets //示例9:三元表达式使用 + │   │   ├── PageOne.ets //示例1:从应用逻辑使用AppStorage和LocalStorage + │   │   ├── PageSeven.ets //示例7:不建议借助@StorageLink的双向同步机制实现事件通知 + │   │   ├── PageSix.ets //示例6:装饰Set类型变量 + │   │   ├── PageTen.ets //示例10:@StorageProp和AppStorage接口配合使用时,需要注意更新规则 + │   │   ├── PageThree.ets //示例3:AppStorage支持联合类型 + │   │   └── PageTwo.ets //示例2:从UI内部使用AppStorage + │   ├── module.json5 + │   └── resources + │   ├── base + │   │   ├── element + │   │   │   ├── color.json + │   │   │   ├── float.json + │   │   │   └── string.json + │   │   ├── media + │   │   │   ├── background.png + │   │   │   ├── foreground.png + │   │   │   ├── layered_image.json + │   │   │   └── startIcon.png + │   │   └── profile + │   │   ├── backup_config.json + │   │   └── main_pages.json + │   ├── dark + │   │   └── element + │   │   └── color.json + │   └── rawfile + ├── mock + │   └── mock-config.json5 + ├── ohosTest + │   ├── ets + │   │   └── test + │   │   ├── Ability.test.ets + │   │   ├── Index.test.ets + │   │   └── List.test.ets + │   └── module.json5 + │   └── ohosTest.md + └── test + ├── List.test.ets + └── LocalUnit.test.ets +``` +## 具体实现 + +1. AppStorage 基础初始化与数据操作实现:通过AppStorage.setOrCreate('propA', 47)初始化全局状态(键propA,值 47),支持跨主线程内多个 UIAbility 共享;通过AppStorage.get('propA')获取值,AppStorage.set('propA', 100)修改值,且操作仅作用于运行内存,应用重启后未持久化的数据会丢失。 +2. @StorageProp 单向同步实现:组件内用@StorageProp('propA') storageProp: number = 1绑定 AppStorage 的propA,本地可修改(如this.storageProp += 1)但不回传 AppStorage;当 AppStorage 中propA更新(如AppStorage.set('propA', 100)),storageProp会被覆盖并触发组件刷新,且禁止从父组件初始化该变量。 +3. @StorageLink 双向同步实现:组件内用@StorageLink('propA') storageLink: number = 1绑定 AppStorage 的propA,本地修改(如this.storageLink += 1)会同步回 AppStorage;AppStorage 中propA更新时,所有绑定该键的@StorageLink和@StorageProp变量均会同步刷新,支持初始化子组件的@State/@Prop等状态。 +4. 联合类型(含 null/undefined)同步实现:API 12 + 支持@StorageLink('linkA') linkA: number | null = null或@StorageProp('propB') propB: number | undefined = undefined;点击文本可切换值(如this.linkA ? this.linkA = null : this.linkA = 1),值变化会同步(双向 / 单向)至 AppStorage,UI 实时展示当前类型值。 +5. Date 类型同步实现:API 12 + 支持@StorageLink('date') selectedDate: Date = new Date('2021-08-08');通过this.selectedDate.setFullYear(this.selectedDate.getFullYear() + 1)修改日期属性,或AppStorage.setOrCreate('date', new Date('2023-07-08'))直接更新 AppStorage,两者均能触发DatePicker组件 UI 刷新。 +6. Map 类型同步实现:API 12 + 支持@StorageLink('map') message: Map = new Map([[0, 'a']]);通过this.message.set(4, 'd')(添加键值对)、this.message.clear()(清空)、AppStorage.get>('map')?.delete(0)(删除键)修改 Map,用ForEach(Array.from(this.message.entries()), ...)遍历展示,修改同步触发 UI 更新。 +7. Set 类型同步实现:API 12 + 支持@StorageLink('set') memberSet: Set = new Set([0,1,2]);通过this.memberSet.add(5)(新增元素)、this.memberSet.delete(0)(删除元素)、AppStorage.get>('set')?.clear()(清空)修改 Set,遍历Array.from(this.memberSet.entries())展示,修改同步至 AppStorage 并刷新 UI。 +8. 与 LocalStorage 隔离使用实现:创建let storage: LocalStorage = new LocalStorage()实例,用storage.setOrCreate('propA', 17)初始化;AppStorage 与 LocalStorage 同名键(如propA)相互独立,AppStorage.get('propA')返回 47,storage.get('propA')返回 17,修改各自存储的值不影响对方。 +9. 避免 @StorageLink 事件通知性能问题实现:不使用@StorageLink双向同步传递事件(避免多组件不必要刷新),改用emitter接口;通过emitter.on(innerEvent, data => {...})订阅事件,emitter.emit(innerEvent, eventData)发送事件,仅目标组件接收回调,减少 UI 刷新开销(如 Gallery 图片选中态切换场景)。 +10. @StorageProp 与 AppStorage 同步一致性实现:若本地修改@StorageProp(如this.propA = true)后,用AppStorage.setOrCreate('propA', false)更新时,因 AppStorage 原值与新值相同,不会触发@StorageProp刷新;需改为@StorageLink(本地修改同步回 AppStorage),或直接通过AppStorage.setOrCreate('propA', true)修改,确保两者值一致。 + +## 相关权限 + +不涉及 + +## 依赖 + +不涉及 + +## 约束和限制 + +1. 本示例支持标准系统上运行,支持设备:RK3568等; + +2. 本示例支持API20版本SDK,版本号:6.0.0.36; + +3. 本示例已支持使DevEco Studio 6.0.0.848 (构建版本:6.0.0.848,构建 2025年10月17日)编译运行 + +## 下载 + +如需单独下载本工程,执行如下命令: + +``` +git init +git config core.sparsecheckout true +echo code/DocsSample/ArkUISample/Prop > .git/info/sparse-checkout +git remote add origin https://gitcode.com/openharmony/applications_app_samples.git +git pull origin master +``` diff --git a/ArkUIKit/AppStorage/build-profile.json5 b/ArkUIKit/AppStorage/build-profile.json5 new file mode 100644 index 0000000000000000000000000000000000000000..4f49e981b594b55098a5ea4a760b1fa21cf3d517 --- /dev/null +++ b/ArkUIKit/AppStorage/build-profile.json5 @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License") + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +{ + "app": { + "signingConfigs": [], + "products": [ + { + "name": "default", + "signingConfig": "default", + "compileSdkVersion": "6.0.0(20)", + "compatibleSdkVersion": "6.0.0(20)", + "targetSdkVersion": "6.0.0(20)", + "runtimeOS": "HarmonyOS", + "buildOption": { + "strictMode": { + "caseSensitiveCheck": true, + "useNormalizedOHMUrl": true + } + } + } + ], + "buildModeSet": [ + { + "name": "debug", + }, + { + "name": "release" + } + ] + }, + "modules": [ + { + "name": "entry", + "srcPath": "./entry", + "targets": [ + { + "name": "default", + "applyToProducts": [ + "default" + ] + } + ] + } + ] +} \ No newline at end of file diff --git a/ArkUIKit/AppStorage/code-linter.json5 b/ArkUIKit/AppStorage/code-linter.json5 new file mode 100644 index 0000000000000000000000000000000000000000..6cb87c1af6693671ede1a49f7f674815355ff099 --- /dev/null +++ b/ArkUIKit/AppStorage/code-linter.json5 @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License") + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +{ + "files": [ + "**/*.ets" + ], + "ignore": [ + "**/src/ohosTest/**/*", + "**/src/test/**/*", + "**/src/mock/**/*", + "**/node_modules/**/*", + "**/oh_modules/**/*", + "**/build/**/*", + "**/.preview/**/*" + ], + "ruleSet": [ + "plugin:@performance/recommended", + "plugin:@typescript-eslint/recommended" + ], + "rules": { + "@security/no-unsafe-aes": "error", + "@security/no-unsafe-hash": "error", + "@security/no-unsafe-mac": "warn", + "@security/no-unsafe-dh": "error", + "@security/no-unsafe-dsa": "error", + "@security/no-unsafe-ecdsa": "error", + "@security/no-unsafe-rsa-encrypt": "error", + "@security/no-unsafe-rsa-sign": "error", + "@security/no-unsafe-rsa-key": "error", + "@security/no-unsafe-dsa-key": "error", + "@security/no-unsafe-dh-key": "error", + "@security/no-unsafe-3des": "error" + } +} \ No newline at end of file diff --git a/ArkUIKit/AppStorage/entry/build-profile.json5 b/ArkUIKit/AppStorage/entry/build-profile.json5 new file mode 100644 index 0000000000000000000000000000000000000000..af77abd78144beb0666cf710cea03f508d928a72 --- /dev/null +++ b/ArkUIKit/AppStorage/entry/build-profile.json5 @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License") + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +{ + "apiType": "stageMode", + "buildOption": { + "resOptions": { + "copyCodeResource": { + "enable": false + } + } + }, + "buildOptionSet": [ + { + "name": "release", + "arkOptions": { + "obfuscation": { + "ruleOptions": { + "enable": false, + "files": [ + "./obfuscation-rules.txt" + ] + } + } + } + }, + ], + "targets": [ + { + "name": "default" + }, + { + "name": "ohosTest", + } + ] +} \ No newline at end of file diff --git a/ArkUIKit/AppStorage/entry/hvigorfile.ts b/ArkUIKit/AppStorage/entry/hvigorfile.ts new file mode 100644 index 0000000000000000000000000000000000000000..9fc0299a6a5a402afd6824bcaead14cfeb32ccf2 --- /dev/null +++ b/ArkUIKit/AppStorage/entry/hvigorfile.ts @@ -0,0 +1,20 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License") + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +import { hapTasks } from '@ohos/hvigor-ohos-plugin'; + +export default { + system: hapTasks, /* Built-in plugin of Hvigor. It cannot be modified. */ + plugins: [] /* Custom plugin to extend the functionality of Hvigor. */ +} \ No newline at end of file diff --git a/ArkUIKit/AppStorage/entry/obfuscation-rules.txt b/ArkUIKit/AppStorage/entry/obfuscation-rules.txt new file mode 100644 index 0000000000000000000000000000000000000000..272efb6ca3f240859091bbbfc7c5802d52793b0b --- /dev/null +++ b/ArkUIKit/AppStorage/entry/obfuscation-rules.txt @@ -0,0 +1,23 @@ +# Define project specific obfuscation rules here. +# You can include the obfuscation configuration files in the current module's build-profile.json5. +# +# For more details, see +# https://developer.huawei.com/consumer/cn/doc/harmonyos-guides-V5/source-obfuscation-V5 + +# Obfuscation options: +# -disable-obfuscation: disable all obfuscations +# -enable-property-obfuscation: obfuscate the property names +# -enable-toplevel-obfuscation: obfuscate the names in the global scope +# -compact: remove unnecessary blank spaces and all line feeds +# -remove-log: remove all console.* statements +# -print-namecache: print the name cache that contains the mapping from the old names to new names +# -apply-namecache: reuse the given cache file + +# Keep options: +# -keep-property-name: specifies property names that you want to keep +# -keep-global-name: specifies names that you want to keep in the global scope + +-enable-property-obfuscation +-enable-toplevel-obfuscation +-enable-filename-obfuscation +-enable-export-obfuscation \ No newline at end of file diff --git a/ArkUIKit/AppStorage/entry/oh-package.json5 b/ArkUIKit/AppStorage/entry/oh-package.json5 new file mode 100644 index 0000000000000000000000000000000000000000..a74009c338e9a8cbffa43098b7165042718d2b89 --- /dev/null +++ b/ArkUIKit/AppStorage/entry/oh-package.json5 @@ -0,0 +1,24 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License") + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +{ + "name": "entry", + "version": "1.0.0", + "description": "Please describe the basic information.", + "main": "", + "author": "", + "license": "", + "dependencies": {} +} + diff --git a/ArkUIKit/AppStorage/entry/src/main/ets/entryability/EntryAbility.ets b/ArkUIKit/AppStorage/entry/src/main/ets/entryability/EntryAbility.ets new file mode 100644 index 0000000000000000000000000000000000000000..14c680ebc7189c91627dde9cfbb0e14157de759d --- /dev/null +++ b/ArkUIKit/AppStorage/entry/src/main/ets/entryability/EntryAbility.ets @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License") + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +import { AbilityConstant, ConfigurationConstant, UIAbility, Want } from '@kit.AbilityKit'; +import { hilog } from '@kit.PerformanceAnalysisKit'; +import { window } from '@kit.ArkUI'; + +const DOMAIN = 0x0000; + +export default class EntryAbility extends UIAbility { + onCreate(want: Want, launchParam: AbilityConstant.LaunchParam): void { + try { + this.context.getApplicationContext().setColorMode(ConfigurationConstant.ColorMode.COLOR_MODE_NOT_SET); + } catch (err) { + hilog.error(DOMAIN, 'testTag', 'Failed to set colorMode. Cause: %{public}s', JSON.stringify(err)); + } + hilog.info(DOMAIN, 'testTag', '%{public}s', 'Ability onCreate'); + } + + onDestroy(): void { + hilog.info(DOMAIN, 'testTag', '%{public}s', 'Ability onDestroy'); + } + + onWindowStageCreate(windowStage: window.WindowStage): void { + // Main window is created, set main page for this ability + hilog.info(DOMAIN, 'testTag', '%{public}s', 'Ability onWindowStageCreate'); + + windowStage.loadContent('pages/Index', (err) => { + if (err.code) { + hilog.error(DOMAIN, 'testTag', 'Failed to load the content. Cause: %{public}s', JSON.stringify(err)); + return; + } + hilog.info(DOMAIN, 'testTag', 'Succeeded in loading the content.'); + }); + } + + onWindowStageDestroy(): void { + // Main window is destroyed, release UI related resources + hilog.info(DOMAIN, 'testTag', '%{public}s', 'Ability onWindowStageDestroy'); + } + + onForeground(): void { + // Ability has brought to foreground + hilog.info(DOMAIN, 'testTag', '%{public}s', 'Ability onForeground'); + } + + onBackground(): void { + // Ability has back to background + hilog.info(DOMAIN, 'testTag', '%{public}s', 'Ability onBackground'); + } +} \ No newline at end of file diff --git a/ArkUIKit/AppStorage/entry/src/main/ets/entrybackupability/EntryBackupAbility.ets b/ArkUIKit/AppStorage/entry/src/main/ets/entrybackupability/EntryBackupAbility.ets new file mode 100644 index 0000000000000000000000000000000000000000..93f99a4842fe306c624f55ca9b40afd3921f325d --- /dev/null +++ b/ArkUIKit/AppStorage/entry/src/main/ets/entrybackupability/EntryBackupAbility.ets @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License") + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +import { hilog } from '@kit.PerformanceAnalysisKit'; +import { BackupExtensionAbility, BundleVersion } from '@kit.CoreFileKit'; + +const DOMAIN = 0x0000; + +export default class EntryBackupAbility extends BackupExtensionAbility { + async onBackup() { + hilog.info(DOMAIN, 'testTag', 'onBackup ok'); + await Promise.resolve(); + } + + async onRestore(bundleVersion: BundleVersion) { + hilog.info(DOMAIN, 'testTag', 'onRestore ok %{public}s', JSON.stringify(bundleVersion)); + await Promise.resolve(); + } +} \ No newline at end of file diff --git a/ArkUIKit/AppStorage/entry/src/main/ets/pages/Index.ets b/ArkUIKit/AppStorage/entry/src/main/ets/pages/Index.ets new file mode 100644 index 0000000000000000000000000000000000000000..21c8b38d77324335caea079e8ffbaa1e91e21de8 --- /dev/null +++ b/ArkUIKit/AppStorage/entry/src/main/ets/pages/Index.ets @@ -0,0 +1,77 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License") + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { router } from '@kit.ArkUI'; +interface Ary { + path:string, + name:string +} +@Entry +@Component +struct Index { + ary:Ary[]=[ + { + name:'PageOne', + path:'pages/PageOne' + }, + { + name:'PageTwo', + path:'pages/PageTwo' + }, + { + name:'PageThree', + path:'pages/PageThree' + }, + { + name:'PageFour', + path:'pages/PageFour' + }, + { + name:'PageFive', + path:'pages/PageFive' + }, + { + name:'PageSix', + path:'pages/PageSix' + }, + { + name:'PageSeven', + path:'pages/PageSeven' + }, + { + name:'PageEight', + path:'pages/PageEight' + }, + { + name:'PageNine', + path:'pages/PageNine' + }, + { + name:'PageTen', + path:'pages/PageTen' + }, + ] + build() { + Scroll() { + Column({ space: 2 }) { + ForEach(this.ary,(item:Ary)=>{ + Button(item.name) + .onClick(() => this.getUIContext().getRouter().pushUrl({ url: item.path })) + },(item:Ary)=>item.name) + } + .width('100%') + } + } +} diff --git a/ArkUIKit/AppStorage/entry/src/main/ets/pages/PageEight.ets b/ArkUIKit/AppStorage/entry/src/main/ets/pages/PageEight.ets new file mode 100644 index 0000000000000000000000000000000000000000..579ad17d06243c133c1db7baae6c7aa71d2db67a --- /dev/null +++ b/ArkUIKit/AppStorage/entry/src/main/ets/pages/PageEight.ets @@ -0,0 +1,116 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License") + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { emitter } from '@kit.BasicServicesKit'; + +let nextId: number = 0; + +class ViewData { + public title: string; + public uri: Resource; + public color: Color = Color.Black; + public id: number; + + constructor(title: string, uri: Resource) { + this.title = title; + this.uri = uri; + this.id = nextId++; + } +} + +@Entry +@Component +struct Gallery { + //$r('app.media.startIcon')需要替换为开发者所需的资源文件; + dataList: Array = [new ViewData('flower', $r('app.media.startIcon')), new ViewData('OMG', $r('app.media.startIcon')), new ViewData('OMG', $r('app.media.startIcon'))]; + scroller: Scroller = new Scroller(); + private preIndex: number = -1; + + build() { + Column() { + Grid(this.scroller) { + ForEach(this.dataList, (item: ViewData) => { + GridItem() { + TapImage({ + uri: item.uri, + index: item.id + }) + }.aspectRatio(1) + .onClick(() => { + if (this.preIndex === item.id) { + return; + } + let innerEvent: emitter.InnerEvent = { eventId: item.id }; + // 选中态:黑变红 + let eventData: emitter.EventData = { + data: { + 'colorTag': 1 + } + }; + emitter.emit(innerEvent, eventData); + + if (this.preIndex != -1) { + console.info(`preIndex: ${this.preIndex}, index: ${item.id}, black`); + let innerEvent: emitter.InnerEvent = { eventId: this.preIndex }; + // 取消选中态:红变黑 + let eventData: emitter.EventData = { + data: { + 'colorTag': 0 + } + }; + emitter.emit(innerEvent, eventData); + } + this.preIndex = item.id; + }) + }, (item: ViewData) => JSON.stringify(item)) + }.columnsTemplate('1fr 1fr') + } + + } +} + +@Component +export struct TapImage { + @State tapColor: Color = Color.Black; + private index: number = 0; + private uri: Resource = { + id: 0, + type: 0, + moduleName: '', + bundleName: '' + }; + + onTapIndexChange(colorTag: emitter.EventData) { + if (colorTag.data != null) { + this.tapColor = colorTag.data.colorTag ? Color.Red : Color.Black; + } + } + + aboutToAppear() { + //定义事件ID + let innerEvent: emitter.InnerEvent = { eventId: this.index }; + emitter.on(innerEvent, data => { + this.onTapIndexChange(data); + }); + } + + build() { + Column() { + Image(this.uri) + .objectFit(ImageFit.Cover) + .border({ width: 5, style: BorderStyle.Dotted, color: this.tapColor }) + } + } +} \ No newline at end of file diff --git a/ArkUIKit/AppStorage/entry/src/main/ets/pages/PageFive.ets b/ArkUIKit/AppStorage/entry/src/main/ets/pages/PageFive.ets new file mode 100644 index 0000000000000000000000000000000000000000..62e0b54c9803c3c6e7fadce5335344fed378a997 --- /dev/null +++ b/ArkUIKit/AppStorage/entry/src/main/ets/pages/PageFive.ets @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License") + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +@Entry +@Component +struct MapSample { + @StorageLink('map') message: Map = new Map([[0, 'a'], [1, 'b'], [3, 'c']]); + + build() { + Row() { + Column() { + ForEach(Array.from(this.message.entries()), (item: [number, string]) => { + Text(`${item[0]}`).fontSize(30) + Text(`${item[1]}`).fontSize(30) + Divider() + }) + Button('init map').onClick(() => { + this.message = new Map([[0, 'a'], [1, 'b'], [3, 'c']]); + }) + Button('set new one').onClick(() => { + this.message.set(4, 'd'); + }) + Button('clear').onClick(() => { + this.message.clear(); + }) + Button('replace the existing one').onClick(() => { + this.message.set(0, 'aa'); + }) + Button('delete the existing one').onClick(() => { + AppStorage.get>('map')?.delete(0); + }) + } + .width('100%') + } + .height('100%') + } +} \ No newline at end of file diff --git a/ArkUIKit/AppStorage/entry/src/main/ets/pages/PageFour.ets b/ArkUIKit/AppStorage/entry/src/main/ets/pages/PageFour.ets new file mode 100644 index 0000000000000000000000000000000000000000..e4c01129dbb44419cb3f3dcd8afac9bf27f5a6db --- /dev/null +++ b/ArkUIKit/AppStorage/entry/src/main/ets/pages/PageFour.ets @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License") + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +@Entry +@Component +struct DateSample { + @StorageLink('date') selectedDate: Date = new Date('2021-08-08'); + + build() { + Column() { + Button('set selectedDate to 2023-07-08') + .margin(10) + .onClick(() => { + AppStorage.setOrCreate('date', new Date('2023-07-08')); + }) + Button('increase the year by 1') + .margin(10) + .onClick(() => { + this.selectedDate.setFullYear(this.selectedDate.getFullYear() + 1); + }) + Button('increase the month by 1') + .margin(10) + .onClick(() => { + this.selectedDate.setMonth(this.selectedDate.getMonth() + 1); + }) + Button('increase the day by 1') + .margin(10) + .onClick(() => { + this.selectedDate.setDate(this.selectedDate.getDate() + 1); + }) + DatePicker({ + start: new Date('1970-1-1'), + end: new Date('2100-1-1'), + selected: $$this.selectedDate + }) + }.width('100%') + } +} \ No newline at end of file diff --git a/ArkUIKit/AppStorage/entry/src/main/ets/pages/PageNine.ets b/ArkUIKit/AppStorage/entry/src/main/ets/pages/PageNine.ets new file mode 100644 index 0000000000000000000000000000000000000000..dc1ccbb93b72ce5d4b70b7bdc330931436ed4e68 --- /dev/null +++ b/ArkUIKit/AppStorage/entry/src/main/ets/pages/PageNine.ets @@ -0,0 +1,79 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License") + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +// xxx.ets +class ViewData { + public title: string; + public uri: Resource; + public color: Color = Color.Black; + + constructor(title: string, uri: Resource) { + this.title = title; + this.uri = uri; + } +} + +@Entry +@Component +struct Gallery { + //$r('app.media.startIcon')需要替换为开发者所需的资源文件; + dataList: Array = [new ViewData('flower', $r('app.media.startIcon')), new ViewData('OMG', $r('app.media.startIcon')), new ViewData('OMG', $r('app.media.startIcon'))]; + scroller: Scroller = new Scroller(); + + build() { + Column() { + Grid(this.scroller) { + ForEach(this.dataList, (item: ViewData, index?: number) => { + GridItem() { + TapImage({ + uri: item.uri, + index: index + }) + }.aspectRatio(1) + + }, (item: ViewData, index?: number) => { + return JSON.stringify(item) + index; + }) + }.columnsTemplate('1fr 1fr') + } + + } +} + +@Component +export struct TapImage { + @StorageLink('tapIndex') tapIndex: number = -1; + private index: number = 0; + private uri: Resource = { + id: 0, + type: 0, + moduleName: '', + bundleName: '' + }; + + build() { + Column() { + Image(this.uri) + .objectFit(ImageFit.Cover) + .onClick(() => { + this.tapIndex = this.index; + }) + .border({ + width: 5, + style: BorderStyle.Dotted, + color: (this.tapIndex >= 0 && this.index === this.tapIndex) ? Color.Red : Color.Black + }) + } + } +} \ No newline at end of file diff --git a/ArkUIKit/AppStorage/entry/src/main/ets/pages/PageOne.ets b/ArkUIKit/AppStorage/entry/src/main/ets/pages/PageOne.ets new file mode 100644 index 0000000000000000000000000000000000000000..0936bf6b298c07914b6da046c54d43881f0d2f78 --- /dev/null +++ b/ArkUIKit/AppStorage/entry/src/main/ets/pages/PageOne.ets @@ -0,0 +1,153 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License") + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +@Entry +@Component +struct StorageDemoPage { + // 存储实例与关联对象 + private storage: LocalStorage = new LocalStorage(); + private link1: SubscribedAbstractProperty = AppStorage.link('propA'); + private link2: SubscribedAbstractProperty = AppStorage.link('propA'); + private prop: SubscribedAbstractProperty = AppStorage.prop('propA'); + + // 状态变量用于UI展示 + @State appPropA: number = 0; + @State localPropA: number = 0; + @State link1Val: number = 0; + @State link2Val: number = 0; + @State propVal: number = 0; + + aboutToAppear() { + // 初始化存储 + AppStorage.setOrCreate('propA', 47); + this.storage.setOrCreate('propA', 17); + this.updateDisplayValues(); + } + + // 更新UI展示值 + private updateDisplayValues() { + this.appPropA = AppStorage.get('propA')!; + this.localPropA = this.storage.get('propA')!; + this.link1Val = this.link1.get(); + this.link2Val = this.link2.get(); + this.propVal = this.prop.get(); + } + + build() { + List() { + // 标题 + ListItem() { + Text('存储同步演示') + .fontSize(20) + .fontWeight(FontWeight.Bold) + .padding(10) + } + + // AppStorage区域 + ListItem() { + List() { + ListItem() { + Text('AppStorage (propA)') + .fontSize(18) + .fontColor('#0066CC') + .padding(5) + } + ListItem() { + Text(`当前值: ${this.appPropA}`) + .padding({ left: 10 }) + } + ListItem() { + Text(`link1: ${this.link1Val} | link2: ${this.link2Val} | prop: ${this.propVal}`) + .fontSize(14) + .padding({ left: 10 }) + } + ListItem() { + List({ space: 5 }) { + ListItem() { + Button('link1.set(48)') + .onClick(() => { + this.link1.set(48); + this.updateDisplayValues(); + }) + .backgroundColor('#0066CC') + .fontSize(12) + } + ListItem() { + Button('prop.set(1)') + .onClick(() => { + this.prop.set(1); + this.updateDisplayValues(); + }) + .backgroundColor('#0066CC') + .fontSize(12) + } + ListItem() { + Button('link1.set(49)') + .onClick(() => { + this.link1.set(49); + this.updateDisplayValues(); + }) + .backgroundColor('#0066CC') + .fontSize(12) + } + } + .padding({ left: 10, top: 5, bottom: 5 }) + } + } + .backgroundColor('#FFFFFF') + .borderRadius(5) + .margin(5) + } + + // LocalStorage区域 + ListItem() { + List() { + ListItem() { + Text('LocalStorage (propA)') + .fontSize(18) + .fontColor('#FF6600') + .padding(5) + } + ListItem() { + Text(`当前值: ${this.localPropA}`) + .padding({ left: 10 }) + } + ListItem() { + Button('storage.set(101)') + .onClick(() => { + this.storage.set('propA', 101); + this.localPropA = this.storage.get('propA')!; + }) + .backgroundColor('#FF6600') + .fontSize(12) + .padding({ left: 10, top: 5, bottom: 5 }) + } + } + .backgroundColor('#FFFFFF') + .borderRadius(5) + .margin(5) + } + + // 同步规则说明 + ListItem() { + Text('规则:\n1. AppStorage与LocalStorage独立\n2. link双向同步,prop单向同步') + .fontSize(14) + .padding(10) + } + } + .width('100%') + .height('100%') + .backgroundColor('#F5F5F5') + } +} \ No newline at end of file diff --git a/ArkUIKit/AppStorage/entry/src/main/ets/pages/PageSeven.ets b/ArkUIKit/AppStorage/entry/src/main/ets/pages/PageSeven.ets new file mode 100644 index 0000000000000000000000000000000000000000..8eff0a8ee8b0f546b025cc0ee4e1d18a2fc152cc --- /dev/null +++ b/ArkUIKit/AppStorage/entry/src/main/ets/pages/PageSeven.ets @@ -0,0 +1,88 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License") + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +// xxx.ets +class ViewData { + public title: string; + public uri: Resource; + public color: Color = Color.Black; + + constructor(title: string, uri: Resource) { + this.title = title; + this.uri = uri; + } +} + +@Entry +@Component +struct Gallery { + //$r('app.media.startIcon')需要替换为开发者所需的资源文件; + dataList: Array = [new ViewData('flower', $r('app.media.startIcon')), new ViewData('OMG', $r('app.media.startIcon')), new ViewData('OMG', $r('app.media.startIcon'))]; + scroller: Scroller = new Scroller(); + + build() { + Column() { + Grid(this.scroller) { + ForEach(this.dataList, (item: ViewData, index?: number) => { + GridItem() { + TapImage({ + uri: item.uri, + index: index + }) + }.aspectRatio(1) + + }, (item: ViewData, index?: number) => { + return JSON.stringify(item) + index; + }) + }.columnsTemplate('1fr 1fr') + } + + } +} + +@Component +export struct TapImage { + @StorageLink('tapIndex') @Watch('onTapIndexChange') tapIndex: number = -1; + @State tapColor: Color = Color.Black; + private index: number = 0; + private uri: Resource = { + id: 0, + type: 0, + moduleName: '', + bundleName: '' + }; + + // 判断是否被选中 + onTapIndexChange() { + if (this.tapIndex >= 0 && this.index === this.tapIndex) { + console.info(`tapindex: ${this.tapIndex}, index: ${this.index}, red`); + this.tapColor = Color.Red; + } else { + console.info(`tapindex: ${this.tapIndex}, index: ${this.index}, black`); + this.tapColor = Color.Black; + } + } + + build() { + Column() { + Image(this.uri) + .objectFit(ImageFit.Cover) + .onClick(() => { + this.tapIndex = this.index; + }) + .border({ width: 5, style: BorderStyle.Dotted, color: this.tapColor }) + } + + } +} \ No newline at end of file diff --git a/ArkUIKit/AppStorage/entry/src/main/ets/pages/PageSix.ets b/ArkUIKit/AppStorage/entry/src/main/ets/pages/PageSix.ets new file mode 100644 index 0000000000000000000000000000000000000000..6a3f7ebec4a8ef7435251aefdfdb13f9beb00931 --- /dev/null +++ b/ArkUIKit/AppStorage/entry/src/main/ets/pages/PageSix.ets @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License") + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +@Entry +@Component +struct SetSample { + @StorageLink('set') memberSet: Set = new Set([0, 1, 2, 3, 4]); + + build() { + Row() { + Column() { + ForEach(Array.from(this.memberSet.entries()), (item: [number, number]) => { + Text(`${item[0]}`) + .fontSize(30) + Divider() + }) + Button('init set') + .onClick(() => { + this.memberSet = new Set([0, 1, 2, 3, 4]); + }) + Button('set new one') + .onClick(() => { + AppStorage.get>('set')?.add(5); + }) + Button('clear') + .onClick(() => { + this.memberSet.clear(); + }) + Button('delete the first one') + .onClick(() => { + this.memberSet.delete(0); + }) + } + .width('100%') + } + .height('100%') + } +} \ No newline at end of file diff --git a/ArkUIKit/AppStorage/entry/src/main/ets/pages/PageTen.ets b/ArkUIKit/AppStorage/entry/src/main/ets/pages/PageTen.ets new file mode 100644 index 0000000000000000000000000000000000000000..c1b90074a824e8bd64f289340414cb9935ee4e75 --- /dev/null +++ b/ArkUIKit/AppStorage/entry/src/main/ets/pages/PageTen.ets @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License") + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +AppStorage.setOrCreate('propA', false); + +@Entry +@Component +struct PageTenIndex { + @StorageProp('propA') @Watch('onChange') propA: boolean = false; + + onChange() { + console.info(`propA change`); + } + + aboutToAppear(): void { + this.propA = true; + } + + build() { + Column() { + Text(`${this.propA}`) + Button('change') + .onClick(() => { + AppStorage.setOrCreate('propA', false); + console.info(`propA: ${this.propA}`); + }) + } + } +} \ No newline at end of file diff --git a/ArkUIKit/AppStorage/entry/src/main/ets/pages/PageThree.ets b/ArkUIKit/AppStorage/entry/src/main/ets/pages/PageThree.ets new file mode 100644 index 0000000000000000000000000000000000000000..f8816488d21049d0774ad352f6495c60a9453e5b --- /dev/null +++ b/ArkUIKit/AppStorage/entry/src/main/ets/pages/PageThree.ets @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License") + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +@Component +struct StorageLinkComponent { + @StorageLink('linkA') linkA: number | null = null; + @StorageLink('linkB') linkB: number | undefined = undefined; + + build() { + Column() { + Text('@StorageLink接口初始化,@StorageLink取值') + Text(`${this.linkA}`).fontSize(20).onClick(() => { + this.linkA ? this.linkA = null : this.linkA = 1; + }) + Text(`${this.linkB}`).fontSize(20).onClick(() => { + this.linkB ? this.linkB = undefined : this.linkB = 1; + }) + } + .borderWidth(3).borderColor(Color.Red) + } +} + +@Component +struct StoragePropComponent { + @StorageProp('propA') propA: number | null = null; + @StorageProp('propB') propB: number | undefined = undefined; + + build() { + Column() { + Text('@StorageProp接口初始化,@StorageProp取值') + Text(`${this.propA}`).fontSize(20).onClick(() => { + this.propA ? this.propA = null : this.propA = 1; + }) + Text(`${this.propB}`).fontSize(20).onClick(() => { + this.propB ? this.propB = undefined : this.propB = 1; + }) + } + .borderWidth(3).borderColor(Color.Blue) + } +} + +@Entry +@Component +struct TestPageThree { + build() { + Row() { + Column() { + StorageLinkComponent() + StoragePropComponent() + } + .width('100%') + } + .height('100%') + } +} \ No newline at end of file diff --git a/ArkUIKit/AppStorage/entry/src/main/ets/pages/PageTwo.ets b/ArkUIKit/AppStorage/entry/src/main/ets/pages/PageTwo.ets new file mode 100644 index 0000000000000000000000000000000000000000..2c1e3b769137f7bdd0eec7ea7164f3a3c1488308 --- /dev/null +++ b/ArkUIKit/AppStorage/entry/src/main/ets/pages/PageTwo.ets @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License") + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +class Data { + public code: number; + + constructor(code: number) { + this.code = code; + } +} + +AppStorage.setOrCreate('propA', 47); +AppStorage.setOrCreate('propB', new Data(50)); +let storage = new LocalStorage(); +storage.setOrCreate('linkA', 48); +storage.setOrCreate('linkB', new Data(100)); + +@Entry(storage) +@Component +struct TestPageTow { + @StorageLink('propA') storageLink: number = 1; + @StorageProp('propA') storageProp: number = 1; + @StorageLink('propB') storageLinkObject: Data = new Data(1); + @StorageProp('propB') storagePropObject: Data = new Data(1); + + build() { + Column({ space: 20 }) { + // @StorageLink与AppStorage建立双向联系,更改数据会同步回AppStorage中key为'propA'的值 + Text(`storageLink ${this.storageLink}`) + .onClick(() => { + this.storageLink += 1; + }) + + // @StorageProp与AppStorage建立单向联系,更改数据不会同步回AppStorage中key为'propA'的值 + // 但能被AppStorage的set/setorCreate更新值 + Text(`storageProp ${this.storageProp}`) + .onClick(() => { + this.storageProp += 1; + }) + + // AppStorage的API虽然能获取值,但是不具有刷新UI的能力,日志能看到数值更改 + // 依赖@StorageLink/@StorageProp才能建立起与自定义组件的联系,刷新UI + Text(`change by AppStorage: ${AppStorage.get('propA')}`) + .onClick(() => { + console.info(`Appstorage.get: ${AppStorage.get('propA')}`); + AppStorage.set('propA', 100); + }) + + Text(`storageLinkObject ${this.storageLinkObject.code}`) + .onClick(() => { + this.storageLinkObject.code += 1; + }) + + Text(`storagePropObject ${this.storagePropObject.code}`) + .onClick(() => { + this.storagePropObject.code += 1; + }) + } + } +} \ No newline at end of file diff --git a/ArkUIKit/AppStorage/entry/src/main/module.json5 b/ArkUIKit/AppStorage/entry/src/main/module.json5 new file mode 100644 index 0000000000000000000000000000000000000000..bf022479e1543f8b4896722d2828b13d1efc47f8 --- /dev/null +++ b/ArkUIKit/AppStorage/entry/src/main/module.json5 @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License") + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +{ + "module": { + "name": "entry", + "type": "entry", + "description": "$string:module_desc", + "mainElement": "EntryAbility", + "deviceTypes": [ + "default" + ], + "deliveryWithInstall": true, + "installationFree": false, + "pages": "$profile:main_pages", + "abilities": [ + { + "name": "EntryAbility", + "srcEntry": "./ets/entryability/EntryAbility.ets", + "description": "$string:EntryAbility_desc", + "icon": "$media:layered_image", + "label": "$string:EntryAbility_label", + "startWindowIcon": "$media:startIcon", + "startWindowBackground": "$color:start_window_background", + "exported": true, + "skills": [ + { + "entities": [ + "entity.system.home" + ], + "actions": [ + "ohos.want.action.home" + ] + } + ] + } + ], + "extensionAbilities": [ + { + "name": "EntryBackupAbility", + "srcEntry": "./ets/entrybackupability/EntryBackupAbility.ets", + "type": "backup", + "exported": false, + "metadata": [ + { + "name": "ohos.extension.backup", + "resource": "$profile:backup_config" + } + ], + } + ] + } +} \ No newline at end of file diff --git a/ArkUIKit/AppStorage/entry/src/main/resources/base/element/color.json b/ArkUIKit/AppStorage/entry/src/main/resources/base/element/color.json new file mode 100644 index 0000000000000000000000000000000000000000..3c712962da3c2751c2b9ddb53559afcbd2b54a02 --- /dev/null +++ b/ArkUIKit/AppStorage/entry/src/main/resources/base/element/color.json @@ -0,0 +1,8 @@ +{ + "color": [ + { + "name": "start_window_background", + "value": "#FFFFFF" + } + ] +} \ No newline at end of file diff --git a/ArkUIKit/AppStorage/entry/src/main/resources/base/element/float.json b/ArkUIKit/AppStorage/entry/src/main/resources/base/element/float.json new file mode 100644 index 0000000000000000000000000000000000000000..a0a93dd91fd48f08f3a9532c76e9b26e68d4c034 --- /dev/null +++ b/ArkUIKit/AppStorage/entry/src/main/resources/base/element/float.json @@ -0,0 +1,8 @@ +{ + "float": [ + { + "name": "page_text_font_size", + "value": "50fp" + } + ] +} \ No newline at end of file diff --git a/ArkUIKit/AppStorage/entry/src/main/resources/base/element/string.json b/ArkUIKit/AppStorage/entry/src/main/resources/base/element/string.json new file mode 100644 index 0000000000000000000000000000000000000000..f94595515a99e0c828807e243494f57f09251930 --- /dev/null +++ b/ArkUIKit/AppStorage/entry/src/main/resources/base/element/string.json @@ -0,0 +1,16 @@ +{ + "string": [ + { + "name": "module_desc", + "value": "module description" + }, + { + "name": "EntryAbility_desc", + "value": "description" + }, + { + "name": "EntryAbility_label", + "value": "label" + } + ] +} \ No newline at end of file diff --git a/ArkUIKit/AppStorage/entry/src/main/resources/base/media/background.png b/ArkUIKit/AppStorage/entry/src/main/resources/base/media/background.png new file mode 100644 index 0000000000000000000000000000000000000000..923f2b3f27e915d6871871deea0420eb45ce102f Binary files /dev/null and b/ArkUIKit/AppStorage/entry/src/main/resources/base/media/background.png differ diff --git a/ArkUIKit/AppStorage/entry/src/main/resources/base/media/foreground.png b/ArkUIKit/AppStorage/entry/src/main/resources/base/media/foreground.png new file mode 100644 index 0000000000000000000000000000000000000000..97014d3e10e5ff511409c378cd4255713aecd85f Binary files /dev/null and b/ArkUIKit/AppStorage/entry/src/main/resources/base/media/foreground.png differ diff --git a/ArkUIKit/AppStorage/entry/src/main/resources/base/media/layered_image.json b/ArkUIKit/AppStorage/entry/src/main/resources/base/media/layered_image.json new file mode 100644 index 0000000000000000000000000000000000000000..fb49920440fb4d246c82f9ada275e26123a2136a --- /dev/null +++ b/ArkUIKit/AppStorage/entry/src/main/resources/base/media/layered_image.json @@ -0,0 +1,7 @@ +{ + "layered-image": + { + "background" : "$media:background", + "foreground" : "$media:foreground" + } +} \ No newline at end of file diff --git a/ArkUIKit/AppStorage/entry/src/main/resources/base/media/startIcon.png b/ArkUIKit/AppStorage/entry/src/main/resources/base/media/startIcon.png new file mode 100644 index 0000000000000000000000000000000000000000..205ad8b5a8a42e8762fbe4899b8e5e31ce822b8b Binary files /dev/null and b/ArkUIKit/AppStorage/entry/src/main/resources/base/media/startIcon.png differ diff --git a/ArkUIKit/AppStorage/entry/src/main/resources/base/profile/backup_config.json b/ArkUIKit/AppStorage/entry/src/main/resources/base/profile/backup_config.json new file mode 100644 index 0000000000000000000000000000000000000000..78f40ae7c494d71e2482278f359ec790ca73471a --- /dev/null +++ b/ArkUIKit/AppStorage/entry/src/main/resources/base/profile/backup_config.json @@ -0,0 +1,3 @@ +{ + "allowToBackupRestore": true +} \ No newline at end of file diff --git a/ArkUIKit/AppStorage/entry/src/main/resources/base/profile/main_pages.json b/ArkUIKit/AppStorage/entry/src/main/resources/base/profile/main_pages.json new file mode 100644 index 0000000000000000000000000000000000000000..ab1c24f409d3be11c4739918293539c6f204d16b --- /dev/null +++ b/ArkUIKit/AppStorage/entry/src/main/resources/base/profile/main_pages.json @@ -0,0 +1,15 @@ +{ + "src": [ + "pages/Index", + "pages/PageTwo", + "pages/PageThree", + "pages/PageFour", + "pages/PageFive", + "pages/PageSix", + "pages/PageSeven", + "pages/PageEight", + "pages/PageNine", + "pages/PageTen", + "pages/PageOne" + ] +} \ No newline at end of file diff --git a/ArkUIKit/AppStorage/entry/src/main/resources/dark/element/color.json b/ArkUIKit/AppStorage/entry/src/main/resources/dark/element/color.json new file mode 100644 index 0000000000000000000000000000000000000000..79b11c2747aec33e710fd3a7b2b3c94dd9965499 --- /dev/null +++ b/ArkUIKit/AppStorage/entry/src/main/resources/dark/element/color.json @@ -0,0 +1,8 @@ +{ + "color": [ + { + "name": "start_window_background", + "value": "#000000" + } + ] +} \ No newline at end of file diff --git a/ArkUIKit/AppStorage/entry/src/mock/mock-config.json5 b/ArkUIKit/AppStorage/entry/src/mock/mock-config.json5 new file mode 100644 index 0000000000000000000000000000000000000000..c588040b46fdc8b1fee0c7f6c344010d52ead650 --- /dev/null +++ b/ArkUIKit/AppStorage/entry/src/mock/mock-config.json5 @@ -0,0 +1,16 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License") + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +{ +} \ No newline at end of file diff --git a/ArkUIKit/AppStorage/entry/src/ohosTest/ets/test/Ability.test.ets b/ArkUIKit/AppStorage/entry/src/ohosTest/ets/test/Ability.test.ets new file mode 100644 index 0000000000000000000000000000000000000000..f133c8fa527ba686e2fad7c24d0289b875006d0a --- /dev/null +++ b/ArkUIKit/AppStorage/entry/src/ohosTest/ets/test/Ability.test.ets @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License") + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +import { hilog } from '@kit.PerformanceAnalysisKit'; +import { describe, beforeAll, beforeEach, afterEach, afterAll, it, expect } from '@ohos/hypium'; + +export default function abilityTest() { + describe('ActsAbilityTest', () => { + // Defines a test suite. Two parameters are supported: test suite name and test suite function. + beforeAll(() => { + // Presets an action, which is performed only once before all test cases of the test suite start. + // This API supports only one parameter: preset action function. + }) + beforeEach(() => { + // Presets an action, which is performed before each unit test case starts. + // The number of execution times is the same as the number of test cases defined by **it**. + // This API supports only one parameter: preset action function. + }) + afterEach(() => { + // Presets a clear action, which is performed after each unit test case ends. + // The number of execution times is the same as the number of test cases defined by **it**. + // This API supports only one parameter: clear action function. + }) + afterAll(() => { + // Presets a clear action, which is performed after all test cases of the test suite end. + // This API supports only one parameter: clear action function. + }) + it('assertContain', 0, () => { + // Defines a test case. This API supports three parameters: test case name, filter parameter, and test case function. + hilog.info(0x0000, 'testTag', '%{public}s', 'it begin'); + let a = 'abc'; + let b = 'b'; + // Defines a variety of assertion methods, which are used to declare expected boolean conditions. + expect(a).assertContain(b); + expect(a).assertEqual(a); + }) + }) +} \ No newline at end of file diff --git a/ArkUIKit/AppStorage/entry/src/ohosTest/ets/test/Index.test.ets b/ArkUIKit/AppStorage/entry/src/ohosTest/ets/test/Index.test.ets new file mode 100644 index 0000000000000000000000000000000000000000..5dcdc13c988a0a2b3efa018bbef9b034ba2d11bc --- /dev/null +++ b/ArkUIKit/AppStorage/entry/src/ohosTest/ets/test/Index.test.ets @@ -0,0 +1,262 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { describe, it, expect, beforeAll, TestType, Level, Size, } from '@ohos/hypium'; +// 导入测试依赖kit +import { abilityDelegatorRegistry, Driver, ON, MatchPattern } from '@kit.TestKit'; +import { UIAbility, Want } from '@kit.AbilityKit'; + +const delegator: abilityDelegatorRegistry.AbilityDelegator = abilityDelegatorRegistry.getAbilityDelegator(); +const bundleName = abilityDelegatorRegistry.getArguments().bundleName; +let want: Want; + +export default function IndexTest() { + describe('IndexTest', () => { + beforeAll(async () => { + want = { + bundleName: bundleName, + abilityName: 'EntryAbility' + }; + await delegator.startAbility(want); + let driver = Driver.create(); + await driver.delayMs(1000); + const ability: UIAbility = await delegator.getCurrentTopAbility(); + console.info('get top ability'); + expect(ability.context.abilityInfo.name).assertEqual('EntryAbility'); + }) + + /** + * @tc.number PageTwoTest + * @tc.name PageTwoTest + * @tc.desc 测试PageTwo是否显示正常 + * @tc.level : Level1 + * @tc.size : MediumTest + * @tc.type : Function + */ + it('PageTwoTest', TestType.FUNCTION | Size.MEDIUMTEST | Level.LEVEL1, async (done: Function) => { + console.info('uitest: PageOneTest begin'); + let driver = Driver.create(); + let button1 = await driver.findComponent(ON.text('PageTwo', MatchPattern.CONTAINS)); + expect(button1 === null).assertFalse(); + await button1.click(); + await driver.delayMs(1000); + await driver.delayMs(1000); + await driver.pressBack(); + console.info('uitest: PageTwo end'); + done(); + }) + + /** + * @tc.number PageThreeTest + * @tc.name PageThreeTest + * @tc.desc 测试PageThree是否显示正常 + * @tc.level : Level1 + * @tc.size : MediumTest + * @tc.type : Function + */ + it('PageThreeTest', TestType.FUNCTION | Size.MEDIUMTEST | Level.LEVEL1, async (done: Function) => { + console.info('uitest: PageThreeTest begin'); + let driver = Driver.create(); + let button1 = await driver.findComponent(ON.text('PageThree', MatchPattern.CONTAINS)); + expect(button1 === null).assertFalse(); + await button1.click(); + await driver.delayMs(1000); + await driver.pressBack(); + console.info('uitest: PageThreeTest end'); + done(); + }) + + /** + * @tc.number PageFourTest + * @tc.name PageFourTest + * @tc.desc 测试PageFour是否显示正常 + * @tc.level : Level1 + * @tc.size : MediumTest + * @tc.type : Function + */ + it('PageFourTest', TestType.FUNCTION | Size.MEDIUMTEST | Level.LEVEL1, async (done: Function) => { + console.info('uitest: PageOneTest begin'); + let driver = Driver.create(); + let button1 = await driver.findComponent(ON.text('PageFour', MatchPattern.CONTAINS)); + expect(button1 === null).assertFalse(); + await button1.click(); + await driver.delayMs(1000); + let button2 = await driver.findComponent(ON.text('increase the year by 1', MatchPattern.CONTAINS)); + expect(button2 === null).assertFalse(); + await button2.click(); + let button3 = await driver.findComponent(ON.text('increase the month by 1', MatchPattern.CONTAINS)); + expect(button3 === null).assertFalse(); + await button3.click(); + let button4 = await driver.findComponent(ON.text('increase the day by 1', MatchPattern.CONTAINS)); + expect(button4 === null).assertFalse(); + await button4.click(); + await driver.pressBack(); + console.info('uitest: PageFourTest end'); + done(); + }) + + /** + * @tc.number PageFiveTest + * @tc.name PageFiveTest + * @tc.desc 测试PageFive是否显示正常 + * @tc.level : Level1 + * @tc.size : MediumTest + * @tc.type : Function + */ + it('PageFiveTest', TestType.FUNCTION | Size.MEDIUMTEST | Level.LEVEL1, async (done: Function) => { + console.info('uitest: PageFiveTest begin'); + let driver = Driver.create(); + let button1 = await driver.findComponent(ON.text('PageFive', MatchPattern.CONTAINS)); + expect(button1 === null).assertFalse(); + await button1.click(); + await driver.delayMs(1000); + let button2 = await driver.findComponent(ON.text('init map', MatchPattern.CONTAINS)); + expect(button2 === null).assertFalse(); + await button2.click(); + await driver.delayMs(1000); + await driver.pressBack(); + console.info('uitest: PageFiveTest end'); + done(); + }) + + /** + * @tc.number PageSixTest + * @tc.name PageSixTest + * @tc.desc 测试PageSix是否显示正常 + * @tc.level : Level1 + * @tc.size : MediumTest + * @tc.type : Function + */ + it('PageSixTest', TestType.FUNCTION | Size.MEDIUMTEST | Level.LEVEL1, async (done: Function) => { + console.info('uitest: PageSixTest begin'); + let driver = Driver.create(); + let button1 = await driver.findComponent(ON.text('PageSix', MatchPattern.CONTAINS)); + expect(button1 === null).assertFalse(); + await button1.click(); + await driver.delayMs(1000); + let button2 = await driver.findComponent(ON.text('init set', MatchPattern.CONTAINS)); + expect(button2 === null).assertFalse(); + await button2.click(); + await driver.delayMs(1000); + let button3 = await driver.findComponent(ON.text('set new one', MatchPattern.CONTAINS)); + expect(button3 === null).assertFalse(); + await button3.click(); + await driver.delayMs(1000); + await driver.pressBack(); + console.info('uitest: PageSixTest end'); + done(); + }) + + /** + * @tc.number PageSevenTest + * @tc.name PageSevenTest + * @tc.desc 测试PageSix是否显示正常 + * @tc.level : Level1 + * @tc.size : MediumTest + * @tc.type : Function + */ + it('PageSevenTest', TestType.FUNCTION | Size.MEDIUMTEST | Level.LEVEL1, async (done: Function) => { + console.info('uitest: PageSevenTest begin'); + let driver = Driver.create(); + let button1 = await driver.findComponent(ON.text('PageSeven', MatchPattern.CONTAINS)); + expect(button1 === null).assertFalse(); + await button1.click(); + await driver.delayMs(1000); + await driver.pressBack(); + console.info('uitest: PageSevenTest end'); + done(); + }) + + /** + * @tc.number PageEightTest + * @tc.name PageEightTest + * @tc.desc 测试PageSix是否显示正常 + * @tc.level : Level1 + * @tc.size : MediumTest + * @tc.type : Function + */ + it('PageEightTest', TestType.FUNCTION | Size.MEDIUMTEST | Level.LEVEL1, async (done: Function) => { + console.info('uitest:PageEightTest begin'); + let driver = Driver.create(); + let button1 = await driver.findComponent(ON.text('PageEight', MatchPattern.CONTAINS)); + expect(button1 === null).assertFalse(); + await button1.click(); + await driver.delayMs(1000); + await driver.pressBack(); + console.info('uitest: PageEightTest end'); + done(); + }) + + /** + * @tc.number PageNineTest + * @tc.name PageNineTest + * @tc.desc 测试PageNine是否显示正常 + * @tc.level : Level1 + * @tc.size : MediumTest + * @tc.type : Function + */ + it('PageNineTest', TestType.FUNCTION | Size.MEDIUMTEST | Level.LEVEL1, async (done: Function) => { + console.info('uitest:PageNineTest begin'); + let driver = Driver.create(); + let button1 = await driver.findComponent(ON.text('PageNine', MatchPattern.CONTAINS)); + expect(button1 === null).assertFalse(); + await button1.click(); + await driver.delayMs(1000); + await driver.pressBack(); + console.info('uitest: PageNineTest end'); + done(); + }) + /** + * @tc.number PageTenTest + * @tc.name PageTenTest + * @tc.desc 测试PageTen是否显示正常 + * @tc.level : Level1 + * @tc.size : MediumTest + * @tc.type : Function + */ + it('PageTenTest', TestType.FUNCTION | Size.MEDIUMTEST | Level.LEVEL1, async (done: Function) => { + console.info('uitest:PageTenTest begin'); + let driver = Driver.create(); + let button1 = await driver.findComponent(ON.text('PageTen', MatchPattern.CONTAINS)); + expect(button1 === null).assertFalse(); + await button1.click(); + await driver.delayMs(1000); + await driver.pressBack(); + console.info('uitest: PageTenTest end'); + done(); + }) + + /** + * @tc.number PageOneTest + * @tc.name PageOneTest + * @tc.desc 测试PageOne是否显示正常 + * @tc.level : Level1 + * @tc.size : MediumTest + * @tc.type : Function + */ + it('PageOneTest', TestType.FUNCTION | Size.MEDIUMTEST | Level.LEVEL1, async (done: Function) => { + console.info('uitest: PageOneTest begin'); + let driver = Driver.create(); + let button1 = await driver.findComponent(ON.text('PageOne', MatchPattern.CONTAINS)); + expect(button1 === null).assertFalse(); + await button1.click(); + await driver.delayMs(1000); + await driver.delayMs(1000); + await driver.pressBack(); + console.info('uitest: PageOneTest end'); + done(); + }) + }) +} \ No newline at end of file diff --git a/ArkUIKit/AppStorage/entry/src/ohosTest/ets/test/List.test.ets b/ArkUIKit/AppStorage/entry/src/ohosTest/ets/test/List.test.ets new file mode 100644 index 0000000000000000000000000000000000000000..006c9247defadebe419e4f972a7bb4a0e0b2b218 --- /dev/null +++ b/ArkUIKit/AppStorage/entry/src/ohosTest/ets/test/List.test.ets @@ -0,0 +1,21 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License") + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +import IndexTest from './Index.test' +import abilityTest from './Ability.test'; + +export default function testsuite() { + abilityTest(); + IndexTest() +} \ No newline at end of file diff --git a/ArkUIKit/AppStorage/entry/src/ohosTest/module.json5 b/ArkUIKit/AppStorage/entry/src/ohosTest/module.json5 new file mode 100644 index 0000000000000000000000000000000000000000..0370f6d6bef710b84fb1ac11e55f23097ae1cd79 --- /dev/null +++ b/ArkUIKit/AppStorage/entry/src/ohosTest/module.json5 @@ -0,0 +1,25 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License") + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +{ + "module": { + "name": "entry_test", + "type": "feature", + "deviceTypes": [ + "default" + ], + "deliveryWithInstall": true, + "installationFree": false + } +} diff --git a/ArkUIKit/AppStorage/entry/src/ohosTest/ohosTest.md b/ArkUIKit/AppStorage/entry/src/ohosTest/ohosTest.md new file mode 100644 index 0000000000000000000000000000000000000000..e4cb619039cefc6e22c08848610ebdd814aea234 --- /dev/null +++ b/ArkUIKit/AppStorage/entry/src/ohosTest/ohosTest.md @@ -0,0 +1,7 @@ +# arkts-appstorage 测试用例归档 + +## 用例表 + +| 测试功能 | 预置条件 | 输入 | 预期输出 | 是否自动 | 测试结果 | +| ------------------- | -------------- |---------------------------------------|----------| :------- | -------- | +| arkts-appstorage示例代码验证 | 设备正常运行 | 进入页面,页面内容显示正常 | 页面信息显示正常 | 是 | Pass | \ No newline at end of file diff --git a/ArkUIKit/AppStorage/entry/src/test/List.test.ets b/ArkUIKit/AppStorage/entry/src/test/List.test.ets new file mode 100644 index 0000000000000000000000000000000000000000..8776baf121056b170cec8b9a273f3b6b0da440eb --- /dev/null +++ b/ArkUIKit/AppStorage/entry/src/test/List.test.ets @@ -0,0 +1,19 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License") + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +import localUnitTest from './LocalUnit.test'; + +export default function testsuite() { + localUnitTest(); +} \ No newline at end of file diff --git a/ArkUIKit/AppStorage/entry/src/test/LocalUnit.test.ets b/ArkUIKit/AppStorage/entry/src/test/LocalUnit.test.ets new file mode 100644 index 0000000000000000000000000000000000000000..32a66f1d864ef46ce9908004362947d171ce0a6f --- /dev/null +++ b/ArkUIKit/AppStorage/entry/src/test/LocalUnit.test.ets @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License") + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +import { describe, beforeAll, beforeEach, afterEach, afterAll, it, expect } from '@ohos/hypium'; + +export default function localUnitTest() { + describe('localUnitTest', () => { + // Defines a test suite. Two parameters are supported: test suite name and test suite function. + beforeAll(() => { + // Presets an action, which is performed only once before all test cases of the test suite start. + // This API supports only one parameter: preset action function. + }); + beforeEach(() => { + // Presets an action, which is performed before each unit test case starts. + // The number of execution times is the same as the number of test cases defined by **it**. + // This API supports only one parameter: preset action function. + }); + afterEach(() => { + // Presets a clear action, which is performed after each unit test case ends. + // The number of execution times is the same as the number of test cases defined by **it**. + // This API supports only one parameter: clear action function. + }); + afterAll(() => { + // Presets a clear action, which is performed after all test cases of the test suite end. + // This API supports only one parameter: clear action function. + }); + it('assertContain', 0, () => { + // Defines a test case. This API supports three parameters: test case name, filter parameter, and test case function. + let a = 'abc'; + let b = 'b'; + // Defines a variety of assertion methods, which are used to declare expected boolean conditions. + expect(a).assertContain(b); + expect(a).assertEqual(a); + }); + }); +} \ No newline at end of file diff --git a/ArkUIKit/AppStorage/hvigor/hvigor-config.json5 b/ArkUIKit/AppStorage/hvigor/hvigor-config.json5 new file mode 100644 index 0000000000000000000000000000000000000000..42b95ab88939c6187981e1682e9bac7fbb4ff698 --- /dev/null +++ b/ArkUIKit/AppStorage/hvigor/hvigor-config.json5 @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License") + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +{ + "modelVersion": "6.0.0", + "dependencies": { + }, + "execution": { + // "analyze": "normal", /* Define the build analyze mode. Value: [ "normal" | "advanced" | "ultrafine" | false ]. Default: "normal" */ + // "daemon": true, /* Enable daemon compilation. Value: [ true | false ]. Default: true */ + // "incremental": true, /* Enable incremental compilation. Value: [ true | false ]. Default: true */ + // "parallel": true, /* Enable parallel compilation. Value: [ true | false ]. Default: true */ + // "typeCheck": false, /* Enable typeCheck. Value: [ true | false ]. Default: false */ + // "optimizationStrategy": "memory" /* Define the optimization strategy. Value: [ "memory" | "performance" ]. Default: "memory" */ + }, + "logging": { + // "level": "info" /* Define the log level. Value: [ "debug" | "info" | "warn" | "error" ]. Default: "info" */ + }, + "debugging": { + // "stacktrace": false /* Disable stacktrace compilation. Value: [ true | false ]. Default: false */ + }, + "nodeOptions": { + // "maxOldSpaceSize": 8192 /* Enable nodeOptions maxOldSpaceSize compilation. Unit M. Used for the daemon process. Default: 8192*/ + // "exposeGC": true /* Enable to trigger garbage collection explicitly. Default: true*/ + } +} diff --git a/ArkUIKit/AppStorage/hvigorfile.ts b/ArkUIKit/AppStorage/hvigorfile.ts new file mode 100644 index 0000000000000000000000000000000000000000..d2e7cad138702c5905d7aee267d9078330d2ee70 --- /dev/null +++ b/ArkUIKit/AppStorage/hvigorfile.ts @@ -0,0 +1,20 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License") + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +import { appTasks } from '@ohos/hvigor-ohos-plugin'; + +export default { + system: appTasks, /* Built-in plugin of Hvigor. It cannot be modified. */ + plugins: [] /* Custom plugin to extend the functionality of Hvigor. */ +} \ No newline at end of file diff --git a/ArkUIKit/AppStorage/oh-package.json5 b/ArkUIKit/AppStorage/oh-package.json5 new file mode 100644 index 0000000000000000000000000000000000000000..5e44e18c752e57480960b55904360294ecc92b90 --- /dev/null +++ b/ArkUIKit/AppStorage/oh-package.json5 @@ -0,0 +1,24 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License") + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +{ + "modelVersion": "6.0.0", + "description": "Please describe the basic information.", + "dependencies": { + }, + "devDependencies": { + "@ohos/hypium": "1.0.24", + "@ohos/hamock": "1.0.0" + } +} diff --git a/ArkUIKit/AppStorage/screenshots/PageTwo.png b/ArkUIKit/AppStorage/screenshots/PageTwo.png new file mode 100644 index 0000000000000000000000000000000000000000..713e6b3b8b838f3fa310df0d52f9674a6569c6ea Binary files /dev/null and b/ArkUIKit/AppStorage/screenshots/PageTwo.png differ diff --git a/ArkUIKit/AppStorage/screenshots/pagesix.PNG b/ArkUIKit/AppStorage/screenshots/pagesix.PNG new file mode 100644 index 0000000000000000000000000000000000000000..01d9b865ce956f12d9668c5b043aee185cad4940 Binary files /dev/null and b/ArkUIKit/AppStorage/screenshots/pagesix.PNG differ diff --git a/ArkUIKit/AppStorage/screenshots/pagethree.png b/ArkUIKit/AppStorage/screenshots/pagethree.png new file mode 100644 index 0000000000000000000000000000000000000000..5fecc558bda06e9417a787a771b004768310b433 Binary files /dev/null and b/ArkUIKit/AppStorage/screenshots/pagethree.png differ diff --git a/ArkUIKit/ArktsMvvmSample/AppScope/app.json5 b/ArkUIKit/ArktsMvvmSample/AppScope/app.json5 new file mode 100644 index 0000000000000000000000000000000000000000..f63eab87effe72fe1e40c1d65ca364cc7360e5ab --- /dev/null +++ b/ArkUIKit/ArktsMvvmSample/AppScope/app.json5 @@ -0,0 +1,25 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +{ + "app": { + "bundleName": "com.sample.arktsmvvmsample", + "vendor": "example", + "versionCode": 1000000, + "versionName": "1.0.0", + "icon": "$media:layered_image", + "label": "$string:app_name" + } +} diff --git a/ArkUIKit/ArktsMvvmSample/AppScope/resources/base/element/string.json b/ArkUIKit/ArktsMvvmSample/AppScope/resources/base/element/string.json new file mode 100644 index 0000000000000000000000000000000000000000..d891776f551e30953535f256fcd764095e04bd6b --- /dev/null +++ b/ArkUIKit/ArktsMvvmSample/AppScope/resources/base/element/string.json @@ -0,0 +1,8 @@ +{ + "string": [ + { + "name": "app_name", + "value": "ArktsMvvmSample" + } + ] +} diff --git a/ArkUIKit/ArktsMvvmSample/AppScope/resources/base/media/background.png b/ArkUIKit/ArktsMvvmSample/AppScope/resources/base/media/background.png new file mode 100644 index 0000000000000000000000000000000000000000..923f2b3f27e915d6871871deea0420eb45ce102f Binary files /dev/null and b/ArkUIKit/ArktsMvvmSample/AppScope/resources/base/media/background.png differ diff --git a/ArkUIKit/ArktsMvvmSample/AppScope/resources/base/media/foreground.png b/ArkUIKit/ArktsMvvmSample/AppScope/resources/base/media/foreground.png new file mode 100644 index 0000000000000000000000000000000000000000..eb9427585b36d14b12477435b6419d1f07b3e0bb Binary files /dev/null and b/ArkUIKit/ArktsMvvmSample/AppScope/resources/base/media/foreground.png differ diff --git a/ArkUIKit/ArktsMvvmSample/AppScope/resources/base/media/layered_image.json b/ArkUIKit/ArktsMvvmSample/AppScope/resources/base/media/layered_image.json new file mode 100644 index 0000000000000000000000000000000000000000..fb49920440fb4d246c82f9ada275e26123a2136a --- /dev/null +++ b/ArkUIKit/ArktsMvvmSample/AppScope/resources/base/media/layered_image.json @@ -0,0 +1,7 @@ +{ + "layered-image": + { + "background" : "$media:background", + "foreground" : "$media:foreground" + } +} \ No newline at end of file diff --git a/ArkUIKit/ArktsMvvmSample/README_zh.md b/ArkUIKit/ArktsMvvmSample/README_zh.md new file mode 100644 index 0000000000000000000000000000000000000000..d7d70a9ee9322d51ea92d389e9fc5dad26a1dd6d --- /dev/null +++ b/ArkUIKit/ArktsMvvmSample/README_zh.md @@ -0,0 +1,95 @@ +# MVVM模式 + +### 介绍 + +本示例展示了[MVVM模式](https://gitcode.com/openharmony/docs/blob/master/zh-cn/application-dev/ui/state-management/arkts-mvvm.md)的使用方法: + +1. 当开发者掌握了状态管理的基本概念后,通常会尝试开发自己的应用,在应用开发初期,如果未能精心规划项目结构,随着项目扩展和复杂化,状态变量的增多将导致组件间关系变得错综复杂。此时,开发新功能可能引起连锁反应,维护成本也会增加。为此,本示例旨在示例MVVM模式以及ArkUI的UI开发模式与MVVM的关系,给开发者予以参考,以便在产品迭代和升级时,能更轻松的开发和维护。; +2. 在应用开发中,UI更新需要实时同步数据状态变化,这直接影响应用程序的性能和用户体验。为了解决数据与UI同步的复杂性,ArkUI采用了 Model-View-ViewModel(MVVM)架构模式。MVVM 将应用分为Model、View和ViewModel三个核心部分,实现数据、视图与逻辑的分离。通过这种模式,UI可以自动更新状态变化,从而更高效地管理数据和视图的绑定与更新。 + +### 效果展示 + + +| @State实现备忘录演示 | @Prop和@Link实现备忘录演示 | +|-------------------------------------------|-------------------------------------------| +| ![](screenshots/StateEffectPreview.gif) | ![](screenshots/PropLinkPreview.gif) | +| ForEach实现备忘录演示 | @Builder实现备忘录演示 | +| ![](screenshots/ForEachEffectPreview.gif) | ![](screenshots/BuilderEffectPreview.gif) | +| Mvvm实现备忘录使用演示 | +| ![](screenshots/MvvmEffectPreview.gif) | + +### 工程目录 +``` +entry/src/ +├── main +│ ├── ets +│ │ ├── entryability +│ │ ├── entrybackupability +│ │ ├── model +│ │ │ ├── ThingModel.ets +│ │ │ └── TodoListModel.ets +│ │ ├── pages +│ │ │ ├── BuilderIndex.ets +│ │ │ ├── ForEachIndex.ets +│ │ │ ├── Index.ets +│ │ │ ├── PropLinkIndex.ets +│ │ │ └── StateIndex.ets +│ │ ├── viewModel +│ │ │ ├── ThingViewModel.ets +│ │ │ └── TodoListViewModel.ets +│ │ └── view +│ │ │ ├── AllChooseComponent.ets +│ │ │ ├── ThingComponent.ets +│ │ │ ├── TodoComponent.ets +│ │ │ └── TodoListComponent.ets +│ ├── module.json5 +│ ├── syscap.json +│ └── resources +│ │ ├── base +│ │ ├── dark +│ │ └── rawfile +│ │ └── default_tasks.json +└── ohosTest + └── ets + └── test + ├── Ability.test.ets // 自动化测试代码 + └── List.test.ets // 测试套执行列表 + +``` + +### 使用说明 + +1. 必须搭配 @Param:仅能与 @Param 共同使用,不可单独使用或与 @State、@Local 等其它装饰器搭配,且仅支持 @ComponentV2 组件(API 12+)。 +2. 初始化仅同步一次:变量初始化时接收外部传入值,后续外部数据源变化时,子组件变量不再同步更新。 +3. 允许本地修改:解除 @Param 默认 “不可本地修改” 的限制,修改后可触发 UI 刷新,且不影响外部数据源。 + + +### 具体实现 + +1. 通过装饰器修饰变量,在变量修改时,数据发生变化,实现备忘录。 +2. 进一步使用@Builder装饰器将组件进一步抽离,进一步靠近mvvm模式的结构。 +3. 分层职责:Model 层仅管数据结构 / 加载,ViewModel 层处理业务逻辑(如全选、状态切换),View 层只负责 UI 渲染,严格遵循 “不跨层访问” 原则。 + +### 相关权限 + +不涉及。 + +### 依赖 + +不涉及。 + +### 约束与限制 + +不涉及。 + +### 下载 + +如需单独下载本工程,执行如下命令: + +``` +git init +git config core.sparsecheckout true +echo code/DocsSample/ArkUISample/ArktsMvvmSample/ > .git/info/sparse-checkout +git remote add origin https://gitcode.com/openharmony/applications_app_samples.git +git pull origin master +``` \ No newline at end of file diff --git a/ArkUIKit/ArktsMvvmSample/build-profile.json5 b/ArkUIKit/ArktsMvvmSample/build-profile.json5 new file mode 100644 index 0000000000000000000000000000000000000000..724b825f1ee429691a14b6b6d138c70fd7c56db9 --- /dev/null +++ b/ArkUIKit/ArktsMvvmSample/build-profile.json5 @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +{ + "app": { + "signingConfigs": [], + "products": [ + { + "name": "default", + "signingConfig": "default", + "compileSdkVersion": "6.0.0(20)", + "compatibleSdkVersion": "6.0.0(20)", + "targetSdkVersion": "6.0.0(20)", + "runtimeOS": "HarmonyOS", + "buildOption": { + "strictMode": { + "caseSensitiveCheck": true, + "useNormalizedOHMUrl": true + } + } + } + ], + "buildModeSet": [ + { + "name": "debug", + }, + { + "name": "release" + } + ] + }, + "modules": [ + { + "name": "entry", + "srcPath": "./entry", + "targets": [ + { + "name": "default", + "applyToProducts": [ + "default" + ] + } + ] + } + ] +} \ No newline at end of file diff --git a/ArkUIKit/ArktsMvvmSample/code-linter.json5 b/ArkUIKit/ArktsMvvmSample/code-linter.json5 new file mode 100644 index 0000000000000000000000000000000000000000..ed05653cca31b61d64cf6471529eaf50d4f70709 --- /dev/null +++ b/ArkUIKit/ArktsMvvmSample/code-linter.json5 @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +{ + "files": [ + "**/*.ets" + ], + "ignore": [ + "**/src/ohosTest/**/*", + "**/src/test/**/*", + "**/src/mock/**/*", + "**/node_modules/**/*", + "**/oh_modules/**/*", + "**/build/**/*", + "**/.preview/**/*" + ], + "ruleSet": [ + "plugin:@performance/recommended", + "plugin:@typescript-eslint/recommended" + ], + "rules": { + "@security/no-unsafe-aes": "error", + "@security/no-unsafe-hash": "error", + "@security/no-unsafe-mac": "warn", + "@security/no-unsafe-dh": "error", + "@security/no-unsafe-dsa": "error", + "@security/no-unsafe-ecdsa": "error", + "@security/no-unsafe-rsa-encrypt": "error", + "@security/no-unsafe-rsa-sign": "error", + "@security/no-unsafe-rsa-key": "error", + "@security/no-unsafe-dsa-key": "error", + "@security/no-unsafe-dh-key": "error", + "@security/no-unsafe-3des": "error" + } +} \ No newline at end of file diff --git a/ArkUIKit/ArktsMvvmSample/entry/build-profile.json5 b/ArkUIKit/ArktsMvvmSample/entry/build-profile.json5 new file mode 100644 index 0000000000000000000000000000000000000000..6bf0d132e6f78049e712446c63f2633b2d1613d3 --- /dev/null +++ b/ArkUIKit/ArktsMvvmSample/entry/build-profile.json5 @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +{ + "apiType": "stageMode", + "buildOption": { + "resOptions": { + "copyCodeResource": { + "enable": false + } + } + }, + "buildOptionSet": [ + { + "name": "release", + "arkOptions": { + "obfuscation": { + "ruleOptions": { + "enable": false, + "files": [ + "./obfuscation-rules.txt" + ] + } + } + } + }, + ], + "targets": [ + { + "name": "default" + }, + { + "name": "ohosTest", + } + ] +} \ No newline at end of file diff --git a/ArkUIKit/ArktsMvvmSample/entry/hvigorfile.ts b/ArkUIKit/ArktsMvvmSample/entry/hvigorfile.ts new file mode 100644 index 0000000000000000000000000000000000000000..cfa8a00f74f409d9647f55cdf270ab6aec69fe41 --- /dev/null +++ b/ArkUIKit/ArktsMvvmSample/entry/hvigorfile.ts @@ -0,0 +1,21 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { hapTasks } from '@ohos/hvigor-ohos-plugin'; + +export default { + system: hapTasks, /* Built-in plugin of Hvigor. It cannot be modified. */ + plugins: [] /* Custom plugin to extend the functionality of Hvigor. */ +} \ No newline at end of file diff --git a/ArkUIKit/ArktsMvvmSample/entry/obfuscation-rules.txt b/ArkUIKit/ArktsMvvmSample/entry/obfuscation-rules.txt new file mode 100644 index 0000000000000000000000000000000000000000..272efb6ca3f240859091bbbfc7c5802d52793b0b --- /dev/null +++ b/ArkUIKit/ArktsMvvmSample/entry/obfuscation-rules.txt @@ -0,0 +1,23 @@ +# Define project specific obfuscation rules here. +# You can include the obfuscation configuration files in the current module's build-profile.json5. +# +# For more details, see +# https://developer.huawei.com/consumer/cn/doc/harmonyos-guides-V5/source-obfuscation-V5 + +# Obfuscation options: +# -disable-obfuscation: disable all obfuscations +# -enable-property-obfuscation: obfuscate the property names +# -enable-toplevel-obfuscation: obfuscate the names in the global scope +# -compact: remove unnecessary blank spaces and all line feeds +# -remove-log: remove all console.* statements +# -print-namecache: print the name cache that contains the mapping from the old names to new names +# -apply-namecache: reuse the given cache file + +# Keep options: +# -keep-property-name: specifies property names that you want to keep +# -keep-global-name: specifies names that you want to keep in the global scope + +-enable-property-obfuscation +-enable-toplevel-obfuscation +-enable-filename-obfuscation +-enable-export-obfuscation \ No newline at end of file diff --git a/ArkUIKit/ArktsMvvmSample/entry/oh-package.json5 b/ArkUIKit/ArktsMvvmSample/entry/oh-package.json5 new file mode 100644 index 0000000000000000000000000000000000000000..c9cb6c8174858277c9b0d465a51547dcab16d5ff --- /dev/null +++ b/ArkUIKit/ArktsMvvmSample/entry/oh-package.json5 @@ -0,0 +1,25 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +{ + "name": "entry", + "version": "1.0.0", + "description": "Please describe the basic information.", + "main": "", + "author": "", + "license": "", + "dependencies": {} +} + diff --git a/ArkUIKit/ArktsMvvmSample/entry/src/main/ets/entryability/EntryAbility.ets b/ArkUIKit/ArktsMvvmSample/entry/src/main/ets/entryability/EntryAbility.ets new file mode 100644 index 0000000000000000000000000000000000000000..3cad08aeb118fdd2cbc21352a3e922c7d6a8eccc --- /dev/null +++ b/ArkUIKit/ArktsMvvmSample/entry/src/main/ets/entryability/EntryAbility.ets @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { AbilityConstant, ConfigurationConstant, UIAbility, Want } from '@kit.AbilityKit'; +import { hilog } from '@kit.PerformanceAnalysisKit'; +import { window } from '@kit.ArkUI'; + +const DOMAIN = 0x0000; + +export default class EntryAbility extends UIAbility { + onCreate(want: Want, launchParam: AbilityConstant.LaunchParam): void { + try { + this.context.getApplicationContext().setColorMode(ConfigurationConstant.ColorMode.COLOR_MODE_NOT_SET); + } catch (err) { + hilog.error(DOMAIN, 'testTag', 'Failed to set colorMode. Cause: %{public}s', JSON.stringify(err)); + } + hilog.info(DOMAIN, 'testTag', '%{public}s', 'Ability onCreate'); + } + + onDestroy(): void { + hilog.info(DOMAIN, 'testTag', '%{public}s', 'Ability onDestroy'); + } + + onWindowStageCreate(windowStage: window.WindowStage): void { + // Main window is created, set main page for this ability + hilog.info(DOMAIN, 'testTag', '%{public}s', 'Ability onWindowStageCreate'); + + windowStage.loadContent('pages/StateIndex', (err) => { + if (err.code) { + hilog.error(DOMAIN, 'testTag', 'Failed to load the content. Cause: %{public}s', JSON.stringify(err)); + return; + } + hilog.info(DOMAIN, 'testTag', 'Succeeded in loading the content.'); + }); + } + + onWindowStageDestroy(): void { + // Main window is destroyed, release UI related resources + hilog.info(DOMAIN, 'testTag', '%{public}s', 'Ability onWindowStageDestroy'); + } + + onForeground(): void { + // Ability has brought to foreground + hilog.info(DOMAIN, 'testTag', '%{public}s', 'Ability onForeground'); + } + + onBackground(): void { + // Ability has back to background + hilog.info(DOMAIN, 'testTag', '%{public}s', 'Ability onBackground'); + } +} \ No newline at end of file diff --git a/ArkUIKit/ArktsMvvmSample/entry/src/main/ets/entrybackupability/EntryBackupAbility.ets b/ArkUIKit/ArktsMvvmSample/entry/src/main/ets/entrybackupability/EntryBackupAbility.ets new file mode 100644 index 0000000000000000000000000000000000000000..0a97e21bd7a15599af76a806695860ff1eb0ebfe --- /dev/null +++ b/ArkUIKit/ArktsMvvmSample/entry/src/main/ets/entrybackupability/EntryBackupAbility.ets @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { hilog } from '@kit.PerformanceAnalysisKit'; +import { BackupExtensionAbility, BundleVersion } from '@kit.CoreFileKit'; + +const DOMAIN = 0x0000; + +export default class EntryBackupAbility extends BackupExtensionAbility { + async onBackup() { + hilog.info(DOMAIN, 'testTag', 'onBackup ok'); + await Promise.resolve(); + } + + async onRestore(bundleVersion: BundleVersion) { + hilog.info(DOMAIN, 'testTag', 'onRestore ok %{public}s', JSON.stringify(bundleVersion)); + await Promise.resolve(); + } +} \ No newline at end of file diff --git a/ArkUIKit/ArktsMvvmSample/entry/src/main/ets/model/ThingModel.ets b/ArkUIKit/ArktsMvvmSample/entry/src/main/ets/model/ThingModel.ets new file mode 100644 index 0000000000000000000000000000000000000000..088f1088998af0658d756ae628366143c1737f62 --- /dev/null +++ b/ArkUIKit/ArktsMvvmSample/entry/src/main/ets/model/ThingModel.ets @@ -0,0 +1,21 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// [Start thing_model_class] +export default class ThingModel { + public thingName: string = 'Todo'; + public isFinish: boolean = false; +} +// [End thing_model_class] \ No newline at end of file diff --git a/ArkUIKit/ArktsMvvmSample/entry/src/main/ets/model/TodoListModel.ets b/ArkUIKit/ArktsMvvmSample/entry/src/main/ets/model/TodoListModel.ets new file mode 100644 index 0000000000000000000000000000000000000000..9b78d731861969621b6482ac638f61e543604b27 --- /dev/null +++ b/ArkUIKit/ArktsMvvmSample/entry/src/main/ets/model/TodoListModel.ets @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// [Start to_do_list_model_class] +import { common } from '@kit.AbilityKit'; +import { util } from '@kit.ArkTS'; +import ThingModel from './ThingModel'; + +export default class TodoListModel { + public things: Array = []; + + constructor(things: Array) { + this.things = things; + } + + async loadTasks(context: common.UIAbilityContext) { + let getJson = await context.resourceManager.getRawFileContent('default_tasks.json'); + let textDecoderOptions: util.TextDecoderOptions = { ignoreBOM: true }; + let textDecoder = util.TextDecoder.create('utf-8', textDecoderOptions); + let result = textDecoder.decodeToString(getJson, { stream: false }); + this.things = JSON.parse(result); + } +} +// [End to_do_list_model_class] \ No newline at end of file diff --git a/ArkUIKit/ArktsMvvmSample/entry/src/main/ets/pages/BuilderIndex.ets b/ArkUIKit/ArktsMvvmSample/entry/src/main/ets/pages/BuilderIndex.ets new file mode 100644 index 0000000000000000000000000000000000000000..3bd4cd922e403c1a305f2ad09129b0f851babcd6 --- /dev/null +++ b/ArkUIKit/ArktsMvvmSample/entry/src/main/ets/pages/BuilderIndex.ets @@ -0,0 +1,147 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// [Start builder_source_update_refresh] +@Observed +class TodoListData { + // $r('app.string.xxx')需要替换为开发者所需的资源文件 + public planList: ResourceStr[] = [ + $r('app.string.get_up'), + $r('app.string.breakfast'), + $r('app.string.lunch'), + $r('app.string.dinner'), + $r('app.string.midnight_snack'), + $r('app.string.bathe'), + $r('app.string.sleep') + ]; +} + +@Component +struct StateTodoComponent { + build() { + Row() { + // $r('app.string.all_tasks')需要替换为开发者所需的资源文件 + Text($r('app.string.all_tasks')) + .fontSize(30) + .fontWeight(FontWeight.Bold) + } + .width('100%') + .margin({ top: 10, bottom: 10 }) + } +} + +@Component +struct BuilderAllChooseComponent { + @Link isFinished: boolean; + + build() { + Row() { + // $r('app.string.check_all')需要替换为开发者所需的资源文件 + Button($r('app.string.check_all'), { type: ButtonType.Capsule }) + .onClick(() => { + this.isFinished = !this.isFinished; + }) + .fontSize(30) + .fontWeight(FontWeight.Bold) + .backgroundColor('#f7f6cc74') + } + .padding({ left: 15 }) + .width('100%') + .margin({ top: 10, bottom: 10 }) + } +} + +@Component +struct BuilderThingComponent { + @Prop isFinished: boolean; + @Prop thing: string; + + @Builder + displayIcon(icon: Resource) { + Image(icon) + .width(28) + .height(28) + .onClick(() => { + this.isFinished = !this.isFinished; + }) + // [StartExclude builder_source_update_refresh] + .id(this.thing) + // [EndExclude builder_source_update_refresh] + } + + build() { + // 待办事项1 + Row({ space: 15 }) { + if (this.isFinished) { + // $r('app.string.finished')需要替换为开发者所需的资源文件 + this.displayIcon($r('app.media.finished')); + } else { + // $r('app.string.unfinished')需要替换为开发者所需的资源文件 + this.displayIcon($r('app.media.unfinished')); + } + Text(`${this.thing}`) + .fontSize(24) + .decoration({ type: this.isFinished ? TextDecorationType.LineThrough : TextDecorationType.None }) + .onClick(() => { + this.thing += '啦'; + }) + } + .height('8%') + .width('90%') + .padding({ left: 15 }) + .opacity(this.isFinished ? 0.3 : 1) + .border({ width: 1 }) + .borderColor(Color.White) + .borderRadius(25) + .backgroundColor(Color.White) + } +} + +@Entry +@Component +struct BuilderIndex { + @State isFinished: boolean = false; + @State data: TodoListData = new TodoListData(); // View绑定ViewModel的数据 + @State context1: Context = this.getUIContext().getHostContext()!; + + aboutToAppear(): void { + for (let i = 0; i < this.data.planList.length; i++) { + this.data.planList[i] = this.context1!.resourceManager.getStringSync((this.data.planList[i] as Resource).id) + } + } + + build() { + Column() { + // 全部待办 + StateTodoComponent() + + // 全选 + BuilderAllChooseComponent({ isFinished: this.isFinished }) + + List() { + ForEach(this.data.planList, (item: string) => { + // 待办事项1 + BuilderThingComponent({ isFinished: this.isFinished, thing: item }) + .margin(5) + }) + } + } + .height('100%') + .width('100%') + .margin({ top: 5, bottom: 5 }) + .backgroundColor('#90f1f3f5') + } +} +// [End builder_source_update_refresh] \ No newline at end of file diff --git a/ArkUIKit/ArktsMvvmSample/entry/src/main/ets/pages/ForEachIndex.ets b/ArkUIKit/ArktsMvvmSample/entry/src/main/ets/pages/ForEachIndex.ets new file mode 100644 index 0000000000000000000000000000000000000000..96dc62db018c1ae4b4fe4ecd7272f0e0c85ac089 --- /dev/null +++ b/ArkUIKit/ArktsMvvmSample/entry/src/main/ets/pages/ForEachIndex.ets @@ -0,0 +1,136 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// [Start foreach_update_refresh] +@Component +struct ForEachTodoComponent { + build() { + Row() { + // $r('app.string.all_tasks')需要替换为开发者所需的资源文件 + Text($r('app.string.all_tasks')) + .fontSize(30) + .fontWeight(FontWeight.Bold) + } + .width('100%') + .margin({ top: 10, bottom: 10 }) + } +} + +@Component +struct ForEachAllChooseComponent { + @Link isFinished: boolean; + + build() { + Row() { + // $r('app.string.check_all')需要替换为开发者所需的资源文件 + Button($r('app.string.check_all'), { type: ButtonType.Normal }) + .onClick(() => { + this.isFinished = !this.isFinished; + }) + .fontSize(30) + .fontWeight(FontWeight.Bold) + .backgroundColor('#f7f6cc74') + } + .padding({ left: 15 }) + .width('100%') + .margin({ top: 10, bottom: 10 }) + } +} + +@Component +struct ForEachThingComponent { + @Prop isFinished: boolean; + @Prop thing: string; + + build() { + // 待办事项1 + Row({ space: 15 }) { + if (this.isFinished) { + // $r('app.string.finished')需要替换为开发者所需的资源文件 + Image($r('app.media.finished')) + .width(28) + .height(28) + } else { + // $r('app.string.unfinished')需要替换为开发者所需的资源文件 + Image($r('app.media.unfinished')) + .width(28) + .height(28) + // [StartExclude foreach_update_refresh] + .id(this.thing) + // [EndExclude foreach_update_refresh] + } + Text(`${this.thing}`) + .fontSize(24) + .decoration({ type: this.isFinished ? TextDecorationType.LineThrough : TextDecorationType.None }) + } + .height('8%') + .width('90%') + .padding({ left: 15 }) + .opacity(this.isFinished ? 0.3 : 1) + .border({ width: 1 }) + .borderColor(Color.White) + .borderRadius(25) + .backgroundColor(Color.White) + .onClick(() => { + this.isFinished = !this.isFinished; + }) + } +} + +@Entry +@Component +struct ForEachIndex { + @State isFinished: boolean = false; + // $r('app.string.xxx')需要替换为开发者所需的资源文件 + @State planList: ResourceStr[] = [ + $r('app.string.get_up'), + $r('app.string.breakfast'), + $r('app.string.lunch'), + $r('app.string.dinner'), + $r('app.string.midnight_snack'), + $r('app.string.bathe'), + $r('app.string.sleep') + ]; + context1 = this.getUIContext().getHostContext(); + + aboutToAppear(): void { + for (let i = 0; i < this.planList.length; i++) { + this.planList[i] = this.context1!.resourceManager.getStringSync((this.planList[i] as Resource).id); + }; + } + + build() { + Column() { + // 全部待办 + ForEachTodoComponent() + + // 全选 + ForEachAllChooseComponent({ isFinished: this.isFinished }) + + List() { + ForEach(this.planList, (item: string) => { + // 待办事项1 + ForEachThingComponent({ isFinished: this.isFinished, thing: item }) + .margin(5) + }) + } + } + .height('100%') + .width('100%') + .margin({ top: 5, bottom: 5 }) + .backgroundColor('#90f1f3f5') + } +} +// [End foreach_update_refresh] \ No newline at end of file diff --git a/ArkUIKit/ArktsMvvmSample/entry/src/main/ets/pages/Index.ets b/ArkUIKit/ArktsMvvmSample/entry/src/main/ets/pages/Index.ets new file mode 100644 index 0000000000000000000000000000000000000000..42baa38cf3cfeab89694201f70bd349a232e04c0 --- /dev/null +++ b/ArkUIKit/ArktsMvvmSample/entry/src/main/ets/pages/Index.ets @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// [Start mvvm_model_main_index] +import { common } from '@kit.AbilityKit'; +// import ViewModel +import TodoListViewModel from '../viewModel/TodoListViewModel'; + +// import View +import { TodoComponent } from '../views/TodoComponent'; +import { AllChooseComponent } from '../views/AllChooseComponent'; +import { TodoListComponent } from '../views/TodoListComponent'; + +@Entry +@Component +struct TodoList { + @State todoListViewModel: TodoListViewModel = new TodoListViewModel(); // View绑定ViewModel的数据 + private context = this.getUIContext().getHostContext() as common.UIAbilityContext; + + async aboutToAppear() { + await this.todoListViewModel.loadTasks(this.context); + } + + build() { + Column() { + Row({ space: 40 }) { + // 全部待办 + TodoComponent() + // 全选 + AllChooseComponent({ todoListViewModel: this.todoListViewModel }) + } + + Column() { + TodoListComponent({ thingViewModelArray: this.todoListViewModel.things }) + } + } + .height('100%') + .width('100%') + .margin({ top: 5, bottom: 5 }) + .backgroundColor('#90f1f3f5') + } +} +// [End mvvm_model_main_index] \ No newline at end of file diff --git a/ArkUIKit/ArktsMvvmSample/entry/src/main/ets/pages/PropLinkIndex.ets b/ArkUIKit/ArktsMvvmSample/entry/src/main/ets/pages/PropLinkIndex.ets new file mode 100644 index 0000000000000000000000000000000000000000..eff123b838db0caf76de2a6fe3b8f2a911443f28 --- /dev/null +++ b/ArkUIKit/ArktsMvvmSample/entry/src/main/ets/pages/PropLinkIndex.ets @@ -0,0 +1,142 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// [Start prop_link_update_refresh] +@Component +struct PropLinkTodoComponent { + build() { + Row() { + // $r('app.string.all_tasks')需要替换为开发者所需的资源文件 + Text($r('app.string.all_tasks')) + .fontSize(30) + .fontWeight(FontWeight.Bold) + } + .width('100%') + .margin({ top: 10, bottom: 10 }) + } +} + +@Component +struct PropLinkAllChooseComponent { + @Link isFinished: boolean; + + build() { + Row() { + // $r('app.string.check_all')需要替换为开发者所需的资源文件 + Button($r('app.string.check_all'), { type: ButtonType.Normal }) + .onClick(() => { + this.isFinished = !this.isFinished; + }) + .fontSize(30) + .fontWeight(FontWeight.Bold) + .backgroundColor('#f7f6cc74') + } + .padding({ left: 15 }) + .width('100%') + .margin({ top: 10, bottom: 10 }) + } +} + +@Component +struct ThingComponent1 { + @Prop isFinished: boolean; + + build() { + // 待办事项1 + Row({ space: 15 }) { + if (this.isFinished) { + // $r('app.string.finished')需要替换为开发者所需的资源文件 + Image($r('app.media.finished')) + .width(28) + .height(28) + } else { + // $r('app.string.unfinished')需要替换为开发者所需的资源文件 + Image($r('app.media.unfinished')) + .width(28) + .height(28) + } + Text($r('app.string.learn_chinese')) + .fontSize(24) + .decoration({ type: this.isFinished ? TextDecorationType.LineThrough : TextDecorationType.None }) + } + .height('40%') + .width('100%') + .border({ width: 5 }) + .padding({ left: 15 }) + .onClick(() => { + this.isFinished = !this.isFinished; + }) + } +} + +@Component +struct ThingComponent2 { + @Prop isFinished: boolean; + + build() { + // 待办事项1 + Row({ space: 15 }) { + if (this.isFinished) { + // $r('app.string.finished')需要替换为开发者所需的资源文件 + Image($r('app.media.finished')) + .width(28) + .height(28) + } else { + // $r('app.string.unfinished')需要替换为开发者所需的资源文件 + Image($r('app.media.unfinished')) + .width(28) + .height(28) + } + // $r('app.string.learn_advanced_math')需要替换为开发者所需的资源文件 + Text($r('app.string.learn_advanced_math')) + .fontSize(24) + .decoration({ type: this.isFinished ? TextDecorationType.LineThrough : TextDecorationType.None }) + } + .height('40%') + .width('100%') + .border({ width: 5 }) + .padding({ left: 15 }) + .onClick(() => { + this.isFinished = !this.isFinished; + }) + } +} + +@Entry +@Component +struct PropLinkIndex { + @State isFinished: boolean = false; + + build() { + Column() { + // 全部待办 + PropLinkTodoComponent() + + // 全选 + PropLinkAllChooseComponent({ isFinished: this.isFinished }) + + // 待办事项1 + ThingComponent1({ isFinished: this.isFinished }) + + // 待办事项2 + ThingComponent2({ isFinished: this.isFinished }) + } + .height('100%') + .width('100%') + .margin({ top: 5, bottom: 5 }) + .backgroundColor('#90f1f3f5') + } +} +// [End prop_link_update_refresh] \ No newline at end of file diff --git a/ArkUIKit/ArktsMvvmSample/entry/src/main/ets/pages/StateIndex.ets b/ArkUIKit/ArktsMvvmSample/entry/src/main/ets/pages/StateIndex.ets new file mode 100644 index 0000000000000000000000000000000000000000..761090cd7ee69c00b85f78fdd182c5824e4970e4 --- /dev/null +++ b/ArkUIKit/ArktsMvvmSample/entry/src/main/ets/pages/StateIndex.ets @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// [Start state_source_update_refresh] +@Entry +@Component +struct StateIndex { + @State isFinished: boolean = false; + + build() { + Column() { + Row() { + // $r('app.string.all_tasks')需要替换为开发者所需的资源文件 + Text($r('app.string.all_tasks')) + .fontSize(30) + .fontWeight(FontWeight.Bold) + } + .width('100%') + .margin({ top: 10, bottom: 10 }) + + // 待办事项 + Row({ space: 15 }) { + if (this.isFinished) { + // $r('app.string.finished')需要替换为开发者所需的资源文件 + Image($r('app.media.finished')) + .width(28) + .height(28) + } else { + // $r('app.string.unfinished')需要替换为开发者所需的资源文件 + Image($r('app.media.unfinished')) + .width(28) + .height(28) + } + // $r('app.string.learn_advanced_math')需要替换为开发者所需的资源文件 + Text($r('app.string.learn_advanced_math')) + .fontSize(24) + .decoration({ type: this.isFinished ? TextDecorationType.LineThrough : TextDecorationType.None }) + } + .height('40%') + .width('100%') + .border({ width: 5 }) + .padding({ left: 15 }) + .onClick(() => { + this.isFinished = !this.isFinished; + }) + } + .height('100%') + .width('100%') + .margin({ top: 5, bottom: 5 }) + .backgroundColor('#90f1f3f5') + } +} +// [End state_source_update_refresh] \ No newline at end of file diff --git a/ArkUIKit/ArktsMvvmSample/entry/src/main/ets/viewModel/ThingViewModel.ets b/ArkUIKit/ArktsMvvmSample/entry/src/main/ets/viewModel/ThingViewModel.ets new file mode 100644 index 0000000000000000000000000000000000000000..cccc3afd25a8842e99a7bc694f74911a63884903 --- /dev/null +++ b/ArkUIKit/ArktsMvvmSample/entry/src/main/ets/viewModel/ThingViewModel.ets @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// [Start thing_view_model] +import ThingModel from '../model/ThingModel'; + +@Observed +export default class ThingViewModel { + @Track public thingName: string = 'Todo'; + @Track public isFinish: boolean = false; + + updateTask(thing: ThingModel) { + this.thingName = thing.thingName; + this.isFinish = thing.isFinish; + } + + updateIsFinish(): void { + this.isFinish = !this.isFinish; + } + + addSuffixes(): void { + this.thingName += '啦'; + } +} +// [End thing_view_model] \ No newline at end of file diff --git a/ArkUIKit/ArktsMvvmSample/entry/src/main/ets/viewModel/TodoListViewModel.ets b/ArkUIKit/ArktsMvvmSample/entry/src/main/ets/viewModel/TodoListViewModel.ets new file mode 100644 index 0000000000000000000000000000000000000000..474bdd9b7c3a74f962c2511f21ad316e3ac946a9 --- /dev/null +++ b/ArkUIKit/ArktsMvvmSample/entry/src/main/ets/viewModel/TodoListViewModel.ets @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// [Start to_do_list_view_model] +import ThingViewModel from './ThingViewModel'; +import { common } from '@kit.AbilityKit'; +import TodoListModel from '../model/TodoListModel'; + +@Observed +export class ThingViewModelArray extends Array { +} + +@Observed +export default class TodoListViewModel { + @Track public isChoosen: boolean = true; + @Track public things: ThingViewModelArray = new ThingViewModelArray(); + + async loadTasks(context: common.UIAbilityContext) { + let todoList = new TodoListModel([]); + await todoList.loadTasks(context); + for (let thing of todoList.things) { + let todoListViewModel = new ThingViewModel(); + todoListViewModel.updateTask(thing); + this.things.push(todoListViewModel); + } + } + + chooseAll(): void { + for (let thing of this.things) { + thing.isFinish = this.isChoosen; + } + this.isChoosen = !this.isChoosen; + } +} +// [End to_do_list_view_model] \ No newline at end of file diff --git a/ArkUIKit/ArktsMvvmSample/entry/src/main/ets/views/AllChooseComponent.ets b/ArkUIKit/ArktsMvvmSample/entry/src/main/ets/views/AllChooseComponent.ets new file mode 100644 index 0000000000000000000000000000000000000000..626575a476e798dd923472ec83199d2a215a0189 --- /dev/null +++ b/ArkUIKit/ArktsMvvmSample/entry/src/main/ets/views/AllChooseComponent.ets @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// [Start all_choose_component_view] +import TodoListViewModel from '../viewModel/TodoListViewModel'; +import { common } from '@kit.AbilityKit'; + +@Component +export struct AllChooseComponent { + context1 = this.getUIContext().getHostContext() as common.UIAbilityContext; + // $r('app.string.check_all')需要替换为开发者所需的资源文件 + @State titleName: ResourceStr = this.context1.resourceManager.getStringSync($r('app.string.check_all').id); + @Link todoListViewModel: TodoListViewModel; + + build() { + Row() { + Button(`${this.titleName}`, { type: ButtonType.Capsule }) + .onClick(() => { + this.todoListViewModel.chooseAll(); // View层点击事件发生时,调用ViewModel层方法chooseAll处理逻辑 + // $r('app.string.xxx')需要替换为开发者所需的资源文件 + this.titleName = this.todoListViewModel.isChoosen ? + this.context1.resourceManager.getStringSync($r('app.string.check_all').id) + : this.context1.resourceManager.getStringSync($r('app.string.deselect_all').id); + }) + .fontSize(30) + .fontWeight(FontWeight.Bold) + .backgroundColor('#f7f6cc74') + } + .padding({ left: this.todoListViewModel.isChoosen ? 15 : 0 }) + .width('100%') + .margin({ top: 10, bottom: 10 }) + } +} +// [End all_choose_component_view] \ No newline at end of file diff --git a/ArkUIKit/ArktsMvvmSample/entry/src/main/ets/views/ThingComponent.ets b/ArkUIKit/ArktsMvvmSample/entry/src/main/ets/views/ThingComponent.ets new file mode 100644 index 0000000000000000000000000000000000000000..ab19aa3bf053e3be17f6c77894615869e52c7905 --- /dev/null +++ b/ArkUIKit/ArktsMvvmSample/entry/src/main/ets/views/ThingComponent.ets @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// [Start thing_component_view] +import ThingViewModel from '../viewModel/ThingViewModel'; + +@Component +export struct ThingComponent { + @ObjectLink thing: ThingViewModel; + + @Builder + displayIcon(icon: Resource) { + Image(icon) + .width(28) + .height(28) + .onClick(() => { + this.thing.updateIsFinish(); // View层点击事件发生时,调用ViewModel层方法updateIsFinish处理逻辑 + }) + // [StartExclude builder_source_update_refresh] + .id(this.thing.thingName) + // [EndExclude builder_source_update_refresh] + } + + build() { + // 待办事项 + Row({ space: 15 }) { + if (this.thing.isFinish) { + // $r('app.string.finished')需要替换为开发者所需的资源文件 + this.displayIcon($r('app.media.finished')); + } else { + // $r('app.string.unfinished')需要替换为开发者所需的资源文件 + this.displayIcon($r('app.media.unfinished')); + } + + Text(`${this.thing.thingName}`) + .fontSize(24) + .decoration({ type: this.thing.isFinish ? TextDecorationType.LineThrough : TextDecorationType.None }) + .onClick(() => { + this.thing.addSuffixes(); // View层点击事件发生时,调用ViewModel层方法addSuffixes处理逻辑 + }) + } + .height('8%') + .width('90%') + .padding({ left: 15 }) + .opacity(this.thing.isFinish ? 0.3 : 1) + .border({ width: 1 }) + .borderColor(Color.White) + .borderRadius(25) + .backgroundColor(Color.White) + } +} +// [End thing_component_view] \ No newline at end of file diff --git a/ArkUIKit/ArktsMvvmSample/entry/src/main/ets/views/TodoComponent.ets b/ArkUIKit/ArktsMvvmSample/entry/src/main/ets/views/TodoComponent.ets new file mode 100644 index 0000000000000000000000000000000000000000..93968970666386eb9380f7d1f3009f638db7bcc2 --- /dev/null +++ b/ArkUIKit/ArktsMvvmSample/entry/src/main/ets/views/TodoComponent.ets @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// [Start to_do_component_view] +@Component +export struct TodoComponent { + build() { + Row() { + // $r('app.string.all_tasks')需要替换为开发者所需的资源文件 + Text($r('app.string.all_tasks')) + .fontSize(30) + .fontWeight(FontWeight.Bold) + } + .padding({ left: 15 }) + .width('50%') + .margin({ top: 10, bottom: 10 }) + } +} +// [End to_do_component_view] \ No newline at end of file diff --git a/ArkUIKit/ArktsMvvmSample/entry/src/main/ets/views/TodoListComponent.ets b/ArkUIKit/ArktsMvvmSample/entry/src/main/ets/views/TodoListComponent.ets new file mode 100644 index 0000000000000000000000000000000000000000..7dbf070c9cfc5960aeb716929943b70b00617ce2 --- /dev/null +++ b/ArkUIKit/ArktsMvvmSample/entry/src/main/ets/views/TodoListComponent.ets @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// [Start to_do_list_component_view] +import ThingViewModel from '../viewModel/ThingViewModel'; +import { ThingViewModelArray } from '../viewModel/TodoListViewModel' +import { ThingComponent } from './ThingComponent'; + +@Component +export struct TodoListComponent { + @ObjectLink thingViewModelArray: ThingViewModelArray; + + build() { + Column() { + List() { + ForEach(this.thingViewModelArray, (item: ThingViewModel) => { + // 待办事项 + ListItem() { + ThingComponent({ thing: item }) + .margin(5) + } + }, (item: ThingViewModel) => { + return item.thingName; + }) + } + } + } +} +// [End to_do_list_component_view] \ No newline at end of file diff --git a/ArkUIKit/ArktsMvvmSample/entry/src/main/module.json5 b/ArkUIKit/ArktsMvvmSample/entry/src/main/module.json5 new file mode 100644 index 0000000000000000000000000000000000000000..e4226557b12a7322c888516a211fcf6c981c7122 --- /dev/null +++ b/ArkUIKit/ArktsMvvmSample/entry/src/main/module.json5 @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +{ + "module": { + "name": "entry", + "type": "entry", + "description": "$string:module_desc", + "mainElement": "EntryAbility", + "deviceTypes": [ + "default" + ], + "deliveryWithInstall": true, + "installationFree": false, + "pages": "$profile:main_pages", + "abilities": [ + { + "name": "EntryAbility", + "srcEntry": "./ets/entryability/EntryAbility.ets", + "description": "$string:EntryAbility_desc", + "icon": "$media:layered_image", + "label": "$string:EntryAbility_label", + "startWindowIcon": "$media:startIcon", + "startWindowBackground": "$color:start_window_background", + "exported": true, + "skills": [ + { + "entities": [ + "entity.system.home" + ], + "actions": [ + "ohos.want.action.home" + ] + } + ] + } + ], + "extensionAbilities": [ + { + "name": "EntryBackupAbility", + "srcEntry": "./ets/entrybackupability/EntryBackupAbility.ets", + "type": "backup", + "exported": false, + "metadata": [ + { + "name": "ohos.extension.backup", + "resource": "$profile:backup_config" + } + ], + } + ] + } +} \ No newline at end of file diff --git a/ArkUIKit/ArktsMvvmSample/entry/src/main/resources/base/element/color.json b/ArkUIKit/ArktsMvvmSample/entry/src/main/resources/base/element/color.json new file mode 100644 index 0000000000000000000000000000000000000000..3c712962da3c2751c2b9ddb53559afcbd2b54a02 --- /dev/null +++ b/ArkUIKit/ArktsMvvmSample/entry/src/main/resources/base/element/color.json @@ -0,0 +1,8 @@ +{ + "color": [ + { + "name": "start_window_background", + "value": "#FFFFFF" + } + ] +} \ No newline at end of file diff --git a/ArkUIKit/ArktsMvvmSample/entry/src/main/resources/base/element/float.json b/ArkUIKit/ArktsMvvmSample/entry/src/main/resources/base/element/float.json new file mode 100644 index 0000000000000000000000000000000000000000..33ea22304f9b1485b5f22d811023701b5d4e35b6 --- /dev/null +++ b/ArkUIKit/ArktsMvvmSample/entry/src/main/resources/base/element/float.json @@ -0,0 +1,8 @@ +{ + "float": [ + { + "name": "page_text_font_size", + "value": "50fp" + } + ] +} diff --git a/ArkUIKit/ArktsMvvmSample/entry/src/main/resources/base/element/string.json b/ArkUIKit/ArktsMvvmSample/entry/src/main/resources/base/element/string.json new file mode 100644 index 0000000000000000000000000000000000000000..696842e6883744cc7c1573cbe941165393adde5f --- /dev/null +++ b/ArkUIKit/ArktsMvvmSample/entry/src/main/resources/base/element/string.json @@ -0,0 +1,68 @@ +{ + "string": [ + { + "name": "module_desc", + "value": "module description" + }, + { + "name": "EntryAbility_desc", + "value": "description" + }, + { + "name": "EntryAbility_label", + "value": "label" + }, + { + "name": "get_up", + "value": "7.30 起床" + }, + { + "name": "breakfast", + "value": "8.30 早餐" + }, + { + "name": "lunch", + "value": "11.30 中餐" + }, + { + "name": "dinner", + "value": "17.30 晚餐" + }, + { + "name": "midnight_snack", + "value": "21.30 夜宵" + }, + { + "name": "bathe", + "value": "22.30 洗澡" + }, + { + "name": "sleep", + "value": "1.30 睡觉" + }, + { + "name": "all_tasks", + "value": "全部待办" + }, + { + "name": "check_all", + "value": "全选" + }, + { + "name": "learn_advanced_math", + "value": "学习高数" + }, + { + "name": "learn_chinese", + "value": "学习语文" + }, + { + "name": "la_la", + "value": "啦" + }, + { + "name": "deselect_all", + "value": "取消全选" + } + ] +} \ No newline at end of file diff --git a/ArkUIKit/ArktsMvvmSample/entry/src/main/resources/base/media/background.png b/ArkUIKit/ArktsMvvmSample/entry/src/main/resources/base/media/background.png new file mode 100644 index 0000000000000000000000000000000000000000..923f2b3f27e915d6871871deea0420eb45ce102f Binary files /dev/null and b/ArkUIKit/ArktsMvvmSample/entry/src/main/resources/base/media/background.png differ diff --git a/ArkUIKit/ArktsMvvmSample/entry/src/main/resources/base/media/finished.png b/ArkUIKit/ArktsMvvmSample/entry/src/main/resources/base/media/finished.png new file mode 100644 index 0000000000000000000000000000000000000000..4cf1ad3f15199bbc3a3127b42f6413e68db10cd1 Binary files /dev/null and b/ArkUIKit/ArktsMvvmSample/entry/src/main/resources/base/media/finished.png differ diff --git a/ArkUIKit/ArktsMvvmSample/entry/src/main/resources/base/media/foreground.png b/ArkUIKit/ArktsMvvmSample/entry/src/main/resources/base/media/foreground.png new file mode 100644 index 0000000000000000000000000000000000000000..97014d3e10e5ff511409c378cd4255713aecd85f Binary files /dev/null and b/ArkUIKit/ArktsMvvmSample/entry/src/main/resources/base/media/foreground.png differ diff --git a/ArkUIKit/ArktsMvvmSample/entry/src/main/resources/base/media/layered_image.json b/ArkUIKit/ArktsMvvmSample/entry/src/main/resources/base/media/layered_image.json new file mode 100644 index 0000000000000000000000000000000000000000..fb49920440fb4d246c82f9ada275e26123a2136a --- /dev/null +++ b/ArkUIKit/ArktsMvvmSample/entry/src/main/resources/base/media/layered_image.json @@ -0,0 +1,7 @@ +{ + "layered-image": + { + "background" : "$media:background", + "foreground" : "$media:foreground" + } +} \ No newline at end of file diff --git a/ArkUIKit/ArktsMvvmSample/entry/src/main/resources/base/media/startIcon.png b/ArkUIKit/ArktsMvvmSample/entry/src/main/resources/base/media/startIcon.png new file mode 100644 index 0000000000000000000000000000000000000000..205ad8b5a8a42e8762fbe4899b8e5e31ce822b8b Binary files /dev/null and b/ArkUIKit/ArktsMvvmSample/entry/src/main/resources/base/media/startIcon.png differ diff --git a/ArkUIKit/ArktsMvvmSample/entry/src/main/resources/base/media/unfinished.png b/ArkUIKit/ArktsMvvmSample/entry/src/main/resources/base/media/unfinished.png new file mode 100644 index 0000000000000000000000000000000000000000..4c25dc3584640763033e6e81d64bdf6b974e8834 Binary files /dev/null and b/ArkUIKit/ArktsMvvmSample/entry/src/main/resources/base/media/unfinished.png differ diff --git a/ArkUIKit/ArktsMvvmSample/entry/src/main/resources/base/profile/backup_config.json b/ArkUIKit/ArktsMvvmSample/entry/src/main/resources/base/profile/backup_config.json new file mode 100644 index 0000000000000000000000000000000000000000..78f40ae7c494d71e2482278f359ec790ca73471a --- /dev/null +++ b/ArkUIKit/ArktsMvvmSample/entry/src/main/resources/base/profile/backup_config.json @@ -0,0 +1,3 @@ +{ + "allowToBackupRestore": true +} \ No newline at end of file diff --git a/ArkUIKit/ArktsMvvmSample/entry/src/main/resources/base/profile/main_pages.json b/ArkUIKit/ArktsMvvmSample/entry/src/main/resources/base/profile/main_pages.json new file mode 100644 index 0000000000000000000000000000000000000000..ebebd027637dd1a106998e6d04c42b2af3a56412 --- /dev/null +++ b/ArkUIKit/ArktsMvvmSample/entry/src/main/resources/base/profile/main_pages.json @@ -0,0 +1,9 @@ +{ + "src": [ + "pages/Index", + "pages/BuilderIndex", + "pages/ForEachIndex", + "pages/PropLinkIndex", + "pages/StateIndex" + ] +} diff --git a/ArkUIKit/ArktsMvvmSample/entry/src/main/resources/dark/element/color.json b/ArkUIKit/ArktsMvvmSample/entry/src/main/resources/dark/element/color.json new file mode 100644 index 0000000000000000000000000000000000000000..79b11c2747aec33e710fd3a7b2b3c94dd9965499 --- /dev/null +++ b/ArkUIKit/ArktsMvvmSample/entry/src/main/resources/dark/element/color.json @@ -0,0 +1,8 @@ +{ + "color": [ + { + "name": "start_window_background", + "value": "#000000" + } + ] +} \ No newline at end of file diff --git a/ArkUIKit/ArktsMvvmSample/entry/src/main/resources/rawfile/default_tasks.json b/ArkUIKit/ArktsMvvmSample/entry/src/main/resources/rawfile/default_tasks.json new file mode 100644 index 0000000000000000000000000000000000000000..adcc57abc891ecde3720e65f74a581cc2498c7e3 --- /dev/null +++ b/ArkUIKit/ArktsMvvmSample/entry/src/main/resources/rawfile/default_tasks.json @@ -0,0 +1,9 @@ +[ + {"thingName": "7.30 起床", "isFinish": false}, + {"thingName": "8.30 早餐", "isFinish": false}, + {"thingName": "11.30 中餐", "isFinish": false}, + {"thingName": "17.30 晚餐", "isFinish": false}, + {"thingName": "21.30 夜宵", "isFinish": false}, + {"thingName": "22.30 洗澡", "isFinish": false}, + {"thingName": "1.30 睡觉", "isFinish": false} +] \ No newline at end of file diff --git a/ArkUIKit/ArktsMvvmSample/entry/src/mock/mock-config.json5 b/ArkUIKit/ArktsMvvmSample/entry/src/mock/mock-config.json5 new file mode 100644 index 0000000000000000000000000000000000000000..b9a78e201535765168a92d3543c690273ecdc019 --- /dev/null +++ b/ArkUIKit/ArktsMvvmSample/entry/src/mock/mock-config.json5 @@ -0,0 +1,17 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +{ +} \ No newline at end of file diff --git a/ArkUIKit/ArktsMvvmSample/entry/src/ohosTest/ets/test/Ability.test.ets b/ArkUIKit/ArktsMvvmSample/entry/src/ohosTest/ets/test/Ability.test.ets new file mode 100644 index 0000000000000000000000000000000000000000..1062c2f0de1ec4b42ef527c7176185420137f56d --- /dev/null +++ b/ArkUIKit/ArktsMvvmSample/entry/src/ohosTest/ets/test/Ability.test.ets @@ -0,0 +1,219 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { describe, beforeAll, beforeEach, afterEach, afterAll, it, Level } from '@ohos/hypium'; +import AbilityDelegatorRegistry from '@ohos.app.ability.abilityDelegatorRegistry'; +import { Want } from '@kit.AbilityKit'; +import { router } from '@kit.ArkUI'; +import { Driver, ON, Component, Point } from '@ohos.UiTest'; + +const DELAY_TIME01 = 1000; //异步等待1秒 +const DELAY_TIME02 = 2000; //异步等待2秒 + +function sleep(time: number) { + return new Promise((resolve) => setTimeout(resolve, time)); +} + +let driver = Driver.create(); + +async function getCenterPoint(comp: Component, offset: number): Promise { + // 获取文件控件边框 + let rect = await comp.getBounds(); + // 计算文字控件高度 + let height = rect.bottom - rect.top; + // 获取文字控件中心点 + let point: Point = await comp.getBoundsCenter(); + point = { x: point.x, y: point.y - height * offset }; + return point; +} + +export default function abilityTest() { + describe('ActsAbilityTest', () => { + // Defines a test suite. Two parameters are supported: test suite name and test suite function. + beforeAll(async () => { + const delegator = AbilityDelegatorRegistry.getAbilityDelegator(); + let want: Want = { + bundleName: "com.sample.arktsmvvmsample", + abilityName: "EntryAbility", + moduleName: "entry" + }; + delegator.startAbility(want); + await sleep(DELAY_TIME01); + // Presets an action, which is performed only once before all test cases of the test suite start. + // This API supports only one parameter: preset action function. + }) + beforeEach(() => { + // Presets an action, which is performed before each unit test case starts. + // The number of execution times is the same as the number of test cases defined by **it**. + // This API supports only one parameter: preset action function. + }) + afterEach(() => { + // Presets a clear action, which is performed after each unit test case ends. + // The number of execution times is the same as the number of test cases defined by **it**. + // This API supports only one parameter: clear action function. + }) + afterAll(() => { + // Presets a clear action, which is performed after all test cases of the test suite end. + // This API supports only one parameter: clear action function. + }) + + /** + * @tc.number SUB_Arkui_Mvvm_Introduce_0100 + * @tc.name SUB_Arkui_Mvvm_Introduce_0100 + * @tc.desc To introduce the MVVM framework + * @tc.size MediumTest + * @tc.type Function + * @tc.level Level 1 + */ + it('SUB_Arkui_Mvvm_Introduce_0100', Level.LEVEL1, + async (done: Function) => { + let box1: Component = await driver.findComponent(ON.text("学习高数")); + await box1.click(); + await sleep(DELAY_TIME01); + await box1.click(); + await sleep(DELAY_TIME01); + done(); + }) + + /** + * @tc.number SUB_Arkui_Mvvm_Introduce_0200 + * @tc.name SUB_Arkui_Mvvm_Introduce_0200 + * @tc.desc To introduce the MVVM framework + * @tc.size MediumTest + * @tc.type Function + * @tc.level Level 1 + */ + it('SUB_Arkui_Mvvm_Introduce_0200', Level.LEVEL1, + async (done: Function) => { + router.pushUrl({ url: "pages/PropLinkIndex" }); + await sleep(DELAY_TIME01); + let box: Component = await driver.findComponent(ON.text("学习高数")); + await box.click(); + await sleep(DELAY_TIME01); + await box.click(); + await sleep(DELAY_TIME01); + let box1: Component = await driver.findComponent(ON.text('全选')); + await box1.click(); + await sleep(DELAY_TIME01); + await box1.click(); + await sleep(DELAY_TIME01); + done(); + }) + + /** + * @tc.number SUB_Arkui_Mvvm_Introduce_0300 + * @tc.name SUB_Arkui_Mvvm_Introduce_0300 + * @tc.desc To introduce the MVVM framework + * @tc.size MediumTest + * @tc.type Function + * @tc.level Level 1 + */ + it('SUB_Arkui_Mvvm_Introduce_0300', Level.LEVEL1, + async (done: Function) => { + router.pushUrl({ url: "pages/ForEachIndex" }); + await sleep(DELAY_TIME02); + let box1: Component = await driver.findComponent(ON.id('7.30 起床')); + let coordinate1 = await getCenterPoint(box1, 0); + await box1.click(); + await sleep(DELAY_TIME01); + await driver.click(coordinate1.x, coordinate1.y); + await sleep(DELAY_TIME01); + let box2: Component = await driver.findComponent(ON.id('8.30 早餐')); + let coordinate2 = await getCenterPoint(box2, 0); + await box2.click(); + await sleep(DELAY_TIME01); + await driver.click(coordinate2.x, coordinate2.y); + await sleep(DELAY_TIME01); + let box3: Component = await driver.findComponent(ON.text('8.30 早餐')); + await box3.click(); + await sleep(DELAY_TIME01); + await box3.click(); + await sleep(DELAY_TIME01); + let box4: Component = await driver.findComponent(ON.text('全选')); + await box4.click(); + await sleep(DELAY_TIME01); + await box4.click(); + await sleep(DELAY_TIME01); + done(); + }) + + /** + * @tc.number SUB_Arkui_Mvvm_Introduce_0400 + * @tc.name SUB_Arkui_Mvvm_Introduce_0400 + * @tc.desc To introduce the MVVM framework + * @tc.size MediumTest + * @tc.type Function + * @tc.level Level 1 + */ + it('SUB_Arkui_Mvvm_Introduce_0400', Level.LEVEL1, + async (done: Function) => { + router.pushUrl({ url: "pages/BuilderIndex" }); + await sleep(DELAY_TIME01); + let box: Component = await driver.findComponent(ON.text('全选')); + await box.click(); + await sleep(DELAY_TIME01); + await box.click(); + await sleep(DELAY_TIME01); + let box1: Component = await driver.findComponent(ON.id('7.30 起床')); + let coordinate = await getCenterPoint(box1, 0); + await box1.click(); + await sleep(DELAY_TIME01); + await driver.click(coordinate.x, coordinate.y); + await sleep(DELAY_TIME01); + let box2: Component = await driver.findComponent(ON.text('7.30 起床')); + await box2.click(); + await sleep(DELAY_TIME01); + await box2.click(); + await sleep(DELAY_TIME01); + let box3: Component = await driver.findComponent(ON.text('8.30 早餐')); + await box3.click(); + await sleep(DELAY_TIME01); + await box3.click(); + await sleep(DELAY_TIME01); + done(); + }) + + /** + * @tc.number SUB_Arkui_Mvvm_Introduce_0500 + * @tc.name SUB_Arkui_Mvvm_Introduce_0500 + * @tc.desc To introduce the MVVM framework + * @tc.size MediumTest + * @tc.type Function + * @tc.level Level 1 + */ + it('SUB_Arkui_Mvvm_Introduce_0500', Level.LEVEL1, + async (done: Function) => { + router.pushUrl({ url: "pages/Index" }); + await sleep(DELAY_TIME01); + let box: Component = await driver.findComponent(ON.text('全选')); + await box.click(); + await sleep(DELAY_TIME01); + await box.click(); + await sleep(DELAY_TIME01); + let box1: Component = await driver.findComponent(ON.id('7.30 起床')); + let coordinate = await getCenterPoint(box1, 0); + await box1.click(); + await sleep(DELAY_TIME01); + await driver.click(coordinate.x, coordinate.y); + await sleep(DELAY_TIME01); + let box2: Component = await driver.findComponent(ON.text("7.30 起床")); + await box2.click(); + await sleep(DELAY_TIME01); + await box2.click(); + await sleep(DELAY_TIME01); + done(); + }) + }) +} \ No newline at end of file diff --git a/ArkUIKit/ArktsMvvmSample/entry/src/ohosTest/ets/test/List.test.ets b/ArkUIKit/ArktsMvvmSample/entry/src/ohosTest/ets/test/List.test.ets new file mode 100644 index 0000000000000000000000000000000000000000..1eac52fcebe8958e19a7b8fed2e8f39c520a3e42 --- /dev/null +++ b/ArkUIKit/ArktsMvvmSample/entry/src/ohosTest/ets/test/List.test.ets @@ -0,0 +1,20 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import abilityTest from './Ability.test'; + +export default function testsuite() { + abilityTest(); +} \ No newline at end of file diff --git a/ArkUIKit/ArktsMvvmSample/entry/src/ohosTest/module.json5 b/ArkUIKit/ArktsMvvmSample/entry/src/ohosTest/module.json5 new file mode 100644 index 0000000000000000000000000000000000000000..84d30586d591412f4252801cc483bbc6d8554104 --- /dev/null +++ b/ArkUIKit/ArktsMvvmSample/entry/src/ohosTest/module.json5 @@ -0,0 +1,26 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +{ + "module": { + "name": "entry_test", + "type": "feature", + "deviceTypes": [ + "default" + ], + "deliveryWithInstall": true, + "installationFree": false + } +} diff --git a/ArkUIKit/ArktsMvvmSample/entry/src/test/List.test.ets b/ArkUIKit/ArktsMvvmSample/entry/src/test/List.test.ets new file mode 100644 index 0000000000000000000000000000000000000000..f1186b1f53c3a70930921c5dbd1417332bec56c9 --- /dev/null +++ b/ArkUIKit/ArktsMvvmSample/entry/src/test/List.test.ets @@ -0,0 +1,20 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import localUnitTest from './LocalUnit.test'; + +export default function testsuite() { + localUnitTest(); +} \ No newline at end of file diff --git a/ArkUIKit/ArktsMvvmSample/entry/src/test/LocalUnit.test.ets b/ArkUIKit/ArktsMvvmSample/entry/src/test/LocalUnit.test.ets new file mode 100644 index 0000000000000000000000000000000000000000..7fc57c77dbf76d8df08a2b802a55b948e3fcf968 --- /dev/null +++ b/ArkUIKit/ArktsMvvmSample/entry/src/test/LocalUnit.test.ets @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { describe, beforeAll, beforeEach, afterEach, afterAll, it, expect } from '@ohos/hypium'; + +export default function localUnitTest() { + describe('localUnitTest', () => { + // Defines a test suite. Two parameters are supported: test suite name and test suite function. + beforeAll(() => { + // Presets an action, which is performed only once before all test cases of the test suite start. + // This API supports only one parameter: preset action function. + }); + beforeEach(() => { + // Presets an action, which is performed before each unit test case starts. + // The number of execution times is the same as the number of test cases defined by **it**. + // This API supports only one parameter: preset action function. + }); + afterEach(() => { + // Presets a clear action, which is performed after each unit test case ends. + // The number of execution times is the same as the number of test cases defined by **it**. + // This API supports only one parameter: clear action function. + }); + afterAll(() => { + // Presets a clear action, which is performed after all test cases of the test suite end. + // This API supports only one parameter: clear action function. + }); + it('assertContain', 0, () => { + // Defines a test case. This API supports three parameters: test case name, filter parameter, and test case function. + let a = 'abc'; + let b = 'b'; + // Defines a variety of assertion methods, which are used to declare expected boolean conditions. + expect(a).assertContain(b); + expect(a).assertEqual(a); + }); + }); +} \ No newline at end of file diff --git a/ArkUIKit/ArktsMvvmSample/hvigor/hvigor-config.json5 b/ArkUIKit/ArktsMvvmSample/hvigor/hvigor-config.json5 new file mode 100644 index 0000000000000000000000000000000000000000..b8fea3f097bd68b0bc4d87de986d2cb7732c1d9b --- /dev/null +++ b/ArkUIKit/ArktsMvvmSample/hvigor/hvigor-config.json5 @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +{ + "modelVersion": "6.0.0", + "dependencies": { + }, + "execution": { + // "analyze": "normal", /* Define the build analyze mode. Value: [ "normal" | "advanced" | "ultrafine" | false ]. Default: "normal" */ + // "daemon": true, /* Enable daemon compilation. Value: [ true | false ]. Default: true */ + // "incremental": true, /* Enable incremental compilation. Value: [ true | false ]. Default: true */ + // "parallel": true, /* Enable parallel compilation. Value: [ true | false ]. Default: true */ + // "typeCheck": false, /* Enable typeCheck. Value: [ true | false ]. Default: false */ + // "optimizationStrategy": "memory" /* Define the optimization strategy. Value: [ "memory" | "performance" ]. Default: "memory" */ + }, + "logging": { + // "level": "info" /* Define the log level. Value: [ "debug" | "info" | "warn" | "error" ]. Default: "info" */ + }, + "debugging": { + // "stacktrace": false /* Disable stacktrace compilation. Value: [ true | false ]. Default: false */ + }, + "nodeOptions": { + // "maxOldSpaceSize": 8192 /* Enable nodeOptions maxOldSpaceSize compilation. Unit M. Used for the daemon process. Default: 8192*/ + // "exposeGC": true /* Enable to trigger garbage collection explicitly. Default: true*/ + } +} diff --git a/ArkUIKit/ArktsMvvmSample/hvigorfile.ts b/ArkUIKit/ArktsMvvmSample/hvigorfile.ts new file mode 100644 index 0000000000000000000000000000000000000000..e3340f07e45ddc5dcadbb87012668555def2e6e0 --- /dev/null +++ b/ArkUIKit/ArktsMvvmSample/hvigorfile.ts @@ -0,0 +1,21 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { appTasks } from '@ohos/hvigor-ohos-plugin'; + +export default { + system: appTasks, /* Built-in plugin of Hvigor. It cannot be modified. */ + plugins: [] /* Custom plugin to extend the functionality of Hvigor. */ +} \ No newline at end of file diff --git a/ArkUIKit/ArktsMvvmSample/oh-package.json5 b/ArkUIKit/ArktsMvvmSample/oh-package.json5 new file mode 100644 index 0000000000000000000000000000000000000000..69cb43cba3addcee1840403c67405134a2a9102c --- /dev/null +++ b/ArkUIKit/ArktsMvvmSample/oh-package.json5 @@ -0,0 +1,25 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +{ + "modelVersion": "6.0.0", + "description": "Please describe the basic information.", + "dependencies": { + }, + "devDependencies": { + "@ohos/hypium": "1.0.24", + "@ohos/hamock": "1.0.0" + } +} diff --git a/ArkUIKit/ArktsMvvmSample/ohosTest.md b/ArkUIKit/ArktsMvvmSample/ohosTest.md new file mode 100644 index 0000000000000000000000000000000000000000..5cb343ec527195e36cbceb3381fc0ef55bf4b092 --- /dev/null +++ b/ArkUIKit/ArktsMvvmSample/ohosTest.md @@ -0,0 +1,12 @@ +# MVVM模式测试用例 + +## 用例表 + +| 测试功能 | 预置条件 | 输入 | 预期输出 | 是否自动 | 测试结果 | +|-------------------|--------|---------------------------------------------------------------------|------------------------------------------------------------------------------------------------------------------|------| -------- | +| 拉起应用 | 设备正常运行 | | 成功拉起应用 | Yes | Pass | +| @State装饰器效果 | 页面正常跳转 | 点击两次'学习高数'文字 | 第一次点击勾选成功,第二次点击取消勾选 | Yes | Pass | +| @Prop和@Link装饰器的效果 | 页面正常跳转 | 点击两次'学习高数'文字,再点击两次全选 | 第一次点击勾选成功,第二次点击取消勾选,第三次点击选择全部,第四次点击取消所有勾选 | Yes | Pass | +| ForEach的效果 | 页面正常跳转 | 点击两次'7.30 起床'前面的选择框,再点击两次'8.30 早餐'前面的选择框,再点击两次"8.30 早餐"文字,最后再点击两次全选 | 第一次点击勾选成功,第二次点击取消勾选,第三次点击勾选成功,第四次点击取消勾选,第五次点击勾选成功,第六次点击取消勾选,第七次点击选择全部,第八次点击取消所有勾选 | Yes | Pass | +| @Builder装饰器的效果 | 页面正常跳转 | 点击两次全选,再点击两次'7.30 起床'前面的选择框,再点击两次'7.30 起床'文字,最后再点击两次"8.30 早餐" | 第一次点击选择全部,第二次点击取消勾选全部,第三次点击勾选成功,第四次点击取消勾选,第五次点击在文字后面加一个'啦'字,第六次点击在文字后面加一个'啦'字,第七次点击在文字后面加一个'啦'字,第八次点击在文字后面加一个'啦'字 | Yes | Pass | +| MVVM结构实现备忘录 | 页面正常跳转 | 点击两次全选,再点击两次'7.30 起床'前面的选择框,最后再点击两次'7.30 起床'文字 | 第一次点击选择全部,第二次点击取消勾选全部,第三次点击勾选成功,第四次点击取消勾选,第五次点击在文字后面加一个'啦'字,第六次点击在文字后面加一个'啦'字 | Yes | Pass | \ No newline at end of file diff --git a/ArkUIKit/ArktsMvvmSample/screenshots/BuilderEffectPreview.gif b/ArkUIKit/ArktsMvvmSample/screenshots/BuilderEffectPreview.gif new file mode 100644 index 0000000000000000000000000000000000000000..e6cd67381495d2dec14efb4ae8bd6e1544012873 Binary files /dev/null and b/ArkUIKit/ArktsMvvmSample/screenshots/BuilderEffectPreview.gif differ diff --git a/ArkUIKit/ArktsMvvmSample/screenshots/ForEachEffectPreview.gif b/ArkUIKit/ArktsMvvmSample/screenshots/ForEachEffectPreview.gif new file mode 100644 index 0000000000000000000000000000000000000000..c935590eec01c9bf19612a9aa9e381be169192d1 Binary files /dev/null and b/ArkUIKit/ArktsMvvmSample/screenshots/ForEachEffectPreview.gif differ diff --git a/ArkUIKit/ArktsMvvmSample/screenshots/MvvmEffectPreview.gif b/ArkUIKit/ArktsMvvmSample/screenshots/MvvmEffectPreview.gif new file mode 100644 index 0000000000000000000000000000000000000000..ae52090ace8950b7bd8ca713778e4debdb5db0e1 Binary files /dev/null and b/ArkUIKit/ArktsMvvmSample/screenshots/MvvmEffectPreview.gif differ diff --git a/ArkUIKit/ArktsMvvmSample/screenshots/PropLinkPreview.gif b/ArkUIKit/ArktsMvvmSample/screenshots/PropLinkPreview.gif new file mode 100644 index 0000000000000000000000000000000000000000..851924cb49dcda563e746c46a487a87402e4b71c Binary files /dev/null and b/ArkUIKit/ArktsMvvmSample/screenshots/PropLinkPreview.gif differ diff --git a/ArkUIKit/ArktsMvvmSample/screenshots/StateEffectPreview.gif b/ArkUIKit/ArktsMvvmSample/screenshots/StateEffectPreview.gif new file mode 100644 index 0000000000000000000000000000000000000000..e9bd5f74e2c21f2177bea2130047d9d54cda91f7 Binary files /dev/null and b/ArkUIKit/ArktsMvvmSample/screenshots/StateEffectPreview.gif differ diff --git a/ArkUIKit/ArktsNewComputed/AppScope/app.json5 b/ArkUIKit/ArktsNewComputed/AppScope/app.json5 new file mode 100644 index 0000000000000000000000000000000000000000..1b1e474d9d6169a90a6e0b87b65f952fbbf3ae06 --- /dev/null +++ b/ArkUIKit/ArktsNewComputed/AppScope/app.json5 @@ -0,0 +1,25 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +{ + "app": { + "bundleName": "com.sample.arktsnewcomputed", + "vendor": "example", + "versionCode": 1000000, + "versionName": "1.0.0", + "icon": "$media:layered_image", + "label": "$string:app_name" + } +} diff --git a/ArkUIKit/ArktsNewComputed/AppScope/resources/base/element/string.json b/ArkUIKit/ArktsNewComputed/AppScope/resources/base/element/string.json new file mode 100644 index 0000000000000000000000000000000000000000..b21daab8c4bb8e3374c0a36d1ca6289378c62984 --- /dev/null +++ b/ArkUIKit/ArktsNewComputed/AppScope/resources/base/element/string.json @@ -0,0 +1,8 @@ +{ + "string": [ + { + "name": "app_name", + "value": "ArktsNevOnce" + } + ] +} diff --git a/ArkUIKit/ArktsNewComputed/AppScope/resources/base/media/background.png b/ArkUIKit/ArktsNewComputed/AppScope/resources/base/media/background.png new file mode 100644 index 0000000000000000000000000000000000000000..923f2b3f27e915d6871871deea0420eb45ce102f Binary files /dev/null and b/ArkUIKit/ArktsNewComputed/AppScope/resources/base/media/background.png differ diff --git a/ArkUIKit/ArktsNewComputed/AppScope/resources/base/media/foreground.png b/ArkUIKit/ArktsNewComputed/AppScope/resources/base/media/foreground.png new file mode 100644 index 0000000000000000000000000000000000000000..eb9427585b36d14b12477435b6419d1f07b3e0bb Binary files /dev/null and b/ArkUIKit/ArktsNewComputed/AppScope/resources/base/media/foreground.png differ diff --git a/ArkUIKit/ArktsNewComputed/AppScope/resources/base/media/layered_image.json b/ArkUIKit/ArktsNewComputed/AppScope/resources/base/media/layered_image.json new file mode 100644 index 0000000000000000000000000000000000000000..fb49920440fb4d246c82f9ada275e26123a2136a --- /dev/null +++ b/ArkUIKit/ArktsNewComputed/AppScope/resources/base/media/layered_image.json @@ -0,0 +1,7 @@ +{ + "layered-image": + { + "background" : "$media:background", + "foreground" : "$media:foreground" + } +} \ No newline at end of file diff --git a/ArkUIKit/ArktsNewComputed/README_zh.md b/ArkUIKit/ArktsNewComputed/README_zh.md new file mode 100644 index 0000000000000000000000000000000000000000..7db6b15250a4a3d1333a2069436d8c122ca05405 --- /dev/null +++ b/ArkUIKit/ArktsNewComputed/README_zh.md @@ -0,0 +1,77 @@ +# @Once:初始化同步一次 + +### 介绍 + +本示例展示了[@Once:初始化同步一次](https://gitcode.com/openharmony/docs/blob/master/zh-cn/application-dev/ui/state-management/arkts-new-once.md)装饰器的使用方法: + +1. @Once用于期望变量仅初始化同步数据源一次,之后不再继续同步变化的场景; +2. 当@Once与@Param结合使用时,可以解除@Param无法在本地修改的限制,并能够触发UI刷新。此时,使用@Param和@Once的效果类似于@Local,但@Param和@Once还能接收外部传入的初始值; + +### 效果预览 + + +| CustomComponentUse页面 | ObservedV2ClassUser界面 | ComputingPropertyResolution界面 | ComputedInitParam界面 | +|-------------------------|-----------------------------|-----------------------------|-----------------------------| +| ![](screenshots/image1.png) | ![](screenshots/image2.png) | ![](screenshots/image3.png) | ![](screenshots/image4.png) | + +### 具体实现 + +1. 到对应模块的官网文档,理解模块功能和使用说明 + +2. 补充对应的代码片段,确保可以运行 + +3. 拿真机,填写测试用例,运行项目 + +4. 拿真机对用例进行自动测试 + +### 使用说明 + +执行测试用例会先打开相应界面,然后会将界面上的按钮点击一遍,演示初始化同步数据源。 + +### 工程目录 +``` +entry/src/ +├── main +│ ├── ets +│ │ ├── entryability +│ │ ├── entrybackupability +│ │ └── pages +│ │ ├── Index.ets +│ │ └── ComputedInitParam.ets +│ │ └── ComputingPropertyResolution.ets +│ │ └── CustomComponentUse.ets +│ │ └── ObservedV2ClassUser.ets +│ ├── module.json5 +│ └── resources +└── ohosTest + └── ets + └── test + ├── Ability.test.ets + └── index.test.ets + └── List.test.ets + +``` + +### 相关权限 + +不涉及。 + +### 依赖 + +不涉及。 + +### 约束与限制 + +1.本示例已适配API version 12及以上版本SDK。 + +### 下载 + +如需单独下载本工程,执行如下命令: + +``` +git init +git config core.sparsecheckout true +echo code/DocsSample/ArkUISample/ArktsNewComputed/ > .git/info/sparse-checkout +git remote add origin https://gitcode.com/openharmony/applications_app_samples.git +git pull origin master +``` \ No newline at end of file diff --git a/ArkUIKit/ArktsNewComputed/build-profile.json5 b/ArkUIKit/ArktsNewComputed/build-profile.json5 new file mode 100644 index 0000000000000000000000000000000000000000..724b825f1ee429691a14b6b6d138c70fd7c56db9 --- /dev/null +++ b/ArkUIKit/ArktsNewComputed/build-profile.json5 @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +{ + "app": { + "signingConfigs": [], + "products": [ + { + "name": "default", + "signingConfig": "default", + "compileSdkVersion": "6.0.0(20)", + "compatibleSdkVersion": "6.0.0(20)", + "targetSdkVersion": "6.0.0(20)", + "runtimeOS": "HarmonyOS", + "buildOption": { + "strictMode": { + "caseSensitiveCheck": true, + "useNormalizedOHMUrl": true + } + } + } + ], + "buildModeSet": [ + { + "name": "debug", + }, + { + "name": "release" + } + ] + }, + "modules": [ + { + "name": "entry", + "srcPath": "./entry", + "targets": [ + { + "name": "default", + "applyToProducts": [ + "default" + ] + } + ] + } + ] +} \ No newline at end of file diff --git a/ArkUIKit/ArktsNewComputed/code-linter.json5 b/ArkUIKit/ArktsNewComputed/code-linter.json5 new file mode 100644 index 0000000000000000000000000000000000000000..ed05653cca31b61d64cf6471529eaf50d4f70709 --- /dev/null +++ b/ArkUIKit/ArktsNewComputed/code-linter.json5 @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +{ + "files": [ + "**/*.ets" + ], + "ignore": [ + "**/src/ohosTest/**/*", + "**/src/test/**/*", + "**/src/mock/**/*", + "**/node_modules/**/*", + "**/oh_modules/**/*", + "**/build/**/*", + "**/.preview/**/*" + ], + "ruleSet": [ + "plugin:@performance/recommended", + "plugin:@typescript-eslint/recommended" + ], + "rules": { + "@security/no-unsafe-aes": "error", + "@security/no-unsafe-hash": "error", + "@security/no-unsafe-mac": "warn", + "@security/no-unsafe-dh": "error", + "@security/no-unsafe-dsa": "error", + "@security/no-unsafe-ecdsa": "error", + "@security/no-unsafe-rsa-encrypt": "error", + "@security/no-unsafe-rsa-sign": "error", + "@security/no-unsafe-rsa-key": "error", + "@security/no-unsafe-dsa-key": "error", + "@security/no-unsafe-dh-key": "error", + "@security/no-unsafe-3des": "error" + } +} \ No newline at end of file diff --git a/ArkUIKit/ArktsNewComputed/entry/build-profile.json5 b/ArkUIKit/ArktsNewComputed/entry/build-profile.json5 new file mode 100644 index 0000000000000000000000000000000000000000..6bf0d132e6f78049e712446c63f2633b2d1613d3 --- /dev/null +++ b/ArkUIKit/ArktsNewComputed/entry/build-profile.json5 @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +{ + "apiType": "stageMode", + "buildOption": { + "resOptions": { + "copyCodeResource": { + "enable": false + } + } + }, + "buildOptionSet": [ + { + "name": "release", + "arkOptions": { + "obfuscation": { + "ruleOptions": { + "enable": false, + "files": [ + "./obfuscation-rules.txt" + ] + } + } + } + }, + ], + "targets": [ + { + "name": "default" + }, + { + "name": "ohosTest", + } + ] +} \ No newline at end of file diff --git a/ArkUIKit/ArktsNewComputed/entry/hvigorfile.ts b/ArkUIKit/ArktsNewComputed/entry/hvigorfile.ts new file mode 100644 index 0000000000000000000000000000000000000000..cfa8a00f74f409d9647f55cdf270ab6aec69fe41 --- /dev/null +++ b/ArkUIKit/ArktsNewComputed/entry/hvigorfile.ts @@ -0,0 +1,21 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { hapTasks } from '@ohos/hvigor-ohos-plugin'; + +export default { + system: hapTasks, /* Built-in plugin of Hvigor. It cannot be modified. */ + plugins: [] /* Custom plugin to extend the functionality of Hvigor. */ +} \ No newline at end of file diff --git a/ArkUIKit/ArktsNewComputed/entry/obfuscation-rules.txt b/ArkUIKit/ArktsNewComputed/entry/obfuscation-rules.txt new file mode 100644 index 0000000000000000000000000000000000000000..272efb6ca3f240859091bbbfc7c5802d52793b0b --- /dev/null +++ b/ArkUIKit/ArktsNewComputed/entry/obfuscation-rules.txt @@ -0,0 +1,23 @@ +# Define project specific obfuscation rules here. +# You can include the obfuscation configuration files in the current module's build-profile.json5. +# +# For more details, see +# https://developer.huawei.com/consumer/cn/doc/harmonyos-guides-V5/source-obfuscation-V5 + +# Obfuscation options: +# -disable-obfuscation: disable all obfuscations +# -enable-property-obfuscation: obfuscate the property names +# -enable-toplevel-obfuscation: obfuscate the names in the global scope +# -compact: remove unnecessary blank spaces and all line feeds +# -remove-log: remove all console.* statements +# -print-namecache: print the name cache that contains the mapping from the old names to new names +# -apply-namecache: reuse the given cache file + +# Keep options: +# -keep-property-name: specifies property names that you want to keep +# -keep-global-name: specifies names that you want to keep in the global scope + +-enable-property-obfuscation +-enable-toplevel-obfuscation +-enable-filename-obfuscation +-enable-export-obfuscation \ No newline at end of file diff --git a/ArkUIKit/ArktsNewComputed/entry/oh-package.json5 b/ArkUIKit/ArktsNewComputed/entry/oh-package.json5 new file mode 100644 index 0000000000000000000000000000000000000000..c9cb6c8174858277c9b0d465a51547dcab16d5ff --- /dev/null +++ b/ArkUIKit/ArktsNewComputed/entry/oh-package.json5 @@ -0,0 +1,25 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +{ + "name": "entry", + "version": "1.0.0", + "description": "Please describe the basic information.", + "main": "", + "author": "", + "license": "", + "dependencies": {} +} + diff --git a/ArkUIKit/ArktsNewComputed/entry/src/main/ets/common/Card.ets b/ArkUIKit/ArktsNewComputed/entry/src/main/ets/common/Card.ets new file mode 100644 index 0000000000000000000000000000000000000000..8a5d71ab7914f99cbbfac51282bceff22857dad8 --- /dev/null +++ b/ArkUIKit/ArktsNewComputed/entry/src/main/ets/common/Card.ets @@ -0,0 +1,137 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +@Component +export struct CompletedRoutableCard { + @Prop + symbol: Resource = $r('sys.symbol.label'); + @Prop + @Require + title: string; + @Prop + @Require + description: ResourceStr; + + build() { + Card({ verticalAlign: VerticalAlign.Top }) { + Button({ type: ButtonType.Circle }) { + SymbolGlyph(this.symbol) + .fontColor(['#fff']) + .fontSize(16) + } + .borderRadius(14) + + Column({ space: 8 }) { + Text(this.title) + .fontColor($r('sys.color.font_primary')) + + Text(this.description) + .fontColor($r('sys.color.font_secondary')) + .fontSize($r('sys.float.Body_S')) + } + .alignItems(HorizontalAlign.Start) + .layoutWeight(1) + } + } +} + +@Component +export struct Card { + @Prop + verticalAlign: VerticalAlign = VerticalAlign.Center; + @BuilderParam + content: () => void; + + build() { + Row({ space: 12 }) { + this.content() + } + .alignItems(this.verticalAlign) + .backgroundColor('#fff') + .borderRadius(12) + .padding(12) + .width('100%') + } +} + +@Component +export struct RoutableCard { + @Prop + icon: Resource = $r('sys.symbol.label'); + @Prop + @Require + title: ResourceStr; + + build() { + Card() { + Button({ type: ButtonType.Circle }) { + SymbolGlyph(this.icon) + .fontColor(['#fff']) + .fontSize(16) + } + .borderRadius(14) + + Text(this.title) + .fontColor($r('sys.color.font_primary')) + .minFontSize(12) + .maxFontSize(16) + .maxLines(1) + .textOverflow({ overflow: TextOverflow.Ellipsis }) + + Blank() + + Button({ type: ButtonType.Normal, buttonStyle: ButtonStyleMode.TEXTUAL }) { + SymbolGlyph($r('sys.symbol.chevron_right')) + .fontSize(18) + .fontColor([$r('sys.color.font_secondary')]) + } + } + } +} + +@Component +export struct ComponentCard { + @Prop + title?: ResourceStr; + @BuilderParam content: () => void; + @Prop + description?: ResourceStr; + + build() { + Column({ space: 8 }) { + Text(this.title) + .fontSize(14) + .fontColor('#666') + Row({ space: 12 }) { + this.content(); + } + + if (this.description) { + Text(this.description) + .backgroundColor('#eee') + .borderRadius(4) + .padding(4) + .fontSize(12) + .fontColor('#999') + .width('100%') + } + } + .alignItems(HorizontalAlign.Start) + .backgroundColor('#fff') + .borderRadius(12) + .padding(12) + .width('100%') + } +} \ No newline at end of file diff --git a/ArkUIKit/ArktsNewComputed/entry/src/main/ets/common/Resource.ets b/ArkUIKit/ArktsNewComputed/entry/src/main/ets/common/Resource.ets new file mode 100644 index 0000000000000000000000000000000000000000..e240a1079ad09a0f19080b49b57a6a0720416e6c --- /dev/null +++ b/ArkUIKit/ArktsNewComputed/entry/src/main/ets/common/Resource.ets @@ -0,0 +1,25 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +export class ResourceManager { + public resourceToString(resource: Resource): string { + return getContext(this).resourceManager.getStringSync(resource); + } +} + +// 默认导出let +let resourceToStringManager = new ResourceManager(); + +export default resourceToStringManager as ResourceManager; \ No newline at end of file diff --git a/ArkUIKit/ArktsNewComputed/entry/src/main/ets/common/Route.ets b/ArkUIKit/ArktsNewComputed/entry/src/main/ets/common/Route.ets new file mode 100644 index 0000000000000000000000000000000000000000..859fec8c9ebd491e575d5baf8d43bd0512add60c --- /dev/null +++ b/ArkUIKit/ArktsNewComputed/entry/src/main/ets/common/Route.ets @@ -0,0 +1,21 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +export interface Route { + title: string; + name: string; + items?: Route[]; + description?: ResourceStr; +} \ No newline at end of file diff --git a/ArkUIKit/ArktsNewComputed/entry/src/main/ets/entryability/EntryAbility.ets b/ArkUIKit/ArktsNewComputed/entry/src/main/ets/entryability/EntryAbility.ets new file mode 100644 index 0000000000000000000000000000000000000000..62f53acbc95e5be7985f8fb1fe2db591cea260bd --- /dev/null +++ b/ArkUIKit/ArktsNewComputed/entry/src/main/ets/entryability/EntryAbility.ets @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { AbilityConstant, ConfigurationConstant, UIAbility, Want } from '@kit.AbilityKit'; +import { hilog } from '@kit.PerformanceAnalysisKit'; +import { window } from '@kit.ArkUI'; + +const DOMAIN = 0x0000; + +export default class EntryAbility extends UIAbility { + onCreate(want: Want, launchParam: AbilityConstant.LaunchParam): void { + try { + this.context.getApplicationContext().setColorMode(ConfigurationConstant.ColorMode.COLOR_MODE_NOT_SET); + } catch (err) { + hilog.error(DOMAIN, 'testTag', 'Failed to set colorMode. Cause: %{public}s', JSON.stringify(err)); + } + hilog.info(DOMAIN, 'testTag', '%{public}s', 'Ability onCreate'); + } + + onDestroy(): void { + hilog.info(DOMAIN, 'testTag', '%{public}s', 'Ability onDestroy'); + } + + onWindowStageCreate(windowStage: window.WindowStage): void { + // Main window is created, set main page for this ability + hilog.info(DOMAIN, 'testTag', '%{public}s', 'Ability onWindowStageCreate'); + + windowStage.loadContent('pages/Index', (err) => { + if (err.code) { + hilog.error(DOMAIN, 'testTag', 'Failed to load the content. Cause: %{public}s', JSON.stringify(err)); + return; + } + hilog.info(DOMAIN, 'testTag', 'Succeeded in loading the content.'); + }); + } + + onWindowStageDestroy(): void { + // Main window is destroyed, release UI related resources + hilog.info(DOMAIN, 'testTag', '%{public}s', 'Ability onWindowStageDestroy'); + } + + onForeground(): void { + // Ability has brought to foreground + hilog.info(DOMAIN, 'testTag', '%{public}s', 'Ability onForeground'); + } + + onBackground(): void { + // Ability has back to background + hilog.info(DOMAIN, 'testTag', '%{public}s', 'Ability onBackground'); + } +} \ No newline at end of file diff --git a/ArkUIKit/ArktsNewComputed/entry/src/main/ets/entrybackupability/EntryBackupAbility.ets b/ArkUIKit/ArktsNewComputed/entry/src/main/ets/entrybackupability/EntryBackupAbility.ets new file mode 100644 index 0000000000000000000000000000000000000000..0a97e21bd7a15599af76a806695860ff1eb0ebfe --- /dev/null +++ b/ArkUIKit/ArktsNewComputed/entry/src/main/ets/entrybackupability/EntryBackupAbility.ets @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { hilog } from '@kit.PerformanceAnalysisKit'; +import { BackupExtensionAbility, BundleVersion } from '@kit.CoreFileKit'; + +const DOMAIN = 0x0000; + +export default class EntryBackupAbility extends BackupExtensionAbility { + async onBackup() { + hilog.info(DOMAIN, 'testTag', 'onBackup ok'); + await Promise.resolve(); + } + + async onRestore(bundleVersion: BundleVersion) { + hilog.info(DOMAIN, 'testTag', 'onRestore ok %{public}s', JSON.stringify(bundleVersion)); + await Promise.resolve(); + } +} \ No newline at end of file diff --git a/ArkUIKit/ArktsNewComputed/entry/src/main/ets/pages/ComputedInitParam.ets b/ArkUIKit/ArktsNewComputed/entry/src/main/ets/pages/ComputedInitParam.ets new file mode 100644 index 0000000000000000000000000000000000000000..1dd94d487d61636f589cc7ddcb6bf54b35683e3f --- /dev/null +++ b/ArkUIKit/ArktsNewComputed/entry/src/main/ets/pages/ComputedInitParam.ets @@ -0,0 +1,92 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// [Start Computed_Init_Param] +@ObservedV2 +class Article { + @Trace public quantity: number = 0; + public unitPrice: number = 0; + + constructor(quantity: number, unitPrice: number) { + this.quantity = quantity; + this.unitPrice = unitPrice; + } +} + +@Entry +@ComponentV2 +export struct ComputedInitParam { + @Local shoppingBasket: Article[] = [new Article(1, 20), new Article(5, 2)]; + + @Computed + get total(): number { + return this.shoppingBasket.reduce((acc: number, item: Article) => acc + (item.quantity * item.unitPrice), 0); + } + + @Computed + get qualifiesForDiscount(): boolean { + return this.total >= 100; + } + + build() { + // [StartExclude Computed_Init_Param] + NavDestination() { + // [EndExclude Computed_Init_Param] + Column() { + Text(`Shopping List: `) + .fontSize(30) + ForEach(this.shoppingBasket, (item: Article) => { + Row() { + Text(`unitPrice: ${item.unitPrice}`) + Button('-') + .onClick(() => { + if (item.quantity > 0) { + item.quantity--; + } + }) + Text(`quantity: ${item.quantity}`) + Button('+') + .onClick(() => { + item.quantity++; + }) + } + + Divider() + }) + Child({ total: this.total, qualifiesForDiscount: this.qualifiesForDiscount }) + }.alignItems(HorizontalAlign.Start) + // [StartExclude Computed_Init_Param] + } + .backgroundColor('#f1f2f3') + .title($r('app.string.computed_title_3')) + // [EndExclude Computed_Init_Param] + } +} + +@ComponentV2 +struct Child { + @Param total: number = 0; + @Param qualifiesForDiscount: boolean = false; + + build() { + Row() { + Text(`Total: ${this.total} `) + .fontSize(30) + Text(`Discount: ${this.qualifiesForDiscount} `) + .fontSize(30) + } + } +} +// [End Computed_Init_Param] diff --git a/ArkUIKit/ArktsNewComputed/entry/src/main/ets/pages/ComputedProperty.ets b/ArkUIKit/ArktsNewComputed/entry/src/main/ets/pages/ComputedProperty.ets new file mode 100644 index 0000000000000000000000000000000000000000..40deefd23a6abf908119f408b78523270f0b9de2 --- /dev/null +++ b/ArkUIKit/ArktsNewComputed/entry/src/main/ets/pages/ComputedProperty.ets @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +import { hilog } from '@kit.PerformanceAnalysisKit'; + +const TAG = '[Sample_Textcomponent]'; +const DOMAIN = 0xF811; +const BUNDLE = 'Textcomponent_'; +@ObservedV2 +class Name { + @Trace public count1: number = 1; + @Trace public count2: number = 2; + @Trace public count3: number = 3; + + // [Start ComputedProperty] + @Computed + get sum() { + return this.count1 + this.count2 + this.count3; + } + // [End ComputedProperty] +} + +const name: Name = new Name(); + +@Entry +@ComponentV2 +export struct ComputedProperty { + name1: Name = name; + + build() { + NavDestination() { + Column() { + // [Start ComputedProperty] + Text(`${this.name1.count1 + this.name1.count2 + this.name1.count3}`) // 计算this.count1 + this.count2 + this.count3 + Text(`${this.name1.count1 + this.name1.count2 + this.name1.count3}`) // 重复计算this.count1 + this.count2 + this.count3 + Text(`${this.name1.sum}`) // 读取@Computed sum的缓存值,节省上述重复计算 + Text(`${this.name1.sum}`) // 读取@Computed sum的缓存值,节省上述重复计算 + // [End ComputedProperty] + } + } + .backgroundColor('#f1f2f3') + .title($r('app.string.computed_property_title')) + } +} diff --git a/ArkUIKit/ArktsNewComputed/entry/src/main/ets/pages/ComputingPropertyResolution.ets b/ArkUIKit/ArktsNewComputed/entry/src/main/ets/pages/ComputingPropertyResolution.ets new file mode 100644 index 0000000000000000000000000000000000000000..6655e3e512150772509d13e51994d6bfce820715 --- /dev/null +++ b/ArkUIKit/ArktsNewComputed/entry/src/main/ets/pages/ComputingPropertyResolution.ets @@ -0,0 +1,72 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +import { hilog } from '@kit.PerformanceAnalysisKit'; + +const TAG = '[Sample_Textcomponent]'; +const DOMAIN = 0xF811; +const BUNDLE = 'Textcomponent_'; + +// [Start Computing_Property_Resolution] +@Entry +@ComponentV2 +export struct ComputingPropertyResolution { + @Local celsius: number = 20; + + @Computed + get fahrenheit(): number { + return this.celsius * 9 / 5 + 32; // C -> F + } + + @Computed + get kelvin(): number { + return (this.fahrenheit - 32) * 5 / 9 + 273.15; // F -> K + } + + @Monitor('kelvin') + onKelvinMonitor(mon: IMonitor) { + hilog.info(DOMAIN, TAG, BUNDLE + 'kelvin changed from' + mon.value()?.before + ' to ' + mon.value()?.now); + } + + build() { + // [StartExclude Computing_Property_Resolution] + NavDestination() { + // [EndExclude Computing_Property_Resolution] + Column({ space: 20 }) { + Row({ space: 20 }) { + Button('-') + .onClick(() => { + this.celsius--; + }) + + Text(`Celsius ${this.celsius.toFixed(1)}`).fontSize(40) + + Button('+') + .onClick(() => { + this.celsius++; + }) + } + + Text(`Fahrenheit ${this.fahrenheit.toFixed(2)}`).fontSize(40) + Text(`Kelvin ${this.kelvin.toFixed(2)}`).fontSize(40) + } + .width('100%') + // [StartExclude Computing_Property_Resolution] + } + .backgroundColor('#f1f2f3') + .title($r('app.string.computed_title_3')) + // [EndExclude Computing_Property_Resolution] + } +} +// [End Computing_Property_Resolution] \ No newline at end of file diff --git a/ArkUIKit/ArktsNewComputed/entry/src/main/ets/pages/CustomComponentUse.ets b/ArkUIKit/ArktsNewComputed/entry/src/main/ets/pages/CustomComponentUse.ets new file mode 100644 index 0000000000000000000000000000000000000000..dd4ed6ea8ddb800dbe0ab3857c232e352afb1814 --- /dev/null +++ b/ArkUIKit/ArktsNewComputed/entry/src/main/ets/pages/CustomComponentUse.ets @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +import { hilog } from '@kit.PerformanceAnalysisKit'; + +const TAG = '[Sample_Textcomponent]'; +const DOMAIN = 0xF811; +const BUNDLE = 'Textcomponent_'; + +// [Start Custom_Component_Use] +@Entry +@ComponentV2 +export struct CustomComponentUse { + @Local private firstName: string = 'Li'; + @Local private lastName: string = 'Hua'; + age: number = 20; // 无法触发Computed + + @Computed + get fullName() { + hilog.info(DOMAIN, TAG, BUNDLE + '---------Computed----------'); + return this.firstName + ' ' + this.lastName + this.age; + } + + build() { + // [StartExclude Custom_Component_Use] + NavDestination() { + // [EndExclude Custom_Component_Use] + Column() { + Text(this.lastName + ' ' + this.firstName) + Text(this.lastName + ' ' + this.firstName) + Divider() + Text(this.fullName) + Text(this.fullName) + Button('changed lastName').onClick(() => { + this.lastName += 'a'; + }) + + Button('changed age').onClick(() => { + this.age++; // 无法触发Computed + }) + } + // [StartExclude Custom_Component_Use] + } + .backgroundColor('#f1f2f3') + .title($r('app.string.computed_title_3')) + // [EndExclude Custom_Component_Use] + } +} +// [End Custom_Component_Use] \ No newline at end of file diff --git a/ArkUIKit/ArktsNewComputed/entry/src/main/ets/pages/Index.ets b/ArkUIKit/ArktsNewComputed/entry/src/main/ets/pages/Index.ets new file mode 100644 index 0000000000000000000000000000000000000000..2f0447abeaf6e7f19a1b04ac78f98fdb8a17a048 --- /dev/null +++ b/ArkUIKit/ArktsNewComputed/entry/src/main/ets/pages/Index.ets @@ -0,0 +1,99 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { LengthMetrics } from '@kit.ArkUI'; +import { RoutableCard } from '../common/Card'; +import { Route } from '../common/Route'; +import resource from '../common/Resource'; +import { CustomComponentUse } from './CustomComponentUse'; +import { ObservedV2ClassUser } from './ObservedV2ClassUser'; +import { ComputingPropertyResolution } from './ComputingPropertyResolution'; +import { ComputedInitParam } from './ComputedInitParam'; + +const routes: Route[] = [ + { + name: 'CustomComponentUse', + title: resource.resourceToString($r('app.string.computed_desc_1')), + description: '' + }, + { + name: 'ObservedV2ClassUser', + title: resource.resourceToString($r('app.string.computed_desc_2')), + description: '' + }, + { + name: 'ComputingPropertyResolution', + title: resource.resourceToString($r('app.string.computed_title_2')), + description: $r('app.string.computed_desc_3') + }, + { + name: 'ComputedInitParam', + title: resource.resourceToString($r('app.string.computed_title_3')), + description: $r('app.string.computed_desc_4') + }, +]; + +@Builder +function computedDestination(name: string) { + if (name.startsWith('CustomComponentUse')) { + CustomComponentUse(); + }else if(name.startsWith('ObservedV2ClassUser')){ + ObservedV2ClassUser(); + }else if(name.startsWith('ComputingPropertyResolution')){ + ComputingPropertyResolution(); + }else if(name.startsWith('ComputedInitParam')){ + ComputedInitParam(); + } +} + + +@Entry +@Component +struct Index { + @State condition: string = ''; + @Provide pathStack: NavPathStack = new NavPathStack(); + + getFilteredRoutes(): Route[] { + if (!this.condition) { + return routes; + } + return routes.filter((route: Route) => { + return route.title.includes(this.condition); + }) + } + + + build() { + Navigation(this.pathStack) { + List({ space: 12 }) { + ForEach(this.getFilteredRoutes(), (route: Route) => { + ListItem() { + RoutableCard({ title: route.title }) + } + .width('100%') + .onClick(() => { + this.pathStack.pushPath({ name: route.name }); + }) + }) + } + .padding({ start: LengthMetrics.vp(16), end: LengthMetrics.vp(16) }) + .contentStartOffset(56) + .height('100%') + .width('100%') + } + .backgroundColor('#f1f3f5') + .navDestination(computedDestination) + } +} diff --git a/ArkUIKit/ArktsNewComputed/entry/src/main/ets/pages/ObservedV2ClassUser.ets b/ArkUIKit/ArktsNewComputed/entry/src/main/ets/pages/ObservedV2ClassUser.ets new file mode 100644 index 0000000000000000000000000000000000000000..edbdfba815d38c84a962ca7bd14e30b904fcb037 --- /dev/null +++ b/ArkUIKit/ArktsNewComputed/entry/src/main/ets/pages/ObservedV2ClassUser.ets @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +import { hilog } from '@kit.PerformanceAnalysisKit'; + +const TAG = '[Sample_Textcomponent]'; +const DOMAIN = 0xF811; +const BUNDLE = 'Textcomponent_'; +// [Start ObservedV2_Class_User] +@ObservedV2 +class Name { + @Trace private firstName: string = 'Hua'; + @Trace public lastName: string = 'Li'; + + @Computed + get fullName() { + hilog.info(DOMAIN, TAG, BUNDLE + '---------Computed----------'); + return this.firstName + ' ' + this.lastName; + } +} + +const name: Name = new Name(); + +@Entry +@ComponentV2 +export struct ObservedV2ClassUser { + name1: Name = name; + + build() { + // [StartExclude ObservedV2_Class_User] + NavDestination() { + // [EndExclude ObservedV2_Class_User] + Column() { + Text(this.name1.fullName) + Text(this.name1.fullName) + Button('changed lastName').onClick(() => { + this.name1.lastName += 'a'; + }) + } + // [StartExclude ObservedV2_Class_User] + } + .backgroundColor('#f1f2f3') + .title($r('app.string.computed_desc_2')) + // [EndExclude ObservedV2_Class_User] + } +} +// [End ObservedV2_Class_User] \ No newline at end of file diff --git a/ArkUIKit/ArktsNewComputed/entry/src/main/module.json5 b/ArkUIKit/ArktsNewComputed/entry/src/main/module.json5 new file mode 100644 index 0000000000000000000000000000000000000000..e7b97706fc3892b66ff98ad95fe7d618fdb42554 --- /dev/null +++ b/ArkUIKit/ArktsNewComputed/entry/src/main/module.json5 @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +{ + "module": { + "name": "entry", + "type": "entry", + "description": "$string:module_desc", + "mainElement": "EntryAbility", + "deviceTypes": [ + "default", + "tablet" + ], + "deliveryWithInstall": true, + "installationFree": false, + "pages": "$profile:main_pages", + "abilities": [ + { + "name": "EntryAbility", + "srcEntry": "./ets/entryability/EntryAbility.ets", + "description": "$string:EntryAbility_desc", + "icon": "$media:layered_image", + "label": "$string:EntryAbility_label", + "startWindowIcon": "$media:startIcon", + "startWindowBackground": "$color:start_window_background", + "exported": true, + "skills": [ + { + "entities": [ + "entity.system.home" + ], + "actions": [ + "ohos.want.action.home" + ] + } + ] + } + ], + "extensionAbilities": [ + { + "name": "EntryBackupAbility", + "srcEntry": "./ets/entrybackupability/EntryBackupAbility.ets", + "type": "backup", + "exported": false, + "metadata": [ + { + "name": "ohos.extension.backup", + "resource": "$profile:backup_config" + } + ], + } + ] + } +} \ No newline at end of file diff --git a/ArkUIKit/ArktsNewComputed/entry/src/main/resources/base/element/color.json b/ArkUIKit/ArktsNewComputed/entry/src/main/resources/base/element/color.json new file mode 100644 index 0000000000000000000000000000000000000000..3c712962da3c2751c2b9ddb53559afcbd2b54a02 --- /dev/null +++ b/ArkUIKit/ArktsNewComputed/entry/src/main/resources/base/element/color.json @@ -0,0 +1,8 @@ +{ + "color": [ + { + "name": "start_window_background", + "value": "#FFFFFF" + } + ] +} \ No newline at end of file diff --git a/ArkUIKit/ArktsNewComputed/entry/src/main/resources/base/element/float.json b/ArkUIKit/ArktsNewComputed/entry/src/main/resources/base/element/float.json new file mode 100644 index 0000000000000000000000000000000000000000..33ea22304f9b1485b5f22d811023701b5d4e35b6 --- /dev/null +++ b/ArkUIKit/ArktsNewComputed/entry/src/main/resources/base/element/float.json @@ -0,0 +1,8 @@ +{ + "float": [ + { + "name": "page_text_font_size", + "value": "50fp" + } + ] +} diff --git a/ArkUIKit/ArktsNewComputed/entry/src/main/resources/base/element/string.json b/ArkUIKit/ArktsNewComputed/entry/src/main/resources/base/element/string.json new file mode 100644 index 0000000000000000000000000000000000000000..1b37caeaf598c88b60e6ec6f29afa2abf16f37a9 --- /dev/null +++ b/ArkUIKit/ArktsNewComputed/entry/src/main/resources/base/element/string.json @@ -0,0 +1,48 @@ +{ + "string": [ + { + "name": "module_desc", + "value": "module description" + }, + { + "name": "EntryAbility_desc", + "value": "description" + }, + { + "name": "EntryAbility_label", + "value": "label" + }, + { + "name": "computed_title_1", + "value": "当被计算的属性变化时,@Computed装饰的getter访问器只会被求解一次。" + }, + { + "name": "computed_title_2", + "value": "@Computed装饰的属性可以被@Monitor监听变化" + }, + { + "name": "computed_title_3", + "value": "@Computed装饰的属性可以初始化@Param" + }, + { + "name": "computed_desc_1", + "value": "在自定义组件中使用计算属性。" + }, + { + "name": "computed_desc_2", + "value": "在@ObservedV2装饰的类中使用计算属性。。" + }, + { + "name": "computed_desc_3", + "value": "如何使用计算属性求解fahrenheit和kelvin。" + }, + { + "name": "computed_desc_4", + "value": "下面的例子使用@Computed初始化@Param。" + }, + { + "name": "computed_property_title", + "value": "当开发者使用相同的计算逻辑重复绑定在UI上时,为了防止重复计算,可以使用@Computed计算属性。计算属性中的依赖的状态变量变化时,只会计算一次。这解决了UI多次重用该属性导致的重复计算和性能问题" + } + ] +} \ No newline at end of file diff --git a/ArkUIKit/ArktsNewComputed/entry/src/main/resources/base/media/background.png b/ArkUIKit/ArktsNewComputed/entry/src/main/resources/base/media/background.png new file mode 100644 index 0000000000000000000000000000000000000000..923f2b3f27e915d6871871deea0420eb45ce102f Binary files /dev/null and b/ArkUIKit/ArktsNewComputed/entry/src/main/resources/base/media/background.png differ diff --git a/ArkUIKit/ArktsNewComputed/entry/src/main/resources/base/media/foreground.png b/ArkUIKit/ArktsNewComputed/entry/src/main/resources/base/media/foreground.png new file mode 100644 index 0000000000000000000000000000000000000000..97014d3e10e5ff511409c378cd4255713aecd85f Binary files /dev/null and b/ArkUIKit/ArktsNewComputed/entry/src/main/resources/base/media/foreground.png differ diff --git a/ArkUIKit/ArktsNewComputed/entry/src/main/resources/base/media/layered_image.json b/ArkUIKit/ArktsNewComputed/entry/src/main/resources/base/media/layered_image.json new file mode 100644 index 0000000000000000000000000000000000000000..fb49920440fb4d246c82f9ada275e26123a2136a --- /dev/null +++ b/ArkUIKit/ArktsNewComputed/entry/src/main/resources/base/media/layered_image.json @@ -0,0 +1,7 @@ +{ + "layered-image": + { + "background" : "$media:background", + "foreground" : "$media:foreground" + } +} \ No newline at end of file diff --git a/ArkUIKit/ArktsNewComputed/entry/src/main/resources/base/media/startIcon.png b/ArkUIKit/ArktsNewComputed/entry/src/main/resources/base/media/startIcon.png new file mode 100644 index 0000000000000000000000000000000000000000..205ad8b5a8a42e8762fbe4899b8e5e31ce822b8b Binary files /dev/null and b/ArkUIKit/ArktsNewComputed/entry/src/main/resources/base/media/startIcon.png differ diff --git a/ArkUIKit/ArktsNewComputed/entry/src/main/resources/base/profile/backup_config.json b/ArkUIKit/ArktsNewComputed/entry/src/main/resources/base/profile/backup_config.json new file mode 100644 index 0000000000000000000000000000000000000000..78f40ae7c494d71e2482278f359ec790ca73471a --- /dev/null +++ b/ArkUIKit/ArktsNewComputed/entry/src/main/resources/base/profile/backup_config.json @@ -0,0 +1,3 @@ +{ + "allowToBackupRestore": true +} \ No newline at end of file diff --git a/ArkUIKit/ArktsNewComputed/entry/src/main/resources/base/profile/main_pages.json b/ArkUIKit/ArktsNewComputed/entry/src/main/resources/base/profile/main_pages.json new file mode 100644 index 0000000000000000000000000000000000000000..1898d94f58d6128ab712be2c68acc7c98e9ab9ce --- /dev/null +++ b/ArkUIKit/ArktsNewComputed/entry/src/main/resources/base/profile/main_pages.json @@ -0,0 +1,5 @@ +{ + "src": [ + "pages/Index" + ] +} diff --git a/ArkUIKit/ArktsNewComputed/entry/src/main/resources/dark/element/color.json b/ArkUIKit/ArktsNewComputed/entry/src/main/resources/dark/element/color.json new file mode 100644 index 0000000000000000000000000000000000000000..79b11c2747aec33e710fd3a7b2b3c94dd9965499 --- /dev/null +++ b/ArkUIKit/ArktsNewComputed/entry/src/main/resources/dark/element/color.json @@ -0,0 +1,8 @@ +{ + "color": [ + { + "name": "start_window_background", + "value": "#000000" + } + ] +} \ No newline at end of file diff --git a/ArkUIKit/ArktsNewComputed/entry/src/main/syscap.json b/ArkUIKit/ArktsNewComputed/entry/src/main/syscap.json new file mode 100644 index 0000000000000000000000000000000000000000..71ed4f89481161d8f97ccbb7e843a71dff5b50c1 --- /dev/null +++ b/ArkUIKit/ArktsNewComputed/entry/src/main/syscap.json @@ -0,0 +1,13 @@ +{ + "devices": { + "general": [], + "custom": [ + { + "xts": [ + "SystemCapability.Account.AppAccount", + "SystemCapability.Account.OsAccount" + ] + } + ] + } +} \ No newline at end of file diff --git a/ArkUIKit/ArktsNewComputed/entry/src/mock/mock-config.json5 b/ArkUIKit/ArktsNewComputed/entry/src/mock/mock-config.json5 new file mode 100644 index 0000000000000000000000000000000000000000..b9a78e201535765168a92d3543c690273ecdc019 --- /dev/null +++ b/ArkUIKit/ArktsNewComputed/entry/src/mock/mock-config.json5 @@ -0,0 +1,17 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +{ +} \ No newline at end of file diff --git a/ArkUIKit/ArktsNewComputed/entry/src/ohosTest/ets/test/Ability.test.ets b/ArkUIKit/ArktsNewComputed/entry/src/ohosTest/ets/test/Ability.test.ets new file mode 100644 index 0000000000000000000000000000000000000000..0f8ce9a2c012f8fe36114cef65216ef0b6254f41 --- /dev/null +++ b/ArkUIKit/ArktsNewComputed/entry/src/ohosTest/ets/test/Ability.test.ets @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { hilog } from '@kit.PerformanceAnalysisKit'; +import { describe, beforeAll, beforeEach, afterEach, afterAll, it, expect } from '@ohos/hypium'; + +export default function abilityTest() { + describe('ActsAbilityTest', () => { + // Defines a test suite. Two parameters are supported: test suite name and test suite function. + beforeAll(() => { + // Presets an action, which is performed only once before all test cases of the test suite start. + // This API supports only one parameter: preset action function. + }) + beforeEach(() => { + // Presets an action, which is performed before each unit test case starts. + // The number of execution times is the same as the number of test cases defined by **it**. + // This API supports only one parameter: preset action function. + }) + afterEach(() => { + // Presets a clear action, which is performed after each unit test case ends. + // The number of execution times is the same as the number of test cases defined by **it**. + // This API supports only one parameter: clear action function. + }) + afterAll(() => { + // Presets a clear action, which is performed after all test cases of the test suite end. + // This API supports only one parameter: clear action function. + }) + it('assertContain', 0, () => { + // Defines a test case. This API supports three parameters: test case name, filter parameter, and test case function. + hilog.info(0x0000, 'testTag', '%{public}s', 'it begin'); + let a = 'abc'; + let b = 'b'; + // Defines a variety of assertion methods, which are used to declare expected boolean conditions. + expect(a).assertContain(b); + expect(a).assertEqual(a); + }) + }) +} \ No newline at end of file diff --git a/ArkUIKit/ArktsNewComputed/entry/src/ohosTest/ets/test/List.test.ets b/ArkUIKit/ArktsNewComputed/entry/src/ohosTest/ets/test/List.test.ets new file mode 100644 index 0000000000000000000000000000000000000000..7c16bc08c6fb53175fcdc9d628a4d6a9b34bef4c --- /dev/null +++ b/ArkUIKit/ArktsNewComputed/entry/src/ohosTest/ets/test/List.test.ets @@ -0,0 +1,22 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import abilityTest from './Ability.test'; +import IndexTest from './index.test'; + +export default function testsuite() { + abilityTest(); + IndexTest(); +} \ No newline at end of file diff --git a/ArkUIKit/ArktsNewComputed/entry/src/ohosTest/ets/test/index.test.ets b/ArkUIKit/ArktsNewComputed/entry/src/ohosTest/ets/test/index.test.ets new file mode 100644 index 0000000000000000000000000000000000000000..79eec43c2cd6447e72ff3fcf136a5279ed4fdcb6 --- /dev/null +++ b/ArkUIKit/ArktsNewComputed/entry/src/ohosTest/ets/test/index.test.ets @@ -0,0 +1,161 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { describe, it, expect, beforeAll, Level } from '@ohos/hypium'; +// 导入测试依赖kit +import { abilityDelegatorRegistry, Driver, ON, MatchPattern, On, Component } from '@kit.TestKit'; +import { UIAbility, Want } from '@kit.AbilityKit'; +import hilog from '@ohos.hilog'; + +const delegator: abilityDelegatorRegistry.AbilityDelegator = abilityDelegatorRegistry.getAbilityDelegator(); +const bundleName = abilityDelegatorRegistry.getArguments().bundleName; +let abilityDelegator: abilityDelegatorRegistry.AbilityDelegator = abilityDelegatorRegistry.getAbilityDelegator(); +let want: Want; +const TAG = '[Sample_Arktsnewcomputed]' +const DOMAIN = 0xF811 +const BUNDLE = 'Arktsnewcomputed_' + +async function getResourceString(resource: Resource): Promise { + let manage = abilityDelegator.getAppContext().resourceManager; + let textString: string = await manage.getStringValue(resource); + return textString; +} + +export default function IndexTest() { + + describe('IndexTest', () => { + beforeAll(async () => { + want = { + bundleName: bundleName, + abilityName: 'EntryAbility' + }; + await delegator.startAbility(want); + let driver = Driver.create(); + await driver.delayMs(1000); + const ability: UIAbility = await delegator.getCurrentTopAbility(); + hilog.info(DOMAIN, TAG, BUNDLE + 'get top ability'); + expect(ability.context.abilityInfo.name).assertEqual('EntryAbility'); + }) + + /** + * @tc.number UiTest_001 + * @tc.name testCustomComponentUse + * @tc.desc 测试在自定义组件中使用计算属性 + * @tc.level: Level 1 + */ + it('testCustomComponentUse', Level.LEVEL1, async (done: Function) => { + hilog.info(DOMAIN, TAG, BUNDLE + 'uitest: testCreateText begin'); + let driver = Driver.create(); + let str = await getResourceString($r('app.string.computed_desc_1')); + let buttonComponent = await driver.findComponent(ON.text(str)); + expect(buttonComponent === null).assertFalse(); + await buttonComponent.click(); + + buttonComponent = await driver.findComponent(ON.text('changed lastName', MatchPattern.CONTAINS)); + expect(buttonComponent === null).assertFalse(); + await buttonComponent.click(); + await buttonComponent.click(); + buttonComponent = await driver.findComponent(ON.text('changed age', MatchPattern.CONTAINS)); + expect(buttonComponent === null).assertFalse(); + await buttonComponent.click(); + await buttonComponent.click(); + + await driver.pressBack(); + hilog.info(DOMAIN, TAG, BUNDLE + 'uitest: testCreateText end'); + done(); + }) + + /** + * @tc.number UiTest_002 + * @tc.name testObservedV2ClassUser + * @tc.desc 测试在自定义组件中使用计算属性 + * @tc.level: Level 1 + */ + it('testObservedV2ClassUser', Level.LEVEL1, async (done: Function) => { + hilog.info(DOMAIN, TAG, BUNDLE + 'uitest: testObservedV2ClassUser begin'); + let driver = Driver.create(); + let str = await getResourceString($r('app.string.computed_desc_2')); + let buttonComponent = await driver.findComponent(ON.text(str)); + expect(buttonComponent === null).assertFalse(); + await buttonComponent.click(); + + buttonComponent = await driver.findComponent(ON.text('changed lastName', MatchPattern.CONTAINS)); + expect(buttonComponent === null).assertFalse(); + await buttonComponent.click(); + await buttonComponent.click(); + + await driver.pressBack(); + hilog.info(DOMAIN, TAG, BUNDLE + 'uitest: testObservedV2ClassUser end'); + done(); + }) + + /** + * @tc.number UiTest_003 + * @tc.name testComputingPropertyResolution + * @tc.desc 测试在自定义组件中使用计算属性 + * @tc.level: Level 1 + */ + it('testComputingPropertyResolution', Level.LEVEL1, async (done: Function) => { + hilog.info(DOMAIN, TAG, BUNDLE + 'uitest: testComputingPropertyResolution begin'); + let driver = Driver.create(); + let str = await getResourceString($r('app.string.computed_title_2')); + let buttonComponent = await driver.findComponent(ON.text(str)); + expect(buttonComponent === null).assertFalse(); + await buttonComponent.click(); + + buttonComponent = await driver.findComponent(ON.text('-', MatchPattern.CONTAINS)); + expect(buttonComponent === null).assertFalse(); + await buttonComponent.click(); + await buttonComponent.click(); + buttonComponent = await driver.findComponent(ON.text('+', MatchPattern.CONTAINS)); + expect(buttonComponent === null).assertFalse(); + await buttonComponent.click(); + await buttonComponent.click(); + + await driver.pressBack(); + hilog.info(DOMAIN, TAG, BUNDLE + 'uitest: testComputingPropertyResolution end'); + done(); + }) + + /** + * @tc.number UiTest_004 + * @tc.name testComputedInitParam + * @tc.desc 测试在自定义组件中使用计算属性 + * @tc.level: Level 1 + */ + it('testComputedInitParam', Level.LEVEL1, async (done: Function) => { + hilog.info(DOMAIN, TAG, BUNDLE + 'uitest: testComputedInitParam begin'); + let driver = Driver.create(); + let str = await getResourceString($r('app.string.computed_title_3')); + let buttonComponent = await driver.findComponent(ON.text(str)); + expect(buttonComponent === null).assertFalse(); + await buttonComponent.click(); + + buttonComponent = await driver.findComponent(ON.text('-', MatchPattern.CONTAINS)); + expect(buttonComponent === null).assertFalse(); + await buttonComponent.click(); + await buttonComponent.click(); + buttonComponent = await driver.findComponent(ON.text('+', MatchPattern.CONTAINS)); + expect(buttonComponent === null).assertFalse(); + await buttonComponent.click(); + await buttonComponent.click(); + + await driver.pressBack(); + hilog.info(DOMAIN, TAG, BUNDLE + 'uitest: testComputedInitParam end'); + done(); + }) + + }) +} \ No newline at end of file diff --git a/ArkUIKit/ArktsNewComputed/entry/src/ohosTest/module.json5 b/ArkUIKit/ArktsNewComputed/entry/src/ohosTest/module.json5 new file mode 100644 index 0000000000000000000000000000000000000000..c3fd9dda3040d888d9d8b0b62bcb5d3b6fbeb614 --- /dev/null +++ b/ArkUIKit/ArktsNewComputed/entry/src/ohosTest/module.json5 @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +{ + "module": { + "name": "entry_test", + "type": "feature", + "deviceTypes": [ + "default", + "tablet" + ], + "deliveryWithInstall": true, + "installationFree": false + } +} diff --git a/ArkUIKit/ArktsNewComputed/entry/src/ohosTest/syscap.json b/ArkUIKit/ArktsNewComputed/entry/src/ohosTest/syscap.json new file mode 100644 index 0000000000000000000000000000000000000000..71ed4f89481161d8f97ccbb7e843a71dff5b50c1 --- /dev/null +++ b/ArkUIKit/ArktsNewComputed/entry/src/ohosTest/syscap.json @@ -0,0 +1,13 @@ +{ + "devices": { + "general": [], + "custom": [ + { + "xts": [ + "SystemCapability.Account.AppAccount", + "SystemCapability.Account.OsAccount" + ] + } + ] + } +} \ No newline at end of file diff --git a/ArkUIKit/ArktsNewComputed/entry/src/test/List.test.ets b/ArkUIKit/ArktsNewComputed/entry/src/test/List.test.ets new file mode 100644 index 0000000000000000000000000000000000000000..f1186b1f53c3a70930921c5dbd1417332bec56c9 --- /dev/null +++ b/ArkUIKit/ArktsNewComputed/entry/src/test/List.test.ets @@ -0,0 +1,20 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import localUnitTest from './LocalUnit.test'; + +export default function testsuite() { + localUnitTest(); +} \ No newline at end of file diff --git a/ArkUIKit/ArktsNewComputed/entry/src/test/LocalUnit.test.ets b/ArkUIKit/ArktsNewComputed/entry/src/test/LocalUnit.test.ets new file mode 100644 index 0000000000000000000000000000000000000000..7fc57c77dbf76d8df08a2b802a55b948e3fcf968 --- /dev/null +++ b/ArkUIKit/ArktsNewComputed/entry/src/test/LocalUnit.test.ets @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { describe, beforeAll, beforeEach, afterEach, afterAll, it, expect } from '@ohos/hypium'; + +export default function localUnitTest() { + describe('localUnitTest', () => { + // Defines a test suite. Two parameters are supported: test suite name and test suite function. + beforeAll(() => { + // Presets an action, which is performed only once before all test cases of the test suite start. + // This API supports only one parameter: preset action function. + }); + beforeEach(() => { + // Presets an action, which is performed before each unit test case starts. + // The number of execution times is the same as the number of test cases defined by **it**. + // This API supports only one parameter: preset action function. + }); + afterEach(() => { + // Presets a clear action, which is performed after each unit test case ends. + // The number of execution times is the same as the number of test cases defined by **it**. + // This API supports only one parameter: clear action function. + }); + afterAll(() => { + // Presets a clear action, which is performed after all test cases of the test suite end. + // This API supports only one parameter: clear action function. + }); + it('assertContain', 0, () => { + // Defines a test case. This API supports three parameters: test case name, filter parameter, and test case function. + let a = 'abc'; + let b = 'b'; + // Defines a variety of assertion methods, which are used to declare expected boolean conditions. + expect(a).assertContain(b); + expect(a).assertEqual(a); + }); + }); +} \ No newline at end of file diff --git a/ArkUIKit/ArktsNewComputed/hvigor/hvigor-config.json5 b/ArkUIKit/ArktsNewComputed/hvigor/hvigor-config.json5 new file mode 100644 index 0000000000000000000000000000000000000000..7a7ab8914d8db6ab89758e185df5855dffe88d04 --- /dev/null +++ b/ArkUIKit/ArktsNewComputed/hvigor/hvigor-config.json5 @@ -0,0 +1,23 @@ +{ + "modelVersion": "6.0.0", + "dependencies": { + }, + "execution": { + // "analyze": "normal", /* Define the build analyze mode. Value: [ "normal" | "advanced" | "ultrafine" | false ]. Default: "normal" */ + // "daemon": true, /* Enable daemon compilation. Value: [ true | false ]. Default: true */ + // "incremental": true, /* Enable incremental compilation. Value: [ true | false ]. Default: true */ + // "parallel": true, /* Enable parallel compilation. Value: [ true | false ]. Default: true */ + // "typeCheck": false, /* Enable typeCheck. Value: [ true | false ]. Default: false */ + // "optimizationStrategy": "memory" /* Define the optimization strategy. Value: [ "memory" | "performance" ]. Default: "memory" */ + }, + "logging": { + // "level": "info" /* Define the log level. Value: [ "debug" | "info" | "warn" | "error" ]. Default: "info" */ + }, + "debugging": { + // "stacktrace": false /* Disable stacktrace compilation. Value: [ true | false ]. Default: false */ + }, + "nodeOptions": { + // "maxOldSpaceSize": 8192 /* Enable nodeOptions maxOldSpaceSize compilation. Unit M. Used for the daemon process. Default: 8192*/ + // "exposeGC": true /* Enable to trigger garbage collection explicitly. Default: true*/ + } +} diff --git a/ArkUIKit/ArktsNewComputed/hvigorfile.ts b/ArkUIKit/ArktsNewComputed/hvigorfile.ts new file mode 100644 index 0000000000000000000000000000000000000000..e3340f07e45ddc5dcadbb87012668555def2e6e0 --- /dev/null +++ b/ArkUIKit/ArktsNewComputed/hvigorfile.ts @@ -0,0 +1,21 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { appTasks } from '@ohos/hvigor-ohos-plugin'; + +export default { + system: appTasks, /* Built-in plugin of Hvigor. It cannot be modified. */ + plugins: [] /* Custom plugin to extend the functionality of Hvigor. */ +} \ No newline at end of file diff --git a/ArkUIKit/ArktsNewComputed/oh-package.json5 b/ArkUIKit/ArktsNewComputed/oh-package.json5 new file mode 100644 index 0000000000000000000000000000000000000000..69cb43cba3addcee1840403c67405134a2a9102c --- /dev/null +++ b/ArkUIKit/ArktsNewComputed/oh-package.json5 @@ -0,0 +1,25 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +{ + "modelVersion": "6.0.0", + "description": "Please describe the basic information.", + "dependencies": { + }, + "devDependencies": { + "@ohos/hypium": "1.0.24", + "@ohos/hamock": "1.0.0" + } +} diff --git a/ArkUIKit/ArktsNewComputed/screenshots/image1.png b/ArkUIKit/ArktsNewComputed/screenshots/image1.png new file mode 100644 index 0000000000000000000000000000000000000000..4bb95857b75ddd7652b2918f9ebdcd771622e88e Binary files /dev/null and b/ArkUIKit/ArktsNewComputed/screenshots/image1.png differ diff --git a/ArkUIKit/ArktsNewComputed/screenshots/image2.png b/ArkUIKit/ArktsNewComputed/screenshots/image2.png new file mode 100644 index 0000000000000000000000000000000000000000..76b6d920159e0b56e2a95fe386756fa6f14d39d0 Binary files /dev/null and b/ArkUIKit/ArktsNewComputed/screenshots/image2.png differ diff --git a/ArkUIKit/ArktsNewComputed/screenshots/image3.png b/ArkUIKit/ArktsNewComputed/screenshots/image3.png new file mode 100644 index 0000000000000000000000000000000000000000..0f2ea568f0e764c5febc365a6768b19db66602b9 Binary files /dev/null and b/ArkUIKit/ArktsNewComputed/screenshots/image3.png differ diff --git a/ArkUIKit/ArktsNewComputed/screenshots/image4.png b/ArkUIKit/ArktsNewComputed/screenshots/image4.png new file mode 100644 index 0000000000000000000000000000000000000000..3e606f7db96ba4d14d1f6bf2aca60859990d8ff0 Binary files /dev/null and b/ArkUIKit/ArktsNewComputed/screenshots/image4.png differ