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