/*
* Copyright (c) Huawei Technologies Co., Ltd. 2024-2025. All rights reserved.
* 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 { LogUtil } from '../utils/LogUtil';
import { SettingsDataUtils } from '../utils/SettingsDataUtils';
import { externalMenuPreferences } from './ExternalMenuPreferences';
import { MenuController } from '../core/controller/MenuController';
import {
ExternalMenuManager,
ExternalMenu,
ExternalMenuChangeListener,
LangChangeListener
} from './ExternalMenuManager';
import { AbilityUtils } from '../utils/AbilityUtils';
import { HiSysEventUtil } from '../systemEvent/HiSysEventUtil';
import { PageLifecycleObserverInterface } from '../core/lifecycle/Lifecycle';
import i18n from '@ohos.i18n';
import dataShare from '@ohos.data.dataShare';
import { SettingsBaseMenu } from '../core/model/menu/SettingsMenu';
import { Controller } from '../core/controller/Controller';
const ENTER_EXTERNAL_ENTRY: string = 'enter_external_entry';
/**
* 外部菜单控制器类
*
* @since 2022-06-25
*/
export class ExternalMenuController extends MenuController implements ExternalMenuChangeListener,
PageLifecycleObserverInterface, LangChangeListener {
public tag: string = 'ExternalMenuController : ';
public externalMenu?: ExternalMenu;
public language?: string;
constructor(menu: SettingsBaseMenu) {
super(menu);
}
static createExternalMenuController(menu: SettingsBaseMenu): Controller {
return new ExternalMenuController(menu)
}
public onLangChange(newLang: string): void {
if (this.externalMenu && this.externalMenu.key) {
LogUtil.info(`${this.tag} onLangChange to ${newLang}, reload menu: ${this.externalMenu.key}`);
this.enforceReloadContentResource();
}
}
public getListenerName(): string {
return this.menu.key ?? ' ';
}
public updateStatus(): void {
super.updateStatus();
this.loadContentResourceForInit(false);
}
public getObserverKey = (): string => {
return this.menu?.key as string;
}
public onPageShow(): void {
if (this.getCurrentVisibleStatus()) {
this.loadResource();
}
}
public onPageHide(): void {
}
public onExternalMenuChange(bundleName: string): void {
if (this.externalMenu?.bundleName === bundleName) {
LogUtil.info(`${this.tag} onExternalMenuChange ${bundleName}`);
this.loadExternalMenu();
}
}
public onExternalMenuLoadFinish(): void {
LogUtil.info(`${this.tag} onExternalMenuLoadFinish ${this.menu?.key}`);
this.loadExternalMenu();
}
public async loadContentResourceForInit(force: boolean): Promise<void> {
LogUtil.info(`${this.tag} loadContentResourceForInit force ${force} ${this.menu?.key}`);
this.externalMenu = await ExternalMenuManager.getInstance().getExternalMenu(this.menu.key);
if (this.externalMenu) {
let resource: string[] = externalMenuPreferences.getTitleAndSummaryResource(this.externalMenu, force);
this.menu.title = resource[0];
this.menu.summary = resource[1];
LogUtil.info(`${this.tag} loadContentResourceForInit ${this.menu.title} `);
}
}
protected registerDataChange(): void {
ExternalMenuManager.getInstance().registerListener(this);
ExternalMenuManager.getInstance().registerLangChangeListener(this);
}
protected unRegisterDataChange(): void {
ExternalMenuManager.getInstance().unRegisterListener(this);
ExternalMenuManager.getInstance().unregisterLangChangeListener(this);
}
protected async loadExternalMenu(): Promise<void> {
LogUtil.info(`${this.tag} loadExternalMenu ${this.menu?.key}`);
this.externalMenu = await ExternalMenuManager.getInstance().getExternalMenu(this.menu.key);
if (!this.externalMenu) {
LogUtil.info(`${this.tag} externalMenu not exist ${this.getLogKey()}`);
this.setVisible(false);
return;
}
}
protected loadResource(): void {
LogUtil.info(`${this.tag} loadResource ${this.menu?.key}`);
let currentLanguage = i18n.System.getSystemLanguage();
externalMenuPreferences.getDisplayVersion();
LogUtil.info(`${this.tag} load resource language ${this.language} to ${currentLanguage}`);
let forceRefresh: boolean = (this.language !== undefined) && (this.language !== currentLanguage);
this.language = currentLanguage;
this.loadContentResource(forceRefresh);
}
protected enforceReloadContentResource(): void {
LogUtil.info(`${this.tag} enforceReloadContentResource ${this.menu?.key}`);
let resource: string[] = externalMenuPreferences.getTitleAndSummaryResource(this.externalMenu, true);
this.menu.title = resource[0];
this.menu.summary = resource[1];
this.setVisible(true);
this.refreshUi();
}
protected loadContentResource(force: boolean): void {
LogUtil.info(`${this.tag} force ${force}`);
const curTitle: ResourceStr | undefined = this.menu.title;
let resource: string[] = externalMenuPreferences.getTitleAndSummaryResource(this.externalMenu, force);
this.menu.title = resource[0];
this.menu.summary = resource[1];
if (!force && String(this.menu.title) === String(curTitle)) {
LogUtil.info(`${this.tag} title is same, no need to refreshUi`);
return;
}
this.setVisible(true);
this.refreshUi();
}
public onMenuClick(): boolean {
let message: string = 'bundleName: ' + this.externalMenu?.bundleName + '; abilityName: ' +
this.externalMenu?.abilityName;
HiSysEventUtil.reportEntryEvent(ENTER_EXTERNAL_ENTRY, message);
AbilityUtils.startAbility({
bundleName: this.externalMenu?.bundleName,
abilityName: this.externalMenu?.abilityName,
});
return true;
}
}
export class UIExtensionMenuController extends ExternalMenuController {
static CreateUIExtensionMenuController(menu: SettingsBaseMenu): Controller {
return new UIExtensionMenuController(menu);
}
public tag: string = 'UIExtensionMenuController : ';
public onMenuClick(): boolean {
if (this.menu && this.menu.pathInfos) {
let message: string = 'bundleName: ' + this.externalMenu?.bundleName + '; abilityName: ' +
this.externalMenu?.abilityName;
HiSysEventUtil.reportEntryEvent(ENTER_EXTERNAL_ENTRY, message);
this.menu.pathInfos.clear();
this.menu.pushName(this.menu.key as string, undefined);
return true;
}
return false;
}
}
export class UIExtensionSubMenuController extends UIExtensionMenuController {
static CreateUIExtensionSubMenuController(menu: SettingsBaseMenu): Controller {
return new UIExtensionSubMenuController(menu);
}
public tag: string = 'UIExtensionSubMenuController : ';
public onMenuClick(): boolean {
if (this.menu && this.menu.pathInfos) {
let message: string = 'bundleName: ' + this.externalMenu?.bundleName + '; abilityName: ' +
this.externalMenu?.abilityName;
HiSysEventUtil.reportEntryEvent(ENTER_EXTERNAL_ENTRY, message);
this.menu.pushName(this.menu.key as string, undefined);
return true;
}
return false;
}
}
export class ExternalStateController extends ExternalMenuController {
public tag: string = 'ExternalStateController : ';
private dataHelper?: dataShare.DataShareHelper;
public onSettingsDataChange = () => {
this.updateMenuState();
}
protected loadResource(): void {
super.loadResource();
this.updateMenuState();
}
private updateMenuState(): void {
this.menu.state = this.externalMenu?.state ?? this.externalMenu?.loadStateResource();
this.refreshUi();
LogUtil.info(`${this.tag} ${this.menu.state}`);
}
protected registerDataChange(): void {
super.registerDataChange();
if (this.dataHelper) {
SettingsDataUtils.registerDataChange(this.dataHelper, this.externalMenu?.stateDbKey, this.onSettingsDataChange)
} else {
(SettingsDataUtils.createDataHelper(this.externalMenu?.stateDbKey as string) as
Promise<dataShare.DataShareHelper>).then((dataShareHelper) => {
if (dataShareHelper) {
this.dataHelper = dataShareHelper;
SettingsDataUtils.registerDataChange(this.dataHelper, this.externalMenu?.stateDbKey,
this.onSettingsDataChange);
}
})
}
}
protected unRegisterDataChange(): void {
super.unRegisterDataChange();
SettingsDataUtils.unRegisterDataChange(this.dataHelper, this.externalMenu?.stateDbKey);
}
}
export class ExternalSwitchController extends ExternalMenuController {
public tag: string = 'ExternalSwitchController : ';
private isChecked: boolean = true;
private dataHelper?: dataShare.DataShareHelper;
public onSettingsDataChange = () => {
this.updateSwitchState();
}
protected async loadResource(): Promise<void> {
super.loadResource();
LogUtil.info(`${this.tag} loadResource switchDbKey ${this.externalMenu?.switchDbKey}`);
LogUtil.info(`${this.tag} loadResource switchDefault ${this.externalMenu?.switchDefault}`);
this.updateSwitchState();
}
private updateSwitchState(): void {
let isChecked = this.updateCheckedState();
this.setChecked(isChecked);
}
protected registerDataChange(): void {
super.registerDataChange();
if (this.dataHelper) {
SettingsDataUtils.registerDataChange(this.dataHelper, this.externalMenu?.switchDbKey, this.onSettingsDataChange);
} else {
(SettingsDataUtils.createDataHelper(this.externalMenu?.stateDbKey as string) as
Promise<dataShare.DataShareHelper>).then((dataShareHelper?: dataShare.DataShareHelper | undefined) => {
if (dataShareHelper) {
this.dataHelper = dataShareHelper;
SettingsDataUtils.registerDataChange(this.dataHelper, this.externalMenu?.switchDbKey,
this.onSettingsDataChange);
}
})
}
}
protected unRegisterDataChange(): void {
super.unRegisterDataChange();
SettingsDataUtils.unRegisterDataChange(this.dataHelper, this.externalMenu?.switchDbKey);
}
/**
* 返回开关的实时状态
*/
protected updateCheckedState(): boolean {
return SettingsDataUtils.getSettingsData(this.externalMenu?.switchDbKey,
this.externalMenu?.switchDefault) === '1';
}
public onToggleChange(isOn: boolean): boolean {
LogUtil.info(`${this.tag} onToggleChange ${isOn}`);
// isOn 可能是 0/1 , 必须转换成boolean值 true/false, 否则开关控件不兼容,有异常
let booleanValue = Boolean(isOn).valueOf();
if (!this.handleCheckedChange(booleanValue)) {
LogUtil.error(`${this.tag} handleCheckedChange fail`);
this.refreshUi();
return false;
}
this.isChecked = booleanValue;
LogUtil.info(`${this.tag} handleCheckedChange success, isChecked : ${this.isChecked}`);
return true;
}
/**
* 返回开关的保存状态
*/
public getChecked(): boolean {
LogUtil.info(`${this.tag} getChecked ${this.isChecked}`);
return this.isChecked;
}
/**
* 设置开关的状态
*/
public setChecked(isChecked: boolean): void {
LogUtil.info(`${this.tag} setChecked ${isChecked}`);
if (this.isChecked !== isChecked) {
this.isChecked = isChecked;
LogUtil.info(`${this.tag} setChecked, refresh : ${this.isChecked}`);
this.refreshUi();
}
}
/**
* 开关变化的回调
*/
protected handleCheckedChange(isChecked: boolean): boolean {
SettingsDataUtils.setSettingsData(this.externalMenu?.switchDbKey, isChecked ? '1' : '0');
return true;
}
}