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