• 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 { AppMenu } from '@ohos/common';
17import { AppIcon } from '@ohos/common';
18import { DockItemInfo } from '@ohos/common';
19import { ScrollerComponent } from '@ohos/common';
20import { CommonConstants } from '@ohos/common';
21import { StyleConstants } from '@ohos/common';
22import { ResourceManager } from '@ohos/common';
23import { Log } from '@ohos/common';
24import { SmartDockStyleConfig } from '../config/SmartDockStyleConfig';
25
26let mSmartDockStyleConfig: SmartDockStyleConfig = null;
27const TAG = 'RecentLayout';
28
29@Component
30export default struct RecentLayout {
31  @StorageLink('sysUiRecentOnClickEvent') @Watch('sysUiRecentOnClick') sysUiRecentOnClickEvent: number = 0;
32  @StorageLink('dockPadding') dockPadding: {right: number, left: number, top: number, bottom: number} = {right: 0, left: 0, top: 0, bottom: 0};
33  @State isHover: boolean = false;
34  @State showPopup: boolean = false;
35  @State onHoverItem: string = '';
36  @Link @Watch('onDockListChange') appList: Array<DockItemInfo>;
37  mRecentMaxNum: number;
38  mSmartDockStyleConfig: SmartDockStyleConfig;
39  onItemClick: Function = null;
40  buildMenu: Function = null;
41  onHoverEvent: Function = null;
42  onDockListChangeFunc: Function = null;
43  isScrollHover: boolean = false;
44  popup: {
45    show: boolean,
46    showItem: string,
47    popup
48  } = { show: false, showItem: '', popup: null };
49  onClickWithPopup: boolean = false;
50  autoCancel: boolean = false;
51  private updateData: Function = null;
52
53  aboutToAppear(): void {
54
55    mSmartDockStyleConfig = this.mSmartDockStyleConfig;
56  }
57
58  private sysUiRecentOnClick() {
59    this.showPopup = false;
60    this.popup = { show: false, showItem: '', popup: null };
61  }
62
63  @Builder popupBuilder() {
64    Column() {
65      ScrollerComponent({
66        popupHide: () => {
67          this.showPopup = false;
68          this.popup = { show: false, showItem: '', popup: null };
69        },
70        updateData: (show, bundleName, callback) => {
71          this.updateData = () => {
72            callback();
73            setTimeout(() => {
74              this.onHoverEvent(true, bundleName);
75            }, 100)
76          }
77          if (show) {
78            this.updateData();
79            this.getShowPopup();
80            return;
81          }
82          this.showPopup = false;
83          this.popup = { show: false, showItem: '', popup: null };
84        }
85      })
86    }.onHover((isScrollHover: boolean) => {
87      this.autoCancel = false;
88      if (isScrollHover) {
89        this.isScrollHover = true;
90      } else {
91        this.isScrollHover = false;
92      }
93      this.getShowPopup();
94    })
95    .onClick(() => {
96      this.getShowPopup();
97    })
98  }
99
100  async getShowPopup() {
101    await this.delay(500);
102    if (this.popup.show || this.isScrollHover) {
103      this.showPopup = true;
104    } else {
105      this.showPopup = false;
106    }
107    return this.showPopup;
108  }
109
110  delay(ms: number) {
111    return new Promise(resolve => setTimeout(resolve, ms));
112  }
113
114  build() {
115    List({ space: mSmartDockStyleConfig.mListItemGap }) {
116      ForEach(this.appList, (item) => {
117        ListItem() {
118          AppItem({
119            appInfo: item,
120            buildMenu: this.buildMenu
121          })
122        }
123        .bindPopup(this.showPopup && item.bundleName == this.onHoverItem && !AppStorage.Get('smartDockShowMenu') as boolean, {
124          builder: this.popupBuilder,
125          placement: Placement.Top,
126          enableArrow: true,
127          autoCancel: this.autoCancel,
128          maskColor: ('rgba(250,250,250,0)'),
129          popupColor: ('rgba(250,250,250,0.6)'),
130          onStateChange: (e) => {
131            if (!e.isVisible && this.autoCancel) {
132              this.popup = { show: false, showItem: '', popup: null };
133              this.onHoverItem = '';
134              this.onClickWithPopup = false;
135              this.autoCancel = false;
136              this.showPopup = false;
137              AppStorage.SetOrCreate('snapshotList', []);
138              AppStorage.SetOrCreate('recentShowPopup', false);
139            }
140            if (this.updateData) {
141              this.updateData();
142              this.updateData = () => {
143              }
144            }
145          },
146        })
147        .onHover((isHover) => {
148          this.autoCancel = false;
149          if (this.onHoverEvent) {
150            this.onHoverEvent(isHover, item.bundleName);
151            this.onHoverItem = item.bundleName;
152            this.getShowPopup();
153          }
154        })
155        .onClick((event: ClickEvent) => {
156          this.onItemClick(event, item);
157          this.onClickWithPopup = AppStorage.Get('recentShowPopup');
158          Log.showInfo(TAG, `onClick this.onClickWithPopup: ${this.onClickWithPopup}`);
159          if (this.onClickWithPopup) {
160            this.autoCancel = true;
161            this.showPopup = true
162            this.onHoverItem = item.bundleName;
163          }
164          AppStorage.SetOrCreate('recentShowPopup', false);
165        })
166      }, (item) => JSON.stringify(item))
167    }
168    .padding(this.dockPadding)
169    .width(this.getListWidth())
170    .height(this.mSmartDockStyleConfig.mDockHeight)
171    .backgroundColor(this.mSmartDockStyleConfig.mBackgroundColor)
172    .borderRadius(this.mSmartDockStyleConfig.mDockRadius)
173    .backdropBlur(this.mSmartDockStyleConfig.mBackdropBlur)
174    .visibility(this.getListWidth() === 0 ? Visibility.None : Visibility.Visible)
175    .listDirection(this.mSmartDockStyleConfig.mListDirection)
176  }
177
178  getListWidth(): number {
179    let mRecentMaxNum = this.mSmartDockStyleConfig.mMaxRecentNum;
180    let width = 0;
181    if (AppStorage.Get("deviceType") == CommonConstants.DEFAULT_DEVICE_TYPE) {
182      return width;
183    }
184    if (typeof this.appList === 'undefined' || this.appList == null || this.appList.length === 0) {
185      return width;
186    }
187    let num = this.appList.length;
188    if (num > mRecentMaxNum) {
189      num = mRecentMaxNum;
190    }
191    width = this.mSmartDockStyleConfig.mDockPadding * 2 + num * (this.mSmartDockStyleConfig.mListItemWidth) + (num - 1) * (this.mSmartDockStyleConfig.mListItemGap);
192    return width;
193  }
194
195  private onDockListChange() {
196    this.onDockListChangeFunc();
197  }
198}
199
200@Component
201struct AppItem {
202  @State isShow: boolean = false;
203  appInfo: DockItemInfo = null;
204  buildMenu: Function = null;
205  private menuInfo;
206
207  aboutToAppear(): void {
208    this.menuInfo = this.buildMenu(this.appInfo);
209  }
210
211  private getLongPress(): boolean {
212    return AppStorage.Get('isLongPress');
213  }
214
215  @Builder MenuBuilder() {
216    Column() {
217      AppMenu({
218        menuInfoList: this.menuInfo,
219        closeMenu: () => {
220          this.isShow = false;
221        }
222      })
223    }
224    .alignItems(HorizontalAlign.Center)
225    .justifyContent(FlexAlign.Center)
226    .width(StyleConstants.CONTEXT_MENU_WIDTH)
227    .height(StyleConstants.DEFAULT_40 * this.menuInfo.length + StyleConstants.DEFAULT_8)
228  }
229
230  build() {
231    Column() {
232      Row() {
233        AppIcon({
234          iconSize: mSmartDockStyleConfig.mIconSize,
235          iconId: this.appInfo.appIconId,
236          bundleName: this.appInfo.bundleName,
237          moduleName: this.appInfo.moduleName,
238          icon: ResourceManager.getInstance().getCachedAppIcon(this.appInfo.appIconId,
239            this.appInfo.bundleName, this.appInfo.moduleName),
240          badgeNumber: this.appInfo.badgeNumber
241        })
242      }
243      .width(mSmartDockStyleConfig.mListItemWidth)
244      .height(mSmartDockStyleConfig.mListItemHeight)
245      .backgroundColor(mSmartDockStyleConfig.mItemBackgroundColor)
246      .borderRadius(mSmartDockStyleConfig.mItemBorderRadius)
247    }
248    .gesture(
249    LongPressGesture({ repeat: false })
250      .onAction((event: GestureEvent) => {
251        this.isShow = true;
252        AppStorage.SetOrCreate('isLongPress', true);
253      })
254    )
255    .bindPopup(this.isShow, {
256      builder: this.MenuBuilder,
257      placement: Placement.Top,
258      popupColor: Color.White,
259      //@ts-ignore
260      arrowOffset: 3 * (mSmartDockStyleConfig.mIconSize / 2) + mSmartDockStyleConfig.mListItemGap,
261      onStateChange: (e) => {
262        if (!e.isVisible) {
263          this.isShow = false;
264        }
265        AppStorage.SetOrCreate('smartDockShowMenu', e.isVisible)
266      },
267      autoCancel: true
268    })
269    .onTouch((event: TouchEvent) => {
270      if (event.type == CommonConstants.TOUCH_TYPE_UP) {
271        AppStorage.SetOrCreate('isLongPress', false);
272      }
273      if (AppStorage.Get('isDrag')) {
274        this.isShow = false;
275      }
276    })
277    .onMouse((event: MouseEvent) => {
278      Log.showInfo(TAG, `onMouse MouseType: ${event.button}`);
279      if (event.button == MouseButton.Right) {
280        event.stopPropagation();
281        AppStorage.SetOrCreate('selectDesktopAppItem', '');
282        this.isShow = true;
283      }
284    })
285  }
286}