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