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'; 29 30/** 31 * form model. 32 */ 33export class FormModel { 34 private readonly mRdbStoreManager: RdbStoreManager; 35 private readonly mFormManager: FormManager; 36 private readonly mFormListInfoCacheManager: FormListInfoCacheManager; 37 private readonly mAppItemFormInfoMap = new Map<string, CardItemInfo[]>(); 38 private readonly mPageDesktopModel: PageDesktopModel; 39 private readonly mAtomicServiceAppItemFormInfoMap = new Map<string, CardItemInfo[]>(); 40 private readonly KEY_FORM_LIST: string = 'formListInfo'; 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: CardItemInfo[]; 87 try { 88 currentBundleFormsInfo = await this.mFormManager.getFormsInfoByApp(bundleName); 89 if (callback != undefined) { 90 callback(bundleName, currentBundleFormsInfo); 91 } 92 AppStorage.setOrCreate('formMgrItem', currentBundleFormsInfo); 93 return currentBundleFormsInfo; 94 } catch (err) { 95 Log.showError(TAG, `getFormsInfoByBundleName bundleName:${bundleName} err: ${JSON.stringify(err)}`); 96 } 97 } 98 99 /** 100 * Get the form info list of all ohos applications on the device by module name. 101 * 102 * @param {string} bundleName 103 * @param {string} moduleName 104 * 105 * @return {array} currentModuleFormsInfo 106 */ 107 async getFormsInfoByModuleName(bundleName: string, moduleName: string) { 108 Log.showDebug(TAG, `getFormsInfoByModuleName bundleName: ${bundleName}, moduleName: ${moduleName}`); 109 const currentModuleFormsInfo = await this.mFormManager.getFormsInfoByModule(bundleName, moduleName); 110 return currentModuleFormsInfo; 111 } 112 113 /** 114 * Get the form info list from rdb. 115 * 116 * @return {array} allFormList 117 */ 118 async getAllFormsInfoFromRdb() { 119 Log.showDebug(TAG, 'getAllFormsInfoFromRdb start'); 120 const allFormList = await this.mRdbStoreManager.getAllFormInfos(); 121 return allFormList; 122 } 123 124 /** 125 * Update the form info in rdb by id. 126 * 127 * @param {object} cardItemInfo 128 * 129 * @return {boolean} result 130 */ 131 async updateFormInfoById(cardItemInfo) { 132 return await this.mRdbStoreManager.updateFormInfoById(cardItemInfo); 133 } 134 135 /** 136 * Delete form in rdb and fms by id. 137 * 138 * @param {number} cardId 139 */ 140 async deleteFormById(cardId: number): Promise<boolean> { 141 try{ 142 await this.mRdbStoreManager.deleteFormInfoById(cardId); 143 await this.mFormManager.deleteCard(cardId.toString()); 144 } catch(error){ 145 Log.showError(TAG, `deleteFormById err: ${JSON.stringify(error)}`); 146 return false; 147 } 148 return true; 149 150 } 151 152 /** 153 * Delete form in fms by formId. 154 * 155 * @param {number} formId 156 */ 157 deleteFormByFormID(formId: number) { 158 this.mFormManager.deleteCard(formId.toString()); 159 } 160 161 /** 162 * Set app item form info into map. 163 * 164 * @param {string} bundleName 165 * @param {array} appItemFormInfo 166 */ 167 setAppItemFormInfo(bundleName: string, appItemFormInfo: CardItemInfo[]): void { 168 this.mAppItemFormInfoMap.set(bundleName, appItemFormInfo); 169 } 170 171 /** 172 * Get app item form info from map. 173 * 174 * @param {string} bundleName 175 * 176 * @return {array | undefined} mAppItemFormInfoMap 177 */ 178 getAppItemFormInfo(bundleName: string, moduleName?: string): CardItemInfo[] | undefined { 179 Log.showDebug(TAG, `getAppItemFormInfo bundleName: ${bundleName}, 180 appItemFormInfo: ${JSON.stringify(this.mAppItemFormInfoMap.get(bundleName))}`); 181 let formList = this.mAppItemFormInfoMap.get(bundleName); 182 if (formList && formList.length && moduleName) { 183 formList = formList.filter(item => item.moduleName === moduleName); 184 } 185 return formList; 186 } 187 188 /** 189 * Update app item form info into map. 190 * 191 * @param {string} bundleName 192 * @param {string | undefined} eventType 193 */ 194 async updateAppItemFormInfo(bundleName: string, eventType?: string): Promise<void> { 195 if (eventType && eventType === EventConstants.EVENT_PACKAGE_REMOVED) { 196 this.mAppItemFormInfoMap.delete(bundleName); 197 return; 198 } 199 this.getFormsInfoByBundleName(bundleName, this.setAppItemFormInfo.bind(this)); 200 } 201 202 /** 203 * Delete form by bundleName and update layout info. 204 * 205 * @param {string} bundleName 206 */ 207 deleteFormByBundleName(bundleName: string): void { 208 const settingsModel = SettingsModel.getInstance(); 209 this.mRdbStoreManager.deleteFormInfoByBundle(bundleName); 210 const formInfoList: any = this.mFormListInfoCacheManager.getCache(this.KEY_FORM_LIST); 211 if (formInfoList === CommonConstants.INVALID_VALUE) { 212 return; 213 } 214 const layoutInfo = settingsModel.getLayoutInfo(); 215 const tempFormInfoList = JSON.parse(JSON.stringify(formInfoList)); 216 const pageItemMap = new Map<string, number>(); 217 for (let i = 0; i < layoutInfo.layoutInfo.length; i++) { 218 const tmpPage = layoutInfo.layoutInfo[i].page.toString(); 219 if (pageItemMap.has(tmpPage)) { 220 pageItemMap.set(tmpPage, pageItemMap.get(tmpPage) + 1); 221 } else { 222 pageItemMap.set(tmpPage, 1); 223 } 224 } 225 for(let i = formInfoList.length - 1; i >= 0; i--) { 226 const formInfo = formInfoList[i]; 227 if (formInfo.bundleName === bundleName) { 228 tempFormInfoList.splice(i, 1); 229 for(let j = layoutInfo.layoutInfo.length - 1; j >= 0; j--) { 230 if (layoutInfo.layoutInfo[j].typeId === CommonConstants.TYPE_CARD && formInfo.cardId == layoutInfo.layoutInfo[j].cardId) { 231 const tmpPage = layoutInfo.layoutInfo[j].page.toString(); 232 pageItemMap.set(tmpPage, pageItemMap.get(tmpPage) - 1); 233 layoutInfo.layoutInfo.splice(j, 1); 234 break; 235 } 236 } 237 } 238 } 239 if (tempFormInfoList.length === 0) { 240 this.mFormListInfoCacheManager.setCache(this.KEY_FORM_LIST, null); 241 } else { 242 this.mFormListInfoCacheManager.setCache(this.KEY_FORM_LIST, tempFormInfoList); 243 } 244 245 this.updateBlankPage(pageItemMap, layoutInfo); 246 settingsModel.setLayoutInfo(layoutInfo); 247 } 248 249 /** 250 * Delete form by cardId. 251 * 252 * @param {number} cardId. 253 */ 254 async deleteForm(cardId) { 255 Log.showDebug(TAG, 'deleteForm start'); 256 let gridLayoutInfo: GridLayoutInfo = { 257 layoutDescription: undefined, 258 layoutInfo: [] 259 }; 260 gridLayoutInfo = SettingsModel.getInstance().getLayoutInfo(); 261 const cardIndex = gridLayoutInfo.layoutInfo.findIndex(item => { 262 return item.typeId === CommonConstants.TYPE_CARD && item.cardId === cardId; 263 }); 264 if (cardIndex != CommonConstants.INVALID_VALUE) { 265 this.deleteFormById(cardId); 266 const page = gridLayoutInfo.layoutInfo[cardIndex].page; 267 gridLayoutInfo.layoutInfo.splice(cardIndex, 1); 268 let ret: boolean = this.mPageDesktopModel.deleteBlankPageFromLayoutInfo(gridLayoutInfo, page); 269 SettingsModel.getInstance().setLayoutInfo(gridLayoutInfo); 270 if(ret){ 271 const curPageIndex = this.mPageDesktopModel.getPageIndex(); 272 Log.showInfo(TAG, 'deleteForm' + curPageIndex); 273 this.mPageDesktopModel.setPageIndex(curPageIndex - 1); 274 } 275 } 276 const formInfoList: any = this.mFormListInfoCacheManager.getCache(this.KEY_FORM_LIST); 277 if (formInfoList === CommonConstants.INVALID_VALUE) { 278 return; 279 } 280 for(let i = 0; i < formInfoList.length; i++) { 281 if (formInfoList[i].cardId === cardId){ 282 formInfoList.splice(i, 1); 283 break; 284 } 285 } 286 if (formInfoList.length === 0) { 287 this.mFormListInfoCacheManager.setCache(this.KEY_FORM_LIST, null); 288 } else { 289 this.mFormListInfoCacheManager.setCache(this.KEY_FORM_LIST, formInfoList); 290 } 291 } 292 293 /** 294 * update page number if blank page is exist 295 * 296 * @param pageItemMap 297 * @param layoutInfo 298 */ 299 private updateBlankPage(pageItemMap, layoutInfo): void { 300 const blankPages = []; 301 for (let [page, count] of pageItemMap) { 302 if (count === 0) { 303 layoutInfo.layoutDescription.pageCount--; 304 blankPages.push(page); 305 } 306 } 307 for (let m = 0; m < layoutInfo.layoutInfo.length; m++) { 308 let pageMinus = 0; 309 for (let n = 0; n < blankPages.length; n++) { 310 if (layoutInfo.layoutInfo[m].page > blankPages[n]) { 311 pageMinus++; 312 } 313 } 314 if (pageMinus != 0) { 315 layoutInfo.layoutInfo[m].page = layoutInfo.layoutInfo[m].page - pageMinus; 316 } 317 } 318 } 319 320 private setAtomicServiceAppItemFormInfo(bundleName: string, appItemFormInfo: CardItemInfo[]): void { 321 this.mAtomicServiceAppItemFormInfoMap.set(bundleName, appItemFormInfo); 322 } 323 324 /** 325 * 获取所有原服务app 卡片信息 326 * 327 * @returns {Map<string, CardItemInfo[]>} mAtomicServiceAppItemFormInfoMap 328 */ 329 getAllAtomicServiceAppItemFormInfoMap(): Map<string, CardItemInfo[]> { 330 return this.mAtomicServiceAppItemFormInfoMap; 331 } 332 333 /** 334 * 先从缓存中获取原服务卡片信息,没有的话,再从卡片管理器获取 335 * 336 * @param bundleName bundleName 337 * @returns {Promise<CardItemInfo[]>} 338 */ 339 async getAtomicServiceFormsInfoFromMapAndManager(bundleName: string): Promise<CardItemInfo[]> { 340 let cardInfo: CardItemInfo[] = this.mAtomicServiceAppItemFormInfoMap.get(bundleName); 341 if (typeof cardInfo === 'undefined') { 342 return this.mFormManager.getFormsInfoByApp(bundleName) 343 .then(bundleFormsInfo => { 344 Log.showInfo(TAG, `getAtomicServiceFormsInfoFromMapAndManager bundleFormsInfo: ${JSON.stringify(bundleFormsInfo)}`); 345 return bundleFormsInfo; 346 }) 347 .catch(err => { 348 Log.showError(TAG, `getAtomicServiceFormsInfoFromMapAndManager err: ${JSON.stringify(err)}`); 349 return []; 350 }); 351 } 352 return cardInfo; 353 } 354 355 /** 356 * 更新原服务应用的卡片信息 357 * 358 * @param bundleName {string} bundleName 359 * @param eventType {string | undefined} eventType 360 * @returns {Promise<void>} 361 */ 362 async updateAtomicServiceAppItemFormInfo(bundleName: string, eventType?: string): Promise<void> { 363 if (eventType && eventType === EventConstants.EVENT_PACKAGE_REMOVED) { 364 this.mAtomicServiceAppItemFormInfoMap.delete(bundleName); 365 return; 366 } 367 await this.getFormsInfoByBundleName(bundleName, this.setAtomicServiceAppItemFormInfo.bind(this)); 368 } 369 370 /** 371 * 从缓存中获取原服务app 卡片信息 372 * 373 * @param bundleName bundleName 374 * @returns CardItemInfo[] 375 */ 376 getAtomicServiceAppItemFormInfo(bundleName: string): CardItemInfo[] | undefined { 377 Log.showInfo(TAG, `getAtomicServiceAppItemFormInfo bundleName: ${bundleName}, ` + 378 `appItemFormInfo: ${JSON.stringify(this.mAtomicServiceAppItemFormInfoMap.get(bundleName))}`); 379 return this.mAtomicServiceAppItemFormInfoMap.get(bundleName); 380 } 381 382 /** 383 * 删除原服务卡片信息 384 * 385 * @param bundleName 包名 386 */ 387 deleteAtomicServiceAppItemFormInfo(bundleName: string): void { 388 this.mAtomicServiceAppItemFormInfoMap.delete(bundleName); 389 } 390 391 getRealForm(cardItemInfos: CardItemInfo[]): CardItemInfo[] { 392 if (cardItemInfos.length <= 0) { 393 return null; 394 } 395 let result: CardItemInfo[] = []; 396 for (let j: number = 0; j < cardItemInfos.length; j++) { 397 let dimensions: number[] = cardItemInfos[j].supportDimensions; 398 for (let i: number = 0; i < dimensions.length; i++) { 399 const tempCard = new CardItemInfo(); 400 this.copyCardItemInfo(tempCard, cardItemInfos[j]); 401 let tempDimensions: number[] = []; 402 tempDimensions.push(dimensions[i]); 403 tempCard.supportDimensions = tempDimensions; 404 tempCard.cardDimension = dimensions[i]; 405 result.push(tempCard); 406 } 407 } 408 return result; 409 } 410 411 copyCardItemInfo(newCard: CardItemInfo, oldCard: CardItemInfo): void { 412 newCard.description = oldCard.description; 413 newCard.bundleName = oldCard.bundleName; 414 newCard.abilityName = oldCard.abilityName; 415 newCard.moduleName = oldCard.moduleName; 416 newCard.cardName = oldCard.cardName; 417 newCard.area = oldCard.area; 418 newCard.formConfigAbility = oldCard.formConfigAbility; 419 } 420 421 async getFullFormsInfoByBundleName(bundleName: string, callback?): Promise<CardItemInfo[]> { 422 let currentBundleFormsInfo: CardItemInfo[] = []; 423 currentBundleFormsInfo = await this.getFormsInfoByBundleName(bundleName, callback); 424 currentBundleFormsInfo = this.getRealForm(currentBundleFormsInfo); 425 AppStorage.setOrCreate('formMgrItem', currentBundleFormsInfo); 426 return currentBundleFormsInfo; 427 } 428 429 async doBeforeJumpToFormManager(formBundleName : string): Promise<void> { 430 const formItem = await this.getFullFormsInfoByBundleName(formBundleName); 431 AppStorage.setOrCreate('formItem', formItem); 432 } 433}