1/** 2 * Copyright (c) 2021-2022 Huawei Device Co., Ltd. 3 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * you may not use this file except in compliance with the License. 5 * You may obtain a copy of the License at 6 * 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * 9 * Unless required by applicable law or agreed to in writing, software 10 * distributed under the License is distributed on an "AS IS" BASIS, 11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 * See the License for the specific language governing permissions and 13 * limitations under the License. 14 */ 15 16import { Log } from '../utils/Log'; 17import { EventConstants } from '../constants/EventConstants'; 18import { CommonConstants } from '../constants/CommonConstants'; 19import { CardItemInfo } from '../bean/CardItemInfo'; 20import { SettingsModel } from './SettingsModel'; 21import { FormManager } from '../manager/FormManager'; 22import { RdbStoreManager } from '../manager/RdbStoreManager'; 23import { FormListInfoCacheManager } from '../cache/FormListInfoCacheManager'; 24import {PageDesktopModel} from './PageDesktopModel'; 25import { GridLayoutInfo } from '../interface'; 26 27 28const TAG = 'FormModel'; 29const KEY_FORM_LIST = 'formListInfo'; 30 31/** 32 * form model. 33 */ 34export class FormModel { 35 private readonly mRdbStoreManager: RdbStoreManager; 36 private readonly mFormManager: FormManager; 37 private readonly mFormListInfoCacheManager: FormListInfoCacheManager; 38 private readonly mAppItemFormInfoMap = new Map<string, CardItemInfo[]>(); 39 private readonly mPageDesktopModel: PageDesktopModel; 40 private readonly mAtomicServiceAppItemFormInfoMap = new Map<string, CardItemInfo[]>(); 41 42 private constructor() { 43 this.mRdbStoreManager = RdbStoreManager.getInstance(); 44 this.mFormManager = FormManager.getInstance(); 45 this.mFormListInfoCacheManager = FormListInfoCacheManager.getInstance(); 46 this.mPageDesktopModel = PageDesktopModel.getInstance(); 47 } 48 49 /** 50 * Get the form model object. 51 * 52 * @return {object} form model singleton 53 */ 54 static getInstance(): FormModel { 55 if (globalThis.FormModelInstance == null) { 56 globalThis.FormModelInstance = new FormModel(); 57 } 58 return globalThis.FormModelInstance; 59 } 60 61 /** 62 * Get the form info list of all ohos applications on the device. 63 * 64 * @return {array} allFormList 65 */ 66 async getAllFormsInfo() { 67 Log.showDebug(TAG, 'getAllFormsInfo start'); 68 const allFormList = await this.mFormManager.getAllFormsInfo(); 69 return allFormList; 70 } 71 72 getAllAppItemFormInfoMap(): Map<string, CardItemInfo[]> { 73 return this.mAppItemFormInfoMap; 74 } 75 76 /** 77 * Get the form info list of all ohos applications on the device by bundle name. 78 * 79 * @param {array} bundleName 80 * @param {function | undefined} callback 81 * 82 * @return {array} currentBundleFormsInfo 83 */ 84 async getFormsInfoByBundleName(bundleName: string, callback?) { 85 Log.showDebug(TAG, `getFormsInfoByBundleName bundleName: ${bundleName}`); 86 let currentBundleFormsInfo: any; 87 await this.mFormManager.getFormsInfoByApp(bundleName) 88 .then(bundleFormsInfo => { 89 currentBundleFormsInfo = bundleFormsInfo; 90 if (callback != undefined) { 91 callback(bundleName, bundleFormsInfo); 92 } 93 }) 94 .catch(err => { 95 Log.showError(TAG, `getFormsInfoByBundleName err: ${JSON.stringify(err)}`); 96 }); 97 AppStorage.setOrCreate('formMgrItem', currentBundleFormsInfo); 98 return currentBundleFormsInfo; 99 } 100 101 /** 102 * Get the form info list of all ohos applications on the device by module name. 103 * 104 * @param {string} bundleName 105 * @param {string} moduleName 106 * 107 * @return {array} currentModuleFormsInfo 108 */ 109 async getFormsInfoByModuleName(bundleName: string, moduleName: string) { 110 Log.showDebug(TAG, `getFormsInfoByModuleName bundleName: ${bundleName}, moduleName: ${moduleName}`); 111 const currentModuleFormsInfo = await this.mFormManager.getFormsInfoByModule(bundleName, moduleName); 112 return currentModuleFormsInfo; 113 } 114 115 /** 116 * Get the form info list from rdb. 117 * 118 * @return {array} allFormList 119 */ 120 async getAllFormsInfoFromRdb() { 121 Log.showDebug(TAG, 'getAllFormsInfoFromRdb start'); 122 const allFormList = await this.mRdbStoreManager.getAllFormInfos(); 123 return allFormList; 124 } 125 126 /** 127 * Update the form info in rdb by id. 128 * 129 * @param {object} cardItemInfo 130 * 131 * @return {boolean} result 132 */ 133 async updateFormInfoById(cardItemInfo) { 134 return await this.mRdbStoreManager.updateFormInfoById(cardItemInfo); 135 } 136 137 /** 138 * Delete form in rdb and fms by id. 139 * 140 * @param {number} cardId 141 */ 142 async deleteFormById(cardId: number): Promise<boolean> { 143 try{ 144 await this.mRdbStoreManager.deleteFormInfoById(cardId); 145 await this.mFormManager.deleteCard(cardId.toString()); 146 } catch(error){ 147 Log.showError(TAG, `deleteFormById err: ${JSON.stringify(error)}`); 148 return false; 149 } 150 return true; 151 152 } 153 154 /** 155 * Delete form in fms by formId. 156 * 157 * @param {number} formId 158 */ 159 deleteFormByFormID(formId: number) { 160 this.mFormManager.deleteCard(formId.toString()); 161 } 162 163 /** 164 * Set app item form info into map. 165 * 166 * @param {string} bundleName 167 * @param {array} appItemFormInfo 168 */ 169 setAppItemFormInfo(bundleName: string, appItemFormInfo: CardItemInfo[]): void { 170 this.mAppItemFormInfoMap.set(bundleName, appItemFormInfo); 171 } 172 173 /** 174 * Get app item form info from map. 175 * 176 * @param {string} bundleName 177 * 178 * @return {array | undefined} mAppItemFormInfoMap 179 */ 180 getAppItemFormInfo(bundleName: string, moduleName?: string): CardItemInfo[] | undefined { 181 Log.showDebug(TAG, `getAppItemFormInfo bundleName: ${bundleName}, 182 appItemFormInfo: ${JSON.stringify(this.mAppItemFormInfoMap.get(bundleName))}`); 183 let formList = this.mAppItemFormInfoMap.get(bundleName); 184 if (formList && formList.length && moduleName) { 185 formList = formList.filter(item => item.moduleName === moduleName); 186 } 187 return formList; 188 } 189 190 /** 191 * Update app item form info into map. 192 * 193 * @param {string} bundleName 194 * @param {string | undefined} eventType 195 */ 196 async updateAppItemFormInfo(bundleName: string, eventType?: string): Promise<void> { 197 if (eventType && eventType === EventConstants.EVENT_PACKAGE_REMOVED) { 198 this.mAppItemFormInfoMap.delete(bundleName); 199 return; 200 } 201 const formsInfoList = this.getFormsInfoByBundleName(bundleName, this.setAppItemFormInfo.bind(this)); 202 } 203 204 /** 205 * Delete form by bundleName and update layout info. 206 * 207 * @param {string} bundleName 208 */ 209 deleteFormByBundleName(bundleName: string): void { 210 const settingsModel = SettingsModel.getInstance(); 211 this.mRdbStoreManager.deleteFormInfoByBundle(bundleName); 212 const formInfoList: any = this.mFormListInfoCacheManager.getCache(KEY_FORM_LIST); 213 if (formInfoList === CommonConstants.INVALID_VALUE) { 214 return; 215 } 216 const layoutInfo = settingsModel.getLayoutInfo(); 217 const tempFormInfoList = JSON.parse(JSON.stringify(formInfoList)); 218 const pageItemMap = new Map<string, number>(); 219 for (let i = 0; i < layoutInfo.layoutInfo.length; i++) { 220 const tmpPage = layoutInfo.layoutInfo[i].page.toString(); 221 if (pageItemMap.has(tmpPage)) { 222 pageItemMap.set(tmpPage, pageItemMap.get(tmpPage) + 1); 223 } else { 224 pageItemMap.set(tmpPage, 1); 225 } 226 } 227 for(let i = formInfoList.length - 1; i >= 0; i--) { 228 const formInfo = formInfoList[i]; 229 if (formInfo.bundleName === bundleName) { 230 tempFormInfoList.splice(i, 1); 231 for(let j = layoutInfo.layoutInfo.length - 1; j >= 0; j--) { 232 if (layoutInfo.layoutInfo[j].typeId === CommonConstants.TYPE_CARD && formInfo.cardId == layoutInfo.layoutInfo[j].cardId) { 233 const tmpPage = layoutInfo.layoutInfo[j].page.toString(); 234 pageItemMap.set(tmpPage, pageItemMap.get(tmpPage) - 1); 235 layoutInfo.layoutInfo.splice(j, 1); 236 break; 237 } 238 } 239 } 240 } 241 if (tempFormInfoList.length === 0) { 242 this.mFormListInfoCacheManager.setCache(KEY_FORM_LIST, null); 243 } else { 244 this.mFormListInfoCacheManager.setCache(KEY_FORM_LIST, tempFormInfoList); 245 } 246 247 this.updateBlankPage(pageItemMap, layoutInfo); 248 settingsModel.setLayoutInfo(layoutInfo); 249 } 250 251 /** 252 * Delete form by cardId. 253 * 254 * @param {number} cardId. 255 */ 256 async deleteForm(cardId) { 257 Log.showDebug(TAG, 'deleteForm start'); 258 let gridLayoutInfo: GridLayoutInfo = { 259 layoutDescription: undefined, 260 layoutInfo: [] 261 }; 262 gridLayoutInfo = SettingsModel.getInstance().getLayoutInfo(); 263 const cardIndex = gridLayoutInfo.layoutInfo.findIndex(item => { 264 return item.typeId === CommonConstants.TYPE_CARD && item.cardId === cardId; 265 }); 266 if (cardIndex != CommonConstants.INVALID_VALUE) { 267 this.deleteFormById(cardId); 268 const page = gridLayoutInfo.layoutInfo[cardIndex].page; 269 gridLayoutInfo.layoutInfo.splice(cardIndex, 1); 270 let ret: boolean = this.mPageDesktopModel.deleteBlankPageFromLayoutInfo(gridLayoutInfo, page); 271 SettingsModel.getInstance().setLayoutInfo(gridLayoutInfo); 272 if(ret){ 273 const curPageIndex = this.mPageDesktopModel.getPageIndex(); 274 Log.showInfo(TAG, 'deleteForm' + curPageIndex); 275 this.mPageDesktopModel.setPageIndex(curPageIndex - 1); 276 } 277 } 278 const formInfoList: any = this.mFormListInfoCacheManager.getCache(KEY_FORM_LIST); 279 if (formInfoList === CommonConstants.INVALID_VALUE) { 280 return; 281 } 282 for(let i = 0; i < formInfoList.length; i++) { 283 if (formInfoList[i].cardId === cardId){ 284 formInfoList.splice(i, 1); 285 break; 286 } 287 } 288 if (formInfoList.length === 0) { 289 this.mFormListInfoCacheManager.setCache(KEY_FORM_LIST, null); 290 } else { 291 this.mFormListInfoCacheManager.setCache(KEY_FORM_LIST, formInfoList); 292 } 293 } 294 295 /** 296 * update page number if blank page is exist 297 * 298 * @param pageItemMap 299 * @param layoutInfo 300 */ 301 private updateBlankPage(pageItemMap, layoutInfo): void { 302 const blankPages = []; 303 for (let [page, count] of pageItemMap) { 304 if (count === 0) { 305 layoutInfo.layoutDescription.pageCount--; 306 blankPages.push(page); 307 } 308 } 309 for (let m = 0; m < layoutInfo.layoutInfo.length; m++) { 310 let pageMinus = 0; 311 for (let n = 0; n < blankPages.length; n++) { 312 if (layoutInfo.layoutInfo[m].page > blankPages[n]) { 313 pageMinus++; 314 } 315 } 316 if (pageMinus != 0) { 317 layoutInfo.layoutInfo[m].page = layoutInfo.layoutInfo[m].page - pageMinus; 318 } 319 } 320 } 321 322 private setAtomicServiceAppItemFormInfo(bundleName: string, appItemFormInfo: CardItemInfo[]): void { 323 this.mAtomicServiceAppItemFormInfoMap.set(bundleName, appItemFormInfo); 324 } 325 326 /** 327 * 获取所有原服务app 卡片信息 328 * 329 * @returns {Map<string, CardItemInfo[]>} mAtomicServiceAppItemFormInfoMap 330 */ 331 getAllAtomicServiceAppItemFormInfoMap(): Map<string, CardItemInfo[]> { 332 return this.mAtomicServiceAppItemFormInfoMap; 333 } 334 335 /** 336 * 先从缓存中获取原服务卡片信息,没有的话,再从卡片管理器获取 337 * 338 * @param bundleName bundleName 339 * @returns {Promise<CardItemInfo[]>} 340 */ 341 async getAtomicServiceFormsInfoFromMapAndManager(bundleName: string): Promise<CardItemInfo[]> { 342 let cardInfo: CardItemInfo[] = this.mAtomicServiceAppItemFormInfoMap.get(bundleName); 343 if (typeof cardInfo === 'undefined') { 344 return this.mFormManager.getFormsInfoByApp(bundleName) 345 .then(bundleFormsInfo => { 346 Log.showInfo(TAG, `getAtomicServiceFormsInfoFromMapAndManager bundleFormsInfo: ${JSON.stringify(bundleFormsInfo)}`); 347 return bundleFormsInfo; 348 }) 349 .catch(err => { 350 Log.showError(TAG, `getAtomicServiceFormsInfoFromMapAndManager err: ${JSON.stringify(err)}`); 351 return []; 352 }); 353 } 354 return cardInfo; 355 } 356 357 /** 358 * 更新原服务应用的卡片信息 359 * 360 * @param bundleName {string} bundleName 361 * @param eventType {string | undefined} eventType 362 * @returns {Promise<void>} 363 */ 364 async updateAtomicServiceAppItemFormInfo(bundleName: string, eventType?: string): Promise<void> { 365 if (eventType && eventType === EventConstants.EVENT_PACKAGE_REMOVED) { 366 this.mAtomicServiceAppItemFormInfoMap.delete(bundleName); 367 return; 368 } 369 await this.getFormsInfoByBundleName(bundleName, this.setAtomicServiceAppItemFormInfo.bind(this)); 370 } 371 372 /** 373 * 从缓存中获取原服务app 卡片信息 374 * 375 * @param bundleName bundleName 376 * @returns CardItemInfo[] 377 */ 378 getAtomicServiceAppItemFormInfo(bundleName: string): CardItemInfo[] | undefined { 379 Log.showInfo(TAG, `getAtomicServiceAppItemFormInfo bundleName: ${bundleName}, ` + 380 `appItemFormInfo: ${JSON.stringify(this.mAtomicServiceAppItemFormInfoMap.get(bundleName))}`); 381 return this.mAtomicServiceAppItemFormInfoMap.get(bundleName); 382 } 383 384 /** 385 * 删除原服务卡片信息 386 * 387 * @param bundleName 包名 388 */ 389 deleteAtomicServiceAppItemFormInfo(bundleName: string): void { 390 this.mAtomicServiceAppItemFormInfoMap.delete(bundleName); 391 } 392 393 getRealForm(cardItemInfos: CardItemInfo[]): CardItemInfo[] { 394 if (cardItemInfos.length <= 0) { 395 return null; 396 } 397 let result: CardItemInfo[] = []; 398 for (let j: number = 0; j < cardItemInfos.length; j++) { 399 let dimensions: number[] = cardItemInfos[j].supportDimensions; 400 for (let i: number = 0; i < dimensions.length; i++) { 401 const tempCard = new CardItemInfo(); 402 this.copyCardItemInfo(tempCard, cardItemInfos[j]); 403 let tempDimensions: number[] = []; 404 tempDimensions.push(dimensions[i]); 405 tempCard.supportDimensions = tempDimensions; 406 tempCard.cardDimension = dimensions[i]; 407 result.push(tempCard); 408 } 409 } 410 return result; 411 } 412 413 copyCardItemInfo(newCard: CardItemInfo, oldCard: CardItemInfo): void { 414 newCard.description = oldCard.description; 415 newCard.bundleName = oldCard.bundleName; 416 newCard.abilityName = oldCard.abilityName; 417 newCard.moduleName = oldCard.moduleName; 418 newCard.cardName = oldCard.cardName; 419 newCard.area = oldCard.area; 420 newCard.formConfigAbility = oldCard.formConfigAbility; 421 } 422 423 async getFullFormsInfoByBundleName(bundleName: string, callback?): Promise<CardItemInfo[]> { 424 let currentBundleFormsInfo: CardItemInfo[] = []; 425 currentBundleFormsInfo = await this.getFormsInfoByBundleName(bundleName, callback); 426 currentBundleFormsInfo = this.getRealForm(currentBundleFormsInfo); 427 AppStorage.setOrCreate('formMgrItem', currentBundleFormsInfo); 428 return currentBundleFormsInfo; 429 } 430 431 async doBeforeJumpToFormManager(formBundleName : string): Promise<void> { 432 const formItem = await this.getFullFormsInfoByBundleName(formBundleName); 433 AppStorage.setOrCreate('formItem', formItem); 434 } 435}