• 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 { Log } from '@ohos/common';
17import { Trace } from '@ohos/common';
18import { CheckEmptyUtils } from '@ohos/common';
19import { MenuInfo } from '@ohos/common';
20import { MissionInfo } from '@ohos/common';
21import { DockItemInfo } from '@ohos/common';
22import { windowManager } from '@ohos/common';
23import { layoutConfigManager } from '@ohos/common';
24import { amsMissionManager }from '@ohos/common';
25import { launcherAbilityManager } from '@ohos/common';
26import { CommonConstants } from '@ohos/common';
27import { BaseViewModel } from '@ohos/common';
28import SmartDockStartAppHandler from '../common/SmartDockStartAppHandler';
29import SmartDockModel from '../model/SmartDockModel';
30import SmartDockDragHandler from '../common/SmartDockDragHandler';
31import { SmartDockStyleConfig } from '../config/SmartDockStyleConfig';
32import SmartDockConstants from '../common/constants/SmartDockConstants';
33import { SmartDockLayoutConfig } from '../config/SmartDockLayoutConfig';
34
35const TAG = 'SmartDockViewModel';
36
37/**
38 * SmartDock Viewmodel
39 */
40export default class SmartDockViewModel extends BaseViewModel {
41  private readonly mSmartDockLayoutConfig: SmartDockLayoutConfig;
42  private readonly mSmartDockStyleConfig: SmartDockStyleConfig;
43  private readonly mSmartDockDragHandler: SmartDockDragHandler;
44  private readonly mSmartDockStartAppHandler: SmartDockStartAppHandler;
45  private readonly mSmartDockModel: SmartDockModel;
46  private mSelectedItem: DockItemInfo;
47  private mSelectedDockType = 0;
48  private mDevice = CommonConstants.DEFAULT_DEVICE_TYPE;
49
50  constructor() {
51    super();
52    this.mSmartDockLayoutConfig = layoutConfigManager.getFunctionConfig(SmartDockLayoutConfig.SMART_DOCK_LAYOUT_INFO);
53    this.mSmartDockStyleConfig = layoutConfigManager.getStyleConfig(SmartDockStyleConfig.APP_LIST_STYLE_CONFIG, SmartDockConstants.FEATURE_NAME);
54    this.mSmartDockDragHandler = SmartDockDragHandler.getInstance();
55    this.mSmartDockStartAppHandler = SmartDockStartAppHandler.getInstance();
56    this.mSmartDockModel = SmartDockModel.getInstance();
57  }
58
59  static getInstance(): SmartDockViewModel{
60    if (globalThis.SmartDockViewModel == null) {
61      globalThis.SmartDockViewModel = new SmartDockViewModel();
62    }
63    return globalThis.SmartDockViewModel;
64  }
65
66  /**
67   * get SmartDockStyleConfig
68   */
69  getStyleConfig(): SmartDockStyleConfig{
70    return layoutConfigManager.getStyleConfig(SmartDockStyleConfig.APP_LIST_STYLE_CONFIG, SmartDockConstants.FEATURE_NAME);
71  }
72
73  /**
74   * resident dock item onClick function
75   * @param event
76   * @param item
77   * @param callback
78   */
79  residentOnClick(event, item, callback?) {
80    // AppCenter entry
81    AppStorage.SetOrCreate('startAppTypeFromPageDesktop', CommonConstants.OVERLAY_TYPE_APP_RESIDENTIAL);
82    if (item.abilityName == CommonConstants.APPCENTER_ABILITY && callback != null) {
83      callback();
84      return;
85    }
86    if (item.abilityName == CommonConstants.RECENT_ABILITY) {
87      globalThis.createWindowWithName(windowManager.RECENT_WINDOW_NAME, windowManager.RECENT_RANK);
88      Trace.start(Trace.CORE_METHOD_START_RECENTS);
89      return;
90    }
91    // app entry
92    Trace.start(Trace.CORE_METHOD_START_APP_ANIMATION);
93    this.setStartAppInfo(item);
94    launcherAbilityManager.startLauncherAbility(item.abilityName, item.bundleName, item.moduleName);
95  }
96
97  /**
98   * recent dock item onClick function
99   * @param event
100   * @param item
101   */
102  public recentOnClick(event, item, callback?) {
103    AppStorage.SetOrCreate('startAppTypeFromPageDesktop', CommonConstants.OVERLAY_TYPE_APP_RECENT);
104    let missionInfoList = [];
105    missionInfoList = AppStorage.Get('missionInfoList');
106    Log.showDebug(TAG, `recentOnClick missionInfoList.length: ${missionInfoList.length}`);
107    if (!CheckEmptyUtils.isEmptyArr(missionInfoList)) {
108      for (let i = 0; i < missionInfoList.length; i++) {
109        if (missionInfoList[i].bundleName === item.bundleName) {
110          let missionList = missionInfoList[i]?.missionInfoList;
111          Log.showDebug(TAG, 'recentOnClick missionList.length:' + missionList.length);
112          if (!CheckEmptyUtils.isEmptyArr(missionList) && missionList.length > 1) {
113            Log.showDebug(TAG, 'recentOnClick callback');
114            callback();
115          } else if (!CheckEmptyUtils.isEmptyArr(missionList) && missionList.length === 1) {
116            let missionId = missionInfoList[i]?.missionInfoList[0]?.missionId;
117            amsMissionManager.moveMissionToFront(missionId).then(() => {}, () => {});
118            // set start app info
119            Trace.start(Trace.CORE_METHOD_START_APP_ANIMATION);
120            this.setStartAppInfo(item);
121          }
122          break;
123        }
124      }
125    }
126  }
127
128  /**
129   * what SmartDockContent.dockItemList onChange
130   */
131  onDockListChange() {
132    this.updateDockParams().then(() => {}, () => {});
133  }
134
135  /**
136   * update drag effective area when dockList changed
137   */
138  async updateDockParams() {
139    const screenWidth: number = AppStorage.Get('screenWidth');
140    const screenHeight: number = AppStorage.Get('screenHeight');
141    const sysUIBottomHeight: number = AppStorage.Get('sysUIBottomHeight');
142    const dockHeight: number = AppStorage.Get('dockHeight');
143    let mResidentWidth: number = this.getListWidth(AppStorage.Get('residentList'));
144    if (AppStorage.Get("deviceType") === CommonConstants.DEFAULT_DEVICE_TYPE) {
145      const maxDockNum = this.getStyleConfig().mMaxDockNum;
146      mResidentWidth = this.mSmartDockStyleConfig.mDockPadding * 2 + maxDockNum * (this.mSmartDockStyleConfig.mListItemWidth) + (maxDockNum - 1) * (this.mSmartDockStyleConfig.mListItemGap);
147    }
148    AppStorage.SetOrCreate('residentWidth', mResidentWidth);
149    AppStorage.SetOrCreate("dockPadding", this.getDockPadding(mResidentWidth));
150    const mRecentWidth: number = this.getListWidth(AppStorage.Get('recentList'));
151    Log.showDebug(TAG, `updateDockParams screenWidth:${screenWidth}, screenHeight:${screenHeight}, sysUIBottomHeight:${sysUIBottomHeight}, dockHeight:${dockHeight}, mResidentWidth:${mResidentWidth}, mRecentWidth:${mRecentWidth}`);
152    if (typeof (this.mSmartDockDragHandler) != 'undefined') {
153      let left = mResidentWidth === 0 ? 0 : (screenWidth - mResidentWidth - (mRecentWidth === 0 ? 0 : (this.mSmartDockStyleConfig.mDockGap + mRecentWidth))) / 2;
154      let right = mResidentWidth === 0 ? screenWidth : (screenWidth - mResidentWidth - (mRecentWidth === 0 ? 0 : (this.mSmartDockStyleConfig.mDockGap + mRecentWidth))) / 2 + mResidentWidth;
155      if (AppStorage.Get('deviceType') == CommonConstants.DEFAULT_DEVICE_TYPE) {
156        left = (screenWidth - mResidentWidth) / 2;
157        right = screenWidth - left;
158      }
159      this.mSmartDockDragHandler.setDragEffectArea({
160        left: left,
161        right: right,
162        top: screenHeight - sysUIBottomHeight - dockHeight,
163        bottom: screenHeight - sysUIBottomHeight - this.mSmartDockStyleConfig.mMarginBottom
164      });
165    }
166  }
167
168  private getDockPadding(residentWidth: number): {right: number, left: number, top: number, bottom: number} {
169    let paddingNum: number = this.mSmartDockStyleConfig.mDockPadding;
170    const residentList: [] = AppStorage.Get('residentList');
171    if (AppStorage.Get("deviceType") === CommonConstants.DEFAULT_DEVICE_TYPE) {
172      paddingNum = (residentWidth - (residentList.length * this.mSmartDockStyleConfig.mListItemWidth + (residentList.length - 1) * (this.mSmartDockStyleConfig.mListItemGap))) / 2;
173    }
174    Log.showDebug(TAG, `getDockPadding paddingNum: ${paddingNum}`);
175    return {right: paddingNum, left: paddingNum, top: this.mSmartDockStyleConfig.mDockPadding, bottom: this.mSmartDockStyleConfig.mDockPadding};
176  }
177
178  /**
179   * build menu for @Component CustomOverlay
180   * @param appInfo
181   * @param dockType
182   * @param callback
183   */
184  buildMenuInfoList(appInfo, dockType, showAppcenter, callback?) {
185    const menuInfoList = new Array<MenuInfo>();
186    const shortcutInfo = this.mSmartDockModel.getShortcutInfo(appInfo.bundleName);
187    if (shortcutInfo) {
188      let menu = null;
189      shortcutInfo.forEach((value) => {
190        menu = new MenuInfo();
191        menu.menuType = CommonConstants.MENU_TYPE_DYNAMIC;
192        menu.menuImgSrc = value.icon;
193        menu.menuText = value.label;
194        menu.shortcutIconId = value.iconId;
195        menu.shortcutLabelId = value.labelId;
196        menu.bundleName = value.bundleName;
197        menu.moduleName = value.moduleName;
198        menu.onMenuClick = () => {
199          Trace.start(Trace.CORE_METHOD_START_APP_ANIMATION);
200          launcherAbilityManager.startLauncherAbility(value.wants[0].targetClass, value.wants[0].targetBundle, value.wants[0].targetModule);
201        };
202        value.bundleName == appInfo.bundleName && value.moduleName == appInfo.moduleName && menuInfoList.push(menu);
203      });
204    }
205
206    let open = new MenuInfo();
207    open.menuType = CommonConstants.MENU_TYPE_FIXED;
208    open.menuImgSrc = '/common/pics/ic_public_add_norm.svg';
209    open.menuText = $r('app.string.app_menu_open');
210    open.onMenuClick = () => {
211      this.residentOnClick(null, appInfo, showAppcenter);
212    };
213    menuInfoList.push(open);
214
215    if (appInfo.itemType != CommonConstants.TYPE_FUNCTION) {
216      this.mDevice = AppStorage.Get('deviceType');
217      if (this.mDevice === CommonConstants.PAD_DEVICE_TYPE && dockType === SmartDockConstants.RESIDENT_DOCK_TYPE) {
218        const addToWorkSpaceMenu = new MenuInfo();
219        addToWorkSpaceMenu.menuType = CommonConstants.MENU_TYPE_FIXED;
220        addToWorkSpaceMenu.menuImgSrc = '/common/pics/ic_public_copy.svg';
221        addToWorkSpaceMenu.menuText = $r('app.string.app_center_menu_add_desktop');
222        addToWorkSpaceMenu.onMenuClick = () => {
223          Log.showDebug(TAG, 'onMenuClick item add to pageDesk:' + appInfo.bundleName);
224          this.mSmartDockModel.addToPageDesk(appInfo);
225        };
226        menuInfoList.push(addToWorkSpaceMenu);
227      }
228
229      const removeMenu = new MenuInfo();
230      removeMenu.menuType = CommonConstants.MENU_TYPE_FIXED;
231      removeMenu.menuImgSrc = this.mDevice === CommonConstants.PAD_DEVICE_TYPE ? '/common/pics/ic_public_remove.svg' : '/common/pics/ic_public_delete.svg';
232      removeMenu.menuText = this.mDevice === CommonConstants.PAD_DEVICE_TYPE ? $r('app.string.delete_app') : $r('app.string.uninstall');
233      removeMenu.onMenuClick = () => {
234        Log.showDebug(TAG, `onMenuClick item remove: ${JSON.stringify(appInfo)}`);
235        const cacheKey = appInfo.appLabelId + appInfo.bundleName + appInfo.moduleName;
236        appInfo.keyName = appInfo.bundleName + appInfo.abilityName + appInfo.moduleName;
237        const appName = this.mSmartDockModel.getAppName(cacheKey);
238        Log.showDebug(TAG, `onMenuClick item remove appName: ${appName}`);
239        if (appName != null) {
240          appInfo.appName = appName;
241        }
242        this.mSelectedItem = appInfo;
243        this.mSelectedDockType = dockType;
244        AppStorage.SetOrCreate('uninstallAppInfo', appInfo);
245        callback();
246      };
247      removeMenu.menuEnabled = appInfo.isUninstallAble;
248      menuInfoList.push(removeMenu);
249    }
250    return menuInfoList;
251  }
252
253  deleteDockItem(dockItem: {bundleName: string | undefined, keyName: string | undefined}, dockType: number) {
254    this.mSmartDockModel.deleteDockItem(dockItem, dockType);
255  }
256
257  getSelectedItem(): any {
258    Log.showDebug(TAG, `getSelectedItem: ${JSON.stringify(this.mSelectedItem)}`);
259    return this.mSelectedItem;
260  }
261
262  getSelectedDockType(): any {
263    Log.showDebug(TAG, `getSelectedDockType: ${JSON.stringify(this.mSelectedDockType)}`);
264    return this.mSelectedDockType;
265  }
266
267  /**
268   * calcaulate dock list width after list change
269   * @param itemList
270   */
271  private getListWidth(itemList: []): number {
272    let width = 0;
273    if (typeof itemList === 'undefined' || itemList == null || itemList.length === 0) {
274      return width;
275    }
276    const num =  itemList.length;
277    width = this.mSmartDockStyleConfig.mDockPadding * 2 + num * (this.mSmartDockStyleConfig.mListItemWidth) + (num - 1) * (this.mSmartDockStyleConfig.mListItemGap);
278    return width;
279  }
280
281  /**
282   * get snapshot
283   *
284   * @param missionIds missionid list
285   * @return snapshot list
286   */
287  async getSnapshot(missionIds: MissionInfo[], name: string) {
288    const snapshotList: {
289      name: string,
290      image: any,
291      missionId: number,
292      boxSize: number,
293      bundleName: string,
294      left?: number,
295      right?: number,
296    }[] = await this.mSmartDockModel.getSnapshot(missionIds, name);
297    return snapshotList;
298  }
299
300  /**
301   * set start app info
302   */
303  private setStartAppInfo(item) {
304    if (CheckEmptyUtils.isEmpty(item)) {
305      Log.showError(TAG, `setStartAppInfo with item`)
306      return;
307    }
308    item.icon = globalThis.ResourceManager.getCachedAppIcon(item.appIconId, item.bundleName, item.moduleName)
309    AppStorage.SetOrCreate('startAppItemInfo', item);
310    this.mSmartDockStartAppHandler.setAppIconSize(this.mSmartDockStyleConfig.mIconSize);
311    this.mSmartDockStartAppHandler.setAppIconInfo();
312  }
313}