1/**
2 * Copyright (c) 2022-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 windowAnimationManager from '@ohos.animation.windowAnimationManager';
17import curves from '@ohos.curves';
18import { Log } from '../utils/Log';
19import { Trace } from '../utils/Trace';
20import { StyleConstants } from '../constants/StyleConstants';
21import { CommonConstants } from '../constants/CommonConstants';
22import OverlayAppIcon from './OverlayAppIcon';
23import RemoteConstants from '../constants/RemoteConstants';
24import { localEventManager } from '../manager/LocalEventManager';
25import { EventConstants } from '../constants/EventConstants';
26import { CloseAppManager } from '../manager/CloseAppManager';
27import WindowAnimationControllerImpl from '../animation/remoteanimation/WindowAnimationControllerImpl';
28import { LauncherDragItemInfo } from '../bean/LauncherDragItemInfo';
29
30const TAG = 'RemoteWindowWrapper';
31
32class StartAppCalculate {
33  public startAppCalculateScaleX: number = 0;
34  public startAppCalculateScaleY: number = 0;
35  public startAppCalculateTranslateX: number = 0;
36  public startAppCalculateTranslateY: number = 0;
37}
38
39class CloseAppCalculate {
40  public closeAppCalculateScaleX: number = 0;
41  public closeAppCalculateScaleY: number = 0;
42  public closeAppCalculateTranslateX: number = 0;
43  public closeAppCalculateTranslateY: number = 0;
44}
45
46@Observed
47class RemoteVo {
48  public remoteAnimationType: number;
49  public finishCallback: windowAnimationManager.WindowAnimationFinishedCallback;
50  public target: windowAnimationManager.WindowAnimationTarget;
51  public fromWindowTarget: windowAnimationManager.WindowAnimationTarget;
52  public remoteWindowKey: string;
53  public iconInfo: StartAppIconInfo;
54  public appItemInfo: StartAppItemInfo;
55  public count: number = 0;
56
57  public mScreenWidth: number;
58  public mScreenHeight: number;
59
60  public startAppTypeFromPageDesktop: number;
61
62  public remoteWindowScaleX: number = 0;
63  public remoteWindowScaleY: number = 0;
64  public remoteWindowTranslateX: number = 0;
65  public remoteWindowTranslateY: number = 0;
66  public remoteWindowWindowAlpha: number = 0;
67  public remoteWindowRadius: number = 0;
68
69  public fromRemoteWindowScaleX: number = 1.0;
70  public fromRemoteWindowScaleY: number = 1.0;
71  public fromRemoteWindowTranslateX: number = 0;
72  public fromRemoteWindowTranslateY: number = 0;
73  public fromRemoteWindowWindowAlpha: number = 1.0;
74
75  public startAppIconScaleX: number = 0;
76  public startAppIconScaleY: number = 0;
77  public startAppIconTranslateX: number = 0;
78  public startAppIconTranslateY: number = 0;
79  public startAppIconWindowAlpha: number = 0;
80
81  constructor(
82    remoteAnimationType: number,
83    startAppTypeFromPageDesktop: number,
84    target: windowAnimationManager.WindowAnimationTarget,
85    iconInfo: StartAppIconInfo = {} as StartAppIconInfo,
86    appItemInfo: StartAppItemInfo = {} as StartAppItemInfo,
87    fromWindowTarget: windowAnimationManager.WindowAnimationTarget | undefined = undefined,
88    finishCallback: windowAnimationManager.WindowAnimationFinishedCallback
89  ) {
90    this.remoteAnimationType = remoteAnimationType;
91    this.target = target;
92    this.fromWindowTarget = fromWindowTarget as WindowAnimationTarget;
93    this.mScreenWidth = px2vp(this.target.windowBounds.width);
94    this.mScreenHeight = px2vp(this.target.windowBounds.height);
95    this.iconInfo = iconInfo;
96    this.appItemInfo = appItemInfo;
97    this.startAppTypeFromPageDesktop = startAppTypeFromPageDesktop;
98    this.finishCallback = finishCallback;
99    this.remoteWindowKey = this.target.bundleName + this.target.abilityName + this.target.missionId;
100    this.initRemoteWindowProperty();
101  }
102
103  initRemoteWindowProperty() {
104    if (this.remoteAnimationType == RemoteConstants.TYPE_START_APP_FROM_LAUNCHER) {
105      const res = this.calculateStartAppProperty();
106      Log.showInfo(TAG, `initRemoteWindowProperty res: ${JSON.stringify(res)}, mScreenWidth: ${this.mScreenWidth}, mScreenHeight: ${this.mScreenHeight}, startAppTypeFromPageDesktop: ${this.startAppTypeFromPageDesktop}`);
107      this.remoteWindowScaleX = res.startAppCalculateScaleX;
108      this.remoteWindowScaleY = res.startAppCalculateScaleY;
109      this.remoteWindowTranslateX = res.startAppCalculateTranslateX;
110      this.remoteWindowTranslateY = res.startAppCalculateTranslateY;
111      this.remoteWindowWindowAlpha = 0.0;
112      this.remoteWindowRadius = 96;
113
114      this.startAppIconWindowAlpha = 1.0;
115      this.startAppIconScaleX = 1.0;
116      this.startAppIconScaleY = 1.0;
117      this.startAppIconTranslateX = 0.0;
118      this.startAppIconTranslateY = 0.0;
119      this.count = 1;
120    } else if (this.remoteAnimationType == RemoteConstants.TYPE_START_APP_FROM_RECENT) {
121    } else if (this.remoteAnimationType == RemoteConstants.TYPE_START_APP_FROM_OTHER) {
122    } else if (this.remoteAnimationType == RemoteConstants.TYPE_APP_TRANSITION) {
123      this.remoteWindowScaleX = 1.0;
124      this.remoteWindowScaleY = 1.0;
125      this.remoteWindowTranslateX = px2vp(this.target?.windowBounds.width - this.target?.windowBounds.left);
126      this.remoteWindowTranslateY = 0.0;
127      this.remoteWindowWindowAlpha = 1.0;
128      this.remoteWindowRadius = 12;
129
130      this.startAppIconScaleX = 1.0;
131      this.startAppIconScaleY = 1.0;
132      this.startAppIconTranslateX = 0.0;
133      this.startAppIconTranslateY = 0.0;
134      this.startAppIconWindowAlpha = 1.0;
135    } else if (this.remoteAnimationType == RemoteConstants.TYPE_MINIMIZE_WINDOW) {
136      this.remoteWindowScaleX = 1.0;
137      this.remoteWindowScaleY = 1.0;
138      this.remoteWindowTranslateX = 0.0;
139      this.remoteWindowTranslateY = 0.0;
140      this.remoteWindowWindowAlpha = 1.0;
141      this.remoteWindowRadius = 12;
142
143      const res = this.calculateCloseAppProperty();
144      this.startAppIconScaleX = res.closeAppCalculateScaleX;
145      this.startAppIconScaleY = res.closeAppCalculateScaleY;
146      this.startAppIconTranslateX = -res.closeAppCalculateTranslateX;
147      this.startAppIconTranslateY = -res.closeAppCalculateTranslateY;
148      this.startAppIconWindowAlpha = 0.0;
149    } else if (this.remoteAnimationType == RemoteConstants.TYPE_CLOSE_WINDOW) {
150      this.remoteWindowScaleX = 1.0;
151      this.remoteWindowScaleY = 1.0;
152      this.remoteWindowTranslateX = 0.0;
153      this.remoteWindowTranslateY = 0.0;
154      this.remoteWindowRadius = 12;
155      this.remoteWindowWindowAlpha = 1.0;
156
157      this.startAppIconScaleX = 1.0;
158      this.startAppIconScaleY = 1.0;
159      this.startAppIconTranslateX = 0.0;
160      this.startAppIconTranslateY = 0.0;
161      this.startAppIconWindowAlpha = 0.0;
162    }
163  }
164
165  calculateStartAppProperty() {
166    let startAppCalculate = new StartAppCalculate();
167    Log.showInfo(TAG, `calculateStartAppProperty appIconSize: ${this.iconInfo?.appIconSize}, windowBounds: ${JSON.stringify(this.target?.windowBounds)},
168    appIconPosition: [${this.iconInfo?.appIconPositionX}, ${this.iconInfo?.appIconPositionY}], appIconPositionY: ${this.startAppTypeFromPageDesktop}`);
169    startAppCalculate.startAppCalculateScaleX = this.iconInfo?.appIconSize / px2vp(this.target?.windowBounds.width);
170    startAppCalculate.startAppCalculateTranslateX =
171      this.iconInfo?.appIconPositionX + this.iconInfo?.appIconSize / 2 -
172      (px2vp(this.target?.windowBounds.left) + px2vp(this.target?.windowBounds.width) / 2);
173
174    if (this.startAppTypeFromPageDesktop === CommonConstants.OVERLAY_TYPE_CARD) {
175      startAppCalculate.startAppCalculateScaleY =
176        this.iconInfo?.appIconHeight / px2vp(this.target?.windowBounds.height);
177      startAppCalculate.startAppCalculateTranslateY =
178        this.iconInfo?.appIconPositionY + this.iconInfo?.appIconHeight / 2 -
179        (px2vp(this.target?.windowBounds.top) + px2vp(this.target?.windowBounds.height) / 2);
180    } else {
181      startAppCalculate.startAppCalculateScaleY = this.iconInfo?.appIconSize / px2vp(this.target?.windowBounds.height);
182      startAppCalculate.startAppCalculateTranslateY =
183        this.iconInfo?.appIconPositionY + this.iconInfo?.appIconSize / 2 -
184        (px2vp(this.target?.windowBounds.top) + px2vp(this.target?.windowBounds.height) / 2);
185    }
186    return startAppCalculate;
187  }
188
189  calculateCloseAppProperty() {
190    let closeAppCalculate = new CloseAppCalculate();
191    closeAppCalculate.closeAppCalculateScaleX = px2vp(this.target?.windowBounds.width) / this.iconInfo?.appIconSize;
192    closeAppCalculate.closeAppCalculateTranslateX =
193      this.iconInfo?.appIconPositionX + this.iconInfo?.appIconSize / 2 -
194      (px2vp(this.target?.windowBounds.left) + px2vp(this.target?.windowBounds.width) / 2);
195    if (this.startAppTypeFromPageDesktop === CommonConstants.OVERLAY_TYPE_CARD) {
196      closeAppCalculate.closeAppCalculateScaleY =
197        px2vp(this.target?.windowBounds.height) / this.iconInfo?.appIconHeight;
198      closeAppCalculate.closeAppCalculateTranslateY =
199        this.iconInfo?.appIconPositionY + this.iconInfo?.appIconHeight / 2 -
200        (px2vp(this.target?.windowBounds.top) + px2vp(this.target?.windowBounds.height) / 2);
201    } else {
202      closeAppCalculate.closeAppCalculateScaleY = px2vp(this.target?.windowBounds.height) / this.iconInfo?.appIconSize;
203      closeAppCalculate.closeAppCalculateTranslateY =
204        this.iconInfo?.appIconPositionY + this.iconInfo?.appIconSize / 2 -
205        (px2vp(this.target?.windowBounds.top) + px2vp(this.target?.windowBounds.height) / 2);
206    }
207    return closeAppCalculate;
208  }
209}
210
211class SelfWindowAnimationController extends WindowAnimationControllerImpl {
212  public mCloseAppManager: CloseAppManager;
213  public mLastRemoteVo: RemoteVo;
214  public calculateAppProperty: (
215    remoteVo: RemoteVo, finishCallback: windowAnimationManager.WindowAnimationFinishedCallback
216  ) => void
217  public getRemoteWindowVo: (remoteWindowKey: string) => RemoteVo | null;
218  public pushRemoteVoIntoList: (remoteVo: RemoteVo) => void;
219
220  constructor(mCloseAppManager: CloseAppManager, mLastRemoteVo: RemoteVo,
221              getRemoteWindowVo: (remoteWindowKey: string) => RemoteVo | null,
222              pushRemoteVoIntoList: (remoteVo: RemoteVo) => void,
223              calculateAppProperty: (remoteVo: RemoteVo,
224                                     finishCallback: windowAnimationManager.WindowAnimationFinishedCallback) => void) {
225    super();
226    this.mCloseAppManager = mCloseAppManager;
227    this.mLastRemoteVo = mLastRemoteVo;
228    this.calculateAppProperty = calculateAppProperty;
229    this.getRemoteWindowVo = getRemoteWindowVo;
230    this.pushRemoteVoIntoList = pushRemoteVoIntoList;
231  }
232  onStartAppFromLauncher(startingWindowTarget: windowAnimationManager.WindowAnimationTarget,
233                         finishCallback: windowAnimationManager.WindowAnimationFinishedCallback) {
234    Log.showInfo(TAG, 'remote window animaion onStartAppFromLauncher');
235    const remoteWindowKey =
236      startingWindowTarget.bundleName + startingWindowTarget.abilityName + startingWindowTarget.missionId;
237    const startAppTypeFromPageDesktop: number = AppStorage.get('startAppTypeFromPageDesktop') as number;
238    const appItemInfo: StartAppItemInfo = AppStorage.get('startAppItemInfo') as StartAppItemInfo;
239    const startAppIconInfo: StartAppIconInfo = AppStorage.get('startAppIconInfo') as StartAppIconInfo;
240    let remoteVo: RemoteVo | null = this.getRemoteWindowVo(remoteWindowKey);
241    if (remoteVo) {
242      remoteVo.remoteAnimationType = RemoteConstants.TYPE_START_APP_FROM_LAUNCHER;
243      remoteVo.target = startingWindowTarget;
244      remoteVo.startAppTypeFromPageDesktop = startAppTypeFromPageDesktop;
245      remoteVo.iconInfo = startAppIconInfo;
246      remoteVo.appItemInfo = appItemInfo;
247      remoteVo.count = remoteVo.count + 1;
248    } else {
249      remoteVo = new RemoteVo(
250        RemoteConstants.TYPE_START_APP_FROM_LAUNCHER,
251        startAppTypeFromPageDesktop,
252        startingWindowTarget,
253        startAppIconInfo,
254        appItemInfo,
255        undefined,
256        finishCallback
257      );
258      this.mLastRemoteVo = remoteVo;
259    }
260    this.pushRemoteVoIntoList(remoteVo);
261    AppStorage.setOrCreate(remoteWindowKey, remoteVo.count);
262    this.calculateAppProperty(remoteVo, finishCallback);
263    super.onStartAppFromLauncher(startingWindowTarget, finishCallback);
264  }
265
266  onStartAppFromRecent(startingWindowTarget: windowAnimationManager.WindowAnimationTarget,
267                       finishCallback: windowAnimationManager.WindowAnimationFinishedCallback) {
268    Log.showInfo(TAG, 'remote window animaion onStartAppFromRecent');
269    const remoteWindowKey =
270      startingWindowTarget.bundleName + startingWindowTarget.abilityName + startingWindowTarget.missionId;
271    const startAppTypeFromPageDesktop: number = AppStorage.get('startAppTypeFromPageDesktop') as number;
272    const appItemInfo: StartAppItemInfo = AppStorage.get('startAppItemInfo') as StartAppItemInfo;
273    const startAppIconInfo: StartAppIconInfo = AppStorage.get('startAppIconInfo') as StartAppIconInfo;
274    let remoteVo: RemoteVo | null = this.getRemoteWindowVo(remoteWindowKey);
275    if (remoteVo) {
276      remoteVo.remoteAnimationType = RemoteConstants.TYPE_START_APP_FROM_LAUNCHER;
277      remoteVo.target = startingWindowTarget;
278      remoteVo.startAppTypeFromPageDesktop = startAppTypeFromPageDesktop;
279      remoteVo.iconInfo = startAppIconInfo;
280      remoteVo.appItemInfo = appItemInfo;
281      remoteVo.count = remoteVo.count + 1;
282    } else {
283      remoteVo = new RemoteVo(
284        RemoteConstants.TYPE_START_APP_FROM_LAUNCHER,
285        startAppTypeFromPageDesktop,
286        startingWindowTarget,
287        startAppIconInfo,
288        appItemInfo,
289        undefined,
290        finishCallback
291      );
292      this.mLastRemoteVo = remoteVo;
293    }
294    this.pushRemoteVoIntoList(remoteVo);
295    AppStorage.setOrCreate(remoteWindowKey, remoteVo.count);
296    this.calculateAppProperty(remoteVo, finishCallback);
297    super.onStartAppFromRecent(startingWindowTarget, finishCallback);
298  }
299
300  onStartAppFromOther(startingWindowTarget: windowAnimationManager.WindowAnimationTarget,
301                      finishCallback: windowAnimationManager.WindowAnimationFinishedCallback) {
302    Log.showInfo(TAG, 'remote window animaion onStartAppFromOther');
303    const remoteWindowKey =
304      startingWindowTarget.bundleName + startingWindowTarget.abilityName + startingWindowTarget.missionId;
305    const startAppTypeFromPageDesktop: number = AppStorage.get('startAppTypeFromPageDesktop') as number;
306    AppStorage.setOrCreate('startAppItemInfo', {} as StartAppItemInfo);
307    AppStorage.setOrCreate('startAppIconInfo', {} as StartAppIconInfo);
308    const appItemInfo: StartAppItemInfo = AppStorage.get('startAppItemInfo') as StartAppItemInfo;
309    const startAppIconInfo: StartAppIconInfo = AppStorage.get('startAppIconInfo') as StartAppIconInfo;
310    let remoteVo: RemoteVo | null = this.getRemoteWindowVo(remoteWindowKey);
311    if (remoteVo) {
312      remoteVo.remoteAnimationType = RemoteConstants.TYPE_START_APP_FROM_LAUNCHER;
313      remoteVo.target = startingWindowTarget;
314      remoteVo.startAppTypeFromPageDesktop = startAppTypeFromPageDesktop;
315      remoteVo.iconInfo = startAppIconInfo;
316      remoteVo.appItemInfo = appItemInfo;
317      remoteVo.count = remoteVo.count + 1;
318    } else {
319      remoteVo = new RemoteVo(
320        RemoteConstants.TYPE_START_APP_FROM_LAUNCHER,
321        startAppTypeFromPageDesktop,
322        startingWindowTarget,
323        startAppIconInfo,
324        appItemInfo,
325        undefined,
326        finishCallback
327      );
328      this.mLastRemoteVo = remoteVo;
329    }
330    this.pushRemoteVoIntoList(remoteVo);
331    AppStorage.setOrCreate(remoteWindowKey, remoteVo.count);
332    this.calculateAppProperty(remoteVo, finishCallback);
333    super.onStartAppFromOther(startingWindowTarget, finishCallback);
334  }
335
336  onAppTransition(fromWindowTarget: windowAnimationManager.WindowAnimationTarget,
337                  toWindowTarget: windowAnimationManager.WindowAnimationTarget,
338                  finishCallback: windowAnimationManager.WindowAnimationFinishedCallback) {
339    Log.showInfo(TAG, 'remote window animaion onAppTransition');
340    const remoteWindowKey = toWindowTarget.bundleName + toWindowTarget.abilityName + toWindowTarget.missionId;
341    const startAppTypeFromPageDesktop: number = AppStorage.get('startAppTypeFromPageDesktop') as number;
342    const remoteVo = new RemoteVo(
343      RemoteConstants.TYPE_APP_TRANSITION,
344      startAppTypeFromPageDesktop,
345      toWindowTarget,
346      {} as StartAppIconInfo,
347      {} as StartAppItemInfo,
348      fromWindowTarget,
349      finishCallback
350    );
351    this.mLastRemoteVo = remoteVo;
352    this.pushRemoteVoIntoList(remoteVo);
353    this.calculateAppProperty(remoteVo, finishCallback);
354    super.onAppTransition(fromWindowTarget, toWindowTarget, finishCallback);
355  }
356
357  onMinimizeWindow(minimizingWindowTarget: windowAnimationManager.WindowAnimationTarget,
358                   finishCallback: windowAnimationManager.WindowAnimationFinishedCallback) {
359    Log.showInfo(TAG, `remote window animaion onMinimizeWindow`);
360    const startAppTypeFromPageDesktop: number = AppStorage.get('startAppTypeFromPageDesktop') as number;
361    const appInfo: StartAppInfo = this.mCloseAppManager.getAppInfo(minimizingWindowTarget);
362    const remoteWindowKey =
363      minimizingWindowTarget.bundleName + minimizingWindowTarget.abilityName + minimizingWindowTarget.missionId;
364    let remoteVo: RemoteVo | null = this.getRemoteWindowVo(remoteWindowKey);
365    if (appInfo.appItemInfo?.page) {
366      AppStorage.setOrCreate('pageIndex', appInfo.appItemInfo?.page);
367    }
368    if (remoteVo) {
369      remoteVo.remoteAnimationType = RemoteConstants.TYPE_MINIMIZE_WINDOW;
370      remoteVo.target = minimizingWindowTarget;
371      remoteVo.startAppTypeFromPageDesktop = startAppTypeFromPageDesktop;
372      remoteVo.iconInfo = appInfo.iconInfo;
373      remoteVo.appItemInfo = appInfo.appItemInfo;
374      remoteVo.count = remoteVo.count + 1;
375    } else {
376      remoteVo = new RemoteVo(
377        RemoteConstants.TYPE_MINIMIZE_WINDOW,
378        startAppTypeFromPageDesktop,
379        minimizingWindowTarget,
380        appInfo.iconInfo,
381        appInfo.appItemInfo,
382        undefined,
383        finishCallback
384      );
385      this.mLastRemoteVo = remoteVo;
386    }
387    this.pushRemoteVoIntoList(remoteVo);
388    AppStorage.setOrCreate(remoteWindowKey, remoteVo.count);
389    this.calculateAppProperty(remoteVo, finishCallback);
390    super.onMinimizeWindow(minimizingWindowTarget, finishCallback);
391  }
392
393  onCloseWindow(closingWindowTarget: windowAnimationManager.WindowAnimationTarget,
394                finishCallback: windowAnimationManager.WindowAnimationFinishedCallback) {
395    Log.showInfo(TAG, 'remote window animaion onCloseWindow');
396    const startAppTypeFromPageDesktop: number = AppStorage.get('startAppTypeFromPageDesktop') as number;
397    const appInfo: StartAppInfo = this.mCloseAppManager.getAppInfo(closingWindowTarget);
398    const remoteWindowKey =
399      closingWindowTarget.bundleName + closingWindowTarget.abilityName + closingWindowTarget.missionId;
400    let remoteVo: RemoteVo | null = this.getRemoteWindowVo(remoteWindowKey);
401    if (remoteVo) {
402      remoteVo.remoteAnimationType = RemoteConstants.TYPE_MINIMIZE_WINDOW;
403      remoteVo.target = closingWindowTarget;
404      remoteVo.startAppTypeFromPageDesktop = startAppTypeFromPageDesktop;
405      remoteVo.iconInfo = appInfo.iconInfo;
406      remoteVo.appItemInfo = appInfo.appItemInfo;
407    } else {
408      remoteVo = new RemoteVo(
409        RemoteConstants.TYPE_MINIMIZE_WINDOW,
410        startAppTypeFromPageDesktop,
411        closingWindowTarget,
412        appInfo.iconInfo,
413        appInfo.appItemInfo,
414        undefined,
415        finishCallback
416      );
417      this.mLastRemoteVo = remoteVo;
418    }
419    this.pushRemoteVoIntoList(remoteVo);
420    AppStorage.setOrCreate(remoteWindowKey, remoteVo.count);
421    this.calculateAppProperty(remoteVo, finishCallback);
422    super.onCloseWindow(closingWindowTarget, finishCallback);
423  }
424}
425
426@Component
427export struct RemoteWindowWrapper {
428  private mCloseAppManager?: CloseAppManager;
429  private mLastRemoteVo?: RemoteVo;
430  @StorageLink('remoteWindowList') remoteWindowList: RemoteVo[] = [];
431
432  getRemoteWindowVo(remoteWindowKey: string): RemoteVo | null {
433    const remoteVoIndex = this.remoteWindowList.findIndex(item => {
434      return (item.remoteWindowKey) == remoteWindowKey;
435    })
436    if (remoteVoIndex != -1) {
437      return this.remoteWindowList[remoteVoIndex];
438    } else if (this.mLastRemoteVo && this.mLastRemoteVo.remoteWindowKey === remoteWindowKey) {
439      return this.mLastRemoteVo;
440    } else {
441      return null;
442    }
443  }
444
445  private pushRemoteVoIntoList(remoteVo: RemoteVo): void {
446    const remoteVoIndex = this.remoteWindowList.findIndex(item => {
447      return (item.remoteWindowKey) == remoteVo.remoteWindowKey;
448    })
449    if (remoteVoIndex == -1) {
450      this.remoteWindowList.push(remoteVo);
451    }
452  }
453
454  aboutToAppear(): void {
455    this.mCloseAppManager = CloseAppManager.getInstance();
456    let control = new SelfWindowAnimationController(this.mCloseAppManager, this.mLastRemoteVo as RemoteVo,
457      this.getRemoteWindowVo, this.pushRemoteVoIntoList, this.calculateAppProperty);
458
459    windowAnimationManager.setController(control);
460  }
461
462  removeRemoteWindowFromList(remoteWindowKey: string): void {
463    const remoteWindowIndex = this.remoteWindowList.findIndex(item => {
464      return item.remoteWindowKey === remoteWindowKey;
465    });
466    if (remoteWindowIndex != CommonConstants.INVALID_VALUE) {
467      this.remoteWindowList.splice(remoteWindowIndex, 1);
468      Log.showDebug(TAG, `removeRemoteWindowFromList remoteWindowList length: ${this.remoteWindowList.length}`);
469    }
470  }
471
472  calculateAppProperty(remoteVo: RemoteVo, finishCallback: windowAnimationManager.WindowAnimationFinishedCallback) {
473    Log.showDebug(TAG, `calculateAppProperty ${remoteVo.remoteAnimationType}`);
474    if (remoteVo.remoteAnimationType == RemoteConstants.TYPE_START_APP_FROM_LAUNCHER) {
475      Trace.start(Trace.CORE_METHOD_START_APP_ANIMATION);
476      const callback = finishCallback;
477      const count = remoteVo.count;
478      localEventManager.sendLocalEventSticky(EventConstants.EVENT_ANIMATION_START_APPLICATION, null);
479      animateTo({
480        duration: 50,
481        delay: 50,
482        curve: Curve.Friction,
483        onFinish: () => {
484        }
485      }, () => {
486        remoteVo.startAppIconWindowAlpha = 0.0;
487        remoteVo.remoteWindowWindowAlpha = 1.0;
488      })
489
490      animateTo({
491        duration: 370,
492        curve: curves.springMotion(0.25, 0.99, 0),
493        onFinish: () => {
494          callback.onAnimationFinish();
495          Trace.end(Trace.CORE_METHOD_START_APP_ANIMATION);
496          const startCount: number = AppStorage.get(remoteVo.remoteWindowKey);
497          Log.showDebug(TAG, `calculateAppProperty ${remoteVo.remoteAnimationType}, count: ${count}, startCount: ${startCount}`);
498          if (startCount === count) {
499            this.removeRemoteWindowFromList(remoteVo.remoteWindowKey);
500            AppStorage.setOrCreate(remoteVo.remoteWindowKey, 0);
501          }
502        }
503      }, () => {
504        remoteVo.remoteWindowScaleX = 1.0;
505        remoteVo.remoteWindowScaleY = 1.0;
506        remoteVo.remoteWindowTranslateX = 0.0;
507        remoteVo.remoteWindowTranslateY = 0.0;
508        remoteVo.startAppIconScaleX = remoteVo.mScreenWidth / remoteVo.iconInfo?.appIconSize;
509        remoteVo.startAppIconTranslateX =
510          remoteVo.mScreenWidth / 2 - remoteVo.iconInfo?.appIconPositionX - remoteVo.iconInfo?.appIconSize / 2;
511        remoteVo.remoteWindowRadius = 0;
512        if (remoteVo.startAppTypeFromPageDesktop === CommonConstants.OVERLAY_TYPE_CARD) {
513          remoteVo.startAppIconScaleY = remoteVo.mScreenHeight / remoteVo.iconInfo?.appIconHeight;
514          remoteVo.startAppIconTranslateY =
515            remoteVo.mScreenHeight / 2 + px2vp(remoteVo.target.windowBounds.top) -
516            remoteVo.iconInfo?.appIconPositionY - remoteVo.iconInfo?.appIconHeight / 2;
517        } else {
518          remoteVo.startAppIconScaleY = remoteVo.mScreenHeight / remoteVo.iconInfo?.appIconSize;
519          remoteVo.startAppIconTranslateY =
520          remoteVo.mScreenHeight / 2 + px2vp(remoteVo.target.windowBounds.top) -
521          remoteVo.iconInfo?.appIconPositionY - remoteVo.iconInfo?.appIconSize / 2;
522        }
523      })
524    } else if (remoteVo.remoteAnimationType == RemoteConstants.TYPE_MINIMIZE_WINDOW) {
525      Trace.start(Trace.CORE_METHOD_CLOSE_APP_ANIMATION);
526      const res = remoteVo.calculateCloseAppProperty();
527      const callback = finishCallback;
528      const count = remoteVo.count;
529      localEventManager.sendLocalEventSticky(EventConstants.EVENT_ANIMATION_CLOSE_APPLICATION, null);
530      animateTo({
531        duration: 370,
532        curve: curves.springMotion(0.25, 0.99, 0),
533        onFinish: () => {
534          callback.onAnimationFinish();
535          Trace.end(Trace.CORE_METHOD_CLOSE_APP_ANIMATION);
536          const startCount: number = AppStorage.get(remoteVo.remoteWindowKey);
537          Log.showDebug(TAG, `calculateAppProperty ${remoteVo.remoteAnimationType}, count: ${count}, startCount: ${startCount}`);
538          if (startCount === count) {
539            this.removeRemoteWindowFromList(remoteVo.remoteWindowKey);
540            AppStorage.setOrCreate(remoteVo.remoteWindowKey, 0);
541          }
542        }
543      }, () => {
544        remoteVo.remoteWindowScaleX = 1 / res.closeAppCalculateScaleX;
545        remoteVo.remoteWindowScaleY = 1 / res.closeAppCalculateScaleY;
546        remoteVo.remoteWindowTranslateX = res.closeAppCalculateTranslateX;
547        remoteVo.remoteWindowTranslateY = res.closeAppCalculateTranslateY;
548
549        remoteVo.startAppIconScaleX = 1.0;
550        remoteVo.startAppIconScaleY = 1.0;
551        remoteVo.startAppIconTranslateX = 0.0;
552        remoteVo.startAppIconTranslateY = 0.0;
553        remoteVo.remoteWindowRadius = 96;
554      })
555
556      animateTo({
557        duration: 50,
558        delay: 50,
559        curve: Curve.Friction,
560        onFinish: () => {
561        }
562      }, () => {
563        remoteVo.startAppIconWindowAlpha = 1.0;
564        remoteVo.remoteWindowWindowAlpha = 0;
565      })
566    } else if (remoteVo.remoteAnimationType == RemoteConstants.TYPE_CLOSE_WINDOW) {
567    } else if (remoteVo.remoteAnimationType == RemoteConstants.TYPE_APP_TRANSITION) {
568      const callback = finishCallback;
569      animateTo({
570        duration: 300,
571        curve: Curve.Friction,
572        onFinish: () => {
573          this.removeRemoteWindowFromList(remoteVo.remoteWindowKey);
574        }
575      }, () => {
576        remoteVo.remoteWindowRadius = 0;
577        remoteVo.remoteWindowTranslateX = 0;
578        remoteVo.fromRemoteWindowTranslateX =
579        px2vp(remoteVo.fromWindowTarget?.windowBounds.left - remoteVo.fromWindowTarget?.windowBounds.width);
580      })
581
582      animateTo({
583        duration: 150,
584        curve: Curve.Friction,
585        onFinish: () => {
586          this.removeRemoteWindowFromList(remoteVo.remoteWindowKey);
587        }
588      }, () => {
589        remoteVo.remoteWindowScaleX = 0.9
590        remoteVo.remoteWindowScaleY = 0.9
591        remoteVo.fromRemoteWindowScaleX = 0.9
592        remoteVo.fromRemoteWindowScaleY = 0.9
593      })
594
595      animateTo({
596        duration: 350,
597        delay: 150,
598        curve: Curve.Friction,
599        onFinish: () => {
600          callback.onAnimationFinish();
601          this.removeRemoteWindowFromList(remoteVo.remoteWindowKey);
602        }
603      }, () => {
604        remoteVo.remoteWindowScaleX = 1.0
605        remoteVo.remoteWindowScaleY = 1.0
606        remoteVo.fromRemoteWindowScaleX = 1.0
607        remoteVo.fromRemoteWindowScaleY = 1.0
608      })
609    }
610  }
611
612  build() {
613    Stack() {
614      ForEach(this.remoteWindowList, (item: RemoteVo) => {
615        if (item.remoteAnimationType == RemoteConstants.TYPE_APP_TRANSITION) {
616          StartAppTransitionRemoteWindow({
617            targetInfo: item
618          })
619        } else {
620          StartAppFromLauncherRemoteWindow({
621            targetInfo: item
622          })
623        }
624      }, (item: RemoteVo) => item.remoteWindowKey)
625    }
626    .width(StyleConstants.PERCENTAGE_100)
627    .height(StyleConstants.PERCENTAGE_100)
628    .focusable(false)
629    .enabled(false)
630  }
631}
632
633@Component
634export struct StartAppFromLauncherRemoteWindow {
635  @ObjectLink targetInfo: RemoteVo;
636
637  aboutToAppear(): void {
638  }
639
640  aboutToDisappear(): void {
641  }
642
643  build() {
644    Stack() {
645      Column() {
646        if (this.targetInfo.startAppTypeFromPageDesktop === CommonConstants.OVERLAY_TYPE_CARD) {
647          FormComponent({
648            id: this.targetInfo.appItemInfo?.cardId as number,
649            name: this.targetInfo.appItemInfo?.cardName as string,
650            bundle: this.targetInfo.appItemInfo?.bundleName as string,
651            ability: this.targetInfo.appItemInfo?.abilityName as string,
652            module: this.targetInfo.appItemInfo?.moduleName as string,
653            dimension: this.targetInfo.appItemInfo?.cardDimension
654          })
655            .clip(new Rect({
656              width: this.targetInfo.iconInfo?.appIconSize as number,
657              height: this.targetInfo.iconInfo?.appIconHeight as number,
658              radius: 24
659            }))
660            .size({
661              width: this.targetInfo.iconInfo?.appIconSize as number,
662              height: this.targetInfo.iconInfo?.appIconHeight as number
663            })
664        } else {
665          OverlayAppIcon({
666            iconSize: this.targetInfo.iconInfo?.appIconSize as number,
667            icon: this.targetInfo.appItemInfo?.icon as ResourceStr
668          })
669        }
670      }
671      .translate({ x: this.targetInfo.startAppIconTranslateX as number,
672        y: this.targetInfo.startAppIconTranslateY as number })
673      .scale({ x: this.targetInfo.startAppIconScaleX as number,
674        y: this.targetInfo.startAppIconScaleY as number })
675      .opacity(this.targetInfo.startAppIconWindowAlpha as number)
676      .position({
677        x: this.targetInfo.iconInfo?.appIconPositionX as number,
678        y: this.targetInfo.iconInfo?.appIconPositionY as number,
679      })
680
681      RemoteWindow(this.targetInfo.target)
682        .translate({ x: this.targetInfo.remoteWindowTranslateX, y: this.targetInfo.remoteWindowTranslateY })
683        .scale({ x: this.targetInfo.remoteWindowScaleX, y: this.targetInfo.remoteWindowScaleY })
684        .opacity(this.targetInfo.remoteWindowWindowAlpha)
685        .position({
686          x: px2vp(this.targetInfo.target?.windowBounds.left), y: px2vp(this.targetInfo.target?.windowBounds.top)
687        })
688        .width(px2vp(this.targetInfo.target?.windowBounds.width))
689        .height(px2vp(this.targetInfo.target?.windowBounds.height))
690        .borderRadius(this.targetInfo.remoteWindowRadius)
691    }
692    .width(StyleConstants.PERCENTAGE_100)
693    .height(StyleConstants.PERCENTAGE_100)
694    .focusable(false)
695    .enabled(false)
696  }
697}
698
699class StartAppItemInfo extends LauncherDragItemInfo {
700  public icon?: ResourceStr;
701}
702
703interface StartAppIconInfo {
704  appIconSize: number;
705  appIconHeight: number;
706  appIconPositionX: number;
707  appIconPositionY: number;
708}
709
710interface StartAppInfo {
711  iconInfo: StartAppIconInfo;
712  appItemInfo: StartAppItemInfo;
713}
714
715@Component
716export struct StartAppTransitionRemoteWindow {
717  @ObjectLink targetInfo: RemoteVo;
718  private target?: windowAnimationManager.WindowAnimationTarget;
719  private mFromWindowTarget?: windowAnimationManager.WindowAnimationTarget = undefined;
720  private remoteAnimationType: number = 0;
721  private startAppTypeFromPageDesktop: number = 1;
722  private mScreenWidth: number = 0;
723  private mScreenHeight: number = 0;
724  private startAppIconInfo: StartAppIconInfo =
725    { appIconSize: 0,
726      appIconHeight: 0,
727      appIconPositionX: 0,
728      appIconPositionY: 0 };
729  private mStartAppItemInfo: StartAppItemInfo = new StartAppItemInfo();
730  private mFinishCallback?: windowAnimationManager.WindowAnimationFinishedCallback;
731  private remoteWindowKey?: string;
732
733  aboutToAppear(): void {
734    this.target = this.targetInfo.target;
735    this.mFromWindowTarget = this.targetInfo.fromWindowTarget;
736    this.mFinishCallback = this.targetInfo.finishCallback;
737    this.remoteWindowKey = this.targetInfo.remoteWindowKey;
738    this.mStartAppItemInfo = this.targetInfo.appItemInfo;
739    this.mScreenWidth = px2vp(this.target.windowBounds.width);
740    this.mScreenHeight = px2vp(this.target.windowBounds.height);
741  }
742
743  aboutToDisappear() {
744  }
745
746  build() {
747    Stack() {
748      Column() {
749        RemoteWindow(this.targetInfo.target)
750          .position({ x: px2vp(this.target?.windowBounds.left as number),
751            y: px2vp(this.target?.windowBounds.top as number) })
752          .width(px2vp(this.target?.windowBounds.width as number))
753          .height(px2vp(this.target?.windowBounds.height as number))
754          .translate({ x: this.targetInfo.remoteWindowTranslateX, y: this.targetInfo.remoteWindowTranslateY })
755          .scale({ x: this.targetInfo.remoteWindowScaleX, y: this.targetInfo.remoteWindowScaleY })
756          .opacity(this.targetInfo.remoteWindowWindowAlpha)
757          .borderRadius(this.targetInfo.remoteWindowRadius)
758
759        RemoteWindow(this.mFromWindowTarget)
760          .translate({ x: this.targetInfo.fromRemoteWindowTranslateX, y: this.targetInfo.fromRemoteWindowTranslateY })
761          .scale({ x: this.targetInfo.fromRemoteWindowScaleX, y: this.targetInfo.fromRemoteWindowScaleY })
762          .opacity(this.targetInfo.fromRemoteWindowWindowAlpha)
763          .position({
764            x: px2vp(this.mFromWindowTarget?.windowBounds.left as number),
765            y: px2vp(this.mFromWindowTarget?.windowBounds.top as number)
766          })
767          .width(px2vp(this.mFromWindowTarget?.windowBounds.width as number))
768          .height(px2vp(this.mFromWindowTarget?.windowBounds.height as number))
769          .borderRadius(this.targetInfo.remoteWindowRadius)
770      }
771      .width(StyleConstants.PERCENTAGE_100)
772      .height(StyleConstants.PERCENTAGE_100)
773      .focusable(false)
774      .enabled(false)
775    }
776  }
777}