init
14
.gitignore
vendored
Normal file
@ -0,0 +1,14 @@
|
||||
/node_modules
|
||||
/oh_modules
|
||||
/local.properties
|
||||
/.idea
|
||||
**/build
|
||||
/.hvigor
|
||||
.cxx
|
||||
/.clangd
|
||||
/.clang-format
|
||||
/.clang-tidy
|
||||
**/.test
|
||||
oh-package-lock.json5
|
||||
/oh-package-lock.json5
|
||||
/pack/sign
|
10
AppScope/app.json5
Normal file
@ -0,0 +1,10 @@
|
||||
{
|
||||
"app": {
|
||||
"bundleName": "net.devwiki.calculator",
|
||||
"vendor": "example",
|
||||
"versionCode": 1000000,
|
||||
"versionName": "1.0.0",
|
||||
"icon": "$media:app_icon",
|
||||
"label": "$string:app_name"
|
||||
}
|
||||
}
|
8
AppScope/resources/base/element/string.json
Normal file
@ -0,0 +1,8 @@
|
||||
{
|
||||
"string": [
|
||||
{
|
||||
"name": "app_name",
|
||||
"value": "Calculator"
|
||||
}
|
||||
]
|
||||
}
|
BIN
AppScope/resources/base/media/app_icon.png
Normal file
After Width: | Height: | Size: 2.0 KiB |
7
app/.gitignore
vendored
Normal file
@ -0,0 +1,7 @@
|
||||
/node_modules
|
||||
/oh_modules
|
||||
/.preview
|
||||
/build
|
||||
/.cxx
|
||||
/.test
|
||||
oh-package-lock.json5
|
28
app/build-profile.json5
Normal file
@ -0,0 +1,28 @@
|
||||
{
|
||||
"apiType": "stageMode",
|
||||
"buildOption": {
|
||||
},
|
||||
"buildOptionSet": [
|
||||
{
|
||||
"name": "release",
|
||||
"arkOptions": {
|
||||
"obfuscation": {
|
||||
"ruleOptions": {
|
||||
"enable": true,
|
||||
"files": [
|
||||
"./obfuscation-rules.txt"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
],
|
||||
"targets": [
|
||||
{
|
||||
"name": "default"
|
||||
},
|
||||
{
|
||||
"name": "ohosTest",
|
||||
}
|
||||
]
|
||||
}
|
6
app/hvigorfile.ts
Normal file
@ -0,0 +1,6 @@
|
||||
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. */
|
||||
}
|
18
app/obfuscation-rules.txt
Normal file
@ -0,0 +1,18 @@
|
||||
# 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://gitee.com/openharmony/arkcompiler_ets_frontend/blob/master/arkguard/README.md
|
||||
|
||||
# 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
|
11
app/oh-package.json5
Normal file
@ -0,0 +1,11 @@
|
||||
{
|
||||
"name": "app",
|
||||
"version": "1.0.0",
|
||||
"description": "Please describe the basic information.",
|
||||
"main": "",
|
||||
"author": "",
|
||||
"license": "",
|
||||
"dependencies": {
|
||||
}
|
||||
}
|
||||
|
41
app/src/main/ets/appability/AppAbility.ets
Normal file
@ -0,0 +1,41 @@
|
||||
import { AbilityConstant, UIAbility, Want } from '@kit.AbilityKit';
|
||||
import { hilog } from '@kit.PerformanceAnalysisKit';
|
||||
import { window } from '@kit.ArkUI';
|
||||
|
||||
export default class AppAbility extends UIAbility {
|
||||
onCreate(want: Want, launchParam: AbilityConstant.LaunchParam): void {
|
||||
hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onCreate');
|
||||
}
|
||||
|
||||
onDestroy(): void {
|
||||
hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onDestroy');
|
||||
}
|
||||
|
||||
onWindowStageCreate(windowStage: window.WindowStage): void {
|
||||
// Main window is created, set main page for this ability
|
||||
hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onWindowStageCreate');
|
||||
|
||||
windowStage.loadContent('pages/Index', (err, data) => {
|
||||
if (err.code) {
|
||||
hilog.error(0x0000, 'testTag', 'Failed to load the content. Cause: %{public}s', JSON.stringify(err) ?? '');
|
||||
return;
|
||||
}
|
||||
hilog.info(0x0000, 'testTag', 'Succeeded in loading the content. Data: %{public}s', JSON.stringify(data) ?? '');
|
||||
});
|
||||
}
|
||||
|
||||
onWindowStageDestroy(): void {
|
||||
// Main window is destroyed, release UI related resources
|
||||
hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onWindowStageDestroy');
|
||||
}
|
||||
|
||||
onForeground(): void {
|
||||
// Ability has brought to foreground
|
||||
hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onForeground');
|
||||
}
|
||||
|
||||
onBackground(): void {
|
||||
// Ability has back to background
|
||||
hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onBackground');
|
||||
}
|
||||
}
|
6
app/src/main/ets/bean/ConvertItem.ets
Normal file
@ -0,0 +1,6 @@
|
||||
|
||||
export class ConvertItem {
|
||||
icon: Resource = $r('app.media.app_icon');
|
||||
name: ResourceStr = '';
|
||||
page: string = '';
|
||||
}
|
4
app/src/main/ets/component/ComponentConst.ts
Normal file
@ -0,0 +1,4 @@
|
||||
export class ComponentConst {
|
||||
|
||||
static readonly ContainerId: string = "__container__"
|
||||
}
|
123
app/src/main/ets/component/TitleBar.ets
Normal file
@ -0,0 +1,123 @@
|
||||
import { ComponentConst } from './ComponentConst';
|
||||
|
||||
export enum TitleBarMenuType{
|
||||
/**
|
||||
* 不显示
|
||||
*/
|
||||
None = 0,
|
||||
/**
|
||||
* 显示Icon
|
||||
*/
|
||||
Icon = 1,
|
||||
/**
|
||||
* 显示文本
|
||||
*/
|
||||
Text = 2
|
||||
}
|
||||
|
||||
@Preview
|
||||
@Component
|
||||
export struct TitleBar {
|
||||
|
||||
@Prop title: ResourceStr;
|
||||
|
||||
@Prop barHeight: number = 48;
|
||||
@Prop menuPadding: number = 8;
|
||||
|
||||
@Prop leftText: ResourceStr = "";
|
||||
@Prop leftIcon: Resource = $r("app.media.ic_chevron_left");
|
||||
@Prop leftMenuType: TitleBarMenuType = TitleBarMenuType.Icon;
|
||||
|
||||
@Prop rightText: ResourceStr = "";
|
||||
@Prop rightIcon: Resource = $r("app.media.ic_close");
|
||||
@Prop rightMenuType: TitleBarMenuType = TitleBarMenuType.None;
|
||||
|
||||
@Prop titleTextAlign: TextAlign = TextAlign.Start;
|
||||
@Prop titleVisible: Visibility = Visibility.Visible;
|
||||
|
||||
onLeftClicked?: Function;
|
||||
onRightClicked?: Function;
|
||||
|
||||
@Styles setWidthAndHeight() {
|
||||
.height(this.barHeight).width(this.barHeight)
|
||||
}
|
||||
|
||||
build() {
|
||||
Row() {
|
||||
RelativeContainer() {
|
||||
if (this.leftMenuType != TitleBarMenuType.None) {
|
||||
Button() {
|
||||
if (this.leftMenuType == TitleBarMenuType.Icon) {
|
||||
Image(this.leftIcon)
|
||||
.setWidthAndHeight()
|
||||
.padding(this.menuPadding)
|
||||
} else {
|
||||
Text(this.leftText)
|
||||
.textAlign(TextAlign.Center)
|
||||
.setWidthAndHeight()
|
||||
}
|
||||
}
|
||||
.setWidthAndHeight()
|
||||
.backgroundColor(0xFFFFFF)
|
||||
.type(ButtonType.Normal)
|
||||
.stateEffect(true)
|
||||
.onClick((event) => {
|
||||
this.onLeftClicked?.(event);
|
||||
})
|
||||
.alignRules({
|
||||
top: { anchor: ComponentConst.ContainerId, align: VerticalAlign.Top },
|
||||
left: { anchor: ComponentConst.ContainerId, align: HorizontalAlign.Start },
|
||||
}).id("left_menu")
|
||||
}
|
||||
|
||||
if (this.titleVisible == Visibility.Visible) {
|
||||
Text(this.title)
|
||||
.textAlign(this.titleTextAlign)
|
||||
.backgroundColor(0xFFFFFF)
|
||||
.padding({
|
||||
left: this.leftMenuType != TitleBarMenuType.None ? 0 : this.menuPadding,
|
||||
right: this.rightMenuType != TitleBarMenuType.None ? 0 : this.menuPadding
|
||||
})
|
||||
.alignRules({
|
||||
top: { anchor: ComponentConst.ContainerId, align: VerticalAlign.Top },
|
||||
left: {
|
||||
anchor: this.leftMenuType != TitleBarMenuType.None ? "left_menu" : ComponentConst.ContainerId,
|
||||
align: this.leftMenuType != TitleBarMenuType.None ? HorizontalAlign.End : HorizontalAlign.Start
|
||||
},
|
||||
right: {
|
||||
anchor: this.rightMenuType != TitleBarMenuType.None ? "right_menu" : ComponentConst.ContainerId,
|
||||
align: this.rightMenuType != TitleBarMenuType.None ? HorizontalAlign.Start : HorizontalAlign.End
|
||||
},
|
||||
bottom: { anchor: ComponentConst.ContainerId, align: VerticalAlign.Bottom }
|
||||
})
|
||||
.id("title")
|
||||
}
|
||||
|
||||
if (this.rightMenuType != TitleBarMenuType.None) {
|
||||
Button() {
|
||||
if (this.rightMenuType == TitleBarMenuType.Icon) {
|
||||
Image(this.rightIcon)
|
||||
.setWidthAndHeight().padding(this.menuPadding)
|
||||
} else {
|
||||
Text(this.rightText)
|
||||
.textAlign(TextAlign.Center)
|
||||
.setWidthAndHeight()
|
||||
}
|
||||
}
|
||||
.setWidthAndHeight()
|
||||
.backgroundColor(0xFFFFFF)
|
||||
.type(ButtonType.Normal)
|
||||
.stateEffect(true)
|
||||
.onClick((event) => {
|
||||
this.onRightClicked?.(event);
|
||||
})
|
||||
.alignRules({
|
||||
top: { anchor: ComponentConst.ContainerId, align: VerticalAlign.Top },
|
||||
right: { anchor: ComponentConst.ContainerId, align: HorizontalAlign.End },
|
||||
}).id("right_menu")
|
||||
}
|
||||
}
|
||||
.width('100%').height('100%')
|
||||
}.height(this.barHeight)
|
||||
}
|
||||
}
|
40
app/src/main/ets/pages/Index.ets
Normal file
@ -0,0 +1,40 @@
|
||||
import { CalculateView } from './calculate/CalculatePage';
|
||||
import { ConvertView, ConvertViewModel } from './convert/ConvertPage';
|
||||
|
||||
@Entry
|
||||
@Component
|
||||
struct Index {
|
||||
@State message: string = 'Hello World';
|
||||
|
||||
@Provide convertViewModel: ConvertViewModel = new ConvertViewModel();
|
||||
|
||||
aboutToAppear(): void {
|
||||
this.convertViewModel.requestRefreshHome = () =>{
|
||||
// 这里处理 Home的 逻辑调用
|
||||
}
|
||||
}
|
||||
|
||||
onPageShow(): void {
|
||||
this.convertViewModel.onPageShow();
|
||||
}
|
||||
|
||||
build() {
|
||||
|
||||
Column() {
|
||||
Stack({ alignContent: Alignment.TopEnd}) {
|
||||
Tabs({ barPosition: BarPosition.Start}) {
|
||||
TabContent() {
|
||||
CalculateView();
|
||||
}
|
||||
.tabBar($r("app.string.calculate"))
|
||||
|
||||
TabContent() {
|
||||
ConvertView();
|
||||
}
|
||||
.tabBar($r("app.string.convert"))
|
||||
}
|
||||
}
|
||||
}
|
||||
.height('100%').width('100%')
|
||||
}
|
||||
}
|
9
app/src/main/ets/pages/calculate/CalculatePage.ets
Normal file
@ -0,0 +1,9 @@
|
||||
|
||||
@Preview
|
||||
@Component
|
||||
export struct CalculateView {
|
||||
|
||||
build() {
|
||||
Text("CalculatePage");
|
||||
}
|
||||
}
|
71
app/src/main/ets/pages/convert/ConvertPage.ets
Normal file
@ -0,0 +1,71 @@
|
||||
import { ConvertItem } from '../../bean/ConvertItem'
|
||||
import { Res } from '../../utils/Res';
|
||||
import { RoutePath } from '../../utils/RoutePath';
|
||||
|
||||
export class ConvertViewModel {
|
||||
|
||||
requestRefreshHome?: ()=> void;
|
||||
|
||||
convertItems: ConvertItem[] = [
|
||||
{ icon: Res.getImage('ic_length'), name: Res.getString('length_convert'), page: RoutePath.LengthPage },
|
||||
{ icon: Res.getImage('ic_weight'), name: Res.getString('weight_convert'), page: RoutePath.WeightPage },
|
||||
{ icon: Res.getImage('ic_area'), name: Res.getString('area_convert'), page: RoutePath.AreaPage },
|
||||
{ icon: Res.getImage('ic_number'), name: Res.getString('number_convert'), page: RoutePath.AreaPage },
|
||||
{ icon: Res.getImage('ic_speed'), name: Res.getString('speed_convert'), page: RoutePath.AreaPage },
|
||||
{ icon: Res.getImage('ic_bmi'), name: Res.getString('bmi_calculate'), page: RoutePath.AreaPage },
|
||||
{ icon: Res.getImage('ic_time'), name: Res.getString('time_convert'), page: RoutePath.TimePage },
|
||||
];
|
||||
|
||||
refresh() {
|
||||
|
||||
}
|
||||
|
||||
onPageShow() {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@Preview
|
||||
@Component
|
||||
export struct ConvertView {
|
||||
@Consume convertViewModel: ConvertViewModel;
|
||||
scroller: Scroller = new Scroller();
|
||||
|
||||
build() {
|
||||
Column() {
|
||||
Grid(this.scroller) {
|
||||
ForEach(this.convertViewModel.convertItems, (item: ConvertItem, index) => {
|
||||
GridItem() {
|
||||
ConvertItemView({ item: item })
|
||||
}
|
||||
.rowStart(index / 3)
|
||||
.columnStart(index % 3)
|
||||
})
|
||||
}.columnsTemplate('1fr 1fr 1fr')
|
||||
.width('100%').rowsGap(20).columnsGap(20)
|
||||
}.width('100%').height('100%').padding(8)
|
||||
}
|
||||
}
|
||||
|
||||
@Component
|
||||
struct ConvertItemView {
|
||||
@Prop item: ConvertItem
|
||||
|
||||
build() {
|
||||
Button() {
|
||||
Column() {
|
||||
Image(this.item.icon).width(32).height(32).objectFit(ImageFit.Contain)
|
||||
|
||||
Text(this.item.name).margin({ top: 8 })
|
||||
}
|
||||
.width(100)
|
||||
.height(100)
|
||||
.borderWidth(1)
|
||||
.borderColor('#eeeeee')
|
||||
.justifyContent(FlexAlign.Center)
|
||||
}.type(ButtonType.Normal).backgroundColor(Color.Transparent)
|
||||
.onClick(() => {
|
||||
this.getUIContext().getRouter().pushUrl({ url: this.item.page })
|
||||
})
|
||||
}
|
||||
}
|
13
app/src/main/ets/pages/convert/LengthPage.ets
Normal file
@ -0,0 +1,13 @@
|
||||
import { TitleBar } from '../../component/TitleBar'
|
||||
import { Res } from '../../utils/Res';
|
||||
|
||||
@Entry
|
||||
@Component
|
||||
export struct LengthPage {
|
||||
|
||||
build() {
|
||||
Column(){
|
||||
TitleBar({title: Res.getString('length_convert')});
|
||||
}.height('100%').width('100%')
|
||||
}
|
||||
}
|
8
app/src/main/ets/theme/CalThemeManager.ets
Normal file
@ -0,0 +1,8 @@
|
||||
|
||||
export class CalThemeManager {
|
||||
|
||||
}
|
||||
|
||||
export class CalTheme {
|
||||
|
||||
}
|
13
app/src/main/ets/utils/Res.ets
Normal file
@ -0,0 +1,13 @@
|
||||
|
||||
export class Res {
|
||||
private constructor() {
|
||||
}
|
||||
|
||||
static getString(name: string): Resource {
|
||||
return $r(`app.string.${name}`)
|
||||
}
|
||||
|
||||
static getImage(name: string): Resource {
|
||||
return $r(`app.media.${name}`)
|
||||
}
|
||||
}
|
13
app/src/main/ets/utils/RoutePath.ets
Normal file
@ -0,0 +1,13 @@
|
||||
|
||||
export class RoutePath {
|
||||
private constructor() {
|
||||
}
|
||||
|
||||
static readonly AreaPage = 'pages/convert/LengthPage';
|
||||
static readonly BMIPage = 'pages/convert/LengthPage';
|
||||
static readonly LengthPage = 'pages/convert/LengthPage';
|
||||
static readonly NumberPage = 'pages/convert/LengthPage';
|
||||
static readonly SpeedPage = 'pages/convert/LengthPage';
|
||||
static readonly TimePage = 'pages/convert/LengthPage';
|
||||
static readonly WeightPage = 'pages/convert/LengthPage';
|
||||
}
|
106
app/src/main/ets/utils/ScreenUtil.ets
Normal file
@ -0,0 +1,106 @@
|
||||
import window from '@ohos.window';
|
||||
import mediaquery from '@ohos.mediaquery';
|
||||
|
||||
export class ScreenUtil {
|
||||
// TODO: 工具待抽离, key统一定义
|
||||
static readonly isPortraitKey: string = "xy_screen_is_portrait";
|
||||
private static instance: ScreenUtil;
|
||||
public width: number = 0
|
||||
public height: number = 0
|
||||
public statusBarHeight: number = 0
|
||||
public bottomSafeHeight: number = 0
|
||||
public contentHeight: number = 0;
|
||||
|
||||
public layoutWidth: number = 0
|
||||
public layoutHeight: number = 0
|
||||
|
||||
|
||||
private portraitListener: mediaquery.MediaQueryListener = mediaquery.matchMediaSync('(orientation: portrait)');
|
||||
|
||||
public static getInstance(): ScreenUtil {
|
||||
if (!ScreenUtil.instance) {
|
||||
ScreenUtil.instance = new ScreenUtil();
|
||||
}
|
||||
return ScreenUtil.instance;
|
||||
}
|
||||
|
||||
initScreenSize(): void {
|
||||
this.portraitListener.on('change', (result)=> {
|
||||
AppStorage.setOrCreate(ScreenUtil.isPortraitKey, result.matches)
|
||||
})
|
||||
window.getLastWindow(getContext(this))
|
||||
.then((windowClass: window.Window) => {
|
||||
let type = window.AvoidAreaType.TYPE_NAVIGATION_INDICATOR; // 以导航条避让为例
|
||||
let avoidArea = windowClass.getWindowAvoidArea(type);
|
||||
this.bottomSafeHeight = px2vp(avoidArea.bottomRect.height); // 获取到导航条区域的高度
|
||||
type = window.AvoidAreaType.TYPE_SYSTEM;
|
||||
avoidArea = windowClass.getWindowAvoidArea(type);
|
||||
this.statusBarHeight = px2vp(avoidArea.topRect.height);
|
||||
this.width = px2vp(windowClass.getWindowProperties().windowRect.width);
|
||||
this.height = px2vp(windowClass.getWindowProperties().windowRect.height);
|
||||
this.layoutWidth = this.width;
|
||||
this.layoutHeight = this.height - this.statusBarHeight - this.bottomSafeHeight;
|
||||
})
|
||||
.catch((error: Error) => {
|
||||
})
|
||||
}
|
||||
|
||||
setPreferredOrientation(orientation: window.Orientation): void {
|
||||
window.getLastWindow(getContext(this))
|
||||
.then((windowClass: window.Window) => {
|
||||
windowClass.setPreferredOrientation(orientation);
|
||||
})
|
||||
.catch((error: Error) => {
|
||||
})
|
||||
}
|
||||
|
||||
setPreferredOrientationCallBack(orientation: window.Orientation, callback: ()=>void): void{
|
||||
window.getLastWindow(getContext(this))
|
||||
.then((windowClass: window.Window) => {
|
||||
windowClass.setPreferredOrientation(orientation,callback);
|
||||
AppStorage.setOrCreate(ScreenUtil.isPortraitKey, orientation == window.Orientation.PORTRAIT || orientation == window.Orientation.PORTRAIT_INVERTED);
|
||||
})
|
||||
.catch((error: Error) => {
|
||||
})
|
||||
}
|
||||
|
||||
setWindowLayoutFullScreen(isLayoutFullScreen: boolean): void {
|
||||
window.getLastWindow(getContext(this))
|
||||
.then((windowClass: window.Window) => {
|
||||
windowClass.setWindowLayoutFullScreen(isLayoutFullScreen);
|
||||
windowClass.setSpecificSystemBarEnabled('status', !isLayoutFullScreen);
|
||||
})
|
||||
.catch((error: Error) => {
|
||||
})
|
||||
}
|
||||
|
||||
setWindowSystemBarProperties(systemBarProperties: window.SystemBarProperties): void {
|
||||
window.getLastWindow(getContext(this))
|
||||
.then((windowClass: window.Window) => {
|
||||
windowClass.setWindowSystemBarProperties(systemBarProperties, (err) => {
|
||||
if (err.code) {
|
||||
console.error('Failed to set the system bar properties. Cause: ' + JSON.stringify(err));
|
||||
return;
|
||||
}
|
||||
console.info('Succeeded in setting the system bar properties.');
|
||||
});
|
||||
})
|
||||
.catch((error: Error) => {
|
||||
})
|
||||
}
|
||||
|
||||
setWindowSystemBarEnable(names:Array<'status' | 'navigation'>){
|
||||
window.getLastWindow(getContext(this))
|
||||
.then((windowClass: window.Window) => {
|
||||
windowClass.setWindowSystemBarEnable(names, (err) => {
|
||||
if (err.code) {
|
||||
console.error('Failed to set the system bar properties. Cause: ' + JSON.stringify(err));
|
||||
return;
|
||||
}
|
||||
console.info('Succeeded in setting the system bar properties.');
|
||||
});
|
||||
})
|
||||
.catch((error: Error) => {
|
||||
})
|
||||
}
|
||||
}
|
38
app/src/main/module.json5
Normal file
@ -0,0 +1,38 @@
|
||||
{
|
||||
"module": {
|
||||
"name": "app",
|
||||
"type": "entry",
|
||||
"description": "$string:module_desc",
|
||||
"mainElement": "AppAbility",
|
||||
"deviceTypes": [
|
||||
"phone",
|
||||
"tablet",
|
||||
"2in1"
|
||||
],
|
||||
"deliveryWithInstall": true,
|
||||
"installationFree": false,
|
||||
"pages": "$profile:main_pages",
|
||||
"abilities": [
|
||||
{
|
||||
"name": "AppAbility",
|
||||
"srcEntry": "./ets/appability/AppAbility.ets",
|
||||
"description": "$string:AppAbility_desc",
|
||||
"icon": "$media:ic_calculator_variant",
|
||||
"label": "$string:AppAbility_label",
|
||||
"startWindowIcon": "$media:ic_calculator_variant",
|
||||
"startWindowBackground": "$color:start_window_background",
|
||||
"exported": true,
|
||||
"skills": [
|
||||
{
|
||||
"entities": [
|
||||
"entity.system.home"
|
||||
],
|
||||
"actions": [
|
||||
"action.system.home"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
8
app/src/main/resources/base/element/color.json
Normal file
@ -0,0 +1,8 @@
|
||||
{
|
||||
"color": [
|
||||
{
|
||||
"name": "start_window_background",
|
||||
"value": "#FFFFFF"
|
||||
}
|
||||
]
|
||||
}
|
52
app/src/main/resources/base/element/string.json
Normal file
@ -0,0 +1,52 @@
|
||||
{
|
||||
"string": [
|
||||
{
|
||||
"name": "module_desc",
|
||||
"value": "module description"
|
||||
},
|
||||
{
|
||||
"name": "AppAbility_desc",
|
||||
"value": "description"
|
||||
},
|
||||
{
|
||||
"name": "AppAbility_label",
|
||||
"value": "Calculator"
|
||||
},
|
||||
{
|
||||
"name": "calculate",
|
||||
"value": "Calculate"
|
||||
},
|
||||
{
|
||||
"name": "convert",
|
||||
"value": "Convert"
|
||||
},
|
||||
{
|
||||
"name": "length_convert",
|
||||
"value": "Length"
|
||||
},
|
||||
{
|
||||
"name": "area_convert",
|
||||
"value": "Area"
|
||||
},
|
||||
{
|
||||
"name": "weight_convert",
|
||||
"value": "Weight"
|
||||
},
|
||||
{
|
||||
"name": "time_convert",
|
||||
"value": "Time"
|
||||
},
|
||||
{
|
||||
"name": "number_convert",
|
||||
"value": "Number"
|
||||
},
|
||||
{
|
||||
"name": "bmi_calculate",
|
||||
"value": "BMI"
|
||||
},
|
||||
{
|
||||
"name": "speed_convert",
|
||||
"value": "Speed"
|
||||
}
|
||||
]
|
||||
}
|
1
app/src/main/resources/base/media/ic_area.svg
Normal file
@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><title>texture-box</title><path d="M20 2H4C2.9 2 2 2.9 2 4V20C2 21.11 2.9 22 4 22H20C21.11 22 22 21.11 22 20V4C22 2.9 21.11 2 20 2M4 6L6 4H10.9L4 10.9V6M4 13.7L13.7 4H18.6L4 18.6V13.7M20 18L18 20H13.1L20 13.1V18M20 10.3L10.3 20H5.4L20 5.4V10.3Z" /></svg>
|
After Width: | Height: | Size: 314 B |
1
app/src/main/resources/base/media/ic_bmi.svg
Normal file
@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><title>scale</title><path d="M8.46,15.06L7.05,16.47L5.68,15.1C4.82,16.21 4.24,17.54 4.06,19H6V21H2V20C2,15.16 5.44,11.13 10,10.2V8.2L2,5V3H22V5L14,8.2V10.2C18.56,11.13 22,15.16 22,20V21H18V19H19.94C19.76,17.54 19.18,16.21 18.32,15.1L16.95,16.47L15.54,15.06L16.91,13.68C15.8,12.82 14.46,12.24 13,12.06V14H11V12.06C9.54,12.24 8.2,12.82 7.09,13.68L8.46,15.06M12,18A2,2 0 0,1 14,20A2,2 0 0,1 12,22C11.68,22 11.38,21.93 11.12,21.79L7.27,20L11.12,18.21C11.38,18.07 11.68,18 12,18Z" /></svg>
|
After Width: | Height: | Size: 544 B |
@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><title>calculator-variant</title><path d="M19 3H5C3.9 3 3 3.9 3 5V19C3 20.1 3.9 21 5 21H19C20.1 21 21 20.1 21 19V5C21 3.9 20.1 3 19 3M13 7.1L14.1 6L15.5 7.4L16.9 6L18 7.1L16.6 8.5L18 9.9L16.9 11L15.5 9.6L14.1 11L13 9.9L14.4 8.5L13 7.1M6.2 7.7H11.2V9.2H6.2V7.7M11.5 16H9.5V18H8V16H6V14.5H8V12.5H9.5V14.5H11.5V16M18 17.2H13V15.7H18V17.2M18 14.8H13V13.3H18V14.8Z" /></svg>
|
After Width: | Height: | Size: 429 B |
1
app/src/main/resources/base/media/ic_chevron_left.svg
Normal file
@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><title>chevron-left</title><path d="M15.41,16.58L10.83,12L15.41,7.41L14,6L8,12L14,18L15.41,16.58Z" /></svg>
|
After Width: | Height: | Size: 167 B |
1
app/src/main/resources/base/media/ic_close.svg
Normal file
@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><title>close</title><path d="M19,6.41L17.59,5L12,10.59L6.41,5L5,6.41L10.59,12L5,17.59L6.41,19L12,13.41L17.59,19L19,17.59L13.41,12L19,6.41Z" /></svg>
|
After Width: | Height: | Size: 208 B |
1
app/src/main/resources/base/media/ic_length.svg
Normal file
@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><title>ruler</title><path d="M1.39,18.36L3.16,16.6L4.58,18L5.64,16.95L4.22,15.54L5.64,14.12L8.11,16.6L9.17,15.54L6.7,13.06L8.11,11.65L9.53,13.06L10.59,12L9.17,10.59L10.59,9.17L13.06,11.65L14.12,10.59L11.65,8.11L13.06,6.7L14.47,8.11L15.54,7.05L14.12,5.64L15.54,4.22L18,6.7L19.07,5.64L16.6,3.16L18.36,1.39L22.61,5.64L5.64,22.61L1.39,18.36Z" /></svg>
|
After Width: | Height: | Size: 407 B |
1
app/src/main/resources/base/media/ic_number.svg
Normal file
@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><title>counter</title><path d="M4,4H20A2,2 0 0,1 22,6V18A2,2 0 0,1 20,20H4A2,2 0 0,1 2,18V6A2,2 0 0,1 4,4M4,6V18H11V6H4M20,18V6H18.76C19,6.54 18.95,7.07 18.95,7.13C18.88,7.8 18.41,8.5 18.24,8.75L15.91,11.3L19.23,11.28L19.24,12.5L14.04,12.47L14,11.47C14,11.47 17.05,8.24 17.2,7.95C17.34,7.67 17.91,6 16.5,6C15.27,6.05 15.41,7.3 15.41,7.3L13.87,7.31C13.87,7.31 13.88,6.65 14.25,6H13V18H15.58L15.57,17.14L16.54,17.13C16.54,17.13 17.45,16.97 17.46,16.08C17.5,15.08 16.65,15.08 16.5,15.08C16.37,15.08 15.43,15.13 15.43,15.95H13.91C13.91,15.95 13.95,13.89 16.5,13.89C19.1,13.89 18.96,15.91 18.96,15.91C18.96,15.91 19,17.16 17.85,17.63L18.37,18H20M8.92,16H7.42V10.2L5.62,10.76V9.53L8.76,8.41H8.92V16Z" /></svg>
|
After Width: | Height: | Size: 763 B |
1
app/src/main/resources/base/media/ic_refresh.svg
Normal file
@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><title>refresh</title><path d="M17.65,6.35C16.2,4.9 14.21,4 12,4A8,8 0 0,0 4,12A8,8 0 0,0 12,20C15.73,20 18.84,17.45 19.73,14H17.65C16.83,16.33 14.61,18 12,18A6,6 0 0,1 6,12A6,6 0 0,1 12,6C13.66,6 15.14,6.69 16.22,7.78L13,11H20V4L17.65,6.35Z" /></svg>
|
After Width: | Height: | Size: 311 B |
1
app/src/main/resources/base/media/ic_speed.svg
Normal file
@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><title>speedometer</title><path d="M12,16A3,3 0 0,1 9,13C9,11.88 9.61,10.9 10.5,10.39L20.21,4.77L14.68,14.35C14.18,15.33 13.17,16 12,16M12,3C13.81,3 15.5,3.5 16.97,4.32L14.87,5.53C14,5.19 13,5 12,5A8,8 0 0,0 4,13C4,15.21 4.89,17.21 6.34,18.65H6.35C6.74,19.04 6.74,19.67 6.35,20.06C5.96,20.45 5.32,20.45 4.93,20.07V20.07C3.12,18.26 2,15.76 2,13A10,10 0 0,1 12,3M22,13C22,15.76 20.88,18.26 19.07,20.07V20.07C18.68,20.45 18.05,20.45 17.66,20.06C17.27,19.67 17.27,19.04 17.66,18.65V18.65C19.11,17.2 20,15.21 20,13C20,12 19.81,11 19.46,10.1L20.67,8C21.5,9.5 22,11.18 22,13Z" /></svg>
|
After Width: | Height: | Size: 638 B |
1
app/src/main/resources/base/media/ic_thermometer.svg
Normal file
@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><title>thermometer</title><path d="M15 13V5A3 3 0 0 0 9 5V13A5 5 0 1 0 15 13M12 4A1 1 0 0 1 13 5V8H11V5A1 1 0 0 1 12 4Z" /></svg>
|
After Width: | Height: | Size: 189 B |
1
app/src/main/resources/base/media/ic_time.svg
Normal file
@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><title>clock-time-three</title><path d="M12 2C6.5 2 2 6.5 2 12C2 17.5 6.5 22 12 22C17.5 22 22 17.5 22 12S17.5 2 12 2M17 13H11V7H12.5V11.5H17V13Z" /></svg>
|
After Width: | Height: | Size: 214 B |
1
app/src/main/resources/base/media/ic_weight.svg
Normal file
@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><title>weight</title><path d="M12,3A4,4 0 0,1 16,7C16,7.73 15.81,8.41 15.46,9H18C18.95,9 19.75,9.67 19.95,10.56C21.96,18.57 22,18.78 22,19A2,2 0 0,1 20,21H4A2,2 0 0,1 2,19C2,18.78 2.04,18.57 4.05,10.56C4.25,9.67 5.05,9 6,9H8.54C8.19,8.41 8,7.73 8,7A4,4 0 0,1 12,3M12,5A2,2 0 0,0 10,7A2,2 0 0,0 12,9A2,2 0 0,0 14,7A2,2 0 0,0 12,5Z" /></svg>
|
After Width: | Height: | Size: 399 B |
BIN
app/src/main/resources/base/media/icon.png
Normal file
After Width: | Height: | Size: 2.0 KiB |
BIN
app/src/main/resources/base/media/startIcon.png
Normal file
After Width: | Height: | Size: 4.2 KiB |
6
app/src/main/resources/base/profile/main_pages.json
Normal file
@ -0,0 +1,6 @@
|
||||
{
|
||||
"src": [
|
||||
"pages/Index",
|
||||
"pages/convert/LengthPage"
|
||||
]
|
||||
}
|
52
app/src/main/resources/en_US/element/string.json
Normal file
@ -0,0 +1,52 @@
|
||||
{
|
||||
"string": [
|
||||
{
|
||||
"name": "module_desc",
|
||||
"value": "module description"
|
||||
},
|
||||
{
|
||||
"name": "AppAbility_desc",
|
||||
"value": "description"
|
||||
},
|
||||
{
|
||||
"name": "AppAbility_label",
|
||||
"value": "Calculator"
|
||||
},
|
||||
{
|
||||
"name": "calculate",
|
||||
"value": "Calculate"
|
||||
},
|
||||
{
|
||||
"name": "convert",
|
||||
"value": "Convert"
|
||||
},
|
||||
{
|
||||
"name": "length_convert",
|
||||
"value": "Length"
|
||||
},
|
||||
{
|
||||
"name": "area_convert",
|
||||
"value": "Area"
|
||||
},
|
||||
{
|
||||
"name": "weight_convert",
|
||||
"value": "Weight"
|
||||
},
|
||||
{
|
||||
"name": "time_convert",
|
||||
"value": "Time"
|
||||
},
|
||||
{
|
||||
"name": "speed_convert",
|
||||
"value": "Speed"
|
||||
},
|
||||
{
|
||||
"name": "number_convert",
|
||||
"value": "Number"
|
||||
},
|
||||
{
|
||||
"name": "bmi_calculate",
|
||||
"value": "BMI"
|
||||
}
|
||||
]
|
||||
}
|
52
app/src/main/resources/zh_CN/element/string.json
Normal file
@ -0,0 +1,52 @@
|
||||
{
|
||||
"string": [
|
||||
{
|
||||
"name": "module_desc",
|
||||
"value": "模块描述"
|
||||
},
|
||||
{
|
||||
"name": "AppAbility_desc",
|
||||
"value": "description"
|
||||
},
|
||||
{
|
||||
"name": "AppAbility_label",
|
||||
"value": "计算器"
|
||||
},
|
||||
{
|
||||
"name": "calculate",
|
||||
"value": "计算"
|
||||
},
|
||||
{
|
||||
"name": "convert",
|
||||
"value": "换算"
|
||||
},
|
||||
{
|
||||
"name": "length_convert",
|
||||
"value": "长度转换"
|
||||
},
|
||||
{
|
||||
"name": "area_convert",
|
||||
"value": "面积转换"
|
||||
},
|
||||
{
|
||||
"name": "weight_convert",
|
||||
"value": "重量转换"
|
||||
},
|
||||
{
|
||||
"name": "time_convert",
|
||||
"value": "时间转换"
|
||||
},
|
||||
{
|
||||
"name": "speed_convert",
|
||||
"value": "速度转换"
|
||||
},
|
||||
{
|
||||
"name": "number_convert",
|
||||
"value": "进制转换"
|
||||
},
|
||||
{
|
||||
"name": "bmi_calculate",
|
||||
"value": "BMI计算"
|
||||
}
|
||||
]
|
||||
}
|
2
app/src/mock/mock-config.json5
Normal file
@ -0,0 +1,2 @@
|
||||
{
|
||||
}
|
35
app/src/ohosTest/ets/test/Ability.test.ets
Normal file
@ -0,0 +1,35 @@
|
||||
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);
|
||||
})
|
||||
})
|
||||
}
|
5
app/src/ohosTest/ets/test/List.test.ets
Normal file
@ -0,0 +1,5 @@
|
||||
import abilityTest from './Ability.test';
|
||||
|
||||
export default function testsuite() {
|
||||
abilityTest();
|
||||
}
|
48
app/src/ohosTest/ets/testability/TestAbility.ets
Normal file
@ -0,0 +1,48 @@
|
||||
import { AbilityConstant, UIAbility, Want } from '@kit.AbilityKit';
|
||||
import { abilityDelegatorRegistry } from '@kit.TestKit';
|
||||
import { hilog } from '@kit.PerformanceAnalysisKit';
|
||||
import { window } from '@kit.ArkUI';
|
||||
import { Hypium } from '@ohos/hypium';
|
||||
import testsuite from '../test/List.test';
|
||||
|
||||
export default class TestAbility extends UIAbility {
|
||||
onCreate(want: Want, launchParam: AbilityConstant.LaunchParam) {
|
||||
hilog.info(0x0000, 'testTag', '%{public}s', 'TestAbility onCreate');
|
||||
hilog.info(0x0000, 'testTag', '%{public}s', 'want param:' + JSON.stringify(want) ?? '');
|
||||
hilog.info(0x0000, 'testTag', '%{public}s', 'launchParam:' + JSON.stringify(launchParam) ?? '');
|
||||
let abilityDelegator: abilityDelegatorRegistry.AbilityDelegator;
|
||||
abilityDelegator = abilityDelegatorRegistry.getAbilityDelegator();
|
||||
let abilityDelegatorArguments: abilityDelegatorRegistry.AbilityDelegatorArgs;
|
||||
abilityDelegatorArguments = abilityDelegatorRegistry.getArguments();
|
||||
hilog.info(0x0000, 'testTag', '%{public}s', 'start run testcase!!!');
|
||||
Hypium.hypiumTest(abilityDelegator, abilityDelegatorArguments, testsuite);
|
||||
}
|
||||
|
||||
onDestroy() {
|
||||
hilog.info(0x0000, 'testTag', '%{public}s', 'TestAbility onDestroy');
|
||||
}
|
||||
|
||||
onWindowStageCreate(windowStage: window.WindowStage) {
|
||||
hilog.info(0x0000, 'testTag', '%{public}s', 'TestAbility onWindowStageCreate');
|
||||
windowStage.loadContent('testability/pages/Index', (err, data) => {
|
||||
if (err.code) {
|
||||
hilog.error(0x0000, 'testTag', 'Failed to load the content. Cause: %{public}s', JSON.stringify(err) ?? '');
|
||||
return;
|
||||
}
|
||||
hilog.info(0x0000, 'testTag', 'Succeeded in loading the content. Data: %{public}s',
|
||||
JSON.stringify(data) ?? '');
|
||||
});
|
||||
}
|
||||
|
||||
onWindowStageDestroy() {
|
||||
hilog.info(0x0000, 'testTag', '%{public}s', 'TestAbility onWindowStageDestroy');
|
||||
}
|
||||
|
||||
onForeground() {
|
||||
hilog.info(0x0000, 'testTag', '%{public}s', 'TestAbility onForeground');
|
||||
}
|
||||
|
||||
onBackground() {
|
||||
hilog.info(0x0000, 'testTag', '%{public}s', 'TestAbility onBackground');
|
||||
}
|
||||
}
|
17
app/src/ohosTest/ets/testability/pages/Index.ets
Normal file
@ -0,0 +1,17 @@
|
||||
@Entry
|
||||
@Component
|
||||
struct Index {
|
||||
@State message: string = 'Hello World';
|
||||
|
||||
build() {
|
||||
Row() {
|
||||
Column() {
|
||||
Text(this.message)
|
||||
.fontSize(50)
|
||||
.fontWeight(FontWeight.Bold)
|
||||
}
|
||||
.width('100%')
|
||||
}
|
||||
.height('100%')
|
||||
}
|
||||
}
|
90
app/src/ohosTest/ets/testrunner/OpenHarmonyTestRunner.ets
Normal file
@ -0,0 +1,90 @@
|
||||
import { abilityDelegatorRegistry, TestRunner } from '@kit.TestKit';
|
||||
import { UIAbility, Want } from '@kit.AbilityKit';
|
||||
import { BusinessError } from '@kit.BasicServicesKit';
|
||||
import { hilog } from '@kit.PerformanceAnalysisKit';
|
||||
import { resourceManager } from '@kit.LocalizationKit';
|
||||
import { util } from '@kit.ArkTS';
|
||||
|
||||
let abilityDelegator: abilityDelegatorRegistry.AbilityDelegator;
|
||||
let abilityDelegatorArguments: abilityDelegatorRegistry.AbilityDelegatorArgs;
|
||||
let jsonPath: string = 'mock/mock-config.json';
|
||||
let tag: string = 'testTag';
|
||||
|
||||
async function onAbilityCreateCallback(data: UIAbility) {
|
||||
hilog.info(0x0000, 'testTag', 'onAbilityCreateCallback, data: ${}', JSON.stringify(data));
|
||||
}
|
||||
|
||||
async function addAbilityMonitorCallback(err: BusinessError) {
|
||||
hilog.info(0x0000, 'testTag', 'addAbilityMonitorCallback : %{public}s', JSON.stringify(err) ?? '');
|
||||
}
|
||||
|
||||
export default class OpenHarmonyTestRunner implements TestRunner {
|
||||
constructor() {
|
||||
}
|
||||
|
||||
onPrepare() {
|
||||
hilog.info(0x0000, 'testTag', '%{public}s', 'OpenHarmonyTestRunner OnPrepare');
|
||||
}
|
||||
|
||||
async onRun() {
|
||||
let tag = 'testTag';
|
||||
hilog.info(0x0000, tag, '%{public}s', 'OpenHarmonyTestRunner onRun run');
|
||||
abilityDelegatorArguments = abilityDelegatorRegistry.getArguments()
|
||||
abilityDelegator = abilityDelegatorRegistry.getAbilityDelegator()
|
||||
let moduleName = abilityDelegatorArguments.parameters['-m'];
|
||||
let context = abilityDelegator.getAppContext().getApplicationContext().createModuleContext(moduleName);
|
||||
let mResourceManager = context.resourceManager;
|
||||
await checkMock(abilityDelegator, mResourceManager);
|
||||
const bundleName = abilityDelegatorArguments.bundleName;
|
||||
const testAbilityName: string = 'TestAbility';
|
||||
let lMonitor: abilityDelegatorRegistry.AbilityMonitor = {
|
||||
abilityName: testAbilityName,
|
||||
onAbilityCreate: onAbilityCreateCallback,
|
||||
moduleName: moduleName
|
||||
};
|
||||
abilityDelegator.addAbilityMonitor(lMonitor, addAbilityMonitorCallback)
|
||||
const want: Want = {
|
||||
bundleName: bundleName,
|
||||
abilityName: testAbilityName,
|
||||
moduleName: moduleName
|
||||
};
|
||||
abilityDelegator.startAbility(want, (err: BusinessError, data: void) => {
|
||||
hilog.info(0x0000, tag, 'startAbility : err : %{public}s', JSON.stringify(err) ?? '');
|
||||
hilog.info(0x0000, tag, 'startAbility : data : %{public}s', JSON.stringify(data) ?? '');
|
||||
})
|
||||
hilog.info(0x0000, tag, '%{public}s', 'OpenHarmonyTestRunner onRun end');
|
||||
}
|
||||
}
|
||||
|
||||
async function checkMock(abilityDelegator: abilityDelegatorRegistry.AbilityDelegator, resourceManager: resourceManager.ResourceManager) {
|
||||
let rawFile: Uint8Array;
|
||||
try {
|
||||
rawFile = resourceManager.getRawFileContentSync(jsonPath);
|
||||
hilog.info(0x0000, tag, 'MockList file exists');
|
||||
let mockStr: string = util.TextDecoder.create("utf-8", { ignoreBOM: true }).decodeWithStream(rawFile);
|
||||
let mockMap: Record<string, string> = getMockList(mockStr);
|
||||
try {
|
||||
abilityDelegator.setMockList(mockMap)
|
||||
} catch (error) {
|
||||
let code = (error as BusinessError).code;
|
||||
let message = (error as BusinessError).message;
|
||||
hilog.error(0x0000, tag, `abilityDelegator.setMockList failed, error code: ${code}, message: ${message}.`);
|
||||
}
|
||||
} catch (error) {
|
||||
let code = (error as BusinessError).code;
|
||||
let message = (error as BusinessError).message;
|
||||
hilog.error(0x0000, tag, `ResourceManager:callback getRawFileContent failed, error code: ${code}, message: ${message}.`);
|
||||
}
|
||||
}
|
||||
|
||||
function getMockList(jsonStr: string) {
|
||||
let jsonObj: Record<string, Object> = JSON.parse(jsonStr);
|
||||
let map: Map<string, object> = new Map<string, object>(Object.entries(jsonObj));
|
||||
let mockList: Record<string, string> = {};
|
||||
map.forEach((value: object, key: string) => {
|
||||
let realValue: string = value['source'].toString();
|
||||
mockList[key] = realValue;
|
||||
});
|
||||
hilog.info(0x0000, tag, '%{public}s', 'mock-json value:' + JSON.stringify(mockList) ?? '');
|
||||
return mockList;
|
||||
}
|
38
app/src/ohosTest/module.json5
Normal file
@ -0,0 +1,38 @@
|
||||
{
|
||||
"module": {
|
||||
"name": "app_test",
|
||||
"type": "feature",
|
||||
"description": "$string:module_test_desc",
|
||||
"mainElement": "TestAbility",
|
||||
"deviceTypes": [
|
||||
"phone",
|
||||
"tablet",
|
||||
"2in1"
|
||||
],
|
||||
"deliveryWithInstall": true,
|
||||
"installationFree": false,
|
||||
"pages": "$profile:test_pages",
|
||||
"abilities": [
|
||||
{
|
||||
"name": "TestAbility",
|
||||
"srcEntry": "./ets/testability/TestAbility.ets",
|
||||
"description": "$string:TestAbility_desc",
|
||||
"icon": "$media:icon",
|
||||
"label": "$string:TestAbility_label",
|
||||
"exported": true,
|
||||
"startWindowIcon": "$media:icon",
|
||||
"startWindowBackground": "$color:start_window_background",
|
||||
"skills": [
|
||||
{
|
||||
"actions": [
|
||||
"action.system.home"
|
||||
],
|
||||
"entities": [
|
||||
"entity.system.home"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
8
app/src/ohosTest/resources/base/element/color.json
Normal file
@ -0,0 +1,8 @@
|
||||
{
|
||||
"color": [
|
||||
{
|
||||
"name": "start_window_background",
|
||||
"value": "#FFFFFF"
|
||||
}
|
||||
]
|
||||
}
|
16
app/src/ohosTest/resources/base/element/string.json
Normal file
@ -0,0 +1,16 @@
|
||||
{
|
||||
"string": [
|
||||
{
|
||||
"name": "module_test_desc",
|
||||
"value": "test ability description"
|
||||
},
|
||||
{
|
||||
"name": "TestAbility_desc",
|
||||
"value": "the test ability"
|
||||
},
|
||||
{
|
||||
"name": "TestAbility_label",
|
||||
"value": "test label"
|
||||
}
|
||||
]
|
||||
}
|
BIN
app/src/ohosTest/resources/base/media/icon.png
Normal file
After Width: | Height: | Size: 2.0 KiB |
5
app/src/ohosTest/resources/base/profile/test_pages.json
Normal file
@ -0,0 +1,5 @@
|
||||
{
|
||||
"src": [
|
||||
"testability/pages/Index"
|
||||
]
|
||||
}
|
5
app/src/test/List.test.ets
Normal file
@ -0,0 +1,5 @@
|
||||
import localUnitTest from './LocalUnit.test';
|
||||
|
||||
export default function testsuite() {
|
||||
localUnitTest();
|
||||
}
|
33
app/src/test/LocalUnit.test.ets
Normal file
@ -0,0 +1,33 @@
|
||||
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);
|
||||
});
|
||||
});
|
||||
}
|
49
build-profile.json5
Normal file
@ -0,0 +1,49 @@
|
||||
{
|
||||
"app": {
|
||||
"signingConfigs": [
|
||||
{
|
||||
"name": "default",
|
||||
"type": "HarmonyOS",
|
||||
"material": {
|
||||
"certpath": "pack\\sign\\Calculator.cer",
|
||||
"storePassword": "0000001B5481E637034868BA817E3587B2970184D289B5D31D4C9419623B4DC7D7BB75754FCA76D10C1041",
|
||||
"keyAlias": "debugKey",
|
||||
"keyPassword": "0000001BD840965E928F712E6EA53F84819A89B66F13335133910D43192ABECAA48A75BA9DD3DA3C30A55A",
|
||||
"profile": "pack\\sign\\Calculator.p7b",
|
||||
"signAlg": "SHA256withECDSA",
|
||||
"storeFile": "pack\\sign\\Calculator.p12"
|
||||
}
|
||||
}
|
||||
],
|
||||
"products": [
|
||||
{
|
||||
"name": "default",
|
||||
"signingConfig": "default",
|
||||
"compatibleSdkVersion": "4.0.0(10)",
|
||||
"runtimeOS": "HarmonyOS",
|
||||
}
|
||||
],
|
||||
"buildModeSet": [
|
||||
{
|
||||
"name": "debug",
|
||||
},
|
||||
{
|
||||
"name": "release"
|
||||
}
|
||||
]
|
||||
},
|
||||
"modules": [
|
||||
{
|
||||
"name": "app",
|
||||
"srcPath": "./app",
|
||||
"targets": [
|
||||
{
|
||||
"name": "default",
|
||||
"applyToProducts": [
|
||||
"default"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
21
hvigor/hvigor-config.json5
Normal file
@ -0,0 +1,21 @@
|
||||
{
|
||||
"modelVersion": "5.0.0",
|
||||
"dependencies": {
|
||||
},
|
||||
"execution": {
|
||||
// "analyze": "default", /* Define the build analyze mode. Value: [ "default" | "verbose" | false ]. Default: "default" */
|
||||
// "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 */
|
||||
},
|
||||
"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": 4096 /* Enable nodeOptions maxOldSpaceSize compilation. Unit M. Used for the daemon process */
|
||||
}
|
||||
}
|
6
hvigorfile.ts
Normal file
@ -0,0 +1,6 @@
|
||||
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. */
|
||||
}
|
15
oh-package.json5
Normal file
@ -0,0 +1,15 @@
|
||||
{
|
||||
"modelVersion": "5.0.0",
|
||||
"name": "calculator",
|
||||
"version": "1.0.0",
|
||||
"description": "Please describe the basic information.",
|
||||
"main": "",
|
||||
"author": "",
|
||||
"license": "",
|
||||
"dependencies": {
|
||||
},
|
||||
"devDependencies": {
|
||||
"@ohos/hypium": "1.0.15",
|
||||
"@ohos/hamock": "1.0.0-rc"
|
||||
}
|
||||
}
|
15
readme.md
Normal file
@ -0,0 +1,15 @@
|
||||
# 项目说明
|
||||
|
||||
本项目代码地址为: [Harmony/Calculator - Calculator - DevWiki Gitea](https://git.devwiki.net/Harmony/Calculator),同时会同步到:
|
||||
- Gitee: [DevWiki/Calculate](https://gitee.com/devwiki/Calculate)
|
||||
- Github: [Dev-Wiki/Calculator](https://github.com/Dev-Wiki/Calculator)
|
||||
|
||||
## 1. 功能说明
|
||||
|
||||
## 2. 代码划分
|
||||
项目包含以下几个模块:
|
||||
- [pages](/app/src/main/ets/pages) : 页面部分
|
||||
- [pages/calculate](/app/src/main/ets/pages/calculate) : 计算器部分
|
||||
- [pages/convert](/app/src/main/ets/pages/convert) : 换算部分
|
||||
- [component](/app/src/main/ets/component) : 自定义组件
|
||||
- [utils](/app/src/main/ets/utils) : 工具类
|