调整架构 添加base 基础工具模块

This commit is contained in:
2024-04-18 18:44:19 +08:00
parent e3873432bc
commit ec474c43d9
29 changed files with 225 additions and 41 deletions

6
base/.gitignore vendored Normal file
View File

@@ -0,0 +1,6 @@
/node_modules
/oh_modules
/.preview
/build
/.cxx
/.test

8
base/Index.ets Normal file
View File

@@ -0,0 +1,8 @@
export { Log } from "./src/main/ets/utils/Log"
export { ScreenUtil } from './src/main/ets/utils/ScreenUtil'
export { BaseLocalStorage, BaseLocalStorageKey } from './src/main/ets/utils/BaseLocalStorage'
export { Emitter, EmitterItem } from './src/main/ets/event/Emitter'
export { WebViewEventKey } from './src/main/ets/event/EventKey'

25
base/build-profile.json5 Normal file
View File

@@ -0,0 +1,25 @@
{
"apiType": "stageMode",
"buildOption": {
},
"buildOptionSet": [
{
"name": "release",
"arkOptions": {
"obfuscation": {
"ruleOptions": {
"enable": true,
"files": [
"./obfuscation-rules.txt"
]
}
}
},
},
],
"targets": [
{
"name": "default"
}
]
}

6
base/hvigorfile.ts Normal file
View File

@@ -0,0 +1,6 @@
import { hspTasks } from '@ohos/hvigor-ohos-plugin';
export default {
system: hspTasks, /* Built-in plugin of Hvigor. It cannot be modified. */
plugins:[] /* Custom plugin to extend the functionality of Hvigor. */
}

View 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
base/oh-package.json5 Normal file
View File

@@ -0,0 +1,11 @@
{
"name": "base",
"version": "1.0.0",
"description": "Please describe the basic information.",
"main": "Index.ets",
"author": "",
"license": "Apache-2.0",
"packageType": "InterfaceHar",
"dependencies": {
}
}

View File

@@ -0,0 +1,110 @@
export interface EmitterItem {
key: string
listener: Function
}
type EmitterAllType = string | object | boolean | number | Object | Number | BigInt;
export class Emitter {
private static instance: Emitter;
private static events: Map<string, EmitterItem[]> = new Map
private static viscosityData: Map<string, EmitterAllType[]> = new Map
public static getInstance(): Emitter {
if (!Emitter.instance) {
Emitter.instance = new Emitter();
}
return Emitter.instance;
}
/**
* 添加监听
* @param key
* @param listener
* @returns
*/
public on(key: string, listener: Function): EmitterItem {
let item: EmitterItem = {key: key, listener: listener};
if (typeof listener !== "function") {
throw new TypeError('the listener not a function')
}
let items: EmitterItem[] | undefined = Emitter.events.get(key);
if (!items) {
items = []
}
items.push(item)
Emitter.events.set(key, items)
if (Emitter.viscosityData.has(key)) {
let value = Emitter.viscosityData.get(key)
if (value == undefined) {
listener();
} else {
listener(...value);
}
}
return item
}
/**
* 取消监听
* @param listener
*/
public off(listener: EmitterItem): void {
let items = Emitter.events.get(listener.key)
if (!items) {
return;
}
items = items.filter((it)=> {
return it !== listener;
})
Emitter.events.set(listener.key, items);
}
/**
* 发布普通消息
* @param key
* @param args
*/
public emmit<T>(key: string, ...args: T[]) {
let items = Emitter.events.get(key)
if (!items || items.length == 0) {
return;
}
items.forEach((item: EmitterItem, index: number) => {
if (typeof item.listener === 'function') {
item.listener(...args)
}
});
}
/**
* 发布粘性消息
* @param key
* @param args
*/
public emmitViscosity<T>(key: string, ...args: T[]) {
this.emmit(key, ...args);
Emitter.viscosityData.set(key, args as EmitterAllType[]);
}
/**
* 移除粘性消息
* @param key
*/
public deleteViscosity<T>(key: string) {
if (Emitter.viscosityData.has(key)) {
Emitter.viscosityData.delete(key)
}
}
/**
* 删除所有监听
*/
public removeAllListener() {
Emitter.events = new Map;
}
}

View File

@@ -0,0 +1,5 @@
export class WebViewEventKey {
public static readonly TitleEvent: string = "web_view_event_title";
public static readonly DarkModeChangedEvent: string = "web_view_event_dark_mode_changed";
public static readonly UrlChangedEvent: string = "web_view_event_url_change_changed";
}

View 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%')
}
}

View File

@@ -0,0 +1,65 @@
import { Context } from '@kit.AbilityKit';
import dataPreferences from '@ohos.data.preferences';
import { Log } from './Log';
export class BaseLocalStorageKey {
static readonly KEY_SERVER_CONFIG = "key_config";
}
export class BaseLocalStorage {
private static instance: BaseLocalStorage;
private static lock: boolean = false;
private static readonly XY_DP_Name = "LocalData";
static getInstance(): BaseLocalStorage {
if (!BaseLocalStorage.instance) {
if (!BaseLocalStorage.lock) {
BaseLocalStorage.lock = true;
BaseLocalStorage.instance = new BaseLocalStorage();
BaseLocalStorage.lock = false;
}
}
return BaseLocalStorage.instance;
}
private context: Context | null = null;
private preferences: dataPreferences.Preferences | null = null;
private constructor() {
}
public init(context: Context): void {
if (!this.context) {
this.context = context.getApplicationContext();
let options: dataPreferences.Options = { name: BaseLocalStorage.XY_DP_Name };
this.preferences = dataPreferences.getPreferencesSync(this.context, options);
} else {
Log.i("LocalStorage is already init.")
}
}
public putData(key: string, value: dataPreferences.ValueType) {
Log.i(`put sp data, key:${key}, value:${value}`)
this.preferences?.putSync(key, value);
this.preferences?.flush();
}
public clearData(key: string) {
this.preferences?.delete(key);
this.preferences?.flush();
}
public getData(key: string, defaultValue: dataPreferences.ValueType): dataPreferences.ValueType | undefined {
let value = this.preferences?.getSync(key, defaultValue);
Log.i(`get sp data, key:${key}, value:${value}`)
return value;
}
public getObject<T>(key: string): T {
let value = this.getData(key, "{}") as string;
if (value.toString().length > 0) {
return JSON.parse(value) as T;
}
return "{}" as T;
}
}

View File

@@ -0,0 +1,33 @@
import hilog from '@ohos.hilog';
let domain: number = 0xFF00;
let prefix: string = 'HM4Demo';
let format: string = `%{public}s, %{public}s`;
export class Log {
static d(...args: string[]) {
hilog.debug(domain, prefix, format, args);
}
static i(...args: string[]) {
hilog.info(domain, prefix, format, args);
}
static w(...args: string[]) {
hilog.warn(domain, prefix, format, args);
}
static e(...args: string[]) {
hilog.error(domain, prefix, format, args);
}
static f(...args: string[]) {
hilog.fatal(domain,prefix, format, args);
}
static isLoggable(level: number) {
hilog.isLoggable(domain, prefix, level);
}
}

View File

@@ -0,0 +1,115 @@
import window from '@ohos.window';
import mediaquery from '@ohos.mediaquery';
import { Log } from './Log';
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) => {
})
}
setWindowKeepScreenOn(isKeep: boolean) {
Log.i(`setWindowKeepScreenOn:${isKeep}`)
window.getLastWindow(getContext(this))
.then((windowClass: window.Window) => {
windowClass.setWindowKeepScreenOn(isKeep);
});
}
}

View File

@@ -0,0 +1,14 @@
{
"module": {
"name": "base",
"type": "shared",
"description": "$string:shared_desc",
"deviceTypes": [
"phone",
"tablet",
"2in1"
],
"deliveryWithInstall": true,
"pages": "$profile:main_pages"
}
}

View File

@@ -0,0 +1,8 @@
{
"color": [
{
"name": "white",
"value": "#FFFFFF"
}
]
}

View File

@@ -0,0 +1,8 @@
{
"string": [
{
"name": "shared_desc",
"value": "description"
}
]
}

View File

@@ -0,0 +1,5 @@
{
"src": [
"pages/Index"
]
}

View File

@@ -0,0 +1,5 @@
import localUnitTest from './LocalUnit.test';
export default function testsuite() {
localUnitTest();
}

View 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);
});
});
}