• 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 */
15import image from '@ohos.multimedia.image';
16import {
17  EventConstants,
18  localEventManager,
19  Log,
20  Trace,
21  CheckEmptyUtils,
22  windowManager,
23  SnapShotInfo,
24  CommonConstants
25} from '@ohos/common';
26import RecentMissionAppIcon from './RecentMissionAppIcon';
27import RecentMissionAppName from './RecentMissionAppName';
28import { RecentMissionsViewModel } from '../../viewmodel/RecentMissionsViewModel';
29import { RecentsStyleConstants } from '../../common/constants/RecentsStyleConstants';
30import { RecentMissionStartAppHandler } from './../RecentMissionStartAppHandler';
31
32const TAG = 'Recent-RecentMissionCard';
33
34/**
35 * Common card component for recent missions.
36 */
37@Component
38export default struct RecentMissionCard {
39  @Link isClickSubComponent: boolean;
40  @State missionId: number = 0;
41  @State appIconId: number = 0;
42  @State appLabelId: number = 0;
43  @State appName: string = '';
44  @State bundleName: string = '';
45  @State moduleName: string = '';
46  @State abilityName: string = '';
47  @State lockedState: boolean = false;
48  @State cardMargin: number = RecentsStyleConstants.SINGLE_LIST_LAYOUT_MARGIN;
49  @State cardLayoutWeight: number = RecentsStyleConstants.SINGLE_LIST_APP_INFO_LAYOUT_WEIGHT;
50  // recentImage default is Resource type, to avoid toolchain typeCheck
51  @State recentImage: image.PixelMap = undefined;
52  private mIsSingleLayout: boolean = true;
53  private snapShotTime: string = '';
54  private mRecentMissionsViewModel: RecentMissionsViewModel;
55  private mRecentMissionStartAppHandler: RecentMissionStartAppHandler;
56  private mReleaseFlag = true;
57
58  aboutToAppear(): void {
59    Log.showInfo(TAG, 'aboutToAppear start');
60    // remove this if toolchain fix requireNApi bug
61    this.mReleaseFlag = false;
62    this.mRecentMissionsViewModel = RecentMissionsViewModel.getInstance();
63    this.mIsSingleLayout = this.mRecentMissionsViewModel.getRecentMissionsRowType() === 'single' ? true : false;
64    this.cardMargin = this.mRecentMissionsViewModel.getRecentMissionsRowType() === 'single' ?
65      RecentsStyleConstants.SINGLE_LIST_LAYOUT_MARGIN * RecentsStyleConstants.DPI_RATIO : RecentsStyleConstants.DOUBLE_LIST_LAYOUT_MARGIN;
66    this.cardLayoutWeight = this.mRecentMissionsViewModel.getRecentMissionsRowType() === 'single' ?
67      RecentsStyleConstants.SINGLE_LIST_APP_INFO_LAYOUT_WEIGHT : RecentsStyleConstants.DOUBLE_LIST_APP_INFO_LAYOUT_WEIGHT;
68    this.mRecentMissionsViewModel.getMissionSnapShot(this.missionId, this.recentMissionsSnapshotCallback.bind(this));
69    this.mRecentMissionStartAppHandler = RecentMissionStartAppHandler.getInstance();
70  }
71
72  aboutToDisappear(): void {
73    Log.showInfo(TAG, `aboutToDisappear start ${this.missionId}`);
74    Log.showDebug(TAG, `typeof this.recentImage ${typeof this.recentImage}`);
75    this.mReleaseFlag = true;
76    // typeof Resource or pixelMap is Object
77    if (!CheckEmptyUtils.isEmpty(this.recentImage)) {
78      this.recentImage.release().catch((err) => {
79        Log.showError(TAG, `image.PixelMap release err: ${err}`);
80      })
81      Log.showInfo(TAG, `aboutToDisappear end ${this.missionId}`);
82    }
83  }
84
85  /**
86 * The callback of Recent missions snapshot.
87 *
88 * @param {number} missionId
89 * @param {any} snapShotInfo
90 */
91  recentMissionsSnapshotCallback(missionId: number, snapShotInfo: SnapShotInfo): void {
92    Log.showDebug(TAG, `recentMissionsSnapshotCallback missionId: ${this.missionId}`);
93    if (!this.mReleaseFlag && missionId === this.missionId) {
94      this.recentImage = snapShotInfo.snapShotImage;
95      let width = snapShotInfo.snapShotImageWidth;
96      let height = snapShotInfo.snapShotImageHeight;
97      Log.showDebug(TAG, `recentMissionsSnapshotCallback recentImage: ${JSON.stringify(this.recentImage)},
98        width: ${JSON.stringify(width)}, height: ${JSON.stringify(height)}`);
99    } else {
100      snapShotInfo.snapShotImage.release().catch((err) => {
101        Log.showError(TAG, `image.PixelMap release err :${err}`)
102      })
103    }
104  }
105
106  build() {
107    Column() {
108      Row() {
109        Row() {
110          RecentMissionAppIcon({
111            iconSize: this.mIsSingleLayout ?
112              RecentsStyleConstants.SINGLE_LIST_DEFAULT_APP_ICON_SIZE * RecentsStyleConstants.DPI_RATIO :
113              RecentsStyleConstants.DOUBLE_LIST_DEFAULT_APP_ICON_SIZE,
114            appIcon: this.appIconId,
115            bundleName: this.bundleName,
116            moduleName: this.moduleName,
117            labelId: this.appLabelId,
118            useCache: false
119          })
120          RecentMissionAppName({
121            appName: this.appName,
122            nameSize: this.mIsSingleLayout ?
123              RecentsStyleConstants.DEFAULT_APP_NAME_SIZE * RecentsStyleConstants.DPI_RATIO :
124              RecentsStyleConstants.DEFAULT_APP_NAME_SIZE,
125            bundleName: this.bundleName,
126            moduleName: this.moduleName,
127            labelId: this.appLabelId,
128            nameMargin: this.cardMargin / 2
129          })
130        }
131        .layoutWeight(this.cardLayoutWeight)
132        .margin({ left: RecentsStyleConstants.SINGLE_LIST_APP_INFO_LEFT_MARGIN })
133
134        .onClick((event) => {
135          this.setStartAppInfo(event?.target?.area?.globalPosition);
136        })
137        if (this.lockedState) {
138          Column() {
139            Image(RecentsStyleConstants.DEFAULT_LOCKED_IMAGE)
140              .width(this.mIsSingleLayout ?
141              RecentsStyleConstants.SINGLE_LIST_DEFAULT_APP_ICON_SIZE_NEW :
142                RecentsStyleConstants.DOUBLE_LIST_DEFAULT_APP_ICON_SIZE - 10)
143              .height(this.mIsSingleLayout ?
144              RecentsStyleConstants.SINGLE_LIST_DEFAULT_APP_ICON_SIZE_NEW :
145                RecentsStyleConstants.DOUBLE_LIST_DEFAULT_APP_ICON_SIZE - 10)
146              .margin({
147                right: this.mIsSingleLayout ? (RecentsStyleConstants.SINGLE_LIST_LOCKED_IMAGE_RIGHT_MARGIN) : (RecentsStyleConstants.DOUBLE_LIST_LOCKED_IMAGE_RIGHT_MARGIN)
148              })
149              .onClick((event) => {
150                this.isClickSubComponent = true;
151                Log.showDebug(TAG, `click set recent mission: ${this.missionId} Locked status: ${!this.lockedState}`);
152                this.mRecentMissionsViewModel.setRecentMissionLock(this.missionId,!this.lockedState);
153                this.setStartAppInfo(event?.target?.area?.globalPosition);
154                this.isClickSubComponent = false;
155              })
156          }
157        }
158      }
159      .margin({
160        top: this.mIsSingleLayout ? RecentsStyleConstants.SINGLE_LIST_APP_INFO_TOP_MARGIN : RecentsStyleConstants.DOUBLE_LIST_APP_INFO_BOTTOM_MARGIN,
161        bottom: this.mIsSingleLayout ? RecentsStyleConstants.SINGLE_LIST_APP_INFO_BOTTOM_MARGIN : RecentsStyleConstants.DOUBLE_LIST_APP_INFO_BOTTOM_MARGIN
162      })
163
164      Image(this.recentImage)
165        .objectFit(ImageFit.Fill)
166        .borderRadius(RecentsStyleConstants.RECENT_IMAGE_RADIUS)
167        .width(this.mIsSingleLayout ?
168          RecentsStyleConstants.SINGLE_LIST_APP_IMAGE_WIDTH :
169          RecentsStyleConstants.DOUBLE_LIST_APP_IMAGE_WIDTH)
170        .height(this.mIsSingleLayout ?
171          RecentsStyleConstants.SINGLE_LIST_APP_IMAGE_HEIGHT :
172          RecentsStyleConstants.DOUBLE_LIST_APP_IMAGE_HEIGHT)
173        .onClick((event) => {
174          this.isClickSubComponent = true;
175          Log.showDebug(TAG, 'onClick start launcher ability');
176          localEventManager.sendLocalEventSticky(EventConstants.EVENT_OPEN_FOLDER_TO_CLOSE, null);
177          windowManager.destroyWindow(windowManager.FORM_MANAGER_WINDOW_NAME);
178          windowManager.destroyWindow(windowManager.FORM_SERVICE_WINDOW_NAME);
179          if (!globalThis.recentMode || !windowManager.isSplitWindowMode(globalThis.recentMode)) {
180            windowManager.hideWindow(windowManager.RECENT_WINDOW_NAME);
181          }
182          Trace.start(Trace.CORE_METHOD_START_APP_ANIMATION);
183          this.setStartAppInfo(event?.target?.area?.globalPosition);
184          this.mRecentMissionsViewModel.moveMissionToFront(this.missionId);
185        })
186    }
187    .width(this.mIsSingleLayout ?
188      RecentsStyleConstants.SINGLE_LIST_APP_IMAGE_WIDTH :
189      RecentsStyleConstants.DOUBLE_LIST_APP_IMAGE_WIDTH)
190    .height(this.mIsSingleLayout ?
191      RecentsStyleConstants.SINGLE_LIST_MISSION_HEIGHT :
192      RecentsStyleConstants.DOUBLE_LIST_MISSION_HEIGHT)
193    .backgroundColor(RecentsStyleConstants.DEFAULT_BG_COLOR)
194    .gesture(
195    PanGesture({ fingers: 1, direction: PanDirection.Vertical, distance: 5 })
196      .onActionEnd((e) => {
197        let offsetWidth = (this.mIsSingleLayout ?
198          RecentsStyleConstants.SINGLE_LIST_APP_IMAGE_WIDTH * RecentsStyleConstants.DPI_RATIO :
199          RecentsStyleConstants.DOUBLE_LIST_APP_IMAGE_WIDTH) / 2;
200        if (e.offsetY < -50 && e.offsetX <= offsetWidth && -offsetWidth <= e.offsetX) {
201          this.mRecentMissionsViewModel.deleteRecentMission(false, this.missionId);
202        } else if (e.offsetY > 50 && e.offsetX <= offsetWidth && -offsetWidth <= e.offsetX) {
203          Log.showDebug(TAG, `gesture set recent mission: ${this.missionId} Locked status: ${!this.lockedState}`);
204          this.mRecentMissionsViewModel.setRecentMissionLock(this.missionId,!this.lockedState);
205        }
206      }))
207  }
208
209  /**
210   * set start app info
211   */
212  private setStartAppInfo(position) {
213    AppStorage.setOrCreate('startAppTypeFromPageDesktop', CommonConstants.OVERLAY_TYPE_APP_ICON);
214    let appParams = {
215      bundleName: this.bundleName,
216      moduleName: this.moduleName,
217      appIconId: this.appIconId,
218      borderRadius: RecentsStyleConstants.RECENT_IMAGE_RADIUS,
219      isSingleLayout: this.mIsSingleLayout,
220      appIconSize:this.mIsSingleLayout ? RecentsStyleConstants.SINGLE_LIST_APP_IMAGE_WIDTH : RecentsStyleConstants.DOUBLE_LIST_APP_IMAGE_WIDTH,
221      appIconHeight: this.mIsSingleLayout ? RecentsStyleConstants.SINGLE_LIST_MISSION_HEIGHT : RecentsStyleConstants.DOUBLE_LIST_MISSION_HEIGHT,
222      position:position
223    }
224    AppStorage.setOrCreate('startAppItemInfo', appParams);
225    this.mRecentMissionStartAppHandler.setAppIconSize(appParams.appIconSize, appParams.appIconHeight);
226    this.mRecentMissionStartAppHandler.setAppIconInfo();
227  }
228}