update systemui code from std

Signed-off-by: r00498791 <renjie32@huawei.com>
This commit is contained in:
r00498791
2022-04-11 12:54:14 +08:00
parent 640665d04a
commit 8343cf3b42
269 changed files with 10268 additions and 2760 deletions
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2021 Huawei Device Co., Ltd.
* Copyright (c) 2021-2022 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
+47
View File
@@ -0,0 +1,47 @@
/*
* Copyright (c) 2021-2022 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 const WindowNameMap = {
2112: 'navigation',
2108: 'status',
2111: 'volume'
};
export interface Rect {
left: number;
top: number;
width: number;
height: number;
};
export type WindowType = 'status' | 'navigation' | 'volume';
export default class Constants {
static URI_VAR: string = 'dataability:///com.ohos.settingsdata.DataAbility';
}
export enum FASlotName {
AUTO_ROTATE = "auto_rotate",
AIR_PLANE = "air_plane",
BATTERY = 'battery',
BLUETOOTH = 'bluetooth',
CAPSULE = 'capsule',
CLOCK = 'clock',
EMPTY = 'empty',
LOCATION = 'location',
NOTIFICATION = 'notification',
RING_MODE = 'ring_mode',
SIGNAL = 'signal',
WIFI = 'wifi',
}
+45
View File
@@ -0,0 +1,45 @@
/*
* Copyright (c) 2022 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 Log from "./Log";
const TAG = "Decorators";
export function debounce(timeout: number) {
return function inner(target: any, propKey: string, descriptor: PropertyDescriptor) {
let curFunc: number = 0;
const original = descriptor.value;
descriptor.value = function (...args: string[]) {
Log.showInfo(TAG, `debounce invoke ${propKey} curFunc: ${curFunc}`);
curFunc && clearTimeout(curFunc);
curFunc = setTimeout(() => original.call(this, ...args), timeout);
};
};
}
export function throttle(waitTime: number) {
return function inner(target: any, propKey: string, descriptor: PropertyDescriptor) {
let lastTime: number = 0;
const original = descriptor.value;
descriptor.value = function (...args: string[]) {
let curTime = Date.now();
Log.showInfo(TAG, `throttle invoke ${propKey} timeInterval: ${curTime - lastTime}`);
if (curTime - lastTime >= waitTime) {
original.call(this, ...args);
lastTime = curTime;
}
};
};
}
@@ -0,0 +1,29 @@
/*
* Copyright (c) 2022 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 EventManager from "./event/EventManager";
import Log from "./Log";
import ScreenLockManager from "./ScreenLockManager";
import ServiceExtensionContext from "application/ServiceExtensionContext";
import TimeManager from "./TimeManager";
const TAG = "initSystemui";
export default function initSystemUi(context: ServiceExtensionContext) {
EventManager.setContext(context);
ScreenLockManager.init();
TimeManager.init(context);
Log.showDebug(TAG, `init done, ctx: ${context}`);
}
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2021 Huawei Device Co., Ltd.
* Copyright (c) 2021-2022 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
@@ -13,20 +13,35 @@
* limitations under the License.
*/
const TAG = 'SystemUI_Default';
const TAG = "SystemUI_Default";
const FILTER_KEYS = [
new RegExp('hide', "gi")
]
export function filterKey(target: any, propKey: string, descriptor: PropertyDescriptor) {
const original = descriptor.value;
descriptor.value = function (...args: string[]) {
let filterResult = args.map((str) => {
let tempStr = str
FILTER_KEYS.forEach((filterKey) => tempStr = tempStr.replace(filterKey, "**"))
return tempStr
});
const result = original.call(this, ...filterResult);
return result;
};
}
/**
* Basic log class
*/
export default class Log {
/**
* print info level log
*
* @param {string} tag - Page or class tag
* @param {string} log - Log needs to be printed
*/
static showInfo(tag, log) {
static showInfo(tag: string, log: string) {
console.info(`${TAG} tag: ${tag} --> ${log}`);
}
@@ -36,7 +51,7 @@ export default class Log {
* @param {string} tag - Page or class tag
* @param {string} log - Log needs to be printed
*/
static showDebug(tag, log) {
static showDebug(tag: string, log: string) {
console.debug(`${TAG} tag: ${tag} --> ${log}`);
}
@@ -46,7 +61,7 @@ export default class Log {
* @param {string} tag - Page or class tag
* @param {string} log - Log needs to be printed
*/
static showError(tag, log) {
static showError(tag: string, log: string) {
console.error(`${TAG} tag: ${tag} --> ${log}`);
}
}
@@ -0,0 +1,96 @@
/*
* Copyright (c) 2022 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 inputConsumer from "@ohos.multimodalInput.inputConsumer";
import Log from "./Log";
import createOrGet from "./SingleInstanceHelper";
export type MultiCallback = (keyOptions: typeof inputConsumer.KeyOptions) => void;
export enum MultiKeyCode {
WIN = 2076,
N = 2030,
I = 2025,
}
const TAG = "MultimodalInputManager";
class MultimodalInputManager {
//win + N
notificationKeyOptions: any = {
preKeys: [2076],
finalKey: 2030,
isFinalKeyDown: true,
finalKeyDownDuration: 0,
};
//win + I
controlKeyOptions: any = {
preKeys: [2076],
finalKey: 2025,
isFinalKeyDown: true,
finalKeyDownDuration: 0,
};
subscribeCombinationKey(keys: MultiKeyCode[], cb: MultiCallback): () => void {
if (keys.length <= 1) {
Log.showError(TAG, `Invalid keys, can't subscribe.`);
return () => {};
}
let keyOptions = {
preKeys: keys.slice(0, keys.length - 1),
finalKey: keys[keys.length - 1],
isFinalKeyDown: true,
finalKeyDownDuration: 0,
};
inputConsumer.on("key", keyOptions, (err, options) => {
Log.showInfo(TAG, `on CombinationKey, options:${JSON.stringify(options)}, err: ${JSON.stringify(err)}`);
cb(options);
});
Log.showInfo(TAG, `subscribe CombinationKey, keys:${JSON.stringify(keys)}`);
return () => {
inputConsumer.off("key", keyOptions, (err, data) => {});
};
}
registerControlListener(callback) {
Log.showInfo(TAG, `registerListener control`);
inputConsumer.on("key", this.controlKeyOptions, (err, data) => {
Log.showInfo(TAG, `controlRegisterCallBack err: ${JSON.stringify(err)} data: ${JSON.stringify(data)}`);
callback.onControlShowOrHide(err, data);
});
Log.showInfo(TAG, `registerListener end`);
}
registerNotificationListener(callback) {
Log.showInfo(TAG, `registerListener notification`);
inputConsumer.on("key", this.notificationKeyOptions, (err, data) => {
Log.showInfo(TAG, `notificationRegisterCallBack err: ${JSON.stringify(err)} data: ${JSON.stringify(data)}`);
callback.onNotificationShowOrHide(err, data);
});
Log.showInfo(TAG, `registerListener end`);
}
unregisterListener() {
Log.showInfo(TAG, `unregisterListener start`);
inputConsumer.off("key", this.notificationKeyOptions, (err, data) => {
Log.showInfo(TAG, `notificationUnregisterCallBack err: ${JSON.stringify(err)} data: ${JSON.stringify(data)}`);
});
inputConsumer.off("key", this.controlKeyOptions, (err, data) => {
Log.showInfo(TAG, `controlUnregisterCallBack err: ${JSON.stringify(err)} data: ${JSON.stringify(data)}`);
});
Log.showInfo(TAG, `unregisterListener end`);
}
}
let sMultimodalInputManager = createOrGet(MultimodalInputManager, TAG);
export default sMultimodalInputManager as MultimodalInputManager;
@@ -1,5 +1,5 @@
/**
* Copyright (c) 2021 Huawei Device Co., Ltd.
* Copyright (c) 2021-2022 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
@@ -13,7 +13,7 @@
* limitations under the License.
*/
import Log from './Log.ets';
import Log from './Log';
import FileIo from '@ohos.fileio';
const DFAULT_SIZE = 4096;
@@ -1,5 +1,5 @@
/**
* Copyright (c) 2021 Huawei Device Co., Ltd.
* Copyright (c) 2021-2022 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
@@ -12,7 +12,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import ResMgr from '@ohos.resourceManager';
import AbilityManager from './abilitymanager/abilityManager'
/**
* Resource util
@@ -25,7 +25,8 @@ export class ResourceUtil {
*/
async initResourceManager(): Promise<void> {
if (!this.resMgr) {
this.resMgr = await ResMgr.getResourceManager('com.ohos.systemui');
let context = AbilityManager.getContext();
this.resMgr = await context.resourceManager;
}
return this.resMgr;
}
@@ -0,0 +1,63 @@
/*
* Copyright (c) 2022 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 commonEvent from "@ohos.commonEvent";
import { CommonEventSubscriber } from "commonEvent/commonEventSubscriber";
import createOrGet from "./SingleInstanceHelper";
import EventManager from "./event/EventManager";
import Log from "./Log";
import { obtainLocalEvent } from "./event/EventUtil";
import { debounce } from "./Decorators";
export const SCREEN_CHANGE_EVENT = "screenChangeEvent";
const TAG = "ScreenLockManager";
const SCREEN_COMMON_EVENT_INFO = {
events: [commonEvent.Support.COMMON_EVENT_SCREEN_OFF, commonEvent.Support.COMMON_EVENT_SCREEN_ON],
};
const debounceTimeout = 500;
class ScreenLockManager {
mSubscriber: CommonEventSubscriber | undefined;
async init() {
this.mSubscriber = await commonEvent.createSubscriber(SCREEN_COMMON_EVENT_INFO);
commonEvent.subscribe(this.mSubscriber, (err, data) => {
if (err.code != 0) {
Log.showError(TAG, `Can't handle screen change, err: ${JSON.stringify(err)}`);
return;
}
Log.showDebug(TAG, `screenChange, err: ${JSON.stringify(err)} data: ${JSON.stringify(data)}`);
switch (data.event) {
case commonEvent.Support.COMMON_EVENT_SCREEN_OFF:
this.notifyScreenEvent(false);
break;
case commonEvent.Support.COMMON_EVENT_SCREEN_ON:
this.notifyScreenEvent(true);
break;
default:
Log.showError(TAG, `unknow event`);
}
});
}
@debounce(debounceTimeout)
notifyScreenEvent(isScreenOn: boolean) {
EventManager.publish(obtainLocalEvent(SCREEN_CHANGE_EVENT, isScreenOn));
Log.showDebug(TAG, `publish ${SCREEN_CHANGE_EVENT} screenState: ${isScreenOn}`);
}
}
let sScreenLockManager = createOrGet(ScreenLockManager, TAG);
export default sScreenLockManager as ScreenLockManager;
@@ -0,0 +1,65 @@
/*
* Copyright (c) 2021-2022 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 settings from "@ohos.settings";
import {DataAbilityHelper} from "ability/dataAbilityHelper";
import featureAbility from "@ohos.ability.featureAbility";
import Log from "./Log";
import Constants from "./Constants";
import createOrGet from "./SingleInstanceHelper";
import AbilityManager from "./abilitymanager/abilityManager";
const TAG = "SettingsUtil";
export class SettingsUtil {
helper: DataAbilityHelper;
constructor() {
Log.showInfo(TAG, `constructor`);
try {
this.helper = featureAbility.acquireDataAbilityHelper(AbilityManager.getContext(), Constants.URI_VAR);
} catch (e) {
Log.showInfo(TAG, `constructor, acquire helper error: ${e.toString()}`);
}
}
getValue(name: string, defValue?: string): string {
Log.showInfo(TAG, `getValue, name: ${name} defValue: ${defValue}`);
let value: string = null;
try {
value = settings.getValueSync(this.helper, name, defValue ? defValue : "");
} catch (e) {
Log.showInfo(TAG, `getValue e: ${e.toString()}`);
}
Log.showInfo(TAG, `getValue, value: ${value}`);
return value;
}
setValue(name: string, value: string): boolean {
Log.showInfo(TAG, `setValue, name: ${name} value: ${value}`);
let result = false;
try {
result = settings.setValueSync(this.helper, name, value);
} catch (e) {
Log.showInfo(TAG, `setValue e: ${e.toString()}`);
}
Log.showInfo(TAG, `setValue, result: ${result}`);
return result;
}
}
let sSettingsUtil = createOrGet(SettingsUtil, TAG);
export default sSettingsUtil as SettingsUtil;
@@ -0,0 +1,36 @@
/**
* Copyright (c) 2021-2022 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 Log from './Log';
import audio from '@ohos.multimedia.audio';
const TAG = "SingleInstanceHelper";
const AUDIO_MANAGER_KEY = 'MultiMediaAudioManager';
export default function createOrGet<T>(objectClass: { new(): T }, storageKey: string): T {
if (!globalThis[storageKey]) {
globalThis[storageKey] = new objectClass();
Log.showInfo(TAG, `Create key of ${storageKey}`);
}
return globalThis[storageKey];
}
export function getAudioManager() {
if (!globalThis[AUDIO_MANAGER_KEY]) {
globalThis[AUDIO_MANAGER_KEY] = audio.getAudioManager();
Log.showInfo(TAG, `Create Audio Manager.`);
}
return globalThis[AUDIO_MANAGER_KEY];
}
@@ -0,0 +1,32 @@
/*
* Copyright (c) 2021-2022 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 StyleManager from './StyleManager';
const TAG = 'Common-StyleConfiguration';
export default class StyleConfiguration {
static getCommonStyle() {
const key: string = TAG + "-Common";
return StyleManager.getStyle(key, () => {
return {
statusBarFontSize: '16fp',
statusBarIconWidth: '24vp',
statusBarIconHeight: '24vp',
statusBarMarginLeftRight: '5vp',
};
});
}
}
@@ -0,0 +1,41 @@
/*
* Copyright (c) 2021-2022 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 Log from './Log';
const TAG = 'Common-StyleManager';
export class StyleManager {
mAbilityPageName: string = '';
setAbilityPageName(name: string): void{
Log.showInfo(TAG, `setAbilityPageName, name: ${name}`);
this.mAbilityPageName = name;
}
getStyle(key: string, generateDefaultFunction: Function) {
let newKey = this.mAbilityPageName + '-' + key;
if (!AppStorage.Has(newKey)) {
let defaultStyle = generateDefaultFunction();
AppStorage.SetOrCreate(newKey, defaultStyle);
Log.showInfo(TAG, `Create storageKey of ${newKey}`);
}
return AppStorage.Get(newKey);
}
}
let styleManager = new StyleManager();
export default styleManager as StyleManager;
@@ -1,101 +0,0 @@
/*
* 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 AccountManager from '@ohos.account.osAccount';
import Log from './Log.ets';
const STORAGE_KEY = 'SwitchUserManager_AppStorage'
const TAG = 'SwitchUserManager'
const SUBSCRIBE_KEY = 'SystemUiAccount'
const USER_CHANGE_EVENT = 'activate'
const INVALID_USER_ID = -1;
interface UserChangeListener {
userChange: Function
}
export class UserInfo {
userId: number = INVALID_USER_ID;
userName: string = '';
userIcon: string | Resource = '';
[key: string]: any ;
}
async function getCurrentAccountInfo() {
let currentAccountInfo = {};
let accountInfos = await AccountManager.getAccountManager().queryAllCreatedOsAccounts();
for (let accountInfo of accountInfos) {
Log.showInfo(TAG, `accountInfo: ${accountInfo.localId}, isActive: ${accountInfo.isActived}`);
if (accountInfo.isActived) {
return accountInfo;
}
}
return new UserInfo();
}
function parseAccountInfo(accountInfo): UserInfo {
return {
userId: accountInfo.localId,
userName: accountInfo.localName,
userIcon: accountInfo.photo
}
}
export default class SwitchUserManager {
mUserInfo: UserInfo = new UserInfo();
mListeners = new Set<UserChangeListener>();
static getInstance(): SwitchUserManager {
if (!AppStorage.Has(STORAGE_KEY)) {
let mamanger = new SwitchUserManager();
AppStorage.SetOrCreate(STORAGE_KEY, mamanger);
}
return AppStorage.Get(STORAGE_KEY);
}
constructor() {
Log.showInfo(TAG, `SwitchUserManager constructor`);
AccountManager.getAccountManager().on(USER_CHANGE_EVENT, SUBSCRIBE_KEY, this.handleUserChange.bind(this));
}
public async getCurrentUserInfo(): Promise<UserInfo> {
if (this.mUserInfo.userId == INVALID_USER_ID) {
let accountInfo = await getCurrentAccountInfo();
this.mUserInfo = parseAccountInfo(accountInfo);
}
return this.mUserInfo;
}
public registerListener(listener: UserChangeListener) {
this.mListeners.add(listener)
}
public unregisterListener(listener: UserChangeListener) {
this.mListeners.delete(listener)
}
handleUserChange(accountId) {
AccountManager.getAccountManager().queryOsAccountById(accountId).then((accountInfo) => {
Log.showInfo(TAG, `userChange, accountInfo: ${JSON.stringify(accountInfo)}`);
this.mUserInfo = parseAccountInfo(accountInfo)
this.notifyUserChange();
})
}
notifyUserChange() {
this.mListeners.forEach((listener) => listener.userChange(this.mUserInfo))
}
}
@@ -0,0 +1,111 @@
/*
* Copyright (c) 2021-2022 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 AccountManager from "@ohos.account.osAccount";
import Log from "./Log";
import getSingleInstance from "./SingleInstanceHelper";
const TAG = "SwitchUserManager";
const SUBSCRIBE_KEY = "SystemUiAccount";
const USER_CHANGE_EVENT = "activate";
const DELAY_TIME = 3 * 1000;
export const INVALID_USER_ID = -1;
type AccountInfo = {
localId: number;
localName: string;
photo: string;
};
export type UserChangeListener = {
userChange: (data: UserInfo) => void;
};
export class UserInfo {
userId: number = INVALID_USER_ID;
userName: string = "";
userIcon: string | Resource = "";
[key: string]: any;
}
async function getCurrentAccountInfo(): Promise<AccountInfo> {
let accountInfos = await AccountManager.getAccountManager().queryAllCreatedOsAccounts();
for (let accountInfo of accountInfos) {
Log.showInfo(TAG, `accountInfo: ${accountInfo.localId}, isActive: ${accountInfo.isActived}`);
if (accountInfo.isActived) {
return accountInfo;
}
}
return { localId: INVALID_USER_ID, localName: "", photo: "" };
}
function parseAccountInfo(accountInfo: AccountInfo): UserInfo {
return {
userId: accountInfo.localId,
userName: accountInfo.localName,
userIcon: accountInfo.photo,
};
}
export default class SwitchUserManager {
mUserInfo: UserInfo = new UserInfo();
mListeners = new Set<UserChangeListener>();
mHasWait: boolean = false;
static getInstance(): SwitchUserManager {
return getSingleInstance(SwitchUserManager, TAG);
}
constructor() {
Log.showInfo(TAG, `SwitchUserManager constructor`);
AccountManager.getAccountManager().on(USER_CHANGE_EVENT, SUBSCRIBE_KEY, this.handleUserChange.bind(this));
}
public async getCurrentUserInfo(): Promise<UserInfo> {
if (this.mUserInfo.userId == INVALID_USER_ID) {
this.mUserInfo = parseAccountInfo(await getCurrentAccountInfo());
while (!this.mHasWait && this.mUserInfo.userId == INVALID_USER_ID) {
await new Promise((resolve) => setTimeout(resolve, DELAY_TIME));
this.mUserInfo = parseAccountInfo(await getCurrentAccountInfo());
}
this.mHasWait = true;
this.mUserInfo = parseAccountInfo(await getCurrentAccountInfo());
}
Log.showInfo(TAG, `getCurrentUserInfo userId: ${this.mUserInfo.userId}`);
return this.mUserInfo;
}
public registerListener(listener: UserChangeListener) {
this.mListeners.add(listener);
}
public unregisterListener(listener: UserChangeListener) {
this.mListeners.delete(listener);
}
handleUserChange(accountId: number): void {
AccountManager.getAccountManager()
.queryOsAccountById(accountId)
.then((accountInfo) => {
Log.showInfo(TAG, `userChange, accountInfo: ${JSON.stringify(accountInfo)}`);
this.mUserInfo = parseAccountInfo(accountInfo);
this.notifyUserChange();
})
.catch((err) => Log.showError(TAG, `Can't query account by ${accountId}, err: ${err}`));
}
notifyUserChange() {
this.mListeners.forEach((listener) => listener.userChange(this.mUserInfo));
}
}
+120
View File
@@ -0,0 +1,120 @@
/**
* Copyright (c) 2021-2022 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 settings from "@ohos.settings";
import commonEvent from "@ohos.commonEvent";
import featureAbility from "@ohos.ability.featureAbility";
import { DataAbilityHelper } from "ability/dataAbilityHelper";
import Log from "./Log";
import EventManager from "./event/EventManager";
import createOrGet from "./SingleInstanceHelper";
import { obtainLocalEvent } from "./event/EventUtil";
import { CommonEventManager, getCommonEventManager, POLICY } from "./commonEvent/CommonEventManager";
export const TIME_CHANGE_EVENT = "Time_Change_Event";
export type TimeEventArgs = {
date: Date;
timeFormat: boolean;
};
const TAG = "TimeManager";
const URI_VAR = "dataability:///com.ohos.settingsdata.DataAbility";
const TIME_FORMAT_KEY = "settings.time.format";
const TIME_SUBSCRIBE_INFO = {
events: [
commonEvent.Support.COMMON_EVENT_TIME_CHANGED,
commonEvent.Support.COMMON_EVENT_TIMEZONE_CHANGED,
commonEvent.Support.COMMON_EVENT_TIME_TICK,
],
};
function fill(value: number) {
return (value > 9 ? "" : "0") + value;
}
export function concatTime(h: number, m: number) {
return `${fill(h)}:${fill(m)}`;
}
class TimeManager {
private mUse24hFormat: boolean = false;
private mSettingsHelper?: DataAbilityHelper;
private mManager?: CommonEventManager;
public init(context: any) {
this.mManager = getCommonEventManager(
TAG,
TIME_SUBSCRIBE_INFO,
() => this.notifyTimeChange(),
(isSubscribe) => isSubscribe && this.notifyTimeChange()
);
this.mManager.subscriberCommonEvent();
this.mManager.applyPolicy([POLICY.SCREEN_POLICY]);
this.initTimeFormat(context);
}
public release() {
this.mManager?.release();
this.mManager = undefined;
this.mSettingsHelper?.off("dataChange", settings.getUriSync(TIME_FORMAT_KEY));
}
public formatTime(date: Date) {
return concatTime(date.getHours() % (this.mUse24hFormat ? 24 : 12), date.getMinutes());
}
private initTimeFormat(context: any) {
Log.showInfo(TAG, "initTimeFormat");
this.mSettingsHelper = featureAbility.acquireDataAbilityHelper(context, URI_VAR);
const handleTimeFormatChange = () => {
if (!this.mSettingsHelper) {
Log.showError(TAG, `Can't get dataAbility helper.`);
return;
}
let timeString = settings.getValueSync(this.mSettingsHelper, TIME_FORMAT_KEY, "24");
Log.showDebug(TAG, `timeFormat change: ${timeString}`);
this.mUse24hFormat = timeString == "24";
this.notifyTimeChange();
};
try {
this.mSettingsHelper.on("dataChange", settings.getUriSync(TIME_FORMAT_KEY), (err) => {
if (err.code !== 0) {
Log.showError(TAG, `failed to getAbilityWant, code: ${err.code}.`);
return;
}
handleTimeFormatChange();
});
} catch (e) {
Log.showError(TAG, `Can't listen timeformate change.`);
}
handleTimeFormatChange();
}
private notifyTimeChange() {
Log.showInfo(TAG, "notifyTimeChange");
let args: TimeEventArgs = {
date: new Date(),
timeFormat: this.mUse24hFormat,
};
EventManager.publish(obtainLocalEvent(TIME_CHANGE_EVENT, args));
}
}
let sTimeManager = createOrGet(TimeManager, TAG);
export default sTimeManager as TimeManager;
@@ -0,0 +1,101 @@
/*
* Copyright (c) 2021-2022 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 Window from "@ohos.window";
import display from "@ohos.display";
import Log from "./Log";
import {WindowType, Rect, WindowNameMap} from "./Constants";
import getSingleInstance from "./SingleInstanceHelper";
const TAG = "TintStateManager";
const LISTENER_SYSTEM_BAR_TINT_CHANGE = "systemBarTintChange";
export type TintStateListener = { onTintStateChange: (state: TintState) => void }
;
export interface TintState {
isEnable?: boolean;
region?: Rect;
backgroundColor?: string;
contentColor?: string;
}
export class TintContentInfo {
contentColor: string = "#FFFFFFFF";
}
export function getOrCreateTintContentInfo(key: string): TintContentInfo {
let storageKey = 'SystemUI_TintContentInfo_' + key;
if (!AppStorage.Has(storageKey)) {
AppStorage.SetOrCreate(storageKey, new TintContentInfo());
Log.showInfo(TAG, `getOrCreateTintContentInfo, Create storageKey of ${storageKey}`);
}
return AppStorage.Get(storageKey);
}
export default class TintStateManager {
mListeners: Map<WindowType, TintStateListener> = new Map();
mStates: Map<WindowType, TintState> = new Map();
static getInstance(): TintStateManager {
return getSingleInstance(TintStateManager, TAG);
}
constructor() {
Log.showInfo(TAG, `init TintStateManager. ${LISTENER_SYSTEM_BAR_TINT_CHANGE}`);
Window.on(LISTENER_SYSTEM_BAR_TINT_CHANGE, this.onSystemBarTintChange.bind(this));
}
registerListener(windowType: WindowType, listener: TintStateListener) {
let tintState = this.mStates.get(windowType);
tintState && listener.onTintStateChange(tintState);
let res = this.mListeners.set(windowType, listener);
Log.showInfo(TAG, `registser listenerSize: ${res.size}`);
}
unregisterListener(windowType: WindowType) {
let res = this.mListeners.delete(windowType);
Log.showInfo(TAG, `unregistser ${windowType}, res: ${res}`);
}
async onSystemBarTintChange(data) {
Log.showInfo(TAG, `onSystemBarTintChange, data: ${JSON.stringify(data)}`);
if (!Array.isArray(data.regionTint)) {
Log.showInfo(TAG, `regionTint is not array.`);
return;
}
let dis = await display.getDefaultDisplay();
if (dis.id != data.displayId) {
Log.showInfo(TAG, `Needn't change, displayId: ${data.displayId}`);
return;
}
data.regionTint.forEach((regionTintData) => {
Log.showInfo(TAG, `onSystemBarTintChange, type: ${WindowNameMap[regionTintData["type"]]}`);
let windowType = WindowNameMap[regionTintData["type"]];
if (!windowType) {
return;
}
let tintState: TintState = {
isEnable: regionTintData.isEnable,
region: regionTintData.region,
backgroundColor: regionTintData.backgroundColor,
contentColor: regionTintData.contentColor,
};
Log.showInfo(TAG, `tintState: ${JSON.stringify(tintState)}`);
this.mStates.set(windowType, tintState);
this.mListeners.get(windowType)?.onTintStateChange(tintState);
});
}
}
@@ -1,99 +0,0 @@
/*
* 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 Window from '@ohos.window';
import display from '@ohos.display'
import Log from './Log.ets';
import ResourceUtil from './ResourceUtil.ets';
const TAG = 'WindowManager';
var maxWidth;
var maxHeight;
var minHeight;
/**
* Manage window size changes.
*/
export default class WindowManager {
async initWindowManager() {
Log.showInfo(TAG, 'initWindowManager');
maxWidth = AppStorage.SetAndLink("maxWidth", 0);
maxHeight = AppStorage.SetAndLink("maxHeight", 0);
minHeight = AppStorage.SetAndLink("minHeight", 0);
await display.getDefaultDisplay()
.then(dis => {
maxWidth.set(dis.width);
maxHeight.set(dis.height);
Log.showInfo(TAG, `initWindowManager maxWidth ${maxWidth.get()} maxHeight ${maxHeight.get()} minHeight ${minHeight.get()}`);
})
}
/**
* Set the window to the maximum size.
*
* @param {Object} callback - Callback function.
*/
setWindowMax(callback) {
Log.showInfo(TAG, 'enter setWindowMax =================');
Window.getTopWindow()
.then((windowData) => {
Log.showInfo(TAG, 'enter setWindowMin maxWidth =================' + maxWidth.get() + " minHeight " + minHeight.get());
windowData.resetSize(parseInt(maxWidth.get()), parseInt(maxHeight.get()))
.then((result) => {
Log.showInfo(TAG, result);
callback(result);
});
windowData.moveTo(0, 0)
.then((result) => {
Log.showInfo(TAG, result);
});
});
}
/**
* Set the window to the minimum size.
*
* @param {Object} callback - Callback function.
*/
setWindowMin(callback) {
Log.showInfo(TAG, 'enter setWindowMin =================');
Window.getTopWindow()
.then((windowData) => {
Log.showInfo(TAG, 'enter setWindowMin maxWidth =================' + maxWidth.get() + " minHeight " + minHeight.get());
windowData.resetSize(parseInt(maxWidth.get()), parseInt(minHeight.get()))
.then((result) => {
Log.showInfo(TAG, result);
callback(result);
});
});
}
/**
* Set the window to the minimum size.
*
* @param {Object} callback - Callback function.
*/
async initWindowMin(width, height, x, y) {
AppStorage.Set("showStatusBar", true);
Log.showInfo(TAG, 'enter initWindowMin =================');
Log.showInfo(TAG, 'width:' + width + ' height:' + height + ' x:' + x + ' y:' + y);
let abilityWindow = await Window.getTopWindow();
await abilityWindow.moveTo(parseInt(x), parseInt(y));
await abilityWindow.resetSize(parseInt(width), parseInt(height));
}
}
@@ -0,0 +1,119 @@
/*
* Copyright (c) 2021-2022 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 Window from "@ohos.window";
import Log from "./Log";
import EventManager from "./event/EventManager";
import { obtainLocalEvent } from "./event/EventUtil";
import { Rect } from "./Constants";
import createOrGet from "./SingleInstanceHelper";
export type WindowInfo = {
visibility: boolean;
rect: Rect;
};
export enum WindowType {
STATUS_BAR = "SystemUi_StatusBar",
NAVIGATION_BAR = "SystemUi_NavigationBar",
DROPDOWN_PANEL = "SystemUi_DropdownPanel",
NOTIFICATION_PANEL = "SystemUi_NotificationPanel",
CONTROL_PANEL = "SystemUi_ControlPanel",
VOLUME_PANEL = "SystemUi_VolumePanel",
BANNER_NOTICE = 'SystemUi_BannerNotice'
}
export const WINDOW_SHOW_HIDE_EVENT = "WindowShowHideEvent";
export const WINDOW_RESIZE_EVENT = "WindowResizeEvent";
type WindowHandle = typeof Window.Window;
const TAG = "WindowManager";
const SYSTEM_WINDOW_TYPE_MAP: { [key in WindowType]: number } = {
SystemUi_StatusBar: 2108,
SystemUi_NavigationBar: 2112,
SystemUi_DropdownPanel: 2109,
SystemUi_NotificationPanel: 2111,
SystemUi_ControlPanel: 2111,
SystemUi_VolumePanel: 2111,
SystemUi_BannerNotice: 2111,
};
const DEFAULT_WINDOW_INFO: WindowInfo = {
visibility: false,
rect: { left: 0, top: 0, width: 0, height: 0 },
};
/**
* Manage window size changes.
*/
class WindowManager {
mWindowInfos: Map<WindowType, WindowInfo> = new Map();
async createWindow(context: any, name: WindowType, rect: Rect, loadContent: string): Promise<WindowHandle> {
Log.showInfo(TAG, `createWindow name: ${name}, rect: ${JSON.stringify(rect)}, url: ${loadContent}`);
let winHandle = await Window.create(context, name, SYSTEM_WINDOW_TYPE_MAP[name]);
await winHandle.moveTo(rect.left, rect.top);
await winHandle.resetSize(rect.width, rect.height);
await winHandle.loadContent(loadContent);
this.mWindowInfos.set(name, { visibility: false, rect });
Log.showInfo(TAG, `create window[${name}] success.`);
return winHandle;
}
async resetSizeWindow(name: WindowType, rect: Rect): Promise<void> {
let window = await Window.find(name);
await window.moveTo(rect.left, rect.top);
await window.resetSize(rect.width, rect.height);
this.mWindowInfos.set(name, { ...(this.mWindowInfos.get(name) ?? DEFAULT_WINDOW_INFO), rect });
EventManager.publish(
obtainLocalEvent(WINDOW_RESIZE_EVENT, {
windowName: name,
rect,
})
);
Log.showInfo(TAG, `resize window[${name}] success, rect: ${JSON.stringify(rect)}.`);
}
async showWindow(name: WindowType): Promise<void> {
let window = await Window.find(name);
await window.show();
this.mWindowInfos.set(name, { ...(this.mWindowInfos.get(name) ?? DEFAULT_WINDOW_INFO), visibility: true });
EventManager.publish(
obtainLocalEvent(WINDOW_SHOW_HIDE_EVENT, {
windowName: name,
isShow: true,
})
);
Log.showInfo(TAG, `show window[${name}] success.`);
}
async hideWindow(name: WindowType): Promise<void> {
let window = await Window.find(name);
await window.hide();
this.mWindowInfos.set(name, { ...(this.mWindowInfos.get(name) ?? DEFAULT_WINDOW_INFO), visibility: false });
EventManager.publish(
obtainLocalEvent(WINDOW_SHOW_HIDE_EVENT, {
windowName: name,
isShow: false,
})
);
Log.showInfo(TAG, `hide window[${name}] success.`);
}
getWindowInfo(name: WindowType): WindowInfo | undefined {
return this.mWindowInfos.get(name);
}
}
let sWindowManager = createOrGet(WindowManager, TAG);
export default sWindowManager as WindowManager;
@@ -0,0 +1,69 @@
/*
* Copyright (c) 2021-2022 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 Log from '../Log';
const TAG = 'AbilityManager';
export default class AbilityManager {
static ABILITY_NAME_ENTRY = 'SystemUi_Entry';
static ABILITY_NAME_STATUS_BAR = 'SystemUi_StatusBar';
static ABILITY_NAME_NAVIGATION_BAR = 'SystemUi_NavigationBar';
static ABILITY_NAME_VOLUME_PANEL = 'SystemUi_VolumePanel';
static ABILITY_NAME_NOTIFICATION_MANAGEMENT = 'SystemUi_NotificationManagement';
static ABILITY_NAME_DROPDOWN_PANEL = 'SystemUi_DropdownPanel';
static ABILITY_NAME_NOTIFICATION_PANEL = 'SystemUi_NotificationPanel';
static ABILITY_NAME_CONTROL_PANEL = 'SystemUi_ControlPanel';
static ABILITY_NAME_BANNER_NOTICE = 'SystemUi_BannerNotice';
static ABILITY_NAME_OWNER_WANT = 'Owner_Want';
static setContext(abilityName: string, context) {
Log.showInfo(TAG, `setContext, abilityName: ${abilityName}`);
globalThis[abilityName + '_Context'] = context;
}
static getContext(abilityName?: string) {
Log.showInfo(TAG, `getContext, abilityName: ${abilityName}`);
if (!abilityName) {
abilityName = AbilityManager.ABILITY_NAME_ENTRY;
}
return globalThis[abilityName + '_Context'];
}
static setAbilityData(abilityName, key, data) {
Log.showInfo(TAG, `setAbilityData, abilityName: ${abilityName} key: ${key} data: ${JSON.stringify(data)}`);
globalThis[abilityName + '_data_' + key] = data;
}
static getAbilityData(abilityName, key) {
Log.showInfo(TAG, `getAbilityData, abilityName: ${abilityName} key: ${key} `);
return globalThis[abilityName + '_data_' + key];
}
static startAbility(want, callback?: Function) {
Log.showInfo(TAG, `startAbility, want: ${JSON.stringify(want)}`);
let context = AbilityManager.getContext();
context.startAbility(want).then(() => {
Log.showInfo(TAG, `startAbility, then`);
if (callback) {
callback(null);
}
}).catch((error) => {
Log.showInfo(TAG, `startAbility, error: ${JSON.stringify(error)}`);
callback(error);
})
}
}
@@ -1,38 +0,0 @@
/*
* 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 BundleMgr from '@ohos.bundle';
import Resmgr from '@ohos.resourceManager';
import Log from '../Log.ets';
const TAG = 'BRManager';
export default class BundleManager {
static async getResourceManager(tag, bundleName, then?: Function) {
Log.showInfo(TAG, `getResourceManager from: ${tag}`);
if (!then) {
return await Resmgr.getResourceManager(bundleName);
}
Resmgr.getResourceManager(bundleName).then(then);
}
static async getBundleInfo(tag, bundleName, getInfo, then?: Function) {
Log.showInfo(TAG, `getBundleInfo from: ${tag}`);
if (!then) {
return await BundleMgr.getBundleInfo(bundleName, getInfo);
}
BundleMgr.getBundleInfo(bundleName, getInfo).then(then);
}
}
@@ -0,0 +1,38 @@
/*
* Copyright (c) 2021-2022 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 BundleMgr from "@ohos.bundle";
import Context from "application/ServiceExtensionContext";
import Log from "../Log";
import SwitchUserManager from "../SwitchUserManager";
const TAG = "BRManager";
export default class BundleManager {
static async getResourceManager(tag: string, context: Context, bundleName: string) {
Log.showInfo(TAG, `getResourceManager from: ${tag}`);
let bundleContext = await context.createBundleContext(bundleName);
return await bundleContext.resourceManager;
}
static async getBundleInfo(tag: string, bundleName: string, getInfo:
any, requestId?: number) {
let userInfo = {
userId: requestId ?? (await SwitchUserManager.getInstance().getCurrentUserInfo()).userId,
};
Log.showInfo(TAG, `getBundleInfo from: ${tag}, userId: ${userInfo.userId}`);
return await BundleMgr.getBundleInfo(bundleName, getInfo, userInfo);
}
}
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2021 Huawei Device Co., Ltd.
* Copyright (c) 2021-2022 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
@@ -14,7 +14,7 @@
*/
import FeatureAbility from '@ohos.ability.featureAbility';
import Log from '../Log.ets';
import Log from '../Log';
const TAG = 'FeatureAbilityManager';
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2021 Huawei Device Co., Ltd.
* Copyright (c) 2021-2022 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
@@ -15,7 +15,7 @@
//import { NotificationSubscriber } from './notification/notificationSubscriber';
import Notification from '@ohos.notification';
import Log from '../Log.ets';
import Log from '../Log';
const TAG = 'NotificationManager';
@@ -0,0 +1,97 @@
/*
* Copyright (c) 2021-2022 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 commonEvent from "@ohos.commonEvent";
import { CommonEventData } from "commonEvent/commonEventData";
import EventManager from "../event/EventManager";
import Log from "../Log";
import { SCREEN_CHANGE_EVENT } from "../ScreenLockManager";
export type CommonEventManager = {
subscriberCommonEvent: () => Promise<void>;
unSubscriberCommonEvent: () => void;
applyPolicy: (policys: Array<POLICY>) => void;
release: () => void;
};
export enum POLICY {
SCREEN_POLICY = "screenOnOffPolicy",
}
type ClearPolicy = () => void;
type InnerManager = { subscriberCommonEvent: () => void; unSubscriberCommonEvent: () => void };
const policyMap: { [key in POLICY]: (manager: InnerManager) => ClearPolicy } = {
screenOnOffPolicy: ScreenPolicy,
};
export function getCommonEventManager(
tag: string,
subscribeInfos: { events: Array<string> },
commonEventCallback: (data: CommonEventData) => void,
subscribeStateChange?: (isSubscribe: boolean) => void
): CommonEventManager {
const TAG = `CommonEvent_${tag}`;
const SUBSCRIBE_INFOS = subscribeInfos;
let unSubcribers: Array<() => void> = [];
let policyClearCb: Map<POLICY, ClearPolicy> | undefined = undefined;
async function subscriberCommonEvent() {
Log.showInfo(TAG, "registerSubscriber start");
let subscriber = await commonEvent.createSubscriber(SUBSCRIBE_INFOS);
commonEvent.subscribe(subscriber, (err, data) => {
if (err.code != 0) {
Log.showError(TAG, `Can't handle common event, err: ${JSON.stringify(err)}`);
return;
}
Log.showInfo(TAG, `handle common event: ${data.event}`);
commonEventCallback(data);
});
unSubcribers.push(() => commonEvent.unsubscribe(subscriber));
subscribeStateChange && subscribeStateChange(true);
Log.showInfo(TAG, `registerSubscriber success, size: ${unSubcribers.length}`);
}
function unSubscriberCommonEvent() {
Log.showInfo(TAG, `UnSubcribers size: ${unSubcribers.length}`);
unSubcribers.forEach((unsubscribe) => unsubscribe());
unSubcribers.length = 0;
subscribeStateChange && subscribeStateChange(false);
}
function applyPolicy(policys: Array<POLICY>) {
const innerManager = { subscriberCommonEvent, unSubscriberCommonEvent };
policyClearCb = policyClearCb ?? new Map();
policys.forEach((policy) => {
if (policyClearCb) {
!policyClearCb.has(policy) && policyClearCb.set(policy, policyMap[policy](innerManager));
Log.showInfo(TAG, `apply policy: ${policy}`);
}
});
}
function release() {
policyClearCb?.forEach((cb) => cb());
policyClearCb?.clear();
unSubscriberCommonEvent();
}
return { subscriberCommonEvent, unSubscriberCommonEvent, applyPolicy, release };
}
function ScreenPolicy(manager: InnerManager): ClearPolicy {
return EventManager.subscribe(SCREEN_CHANGE_EVENT, (isScreenOn: boolean) => {
isScreenOn ? manager.subscriberCommonEvent() : manager.unSubscriberCommonEvent();
});
}
@@ -0,0 +1,76 @@
/*
* Copyright (c) 2022 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 Log from "../Log";
export type Callback = (args: any) => void;
const TAG = "EventBus";
export interface EventBus<T> {
on(event: T | T[], cb: Callback): () => void;
once(event: T, cb: Callback): () => void;
off(event: T | T[] | undefined, cb: Callback): void;
emit(event: T, args: any): void;
}
export function createEventBus<T extends string>(): EventBus<T> {
let _cbs: { [key: string]: Set<Callback> } = {};
function on(events: T | T[], cb: Callback): () => void {
if (Array.isArray(events)) {
events.forEach((e) => on(e, cb));
} else {
(_cbs[events] || (_cbs[events] = new Set())).add(cb);
Log.showInfo(TAG, `add event[${events}] callback, size: ${_cbs[events]?.size}`);
}
return () => off(events, cb);
}
function once(event: T, cb: Callback): () => void {
let newCallback = (args: any) => {
cb(args);
removeSelf();
};
function removeSelf() {
off(event, newCallback);
}
return on(event, newCallback);
}
function off(event: T | T[] | undefined, cb: Callback) {
if (!event) {
_cbs = {};
Log.showInfo(TAG, `remove event[${event}] all callback`);
return;
}
if (Array.isArray(event)) {
event.forEach((e) => off(e, cb));
return;
}
_cbs[event]?.delete(cb);
Log.showInfo(TAG, `remove event[${event}] callback, size: ${_cbs[event]?.size}`);
}
function emit(event: T, args: any) {
_cbs[event]?.forEach((cb) => cb(args));
}
function stickyEmit(event: T, argument: any[]) {}
return {
on,
once,
off,
emit,
};
}
@@ -0,0 +1,94 @@
/*
* Copyright (c) 2022 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 ServiceExtensionContext from "application/ServiceExtensionContext";
import Log from "../Log";
import createOrGet from "../SingleInstanceHelper";
import { EventParser, START_ABILITY_EVENT, Event, LocalEvent } from "./EventUtil";
import { Callback, createEventBus, EventBus } from "./EventBus";
export type unsubscribe = () => void;
export type Events = string | string[];
const TAG = "EventManager";
class EventManager {
mEventBus: EventBus<string>;
eventParser: EventParser;
mContext: ServiceExtensionContext | undefined;
constructor() {
this.mEventBus = createEventBus();
this.eventParser = {
local: this.publishLocalEvent,
ability: this.startAbility,
commonEvent: this.publishCommonEvent,
remote: this.publishRemoteEvent,
};
}
setContext(ctx: ServiceExtensionContext) {
this.mContext = ctx;
}
publish(event: Event): boolean {
return this.eventParser[event.target].call(this, event.data);
}
subscribe(eventType: Events, callback: Callback): unsubscribe {
return this.mEventBus.on(eventType, callback);
}
subscribeOnce(eventType: string, callback: Callback): unsubscribe {
return this.mEventBus.once(eventType, callback);
}
private publishLocalEvent(data: LocalEvent): boolean {
Log.showInfo(TAG, `publish localEvent type: ${data.eventName}`);
if (data.eventName) {
this.mEventBus.emit(data.eventName, data.args);
return true;
}
return false;
}
private startAbility(data: { [key: string]: any }): boolean {
Log.showInfo(TAG, `start Ability: ${data.abilityName}`);
if (data.bundleName && data.abilityName && this.mContext) {
this.mEventBus.emit(START_ABILITY_EVENT, { abilityName: data.abilityName });
this.mContext.startAbility({
bundleName: data.bundleName,
abilityName: data.abilityName,
parameters: data.args??undefined
});
return true;
}
return false;
}
private publishRemoteEvent(data: { [key: string]: any }): boolean {
// todo publish to remote device
return false;
}
private publishCommonEvent(data: { [key: string]: any }): boolean {
// todo publish commonEvent to other app
return false;
}
}
let sEventManager = createOrGet(EventManager, TAG);
export default sEventManager as EventManager;
@@ -0,0 +1,81 @@
/*
* Copyright (c) 2022 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 Log from "../Log";
export type EventTarget = "local" | "remote" | "ability" | "commonEvent";
export type Event = {
target: EventTarget;
data: { [key: string]: any };
};
export type EventParser = {
[key in EventTarget]: (data: any) => boolean;
};
export type LocalEvent = {
eventName: string;
args: any;
};
export const START_ABILITY_EVENT = "startAbilityEvent";
export const PUBLISH_COMMON_EVENT = "publishCommonEvent";
const TAG = "EventUtil";
const LOCAL_EVENT_TYPE = "local";
const START_ABILITY_TYPE = "ability";
export function obtainLocalEvent(event: string, args: any): Event & { data: LocalEvent } {
return {
target: LOCAL_EVENT_TYPE,
data: {
eventName: event,
args,
},
};
}
export function obtainStartAbility(bundleName: string, abilityName: string, args?: any): Event {
return {
target: START_ABILITY_TYPE,
data: {
bundleName,
abilityName,
args
},
};
}
export function parseEventString(eventString: string | undefined): Event | undefined {
// string must be "local=eventName|args" or "ability=bundleName|abilityName"
if (!eventString) {
return;
}
let [eventType, eventData] = eventString.split("=");
if (eventType == LOCAL_EVENT_TYPE && eventData) {
let [localEventName, args] = eventData.split("|");
if (localEventName) {
Log.showDebug(TAG, `parseEventData name:${localEventName}, args: ${args}`);
return obtainLocalEvent(localEventName, args);
}
}
if (eventType == START_ABILITY_TYPE && eventData) {
let [bundleName, abilityName] = eventData.split("|");
if (bundleName && abilityName) {
Log.showDebug(TAG, `parseEventData bundleName:${bundleName}, abilityName: ${abilityName}`);
return obtainStartAbility(bundleName, abilityName);
}
}
Log.showError(TAG, `Can't parse event data: ${eventString}`);
return undefined;
}
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2021 Huawei Device Co., Ltd.
* Copyright (c) 2021-2022 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
@@ -12,7 +12,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import Log from '../Log.ets';
import Log from '../Log';
const STATUS_BAR_MIN_HEIGHT = 24
const STATUS_BAR_COEFFICIENT = 1.0
@@ -1,114 +0,0 @@
/*
* 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 Log from '../default/Log.ets';
import worker from '@ohos.worker';
import Constants, {obtainMsg} from './common/Constants.ets';
const TAG = 'PluginDataSourceAdapter';
const WORKER_JS_URL = 'workers/PluginDataSourceWorker.js';
export default class PluginDataSourceAdapter {
mWorker: any;
mName: any;
mListener: any;
constructor(name: String) {
Log.showInfo(TAG, `constructor, name: ${name}`)
this.mName = name;
this.mWorker = new worker.Worker(WORKER_JS_URL, {
type: "classic", name: this.mName
});
this.mWorker.onmessage = this.onMessage.bind(this);
this.mWorker.onmessageerror = this.onMessageError.bind(this);
this.mWorker.onexit = this.onExit.bind(this);
this.mWorker.onerror = this.onError.bind(this);
}
initDataSource(configs) {
Log.showInfo(TAG, `initDataSource, configs: ${JSON.stringify(configs)}`)
this.mWorker.postMessage(obtainMsg(Constants.INIT_CONFIG, configs));
}
loadData(userId) {
Log.showInfo(TAG, `loadData`)
this.mWorker.postMessage(obtainMsg(Constants.LOAD_DATA, userId));
}
clearAll() {
Log.showInfo(TAG, `clearAll`)
this.mWorker.postMessage(obtainMsg(Constants.CLEAR_ALL, {}));
}
onMessage(msg) {
Log.showInfo(TAG, `onMessage, msg: ${JSON.stringify(msg)}`)
let data = msg.data;
switch (data.action) {
case Constants.INIT_FINISH:
this.onInitFinish();
break;
case Constants.ADD_ITEM:
this.onItemAdd(data.data);
break;
case Constants.REMOVE_ITEM:
this.onItemRemove(data.data);
break;
default:
Log.showError(TAG, `unknown type: ${JSON.stringify(msg)}`)
}
}
onInitFinish() {
Log.showInfo(TAG, `onInitFinish`)
this.mListener.initFinish();
}
onItemAdd(itemData) {
Log.showInfo(TAG, `onItemAdd, itemData: ${JSON.stringify(itemData)}`)
this.mListener.addItem(itemData);
}
onItemRemove(itemData) {
Log.showInfo(TAG, `onItemRemove, itemData: ${JSON.stringify(itemData)}`)
this.mListener.removeItem(itemData);
}
registerListener(listener: {
'initFinish': Function,
'addItem': Function,
'removeItem': Function
}) {
Log.showInfo(TAG, `registerListener`)
this.mListener = listener;
}
unregisterListener() {
Log.showInfo(TAG, `mListener`)
this.mListener = null;
}
onMessageError(event) {
Log.showInfo(TAG, `mWorker.onmessageerror, event: ${event}`)
};
onExit(code) {
Log.showInfo(TAG, `mWorker.onexit, code: ${code}`)
};
onError(err) {
Log.showInfo(TAG, `mWorker.onerror, err: ${JSON.stringify(err)}`)
};
}
@@ -0,0 +1,130 @@
/*
* Copyright (c) 2021-2022 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 worker from "@ohos.worker";
import Log from "../default/Log";
import BundleManager from "../default/abilitymanager/bundleManager";
import Constants, { ItemComponentData, obtainMsg, RootConfigInfo } from "./common/Constants";
import Context from "application/ServiceExtensionContext";
export type pluginWorkerListener = {
initFinish: () => void;
onItemAdd: (data: ItemComponentData) => void;
onItemRemove: (data: ItemComponentData) => void;
};
const TAG = "PluginDataSourceAdapter";
const WORKER_JS_URL = "workers/PluginDataSourceWorker.js";
export default class PluginDataSourceAdapter {
mContext: Context;
mWorker: any;
mName: string;
mListener: pluginWorkerListener;
constructor(name: string, context: Context, listener: pluginWorkerListener) {
Log.showInfo(TAG, `constructor, name: ${name}`);
this.mName = name;
this.mContext = context;
this.mListener = listener;
this.mWorker = new worker.Worker(WORKER_JS_URL, {
type: "classic",
name: this.mName,
});
this.mWorker.onmessage = this.onMessage.bind(this);
this.mWorker.onmessageerror = this.onMessageError.bind(this);
this.mWorker.onexit = this.onExit.bind(this);
this.mWorker.onerror = this.onError.bind(this);
}
initDataSource(configs: RootConfigInfo) {
Log.showInfo(TAG, `initDataSource, configs: ${JSON.stringify(configs)}`);
this.mWorker.postMessage(obtainMsg(Constants.INIT_CONFIG, configs));
}
loadData(userId: number) {
Log.showInfo(TAG, `loadData`);
this.mWorker.postMessage(obtainMsg(Constants.LOAD_DATA, userId));
}
clearAll() {
Log.showInfo(TAG, `clearAll`);
this.mWorker.postMessage(obtainMsg(Constants.CLEAR_ALL, {}));
}
onMessage(msg: { data: any }) {
Log.showInfo(TAG, `onMessage, msg: ${JSON.stringify(msg)}`);
let data = msg.data;
switch (data.action) {
case Constants.INIT_FINISH:
this.onInitFinish();
break;
case Constants.ADD_ITEM:
this.onItemAdd(data.data);
break;
case Constants.REMOVE_ITEM:
this.onItemRemove(data.data);
break;
default:
Log.showError(TAG, `unknown type: ${JSON.stringify(msg)}`);
}
}
onInitFinish() {
Log.showInfo(TAG, `onInitFinish`);
this.mListener.initFinish();
}
async onItemAdd(itemData: ItemComponentData) {
Log.showInfo(TAG, `onItemAdd, itemData: ${JSON.stringify(itemData)}`);
itemData.label && (itemData.label = decodeURIComponent(itemData.label));
if (itemData.label && itemData.iconUrl) {
this.mListener.onItemAdd(itemData);
return;
}
let manager = await BundleManager.getResourceManager(TAG, this.mContext, itemData.bundleName);
Log.showInfo(TAG, `${itemData.id} Can't find label or icon, fetch data from ${manager}`);
if (manager) {
Promise.all([
itemData.iconUrl ?? manager.getMediaBase64(itemData.abilityIconId),
itemData.label ?? manager.getString(itemData.abilityLabelId),
])
.then(([iconValue, labelValue]) => {
iconValue && (itemData.iconUrl = iconValue);
labelValue && (itemData.label = labelValue);
this.mListener.onItemAdd(itemData);
})
.catch((err) => Log.showError(TAG, `Can't get bundle info, err: ${JSON.stringify(err)}`));
}
}
onItemRemove(itemData: ItemComponentData) {
Log.showInfo(TAG, `onItemRemove, itemData: ${JSON.stringify(itemData)}`);
this.mListener.onItemRemove(itemData);
}
onMessageError(event: any) {
Log.showInfo(TAG, `mWorker.onmessageerror, event: ${event}`);
}
onExit(code: any) {
Log.showInfo(TAG, `mWorker.onexit, code: ${code}`);
}
onError(err: any) {
Log.showInfo(TAG, `mWorker.onerror, err: ${JSON.stringify(err)}`);
}
}
@@ -1,62 +0,0 @@
/*
* 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 Log from '../default/Log.ets';
import SourceLoaderFactory from './sourceloader/SourceLoaderFactory.ets';
import SourceLoader from './sourceloader/SourceLoader.ets';
const TAG = "PluginDataSourceManager";
export default class PluginDataSourceManager {
mLoaders: Map<String, SourceLoader> = new Map();
initDataSource(configs) {
Log.showInfo(TAG, `initDataSource, configs: ${JSON.stringify(configs)}`);
let factory = new SourceLoaderFactory({
'add': this.onItemAdd.bind(this),
'remove': this.onItemRemove.bind(this)
});
for (let pluginType in configs) {
factory.getSourceLoader(pluginType, configs[pluginType], (sourceLoader) => {
Log.showInfo(TAG, `getSourceLoader callback`);
if (sourceLoader instanceof SourceLoader) {
this.mLoaders.set(pluginType, sourceLoader);
Log.showInfo(TAG, `getSourceLoader callback, plugin: ${pluginType} ${this.mLoaders.get(pluginType)}`);
}
})
}
}
onItemAdd(itemData) {
Log.showInfo(TAG, `onItemAdd, itemData: ${JSON.stringify(itemData)}`);
}
onItemRemove(itemData) {
Log.showInfo(TAG, `onItemRemove, itemData: ${JSON.stringify(itemData)}`);
}
clearAll() {
Log.showInfo(TAG, `clearAll`);
this.mLoaders.forEach((sourceLoader) => sourceLoader.stopLoad());
this.mLoaders.clear();
}
loadData(userId) {
Log.showInfo(TAG, `loadData`);
this.mLoaders.forEach((sourceLoader) => {
sourceLoader.loadData(userId);
});
}
}
@@ -0,0 +1,118 @@
/*
* Copyright (c) 2021-2022 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 Log from "../default/Log";
import SourceLoaderFactory from "./sourceloader/SourceLoaderFactory";
import SourceLoader from "./sourceloader/SourceLoader";
import { FilterData, ItemComponentData, RootConfigInfo } from "./common/Constants";
import {
AbilityInfoWithId,
BundleEventType,
ListenerHandle,
queryAbility,
registerBundleListener,
} from "./common/BundleParseUtil";
import { AbilityInfo } from "bundle/abilityInfo";
export type PluginListener = {
onItemAdd: (itemData: ItemComponentData) => void;
onItemRemove: (itemData: ItemComponentData) => void;
};
const TAG = "PluginDataSourceManager";
const INVALID_USERID = -1;
export default class PluginDataSourceManager {
mAction: string = "";
mUserId: number = INVALID_USERID;
mListenerHandle: ListenerHandle | undefined = undefined;
mFilterDatas: Map<string, string> = new Map();
mLoaders: Map<string, SourceLoader> = new Map();
mFactory: SourceLoaderFactory;
constructor(listener: PluginListener) {
this.mFactory = new SourceLoaderFactory({
add: listener.onItemAdd,
remove: listener.onItemRemove,
});
}
initDataSource(configs: RootConfigInfo) {
Log.showInfo(TAG, `initDataSource, configs: ${JSON.stringify(configs)}`);
this.mAction = configs.action;
configs.filterDatas.forEach((data: FilterData) => this.mFilterDatas.set(data.abilityName, data.id));
for (let pluginType in configs.loaderConfig) {
const sourceLoader = this.mFactory.getSourceLoader(pluginType, configs.loaderConfig[pluginType]);
if (sourceLoader instanceof SourceLoader) {
this.mLoaders.set(pluginType, sourceLoader);
Log.showInfo(TAG, `getSourceLoader plugin: ${pluginType}, loader${this.mLoaders.get(pluginType)}`);
}
}
Log.showInfo(TAG, `action:${this.mAction}, filterData: ${JSON.stringify(this.mFilterDatas)}`);
registerBundleListener(this, (handle) => {
this.mListenerHandle = handle;
});
}
async onBundleNotify(bundleName: string, event: BundleEventType) {
Log.showInfo(TAG, `onBundleNotify, bundleName: ${bundleName}, event: ${event}`);
if (event == BundleEventType.BUNDLE_CHANGE || event == BundleEventType.BUNDLE_REMOVE) {
this.mLoaders.forEach((loader) => loader.onBundleRemove(bundleName));
}
if (event == BundleEventType.BUNDLE_CHANGE || event == BundleEventType.BUNDLE_ADD) {
let abilityInfos = await queryAbility(this.mAction, this.mUserId, bundleName);
Log.showInfo(TAG, `abilityInfos: ${JSON.stringify(abilityInfos)}`);
abilityInfos.forEach((info) => this.notifyAbilityAdd(info));
}
}
clearAll() {
Log.showInfo(TAG, `clearAll`);
this.unregisterListener();
this.mLoaders.forEach((sourceLoader) => sourceLoader.clearData());
}
async loadData(userId: number) {
if (this.mUserId != userId) {
this.mUserId = userId;
this.mLoaders.forEach((sourceLoader) => sourceLoader.clearData());
let abilityInfos = await queryAbility(this.mAction, this.mUserId);
abilityInfos.forEach((info) => this.notifyAbilityAdd(info));
}
this.mLoaders.forEach((sourceLoader) => sourceLoader.reloadData(this.mUserId));
}
private notifyAbilityAdd(info: AbilityInfo) {
let itemId = this.mFilterDatas.get(info.name);
if (!itemId) {
Log.showInfo(TAG, `notifyAbilityAdd, can't find itemId, ability:${info.name}`);
return;
}
let abilityInfo: AbilityInfoWithId = {
...info,
itemId: itemId,
};
if (!abilityInfo.metaData || !abilityInfo.metaData.length) {
Log.showInfo(TAG, `Can't find metaData, abilityId: ${abilityInfo.name}`);
return;
}
this.mLoaders.forEach((loader) => loader.onAbilityAdd(abilityInfo));
}
private unregisterListener() {
this.mListenerHandle?.unRegister();
this.mListenerHandle = undefined;
}
}
@@ -0,0 +1,116 @@
/*
* Copyright (c) 2022 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 bundleManager from "@ohos.bundle";
import commonEvent from "@ohos.commonEvent";
import { AbilityInfo } from "bundle/abilityInfo";
import Log from "../../default/Log";
export type AbilityInfoWithId = AbilityInfo & { itemId: string };
export type BundleListener = {
onBundleNotify: (bundleName: string, event: BundleEventType) => void;
};
export type ListenerHandle = {
unRegister: () => void;
};
export type PluginData = {
[key: string | number]: any;
};
export enum BundleEventType {
BUNDLE_ADD,
BUNDLE_CHANGE,
BUNDLE_REMOVE,
UNKNOWN_EVENT,
}
const TAG = "SourceLoader-BundleParseUtil";
const DEFAULT_BUNDLE_FLAG =
bundleManager.BundleFlag.GET_ABILITY_INFO_WITH_METADATA | bundleManager.BundleFlag.GET_ABILITY_INFO_WITH_PERMISSION;
const BUNDLE_SUBSCRIBE_INFO = {
events: [
commonEvent.Support.COMMON_EVENT_PACKAGE_ADDED,
commonEvent.Support.COMMON_EVENT_PACKAGE_REMOVED,
commonEvent.Support.COMMON_EVENT_PACKAGE_CHANGED,
],
};
export async function queryAbility(action: string, userId: number, bundleName?: string): Promise<Array<AbilityInfo>> {
if (bundleName) {
return await bundleManager.queryAbilityByWant(
{
action: action,
bundleName: bundleName,
},
DEFAULT_BUNDLE_FLAG,
userId
);
}
return await bundleManager.queryAbilityByWant({ action: action }, DEFAULT_BUNDLE_FLAG, userId);
}
export function filterAbilityInfo(info: AbilityInfoWithId, filterKey: string): PluginData | undefined {
let pluginDatas = info.metaData.filter((data) => data.name == filterKey);
if (!pluginDatas.length) {
Log.showDebug(TAG, `filterKey: ${filterKey}, metaData: ${JSON.stringify(info.metaData.values)}`);
return undefined;
}
let pluginData = JSON.parse("{" + pluginDatas[0].extra + "}");
if (!pluginData) {
Log.showError(TAG, `Can't parse pluginData: ${pluginDatas[0]} filterKey: ${filterKey}`);
return undefined;
}
Log.showInfo(TAG, `createItemComponentData, pluginData: ${JSON.stringify(pluginData)}`);
return pluginData;
}
export function registerBundleListener(listener: BundleListener, callback: (handle: ListenerHandle) => void) {
commonEvent.createSubscriber(BUNDLE_SUBSCRIBE_INFO, (err, handle) => {
Log.showDebug(TAG, `registerBundleListener, err: ${JSON.stringify(err)}, handle: ${handle}`);
if (err.code != 0) {
Log.showError(TAG, `Can't regitser bundle subscribe, err: ${JSON.stringify(err)}`);
return;
}
commonEvent.subscribe(handle, (err, data) => {
Log.showDebug(TAG, `bundle change, err: ${JSON.stringify(err)} data: ${JSON.stringify(data)}`);
if (err.code != 0) {
Log.showError(TAG, `Can't handle bundle change, err: ${JSON.stringify(err)}`);
return;
}
let event = BundleEventType.UNKNOWN_EVENT;
switch (data.event) {
case commonEvent.Support.COMMON_EVENT_PACKAGE_ADDED:
event = BundleEventType.BUNDLE_ADD;
break;
case commonEvent.Support.COMMON_EVENT_PACKAGE_CHANGED:
event = BundleEventType.BUNDLE_CHANGE;
break;
case commonEvent.Support.COMMON_EVENT_PACKAGE_REMOVED:
event = BundleEventType.BUNDLE_REMOVE;
break;
default:
Log.showError(TAG, `unknow event: ${event}`);
}
listener.onBundleNotify(data.bundleName ?? "unkown", event);
});
callback({
unRegister: () => {
commonEvent.unsubscribe(handle, () => {
Log.showInfo(TAG, `unRegister bundle info listener, handle: ${handle}`);
});
},
});
});
}
@@ -1,58 +0,0 @@
/*
* 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 class Constants {
static INIT_CONFIG = "initConfig";
static INIT_FINISH = "initFinish";
static CLEAR_ALL = "clearAll";
static ADD_ITEM = "addItem";
static REMOVE_ITEM = "removeItem";
static LOAD_DATA = "loadData";
static DEFAULT_USER_ID = 0;
static DEFAULT_BUNDLE_FLAG = 0x00000020 | 0x00000008;
}
export enum PluginType {
SIMPLE = 1,
OBSERVER = 2,
LISTENER = 3,
}
export function obtainMsg(action, data) {
return { "action": action, "data": data };
}
export class ItemComponentData {
id: string;
pluginType: number;
deviceId: string;
bundleName: string;
abilityName: string;
abilityLabelId: number;
abilityIconId: number;
label: string;
iconUrl: Resource | string;
template?: string;
state?: any;
actionData?: ActionData;
}
export class ActionData {
clickAction?: string;
longClickAction?: string;
launchType?: number;
pluginData?: any;
extra?: any;
}
@@ -0,0 +1,76 @@
/*
* Copyright (c) 2021-2022 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 { Event } from "../../default/Event/EventUtil";
export default class Constants {
static INIT_CONFIG = "initConfig";
static INIT_FINISH = "initFinish";
static CLEAR_ALL = "clearAll";
static ADD_ITEM = "addItem";
static REMOVE_ITEM = "removeItem";
static LOCAL_DEVICE = "local";
static LOAD_DATA = "loadData";
}
export type FilterData = {
id: string;
abilityName: string;
};
export type RootConfigInfo = {
action: string;
filterDatas: FilterData[];
loaderConfig: {
[key in any]: LoaderConfigInfo;
};
};
export type LoaderConfigInfo = {
[key: string]: any;
};
export enum PluginType {
META = 1,
DATA_ABILITY = 2,
PLUGIN_COMPONENT = 3,
}
export function obtainMsg(action: string, data: any) {
return { action: action, data: data };
}
export type ItemComponentData = {
id: string;
pluginType: number;
deviceId: string;
bundleName: string;
abilityName: string;
abilityLabelId: number;
abilityIconId: number;
label?: string;
iconUrl?: Resource | string;
template?: string;
state?: any;
actionData?: ActionData;
}
export class ActionData {
clickAction?: Event;
longClickAction?: Event;
launchType?: number;
pluginData?: any;
extra?: any;
}
@@ -1,216 +0,0 @@
/*
* 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 bundleManager from "@ohos.bundle";
import commonEvent from '@ohos.commonEvent';
import Log from '../../default/Log.ets';
import CheckEmptyUtils from '../../default/CheckEmptyUtils.ets';
import SourceLoader from './SourceLoader.ets';
import Constants, {ItemComponentData, ActionData} from '../common/Constants.ets';
const TAG = "BaseMetaSourceLoader";
let mCommonEventSubscribeInfo = {
events: [
commonEvent.Support.COMMON_EVENT_PACKAGE_ADDED,
commonEvent.Support.COMMON_EVENT_PACKAGE_REMOVED,
commonEvent.Support.COMMON_EVENT_PACKAGE_CHANGED
]
};
export default abstract class BaseMetaSourceLoader extends SourceLoader {
mAction: string = null;
mPermission: string = null;
mFilterIds: string[] = null;
mPluginType: number = null;
mItemComponentDatas: ItemComponentData[] = [];
mCommonEventSubscriber = null;
mUserId: string = null;
constructor(config, channel, pluginType) {
super(channel);
Log.showInfo(TAG, `constructor, config: ${JSON.stringify(config)} channel: ${channel} pluginType: ${pluginType}`)
this.mPluginType = pluginType;
this.initSourceLoader(config);
}
initSourceLoader(config) {
Log.showInfo(TAG, `init loader, config: ${JSON.stringify(config)}`)
this.mAction = config.action;
this.mPermission = config.permission;
this.mFilterIds = config.filterIds;
Log.showInfo(TAG, `init loader, mCommonEventSubscribeInfo: ${JSON.stringify(mCommonEventSubscribeInfo)}`)
commonEvent.createSubscriber(
mCommonEventSubscribeInfo,
this.createCommonEventSubscriberCallBack.bind(this)
);
}
stopLoad() {
Log.showInfo(TAG, `stop loader`)
this.unRegisterCommonEventListener();
this.removeAllItemComponentData();
}
loadData(userId) {
Log.showInfo(TAG, `load loader userId = ` + userId)
this.mUserId = userId;
this.removeAllItemComponentData();
this.addAbilityItemComponentData({
"action": this.mAction
});
}
createCommonEventSubscriberCallBack(err, data) {
Log.showInfo(TAG, `createCommonEventSubscriberCallBack, err: ${JSON.stringify(err)}`);
if (err.code != 0) {
return;
}
this.mCommonEventSubscriber = data;
commonEvent.subscribe(this.mCommonEventSubscriber, this.procCommonEventSubscriberCallBack.bind(this));
}
procCommonEventSubscriberCallBack(err, data) {
Log.showInfo(TAG, `procCommonEventSubscriberCallBack, err: ${JSON.stringify(err)} data: ${JSON.stringify(data)}`);
if (err.code != 0) {
return;
}
let event = data.event;
let bundleName = data.bundleName;
if (event == commonEvent.Support.COMMON_EVENT_PACKAGE_CHANGED || event == commonEvent.Support.COMMON_EVENT_PACKAGE_REMOVED) {
this.removeItemComponentData(bundleName);
}
if (event == commonEvent.Support.COMMON_EVENT_PACKAGE_ADDED || event == commonEvent.Support.COMMON_EVENT_PACKAGE_CHANGED) {
this.addAbilityItemComponentData({
"bundleName": bundleName,
"action": this.mAction
});
}
}
unRegisterCommonEventListener() {
Log.showInfo(TAG, 'unRegisterCommonEventListener')
commonEvent.unsubscribe(this.mCommonEventSubscriber, () => {
Log.showInfo(TAG, 'unRegisterCommonEventListener unregister Listener ===============');
});
}
removeAllItemComponentData(): void{
Log.showInfo(TAG, `removeAllItemComponentData`);
for (let itemComponentData of this.mItemComponentDatas) {
this.removeItem(itemComponentData);
}
this.mItemComponentDatas = [];
}
addAbilityItemComponentData(want): void{
Log.showInfo(TAG, `addAbilityItemComponentData, want: ${JSON.stringify(want)} BundleFlag: ${Constants.DEFAULT_BUNDLE_FLAG}this.mUserId:${this.mUserId}`);
bundleManager.queryAbilityByWant(want, Constants.DEFAULT_BUNDLE_FLAG, this.mUserId ? this.mUserId : Constants.DEFAULT_USER_ID,
(err, abilityInfos) => {
Log.showInfo(TAG, `addAbilityItemComponentData queryAbilityByWant callback, want: ${JSON.stringify(want)} err: ${JSON.stringify(err)} abilityInfos: ${abilityInfos.length} ${JSON.stringify(abilityInfos)} `)
if (err != 0) {
return;
}
for (let abilityInfo of abilityInfos) {
this.createItemComponentData(abilityInfo, (itemComponentData) => {
this.addItemComponentData(itemComponentData);
});
}
Log.showInfo(TAG, `addAbilityItemComponentData, mItemComponentDatas: ${JSON.stringify(this.mItemComponentDatas)} `)
});
}
createItemComponentData(abilityInfo, callback: Function): void{
Log.showInfo(TAG, `createItemComponentData, abilityInfo: ${JSON.stringify(abilityInfo)}`);
let pluginData: any = null;
Log.showInfo(TAG, `abilityInfo.metaData: ${JSON.stringify(abilityInfo.metaData)}`);
if (abilityInfo.metaData) {
for (let index in abilityInfo.metaData) {
if (abilityInfo.metaData[index].name == this.mAction) {
Log.showInfo(TAG, `customizeData.extra: ${abilityInfo.metaData[index].extra}`);
pluginData = JSON.parse("{" + abilityInfo.metaData[index].extra + "}");
break;
}
}
}
Log.showInfo(TAG, `createItemComponentData, pluginData: ${JSON.stringify(pluginData)}`);
if (!pluginData && parseInt(pluginData.pluginType) != this.mPluginType) {
return;
}
if (this.mFilterIds.indexOf(pluginData.id) < 0) {
return;
}
let itemComponentData = new ItemComponentData();
{
itemComponentData.id = pluginData.id;
itemComponentData.pluginType = this.mPluginType;
itemComponentData.deviceId = null;
itemComponentData.bundleName = abilityInfo.bundleName;
itemComponentData.abilityName = abilityInfo.name;
itemComponentData.abilityLabelId = abilityInfo.labelId;
itemComponentData.abilityIconId = abilityInfo.iconId;
if (!CheckEmptyUtils.isEmpty(pluginData.label)) {
itemComponentData.label = encodeURIComponent(pluginData.label);
}
if (!CheckEmptyUtils.isEmpty(pluginData.icon)) {
itemComponentData.iconUrl = pluginData.icon;
}
if (!CheckEmptyUtils.isEmpty(pluginData.template)) {
itemComponentData.template = pluginData.template;
}
{
let actionData = new ActionData();
actionData.clickAction = pluginData.clickAction;
actionData.longClickAction = pluginData.longClickAction;
actionData.launchType = pluginData.launchType;
actionData.pluginData = pluginData.pluginData;
actionData.extra = pluginData.extra;
itemComponentData.actionData = actionData;
}
}
Log.showInfo(TAG, `createItemComponentData, itemComponentData: ${JSON.stringify(itemComponentData)}`);
callback(itemComponentData);
}
addItemComponentData(itemComponentData): void {
Log.showInfo(TAG, `addItemComponentData, itemComponentData: ${JSON.stringify(itemComponentData)} `);
this.addItem(itemComponentData);
this.mItemComponentDatas.push(itemComponentData);
}
removeItemComponentData(bundleName): void {
Log.showInfo(TAG, `removeItemComponentData, bundleName: ${bundleName}`);
let deleteIndexs = [];
for (let i = 0;i < this.mItemComponentDatas.length; i++) {
if (this.mItemComponentDatas[i].bundleName == bundleName) {
deleteIndexs.push(i);
}
}
Log.showInfo(TAG, `removeItemComponentData, deleteIndexs: ${JSON.stringify(deleteIndexs)}`);
for (let i = (deleteIndexs.length - 1);i >= 0; i--) {
let itemComponentData = this.mItemComponentDatas[deleteIndexs[i]];
this.removeItem(itemComponentData);
this.mItemComponentDatas.splice(deleteIndexs[i], 1);
}
Log.showInfo(TAG, `removeItemComponentData, mItemComponentDatas: ${JSON.stringify(this.mItemComponentDatas)}`);
}
}
@@ -1,31 +0,0 @@
/*
* 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 Log from '../../default/Log.ets';
import BaseMetaSourceLoader from './BaseMetaSourceLoader.ets';
import {PluginType} from '../common/Constants.ets';
const TAG = "DataAbilitySourceLoader";
export default class DataAbilitySourceLoader extends BaseMetaSourceLoader {
// config = {"methodName":"xxx/xx/xx"}
constructor(config, channel) {
super(config, channel, PluginType.OBSERVER);
Log.showInfo(TAG, `constructor, config: ${JSON.stringify(config)} channel: ${channel}`)
}
// todo 启动监听,监听call方法,数据转换为ItemComponentData,通过addItem/removewItem传输
}
@@ -0,0 +1,33 @@
/*
* Copyright (c) 2021-2022 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 Log from "../../default/Log";
import { AbilityInfoWithId } from "../common/BundleParseUtil";
import { LoaderConfigInfo } from "../common/Constants";
import SourceLoader from "./SourceLoader";
const TAG = "DataAbilitySourceLoader";
export default class DataAbilitySourceLoader extends SourceLoader {
constructor(config: LoaderConfigInfo) {
super(config);
Log.showInfo(TAG, `constructor`);
}
clearData(): void {}
reloadData(userId: number): void {}
onAbilityAdd(abilityInfo: AbilityInfoWithId): void {}
onBundleRemove(bundleName: string): void {}
}
@@ -0,0 +1,96 @@
/*
* Copyright (c) 2021-2022 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 Log from "../../default/Log";
import SourceLoader from "./SourceLoader";
import Constants, { PluginType, ItemComponentData, LoaderConfigInfo } from "../common/Constants";
import { AbilityInfoWithId, filterAbilityInfo, PluginData } from "../common/BundleParseUtil";
import { parseEventString } from "../../default/Event/EventUtil";
const TAG = "MetaSourceLoader";
export default class MetaSourceLoader extends SourceLoader {
mPluginFilter: string = "";
mPermission: string = "";
mItemDatas: ItemComponentData[] = [];
constructor(config: LoaderConfigInfo) {
super(config);
this.mPluginFilter = config.action;
this.mPermission = config.permission;
Log.showInfo(TAG, `init loader, mPluginFilter: ${this.mPluginFilter}, mPermission: ${this.mPermission}`);
}
onAbilityAdd(abilityInfo: AbilityInfoWithId): void {
let pluginData: PluginData | undefined = filterAbilityInfo(abilityInfo, this.mPluginFilter);
if (pluginData) {
let itemData = parseData(abilityInfo, pluginData);
if (!itemData) {
return;
}
this.mItemDatas.push(itemData);
this.addItem(itemData);
Log.showInfo(TAG, `item[${itemData.id}] add success, name: ${abilityInfo.name}`);
return;
}
Log.showDebug(TAG, `Can't filter ${abilityInfo.name}.`);
}
onBundleRemove(bundleName: string): void {
for (let i = this.mItemDatas.length - 1; i >= 0; i--) {
if (bundleName == this.mItemDatas[i].bundleName) {
Log.showDebug(TAG, `remove item index: ${i}, abilityname: ${this.mItemDatas[i].abilityName}`);
this.removeItem(this.mItemDatas[i]);
this.mItemDatas.splice(i, 1);
}
}
}
clearData(): void {
Log.showDebug(TAG, `clear all, size: ${this.mItemDatas.length}`);
this.mItemDatas.forEach((data) => this.removeItem(data));
this.mItemDatas.length = 0;
}
reloadData(userId: number): void {
Log.showDebug(TAG, `reloadData userId: ${userId}`);
}
}
function parseData(info: AbilityInfoWithId, data: PluginData): ItemComponentData {
let { label, pluginType, icon, template, clickAction, longClickAction, launchType, ...extra } = data;
if (pluginType.toString() != PluginType.META.toString()) {
return undefined;
}
let itemData: ItemComponentData = {
id: info.itemId,
pluginType: PluginType.META,
deviceId: Constants.LOCAL_DEVICE,
bundleName: info.bundleName,
abilityName: info.name,
abilityLabelId: info.labelId,
abilityIconId: info.iconId,
label: label,
iconUrl: icon,
template: template,
actionData: {
clickAction: parseEventString(clickAction),
longClickAction: parseEventString(longClickAction),
launchType: launchType,
extra: extra,
},
};
return itemData;
}
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2021 Huawei Device Co., Ltd.
* Copyright (c) 2021-2022 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
@@ -13,28 +13,21 @@
* limitations under the License.
*/
import Log from '../../default/Log.ets';
import SourceLoader from './SourceLoader.ets';
import Log from "../../default/Log";
import { AbilityInfoWithId } from "../common/BundleParseUtil";
import { LoaderConfigInfo } from "../common/Constants";
import SourceLoader from "./SourceLoader";
const TAG = "PluginSourceLoader";
export default class PluginSourceLoader extends SourceLoader {
constructor(config, channel) {
super(channel);
this.initSourceLoader(config);
}
constructor(config: LoaderConfigInfo) {
super(config);
Log.showInfo(TAG, `constructor`);
}
initSourceLoader(config) {
Log.showInfo(TAG, `init loader, config: ${JSON.stringify(config)}`)
// todo 配置解析, config格式配置
// todo 启动监听,数据转换为ItemComponentData,通过addItem/removewItem传输
}
stopLoad() {
// todo 停止监听,清除数据
}
loadData(userId) {
// todo 重新获取一次数据
}
clearData(): void {}
reloadData(userId: number): void {}
onAbilityAdd(abilityInfo: AbilityInfoWithId): void {}
onBundleRemove(bundleName: string): void {}
}
@@ -1,42 +0,0 @@
/*
* 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 Log from '../../default/Log.ets';
import {ItemComponentData} from '../common/Constants.ets';
const TAG = "SourceLoader";
export default abstract class SourceLoader {
mChannel: any;
constructor(channel) {
Log.showInfo(TAG, `constructor, channel: ${channel}`)
this.mChannel = channel;
}
abstract stopLoad(): void;
abstract loadData(userId): void;
addItem(itemData: ItemComponentData) {
Log.showInfo(TAG, `addItem, itemData: ${JSON.stringify(itemData)}`)
this.mChannel.add(itemData);
}
removeItem(itemData:ItemComponentData) {
Log.showInfo(TAG, `remove, itemData: ${JSON.stringify(itemData)}`)
this.mChannel.remove(itemData);
}
}
@@ -0,0 +1,53 @@
/*
* Copyright (c) 2021-2022 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 Log from "../../default/Log";
import { ItemComponentData, LoaderConfigInfo } from "../common/Constants";
import { AbilityInfoWithId } from "../common/BundleParseUtil";
const TAG = "SourceLoader";
export type LoaderChannel = {
add: (item: ItemComponentData) => void;
remove: (item: ItemComponentData) => void;
};
export default abstract class SourceLoader {
mChannel: LoaderChannel | undefined;
constructor(config: LoaderConfigInfo) {
Log.showInfo(TAG, `constructor`);
}
public setChannel(channel: LoaderChannel) {
this.mChannel = channel;
}
protected addItem(itemData: ItemComponentData) {
this.mChannel?.add(itemData);
}
protected removeItem(itemData: ItemComponentData) {
this.mChannel?.remove(itemData);
}
abstract clearData(): void;
abstract onBundleRemove(bundleName: string): void;
abstract reloadData(userId: number): void;
abstract onAbilityAdd(abilityInfo: AbilityInfoWithId): void;
}
@@ -1,47 +0,0 @@
/*
* 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 Log from '../../default/Log.ets';
import DataAbilitySourceLoader from './DataAbilitySourceLoader.ets'
import MetaSourceLoader from './MetaSourceLoader.ets'
import PluginSourceLoader from './PluginSourceLoader.ets'
const TAG = "SourceLoaderFactory";
const classMap = new Map([
["MetaSource", MetaSourceLoader],
["PluginSourceLoader", PluginSourceLoader],
["DataAbilitySourceLoader", DataAbilitySourceLoader]
]);
export default class SourceLoaderFactory {
mChannel: any;
constructor(channel: {
add: Function,
remove: Function
}) {
Log.showInfo(TAG, `constructor, channel: ${channel}`)
this.mChannel = channel;
}
getSourceLoader(pluginType, config, callback) {
Log.showInfo(TAG, `getSourceLoader, pluginType: ${pluginType} config: ${JSON.stringify(config)}`)
if (!classMap.has(pluginType)) {
return;
}
callback(new (classMap.get(pluginType))(config, this.mChannel));
}
}
@@ -0,0 +1,49 @@
/*
* Copyright (c) 2021-2022 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 Log from "../../default/Log";
import SourceLoader, { LoaderChannel } from "./SourceLoader";
import DataAbilitySourceLoader from "./DataAbilitySourceLoader";
import MetaSourceLoader from "./MetaSourceLoader";
import PluginSourceLoader from "./PluginSourceLoader";
import { LoaderConfigInfo } from "../common/Constants";
const TAG = "SourceLoaderFactory";
const classMap: { [key: string]: any } = {
MetaSource: MetaSourceLoader,
PluginSourceLoader: PluginSourceLoader,
DataAbilitySourceLoader: DataAbilitySourceLoader,
};
export default class SourceLoaderFactory {
mChannel: LoaderChannel;
constructor(channel: LoaderChannel) {
Log.showInfo(TAG, `constructor, channel: ${channel}`);
this.mChannel = channel;
}
getSourceLoader(pluginType: string, config: LoaderConfigInfo): null | SourceLoader {
let clz = classMap[pluginType];
if (!clz) {
Log.showError(TAG, `Can't find pluginType: ${pluginType}`);
return null;
}
let loader: SourceLoader = new clz(config);
loader.setChannel(this.mChannel);
return loader;
}
}
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2021 Huawei Device Co., Ltd.
* Copyright (c) 2021-2022 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
@@ -13,106 +13,105 @@
* limitations under the License.
*/
import Log from '../default/Log.ets'
import UniformConfig from './UniformConfig.ets'
import Log from '../default/Log'
import StyleConfiguration from './common/StyleConfiguration'
const TAG = 'SimpleToggleBase.ets'
const TAG = 'SimpleToggleBase'
@Component
export default struct SimpleToggleBase {
private mConfig = UniformConfig.config
@Prop mToggleId: string
@Link @Watch('onIconUpdated') mIcon: string | Resource
@State @Watch('onIconStrUpdated') mIconStr: string = ''
private mToggleId: string
@Link mIcon: string | Resource
@State mIconStr: string = ''
private mUseIconStr: boolean = false
private mAutoIconColor: boolean = false
@Link @Watch('onChangeSwitchUpdated') mChangeSwitch: boolean
@Prop mChangeSwitch: boolean
@Link mLabel: string | Resource
@State mLabelStr: string = ''
private mUseLabelStr: boolean = false
@Prop mShowLabel: boolean
@Prop mEditMode: boolean
private mIconOnBG: string | Resource
private mEditMode: boolean = false
private mDragMode: boolean = false
private mClickEvent: Function
private mLongClickEvent: Function
private appStorageIconKey: string
private appStorageChangeSwitchKey: string
@State mIconIsHover: boolean = false
@State mTextIsHover: boolean = false
@State style: any = StyleConfiguration.getSimpleToggleBaseStyle()
aboutToAppear() {
Log.showInfo(TAG, `aboutToAppear, mToggleId: ${this.mToggleId}`)
Log.showInfo(TAG, `aboutToAppear, mLabel: ${JSON.stringify(this.mLabel)}`)
if (this.mEditMode) {
this.appStorageIconKey = "TOGGLE_ICON_" + this.mToggleId
this.appStorageChangeSwitchKey = "TOGGLE_CHANGE_SWITCH_" + this.mToggleId
if (this.mUseIconStr) {
AppStorage.SetOrCreate(this.appStorageIconKey, this.mIconStr)
} else {
AppStorage.SetOrCreate(this.appStorageIconKey, this.mIcon)
}
AppStorage.SetOrCreate(this.appStorageChangeSwitchKey, this.mChangeSwitch)
}
Log.showInfo(TAG, `aboutToAppear, mEditMode: ${this.mEditMode} mDragMode: ${this.mDragMode}`)
}
aboutToDisappear() {
Log.showInfo(TAG, 'aboutToDisappear')
}
onIconUpdated(propName: string): void {
Log.showInfo(TAG, `onIconUpdated, propName: ${propName} mIcon: ${JSON.stringify(this.mIcon)}`)
if (this.mEditMode) {
AppStorage.SetOrCreate(this.appStorageIconKey, this.mIcon)
}
}
onIconStrUpdated(propName: string): void {
Log.showInfo(TAG, `onIconStrUpdated, propName: ${propName} mIconStr: ${this.mIconStr}`)
if (this.mEditMode) {
AppStorage.SetOrCreate(this.appStorageIconKey, this.mIconStr)
}
}
onChangeSwitchUpdated(propName: string): void {
Log.showInfo(TAG, `onIconUpdated, propName: ${propName} mChangeSwitch: ${this.mChangeSwitch}`)
if (this.mEditMode) {
AppStorage.SetOrCreate(this.appStorageChangeSwitchKey, this.mChangeSwitch)
}
}
build() {
Column() {
Stack() {
Flex()
.backgroundColor(this.mChangeSwitch == false ? this.mConfig.iconOffBG : this.mConfig.iconOnBG)
.clip(new Circle({ width: this.mConfig.circleWidth, height: this.mConfig.circleHeight }))
.width(this.mConfig.circleWidth)
.height(this.mConfig.circleHeight)
if (this.mAutoIconColor) {
Image(this.mUseIconStr ? this.mIconStr : this.mIcon)
.size({ width: this.mConfig.iconWidth, height: this.mConfig.iconHeight })
.objectFit(ImageFit.Contain)
.fillColor(this.mChangeSwitch ? this.mConfig.iconOnColor : this.mConfig.iconOffColor)
} else {
Image(this.mUseIconStr ? this.mIconStr : this.mIcon)
.size({ width: this.mConfig.iconWidth, height: this.mConfig.iconHeight })
.objectFit(ImageFit.Contain)
.backgroundColor(this.mChangeSwitch ? (this.mIconOnBG ? this.mIconOnBG : this.style.iconOnBG) : this.style.iconOffBG)
.clip(new Circle({
width: this.mDragMode ? this.style.dragCircleWidth : this.style.circleWidth,
height: this.mDragMode ? this.style.dragCircleHeight : this.style.circleHeight
}))
.width(this.mDragMode ? this.style.dragCircleWidth : this.style.circleWidth)
.height(this.mDragMode ? this.style.dragCircleHeight : this.style.circleHeight)
if (!this.mDragMode) {
Flex()
.backgroundColor(this.mIconIsHover ? this.style.hoverColor : this.style.transparentColor)
.clip(new Circle({ width: this.style.circleWidth, height: this.style.circleHeight }))
.width(this.style.circleWidth)
.height(this.style.circleHeight)
}
Image(this.mUseIconStr ? this.mIconStr : this.mIcon)
.size({
width: this.mDragMode ? this.style.dragIconWidth : this.style.iconWidth,
height: this.mDragMode ? this.style.dragIconHeight : this.style.iconHeight })
.objectFit(ImageFit.Contain)
.fillColor(this.mChangeSwitch ? this.style.iconOnColor : this.style.iconOffColor)
.onHover((isHover) => {
this.mIconIsHover = isHover;
})
}
.width(this.mDragMode ? this.style.dragCircleWidth : this.style.circleWidth)
.height(this.mDragMode ? this.style.dragCircleHeight : this.style.circleHeight)
.onClick(this.onIconItemClick.bind(this))
if (!this.mDragMode) {
Column()
.width('100%')
.height(this.style.componentGap)
Stack() {
Flex()
.backgroundColor(this.mTextIsHover ? this.style.hoverColor : this.style.transparentColor)
.clip(new Rect({
width: this.style.textHoverWidth,
height: this.style.textHoverHeight
}).radius(this.style.textHoverRadius))
.width(this.style.textHoverWidth)
.height(this.style.textHoverHeight)
Text(this.mUseLabelStr ? this.mLabelStr : this.mLabel)
.fontSize(this.style.titleSize)
.fontColor(this.style.titleColor)
.textAlign(TextAlign.Center)
.maxLines(2)
.onHover((isHover) => {
this.mTextIsHover = isHover;
})
}
}
.width(this.mConfig.circleWidth)
.height(this.mConfig.circleHeight)
if (this.mShowLabel) {
Column()
.width(this.mConfig.circleWidth)
.height(10)
Text(this.mUseLabelStr ? this.mLabelStr : this.mLabel)
.fontSize(this.mConfig.simpleToggleTitleSize)
}
}
.onClick(this.onIconItemClick.bind(this))
.gesture(LongPressGesture({ repeat: false }).onAction(this.onIconItemLongPressGesture.bind(this)))
.width('100%')
.height('100%')
}
onIconItemClick(event: ClickEvent) {
if (this.mDragMode) {
return
}
Log.showInfo(TAG, `onIconItemClick`)
if (this.mClickEvent) {
this.mClickEvent()
@@ -120,7 +119,7 @@ export default struct SimpleToggleBase {
}
onIconItemLongPressGesture(event: GestureEvent) {
if (this.mEditMode) {
if (this.mEditMode || this.mDragMode) {
return
}
Log.showInfo(TAG, `onIconItemLongPressGesture, event: ${JSON.stringify(event)}`)
@@ -1,51 +0,0 @@
/*
* 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 class UniformConfig {
static config = {
iconOnBG: "#0A59F7",
iconOffBG: "#F5F5F5",
iconOnColor: "#FFFFFF",
iconOffColor: "#404345",
baseColor: "#CCFFFFFF",
circleWidth: '80px',
circleHeight: '80px',
iconWidth: '50px',
iconHeight: '50px',
titleSize: '20px',
baseBorderRadius: 15,
simpleToggleTitleSize: '18px'
}
static initParams(params?) {
console.log('----initParams(params)----ing');
UniformConfig.config = params || {
iconOnBG: "#0A59F7",
iconOffBG: "#F5F5F5",
iconOnColor: "#FFFFFF",
iconOffColor: "#404345",
baseColor: "#CCFFFFFF",
circleWidth: '80px',
circleHeight: '80px',
iconWidth: '50px',
iconHeight: '50px',
titleSize: '20px',
baseBorderRadius: 15,
simpleToggleTitleSize: '18px'
}
console.log('----initParams(params)----finish');
}
}
@@ -0,0 +1,87 @@
/*
* Copyright (c) 2021-2022 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 StyleManager from '../../default/StyleManager';
const TAG = 'CommonTemplate-StyleConfiguration';
export default class StyleConfiguration {
static getIconTitleBaseStyle() {
const key: string = TAG + "-IconTitleBase";
return StyleManager.getStyle(key, () => {
return {
marginLeft: '24vp',
marginRight: '16vp',
componentGap: '8vp',
titleSize: '24vp',
titleColor:$r("sys.color.ohos_id_color_text_secondary"),
borderRadius: '48vp',
backgroundColor: '#ffffff',
textMargin: '8vp',
textHoverHeight: '52vp',
textHoverWidth: '136vp',
textHoverRadius: '8vp',
hoverColor: 'rgba(0, 0, 0, 0.05)',
transparentColor: 'rgba(255, 255, 255, 0)',
};
});
}
static getIconComponentStyle() {
const key: string = TAG + "-IconComponent";
return StyleManager.getStyle(key, () => {
return {
circleWidth: '96vp',
circleHeight: '96vp',
iconWidth: '48vp',
iconHeight: '48vp',
iconOffBG: '#1A000000',
iconOnBG: '#FF007DFF',
iconOnColor: '#FFFFFFFF',
iconOffColor: $r("sys.color.ohos_id_color_secondary"),
hoverColor: 'rgba(0, 0, 0, 0.05)',
transparentColor: 'rgba(255, 255, 255, 0)',
};
});
}
static getSimpleToggleBaseStyle() {
const key: string = TAG + "-SimpleToggleBase";
return StyleManager.getStyle(key, () => {
return {
circleWidth: '96vp',
circleHeight: '96vp',
iconWidth: '48vp',
iconHeight: '48vp',
dragCircleWidth: '120vp',
dragCircleHeight: '120vp',
dragIconWidth: '72vp',
dragIconHeight: '72vp',
iconOffBG: '#1A000000',
iconOnBG: '#FF007DFF',
iconOnColor: '#FFFFFFFF',
iconOffColor: $r("sys.color.ohos_id_color_secondary"),
componentGap: '10vp',
titleSize: '24fp',
titleColor: $r("sys.color.ohos_id_color_text_secondary"),
textHoverWidth: '136vp',
textHoverHeight: '36vp',
textHoverRadius: '8vp',
hoverColor: 'rgba(0, 0, 0, 0.05)',
transparentColor: 'rgba(255, 255, 255, 0)',
};
});
}
}
+25 -13
View File
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2021 Huawei Device Co., Ltd.
* Copyright (c) 2021-2022 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
@@ -13,23 +13,25 @@
* limitations under the License.
*/
import Log from '../default/Log.ets';
import UniformConfig from './UniformConfig.ets'
import Log from '../default/Log';
import StyleConfiguration from './common/StyleConfiguration'
const TAG= 'iconComponent.ets'
const TAG = 'iconComponent'
@Component
export default
struct iconComponent {
private mConfig = UniformConfig.config;
@State iconOff: any = ""
@State iconOn: any = ""
@Prop iconOffStr: string
@Prop iconOnStr: string
private useIconStr = false
@State mIconIsHover: boolean = false
@Link changeSwitch: boolean
@State style: any = StyleConfiguration.getIconComponentStyle()
aboutToAppear() {
Log.showInfo(TAG,`aboutToAppear, ${this.changeSwitch} ${JSON.stringify(this.iconOff)} ${JSON.stringify(this.iconOn)}`)
@@ -44,15 +46,25 @@ struct iconComponent {
Column() {
Stack() {
Flex()
.backgroundColor(this.changeSwitch == false? this.mConfig.iconOffBG : this.mConfig.iconOnBG)
.clip(Circle({ width: this.mConfig.circleWidth, height: this.mConfig.circleHeight }))
.width(this.mConfig.circleWidth )
.height(this.mConfig.circleHeight )
Image(this.changeSwitch == false? (this.useIconStr ? this.iconOffStr : this.iconOff): (this.useIconStr ? this.iconOnStr : this.iconOn))
.size({ width: this.mConfig.iconWidth, height: this.mConfig.iconHeight})
.backgroundColor(this.changeSwitch? this.style.iconOnBG: this.style.iconOffBG)
.clip(new Circle({ width: this.style.circleWidth, height: this.style.circleHeight }))
.width(this.style.circleWidth)
.height(this.style.circleHeight)
Flex()
.backgroundColor(this.mIconIsHover? this.style.hoverColor: this.style.transparentColor)
.clip(new Circle({ width: this.style.circleWidth, height: this.style.circleHeight }))
.width(this.style.circleWidth)
.height(this.style.circleHeight)
Image(this.changeSwitch == false ? (this.useIconStr ? this.iconOffStr : this.iconOff) : (this.useIconStr ? this.iconOnStr : this.iconOn))
.size({ width: this.style.iconWidth, height: this.style.iconHeight })
.objectFit(ImageFit.Contain)
}.margin({ left: 10 })
.fillColor(this.changeSwitch ? this.style.iconOnColor : this.style.iconOffColor)
.onHover((isHover) => {
this.mIconIsHover = isHover;
})
}
.width(this.style.circleWidth)
.height(this.style.circleHeight)
}
.flexShrink(0)
}
}
+55 -39
View File
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2021 Huawei Device Co., Ltd.
* Copyright (c) 2021-2022 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
@@ -13,11 +13,11 @@
* limitations under the License.
*/
import UniformConfig from './UniformConfig.ets'
import Log from '../default/Log.ets';
import iconComponent from './iconComponent.ets'
import Log from '../default/Log';
import StyleConfiguration from './common/StyleConfiguration'
import iconComponent from './iconComponent'
const TAG= 'iconTitleBase.ets'
const TAG= 'iconTitleBase'
@Component
export default
@@ -31,11 +31,14 @@ struct iconBaseComponent {
@State mTitleStr: string = ""
private useIconStr = false
private useTitleStr = false
private mConfig = UniformConfig.config;
private mClickEvent: Function
private mLongClickEvent: Function
@State mTextIsHover: boolean = false
@Link changeSwitch: boolean
@State style: any = StyleConfiguration.getIconTitleBaseStyle()
aboutToAppear() {
Log.showInfo(TAG,'aboutToAppear')
}
@@ -45,44 +48,57 @@ struct iconBaseComponent {
}
build() {
Flex({ direction: FlexDirection.Row, alignItems: ItemAlign.Center, justifyContent: FlexAlign.Start }) {
Flex({ direction: FlexDirection.Column, alignItems: ItemAlign.Center, justifyContent: FlexAlign.Center }) {
iconComponent({
useIconStr: this.useIconStr,
iconOff: this.iconOff,
iconOn: this.iconOn,
iconOffStr: this.iconOffStr,
iconOnStr: this.iconOnStr,
changeSwitch: $changeSwitch,
Row() {
Column().width(this.style.marginLeft).height('100%').layoutWeight(0)
Row() {
Row() {
iconComponent({
useIconStr: this.useIconStr,
iconOff: this.iconOff,
iconOn: this.iconOn,
iconOffStr: this.iconOffStr,
iconOnStr: this.iconOnStr,
changeSwitch: $changeSwitch,
})
}
.onClick(() => {
console.log(`start clickEvent ${this.changeSwitch}`)
if (this.mClickEvent) {
this.mClickEvent()
}
console.log(`end clickEvent ${this.changeSwitch}`)
})
}
.flexShrink(0)
.height('100%')
.onClick(() => {
console.log(`start clickEvent ${this.changeSwitch}`)
if(this.mClickEvent){
this.mClickEvent()
.layoutWeight(0)
Column().width(this.style.componentGap).height('100%').layoutWeight(0)
Row(){
Row() {
Column().width(this.style.textMargin).height('100%').layoutWeight(0)
Text(this.useTitleStr ? this.mTitleStr : this.mTitle)
.fontSize(this.style.titleSize)
.fontColor(this.style.titleColor)
.textOverflow({ overflow: TextOverflow.Ellipsis })
.maxLines(2)
.layoutWeight(1)
.onHover((isHover) => {
this.mTextIsHover = isHover;
})
Column().width(this.style.textMargin).height('100%').layoutWeight(0)
}
console.log(`end clickEvent ${this.changeSwitch}`)
})
.gesture(LongPressGesture({ repeat: false }).onAction(()=>{
console.log(`start longClickEvent ${this.changeSwitch}`)
if(this.mLongClickEvent){
this.mLongClickEvent()
}
console.log(`end longClickEvent ${this.changeSwitch}`)
}))
Flex({ direction: FlexDirection.Column, alignItems: ItemAlign.Start, justifyContent: FlexAlign.Center }) {
Text(this.useTitleStr ? this.mTitleStr : this.mTitle)
.fontSize(this.mConfig.titleSize)
.textOverflow({ overflow: TextOverflow.Ellipsis })
.maxLines(2)
.margin({ left: 10, right: 10 })
}
.height('100%')
.width('100%')
.height(this.style.textHoverHeight)
.width(this.style.textHoverWidth)
.backgroundColor(this.mTextIsHover? this.style.hoverColor: this.style.transparentColor)
.borderRadius(this.style.textHoverRadius)
.clip(true)
}.height('100%')
.layoutWeight(1)
Column().width(this.style.marginRight).height('100%').layoutWeight(0)
}
.borderRadius(this.mConfig.baseBorderRadius)
.backgroundColor(this.mConfig.baseColor)
.borderRadius(this.style.borderRadius)
.clip(true)
.backgroundColor(this.style.backgroundColor)
.height('100%')
.width('100%')
}
+1 -1
View File
@@ -17,7 +17,7 @@
```
### 环境搭建
打开DevEco Studio链接下载安装,安装步骤及安装说明详见开发者网站
打开DevEco Studio链接下载安装,安装步骤及安装说明详见下载地址([下载地址](https://developer.harmonyos.com/cn/develop/deveco-studio#download)
## 基础开发说明
### 系统接口调用
View File
View File
View File
+91
View File
@@ -0,0 +1,91 @@
{
"app": {
"bundleName": "com.ohos.systemui",
"vendor": "ohos",
"version": {
"code": 1,
"name": "1.0"
},
"singleton": true
},
"deviceConfig": {},
"module": {
"package": "com.ohos.systemui",
"name": ".MyApplication",
"deviceType": [
"tablet"
],
"distro": {
"deliveryWithInstall": true,
"moduleName": "pc_entry",
"moduleType": "entry"
},
"abilities": [
{
"visible": true,
"srcPath": "ServiceExtAbility",
"name": ".ServiceExtAbility",
"icon": "$media:icon",
"srcLanguage": "ets",
"description": "$string:description_mainability",
"label": "$string:app_name",
"type": "service"
}
],
"js": [
{
"mode": {
"syntax": "ets",
"type": "pageAbility"
},
"name": "ServiceExtAbility",
"window": {
"designWidth": 720,
"autoDesignWidth": false
},
"pages": ["pages/index"]
}
],
"reqPermissions": [
{
"name": "ohos.permission.GET_BUNDLE_INFO_PRIVILEGED"
},
{
"name": "ohos.permission.MANAGE_LOCAL_ACCOUNTS"
},
{
"name": "ohos.permission.INTERACT_ACROSS_LOCAL_ACCOUNTS_EXTENSION"
},
{
"name": "ohos.permission.NOTIFICATION_CONTROLLER"
},
{
"name": "ohos.permission.GET_WIFI_INFO"
},
{
"name": "ohos.permission.SET_WIFI_INFO"
},
{
"name": "ohos.permission.MANAGE_WIFI_CONNECTION"
},
{
"name": "ohos.permission.GET_NETWORK_INFO"
},
{
"name": "ohos.permission.USE_BLUETOOTH"
},
{
"name": "ohos.permission.DISCOVER_BLUETOOTH"
},
{
"name": "ohos.permission.MANAGE_BLUETOOTH"
},
{
"name": "ohos.permission.CAPTURE_SCREEN"
},
{
"name": "ohos.permission.MANAGE_SECURE_SETTINGS"
}
]
}
}
+24
View File
@@ -0,0 +1,24 @@
/*
* Copyright (c) 2021-2022 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 AbilityStage from "@ohos.application.AbilityStage"
import Log from '../../../../../common/src/main/ets/default/Log'
const TAG = "SystemUI_AbilityStage"
export default class MainAbilityStage extends AbilityStage {
onCreate() {
Log.showInfo(TAG, "onCreate")
}
}
@@ -0,0 +1,64 @@
/*
* Copyright (c) 2021-2022 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 ServiceExtension from '@ohos.application.ServiceExtensionAbility'
import Log from '../../../../../../common/src/main/ets/default/Log'
import AbilityManager from '../../../../../../common/src/main/ets/default/abilitymanager/abilityManager'
import initSystemUi from '../../../../../../common/src/main/ets/default/InitSystemUi'
const TAG = "SystemUI_ServiceExtAbility"
var statusBarWant = {
"bundleName": "com.ohos.systemui",
"abilityName": "com.ohos.systemui.statusbar.ServiceExtAbility"
}
var navigationBarWant = {
"bundleName": "com.ohos.systemui",
"abilityName": "com.ohos.systemui.navigationbar.ServiceExtAbility"
}
var volumePanelWant = {
"bundleName": "com.ohos.systemui",
"abilityName": "com.ohos.systemui.volumepanel.ServiceExtAbility"
}
var controlPanelWant = {
"bundleName": "com.ohos.systemui",
"abilityName": "com.ohos.systemui.controlpanel.ServiceExtAbility"
}
var notificationPanelWant = {
"bundleName": "com.ohos.systemui",
"abilityName": "com.ohos.systemui.notificationpanel.ServiceExtAbility"
}
class ServiceExtAbility extends ServiceExtension {
onCreate(want) {
Log.showInfo(TAG, `api8New onCreate, want: ${JSON.stringify(want)}`)
initSystemUi(this.context);
AbilityManager.setContext(AbilityManager.ABILITY_NAME_ENTRY, this.context)
AbilityManager.startAbility(statusBarWant)
AbilityManager.startAbility(navigationBarWant)
AbilityManager.startAbility(volumePanelWant)
AbilityManager.startAbility(controlPanelWant)
AbilityManager.startAbility(notificationPanelWant)
}
onDestroy() {
Log.showInfo(TAG, 'api8New onDestroy')
}
}
export default ServiceExtAbility
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2021 Huawei Device Co., Ltd.
* Copyright (c) 2021-2022 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
@@ -0,0 +1,16 @@
{
"string": [
{
"name": "app_name",
"value": "SystemUI"
},
{
"name": "mainability_description",
"value": "JS_Phone_Empty Feature Ability"
},
{
"name": "description_mainability",
"value": "SystemUI ServiceExtension"
}
]
}

Before

Width:  |  Height:  |  Size: 6.6 KiB

After

Width:  |  Height:  |  Size: 6.6 KiB

+1
View File
@@ -0,0 +1 @@
/build
@@ -4,11 +4,9 @@ ohos {
defaultConfig {
compatibleSdkVersion rootProject.ext.version.compatibleSdk
}
entryModules "entry"
}
dependencies {
entryImplementation project(':entry')
implementation fileTree(dir: 'libs', include: ['*.jar', '*.har'])
testCompile 'junit:junit:4.12'
}
+88
View File
@@ -0,0 +1,88 @@
{
"app": {
"bundleName": "com.ohos.systemui",
"vendor": "ohos",
"version": {
"code": 1,
"name": "1.0"
},
"singleton": true
},
"deviceConfig": {},
"module": {
"package": "com.ohos.systemui",
"name": ".MyApplication",
"deviceType": [
"phone"
],
"distro": {
"deliveryWithInstall": true,
"moduleName": "phone_entry",
"moduleType": "entry"
},
"abilities": [
{
"visible": true,
"srcPath": "ServiceExtAbility",
"name": ".ServiceExtAbility",
"icon": "$media:icon",
"srcLanguage": "ets",
"description": "$string:description_mainability",
"label": "$string:app_name",
"type": "service"
}
],
"js": [
{
"mode": {
"syntax": "ets",
"type": "pageAbility"
},
"name": "ServiceExtAbility",
"window": {
"designWidth": 720,
"autoDesignWidth": false
},
"pages": ["pages/index"]
}
],
"reqPermissions": [
{
"name": "ohos.permission.GET_BUNDLE_INFO_PRIVILEGED"
},
{
"name": "ohos.permission.MANAGE_LOCAL_ACCOUNTS"
},
{
"name": "ohos.permission.INTERACT_ACROSS_LOCAL_ACCOUNTS_EXTENSION"
},
{
"name": "ohos.permission.NOTIFICATION_CONTROLLER"
},
{
"name": "ohos.permission.GET_WIFI_INFO"
},
{
"name": "ohos.permission.SET_WIFI_INFO"
},
{
"name": "ohos.permission.MANAGE_WIFI_CONNECTION"
},
{
"name": "ohos.permission.USE_BLUETOOTH"
},
{
"name": "ohos.permission.DISCOVER_BLUETOOTH"
},
{
"name": "ohos.permission.MANAGE_BLUETOOTH"
},
{
"name": "ohos.permission.CAPTURE_SCREEN"
},
{
"name": "ohos.permission.MANAGE_SECURE_SETTINGS"
}
]
}
}
+24
View File
@@ -0,0 +1,24 @@
/*
* Copyright (c) 2021-2022 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 AbilityStage from "@ohos.application.AbilityStage"
import Log from '../../../../../common/src/main/ets/default/Log'
const TAG = "SystemUI_AbilityStage"
export default class MainAbilityStage extends AbilityStage {
onCreate() {
Log.showInfo(TAG, "onCreate")
}
}
@@ -0,0 +1,58 @@
/*
* Copyright (c) 2021-2022 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 ServiceExtension from '@ohos.application.ServiceExtensionAbility'
import Log from '../../../../../../common/src/main/ets/default/Log'
import AbilityManager from '../../../../../../common/src/main/ets/default/abilitymanager/abilityManager'
import initSystemUi from '../../../../../../common/src/main/ets/default/InitSystemUi'
const TAG = "SystemUI_ServiceExtAbility"
var statusBarWant = {
"bundleName": "com.ohos.systemui",
"abilityName": "com.ohos.systemui.statusbar.ServiceExtAbility"
}
var navigationBarWant = {
"bundleName": "com.ohos.systemui",
"abilityName": "com.ohos.systemui.navigationbar.ServiceExtAbility"
}
var volumePanelWant = {
"bundleName": "com.ohos.systemui",
"abilityName": "com.ohos.systemui.volumepanel.ServiceExtAbility"
}
var dropdownPanelWant = {
"bundleName": "com.ohos.systemui",
"abilityName": "com.ohos.systemui.dropdownpanel.ServiceExtAbility"
}
class ServiceExtAbility extends ServiceExtension {
onCreate(want) {
Log.showInfo(TAG, `api8New onCreate, want: ${JSON.stringify(want)}`)
initSystemUi(this.context)
AbilityManager.setContext(AbilityManager.ABILITY_NAME_ENTRY, this.context)
AbilityManager.startAbility(statusBarWant)
AbilityManager.startAbility(navigationBarWant)
AbilityManager.startAbility(volumePanelWant)
AbilityManager.startAbility(dropdownPanelWant)
}
onDestroy() {
Log.showInfo(TAG, 'api8New onDestroy')
}
}
export default ServiceExtAbility
@@ -1,4 +1,4 @@
/**
/*
* 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.
@@ -13,16 +13,12 @@
* limitations under the License.
*/
export class DateAndTimeUtil {
concatTime(hours, minutes) {
return `${this.fill(hours)}:${this.fill(minutes)}`;
};
fill(value) {
return (value > 9 ? "" : "0") + value;
};
export default {
onCreate() {
console.info('SystemUI entry Application onDestroy')
},
onDestroy() {
console.info('SystemUI entry Application onDestroy')
},
}
let dateAndTimeUtil = new DateAndTimeUtil();
export default dateAndTimeUtil as DateAndTimeUtil
@@ -0,0 +1,27 @@
/*
* Copyright (c) 2021-2022 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
@Entry
@Component
struct Index {
build() {
Flex({ direction: FlexDirection.Row, alignItems: ItemAlign.Center, justifyContent: FlexAlign.Center }) {
}
.width('100%')
.height('100%')
}
}
@@ -0,0 +1,16 @@
{
"string": [
{
"name": "app_name",
"value": "SystemUI"
},
{
"name": "mainability_description",
"value": "JS_Phone_Empty Feature Ability"
},
{
"name": "description_mainability",
"value": "SystemUI ServiceExtension"
}
]
}

Before

Width:  |  Height:  |  Size: 6.6 KiB

After

Width:  |  Height:  |  Size: 6.6 KiB

+1 -1
View File
@@ -1,6 +1,6 @@
ext {
version = [
compileSdk: 8,
compatibleSdk: 4
compatibleSdk: 8
]
}
@@ -0,0 +1,16 @@
apply plugin: 'com.huawei.ohos.hap'
ohos {
compileSdkVersion rootProject.ext.version.compileSdk
defaultConfig {
compatibleSdkVersion rootProject.ext.version.compatibleSdk
}
entryModules "phone_entry,pc_entry"
}
dependencies {
entryImplementation project(':phone_entry')
entryImplementation project(':pc_entry')
implementation fileTree(dir: 'libs', include: ['*.jar', '*.har'])
testCompile 'junit:junit:4.12'
implementation project(':features:navigationservice')
}
@@ -5,30 +5,31 @@
"version": {
"code": 1,
"name": "1.0"
}
},
"singleton": true
},
"deviceConfig": {},
"module": {
"package": "com.ohos.systemui.navigationbar",
"name": ".MyApplication",
"deviceType": [
"phone"
"phone", "tablet"
],
"distro": {
"deliveryWithInstall": true,
"moduleName": "navigationBar",
"moduleName": "default_navigationBar",
"moduleType": "feature"
},
"abilities": [
{
"visible": true,
"name": "com.ohos.systemui.navigationbar.MainAbility",
"name": "com.ohos.systemui.navigationbar.ServiceExtAbility",
"icon": "$media:icon",
"description": "$string:mainability_description",
"label": "$string:app_name",
"type": "page",
"type": "service",
"launchType": "singleton",
"srcPath": "default",
"srcPath": "ServiceExtAbility",
"srcLanguage": "ets"
}
],
@@ -40,13 +41,12 @@
"pages": [
"pages/index"
],
"name": "default",
"name": "ServiceExtAbility",
"window": {
"designWidth": 720,
"autoDesignWidth": false
}
}
],
"srcPath": "default"
]
}
}
@@ -0,0 +1,23 @@
/*
* Copyright (c) 2021-2022 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 AbilityStage from "@ohos.application.AbilityStage"
import Log from '../../../../../../common/src/main/ets/default/Log'
const TAG = "NavigationBar_AbilityStage"
export default class MainAbilityStage extends AbilityStage {
onCreate() {
Log.showInfo(TAG, "onCreate")
}
}
@@ -0,0 +1,73 @@
/*
* Copyright (c) 2021-2022 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 ServiceExtension from '@ohos.application.ServiceExtensionAbility'
import Log from '../../../../../../../common/src/main/ets/default/Log'
import WindowManager, { WindowType } from '../../../../../../../common/src/main/ets/default/WindowManager'
import AbilityManager from '../../../../../../../common/src/main/ets/default/abilitymanager/abilityManager'
import NavBarConfiguration from './common/NavBarConfiguration'
const TAG = "NavigationBar_ServiceExtAbility"
class ServiceExtAbility extends ServiceExtension {
async onCreate(want) {
Log.showInfo(TAG, `api8New onCreate, want: ${JSON.stringify(want)}`);
AbilityManager.setContext(AbilityManager.ABILITY_NAME_NAVIGATION_BAR, this.context)
let configInfo = await NavBarConfiguration.getConfiguration();
if (configInfo.showNavHorizontal) {
if (configInfo.maxWidth > configInfo.maxHeight) { // Pad、PC Mode
configInfo.realHeight = 44 * configInfo.maxWidth / 1280
} else { // Phone Mode
configInfo.realHeight = 36 * configInfo.maxWidth / 360
}
configInfo.minHeight = configInfo.realHeight
if (configInfo.yCoordinate > 0) {
configInfo.yCoordinate = configInfo.maxHeight - configInfo.realHeight
}
} else {
if (configInfo.maxWidth > configInfo.maxHeight) { // Pad、PC Mode
configInfo.realWidth = 44 * configInfo.maxWidth / 1280
} else { // Phone Mode
configInfo.realWidth = 36 * configInfo.maxWidth / 360
}
configInfo.minHeight = configInfo.realWidth
if (configInfo.xCoordinate > 0) {
configInfo.xCoordinate = configInfo.maxWidth - configInfo.realWidth
}
}
AbilityManager.setAbilityData(AbilityManager.ABILITY_NAME_NAVIGATION_BAR, 'config', configInfo)
Log.showInfo(TAG, `api8New onCreate, configInfo: ${JSON.stringify(configInfo)}`)
let navigationBarRect = {
left: configInfo.xCoordinate,
top: configInfo.yCoordinate,
width: configInfo.realWidth,
height: configInfo.realHeight
}
WindowManager.createWindow(this.context, WindowType.NAVIGATION_BAR, navigationBarRect, "pages/index")
.then(() => {
Log.showInfo(TAG, `api8New onCreate, createWindow success.`);
WindowManager.showWindow(WindowType.NAVIGATION_BAR);
})
.catch((err) => Log.showError(TAG, `Can't create window, err:${err}`));
}
onDestroy() {
Log.showInfo(TAG, 'api8New onDestroy');
}
}
export default ServiceExtAbility
@@ -12,19 +12,20 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import WindowManager from '../../../../../../common/src/main/ets/default/WindowManager.ets'
import StatusBarConfiguration from '../../../../../../features/statusbarcomponent/src/main/ets/com/ohos/common/StatusBarConfiguration.ets';
import AbilityManager from '../../../../../../../common/src/main/ets/default/abilitymanager/abilityManager'
import configManager from '../../../../../../../features/navigationservice/src/main/ets/com/ohos/navigationservice/ConfigManager'
let mConfigManager = configManager
export default {
async onCreate() {
console.info('SystemUI statusBar Application onCreate')
let val = await StatusBarConfiguration.getConfiguration();
let mWindowManager = new WindowManager();
await mWindowManager.initWindowManager();
await mWindowManager.initWindowMin(val.realWidth, val.realHeight, val.xCoordinate, val.yCoordinate)
console.info('SystemUI navigationBar Application onCreate')
let configInfo = AbilityManager.getAbilityData(AbilityManager.ABILITY_NAME_NAVIGATION_BAR, 'config')
AppStorage.SetAndLink("showNavHorizontal", configInfo.showNavHorizontal)
mConfigManager.initConfig()
},
onDestroy() {
console.info('SystemUI statusBar Application onDestroy')
console.info('SystemUI navigationBar Application onDestroy')
},
}
}
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2021 Huawei Device Co., Ltd.
* Copyright (c) 2021-2022 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
@@ -14,8 +14,8 @@
*/
import display from '@ohos.display';
import Log from '../../../../../../../common/src/main/ets/default/Log.ets';
import ResourceUtil from '../../../../../../../common/src/main/ets/default/ResourceUtil.ets';
import Log from '../../../../../../../../common/src/main/ets/default/Log';
import ResourceUtil from '../../../../../../../../common/src/main/ets/default/ResourceUtil';
const TAG = 'NavBarConfiguration';
var directionNav;
@@ -46,13 +46,14 @@ enum Position {
class NavBarConfiguration {
async initNavBarConfiguration() {
Log.showInfo(TAG, 'initNavBarConfiguration');
minHeight = AppStorage.SetAndLink("minNavHeight", 0);
minHeight = 0;
await display.getDefaultDisplay()
.then(dis => {
Log.showInfo(TAG, `initNavBarConfiguration dis ${JSON.stringify(dis)}`);
maxWidth = dis.width;
maxHeight = dis.height;
Log.showInfo(TAG, `initNavBarConfiguration maxWidth ${maxWidth} maxHeight ${maxHeight} minHeight ${minHeight.get()}`);
Log.showInfo(TAG, `initNavBarConfiguration maxWidth ${maxWidth} maxHeight ${maxHeight} minHeight ${minHeight}`);
})
}
@@ -94,9 +95,10 @@ class NavBarConfiguration {
await this.getDirectionAndPosition();
let showNavHorizontal = false;
if (navbarPosition == Position.TOP_POSITION || navbarPosition == Position.BOTTOM_POSITION) {
AppStorage.Set("showNavHorizontal", true);
minHeight.set(parseInt(navShortSideLength));
showNavHorizontal = true;
minHeight = parseInt(navShortSideLength);
Log.showInfo(TAG, 'TOP_POSITION = ' + 2);
if (statusbarPosition == Position.LEFT_POSITION || statusbarPosition == Position.RIGHT_POSITION) {
realWidth = parseInt(maxWidth) - parseInt(statusShortSideLength);
@@ -117,8 +119,8 @@ class NavBarConfiguration {
Log.showInfo(TAG, 'BOTTOM_POSITION = ' + yCoordinate);
}
} else if (navbarPosition == Position.LEFT_POSITION || navbarPosition == Position.RIGHT_POSITION) {
AppStorage.Set("showNavHorizontal", false);
minHeight.set(parseInt(navShortSideLength));
showNavHorizontal = false;
minHeight = parseInt(navShortSideLength);
if (statusbarPosition == Position.TOP_POSITION || statusbarPosition == Position.BOTTOM_POSITION) {
realHeight = parseInt(maxHeight) - parseInt(statusShortSideLength);
} else {
@@ -140,6 +142,10 @@ class NavBarConfiguration {
Log.showInfo(TAG, `initWindowManager xCoordinate ${xCoordinate} yCoordinate ${yCoordinate}`);
Log.showInfo(TAG, `initWindowManager realWidth ${realWidth} realHeight ${realHeight}`);
var configuration = {
maxWidth: maxWidth,
maxHeight: maxHeight,
minHeight: minHeight,
showNavHorizontal: showNavHorizontal,
realWidth: realWidth,
realHeight: realHeight,
xCoordinate: xCoordinate,
@@ -0,0 +1,33 @@
/*
* Copyright (c) 2021-2022 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 StyleManager from '../../../../../../../../common/src/main/ets/default/StyleManager';
const TAG = 'NavigationBar-StyleConfiguration';
export default class StyleConfiguration {
static getKeyButtonStyle() {
const key: string = TAG + "-KeyButton";
return StyleManager.getStyle(key, () => {
return {
buttonWidth: $r('app.float.navigation_bar_button_width'),
buttonHeight: $r('app.float.navigation_bar_button_height'),
buttonBorderRadius: $r('app.float.navigation_bar_button_radius'),
buttonIconWidth: $r('app.float.navigation_bar_button_icon_width'),
buttonIconHeight: $r('app.float.navigation_bar_button_icon_height'),
};
});
}
}
@@ -0,0 +1,77 @@
/*
* Copyright (c) 2021-2022 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 Log from '../../../../../../../../common/src/main/ets/default/Log';
import AbilityManager from '../../../../../../../../common/src/main/ets/default/abilitymanager/abilityManager';
import StyleConfiguration from './StyleConfiguration'
const TAG = 'StatusBar-StyleManager';
export default class StyleManager {
static PAD_STANDARD_DISPLAY_WIDTH: number = 1280;
static PAD_STANDARD_DISPLAY_HEIGHT: number = 800;
static PHONE_STANDARD_DISPLAY_WIDTH: number = 720;
static PHONE_STANDARD_DISPLAY_HEIGHT: number = 1280;
static maxWidth: number = StyleManager.PAD_STANDARD_DISPLAY_WIDTH;
static rumMode: string = 'pad';
static setPadStyle() {
Log.showInfo(TAG, `setPadStyle`)
let config = AbilityManager.getAbilityData(AbilityManager.ABILITY_NAME_NAVIGATION_BAR, 'config');
StyleManager.maxWidth = config.maxWidth;
StyleManager.rumMode = 'pad'
// keyButton
{
let style: any = StyleConfiguration.getKeyButtonStyle();
style.buttonWidth = StyleManager.calcScaleSizePx(88);
style.buttonHeight = StyleManager.calcScaleSizePx(44);
style.buttonBorderRadius = StyleManager.calcScaleSizePx(22);
style.buttonIconWidth = StyleManager.calcScaleSizePx(15);
style.buttonIconHeight = StyleManager.calcScaleSizePx(15);
}
}
static setPhoneStyle() {
Log.showInfo(TAG, `setPhoneStyle`)
let config = AbilityManager.getAbilityData(AbilityManager.ABILITY_NAME_NAVIGATION_BAR, 'config');
StyleManager.maxWidth = config.maxWidth;
StyleManager.rumMode = 'phone'
// keyButton
{
let style: any = StyleConfiguration.getKeyButtonStyle();
style.buttonWidth = StyleManager.calcScaleSizePx(144);
style.buttonHeight = StyleManager.calcScaleSizePx(72);
style.buttonBorderRadius = StyleManager.calcScaleSizePx(36);
style.buttonIconWidth = StyleManager.calcScaleSizePx(24);
style.buttonIconHeight = StyleManager.calcScaleSizePx(24);
}
}
static number2px(n: number): string {
return n.toString() + 'px';
}
static calcScaleSize(n: number): number {
return n * StyleManager.maxWidth / (StyleManager.rumMode == 'pad' ? StyleManager.PAD_STANDARD_DISPLAY_WIDTH : StyleManager.PHONE_STANDARD_DISPLAY_WIDTH);
}
static calcScaleSizePx(n: number): string {
return StyleManager.number2px(StyleManager.calcScaleSize(n));
}
}
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2021 Huawei Device Co., Ltd.
* Copyright (c) 2021-2022 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
@@ -24,7 +24,10 @@ class Constants{
static THREE_TEMPLATE: string = '1fr 1fr 1fr';
static ONE_ICON_LAYOUT: number = 1;
static THREE_ICON_LAYOUT: number = 3;
static IMAGE_WIDTH: number = 32;
static IMAGE_HEIGHT: number = 32;
static BUTTON_WIDTH: number = 100;
}
}
export class NavigationBarComponentData {
isEnable: boolean = true;
backgroundColor: string = "#00000000";
contentColor: string = "#FFFFFFFF";
}
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2021 Huawei Device Co., Ltd.
* Copyright (c) 2021-2022 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
@@ -13,10 +13,10 @@
* limitations under the License.
*/
import Fileio from '@ohos.fileio';
import Log from '../../../../../../../../common/src/main/ets/default/Log.ets'
import Log from '../../../../../../../../../common/src/main/ets/default/Log'
const DEFAULT_LAYOUT_INFO_FILE_PATH = "/data/accounts/account_0/applications/com.ohos.systemui/" +
"com.ohos.systemui.navigationbar/assets/navigationBar/resources/rawfile/navigationBarLayoutConfig.json";
"com.ohos.systemui.navigationbar/assets/default_navigationBar/resources/rawfile/navigationBarLayoutConfig.json";
const READ_DATA_SIZE = 4096;
const TAG = "ConfigReader";
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2021 Huawei Device Co., Ltd.
* Copyright (c) 2021-2022 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
@@ -13,13 +13,16 @@
* limitations under the License.
*/
import Three from './threeLayout.ets'
import Log from '../../../../../../../common/src/main/ets/default/Log.ets';
import HeightConfigUtils from '../../../../../../../common/src/main/ets/default/heightcofigUtils/HeightConfigUtils.ets';
import Three from './threeLayout'
import Log from '../../../../../../../../common/src/main/ets/default/Log';
import AbilityManager from '../../../../../../../../common/src/main/ets/default/abilitymanager/abilityManager'
import CommonStyleManager from '../../../../../../../../common/src/main/ets/default/StyleManager'
import NavigationBarViewModel from '../viewmodel/NavigationBarViewModel';
import {NavigationBarComponentData} from '../common/constants'
import StyleManager from '../common/StyleManager'
const STORAGE_NAVIGATION_TYPE = 'navigationType'
let mHeightConfigUtils;
const TAG = 'NavigationBar-Index';
@Entry
@@ -28,6 +31,7 @@ struct Index {
@StorageLink('navigationLayoutConfig') mConfig: any = {}
@StorageLink('minNavHeight') minNavHeight: number = 32
@StorageLink("showNavHorizontal") showNavHorizontal: boolean = true
@State mNavigationBarComponentData: NavigationBarComponentData = new NavigationBarComponentData()
onBackPress(): boolean {
@@ -36,12 +40,24 @@ struct Index {
aboutToAppear() {
Log.showInfo(TAG, `aboutToAppear Start`)
let NavCoefficient = AppStorage.SetAndLink("NavCoefficient", 1.0);
NavCoefficient.set(mHeightConfigUtils.getNavHCoefficient());
setAppBgColor('#00000000')
CommonStyleManager.setAbilityPageName(TAG)
let configInfo = AbilityManager.getAbilityData(AbilityManager.ABILITY_NAME_NAVIGATION_BAR, 'config')
if (configInfo.maxWidth > configInfo.maxHeight) { // Pad、PC Mode
StyleManager.setPadStyle()
} else { // Phone Mode
StyleManager.setPhoneStyle()
}
let navigationBarViewModelInstance = NavigationBarViewModel.getInstance();
navigationBarViewModelInstance.install();
this.mNavigationBarComponentData = navigationBarViewModelInstance.getNavigationBarComponentData();
}
aboutToDisappear() {
Log.showInfo(TAG, `aboutToDisAppear`)
NavigationBarViewModel.getInstance().uninstall()
}
build() {
@@ -51,7 +67,7 @@ struct Index {
.width('100%')
.height('100%')
.constraintSize({ minHeight: this.minNavHeight + 'px'})
.backgroundColor($r('app.color.index_background'))
.backgroundColor(this.mNavigationBarComponentData.backgroundColor)
.padding(this.showNavHorizontal ? { left: '18%', right: '18%' } : { top: '18%', bottom: '18%' })
}
}
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2021 Huawei Device Co., Ltd.
* Copyright (c) 2021-2022 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
@@ -13,10 +13,12 @@
* limitations under the License.
*/
import keyCodeEvent from '../../../../../../../features/navigationservice/src/main/ets/com/ohos/navigationservice/KeyCodeEvent.ets';
import Log from '../../../../../../../common/src/main/ets/default/Log.ets';
import Constants from '../common/constants.ets'
import keyCodeEvent from '../../../../../../../../features/navigationservice/src/main/ets/com/ohos/navigationservice/KeyCodeEvent';
import Log from '../../../../../../../../common/src/main/ets/default/Log';
import Constants from '../common/constants'
import StyleConfiguration from '../common/StyleConfiguration'
import NavigationBarViewModel from '../viewmodel/NavigationBarViewModel';
import {NavigationBarComponentData} from '../common/constants'
const TAG = 'NavigationBar-KeyButton';
@@ -26,8 +28,10 @@ export default struct keyButton {
private uri: any;
@Prop keyCode: number;
@State backGroundColor: any = $r('app.color.button_default_background');
@StorageLink('NavCoefficient') NavCoefficient:number = 1.0
@StorageLink("showNavHorizontal") showNavHorizontal: boolean = AppStorage.SetAndLink("showNavHorizontal", true).get();
@State mNavigationBarComponentData: NavigationBarComponentData = NavigationBarViewModel.getInstance()
.getNavigationBarComponentData()
@State style: any = StyleConfiguration.getKeyButtonStyle()
aboutToAppear() {
Log.showInfo(TAG, `aboutToAppear Start`)
@@ -40,17 +44,21 @@ export default struct keyButton {
build() {
Stack({ alignContent: Alignment.Center }) {
Flex() {}
.borderRadius($r('app.float.button_radius'))
.borderRadius(this.style.buttonBorderRadius)
.width('100%')
.height('100%')
.backgroundColor(this.backGroundColor)
Image(this.uri)
.objectFit(ImageFit.Contain)
.size({ width: Constants.IMAGE_WIDTH*this.NavCoefficient, height:Constants.IMAGE_HEIGHT*this.NavCoefficient })
.size({
width: this.style.buttonIconWidth,
height: this.style.buttonIconHeight
})
.fillColor(this.mNavigationBarComponentData.contentColor)
}
.onTouch(this.onKeyTouch.bind(this))
.width(this.showNavHorizontal ? Constants.BUTTON_WIDTH*this.NavCoefficient : '100%')
.height(this.showNavHorizontal ? '100%' : Constants.BUTTON_WIDTH*this.NavCoefficient )
.width(this.showNavHorizontal ? this.style.buttonWidth : this.style.buttonHeight)
.height(this.showNavHorizontal ? this.style.buttonHeight : this.style.buttonWidth)
}
private onKeyTouch(event:TouchEvent) {
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2021 Huawei Device Co., Ltd.
* Copyright (c) 2021-2022 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
@@ -13,14 +13,14 @@
* limitations under the License.
*/
import keyButton from './keyButton.ets';
import Constants from '../common/constants.ets'
import Log from '../../../../../../../common/src/main/ets/default/Log.ets';
import keyButton from './keyButton';
import Constants from '../common/constants'
import Log from '../../../../../../../../common/src/main/ets/default/Log';
const TAG = 'NavigationBar-OneLayout';
let KeyCodeArr: any[] = [
{
"uri": $r('app.media.ic_navigation_home'),
"uri": $r('app.media.ic_systemui_home'),
"keyCode": Constants.KEYCODE_HOME
}];
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2021 Huawei Device Co., Ltd.
* Copyright (c) 2021-2022 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
@@ -13,22 +13,22 @@
* limitations under the License.
*/
import keyButton from './keyButton.ets';
import Constants from '../common/constants.ets'
import Log from '../../../../../../../common/src/main/ets/default/Log.ets';
import keyButton from './keyButton';
import Constants from '../common/constants'
import Log from '../../../../../../../../common/src/main/ets/default/Log';
const TAG = 'NavigationBar-ThreeLayout';
let KeyCodeArr: any[] = [
{
"uri": $r('app.media.ic_navigation_back'),
"uri": $r('app.media.ic_systemui_back'),
"keyCode": Constants.KEYCODE_BACK
},
{
"uri": $r('app.media.ic_navigation_home'),
"uri": $r('app.media.ic_systemui_home'),
"keyCode": Constants.KEYCODE_HOME
},
{
"uri": $r('app.media.ic_navigation_recent'),
"uri": $r('app.media.ic_systemui_recent'),
"keyCode": Constants.KEYCODE_RECENT
}];
@@ -50,7 +50,9 @@ struct threeLayout {
Grid() {
ForEach(KeyCodeArr, (item: any) => {
GridItem() {
keyButton({ uri: item.uri, keyCode: item.keyCode })
Row() {
keyButton({ uri: item.uri, keyCode: item.keyCode })
}.height('100%')
}
.height('100%')
.constraintSize({ minHeight: this.minNavHeight + 'px'})
@@ -64,7 +66,9 @@ struct threeLayout {
Grid() {
ForEach(KeyCodeArr, (item: any) => {
GridItem() {
keyButton({ uri: item.uri, keyCode: item.keyCode })
Column() {
keyButton({ uri: item.uri, keyCode: item.keyCode })
}.width('100%')
}
.width('100%')
.constraintSize({ minHeight: this.minNavHeight + 'px'})
@@ -0,0 +1,158 @@
/*
* Copyright (c) 2021-2022 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 Log from '../../../../../../../../common/src/main/ets/default/Log';
import WindowManager, { WindowType } from '../../../../../../../../common/src/main/ets/default/WindowManager';
import getSingleInstance from '../../../../../../../../common/src/main/ets/default/SingleInstanceHelper';
import TintStateManager, {TintState, TintStateListener
} from '../../../../../../../../common/src/main/ets/default/TintStateManager';
import {NavigationBarComponentData} from '../common/constants';
import featureAbility from '@ohos.ability.featureAbility';
import settings from '@ohos.settings';
import AbilityManager from '../../../../../../../../common/src/main/ets/default/abilitymanager/abilityManager';
import CommonConstants from "../../../../../../../../common/src/main/ets/default/Constants";
const TAG = 'NavigationBarViewModel';
const NAVIGATION_BAE_VIEW_MODEL_KEY = 'AppStorage_NavigationBarViewModel';
const NavigationBarComponentDataKey = 'AppStorage_NavigationBarComponentData';
export default class NavigationBarViewModel {
private settingDataKey = 'settings.display.navigationbar_status';
private urivar: string = null;
private helper: any = null;
private navigationBarStatusDefaultValue: string = '1';
private isDisplay = true;
mNavigationBarComponentData?: NavigationBarComponentData = {
...new NavigationBarComponentData()
};
mUseCount?: number = 0;
static getInstance(): NavigationBarViewModel {
return getSingleInstance(NavigationBarViewModel, NAVIGATION_BAE_VIEW_MODEL_KEY);
}
constructor() {
this.mNavigationBarComponentData =
AppStorage.SetAndLink(NavigationBarComponentDataKey, this.mNavigationBarComponentData).get()
this.urivar = settings.getUriSync(this.settingDataKey);
this.helper = featureAbility.acquireDataAbilityHelper(AbilityManager.getContext(), CommonConstants.URI_VAR);
this.initNavigationBarStatus();
}
install?() {
Log.showInfo(TAG, `install, useCount: ${this.mUseCount}`);
if (!this.mUseCount) {
TintStateManager.getInstance().registerListener('navigation', this as TintStateListener);
}
this.mUseCount++;
}
uninstall?() {
Log.showInfo(TAG, `uninstall, useCount: ${this.mUseCount}`);
this.mUseCount--;
if (this.mUseCount) {
TintStateManager.getInstance().unregisterListener('navigation');
}
}
getNavigationBarComponentData?(): NavigationBarComponentData {
Log.showInfo(TAG, `getNavigationBarComponentData`)
return this.mNavigationBarComponentData;
}
onTintStateChange?(tintState: TintState) {
Log.showInfo(TAG, `onTintStateChange, tintState: ${JSON.stringify(tintState)}`)
if (typeof (tintState.isEnable) == 'boolean') {
this.setWindowEnable(tintState.isEnable);
}
if (tintState.backgroundColor) {
this.mNavigationBarComponentData.backgroundColor = tintState.backgroundColor;
}
if (tintState.contentColor) {
this.mNavigationBarComponentData.contentColor = tintState.contentColor;
}
Log.showInfo(TAG, `onTintStateChange, backgroundColor ${this.mNavigationBarComponentData.backgroundColor}`);
Log.showInfo(TAG, `onTintStateChange, contentColor ${this.mNavigationBarComponentData.contentColor}`);
}
setWindowEnable?(isEnable: boolean) {
Log.showInfo(TAG, `setWindowEnable, isEnable ${isEnable}`);
if (this.mNavigationBarComponentData.isEnable == isEnable) {
return;
}
this.mNavigationBarComponentData.isEnable = isEnable;
if (isEnable && this.isDisplay) {
WindowManager.showWindow(WindowType.NAVIGATION_BAR);
} else {
WindowManager.hideWindow(WindowType.NAVIGATION_BAR);
}
}
private setValue(value: string) {
settings.setValueSync(this.helper, this.settingDataKey, value);
}
private getValue(defaultValue?: string) {
return settings.getValueSync(
this.helper, this.settingDataKey, defaultValue ? defaultValue : this.navigationBarStatusDefaultValue
);
}
private registerListenForDataChanges(callback) {
this.helper.on("dataChange", this.urivar, (data) => {
callback(data);
})
}
/**
* Initialize the NavigationBar status.
*/
public initNavigationBarStatus() {
try {
let initValue = this.getValue();
Log.showInfo(TAG, `initNavigationBarStatus initValue ${initValue}`);
this.windowSwitches(initValue);
this.registerListenForDataChanges(this.dataChangesCallback.bind(this));
} catch (e) {
Log.showInfo(TAG, `initNavigationBarStatus error: ${e.toString()}`);
}
}
/**
* Get NavigationBar status data.
* @return
*/
public dataChangesCallback(data: any) {
if (data.code !== 0) {
Log.showInfo(TAG, `dataChangesCallback failed, because ${data.message}`);
return;
} else {
let getRetValue = this.getValue();
Log.showInfo(TAG, `dataChangesCallback initValue ${getRetValue}`);
this.windowSwitches(getRetValue);
}
}
private windowSwitches(navigationBarStatusValue) {
this.isDisplay = navigationBarStatusValue == '1' ? true : false;
if (!this.isDisplay) {
WindowManager.hideWindow(WindowType.NAVIGATION_BAR);
} else {
WindowManager.showWindow(WindowType.NAVIGATION_BAR);
}
}
}
@@ -1,9 +1,5 @@
{
"color": [
{
"name": "index_background",
"value": "#66000000"
},
{
"name": "button_default_background",
"value": "#00000000"
@@ -0,0 +1,24 @@
{
"float": [
{
"name": "navigation_bar_button_width",
"value": "144vp"
},
{
"name": "navigation_bar_button_height",
"value": "72vp"
},
{
"name": "navigation_bar_button_radius",
"value": "36vp"
},
{
"name": "navigation_bar_button_icon_width",
"value": "24vp"
},
{
"name": "navigation_bar_button_icon_height",
"value": "24vp"
}
]
}
@@ -2,11 +2,11 @@
"string": [
{
"name": "nav_bar_size_portrait",
"value": "102"
"value": "72"
},
{
"name": "nav_bar_size_landscape",
"value": "102"
"value": "72"
},
{
"name": "nav_bar_position_portrait",
@@ -22,11 +22,11 @@
},
{
"name": "status_bar_size_portrait",
"value": "102"
"value": "48"
},
{
"name": "status_bar_size_landscape",
"value": "102"
"value": "48"
},
{
"name": "status_bar_position_portrait",
@@ -0,0 +1,10 @@
<svg class="icon"
viewBox="0 0 1024 1024"
version="1.1"
xmlns="http://www.w3.org/2000/svg"
width="24"
height="24">
<path
d="m863.26281,972.288a33.34135,25.664 0 0 1 -20.70323,-5.568l-709.39742,-435.456c-7.89882,-4.864 -12.55497,-12.224 -12.47182,-20.032s4.65615,-15.168 12.55497,-20.032l709.39742,-433.92a33.17506,25.536 0 0 1 53.96143,20.032l0,869.44a33.17506,25.536 0 0 1 -33.2582,25.6l-0.08315,-0.064zm-655.93485,-460.992l624.66646,382.272l-1.90666,-763.264l-622.7598,380.928l0,0.064z"
fill="#ffffff"></path>
</svg>

After

Width:  |  Height:  |  Size: 563 B

@@ -0,0 +1,10 @@
<svg class="icon"
viewBox="0 0 1024 1024"
version="1.1"
xmlns="http://www.w3.org/2000/svg"
width="24"
height="24">
<path
d="M512 998.4C243.776 998.4 25.6 780.224 25.6 512S243.776 25.6 512 25.6s486.4 218.176 486.4 486.4-218.176 486.4-486.4 486.4zM512 76.8C272 76.8 76.8 272 76.8 512s195.2 435.2 435.2 435.2 435.2-195.2 435.2-435.2S752 76.8 512 76.8z"
fill="#ffffff"></path>
</svg>

After

Width:  |  Height:  |  Size: 424 B

@@ -0,0 +1,10 @@
<svg class="icon"
viewBox="0 0 1024 1024"
version="1.1"
xmlns="http://www.w3.org/2000/svg"
width="24"
height="24">
<path
d="M923.072 972.8H100.992a49.856 49.856 0 0 1-49.792-49.728V100.992c0-27.456 22.336-49.792 49.792-49.792h822.08c27.456 0 49.792 22.336 49.792 49.792v822.08a49.856 49.856 0 0 1-49.728 49.792zM921.6 100.992L100.992 102.4 102.4 923.072l819.2-1.472V100.992z"
fill="#ffffff"></path>
</svg>

After

Width:  |  Height:  |  Size: 450 B

Before

Width:  |  Height:  |  Size: 6.6 KiB

After

Width:  |  Height:  |  Size: 6.6 KiB

@@ -2,11 +2,11 @@
"string": [
{
"name": "nav_bar_size_portrait",
"value": "102"
"value": "72"
},
{
"name": "nav_bar_size_landscape",
"value": "102"
"value": "72"
},
{
"name": "nav_bar_position_portrait",
@@ -22,11 +22,11 @@
},
{
"name": "status_bar_size_portrait",
"value": "102"
"value": "48"
},
{
"name": "status_bar_size_landscape",
"value": "102"
"value": "48"
},
{
"name": "status_bar_position_portrait",

Some files were not shown because too many files have changed in this diff Show More