• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1/*
2 * Copyright (c) 2023 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 router from '@system.router';
17import display from '@ohos.display';
18import deviceInfo from '@ohos.deviceInfo'
19import { BigVideoTimer } from './BigVideoTimer'
20import { Action, UiStateMode } from '@ohos/common/src/main/ets/default/redux/actions/Action'
21import { AssistiveGridView } from '@ohos/common/src/main/ets/default/featurecommon/assistivegridview/AssistiveGridView'
22import { BigText } from '@ohos/common/src/main/ets/default/featurecommon/bigtext/BigText'
23import { CameraNeedStatus, CameraStatus } from '@ohos/common/src/main/ets/default/utils/Constants'
24import { CameraId } from '@ohos/common/src/main/ets/default/setting/settingitem/CameraId'
25import { EventBus } from '@ohos/common/src/main/ets/default/worker/eventbus/EventBus'
26import { EventBusManager } from '@ohos/common/src/main/ets/default/worker/eventbus/EventBusManager'
27import { OhCombinedState } from '@ohos/common/src/main/ets/default/redux/store'
28import { getStore } from '@ohos/common/src/main/ets/default/redux/store'
29import { Log } from '@ohos/common/src/main/ets/default/utils/Log'
30import { GeoLocation } from '@ohos/common/src/main/ets/default/featurecommon/geolocation/GeoLocation'
31import { ScreenLockManager } from '@ohos/common/src/main/ets/default/featurecommon/screenlock/ScreenLockManager'
32import { SettingManager } from '@ohos/common/src/main/ets/default/setting/SettingManager'
33import { ShowFlashBlack } from '@ohos/common/src/main/ets/default/featurecommon/animate/ShowFlashBlack'
34import { TimeLapseView } from '@ohos/common/src/main/ets/default/featurecommon/timelapseview/TimeLapseView'
35import { ZoomText } from '@ohos/common/src/main/ets/default/featurecommon/zoomview/ZoomText'
36import { SmallVideoTimer } from './SmallVideoTimer'
37import promptAction from '@ohos.promptAction';
38import wantConstant from '@ohos.ability.wantConstant';
39import { GlobalContext } from '@ohos/common/src/main/ets/default/utils/GlobalContext';
40import { CameraPlatformCapability } from '@ohos/common/src/main/ets/default/camera/CameraPlatformCapability';
41import { BusinessError } from '@ohos.base';
42import { MapDispatchProp, MapStateProp } from '@ohos/common/src/main/ets/default/redux/core/ohredux/connect';
43
44const DEFAULT_FUNCTION: Function = () => {
45};
46
47class StateStruct {
48  mode: string = '';
49  curMode: string = '';
50  isShowPreview: boolean = true;
51  surfaceId: number = 0;
52  xComponentWidth: number = 0;
53  xComponentHeight: number = 0;
54  cameraPosition: CameraId = CameraId.BACK;
55  curCameraPosition: CameraId = CameraId.BACK;
56  minZoomRatio: number = 0;
57  maxZoomRatio: number = 0;
58  zoomRatio: number = 0;
59  platformCapability: CameraPlatformCapability | undefined = undefined;
60  videoState: string = '';
61  footBarHeight: number = 0;
62  isShowZoomText: boolean = false;
63  showZoomLabelValue: boolean = false;
64  modeIndex: number = 0;
65  isThirdPartyCall: boolean = false;
66  isShowBigText: boolean = false;
67  isShowtimeLapse: boolean = false;
68  isBigVideoTimerVisible: boolean = false;
69  isSmallVideoTimerVisible: boolean = false;
70  isAssGridViewShow: string = '';
71  isShowFlashBlack: boolean = false;
72  modeChangeDone: boolean = false;
73  isShowPageView: boolean = false;
74  showBlur: boolean = false;
75  isFaCall: boolean = false;
76  baseZoom: number = 0;
77  initCamera: Function = DEFAULT_FUNCTION;
78  initZoomRatio: Function = DEFAULT_FUNCTION;
79  changeZoomRatio: Function = DEFAULT_FUNCTION;
80  updateZoomPercentage: Function = DEFAULT_FUNCTION;
81  prepareSurface: Function = DEFAULT_FUNCTION;
82  startPreview: Function = DEFAULT_FUNCTION;
83  switchCamera: Function = DEFAULT_FUNCTION;
84  updateCameraPosition: Function = DEFAULT_FUNCTION;
85  startVideoFlag: Function = DEFAULT_FUNCTION;
86  changeXComponentSize: Function = DEFAULT_FUNCTION;
87  updateShowPreviewFlag: Function = DEFAULT_FUNCTION;
88  updateIsShowZoomText: Function = DEFAULT_FUNCTION;
89  updateIsPhotoZoomDetails: Function = DEFAULT_FUNCTION;
90  updateBaseZoom: Function = DEFAULT_FUNCTION;
91  changeImageSize: Function = DEFAULT_FUNCTION;
92  changeVideoSize: Function = DEFAULT_FUNCTION;
93  close: Function = DEFAULT_FUNCTION;
94  stopRecording: Function = DEFAULT_FUNCTION;
95  changeTimeLapse: Function = DEFAULT_FUNCTION;
96  capture: Function = DEFAULT_FUNCTION;
97  startRecording: Function = DEFAULT_FUNCTION;
98  assistiveGridView: Function = DEFAULT_FUNCTION;
99  swipeChangeMode: Function = DEFAULT_FUNCTION;
100  thirdPartyCall: Function = DEFAULT_FUNCTION;
101  faCall: Function = DEFAULT_FUNCTION;
102  initMode: Function = DEFAULT_FUNCTION;
103  updateMode: Function = DEFAULT_FUNCTION;
104  changeToMode: Function = DEFAULT_FUNCTION;
105  updateModeIndex: Function = DEFAULT_FUNCTION;
106  updateShowZoomLabelValue: Function = DEFAULT_FUNCTION;
107  reloadThumbnail: Function = DEFAULT_FUNCTION;
108  updateShowPinch: Function = DEFAULT_FUNCTION;
109  swipeModeChangeDone: Function = DEFAULT_FUNCTION;
110  updateInitShowFlag: Function = DEFAULT_FUNCTION;
111  hideSettingView: Function = DEFAULT_FUNCTION;
112}
113
114GlobalContext.get().setXComponentController(new XComponentController())
115
116interface ScreenSizeType {
117  width: number
118  height: number
119}
120
121interface PlatformCapability {
122  platformCapability: CameraPlatformCapability
123}
124
125interface ModeData {
126  mode: string
127}
128
129interface KeepScreenData {
130  isKeepScreenOn: boolean
131}
132
133@Component
134export struct PreviewAreaLand {
135  private TAG: string = '[PreviewAreaLand]:';
136  appEventBus: EventBus = EventBusManager.getInstance().getEventBus();
137  @State state: StateStruct = new StateStruct();
138  @State btnSwitch: boolean = false;
139  @State btnSwitchSec: boolean = false;
140  @State pinchGestureTimerId: number = 0;
141  @State onTouchDownTimerId: number = 0;
142  @State scaleX: number = 1;
143  @State scaleXSec: number = 0.8;
144  @State rotateAngle: number = 0;
145  @State rotateAngleSec: number = 80;
146  @State btnOpacityFirst: number = 1;
147  @State btnOpacitySec: number = 0;
148  @State switchBackgroundOpacity: number = 1;
149  @State isSwitchBackground: boolean = false;
150  @State pageType: string = '';
151  @Link screenSize: ScreenSizeType;
152  @State isShowBlurSize: ScreenSizeType = { width: 0, height: 0 };
153  private mConnect: Function = () => {
154  };
155  private isShowPreview: boolean = false;
156  private settingManager = SettingManager.getInstance();
157  private pinchGestureTimer: number = 0;
158  private baseZoom: number = 0;
159  private modeArray: Array<string> = ['MULTI', 'PHOTO', 'VIDEO'];
160
161  private async onCameraInit(): Promise<void> {
162    Log.info(`${this.TAG} EventBus onCameraInit isShowPreview = ${this.isShowPreview}
163      platformCapability = ${this.state.platformCapability} E`);
164    if (this.state.platformCapability) {
165      this.settingManager.loadAllSetting().then(() => {
166        this.settingManager.setCameraId(this.state.cameraPosition);
167
168        let imageSize = this.settingManager.getImageSize();
169        this.state.changeImageSize(imageSize);
170
171        let videoSize = this.settingManager.getVideoSize();
172        this.state.changeVideoSize(videoSize);
173
174        let isAssGridViewShow = this.settingManager.getAssistiveGrid();
175        this.state.assistiveGridView(isAssGridViewShow);
176
177        GeoLocation.getInstance().on();
178
179        this.resetScreenSize(this.screenSize);
180        this.state.updateShowPreviewFlag(true);
181      })
182    }
183    Log.info(`${this.TAG} onCameraInit isShowPreview = ${this.state.isShowPreview}  X`);
184  }
185
186  private async doCameraAction() {
187    Log.info(`${this.TAG} doCameraAction E`);
188    this.settingManager.setCameraId(this.state.cameraPosition);
189    Log.info(`${this.TAG} curMode:${this.state.curMode} mode:${this.state.mode}`);
190    if (this.state.curCameraPosition != this.state.cameraPosition) {
191      this.state.switchCamera(this.state.cameraPosition, this.state.mode);
192      this.state.updateCameraPosition(this.state.cameraPosition);
193    } else if (this.state.curMode != this.state.mode) {
194      this.state.changeToMode(this.state.mode);
195      this.state.updateMode(this.state.mode);
196    } else {
197      if (GlobalContext.get().getT<boolean>('keepCameraZoomRatio') && GlobalContext.get().getT<boolean>('keepCameraZoomRatio')) {
198        GlobalContext.get().setObject('keepCameraZoomRatio', false)
199        Log.info(`${this.TAG} keep zoomRatio: ` + this.state.zoomRatio);
200      } else {
201        this.state.changeZoomRatio(1);
202        Log.info(`${this.TAG} change zoomRatio: 1`);
203      }
204      this.state.startPreview(this.state.zoomRatio);
205    }
206    Log.info(`${this.TAG} doCameraAction X`);
207    this.state.updateInitShowFlag(true);
208  }
209
210  private async onModeChanged(data: ModeData) {
211    Log.debug(`${this.TAG} onModeChanged E data.mode: ${data.mode}`);
212    this.state.changeZoomRatio(1);
213    this.state.updateShowPreviewFlag(true);
214    Log.debug(`${this.TAG} onModeChanged X`);
215  }
216
217  private async onRecordError() {
218    Log.info(`${this.TAG} onRecordError invoke E`);
219    promptAction.showToast({
220      message: "录像异常",
221      duration: 2000,
222    })
223    if (this.state.videoState === 'startTakeVideo') {
224      this.state.stopRecording();
225    }
226    this.state.close();
227    Log.info(`${this.TAG} onRecordError invoke X`);
228  }
229
230  aboutToAppear(): void {
231    Log.info(`${this.TAG} aboutToAppear E ${JSON.stringify(router.getParams())}`);
232    let routerParams = router.getParams();
233    if (routerParams && routerParams.pageType) {
234      this.pageType = routerParams.pageType.toString();
235    }
236    this.mConnect = getStore().connect((state: OhCombinedState) => {
237      let isShowBlur = !state.ContextReducer.uiEnable && state.ContextReducer.uiStateMode == UiStateMode.NONE;
238      return {
239        mode: state.ModeReducer.mode,
240        curMode: state.ModeReducer.curMode,
241        isShowPreview: state.PreviewReducer.isShowPreview,
242        surfaceId: state.PreviewReducer.surfaceId,
243        xComponentWidth: state.PreviewReducer.xComponentWidth,
244        xComponentHeight: state.PreviewReducer.xComponentHeight,
245        cameraPosition: state.CameraReducer.cameraPosition,
246        curCameraPosition: state.CameraReducer.curCameraPosition,
247        minZoomRatio: state.ZoomReducer.minZoomRatio,
248        maxZoomRatio: state.ZoomReducer.maxZoomRatio,
249        zoomRatio: state.ZoomReducer.zoomRatio,
250        platformCapability: state.CameraInitReducer.platformCapability,
251        videoState: state.RecordReducer.videoState,
252        footBarHeight: state.ContextReducer.footBarHeight,
253        isShowZoomText: state.ZoomReducer.isShowZoomText,
254        showZoomLabelValue: state.ZoomReducer.showZoomLabelValue,
255        modeIndex: state.ModeReducer.modeIndex,
256        isThirdPartyCall: state.ContextReducer.isThirdPartyCall,
257        isShowBigText: state.ModeReducer.isShowBigText,
258        isShowtimeLapse: state.SettingReducer.isShowtimeLapse,
259        isBigVideoTimerVisible: state.RecordReducer.isBigVideoTimerVisible,
260        isSmallVideoTimerVisible: state.RecordReducer.isSmallVideoTimerVisible,
261        isAssGridViewShow: state.SettingReducer.isAssGridViewShow,
262        isShowFlashBlack: state.PreviewReducer.isShowFlashBlack,
263        modeChangeDone: state.ModeReducer.modeChangeDone,
264        isShowPageView: state.SettingReducer.isShowSettingView,
265        showBlur: isShowBlur,
266        isFaCall: state.ContextReducer.isFaCall
267      };
268    }, (dispatch) => {
269      return {
270        initCamera: (cameraId: CameraId, mode: string): void => {
271          dispatch(Action.initCamera(cameraId, mode));
272        },
273        initZoomRatio: (min: number, max: number): void => {
274          dispatch(Action.initZoomRatio(min, max));
275        },
276        changeZoomRatio: (zoomRatio: number): void => {
277          dispatch(Action.changeZoomRatio(zoomRatio));
278        },
279        updateZoomPercentage: (zoomPercentage: number): void => {
280          dispatch(Action.updateZoomPercentage(zoomPercentage));
281        },
282        prepareSurface: (surfaceId: number): void => {
283          dispatch(Action.prepareSurface(surfaceId));
284        },
285        startPreview: (zoomRatio: number): void => {
286          dispatch(Action.startPreview(zoomRatio));
287        },
288        switchCamera: (cameraId: CameraId, mode: string): void => {
289          dispatch(Action.switchCamera(cameraId, mode));
290        },
291        updateCameraPosition: (cameraPosition: string): void => {
292          dispatch(Action.updateCameraPosition(cameraPosition));
293        },
294        startVideoFlag: (isStartVideo: boolean): void => {
295          dispatch(Action.startVideoFlag(isStartVideo));
296        },
297        changeXComponentSize: (xComponentWidth: number, xComponentHeight: number): void => {
298          dispatch(Action.changeXComponentSize(xComponentWidth, xComponentHeight));
299        },
300        updateShowPreviewFlag: (isShowPreview: boolean): void => {
301          dispatch(Action.updateShowPreviewFlag(isShowPreview));
302        },
303        updateIsShowZoomText: (isShowZoomText: boolean): void => {
304          dispatch(Action.updateShowZoomTextFlag(isShowZoomText));
305        },
306        updateIsPhotoZoomDetails: (isPhotoZoomDetails: boolean): void => {
307          dispatch(Action.updatePhotoZoomDetailsFlag(isPhotoZoomDetails));
308        },
309        updateBaseZoom: (zoomRatio: number): void => {
310          dispatch(Action.updateBaseZoom(zoomRatio));
311        },
312        changeImageSize: (imageSize: ScreenSizeType): void => {
313          dispatch(Action.changeImageSize(imageSize));
314        },
315        changeVideoSize: (videoSize: ScreenSizeType): void => {
316          dispatch(Action.changeVideoSize(videoSize));
317        },
318        close: (): void => {
319          dispatch(Action.close());
320        },
321        stopRecording: (): void => {
322          dispatch(Action.stopRecording());
323          dispatch(Action.updateVideoState('beforeTakeVideo'));
324          dispatch(Action.updateBigVideoTimerVisible(false));
325          dispatch(Action.updateSmallVideoTimerVisible(false));
326          dispatch(Action.updateScreenStatus(false));
327        },
328        changeTimeLapse: (isShowtimeLapse: boolean): void => {
329          dispatch(Action.changeTimeLapse(isShowtimeLapse));
330        },
331        capture: (): void => {
332          dispatch(Action.updateShowFlashBlackFlag(true));
333          dispatch(Action.capture());
334        },
335        startRecording: (): void => {
336          dispatch(Action.startRecording());
337          dispatch(Action.updateVideoState('startTakeVideo'));
338          dispatch(Action.updateBigVideoTimerVisible(true));
339          dispatch(Action.updateScreenStatus(true));
340        },
341        assistiveGridView: (isViewShow: number): void => {
342          dispatch(Action.assistiveGridView(isViewShow));
343        },
344        swipeChangeMode: (swipeModeIndex: number): void => {
345          dispatch(Action.swipeChangeMode(swipeModeIndex));
346        },
347        thirdPartyCall: (isThirdPartyCall: boolean, action: string): void => {
348          dispatch(Action.thirdPartyCall(isThirdPartyCall, action));
349        },
350        faCall: (isFaCall: boolean): void => {
351          dispatch(Action.faCall(isFaCall));
352        },
353        initMode: (mode: string): void => {
354          dispatch(Action.initMode(mode));
355        },
356        updateMode: (mode: string): void => {
357          dispatch(Action.updateMode(mode));
358        },
359        changeToMode: (mode: string): void => {
360          dispatch(Action.changeMode(mode));
361        },
362        updateModeIndex: (index: number): void => {
363          dispatch(Action.updateModeIndex(index));
364        },
365        updateShowZoomLabelValue: (flag: boolean): void => {
366          dispatch(Action.updateShowZoomLabelValue(flag));
367        },
368        reloadThumbnail: (): void => {
369          dispatch(Action.reloadThumbnail());
370        },
371        updateShowPinch: (flag: boolean): void => {
372          dispatch(Action.updateShowPinch(flag));
373        },
374        swipeModeChangeDone: (actionOff: boolean): void => {
375          dispatch(Action.swipeModeChangeDone(actionOff));
376        },
377        updateInitShowFlag: (initShowFlag: boolean): void => {
378          dispatch(Action.updateInitShowFlag(initShowFlag));
379        },
380        hideSettingView: (): void => {
381          dispatch(Action.showSettingView(false));
382        }
383      };
384    });
385    this.mConnect(this.state)
386    this.appEventBus.on(Action.ACTION_INIT_DONE, () => this.onCameraInit);
387    this.appEventBus.on(Action.ACTION_ON_MODE_CHANGED, () => this.onModeChanged);
388    this.appEventBus.on(Action.ACTION_KEEP_SCREEN_ON, () => this.onKeepScreen);
389    this.appEventBus.on("windowSize", () => this.windowSizeChange);
390    this.appEventBus.on(Action.ACTION_RECORD_ERROR, () => this.onRecordError);
391    this.appEventBus.on(ScreenLockManager.SCREEN_CHANGE_EVENT, () => this.onScreenChange);
392    this.appEventBus.on(Action.ACTION_UPDATE_CAMERA_STATUS, () => this.updateCameraStatus);
393    GlobalContext.get().setObject('updateCameraStatus', () => {
394      Log.info(`${this.TAG} globalThis.updateCameraStatus called`);
395      this.updateCameraStatus();
396    });
397    display.getDefaultDisplay().then((dis) => {
398      this.isShowBlurSize = { width: px2vp(dis.width), height: px2vp(dis.height) };
399    })
400    this.calledByOther();
401    this.state.initCamera(this.state.cameraPosition, this.state.mode);
402    this.state.initZoomRatio(1, 6); //TODO 需要动态取得实际变焦能力范围
403    Log.info(`${this.TAG} aboutToAppear X`);
404    Log.start(Log.X_COMPONENT_LIFE);
405  }
406
407  private releaseCamera(): void {
408    Log.info(`${this.TAG} globalThis.releaseCamera called`);
409    GlobalContext.get().setObject('cameraNeedStatus', CameraNeedStatus.CAMERA_NO_NEED_TO_DO);
410    if (this.state.videoState === 'startTakeVideo') {
411      this.state.stopRecording();
412    }
413    this.state.close();
414  }
415
416  private async onForegroundInit() {
417    Log.info(`${this.TAG} onForegroundInit E `);
418    this.pageType = '';
419    GlobalContext.get().setObject('cameraNeedStatus', CameraNeedStatus.CAMERA_NO_NEED_TO_DO);
420    this.calledByOther();
421    this.state.initCamera(this.state.cameraPosition, this.state.mode);
422    await new Promise<Function | string>((resolve: Function | string) => setTimeout(resolve, 40));
423    this.doCameraAction();
424    this.state.updateInitShowFlag(true);
425    if (!this.state.isThirdPartyCall) {
426      this.state.reloadThumbnail();
427    }
428    Log.info(`${this.TAG} onForegroundInit X`);
429  }
430
431  private calledByOther(): void {
432    Log.info(`${this.TAG} calledByOther invoke E`);
433    let from: string = "";
434    let action: string = "";
435
436    if (GlobalContext.get().getCameraAbilityWant()) {
437      Log.info(`${this.TAG} cameraAbilityWant: ${JSON.stringify(GlobalContext.get().getCameraAbilityWant())}`);
438      if (GlobalContext.get().getCameraAbilityWant()?.parameters?.from) {
439        from = GlobalContext.get().getCameraAbilityWant()?.parameters?.from as string;
440      }
441      let cameraAbilityWant = GlobalContext.get().getCameraAbilityWant();
442      if (cameraAbilityWant?.action) {
443        action = cameraAbilityWant?.action;
444      }
445    } else {
446      this.state.thirdPartyCall(false, "");
447      return;
448    }
449    Log.info(`${this.TAG} from: ${from}  uri: ${action}`);
450
451    if (from === "FA") {
452      Log.info(`from === "FA"`);
453      if (GlobalContext.get().getCameraAbilityWant()?.parameters?.action) {
454        action = GlobalContext.get().getCameraAbilityWant()?.parameters?.action as string;
455      }
456      this.state.faCall(true);
457      this.state.thirdPartyCall(false, "");
458      this.initStateMode(action);
459    } else if (action != "") {
460      this.state.faCall(false);
461      this.state.thirdPartyCall(true, GlobalContext.get().getCameraAbilityWant().action);
462      this.initStateMode(action);
463    } else {
464      this.state.faCall(false);
465      this.state.thirdPartyCall(false, "");
466    }
467    Log.info(`${this.TAG} calledByOther invoke X: ${this.state.mode}`);
468  }
469
470  private initStateMode(action: string): void {
471    switch (action) {
472      case wantConstant.Action.ACTION_IMAGE_CAPTURE:
473        this.state.initMode('PHOTO');
474        this.state.updateModeIndex(1);
475        break;
476      case wantConstant.Action.ACTION_VIDEO_CAPTURE:
477        this.state.initMode('VIDEO');
478        this.state.updateModeIndex(2);
479        break;
480      default:
481        Log.info(`${this.TAG} FA default`);
482        break;
483    }
484  }
485
486  private updateCameraStatus(): void {
487    Log.info(`${this.TAG} updateCameraStatus  cameraStatus: ${GlobalContext.get().getT<string>('cameraStatus')}
488      cameraNeedStatus: ${GlobalContext.get().getT<string>('cameraNeedStatus')}`);
489    if (this.canInit() && GlobalContext.get().getT<string>('cameraNeedStatus') == CameraNeedStatus.CAMERA_NEED_INIT) {
490      this.onForegroundInit();
491    }
492    if (this.canRelease() && GlobalContext.get().getT<string>('cameraNeedStatus') == CameraNeedStatus.CAMERA_NEED_RELEASE) {
493      this.releaseCamera();
494    }
495    Log.info(`${this.TAG} updateCameraStatus X`);
496  }
497
498  private canInit(): boolean {
499    //相机状态是首次加载或者session释放完成状态,才能进行初始化操作
500    return GlobalContext.get().getT<string>('cameraStatus') == CameraStatus.CAMERA_BEFORE_VALUE ||
501    GlobalContext.get().getT<string>('cameraStatus') == CameraStatus.CAMERA_RELEASE_FINISHED;
502  }
503
504  private canRelease(): boolean {
505    //相机状态是预览完成状态或录像完成状态才能进行释放操作
506    return GlobalContext.get().getT<string>('cameraStatus') == CameraStatus.CAMERA_PREVIEW_FINISHED ||
507    GlobalContext.get().getT<string>('cameraStatus') == CameraStatus.CAMERA_TAKE_VIDEO_FINISHED;
508  }
509
510  aboutToDisappear(): void {
511    Log.info(`${this.TAG} aboutToDisappear E`);
512    this.appEventBus.off(Action.ACTION_INIT_DONE, () => this.onCameraInit);
513    this.appEventBus.off(Action.ACTION_ON_MODE_CHANGED, () => this.onModeChanged);
514    this.appEventBus.off("windowSize", () => this.windowSizeChange);
515    this.appEventBus.off(Action.ACTION_UPDATE_CAMERA_STATUS, () => this.updateCameraStatus);
516    // this.mConnect?.destroy();
517    GeoLocation.getInstance().off();
518    GlobalContext.get().setObject('cameraNeedStatus', CameraNeedStatus.CAMERA_NEED_RELEASE)
519    this.updateCameraStatus();
520    Log.info(`${this.TAG} aboutToDisappear X`);
521  }
522
523  onPageHide(): void {
524    this.state.startVideoFlag(false);
525    Log.info(`${this.TAG} onPageHide`);
526  }
527
528  private switchAnimationSec(): void {
529    Log.info(`${this.TAG} switchAnimationSec called`);
530    animateTo({ duration: 200,
531      delay: 0,
532      curve: Curve.Sharp,
533    }, () => {
534      this.btnOpacitySec = 1;
535    })
536    animateTo({
537      duration: 350,
538      curve: Curve.FastOutSlowIn,
539      delay: 0,
540    }, () => {
541      Log.info(`${this.TAG} btnSwitchSec callback btnSwitchSec= ${this.btnSwitchSec}`);
542      this.scaleXSec = 1;
543    })
544    animateTo({
545      duration: 350,
546      curve: 'cubic-bezier(0.21, 0.27, 0.20, 1.00)',
547      delay: 0,
548      onFinish: () => {
549        Log.info(`${this.TAG} btnSwitchSec onFinish btnSwitchSec= ${this.btnSwitchSec}`);
550        this.btnSwitchSec = false;
551        this.btnOpacitySec = 0;
552        this.scaleXSec = 0.8;
553        this.rotateAngleSec = 80;
554        this.switchBackgroundAnimation();
555      }
556    }, () => {
557      Log.info(`${this.TAG} btnSwitchSec callback btnSwitchSec= ${this.btnSwitchSec}`);
558      this.rotateAngleSec = 0;
559      //      this.btnSwitchSec = true
560    })
561  }
562
563  private switchBackgroundAnimation(): void {
564    animateTo({ duration: 350,
565      delay: 0,
566      curve: Curve.Sharp,
567      onFinish: () => {
568        this.isSwitchBackground = false;
569        this.switchBackgroundOpacity = 1;
570      }
571    }, () => {
572      this.switchBackgroundOpacity = 0;
573    })
574  }
575
576  private pinchGestureStart(event: GestureEvent): void {
577    Log.info(`${this.TAG} pinchGestureStart invoke E`);
578    if (this.state.mode != 'MULTI' && this.state.cameraPosition !== 'FRONT') {
579      clearTimeout(this.pinchGestureTimer);
580      this.state.updateIsShowZoomText(true);
581      this.state.updateShowPinch(true);
582      this.state.updateShowZoomLabelValue(false);
583      this.baseZoom = this.state.zoomRatio;
584    }
585    if (this.state.mode !== "MULTI" && this.state.cameraPosition !== 'FRONT') {
586      this.state.updateIsShowZoomText(true);
587      this.state.updateShowPinch(true);
588      this.state.updateIsPhotoZoomDetails(true);
589      this.state.updateBaseZoom(this.state.zoomRatio);
590      clearTimeout(this.pinchGestureTimerId);
591      clearTimeout(this.onTouchDownTimerId);
592    }
593    Log.info(`${this.TAG} pinchGestureStart invoke X`);
594  }
595
596  private pinchGestureUpdate(event: GestureEvent): void {
597    Log.info(`${this.TAG} pinchGestureUpdate invoke E`);
598    if (this.state.mode != 'MULTI' && this.state.cameraPosition !== 'FRONT') {
599      let zoomRatio = event.scale + this.baseZoom - 1;
600      if (zoomRatio > 6) {
601        zoomRatio = 6;
602      }
603      if (zoomRatio < 1) {
604        zoomRatio = 1;
605      }
606      this.state.changeZoomRatio(zoomRatio);
607    }
608    Log.info(`${this.TAG} pinchGestureUpdate invoke X`);
609  }
610
611  private pinchGestureEnd(event: GestureEvent): void {
612    Log.info(`${this.TAG} pinchGestureEnd invoke E`);
613    this.state.updateShowZoomLabelValue(true);
614    this.state.updateShowPinch(false);
615    if (this.state.mode != 'MULTI' && this.state.cameraPosition !== 'FRONT') {
616      this.pinchGestureTimer = setTimeout(() => {
617        this.state.updateIsShowZoomText(false);
618      }, 2000)
619    }
620    Log.info(`${this.TAG} pinchGestureEnd invoke X`);
621  }
622
623  private onPreviewClicked(): void {
624    Log.info(`${this.TAG} onPreviewClicked isShowtimeLapse= ${this.state.isShowtimeLapse}, state.mode= ${this.state.mode}`);
625    if (this.state.mode === 'PHOTO' && this.state.isShowtimeLapse) {
626      this.state.changeTimeLapse(false);
627      this.state.capture();
628    } else if (this.state.mode === 'VIDEO' && this.state.isShowtimeLapse) {
629      this.state.changeTimeLapse(false);
630      this.state.startRecording();
631    }
632    Log.info(`${this.TAG} onPreviewClicked invoke X`);
633  }
634
635  private swipeChangeMode(swipe: number): void {
636    Log.info(`${this.TAG} swipeChangeMode E`);
637    if (!this.state.modeChangeDone && this.state.modeIndex + swipe >= 0 && this.state.modeIndex + swipe <= this.modeArray.length - 1 && !this.state.isShowtimeLapse) {
638      this.state.swipeChangeMode(this.state.modeIndex + swipe);
639      this.state.swipeModeChangeDone(true);
640    }
641    Log.info(`${this.TAG} swipeChangeMode X`);
642  }
643
644  private onKeepScreen(data: KeepScreenData): void {
645    Log.info(`${this.TAG} onKeepScreen E`);
646    if (data) {
647      GlobalContext.get().getCameraWinClass().setKeepScreenOn(data.isKeepScreenOn).then((v) => {
648        Log.info('Succeeded in setting the screen to be always on. Data: ' + JSON.stringify(v));
649      }).catch((err: BusinessError) => {
650        Log.error('Failed to set the screen to be always on. Cause: ' + JSON.stringify(err));
651      });
652    }
653    Log.info(`${this.TAG} onKeepScreen X`);
654  }
655
656  private windowSizeChange(data: ScreenSizeType): void {
657    if (this.screenSize != data) {
658      this.screenSize = data;
659      this.resetScreenSize(data);
660    }
661  }
662
663  private resetScreenSize(size: ScreenSizeType): void {
664    this.settingManager.setScreenHeight(size.height);
665    this.settingManager.setScreenWidth(size.width);
666    let xComponentSize = this.settingManager.getPreviewDisplaySize(this.state.mode);
667    Log.info(this.TAG + " PreviewArea xComponentSize = " + JSON.stringify(xComponentSize));
668    this.state.changeXComponentSize(xComponentSize.width, xComponentSize.height);
669  }
670
671  private async onScreenChange(isScreenOn: boolean) {
672    Log.info(`${this.TAG} onScreenChanged E isScreenOn: ${isScreenOn}`);
673    if (!isScreenOn) {
674      GlobalContext.get().setObject('keepCameraZoomRatio', true);
675      if (this.state.isShowPageView) {
676        this.state.hideSettingView();
677      }
678    }
679    Log.info(`${this.TAG} onScreenChanged X`);
680  }
681
682  build() {
683    Column() {
684      if (this.state.isShowPreview) {
685        Stack() {
686          XComponent({
687            id: '',
688            type: 'surface',
689            libraryname: '',
690            controller: GlobalContext.get().getXComponentController()
691          })
692            .onLoad(() => {
693              Log.end(Log.X_COMPONENT_LIFE);
694              Log.info(`${this.TAG} XComponent_onLoad`);
695              let surfaceId: string = GlobalContext.get().getXComponentController().getXComponentSurfaceId();
696              this.state.prepareSurface(surfaceId);
697              this.doCameraAction();
698            })
699            .width(this.state.xComponentWidth)
700            .height(this.state.xComponentHeight)
701            .animation({
702              duration: 100,
703              curve: Curve.Sharp,
704              delay: 0,
705              iterations: 1,
706              playMode: PlayMode.Normal
707            })
708
709          if (this.isSwitchBackground) {
710            Column() {
711            }
712            .width(this.state.xComponentWidth)
713            .height(this.state.xComponentHeight)
714            .backgroundColor('#000')
715            .opacity(this.switchBackgroundOpacity)
716          }
717
718          if (this.btnSwitch) {
719            Image($r('app.media.whitePicture'))
720              .width(this.state.xComponentWidth)
721              .height(this.state.xComponentHeight)
722              .syncLoad(false)
723              .scale({ x: this.scaleX, y: 1.0 })
724              .rotate({ x: 0, y: 10, z: 0, angle: this.rotateAngle })
725                // .opacity(this.state.btnOpacity_first)
726              .onComplete(() => { /* this.switchAnimation() */
727              })
728          }
729
730          if (this.btnSwitchSec) {
731            Image($r('app.media.whitePicture'))
732              .width(this.state.xComponentWidth)
733              .height(this.state.xComponentHeight)
734              .syncLoad(false)
735              .scale({ x: this.scaleX, y: 1.0 })
736              .rotate({ x: 0, y: 10, z: 0, angle: this.rotateAngleSec })
737                // .opacity(this.state.btnOpacity_sec)
738              .onComplete(() => { /* this.switchAnimationSec() */
739              })
740          }
741
742          if (this.state.isShowFlashBlack) {
743            ShowFlashBlack();
744          }
745
746          if (this.state.isShowZoomText && deviceInfo.deviceType !== "default" && !this.state.isShowtimeLapse) {
747            Stack({ alignContent: Alignment.Top }) {
748              Column() {
749                Column() {
750                  ZoomText({ state: $state })
751                }
752                .width('100%')
753                .height('100%')
754              }
755              .width('100%')
756              .height('100%')
757              .alignItems(HorizontalAlign.Start)
758            }
759            .width('100%')
760            .height('96%')
761          }
762
763          if (this.state.isAssGridViewShow === '1' && this.state.mode !== 'MORE') {
764            AssistiveGridView();
765          }
766
767          if (this.state.isSmallVideoTimerVisible) {
768            Column() {
769              SmallVideoTimer();
770            }
771            .width('100%')
772            .height('100%')
773            .alignItems(HorizontalAlign.Start)
774          }
775          if (this.state.isBigVideoTimerVisible) {
776            Column() {
777              BigVideoTimer();
778            }
779            .width('100%')
780            .height('100%')
781            .alignItems(HorizontalAlign.Start)
782          }
783          if (this.state.isShowtimeLapse) {
784            Flex({ direction: FlexDirection.Column, alignItems: ItemAlign.Center, justifyContent: FlexAlign.Center }) {
785              Column() {
786                TimeLapseView();
787              }.width('100%').height(150)
788            }.width('100%').height('100%')
789          }
790          if (this.state.showBlur) {
791            Column()
792              .width(this.isShowBlurSize.width)
793              .height(this.isShowBlurSize.height)
794              .backgroundColor(Color.Black)
795              .border({ width: { top: 0.5, bottom: 0.5 }, color: Color.Black })
796          }
797
798          Stack() {
799            if (this.state.isShowBigText) {
800              Stack({ alignContent: Alignment.BottomStart }) {
801                Column() {
802                  Column() {
803                    BigText()
804                  }
805                  .width('100%')
806                  .height('100%')
807                }
808                .width('100%')
809                .height('96vp')
810                .alignItems(HorizontalAlign.Start)
811              }
812              .width('100%')
813              .height('100%')
814            }
815          }
816          .width(this.screenSize.width > this.screenSize.height ? this.screenSize.height : this.screenSize.width)
817          .height(this.screenSize.height > (this.screenSize.width * 9 / 16) ? (this.screenSize.width * 9 / 16) :
818          this.screenSize.height)
819        }
820        .width('100%')
821        .height('100%')
822      }
823    }
824    .width(this.state.xComponentWidth)
825    .height(this.state.xComponentHeight)
826    .margin({ top: 0 })
827    .backgroundColor('#000')
828    .gesture(
829    GestureGroup(
830    GestureMode.Exclusive,
831    TapGesture({ fingers: 1, count: 1 })
832      .onAction(() => this.onPreviewClicked),
833    PinchGesture({ fingers: 2, distance: 1 })
834      .onActionStart(() => this.pinchGestureStart)
835      .onActionUpdate(() => this.pinchGestureUpdate)
836      .onActionEnd(() => this.pinchGestureEnd),
837    PanGesture({ fingers: 1, direction: PanDirection.Up, distance: 10 })
838      .onActionEnd(() => {
839        if (!this.state.isThirdPartyCall && !this.state.isFaCall) {
840          this.swipeChangeMode(1);
841        }
842      }),
843    PanGesture({ fingers: 1, direction: PanDirection.Down, distance: 10 })
844      .onActionEnd(() => {
845        if (!this.state.isThirdPartyCall && !this.state.isFaCall) {
846          this.swipeChangeMode(-1);
847        }
848      })
849    )
850    )
851  }
852}