Signed-off-by: zhuchengfeng <940848916@qq.com>
This commit is contained in:
zhuchengfeng 2022-04-11 14:46:45 +08:00
parent a1eceab582
commit ec8944a7b3
224 changed files with 8051 additions and 3919 deletions

2
.gitignore vendored
View File

@ -7,8 +7,8 @@
/features/shortcutcomponent/build/
/features/wallpapercomponent/build/
/features/noticeitem/build/
/features/notificationservice/build/
/features/screenlock/build/
/.idea
/.gradle
local.properties
tsconfig.json

View File

@ -67,8 +67,6 @@
<filteritem type="filepath" name="features/noticeitem/src/main/resources/base/media/.*.png" desc="self developed image"/>
<filteritem type="filepath" name="features/notificationservice/src/main/resources/base/media/.*.png" desc="self developed image"/>
<filteritem type="filepath" name="features/screenlock/src/main/resources/base/media/.*.png" desc="self developed image"/>
<filteritem type="filepath" name="product/pc/src/main/resources/base/media/.*.png" desc="self developed image"/>

View File

@ -3,7 +3,7 @@
## 简介
### 内容介绍
锁屏应用是OpenHarmony中预置的系统应用为用户提供锁屏的基础能力提供滑动解锁、密码解锁等解锁能力,以及锁屏页面的信息展示能力。
锁屏应用是OpenHarmony中预置的系统应用为用户提供锁屏的基础能力提供滑动解锁、密码解锁等解锁能力,以及锁屏页面的信息展示能力。
### 架构图介绍
@ -11,29 +11,25 @@
feature
```
1.在开机流程、亮屏流程、灭屏流程中添加加锁流程及所对应的解锁流程,实现和系统的交互。\
2.通过时间日期组件、通知组件、状态栏组件、lockIcon和快捷开关组件实现不要的信息展示。\
1.在开机流程、亮屏流程、灭屏流程中添加加锁流程及所对应的解锁流程,实现与系统交互。\
2.通过时间日期组件、通知组件、状态栏组件、lockIcon和快捷开关组件实现相关的信息展示。\
3.支持数字解锁、图案解锁、人脸解锁和密码混合解锁。
```
common
```
通用接口,实现日志打印,外部接口管理等功能
通用接口,实现日志打印,外部接口管理等功能
```
## 目录
```
/applications/standard/screenlock
├── build.gradle # 全局编译配置文件
├── settings.gradle # 编译模块配置文件
├── LICENSE # 许可文件
├── common # 通用工具类目录
├── signature # 证书文件目录
├── entry # entry模块目录
├── features # 子组件目录
│ ├── batterycomponent # 电池组件
│ ├── clockcomponent # 时钟组件
│ ├── datetimecomponent # 日期时间组件
│ ├── shortcutcomponent # 快捷开关组件
│ ├── wallpapercomponent # 壁纸组件
│ ├── noticeitem # 通知子组件
│ ├── notificationservice # 通知服务组件
│ ├── screenlock # 锁屏组件
@ -41,11 +37,18 @@ common
│ ├── model # 数据管理
│ ├── view # 组件样式管理
│ ├── vm # 数据样式绑定管理
│ ├── shortcutcomponent # 快捷开关组件
│ ├── wallpapercomponent # 壁纸组件
│ ├── wificomponent # wifi组件
├── product # 锁屏总体功能目录
│ ├── pc # 模块目录
│ ├── pages/slidesrceenlock # 滑动锁屏
│ ├── phone # 模块目录
│ ├── pages/slidesrceenlock # 滑动锁屏
├── signature # 证书文件目录
├── build.gradle # 全局编译配置文件
├── LICENSE # 许可文件
├── settings.gradle # 编译模块配置文件
```
## 相关仓

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

View File

@ -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.
*/
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';
export default class Constants {
static URI_VAR: string = 'dataability:///com.ohos.settingsdata.DataAbility';
}

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

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

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
@ -14,19 +14,34 @@
*/
const TAG = 'ScreenLock-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}`);
}
}

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,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;

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
@ -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';
import FileIo from '@ohos.fileio';
const TAG = 'ScreenLock-ScreenLockCommon';
@ -21,7 +21,9 @@ const CHAR_CODE_AT_INDEX = 0;
export enum ScreenLockStatus {
Locking = 1,
Unlock = 2
Unlock = 2,
RecognizingFace = 3,
FaceNotRecognized = 4
}
export function ReadConfigFile(fileName) {

View File

@ -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;

View File

@ -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];
}

View File

@ -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',
};
});
}
}

View File

@ -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;

View File

@ -0,0 +1,107 @@
/*
* 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 = 50 * 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 Promise.reject("Can't get active userInfo.");
}
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.mHasWait && (await new Promise((resolve) => setTimeout(resolve, DELAY_TIME)));
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));
}
}

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;

View File

@ -1,87 +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';
const TAG = 'WindowManager';
//const STATUS_BAR_H = 0.07;
const STATUS_BAR_H = 0.03;
var maxWidth;
var maxHeight;
var minHeight;
var quicklySettingH;
var notificationH;
/**
* Manage window size changes.
*/
export default class WindowManager {
initWindowManager() {
Log.showInfo(TAG, 'initWindowManager ');
maxWidth = AppStorage.SetAndLink("maxWidth", 0);
maxHeight = AppStorage.SetAndLink("maxHeight", 0);
minHeight = AppStorage.SetAndLink("minHeight", 0);
display.getDefaultDisplay()
.then(dis => {
maxWidth.set(dis.width);
maxHeight.set(dis.height);
minHeight.set(this.getStatusBarDefaultHeight(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) => {
windowData.resetSize(maxWidth.get(), maxHeight.get())
.then((result) => {
Log.showInfo(TAG, result);
callback(result);
});
});
}
/**
* Set the window to the minimum size.
*
* @param {Object} callback - Callback function.
*/
setWindowMin(callback) {
Log.showInfo(TAG, 'enter setWindowMin =================');
Window.getTopWindow()
.then((windowData) => {
windowData.resetSize(maxWidth.get(), minHeight.get())
.then((result) => {
Log.showInfo(TAG, result);
callback(result);
});
});
}
getStatusBarDefaultHeight(maxheight) {
return parseInt((maxheight * STATUS_BAR_H).toString())
}
}

View File

@ -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 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);
}
// function need remove
setWindowInfo(configInfo) {
Log.showInfo(TAG, `setWindowInfo, configInfo ${JSON.stringify(configInfo)}`);
let maxWidth = AppStorage.SetAndLink("maxWidth", configInfo.maxWidth);
let maxHeight = AppStorage.SetAndLink("maxHeight", configInfo.maxHeight);
let minHeight = AppStorage.SetAndLink("minHeight", configInfo.minHeight);
maxWidth.set(configInfo.maxWidth);
maxHeight.set(configInfo.maxHeight);
minHeight.set(configInfo.minHeight);
}
}
let sWindowManager = createOrGet(WindowManager, TAG);
export default sWindowManager as WindowManager;

View File

@ -0,0 +1,68 @@
/*
* 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_SCREEN_LOCK = 'SystemUi_ScreenLock';
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);
})
}
}

View File

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

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
@ -14,14 +14,14 @@
*/
import FeatureAbility from '@ohos.ability.featureAbility';
import Log from '../Log.ets';
import Log from '../Log';
const TAG = 'FeatureAbilityManager';
export default class FeatureAbilityManager {
openAbility(tag, want) {
Log.showInfo(TAG, `openAbility from: ${tag}`);
Log.showInfo(TAG, `openAbility from: ${tag}`));
let result = FeatureAbility.startAbility(want)
.then(data =>
Log.showInfo(TAG, `tag: ${tag} promise then: ${JSON.stringify(data)}`))

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
@ -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';
@ -27,27 +27,27 @@ export default class NotificationManager {
static TYPE_MULTI: number = Notification.ContentType.NOTIFICATION_CONTENT_MULTILINE;
static subscribeNotification(tag, subscriber, asyncCallback) {
Log.showInfo(TAG, `subscribeNotification from: ${tag}`);
Log.showInfo(TAG, `subscribeNotification from: ${tag}`));
Notification.subscribe(subscriber, asyncCallback);
}
static unsubscribeNotification(tag, subscriber) {
Log.showInfo(TAG, `subscribeNotification from: ${tag}`);
Log.showInfo(TAG, `subscribeNotification from: ${tag}`));
Notification.unsubscribe(subscriber);
}
static removeAll(tag, callback) {
Log.showInfo(TAG, `removeAll from: ${tag}`);
Log.showInfo(TAG, `removeAll from: ${tag}`));
Notification.removeAll(callback);
}
static remove(tag, hashCode, callback) {
Log.showInfo(TAG, `remove from: ${tag}`);
Log.showInfo(TAG, `remove from: ${tag}`));
Notification.remove(hashCode, callback)
}
static getAllActiveNotifications(tag, callback) {
Log.showInfo(TAG, `getAllActiveNotifications from: ${tag}`);
Log.showInfo(TAG, `getAllActiveNotifications from: ${tag}`));
Notification.getAllActiveNotifications(callback);
}

View File

@ -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();
});
}

View File

@ -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,
};
}

View File

@ -0,0 +1,92 @@
/*
* 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 {
return false;
}
private publishCommonEvent(data: { [key: string]: any }): boolean {
return false;
}
}
let sEventManager = createOrGet(EventManager, TAG);
export default sEventManager as EventManager;

View File

@ -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;
}

View File

@ -14,7 +14,7 @@
*/
import AbilityStage from "@ohos.application.AbilityStage"
import Log from '../../../../common/src/main/ets/default/Log.ets'
import Log from '../../../../common/src/main/ets/default/Log'
const TAG = "MainAbilityStage"

View File

@ -1,48 +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 {
//layout params - Icon
static WHOLE_CONTAINER_MARGIN = 2
static WHOLE_CONTAINER_WIDTH = 100
static WHOLE_CONTAINER_HEIGHT = 24
static PIC_CONTAINER_WIDTH = '70%'
static PIC_CONTAINER_HEIGHT = '85%'
//layout params - Pic
static FULL_CONTAINER_WIDTH = '100%'
static FULL_CONTAINER_HEIGHT = '100%'
static BATTERY_BORDER_WIDTH = '88%'
static BATTERY_BORDER_HEIGHT = '80%'
static BATTERY_BORDER_RADIUS = 2
static BATTERY_BORDER_MARGIN = 2
static BATTERY_CONTENT_PADDING = 2
static BATTERY_DECORATOR_WIDTH = '10%'
static BATTERY_DECORATOR_HEIGHT = '50%'
static BATTERY_DECORATOR_MARGIN = 2
//layout params - Soc
static SOC_FONT_SIZE = 16
//value
static BATTERY_LEVEL_LOW = 20
static NONE = 0;
static ENABLE = 1;
static DISABLE = 2;
static FULL = 3;
static PERCENT_NUMBER = 100;
static DEFAULT_PROGRESS = 100;
}

View File

@ -1,152 +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 '../../../../../../common/src/main/ets/default/Log.ets';
import Constants from './common/constants.ets';
import BatteryInfo from '@ohos.batteryInfo';
import BatterySubscriber from '@ohos.commonEvent';
const TAG = 'BatteryComponent-batteryModel';
let mProgress = Constants.DEFAULT_PROGRESS;
let mBatteryEventSubscriber = null;
let mBatteryEventSubscribeInfo = {
events: ['usual.event.BATTERY_CHANGED']
}
var mBatterySoc;
var mBatteryCharging;
export class BatteryModel {
initBatteryModel() {
Log.showInfo(TAG, 'initBatteryModel');
mBatterySoc = AppStorage.SetAndLink('batterySoc', 0);
mBatteryCharging = AppStorage.SetAndLink('batteryCharging', false);
if (mBatteryEventSubscriber == null) {
this.registerBatteryListener();
}
this.getBatteryStatus();
}
uninitBatteryModel() {
Log.showInfo(TAG, 'uninitBatteryModel');
this.unregisterBatteryListener();
}
/**
* Subscribe Battery events
*/
private registerBatteryListener() {
Log.showInfo(TAG, 'registerBatteryListener start');
BatterySubscriber.createSubscriber(
mBatteryEventSubscribeInfo,
this.createBatterySubscriberCallBack.bind(this)
);
}
/**
* Unsubscribe wifi events
*
*/
private unregisterBatteryListener() {
Log.showInfo(TAG, 'unregisterBatteryListener');
BatterySubscriber.unsubscribe(mBatteryEventSubscriber, () => {
Log.showInfo(TAG, `unregister Battery Status Listener ===============`);
});
}
/**
* Callback of the subscriber
*
* @param {Object} err - error returns from the caller
* @param {Object} data - data returns from the caller
*/
private createBatterySubscriberCallBack(err, data) {
Log.showInfo(TAG, `Subscriberregister createBatterySubscriberCallBack err: ${JSON.stringify(err)} data: ${JSON.stringify(data)}`);
mBatteryEventSubscriber = data;
BatterySubscriber.subscribe(mBatteryEventSubscriber, this.batterySubscriberCallBack.bind(this));
}
/**
* Callback of the events
*
* @param {Object} err - error returns from the caller
* @param {Object} data - data returns from the caller
*/
private batterySubscriberCallBack(err, data) {
Log.showInfo(TAG, `batterySubscriberCallBack err: ${JSON.stringify(err)} data: ${JSON.stringify(data)}`);
if (err.code == 0) {
if (data.event == 'usual.event.BATTERY_CHANGED') {
this.getBatteryStatus();
}
} else {
Log.showInfo(TAG, 'Subscriberregister error when subscribing ========');
}
}
/**
* Get battery status and remaining power
*/
private getBatteryStatus() {
Log.showInfo(TAG,'getBatteryStatus')
let batterySoc = BatteryInfo.batterySOC;
let batteryCharging = BatteryInfo.chargingStatus;
if (null == batterySoc) {
// Set the battery Soc as full when there is no battery hardware
batterySoc = mProgress;
}
if (batterySoc <= 0) {
// If the result is a negative number, set it as positive number.
batterySoc = Math.abs(batterySoc) * Constants.PERCENT_NUMBER;
}
// Set the battery status as charging when there is no battery hardware
this.checkBatteryStatus(batteryCharging, (result) => {
let batteryStatus = result;
mBatterySoc.set(batterySoc);
mBatteryCharging.set(batteryStatus);
});
}
/**
* Check the battery charging status
*
* @param {number} charging - the battery charging status
* @param {object} callback - Function callback
*/
private checkBatteryStatus(charging, callback) {
Log.showInfo(TAG, `checkBatteryStatus charging: ${charging}`);
let batteryStatus;
switch (charging) {
case Constants.NONE:
batteryStatus = false;
break;
case Constants.DISABLE:
case Constants.ENABLE:
case Constants.FULL:
batteryStatus = true;
break;
default:
batteryStatus = false;
break;
}
callback(batteryStatus);
}
}
let mBatteryModel = new BatteryModel();
export default mBatteryModel as BatteryModel;

View File

@ -0,0 +1,99 @@
/*
* 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 BatteryInfo from "@ohos.batteryInfo";
import commonEvent from "@ohos.commonEvent";
import createOrGet from "../../../../../../common/src/main/ets/default/SingleInstanceHelper";
import Constants from "./common/constants";
import Log from "../../../../../../common/src/main/ets/default/Log";
import { CommonEventData } from "commonEvent/commonEventData";
import {
CommonEventManager,
getCommonEventManager,
POLICY,
} from "../../../../../../common/src/main/ets/default/commonEvent/CommonEventManager";
const TAG = "BatteryComponent-batteryModel";
const DEFAULT_PROGRESS = 100;
const SUBSCRIBE_INFO = {
events: [commonEvent.Support.COMMON_EVENT_BATTERY_CHANGED],
};
function getChargingStatus(state: typeof BatteryInfo.BatteryChargeState): boolean {
Log.showInfo(TAG, `charging status update: ${state}`);
let batteryStatus = false;
switch (state) {
case BatteryInfo.BatteryChargeState.DISABLE:
case BatteryInfo.BatteryChargeState.ENABLE:
case BatteryInfo.BatteryChargeState.FULL:
batteryStatus = true;
break;
default:
batteryStatus = false;
break;
}
return batteryStatus;
}
export class BatteryModel {
private mBatterySoc: any;
private mBatteryCharging: any;
private mManager?: CommonEventManager;
initBatteryModel() {
if (this.mManager) {
return;
}
this.mManager = getCommonEventManager(
TAG,
SUBSCRIBE_INFO,
() => this.updateBatteryStatus(),
(isSubscribe: boolean) => isSubscribe && this.updateBatteryStatus()
);
Log.showInfo(TAG, "initBatteryModel");
this.mBatterySoc = AppStorage.SetAndLink("batterySoc", 0);
this.mBatteryCharging = AppStorage.SetAndLink("batteryCharging", false);
this.mManager.subscriberCommonEvent();
this.mManager.applyPolicy([POLICY.SCREEN_POLICY]);
}
unInitBatteryModel() {
Log.showInfo(TAG, "unInitBatteryModel");
this.mManager?.release();
this.mManager = undefined;
}
/**
* Get battery status and remaining power
*/
private updateBatteryStatus() {
Log.showInfo(TAG, "updateBatteryStatus");
let batterySoc = BatteryInfo.batterySOC ?? DEFAULT_PROGRESS;
let batteryCharging = BatteryInfo.chargingStatus;
if (batterySoc <= 0) {
// If the result is a negative number, set it as positive number.
batterySoc = Math.abs(batterySoc) * Constants.PERCENT_NUMBER;
}
Log.showInfo(TAG, "batterySoc = " + batterySoc);
// Set the battery status as charging when there is no battery hardware
this.mBatterySoc.set(batterySoc);
this.mBatteryCharging.set(getChargingStatus(batteryCharging));
}
}
let mBatteryModel = createOrGet(BatteryModel, TAG);
export default mBatteryModel as BatteryModel;

View File

@ -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 StyleManager from '../../../../../../../common/src/main/ets/default/StyleManager';
import Constants from './Constants'
const TAG = 'battery-StyleConfiguration';
export default class StyleConfiguration {
static getBatteryComponentStyle() {
const key: string = TAG + "-BatteryComponent";
return StyleManager.getStyle(key, () => {
return {
componentGap: $r('app.float.battery_component_gap')
};
});
}
static getBatteryPicStyle() {
const key: string = TAG + "-BatteryPicComponent";
return StyleManager.getStyle(key, () => {
return {
picGap: $r('app.float.battery_component_pic_gap'),
picBodyWidth: $r('app.float.battery_component_pic_body_width'),
picBodyHeight: $r('app.float.battery_component_pic_body_height'),
picBodyPadding: $r('app.float.battery_component_pic_body_padding'),
picBodyBorderWidth: $r('app.float.battery_component_pic_body_border_width'),
picBorderRadius: $r('app.float.battery_component_pic_border_radius'),
picHeadBorderRadius: $r('app.float.battery_component_pic_head_radius'),
picChargingColor: $r('app.color.battery_component_pic_charging_color'),
picLevelLowColor: $r('app.color.battery_component_pic_level_low_color'),
picHeadWidth: $r('app.float.battery_component_pic_head_width'),
picHeadHeight: $r('app.float.battery_component_pic_head_height'),
};
});
}
}

View File

@ -1,48 +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 {
//layout params - Icon
static WHOLE_CONTAINER_MARGIN = 2
static WHOLE_CONTAINER_WIDTH = 100
static WHOLE_CONTAINER_HEIGHT = 24
static PIC_CONTAINER_WIDTH = '70%'
static PIC_CONTAINER_HEIGHT = '85%'
//layout params - Pic
static FULL_CONTAINER_WIDTH = '100%'
static FULL_CONTAINER_HEIGHT = '100%'
static BATTERY_BORDER_WIDTH = '88%'
static BATTERY_BORDER_HEIGHT = '80%'
static BATTERY_BORDER_RADIUS = 2
static BATTERY_BORDER_MARGIN = 2
static BATTERY_CONTENT_PADDING = 2
static BATTERY_DECORATOR_WIDTH = '10%'
static BATTERY_DECORATOR_HEIGHT = '50%'
static BATTERY_DECORATOR_MARGIN = 2
//layout params - Soc
static SOC_FONT_SIZE = 16
//value
static BATTERY_LEVEL_LOW = 20
static NONE = 0;
static ENABLE = 1;
static DISABLE = 2;
static FULL = 3;
static PERCENT_NUMBER = 100;
static DEFAULT_PROGRESS = 100;
}

View File

@ -0,0 +1,19 @@
/*
* 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 default class Constants {
static BATTERY_LEVEL_LOW = 20
static PERCENT_NUMBER = 100;
}

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,12 +13,16 @@
* limitations under the License.
*/
import mBatteryModel from '../batteryModel.ets';
import BatteryPic from './batteryPic.ets'
import mBatteryModel from '../batteryModel';
import BatteryPic from './batteryPic'
import BatterySoc from './batterySoc'
import Constants from '../common/constants.ets'
import Log from '../../../../../../../common/src/main/ets/default/Log.ets'
import Constants from '../common/constants'
import Log from '../../../../../../../common/src/main/ets/default/Log'
import StyleConfigurationCommon from '../../../../../../../common/src/main/ets/default/StyleConfiguration'
import StyleConfiguration from '../common/StyleConfiguration'
import {StatusBarGroupComponentData
} from '../../../../../../screenlock/src/main/ets/com/ohos/common/Constants'
import StatusBarVM from '../../../../../../screenlock/src/main/ets/com/ohos/vM/StatusBarVM'
const TAG = 'BatteryComponent-batteryIcon'
@ -26,34 +30,29 @@ const TAG = 'BatteryComponent-batteryIcon'
export default struct BatteryIcon {
@StorageLink('batterySoc') batterySoc: number = 100
@StorageLink('StatusCoefficient') StatusCoefficient: number = 1.0
private mGroupId: string = ''
@State mStatusBarGroupComponentData: StatusBarGroupComponentData = new StatusBarGroupComponentData()
@State style: any = StyleConfiguration.getBatteryComponentStyle()
@State styleCommon: any = StyleConfigurationCommon.getCommonStyle()
aboutToAppear() {
this.mStatusBarGroupComponentData = StatusBarVM.getStatusBarGroupComponentData(this.mGroupId)
mBatteryModel.initBatteryModel();
Log.showInfo(TAG, 'aboutToAppear');
}
aboutToDisappear() {
mBatteryModel.uninitBatteryModel();
Log.showInfo(TAG, 'aboutToDisappear');
}
build() {
Flex({ direction: FlexDirection.Row, alignItems: ItemAlign.Center, justifyContent: FlexAlign.Center }) {
Flex({ direction: FlexDirection.Row, alignItems: ItemAlign.Center, justifyContent: FlexAlign.End }) {
BatterySoc()
Row() {
Row().width(this.styleCommon.statusBarMarginLeftRight).height('100%')
BatterySoc({ mContentColor: this.mStatusBarGroupComponentData.contentColor })
Row().width(this.style.componentGap).height('100%')
BatteryPic({ mContentColor: this.mStatusBarGroupComponentData.contentColor })
Row().width(this.styleCommon.statusBarMarginLeftRight).height('100%')
}
Flex({ direction: FlexDirection.Row, alignItems: ItemAlign.Center, justifyContent: FlexAlign.Start }) {
BatteryPic()
}
// .width('70%')
// .height('100%')
.width('40%')
.height('42%')
.margin({right:$r('app.float.battery_margin')})
}
.width(Constants.WHOLE_CONTAINER_WIDTH * this.StatusCoefficient)
.height(Constants.WHOLE_CONTAINER_HEIGHT * this.StatusCoefficient)
.margin($r('app.float.whole_container_margin'))
.height('100%')
}
}

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,8 +13,10 @@
* limitations under the License.
*/
import Constants from '../common/constants.ets'
import Log from '../../../../../../../common/src/main/ets/default/Log.ets'
import Constants from '../common/constants'
import Log from '../../../../../../../common/src/main/ets/default/Log'
import StyleConfiguration from '../common/StyleConfiguration'
const TAG = 'BatteryComponent-batteryPic'
@Component
@ -22,6 +24,9 @@ export default
struct BatteryPic {
@StorageLink('batterySoc') batterySoc: number = 100
@StorageLink('batteryCharging') batteryCharging : boolean = false
@Prop mContentColor: string
@State style: any = StyleConfiguration.getBatteryPicStyle()
aboutToAppear(){
Log.showInfo(TAG,'aboutToAppear Start');
}
@ -32,45 +37,48 @@ struct BatteryPic {
build() {
Flex({ direction: FlexDirection.Row, alignItems: ItemAlign.Center, justifyContent: FlexAlign.Start }) {
Flex({ direction: FlexDirection.Row, alignItems: ItemAlign.Center, justifyContent: FlexAlign.Start }) {
Flex({ direction: FlexDirection.Row, alignItems: ItemAlign.Center, justifyContent: FlexAlign.Start }) {
Row() {
Row() {
Row() {
}
.height('100%')
.width(this.batterySoc + '%')
.width((this.batterySoc < 100 ? this.batterySoc: 100) + '%')
.backgroundColor(this.getBatteryColor(this.batterySoc, this.batteryCharging))
}
.width('88%')
.height('100%')
.width(this.style.picBodyWidth)
.height(this.style.picBodyHeight)
.backgroundColor($r('app.color.battery_background'))
.border({ width: $r('app.float.battery_border_width'),
color: $r('app.color.battery_border'),
radius: $r('app.float.battery_border_radius'),
.border({ width: this.style.picBodyBorderWidth,
color: this.mContentColor,
radius: this.style.picBorderRadius,
style: BorderStyle.Solid })
.padding($r('app.float.battery_content_padding'))
.padding(this.style.picBodyPadding)
Flex({ direction: FlexDirection.Row, alignItems: ItemAlign.Center, justifyContent: FlexAlign.Start }) {
Row() {
}
.width('10%')
.height('50%')
.backgroundColor($r('app.color.battery_border'))
.borderRadius($r('app.float.battery_border_radius'))
.margin({ left: $r('app.float.battery_decorator_margin') })
.width(this.style.picGap)
.height(1)
Row() {
}
.width(this.style.picHeadWidth)
.height(this.style.picHeadHeight)
.backgroundColor(this.mContentColor)
.borderRadius(this.style.picHeadBorderRadius)
}
.width('100%')
.height('100%')
}
private getBatteryColor(val, charging) {
Log.showInfo(TAG, `getBatteryColor, val: ${ val } charging: ${ charging } `);
if (charging) {
return $r('app.color.battery_charging_color');
return this.style.picChargingColor;
} else if (val <= Constants.BATTERY_LEVEL_LOW) {
return $r('app.color.battery_low_color');
return this.style.picLevelLowColor;
} else {
return $r('app.color.battery_default_color');
return this.mContentColor;
}
}
}

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,12 +13,16 @@
* limitations under the License.
*/
import Log from '../../../../../../../common/src/main/ets/default/Log.ets'
import Log from '../../../../../../../common/src/main/ets/default/Log'
import StyleConfigurationCommon from '../../../../../../../common/src/main/ets/default/StyleConfiguration'
const TAG = 'BatteryComponent-batterySoc'
@Component
export default
struct BatterySoc {
@StorageLink('batterySoc') batterySoc: number = 100
@Prop mContentColor: string
@State styleCommon: any = StyleConfigurationCommon.getCommonStyle()
aboutToAppear(){
Log.showInfo(TAG,'aboutToAppear Start');
@ -29,11 +33,8 @@ struct BatterySoc {
}
build() {
Flex({ direction: FlexDirection.Row, alignItems: ItemAlign.Center, justifyContent: FlexAlign.End }) {
Text(this.batterySoc + '%')
.height('100%')
.fontColor($r('app.color.battery_default_color'))
.fontSize($r('app.float.fontSize_network_state'))
}
.fontColor(this.mContentColor)
.fontSize(this.styleCommon.statusBarFontSize)
}
}

View File

@ -1,18 +1,14 @@
{
"color": [
{
"name": "battery_low_color",
"name": "battery_component_pic_level_low_color",
"value": "#ff0000"
},{
"name": "battery_default_color",
"value": "#ffffff"
},{
"name": "battery_charging_color",
},
{
"name": "battery_component_pic_charging_color",
"value": "#00ff21"
},{
"name": "battery_border",
"value": "#fff"
},{
},
{
"name": "battery_background",
"value": "#00000000"
}

View File

@ -1,36 +1,44 @@
{
"float": [
{
"name": "fontSize_network_state",
"value": "16"
"name": "battery_component_gap",
"value": "8.5vp"
},
{
"name": "whole_container_width",
"value": "100"
"name": "battery_component_pic_gap",
"value": "2vp"
},
{
"name": "whole_container_margin",
"value": "2"
"name": "battery_component_pic_body_height",
"value": "19vp"
},
{
"name": "battery_decorator_margin",
"value": "2"
"name": "battery_component_pic_body_width",
"value": "34.5vp"
},
{
"name": "battery_border_radius",
"value": "2"
"name": "battery_component_pic_body_padding",
"value": "2vp"
},
{
"name": "battery_content_padding",
"value": "2"
"name": "battery_component_pic_body_border_width",
"value": "1vp"
},
{
"name": "battery_border_width",
"value": "1"
"name": "battery_component_pic_border_radius",
"value": "2vp"
},
{
"name": "battery_margin",
"value": "20"
"name": "battery_component_pic_head_radius",
"value": "2vp"
},
{
"name": "battery_component_pic_head_width",
"value": "3vp"
},
{
"name": "battery_component_pic_head_height",
"value": "10vp"
}
]
}

1
features/clockcomponent/.gitignore vendored Normal file
View File

@ -0,0 +1 @@
build

View File

@ -0,0 +1,23 @@
{
"app": {
"bundleName": "com.ohos.systemui",
"vendor": "ohos",
"version": {
"code": 1000000,
"name": "1.0.0"
}
},
"deviceConfig": {},
"module": {
"package": "com.ohos.systemui.clockcomponent",
"deviceType": [
"phone"
],
"distro": {
"deliveryWithInstall": true,
"moduleName": "clockcomponent",
"moduleType": "har"
},
"srcPath": "default"
}
}

View File

@ -13,9 +13,11 @@
* limitations under the License.
*/
export interface RuleData {
isAllowBanner:boolean;
sound:string;
vibration:string;
isAllowLockScreen:boolean;
export default {
onCreate() {
console.info('Application onCreate')
},
onDestroy() {
console.info('Application onDestroy')
},
}

View File

@ -0,0 +1,29 @@
/*
* 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 = 'clock-StyleConfiguration';
export default class StyleConfiguration {
static getClockComponentStyle() {
const key: string = TAG + "-ClockComponent";
return StyleManager.getStyle(key, () => {
return {
statusBarClockMaxWidth: $r('app.float.status_bar_clock_width')
};
});
}
}

View File

@ -0,0 +1,63 @@
/*
* 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 StyleConfiguration from '../common/StyleConfiguration'
import StyleConfigurationCommon from '../../../../../../../common/src/main/ets/default/StyleConfiguration'
import {StatusBarGroupComponentData} from '../../../../../../screenlock/src/main/ets/com/ohos/common/Constants'
import StatusBarVM from '../../../../../../screenlock/src/main/ets/com/ohos/vm/StatusBarVM'
import TimeManager, {
TimeEventArgs,
TIME_CHANGE_EVENT,
} from '../../../../../../../common/src/main/ets/default/TimeManager'
import EventManager, {unsubscribe} from '../../../../../../../common/src/main/ets/default/event/EventManager'
const TAG = 'ClockComponent-clockIcon';
@Component
export default struct ClockIcon {
@State mTime: string = '16:01'
private mGroupId: string = ''
@State mStatusBarGroupComponentData: StatusBarGroupComponentData = new StatusBarGroupComponentData()
@State style: any = StyleConfiguration.getClockComponentStyle()
@State styleCommon: any = StyleConfigurationCommon.getCommonStyle()
unSubscriber?: unsubscribe;
aboutToAppear() {
Log.showInfo(TAG, 'aboutToAppear');
this.mStatusBarGroupComponentData = StatusBarVM.getStatusBarGroupComponentData(this.mGroupId)
this.unSubscriber = EventManager.subscribe(TIME_CHANGE_EVENT, (args: TimeEventArgs) => {
this.mTime = TimeManager.formatTime(args.date);
});
this.mTime = TimeManager.formatTime(new Date());
}
aboutToDisappear() {
Log.showInfo(TAG, 'aboutToDisappear');
this.unSubscriber && this.unSubscriber();
this.unSubscriber = undefined;
}
build() {
Row() {
Row().width(this.styleCommon.statusBarMarginLeftRight).height('100%')
Text(this.mTime)
.fontColor(this.mStatusBarGroupComponentData.contentColor)
.fontSize(this.styleCommon.statusBarFontSize)
.width(this.style.statusBarClockMaxWidth)
Row().width(this.styleCommon.statusBarMarginLeftRight).height('100%')
}
}
}

View File

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

View File

@ -0,0 +1,8 @@
{
"float": [
{
"name": "status_bar_clock_width",
"value": "60vp"
}
]
}

View File

@ -0,0 +1,12 @@
{
"string": [
{
"name": "clockcomponent_MainAbility",
"value": "clockcomponent_MainAbility"
},
{
"name": "mainability_description",
"value": "ETS_Empty Feature Ability"
}
]
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.6 KiB

View File

@ -0,0 +1,12 @@
{
"string": [
{
"name": "clockcomponent_MainAbility",
"value": "clockcomponent_MainAbility"
},
{
"name": "mainability_description",
"value": "ETS_Empty Feature Ability"
}
]
}

View File

@ -0,0 +1,12 @@
{
"string": [
{
"name": "clockcomponent_MainAbility",
"value": "clockcomponent_MainAbility"
},
{
"name": "mainability_description",
"value": "ETS_Empty Feature Ability"
}
]
}

View File

@ -13,18 +13,17 @@
* limitations under the License.
*/
import Log from '../../../../../../../../../common/src/main/ets/default/Log.ets'
import Log from '../../../../../../../../../common/src/main/ets/default/Log'
import ViewModel from '../../vm/dateTimeViewModel'
import Constants from '../../common/constants'
import {ScreenLockStatus} from '../../../../../../../../../common/src/main/ets/default/ScreenLockCommon.ets'
import {ScreenLockStatus} from '../../../../../../../../../common/src/main/ets/default/ScreenLockCommon'
const TAG = 'ScreenLock-DateTime'
@Component
export default struct DateTime {
@StorageLink('lockStatus') @Watch("onStatusChange") lockStatus: ScreenLockStatus = ScreenLockStatus.Locking
@State mViewModel: ViewModel = new ViewModel()
private isShowData: boolean= true
@Prop isShowDate: boolean
aboutToAppear() {
Log.showInfo(TAG, `aboutToAppear`)
@ -37,26 +36,21 @@ export default struct DateTime {
}
build() {
Flex({ direction: FlexDirection.Column, justifyContent: FlexAlign.Start, alignItems: ItemAlign.Center }) {
Column() {
Text(this.mViewModel.timeVal)
.fontSize($r('app.float.time_fontsize'))
.fontColor($r('app.color.date_time_color'))
.margin({ top: $r('app.float.time_top_margin'), bottom: $r('app.float.time_bottom_margin') })
if (this.isShowData) {
if (this.isShowDate) {
Row() {
Text($r('app.string.yyyy_mm_dd', this.mViewModel.dateVal.year, this.mViewModel.dateVal.month, this.mViewModel.dateVal.day))
.fontSize($r('app.float.date_fontsize'))
.fontColor($r('app.color.date_time_color'))
Text(this.mViewModel.weekVal).fontSize($r('app.float.date_fontsize'))
.fontColor($r('app.color.date_time_color'))
}
}.height($r('app.float.date_week_area_height'))
}
}
.width(Constants.FULL_CONTAINER_WIDTH)
}
onStatusChange(propName: string): void {
Log.showInfo(TAG, `onStatusChange`)
this.mViewModel.onStatusChange(this.lockStatus)
}
}

View File

@ -14,14 +14,26 @@
*/
import featureAbility from '@ohos.ability.featureAbility'
import commonEvent from '@ohos.commonEvent';
import settings from '@ohos.settingsnapi';
import Log from '../../../../../../../../common/src/main/ets/default/Log.ets'
import Log from '../../../../../../../../common/src/main/ets/default/Log'
import DateTimeCommon from '../../../../../../../../common/src/main/ets/default/DateTimeCommon'
import Constants from '../common/constants'
import {ScreenLockStatus} from '../../../../../../../../common/src/main/ets/default/ScreenLockCommon.ets'
import sTimeManager, {TimeEventArgs, TIME_CHANGE_EVENT,
} from '../../../../../../../../common/src/main/ets/default/TimeManager';
import EventManager, {unsubscribe} from '../../../../../../../../common/src/main/ets/default/event/EventManager'
const TAG = 'ScreenLock-DateTimeViewModel'
let mCommonEventSubscribeInfo = {
events: [
commonEvent.Support.COMMON_EVENT_TIME_CHANGED,
commonEvent.Support.COMMON_EVENT_TIMEZONE_CHANGED,
commonEvent.Support.COMMON_EVENT_TIME_TICK
]
};
let mEventSubscriber
/**
* DateTimeViewModel class
*/
@ -29,74 +41,38 @@ export default class DateTimeViewModel {
timeVal: string = ''
dateVal: any = {}
weekVal: any = {}
setDateTimeHandle: number = -1
isUsing24hFormat: boolean= false
unSubscriber?: unsubscribe;
ViewModelInit(): void{
Log.showInfo(TAG, 'ViewModelInit');
// TODO api 8 下有问题,临时注释
// this.timeFormatMonitor();
this.setDateTime.bind(this)()
this.setDateTimeHandle = setInterval(this.setDateTime.bind(this), Constants.INTERVAL);
commonEvent.createSubscriber(mCommonEventSubscribeInfo, this.createSubscriberCallBack.bind(this));
this.unSubscriber = EventManager.subscribe(TIME_CHANGE_EVENT, (args: TimeEventArgs) => {
this.setDateTime(args.date)
});
Log.showInfo(TAG, 'ViewModelInit end');
}
private timeFormatMonitor(): void {
Log.showInfo(TAG, 'timeFormatMonitor');
let urivar = settings.getUri('settings.time.format')
let helper = featureAbility.acquireDataAbilityHelper(urivar);
this.checkTimeFormat(helper);
helper.on("dataChange", urivar, (err) => {
if (err.code !== 0) {
Log.showError(TAG, `failed to getAbilityWant because ${err.message}`);
return;
} else {
this.checkTimeFormat(helper);
}
Log.showInfo(TAG, 'observer reveive notifychange on success data : ' + JSON.stringify(err))
})
}
private checkTimeFormat(helper) {
Log.showInfo(TAG, 'checkTimeFormat');
let getRetValue = settings.getValue(helper, 'settings.time.format', '24')
if (getRetValue === '12') {
this.isUsing24hFormat = false;
} else if (getRetValue === '24') {
this.isUsing24hFormat = true;
}
}
private setDateTime() {
private setDateTime(date?: Date) {
Log.showInfo(TAG, `setDateTime`)
this.timeVal = DateTimeCommon.getSystemTime(this.isUsing24hFormat)
this.timeVal = sTimeManager.formatTime(date ?? new Date())
this.dateVal = DateTimeCommon.getSystemDate()
this.weekVal = DateTimeCommon.getSystemWeek()
}
stopPolling() {
Log.showInfo(TAG, `stopPolling start`)
Log.showInfo(TAG, `stopPolling setDateTimeHandle:${this.setDateTimeHandle}`);
if (this.setDateTimeHandle > 0) {
clearInterval(this.setDateTimeHandle)
this.setDateTimeHandle = -1
Log.showInfo(TAG, `stopPolling setDateTimeHandle new :${this.setDateTimeHandle}`);
}
Log.showInfo(TAG, `stopPolling end`)
private createSubscriberCallBack(err, data) {
Log.showInfo(TAG, "start createSubscriberCallBack " + JSON.stringify(data))
mEventSubscriber = data
commonEvent.subscribe(data, this.setDateTime.bind(this));
Log.showInfo(TAG, "start createSubscriberCallBack finish")
}
onStatusChange(lockStatus: ScreenLockStatus): void {
Log.showInfo(TAG, `onStatusChange lockStatus:${lockStatus}`);
Log.showInfo(TAG, `onStatusChange setDateTimeHandle:${this.setDateTimeHandle}`);
if (lockStatus == ScreenLockStatus.Locking) {
if (this.setDateTimeHandle <= 0) {
this.setDateTimeHandle = setInterval(this.setDateTime.bind(this), Constants.INTERVAL);
Log.showInfo(TAG, `onStatusChange setDateTimeHandle new:${this.setDateTimeHandle}`);
}
} else {
this.stopPolling();
}
stopPolling() {
Log.showInfo(TAG, `stopPolling start`)
commonEvent.unsubscribe(mEventSubscriber);
this.unSubscriber && this.unSubscriber();
this.unSubscriber = undefined;
Log.showInfo(TAG, `stopPolling end`)
}
}

View File

@ -14,7 +14,12 @@
},
{
"name": "date_fontsize",
"value": "18"
"value": "36"
},
{
"name": "date_week_area_height",
"value": "48"
}
]
}

View File

@ -1,5 +1,4 @@
apply plugin: 'com.huawei.ohos.library'
//For instructions on signature configuration, see https://developer.harmonyos.com/cn/docs/documentation/doc-guides/ide_debug_device-0000001053822404#section1112183053510
ohos {
compileSdkVersion rootProject.ext.version.compileSdk
defaultConfig {

View File

@ -0,0 +1,42 @@
/*
* 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 WantAgent from '@ohos.wantAgent';
const TAG = 'CommonUtil';
const DEFAULT_INFO = {
code: 0,
want: '',
permission: '',
extraInfo: {}
};
export default class CommonUtil {
static startWant(want, triggerInfo?: any) {
let info = (triggerInfo) ? triggerInfo : DEFAULT_INFO;
Log.showInfo(TAG, `startWant ${JSON.stringify(want)}, info ${JSON.stringify(info)}`);
WantAgent.trigger(want, info, ((err, data) => {
Log.showInfo(TAG, `wantAgent trigger err ${JSON.stringify(err)} data ${JSON.stringify(data)}`);
}));
}
static checkVisibilityByUser(notificationUser: number, currentUser: number): boolean{
return (0 <= notificationUser && notificationUser < 100) || notificationUser == currentUser
}
}

View File

@ -0,0 +1,50 @@
/*
* 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';
const TAG = 'ScrollbarManager';
export default class ScrollbarManager {
static NotificationScrollBar = new Set<Scroller>();
static add(scroller) {
Log.showInfo(TAG, `add`);
let res = ScrollbarManager.NotificationScrollBar.add(scroller);
Log.showInfo(TAG, `add set's size:${res.size}`);
}
static delete(scroller) {
Log.showInfo(TAG, `delete`);
ScrollbarManager.NotificationScrollBar.delete(scroller);
}
static clear() {
Log.showInfo(TAG, `clear`);
ScrollbarManager.NotificationScrollBar.clear();
}
static restoreOtherScroll(scroller) {
Log.showInfo(TAG, `restoreOtherScroll`);
if (scroller.currentOffset().xOffset > 0) {
ScrollbarManager.NotificationScrollBar.forEach((item) => {
if (item !== scroller && item.currentOffset().xOffset > 0) {
item.scrollEdge(Edge.Start)
}
})
ScrollbarManager.clear();
ScrollbarManager.NotificationScrollBar.add(scroller);
}
}
}

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
@ -16,10 +16,13 @@
export default class Constants {
static NOTIFICATION_TYPE_BASIC: string = '0';
static NOTIFICATION_TYPE_LONG: string = '1';
static NOTIFICATION_TYPE_IMAGE: string = '2';
static NOTIFICATION_TYPE_PICTURE: string = '2';
static NOTIFICATION_TYPE_MULTILINE: string = '4';
static NOTIFICATION_TYPE_SOCIAL: string = '3';
static NOTIFICATION_TYPE_MEDIA: string = '5';
static NOTIFICATION_TYPE_NONE: number = 0;
static NOTIFICATION_TYPE_OPEN: number = 1;
static NOTIFICATION_TYPE_CLOSE: number = 2;
static TEXT_MAX_LENGTH: number = 21;
static TEXT_EXPANDED_MAX_LENGTH: number = 13;
static TOUCH_TYPE_DOWN: number = 0;
@ -29,23 +32,60 @@ export default class Constants {
static DISPLAY_TRANSLATE_X: number = -150;
static REMOVE_TRANSLATE_X: number = 150;
static DEFAULT_MAX_LINES: number= 1;
static SINGLE_LINE: number= 1;
static EXPENDED_MAX_LINES: number= 8;
static CONTENT_LINE_HEIGHT: number = 20;
static SETTING_CONT_HEIGHT = '50';
static SETTING_DIALOG_WITH = '80%';
static SETTING_CONT_HEIGHT = '40vp';
static SETTING_DIALOG_WITH = '330vp';
static SETTING_CONTENT_WITH = '100%'
static SETTING_DIALOG_HEIGHT = '380';
static CONFIRM_DIALOG_HEIGHT = '250'
static CONFIRM_DIALOG_WITH = '80%'
static CONFIRM_BUTTON_WITH = '50%'
static SETTING_DIALOG_HEIGHT = '192vp';
static SETTING_DIALOG_WIDTH = '362vp';
static CONFIRM_DIALOG_HEIGHT = '146vp';
static CONFIRM_DIALOG_WITH = '280';
static CONFIRM_BUTTON_WITH = '140';
static QUICKLY_SETTING_H = 83;
static ERROR_CALLBACK: number = 0;
static SUCCESS_CALLBACK: number = 1;
static KEY_INPUT: string = 'inputAction';
static FULL_CONTAINER_WIDTH = '100%'
}
export class NotificationLayout {
static ACTION_HEIGHT = 48;
static ACTION_MARGIN = 12;
static INPUT_IMAGE_SIZE = 24;
static INPUT_TEXT_HEIGHT = 40;
static INPUT_LAYOUT_HEIGHT = 82;
static NOTIFICATION_PIC_SIZE = 40;
static ICON_SIZE = 24;
static TEXT_LINE_HEIGHT = 20;
static BUTTON_SIZE = 40;
static ICON_MARGIN = 12;
static SCROLL_THRESHOLD = 10;
static TITLE_IMAGE_SIZE = 16;
static TITLE_HEIGHT = 40;
static ITEM_MARGIN = 12;
static EXPAND_PADDING_BOTTOM = 20;
}
export class InputActionButtonData {
isSending: boolean = false;
content: string = '';
}
interface RuleData {
isAllowBanner?: boolean;
isAllowSound?: boolean;
isAllowVibrationValues?: boolean;
isAllowStatusBarShow?: boolean;
isAllowNotificationListShow?: boolean;
}
export interface NotificationItemData {
id: string;
hashcode: string;
userId: number;
uid: number;
contentType: string;
timestamp: number;
time: string;
@ -53,8 +93,9 @@ export interface NotificationItemData {
want: any;
actionButtons: any[];
bundleName: string;
smallIcon?: Resource | string;
largeIcon?: Resource | string;
smallIcon?: PixelMap | string;
largeIcon?: PixelMap | string;
picture?: PixelMap;
title?: string;
text?: string;
additionalText?: string;
@ -66,11 +107,26 @@ export interface NotificationItemData {
slotLevel?: any;
source?: number;
versionName?: string;
sound?: string;
vibrationValues?: Array<number>;
notificationFlags?: any;
ruleData?: RuleData;
template?: any;
isOngoing?: boolean;
isUnremovable?: boolean;
isRemoveAllowed?: boolean;
distributedOption?: any;
deviceId?: string;
groupName?: string;
}
export interface NotificationServiceListener {
onNotificationConsume?: (data: NotificationItemData) => void;
onNotificationLoad?:(data: NotificationItemData) => void;
onNotificationCancel?:(data: NotificationItemData) => void;
onNotificationLoad?: (data: NotificationItemData) => void;
onNotificationCancel?: (data: NotificationItemData) => void;
}
export enum ScreenLockStatus {
Locking = 1,
Unlock = 2
}

View File

@ -1,41 +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 Constants from '../common/constants.ets';
import {NotificationItemData} from '../../../../../../../../notificationService/src/main/ets/com/ohos/notificationservice/common/constants.ets';
@Component
export default struct BasicItem {
@State itemData: NotificationItemData= undefined
build() {
Flex({ direction: FlexDirection.Column, justifyContent: FlexAlign.Start, alignItems: ItemAlign.Start }) {
Text(this.itemData.title)
.maxLines(Constants.DEFAULT_MAX_LINES)
.textOverflow({ overflow: TextOverflow.Ellipsis })
.fontSize($r('app.float.notification_title_fontsize'))
.fontColor($r('app.color.title_text_color'))
.fontWeight(FontWeight.Bold)
.lineHeight(Constants.CONTENT_LINE_HEIGHT)
Text(this.itemData.text)
.maxLines(Constants.DEFAULT_MAX_LINES)
.textOverflow({ overflow: TextOverflow.Clip })
.fontSize($r('app.float.notification_content_fontsize'))
.fontColor($r('app.color.content_text_color'))
.lineHeight(Constants.CONTENT_LINE_HEIGHT)
.margin({ top: $r('app.float.content_margin_top') })
}.width('100%')
}
}

View File

@ -1,44 +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 Constants from '../common/constants.ets';
import {NotificationItemData} from '../../../../../../../../notificationService/src/main/ets/com/ohos/notificationservice/common/constants.ets';
@Component
export default
struct LongItem {
@State itemData: NotificationItemData= undefined
@Prop isExpand: boolean
build() {
Flex({ direction: FlexDirection.Column, justifyContent: FlexAlign.Start, alignItems: ItemAlign.Start }) {
Text(this.isExpand ? this.itemData.expandedTitle : this.itemData.title)
.maxLines(Constants.DEFAULT_MAX_LINES)
.textOverflow({ overflow: TextOverflow.Ellipsis })
.fontSize($r('app.float.notification_title_fontsize'))
.fontColor($r('app.color.title_text_color'))
.fontWeight(FontWeight.Bold)
.lineHeight(Constants.CONTENT_LINE_HEIGHT) //not support Resource type
Text(this.isExpand ? this.itemData.longText : this.itemData.text)
.maxLines(this.isExpand ? Constants.EXPENDED_MAX_LINES : Constants.DEFAULT_MAX_LINES)
.textOverflow({ overflow: TextOverflow.Ellipsis })
.constraintSize({ maxHeight: $r('app.float.notification_expanded_text_maxheight') })
.fontSize($r('app.float.notification_content_fontsize'))
.fontColor($r('app.color.content_text_color'))
.lineHeight(Constants.CONTENT_LINE_HEIGHT)
.margin({ top: $r('app.float.content_margin_top') })
}.width('100%')
}
}

View File

@ -1,52 +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 Constants from '../common/constants.ets';
import {NotificationItemData} from '../../../../../../../../notificationService/src/main/ets/com/ohos/notificationservice/common/constants.ets';
@Component
export default struct MultiItem {
@State itemData: NotificationItemData= undefined
@Prop isExpand: boolean
build() {
Flex({ direction: FlexDirection.Column, justifyContent: FlexAlign.Start, alignItems: ItemAlign.Start }) {
Text(this.isExpand ? this.itemData.longTitle : this.itemData.title)
.maxLines(Constants.DEFAULT_MAX_LINES)
.textOverflow({ overflow: TextOverflow.Ellipsis })
.fontSize($r('app.float.notification_title_fontsize'))
.fontColor($r('app.color.title_text_color'))
.fontWeight(FontWeight.Bold)
.lineHeight(Constants.CONTENT_LINE_HEIGHT)
if (this.isExpand) {
ForEach(this.itemData.lines,
(item: string) => {
Text(`${item}`)
.fontSize($r('app.float.notification_content_fontsize'))
.fontColor($r('app.color.content_text_color'))
.margin({ top: $r('app.float.content_margin_top') })
}, (item: string) => item.toString()
)
} else {
Text(this.itemData.text)
.fontSize($r('app.float.notification_content_fontsize'))
.maxLines(Constants.DEFAULT_MAX_LINES)
.textOverflow({ overflow: TextOverflow.Ellipsis })
.fontColor($r('app.color.content_text_color'))
.margin({ top: $r('app.float.content_margin_top') })
}
}.width('100%')
}
}

View File

@ -1,224 +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 Constants from '../common/constants.ets';
import basicItem from './basicItem.ets';
import longItem from './longItem.ets';
import multiItem from './multiItem.ets';
import titleItem from './titleItem';
import Log from '../../../../../../../../../common/src/main/ets/default/Log.ets';
import CheckEmptyUtils from '../../../../../../../../../common/src/main/ets/default/CheckEmptyUtils.ets';
import mNotificationService from '../../../../../../../../../features/notificationService/src/main/ets/com/ohos/notificationservice/NotificationService.ets'
import WantAgent from '@ohos.wantAgent';
import WindowManager from '../../../../../../../../../common/src/main/ets/default/WindowManager.ets';
import {NotificationItemData} from '../../../../../../../../notificationService/src/main/ets/com/ohos/notificationservice/common/constants.ets';
const TAG = 'NoticeItem-NotificationItem';
let mWindowManager;
@Component
export default struct NotificationItem {
@Link showStatusBar: boolean
private itemData: NotificationItemData
@State hasPicture: boolean = false
@State isExpand: boolean = false
@State needExpand: boolean = true
@State deleteIconDisplay: boolean = false;
@State itemWidth: string = '100%'
startX: number = 0
startY: number = 0
@State moveX: number = 0
@State moveY: number = 0
aboutToAppear() {
Log.showInfo(TAG, `aboutToDisAppear Start`)
mWindowManager = new WindowManager();
if (CheckEmptyUtils.isEmpty(this.itemData.largeIcon)) {
this.hasPicture = false;
} else {
this.hasPicture = true;
}
this.needExpand=this.checkItemNeedExpand()
}
checkItemNeedExpand(){
if(this.itemData.contentType===Constants.NOTIFICATION_TYPE_BASIC&&(!(this.itemData.actionButtons?.length>0))){
return false;
}else{
return true;
}
}
aboutToDisappear() {
Log.showInfo(TAG, `aboutToDisAppear`);
}
build() {
Flex({ direction: FlexDirection.Column, justifyContent: FlexAlign.Start, alignItems: ItemAlign.Center }) {
Row() {
Column() {
titleItem({
notificationSmallIcon: this.itemData.smallIcon,
notificationName: this.itemData.name,
notificationTime: this.itemData.time,
isExpand: $isExpand,
needExpand: this.needExpand
})
Flex({ direction: FlexDirection.Row, justifyContent: FlexAlign.Start, alignItems: ItemAlign.Start }) {
Flex({ direction: FlexDirection.Column, justifyContent: FlexAlign.Start, alignItems: ItemAlign.Start }) {
if (this.itemData.contentType === Constants.NOTIFICATION_TYPE_BASIC) {
basicItem({
itemData: this.itemData
});
}
if (this.itemData.contentType === Constants.NOTIFICATION_TYPE_LONG) {
longItem({
itemData: this.itemData,
isExpand: this.isExpand
});
}
if (this.itemData.contentType === Constants.NOTIFICATION_TYPE_MULTILINE) {
multiItem({
itemData: this.itemData,
isExpand: this.isExpand
});
}
}
.width(this.hasPicture ? '85%' : '100%')
.margin({ top: $r('app.float.body_margin_top') })
if (this.hasPicture) {
Column() {
Image(this.itemData.largeIcon)
.objectFit(ImageFit.Contain)
.width(50)
.height(50)
}
.alignItems(HorizontalAlign.End)
.width('15%')
}
}.onClick(this.clickItem.bind(this))
if(this.isExpand){
Flex({ direction: FlexDirection.Row, justifyContent: FlexAlign.Start, alignItems: ItemAlign.Start }) {
ForEach(this.itemData.actionButtons, (item: any) => {
Text(item.title)
.fontSize(20)
.height(30)
.fontColor(Color.Blue)
.margin({ right: 20 })
.onClick(() => {
Log.showInfo(TAG, `clickbuttonEvent: ${JSON.stringify(item.wantAgent)}`)
this.startTargetAbility(item.wantAgent)
})
})
}
.margin({ top: 10 })
}
}
.backgroundColor($r('app.color.notificationitem_background'))
.opacity($r('app.float.item_opicaty'))
.borderRadius($r('app.float.item_borderradius'))
.margin({
left: $r('app.float.item_marginleft'),
right: $r('app.float.item_marginright'),
top: $r('app.float.item_margintop')
})
.padding({
left: $r('app.float.item_paddingleft'),
right: $r('app.float.item_paddingright'),
bottom: $r('app.float.item_paddingbottom')
})
.onTouch(this.touchNotificationItem.bind(this))
.width(this.itemWidth)
if (this.deleteIconDisplay) {
Flex({ direction: FlexDirection.Row, justifyContent: FlexAlign.SpaceAround, alignItems: ItemAlign.Center }) {
Image($r('app.media.delete')) //delete
.objectFit(ImageFit.Contain)
.width($r('app.float.item_delete_image_width'))
.height($r('app.float.item_delete_image_height'))
.onClick(() => {
this.removeNotificationItem(this.itemData.hashcode);
})
}
.width('30%')
}
}
}
}
touchNotificationItem(event: TouchEvent) {
if (event.type == Constants.TOUCH_TYPE_DOWN) { //down
this.startX = event.touches[0].x;
this.startY = event.touches[0].y;
Log.showInfo(TAG, `touchStart=======startX: ${this.startX}, startY: ${this.startY}`);
} else if (event.type == Constants.TOUCH_TYPE_MOVE) { //move
this.moveX = event.touches[0].x - this.startX;
this.moveY = event.touches[0].y - this.startY;
} else if (event.type == Constants.TOUCH_TYPE_UP) { //up
Log.showInfo(TAG, `touchEnd, moveX: ${this.moveX}, moveY: ${this.moveY}`);
if (this.deleteIconDisplay) {
if (this.moveX > Constants.HIDDEN_TRANSLATE_X) {
//hidden
this.deleteIconDisplay = false;
this.itemWidth = '100%';
Log.showInfo(TAG, 'hidden');
}
} else {
if (this.moveX < Constants.DISPLAY_TRANSLATE_X) {
this.deleteIconDisplay = true;
this.itemWidth = '70%';
Log.showInfo(TAG, 'display');
} else if (this.moveX > Constants.REMOVE_TRANSLATE_X) {
this.removeNotificationItem(this.itemData.hashcode);
}
}
}
}
removeNotificationItem(hashCode: string) {
Log.showInfo(TAG, 'removeNotificationItem');
mNotificationService.removeNotificationItem(hashCode, true);
}
clickItem() {
Log.showInfo(TAG, 'click Item');
this.startTargetAbility(this.itemData.want);
}
startTargetAbility(want) {
Log.showInfo(TAG, 'startTargetAbility');
//close window
this.showStatusBar = true;
mWindowManager.setWindowMin((result) => {
Log.showInfo(TAG, `setWindowMin ${result}`);
});
//open app
Log.showInfo(TAG, `itemClick wantAgent ${JSON.stringify(this.itemData.want)} id: ${this.itemData.id}`);
let TriggerInfo = {
code: 0,
want: '',
permission: '',
extraInfo: {}
};
WantAgent.trigger(want, TriggerInfo, ((err, data) => {
Log.showInfo(TAG, `itemClick wantAgent trigger err ${JSON.stringify(err)} data ${JSON.stringify(data)}`);
}));
//remove notification
this.removeNotificationItem(this.itemData.hashcode);
}
}

View File

@ -1,89 +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 Constants from '../common/constants.ets';
import Log from '../../../../../../../../../common/src/main/ets/default/Log.ets';
import CheckEmptyUtils from '../../../../../../../../../common/src/main/ets/default/CheckEmptyUtils.ets';
const TAG = 'NoticeItem-TitleItem';
@Component
export default
struct TitleItem {
private notificationSmallIcon: PixelMap
@Prop notificationName: string
@Prop notificationTime: string
@State srcIconDisplay: any = $r('app.media.ic_notification_down')
@Link isExpand: boolean
@Prop needExpand: boolean
@State rowSpace: any = $r('app.float.titleitem_row_space')
aboutToAppear() {
Log.showInfo(TAG, `aboutToAppear Start`);
}
aboutToDisappear() {
Log.showInfo(TAG, `aboutToDisAppear`);
}
build() {
Row() {
Row({ space: this.rowSpace }) {
if (!CheckEmptyUtils.isEmpty(this.notificationSmallIcon)) {
Image(this.notificationSmallIcon)
.objectFit(ImageFit.Contain)
.width($r('app.float.title_image_width'))
.height($r('app.float.title_image_height'))
.flexShrink(0)
}
Text(this.notificationName)
.maxLines(Constants.DEFAULT_MAX_LINES)
.textOverflow({ overflow: TextOverflow.Ellipsis })
.fontSize($r('app.float.title_name_fontsize'))
.flexShrink(1)
Text(this.notificationTime)
.fontSize($r('app.float.title_time_fontsize'))
.flexShrink(0)
}
.width(this.needExpand ? '80%' : '100%')
if (this.needExpand) {
Flex({ direction: FlexDirection.Row, justifyContent: FlexAlign.End, alignItems: ItemAlign.Center }) {
Image(this.srcIconDisplay)
.objectFit(ImageFit.Contain)
.width($r('app.float.displayicon_width'))
.height($r('app.float.displayicon_height'))
}
.width('20%')
}
}
.height($r('app.float.titleitem_height'))
.width('100%')
.onClick(this.clickTitleItem.bind(this))
}
clickTitleItem() {
Log.showInfo(TAG, 'clickTitleItem');
if (this.needExpand) {
if (this.isExpand) {
this.isExpand = false;
this.srcIconDisplay = $r('app.media.ic_notification_down');
} else {
this.isExpand = true;
this.srcIconDisplay = $r('app.media.ic_notification_up');
}
}
}
}

View File

@ -1,36 +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 ReadConfigUtil from '../../../../../../../../../common/src/main/ets/default/ReadConfigUtil.ets';
import Log from '../../../../../../../../../common/src/main/ets/default/Log.ets';
const FILE_URI = '/data/accounts/account_0/applications/com.ohos.systemui'
+ '/com.ohos.systemui.statusbar/assets/{0}/resources/rawfile/notificationConfig.json'
const TAG = 'NotificationConfig'
export class NotificationConfig {
static USE_NOTIFICATION_ICON = true;
readNotificationConfig(deviceType: string): any{
Log.showInfo(TAG, `readSlidingLength deviceType:${deviceType}`);
let notificationConfig = ReadConfigUtil.ReadConfigFile(FILE_URI.replace('{0}', deviceType))
return notificationConfig
}
}
let notificationConfig = new NotificationConfig();
export default notificationConfig as NotificationConfig;

View File

@ -0,0 +1,50 @@
/*
* 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 ReadConfigUtil from '../../../../../../../../../common/src/main/ets/default/ReadConfigUtil';
import Log from '../../../../../../../../../common/src/main/ets/default/Log';
const TAG = 'NotificationConfig'
/**
* Notification Flow Config
* limitTotal:Total number of notifications that can be displayed.Beyond the range will not be displayed.
* app:The application configuration that app needs to limit is in this array.
* See the following for specific configuration attributes:
* --bundleName:Application bundleName.
* --canShow:Specifies whether application notifications can be displayed.
* --limit:Specifies the total number of notifications that the application can display.
* Beyond the range will not be displayed.
*/
const Config = {
"limitTotal": 10000,
"app":
[
{ "bundleName": "com.ohos.publishnotifications", "canShow": true, "limit": 100 },
{ "bundleName": "com.ohos.app2", "canShow": true, "limit": 100 }
]
}
export class NotificationConfig {
static USE_NOTIFICATION_ICON = true;
readNotificationConfig(deviceType?: string): any{
return Config
}
}
let notificationConfig = new NotificationConfig();
export default notificationConfig as NotificationConfig;

View File

@ -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 Log from '../../../../../../../../../common/src/main/ets/default/Log';
import DeviceManager from '@ohos.distributedHardware.deviceManager';
import DeviceInfo from '@ohos.deviceInfo';
const TAG = `NotificationDistributionManager`;
let distributionManager = null;
export default class NotificationDistributionManager {
deviceManager = null
static getInstance() {
Log.showInfo(TAG, `getInstance`);
if (distributionManager == null) {
Log.showInfo(TAG, `getInstance distributionManager new`);
distributionManager = new NotificationDistributionManager();
distributionManager.initDeviceManager();
return distributionManager;
}
Log.showInfo(TAG, `getInstance return distributionManager`);
return distributionManager;
}
constructor() {
Log.showInfo(TAG, `constructor`);
}
initDeviceManager() {
Log.showInfo(TAG, `initDeviceManager`);
DeviceManager.createDeviceManager("com.ohos.systemui", (err, data) => {
if (err) {
console.info("createDeviceManager err:" + JSON.stringify(err));
return;
}
console.info("createDeviceManager success");
this.deviceManager = data;
});
}
getTrustedDeviceDeviceName(deviceId) {
Log.showInfo(TAG, `getTrustedDeviceDeviceName deviceId:${deviceId}`);
let deviceName = '';
let deviceArr:any[] = this.getTrustedDeviceListSync();
Log.showInfo(TAG, `getTrustedDeviceDeviceName deviceArr:${JSON.stringify(deviceArr)}`);
if (deviceArr && deviceArr.length > 0) {
for (let item of deviceArr) {
Log.showInfo(TAG, `getTrustedDeviceDeviceName deviceArr item:${JSON.stringify(item)}`);
if (item.deviceId == deviceId) {
deviceName = item.deviceName;
break;
}
}
}
return deviceName;
}
getTrustedDeviceListSync(): Array<any>{
Log.showInfo(TAG, `getTrustedDeviceListSync`);
return this.deviceManager.getTrustedDeviceListSync();
}
getLocalDeviceInfoSync() {
Log.showInfo(TAG, `getLocalDeviceInfoSync`);
return this.deviceManager.getLocalDeviceInfoSync();
}
release() {
this.deviceManager.release();
}
}
NotificationDistributionManager.getInstance();

View File

@ -1,54 +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 { NotificationSubscriber } from './notification/notificationSubscriber';
import Notification from '@ohos.notification';
import Log from '../../../../../../../../../common/src/main/ets/default/Log.ets';
const TAG = 'NotificationManager';
export default class NotificationManager {
static TYPE_BASIC: number = Notification.ContentType.NOTIFICATION_CONTENT_BASIC_TEXT;
static TYPE_LONG: number = Notification.ContentType.NOTIFICATION_CONTENT_LONG_TEXT;
static TYPE_MULTI: number = Notification.ContentType.NOTIFICATION_CONTENT_MULTILINE;
static subscribeNotification(tag, subscriber, asyncCallback) {
Log.showInfo(TAG, `subscribeNotification from: ${tag}`);
Notification.subscribe(subscriber, asyncCallback);
}
static unsubscribeNotification(tag, subscriber) {
Log.showInfo(TAG, `subscribeNotification from: ${tag}`);
Notification.unsubscribe(subscriber);
}
static removeAll(tag, callback) {
Log.showInfo(TAG, `removeAll from: ${tag}`);
Notification.removeAll(callback);
}
static remove(tag, hashCode, callback) {
Log.showInfo(TAG, `remove from: ${tag}`);
Notification.remove(hashCode, callback)
}
static getAllActiveNotifications(tag, callback) {
Log.showInfo(TAG, `getAllActiveNotifications from: ${tag}`);
Notification.getAllActiveNotifications(callback);
}
}

View File

@ -0,0 +1,166 @@
/*
* 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 { NotificationSubscriber } from './notification/notificationSubscriber';
import Notification from '@ohos.notification';
import PluginComponentManager from '@ohos.plugincomponent';
import Systemparameter from '@ohos.systemparameter';
import Log from '../../../../../../../../../common/src/main/ets/default/Log';
const TAG = 'NotificationManager';
// Temporary path
const EXTERNAL_JSON_PATH = '/system/etc/NotificationTemplate/external.json'
const DEBUG_SETTING_KEY = 'debug.systemui.notificationtemplate';
const DEBUG_BUNDLE_NAME = 'com.ohos.example.notificationtemplate'
const DEBUG_ABILITY_NAME = 'com.ohos.example.notificationtemplate.MainAbility'
const DEBUG_TEMPLATE_NAME = 'NotificationTemplate'
export default class NotificationManager {
static TYPE_BASIC: number = Notification.ContentType.NOTIFICATION_CONTENT_BASIC_TEXT;
static TYPE_LONG: number = Notification.ContentType.NOTIFICATION_CONTENT_LONG_TEXT;
static TYPE_MULTI: number = Notification.ContentType.NOTIFICATION_CONTENT_MULTILINE;
static TYPE_PICTURE: number = Notification.ContentType.NOTIFICATION_CONTENT_PICTURE;
static NotificationTemplateMap = new Map();
static subscribeNotification(tag, subscriber, asyncCallback) {
Log.showInfo(TAG, `subscribeNotification from: ${tag}`);
Notification.subscribe(subscriber, asyncCallback);
}
static unsubscribeNotification(tag, subscriber) {
Log.showInfo(TAG, `subscribeNotification from: ${tag}`);
Notification.unsubscribe(subscriber);
}
static removeAll(tag, callback) {
Log.showInfo(TAG, `removeAll from: ${tag}`);
Notification.removeAll(callback);
}
static remove(tag, hashCode, callback) {
Log.showInfo(TAG, `remove from: ${tag}`);
Notification.remove(hashCode, callback)
}
static getAllActiveNotifications(tag, callback) {
Log.showInfo(TAG, `getAllActiveNotifications from: ${tag}`);
Notification.getAllActiveNotifications(callback);
}
static enableNotification(tag, bundleOption, data, callback) {
Log.showInfo(TAG, `enableNotification from: ${tag}`);
Notification.enableNotification(bundleOption, data, callback);
}
static initNotificationTemplateMap(tag) {
Log.showInfo(TAG, `initNotificationTemplateMap from: ${tag}`);
if (NotificationManager.isDebugMode(tag)) {
NotificationManager.requestDebugTemplate(tag);
} else {
NotificationManager.requestTemplate(tag, '', EXTERNAL_JSON_PATH);
}
}
static request(tag, param, asyncCallback) {
Log.showInfo(TAG, `request from: ${tag}`);
PluginComponentManager.request(param, (err, data) => {
asyncCallback(err, data);
});
}
static push(tag, param, asyncCallback) {
Log.showInfo(TAG, `push from: ${tag}`);
PluginComponentManager.push(param, () => {
asyncCallback();
});
}
static requestListener(tag, asyncCallback) {
Log.showInfo(TAG, `requestListener from: ${tag}`);
PluginComponentManager.on('request', (source, name, data) => {
asyncCallback(source, name, data);
})
}
static pushListener(tag, asyncCallback) {
Log.showInfo(TAG, `pushListener from: ${tag}`);
PluginComponentManager.on('push', (source, template, data, extraData) => {
asyncCallback(source, template, data, extraData);
});
}
static requestTemplate(tag, templateName, templatePath) {
Log.showInfo(TAG, `requestTemplate from: ${tag}`);
let reqWant = {
bundleName: '',
abilityName: ''
};
let reqData = {}
let requestParam = {
want: reqWant,
name: templateName,
data: reqData,
jsonPath: templatePath
};
Log.showInfo(TAG, `requestTemplate requestParam: ${JSON.stringify(requestParam)}`)
NotificationManager.request(tag, requestParam, (err, data) => {
Log.showInfo(TAG, `request finished err: ${JSON.stringify(err)} data: ${JSON.stringify(data)}`)
Log.showInfo(TAG, `request finished templateData: ${templateName} data: ${JSON.stringify(data.componentTemplate)}`)
if (data !== null && data !== undefined) {
Log.showInfo(TAG, `request finished data.componentTemplate.source:${JSON.stringify(data.componentTemplate.source)}`)
let templates = JSON.parse(data.componentTemplate.source);
Log.showInfo(TAG, `request templates: ${JSON.stringify(templates)}`)
for (let key in templates) {
NotificationManager.NotificationTemplateMap.set(key, {
"source": templates[key], "ability": ""
});
}
}
});
}
static requestDebugTemplate(tag) {
Log.showInfo(TAG, `requestDebugTemplate from: ${tag}`);
let reqWant = {
bundleName: DEBUG_BUNDLE_NAME,
abilityName: DEBUG_ABILITY_NAME
};
let reqData = {}
let requestParam = {
want: reqWant,
name: DEBUG_TEMPLATE_NAME,
data: reqData
};
Log.showInfo(TAG, `requestDebugTemplate requestParam: ${JSON.stringify(requestParam)}`);
NotificationManager.request(tag, requestParam, (err, data) => {
Log.showInfo(TAG, `requestDebugTemplate finished err: ${JSON.stringify(err)} data: ${JSON.stringify(data)}`)
if (!!data) {
Log.showInfo(TAG, `requestDebugTemplate finished data.componentTemplate.source:${JSON.stringify(data.componentTemplate.source)}`)
NotificationManager.NotificationTemplateMap.set(DEBUG_TEMPLATE_NAME, data.componentTemplate);
}
});
}
static isDebugMode(tag): boolean{
Log.showInfo(TAG, `isDebugMode from: ${tag}`);
let debug = Systemparameter.getSync(DEBUG_SETTING_KEY, "")
Log.showInfo(TAG, `Systemparameter DEBUG_SETTING: ${debug}`);
return!!debug;
}
}

View File

@ -1,135 +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 notification from '@ohos.notification';
import NotificationSubscriber from '@ohos.notificationSubscriber';
import Log from '../../../../../../../../../common/src/main/ets/default/Log.ets';
import NotificationManager from './NotificationManager.ets';
import ParseDataUtil from './ParseDataUtil.ets';
const TAG = 'NotificationService';
let mSubscriber;
let listeners;
/**
* notification service api
*/
export class NotificationService {
constructor() {
listeners = [];
this.init();
}
init() {
this.loadAllNotifications();
this.subscribeNotification(this.getSubscriber());
}
public register(listener) {
Log.showInfo(TAG, "register listener")
listeners.push(listener);
}
public unRegister(listener) {
Log.showInfo(TAG, "unRegister listener")
let removedIndex = listeners.indexOf(listener);
if (removedIndex == -1) {
Log.showInfo(TAG, "unRegister listener, listener is not found");
return;
}
listeners.splice(removedIndex, 1)
Log.showInfo(TAG, "unRegister listener success");
}
public removeAll(){
Log.showInfo(TAG, 'removeAll start');
NotificationManager.removeAll(TAG, (data) => {
Log.showInfo(TAG, `removeAll => data: ${JSON.stringify(data)}`);
});
}
public remove(code: string) {
NotificationManager.remove(TAG, code,(data) => {
Log.showInfo(TAG, `removeNotificationItem ==> data: ${JSON.stringify(data)}`);
})
}
public loadAllNotifications() {
NotificationManager.getAllActiveNotifications(TAG, (err, requestsArr) => {
Log.showInfo(TAG, `getAllActiveNotifications err: ${JSON.stringify(err)}`);
Log.showInfo(TAG, `getAllActiveNotifications requestsArr: ${JSON.stringify(requestsArr)}`);
if (Array.isArray(requestsArr)) {
for(let i = 0,len = requestsArr.length; i< len; i++) {
this.handleNotificationLoad(requestsArr[i]);
}
}
})
}
getSubscriber() {
if (mSubscriber == null || mSubscriber == undefined) {
mSubscriber = {
onConsume: this.handleNotificationAdd.bind(this),
onCancel: this.handleNotificationCancel.bind(this),
}
}
return mSubscriber;
}
handleNotificationAdd(data) {
Log.showInfo(TAG, 'handleNotificationAdd started');
Log.showInfo(TAG, 'sortingMap' + JSON.stringify(data.sortingMap||{}));
Log.showInfo(TAG, JSON.stringify(data));
ParseDataUtil.parseData(data, (err, record) => {
Log.showInfo(TAG, `parseData after = ${JSON.stringify(record)}`);
Log.showInfo(TAG, `listeners.length = ${JSON.stringify(data)}`);
for(let i = 0,len = listeners.length; i< len; i++) {
Log.showInfo(TAG, `notify listener ` + i);
listeners[i].onNotificationConsume(record);
}
});
}
handleNotificationCancel(data) {
console.info("===>handleNotificationCancel data : ==> " + `data:${JSON.stringify(data)}`);
ParseDataUtil.parseData(data, (err, record) => {
for(let i = 0,len = listeners.length; i< len; i++) {
listeners[i].onNotificationCancel(record);
}
});
}
handleNotificationLoad(data) {
console.info("===>handleNotificationLoad data : ==> " + `data:${JSON.stringify(data)}`);
ParseDataUtil.parseData(data, (err, record) => {
for(let i = 0,len = listeners.length; i< len; i++) {
listeners[i].onNotificationLoad(record);
}
});
}
subscribeNotification(subscriber) {
let callback = (err,data) => {
Log.showInfo(TAG, `subscribeCallback finished err: ${JSON.stringify(err)} data: ${JSON.stringify(data)}`)
};
NotificationManager.subscribeNotification(TAG, subscriber, callback);
}
}
let notificationService = new NotificationService();
export default notificationService as NotificationService;

View File

@ -0,0 +1,160 @@
/*
* 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 notification from '@ohos.notification';
import NotificationSubscriber from '@ohos.notificationSubscriber';
import Log from '../../../../../../../../../common/src/main/ets/default/Log';
import NotificationManager from './NotificationManager';
import ParseDataUtil from './ParseDataUtil';
import RuleController from './rule/RuleController';
import CommonUtil from '../common/CommonUtil';
import createOrGet from "../../../../../../../../../common/src/main/ets/default/SingleInstanceHelper";
import DistributionManager from './NotificationDistributionManager';
const TAG = 'NotificationService';
interface NotificationListener {
userId: number;
onNotificationConsume: Function;
onNotificationCancel: (hashcode: number) => void;
}
/**
* notification service api
*/
export class NotificationService {
mListeners = new Set<NotificationListener>();
mSubscriber;
mSortingMap = {};
constructor() {
this.subscribeNotification(this.getSubscriber());
this.loadNotificationTemplate()
}
public register(listener: NotificationListener) {
let res = this.mListeners.add(listener);
Log.showInfo(TAG, `register, listener size: ${res.size}`);
}
public unRegister(listener: NotificationListener) {
let res = this.mListeners.delete(listener);
Log.showInfo(TAG, `unRegister, res: ${res}`);
}
public removeAll() {
Log.showInfo(TAG, 'removeAll start');
NotificationManager.removeAll(TAG, (data) => {
Log.showInfo(TAG, `removeAll => data: ${JSON.stringify(data)}`);
});
}
public remove(code: string) {
NotificationManager.remove(TAG, code, (data) => {
Log.showInfo(TAG, `removeNotificationItem ==> data: ${JSON.stringify(data)}`);
})
}
public loadAllNotifications() {
NotificationManager.getAllActiveNotifications(TAG, (err, requestsArr) => {
Log.showInfo(TAG, `getAllActiveNotifications error:${err}}, requestsArr: ${JSON.stringify(requestsArr)}`);
if (Array.isArray(requestsArr)) {
for (let i = 0, len = requestsArr.length; i < len; i++) {
this.handleNotificationAdd(requestsArr[i]);
}
}
})
}
getSubscriber() {
if (!this.mSubscriber) {
this.mSubscriber = {
onConsume: this.handleNotificationAddAndSortMap.bind(this),
onCancel: this.handleNotificationCancel.bind(this),
}
}
return this.mSubscriber;
}
handleNotificationAddAndSortMap(data) {
Log.showInfo(TAG, 'handleNotificationAddAndSortMap, sortingMap' + JSON.stringify(data.sortingMap || {}));
this.mSortingMap = { ...this.mSortingMap, ...data?.sortingMap };
this.handleNotificationAdd(data?.request);
}
handleNotificationAdd(request) {
ParseDataUtil.parseData(request, this.mSortingMap).then((intermediateData) => {
Log.showInfo(TAG, `parseData after = ${JSON.stringify(intermediateData)}`);
RuleController.getNotificationData(intermediateData, (finalItemData) => {
Log.showInfo(TAG, `RuleController.getNotificationData after = ${JSON.stringify(finalItemData)}`);
this.mListeners.forEach((listener) => {
Log.showInfo(TAG, `notifcationUserId: ${finalItemData.userId}, listener.userId: ${listener.userId}`);
if (CommonUtil.checkVisibilityByUser(finalItemData.userId, listener.userId)) {
listener.onNotificationConsume(finalItemData);
}
})
});
}).catch(errorInfo => Log.showError(TAG, errorInfo));
}
handleNotificationCancel(data) {
Log.showInfo(TAG, `handleNotificationCancel hashCode: ${JSON.stringify(data?.request?.hashCode)}`);
this.mSortingMap = { ...this.mSortingMap, ...data?.sortingMap };
const hashCode = data?.request?.hashCode;
if (!hashCode) {
Log.showError(TAG, `handleNotificationCancel data: ${JSON.stringify(data)}`);
return;
}
this.mListeners.forEach((listener) => listener.onNotificationCancel(hashCode));
}
subscribeNotification(subscriber) {
let callback = (err, data) => {
Log.showInfo(TAG, `subscribeCallback finished err: ${JSON.stringify(err)} data: ${JSON.stringify(data)}`)
};
NotificationManager.subscribeNotification(TAG, subscriber, callback);
}
loadNotificationTemplate() {
Log.showInfo(TAG, 'loadNotificationTemplate start');
NotificationManager.initNotificationTemplateMap(TAG);
}
getPluginTempLate(templateName) {
Log.showInfo(TAG, `getPluginTempLate param:${templateName}`);
let pluginTempLate = null;
if (NotificationManager.NotificationTemplateMap !== null) {
pluginTempLate = NotificationManager.NotificationTemplateMap.get(templateName);
}
Log.showInfo(TAG, `getPluginTempLate pluginTempLate:${JSON.stringify(pluginTempLate)}`);
return pluginTempLate;
}
enableNotification(bundleOption, data) {
Log.showInfo(TAG, `enableNotification bundleOption:${JSON.stringify(bundleOption)} data:${JSON.stringify(data)} `);
NotificationManager.enableNotification(TAG, bundleOption, data, (result) => {
Log.showInfo(TAG, `enableNotification ==> result: ${JSON.stringify(result)}`);
});
}
getTrustedDeviceDeviceName(deviceId) {
Log.showInfo(TAG, `getTrustedDeviceDeviceName deviceId:${JSON.stringify(deviceId)} `);
return DistributionManager.getInstance().getTrustedDeviceDeviceName(deviceId);
}
}
let notificationService = createOrGet(NotificationService, TAG);
export default notificationService as NotificationService;

View File

@ -0,0 +1,35 @@
/*
* 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 EventManager from "../../../../../../../../../common/src/main/ets/default/event/EventManager";
import {obtainLocalEvent} from "../../../../../../../../../common/src/main/ets/default/event/EventUtil";
const TAG = `NotificationWindowManager`;
class NotificationWindowManager {
showNotificationWindow() {
}
hideNotificationWindow() {
Log.showInfo(TAG, 'hide Notification window');
EventManager.publish(obtainLocalEvent('hideNotificationWindowEvent', ''));
}
}
let sNotificationWindowManager = new NotificationWindowManager();
export default sNotificationWindowManager as NotificationWindowManager;

View File

@ -1,164 +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 Notification from '@ohos.notification';
import Log from '../../../../../../../../../common/src/main/ets/default/Log.ets';
import BundleManager from '../../../../../../../../../common/src/main/ets/default/abilitymanager/bundleManager.ets';
import NotificationManager from './NotificationManager.ets';
import Constants,{NotificationItemData} from '../common/constants.ets';
import {NotificationConfig} from './NotificationConfig.ets';
let mDate;
let mAppName;
let mEmptyArray;
const TAG = 'Notification_ParseDataUtil';
mDate = new Date();
mAppName = new Map();
mEmptyArray = [];
let appDataMap = new Map();
/**
* parse data util class.
*/
export default class ParseDataUtil {
static parseData(data, callback) {
let request = data?.request;
if (request == null || request == undefined) {
Log.showInfo(TAG, 'consumeCallback request is empty');
callback(Constants.ERROR_CALLBACK, undefined);
return;
}
let slotLevel;
try {
slotLevel = data?.sortingMap?.sortings[request.hashCode]?.slot.level;
} catch (e) {
Log.showInfo(TAG, `slot level get error: ${e.toString()}`);
}
Log.showInfo(TAG, `want = ${JSON.stringify(request.wantAgent)}`);
Log.showInfo(TAG, `actionButtons = ${JSON.stringify(request.actionButtons)}`);
Log.showInfo(TAG, `largeIcon = ${request.largeIcon}`);
ParseDataUtil.getAppData(request.creatorBundleName, (err, appMessage) => {
let notificationItem: NotificationItemData = {
id: request.id,
hashcode: request.hashCode,
contentType: request?.content?.contentType + '',
timestamp: request.deliveryTime,
time: ParseDataUtil.getStandardTime(request.deliveryTime),
appName: appMessage.appName,
want: request.wantAgent,
bundleName: request.creatorBundleName,
actionButtons: request.actionButtons,
smallIcon: NotificationConfig.USE_NOTIFICATION_ICON ? (request?.smallIcon ?? appMessage.icon) : appMessage.icon,
largeIcon: request.largeIcon,
slotLevel: slotLevel,
source: request.source
};
Log.showInfo(TAG, `notificationItem construct over ====================`);
switch (request?.content?.contentType) {
case NotificationManager.TYPE_BASIC:
Log.showInfo(TAG, `contentType NOTIFICATION_CONTENT_BASIC_TEXT ====================`);
notificationItem.title = request.content.normal?.title ?? '';
notificationItem.text = request.content.normal?.text ?? '';
notificationItem.additionalText = request.content.normal?.additionalText ?? '';
break;
case NotificationManager.TYPE_LONG:
Log.showInfo(TAG, `contentType NOTIFICATION_CONTENT_LONG_TEXT ====================`);
notificationItem.title = request.content.longText?.title ?? '';
notificationItem.text = request.content.longText?.text ?? '';
notificationItem.additionalText = request.content.longText?.additionalText ?? '';
notificationItem.briefText = request.content.longText?.briefText ?? '';
notificationItem.expandedTitle = request.content.longText?.expandedTitle ?? '';
notificationItem.longText = request.content.longText?.longText ?? '';
break;
case NotificationManager.TYPE_MULTI:
Log.showInfo(TAG, `contentType NOTIFICATION_CONTENT_MULTILINE ====================`);
notificationItem.title = request.content.multiLine?.title ?? '';
notificationItem.text = request.content.multiLine?.text ?? '';
notificationItem.additionalText = request.content.multiLine?.additionalText ?? '';
notificationItem.briefText = request.content.multiLine?.briefText ?? '';
notificationItem.longTitle = request.content.multiLine?.longTitle ?? '';
notificationItem.lines = request.content.multiLine?.lines ?? mEmptyArray;
Log.showInfo(TAG, `multilines: ${JSON.stringify(request.content.multiLine?.lines)}`)
break;
default:
Log.showInfo(TAG, 'no match content type');
break;
}
callback(Constants.SUCCESS_CALLBACK, notificationItem);
})
}
/**
* Get app data by bundleName.
*
* @param {string} bundleName - BundleName of the target app.
* @return {object} appData
*/
static getAppData(bundleName, callback) {
Log.showInfo(TAG, 'getAppName start ====================');
if (appDataMap.has(bundleName)) {
callback(Constants.SUCCESS_CALLBACK,appDataMap.get(bundleName));
return;
}
BundleManager.getBundleInfo(TAG, bundleName, 0, (data) => {
Log.showInfo(TAG, `getBundleInfo` + JSON.stringify(data));
let labelId = data.appInfo.labelId;
let iconId = data.appInfo.iconId;
let appName = '';
BundleManager.getResourceManager(TAG, bundleName, (item) => {
Log.showInfo(TAG, `BundleManager.getResourceManager ${BundleManager.getResourceManager}`);
item.getString(labelId, (error, value) => {
Log.showInfo(TAG, `getString` + JSON.stringify(value));
if (value != null && value != undefined) {
appName = value
}
item.getMediaBase64(iconId, (error, MediaValue) => {
Log.showInfo(TAG, `getMediaBase64` + JSON.stringify(MediaValue));
if (MediaValue != null) {
let appMessage = {
'appName': appName,
'icon': MediaValue
}
Log.showInfo(TAG, `appDataMap set appInfo, appName = ` + JSON.stringify(appName));
if (appName != null && appName != undefined && appName != '') {
appDataMap.set(bundleName, appMessage);
}
Log.showInfo(TAG, `getAppData success, appMessage ` + JSON.stringify(appMessage));
callback(Constants.SUCCESS_CALLBACK,appDataMap.get(bundleName));
}
});
})
})
});
}
/**
* Reformat the timestamp to hh:mm.
*
* @param {number} timestamp - Target timestamp.
*/
static getStandardTime(timestamp) {
Log.showInfo(TAG, 'getStandardTime start ====================');
if (timestamp == 0 || timestamp == undefined || timestamp == null) {
return '';
}
mDate.setTime(timestamp);
let hoursNumber = mDate.getHours();
let minutesNumber = mDate.getMinutes();
let hours = hoursNumber < 10 ? '0' + hoursNumber : hoursNumber;
let minutes = minutesNumber < 10 ? '0' + minutesNumber : minutesNumber;
return hours + ':' + minutes;
}
}

View File

@ -0,0 +1,176 @@
/*
* 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 Notification from '@ohos.notification';
import AccountManager from '@ohos.account.osAccount';
import Log from '../../../../../../../../../common/src/main/ets/default/Log';
import BundleManager from '../../../../../../../../../common/src/main/ets/default/abilitymanager/bundleManager';
import AbilityManager from '../../../../../../../../../common/src/main/ets/default/abilitymanager/abilityManager';
import DistributionManager from './NotificationDistributionManager';
import NotificationManager from './NotificationManager';
import Constants, {NotificationItemData} from '../common/constants';
import {NotificationConfig} from './NotificationConfig';
const TAG = 'Notification_ParseDataUtil';
let mDate = new Date();
let appDataMap = new Map();
type NotificationContent = {
title: string,
text: string,
additionalText: string,
briefText?: string,
expandedTitle?: string,
longText?: string,
lines?: [],
picture?: any
}
async function getUserId(uid) {
let userId = await AccountManager.getAccountManager().getOsAccountLocalIdFromUid(uid);
Log.showInfo(TAG, `getOsAccountLocalIdFromUid uid = ${uid}, userId = ${userId}`);
return userId;
}
/**
* parse data util class.
*/
export default class ParseDataUtil {
static async parseData(request, sortingMap?) {
if (!request) {
return Promise.reject('consumeCallback request is empty');
}
Log.showInfo(TAG, `parse data start, want = ${JSON.stringify(request.wantAgent)}`);
Log.showInfo(TAG, `actionButtons = ${JSON.stringify(request.actionButtons)}`);
let userId = await getUserId(request.creatorUid);
let appMessage = await ParseDataUtil.getAppData(request.creatorBundleName, userId);
let notificationItem: NotificationItemData = {
id: request.id,
userId: userId,
uid: request.creatorUid,
hashcode: request.hashCode,
contentType: request?.content?.contentType + '',
timestamp: request.deliveryTime,
time: ParseDataUtil.getStandardTime(request.deliveryTime),
appName: appMessage.appName,
want: request.wantAgent,
bundleName: request.creatorBundleName,
actionButtons: request.actionButtons,
smallIcon: NotificationConfig.USE_NOTIFICATION_ICON ? (request?.smallIcon ?? appMessage.icon) : appMessage.icon,
largeIcon: request.largeIcon,
slotLevel: sortingMap?.sortings[request?.hashCode]?.slot?.level,
source: request.source,
sound: sortingMap?.sortings[request?.hashCode]?.slot?.sound ?? '',
vibrationValues: sortingMap?.sortings[request?.hashCode]?.slot?.vibrationValues ?? [],
notificationFlags: request.notificationFlags,
template: request?.template,
isOngoing: request.isOngoing,
isUnremovable: request.isUnremovable,
isRemoveAllowed: request.isRemoveAllowed,
distributedOption: request.distributedOption,
deviceId: request.deviceId,
groupName: request.groupName??request.hashcode
};
Log.showInfo(TAG, `notificationItem construct over ====================`);
notificationItem = {
...notificationItem, ...ParseDataUtil.getContentByType(request?.content?.contentType, request)
}
return notificationItem;
}
/**
* Get app data by bundleName.
*
* @param {string} bundleName - BundleName of the target app.
* @return {object} appData
*/
static async getAppData(bundleName, userId) {
Log.showInfo(TAG, `getAppName start by ${bundleName}`);
if (appDataMap.has(bundleName)) {
Log.showInfo(TAG, `getAppData success.`);
return appDataMap.get(bundleName);
}
let data = await BundleManager.getBundleInfo(TAG, bundleName, 0, userId);
let labelId = data?.appInfo?.labelId;
let iconId = data?.appInfo?.iconId;
let context = AbilityManager.getContext()??AbilityManager.getContext(AbilityManager.ABILITY_NAME_SCREEN_LOCK);
let item = await BundleManager.getResourceManager(TAG, context, bundleName);
let appMessage = {
appName: labelId > 0 ? await item.getString(labelId) : '',
icon: iconId > 0 ? await item.getMediaBase64(iconId) : null
};
if (appMessage.icon != null && appMessage.appName) {
appDataMap.set(bundleName, appMessage);
Log.showInfo(TAG, `getAppData success ${appMessage.appName} by ${bundleName}`);
}
return appMessage;
}
/**
* Reformat the timestamp to hh:mm.
*
* @param {number} timestamp - Target timestamp.
*/
static getStandardTime(timestamp) {
if (timestamp == 0 || timestamp == undefined || timestamp == null) {
return '';
}
mDate.setTime(timestamp);
let hoursNumber = mDate.getHours();
let minutesNumber = mDate.getMinutes();
let hours = hoursNumber < 10 ? '0' + hoursNumber : hoursNumber;
let minutes = minutesNumber < 10 ? '0' + minutesNumber : minutesNumber;
return hours + ':' + minutes;
}
static getContentByType(notificationType, request): NotificationContent {
let content = {
title: '', text: '', additionalText: ''
}
function getContentByKey(keysAndDefault, source) {
if (source) {
keysAndDefault.forEach(([key, defualt]) => {
content[key] = source[key] ?? defualt
})
}
}
switch (notificationType) {
case NotificationManager.TYPE_BASIC:
getContentByKey([['title', ''], ['text', ''], ['additionalText', '']], request.content.normal)
break;
case NotificationManager.TYPE_LONG:
getContentByKey([['title', ''], ['text', ''], ['additionalText', []], ['briefText', ''],
['expandedTitle', ''], ['longText', '']], request.content.longText)
break;
case NotificationManager.TYPE_MULTI:
getContentByKey([['title', ''], ['text', ''], ['additionalText', []], ['briefText', ''],
['longTitle', ''], ['lines', []]], request.content.multiLine)
break;
case NotificationManager.TYPE_PICTURE:
getContentByKey([['title', ''], ['text', ''], ['additionalText', []], ['briefText', ''],
['expandedTitle', ''], ['picture', '']], request.content.picture)
break;
default:
Log.showInfo(TAG, 'no match content type');
break;
}
Log.showInfo(TAG, `notificationType = ${notificationType}, content = ${JSON.stringify(content)}`);
return content
}
}

View File

@ -1,119 +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 {NotificationItemData} from '../../common/constants.ets'
import Log from '../../../../../../../../../common/src/main/ets/default/Log.ets';
const TAG = 'RuleController';
export default class RuleController {
/**
* Check if this notification is allow show or not
*
* @param {notificationItemData} Data of the notification
* @param {callback} Data of the type to show the notification
*/
static getNotificationData(notificationItemData, callback) {
if (typeof notificationItemData !== NotificationItemData) {
Log.showInfo(TAG, "type is not NotificationItemData")
callback(undefined)
return
}
this.this.isAllowSendNotification(notificationItemData.name, 0, "", (isSuccess) => {
if (!isSuccess) {
Log.showInfo(TAG, "user is not allow this to send notification")
callback(undefined)
return
}
this.isTooMuchNotification((isSuccess) => {
if (!isSuccess) {
Log.showInfo(TAG, "There are too much notification")
callback(undefined)
return
}
this.isAppTooMuchNotification(notificationItemData.name, 0, (isSuccess) => {
if (!isSuccess) {
Log.showInfo(TAG, "There are too much notification")
callback(undefined)
}
this.getNotificationDataByApp(notificationItemData.name, 0, "", (originData) => {
this.updateNotificationDataBySense(originData, (finialData) => {
callback(finalData)
});
});
});
});
});
}
/**
* Check if user allow the app send notification or not
*
* @param {name} Package name of the app
* @param {uid} Uid of the app to distinguish twin app
* @param {channelId} The channel id of the app which is used to send notification
* @param {callback} The user allow the app send notification or not
*/
private static isAllowSendNotification(name, uid, channelId, callback) {
// TODO 权限管理
}
/**
* Check there have been too much notification that there is no need to show another
*
*
* @param {callback} Send too much notification or not
*/
private static isTooMuchNotification(callback) {
// TODO 通知总条数显示限制
}
/**
* Check if the app send too much notification to can not show another from this app
*
*
* @param {name} Package name of the app
* @param {uid} Uid of the app to distinguish twin app
* @param {callback} Send too much notification or not
*/
private static isAppTooMuchNotification(name, uid, callback) {
// TODO 单应用通知显示限制
}
/**
* Get notification data of the notification channel
*
* @param {name} Package name of the app which send notification
* @param {uid} Uid of the app which send notification to distinguish twin app
* @param {channelId} The channel id of the app which is used to send notification
* @param {callback} The type to show notification
*/
private static getNotificationDataByApp(name, uid, channelId, callback) {
// TODO 提醒方式
}
/**
* Check the sense of the phone to update the show type
*
* @param {notificationData} The origin notification data
* @param {callback} The finial notification data
*/
private static updateNotificationDataBySense(notificationData, callback) {
// TODO 场景管理
}
}

View File

@ -0,0 +1,150 @@
/*
* 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 {NotificationItemData} from '../../common/constants';
import Log from '../../../../../../../../../../common/src/main/ets/default/Log';
import {SlotLevel} from '@ohos.notification';
import Notification from '@ohos.notification';
import CheckEmptyUtils from '../../../../../../../../../../common/src/main/ets/default/CheckEmptyUtils';
import Bundle from '@ohos.bundle';
const TAG = 'NotificationRuleController';
export class RuleController {
/**
* Check if this notification is allow show or not
*
* @param {notificationItemData} Data of the notification
* @param {callback} Data of the type to show the notification
*/
getNotificationData(notificationItemData: NotificationItemData, callback) {
Log.showInfo(TAG, "getNotificationData start")
this.isAllowSendNotification(notificationItemData, (isSuccess) => {
if (!isSuccess) {
Log.showInfo(TAG, "user is not allow this to send notification");
callback(undefined);
return;
}
this.getNotificationDataByApp(notificationItemData, (originalData) => {
Log.showInfo(TAG, `originalData = ${JSON.stringify(originalData)}`);
this.updateNotificationDataBySense(originalData, (finalData) => {
Log.showInfo(TAG, `finalData = ${JSON.stringify(finalData)}`);
callback(finalData);
});
});
});
}
/**
* Check if user allow the app send notification or not
*
* @param {notificationItemData} The origin notification data
* @param {callback} The user allow the app send notification or not
*/
isAllowSendNotification(notificationItemData, callback) {
Log.showInfo(TAG, "isAllowSendNotification start");
Notification.isNotificationEnabled({ bundle: notificationItemData.bundleName, uid: notificationItemData.uid })
.then((flag) => {
Log.showInfo(TAG, `Notification.isNotificationEnabled:` + flag)
callback(flag);
});
}
/**
* Check whether sound or vibration is allowed
*
* @param {notificationItemData} The origin notification data
* @param {callback} whether sound or vibration is allowed
*/
SoundOrVibrate(notificationItemData, callback) {
Log.showInfo(TAG, "SoundOrVibrate start")
let sound = false;
let vibrationValues = false;
if (!CheckEmptyUtils.checkStrIsEmpty(notificationItemData.sound)) {
sound = true;
Log.showInfo(TAG, `notificationItemData.sound is allowed = ${sound}`);
}
if (!CheckEmptyUtils.isEmptyArr(notificationItemData.vibrationValues)) {
vibrationValues = true;
Log.showInfo(TAG, `notificationItemData.vibrationValues is allowed = ${vibrationValues}`);
}
callback(sound, vibrationValues);
}
/**
* Get notification data of the notification
*
* @param {notificationItemData} The origin notification data
* @param {callback} The type to show notification
*/
getNotificationDataByApp(notificationItemData, callback) {
Log.showInfo(TAG, "getNotificationDataByApp start")
let mNotificationItemData : NotificationItemData = notificationItemData;
mNotificationItemData.ruleData = {
isAllowBanner: false,
isAllowSound: false,
isAllowVibrationValues: false,
isAllowStatusBarShow : false,
isAllowNotificationListShow : false
};
Log.showInfo(TAG, `notificationItemData.slotLevel = ${notificationItemData.slotLevel}`);
if (notificationItemData.slotLevel === SlotLevel.LEVEL_HIGH) {
mNotificationItemData.ruleData.isAllowBanner = true;
this.SoundOrVibrate(notificationItemData, (sound, vibrationValues) => {
mNotificationItemData.ruleData.isAllowSound = sound;
mNotificationItemData.ruleData.isAllowVibrationValues = vibrationValues;
});
mNotificationItemData.ruleData.isAllowStatusBarShow = true;
mNotificationItemData.ruleData.isAllowNotificationListShow = true;
} else if (notificationItemData.slotLevel === SlotLevel.LEVEL_DEFAULT) {
this.SoundOrVibrate(notificationItemData, (sound, vibrationValues) => {
mNotificationItemData.ruleData.isAllowSound = sound;
mNotificationItemData.ruleData.isAllowVibrationValues = vibrationValues;
});
mNotificationItemData.ruleData.isAllowStatusBarShow = true;
mNotificationItemData.ruleData.isAllowNotificationListShow = true;
} else if (notificationItemData.slotLevel === SlotLevel.LEVEL_LOW ||
notificationItemData.slotLevel === SlotLevel.LEVEL_MIN) {
mNotificationItemData.ruleData.isAllowNotificationListShow = true;
} else {
mNotificationItemData.ruleData.isAllowNotificationListShow = false;
}
Log.showInfo(TAG, `mNotificationItemData.ruleData = ${JSON.stringify(mNotificationItemData.ruleData)}`);
callback(mNotificationItemData);
}
/**
* Check the sense of the phone to update the show type
*
* @param {notificationItemData} The origin notification data
* @param {callback} The final notification data
*/
updateNotificationDataBySense(notificationItemData, callback) {
Log.showInfo(TAG, "updateNotificationDataBySense start")
let mNotificationItemData = notificationItemData;
callback(mNotificationItemData);
}
}
let ruleController = new RuleController();
export default ruleController as RuleController;

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,24 +13,28 @@
* limitations under the License.
*/
import Log from '../../../../../../../../../common/src/main/ets/default/Log.ets';
import Constants from '../common/constants.ets';
import NotificationItem from './item/notificationItem.ets'
import ViewModel from '../viewmodel/ViewModel.ets'
import Log from '../../../../../../../../../common/src/main/ets/default/Log';
import Constants, {NotificationLayout as Layout} from '../common/constants';
import NotificationItem from './item/notificationItem'
import GroupNotificationItem from './item/groupItem'
import ViewModel from '../viewmodel/ViewModel'
const TAG = 'NoticeItem-NotificationListComponent';
type NotificationLayoutConfig = {
itemMargin: number;
}
@Component
export default struct NotificationListComponent {
@Provide('notificationUpdate') update: number = 0;
@StorageLink('notificationList') notificationList: any[] = []
@StorageProp('maxHeight') maxHeight: number = 0
@StorageProp('minHeight') minHeight: number = 0
@State notificationH: number = 0
private config: NotificationLayoutConfig = {
itemMargin: Layout.ITEM_MARGIN
}
aboutToAppear() {
Log.showInfo(TAG, `notificationList, aboutToAppear`)
this.notificationH = this.maxHeight - (this.minHeight * 2) - Constants.QUICKLY_SETTING_H;
}
aboutToDisappear() {
@ -38,37 +42,21 @@ export default struct NotificationListComponent {
}
build() {
Flex({ direction: FlexDirection.Column, justifyContent: FlexAlign.Start, alignItems: ItemAlign.Center }) {
if (this.notificationList.length == 0) {
//text: no notification
Flex({ direction: FlexDirection.Column, justifyContent: FlexAlign.Center, alignItems: ItemAlign.Center }) {
Text($r('app.string.nonotification_text'))
.fontColor($r('app.color.nonotification_text_color'))
List({ space: this.config.itemMargin }) {
if (this.update && false) {
ListItem() {
}
}
} else {
Stack({ alignContent: Alignment.TopStart }) {
List() {
ForEach(this.notificationList, (item: any) => {
ListItem() {
NotificationItem({ itemData: item })
if (item.length > 1) {
GroupNotificationItem({ groupData: item })
} else {
NotificationItem({ itemData: item[0] })
}
}, (item: any) => item.hashcode.toString())
}
.onTouch((event: TouchEvent) => {
Log.showInfo(TAG, `Touch Event ${event.type} at Point ${event.touches[0].x}, ${event.touches[0].y}`)
event.stopPropagation();
})
Flex() { //bottom Line
}.width('100%').height('7%')
.opacity($r('app.float.deleteall_image_opacity'))
.position({ x: 0, y: '93%' })
}, (list: any) => JSON.stringify(list.map((item) => item.hashcode)))
}
.width('100%')
.height('100%')
}
}
.width('100%')
.height(this.notificationH)
}
}

View File

@ -0,0 +1,115 @@
/*
* 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 CheckEmptyUtils from '../../../../../../../../../../common/src/main/ets/default/CheckEmptyUtils';
import ViewModel from '../../viewmodel/ViewModel';
import Constants, {InputActionButtonData, NotificationLayout as Layout} from '../../common/constants';
const TAG = 'NoticeItem-ActionComponent';
@Component
export default struct ActionComponent {
@State showInputText: boolean = false;
@State placeholder: string = '';
@State inputData: any = undefined;
@State inputActionData: InputActionButtonData = new InputActionButtonData();
private itemData: any = undefined;
aboutToAppear() {
Log.showInfo(TAG, `aboutToAppear Start`);
let actionData = AppStorage.Get(Constants.KEY_INPUT + this.itemData.id);
this.inputActionData = (actionData instanceof InputActionButtonData) ? actionData : this.inputActionData;
}
aboutToDisappear() {
Log.showInfo(TAG, `aboutToDisAppear`);
}
build() {
Flex({ direction: FlexDirection.Row, justifyContent: FlexAlign.Start, alignItems: ItemAlign.Center }) {
if (!this.inputData) {
ForEach(this.itemData.actionButtons, (item: any) => {
ActionButton({
content: item.title,
clickEvent: () => {
if (CheckEmptyUtils.isEmpty(item.userInput)) {
ViewModel.clickItem(this.itemData, item.wantAgent);
} else {
this.inputData = { inputKey: item.userInput.inputKey, wantAgent: item.wantAgent };
}
}
})
})
} else {
TextInput({ placeholder: this.placeholder, text: this.inputActionData.content })
.type(InputType.Normal)
.caretColor(Color.Green)
.enterKeyType(EnterKeyType.Send)
.height(Layout.INPUT_TEXT_HEIGHT)
.enabled(this.inputActionData.isSending ? false : true)
.flexGrow(1)
.margin({ right: Layout.ACTION_MARGIN })
Image($r("app.media.send"))
.objectFit(ImageFit.Contain)
.width(Layout.INPUT_IMAGE_SIZE)
.height(Layout.INPUT_IMAGE_SIZE)
.onClick(() => {
ViewModel.clickReply(this.inputData.inputKey, this.placeholder, this.inputData.wantAgent);
this.inputActionData = {
isSending: true,
content: this.placeholder
};
AppStorage.SetOrCreate(Constants.KEY_INPUT + this.itemData.id, this.inputActionData);
})
}
}.height(!this.inputData ? Layout.ACTION_HEIGHT : Layout.INPUT_LAYOUT_HEIGHT)
}
}
@Component
struct ActionButton {
@State backgroundColor: Resource = $r("app.color.transparent");
@Prop content: string;
clickable: boolean = true;
clickEvent: () => void = () => {
};
build() {
Text(this.content)
.fontSize($r("sys.float.ohos_id_text_size_button2"))
.fontColor($r("sys.color.ohos_id_color_text_primary_activated"))
.borderRadius($r("sys.float.ohos_fa_corner_radius_default_s"))
.height(Layout.ACTION_HEIGHT)
.padding({ left: Layout.ACTION_MARGIN, right: Layout.ACTION_MARGIN })
.backgroundColor(this.backgroundColor)
.onTouch((event: TouchEvent) => {
if (!this.clickable) {
return;
}
if (event.type == TouchType.Down) {
this.backgroundColor = $r("sys.color.ohos_fa_click_effect");
} else if (event.type == TouchType.Up) {
this.backgroundColor = $r("app.color.transparent");
}
})
.onClick(() => {
if (!this.clickable) {
return;
}
this.clickEvent();
})
}
}

View File

@ -0,0 +1,272 @@
/*
* 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 WindowManager, { WindowType } from '../../../../../../../../../../common/src/main/ets/default/WindowManager'
import Constants, {NotificationLayout as Layout} from '../../common/constants';
import ViewModel from '../../viewmodel/ViewModel';
import CustomItem from './customItem';
import titleItem from './titleItem';
import basicItem from './basicItem';
import longItem from './longItem';
import multiItem from './multiItem';
import pictureItem from './pictureItem';
import ActionComponent from './actionComponent';
import DevicesDialog from './devicesDialog';
import WantAgent from '@ohos.wantAgent';
const TAG = 'NoticeItem-BannerNotificationItem'
const INTERVAL = 5 * 1000
@Component
export default struct BannerNotificationItem {
@State want : any = {};
@Link distributedDeviceName: string;
@Link mBannerNoticeCnt: number;
@Link mLastActionTime: number;
@Link needExpand: boolean;
@Link isExpand: boolean;
@State mCloseEnableFlg: boolean = false;
private nowWant: any;
private onBannerNoticeHide: () => void
private devicesDialogController: CustomDialogController = new CustomDialogController({
builder: DevicesDialog({
action: (deviceID) => this.selectedDevice(deviceID)
}),
autoCancel: false,
offset: { dx: 0, dy: 200 }
});
mInterval: number = INTERVAL;
mDefaultBannerRect: any;
expandPaddingBottom: number = Layout.EXPAND_PADDING_BOTTOM;
aboutToAppear() {
Log.showInfo(TAG, `aboutToAppear Start`)
setAppBgColor('#00000000')
this.mCloseEnableFlg = false;
this.mDefaultBannerRect = AbilityManager.getAbilityData(AbilityManager.ABILITY_NAME_BANNER_NOTICE, 'bannerRect');
setTimeout(() => {
this.hideWindowForTimeout();
}, this.mInterval);
Log.showInfo(TAG, `aboutToAppear End`)
}
aboutToDisappear() {
Log.showInfo(TAG, `aboutToDisAppear`)
}
build() {
Column() {
if (this.mBannerNoticeCnt > 0) {
if (this.want.template) {
CustomItem({ customItemData: this.want, isSubItem: false })
} else {
Row() {
Flex({ alignItems: ItemAlign.Center, justifyContent: FlexAlign.Start }) {
Row() {
titleItem({
notificationSmallIcon: this.want.smallIcon,
notificationName: this.want.appName,
notificationTime: this.want.time,
isExpand: $isExpand,
needExpand: this.needExpand,
distributedDeviceName: this.distributedDeviceName,
isSubItem: false,
clickTitleAction: () => this.refreshLastActionTime()
})
}
Row() {
Image($r('app.media.ic_close'))
.objectFit(ImageFit.Contain)
.width(Layout.TITLE_IMAGE_SIZE)
.height(Layout.TITLE_IMAGE_SIZE)
.margin({ left: Layout.ICON_MARGIN })
.visibility(this.mCloseEnableFlg ? Visibility.Visible : Visibility.None)
.onClick(this.clickCloseIcon.bind(this))
}
}
.margin({ left: 12, right: 12 })
.height(Layout.TITLE_HEIGHT)
}
Row() {
ContentComponent({
isExpand: this.isExpand,
itemData: this.want
});
if (this.isExpand && this.want.actionButtons.length) {
ActionComponent({ itemData: this.want })
} else {
Blank()
.height(Layout.ITEM_MARGIN)
}
}
.padding({
bottom: $r('app.float.item_paddingbottom')
})
.onClick(this.showDevicesDialog.bind(this))
.onAreaChange((e, e2) => {
Log.showInfo(TAG, `onAreaChange, e: ${JSON.stringify(e)} e2: ${JSON.stringify(e2)}`);
let heightEx = parseInt(e['height']);
let heightCur = parseInt(e2['height']);
let heightWin = parseInt(this.mDefaultBannerRect['height']);
if (this.isExpand) {
heightWin = heightWin + (heightCur - heightEx) + this.expandPaddingBottom;
}
let bannerRect = {
top: this.mDefaultBannerRect['top'],
left: this.mDefaultBannerRect['left'],
width: this.mDefaultBannerRect['width'],
height: heightWin
};
WindowManager.resetSizeWindow(WindowType.BANNER_NOTICE, bannerRect);
WindowManager.showWindow(WindowType.BANNER_NOTICE);
})
}
} else {
Row() {
Blank()
}
}
}
.width('100%')
.height('100%')
.borderRadius($r("sys.float.ohos_id_corner_radius_default_l"))
.backgroundColor($r('app.color.notificationitem_background'))
.clip(true)
.onHover((isHover) => {
this.mCloseEnableFlg = isHover;
})
}
isCreateNewNotification(notificationCount:number):boolean{
Log.showInfo(TAG, `isCreateNewNotification, notificationCount: ${notificationCount}`);
return true;
}
hideWindowForTimeout() {
Log.showInfo(TAG, `check need hide window or not.`)
if ((new Date()).getTime() - this.mLastActionTime >= this.mInterval) {
if (this.mCloseEnableFlg) {
this.mLastActionTime = (new Date()).getTime();
setTimeout(() => {
this.hideWindowForTimeout();
}, this.mInterval);
return;
}
this.onBannerNoticeHide();
} else {
setTimeout(() => {
this.hideWindowForTimeout();
}, this.mInterval);
}
}
clickCloseIcon() {
Log.showInfo(TAG, 'clickCloseIcon');
this.onBannerNoticeHide();
}
showDevicesDialog() {
Log.showInfo(TAG, `showDevicesDialog`)
if (!this.want?.distributedOption?.isDistributed) {
ViewModel.clickItem(this.want);
this.onBannerNoticeHide();
return;
}
let wantAgent = this.want?.want;
if (!!wantAgent) {
WantAgent.getWant(wantAgent).then((wantData) => {
this.nowWant = wantData
if (!wantData?.deviceId) {
this.devicesDialogController.open();
} else{
ViewModel.clickItem(this.want);
}
this.onBannerNoticeHide();
})
}
}
selectedDevice(deviceID) {
Log.showInfo(TAG, `selectedDevice deviceID:${deviceID}`)
this.nowWant.deviceId = deviceID;
let triggerInfo = {
code: 0,
want: this.nowWant,
permission: '',
extraInfo: {}
};
ViewModel.clickDistributionItem(this.want, triggerInfo)
}
refreshLastActionTime() {
this.mLastActionTime = (new Date()).getTime();
setTimeout(() => {
this.hideWindowForTimeout();
}, this.mInterval);
}
}
@Component
struct ContentComponent {
@Prop isExpand: boolean;
itemData: any;
aboutToAppear() {
Log.showInfo(TAG, `aboutToDisappear pict: ${this.itemData.picture}`);
Log.showInfo(TAG, `NotificationItemData: ${JSON.stringify(this.itemData)}`)
}
build() {
Flex({ alignItems: ItemAlign.Center, justifyContent: FlexAlign.Start }) {
Row() {
if (this.itemData.contentType === Constants.NOTIFICATION_TYPE_BASIC) {
basicItem({
itemData: this.itemData
});
}
if (this.itemData.contentType === Constants.NOTIFICATION_TYPE_LONG) {
longItem({
itemData: this.itemData,
isExpand: this.isExpand
});
}
if (this.itemData.contentType === Constants.NOTIFICATION_TYPE_MULTILINE) {
multiItem({
itemData: this.itemData,
isExpand: this.isExpand
});
}
if (this.itemData.contentType === Constants.NOTIFICATION_TYPE_PICTURE) {
pictureItem({
itemData: this.itemData,
isExpand: this.isExpand
});
}
}.flexGrow(1)
if (this.itemData.picture) {
Image(this.itemData.picture)
.objectFit(ImageFit.Contain)
.width(Layout.NOTIFICATION_PIC_SIZE)
.height(Layout.NOTIFICATION_PIC_SIZE)
}
}.margin({ left: Layout.ITEM_MARGIN, right: Layout.ITEM_MARGIN })
}
}

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,28 +13,28 @@
* limitations under the License.
*/
import Constants,{NotificationItemData} from '../../common/constants.ets';
import Constants, {NotificationItemData, NotificationLayout as Layout} from '../../common/constants';
@Component
export default struct BasicItem {
@State itemData: NotificationItemData= undefined
@State itemData: NotificationItemData = undefined
build() {
Flex({ direction: FlexDirection.Column, justifyContent: FlexAlign.Start, alignItems: ItemAlign.Start }) {
Column() {
Text(this.itemData.title)
.maxLines(Constants.DEFAULT_MAX_LINES)
.maxLines(Constants.SINGLE_LINE)
.textOverflow({ overflow: TextOverflow.Ellipsis })
.fontSize($r('app.float.notification_title_fontsize'))
.fontColor($r('app.color.title_text_color'))
.fontWeight(FontWeight.Bold)
.lineHeight(Constants.CONTENT_LINE_HEIGHT)
.fontColor($r("sys.color.ohos_fa_text_primary"))
.fontSize($r("sys.float.ohos_id_text_size_body2"))
.fontWeight(FontWeight.Medium)
.lineHeight(Layout.TEXT_LINE_HEIGHT)
Text(this.itemData.text)
.maxLines(Constants.DEFAULT_MAX_LINES)
.textOverflow({ overflow: TextOverflow.Clip })
.fontSize($r('app.float.notification_content_fontsize'))
.fontColor($r('app.color.content_text_color'))
.lineHeight(Constants.CONTENT_LINE_HEIGHT)
.margin({ top: $r('app.float.content_margin_top') })
}.width('100%')
.maxLines(Constants.SINGLE_LINE)
.textOverflow({ overflow: TextOverflow.Ellipsis })
.fontColor($r("sys.color.ohos_fa_text_secondary"))
.fontSize($r("sys.float.ohos_id_text_size_body2"))
.fontWeight(FontWeight.Regular)
.lineHeight(Layout.TEXT_LINE_HEIGHT)
}
.alignItems(HorizontalAlign.Start)
}
}

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,8 +13,8 @@
* limitations under the License.
*/
import Constants from '../../common/constants.ets';
import Log from '../../../../../../../../../../common/src/main/ets/default/Log.ets';
import Constants from '../../common/constants';
import Log from '../../../../../../../../../../common/src/main/ets/default/Log';
const TAG = 'NoticeItem-Confirm';
@ -30,18 +30,19 @@ export default struct ConfirmDialog {
build() {
Column({ space: 30 }) {
Column() {
Row() {
Text(this.title)
.fontSize($r('app.float.confirm_title_fontsize'))
.fontWeight(FontWeight.Bold)
}.width(Constants.SETTING_DIALOG_WITH)
.margin({ top: 20 })
.margin({top:$r('app.float.title_font_margin_t')})
Row() {
Text($r('app.string.confirm_message', this.bundleName))
.fontSize($r('app.float.confirm_cont_fontsize'))
}.width(Constants.SETTING_DIALOG_WITH)
.margin({top:$r('app.float.message_font_margin_t')})
Row() {
Column() {
@ -53,7 +54,6 @@ export default struct ConfirmDialog {
})
.alignItems(HorizontalAlign.Center)
.width(Constants.CONFIRM_BUTTON_WITH)
Divider()
.vertical(true)
.color($r('app.color.confirm_divider_color'))
@ -63,7 +63,6 @@ export default struct ConfirmDialog {
Text($r('app.string.close'))
.fontSize($r('app.float.confirm_cont_fontsize'))
.fontColor(Color.Red)
}.onClick(() => {
Log.showInfo(TAG, `confirm button of TimeDialog on click`)
this.controller.close();
@ -73,8 +72,11 @@ export default struct ConfirmDialog {
.width(Constants.CONFIRM_BUTTON_WITH)
}
.width(Constants.CONFIRM_DIALOG_WITH)
.height($r('app.float.confirm_button_height'))
.margin({top:$r('app.float.confirm_button_margin_t')})
}.height(Constants.CONFIRM_DIALOG_HEIGHT)
.width(Constants.SETTING_DIALOG_WIDTH)
.backgroundColor('#FFFFFFFF')
.border({ width: $r('app.float.setting_border_width'), color: Color.White,
radius: $r('app.float.notification_border_radius') })
}
}

View File

@ -0,0 +1,79 @@
/*
* 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 ViewModel from '../../viewmodel/ViewModel';
import NotificationManager from '../../model/NotificationManager';
const TAG = 'NoticeItem-CustomItem';
@Component
export default struct CustomItem {
private customItemData: any = {};
private template: any = {};
private templateData: any = {};
private isSubItem: boolean= false;
@State isDebugMode: boolean = false;
aboutToAppear() {
Log.showInfo(TAG, `aboutToAppear Start`)
this.template = ViewModel.getPluginTempLate(this.customItemData.template.name);
this.templateData = this.customItemData.template.data;
this.isDebugMode = NotificationManager.isDebugMode(TAG);
Log.showInfo(TAG, `template = ${JSON.stringify(this.template)}`)
Log.showInfo(TAG, `templateData = ${JSON.stringify(this.templateData)}`)
Log.showInfo(TAG, `isDebugMode = ${this.isDebugMode}`)
}
build() {
Stack({ alignContent: Alignment.TopStart }) {
Column() {
PluginComponent({
template: this.template,
data: this.templateData
}).onComplete(() => {
Log.showInfo(TAG, `Complete`)
}).onError(({errcode, msg}) => {
Log.showInfo(TAG, `Error code:${errcode} message:${msg}`)
})
.size({ width: 400, height: 130 })
}
.backgroundColor($r('app.color.notificationitem_background'))
.opacity($r('app.float.item_opicaty'))
.borderRadius(!this.isSubItem ? $r('app.float.item_borderradius') : 0)
.margin({
left: $r('app.float.item_marginleft'),
right: $r('app.float.item_marginright'),
top: $r('app.float.item_margintop')
})
.padding({
left: $r('app.float.item_paddingleft'),
right: $r('app.float.item_paddingright'),
bottom: $r('app.float.item_paddingbottom')
})
if (this.isDebugMode) {
Column() {
Text("-- DEBUG --")
.fontSize('32')
.fontWeight(FontWeight.Bold)
.fontColor(0xCCCCCC)
.opacity(0.5)
}.margin(10)
}
}
}
}

View File

@ -0,0 +1,91 @@
/*
* 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 Constants from '../../common/constants';
import Log from '../../../../../../../../../../common/src/main/ets/default/Log';
import DistributionManager from '../../model/NotificationDistributionManager';
const TAG = 'NoticeItem-DevicesDialog';
/**
* Devices dialog
*/
@CustomDialog
export default struct DevicesDialog {
private deviceInfoList: Array<any>;
public controller: CustomDialogController
public action: (deviceID) => void
build() {
Column({ space: 30 }) {
Row() {
Text($r('app.float.confirm_title_fontsize'))
.fontSize($r('app.float.confirm_title_fontsize'))
.fontWeight(FontWeight.Bold)
}.width(Constants.SETTING_DIALOG_WITH)
.margin({ top: 20 })
Column() {
List() {
ForEach(this.deviceInfoList, (item) => {
ListItem() {
Row() {
Column() {
Text(item.deviceName)
.fontSize($r('app.float.setting_cont_fontsize'))
.fontColor($r('app.color.dialog_font_color'))
.height(Constants.SETTING_CONT_HEIGHT)
}.alignItems(HorizontalAlign.Center)
.width(Constants.FULL_CONTAINER_WIDTH)
}
.width(Constants.SETTING_DIALOG_WITH)
.alignItems(VerticalAlign.Center)
.align(Alignment.Center)
.border({ width: $r('app.float.setting_border_width'), color: Color.White,
radius: $r('app.float.setting_border_radius') })
.backgroundColor($r('app.color.dialog_font_back_color'))
.onClick(() => {
this.action(item.deviceId);
this.controller.close();
})
}
})
}
.divider({
strokeWidth: 1,
color: $r('app.color.device_divider_color'),
startMargin: $r('app.float.device_divider_margin_l'),
endMargin: $r('app.float.device_divider_margin_r')
})
.width('100%')
.height('100%')
.visibility(Visibility.Visible)
.zIndex(0)
.border({ width: $r('app.float.device_border_width'), color: Color.White,
radius: $r('app.float.device_border_radius') })
.backgroundColor(Color.White)
}
}.height(Constants.CONFIRM_DIALOG_HEIGHT)
}
aboutToAppear() {
Log.showInfo(TAG, `aboutToAppear`)
this.deviceInfoList = DistributionManager.getInstance().getTrustedDeviceListSync();
Log.showInfo(TAG, `aboutToAppear deviceInfoList:${JSON.stringify(this.deviceInfoList)}`)
}
}

View File

@ -0,0 +1,144 @@
/*
* 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 Constants, {NotificationLayout as Layout} from '../../common/constants';
import basicItem from './basicItem';
import longItem from './longItem';
import multiItem from './multiItem';
import pictureItem from './pictureItem';
import titleItem from './titleItem';
import Log from '../../../../../../../../../../common/src/main/ets/default/Log';
import CheckEmptyUtils from '../../../../../../../../../../common/src/main/ets/default/CheckEmptyUtils';
import ViewModel from '../../viewmodel/ViewModel';
import ActionComponent from './actionComponent';
const TAG = 'NoticeItem-GeneralItem';
@Component
export default struct GeneralItem {
@Consume('notificationUpdate') updateFlag: number;
@State hasPicture: boolean = false
@State @Watch('expandChange') isExpand: boolean = false
@State needExpand: boolean = true
@State distributedDeviceName: string = ''
private itemData: any = {}
private clickAction: () => void
private isSubItem: boolean= false;
expandChange() {
this.updateFlag++;
}
aboutToAppear() {
Log.showInfo(TAG, `aboutToAppear Start`)
if (CheckEmptyUtils.isEmpty(this.itemData.largeIcon)) {
this.hasPicture = false;
} else {
this.hasPicture = true;
}
this.needExpand = this.checkItemNeedExpand()
ViewModel.getDistributedDeviceName(this.itemData).then((deviceName) => {
this.distributedDeviceName = deviceName;
})
}
checkItemNeedExpand() {
if (this.itemData.contentType === Constants.NOTIFICATION_TYPE_BASIC
&& (!(this.itemData.actionButtons?.length > 0))) {
return false;
} else {
return true;
}
}
aboutToDisappear() {
Log.showInfo(TAG, `aboutToDisappear`);
}
build() {
Column() {
titleItem({
notificationSmallIcon: this.itemData.smallIcon,
notificationName: this.itemData.appName,
notificationTime: this.itemData.time,
isExpand: $isExpand,
needExpand: this.needExpand,
distributedDeviceName: this.distributedDeviceName,
isSubItem: this.isSubItem,
clickTitleAction: () => null
})
ContentComponent({
isExpand: this.isExpand,
itemData: this.itemData
});
if (this.isExpand && this.itemData.actionButtons.length) {
ActionComponent({ itemData: this.itemData })
} else {
Blank()
.height(Layout.ITEM_MARGIN)
}
}.onClick(() => {
this.clickAction();
})
}
}
@Component
struct ContentComponent {
@Prop isExpand: boolean;
itemData: any;
aboutToAppear() {
Log.showInfo(TAG, `aboutToDisappear pict: ${this.itemData.picture}`);
}
build() {
Flex({ alignItems: ItemAlign.Center, justifyContent: FlexAlign.Start }) {
Row() {
if (this.itemData.contentType === Constants.NOTIFICATION_TYPE_BASIC) {
basicItem({
itemData: this.itemData
});
}
if (this.itemData.contentType === Constants.NOTIFICATION_TYPE_LONG) {
longItem({
itemData: this.itemData,
isExpand: this.isExpand
});
}
if (this.itemData.contentType === Constants.NOTIFICATION_TYPE_MULTILINE) {
multiItem({
itemData: this.itemData,
isExpand: this.isExpand
});
}
if (this.itemData.contentType === Constants.NOTIFICATION_TYPE_PICTURE) {
pictureItem({
itemData: this.itemData,
isExpand: this.isExpand
});
}
}.flexGrow(1)
if (this.itemData.picture) {
Image(this.itemData.picture)
.objectFit(ImageFit.Contain)
.width(Layout.NOTIFICATION_PIC_SIZE)
.height(Layout.NOTIFICATION_PIC_SIZE)
}
}.margin({ left: Layout.ITEM_MARGIN, right: Layout.ITEM_MARGIN })
}
}

View File

@ -0,0 +1,193 @@
/*
* 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 Constants, {NotificationLayout as Layout} from '../../common/constants';
import NotificationItem from './notificationItem'
import titleItem from './titleItem';
import IconListComponent, {getIconListSize} from './iconListComponent';
import ScrollbarManager from '../../common/ScrollbarManager';
const TAG = 'NoticeItem-GroupItem';
@Component
export default struct GroupItem {
@Consume('notificationUpdate') updateFlag: number;
@State distributedDeviceName: string = ''
@State @Watch('expandChange') toExpand: boolean = false;
private groupData: any[] = []
private mScroller: Scroller = new Scroller();
@State mIconAlpha: number = 0;
@State @Watch('scrollEdge') mEdgeEnd: boolean = false;
aboutToAppear() {
Log.showInfo(TAG, `aboutToAppear`)
}
aboutToDisappear() {
Log.showInfo(TAG, `aboutToDisAppear`);
}
expandChange() {
this.updateFlag++;
}
build() {
Stack({ alignContent: Alignment.TopEnd }) {
Scroll(this.mScroller) {
Row() {
Column() {
Row() {
titleItem({
notificationSmallIcon: this.groupData[0].smallIcon,
notificationName: this.groupData[0].appName,
notificationTime: this.groupData[0].time,
isExpand: $toExpand,
needExpand: true,
distributedDeviceName: this.distributedDeviceName,
clickTitleAction: () => null
})
}.backgroundColor($r('app.color.notificationitem_background'))
.width(Constants.FULL_CONTAINER_WIDTH)
Row() {
ContentList({ groupData: this.groupData, toExpand: this.toExpand })
}.width(Constants.FULL_CONTAINER_WIDTH)
.enabled(!this.mEdgeEnd)
}
.borderRadius($r("sys.float.ohos_id_corner_radius_default_l"))
.clip(true)
Row() {
IconListComponent({ iconAlpha: this.mIconAlpha, itemData: this.groupData[0], isGroup: true })
}.width(getIconListSize())
}.alignItems(VerticalAlign.Top)
}
.borderRadius($r("sys.float.ohos_id_corner_radius_default_l"))
.clip(true)
.scrollable(ScrollDirection.Horizontal)
.scrollBar(BarState.On)
.onScroll(() => {
this.mIconAlpha += 0.1;
this.mIconAlpha = this.mScroller.currentOffset().xOffset * 1.0 / getIconListSize();
})
.onScrollEnd(() => {
this.mEdgeEnd = (this.mEdgeEnd &&
this.mScroller.currentOffset().xOffset > (getIconListSize() - Layout.SCROLL_THRESHOLD))
|| (!this.mEdgeEnd && this.mScroller.currentOffset().xOffset > Layout.SCROLL_THRESHOLD)
ScrollbarManager.restoreOtherScroll(this.mScroller);
})
}
.width(Constants.FULL_CONTAINER_WIDTH)
}
scrollEdge() {
this.mScroller.scrollEdge(this.mEdgeEnd ? Edge.End : Edge.Start)
}
}
@Component
struct ContentList {
@State @Watch('remainderChange') groupData: any[] = []
@Prop toExpand: boolean
@State remainderNum: number= 0
aboutToAppear() {
Log.showInfo(TAG, `aboutToAppear`)
this.remainderNum = this.groupData.length - 2;
Log.showInfo(TAG, `aboutToAppear remainderNum:${this.remainderNum}`)
}
build() {
Column() {
if (!this.toExpand) {
Column() {
Row({ space: 5 }) {
Text(this.groupData[0].title)
.maxLines(Constants.SINGLE_LINE)
.textOverflow({ overflow: TextOverflow.Ellipsis })
.fontColor($r("sys.color.ohos_fa_text_primary"))
.fontSize($r("sys.float.ohos_id_text_size_body2"))
.fontWeight(FontWeight.Medium)
.lineHeight(Layout.TEXT_LINE_HEIGHT)
Text(this.groupData[0].text)
.maxLines(Constants.SINGLE_LINE)
.textOverflow({ overflow: TextOverflow.Ellipsis })
.fontColor($r("sys.color.ohos_fa_text_secondary"))
.fontSize($r("sys.float.ohos_id_text_size_body2"))
.fontWeight(FontWeight.Regular)
.lineHeight(Layout.TEXT_LINE_HEIGHT)
Blank()
.margin({ left: Layout.ITEM_MARGIN, right: Layout.ITEM_MARGIN })
}.width(Constants.FULL_CONTAINER_WIDTH)
.margin({ left: Layout.ITEM_MARGIN, right: Layout.ITEM_MARGIN })
Row({ space: 5 }) {
Text(this.groupData[1].title)
.maxLines(Constants.SINGLE_LINE)
.textOverflow({ overflow: TextOverflow.Ellipsis })
.fontColor($r("sys.color.ohos_fa_text_primary"))
.fontSize($r("sys.float.ohos_id_text_size_body2"))
.fontWeight(FontWeight.Medium)
.lineHeight(Layout.TEXT_LINE_HEIGHT)
Text(this.groupData[1].text)
.maxLines(Constants.SINGLE_LINE)
.textOverflow({ overflow: TextOverflow.Ellipsis })
.fontColor($r("sys.color.ohos_fa_text_secondary"))
.fontSize($r("sys.float.ohos_id_text_size_body2"))
.fontWeight(FontWeight.Regular)
.lineHeight(Layout.TEXT_LINE_HEIGHT)
Blank()
Text('+' + this.remainderNum)
.maxLines(Constants.SINGLE_LINE)
.textOverflow({ overflow: TextOverflow.None })
.fontColor($r("sys.color.ohos_fa_text_secondary"))
.fontSize($r("sys.float.ohos_id_text_size_body2"))
.visibility((this.remainderNum > 0) ? Visibility.Visible : Visibility.Hidden)
.margin({ left: Layout.ITEM_MARGIN, right: Layout.ITEM_MARGIN })
}
.width(Constants.FULL_CONTAINER_WIDTH)
.margin({ left: Layout.ITEM_MARGIN, right: Layout.ITEM_MARGIN })
Blank()
.height(Layout.ITEM_MARGIN)
}.width(Constants.FULL_CONTAINER_WIDTH)
.backgroundColor($r('app.color.notificationitem_background'))
.alignItems(HorizontalAlign.Start)
} else {
List() {
ForEach(this.groupData, (item: any) => {
ListItem() {
NotificationItem({ itemData: item, isSubItem: true })
}
}, (item: any) => `${item.hashcode}_${item.timestamp}_subitem`)
}
.divider({
strokeWidth: 1,
color: $r('app.color.device_divider_color')
})
}
}
.alignItems(HorizontalAlign.Start)
.width(Constants.FULL_CONTAINER_WIDTH)
}
remainderChange() {
this.remainderNum = this.groupData.length - 2;
Log.showInfo(TAG, `aboutToAppear remainderNum:${this.remainderNum}`)
}
}

View File

@ -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 Constants, {NotificationLayout as Layout} from '../../common/constants';
import Log from '../../../../../../../../../../common/src/main/ets/default/Log';
import SettingDialog from './settingDialog';
import ConfirmDialog from './confirmDialog'
import ViewModel from '../../viewmodel/ViewModel';
const TAG = 'NoticeItem-IconListComponent';
let iconSize: number = 0;
type IconData = {
src?: Resource;
callback?: () => void
}
export type NotificationUiConfig = {
iconSize: number;
}
export function getIconListSize(list?: IconData[]) {
let listSize = list?.length??iconSize;
return listSize * (Layout.BUTTON_SIZE + 2 * Layout.ICON_MARGIN) + Layout.ICON_MARGIN
}
@Component
export default struct IconListComponent {
private itemData: any = {}
private isGroup: boolean= false;
@Prop iconAlpha: number
private settingDialogController: CustomDialogController = new CustomDialogController({
builder: SettingDialog({
itemData: this.itemData,
action: () => this.confirmDialogController.open()
}),
autoCancel: false,
offset: { dx: 0, dy: $r('app.float.setting_dialog_dy') },
customStyle:true
});
private confirmDialogController: CustomDialogController = new CustomDialogController({
builder: ConfirmDialog({
title: $r('app.string.closeNovice'),
bundleName: this.itemData.name,
action: () => ViewModel.enableNotification(this.itemData, false)
}),
autoCancel: false,
offset: { dx: 0, dy: $r('app.float.confirm_dialog_dy') },
customStyle:true
});
private iconConfigs: IconData[] = [
{
src: $r("app.media.ic_public_settings_filled"),
callback: () => {
Log.showInfo(TAG, `click settings hashcode: ${this.itemData?.hashcode}`);
this.settingDialogController.open()
}
}, {
src: $r("app.media.ic_public_delete_filled"),
callback: () => {
if (!this.isGroup) {
Log.showInfo(TAG, `click delete hashcode: ${this.itemData?.hashcode}`);
ViewModel.removeNotificationItem(this.itemData, true)
} else {
Log.showInfo(TAG, `click delete groupName: ${this.itemData?.groupName}`);
ViewModel.removeGroupNotification(this.itemData, true)
}
}
}
]
aboutToAppear() {
Log.showInfo(TAG, `iconConfigs: ${JSON.stringify(this.iconConfigs)}`)
iconSize = this.iconConfigs.length;
}
build() {
Flex({ direction: FlexDirection.Row, alignItems: ItemAlign.End, justifyContent: FlexAlign.End }) {
ForEach(this.iconConfigs, (item) => {
Button({ type: ButtonType.Circle, stateEffect: true }) {
if (item.src) {
Image(item.src)
.objectFit(ImageFit.Contain)
.fillColor($r("sys.color.ohos_id_color_primary_contrary"))
.width(Layout.ICON_SIZE)
.height(Layout.ICON_SIZE)
}
}
.width(Layout.BUTTON_SIZE)
.height(Layout.BUTTON_SIZE)
.opacity(this.iconAlpha)
.backgroundColor($r("app.color.button_background"))
.margin({ left: Layout.ICON_MARGIN, right: Layout.ICON_MARGIN })
.onClick(() => item.callback && item.callback())
})
}
.margin({ left: Layout.ICON_MARGIN })
}
}

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,7 +13,7 @@
* limitations under the License.
*/
import Constants,{NotificationItemData} from '../../common/constants.ets';
import Constants, {NotificationItemData, NotificationLayout as Layout} from '../../common/constants';
@Component
export default
@ -22,22 +22,22 @@ struct LongItem {
@Prop isExpand: boolean
build() {
Flex({ direction: FlexDirection.Column, justifyContent: FlexAlign.Start, alignItems: ItemAlign.Start }) {
Column() {
Text(this.isExpand ? this.itemData.expandedTitle : this.itemData.title)
.maxLines(Constants.DEFAULT_MAX_LINES)
.maxLines(Constants.SINGLE_LINE)
.textOverflow({ overflow: TextOverflow.Ellipsis })
.fontSize($r('app.float.notification_title_fontsize'))
.fontColor($r('app.color.title_text_color'))
.fontWeight(FontWeight.Bold)
.lineHeight(Constants.CONTENT_LINE_HEIGHT) //not support Resource type
.fontColor($r("sys.color.ohos_fa_text_primary"))
.fontSize($r("sys.float.ohos_id_text_size_body2"))
.fontWeight(FontWeight.Medium)
.lineHeight(Layout.TEXT_LINE_HEIGHT)
Text(this.isExpand ? this.itemData.longText : this.itemData.text)
.maxLines(this.isExpand ? Constants.EXPENDED_MAX_LINES : Constants.DEFAULT_MAX_LINES)
.maxLines(this.isExpand ? Constants.EXPENDED_MAX_LINES : Constants.SINGLE_LINE)
.textOverflow({ overflow: TextOverflow.Ellipsis })
.constraintSize({ maxHeight: $r('app.float.notification_expanded_text_maxheight') })
.fontSize($r('app.float.notification_content_fontsize'))
.fontColor($r('app.color.content_text_color'))
.lineHeight(Constants.CONTENT_LINE_HEIGHT)
.margin({ top: $r('app.float.content_margin_top') })
}.width('100%')
.fontColor($r("sys.color.ohos_fa_text_secondary"))
.fontSize($r("sys.float.ohos_id_text_size_body2"))
.fontWeight(FontWeight.Regular)
.lineHeight(Layout.TEXT_LINE_HEIGHT)
}
.alignItems(HorizontalAlign.Start)
}
}

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,7 +13,7 @@
* limitations under the License.
*/
import Constants,{NotificationItemData} from '../../common/constants.ets';
import Constants, {NotificationItemData, NotificationLayout as Layout} from '../../common/constants';
@Component
export default struct MultiItem {
@ -21,31 +21,35 @@ export default struct MultiItem {
@Prop isExpand: boolean
build() {
Flex({ direction: FlexDirection.Column, justifyContent: FlexAlign.Start, alignItems: ItemAlign.Start }) {
Column() {
Text(this.isExpand ? this.itemData.longTitle : this.itemData.title)
.maxLines(Constants.DEFAULT_MAX_LINES)
.maxLines(Constants.SINGLE_LINE)
.textOverflow({ overflow: TextOverflow.Ellipsis })
.fontSize($r('app.float.notification_title_fontsize'))
.fontColor($r('app.color.title_text_color'))
.fontWeight(FontWeight.Bold)
.lineHeight(Constants.CONTENT_LINE_HEIGHT)
.fontColor($r("sys.color.ohos_fa_text_primary"))
.fontSize($r("sys.float.ohos_id_text_size_body2"))
.fontWeight(FontWeight.Medium)
.lineHeight(Layout.TEXT_LINE_HEIGHT)
if (this.isExpand) {
ForEach(this.itemData.lines,
(item: string) => {
Text(`${item}`)
.fontSize($r('app.float.notification_content_fontsize'))
.fontColor($r('app.color.content_text_color'))
.margin({ top: $r('app.float.content_margin_top') })
Text(item)
.maxLines(Constants.SINGLE_LINE)
.textOverflow({ overflow: TextOverflow.Ellipsis })
.fontColor($r("sys.color.ohos_fa_text_secondary"))
.fontSize($r("sys.float.ohos_id_text_size_body2"))
.fontWeight(FontWeight.Regular)
.lineHeight(Layout.TEXT_LINE_HEIGHT)
}, (item: string) => item.toString()
)
} else {
Text(this.itemData.text)
.fontSize($r('app.float.notification_content_fontsize'))
.maxLines(Constants.DEFAULT_MAX_LINES)
.maxLines(Constants.SINGLE_LINE)
.textOverflow({ overflow: TextOverflow.Ellipsis })
.fontColor($r('app.color.content_text_color'))
.margin({ top: $r('app.float.content_margin_top') })
.fontColor($r("sys.color.ohos_fa_text_secondary"))
.fontSize($r("sys.float.ohos_id_text_size_body2"))
.fontWeight(FontWeight.Regular)
.lineHeight(Layout.TEXT_LINE_HEIGHT)
}
}.width('100%')
}.alignItems(HorizontalAlign.Start)
}
}

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,215 +13,117 @@
* limitations under the License.
*/
import Constants,{NotificationItemData} from '../../common/constants.ets';
import basicItem from './basicItem.ets';
import longItem from './longItem.ets';
import multiItem from './multiItem.ets';
import titleItem from './titleItem.ets';
import Log from '../../../../../../../../../../common/src/main/ets/default/Log.ets';
import CheckEmptyUtils from '../../../../../../../../../../common/src/main/ets/default/CheckEmptyUtils.ets';
import Constants, {NotificationLayout as Layout} from '../../common/constants';
import GeneralItem from './generalItem';
import CustomItem from './customItem';
import Log from '../../../../../../../../../../common/src/main/ets/default/Log';
import ViewModel from '../../viewmodel/ViewModel';
import DevicesDialog from './devicesDialog';
import WantAgent from '@ohos.wantAgent';
import ViewModel from '../../viewmodel/ViewModel.ets';
import SettingDialog from './settingDialog.ets';
import ConfirmDialog from './confirmDialog.ets'
import IconListComponent, {getIconListSize} from './iconListComponent';
import ScrollbarManager from '../../common/ScrollbarManager';
const TAG = 'NoticeItem-NotificationItem';
@Component
export default struct NotificationItem {
private itemData: any = {}
@State hasPicture: boolean = false
@State isExpand: boolean = false
@State needExpand: boolean = true
@State deleteIconDisplay : boolean = false;
@State mIconAlpha: number = 0;
@State @Watch('scrollEdge') mEdgeEnd: boolean = false;
@State itemWidth: string = '100%'
startX: number = 0
startY: number = 0
@State moveX: number = 0
@State moveY: number = 0
private itemData: any = {}
private isSubItem: boolean= false;
private mScroller: Scroller = new Scroller();
settingDialogController: CustomDialogController = new CustomDialogController({
builder: SettingDialog({
itemData: this.itemData,
action: this.showConfirmDialog.bind(this)
build() {
Stack() {
IconListComponent({ iconAlpha: this.mIconAlpha, itemData: this.itemData })
Scroll(this.mScroller) {
Row() {
FrontItem({ itemData: this.itemData, isSubItem: this.isSubItem })
IconListComponent({ iconAlpha: 0, itemData: this.itemData })
}
}
.scrollable(ScrollDirection.Horizontal)
.scrollBar(BarState.On)
.onScroll(() => {
this.mIconAlpha += 0.1;
this.mIconAlpha = this.mScroller.currentOffset().xOffset * 1.0 / getIconListSize();
})
.onScrollEnd(() => {
this.mEdgeEnd = (this.mEdgeEnd &&
this.mScroller.currentOffset().xOffset > (getIconListSize() - Layout.SCROLL_THRESHOLD))
|| (!this.mEdgeEnd && this.mScroller.currentOffset().xOffset > Layout.SCROLL_THRESHOLD)
ScrollbarManager.restoreOtherScroll(this.mScroller);
})
}.width(this.itemWidth)
.borderRadius(!this.isSubItem ? $r("sys.float.ohos_id_corner_radius_default_l") : 0)
.clip(!this.isSubItem)
}
scrollEdge() {
this.mScroller.scrollEdge(this.mEdgeEnd ? Edge.End : Edge.Start)
}
}
@Component
struct FrontItem {
private itemData: any = {}
private nowWant: any;
private isSubItem: boolean= false;
private devicesDialogController: CustomDialogController = new CustomDialogController({
builder: DevicesDialog({
action: (deviceID) => this.selectedDevice(deviceID)
}),
autoCancel: false,
offset: { dx: 0, dy: 200 }
});
confirmDialogController: CustomDialogController = new CustomDialogController({
builder: ConfirmDialog({
title: $r('app.string.closeNovice'),
bundleName: this.itemData.name,
action: ViewModel.removeNotificationItem.bind(ViewModel,this.itemData,true)
}),
autoCancel: false,
offset: { dx: 0, dy: 250 }
});
aboutToAppear() {
Log.showInfo(TAG, `aboutToAppear Start`)
if (CheckEmptyUtils.isEmpty(this.itemData.largeIcon)) {
this.hasPicture = false;
} else {
this.hasPicture = true;
}
this.needExpand=this.checkItemNeedExpand()
}
checkItemNeedExpand(){
if(this.itemData.contentType===Constants.NOTIFICATION_TYPE_BASIC&&(!(this.itemData.actionButtons?.length>0))){
return false;
}else{
return true;
}
}
aboutToDisappear() {
Log.showInfo(TAG, `aboutToDisappear`);
}
build() {
Flex({ direction: FlexDirection.Column, justifyContent: FlexAlign.Start, alignItems: ItemAlign.Center }) {
Row() {
Column() {
titleItem({
notificationSmallIcon: this.itemData.smallIcon,
notificationName: this.itemData.appName,
notificationTime: this.itemData.time,
isExpand: $isExpand,
needExpand: this.needExpand
})
Flex({ direction: FlexDirection.Row, justifyContent: FlexAlign.Start, alignItems: ItemAlign.Start }) {
Flex({ direction: FlexDirection.Column, justifyContent: FlexAlign.Start, alignItems: ItemAlign.Start }) {
if (this.itemData.contentType === Constants.NOTIFICATION_TYPE_BASIC) {
basicItem({
itemData: this.itemData
});
}
if (this.itemData.contentType === Constants.NOTIFICATION_TYPE_LONG) {
longItem({
itemData: this.itemData,
isExpand: this.isExpand
});
}
if (this.itemData.contentType === Constants.NOTIFICATION_TYPE_MULTILINE) {
multiItem({
itemData: this.itemData,
isExpand: this.isExpand
});
}
}
.width(this.hasPicture ? '85%' : '100%')
.margin({ top: $r('app.float.body_margin_top') })
if (this.hasPicture) {
Column() {
Image(this.itemData.largeIcon)
.objectFit(ImageFit.Contain)
.width(50)
.height(50)
}
.alignItems(HorizontalAlign.End)
.width('15%')
}
}
.onClick(() => {
ViewModel.startTargetAbility(this.itemData);
})
if (this.isExpand) {
Flex({ direction: FlexDirection.Row, justifyContent: FlexAlign.Start, alignItems: ItemAlign.Start }) {
ForEach(this.itemData.actionButtons, (item: any) => {
Text(item.title)
.fontSize(20)
.height(30)
.fontColor(Color.Blue)
.margin({ right: 20 })
.onClick(() => {
ViewModel.startTargetAbility(this.itemData);
})
})
}
.margin({ top: 10 })
}
}
.backgroundColor($r('app.color.notificationitem_background'))
.opacity($r('app.float.item_opicaty'))
.borderRadius($r('app.float.item_borderradius'))
.margin({
left: $r('app.float.item_marginleft'),
right: $r('app.float.item_marginright'),
top: $r('app.float.item_margintop')
})
.padding({
left: $r('app.float.item_paddingleft'),
right: $r('app.float.item_paddingright'),
bottom: $r('app.float.item_paddingbottom')
})
.onTouch(this.touchNotificationItem.bind(this))
.width(this.itemWidth)
if (this.deleteIconDisplay) {
Flex({ direction: FlexDirection.Row, justifyContent: FlexAlign.SpaceAround, alignItems: ItemAlign.Center }) {
Row({ space: 30 }) {
Image($r("app.media.ic_setting")) //setting
.objectFit(ImageFit.Contain)
.width($r('app.float.item_delete_image_width'))
.height($r('app.float.item_delete_image_height'))
.onClick(this.showSettingDialog.bind(this))
Image($r('app.media.delete')) //delete
.objectFit(ImageFit.Contain)
.width($r('app.float.item_delete_image_width'))
.height($r('app.float.item_delete_image_height'))
.onClick(() => {
ViewModel.removeNotificationItem(this.itemData, true);
})
}
}
.width('30%')
}
}
}
}
showSettingDialog() {
Log.showInfo(TAG, `showSettingDialog`)
this.settingDialogController.open()
}
showConfirmDialog() {
Log.showInfo(TAG, `showConfirmDialog`)
this.confirmDialogController.open()
}
touchNotificationItem(event: TouchEvent) {
if (event.type == Constants.TOUCH_TYPE_DOWN) { //down
this.startX = event.touches[0].x;
this.startY = event.touches[0].y;
Log.showInfo(TAG, `touchStart=======startX: ${this.startX}, startY: ${this.startY}`);
} else if (event.type == Constants.TOUCH_TYPE_MOVE) { //move
this.moveX = event.touches[0].x - this.startX;
this.moveY = event.touches[0].y - this.startY;
} else if (event.type == Constants.TOUCH_TYPE_UP) { //up
Log.showInfo(TAG, `touchEnd, moveX: ${this.moveX}, moveY: ${this.moveY}`);
if (this.deleteIconDisplay) {
if (this.moveX > Constants.HIDDEN_TRANSLATE_X) {
//hidden
this.deleteIconDisplay = false;
this.itemWidth = '100%';
Log.showInfo(TAG, 'hidden');
}
if (this.itemData.template) {
CustomItem({ customItemData: this.itemData, isSubItem: this.isSubItem })
} else {
if (this.moveX < Constants.DISPLAY_TRANSLATE_X) {
this.deleteIconDisplay = true;
this.itemWidth = '70%';
Log.showInfo(TAG, 'display');
} else if (this.moveX > Constants.REMOVE_TRANSLATE_X) {
ViewModel.removeNotificationItem(this.itemData, true);
GeneralItem({ itemData: this.itemData, clickAction: () => this.showDevicesDialog(), isSubItem: this.isSubItem })
}
}
.width('100%')
.borderRadius(!this.isSubItem ? $r("sys.float.ohos_id_corner_radius_default_l") : 0)
.backgroundColor($r('app.color.notificationitem_background'))
}
showDevicesDialog() {
Log.showInfo(TAG, `showDevicesDialog isDistributed: ${this.itemData?.distributedOption?.isDistributed}`)
if (!this.itemData?.distributedOption?.isDistributed) {
ViewModel.clickItem(this.itemData);
return;
}
let wantAgent = this.itemData?.want;
if (!!wantAgent) {
WantAgent.getWant(wantAgent).then((want) => {
this.nowWant = want
Log.showInfo(TAG, `showDevicesDialog want: ${JSON.stringify(this.nowWant)}`)
if (!want?.deviceId) {
this.devicesDialogController.open()
} else {
ViewModel.clickItem(this.itemData);
}
})
} else {
ViewModel.clickItem(this.itemData);
}
}
selectedDevice(deviceID) {
Log.showInfo(TAG, `selectedDevice deviceID:${deviceID}`)
this.nowWant.deviceId = deviceID;
let triggerInfo = {
code: 0,
want: this.nowWant,
permission: '',
extraInfo: {}
};
ViewModel.clickDistributionItem(this.itemData, triggerInfo)
}
}

View File

@ -0,0 +1,44 @@
/*
* 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 Constants, {NotificationItemData, NotificationLayout as Layout} from '../../common/constants';
import CheckEmptyUtils from '../../../../../../../../../../common/src/main/ets/default/CheckEmptyUtils';
@Component
export default struct PictureItem {
@State itemData: NotificationItemData= undefined
@Prop isExpand: boolean
build() {
Column() {
Text(this.isExpand ? this.itemData.expandedTitle : this.itemData.title)
.maxLines(Constants.SINGLE_LINE)
.textOverflow({ overflow: TextOverflow.Ellipsis })
.fontColor($r("sys.color.ohos_fa_text_primary"))
.fontSize($r("sys.float.ohos_id_text_size_body2"))
.fontWeight(FontWeight.Medium)
.lineHeight(Layout.TEXT_LINE_HEIGHT)
Text(this.isExpand ? this.itemData.briefText : this.itemData.text)
.maxLines(this.isExpand ? Constants.EXPENDED_MAX_LINES : Constants.SINGLE_LINE)
.textOverflow({ overflow: TextOverflow.Ellipsis })
.fontColor($r("sys.color.ohos_fa_text_secondary"))
.fontSize($r("sys.float.ohos_id_text_size_body2"))
.fontWeight(FontWeight.Regular)
.lineHeight(Layout.TEXT_LINE_HEIGHT)
}
.alignItems(HorizontalAlign.Start)
}
}

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 Constants,{NotificationItemData} from '../../common/constants.ets';
import Log from '../../../../../../../../../../common/src/main/ets/default/Log.ets';
import CheckEmptyUtils from '../../../../../../../../../../common/src/main/ets/default/CheckEmptyUtils.ets';
import FeatureAbilityManager from '../../../../../../../../../../common/src/main/ets/default/abilitymanager/featureAbilityManager.ets';
import WindowManager from '../../../../../../../../../../common/src/main/ets/default/WindowManager.ets'
import Constants,{NotificationItemData} from '../../common/constants';
import Log from '../../../../../../../../../../common/src/main/ets/default/Log';
import CheckEmptyUtils from '../../../../../../../../../../common/src/main/ets/default/CheckEmptyUtils';
import EventManager from "../../../../../../../../../../common/src/main/ets/default/event/EventManager"
import {obtainStartAbility} from "../../../../../../../../../../common/src/main/ets/default/event/EventUtil"
import Notification from '@ohos.notification';
const TAG = 'NoticeItem-Setting';
@ -32,9 +32,8 @@ export default struct SettingDialog {
public action: () => void
build() {
Column({ space: 30 }) {
Row({ space: 10 }) {
Column({ space: 4 }) {
Row({ space: 4 }) {
if (!CheckEmptyUtils.isEmpty(this.itemData.smallIcon)) {
Image(this.itemData.smallIcon)
.objectFit(ImageFit.Contain)
@ -43,8 +42,10 @@ export default struct SettingDialog {
}
Text(this.itemData.appName)
.fontSize($r('app.float.setting_title_fontsize'))
.fontWeight(500)
}.width(Constants.SETTING_DIALOG_WITH)
.margin({ top: 50 })
.margin( {top: $r('app.float.notification_appname_margin_top')} )
.height($r('app.float.title_font_height'))
Row() {
Column() {
@ -52,13 +53,13 @@ export default struct SettingDialog {
.fontSize($r('app.float.setting_cont_fontsize'))
.fontColor($r('app.color.dialog_font_color'))
.height(Constants.SETTING_CONT_HEIGHT)
}.alignItems(HorizontalAlign.Center)
.width(Constants.SETTING_CONTENT_WITH)
}
.width(Constants.SETTING_DIALOG_WITH)
.alignItems(VerticalAlign.Center)
.align(Alignment.Center)
.margin({ top: $r('app.float.close_notification_margin_top') })
.border({ width: $r('app.float.setting_border_width'), color: Color.White,
radius: $r('app.float.setting_border_radius') })
.backgroundColor($r('app.color.dialog_font_back_color'))
@ -68,17 +69,17 @@ export default struct SettingDialog {
Column() {
Text($r('app.string.moreSettings'))
.fontSize($r('app.float.setting_cont_fontsize'))
.fontColor($r('app.color.dialog_font_color'))
.fontColor($r('app.color.dialog_font_back_color'))
.height(Constants.SETTING_CONT_HEIGHT)
}.alignItems(HorizontalAlign.Center)
.width(Constants.SETTING_CONTENT_WITH)
.align(Alignment.Center)
}
.width(Constants.SETTING_DIALOG_WITH)
.alignItems(VerticalAlign.Center)
.align(Alignment.Center)
.border({ width: $r('app.float.setting_border_width'), color: Color.White,
radius: $r('app.float.setting_border_radius') })
.backgroundColor($r('app.color.dialog_font_back_color'))
.backgroundColor($r('app.color.action_button_click_color'))
.onClick(this.openAbility.bind(this))
Row() {
@ -88,11 +89,11 @@ export default struct SettingDialog {
.textOverflow({ overflow: TextOverflow.Ellipsis })
.fontSize($r('app.float.setting_cont_fontsize'))
.fontColor($r('app.color.dialog_font_back_color'))
.height(Constants.SETTING_CONT_HEIGHT)
}.alignItems(HorizontalAlign.Center)
.width(Constants.SETTING_CONTENT_WITH)
}
.width(Constants.SETTING_DIALOG_WITH)
.margin( {top: $r('app.float.notification_cancle_margin_top')} )
.alignItems(VerticalAlign.Center)
.align(Alignment.Center)
.border({ width: $r('app.float.setting_border_width'), color: Color.White,
@ -100,6 +101,10 @@ export default struct SettingDialog {
.backgroundColor($r('app.color.dialog_font_color'))
.onClick(this.closeAbility.bind(this))
}.height(Constants.SETTING_DIALOG_HEIGHT)
.width(Constants.SETTING_DIALOG_WIDTH)
.backgroundColor('#FFFFFFFF')
.border({ width: $r('app.float.setting_border_width'), color: Color.White,
radius: $r('app.float.notification_border_radius') })
}
closeNotification() {
@ -109,18 +114,8 @@ export default struct SettingDialog {
openAbility() {
Log.showInfo(TAG, ` openAbility:showNotificationManagement`)
let mWindowManager = new WindowManager();
mWindowManager.setWindowMin((result) => {
Log.showInfo(TAG, `showNotificationManagement setWindowMin`)
let mFeatureAbilityManager = new FeatureAbilityManager()
mFeatureAbilityManager.openAbility(TAG, {
want: {
bundleName: 'com.ohos.systemui',
abilityName: 'com.ohos.systemui.notificationmanagement.MainAbility'
}
});
});
AppStorage.Set("showStatusBar", true);
EventManager.publish(obtainStartAbility('com.ohos.systemui', 'com.ohos.systemui.notificationmanagement.MainAbility',
{ 'migrateUri': 'pages/setEnable', 'migrateBundle': this.itemData.bundleName }))
this.closeAbility()
}

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,22 +13,23 @@
* limitations under the License.
*/
import Constants from '../../common/constants.ets';
import Log from '../../../../../../../../../../common/src/main/ets/default/Log.ets';
import CheckEmptyUtils from '../../../../../../../../../../common/src/main/ets/default/CheckEmptyUtils.ets';
import Constants, {NotificationLayout as Layout} from '../../common/constants';
import Log from '../../../../../../../../../../common/src/main/ets/default/Log';
import CheckEmptyUtils from '../../../../../../../../../../common/src/main/ets/default/CheckEmptyUtils';
const TAG = 'NoticeItem-TitleItem';
@Component
export default
struct TitleItem {
export default struct TitleItem {
private notificationSmallIcon: PixelMap
@Prop notificationName: string
@Prop notificationTime: string
@State srcIconDisplay: any = $r('app.media.ic_notification_down')
@Link isExpand: boolean
@Prop needExpand: boolean
@State rowSpace: any = $r('app.float.titleitem_row_space')
@Prop distributedDeviceName: string
private isSubItem: boolean= false;
private clickTitleAction: () => void
aboutToAppear() {
Log.showInfo(TAG, `aboutToAppear Start`);
@ -39,37 +40,55 @@ struct TitleItem {
}
build() {
Row() {
Row({ space: this.rowSpace }) {
if (!CheckEmptyUtils.isEmpty(this.notificationSmallIcon)) {
Flex({ alignItems: ItemAlign.Center, justifyContent: FlexAlign.Start }) {
if (!this.isSubItem) {
if (this.notificationSmallIcon) {
Image(this.notificationSmallIcon)
.objectFit(ImageFit.Contain)
.width($r('app.float.title_image_width'))
.height($r('app.float.title_image_height'))
.flexShrink(0)
.width(Layout.TITLE_IMAGE_SIZE)
.height(Layout.TITLE_IMAGE_SIZE)
}
Row() {
Text(this.notificationName)
.maxLines(Constants.DEFAULT_MAX_LINES)
.fontSize($r('app.float.title_name_fontsize'))
.flexShrink(1)
.fontColor($r("sys.color.ohos_fa_text_primary"))
.fontSize($r("sys.float.ohos_id_text_size_body3"))
.fontWeight(FontWeight.Regular)
.textOverflow({ overflow: TextOverflow.Ellipsis })
.maxLines(Constants.SINGLE_LINE)
}.margin({ left: 8 })
}
Text(this.notificationTime)
.fontSize($r('app.float.title_time_fontsize'))
.flexShrink(0)
}
.width(this.needExpand ? '80%' : '100%')
.fontColor($r("sys.color.ohos_fa_text_primary"))
.fontSize($r("sys.float.ohos_id_text_size_body3"))
.fontWeight(FontWeight.Regular)
.maxLines(Constants.SINGLE_LINE)
.flexGrow(0)
.margin({ left: !this.isSubItem ? 8 : 0, right: 8 })
Text($r('app.string.distributed_devicename', this.distributedDeviceName))
.fontColor($r("sys.color.ohos_fa_text_primary"))
.fontSize($r("sys.float.ohos_id_text_size_body3"))
.fontWeight(FontWeight.Regular)
.maxLines(Constants.SINGLE_LINE)
.visibility((this.distributedDeviceName ? true : false) ? Visibility.Visible : Visibility.None)
Blank()
if (this.needExpand) {
Flex({ direction: FlexDirection.Row, justifyContent: FlexAlign.End, alignItems: ItemAlign.Center }) {
Image(this.srcIconDisplay)
if (this.isExpand) {
Image($r('app.media.ic_notification_up'))
.objectFit(ImageFit.Contain)
.width($r('app.float.displayicon_width'))
.height($r('app.float.displayicon_height'))
}
.width('20%')
.width(Layout.TITLE_IMAGE_SIZE)
.height(Layout.TITLE_IMAGE_SIZE)
} else {
Image($r('app.media.ic_notification_down'))
.objectFit(ImageFit.Contain)
.width(Layout.TITLE_IMAGE_SIZE)
.height(Layout.TITLE_IMAGE_SIZE)
}
}
.height($r('app.float.titleitem_height'))
.width('100%')
}
.margin({ left: 12, right: 12 })
.height(Layout.TITLE_HEIGHT)
.onClick(this.clickTitleItem.bind(this))
}
@ -78,10 +97,11 @@ struct TitleItem {
if (this.needExpand) {
if (this.isExpand) {
this.isExpand = false;
this.srcIconDisplay = $r('app.media.ic_notification_down');
} else {
this.isExpand = true;
this.srcIconDisplay = $r('app.media.ic_notification_up');
}
if (this.clickTitleAction) {
this.clickTitleAction();
}
}
}

View File

@ -1,314 +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 '../../../../../../../../../common/src/main/ets/default/Log.ets';
import media from '@ohos.multimedia.media';
import NotificationService from '../model/NotificationService.ets'
import wantAgent from '@ohos.wantAgent';
import WindowManager from '../../../../../../../../../common/src/main/ets/default/WindowManager.ets';
import SourceType from '@ohos.notification'
import NotificationConfig from '../model/NotificationConfig.ets';
import CheckEmptyUtils from '../../../../../../../../../common/src/main/ets/default/CheckEmptyUtils.ets';
const TAG = 'NotificationViewModel';
const GROUP_THRESHOLD = 10;
/**
* Notification ViewModel class.
*/
export class ViewModel {
mWindowManager: WindowManager
audioPlayer: any
mNotificationList: any[];
mAppNotificationCount: any;
mCallback: any;
mNotificationCtrl: any = {}
constructor() {
this.mWindowManager = new WindowManager();
let tempLink = AppStorage.SetAndLink('notificationList', []);
this.mNotificationList = tempLink.get();
this.mAppNotificationCount = new Map();
this.audioPlayer = media.createAudioPlayer();
this.audioPlayer.src = 'file://system/etc/Light.ogg';
this.registerCallback();
this.loadFlowControlInfos()
}
registerCallback() {
this.mCallback = {
onNotificationConsume: this.onNotificationConsume.bind(this),
onNotificationCancel: this.onNotificationCancel.bind(this),
onNotificationLoad: this.onNotificationLoad.bind(this)
}
NotificationService.register(this.mCallback);
}
unregisterCallback() {
NotificationService.unRegister(this.mCallback);
}
/**
* notification CancelCallback
*
* @param {Object} data - return notificationItemData.
*/
onNotificationConsume(notificationItemData) {
Log.showInfo(TAG, `onNotificationConsume ${JSON.stringify(notificationItemData)}`);
//Verify the notifications can be displayed
if (!this.isCanShow(notificationItemData.bundleName)) {
//can not displayed
return;
}
if (!this.mAppNotificationCount.has(notificationItemData.appName)) {
this.mAppNotificationCount.set(notificationItemData.appName, 0);
}
this.mAppNotificationCount[notificationItemData.appName] += 1;
if (this.mAppNotificationCount[notificationItemData.appName] >= GROUP_THRESHOLD) {
this.groupNotification(notificationItemData, this.mAppNotificationCount[notificationItemData.appName]);
} else {
// Todo 排序插入
this.mNotificationList.unshift(notificationItemData);
this.updateFlowControlInfos(notificationItemData.bundleName, true)
this.updateNotification();
}
// Todo doAction(notificationItemData); 根据ruleData做处理
}
/**
* notification CancelCallback
*/
onNotificationCancel(notificationItemData) {
Log.showInfo(TAG, `onNotificationCancel ${JSON.stringify(notificationItemData)}`);
if (this.mAppNotificationCount[notificationItemData.appName] >= GROUP_THRESHOLD) {
// 组通知删除逻辑处理
return;
}
// 普通通知删除逻辑处理
for (let i = 0, len = this.mNotificationList.length; i < len; i++) {
if (this.mNotificationList[i].hashcode == notificationItemData.hashcode) {
Log.showInfo(TAG, `onNotificationCancel i = ${i}`);
this.mAppNotificationCount[notificationItemData.appName] -= 1;
let removeItemArr = this.mNotificationList.splice(i, 1);
Log.showInfo(TAG, `onNotificationCancel removeItemArr= ${JSON.stringify(removeItemArr)}`);
if (!CheckEmptyUtils.isEmpty(removeItemArr)) {
this.updateFlowControlInfos(removeItemArr[0].bundleName, false)
}
break;
}
}
}
onNotificationLoad() {
}
/**
* notification CancelCallback
*
* @param {Object} data - return notificationItemData.
*/
groupNotification(notificationItemData, num) {
if (num == GROUP_THRESHOLD) {
// 组通知转化
} else {
// 组通知添加
}
}
updateNotification() {
Log.showInfo(TAG, `updateNotification list: ${JSON.stringify(this.mNotificationList)}`);
Log.showInfo(TAG, `updateNotification len: ${this.mNotificationList.length}`);
this.sortNotification()
let listLink = AppStorage.Link('notificationList');
listLink.set(this.mNotificationList);
Log.showInfo(TAG, `updateNotification list: ${JSON.stringify(listLink.get())}`);
}
/**
* Sort the notifications.
*/
sortNotification() {
Log.showInfo(TAG, `sortNotification`);
if (this.mNotificationList == undefined || this.mNotificationList == null || this.mNotificationList.length < 1) {
return
}
this.mNotificationList.sort((itemA, itemB) => {
//long term notification come first
if (itemA.source == SourceType.TYPE_CONTINUOUS && itemB.source != SourceType.TYPE_CONTINUOUS) {
return -1
}
//long term notification come first
if (itemA.source != SourceType.TYPE_CONTINUOUS && itemB.source == SourceType.TYPE_CONTINUOUS) {
return 1
}
if ((itemA.source == SourceType.TYPE_CONTINUOUS && itemB.source == SourceType.TYPE_CONTINUOUS) ||
(itemA.source != SourceType.TYPE_CONTINUOUS && itemB.source != SourceType.TYPE_CONTINUOUS)
) {
return -1 * (itemA.timestamp - itemB.timestamp)
}
})
}
/**
* Remove all notifications.
*/
removeAllNotifications() {
if (this.mNotificationList == undefined || this.mNotificationList == null || this.mNotificationList.length < 1) {
this.mNotificationList = []
} else {
let index = this.mNotificationList.length
while (index--) {
Log.showInfo(TAG, `mNotificationList[${index}].source: ${this.mNotificationList[index].source}`);
//Except the Long term notifications
if (this.mNotificationList[index].source != SourceType.TYPE_CONTINUOUS) {
Log.showInfo(TAG, `mNotificationList[${index}].hashcode: ${this.mNotificationList[index].hashcode}`);
let hashCode = this.mNotificationList[index].hashcode
this.removeSysNotificationItem(hashCode)
let removeItemArr = this.mNotificationList.splice(index, 1)
Log.showInfo(TAG, `removeAllNotifications removeItemArr= ${JSON.stringify(removeItemArr)}`);
if (!CheckEmptyUtils.isEmpty(removeItemArr)) {
this.updateFlowControlInfos(removeItemArr[0].bundleName, false)
}
}
}
}
this.updateNotification()
}
removeNotificationItem(itemData, isDelSysConent) {
Log.showInfo(TAG, `removeNotificationItem, hashcode: ${itemData.hashcode}`);
for (let i = 0, len = this.mNotificationList.length; i < len; i++) {
if (this.mNotificationList[i].hashcode == itemData.hashcode) {
Log.showInfo(TAG, `this.mNotificationList[i].hashcode=${this.mNotificationList[i].hashcode}, itemData.hashcode=${itemData.hashcode}`);
Log.showInfo(TAG, `removeNotificationItem i = ${i}`);
this.mAppNotificationCount[itemData.appName] -= 1;
let removeItemArr = this.mNotificationList.splice(i, 1);
Log.showInfo(TAG, `removeNotificationItem removeItemArr= ${JSON.stringify(removeItemArr)}`);
if (!CheckEmptyUtils.isEmpty(removeItemArr)) {
this.updateFlowControlInfos(removeItemArr[0].bundleName, false)
}
break;
}
}
this.updateNotification();
if (isDelSysConent) {
this.removeSysNotificationItem(itemData.hashcode);
}
}
removeSysNotificationItem(hashcode) {
NotificationService.remove(hashcode);
}
startTargetAbility(itemData) {
Log.showInfo(TAG, 'startTargetAbility');
//close window
AppStorage.Set("showStatusBar", true);
this.mWindowManager.setWindowMin((result) => {
Log.showInfo(TAG, `setWindowMin ${result}`);
});
//open app
Log.showInfo(TAG, `itemClick wantAgent ${JSON.stringify(itemData.want)} id: ${itemData.id}`);
let TriggerInfo = {
code: 0,
want: '',
permission: '',
extraInfo: {}
};
wantAgent.trigger(itemData.want, TriggerInfo, ((err, data) => {
Log.showInfo(TAG, `itemClick wantAgent trigger err ${JSON.stringify(err)} data ${JSON.stringify(data)}`);
}));
//remove notification
this.removeNotificationItem(itemData, true);
}
loadFlowControlInfos() {
Log.showInfo(TAG, 'loadFlowControlInfos enter');
let notificationConfig = NotificationConfig.readNotificationConfig('statusbar')
Log.showInfo(TAG, 'NotificationConfig: ' + JSON.stringify(notificationConfig));
if (CheckEmptyUtils.isEmpty(notificationConfig)) {
Log.showInfo(TAG, 'NotificationConfig is no definition');
Log.showInfo(TAG, 'loadFlowControlInfos end');
return
}
this.mNotificationCtrl['currentTotal'] = 0;
this.mNotificationCtrl['limitTotal'] = notificationConfig.limitTotal
this.mNotificationCtrl['app'] = new Map();
for (let item of notificationConfig.app) {
let tmp = {
'canShow': item.canShow,
'currentNum': 0,
'limit': item.limit
}
this.mNotificationCtrl['app'].set(item.bundleName, tmp);
}
Log.showInfo(TAG, 'mNotificationCtrl: ' + JSON.stringify(this.mNotificationCtrl));
Log.showInfo(TAG, 'loadFlowControlInfos end');
}
isCanShow(bundleName: string): boolean {
Log.showInfo(TAG, 'isCanShow');
let result: boolean = true
if (!CheckEmptyUtils.isEmpty(this.mNotificationCtrl)) {
let currentTotal = this.mNotificationCtrl['currentTotal']
let limitTotal = this.mNotificationCtrl['limitTotal']
Log.showInfo(TAG, `isCanShow Total: currentTotal=${currentTotal},limitTotal=${limitTotal}`);
if (currentTotal + 1 > limitTotal) {
result = false
} else if (this.mNotificationCtrl['app'].has(bundleName)) {
let tmp = this.mNotificationCtrl['app'].get(bundleName)
Log.showInfo(TAG, `isCanShow appTotal: canShow=${tmp['canShow']},tmp['currentNum']=${tmp['currentNum']}`);
if (tmp['canShow'] === false || (tmp['currentNum'] + 1 > tmp['limit'])) {
result = false
}
}
}
Log.showInfo(TAG, `isCanShow :${result}`);
return result;
}
updateFlowControlInfos(bundleName: string, plusOrMinus: boolean): void {
Log.showInfo(TAG, `updateFlowControlInfos`);
if (!CheckEmptyUtils.isEmpty(this.mNotificationCtrl)) {
if (this.mNotificationCtrl['app'].has(bundleName)) {
let tmp = this.mNotificationCtrl['app'].get(bundleName)
if (plusOrMinus) {
tmp['currentNum'] += 1
} else if (tmp['currentNum'] > 0) {
tmp['currentNum'] -= 1
}
this.mNotificationCtrl['app'].set(bundleName, tmp)
}
if (plusOrMinus) {
this.mNotificationCtrl['currentTotal'] += 1
} else if (this.mNotificationCtrl['currentTotal'] > 0) {
this.mNotificationCtrl['currentTotal'] -= 1
}
}
Log.showInfo(TAG, `updateFlowControlInfos:${JSON.stringify(this.mNotificationCtrl)}`);
}
}
let viewModel = new ViewModel();
export default viewModel as ViewModel;

View File

@ -0,0 +1,419 @@
/*
* 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 SwitchUserManager from '../../../../../../../../../common/src/main/ets/default/SwitchUserManager';
import media from '@ohos.multimedia.media';
import vibrator from '@ohos.vibrator';
import wantAgent from '@ohos.wantAgent';
import SourceType from '@ohos.notification'
import NotificationService from '../model/NotificationService'
import NotificationWindowManager from '../model/NotificationWindowManager';
import NotificationConfig from '../model/NotificationConfig';
import CheckEmptyUtils from '../../../../../../../../../common/src/main/ets/default/CheckEmptyUtils';
import AbilityManager from "../../../../../../../../../common/src/main/ets/default/abilitymanager/abilityManager"
import EventManager from "../../../../../../../../../common/src/main/ets/default/event/EventManager"
import {obtainLocalEvent} from "../../../../../../../../../common/src/main/ets/default/event/EventUtil"
import CommonUtil from '../common/CommonUtil';
import Constants from '../common/constants';
const TAG = 'NotificationViewModel';
/**
* Notification ViewModel class.
*/
export class ViewModel {
audioPlayer: any;
mNotificationList: any[];
mCallback: any;
mNotificationCtrl: any = {};
constructor() {
Log.showInfo(TAG, `constructor`);
this.mNotificationList = [];
this.audioPlayer = media.createAudioPlayer();
// this.audioPlayer.src = 'file://system/etc/capture.ogg';
SwitchUserManager.getInstance().registerListener(this);
this.initFlowControlInfos();
SwitchUserManager.getInstance()
.getCurrentUserInfo()
.then((userInfo) => this.registerCallback(userInfo.userId))
.catch((err) => Log.showError(TAG, `Can't get current user, err: ${err}`));
}
registerCallback(userId) {
this.mCallback = {
userId: userId,
onNotificationConsume: this.onNotificationConsume.bind(this),
onNotificationCancel: this.onNotificationCancel.bind(this)
}
NotificationService.register(this.mCallback);
}
unregisterCallback() {
NotificationService.unRegister(this.mCallback);
}
userChange(userInfo) {
Log.showInfo(TAG, `UserChange, userInfo: ${JSON.stringify(userInfo)}`);
this.unregisterCallback();
this.mNotificationList.length = 0;
this.initFlowControlInfos();
this.registerCallback(userInfo.userId);
this.updateNotification();
NotificationService.loadAllNotifications();
}
/**
* notification CancelCallback
*
* @param {Object} data - return notificationItemData.
*/
onNotificationConsume(notificationItemData) {
if (notificationItemData === undefined) {
Log.showInfo(TAG, `onNotificationConsume notificationItemData is undefined`);
return;
}
this.onNotificationCancel(notificationItemData.hashcode)
Log.showInfo(TAG, `onNotificationConsume ${JSON.stringify(notificationItemData)}`);
//Verify the notifications can be displayed
if (!this.isCanShow(notificationItemData.bundleName)) {
//can not displayed
return;
}
if (notificationItemData.ruleData.isAllowStatusBarShow) {
}
if (notificationItemData.ruleData.isAllowNotificationListShow) {
this.mNotificationList.unshift(notificationItemData);
Log.showInfo(TAG, `reminder start `);
this.reminderWay(notificationItemData);
Log.showInfo(TAG, `reminder end `);
this.updateFlowControlInfos(notificationItemData.bundleName, true)
}
this.updateNotification();
}
/**
* notification CancelCallback
*/
onNotificationCancel(hashCode: string) {
Log.showInfo(TAG, `onNotificationCancel hashCode: ${JSON.stringify(hashCode)}`);
// Common Notification Deletion Logic Processing
for (let i = 0, len = this.mNotificationList.length; i < len; i++) {
if (this.mNotificationList[i].hashcode == hashCode) {
Log.showInfo(TAG, `removeNotificationItem i = ${i}`);
let removeItemArr = this.mNotificationList.splice(i, 1);
Log.showInfo(TAG, `onNotificationCancel removeItemArr= ${JSON.stringify(removeItemArr)}`);
if (!CheckEmptyUtils.isEmpty(removeItemArr)) {
this.updateFlowControlInfos(removeItemArr[0].bundleName, false)
}
this.updateNotification();
break;
}
}
}
updateNotification() {
Log.showInfo(TAG, `updateNotification list: ${JSON.stringify(this.mNotificationList)}`);
Log.showInfo(TAG, `updateNotification length: ${this.mNotificationList.length}`);
this.sortNotification()
let notificationList = this.groupByGroupName();
AppStorage.SetOrCreate('notificationList', notificationList);
}
groupByGroupName(): any[]{
Log.showInfo(TAG, `groupByGroupName`);
if (!this.mNotificationList || this.mNotificationList.length < 1) {
return [];
}
let groupArr: any[] = [];
let groups = {};
this.mNotificationList.forEach((item) => {
const groupName = `${item.bundleName}_${item.groupName}`;
Log.showInfo(TAG, `groupByGroupName groupName:${groupName}`);
if (!groups[groupName] || groups[groupName].length < 1) {
groups[groupName] = [];
groupArr.push(groups[groupName]);
}
groups[groupName].push(item)
})
Log.showInfo(TAG, `groupByGroupName groupArr:${JSON.stringify(groupArr)}`);
return groupArr;
}
/**
* Sort the notifications.
*/
sortNotification() {
Log.showInfo(TAG, `sortNotification`);
if (this.mNotificationList == undefined || this.mNotificationList == null || this.mNotificationList.length < 1) {
return
}
this.mNotificationList.sort((itemA, itemB) => {
//long term notification come first
if (itemA.source == SourceType.TYPE_CONTINUOUS && itemB.source != SourceType.TYPE_CONTINUOUS) {
return -1
}
//long term notification come first
if (itemA.source != SourceType.TYPE_CONTINUOUS && itemB.source == SourceType.TYPE_CONTINUOUS) {
return 1
}
if ((itemA.source == SourceType.TYPE_CONTINUOUS && itemB.source == SourceType.TYPE_CONTINUOUS) ||
(itemA.source != SourceType.TYPE_CONTINUOUS && itemB.source != SourceType.TYPE_CONTINUOUS)
) {
return -1 * (itemA.timestamp - itemB.timestamp)
}
})
}
/**
* Remove all notifications.
*/
removeAllNotifications() {
Log.showInfo(TAG, `removeAllNotifications`);
if (this.mNotificationList == undefined || this.mNotificationList == null || this.mNotificationList.length < 1) {
this.mNotificationList = []
} else {
let index = this.mNotificationList.length
while (index--) {
Log.showInfo(TAG, `removeAllNotifications isRemoveAllowed: ${index} ${this.mNotificationList[index].isRemoveAllowed} `);
Log.showInfo(TAG, `removeAllNotifications isOngoing: ${index} ${this.mNotificationList[index].isOngoing} `);
Log.showInfo(TAG, `removeAllNotifications isUnremovable: ${index} ${this.mNotificationList[index].isUnremovable} `);
//Except the Long term notifications
if (this.mNotificationList[index].isRemoveAllowed &&
!this.mNotificationList[index].isOngoing && !this.mNotificationList[index].isUnremovable) {
Log.showInfo(TAG, `mNotificationList[${index}].hashcode: ${this.mNotificationList[index].hashcode}`);
let hashCode = this.mNotificationList[index].hashcode
this.removeSysNotificationItem(hashCode)
let removeItemArr = this.mNotificationList.splice(index, 1)
Log.showInfo(TAG, `removeAllNotifications removeItemArr= ${JSON.stringify(removeItemArr)}`);
if (!CheckEmptyUtils.isEmpty(removeItemArr)) {
this.updateFlowControlInfos(removeItemArr[0].bundleName, false)
}
}
}
}
this.updateNotification()
}
removeNotificationItem(itemData, isDelSysConent) {
Log.showInfo(TAG, `removeNotificationItem, hashcode: ${itemData.hashcode}`);
for (let i = 0, len = this.mNotificationList.length; i < len; i++) {
if (this.mNotificationList[i].hashcode == itemData.hashcode) {
Log.showInfo(TAG, `removeNotificationItem i = ${i}`);
let removeItemArr = this.mNotificationList.splice(i, 1);
Log.showInfo(TAG, `removeNotificationItem removeItemArr= ${JSON.stringify(removeItemArr)}`);
if (!CheckEmptyUtils.isEmpty(removeItemArr)) {
this.updateFlowControlInfos(removeItemArr[0].bundleName, false)
}
break;
}
}
this.updateNotification();
if (isDelSysConent) {
this.removeSysNotificationItem(itemData.hashcode);
}
AppStorage.Delete(Constants.KEY_INPUT + itemData.id);
}
removeGroupNotification(itemData, isDelSysConent) {
Log.showInfo(TAG, `removeGroupNotification, groupName: ${itemData.groupName}`);
let groupName = itemData.groupName
for (let i = 0, len = this.mNotificationList.length; i < len; i++) {
if (this.mNotificationList[i].groupName == groupName) {
Log.showInfo(TAG, `removeGroupNotification i = ${i}`);
let id = this.mNotificationList[i].id
let hashcode = this.mNotificationList[i].hashcode
let removeItemArr = this.mNotificationList.splice(i, 1);
Log.showInfo(TAG, `removeGroupNotification removeItemArr= ${JSON.stringify(removeItemArr)}`);
if (!CheckEmptyUtils.isEmpty(removeItemArr)) {
this.updateFlowControlInfos(removeItemArr[0].bundleName, false)
}
if (isDelSysConent) {
this.removeSysNotificationItem(hashcode);
}
AppStorage.Delete(Constants.KEY_INPUT + id);
}
}
this.updateNotification();
}
removeSysNotificationItem(hashcode) {
NotificationService.remove(hashcode);
}
clickItem(itemData, want?: any) {
Log.showInfo(TAG, `clickItem itemId: ${itemData.id}, want: ${JSON.stringify(want)}`);
NotificationWindowManager.hideNotificationWindow();
CommonUtil.startWant((want) ? want : itemData.want);
this.removeNotificationItem(itemData, true);
}
clickReply(inputKey, content, want) {
Log.showInfo(TAG, `clickReply inputKey: ${inputKey}, content: ${content}, want: ${JSON.stringify(want)}`);
let info = {
code: 0,
want: { key: inputKey, data: content },
permission: '',
extraInfo: {}
}
CommonUtil.startWant(want, info);
}
initFlowControlInfos() {
Log.showInfo(TAG, 'initFlowControlInfos enter');
let notificationConfig = NotificationConfig.readNotificationConfig('statusbar')
Log.showInfo(TAG, 'NotificationConfig: ' + JSON.stringify(notificationConfig));
if (CheckEmptyUtils.isEmpty(notificationConfig)) {
Log.showInfo(TAG, 'NotificationConfig is no definition');
return
}
this.mNotificationCtrl = {
currentTotal: 0,
limitTotal: notificationConfig.limitTotal,
app: new Map()
}
for (let item of notificationConfig.app) {
let tmp = {
'canShow': item.canShow,
'currentNum': 0,
'limit': item.limit
}
this.mNotificationCtrl['app'].set(item.bundleName, tmp);
}
Log.showInfo(TAG, 'initFlowControlInfos end, mNotificationCtrl: ' + JSON.stringify(this.mNotificationCtrl));
}
isCanShow(bundleName: string): boolean {
Log.showInfo(TAG, 'isCanShow');
let result: boolean = true
if (!CheckEmptyUtils.isEmpty(this.mNotificationCtrl)) {
let currentTotal = this.mNotificationCtrl['currentTotal']
let limitTotal = this.mNotificationCtrl['limitTotal']
Log.showInfo(TAG, `isCanShow Total: currentTotal=${currentTotal},limitTotal=${limitTotal}`);
if (currentTotal + 1 > limitTotal) {
result = false
} else if (this.mNotificationCtrl['app'].has(bundleName)) {
let tmp = this.mNotificationCtrl['app'].get(bundleName)
Log.showInfo(TAG, `isCanShow appTotal: canShow=${tmp['canShow']},tmp['currentNum']=${tmp['currentNum']}`);
if (tmp['canShow'] === false || (tmp['currentNum'] + 1 > tmp['limit'])) {
result = false
}
}
}
Log.showInfo(TAG, `isCanShow :${result}`);
return result;
}
updateFlowControlInfos(bundleName: string, plusOrMinus: boolean): void {
Log.showInfo(TAG, `updateFlowControlInfos`);
if (!CheckEmptyUtils.isEmpty(this.mNotificationCtrl)) {
if (this.mNotificationCtrl['app'].has(bundleName)) {
let tmp = this.mNotificationCtrl['app'].get(bundleName)
if (plusOrMinus) {
tmp['currentNum'] += 1
} else if (tmp['currentNum'] > 0) {
tmp['currentNum'] -= 1
}
this.mNotificationCtrl['app'].set(bundleName, tmp)
}
if (plusOrMinus) {
this.mNotificationCtrl['currentTotal'] += 1
} else if (this.mNotificationCtrl['currentTotal'] > 0) {
this.mNotificationCtrl['currentTotal'] -= 1
}
}
Log.showInfo(TAG, `updateFlowControlInfos:${JSON.stringify(this.mNotificationCtrl)}`);
}
reminderWay(itemData) {
if (itemData.ruleData.isAllowBanner) {
Log.showInfo(TAG, `banner start `);
AbilityManager.setAbilityData(AbilityManager.ABILITY_NAME_BANNER_NOTICE, 'itemData', itemData);
EventManager.publish(obtainLocalEvent('onBannerNoticeShow', { 'itemData': itemData }))
Log.showInfo(TAG, `banner end `);
}
if (itemData.notificationFlags?.soundEnabled != Constants.NOTIFICATION_TYPE_CLOSE) {
if (itemData.ruleData.isAllowSound) {
try {
this.audioPlayer.src = itemData.sound;
Log.showInfo(TAG, `sound start `);
this.audioPlayer.play();
Log.showInfo(TAG, `sound end `);
} catch (e) {
Log.showInfo(TAG, `sound notificationItem id${itemData.id} alert error: ${e.toString()}`);
}
}
}
if (itemData.notificationFlags?.vibrationEnabled != Constants.NOTIFICATION_TYPE_CLOSE) {
if (itemData.ruleData.isAllowVibrationValues) {
// Log.showInfo(TAG, `vibrate start`);
// for (let i = 0, len = itemData.vibrationValues.length; i < len; i++) {
// vibrator.vibrate(itemData.vibrationValues[i], function(error){
// Log.showInfo(TAG, `vibrate id${i}`);
// if (error) {
// Log.showInfo(TAG, "error.code" + error.code + "error.message" + error.message);
// } else {
// Log.showInfo(TAG, "Callback returned to indicate a successful vibration.");
// }
// })
// }
}
}
}
getPluginTempLate(templateName) {
Log.showInfo(TAG, 'getPluginTempLate: ' + templateName);
return NotificationService.getPluginTempLate(templateName)
}
enableNotification(itemData, enable: boolean) {
Log.showInfo(TAG, `enableNotification, bundleName: ${itemData.bundleName} uid: ${itemData.uid}`);
return NotificationService.enableNotification({ bundle: itemData.bundleName, uid: itemData.uid }, enable);
}
clickDistributionItem(itemData, triggerInfo) {
Log.showInfo(TAG, `clickDistributionItem wantAgen: ${JSON.stringify(itemData.want)}, triggerInfo: ${JSON.stringify(triggerInfo)}`);
NotificationWindowManager.hideNotificationWindow();
CommonUtil.startWant(itemData.want, triggerInfo);
this.removeNotificationItem(itemData, true);
}
//get distributed device name
getDistributedDeviceName(itemData): Promise<string>{
Log.showInfo(TAG, `getDistributedDeviceName`);
Log.showInfo(TAG, `getDistributedDeviceName itemData want:${JSON.stringify(itemData.want)}`);
Log.showInfo(TAG, `getDistributedDeviceName itemData deviceId:${itemData.deviceId}`);
return new Promise((resolve) => {
let deviceName: string = '';
if (itemData.distributedOption?.isDistributed && !!itemData.deviceId) {
deviceName = NotificationService.getTrustedDeviceDeviceName(itemData.deviceId);
resolve(deviceName);
} else {
resolve(deviceName);
}
});
}
}
let viewModel = new ViewModel();
export default viewModel as ViewModel;

View File

@ -2,7 +2,7 @@
"color": [
{
"name":"notificationitem_background",
"value":"#ffffff"
"value":"#F2F1F3F5"
},
{
"name":"title_text_color",
@ -24,6 +24,10 @@
"name":"dialog_font_color",
"value":"#ffffff"
},
{
"name": "action_button_color",
"value": "#007DFF"
},
{
"name":"dialog_font_back_color",
"value":"#0759f6"
@ -31,6 +35,22 @@
{
"name": "confirm_divider_color",
"value": "#E3E3E3"
},
{
"name":"action_button_click_color",
"value":"#0D000000"
},
{
"name":"transparent",
"value":"#00000000"
},
{
"name": "button_background",
"value": "#4d000000"
},
{
"name": "device_divider_color",
"value": "#E3E3E3"
}
]
}

View File

@ -92,6 +92,18 @@
"name": "title_image_height",
"value": "30"
},
{
"name": "title_font_height",
"value": "28vp"
},
{
"name": "title_font_margin_t",
"value": "13vp"
},
{
"name": "message_font_margin_t",
"value": "14vp"
},
{
"name": "title_name_fontsize",
"value": "20"
@ -114,11 +126,11 @@
},
{
"name": "setting_title_fontsize",
"value": "28"
"value": "40"
},
{
"name": "setting_cont_fontsize",
"value": "26"
"value": "32"
},
{
"name": "setting_border_width",
@ -126,23 +138,83 @@
},
{
"name": "setting_border_radius",
"value": "30"
"value": "80"
},
{
"name": "notification_border_radius",
"value": "24vp"
},
{
"name": "action_button_height",
"value": "48"
},
{
"name": "action_button_padding",
"value": "12"
},
{
"name": "picture_default_height",
"value": "300"
},
{
"name": "confirm_title_fontsize",
"value": "28"
"value": "40"
},
{
"name": "confirm_cont_fontsize",
"value": "26"
"value": "32"
},
{
"name": "confirm_divider_height",
"value": "20"
"value": "44"
},
{
"name": "confirm_button_height",
"value": "60"
},
{
"name": "confirm_button_margin_t",
"value": "23vp"
},
{
"name": "icon_item_fontsize",
"value": "18"
},
{
"name": "setting_dialog_dy",
"value": "200"
},
{
"name": "confirm_dialog_dy",
"value": "250"
},
{
"name": "close_notification_margin_top",
"value": "15vp"
},
{
"name": "notification_appname_margin_top",
"value": "11vp"
},
{
"name": "notification_cancle_margin_top",
"value": "11vp"
},
{
"name": "device_divider_margin_l",
"value": "70"
},
{
"name": "device_divider_margin_r",
"value": "30"
},
{
"name": "device_border_width",
"value": "1"
},
{
"name": "device_border_radius",
"value": "30"
}
]
}

View File

@ -20,6 +20,14 @@
"name": "cancel",
"value": "取消"
},
{
"name": "enter",
"value": "回复"
},
{
"name": "Sending",
"value": "发送中"
},
{
"name": "close",
"value": "关闭"
@ -31,6 +39,14 @@
{
"name": "confirm_message",
"value": "是否关掉”%s“的所有通知?"
},
{
"name": "device_dialog_title",
"value": "设备选择"
},
{
"name": "distributed_devicename",
"value": "来自”%s“设备"
}
]
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.0 KiB

View File

@ -0,0 +1 @@
<svg id="图层_1" data-name="图层 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 96 96"><defs><style>.cls-1{fill:#1a1a1a;}</style></defs><title>ic</title><path class="cls-1" d="M76.29,72.05,52.24,48,76.29,24a3,3,0,1,0-4.24-4.24l-24,24-24-24A3,3,0,1,0,19.71,24L43.76,48l-24,24A3,3,0,1,0,24,76.29L48,52.24l24,24.05a3,3,0,0,0,4.24-4.24Z"/></svg>

After

Width:  |  Height:  |  Size: 349 B

View File

@ -0,0 +1,13 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="24px" height="24px" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<title>Public/ic_public_delete_filled</title>
<defs>
<path d="M19.905,7 L18.7182288,19.0681369 C18.5545878,20.7318206 17.1555495,22 15.4838372,22 L15.4838372,22 L8.51616277,22 C6.84445049,22 5.44541221,20.7318206 5.28177119,19.0681369 L5.28177119,19.0681369 L4.094,7 L19.905,7 Z M10,11.75 C9.58578644,11.75 9.25,12.0857864 9.25,12.5 L9.25,12.5 L9.25,18.5 C9.25,18.9142136 9.58578644,19.25 10,19.25 C10.4142136,19.25 10.75,18.9142136 10.75,18.5 L10.75,18.5 L10.75,12.5 C10.75,12.0857864 10.4142136,11.75 10,11.75 Z M14,11.75 C13.5857864,11.75 13.25,12.0857864 13.25,12.5 L13.25,12.5 L13.25,18.5 C13.25,18.9142136 13.5857864,19.25 14,19.25 C14.4142136,19.25 14.75,18.9142136 14.75,18.5 L14.75,18.5 L14.75,12.5 C14.75,12.0857864 14.4142136,11.75 14,11.75 Z M12,1.75 C13.5727118,1.75 14.862769,2.9601879 14.9897427,4.50013463 L21.25,4.5 C21.6642136,4.5 22,4.83578644 22,5.25 C22,5.64942022 21.68777,5.97591522 21.2940682,5.99872683 L21.25,6 L2.75,6 C2.33578644,6 2,5.66421356 2,5.25 C2,4.85057978 2.31222999,4.52408478 2.7059318,4.50127317 L2.75,4.5 L9.01025734,4.50013463 C9.13723098,2.9601879 10.4272882,1.75 12,1.75 Z" id="path-1"></path>
</defs>
<g id="Public/ic_public_delete_filled" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<mask id="mask-2" fill="white">
<use xlink:href="#path-1"></use>
</mask>
<use id="形状结合" fill="#000000" fill-rule="nonzero" xlink:href="#path-1"></use>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.6 KiB

View File

@ -0,0 +1,13 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="24px" height="24px" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<title>Public/ic_public_settings_filled</title>
<defs>
<path d="M13.4894964,1.25 C14.1901033,1.25 14.8231865,1.66785112 15.0986042,2.31205231 L15.0986042,2.31205231 L15.92125,4.23625 L16.77175,4.72725 L18.8556101,4.47607817 C19.5285537,4.39491431 20.1856012,4.70961774 20.5451004,5.27951678 L20.5451004,5.27951678 L20.5800481,5.33735213 L22.0680131,7.91013134 C22.4194652,8.51781272 22.3737758,9.27669833 21.9519545,9.83782407 L21.9519545,9.83782407 L20.69375,11.51125 L20.69375,12.4885 L21.9519801,14.16219 C22.3597241,14.70461 22.4160026,15.4318142 22.1018413,16.0285992 L22.1018413,16.0285992 L22.0680196,16.0898574 L20.5800481,18.6626479 C20.2293867,19.2689622 19.5509852,19.6077912 18.8556101,19.5239218 L18.8556101,19.5239218 L16.77175,19.2725 L15.92125,19.7635 L15.0986042,21.6879477 C14.832071,22.3113682 14.2305752,22.7228063 13.5570765,22.748702 L13.5570765,22.748702 L13.4894964,22.75 L10.5105451,22.75 C9.80990141,22.75 9.17679241,22.3321056 8.90139751,21.6878548 L8.90139751,21.6878548 L8.0785,19.7635 L7.228,19.2725 L5.14438986,19.5239218 C4.47144629,19.6050857 3.81439883,19.2903823 3.45489956,18.7204832 L3.45489956,18.7204832 L3.41995189,18.6626479 L1.9319804,16.0898574 C1.58053408,15.482186 1.62621577,14.7233142 2.04801988,14.16219 L2.04801988,14.16219 L3.306,12.4885 L3.306,11.51125 L2.04804545,9.83782407 C1.64028496,9.29540252 1.58399872,8.56818536 1.89816473,7.97139057 L1.89816473,7.97139057 L1.93198692,7.91013134 L3.41995189,5.33735213 C3.77061333,4.73103782 4.44901483,4.39220884 5.14438986,4.47607817 L5.14438986,4.47607817 L7.228,4.72725 L8.0785,4.23625 L8.90139751,2.31214525 C9.1679087,1.68867667 9.7694279,1.27719647 10.4429614,1.25129813 L10.4429614,1.25129813 L10.5105451,1.25 Z M12,7.5 C9.51471863,7.5 7.5,9.51471863 7.5,12 C7.5,14.4852814 9.51471863,16.5 12,16.5 C14.4852814,16.5 16.5,14.4852814 16.5,12 C16.5,9.51471863 14.4852814,7.5 12,7.5 Z M12,9 C13.6568542,9 15,10.3431458 15,12 C15,13.6568542 13.6568542,15 12,15 C10.3431458,15 9,13.6568542 9,12 C9,10.3431458 10.3431458,9 12,9 Z" id="path-1"></path>
</defs>
<g id="Public/ic_public_settings_filled" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<mask id="mask-2" fill="white">
<use xlink:href="#path-1"></use>
</mask>
<use id="形状结合" fill="#000000" fill-rule="nonzero" xlink:href="#path-1"></use>
</g>
</svg>

After

Width:  |  Height:  |  Size: 2.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.7 KiB

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