* 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 router from '@ohos.router'
import AppItemInfo from '../../../../../../base/src/main/ets/default/bean/AppItemInfo'
import CheckEmptyUtils from '../../../../../../base/src/main/ets/default/utils/CheckEmptyUtils'
import CommonConstants from '../../../../../../base/src/main/ets/default/constants/CommonConstants'
import GridLayoutItemInfo from '../../../../../../base/src/main/ets/default/bean/GridLayoutItemInfo'
import FormManager from '../../../../../../base/src/main/ets/default/manager/FormManager'
import FormModel from '../../../../../../base/src/main/ets/default/model/FormModel'
import Logger from '../../../../../../base/src/main/ets/default/utils/Logger'
import LauncherAbilityManager from '../../../../../../base/src/main/ets/default/manager/LauncherAbilityManager'
import MenuInfo from '../../../../../../base/src/main/ets/default/bean/MenuInfo'
import ResourceManager from '../../../../../../base/src/main/ets/default/manager/ResourceManager'
const TAG: string = 'LayoutInfoModel'
const SYSTEM_APPLICATIONS: string = 'com.ohos.launcher,ohos.samples.launcher,com.ohos.systemui,com.ohos.devicemanagerui,com.ohos.callui,com.example.kikakeyboard,com.ohos.contactdataability,com.ohos.telephonydataability,com.ohos.medialibrary.MediaLibraryDataA,com.ohos.medialibrary.MediaScannerAbilityA'
const KEY_NAME = 'name'
export default class DesktopLayoutModel {
private layoutInfo: Array<Array<GridLayoutItemInfo>> = []
private readonly mSystemApplicationName = SYSTEM_APPLICATIONS.split(',')
private mLauncherAbilityManager: LauncherAbilityManager = undefined
private context: any = undefined
constructor(context) {
this.context = context
this.mLauncherAbilityManager = LauncherAbilityManager.getInstance(context)
}
* Get the application data model object.
*
* @return {object} application data model singleton
*/
static getInstance(context): DesktopLayoutModel {
if (globalThis.LayoutInfoModel == null) {
globalThis.LayoutInfoModel = new DesktopLayoutModel(context)
}
return globalThis.LayoutInfoModel
}
* getAppItemFormInfo
*
* @param bundleName
*/
getAppItemFormInfo(bundleName: string) {
return FormModel.getAppItemFormInfo(bundleName)
}
* buildMenuInfoList
*
* @param appInfo: GridLayoutItemInfo
*/
buildMenuInfoList(appInfo: GridLayoutItemInfo) {
if (CheckEmptyUtils.isEmpty(appInfo)) {
return undefined
}
let menuInfoList = new Array<MenuInfo>()
let open = new MenuInfo()
open.menuImgSrc = $r('app.media.ic_public_add_norm')
open.menuText = $r('app.string.app_menu_open')
open.onMenuClick = () => {
this.jumpTo(appInfo.abilityName, appInfo.bundleName)
}
menuInfoList.push(open)
Logger.info(TAG, `buildMenuInfoList getAppItemFormInfo,bundleName = ${appInfo.bundleName}`)
const formInfoList = FormModel.getAppItemFormInfo(appInfo.bundleName)
Logger.info(TAG, `buildMenuInfoList formInfoList = ${JSON.stringify(formInfoList)}`)
if (!CheckEmptyUtils.isEmptyArr(formInfoList)) {
let addFormToDeskTopMenu = new MenuInfo()
addFormToDeskTopMenu.menuImgSrc = $r('app.media.ic_public_app')
addFormToDeskTopMenu.menuText = $r('app.string.add_form_to_desktop')
addFormToDeskTopMenu.onMenuClick = () => {
Logger.info(TAG, 'Launcher click menu item into add form to desktop view')
if (!CheckEmptyUtils.isEmpty(appInfo)) {
AppStorage.SetOrCreate('formAppInfo', appInfo)
Logger.info(TAG, 'Launcher AppStorage.SetOrCreate formAppInfo')
this.jumpToFormManagerView(appInfo)
}
}
menuInfoList.push(addFormToDeskTopMenu)
}
return menuInfoList
}
* buildCardInfoList
*
* @param dialog
*/
buildCardInfoList(dialog: any) {
let menuInfoList = new Array<MenuInfo>()
const uninstallMenu = new MenuInfo()
uninstallMenu.menuImgSrc = $r('app.media.ic_public_delete')
uninstallMenu.menuText = $r('app.string.remove')
uninstallMenu.onMenuClick = () => {
Logger.info(TAG, 'Launcher click menu item uninstall')
if (!CheckEmptyUtils.isEmpty(dialog)) {
dialog.open()
}
}
menuInfoList.push(uninstallMenu)
return menuInfoList
}
* getAppName
*
* @param cacheKey
*/
getAppName(cacheKey: string) {
return ResourceManager.getInstance(this.context).getAppResourceCache(cacheKey, KEY_NAME)
}
* jump to form manager
* @param formInfo
* */
jumpToFormManagerView(formInfo: GridLayoutItemInfo) {
router.push({
url: 'pages/FormPage',
params: {
formInfo: formInfo
}
})
}
* Start target ability
*
* @param bundleName target bundle name
* @param abilityName target ability name
*/
jumpTo(abilityName: string, bundleName: string): void {
this.mLauncherAbilityManager.startLauncherAbility(abilityName, bundleName)
}
* getLayoutInfoCache
*/
getLayoutInfoCache() {
return this.layoutInfo
}
* Get the list of apps displayed on the desktop (private function).
*
* @return {array} bundleInfoList, excluding system applications
*/
async getAppListAsync(): Promise<AppItemInfo[]> {
let allAbilityList: AppItemInfo[] = await this.mLauncherAbilityManager.getLauncherAbilityList()
Logger.info(TAG, `getAppListAsync allAbilityList length: ${allAbilityList.length}`)
let launcherAbilityList: AppItemInfo[] = []
for (let i in allAbilityList) {
if (this.mSystemApplicationName.indexOf(allAbilityList[i].bundleName) === CommonConstants.INVALID_VALUE) {
launcherAbilityList.push(allAbilityList[i])
FormModel.updateAppItemFormInfo(allAbilityList[i].bundleName)
}
}
Logger.debug(TAG, `getAppListAsync launcherAbiltyList length: ${launcherAbilityList.length}`)
return launcherAbilityList
}
* getLayoutInfo
*/
async getLayoutInfo() {
let infos = await this.getAppListAsync()
let result = this.initPositionInfos(infos)
Logger.info(TAG, `getLayoutInfo result0,${JSON.stringify(result)}`)
this.layoutInfo = result
return this.layoutInfo
}
* initPositionInfos
*
* @param appInfos
*/
initPositionInfos(appInfos: Array<AppItemInfo>) {
Logger.info(TAG, `initPositionInfos, appInfos size = ${appInfos.length}`)
let countsOnePage = CommonConstants.DEFAULT_COLUMN_COUNT * CommonConstants.DEFAULT_ROW_COUNT
let result: Array<Array<GridLayoutItemInfo>> = []
let page = Math.floor(appInfos.length / countsOnePage) + 1
for (let i = 0;i < page; i++) {
let item: Array<GridLayoutItemInfo> = []
result.push(item)
}
Logger.debug(TAG, `result0 = ${JSON.stringify(result)}`)
for (let j = 0;j < appInfos.length; j++) {
let item = appInfos[j]
Logger.debug(TAG, `infos[${j}], item = ${JSON.stringify(item)}`)
let page = Math.floor(j / countsOnePage)
let column = Math.floor(j % CommonConstants.DEFAULT_COLUMN_COUNT)
let row = Math.floor(j / CommonConstants.DEFAULT_COLUMN_COUNT) % countsOnePage
let gridItem: GridLayoutItemInfo = this.covertAppItemToGridItem(item, page, column, row)
if (!CheckEmptyUtils.isEmpty(gridItem)) {
result[page].push(gridItem)
}
Logger.debug(TAG, `infos[${j}], page = ${page},row = ${row},column = ${column}`)
}
Logger.debug(TAG, `result1 = ${JSON.stringify(result)}`)
return result
}
private covertAppItemToGridItem(item: AppItemInfo, page: number, column: number, row: number) {
if (CheckEmptyUtils.isEmpty(item)) {
return undefined
}
let gridItem: GridLayoutItemInfo = new GridLayoutItemInfo()
gridItem.appName = item.appName
gridItem.appIconId = item.appIconId
gridItem.bundleName = item.bundleName
gridItem.moduleName = item.moduleName
gridItem.abilityName = item.abilityName
gridItem.container = -100
gridItem.page = page
gridItem.column = column
gridItem.row = row
gridItem.area = [1, 1]
gridItem.typeId = 0
return gridItem
}
* createCardToDeskTop
*
* @param formCardItem
*/
async createCardToDeskTop(formCardItem: any) {
if (CheckEmptyUtils.isEmpty(formCardItem)) {
return
}
Logger.info(TAG, `createCardToDeskTop formCardItem ${JSON.stringify(formCardItem)}`)
let gridItem = this.createNewCardItemInfo(formCardItem)
let page = this.layoutInfo.length
gridItem = this.updateItemLayoutInfo(gridItem)
if (gridItem.page >= page) {
this.layoutInfo.push([])
}
this.layoutInfo[gridItem.page].push(gridItem)
Logger.info(TAG, `createCardToDeskTop gridItem2 = ${JSON.stringify(gridItem)}`)
AppStorage.SetOrCreate('isRefresh', true)
}
* remove item from desktop
*
* @param item
*/
async removeItemFromDeskTop(item: GridLayoutItemInfo) {
if (CheckEmptyUtils.isEmpty(item)) {
return
}
Logger.info(TAG, 'removeCardFromDeskTop start')
let pageInfos = this.layoutInfo
searchCircle:for (let i = 0;i < pageInfos.length; i++) {
Logger.info(TAG, `removeCardFromDeskTop pageInfos${i}`)
for (let j = 0;j < pageInfos[i].length; j++) {
if (pageInfos[i][j].bundleName === item.bundleName && pageInfos[i][j].page === item.page
&& pageInfos[i][j].row === item.row && pageInfos[i][j].column === item.column) {
Logger.debug(TAG, `removeCardFromDeskTop pageInfos${i}${j} is find,remove`)
pageInfos[i].splice(j, 1)
if (pageInfos[i].length === 0) {
pageInfos.splice(i, 1)
}
break searchCircle
}
}
}
this.layoutInfo = pageInfos
Logger.info(TAG, `removeCardFromDeskTop item= ${JSON.stringify(item)}`)
AppStorage.SetOrCreate('isRefresh', true)
}
private updateItemLayoutInfo(item: GridLayoutItemInfo) {
let page = this.layoutInfo.length
const row = CommonConstants.DEFAULT_ROW_COUNT
const column = CommonConstants.DEFAULT_COLUMN_COUNT
let isNeedNewPage = true
pageCycle: for (let i = 0; i < page; i++) {
for (let y = 0; y < row; y++) {
for (let x = 0; x < column; x++) {
if (this.isPositionValid(item, i, x, y)) {
isNeedNewPage = false
item.page = i
item.column = x
item.row = y
break pageCycle
}
}
}
}
if (isNeedNewPage) {
item.page = page
item.column = 0
item.row = 0
}
return item
}
private isPositionValid(item: GridLayoutItemInfo, page: number, startColumn: number, startRow: number) {
const row = CommonConstants.DEFAULT_ROW_COUNT
const column = CommonConstants.DEFAULT_COLUMN_COUNT
if ((startRow + item.area[0]) > row || (startColumn + item.area[1]) > column) {
Logger.info(TAG, 'isPositionValid return false 1')
return false
}
let isValid = true
for (let x = startColumn; x < startColumn + item.area[1]; x++) {
for (let y = startRow; y < startRow + item.area[0]; y++) {
if (this.isPositionOccupied(page, x, y)) {
Logger.info(TAG, 'isPositionValid return false 2')
isValid = false
break
}
}
}
return isValid
}
private isPositionOccupied(page: number, column: number, row: number) {
const layoutInfo = this.layoutInfo[page]
for (const item of layoutInfo) {
const xMatch = (column >= item.column) && (column < item.column + item.area[1])
const yMatch = (row >= item.row) && (row < item.row + item.area[0])
if (xMatch && yMatch) {
return true
}
}
return false
}
private createNewCardItemInfo(formCardItem: any): GridLayoutItemInfo {
if (CheckEmptyUtils.isEmpty(formCardItem)) {
return undefined
}
let gridItem: GridLayoutItemInfo = new GridLayoutItemInfo()
gridItem.appName = formCardItem.appName
gridItem.typeId = CommonConstants.TYPE_CARD
gridItem.cardId = formCardItem.cardId
gridItem.cardName = formCardItem.cardName
gridItem.bundleName = formCardItem.bundleName
gridItem.moduleName = formCardItem.moduleName
gridItem.abilityName = formCardItem.abilityName
gridItem.container = -100
gridItem.page = 0
gridItem.column = 0
gridItem.row = 0
gridItem.area = FormManager.getCardSize(formCardItem.dimension)
return gridItem
}
}