• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 Prompt from '@ohos.promptAction';
17import {
18  Log,
19  Trace,
20  CheckEmptyUtils,
21  StyleConstants,
22  EventConstants,
23  CommonConstants,
24  FormManager,
25  BadgeManager,
26  windowManager,
27  layoutConfigManager,
28  BaseViewModel,
29  SettingsModelObserver,
30  FormListInfoCacheManager,
31  FormModel,
32  SettingsModel,
33  PageDesktopModel,
34  MenuInfo,
35  CardItemInfo,
36  localEventManager
37} from '@ohos/common';
38import { BigFolderModel } from '@ohos/bigfolder';
39import { FormDetailLayoutConfig } from '@ohos/form';
40import PageDesktopConstants from '../common/constants/PageDesktopConstants';
41import { PageDesktopGridStyleConfig } from '../common/PageDesktopGridStyleConfig';
42import formHost from '@ohos.app.form.formHost';
43
44const TAG = 'PageDesktopViewModel';
45const KEY_APP_LIST = 'appListInfo';
46const KEY_FORM_LIST = 'formListInfo';
47
48export class PageDesktopViewModel extends BaseViewModel {
49  private readonly pageDesktopStyleConfig: PageDesktopGridStyleConfig = null;
50  private readonly formDetailLayoutConfig: FormDetailLayoutConfig = null;
51  private readonly mSettingsModel: SettingsModel;
52  private readonly mFolderModel: BigFolderModel;
53  private readonly mFormModel: FormModel;
54  private readonly mPageDesktopModel: PageDesktopModel;
55  private readonly mBadgeManager: BadgeManager;
56  private readonly mFormListInfoCacheManager: FormListInfoCacheManager;
57  private mBundleInfoList;
58  private mHideBundleInfoList = new Array<any>();
59  private mGridConfig;
60  private mGridAppsInfos;
61  private readonly mPageCoordinateData = {
62    gridXAxis: [],
63    gridYAxis: []
64  };
65  private isPad = false;
66  private isAddByDraggingFlag = false;
67  private desktopSwiperController: SwiperController;
68
69  async showFormManager(params) {
70    globalThis.createWindowWithName(windowManager.FORM_MANAGER_WINDOW_NAME, windowManager.RECENT_RANK);
71  }
72
73  setSwiperController(swiperController: SwiperController): void {
74    this.desktopSwiperController = swiperController;
75  }
76
77  showNext(): void {
78    this.desktopSwiperController?.showNext();
79  }
80
81  showPrevious(): void {
82    this.desktopSwiperController?.showPrevious();
83  }
84
85  private readonly mLocalEventListener = {
86    onReceiveEvent: (event, params) => {
87      Log.showDebug(TAG, `localEventListener receive event: ${event}, params: ${params}`);
88      switch (event) {
89        case EventConstants.EVENT_REQUEST_PAGEDESK_ITEM_ADD:
90          this.addToDesktop(params);
91          break;
92        case EventConstants.EVENT_REQUEST_PAGEDESK_ITEM_DELETE:
93          this.deleteAppItem(params);
94          break;
95        case EventConstants.EVENT_REQUEST_PAGEDESK_ITEM_UPDATE:
96          this.getGridList();
97          break;
98        case EventConstants.EVENT_BADGE_UPDATE:
99          this.updateBadgeNumber(params);
100          break;
101        case EventConstants.EVENT_REQUEST_PAGEDESK_FORM_ITEM_ADD:
102          this.createCardToDeskTop(params);
103          break;
104        case EventConstants.EVENT_SMARTDOCK_INIT_FINISHED:
105          this.getGridList();
106          break;
107        case EventConstants.EVENT_REQUEST_PAGEDESK_REFRESH:
108          this.pagingFiltering();
109          break;
110        case EventConstants.EVENT_REQUEST_FORM_ITEM_VISIBLE:
111          this.notifyVisibleForms();
112          break;
113        default:
114          if (!this.isPad) {
115            Log.showDebug(TAG, 'localEventListener hideBundleInfoList!')
116            this.mHideBundleInfoList = params;
117            this.getGridList();
118          }
119          break;
120      }
121    }
122  };
123
124  /**
125   * Notify forms on current page become visible.
126   */
127  notifyVisibleForms(): void {
128    let pageIndex = this.mPageDesktopModel.getPageIndex();
129    let formList = [];
130    let items = this.mGridAppsInfos[pageIndex];
131    for (let i = 0; i < items.length; i++) {
132      if (items[i].typeId == CommonConstants.TYPE_CARD) {
133        formList.push(String(items[i].cardId));
134      }
135    }
136    if (formList.length > 0) {
137      try {
138        formHost.notifyVisibleForms(formList).then(() => {
139          Log.showInfo(TAG, 'formHost notifyVisibleForms success');
140        }).catch((error) => {
141          Log.showInfo(TAG, 'formHost notifyVisibleForms, error:' + JSON.stringify(error));
142        });
143      } catch(error) {
144        Log.showInfo(TAG, `catch err->${JSON.stringify(error)}`);
145      }
146    }
147  }
148
149  private readonly mSettingsChangeObserver: SettingsModelObserver = (event: number)=> {
150    this.mGridConfig = this.getGridConfig();
151    this.pagingFiltering();
152  };
153
154  private constructor() {
155    super();
156    this.mPageDesktopModel = PageDesktopModel.getInstance();
157    this.mFolderModel = BigFolderModel.getInstance();
158    this.mFormModel = FormModel.getInstance();
159    this.mSettingsModel = SettingsModel.getInstance();
160    this.mBadgeManager = BadgeManager.getInstance();
161    this.mFormListInfoCacheManager = FormListInfoCacheManager.getInstance();
162    this.mSettingsModel.forceReloadConfig();
163    this.mSettingsModel.addObserver(this.mSettingsChangeObserver);
164    this.onPageDesktopCreate();
165    this.mGridConfig = this.getGridConfig();
166    this.pageDesktopStyleConfig = layoutConfigManager.getStyleConfig(PageDesktopGridStyleConfig.APP_GRID_STYLE_CONFIG, PageDesktopConstants.FEATURE_NAME);
167    this.formDetailLayoutConfig = layoutConfigManager.getStyleConfig(FormDetailLayoutConfig.FORM_LAYOUT_INFO, PageDesktopConstants.FEATURE_NAME);
168  }
169
170  /**
171   * Obtains the PageDesktopViewModel instance.
172   *
173   * @return PageDesktopViewModel
174   */
175  static getInstance(): PageDesktopViewModel {
176    if (globalThis.PageDesktopViewModel == null) {
177      globalThis.PageDesktopViewModel = new PageDesktopViewModel();
178    }
179    return globalThis.PageDesktopViewModel;
180  }
181
182  /**
183   * Registering Listening Events.
184   */
185  private onPageDesktopCreate(): void {
186    this.mAppModel.registerAppListEvent();
187    this.mPageDesktopModel.registerPageDesktopItemAddEvent(this.mLocalEventListener);
188    this.mPageDesktopModel.registerPageDesktopBadgeUpdateEvent(this.mLocalEventListener);
189  }
190
191  /**
192   * Unregistering Listening Events.
193   */
194  private onPageDesktopDestroy(): void {
195    this.mAppModel.unregisterAppListEvent();
196    this.mPageDesktopModel.unregisterEventListener(this.mLocalEventListener);
197  }
198
199  /**
200   * Obtains the application list displayed on the desktop.
201   */
202  async getGridList() {
203    const appInfoList = await this.getAppList();
204    const bundleInfoListTemp = [];
205    this.appendAppData(appInfoList, bundleInfoListTemp);
206    const folderInfoList = await this.mFolderModel.getFolderList();
207    Log.showDebug(TAG, 'getAppList folderInfoList length: ' + folderInfoList.length);
208    this.appendFolderData(folderInfoList, bundleInfoListTemp);
209    let formInfoList: any = this.mFormListInfoCacheManager.getCache(KEY_FORM_LIST);
210    if (formInfoList == CommonConstants.INVALID_VALUE) {
211      formInfoList = await this.mFormModel.getAllFormsInfoFromRdb();
212      if (formInfoList && formInfoList.length > 0) {
213        this.mFormListInfoCacheManager.setCache(KEY_FORM_LIST, formInfoList);
214      }
215    }
216    this.appendFormData(formInfoList, bundleInfoListTemp);
217    this.mBundleInfoList = bundleInfoListTemp;
218    this.pagingFiltering();
219  }
220
221  async updateDesktopInfo(): Promise<void> {
222    await this.mAppModel.getAppListAsync();
223    this.getGridList();
224    AppStorage.setOrCreate('formRefresh', String(new Date()));
225  }
226
227  async updateForms(): Promise<void> {
228    Log.showInfo(TAG, 'updateForms start');
229    let allFormsInfo: CardItemInfo[] = await this.mFormModel.getAllFormsInfoFromRdb();
230    if (allFormsInfo.length) {
231      for (const { cardId } of allFormsInfo) {
232        if (CheckEmptyUtils.isEmpty(cardId)) {
233          continue;
234        }
235        Log.showInfo(TAG, `updateForms cardId: ${cardId}`);
236        this.requestForm(String(cardId));
237      }
238    }
239  }
240
241  requestForm(formId: string): void {
242    Log.showInfo(TAG, `formHost requestForm ${formId}`);
243    try {
244      formHost.requestForm(formId).then(() => {
245        Log.showInfo(TAG, 'formHost requestForm success');
246      }).catch((error) => {
247        Log.showError(TAG, `formHost requestForm error, code: ${error.code}, message: ${error.message}`);
248      });
249    } catch (err) {
250      Log.showError(TAG, `formHost requestForm fail, err->${JSON.stringify(err)}`);
251    }
252  }
253
254  private async getAppList() {
255    Log.showInfo(TAG, 'getAppList start');
256
257    // get total app from system
258    const totalAppInfoList = await this.mAppModel.getAppList();
259
260    // get pageDesktop app from config
261    let pageDesktopInfo = this.mSettingsModel.getAppListInfo();
262
263    // get from config empty then init pageDesktop app
264    if (!this.mSettingsModel.isAppListInfoExist() && this.ifInfoIsNull(pageDesktopInfo)) {
265      for (const appInfo of totalAppInfoList) {
266        pageDesktopInfo.push(appInfo);
267      }
268    } else {
269      // remove uninstalled app
270      pageDesktopInfo = pageDesktopInfo.filter(item => {
271        for (const appInfo of totalAppInfoList) {
272          if (item.keyName == appInfo.keyName) {
273            item.appName = appInfo.appName;
274            return true;
275          }
276        }
277        return false;
278      });
279    }
280
281    // product phone logic
282    if (!this.isPad) {
283      this.addNewInstalledInfo(totalAppInfoList, pageDesktopInfo);
284      this.removeBottomBarInfo(pageDesktopInfo);
285    }
286    this.removeFolderInfo(pageDesktopInfo);
287
288    // update pageDesktop app config
289    this.mSettingsModel.setAppListInfo(pageDesktopInfo);
290    AppStorage.setOrCreate('isDesktopLoadFinished', true);
291    return pageDesktopInfo;
292  }
293
294  /**
295   * delete app in pageDesktop
296   *
297   * @param abilityName
298   * @param bundleName
299   */
300  deleteAppItem(appItem: {bundleName: string | undefined, keyName: string | undefined}) {
301    this.mBundleInfoList = this.mSettingsModel.getAppListInfo();
302    Log.showDebug(TAG, `deleteAppItem appItem: ${JSON.stringify(appItem)}`);
303    if (appItem.bundleName) {
304      this.mBundleInfoList = this.mBundleInfoList.filter(item => item.bundleName !== appItem.bundleName);
305    } else if(appItem.keyName) {
306      this.mBundleInfoList = this.mBundleInfoList.filter(item => item.keyName !== appItem.keyName);
307    }
308    this.mSettingsModel.setAppListInfo(this.mBundleInfoList);
309
310    const gridLayoutInfo = this.mSettingsModel.getLayoutInfo();
311    const layoutInfo = gridLayoutInfo.layoutInfo;
312    for (let i = 0; i < layoutInfo.length; i++) {
313      if (layoutInfo[i].typeId == CommonConstants.TYPE_APP &&
314      (layoutInfo[i].bundleName == appItem.bundleName || layoutInfo[i].keyName == appItem.keyName)) {
315        const page = layoutInfo[i].page;
316        gridLayoutInfo.layoutInfo.splice(i, 1);
317        let ret: boolean = this.mPageDesktopModel.deleteBlankPageFromLayoutInfo(gridLayoutInfo, page);
318        this.mSettingsModel.setLayoutInfo(gridLayoutInfo);
319        if(ret){
320          const curPageIndex = this.mPageDesktopModel.getPageIndex();
321          Log.showInfo(TAG, 'deleteAppItem' + curPageIndex);
322          this.mPageDesktopModel.setPageIndex(curPageIndex - 1);
323        }
324        break;
325      }
326    }
327    this.getGridList();
328  }
329
330  /**
331   * add app to pageDesktop
332   *
333   * @param appInfo
334   */
335  addToDesktop(appInfo) {
336    this.mBundleInfoList = this.mSettingsModel.getAppListInfo();
337    Log.showDebug(TAG, `addToDesktop keyName: ${appInfo.keyName} mBundleInfoList length: ${this.mBundleInfoList.length}`);
338    for (let i = 0; i < this.mBundleInfoList.length; i++) {
339      if (this.mBundleInfoList[i].keyName === appInfo.keyName) {
340        Prompt.showToast({
341          message: $r('app.string.duplicate_add')
342        });
343        return;
344      }
345    }
346
347    const gridLayoutInfo = this.mSettingsModel.getLayoutInfo();
348
349    // Check if app is in folder
350    for (let i = 0; i < gridLayoutInfo.layoutInfo.length; i++) {
351      if (gridLayoutInfo.layoutInfo[i].typeId === CommonConstants.TYPE_FOLDER) {
352        const appIndex = gridLayoutInfo.layoutInfo[i].layoutInfo[0].findIndex(item => {
353          return item.keyName === appInfo.keyName;
354        })
355        if (appIndex != CommonConstants.INVALID_VALUE) {
356          Prompt.showToast({
357            message: $r('app.string.duplicate_add')
358          });
359          return;
360        }
361      }
362    }
363
364    this.mBundleInfoList.push(appInfo);
365    this.mSettingsModel.setAppListInfo(this.mBundleInfoList);
366    this.getGridList();
367  }
368
369  /**
370   * add form to pageDesktop
371   *
372   * @param appInfo
373   */
374  addFormToDesktop(formInfo) {
375    Log.showInfo(TAG, 'addFormToDesktop');
376    this.mBundleInfoList = this.mSettingsModel.getAppListInfo();
377    switch(formInfo.dimension) {
378      case FormDimension.Dimension_1_2:
379        formInfo.row = this.formDetailLayoutConfig.getFormLayoutInfo().formLayoutDimension1X2.row;
380        formInfo.column = this.formDetailLayoutConfig.getFormLayoutInfo().formLayoutDimension1X2.column;
381        formInfo.area = this.formDetailLayoutConfig.getFormLayoutInfo().formLayoutDimension1X2.area;
382        break;
383      case FormDimension.Dimension_2_2:
384        formInfo.row = this.formDetailLayoutConfig.getFormLayoutInfo().formLayoutDimension2X2.row;
385        formInfo.column = this.formDetailLayoutConfig.getFormLayoutInfo().formLayoutDimension2X2.column;
386        formInfo.area = this.formDetailLayoutConfig.getFormLayoutInfo().formLayoutDimension2X2.area;
387        break;
388      case FormDimension.Dimension_2_4:
389        formInfo.row = this.formDetailLayoutConfig.getFormLayoutInfo().formLayoutDimension2X4.row;
390        formInfo.column = this.formDetailLayoutConfig.getFormLayoutInfo().formLayoutDimension2X4.column;
391        formInfo.area = this.formDetailLayoutConfig.getFormLayoutInfo().formLayoutDimension2X4.area;
392        break;
393      case FormDimension.Dimension_4_4:
394        formInfo.row = this.formDetailLayoutConfig.getFormLayoutInfo().formLayoutDimension4X4.row;
395        formInfo.column = this.formDetailLayoutConfig.getFormLayoutInfo().formLayoutDimension4X4.column;
396        formInfo.area = this.formDetailLayoutConfig.getFormLayoutInfo().formLayoutDimension4X4.area;
397        break;
398      default:
399        break;
400    }
401    this.mBundleInfoList.push(formInfo);
402    this.mSettingsModel.setAppListInfo(this.mBundleInfoList);
403    this.getGridList();
404  }
405
406  /**
407   * update badge in desktop
408   *
409   * @param badgeInfo
410   */
411  updateBadgeNumber(badgeInfo) {
412    this.mBundleInfoList = this.mSettingsModel.getAppListInfo();
413
414    let appInfo = this.mBundleInfoList.find(item => {
415      return item.bundleName == badgeInfo.bundleName;
416    });
417    if (!this.ifInfoIsNull(appInfo)) {
418      Log.showDebug(TAG, `updateBadgeNumber bundleName: ${badgeInfo.bundleName}`);
419      appInfo.badgeNumber = badgeInfo.badgeNumber;
420      this.mSettingsModel.setAppListInfo(this.mBundleInfoList);
421      this.getGridList();
422    } else {
423      Log.showDebug(TAG, 'updateBadgeNumber appInfo is null ');
424      const gridLayoutInfo = this.mSettingsModel.getLayoutInfo();
425      const layoutInfo = gridLayoutInfo.layoutInfo;
426      let hasFound = false;
427      for (let i = 0; i < layoutInfo.length; i++) {
428        if (hasFound) {
429          break;
430        }
431        if (layoutInfo[i].typeId == CommonConstants.TYPE_FOLDER && !hasFound) {
432          for (let j = 0; j < layoutInfo[i].layoutInfo.length; j++) {
433            appInfo = layoutInfo[i].layoutInfo[j].find(item => {
434              return item.bundleName == badgeInfo.bundleName;
435            });
436
437            if (!this.ifInfoIsNull(appInfo)) {
438              hasFound = true;
439              appInfo.badgeNumber = badgeInfo.badgeNumber;
440              break;
441            }
442          }
443          layoutInfo[i].badgeNumber = this.getFolderBadgeNumber(layoutInfo[i]);
444        }
445      }
446      if (hasFound) {
447        this.mSettingsModel.setLayoutInfo(gridLayoutInfo);
448        this.getGridList();
449      }
450    }
451  }
452
453  private getFolderBadgeNumber(folderInfo) {
454    let bidfolderBadgeNumber: number = 0;
455    let layoutInfo: [[]] = folderInfo.layoutInfo;
456    for (var i = 0; i < layoutInfo.length; i++) {
457      layoutInfo[i].forEach((item: any) => {
458        if (item.badgeNumber && item.badgeNumber > 0) {
459          bidfolderBadgeNumber = bidfolderBadgeNumber + item.badgeNumber;
460        }
461      });
462    }
463    return bidfolderBadgeNumber;
464  }
465
466  /**
467   * add app to pageDesktop by dragging
468   *
469   * @param appInfo
470   */
471  addToDesktopByDraging(appInfo) {
472    Log.showDebug(TAG, `addToDesktopByDraging bundleName: ${appInfo.bundleName}`);
473    this.mGridConfig = this.mSettingsModel.getGridConfig();
474    for (let i = 0; i < this.mBundleInfoList.length; i++) {
475      if (this.mBundleInfoList[i].bundleName === appInfo.bundleName) {
476        Prompt.showToast({
477          message: $r('app.string.duplicate_add')
478        });
479        return;
480      }
481    }
482    this.mBundleInfoList.push(appInfo);
483    this.mSettingsModel.setAppListInfo(this.mBundleInfoList);
484    this.getGridList();
485  }
486
487  /**
488   * add app to dock
489   *
490   * @param appInfo
491   */
492  addToDock(appInfo) {
493    this.mPageDesktopModel.sendDockItemChangeEvent(appInfo);
494  }
495
496  private appendAppData(appInfoList, bundleInfoList) {
497    for (let i = 0; i < appInfoList.length; i++) {
498      if (this.isInHideAppList(appInfoList[i])) {
499        continue;
500      }
501      appInfoList[i].typeId = CommonConstants.TYPE_APP;
502      appInfoList[i].area = [1, 1];
503      bundleInfoList.push(appInfoList[i]);
504    }
505  }
506
507  private isInHideAppList(appInfo): boolean {
508    for (const hideInfo of this.mHideBundleInfoList) {
509      if (appInfo.keyName == hideInfo.keyName) {
510        return true;
511      }
512    }
513    return false;
514  }
515
516  private appendFolderData(folderInfoList, bundleInfoList) {
517    for (let i = 0; i < folderInfoList.length; i++) {
518      for (let j = 0; j < folderInfoList[i].layoutInfo.length; j++) {
519        for (let k = 0; k < folderInfoList[i].layoutInfo[j].length; k++) {
520          const appIndex = bundleInfoList.findIndex(item => {
521            return item.keyName === folderInfoList[i].layoutInfo[j][k].keyName;
522          });
523          if (appIndex != CommonConstants.INVALID_VALUE) {
524            bundleInfoList.splice(appIndex, 1);
525          }
526        }
527      }
528    }
529  }
530
531  private appendFormData(formInfoList, bundleInfoList) {
532    for (let i = 0; i < formInfoList.length; i++) {
533      formInfoList[i].typeId = CommonConstants.TYPE_CARD;
534      bundleInfoList.push(formInfoList[i]);
535    }
536  }
537
538  /**
539   * Obtains Grid Configuration.
540   */
541  getGridConfig() {
542    return this.mSettingsModel.getGridConfig();
543  }
544
545  /**
546   * refresh page
547   */
548  pagingFiltering() {
549    const appInfo = {
550      appGridInfo: []
551    };
552    const appListInfo = [];
553    const info = this.getAndSetLayoutInfo();
554    const layoutInfo = info.layoutInfo;
555    for (let i = 0; i < layoutInfo.length; i++) {
556      if (layoutInfo[i].typeId == CommonConstants.TYPE_APP) {
557        for (let j = 0; j < this.mBundleInfoList.length; j++) {
558          if (layoutInfo[i].keyName == this.mBundleInfoList[j].keyName
559          && layoutInfo[i].typeId == this.mBundleInfoList[j].typeId) {
560            this.mBundleInfoList[j].area = layoutInfo[i].area;
561            this.mBundleInfoList[j].page = layoutInfo[i].page;
562            this.mBundleInfoList[j].row = layoutInfo[i].row;
563            this.mBundleInfoList[j].column = layoutInfo[i].column;
564            this.mBundleInfoList[j].x = 0;
565            appListInfo.push(this.mBundleInfoList[j]);
566          }
567        }
568      } else if (layoutInfo[i].typeId == CommonConstants.TYPE_FOLDER) {
569        appListInfo.push(layoutInfo[i]);
570      } else if (layoutInfo[i].typeId == CommonConstants.TYPE_CARD) {
571        for (let j = 0; j < this.mBundleInfoList.length; j++) {
572          if (layoutInfo[i].cardId == this.mBundleInfoList[j].cardId
573          && layoutInfo[i].typeId == this.mBundleInfoList[j].typeId) {
574            this.mBundleInfoList[j].cardId = layoutInfo[i].cardId;
575            this.mBundleInfoList[j].area = layoutInfo[i].area;
576            this.mBundleInfoList[j].page = layoutInfo[i].page;
577            this.mBundleInfoList[j].row = layoutInfo[i].row;
578            this.mBundleInfoList[j].column = layoutInfo[i].column;
579            this.mBundleInfoList[j].x = 0;
580            appListInfo.push(this.mBundleInfoList[j]);
581          }
582        }
583      }
584    }
585    appInfo.appGridInfo = this.integrateSwiper(appListInfo);
586    Log.showInfo(TAG, 'pagingFiltering appListInfo length:' + appListInfo.length);
587    AppStorage.setOrCreate('selectDesktopAppItem', '');
588    AppStorage.setOrCreate(KEY_APP_LIST, appInfo);
589  }
590
591  private integrateSwiper(list) {
592    let gridAppsInfos = [];
593    const allPageCount = this.mSettingsModel.getLayoutInfo().layoutDescription.pageCount;
594    let max = allPageCount;
595    for (let i = 0;i < list.length; i++) {
596      if (max <= list[i].page + 1) {
597        max = list[i].page + 1;
598      }
599    }
600
601    for (let i = 0;i < max; i++) {
602      gridAppsInfos.push([]);
603    }
604
605    for (let i = 0;i < list.length; i++) {
606      gridAppsInfos[list[i].page].push(list[i]);
607    }
608
609    //If the workspace has no applications,
610    // it needs to be initialized to [].
611    if (gridAppsInfos.length == 0) {
612      gridAppsInfos.push([]);
613    }
614
615    this.mGridAppsInfos = gridAppsInfos;
616    return gridAppsInfos;
617  }
618
619  private getAndSetLayoutInfo() {
620    let info = this.mSettingsModel.getLayoutInfo();
621    const isLegal = this.ifLayoutRationality(info);
622    if (isLegal) {
623      info = this.updateLayoutInfo(info);
624    } else {
625      info = this.updateLayoutInfo(this.createNewLayoutInfo());
626    }
627    this.mSettingsModel.setLayoutInfo(info);
628    return info;
629  }
630
631  private ifLayoutRationality(info) {
632    //verify whether the info is null.
633    if (this.ifInfoIsNull(info)) {
634      return false;
635    }
636    const layoutDescription = info.layoutDescription;
637
638    //verify whether the layoutDescription is different.
639    this.mGridConfig = this.getGridConfig();
640    const column = this.mGridConfig.column;
641    const row = this.mGridConfig.row;
642    if (this.ifDescriptionIsDifferent(layoutDescription, row, column)) {
643      return false;
644    }
645
646    //verify whether the layoutInfo's row and column is more than standard.
647    if (this.ifColumnOrRowAreBigger(info.layoutInfo, row, column)) {
648      return false;
649    }
650
651    //verify whether the layoutInfo's position is duplicated.
652    if (this.ifDuplicatePosition(info.layoutInfo)) {
653      return false;
654    }
655    //verify whether the layoutInfo's keyName is duplicated.
656    if (this.ifDuplicateKeyName(info.layoutInfo)) {
657      return false;
658    }
659    return true;
660  };
661
662  private ifInfoIsNull(info) {
663    if (info == undefined || info == '' || JSON.stringify(info) == '{}' || info == null) {
664      return true;
665    }
666    return false;
667  }
668
669  private ifDescriptionIsDifferent(layoutDescription, row, column) {
670    if (row != layoutDescription.row || column != layoutDescription.column) {
671      return true;
672    }
673    return false;
674  }
675
676  private ifColumnOrRowAreBigger(layoutInfo, row, column) {
677    for (let i = 0; i < layoutInfo.length; i++) {
678      //column or row are bigger than legal num
679      if (layoutInfo[i].column >= column || layoutInfo[i].row >= row) {
680        return true;
681      }
682    }
683    return false;
684  }
685
686  private ifDuplicatePosition(layoutInfo) {
687    const mPositionInfo = [];
688    for (let i = 0; i < layoutInfo.length; i++) {
689      for(let j = 0; j < layoutInfo[i].area[1]; j++){
690        for(let k = 0; k < layoutInfo[i].area[0]; k++){
691          const position = [];
692          position[0] = layoutInfo[i].page;
693          position[1] = layoutInfo[i].row + j;
694          position[2] = layoutInfo[i].column + k;
695          mPositionInfo.push(position);
696        }
697      }
698    }
699    for (let i = 0; i < mPositionInfo.length; i++) {
700      for (let j = mPositionInfo.length - 1; j > 0 && j > i; j--) {
701        if (mPositionInfo[i][0] == mPositionInfo[j][0] && mPositionInfo[i][1] == mPositionInfo[j][1] && mPositionInfo[i][2] == mPositionInfo[j][2]) {
702          return true;
703        }
704
705      }
706    }
707    return false;
708  }
709
710  private ifDuplicateKeyName(layoutInfo) {
711    const count = [];
712    for (let i = 0; i < layoutInfo.length; i++) {
713      if (CheckEmptyUtils.isEmpty(count[layoutInfo[i].keyName])) {
714        count[layoutInfo[i].keyName] = 0;
715      } else if (layoutInfo[i].typeId == CommonConstants.TYPE_APP) {
716        return true;
717      }
718    }
719    return false;
720  }
721
722  private updateLayoutInfo(info) {
723    let layoutInfo = info.layoutInfo;
724    this.mGridConfig = this.getGridConfig();
725    Log.showDebug(TAG, 'updateLayoutInfo mGridConfig:' + JSON.stringify(this.mGridConfig));
726    info.layoutDescription.row = this.mGridConfig.row;
727    info.layoutDescription.column = this.mGridConfig.column;
728    const newApp = [];
729    //Detect newly installed apps
730    for (const i in this.mBundleInfoList) {
731      let sign = false;
732      for (const j in layoutInfo) {
733        if (this.mBundleInfoList[i].typeId == layoutInfo[j].typeId
734        && this.mBundleInfoList[i].typeId == CommonConstants.TYPE_APP
735        && this.mBundleInfoList[i].keyName == layoutInfo[j].keyName) {
736          layoutInfo[j].badgeNumber = this.mBundleInfoList[i].badgeNumber;
737          sign = true;
738          break;
739        }
740      }
741      if (!sign) {
742        newApp.push(this.mBundleInfoList[i]);
743      }
744    }
745
746    //Detect uninstalled apps, remove all apps which have same bundleName when one app is uninstalled
747    layoutInfo = layoutInfo.filter(item => {
748      if (item.typeId == CommonConstants.TYPE_FOLDER || item.typeId == CommonConstants.TYPE_CARD) {
749        return true;
750      }
751      for (const bundleInfo of this.mBundleInfoList) {
752        if (item.keyName == bundleInfo.keyName) {
753          return true;
754        }
755      }
756      return false;
757    })
758    info.layoutInfo = layoutInfo;
759
760    // calculate the layout of new apps
761    for (let i = 0; i < newApp.length; i++) {
762      if (newApp[i].typeId == CommonConstants.TYPE_APP) {
763        this.mPageDesktopModel.updateAppItemLayoutInfo(info, newApp[i]);
764      }
765    }
766    let infoOld = this.mSettingsModel.getLayoutInfo();
767    for (const item of infoOld.layoutInfo) {
768      if (item.typeId == CommonConstants.TYPE_APP) {
769        for (const infoNew of info.layoutInfo) {
770          if (item.keyName == infoNew.keyName) {
771            infoNew.page = item.page;
772          }
773        }
774      }
775    }
776    return info;
777  }
778
779  private createNewInfo() {
780    this.mGridConfig = this.getGridConfig();
781    const column = this.mGridConfig.column;
782    const row = this.mGridConfig.row;
783    const layoutNum = this.mBundleInfoList.length;
784    const maxPerPage = column * row;
785    const pageNum = Math.ceil(layoutNum / maxPerPage);
786    const newLayoutInfo = {
787      layoutDescription: {},
788      layoutInfo: []
789    };
790    newLayoutInfo.layoutDescription = {
791      'pageCount': pageNum,
792      'row': row,
793      'column': column,
794    };
795    newLayoutInfo.layoutInfo = [];
796    return newLayoutInfo;
797  }
798
799  private createNewLayoutInfo() {
800    const info = this.mSettingsModel.getLayoutInfo();
801    this.mGridConfig = this.getGridConfig();
802    const column = this.mGridConfig.column;
803    const row = this.mGridConfig.row;
804    const layoutNum = info.layoutInfo.length;
805    const maxPerPage = column * row;
806    const pageNum = Math.ceil(layoutNum / maxPerPage);
807    const newLayoutInfo = {
808      layoutDescription: {},
809      layoutInfo: []
810    };
811    newLayoutInfo.layoutDescription = {
812      'pageCount': info.layoutDescription.pageCount,
813      'row': row,
814      'column': column
815    };
816    if (AppStorage.has('isPortrait') && AppStorage.get('isPortrait')) {
817      let cardInfoHorizontal: any[] = [];
818      for (let i = 0; i < info.layoutInfo.length; i++) {
819        if (info.layoutInfo[i].typeId == CommonConstants.TYPE_FOLDER) {
820          let tt = info.layoutInfo[i].column
821          info.layoutInfo[i].column = info.layoutInfo[i].row;
822          info.layoutInfo[i].row = tt;
823          newLayoutInfo.layoutInfo.push(info.layoutInfo[i]);
824        }
825      }
826
827      for (let i = 0; i < info.layoutInfo.length; i++) {
828        if (info.layoutInfo[i].typeId == CommonConstants.TYPE_CARD) {
829          if (info.layoutInfo[i].area[0] == info.layoutInfo[i].area[1]) {
830            let tt = info.layoutInfo[i].column
831            info.layoutInfo[i].column = info.layoutInfo[i].row;
832            info.layoutInfo[i].row = tt;
833            newLayoutInfo.layoutInfo.push(info.layoutInfo[i]);
834          } else {
835            cardInfoHorizontal.push(JSON.stringify(info.layoutInfo[i]));
836            this.mPageDesktopModel.updatePageDesktopLayoutInfo(newLayoutInfo, info.layoutInfo[i]);
837            newLayoutInfo.layoutInfo.push(info.layoutInfo[i]);
838          }
839        }
840      }
841      AppStorage.setOrCreate('isPortraitCard', cardInfoHorizontal);
842    }
843
844    if (AppStorage.has('isPortrait') && !AppStorage.get('isPortrait')) {
845      for (let i = 0; i < info.layoutInfo.length; i++) {
846        if (info.layoutInfo[i].typeId == CommonConstants.TYPE_FOLDER) {
847          let tt = info.layoutInfo[i].column
848          info.layoutInfo[i].column = info.layoutInfo[i].row;
849          info.layoutInfo[i].row = tt;
850          newLayoutInfo.layoutInfo.push(info.layoutInfo[i]);
851        }
852      }
853
854      for (let i = 0; i < info.layoutInfo.length; i++) {
855        if (info.layoutInfo[i].typeId == CommonConstants.TYPE_CARD) {
856          if (info.layoutInfo[i].area[0] == info.layoutInfo[i].area[1]) {
857            let tt = info.layoutInfo[i].column
858            info.layoutInfo[i].column = info.layoutInfo[i].row;
859            info.layoutInfo[i].row = tt;
860            newLayoutInfo.layoutInfo.push(info.layoutInfo[i]);
861          } else {
862            let cardInfoOld: [] = AppStorage.get('isPortraitCard');
863            Log.showInfo(TAG, 'cardInfoOld:' + JSON.stringify(cardInfoOld));
864            if (!cardInfoOld.find(item => JSON.parse(item).cardId === info.layoutInfo[i].cardId)) {
865              this.mPageDesktopModel.updatePageDesktopLayoutInfo(newLayoutInfo, info.layoutInfo[i]);
866              newLayoutInfo.layoutInfo.push(info.layoutInfo[i]);
867            }
868            for (let index = 0; index < cardInfoOld.length; index++) {
869              if (!newLayoutInfo.layoutInfo.find(item => item.cardId == JSON.parse(cardInfoOld[index]).cardId)) {
870                newLayoutInfo.layoutInfo.push(JSON.parse(cardInfoOld[index]));
871              }
872            }
873          }
874        }
875      }
876    }
877
878    if (!AppStorage.has('isPortrait')) {
879      newLayoutInfo.layoutDescription = {
880        'pageCount': pageNum,
881        'row': row,
882        'column': column
883      };
884      newLayoutInfo.layoutInfo = [];
885    }
886
887    return newLayoutInfo;
888  }
889
890  regroupDataAppListChange(callbackList) {
891    this.getGridList();
892  }
893
894  /**
895   * Open the app.
896   *
897   * @param abilityName
898   * @param bundleName
899   */
900  openApplication(abilityName: string, bundleName: string, moduleName: string): void {
901    this.jumpTo(abilityName, bundleName, moduleName);
902  }
903
904  /**
905   * Open Settings.
906   */
907  intoSetting(): void {
908    Log.showInfo(TAG, 'intoSetting');
909    this.jumpToSetting();
910  }
911
912  /**
913   * Get strings for addBlankPageButton.
914   *
915   * @return {string} AddBlankPageButton Strings.
916   */
917  getBlankPageBtnStr() {
918    return this.isBlankPage() ? $r('app.string.delete_blank_page') : $r('app.string.add_blank_page');
919  }
920
921  /**
922   * Get strings for deleteBlankPageButton.
923   *
924   * @return {string} AddBlankPageButton Strings.
925   */
926  getBlankPageBtnIcon() {
927    return this.isBlankPage() ? '/common/pics/ic_public_delete.svg' : '/common/pics/ic_public_add_black.svg';
928  }
929
930  isBlankPage(): boolean {
931    const curPageIndex = this.mPageDesktopModel.getPageIndex();
932    // 当且仅当只有一个页面时,菜单项只允许添加
933    if (this.getGridPageCount() <= 1) {
934      return false;
935    }
936    if (CheckEmptyUtils.isEmpty(this.mGridAppsInfos) || CheckEmptyUtils.isEmpty(this.mGridAppsInfos[curPageIndex])
937    || CheckEmptyUtils.isEmpty(this.mGridAppsInfos[curPageIndex].length)) {
938      return true;
939    }
940    if (this.mGridAppsInfos[curPageIndex].length === 0) {
941      return true;
942    }
943    return false;
944  }
945
946  /**
947   * Add or delete the chosen blank page.
948   */
949  addOrDeleteBlankPage(): void {
950    if (this.isBlankPage()) {
951      this.deleteBlankPage();
952    } else {
953      this.addBlankPage(false);
954    }
955  }
956
957  /**
958   * Add a blank page.
959   *
960   * @param {boolean} isAddByDrag
961   */
962  addBlankPage(isAddByDrag: boolean): void {
963    this.mPageDesktopModel.setAddByDragging(isAddByDrag);
964    const allPageCount = this.mSettingsModel.getLayoutInfo().layoutDescription.pageCount + 1;
965    this.setGridPageCount(allPageCount);
966    this.pagingFiltering();
967    this.mPageDesktopModel.setPageIndex(allPageCount - 1);
968  }
969
970  /**
971   * Get pageCount.
972   *
973   * @return {number} PageCount.
974   */
975  /**
976   * Get pageCount.
977   *
978   * @return {number} PageCount.
979   */
980  getGridPageCount(): number {
981    return this.mSettingsModel.getLayoutInfo().layoutDescription.pageCount;
982  }
983
984  /**
985   * Set pageCount.
986   *
987   * @param {number} pageCount - PageCount.
988   */
989  private setGridPageCount(pageCount: number): void {
990    const gridLayoutInfo = this.mSettingsModel.getLayoutInfo();
991    gridLayoutInfo.layoutDescription.pageCount = pageCount;
992    this.mSettingsModel.setLayoutInfo(gridLayoutInfo);
993  }
994
995  /**
996   * Delete the chosen blank page.
997   */
998  private deleteBlankPage(): void {
999    const curPageIndex = this.mPageDesktopModel.getPageIndex();
1000    this.deleteGridPage(curPageIndex);
1001    if (curPageIndex === 0) {
1002      this.mPageDesktopModel.setPageIndex(curPageIndex);
1003    } else {
1004      this.mPageDesktopModel.setPageIndex(curPageIndex - 1);
1005    }
1006    this.setGridPageCount(this.mSettingsModel.getLayoutInfo().layoutDescription.pageCount - 1);
1007    this.pagingFiltering();
1008  }
1009
1010  /**
1011   * Delete blank page.
1012   *
1013   * @param {number} pageIndex - Index of the page which is to be deleted.
1014   */
1015  private deleteGridPage(pageIndex: number): void {
1016    const info = this.mSettingsModel.getLayoutInfo();
1017    const layoutInfo = info.layoutInfo;
1018    for (const element of layoutInfo) {
1019      if (element.page > pageIndex) {
1020        element.page = element.page - 1;
1021      }
1022    }
1023    info.layoutInfo = layoutInfo;
1024    this.mSettingsModel.setLayoutInfo(info);
1025  }
1026
1027  /**
1028   * Set device type.
1029   *
1030   * @param EType: Device type
1031   */
1032  setDevice(EType): void {
1033    this.mSettingsModel.setDevice(EType);
1034    this.isPad = EType === CommonConstants.PAD_DEVICE_TYPE;
1035  }
1036
1037  /**
1038   * Get device type.
1039   */
1040  getDevice(): boolean {
1041    return this.isPad;
1042  }
1043
1044  buildMenuInfoList(appInfo, dialog, formDialog?, folderCallback?, openClickCallback?): MenuInfo[] {
1045    let menuInfoList = new Array<MenuInfo>();
1046    const shortcutInfo: any = this.mAppModel.getShortcutInfo(appInfo.bundleName);
1047    if (shortcutInfo) {
1048      let menu = null;
1049      shortcutInfo.forEach((value) => {
1050        menu = new MenuInfo();
1051        menu.menuType = CommonConstants.MENU_TYPE_DYNAMIC;
1052        menu.menuImgSrc = value.icon;
1053        menu.menuText = value.label;
1054        menu.shortcutIconId = value.iconId;
1055        menu.shortcutLabelId =  value.labelId;
1056        menu.bundleName = value.bundleName;
1057        menu.moduleName = value.moduleName;
1058        menu.onMenuClick = () => {
1059          Trace.start(Trace.CORE_METHOD_START_APP_ANIMATION);
1060          if (openClickCallback) {
1061            openClickCallback();
1062          }
1063          if (AppStorage.get('openFolderStatus') != 0) {
1064            AppStorage.setOrCreate('openFolderStatus', 0);
1065          }
1066          this.jumpTo(value.wants[0].targetClass, value.wants[0].targetBundle, value.wants[0].targetModule);
1067        };
1068        value.bundleName == appInfo.bundleName && value.moduleName == appInfo.moduleName && menuInfoList.push(menu);
1069      });
1070    }
1071
1072    let open = new MenuInfo();
1073    open.menuType = CommonConstants.MENU_TYPE_FIXED;
1074    open.menuImgSrc = '/common/pics/ic_public_add_norm.svg';
1075    open.menuText = $r('app.string.app_menu_open');
1076    open.onMenuClick = () => {
1077      if (AppStorage.get('openFolderStatus') != 0 && AppStorage.get('deviceType') === CommonConstants.PAD_DEVICE_TYPE) {
1078        AppStorage.setOrCreate('openFolderStatus', 0);
1079      }
1080      this.setStartAppInfo()
1081      this.jumpTo(appInfo.abilityName, appInfo.bundleName, appInfo.moduleName);
1082    };
1083    menuInfoList.push(open);
1084
1085    const formInfoList = this.mFormModel.getAppItemFormInfo(appInfo.bundleName, appInfo.moduleName);
1086    if (!CheckEmptyUtils.isEmptyArr(formInfoList)) {
1087      let addFormToDeskTopMenu = new MenuInfo();
1088      addFormToDeskTopMenu.menuType = CommonConstants.MENU_TYPE_FIXED;
1089      addFormToDeskTopMenu.menuImgSrc = '/common/pics/ic_public_app.svg';
1090      addFormToDeskTopMenu.menuText = $r('app.string.add_form_to_desktop');
1091      addFormToDeskTopMenu.onMenuClick = () => {
1092        Log.showDebug(TAG, 'Launcher click menu item into add form to desktop view');
1093        const appName = this.getAppName(appInfo.appLabelId + appInfo.bundleName + appInfo.moduleName);
1094        if (appName != null) {
1095          appInfo.appName = appName;
1096        }
1097        AppStorage.setOrCreate('formAppInfo', appInfo);
1098        if (!this.isPad) {
1099          this.showFormManager(appInfo);
1100        } else {
1101          formDialog.open();
1102        }
1103      };
1104      menuInfoList.push(addFormToDeskTopMenu);
1105
1106      let formCenterMenu: MenuInfo = new MenuInfo();
1107      formCenterMenu.menuType = CommonConstants.MENU_TYPE_FIXED;
1108      formCenterMenu.menuImgSrc = '/common/pics/ic_form_center.svg';
1109      formCenterMenu.menuText = $r('app.string.form_center');
1110      formCenterMenu.onMenuClick = (): void => {
1111        Log.showInfo(TAG, 'Launcher click menu into form center view.');
1112        if (!this.isPad) {
1113          globalThis.createWindowWithName(windowManager.FORM_SERVICE_WINDOW_NAME, windowManager.RECENT_RANK);
1114        }
1115      };
1116      menuInfoList.push(formCenterMenu);
1117    }
1118
1119    if (this.isPad) {
1120      const addToDockMenu = new MenuInfo();
1121      addToDockMenu.menuType = CommonConstants.MENU_TYPE_FIXED;
1122      addToDockMenu.menuImgSrc = '/common/pics/ic_public_copy.svg';
1123      addToDockMenu.menuText = $r('app.string.app_center_menu_add_dock');
1124      addToDockMenu.onMenuClick = () => {
1125        Log.showDebug(TAG, 'Launcher click menu item add to dock');
1126        const appName = this.getAppName(appInfo.appLabelId + appInfo.bundleName + appInfo.moduleName);
1127        if (appName != null) {
1128          appInfo.appName = appName;
1129        }
1130        this.addToDock(appInfo);
1131      };
1132      menuInfoList.push(addToDockMenu);
1133    }
1134
1135    if (folderCallback) {
1136      const moveOutMenu = new MenuInfo();
1137      moveOutMenu.menuType = CommonConstants.MENU_TYPE_FIXED;
1138      moveOutMenu.menuImgSrc = '/common/pics/ic_public_remove.svg';
1139      moveOutMenu.menuText = $r('app.string.remove_app_from_folder');
1140      moveOutMenu.onMenuClick = () => {
1141        Log.showDebug(TAG, 'Launcher click menu item remove app from folder');
1142        // remove app from folder
1143        folderCallback(appInfo);
1144      };
1145      menuInfoList.push(moveOutMenu);
1146    }
1147
1148    const uninstallMenu = new MenuInfo();
1149    uninstallMenu.menuType = CommonConstants.MENU_TYPE_FIXED;
1150    uninstallMenu.menuImgSrc = this.isPad ? '/common/pics/ic_public_remove.svg' : '/common/pics/ic_public_delete.svg';
1151    uninstallMenu.menuText = this.isPad ?  $r('app.string.delete_app') : $r('app.string.uninstall');
1152    uninstallMenu.onMenuClick = () => {
1153      Log.showDebug(TAG, 'Launcher click menu item uninstall');
1154      const appName = this.getAppName(appInfo.appLabelId + appInfo.bundleName + appInfo.moduleName);
1155      if (appName != null) {
1156        appInfo.appName = appName;
1157      }
1158      AppStorage.setOrCreate('uninstallAppInfo', appInfo);
1159      dialog.open();
1160    };
1161    uninstallMenu.menuEnabled = appInfo.isUninstallAble;
1162    menuInfoList.push(uninstallMenu);
1163    return menuInfoList;
1164  }
1165
1166  buildCardMenuInfoList(formInfo, dialog, formDialog): MenuInfo[] {
1167    const menuInfoList = new Array<MenuInfo>();
1168    if (!this.ifStringIsNull(formInfo.formConfigAbility)
1169    && formInfo.formConfigAbility.startsWith(CommonConstants.FORM_CONFIG_ABILITY_PREFIX, 0)) {
1170      const editForm = new MenuInfo();
1171      editForm.menuType = CommonConstants.MENU_TYPE_FIXED;
1172      editForm.menuImgSrc = '/common/pics/ic_public_edit.svg';
1173      editForm.menuText = $r('app.string.form_edit');
1174      editForm.onMenuClick = () => {
1175        Log.showDebug(TAG, `Launcher click menu item into form edit view:${formInfo.formConfigAbility}`);
1176        const abilityName = formInfo.formConfigAbility.slice(CommonConstants.FORM_CONFIG_ABILITY_PREFIX.length);
1177        this.jumpToForm(abilityName, formInfo.bundleName, formInfo.moduleName, formInfo.cardId);
1178      };
1179      menuInfoList.push(editForm);
1180    }
1181    const addFormToDeskTopMenu = new MenuInfo();
1182    addFormToDeskTopMenu.menuType = CommonConstants.MENU_TYPE_FIXED;
1183    addFormToDeskTopMenu.menuImgSrc = '/common/pics/ic_desktop_servicewidgets.svg';
1184    addFormToDeskTopMenu.menuText = $r('app.string.add_form_to_desktop_more');
1185    addFormToDeskTopMenu.onMenuClick = () => {
1186      Log.showDebug(TAG, 'Launcher click menu item into add form to desktop view');
1187      const appName = this.getAppName(formInfo.appLabelId + formInfo.bundleName + formInfo.moduleName);
1188      if (appName != null) {
1189        formInfo.appName = appName;
1190      }
1191      AppStorage.setOrCreate('formAppInfo', formInfo);
1192      if (!this.isPad) {
1193        this.showFormManager(formInfo);
1194      } else {
1195        formDialog.open();
1196      }
1197    };
1198    menuInfoList.push(addFormToDeskTopMenu);
1199
1200    let formCenterMenu: MenuInfo = new MenuInfo();
1201    formCenterMenu.menuType = CommonConstants.MENU_TYPE_FIXED;
1202    formCenterMenu.menuImgSrc = '/common/pics/ic_form_center.svg';
1203    formCenterMenu.menuText = $r('app.string.form_center');
1204    formCenterMenu.onMenuClick = (): void => {
1205      Log.showInfo(TAG, 'Launcher click menu into form center view.');
1206      if (!this.isPad) {
1207        globalThis.createWindowWithName(windowManager.FORM_SERVICE_WINDOW_NAME, windowManager.RECENT_RANK);
1208      }
1209    };
1210    menuInfoList.push(formCenterMenu);
1211
1212    const deleteFormFromDeskTop = new MenuInfo();
1213    deleteFormFromDeskTop.menuType = CommonConstants.MENU_TYPE_FIXED;
1214    deleteFormFromDeskTop.menuImgSrc = '/common/pics/ic_public_remove.svg';
1215    deleteFormFromDeskTop.menuText = $r('app.string.delete_form');
1216    deleteFormFromDeskTop.onMenuClick = () => {
1217      Log.showDebug(TAG, 'Launcher click menu item remove form to desktop view');
1218      const formAnimateData: {
1219        cardId: number,
1220        isOpenRemoveFormDialog: boolean,
1221      } = { cardId: formInfo.cardId, isOpenRemoveFormDialog: true };
1222      AppStorage.setOrCreate('formAnimateData', formAnimateData);
1223      dialog.open();
1224    };
1225    menuInfoList.push(deleteFormFromDeskTop);
1226    return menuInfoList;
1227  }
1228
1229  buildRenameMenuInfoList(folderItemInfo, menuCallback): MenuInfo[] {
1230    const menuInfoList = new Array<MenuInfo>();
1231    const renameMenu = new MenuInfo();
1232    renameMenu.menuType = CommonConstants.MENU_TYPE_DYNAMIC;
1233    renameMenu.menuImgSrc = StyleConstants.DEFAULT_RENAME_IMAGE;
1234    renameMenu.menuText = $r('app.string.rename_folder');
1235    renameMenu.onMenuClick = () => {
1236      Log.showDebug(TAG, 'Launcher click menu to rename');
1237      menuCallback();
1238    };
1239    menuInfoList.push(renameMenu);
1240    return menuInfoList;
1241  }
1242
1243  /**
1244   * Get PageDesktopStyleConfig.
1245   */
1246  getPageDesktopStyleConfig() {
1247    return this.pageDesktopStyleConfig;
1248  }
1249
1250  /**
1251   * Get workSpaceWidth.
1252   */
1253  getWorkSpaceWidth() {
1254    return AppStorage.get('workSpaceWidth');
1255  }
1256
1257  /**
1258   * Get workSpaceHeight.
1259   */
1260  getWorkSpaceHeight() {
1261    return AppStorage.get('workSpaceHeight');
1262  }
1263
1264  /**
1265   * Get getAppPageStartConfig.
1266   */
1267  getAppPageStartConfig() {
1268    return this.mSettingsModel.getAppPageStartConfig();
1269  }
1270
1271  /**
1272   * click event
1273   *
1274   * @param abilityName ability name
1275   * @param bundleName bundle name
1276   */
1277  onAppClick(abilityName: string, bundleName: string, moduleName: string) {
1278    if (!this.isPad) {
1279      this.jumpTo(abilityName, bundleName, moduleName);
1280      return;
1281    }
1282    Log.showDebug(TAG, `onAppClick keyName ${bundleName + abilityName + moduleName}`);
1283    AppStorage.setOrCreate('selectDesktopAppItem', bundleName + abilityName + moduleName);
1284  }
1285
1286  /**
1287   * double click event
1288   *
1289   * @param abilityName ability name
1290   * @param bundleName bundle name
1291   */
1292  onAppDoubleClick(abilityName: string, bundleName: string, moduleName: string): void {
1293    AppStorage.setOrCreate('selectDesktopAppItem', '');
1294    this.jumpTo(abilityName, bundleName, moduleName);
1295  }
1296
1297  /**
1298   * other app publish card to pageDesktop
1299   *
1300   * @param parameters
1301   */
1302  async publishCardToDesktop(parameters:any) {
1303    Log.showDebug(TAG, 'publishCardToDesktop');
1304    const formItem = await FormManager.getInstance().getFormCardItemByWant(parameters);
1305    localEventManager.sendLocalEventSticky(EventConstants.EVENT_REQUEST_PAGEDESK_FORM_ITEM_ADD, formItem);
1306  }
1307
1308  /**
1309   * add card to pageDesktop
1310   *
1311   * @param appInfo
1312   */
1313  async createCardToDeskTop(formCardItem) {
1314    Log.showDebug(TAG, `createCardToDeskTop formCardItem id: ${formCardItem.cardId}`);
1315    const cardItemInfo = this.createNewCardItemInfo(formCardItem);
1316
1317    let formInfoList: any = this.mFormListInfoCacheManager.getCache(KEY_FORM_LIST);
1318    if (formInfoList == CommonConstants.INVALID_VALUE) {
1319      formInfoList = new Array<CardItemInfo>();
1320    }
1321    formInfoList.push(cardItemInfo);
1322    this.mFormListInfoCacheManager.setCache(KEY_FORM_LIST, formInfoList);
1323
1324    const result = await this.mFormModel.updateFormInfoById(cardItemInfo);
1325    if (result) {
1326      const gridLayoutInfo = this.mSettingsModel.getLayoutInfo();
1327      const cardItemLayoutInfo = {
1328        cardId: cardItemInfo.cardId,
1329        typeId: CommonConstants.TYPE_CARD,
1330        area: FormManager.getInstance().getCardSize(cardItemInfo.cardDimension),
1331        page: 0,
1332        row: 0,
1333        column: 0
1334      };
1335
1336      const needNewPage: boolean =this.mPageDesktopModel.updatePageDesktopLayoutInfo(gridLayoutInfo, cardItemLayoutInfo);
1337      const curPageIndex = this.mPageDesktopModel.getPageIndex();
1338      if (needNewPage) {
1339        gridLayoutInfo.layoutDescription.pageCount = gridLayoutInfo.layoutDescription.pageCount + 1;
1340        for (let index = 0; index < gridLayoutInfo.layoutInfo.length; index++) {
1341          if (gridLayoutInfo.layoutInfo[index].page > curPageIndex) {
1342            gridLayoutInfo.layoutInfo[index].page++;
1343          }
1344        }
1345      }
1346
1347      // Push card into the layoutInfo
1348      gridLayoutInfo.layoutInfo.push(cardItemLayoutInfo);
1349      this.mSettingsModel.setLayoutInfo(gridLayoutInfo);
1350      if (needNewPage) {
1351        this.mPageDesktopModel.setPageIndex(curPageIndex + 1);
1352      }
1353    }
1354    this.getGridList();
1355  }
1356
1357  /**
1358   * create new cardItemInfo by formItemInfo
1359   *
1360   * @param formCardItem
1361   */
1362  private createNewCardItemInfo(formCardItem): CardItemInfo {
1363    const cardItemInfo = new CardItemInfo();
1364    cardItemInfo.cardId = formCardItem.cardId;
1365    cardItemInfo.cardName = formCardItem.cardName;
1366    cardItemInfo.bundleName = formCardItem.bundleName;
1367    cardItemInfo.abilityName = formCardItem.abilityName;
1368    cardItemInfo.moduleName = formCardItem.moduleName;
1369    cardItemInfo.formConfigAbility = formCardItem.formConfigAbility;
1370    cardItemInfo.appLabelId = formCardItem.appLabelId;
1371    cardItemInfo.cardDimension = formCardItem.cardDimension;
1372    return cardItemInfo;
1373  }
1374
1375  private ifStringIsNull(str): boolean {
1376    if (str == undefined || str == '' || str == null) {
1377      return true;
1378    }
1379    return false;
1380  }
1381
1382  private addNewInstalledInfo(totalAppInfoList, pageDesktopInfo): void {
1383    for (const i in totalAppInfoList) {
1384      let hasInstalled = false;
1385      for (const j in pageDesktopInfo) {
1386        if (totalAppInfoList[i].keyName == pageDesktopInfo[j].keyName) {
1387          hasInstalled = true;
1388          break;
1389        }
1390      }
1391      if (!hasInstalled) {
1392        pageDesktopInfo.push(totalAppInfoList[i]);
1393      }
1394    }
1395  }
1396
1397  private removeBottomBarInfo(pageDesktopInfo) {
1398    let bottomAppList = [];
1399    bottomAppList = AppStorage.get('residentList');
1400    Log.showDebug(TAG, `removeBottomBarInfo bottomAppList length: ${bottomAppList.length}`);
1401    if (!CheckEmptyUtils.isEmptyArr(bottomAppList)) {
1402      for (let i = 0; i < bottomAppList.length; i++) {
1403        Log.showDebug(TAG, `removeBottomBarInfo bottomAppList[${i}]: ${JSON.stringify(bottomAppList[i])}`);
1404        const appInfo = pageDesktopInfo.find(item => {
1405          if (item.keyName == bottomAppList[i].keyName) {
1406            return true;
1407          }
1408        });
1409        if (!this.ifInfoIsNull(appInfo)) {
1410          const index = pageDesktopInfo.indexOf(appInfo);
1411          pageDesktopInfo.splice(index, 1);
1412        }
1413      }
1414    }
1415  }
1416
1417  private removeFolderInfo(pageDesktopInfo): void {
1418    const gridLayoutInfo = this.mSettingsModel.getLayoutInfo();
1419    const layoutInfo = gridLayoutInfo.layoutInfo;
1420    for (let i = 0; i < layoutInfo.length; i++) {
1421      if (layoutInfo[i].typeId == CommonConstants.TYPE_FOLDER) {
1422        for (let j = 0; j < layoutInfo[i].layoutInfo.length; j++) {
1423          for (let k = 0; k < layoutInfo[i].layoutInfo[j].length; k++) {
1424            const appInfo = pageDesktopInfo.find(item => {
1425              if (item.keyName == layoutInfo[i].layoutInfo[j][k].keyName) {
1426                return true;
1427              }
1428            });
1429            if (!this.ifInfoIsNull(appInfo)) {
1430              const index = pageDesktopInfo.indexOf(appInfo);
1431              pageDesktopInfo.splice(index, 1);
1432              Log.showDebug(TAG, `removeFolderInfo keyName: ${appInfo.keyName}`);
1433            }
1434          }
1435        }
1436      }
1437    }
1438  }
1439
1440  /**
1441   * set start app info
1442   */
1443  private setStartAppInfo() {
1444    AppStorage.setOrCreate('startAppIconInfo', {
1445      appIconSize: 0,
1446      appIconHeight: 0,
1447      appIconPositionX: 0,
1448      appIconPositionY: 0
1449    });
1450  }
1451}