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'; 25 26 27const TAG = 'FormModel'; 28const KEY_FORM_LIST = 'formListInfo'; 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 41 private constructor() { 42 this.mRdbStoreManager = RdbStoreManager.getInstance(); 43 this.mFormManager = FormManager.getInstance(); 44 this.mFormListInfoCacheManager = FormListInfoCacheManager.getInstance(); 45 this.mPageDesktopModel = PageDesktopModel.getInstance(); 46 } 47 48 /** 49 * Get the form model object. 50 * 51 * @return {object} form model singleton 52 */ 53 static getInstance(): FormModel { 54 if (globalThis.FormModelInstance == null) { 55 globalThis.FormModelInstance = new FormModel(); 56 } 57 return globalThis.FormModelInstance; 58 } 59 60 /** 61 * Get the form info list of all ohos applications on the device. 62 * 63 * @return {array} allFormList 64 */ 65 async getAllFormsInfo() { 66 Log.showDebug(TAG, 'getAllFormsInfo start'); 67 const allFormList = await this.mFormManager.getAllFormsInfo(); 68 return allFormList; 69 } 70 71 getAllAppItemFormInfoMap(): Map<string, CardItemInfo[]> { 72 return this.mAppItemFormInfoMap; 73 } 74 75 /** 76 * Get the form info list of all ohos applications on the device by bundle name. 77 * 78 * @param {array} bundleName 79 * @param {function | undefined} callback 80 * 81 * @return {array} currentBundleFormsInfo 82 */ 83 async getFormsInfoByBundleName(bundleName: string, callback?) { 84 Log.showDebug(TAG, `getFormsInfoByBundleName bundleName: ${bundleName}`); 85 let currentBundleFormsInfo: any; 86 await this.mFormManager.getFormsInfoByApp(bundleName) 87 .then(bundleFormsInfo => { 88 currentBundleFormsInfo = bundleFormsInfo; 89 if (callback != undefined) { 90 callback(bundleName, bundleFormsInfo); 91 } 92 }) 93 .catch(err => { 94 Log.showError(TAG, `getFormsInfoByBundleName err: ${JSON.stringify(err)}`); 95 }); 96 AppStorage.setOrCreate('formMgrItem', currentBundleFormsInfo); 97 return currentBundleFormsInfo; 98 } 99 100 /** 101 * Get the form info list of all ohos applications on the device by module name. 102 * 103 * @param {string} bundleName 104 * @param {string} moduleName 105 * 106 * @return {array} currentModuleFormsInfo 107 */ 108 async getFormsInfoByModuleName(bundleName: string, moduleName: string) { 109 Log.showDebug(TAG, `getFormsInfoByModuleName bundleName: ${bundleName}, moduleName: ${moduleName}`); 110 const currentModuleFormsInfo = await this.mFormManager.getFormsInfoByModule(bundleName, moduleName); 111 return currentModuleFormsInfo; 112 } 113 114 /** 115 * Get the form info list from rdb. 116 * 117 * @return {array} allFormList 118 */ 119 async getAllFormsInfoFromRdb() { 120 Log.showDebug(TAG, 'getAllFormsInfoFromRdb start'); 121 const allFormList = await this.mRdbStoreManager.getAllFormInfos(); 122 return allFormList; 123 } 124 125 /** 126 * Update the form info in rdb by id. 127 * 128 * @param {object} cardItemInfo 129 * 130 * @return {boolean} result 131 */ 132 async updateFormInfoById(cardItemInfo) { 133 return await this.mRdbStoreManager.updateFormInfoById(cardItemInfo); 134 } 135 136 /** 137 * Delete form in rdb and fms by id. 138 * 139 * @param {number} cardId 140 */ 141 async deleteFormById(cardId: number): Promise<boolean> { 142 try{ 143 await this.mRdbStoreManager.deleteFormInfoById(cardId); 144 await this.mFormManager.deleteCard(cardId.toString()); 145 } catch(error){ 146 Log.showError(TAG, `deleteFormById err: ${JSON.stringify(error)}`); 147 return false; 148 } 149 return true; 150 151 } 152 153 /** 154 * Delete form in fms by formId. 155 * 156 * @param {number} formId 157 */ 158 deleteFormByFormID(formId: number) { 159 this.mFormManager.deleteCard(formId.toString()); 160 } 161 162 /** 163 * Set app item form info into map. 164 * 165 * @param {string} bundleName 166 * @param {array} appItemFormInfo 167 */ 168 setAppItemFormInfo(bundleName: string, appItemFormInfo: CardItemInfo[]): void { 169 this.mAppItemFormInfoMap.set(bundleName, appItemFormInfo); 170 } 171 172 /** 173 * Get app item form info from map. 174 * 175 * @param {string} bundleName 176 * 177 * @return {array | undefined} mAppItemFormInfoMap 178 */ 179 getAppItemFormInfo(bundleName: string, moduleName?: string): CardItemInfo[] | undefined { 180 Log.showDebug(TAG, `getAppItemFormInfo bundleName: ${bundleName}, 181 appItemFormInfo: ${JSON.stringify(this.mAppItemFormInfoMap.get(bundleName))}`); 182 let formList = this.mAppItemFormInfoMap.get(bundleName); 183 if (formList && formList.length && moduleName) { 184 formList = formList.filter(item => item.moduleName === moduleName); 185 } 186 return formList; 187 } 188 189 /** 190 * Update app item form info into map. 191 * 192 * @param {string} bundleName 193 * @param {string | undefined} eventType 194 */ 195 async updateAppItemFormInfo(bundleName: string, eventType?: string): Promise<void> { 196 if (eventType && eventType === EventConstants.EVENT_PACKAGE_REMOVED) { 197 this.mAppItemFormInfoMap.delete(bundleName); 198 return; 199 } 200 const formsInfoList = this.getFormsInfoByBundleName(bundleName, this.setAppItemFormInfo.bind(this)); 201 } 202 203 /** 204 * Delete form by bundleName and update layout info. 205 * 206 * @param {string} bundleName 207 */ 208 deleteFormByBundleName(bundleName: string): void { 209 const settingsModel = SettingsModel.getInstance(); 210 this.mRdbStoreManager.deleteFormInfoByBundle(bundleName); 211 const formInfoList: any = this.mFormListInfoCacheManager.getCache(KEY_FORM_LIST); 212 if (formInfoList === CommonConstants.INVALID_VALUE) { 213 return; 214 } 215 const layoutInfo = settingsModel.getLayoutInfo(); 216 const tempFormInfoList = JSON.parse(JSON.stringify(formInfoList)); 217 const pageItemMap = new Map<string, number>(); 218 for (let i = 0; i < layoutInfo.layoutInfo.length; i++) { 219 const tmpPage = layoutInfo.layoutInfo[i].page.toString(); 220 if (pageItemMap.has(tmpPage)) { 221 pageItemMap.set(tmpPage, pageItemMap.get(tmpPage) + 1); 222 } else { 223 pageItemMap.set(tmpPage, 1); 224 } 225 } 226 for(let i = formInfoList.length - 1; i >= 0; i--) { 227 const formInfo = formInfoList[i]; 228 if (formInfo.bundleName === bundleName) { 229 tempFormInfoList.splice(i, 1); 230 for(let j = layoutInfo.layoutInfo.length - 1; j >= 0; j--) { 231 if (layoutInfo.layoutInfo[j].typeId === CommonConstants.TYPE_CARD && formInfo.cardId == layoutInfo.layoutInfo[j].cardId) { 232 const tmpPage = layoutInfo.layoutInfo[j].page.toString(); 233 pageItemMap.set(tmpPage, pageItemMap.get(tmpPage) - 1); 234 layoutInfo.layoutInfo.splice(j, 1); 235 break; 236 } 237 } 238 } 239 } 240 if (tempFormInfoList.length === 0) { 241 this.mFormListInfoCacheManager.setCache(KEY_FORM_LIST, null); 242 } else { 243 this.mFormListInfoCacheManager.setCache(KEY_FORM_LIST, tempFormInfoList); 244 } 245 246 this.updateBlankPage(pageItemMap, layoutInfo); 247 settingsModel.setLayoutInfo(layoutInfo); 248 } 249 250 /** 251 * Delete form by cardId. 252 * 253 * @param {number} cardId. 254 */ 255 async deleteForm(cardId) { 256 Log.showDebug(TAG, 'deleteForm start'); 257 let gridLayoutInfo = { 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(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(KEY_FORM_LIST, null); 288 } else { 289 this.mFormListInfoCacheManager.setCache(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}