diff --git a/README.md b/README.md
index 7aa6d502..c7013e42 100755
--- a/README.md
+++ b/README.md
@@ -1,400 +1,46 @@
-# Settings 源码开发说明
+# Settings
-## 1. 项目介绍
-Settings是基于 OpenHarmony 平台开发的基于OHOS提供基础设置功能。主要包括页面展示跳转逻辑、基础设置项(wifi设置、亮度设置、应用管理、日期和时间、关于手机)以及本设备其他应用设置项的收集、其他设备设置项收集的实现。项目采用MVVM架构模式,让各个层级之间不直接访问减少相互依赖。
+- [Introduction](#section11660541593)
+ - [Architecture](#section48896451454)
-Settings采用纯 ETS 语言开发,开发过程中不涉及任何 Java 部分的代码。
+- [Directory Structure](#section161941989596)
+- [Repositories Involved](#section1371113476307)
-## 2. 工程结构
-### 目录结构
+## Introduction
+The Settings is a system application prebuilt in OpenHarmony. It provides a human-machine interactions entry for users to set system configs like settings system time, lightness of screen and etc.
- /applications/standard/settings
- ├── entry # 主entry模块目录
- │ └── src
- │ ├── main
- │ ├── ets # ets模块目录
- │ ├── default
- │ ├── common # 公共工具存放目录
- │ ├── model # 数据管理和决策逻辑存放目录
- │ ├── pages # 组件页面存放目录
- │ ├── res # 部分图片资源
- │ ├── resources # 其它共用资源
- │ ├── app.ets # 全局ets逻辑和应用生命周期管理文件
- │ ├── resources # 资源配置文件存放目录
- │ ├── base # 默认语言场景,图片资源,字体大小,颜色资源内容存放目录
- │ ├── en_AS.element # 英文语言场景资源内容存放目录
- │ ├── rawfile # 本地配置文件存放目录
- │ ├── zh_CN.element # 中文语言场景资源内容存放目录
- │ └── config.json # 全局配置文件
- ├── signature # 证书文件目录
- ├── LICENSE # 许可文件
+### Architecture
-### 整体架构
+![](figures/en-us_image_0000001153225717.png)
-![](./figures/en-us_image_0000001153225717.png)
-
-设置 整体是 openHarmony 系统中预置的系统应用,为用户提供设置系统属性的交互界面。例如设置wifi状态,系统时间,屏幕亮度等系统属性。
-
-Settings整体采用MVVM架构设计。关于MVVM架构中各层级的描述如下:
-
-View:视图层,负责界面数据的展示,与用户进行交互。
-
-ViewModel:视图模型,用UI Component将公用逻辑抽离,建立一套公用的ui引擎处理视图层(View)发送的业务逻辑处理请求,并连通 Model 层获取数据。
-
-Model:模型层,负责处理数据,包括wifi的model,应用管理model,日期时间model等。
-
-## 3. 代码使用
-### 代码下载
-基于L2的 Settings代码可以采用从码云上克隆的方式下载。
-[下载地址](https://gitee.com/openharmony/applications_settings)
-
-#### 从码云克隆代码
-##### 1.配置SSH公钥
-1. 通过[登录网址](https://gitee.com/login)登录码云
-2. 在码云的个人设置中设置SSH公钥
- 1. 生成SSH公私钥
- 在命令窗口输入以下命令,邮箱地址替换为自己的邮箱地址,一直回车直至完成为止。
- ```
- ssh-keygen -t rsa -C "xxxx@xxxx.com"
- ```
- > 执行完成后,会在用户目录下的.ssh文件夹内生成 `id_rsa` 与 `id_rsa.pub` 两个文件,其中的 `id_rsa.pub` 即为生成的 SSH公钥
- >
- > ![](./figures/git_ssh_pub_key.png)
- >
- > 2. 复制公钥内容
- > 输入`cat .ssh/id_rsa.pub`,复制打印内容。
- > ![](./figures/3-1.png)
- > 3. 在设置->安全设置->SSH公钥 中设置 SSH公钥
- > 将第二步中复制的内容按照画面提示粘贴到码云上相应的内容区域,并点击确定。
- > ![](./figures/3-2.png)
- > 注意,在码云中,添加SSH公钥之后,需要进行账号的密码验证,验证通过才能成功添加。
-##### 2.下载代码
-1. 浏览器打开[下载地址](https://gitee.com/openharmony/applications_settings)。
-2. 点击“克隆/下载”按钮,选择 SSH,点击“复制”按钮。
- ![](./figures/source_download_1.png)
-3. 在本地新建 Settings 目录,在 Settings 目录中执行如下命令
- ```
- git clone 步骤2中复制的地址
- ```
-
-## 4. 基础开发说明
-
-
-### 多语言支持
-
-#### 定义资源文件
-
-- 在 `src/main/ets/resources/`目录下,根据不同的语言定义不同的文件夹下面的 `string.json` 资源文件。
- ![](./figures/ds_i18n_files.png)
-
-#### 引用资源
-
-- 在对应ets文件中,可直接通过`$r()`引用。
-
- ````
- this.title = $r('app.string.world');
- this.icon = $r('app.media.icon');
- ````
-
-## 5. 典型接口的使用
-
-1. 读取json配置文件
+## Directory Structure
```
- import fileio from '@ohos.fileio';
-
- readLocalFile(fileName): any[]{
- try {
- let stream = FileIo.createStreamSync(fileName, 'r');
- LogUtil.info('settings readLocalFile stream:' + stream);
- let buf = new ArrayBuffer(4096);
- let len = stream.readSync(buf);
- LogUtil.info('settings readLocalFile len:' + len);
- let arr = new Uint8Array(buf);
- let charAt = ' '.charCodeAt(0);
- for (let i = len;i < 4096; i++) {
- arr[i] = charAt;
- }
- let content = String.fromCharCode.apply(null, arr);
- stream.closeSync();
- LogUtil.info('settings readLocalFile content:' + JSON.stringify(content));
- return JSON.parse(content);
- } catch (jsonError) {
- LogUtil.info('settings readLocalFile jsonError:' + jsonError);
- }
- }
+/applications/standard/settings
+├── entry # main entry module
+│ └── src
+│ ├── main
+│ ├── ets # ets module
+│ ├── default
+│ ├── common # common code and utils
+│ ├── model # data management and logic control
+│ ├── pages # code of view components
+│ ├── res # some image resources
+│ ├── resources # other resources
+│ ├── app.ets # main process
+│ ├── resources # resources configs
+│ ├── base # default language, image resources, font size and colors
+│ ├── en_AS.element # English resources
+│ ├── rawfile # local configs
+│ ├── zh_CN.element # Chinese resources
+│ └── config.json # global configs
+├── signature # Certificate files
+├── LICENSE # Copyright license file
```
+## Repositories Involved
-2. 查询所有应用信息
-
-```
-import Bundle from '@ohos.bundle';
-
-Bundle.getAllBundleInfo(0)
- .then((data) => {
- console.info('Settings getAllBundleInfo: '+JSON.stringify(data));
- }
- );
-```
-
-3. 获取wifi扫描信息
-
-```
-import wifi_native_js from '@ohos.wifi_native_js';
-
-getScanInfos() {
- wifi_native_js.getScanInfos(result => {
- this.animator_on = false;
- var clen = Object.keys(result).length;
- console.log("[wifi_js_test] wifi received scan info call back: " + clen);
- for (var j = 0; j < clen; j++) {
- console.log("result[0].ssid :" + result[j].ssid);
- console.info("securityType: " + result[j].securityType);
- console.info("rssi: " + result[j].rssi);
- console.info("band: " + result[j].band);
- }
- });
-}
-```
-
-4. Preferences 存取数据
-
-```
-import storage from '@ohos.data.storage';
-// 数据存放路径
-const PREFERENCES_PATH = '/data/accounts/account_0/appdata/com.ohos.settings/sharedPreference/SettingsPreference';
-let mPreferences = Storage.getStorageSync(PREFERENCES_PATH);
-
-save(key,value) {
- mPreferences.putSync(key, value);
- mPreferences.flushSync();
-}
-
-get(key,defaultValue): any {
- return mPreferences.getSync(key, defaultValue);
-}
-```
-
-
-## 6. 签名打包
-
-### 签名
-
-#### 签名文件的获取
-
-1. 拷贝 OpenHarmony 标准版的 prebuilts\signcenter 目录到操作目录
-2. 拷贝Settings工程的 signature\settings.p7b 到该目录下
-
-#### 签名文件的配置
-
-打开项目工程,选择 File → Project Structure
-
-![](./figures/signature_1.png)
-
-选择 Modules → Signing Configs,将对应的签名文件配置如下,完成后点击Apply,再点击OK。
-
-![](./figures/signature_2.png)
-
-配置完成后,对应的build.gradle文件中会出现如下内容
-
-![](./figures/signature_3.png)
-
-### 打包
-
-DevEco Studio 支持 debug 与 release 两种打包类型。可以在 OhosBuild Variants 窗口中进行切换。
-
- ![](./figures/ds_ohosbuild_variants.png)
-
-#### debug打包
-
-1. 代码准备完成后,在 OhosBuild Variants 窗口的 Selected Variant 中选择 debug。
-
- ![](./figures/ds_ohosbuild_variants_debug.png)
-
-2. 选择Build → Build Haps(s)/APP(s) → Build Hap(s)
-
- ![](./figures/ds_build_haps.png)
-
-3. 编译完成后,hap包会生成在工程目录下的 `\build\outputs\hap\debug\phone\`路径下(如果没有配置签名,则只会生成未签名的hap包)
-
- ![](./figures/ds_ohosbuild_output_dir.png)
-
-#### release打包
-
-1. 代码准备完成后,在 OhosBuild Variants 窗口的 Selected Variant 中选择 release
-
- ![](./figures/ds_ohosbuild_variants_release.png)
-
-2. 选择Build → Build Haps(s)/APP(s) → Build Hap(s)
-
- ![](./figures/ds_build_haps.png)
-
-3. 编译完成后,hap包会生成在工程目录下的 `\build\outputs\hap\release\phone\`路径下(如果没有配置签名,则只会生成未签名的hap包)
-
- ![](./figures/ds_ohosbuild_output_dir.png)
-
-
-
-## 7. 安装、运行、调试
-
-## 应用安装
-
-配置 hdc:
-进入SDK目录中的toolchains文件夹下,获取文件路径:
-
-![](./figures/sdk_catalogue.png)
-
-> 注意,此处的hdc.exe如果版本较老,可能不能正常使用,需要获取新的hdc.exe文件
-
-并将此路径配置到环境变量中:
-
-![](./figures/sdk_environment_variable.png)
-
-重启电脑使环境变量生效
-
-连接开发板,打开cmd命令窗口,执行hdc list targets,弹出窗口如下:
-
-![](./figures/cmd1.png)
-
-等待一段时间后,窗口出现如下打印,可回到输入 hdc list targets 的命令窗口继续操作:
-
-![](./figures/cmd2.png)
-
-再次输入hdc list targets,出现如下结果,说明hdc连接成功
-
-![](./figures/cmd3.png)
-
-获取 root 权限与读写权限:
-
-```
-hdc smode(当前版本可能仍不稳定,执行此命令可能导致后续的hdc target mount 失败,可不执行)
-hdc target mount(效果与remount类似)
-```
-
-将签名好的 hap 包放入设备的 `/system/app` 目录下,并修改hap包的权限
-
-```
-hdc file send 本地hap包路径 /system/app/hap包名称
-例如:hdc file send Settings.hap /system/app/Settings.hap
-```
-
-> 注意,如果设备不存在 `/system/app` 目录,则需要手动创建该目录并修改权限。
->
-> ```
-> hdc shell
-> cd system
-> mkdir app
-> chmod 777 app
-> ```
->
-> `/system/app` 目录放置系统应用,例如:Launcher,SystemUI,Settings 等。
->
-> 但hap包需要在该目录下手动设置权限
->
-> ```
-> chmod 666 hap包名
-> ```
->
-> 此目录应用不用手动安装,系统自动拉起。
-
-## 应用运行
-
-Settings 属于系统应用,在将签名的 hap 包放入 `/system/app` 目录后,重启系统,应用会自动拉起。
-
-```
-hdc shell reboot (不可以直接执行hdc reboot,命令是无效的)
-```
-
-> 注意,如果设备之前安装过系统应用,则需要执行如下两条命令清除设备中存储的应用信息,才能够在设备重启的时候将最新装入设备的新 hap 包正常拉起。
->
-> ```
-> hdc shell rm -rf /data/misc_de/0/mdds/0/default/bundle_manager_service
-> hdc shell rm -rf /data/accounts
-> ```
-
-## 应用调试
-
-#### log打印
-- 在程序中添加 log
-```
-console.info("Setting log info");
-```
-#### log获取及过滤
-- log获取
-
-将log输出至文件
-```
-hdc shell hilog > 输出文件名称
-```
-
-例:
-在真实环境查看log,将全log输出到当前目录的hilog.log文件中
-
-```
-hdc shell hilog > hilog.log
-```
-
-- log过滤
-
-在命令行窗口中过滤log
-```
-hilog | grep 过滤信息
-```
-
-例:过滤包含信息 Label 的 hilog
-```
-hilog | grep Label
-```
-
-## 8. 贡献代码
-
-### Fork 代码仓库
-
-1. 在码云上打开 Settings 代码仓库([仓库地址](https://gitee.com/openharmony/applications_settings))。
-2. 点击仓库右上角的 Forked 按钮
- ![](./figures/commit_source_fork_button.png)
-3. 在弹出的画面中,选择将仓库 fork 到哪里,点击确认。
- ![](./figures/commit_source_fork_confirm.png)
-4. Fork 成功之后,会在自己的账号下看见 fork 的代码仓库。
- ![](./figures/commit_source_forked_repo1.png)
-
-### 提交代码
-
-1. 访问我们自己在码云账号上 fork 的代码仓库,点击“克隆/下载”按钮,选择 SSH,点击“复制”按钮。
- ![](./figures/commit_source_clone_page.png)
-
-2. 在本地新建 Settings 目录,在 Settings 目录中执行如下命令
-
- ```
- git clone 步骤1中复制的地址
- ```
-
-3. 修改代码。
-
- > 将代码引入工程,以及编译工程等相关内容请参见 **3. 代码使用** 部分的相关内容。
-
-4. 提交代码到 fork 仓库。
-
- > 修改后的代码,首先执行 `git add` 命令,然后执行 `git commit -s` 命令与 `git push` 命令,将代码 push 到我们自己的 fork 仓中。
- > 关于代码提交的这部分内容涉及 git 的使用,可以参照 [git官网](https://git-scm.com/) 的内容,在此不再赘述。
-
-### 发起 Pull Request (PR)
-
-在将代码提交到 fork 仓之后,我们可以通过发起 Pull Request(PR)的方式来为 OpenHarmony 的相关项目贡献代码。
-
-1. 打开 fork 仓库。选择 `Pull Requests` → `新建 Pull Request`
-
- ![](./figures/commit_source_new_pull_request.png)
-
-2. 在 `新建 Pull Request` 画面填入标题与说明,点击 `创建` 按钮。
-
- ![](./figures/commit_source_new_pull_request_confirm.png)
-
-3. 创建 Pull Request 完成。 PR 创建完成后,会有专门的代码审查人员对代码进行评审,评审通过之后会合入相应的代码库。
-
- ![](./figures/commit_source_new_pr_done.png)
-
-系统应用
+System apps
**applications\_settings**
+
diff --git a/build.gradle b/build.gradle
index 5ab79aa5..61859631 100755
--- a/build.gradle
+++ b/build.gradle
@@ -12,7 +12,7 @@ ohos {
buildscript {
repositories {
maven {
- url 'http://repo.ark.tools.huawei.com/artifactory/maven-public/'
+ url 'https://repo.ark.tools.huawei.com/artifactory/maven-public/'
}
maven {
url 'https://mirrors.huaweicloud.com/repository/maven/'
@@ -30,7 +30,7 @@ buildscript {
allprojects {
repositories {
maven {
- url 'http://repo.ark.tools.huawei.com/artifactory/maven-public/'
+ url 'https://repo.ark.tools.huawei.com/artifactory/maven-public/'
}
maven {
url 'https://mirrors.huaweicloud.com/repository/maven/'
diff --git a/common/component/build.gradle b/common/component/build.gradle
new file mode 100644
index 00000000..525fd4ec
--- /dev/null
+++ b/common/component/build.gradle
@@ -0,0 +1,20 @@
+apply plugin: 'com.huawei.ohos.library'
+//For instructions on signature configuration, see https://developer.harmonyos.com/cn/docs/documentation/doc-guides/ide_debug_device-0000001053822404#section1112183053510
+ohos {
+ compileSdkVersion 7
+ defaultConfig {
+ compatibleSdkVersion 6
+ }
+
+ buildTypes {
+ release {
+ proguardOpt {
+ proguardEnabled false
+ rulesFiles 'proguard-rules.pro'
+ }
+ }
+ }
+}
+
+dependencies {
+}
diff --git a/entry/proguard-rules.pro b/common/component/proguard-rules.pro
similarity index 100%
rename from entry/proguard-rules.pro
rename to common/component/proguard-rules.pro
diff --git a/common/component/src/main/config.json b/common/component/src/main/config.json
new file mode 100644
index 00000000..1e672ec6
--- /dev/null
+++ b/common/component/src/main/config.json
@@ -0,0 +1,22 @@
+{
+ "app": {
+ "bundleName": "com.ohos.settings",
+ "vendor": "ohos",
+ "version": {
+ "code": 1000000,
+ "name": "1.0.0"
+ }
+ },
+ "deviceConfig": {},
+ "module": {
+ "package": "com.ohos.settings.common",
+ "deviceType": [
+ "phone"
+ ],
+ "distro": {
+ "deliveryWithInstall": true,
+ "moduleName": "component",
+ "moduleType": "har"
+ }
+ }
+}
\ No newline at end of file
diff --git a/entry/src/main/ets/default/common/baseUtil/ConfigData.ets b/common/component/src/main/ets/default/ComponentConfig.ets
similarity index 52%
rename from entry/src/main/ets/default/common/baseUtil/ConfigData.ets
rename to common/component/src/main/ets/default/ComponentConfig.ets
index 0a2946e7..fa2dab61 100644
--- a/entry/src/main/ets/default/common/baseUtil/ConfigData.ets
+++ b/common/component/src/main/ets/default/ComponentConfig.ets
@@ -13,24 +13,10 @@
* limitations under the License.
*/
-export class ConfigData {
- FILE_URI = '/data/accounts/account_0/applications/com.ohos.settings'
- + '/com.ohos.settings/assets/entry/resources/rawfile/';
- PREFERENCES_PATH = '/data/accounts/account_0/appdata/com.ohos.settings/sharedPreference/SettingPreferences';
- BRIGHTNESS_SAVE_VALUE_KEY = 'BrightnessSaveValue';
- VOLUME_SAVE_VALUE_KEY = 'VolumeSaveValue';
- SENT_EVENT_BROADCAST_BRIGHTNESS_VALUE = 'BRIGHTNESS_VALUE';
- SENT_EVENT_BROADCAST_VOLUME_VALUE = 'VOLUME_VALUE';
- SENT_EVENT_WIFI_CONNECT_NAME = 'WIFI_CONNECT_NAME';
- BRIGHTNESS_DEFAULT_VALUE = 50;
- DEFAULT_BUNDLE_NAME = 'com.ohos.settings';
- DATE_AND_TIME_YEAR='DATE_AND_TIME_YEAR'
- DATE_AND_TIME_MONTH='DATE_AND_TIME_MONTH'
- DATE_AND_TIME_DAY='DATE_AND_TIME_DAY'
- TAG='Settings '
-
+export class ComponentConfig {
WH_100_100 = '100%';
WH_30_100 = '30%';
+ WH_33_100 = '33%';
WH_35_100 = '35%';
WH_40_100 = '40%';
WH_45_100 = '45%';
@@ -48,6 +34,5 @@ export class ConfigData {
DURATION_TIME = 200;
}
-let configData = new ConfigData();
-export default configData as ConfigData
-;
\ No newline at end of file
+let componentConfig = new ComponentConfig();
+export default componentConfig as ComponentConfig;
\ No newline at end of file
diff --git a/common/component/src/main/ets/default/controller/BaseSettingsController.ets b/common/component/src/main/ets/default/controller/BaseSettingsController.ets
new file mode 100644
index 00000000..d50702b5
--- /dev/null
+++ b/common/component/src/main/ets/default/controller/BaseSettingsController.ets
@@ -0,0 +1,86 @@
+/**
+ * Copyright (c) 2021 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 ISettingsController from './ISettingsController'
+
+export default abstract class BaseSettingsController implements ISettingsController {
+ protected getComponent: () => any;
+
+ /**
+ * Bind component.
+ */
+ bindComponent(component: any): ISettingsController{
+ this.getComponent = () => component;
+
+ // set default property values by component
+ for (var key in this) {
+ if (key in component) {
+ this[key] = component[key];
+ }
+ }
+
+ return this;
+ }
+
+ /**
+ * Bind component's properties.
+ */
+ bindProperties(componentProperties: string[], controllerProperties?: string[]): ISettingsController {
+ for (let i = 0; i < componentProperties.length; i++) {
+ this.defineBoundProperty(componentProperties[i], controllerProperties ? controllerProperties[i] : componentProperties[i]);
+ }
+
+ return this;
+ }
+
+ /**
+ * Initialize data.
+ */
+ initData(): ISettingsController {
+ return this;
+ };
+
+ /**
+ * Subscribe listeners.
+ */
+ subscribe(): ISettingsController {
+ return this;
+ };
+
+ /**
+ * Unsubscribe listeners.
+ */
+ unsubscribe(): ISettingsController {
+ return this;
+ };
+
+ /**
+ * Define bound properties.
+ */
+ private defineBoundProperty(componentProperty: string, controllerProperty: string): void {
+ let __v = this[controllerProperty];
+
+ Object.defineProperty(this, controllerProperty, {
+ get: function () {
+ return __v;
+ },
+ set: function (value) {
+ __v = value;
+ this.getComponent()[componentProperty] = value;
+ }
+ });
+ }
+
+}
\ No newline at end of file
diff --git a/common/component/src/main/ets/default/controller/ISettingsController.ts b/common/component/src/main/ets/default/controller/ISettingsController.ts
new file mode 100644
index 00000000..7a59b623
--- /dev/null
+++ b/common/component/src/main/ets/default/controller/ISettingsController.ts
@@ -0,0 +1,43 @@
+/**
+ * Copyright (c) 2021 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 default interface ISettingsController {
+
+ /**
+ * Bind component.
+ */
+ bindComponent(component: any): ISettingsController;
+
+ /**
+ * Bind component's properties.
+ */
+ bindProperties(componentProperties: string[], controllerProperties?: string[]): ISettingsController
+
+ /**
+ * Initialize data.
+ */
+ initData(): ISettingsController;
+
+ /**
+ * Subscribe listeners.
+ */
+ subscribe(): ISettingsController;
+
+ /**
+ * Unsubscribe listeners.
+ */
+ unsubscribe(): ISettingsController;
+
+}
\ No newline at end of file
diff --git a/common/component/src/main/ets/default/controller/SwitchController.ets b/common/component/src/main/ets/default/controller/SwitchController.ets
new file mode 100644
index 00000000..db302562
--- /dev/null
+++ b/common/component/src/main/ets/default/controller/SwitchController.ets
@@ -0,0 +1,35 @@
+/**
+ * Copyright (c) 2021 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 BaseSettingsController from './BaseSettingsController.ets'
+
+/**
+ * Switch controller
+ */
+export default abstract class SwitchController extends BaseSettingsController {
+ protected isOn: boolean = false;
+
+ /**
+ * Set toggle value
+ */
+ toggleValue(isOn: boolean) {
+ this.isOn = new Boolean(isOn).valueOf()
+ this.afterCurrentValueChanged();
+ }
+
+ /**
+ * After current value changed
+ */
+ abstract afterCurrentValueChanged();
+}
\ No newline at end of file
diff --git a/entry/src/main/ets/default/pages/component/entryComponent.ets b/common/component/src/main/ets/default/entryComponent.ets
similarity index 88%
rename from entry/src/main/ets/default/pages/component/entryComponent.ets
rename to common/component/src/main/ets/default/entryComponent.ets
index bda03321..f4ab4c70 100644
--- a/entry/src/main/ets/default/pages/component/entryComponent.ets
+++ b/common/component/src/main/ets/default/entryComponent.ets
@@ -12,7 +12,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-import ConfigData from '../../common/baseUtil/ConfigData.ets';
+import ComponentConfig from './ComponentConfig.ets';
/**
* item custom component
@@ -29,6 +29,9 @@ struct EntryComponent {
@Prop settingArrow: string;
@Prop settingArrowStyle: string;
@Prop settingUri: string;
+ @State titleFontColor: Color | number | string | Resource = $r('app.color.color_333333_grey');
+ private enabled : boolean = true;
+ private onArrowClick?: () => void;
build() {
Flex({ justifyContent: FlexAlign.SpaceBetween }) {
@@ -41,10 +44,11 @@ struct EntryComponent {
.objectFit(ImageFit.Contain);
Column() {
Text(this.settingTitle)
+ .fontColor(this.titleFontColor)
.fontColor($r('app.color.color_333333_grey'))
.fontSize($r('app.float.font_20'))
.textAlign(TextAlign.Start)
- .maxLines(ConfigData.MAX_LINES_3)
+ .maxLines(ComponentConfig.MAX_LINES_3)
.textOverflow({ overflow: TextOverflow.Ellipsis })
.margin({ top: $r('app.float.wh_value_10'), bottom: $r('app.float.wh_value_5') });
Row() {
@@ -52,7 +56,7 @@ struct EntryComponent {
.fontColor($r('app.color.color_999999_grey'))
.fontSize($r('app.float.font_18'))
.textAlign(TextAlign.Start)
- .maxLines(ConfigData.MAX_LINES_1)
+ .maxLines(ComponentConfig.MAX_LINES_1)
.textOverflow({ overflow: TextOverflow.Ellipsis })
.visibility('pages/applicationInfo' === this.settingUri ? Visibility.Visible : Visibility.None)
.margin({ bottom: $r('app.float.wh_value_10') });
@@ -60,7 +64,7 @@ struct EntryComponent {
.fontColor($r('app.color.color_999999_grey'))
.fontSize($r('app.float.font_18'))
.textAlign(TextAlign.Start)
- .maxLines(ConfigData.MAX_LINES_1)
+ .maxLines(ComponentConfig.MAX_LINES_1)
.textOverflow({ overflow: TextOverflow.Ellipsis })
.visibility('' === this.settingSummary || undefined === this.settingSummary ? Visibility.None : Visibility.Visible)
.margin({ bottom: $r('app.float.wh_value_10') });
@@ -88,6 +92,6 @@ struct EntryComponent {
.align(Alignment.End);
}
.margin({ left: $r('app.float.wh_value_15') })
- .width(ConfigData.WH_100_100);
+ .enabled(this.enabled);
}
}
\ No newline at end of file
diff --git a/entry/src/main/ets/default/pages/component/headComponent.ets b/common/component/src/main/ets/default/headComponent.ets
similarity index 73%
rename from entry/src/main/ets/default/pages/component/headComponent.ets
rename to common/component/src/main/ets/default/headComponent.ets
index 9766554b..a2d2d8db 100644
--- a/entry/src/main/ets/default/pages/component/headComponent.ets
+++ b/common/component/src/main/ets/default/headComponent.ets
@@ -12,7 +12,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-import ConfigData from '../../common/baseUtil/ConfigData.ets';
+import ComponentConfig from './ComponentConfig.ets';
import Router from '@system.router';
/**
@@ -33,27 +33,32 @@ struct HeadComponent {
.height($r('app.float.wh_value_50'))
.borderRadius($r('app.float.wh_value_15'))
.margin({
- left: $r('app.float.wh_value_15'),
- top: $r('app.float.wh_value_5'),
- bottom: $r('app.float.wh_value_5')
- })
+ left: $r('app.float.wh_value_15'),
+ top: $r('app.float.wh_value_5'),
+ bottom: $r('app.float.wh_value_5')})
.backgroundColor(this.isTouch ? $r('app.color.color_E3E3E3_grey') : $r('app.color.color_00000000_transparent'))
.visibility(this.icBackIsVisibility ? Visibility.Visible : Visibility.None)
- .onTouch(() => {
- this.isTouch = true;
- AppStorage.SetOrCreate('wifiPsd', '');
- Router.back();
- })
+ .onClick(()=>{
+ Router.back();
+ })
+ .onTouch((event: TouchEvent) => {
+ if (event.type === TouchType.Down) {
+ this.isTouch = true;
+ }
+ if (event.type === TouchType.Up) {
+ this.isTouch = false;
+ }
+ });
Text(this.headName)
.fontSize($r('app.float.font_24'))
.fontWeight(FontWeight.Bold)
.fontColor(Color.Black)
- .width(ConfigData.WH_90_100)
- .maxLines(ConfigData.MAX_LINES_1)
+ .width(ComponentConfig.WH_90_100)
+ .maxLines(ComponentConfig.MAX_LINES_1)
.textOverflow({ overflow: TextOverflow.Ellipsis })
.margin({ left: $r('app.float.wh_value_15'), right: $r('app.float.wh_value_15') });
}
- .width(ConfigData.WH_100_100)
+ .width(ComponentConfig.WH_100_100)
.height($r('app.float.wh_value_70'))
.alignItems(VerticalAlign.Center)
.align(Alignment.Start);
diff --git a/entry/src/main/ets/default/pages/component/imageAnimatorComponent.ets b/common/component/src/main/ets/default/imageAnimatorComponent.ets
similarity index 84%
rename from entry/src/main/ets/default/pages/component/imageAnimatorComponent.ets
rename to common/component/src/main/ets/default/imageAnimatorComponent.ets
index af0da4ad..10e754e1 100644
--- a/entry/src/main/ets/default/pages/component/imageAnimatorComponent.ets
+++ b/common/component/src/main/ets/default/imageAnimatorComponent.ets
@@ -12,7 +12,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-import ConfigData from '../../common/baseUtil/ConfigData.ets';
+import ComponentConfig from './ComponentConfig.ets';
/**
* ImageAnimator component
@@ -22,7 +22,7 @@ export default
struct ImageAnimatorComponent {
@State imageWidth: number = 0
@State imageHeight: number = 0
- @State whtl: number = ConfigData.value_20;
+ @State whtl: number = ComponentConfig.value_20;
build() {
Column() {
@@ -30,7 +30,7 @@ struct ImageAnimatorComponent {
.images([
{
src: 'res/image/xxxhdpi/ic_loading01.png',
- duration: ConfigData.DURATION_TIME,
+ duration: ComponentConfig.DURATION_TIME,
width: this.whtl,
height: this.whtl,
top: this.whtl,
@@ -38,7 +38,7 @@ struct ImageAnimatorComponent {
},
{
src: 'res/image/xxxhdpi/ic_loading02.png',
- duration: ConfigData.DURATION_TIME,
+ duration: ComponentConfig.DURATION_TIME,
width: this.whtl,
height: this.whtl,
top: this.whtl,
@@ -46,7 +46,7 @@ struct ImageAnimatorComponent {
},
{
src: 'res/image/xxxhdpi/ic_loading03.png',
- duration: ConfigData.DURATION_TIME,
+ duration: ComponentConfig.DURATION_TIME,
width: this.whtl,
height: this.whtl,
top: this.whtl,
@@ -54,7 +54,7 @@ struct ImageAnimatorComponent {
},
{
src: 'res/image/xxxhdpi/ic_loading04.png',
- duration: ConfigData.DURATION_TIME,
+ duration: ComponentConfig.DURATION_TIME,
width: this.whtl,
height: this.whtl,
top: this.whtl,
@@ -62,7 +62,7 @@ struct ImageAnimatorComponent {
},
{
src: 'res/image/xxxhdpi/ic_loading05.png',
- duration: ConfigData.DURATION_TIME,
+ duration: ComponentConfig.DURATION_TIME,
width: this.whtl,
height: this.whtl,
top: this.whtl,
@@ -70,7 +70,7 @@ struct ImageAnimatorComponent {
},
{
src: 'res/image/hdpi/ic_loading06.png',
- duration: ConfigData.DURATION_TIME,
+ duration: ComponentConfig.DURATION_TIME,
width: this.whtl,
height: this.whtl,
top: this.whtl,
diff --git a/common/component/src/main/ets/default/radioListComponent.ets b/common/component/src/main/ets/default/radioListComponent.ets
new file mode 100644
index 00000000..84ddea70
--- /dev/null
+++ b/common/component/src/main/ets/default/radioListComponent.ets
@@ -0,0 +1,135 @@
+/**
+ * Copyright (c) 2021 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 ComponentConfig from './ComponentConfig.ets';
+import LogUtil from '../../../../../utils/src/main/ets/default/baseUtil/LogUtil.ets';
+import Log from '../../../../../utils/src/main/ets/default/baseUtil/LogDecorator.ets';
+
+/**
+ * Radio component
+ */
+@Component
+export default
+struct RadioListComponent {
+ @State dataList: any[] = [];
+ @State checkedValue: string = '';
+ private showRadio: boolean = true;
+ private onChange?: (item : any) => void;
+
+ build() {
+ Column() {
+ List() {
+ ForEach(this.dataList, (item: any) => {
+ ListItem() {
+ RadioComponent({
+ settingIcon: item.settingIcon,
+ settingTitle: item.settingTitle,
+ settingSummary: item.settingSummary,
+ settingValue: item.settingValue,
+ showRadio: this.showRadio,
+ isChecked: (this.checkedValue == item.settingValue),
+ onChange:() => {
+ this.checkedValue = item.settingValue;
+ if (this.onChange) {
+ LogUtil.info('settings RadioListComponent : onChange: settingValue = ' + item.settingValue)
+ this.onChange(item);
+ }
+ }
+ });
+ }
+ .height(item.settingIcon ? $r('app.float.audio_no_icon_height') : $r('app.float.audio_icon_height'));
+ });
+ }
+ .divider({
+ strokeWidth: 1,
+ color: $r('app.color.color_E3E3E3_grey'),
+ startMargin: $r('app.float.audio_start_end_margin_left'),
+ endMargin: $r('app.float.audio_start_end_margin_left')
+ })
+ .width(ComponentConfig.WH_100_100)
+ .alignSelf(ItemAlign.Start);
+ }
+ .width(ComponentConfig.WH_100_100);
+ }
+}
+
+/**
+ * set up radio component
+ */
+@Component
+struct RadioComponent {
+ private settingIcon: string = '';
+ private settingTitle: string = '';
+ private settingSummary: string = '';
+ private settingValue: string = '';
+ private isChecked: boolean = false;
+ private onChange?: () => void;
+ private showRadio: boolean = true;
+
+ build() {
+ Flex({ justifyContent: FlexAlign.SpaceBetween }) {
+ Row() {
+ Image(this.settingIcon)
+ .width($r('app.float.audio_image_common_size'))
+ .height($r('app.float.audio_image_common_size'))
+ .margin({ right: $r('app.float.audio_image_margin_right') })
+ .visibility(this.settingIcon ? Visibility.Visible : Visibility.None)
+ .objectFit(ImageFit.Contain);
+ Column() {
+ Text(this.settingTitle)
+ .fontColor($r('app.color.color_333333_grey'))
+ .fontSize($r('app.float.control_common_font_size'))
+ .textAlign(TextAlign.Start)
+ .maxLines(ComponentConfig.MAX_LINES_3)
+ .textOverflow({ overflow: TextOverflow.Ellipsis })
+ .margin({ top: $r('app.float.audio_subtitle_margin_top'), bottom: $r('app.float.audio_subtitle_margin_bottom') });
+
+ Text(this.settingSummary)
+ .fontColor($r('app.color.color_999999_grey'))
+ .fontSize($r('app.float.audio_subtitle_font_size'))
+ .textAlign(TextAlign.Start)
+ .maxLines(ComponentConfig.MAX_LINES_1)
+ .textOverflow({ overflow: TextOverflow.Ellipsis })
+ .visibility(this.settingSummary ? Visibility.Visible : Visibility.None)
+ .margin({ bottom: $r('app.float.audio_summary_subtitle_margin_bottom') });
+ }
+ .margin({ left: $r('app.float.audio_title_summary_margin_left') })
+ .alignItems(HorizontalAlign.Start);
+ }
+ .flexShrink(0)
+ .alignItems(VerticalAlign.Center)
+ .align(Alignment.Start);
+
+ Row() {
+ Radio( {value: this.settingValue} )
+ .height($r('app.float.radio_component_height'))
+ .margin({ right: $r('app.float.radio_component_margin_bottom_right') })
+ .align(Alignment.End)
+ .enabled(false)
+ .checked(this.isChecked)
+ .visibility(this.showRadio ? Visibility.Visible : Visibility.None)
+ }
+ .align(Alignment.End);
+ }
+ .margin({ left: $r('app.float.audio_margin_left') })
+ .width(ComponentConfig.WH_100_100)
+ .onClick(() => {
+ LogUtil.info('settings RadioComponent : call onClick.')
+ if (this.onChange) {
+ this.onChange()
+ }
+ });
+ }
+
+}
diff --git a/common/component/src/main/ets/default/sliderComponent.ets b/common/component/src/main/ets/default/sliderComponent.ets
new file mode 100644
index 00000000..f82c3c04
--- /dev/null
+++ b/common/component/src/main/ets/default/sliderComponent.ets
@@ -0,0 +1,103 @@
+/**
+ * Copyright (c) 2021 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 ComponentConfig from './ComponentConfig.ets';
+
+/**
+ * Slider component
+ */
+@Component
+export default struct SliderComponent {
+ private visible: boolean = true;
+ private min: number = 0;
+ private max: number = 100;
+ private step?: number = 1;
+ private leftImage: string = '';
+ private rightImage: string = '';
+ @State clickConfirm: boolean = true;
+ @State showStep: boolean = false;
+ @State value: number = 0;
+ private onChange?: (value: number, mode: SliderChangeMode) => void
+ private summary: string | Resource; // Text details
+ @State fontSize: number = 18; // Font size
+
+ build() {
+ Flex({ direction: FlexDirection.Row }) {
+ Column() {
+ Image(this.leftImage)
+ .width($r('app.float.slider_image_width'))
+ .height($r('app.float.slider_image_height'))
+ .objectFit(ImageFit.Contain);
+ }.align(Alignment.TopStart).visibility(this.visible ? Visibility.Visible : Visibility.None)
+ .padding({ left: $r('app.float.slider_image_margin') })
+ .onClick(() => {
+ if (this.value != this.min && this.clickConfirm) {
+ this.value = Math.max(this.min, this.value - this.step);
+ this.onChangeHandler(this.value, SliderChangeMode.END);
+ }
+ }).align(Alignment.Center)
+
+ Column() {
+ Row() {
+ Text(this.summary)
+ .fontSize(this.fontSize)
+ .textAlign(TextAlign.Start);
+ }
+ .width(ComponentConfig.WH_83_100)
+
+ Slider({
+ value: this.value,
+ min: this.min,
+ max: this.max,
+ step: this.step
+ })
+ .selectedColor(Color.Blue)
+ .blockColor(Color.Blue)
+ .width(ComponentConfig.WH_100_100)
+ .showSteps(this.showStep)
+ .onChange((value, mode) => {
+ this.onChangeHandler(value, mode)
+ });
+ }.align(Alignment.Center).flexGrow(1)
+
+ Column() {
+ Image(this.rightImage)
+ .width($r('app.float.slider_image_width'))
+ .height($r('app.float.slider_image_height'))
+ .align(Alignment.Start)
+ .objectFit(ImageFit.Contain);
+ }.align(Alignment.TopEnd).visibility(this.visible ? Visibility.Visible : Visibility.None)
+ .padding({ right: $r('app.float.slider_image_margin') })
+ .onClick(() => {
+ if (this.value != this.max && this.clickConfirm) {
+ this.value = Math.min(this.max, this.value + this.step);
+ this.onChangeHandler(this.value, SliderChangeMode.END);
+ }
+ }).align(Alignment.Center)
+
+ }.width(ComponentConfig.WH_100_100).align(Alignment.TopStart)
+ }
+
+/**
+ * Change handler
+ *
+ * @param value - Change value
+ * @param mode - State
+ */
+ onChangeHandler(value, mode) {
+ if (this.onChange) {
+ this.onChange(value, mode);
+ }
+ }
+}
\ No newline at end of file
diff --git a/common/component/src/main/ets/default/switchComponent.ets b/common/component/src/main/ets/default/switchComponent.ets
new file mode 100644
index 00000000..a4b2febc
--- /dev/null
+++ b/common/component/src/main/ets/default/switchComponent.ets
@@ -0,0 +1,92 @@
+/**
+ * Copyright (c) 2021 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 ComponentConfig from './ComponentConfig.ets';
+import SwitchController from './controller/switchController.ets'
+
+/**
+ * Toggle component
+ */
+@Component
+export default struct SwitchComponent {
+ @Link isOn: boolean;
+ @Prop title: string;
+ private toggleValue: (isOn: boolean) => void;
+ private controller: SwitchController;
+ private cssValue: {
+ fontSize?: number | string | Resource,
+ height?: number | string | Resource,
+ width?: number | string | Resource,
+ margin?: {
+ top?: number | string | Resource,
+ right?: number | string | Resource,
+ bottom?: number | string | Resource,
+ left?: number | string | Resource
+ } | number | string | Resource,
+ padding: {
+ top?: number | string | Resource,
+ right?: number | string | Resource,
+ bottom?: number | string | Resource,
+ left?: number | string | Resource
+ } | number | string | Resource,
+ };
+
+ build() {
+ Flex({ direction: FlexDirection.Row, justifyContent: FlexAlign.SpaceBetween, alignItems: ItemAlign.Center }) {
+ Text(this.title)
+ .cssSwitchComponentTiTle(this.cssValue?.fontSize)
+ Toggle({ type: ToggleType.Switch, isOn: this.isOn })
+ .cssSwitchComponentToggle()
+ .onChange((isOn: boolean) => {
+ this.isOn = new Boolean(isOn).valueOf();
+ if (this.toggleValue) {
+ this.toggleValue(isOn);
+ }
+ });
+ }
+ .cssSwitchComponentFlex(this.cssValue?.margin, this.cssValue?.padding, this.cssValue?.width, this.cssValue?.height);
+ }
+
+ aboutToAppear() {
+ if (this.controller) {
+ // bind event handlers
+ this.toggleValue = this.controller.toggleValue.bind(this.controller);
+
+ // bind component and initialize
+ this.controller.bindComponent(this)
+ .bindProperties(["isOn"])
+ .initData();
+ }
+ }
+}
+
+@Extend(Text) function cssSwitchComponentTiTle (fontSize: number | string | Resource=$r('app.float.switch_title_subtitle_size')) {
+ .fontColor(Color.Black)
+ .fontStyle(FontStyle.Normal)
+ .padding({ left: $r('app.float.switch_component_margin') })
+ .fontSize(fontSize)
+}
+
+@Extend(Toggle) function cssSwitchComponentToggle () {
+ .width($r('app.float.switch_toggle_width'))
+ .height($r('app.float.switch_toggle_height'))
+ .padding({ right: $r('app.float.switch_component_margin') })
+}
+
+@Extend(Flex) function cssSwitchComponentFlex (margin: any, padding: any, width: number | string | Resource=ComponentConfig.WH_100_100, height: number | string | Resource=$r('app.float.switch_component_height')) {
+ .width(width)
+ .height(height)
+ .margin(margin)
+ .padding(padding)
+}
\ No newline at end of file
diff --git a/entry/src/main/ets/default/pages/component/textInputComponent.ets b/common/component/src/main/ets/default/textInputComponent.ets
similarity index 92%
rename from entry/src/main/ets/default/pages/component/textInputComponent.ets
rename to common/component/src/main/ets/default/textInputComponent.ets
index 29183679..b18bf427 100644
--- a/entry/src/main/ets/default/pages/component/textInputComponent.ets
+++ b/common/component/src/main/ets/default/textInputComponent.ets
@@ -12,7 +12,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-import ConfigData from '../../common/baseUtil/ConfigData.ets';
+import ComponentConfig from './ComponentConfig.ets';
/**
* TextInput component
@@ -30,7 +30,7 @@ export default struct textInputComponent {
.height($r('app.float.wh_value_70'))
.backgroundColor(Color.White)
.type(InputType.Password)
- .width(ConfigData.WH_100_100)
+ .width(ComponentConfig.WH_100_100)
.margin({ left: $r('app.float.wh_value_15'), right: $r('app.float.wh_value_15') })
.onChange((value: string) => {
this.contextText = value;
diff --git a/common/component/src/main/resources/base/element/string.json b/common/component/src/main/resources/base/element/string.json
new file mode 100644
index 00000000..bc311734
--- /dev/null
+++ b/common/component/src/main/resources/base/element/string.json
@@ -0,0 +1,4 @@
+{
+ "string": [
+ ]
+}
\ No newline at end of file
diff --git a/common/search/build.gradle b/common/search/build.gradle
new file mode 100644
index 00000000..525fd4ec
--- /dev/null
+++ b/common/search/build.gradle
@@ -0,0 +1,20 @@
+apply plugin: 'com.huawei.ohos.library'
+//For instructions on signature configuration, see https://developer.harmonyos.com/cn/docs/documentation/doc-guides/ide_debug_device-0000001053822404#section1112183053510
+ohos {
+ compileSdkVersion 7
+ defaultConfig {
+ compatibleSdkVersion 6
+ }
+
+ buildTypes {
+ release {
+ proguardOpt {
+ proguardEnabled false
+ rulesFiles 'proguard-rules.pro'
+ }
+ }
+ }
+}
+
+dependencies {
+}
diff --git a/common/search/proguard-rules.pro b/common/search/proguard-rules.pro
new file mode 100644
index 00000000..f7666e47
--- /dev/null
+++ b/common/search/proguard-rules.pro
@@ -0,0 +1 @@
+# config module specific ProGuard rules here.
\ No newline at end of file
diff --git a/common/search/src/main/config.json b/common/search/src/main/config.json
new file mode 100644
index 00000000..ccb0ae17
--- /dev/null
+++ b/common/search/src/main/config.json
@@ -0,0 +1,22 @@
+{
+ "app": {
+ "bundleName": "com.ohos.settings",
+ "vendor": "ohos",
+ "version": {
+ "code": 1000000,
+ "name": "1.0.0"
+ }
+ },
+ "deviceConfig": {},
+ "module": {
+ "package": "com.ohos.settings.common",
+ "deviceType": [
+ "phone"
+ ],
+ "distro": {
+ "deliveryWithInstall": true,
+ "moduleName": "search",
+ "moduleType": "har"
+ }
+ }
+}
\ No newline at end of file
diff --git a/common/search/src/main/ets/default/common/ResourceUtil.ets b/common/search/src/main/ets/default/common/ResourceUtil.ets
new file mode 100644
index 00000000..b55ab528
--- /dev/null
+++ b/common/search/src/main/ets/default/common/ResourceUtil.ets
@@ -0,0 +1,50 @@
+// @ts-nocheck
+/**
+ * Copyright (c) 2021 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 ConfigData from '../../../../../../utils/src/main/ets/default/baseUtil/ConfigData.ets';
+import ResMgr from '@ohos.resourceManager';
+import Log from '../../../../../../utils/src/main/ets/default/baseUtil/LogDecorator.ets';
+
+/**
+ * Resource util
+ */
+export class ResourceUtil {
+ private resMgr: ResMgr.ResourceManager;
+
+ /**
+ * Initialize ResourceManager
+ */
+ @Log
+ async initResourceManager(): Promise {
+ if (!this.resMgr) {
+ this.resMgr = await ResMgr.getResourceManager(ConfigData.DEFAULT_BUNDLE_NAME);
+ }
+ }
+
+ /**
+ * Get string value from NormalResource instance
+ *
+ * @param resource - NormalResource instance
+ */
+ @Log
+ async getString(resource): Promise {
+ await this.initResourceManager();
+ return await this.resMgr.getString(resource.id);
+ }
+
+}
+
+let resourceUtil = new ResourceUtil();
+export default resourceUtil as ResourceUtil;
diff --git a/common/search/src/main/ets/default/common/SearchConfig.ets b/common/search/src/main/ets/default/common/SearchConfig.ets
new file mode 100644
index 00000000..4d960883
--- /dev/null
+++ b/common/search/src/main/ets/default/common/SearchConfig.ets
@@ -0,0 +1,41 @@
+/**
+ * Copyright (c) 2021 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.
+ */
+
+/**
+ * Search config
+ */
+export default {
+ RDB_NAME: 'settings.db',
+ search: {
+ TABLE_NAME: 'SEARCH_DATA',
+ FIELD_ID: 'ID',
+ FIELD_ICON: 'ICON',
+ FIELD_TITLE: 'TITLE',
+ FIELD_KEYWORD: 'KEYWORD',
+ FIELD_SUMMARY: 'SUMMARY',
+ FIELD_SYNONYM: 'SYNONYM',
+ FIELD_URI: 'URI',
+ DDL_TABLE_CREATE: 'CREATE TABLE IF NOT EXISTS SEARCH_DATA (' +
+ 'ID INTEGER PRIMARY KEY AUTOINCREMENT, ' +
+ 'URI VARCHAR(200) NOT NULL, ' +
+ 'ICON VARCHAR(200), ' +
+ 'TITLE TEXT NOT NULL COLLATE NOCASE, ' +
+ 'KEYWORD TEXT NOT NULL COLLATE NOCASE, ' +
+ 'SUMMARY TEXT, ' +
+ 'SYNONYM TEXT )',
+ SQL_DELETE_ALL: 'DELETE FROM SEARCH_DATA',
+ PATH_SEPARATOR: ' > '
+ }
+}
diff --git a/common/search/src/main/ets/default/common/SearchUtil.ets b/common/search/src/main/ets/default/common/SearchUtil.ets
new file mode 100644
index 00000000..38b8f09f
--- /dev/null
+++ b/common/search/src/main/ets/default/common/SearchUtil.ets
@@ -0,0 +1,77 @@
+/**
+ * Copyright (c) 2021 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 SearchData from '../model/SearchData';
+import Log from '../../../../../../utils/src/main/ets/default/baseUtil/LogDecorator.ets';
+import ResourceUtil from './ResourceUtil.ets';
+
+/**
+ * Search util
+ */
+export class SearchUtil {
+
+ /**
+ * Convert json to instance
+ */
+ @Log
+ convertJsonToInstance (json: any, t: {new(): T}): T {
+ var instance = new t();
+
+ for (var key in json) {
+ if (instance.hasOwnProperty(key)) {
+ instance[key] = json[key];
+ }
+ }
+
+ return instance;
+ }
+
+ /**
+ * Convert json to SearchData instance
+ */
+ @Log
+ async convertToSearchData(rawData): Promise {
+ let result: Array = [];
+
+ for (let jsonData of rawData.data) {
+ let searchData: SearchData = new SearchData();
+ searchData.title = await ResourceUtil.getString(rawData.title);
+ searchData.keyword = await ResourceUtil.getString(jsonData.keyword);
+ searchData.summary = jsonData.summary ? await ResourceUtil.getString(jsonData.summary) : jsonData.summary;
+ searchData.synonym = jsonData.synonym ? await ResourceUtil.getString(jsonData.synonym) : jsonData.synonym;
+
+ result.push(searchData);
+ };
+
+ return result;
+ }
+
+ /**
+ * Delete illegal characters from search keyword
+ *
+ * @param text
+ */
+ stripKeyword(text: string): string {
+ var pattern = new RegExp("[`~!@#$%^&*()=|{}':;',\\[\\].<>/?~!@#¥……&*()——|{}【】‘;:”“'。,、?]")
+ var rs = "";
+ for (var i = 0; i < text.length; i++) {
+ rs = rs + text.substr(i, 1).replace(pattern, '');
+ }
+ return rs;
+ }
+
+}
+
+let searchUtil = new SearchUtil();
+export default searchUtil as SearchUtil;
diff --git a/common/search/src/main/ets/default/model/SearchData.ts b/common/search/src/main/ets/default/model/SearchData.ts
new file mode 100644
index 00000000..a02545f8
--- /dev/null
+++ b/common/search/src/main/ets/default/model/SearchData.ts
@@ -0,0 +1,29 @@
+/**
+ * Copyright (c) 2021 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.
+ */
+
+/**
+ * Search data dto class
+ */
+export default class SearchData {
+ uri: string = '';
+ icon: string = '';
+ title: string = '';
+ keyword: string = '';
+ summary: string = '';
+ synonym: string = '';
+
+ constructor() {
+ }
+}
\ No newline at end of file
diff --git a/common/search/src/main/ets/default/model/SearchModel.ets b/common/search/src/main/ets/default/model/SearchModel.ets
new file mode 100644
index 00000000..d5d82e6a
--- /dev/null
+++ b/common/search/src/main/ets/default/model/SearchModel.ets
@@ -0,0 +1,220 @@
+/**
+ * Copyright (c) 2021 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 ConfigData from '../../../../../../utils/src/main/ets/default/baseUtil/ConfigData.ets';
+import Log from '../../../../../../utils/src/main/ets/default/baseUtil/LogDecorator.ets';
+import { BaseData } from '../../../../../../utils/src/main/ets/default/model/BaseData.ets';
+import LogUtil from '../../../../../../utils/src/main/ets/default/baseUtil/LogUtil.ets';
+import SearchConfig from '../common/SearchConfig.ets';
+import SearchData from '../model/SearchData';
+import SearchDataProvider from '../provider/SearchDataProvider';
+import BaseParseConfModel from '../../../../../../utils/src/main/ets/default/model/BaseParseConfModel.ets';
+import ohosDataRdb from '@ohos.data.rdb';
+
+/**
+ * Search service class
+ */
+export default class SearchModel {
+ private rdbStore;
+ private searchDataConfig;
+
+ constructor(configData: Array