• 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 {
17  Log,
18  PinyinSort,
19  CheckEmptyUtils,
20  EventConstants,
21  CommonConstants,
22  BaseViewModel,
23  SettingsModel,
24  PageDesktopModel,
25  ResourceManager,
26  localEventManager,
27  layoutConfigManager,
28  FolderLayoutConfig,
29  AppItemInfo,
30  GridLayoutInfo,
31  FolderData,
32  LauncherDragItemInfo
33} from '@ohos/common';
34import { BigFolderModel } from '../model/BigFolderModel';
35import { BigFolderStyleConfig } from '../common/BigFolderStyleConfig';
36import { BigFolderConstants } from '../common/constants/BigFolderConstants';
37import { BigFolderStyleConstants } from '../common/constants/BigFolderStyleConstants';
38
39const TAG = 'BigFolderViewModel';
40
41interface AppListInfo {
42  appGridInfo: LauncherDragItemInfo[][]
43}
44
45export class BigFolderViewModel extends BaseViewModel {
46  private readonly mSettingsModel: SettingsModel;
47  private readonly mBigFolderModel: BigFolderModel;
48  private readonly mPageDesktopModel: PageDesktopModel;
49  private readonly mPinyinSort: PinyinSort;
50  private readonly mGridConfig;
51  private HEXADECIMAL_VALUE: number = 36;
52  private mPageIndex: number = 0;
53  private readonly mFolderStyleConfig: BigFolderStyleConfig;
54  private readonly mFolderLayoutConfig: FolderLayoutConfig;
55  private readonly mLocalEventListener = {
56    onReceiveEvent: (event, params) => {
57      Log.showDebug(TAG, `onReceiveEvent receive event: ${event}, params: ${JSON.stringify(params)}`);
58      const openStatus = AppStorage.get('openFolderStatus');
59      if (event === EventConstants.EVENT_BADGE_UPDATE && (openStatus == BigFolderConstants.OPEN_FOLDER_STATUS_OPEN || openStatus == BigFolderConstants.OPEN_FOLDER_STATUS_STATIC)) {
60        const openFolderData: FolderData = AppStorage.get('openFolderData');
61        this.updateBadge(openFolderData, params);
62      } else if (event === EventConstants.EVENT_FOLDER_PACKAGE_REMOVED) {
63        this.deleteAppFromFolderByUninstall(params);
64      } else if (event === EventConstants.EVENT_OPEN_FOLDER_TO_CLOSE) {
65        this.closeFolder();
66      }
67    }
68  };
69
70  // badge will be designed lastly
71  private updateBadge(openFolderData: FolderData, params: AppItemInfo): void {
72    for (let i = 0; i < openFolderData.layoutInfo.length; i++) {
73      const appInfo: AppItemInfo = openFolderData.layoutInfo[i].find(item => {
74        return item.bundleName === params.bundleName;
75      });
76      if (appInfo !== undefined && appInfo.bundleName.length > 0) {
77        const index = openFolderData.layoutInfo[i].indexOf(appInfo);
78        appInfo.badgeNumber = params.badgeNumber;
79        openFolderData.layoutInfo[i][index] = appInfo;
80        break;
81      }
82    }
83    Log.showDebug(TAG, `mLocalEventListener openFolderData: ${JSON.stringify(openFolderData)}`);
84    this.refreshFolder(openFolderData);
85  }
86
87  private constructor() {
88    super();
89    this.mBigFolderModel = BigFolderModel.getInstance();
90    this.mSettingsModel = SettingsModel.getInstance();
91    this.mPageDesktopModel = PageDesktopModel.getInstance();
92    this.mGridConfig = this.mSettingsModel.getGridConfig();
93    this.mPinyinSort = new PinyinSort();
94    this.mBigFolderModel.registerFolderUpdateEvent(this.mLocalEventListener);
95    this.mFolderStyleConfig = layoutConfigManager.getStyleConfig(BigFolderStyleConfig.APP_LIST_STYLE_CONFIG,
96      BigFolderConstants.FEATURE_NAME);
97    this.mFolderLayoutConfig = layoutConfigManager.getFunctionConfig(FolderLayoutConfig.FOLDER_GRID_LAYOUT_INFO);
98  }
99
100  static getInstance(): BigFolderViewModel {
101    if (globalThis.BigFolderViewModelInstance == null) {
102      globalThis.BigFolderViewModelInstance = new BigFolderViewModel();
103    }
104    return globalThis.BigFolderViewModelInstance;
105  }
106
107  /**
108   * return BigFolderStyleConfig
109   */
110  getFolderStyleConfig(): BigFolderStyleConfig {
111    return this.mFolderStyleConfig;
112  }
113
114  /**
115    * return folderOpenLayoutTable
116    */
117  getFolderLayoutConfig(): any {
118    return this.mFolderLayoutConfig.getFolderLayoutInfo().folderOpenLayoutTable;
119  }
120
121  /**
122   * add new folder
123   *
124   * @param {AppItemInfo[]} appLayoutInfo (two app for create new folder).
125   */
126  async addNewFolder(appLayoutInfo: AppItemInfo[]) {
127    const gridLayoutInfo = this.mSettingsModel.getLayoutInfo();
128    const settingAppInfoList = this.mSettingsModel.getAppListInfo();
129    const folderAppInfo: AppItemInfo[] = [];
130    for (let j = 0; j < appLayoutInfo.length; j++) {
131      Log.showDebug(TAG, `addNewFolder appLayoutInfo: ${JSON.stringify(appLayoutInfo[j])}`)
132      for (let i = 0; i < settingAppInfoList.length; i++) {
133        if (settingAppInfoList[i].keyName === appLayoutInfo[j].keyName) {
134          folderAppInfo.push(settingAppInfoList[i]);
135          break;
136        }
137      }
138    }
139
140    // sum all app badgeNumber
141    let badgeNumber = 0;
142    for (let i = 0; i < folderAppInfo.length; i++) {
143      if (folderAppInfo[i].badgeNumber && folderAppInfo[i].badgeNumber > 0) {
144        badgeNumber = badgeNumber + folderAppInfo[i].badgeNumber;
145      }
146    }
147
148    // Delete {the app list} from desktop app list
149    for (let i = 0; i < appLayoutInfo.length; i++) {
150      const index = gridLayoutInfo.layoutInfo.indexOf(appLayoutInfo[i] as LauncherDragItemInfo);
151      if (index != CommonConstants.INVALID_VALUE) {
152        gridLayoutInfo.layoutInfo.splice(index, 1);
153      }
154    }
155
156    const folderInfo = await this.createNewFolderInfo();
157    folderInfo.layoutInfo.push(folderAppInfo);
158    folderInfo.badgeNumber = badgeNumber;
159
160    const needNewPage: boolean = this.mPageDesktopModel.updatePageDesktopLayoutInfo(gridLayoutInfo, folderInfo);
161    if (needNewPage) {
162      gridLayoutInfo.layoutDescription.pageCount = gridLayoutInfo.layoutDescription.pageCount + 1;
163      for (let index = 0; index < gridLayoutInfo.layoutInfo.length; index++) {
164        if (gridLayoutInfo.layoutInfo[index].page > this.mPageDesktopModel.getPageIndex()) {
165          gridLayoutInfo.layoutInfo[index].page++;
166        }
167      }
168    }
169
170    // Push folder into the layoutInfo,include {the app list}
171    gridLayoutInfo.layoutInfo.push(folderInfo as LauncherDragItemInfo);
172    this.deleteAppLayoutItems(gridLayoutInfo, appLayoutInfo);
173    if (needNewPage) {
174      this.mPageDesktopModel.setPageIndex(this.mPageDesktopModel.getPageIndex() + 1);
175    }
176  }
177
178  /**
179   * add app to folder
180   *
181   * @param appInfo AppInfo
182   * @param folderId folderId
183   */
184  addOneAppToFolder(appInfo, folderId): void {
185    const gridLayoutInfo = this.mSettingsModel.getLayoutInfo();
186    let appListInfo = this.mSettingsModel.getAppListInfo();
187    appListInfo = appListInfo.filter(item => item.keyName !== appInfo.keyName);
188    // add App
189    for (let i = 0; i < gridLayoutInfo.layoutInfo.length; i++) {
190      const layoutInfo = gridLayoutInfo.layoutInfo[i];
191      if (layoutInfo.typeId === CommonConstants.TYPE_FOLDER && layoutInfo.folderId === folderId) {
192        const info = layoutInfo.layoutInfo;
193        if (layoutInfo.badgeNumber && layoutInfo.badgeNumber > 0) {
194          if (appInfo.badgeNumber && appInfo.badgeNumber > 0) {
195            layoutInfo.badgeNumber = layoutInfo.badgeNumber + appInfo.badgeNumber;
196          }
197        } else {
198          layoutInfo.badgeNumber = appInfo.badgeNumber;
199        }
200        const lastPageItems = info[info.length - 1];
201        if (lastPageItems[lastPageItems.length - 1].typeId == CommonConstants.TYPE_ADD) {
202          lastPageItems[lastPageItems.length - 1] = appInfo;
203        } else {
204          const openFolderConfig = this.mBigFolderModel.getFolderOpenLayout();
205          if (lastPageItems.length == openFolderConfig.column * openFolderConfig.row) {
206            info.push([appInfo]);
207          } else {
208            lastPageItems.push(appInfo);
209          }
210        }
211        break;
212      }
213    }
214
215    // delete app from desktop
216    this.mSettingsModel.setAppListInfo(appListInfo);
217    this.deleteAppLayoutItems(gridLayoutInfo, [appInfo]);
218  }
219
220  /**
221 * delete apps in pageDesktop
222 * @param appListInfo
223 */
224  private deleteAppLayoutItems(gridLayoutInfo, appLayoutInfo) {
225    for (let i = 0; i < appLayoutInfo.length; i++) {
226      gridLayoutInfo.layoutInfo = gridLayoutInfo.layoutInfo.filter(item => item.keyName != appLayoutInfo[i].keyName);
227    }
228    Log.showDebug(TAG, `deleteAppItems gridLayoutInfo.layoutInfo: ${gridLayoutInfo.layoutInfo.length}`);
229    this.mSettingsModel.setLayoutInfo(gridLayoutInfo);
230    localEventManager.sendLocalEventSticky(EventConstants.EVENT_REQUEST_PAGEDESK_ITEM_UPDATE, null);
231  }
232
233  /**
234   * Delete app from folder by dragging
235   *
236   * @param {AppItemInfo[]} folderAppList.
237   * @param {number} index.
238   */
239  deleteAppByDraging(folderAppList: AppItemInfo[], index: number): boolean {
240    const gridLayoutInfo = this.mSettingsModel.getLayoutInfo();
241    if (folderAppList.length == 0 || folderAppList.length <= index) {
242      return false;
243    }
244    const dragAppInfo = folderAppList[index];
245    if (folderAppList.length > 2) {
246      const needNewPage: boolean = this.mPageDesktopModel.updatePageDesktopLayoutInfo(gridLayoutInfo, dragAppInfo);
247      Log.showDebug(TAG, `deleteAppByDraging needNewPage: ${needNewPage}`);
248      if (needNewPage) {
249        return false;
250      }
251    }
252
253    folderAppList.splice(index, 1);
254    if (folderAppList.length > 0 && folderAppList[folderAppList.length - 1].typeId == CommonConstants.TYPE_ADD) {
255      folderAppList.pop();
256    }
257    const folderLayoutInfo = this.filterFolderPage(folderAppList);
258    const openFolderData: FolderData = AppStorage.get('openFolderData');
259    const removeAppInfos = [dragAppInfo];
260    const folderIndex = gridLayoutInfo.layoutInfo.findIndex(item => {
261      return item.typeId === CommonConstants.TYPE_FOLDER && item.folderId === openFolderData.folderId;
262    });
263
264    if (folderLayoutInfo.length == 1 && folderLayoutInfo[0].length == 1) {
265      // delete folder and add app to desktop
266      removeAppInfos.push(folderLayoutInfo[0][0]);
267      gridLayoutInfo.layoutInfo.splice(folderIndex, 1);
268    } else {
269      this.updateBadgeNumber(gridLayoutInfo.layoutInfo[folderIndex], dragAppInfo);
270      openFolderData.layoutInfo = folderLayoutInfo;
271    }
272
273    const appListInfo = this.mSettingsModel.getAppListInfo();
274    for (let i = 0; i < removeAppInfos.length; i++) {
275      this.mPageDesktopModel.updatePageDesktopLayoutInfo(gridLayoutInfo, removeAppInfos[i]);
276      const gridLayout = this.createAppLayoutInfo(removeAppInfos[i]);
277      gridLayoutInfo.layoutInfo.push(gridLayout as LauncherDragItemInfo);
278      appListInfo.push(removeAppInfos[i]);
279    }
280    this.mSettingsModel.setAppListInfo(appListInfo);
281    this.mSettingsModel.setLayoutInfo(gridLayoutInfo);
282    return true;
283  }
284
285  /**
286   * create new app layoutInfo
287   *
288   * @param appInfo
289   */
290  private createAppLayoutInfo(appInfo: AppItemInfo): AppItemInfo {
291    const appLayout: AppItemInfo = new AppItemInfo();
292    appLayout.bundleName = appInfo.bundleName;
293    appLayout.abilityName = appInfo.abilityName;
294    appLayout.moduleName = appInfo.moduleName;
295    appLayout.keyName = appInfo.keyName;
296    appLayout.typeId = appInfo.typeId;
297    appLayout.area = appInfo.area;
298    appLayout.page = appInfo.page;
299    appLayout.column = appInfo.column;
300    appLayout.row = appInfo.row;
301    return appLayout;
302  }
303
304  /**
305   * update folder badgeNumber
306   *
307   * @param folderLayoutInfo
308   * @param dragAppInfo
309   */
310  private updateBadgeNumber(folderLayoutInfo, dragAppInfo): void {
311    let folderBadgeNumber = 0;
312    if (folderLayoutInfo.badgeNumber && folderLayoutInfo.badgeNumber > 0) {
313      folderBadgeNumber = folderLayoutInfo.badgeNumber;
314      if (dragAppInfo.badgeNumber && dragAppInfo.badgeNumber > 0) {
315        folderBadgeNumber = folderBadgeNumber - dragAppInfo.badgeNumber;
316      }
317    }
318    folderLayoutInfo.badgeNumber = folderBadgeNumber;
319  }
320
321  /**
322   * Delete app from open folder
323   *
324   * @param {AppItemInfo} appInfo.
325   */
326  deleteAppFromOpenFolder(appInfo: AppItemInfo): FolderData {
327    let openFolderData: FolderData = AppStorage.get('openFolderData');
328    const folderLayoutInfo = this.getFolderLayoutInfo(openFolderData, appInfo);
329
330    // Delete app from the folder
331    const gridLayoutInfo = this.mSettingsModel.getLayoutInfo();
332    const folderIndex = gridLayoutInfo.layoutInfo.findIndex(item => {
333      return item.typeId === CommonConstants.TYPE_FOLDER && item.folderId === openFolderData.folderId;
334    });
335
336    const appListInfo = this.mSettingsModel.getAppListInfo();
337    if (folderLayoutInfo.length == 1 && folderLayoutInfo[0].length == 1) {
338      // delete from folder and add app to desktop
339      const appLayout = {
340        bundleName: folderLayoutInfo[0][0].bundleName,
341        abilityName: folderLayoutInfo[0][0].abilityName,
342        moduleName: folderLayoutInfo[0][0].moduleName,
343        keyName: folderLayoutInfo[0][0].keyName,
344        typeId: folderLayoutInfo[0][0].typeId,
345        area: folderLayoutInfo[0][0].area,
346        page: gridLayoutInfo.layoutInfo[folderIndex].page,
347        column: gridLayoutInfo.layoutInfo[folderIndex].column,
348        row: gridLayoutInfo.layoutInfo[folderIndex].row
349      };
350      gridLayoutInfo.layoutInfo.push(appLayout as LauncherDragItemInfo);
351      appListInfo.push(folderLayoutInfo[0][0]);
352      gridLayoutInfo.layoutInfo.splice(folderIndex, 1);
353      openFolderData = {
354        folderId: '',folderName: '', enterEditing: false, layoutInfo: []
355      };
356    } else {
357      this.updateBadgeNumber(gridLayoutInfo.layoutInfo[folderIndex], appInfo);
358      openFolderData.layoutInfo = folderLayoutInfo;
359    }
360    this.mSettingsModel.setAppListInfo(appListInfo);
361    this.mSettingsModel.setLayoutInfo(gridLayoutInfo);
362    return openFolderData;
363  }
364
365  /**
366   * update folder app list info
367   *
368   * @param {AppItemInfo[]} appInfos.
369   * @param {FolderData} folderItem.
370   */
371  async updateFolderAppList(appInfos: AppItemInfo[], folderItem: FolderData): Promise<void> {
372    Log.showDebug(TAG, 'updateFolderAppList start');
373    let removeFolderApp: AppItemInfo[] = [];
374    let gridLayoutInfoTemp: GridLayoutInfo;
375    let gridLayoutInfo = {
376      layoutInfo: []
377    };
378    gridLayoutInfo = this.mSettingsModel.getLayoutInfo();
379    gridLayoutInfoTemp = this.mSettingsModel.getLayoutInfo();
380    removeFolderApp = this.layoutInfoToList(folderItem);
381    // checked app <= 1
382    if (appInfos.length <= CommonConstants.FOLDER_APP_VALUE) {
383      for (let i = 0; i < gridLayoutInfoTemp.layoutInfo.length; i++) {
384        if (gridLayoutInfoTemp.layoutInfo[i].folderId === folderItem.folderId) {
385          gridLayoutInfoTemp.layoutInfo.splice(i, 1);
386          break;
387        }
388      }
389      folderItem.layoutInfo = [[]];
390      for (let i = 0; i < removeFolderApp.length; i++) {
391        localEventManager.sendLocalEventSticky(EventConstants.EVENT_REQUEST_PAGEDESK_ITEM_ADD, removeFolderApp[i]);
392        this.mPageDesktopModel.updatePageDesktopLayoutInfo(gridLayoutInfoTemp, removeFolderApp[i]);
393        const gridLayout = this.createAppLayoutInfo(removeFolderApp[i]);
394        gridLayoutInfoTemp.layoutInfo.push(gridLayout as LauncherDragItemInfo);
395      }
396      this.mSettingsModel.setLayoutInfo(gridLayoutInfoTemp);
397    } else {
398      // checked app's count >= 2
399      // update badgeNumber of folder
400      this.updateFolderBadgeNumber(appInfos, folderItem, gridLayoutInfo, gridLayoutInfoTemp);
401      // move app from other folder
402      this.moveAppFromOtherFolders(appInfos, folderItem, gridLayoutInfo, gridLayoutInfoTemp);
403      // move apps from desktop to folder
404      this.moveAppFromDesktopToFolder(appInfos, gridLayoutInfo, gridLayoutInfoTemp);
405      // move apps from folder to desktop
406      this.moveAppFromFolderToDesktop(appInfos, removeFolderApp, gridLayoutInfoTemp);
407      // delete blank page
408      this.deleteBlankPage();
409    }
410    Log.showDebug(TAG, 'updateFolderAppList end');
411  }
412
413  /**
414   * delete blank page
415   */
416  private deleteBlankPage(): void {
417    const layoutInfo = this.mSettingsModel.getLayoutInfo();
418    const pageItemMap = new Map<string, number>();
419    for (let i = 0; i < layoutInfo.layoutDescription.pageCount; i++) {
420      pageItemMap.set(i.toString(), 0);
421    }
422    for (let i = 0; i < layoutInfo.layoutInfo.length; i++) {
423     const tmpPage = layoutInfo.layoutInfo[i].page.toString();
424      pageItemMap.set(tmpPage, pageItemMap.get(tmpPage) + 1);
425    }
426
427    let appListInfo: AppListInfo | undefined = AppStorage.get('appListInfo');
428    let addCheckedList: LauncherDragItemInfo[] = AppStorage.get('selectAppItemList');
429    const blankPages = [];
430    appListInfo?.appGridInfo.forEach((item: LauncherDragItemInfo[], index) => {
431      if (CheckEmptyUtils.isEmptyArr(item)) {
432        return;
433      }
434      // Each page of apps can be found in the list of apps added
435      let isEvery = item.every((itemEvery) => {
436        return addCheckedList.find((itemFind) => {
437          return itemEvery.bundleName === itemFind.bundleName;
438        });
439      })
440      if (!isEvery) {
441        return;
442      }
443      layoutInfo.layoutDescription.pageCount--;
444      let page = pageItemMap.get(index.toString());
445      blankPages.push(page);
446    })
447
448    // Dissolve Delete separate large folders
449    appListInfo?.appGridInfo.forEach((item: LauncherDragItemInfo[], index)=> {
450      if (item.length == 1 && item[0].folderId) {
451        let isFolder = layoutInfo.layoutInfo.find((value)=> {
452          return value.folderId === item[0].folderId;
453        })
454        if (!isFolder) {
455          let page = pageItemMap.get(index.toString());
456          blankPages.push(page);
457          layoutInfo.layoutDescription.pageCount = layoutInfo.layoutDescription.pageCount - 1;
458        }
459      }
460    })
461
462    for (let m = 0; m < layoutInfo.layoutInfo.length; m++) {
463      let pageMinus = 0;
464      for (let n = 0; n < blankPages.length; n++) {
465        if (layoutInfo.layoutInfo[m].page > blankPages[n]) {
466          pageMinus++;
467        }
468      }
469      let isSome: LauncherDragItemInfo = addCheckedList.find((itemFind) => {
470        return itemFind.bundleName !== layoutInfo.layoutInfo[m].bundleName;
471      })
472      let isSomePage: boolean = layoutInfo.layoutInfo[m].page > isSome.page;
473      if (isSome && pageMinus !=0 && isSomePage) {
474        layoutInfo.layoutInfo[m].page = layoutInfo.layoutInfo[m].page - pageMinus;
475      }
476    }
477    AppStorage.setOrCreate('selectAppItemList', []);
478    this.mSettingsModel.setLayoutInfo(layoutInfo);
479    localEventManager.sendLocalEventSticky(EventConstants.EVENT_REQUEST_PAGEDESK_ITEM_UPDATE, null);
480  }
481
482  /**
483   * get apps in checked appinfos, not in folderAppList
484   *
485   * @param appInfos
486   * @param folderAppList
487   */
488  getAppRemainInOtherFolder(appInfos: AppItemInfo[], folderAppList: AppItemInfo[]): AppItemInfo[] {
489    const appInfosRemaining = [];
490    for (let m = 0; m < folderAppList.length; m++) {
491      const appIndex = appInfos.findIndex(item => {
492        return item.keyName === folderAppList[m].keyName;
493      });
494      if (appIndex == CommonConstants.INVALID_VALUE) {
495        appInfosRemaining.push(folderAppList[m]);
496      }
497    }
498    return appInfosRemaining;
499  }
500
501  /**
502   * update badgeNumber of folder
503   *
504   * @param appInfos
505   * @param folderItem
506   * @param gridLayoutInfo
507   */
508  private updateFolderBadgeNumber(appInfos: AppItemInfo[], folderItem: FolderData, gridLayoutInfo, gridLayoutInfoTemp): void {
509    for (let i = 0; i < gridLayoutInfo.layoutInfo.length; i++) {
510      if (gridLayoutInfo.layoutInfo[i].typeId === CommonConstants.TYPE_FOLDER
511      && gridLayoutInfo.layoutInfo[i].folderId === folderItem.folderId) {
512        let badgeNumber = 0;
513        appInfos.forEach((item) => {
514          if (item.badgeNumber && item.badgeNumber > 0) {
515            badgeNumber = badgeNumber + item.badgeNumber;
516          }
517        });
518        const folderLayoutInfo = this.filterFolderPage(appInfos);
519        folderItem.layoutInfo = folderLayoutInfo;
520        folderItem.badgeNumber = badgeNumber;
521        gridLayoutInfoTemp.layoutInfo[i].layoutInfo = JSON.parse(JSON.stringify(folderLayoutInfo));
522        this.mSettingsModel.setLayoutInfo(gridLayoutInfoTemp);
523        localEventManager.sendLocalEventSticky(EventConstants.EVENT_REQUEST_PAGEDESK_ITEM_UPDATE, null);
524        break;
525      }
526    }
527  }
528
529  /**
530   * move app from other folders to folder or to desktop
531   *
532   * @param appInfos
533   * @param gridLayoutInfo
534   * @param gridLayoutInfoTemp
535   */
536  private moveAppFromOtherFolders(appInfos, folderItem, gridLayoutInfo, gridLayoutInfoTemp): void {
537    for (let i = gridLayoutInfo.layoutInfo.length - 1; i >= 0; i--) {
538      if (gridLayoutInfo.layoutInfo[i].typeId === CommonConstants.TYPE_FOLDER
539      && gridLayoutInfo.layoutInfo[i].folderId !== folderItem.folderId) {
540        const folderAppList = this.layoutInfoToList(gridLayoutInfo.layoutInfo[i]);
541        const appInfosRemaining = this.getAppRemainInOtherFolder(appInfos, folderAppList);
542        const thisFolderItemIndex = gridLayoutInfoTemp.layoutInfo.findIndex(item => {
543          return item.folderId === gridLayoutInfo.layoutInfo[i].folderId;
544        });
545
546        if (appInfosRemaining.length === 0) {
547          gridLayoutInfoTemp.layoutInfo.splice(thisFolderItemIndex, 1);
548          this.mSettingsModel.setLayoutInfo(gridLayoutInfoTemp);
549          localEventManager.sendLocalEventSticky(EventConstants.EVENT_REQUEST_PAGEDESK_ITEM_UPDATE, null);
550        } else if (appInfosRemaining.length === CommonConstants.FOLDER_APP_VALUE) {
551          gridLayoutInfoTemp.layoutInfo.splice(thisFolderItemIndex, 1);
552          this.mSettingsModel.setLayoutInfo(gridLayoutInfoTemp);
553          localEventManager.sendLocalEventSticky(EventConstants.EVENT_REQUEST_PAGEDESK_ITEM_ADD, appInfosRemaining[0]);
554        } else {
555          let badgeNumber = 0;
556          appInfosRemaining.forEach((item) => {
557            if (item.badgeNumber && item.badgeNumber > 0) {
558              badgeNumber = badgeNumber + item.badgeNumber;
559            }
560          });
561          gridLayoutInfoTemp.layoutInfo[thisFolderItemIndex].badgeNumber = badgeNumber;
562          gridLayoutInfoTemp.layoutInfo[thisFolderItemIndex].layoutInfo = this.filterFolderPage(appInfosRemaining);
563          this.mSettingsModel.setLayoutInfo(gridLayoutInfoTemp);
564          localEventManager.sendLocalEventSticky(EventConstants.EVENT_REQUEST_PAGEDESK_ITEM_UPDATE, null);
565        }
566      }
567    }
568  }
569
570  /**
571   * move apps from desktop to folder
572   *
573   * @param appInfos
574   * @param gridLayoutInfo
575   * @param gridLayoutInfoTemp
576   */
577  private moveAppFromDesktopToFolder(appInfos, gridLayoutInfo, gridLayoutInfoTemp): void {
578    const appDesktopToFolder = [];
579    for (let i = 0; i < appInfos.length; i++) {
580      for (let j = 0; j < gridLayoutInfo.layoutInfo.length; j++) {
581        if (gridLayoutInfo.layoutInfo[j].typeId == CommonConstants.TYPE_APP &&
582        appInfos[i].keyName == gridLayoutInfo.layoutInfo[j].keyName) {
583          appDesktopToFolder.push(gridLayoutInfo.layoutInfo[j]);
584          break;
585        }
586      }
587    }
588
589    if (appDesktopToFolder.length > 0) {
590      this.deleteAppLayoutItems(gridLayoutInfoTemp, appDesktopToFolder);
591    }
592  }
593
594  /**
595   * move app from folder to desktop
596   *
597   * @param appInfos
598   * @param removeFolderApp
599   * @param gridLayoutInfoTemp
600   */
601  private moveAppFromFolderToDesktop(appInfos, removeFolderApp, gridLayoutInfoTemp) {
602    const appFolderToDesktop = [];
603    for (let i = 0; i < removeFolderApp.length; i++) {
604      let remainFlag = false;
605      for (let j = 0; j < appInfos.length; j++) {
606        if (appInfos[j].keyName == removeFolderApp[i].keyName) {
607          remainFlag = true;
608          break;
609        }
610      }
611      if (!remainFlag) {
612        appFolderToDesktop.push(removeFolderApp[i]);
613      }
614    }
615
616    if (appFolderToDesktop.length > 0) {
617      for (let i = 0; i < appFolderToDesktop.length; i++) {
618        const needNewPage: boolean = this.mPageDesktopModel.updatePageDesktopLayoutInfo(gridLayoutInfoTemp, appFolderToDesktop[i]);
619        if (needNewPage) {
620          gridLayoutInfoTemp.layoutDescription.pageCount = gridLayoutInfoTemp.layoutDescription.pageCount + 1;
621          for (let index = 0; index < gridLayoutInfoTemp.layoutInfo.length; index++) {
622            if (gridLayoutInfoTemp.layoutInfo[index].page > this.mPageDesktopModel.getPageIndex()) {
623              gridLayoutInfoTemp.layoutInfo[index].page++;
624            }
625          }
626        }
627        const gridLayout = this.createAppLayoutInfo(appFolderToDesktop[i]);
628        gridLayoutInfoTemp.layoutInfo.push(gridLayout);
629        localEventManager.sendLocalEventSticky(EventConstants.EVENT_REQUEST_PAGEDESK_ITEM_ADD, appFolderToDesktop[i]);
630      }
631      this.mSettingsModel.setLayoutInfo(gridLayoutInfoTemp);
632    }
633  }
634
635  /**
636   * get folder app list
637   *
638   * @param {array} folderId.
639   * @return {array} folderAppList.
640   */
641  async getFolderAppList(folderId) {
642    Log.showDebug(TAG, 'getFolderAppList start');
643    let folderAppList = [];
644    let gridLayoutInfo = {
645      layoutInfo: []
646    };
647    gridLayoutInfo = this.mSettingsModel.getLayoutInfo();
648
649    // Get folder app list form the layout info
650    for (let i = 0; i < gridLayoutInfo.layoutInfo.length; i++) {
651      const layoutInfo = gridLayoutInfo.layoutInfo[i];
652      if (layoutInfo.typeId === CommonConstants.TYPE_FOLDER && layoutInfo.folderId === folderId) {
653        for (let j = 0; j < layoutInfo.layoutInfo.length; j++) {
654          folderAppList = folderAppList.concat(layoutInfo.layoutInfo[j]);
655        }
656      }
657    }
658    if (folderAppList.length > 0 && folderAppList[folderAppList.length - 1].typeId == CommonConstants.TYPE_ADD) {
659      folderAppList.pop();
660    }
661    AppStorage.setOrCreate('folderAppList', folderAppList);
662    return folderAppList;
663  }
664
665  /**
666   * get all folder list
667   *
668   * @return {array} folderList.
669   */
670  async getAllFolderList() {
671    Log.showDebug(TAG, 'getAllFolderList start');
672    const folderList = [];
673    let gridLayoutInfo = {
674      layoutInfo: []
675    };
676    gridLayoutInfo = this.mSettingsModel.getLayoutInfo();
677
678    // Get folder list form the layout info
679    for (let i = 0; i < gridLayoutInfo.layoutInfo.length; i++) {
680      if (gridLayoutInfo.layoutInfo[i].typeId === CommonConstants.TYPE_FOLDER) {
681        folderList.push(gridLayoutInfo.layoutInfo[i]);
682      }
683    }
684    AppStorage.setOrCreate('allFolderList', folderList);
685    return folderList;
686  }
687
688  /**
689   * get the all app list for folder
690   *
691   * @param {number} folderId
692   *
693   */
694  async getFolderAddAppList(folderId: string): Promise<AppItemInfo[]> {
695    Log.showDebug(TAG, 'getFolderAddAppList start');
696    if (CheckEmptyUtils.checkStrIsEmpty(folderId)) {
697      Log.showDebug(TAG, 'getFolderAddAppList folderId is Empty');
698      return;
699    }
700    let allAppList: AppItemInfo[] = [];
701    let appInfos: AppItemInfo[] = [];
702    let gridLayoutInfo = {
703      layoutInfo: []
704    };
705    gridLayoutInfo = this.mSettingsModel.getLayoutInfo();
706    const appListInfo = await this.mAppModel.getAppList();
707
708    // first push this current app
709    for (let i = 0; i < gridLayoutInfo.layoutInfo.length; i++) {
710      const layoutInfo = gridLayoutInfo.layoutInfo[i];
711      if (layoutInfo.typeId === CommonConstants.TYPE_FOLDER && layoutInfo.folderId === folderId) {
712        for (let j = 0; j < layoutInfo.layoutInfo.length; j++) {
713          appInfos = layoutInfo.layoutInfo[j];
714          for (let k = 0; k < appInfos.length; k++) {
715            appInfos[k].checked = true;
716            allAppList.push(appInfos[k]);
717          }
718        }
719        break;
720      }
721    }
722
723    if (allAppList.length > 0 && allAppList[allAppList.length - 1].typeId == CommonConstants.TYPE_ADD) {
724      allAppList.pop();
725    }
726
727    for (let i = 0; i < appListInfo.length; i++) {
728      let isExist = false;
729      for (let j = 0; j < allAppList.length; j++) {
730        if (appListInfo[i].keyName === allAppList[j].keyName) {
731          isExist = true;
732          break;
733        }
734      }
735      if (!isExist) {
736        appListInfo[i].checked = false;
737        allAppList.push(appListInfo[i]);
738      }
739    }
740    if (!this.getIsPad()) {
741      let bottomAppList: AppItemInfo[] = AppStorage.get('residentList') as AppItemInfo[];
742      if (!CheckEmptyUtils.isEmptyArr(bottomAppList)) {
743        for (let i = 0; i < bottomAppList.length; i++) {
744          allAppList = allAppList.filter((item) => {
745            if (bottomAppList[i].keyName == item.keyName) {
746              return false;
747            }
748            return true;
749          })
750        }
751      }
752    }
753    AppStorage.setOrCreate('allAppListForFolder', allAppList);
754    return allAppList;
755  }
756
757  /**
758   * open folder
759   *
760   * @param {FolderData} folderInfo.
761   */
762  addAddIcon(folderItem: FolderData): FolderData {
763    Log.showDebug(TAG, 'addAddIcon start');
764
765    if (folderItem.layoutInfo.length == 0) {
766      return folderItem;
767    }
768    const lastPageItem = folderItem.layoutInfo[folderItem.layoutInfo.length - 1];
769    if (lastPageItem[lastPageItem.length - 1].typeId === CommonConstants.TYPE_ADD) {
770      return folderItem;
771    }
772
773    const openFolderConfig = this.mBigFolderModel.getFolderOpenLayout();
774    const column = openFolderConfig.column;
775    const row = openFolderConfig.row;
776    const addInfo: AppItemInfo = new AppItemInfo();
777    addInfo.typeId = CommonConstants.TYPE_ADD;
778    addInfo.appName = '';
779    if (folderItem.layoutInfo[folderItem.layoutInfo.length - 1].length === column * row) {
780      folderItem.layoutInfo.push([addInfo]);
781    } else {
782      folderItem.layoutInfo[folderItem.layoutInfo.length - 1].push(addInfo);
783    }
784
785    Log.showDebug(TAG, 'addAddIcon end');
786    return folderItem;
787  }
788
789  /**
790   * open folder
791   *
792   * @param {FolderData} folderInfo.
793   */
794  delAddIcon(folderItem: FolderData): FolderData {
795    Log.showDebug(TAG, 'delAddIcon start');
796
797    if (folderItem.layoutInfo.length == 0) {
798      return folderItem;
799    }
800    const lastPageItem = folderItem.layoutInfo[folderItem.layoutInfo.length - 1];
801    if (lastPageItem[lastPageItem.length - 1].typeId !== CommonConstants.TYPE_ADD) {
802      return folderItem;
803    }
804    lastPageItem.pop();
805    if (lastPageItem.length == 0) {
806      folderItem.layoutInfo.pop();
807    } else {
808      folderItem.layoutInfo[folderItem.layoutInfo.length - 1] = lastPageItem;
809    }
810
811    Log.showDebug(TAG, 'delAddIcon end');
812    return folderItem;
813  }
814
815  /**
816   * open folder
817   *
818   * @param {boolean} isRename.
819   * @param {FolderData} folderItem.
820   */
821  async openFolder(isRename: boolean, folderItem: FolderData) {
822    Log.showDebug(TAG, 'openFolder start');
823    folderItem.enterEditing = isRename;
824
825    AppStorage.setOrCreate('openFolderData', folderItem);
826    this.mPageIndex = 0;
827    AppStorage.setOrCreate('openFolderPageIndex', this.mPageIndex);
828    AppStorage.setOrCreate('openFolderStatus', BigFolderConstants.OPEN_FOLDER_STATUS_OPEN);
829    Log.showDebug(TAG, 'openFolder end');
830  }
831
832  /**
833   * close folder
834   */
835  async closeFolder() {
836    Log.showDebug(TAG, 'closeFolder start');
837
838    this.mPageIndex = 0;
839    AppStorage.setOrCreate('openFolderPageIndex', this.mPageIndex);
840    AppStorage.setOrCreate('openFolderStatus', BigFolderConstants.OPEN_FOLDER_STATUS_CLOSE);
841  }
842
843  /**
844   * refresh folder data
845   *
846   * @param folderItem
847   */
848  async refreshFolder(folderItem: FolderData) {
849    Log.showDebug(TAG, 'refreshFolder start');
850    folderItem.enterEditing = false;
851    this.updateOpenFolderStatus(folderItem);
852    Log.showDebug(TAG, 'refreshFolder end');
853  }
854
855  /**
856   * get device type
857   *
858   * @return {boolean} isPad.
859   */
860  getIsPad(): boolean {
861    return CommonConstants.PAD_DEVICE_TYPE == AppStorage.get('deviceType');
862  }
863
864  /**
865   * modify folder name
866   *
867   * @param {FolderData} folderModel.
868   */
869  modifyFolderName(folderModel: FolderData): void {
870    let gridLayoutInfo: GridLayoutInfo = {
871      layoutDescription: undefined,
872      layoutInfo: []
873    };
874    gridLayoutInfo = this.mSettingsModel.getLayoutInfo();
875
876    for (let i = 0; i < gridLayoutInfo.layoutInfo.length; i++) {
877      if (gridLayoutInfo.layoutInfo[i].typeId === CommonConstants.TYPE_FOLDER &&
878      gridLayoutInfo.layoutInfo[i].folderId === folderModel.folderId) {
879        gridLayoutInfo.layoutInfo[i].folderName = folderModel.folderName;
880      }
881    }
882    this.mSettingsModel.setLayoutInfo(gridLayoutInfo);
883  }
884
885  /**
886   * make the applist into folder page
887   *
888   * @param appInfos
889   */
890  filterFolderPage(appInfos: AppItemInfo[]): AppItemInfo[][] {
891    const folderLayoutInfo = [];
892    const appListInfo = JSON.parse(JSON.stringify(appInfos));
893    const openFolderConfig = this.mBigFolderModel.getFolderOpenLayout();
894
895    const itemCountByPage = openFolderConfig.column * openFolderConfig.row;
896    let pageCount = Math.floor(appListInfo.length / itemCountByPage);
897    if (appListInfo.length % itemCountByPage != 0) {
898      pageCount = pageCount + 1;
899    }
900    Log.showDebug(TAG, `filterFolderPage pageCount: ${pageCount}`);
901    for (let i = 0; i < pageCount; i++) {
902      let pageInfo = [];
903      if (itemCountByPage > appListInfo.length) {
904        pageInfo = appListInfo.splice(0, appListInfo.length);
905      } else {
906        pageInfo = appListInfo.splice(0, itemCountByPage);
907      }
908      folderLayoutInfo.push(pageInfo);
909    }
910    return folderLayoutInfo;
911  }
912
913  /**
914   * make the folder layoutInfo into list
915   *
916   * @param {FolderData} folderInfo
917   */
918  private layoutInfoToList(folderInfo: FolderData): AppItemInfo[] {
919    let appInfo: AppItemInfo[] = [];
920    for (let i = 0; i < folderInfo.layoutInfo.length; i++) {
921      for (let j = 0; j < folderInfo.layoutInfo[i].length; j++) {
922        if (folderInfo.layoutInfo[i][j].typeId != CommonConstants.TYPE_ADD) {
923          appInfo = appInfo.concat(folderInfo.layoutInfo[i][j]);
924        }
925      }
926    }
927    return appInfo;
928  }
929
930  /**
931   * create folder info
932   *
933   * @return {LauncherDragItemInfo} folderInfo.
934   */
935  private async createNewFolderInfo() {
936    const folderConfig = this.mBigFolderModel.getFolderLayout();
937    const folderName = await this.generateFolderName();
938    // Create new folder info
939    const folderInfo = {
940      folderId: this.getUUID(),
941      folderName: folderName,
942      layoutInfo: [],
943      typeId: CommonConstants.TYPE_FOLDER,
944      area: folderConfig.area,
945      badgeNumber: 0
946    };
947    return folderInfo as LauncherDragItemInfo;
948  }
949
950  /**
951   * generate folder name
952   *
953   * @return {string} folderName.
954   */
955  private async generateFolderName() {
956    Log.showDebug(TAG, 'generateFolderName start');
957    const folderList = await this.getAllFolderList();
958    let folderName: string = await ResourceManager.getInstance().getStringByIdSync($r('app.string.new_folder_name').id);
959    const autoNameFolderList = folderList.filter((element, index, self) => {
960      return element.folderName.startsWith(folderName) && (element.folderName.length > folderName.length);
961    });
962
963    autoNameFolderList.sort(this.mPinyinSort.sortByFolderName.bind(this.mPinyinSort));
964
965    let nameNumber = 1;
966    let tempFolderName = folderName + nameNumber;
967    for (let i = 0; i < autoNameFolderList.length; i++) {
968      if (autoNameFolderList[i].folderName == tempFolderName) {
969        nameNumber = nameNumber + 1;
970        tempFolderName = folderName + nameNumber;
971      } else {
972        break;
973      }
974    }
975    folderName = folderName + nameNumber;
976    return folderName;
977  }
978
979  /**
980   * generate a non duplicate ID
981   *
982   * @param {string} idLength
983   */
984  private getUUID(): string {
985    Log.showDebug(TAG, 'getUUID start');
986    let id = Date.now().toString(this.HEXADECIMAL_VALUE);
987    id += Math.random().toString(this.HEXADECIMAL_VALUE).substr(2);
988    return id;
989  }
990
991  /**
992   * change the open folder page number.
993   *
994   * @param idx: Page number
995   */
996  changeIndex(idx): void {
997    this.mPageIndex = idx;
998    AppStorage.setOrCreate('openFolderPageIndex', this.mPageIndex);
999  }
1000
1001  /**
1002   * get the open folder page number.
1003   */
1004  getIndex(): number {
1005    return this.mPageIndex;
1006  }
1007
1008  /**
1009   * get addlist dialog's column
1010   */
1011  getAddListColumn(): number {
1012    return this.mBigFolderModel.getFolderAddAppLayout().column;
1013  }
1014
1015  /**
1016   * get add app dialog's height
1017   *
1018   * @param appList
1019   */
1020  getDialogHeight(appList: AppItemInfo[]): number {
1021    let height = 0;
1022    const styleConfig = this.mFolderStyleConfig;
1023    const column = this.mBigFolderModel.getFolderAddAppLayout().column;
1024    const row = this.mBigFolderModel.getFolderAddAppLayout().row;
1025    const num = Math.ceil(appList.length / column);
1026    if (num <= row) {
1027      height = styleConfig.mAddFolderDialogHeight;
1028    } else {
1029      const gridHeight = num * (this.mFolderStyleConfig.mAddFolderIconSize + this.mFolderStyleConfig.mAddFolderTextLines) + num * styleConfig.mAddFolderGridGap +
1030      styleConfig.mAddFolderGridMargin * 2;
1031      height = gridHeight + BigFolderStyleConstants.DEFAULT_APP_ADD_TITLE_SIZE +
1032      BigFolderStyleConstants.DEFAULT_BUTTON_HEIGHT + BigFolderStyleConstants.DEFAULT_DIALOG_BOTTOM_MARGIN;
1033      if (height > styleConfig.mAddFolderMaxHeight) {
1034        height = styleConfig.mAddFolderMaxHeight;
1035      }
1036    }
1037    return height;
1038  }
1039
1040  /**
1041   * delete app from folder
1042   *
1043   * @param bundleName
1044   */
1045  deleteAppFromFolderByUninstall(bundleName): void {
1046    Log.showDebug(TAG, 'deleteAppFromFolderByUninstall start');
1047    const gridLayoutInfo = this.mSettingsModel.getLayoutInfo();
1048    const layoutInfo = gridLayoutInfo.layoutInfo;
1049    for (let i = 0; i < layoutInfo.length; i++) {
1050      if (layoutInfo[i].typeId == CommonConstants.TYPE_FOLDER) {
1051        let folderAppList = this.layoutInfoToList(layoutInfo[i] as FolderData);
1052        folderAppList = folderAppList.filter(item => item.bundleName != bundleName);
1053        this.updateFolderInfo(folderAppList, gridLayoutInfo, i);
1054      }
1055    }
1056    Log.showDebug(TAG, 'deleteAppFromFolderByUninstall end');
1057  }
1058
1059  /**
1060   * update layoutInfo when only one item in the folder
1061   *
1062   * @param folderAppList
1063   * @param gridLayoutInfo
1064   * @param index
1065   */
1066  private updateFolderInfo(folderAppList, gridLayoutInfo, index): void {
1067    if (folderAppList.length == 0) {
1068      gridLayoutInfo.layoutInfo.splice(index, 1);
1069      this.mSettingsModel.setLayoutInfo(gridLayoutInfo);
1070      localEventManager.sendLocalEventSticky(EventConstants.EVENT_REQUEST_PAGEDESK_ITEM_UPDATE, null);
1071    } else if (folderAppList.length == 1) {
1072      const appLayoutInfo = {
1073        bundleName: folderAppList[0].bundleName,
1074        abilityName: folderAppList[0].abilityName,
1075        moduleName: folderAppList[0].moduleName,
1076        keyName: folderAppList[0].keyName,
1077        typeId: CommonConstants.TYPE_APP,
1078        area: [1, 1],
1079        page: gridLayoutInfo.layoutInfo[index].page,
1080        column: gridLayoutInfo.layoutInfo[index].column,
1081        row: gridLayoutInfo.layoutInfo[index].row
1082      };
1083      gridLayoutInfo.layoutInfo.splice(index, 1);
1084      gridLayoutInfo.layoutInfo.push(appLayoutInfo);
1085      this.mSettingsModel.setLayoutInfo(gridLayoutInfo);
1086      localEventManager.sendLocalEventSticky(EventConstants.EVENT_REQUEST_PAGEDESK_ITEM_ADD, folderAppList[0]);
1087    } else {
1088      gridLayoutInfo.layoutInfo[index].layoutInfo = this.filterFolderPage(folderAppList);
1089      this.mSettingsModel.setLayoutInfo(gridLayoutInfo);
1090      localEventManager.sendLocalEventSticky(EventConstants.EVENT_REQUEST_PAGEDESK_ITEM_UPDATE, null);
1091    }
1092  }
1093
1094  /**
1095   * remove app from folder
1096   *
1097   * @param {AppItemInfo} appInfo.
1098   */
1099  removeAppOutOfFolder(appInfo: AppItemInfo): void {
1100    let openFolderData: FolderData = AppStorage.get('openFolderData');
1101
1102    const folderAppList = this.getAppListInFolder(openFolderData);
1103    this.deleteAppFromFolderAppList(appInfo, folderAppList);
1104    const folderLayoutInfo = this.filterFolderPage(folderAppList);
1105
1106    const removeAppInfos = [appInfo];
1107    const gridLayoutInfo = this.mSettingsModel.getLayoutInfo();
1108    const folderIndex = gridLayoutInfo.layoutInfo.findIndex(item => {
1109      return item.typeId === CommonConstants.TYPE_FOLDER && item.folderId === openFolderData.folderId;
1110    });
1111
1112    if (folderLayoutInfo.length == 1 && folderLayoutInfo[0].length == 1) {
1113      // delete folder and add app to desktop
1114      removeAppInfos.push(folderLayoutInfo[0][0]);
1115      gridLayoutInfo.layoutInfo.splice(folderIndex, 1);
1116      openFolderData = {
1117        folderId: '',enterEditing: false, folderName: '', layoutInfo: []
1118      };
1119    } else {
1120      this.updateBadgeNumber(gridLayoutInfo.layoutInfo[folderIndex], appInfo);
1121      openFolderData.layoutInfo = folderLayoutInfo;
1122    }
1123    const appListInfo = this.mSettingsModel.getAppListInfo();
1124    // Add app to desktop app list
1125    for (let i = 0; i < removeAppInfos.length; i++) {
1126      const needNewPage: boolean = this.mPageDesktopModel.updatePageDesktopLayoutInfo(gridLayoutInfo, removeAppInfos[i]);
1127      if (needNewPage) {
1128        gridLayoutInfo.layoutDescription.pageCount = gridLayoutInfo.layoutDescription.pageCount + 1;
1129        for (let index = 0; index < gridLayoutInfo.layoutInfo.length; index++) {
1130          if (gridLayoutInfo.layoutInfo[index].page > this.mPageDesktopModel.getPageIndex()) {
1131            gridLayoutInfo.layoutInfo[index].page++;
1132          }
1133        }
1134      }
1135      const gridLayout = this.createAppLayoutInfo(removeAppInfos[i]);
1136      gridLayoutInfo.layoutInfo.push(gridLayout as LauncherDragItemInfo);
1137      const appIndex = appListInfo.findIndex(item => {
1138        return item.keyName === removeAppInfos[i].keyName;
1139      })
1140      if (appIndex == CommonConstants.INVALID_VALUE) {
1141        appListInfo.push(removeAppInfos[i]);
1142      }
1143    }
1144    this.mSettingsModel.setAppListInfo(appListInfo);
1145    this.mSettingsModel.setLayoutInfo(gridLayoutInfo);
1146    localEventManager.sendLocalEventSticky(EventConstants.EVENT_REQUEST_PAGEDESK_ITEM_UPDATE, null);
1147    this.updateOpenFolderStatus(openFolderData);
1148  }
1149
1150  /**
1151   * update folderData and openFolderStatus
1152   *
1153   * @param openFolderData
1154   */
1155  private updateOpenFolderStatus(openFolderData: FolderData): void {
1156    AppStorage.setOrCreate('openFolderData', openFolderData);
1157    if (openFolderData.folderId == '') {
1158      AppStorage.setOrCreate('openFolderStatus', BigFolderConstants.OPEN_FOLDER_STATUS_CLOSE);
1159    } else {
1160      AppStorage.setOrCreate('openFolderStatus', BigFolderConstants.OPEN_FOLDER_STATUS_REFRESH);
1161    }
1162  }
1163
1164  /**
1165   * delete appInfo from folder
1166   *
1167   * @param appInfo
1168   * @param folderAppList
1169   */
1170  private deleteAppFromFolderAppList(appInfo, folderAppList): void {
1171    const appIndex = folderAppList.findIndex(item => {
1172      return item.keyName === appInfo.keyName;
1173    });
1174    if (appIndex !== CommonConstants.INVALID_VALUE) {
1175      folderAppList.splice(appIndex, 1);
1176    }
1177  }
1178
1179  /**
1180   * get folder's appList from appStorage
1181   *
1182   * @param openFolderData
1183   */
1184  private getAppListInFolder(openFolderData: FolderData): AppItemInfo[] {
1185    let folderAppList = [];
1186    for (let i = 0; i < openFolderData.layoutInfo.length; i++) {
1187      folderAppList = folderAppList.concat(openFolderData.layoutInfo[i]);
1188    }
1189    if (folderAppList.length > 0 && folderAppList[folderAppList.length - 1].typeId === CommonConstants.TYPE_ADD) {
1190      folderAppList.pop();
1191    }
1192    return folderAppList;
1193  }
1194
1195  /**
1196   * get folder layoutInfo after delete appInfo from folder
1197   *
1198   * @param openFolderData
1199   * @param appInfo
1200   */
1201  private getFolderLayoutInfo(openFolderData: FolderData, appInfo: AppItemInfo): AppItemInfo[][] {
1202    let folderAppList = this.getAppListInFolder(openFolderData);
1203    const index = folderAppList.findIndex(item => {
1204      return item.keyName === appInfo.keyName;
1205    });
1206    if (index !== CommonConstants.INVALID_VALUE) {
1207      folderAppList.splice(index, 1);
1208    }
1209    return this.filterFolderPage(folderAppList);
1210  }
1211}