• 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 '../utils/Log';
17import { SettingsModel } from '../model/SettingsModel';
18import { StyleConstants } from '../constants/StyleConstants';
19import { CommonConstants } from '../constants/CommonConstants';
20import { ResourceManager } from '../manager/ResourceManager';
21import { PresetStyleConstants } from '../constants/PresetStyleConstants';
22import { AppIcon } from './AppIcon';
23import { AppName } from './AppName';
24import { AppMenu } from './AppMenu';
25
26const TAG = 'FolderComponent';
27
28@Component
29export struct FolderComponent {
30  @StorageLink('openFolderStatus') @Watch('updateFolderAnimate') openFolderStatus: number = 1;
31  @State folderAnimateData: {
32    folderId: string,
33    isOpenFolder: boolean,
34  } = { folderId: '', isOpenFolder: false };
35  @State folderPositionX: number = 0;
36  @State folderPositionY: number = 0;
37  @State folderItemPositionX: number = 0;
38  @State folderItemPositionY: number = 0;
39  @State animateFolderPositionX: number = 0;
40  @State animateFolderPositionY: number = 0;
41  @State animateOpacity: number = 1.0;
42  @State animateScale: number = 1.0;
43  @State showFolderName: boolean = true;
44  @State folderNameHeight: number = 0;
45  @State folderNameSize: number = 0;
46  @State nameFontColor: string = '';
47  @State appIconSize: number = 0;
48  @State superposeIconVisible: boolean = false;
49  @State isHover: boolean = false;
50  mPaddingTop: number = StyleConstants.DEFAULT_10;
51  folderGridSize: number = StyleConstants.DEFAULT_FOLDER_GRID_SIZE;
52  gridMargin: number = StyleConstants.DEFAULT_FOLDER_GRID_MARGIN;
53  gridGap: number = StyleConstants.DEFAULT_FOLDER_GRID_GAP;
54  badgeNumber: number = 0;
55  private mSettingsModel: SettingsModel;
56  private isPad: boolean = false;
57  private mFolderItem: any;
58  private mShowAppList: any = [];
59  private mSuperposeAppList: any = [];
60  onAppIconClick?: Function = null;
61  onOpenFolderClick?: Function = null;
62  onFolderTouch?: Function = null;
63  onGetPosition?: Function = null;
64  buildMenu: Function = null;
65  folderNameLines: number = PresetStyleConstants.DEFAULT_APP_NAME_LINES;
66  iconNameMargin: number = PresetStyleConstants.DEFAULT_ICON_NAME_GAP;
67  isSelect?: boolean;
68  dragStart: Function;
69
70  aboutToAppear(): void  {
71    Log.showInfo(TAG, `aboutToAppear start`);
72    this.updateShowList();
73    this.mSettingsModel = SettingsModel.getInstance();
74    if (this.mSettingsModel.getDevice() != "phone") {
75      this.isPad = true;
76    }
77  }
78
79  aboutToDisappear(): void {
80    this.onAppIconClick = null;
81    this.onOpenFolderClick = null;
82    this.onFolderTouch = null;
83    this.onGetPosition = null;
84    this.buildMenu = null;
85    this.dragStart = null;
86  }
87
88  updateShowList(): void {
89    if (this.mFolderItem.layoutInfo[0].length > CommonConstants.FOLDER_STATIC_SHOW_LENGTH) {
90      this.mShowAppList = this.mFolderItem.layoutInfo[0].slice(0, CommonConstants.FOLDER_STATIC_SHOW_LENGTH);
91    } else {
92      this.mShowAppList = this.mFolderItem.layoutInfo[0];
93    }
94
95    let showLength = CommonConstants.FOLDER_STATIC_SHOW_LENGTH - CommonConstants.FOLDER_STATIC_SUPERPOSEAPP_LENGTH;
96    if (this.mShowAppList.length > showLength) {
97      this.mSuperposeAppList = this.mShowAppList.slice(showLength);
98      this.mShowAppList = this.mShowAppList.slice(0, showLength);
99      this.superposeIconVisible = true;
100    }
101
102    let length = this.mSuperposeAppList.length;
103    if (length > CommonConstants.FOLDER_STATIC_SUPERPOSEAPP_LENGTH) {
104      this.mSuperposeAppList = this.mSuperposeAppList.slice(0, CommonConstants.FOLDER_STATIC_SUPERPOSEAPP_LENGTH);
105    } else {
106      for (let i = 0; i < (CommonConstants.FOLDER_STATIC_SUPERPOSEAPP_LENGTH - length); i++) {
107        this.mSuperposeAppList.push({ 'isEmpty': true });
108      }
109    }
110    this.mSuperposeAppList = this.mSuperposeAppList.reverse();
111    this.mSuperposeAppList[0].alignContent = Alignment.TopStart;
112    this.mSuperposeAppList[1].alignContent = Alignment.Center;
113    this.mSuperposeAppList[2].alignContent = Alignment.BottomEnd;
114
115    Log.showInfo(TAG, `superposeIconVisible:${this.superposeIconVisible}`);
116    Log.showInfo(TAG, `FolderItem.layoutInfo[0].length:${this.mFolderItem.layoutInfo[0].length}`);
117    Log.showInfo(TAG, `SuperposeAppList length:${this.mSuperposeAppList.length}`);
118  }
119
120  @Builder MenuBuilder() {
121    Column() {
122      AppMenu({
123        menuInfoList: this.buildMenu(this.mFolderItem),
124      })
125    }
126    .alignItems(HorizontalAlign.Center)
127    .justifyContent(FlexAlign.Center)
128    .width(StyleConstants.CONTEXT_MENU_WIDTH)
129  }
130
131  private updateFolderAnimate() {
132    Log.showInfo(TAG, `updateFolderAnimate start`);
133    if (this.openFolderStatus == 0) {
134      this.folderAnimateData = AppStorage.Get('folderAnimateData');
135      if (this.mFolderItem.folderId === this.folderAnimateData.folderId &&
136      this.folderAnimateData.isOpenFolder &&
137      this.folderAnimateData.folderId != '' &&
138      this.animateOpacity != 1.0 &&
139      this.animateScale != 1.0) {
140        this.folderAnimateData.isOpenFolder = false;
141        AppStorage.SetOrCreate('folderAnimateData', this.folderAnimateData);
142        Log.showInfo(TAG, `updateFolderAnimate show`);
143        this.showAnimate(1.0, 1.0, false);
144      }
145    }
146  }
147
148  private showAnimate(animateScale: number, animateOpacity: number, isMoveFolder: boolean) {
149    let positionX = 0;
150    let positionY = 0;
151    if (this.onGetPosition) {
152      this.onGetPosition(this.getPosition.bind(this));
153      if (isMoveFolder) {
154        positionX = this.animateFolderPositionX;
155        positionY = this.animateFolderPositionY;
156      }
157    }
158    animateTo({
159      duration: 250,
160      tempo: 0.5,
161      curve: Curve.Friction,
162      delay: 0,
163      iterations: 1,
164      playMode: PlayMode.Normal,
165      onFinish: () => {
166        Log.showInfo(TAG, ` onFinish x: ${this.folderPositionX}, y: ${this.folderPositionY}`);
167      }
168    }, () => {
169      this.animateScale = animateScale;
170      this.animateOpacity = animateOpacity;
171      this.folderPositionX = positionX;
172      this.folderPositionY = positionY;
173    })
174  }
175
176  public getPosition(x: number, y: number): void  {
177    this.folderItemPositionX = x;
178    this.folderItemPositionY = y;
179    let screenWidth: number = AppStorage.Get('screenWidth');
180    let screenHeight: number = AppStorage.Get('screenHeight');
181    this.animateFolderPositionX = (screenWidth - this.folderGridSize * 1.5) / 2 - this.folderItemPositionX;
182    this.animateFolderPositionY = (screenHeight - this.folderGridSize * 1.5) / 2 - this.folderItemPositionY;
183    Log.showInfo(TAG, `getPosition animatePosition x: ${this.animateFolderPositionX}, y: ${this.animateFolderPositionY}`);
184  }
185
186  build() {
187    Column() {
188      Column() {
189        Badge({
190          count: this.badgeNumber,
191          maxCount: StyleConstants.MAX_BADGE_COUNT,
192          style: {
193            color: StyleConstants.DEFAULT_FONT_COLOR,
194            fontSize: StyleConstants.DEFAULT_BADGE_FONT_SIZE,
195            badgeSize: (this.badgeNumber > 0 ? StyleConstants.DEFAULT_BADGE_SIZE : 0),
196            badgeColor: Color.Red,
197          }
198        }) {
199          Stack() {
200            Column() {
201            }
202            .backgroundColor(Color.White)
203            .borderRadius(24)
204            .opacity(0.5)
205            .height(this.folderGridSize)
206            .width(this.folderGridSize)
207
208            Grid() {
209              ForEach(this.mShowAppList, (item) => {
210                GridItem() {
211                  AppIcon({
212                    iconSize: this.appIconSize,
213                    iconId: item.appIconId,
214                    icon: ResourceManager.getInstance().getCachedAppIcon(item.appIconId, item.bundleName, item.moduleName),
215                    bundleName: item.bundleName,
216                    moduleName: item.moduleName,
217                    badgeNumber: item.badgeNumber
218                  })
219                }
220                .height(StyleConstants.PERCENTAGE_100)
221                .width(StyleConstants.PERCENTAGE_100)
222                .onClick((event: ClickEvent) => {
223                  if (this.onAppIconClick) {
224                    this.onAppIconClick(event, item);
225                  }
226                })
227              }, (item) => JSON.stringify(item))
228
229              if (this.mSuperposeAppList.length > 0) {
230                GridItem() {
231                  Stack() {
232                    ForEach(this.mSuperposeAppList, (item) => {
233                      Stack({ alignContent: item.alignContent }) {
234                        if (item.isEmpty) {
235                          Column() {
236                            Column() {
237                            }
238                            .backgroundColor(Color.White)
239                            .borderRadius(10)
240                            .opacity(0.5)
241                            .width(StyleConstants.PERCENTAGE_100)
242                            .height(StyleConstants.PERCENTAGE_100)
243                          }
244                          .alignItems(HorizontalAlign.Start)
245                          .width(StyleConstants.PERCENTAGE_80)
246                          .height(StyleConstants.PERCENTAGE_80)
247                        } else {
248                          Column() {
249                            AppIcon({
250                              iconSize: this.appIconSize * StyleConstants.PERCENTAGE_80_number,
251                              iconId: item.appIconId,
252                              icon: ResourceManager.getInstance().getCachedAppIcon(item.appIconId, item.bundleName, item.moduleName),
253                              bundleName: item.bundleName,
254                              moduleName: item.moduleName,
255                              badgeNumber: item.badgeNumber
256                            })
257                          }
258                          .width(StyleConstants.PERCENTAGE_80)
259                          .height(StyleConstants.PERCENTAGE_80)
260                          .alignItems(HorizontalAlign.Start)
261                        }
262                      }
263                      .width(StyleConstants.PERCENTAGE_100)
264                      .height(StyleConstants.PERCENTAGE_100)
265                    }, (item) => JSON.stringify(item))
266                  }
267                  .width(this.isPad ?
268                    StyleConstants.DEFAULT_FOLDER_APP_ITEM_WIDTH_SMALL :
269                    StyleConstants.DEFAULT_FOLDER_APP_ITEM_WIDTH)
270                  .height(this.isPad ?
271                    StyleConstants.DEFAULT_FOLDER_APP_ITEM_WIDTH_SMALL :
272                    StyleConstants.DEFAULT_FOLDER_APP_ITEM_WIDTH)
273                }
274                .visibility(this.superposeIconVisible ? Visibility.Visible : Visibility.Hidden)
275                .width(StyleConstants.PERCENTAGE_100)
276                .height(StyleConstants.PERCENTAGE_100)
277                .onClick((event: ClickEvent) => {
278                  Log.showInfo(TAG, `last item onClick`);
279                  this.showAnimate(1.5, 0, true);
280                  if (this.onOpenFolderClick) {
281                    this.folderAnimateData.folderId = this.mFolderItem.folderId;
282                    this.folderAnimateData.isOpenFolder = true;
283                    AppStorage.SetOrCreate('folderAnimateData', this.folderAnimateData);
284                    this.onOpenFolderClick(event, this.mFolderItem);
285                  }
286                })
287              }
288            }
289            .onDragStart((event: DragEvent) => {
290              return this.dragStart(event);
291            })
292            .bindContextMenu(this.MenuBuilder, ResponseType.LongPress)
293            .bindContextMenu(this.MenuBuilder, ResponseType.RightClick)
294            .padding(this.gridMargin)
295            .columnsTemplate('1fr 1fr 1fr')
296            .rowsTemplate('1fr 1fr 1fr')
297            .columnsGap(this.gridGap)
298            .rowsGap(this.gridGap)
299            .onClick((event: ClickEvent) => {
300              Log.showInfo(TAG, `grid onClick`);
301              this.showAnimate(1.5, 0, true);
302              if (this.onOpenFolderClick) {
303                this.folderAnimateData.folderId = this.mFolderItem.folderId;
304                this.folderAnimateData.isOpenFolder = true;
305                AppStorage.SetOrCreate('folderAnimateData', this.folderAnimateData);
306                this.onOpenFolderClick(event, this.mFolderItem);
307              }
308            })
309            .onTouch((event: TouchEvent) => {
310              Log.showInfo(TAG, "onTouch start");
311              if (this.onFolderTouch) {
312                this.onFolderTouch(event, this.mFolderItem);
313              }
314              Log.showInfo(TAG, "onTouch end");
315            })
316          }
317          .height(StyleConstants.PERCENTAGE_100)
318          .width(StyleConstants.PERCENTAGE_100)
319          .onHover((isHover: boolean) => {
320            Log.showInfo(TAG, `onHover isHover:${isHover}`);
321            this.isHover = isHover;
322          })
323        }
324        .height(this.folderGridSize)
325        .width(this.folderGridSize)
326
327        Column() {
328          AppName({
329            nameHeight: this.folderNameHeight,
330            nameSize: this.folderNameSize,
331            nameFontColor: this.nameFontColor,
332            appName: this.mFolderItem.folderName,
333            nameLines: this.folderNameLines,
334            marginTop: this.iconNameMargin
335          })
336        }
337        .visibility(this.showFolderName ? Visibility.Visible : Visibility.Hidden)
338      }
339      .width(StyleConstants.PERCENTAGE_100)
340      .height(StyleConstants.PERCENTAGE_100)
341      .offset({ x: this.folderPositionX, y: this.folderPositionY })
342      .scale({ x: this.isHover ? 1.05 : this.animateScale, y: this.isHover ? 1.05 : this.animateScale })
343      .opacity(this.animateOpacity)
344    }
345    .width(this.isSelect ? this.folderGridSize + StyleConstants.DEFAULT_40 : StyleConstants.PERCENTAGE_100)
346    .height(this.isSelect ? this.folderGridSize + StyleConstants.DEFAULT_40 : StyleConstants.PERCENTAGE_100)
347    .backgroundColor(this.isSelect ? StyleConstants.DEFAULT_BROAD_COLOR : StyleConstants.DEFAULT_TRANSPARENT_COLOR)
348    .borderRadius(this.isSelect ? StyleConstants.DEFAULT_15 : StyleConstants.DEFAULT_0)
349    .padding(this.isSelect ? { left: StyleConstants.DEFAULT_20,
350                               right: StyleConstants.DEFAULT_20, top: this.mPaddingTop + StyleConstants.DEFAULT_10 } : { top: this.mPaddingTop })
351  }
352}