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  UninstallDialog,
18} from '@ohos/common/component'
19import {
20  Log,
21  CommonConstants,
22  ResourceManager,
23  RecentBundleMissionInfo, DockItemInfo,
24  MenuInfo } from '@ohos/common';
25import RecentLayout from './RecentLayout';
26import ResidentLayout from './ResidentLayout';
27import SmartDockViewModel from '../viewmodel/SmartDockViewModel';
28import SmartDockConstants from '../common/constants/SmartDockConstants';
29import { SmartDockStyleConfig } from '../config/SmartDockStyleConfig';
30
31const TAG = 'SmartDock';
32
33interface DockRecentPopup {
34  show: boolean;
35  showItem: string;
36  popup: CustomPopupOptions | null;
37}
38
39@Component
40export struct SmartDock {
41  popup: DockRecentPopup = { show: false, showItem: '', popup: null };
42  showAppCenter: () => void = () => {};
43  @StorageLink('showDock') showDock: boolean = false;
44  @StorageLink('recentList') recentList: Array<RecentBundleMissionInfo> = [];
45  @StorageLink('missionInfoList') missionInfoList: Array<RecentBundleMissionInfo> = [];
46  @StorageLink('desktopEventResponse') desktopEventResponse: boolean = true;
47  private deviceType: string = CommonConstants.DEFAULT_DEVICE_TYPE;
48  private mSmartDockViewModel?: SmartDockViewModel;
49  private mSelectedItem: DockItemInfo | null = null;
50  private mSelectedDockType = 0;
51  private dialogName = '';
52  @State mSmartDockStyleConfig: SmartDockStyleConfig | undefined = undefined;
53
54  aboutToAppear(): void {
55    Log.showInfo(TAG, 'aboutToAppear start!');
56    this.deviceType = AppStorage.get('deviceType') as string;
57    try {
58      this.mSmartDockViewModel = SmartDockViewModel.getInstance();
59      this.mSmartDockStyleConfig = this.mSmartDockViewModel.getStyleConfig() as SmartDockStyleConfig;
60    } catch (error) {
61      Log.showError(TAG, `catch error ${JSON.stringify(error)}`);
62    }
63    ResourceManager.getInstance().getStringByResource(this.deviceType === CommonConstants.PAD_DEVICE_TYPE
64      ? $r('app.string.is_delete_form') : $r('app.string.isUninstall')).then((resName) => {
65      this.dialogName = resName;
66    });
67  }
68
69  aboutToDisappear(): void {
70    Log.showInfo(TAG, 'aboutToDisappear!');
71    this.mDialogController = null;
72  }
73
74  private mDialogController: CustomDialogController | null = new CustomDialogController({
75    builder: UninstallDialog({
76      cancel: () => {
77        this.mDialogController?.close()
78      },
79      confirm: () => {
80        this.onConfirm()
81      },
82      dialogName: this.dialogName,
83      dialogContent: this.mSelectedItem?.appName + ' ?',
84    }),
85    cancel: () => {
86    },
87    autoCancel: false,
88    customStyle: true
89  });
90
91  onConfirm() {
92    if (this.mSelectedItem == null || this.mSelectedDockType == null) {
93      Log.showDebug(TAG, 'onConfirm click menu item null!');
94      return;
95    }
96    if (this.deviceType === CommonConstants.PAD_DEVICE_TYPE) {
97      this.mSmartDockViewModel?.deleteDockItem({
98        bundleName: undefined,
99        keyName: this.mSelectedItem?.keyName
100      } as DockItemInfo, this.mSelectedDockType);
101    } else {
102      this.mSmartDockViewModel?.uninstallApp(this.mSelectedItem?.bundleName, this.mSelectedItem?.isUninstallAble);
103    }
104    this.mDialogController?.close();
105  }
106
107  showDialog = () => {
108    this.mSelectedItem = this.mSmartDockViewModel?.getSelectedItem() as DockItemInfo | null;
109    this.mSelectedDockType = this.mSmartDockViewModel?.getSelectedDockType() as number;
110    this.mDialogController?.open();
111  }
112
113  async onHoverEvent(onHover: boolean, bundleName?: string) {
114    if (!onHover || !bundleName) {
115      this.popup = { show: false, showItem: '', popup: null };
116      return;
117    }
118
119    let list = this.missionInfoList.filter(it => it.bundleName == bundleName);
120    if (list.length <= 0) {
121      AppStorage.setOrCreate('snapshotList', []);
122      AppStorage.setOrCreate('snapShotWidth', 0);
123      this.popup = { show: false, showItem: '', popup: null };
124      return;
125    }
126    this.popup = {
127      show: true,
128      showItem: bundleName,
129      popup: {
130        builder: () => {},
131        placement: Placement.Top,
132        enableArrow: true
133      }
134    }
135    await this.mSmartDockViewModel?.getSnapshot(list[0].missionInfoList, list[0].appName);
136  }
137
138  private buildLog(): boolean {
139    Log.showDebug(TAG, 'SmartDock buildLog');
140    return true;
141  }
142
143  build() {
144    List({
145      space: this.deviceType ==
146      CommonConstants.DEFAULT_DEVICE_TYPE || this.recentList.length == 0 ? CommonConstants.DOCK_SPACE :
147        (this.mSmartDockViewModel?.getStyleConfig().mDockGap as number)
148    }) {
149      if (this.buildLog()) {
150      }
151      ListItem() {
152        ResidentLayout({
153          mSmartDockStyleConfig: $mSmartDockStyleConfig,
154          onItemClick: (event: ClickEvent, item: DockItemInfo) => {
155            this.mSmartDockViewModel?.residentOnClick(event, item, this.showAppCenter);
156          },
157          buildMenu: (item: DockItemInfo): MenuInfo[] => {
158            return this.mSmartDockViewModel?.buildMenuInfoList(item, SmartDockConstants.RESIDENT_DOCK_TYPE,
159              this.showAppCenter, this.showDialog) as MenuInfo[];
160          },
161          onDockListChangeFunc: () => {
162            this.mSmartDockViewModel?.onDockListChange();
163          },
164        })
165      }
166
167      ListItem() {
168        RecentLayout({
169          appList: $recentList,
170          mSmartDockStyleConfig: $mSmartDockStyleConfig,
171          onItemClick: (event: ClickEvent, item: DockItemInfo) => {
172            this.mSmartDockViewModel?.recentOnClick(event, item, () => {
173              this.recentOnClickWithPopup(item);
174            })
175          },
176          buildMenu: (item: DockItemInfo): MenuInfo[] => {
177            return this.mSmartDockViewModel?.buildMenuInfoList(item, SmartDockConstants.RECENT_DOCK_TYPE,
178              this.showAppCenter, this.showDialog) as MenuInfo[];
179          },
180          onDockListChangeFunc: () => {
181            this.mSmartDockViewModel?.onDockListChange();
182          },
183          popup: this.popup,
184          onHoverEvent: (onHover: boolean, bundleName: string) => {
185            this.onHoverEvent(onHover, bundleName);
186          }
187        })
188      }
189    }
190    .enableScrollInteraction(false)
191    .scrollBar(BarState.Off)
192    .hitTestBehavior(this.desktopEventResponse ? HitTestMode.Default : HitTestMode.Block)
193    .alignListItem(ListItemAlign.Center)
194    .height(SmartDockConstants.PERCENTAGE_100)
195    .listDirection(Axis[SmartDockConstants.LIST_DIRECTION])
196  }
197
198  recentOnClickWithPopup(item: DockItemInfo) {
199    this.onHoverEvent(true, item.bundleName);
200    AppStorage.setOrCreate('recentShowPopup', true);
201  }
202}