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