/*
* 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 bundle from '@ohos.bundle.bundleManager';
import bundleManager from '@ohos.bundle.bundleManager';
import defaultAppMgr from '@ohos.bundle.defaultAppManager';
import { EventBus } from '@ohos/settings.common/src/main/ets/framework/common/EventBus';
import { DynamicDataSource } from '@ohos/settings.common/src/main/ets/framework/model/DynamicDataSource';
import {
CompCtrlParam,
ComponentControl,
SettingBaseModel,
} from '@ohos/settings.common/src/main/ets/framework/model/SettingBaseModel';
import {
ItemResultType,
ItemType,
SettingIconStyle,
SettingIconType,
SettingItemModel } from '@ohos/settings.common/src/main/ets/framework/model/SettingItemModel';
import { LogUtil } from '@ohos/settings.common/src/main/ets/utils/LogUtil';
import { PushParam } from '@ohos/settings.common/src/main/ets/core/controller/Controller';
import { ResourceUtil } from '@ohos/settings.common/src/main/ets/utils/ResourceUtil';
import { AppListInfo } from '../model/SettingAppItemModel';
import { BrowserRadioController } from './BrowserRadioController';
import { AppEntry } from '../AppModel';
import { AppListLoader } from '../AppListLoader';
import { DefaultBrowserUtil } from '../util/DefaultBrowserUtil';
/* instrument ignore file */
const TAG = 'BrowserListController: ';
export class BrowserListController implements ComponentControl {
private compId: string = '';
private params: PushParam = new PushParam();
private dataSource: DynamicDataSource = new DynamicDataSource();
private radioController?: BrowserRadioController;
private bundleName: string = '';
private isSystemApp: boolean = true;
private appListAddCb = (data: object, appIndex: number) => {
LogUtil.info(`${TAG} app add`);
let bundleName = (data as String).toString();
if (bundleName) {
this.onAppListAdd(bundleName, appIndex);
}
};
private appListRemoveCb = (data: object, appIndex: number) => {
LogUtil.info(`${TAG} app remove`);
let bundleName = (data as String).toString();
if (bundleName) {
this.onAppListRemove(bundleName, appIndex);
}
};
constructor(radioController: BrowserRadioController, isSystemApp: boolean) {
this.isSystemApp = isSystemApp;
this.radioController = radioController;
}
init(compParam: CompCtrlParam): void {
LogUtil.showInfo(TAG, `onInit`);
if (!compParam || !compParam.compId) {
LogUtil.error(`${TAG} init fail, compParam is invalid`);
return;
}
LogUtil.info(`${TAG} init begin: ${compParam.compId}`);
this.compId = compParam.compId;
this.params = compParam.param as PushParam;
this.dataSource = compParam.dataSource as DynamicDataSource;
EventBus.getInstance().on('EVENT_ID_APP_LIST_ADD', this.appListAddCb);
EventBus.getInstance().on('EVENT_ID_APP_LIST_REMOVE', this.appListRemoveCb);
}
private async initData(): Promise<void> {
await this.initDefaultBrowser();
this.getBrowserList().then((browserListPro) => {
this.initGroups(browserListPro);
});
}
onPageShow(component: SettingBaseModel): void {
LogUtil.info(`${TAG} ${this.compId} onPageShow.`);
this.initData();
}
onPageHide(component: SettingBaseModel): void {
LogUtil.info(`${TAG} ${this.compId} onPageHide.`);
}
destroy(): void {
LogUtil.showInfo(TAG, 'onDestroy');
EventBus.getInstance().on('EVENT_ID_APP_LIST_ADD', this.appListRemoveCb);
EventBus.getInstance().detach('EVENT_ID_APP_LIST_REMOVE', this.appListRemoveCb);
}
private onAppListAdd(bundleName: string, appIndex: number): void {
LogUtil.info(`${TAG} onAppListAdd ${bundleName}`);
this.initData();
}
private onAppListRemove(bundleName: string, appIndex: number): void {
LogUtil.info(`${TAG} onAppListRemove ${bundleName}`);
this.initData();
}
public async getBrowserList(): Promise<AppListInfo[]> {
let browserListPro: AppListInfo[] = [];
try {
let browserList = await bundle.queryAbilityInfo({
'action': 'ohos.want.action.viewData',
'entities': ['entity.system.browsable'],
'uri': 'http'
}, bundle.AbilityFlag.GET_ABILITY_INFO_WITH_APPLICATION)
LogUtil.info(`${TAG} getBrowserList, ${browserList.length}`);
for (let browserListItem of browserList) {
browserListPro.push(await this.newAppInfo(browserListItem));
};
LogUtil.info(`${TAG} browserlistPro, ${browserListPro.length}`);
} catch (error) {
LogUtil.error(`${TAG} catch error : ${error?.message}`);
}
return browserListPro;
}
private async newAppInfo(browserListItem: bundle.AbilityInfo): Promise<AppListInfo> {
const bundleName: string = browserListItem.bundleName;
const appIndex: number = browserListItem.appIndex;
let entry: AppEntry = await AppListLoader.getInstance()
.getAndUpdateAppEntryByName(bundleName, appIndex) as AppEntry;
if (!entry) {
entry = await AppListLoader.getInstance().createAndCache(bundleName, appIndex) as AppEntry;
}
return {
labelId: browserListItem?.labelId as number,
label: entry?.label,
icon: entry.icon as PixelMap,
bundleName: browserListItem?.bundleName,
name: browserListItem?.name,
isSystemApp: browserListItem?.applicationInfo?.systemApp,
moduleName: browserListItem?.moduleName
};
}
private async initDefaultBrowser(): Promise<void> {
LogUtil.info(`${TAG} initDefaultBrowser`);
await this.getDefaultBrowser();
}
private async getDefaultBrowserApp(curDefaultBundleName: string): Promise<void> {
try {
let browserListPro: AppListInfo[] = await this.getBrowserList();
const defaultApp = browserListPro.find(browser => curDefaultBundleName === browser.bundleName);
if (defaultApp && defaultApp.isSystemApp === this.isSystemApp) {
this.bundleName = defaultApp.bundleName as string;
this.radioController?.initValue(this.compId, defaultApp);
return;
}
} catch (err) {
LogUtil.error(`${TAG} update browser state fail`);
}
}
private getLabel(defaultApp: AppListInfo): string {
let label: string = defaultApp?.label as string;
let text: string = ResourceUtil.getFormatStringSync($r('app.string.system_default'), '');
return defaultApp?.isSystemApp ? `${label} (${text})` : label;
}
private async getDefaultBrowser(): Promise<void> {
try {
let data: bundleManager.BundleInfo = await defaultAppMgr.getDefaultApplication(defaultAppMgr.ApplicationType
.BROWSER);
this.bundleName = data?.name;
await this.getDefaultBrowserApp(this.bundleName);
LogUtil.info(`${TAG} Operation successful. bundleInfo: ${data?.name}`);
} catch (err) {
LogUtil.error(`getDefaultBrowser Cause:code: ${err.code} message: ${err.message}`);
this.setSystemBrowserApp();
}
}
initGroups(appList: AppListInfo[]): void {
LogUtil.info(`${TAG} initGroups: ${appList.length} ${this.isSystemApp}`);
let systemBrowsers: AppListInfo[] = [];
if (this.isSystemApp) {
systemBrowsers = appList.filter(item => item.isSystemApp);
} else {
systemBrowsers = appList.filter(item => !item.isSystemApp);
}
if (systemBrowsers.length > 0) {
this.dataSource?.splice(0, this.dataSource?.length);
this.dataSource.pushData(...this.createItems(systemBrowsers));
}
}
private setSystemBrowserApp(): void {
try {
this.getBrowserList().then((browserListPro) => {
const systemBrowserApp = browserListPro.find(appInfo => appInfo.isSystemApp);
if (systemBrowserApp && systemBrowserApp.bundleName) {
DefaultBrowserUtil.setDefaultBrowser(systemBrowserApp.bundleName, 'entry',
systemBrowserApp.moduleName as string);
return;
}
LogUtil.error(`${TAG} System browser not foundApp`);
});
} catch (err) {
LogUtil.error(`${TAG} System browser set failed`);
}
}
private createItems(appList: AppListInfo[]): SettingItemModel[] {
let items: SettingItemModel[] = [];
for (let appInfo of appList) {
let item: SettingItemModel = {
id: appInfo.bundleName as string,
type: ItemType.ITEM_TYPE_STANDARD,
icon: {
icon: appInfo.icon as PixelMap,
iconType: SettingIconType.ICON_TYPE_APPICON,
style: this.getIconStyle()
},
title: { content: this.getLabel(appInfo) },
result: {
type: ItemResultType.RESULT_TYPE_RADIO,
result: {
style: { width: 22, height: 22, showUnchecked: true },
checked: this.setChecked(appInfo),
},
},
compControl: {
init: (param: CompCtrlParam) => {},
destroy: () => {},
onClick: (component: SettingBaseModel) => {
this.radioController?.onItemClick(this.compId, appInfo);
}
}
};
items.push(item);
}
return items;
}
private getIconStyle(): SettingIconStyle {
// 接入了HDS之后,图标不需要主动做描边处理
let style: SettingIconStyle = {
border: { width: '0px', color: '#00000000', radius: 0 },
borderRadius: 0,
width: 48,
height: 48,
mirrored: false
};
return style;
}
private setChecked(appInfo: AppListInfo): boolean | undefined {
LogUtil.info(`${TAG} setChecked ${this.bundleName}`);
return this.bundleName === appInfo.bundleName;
}
}