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 display from '@ohos.display'; 17import deviceInfo from '@ohos.deviceInfo'; 18import { ModeMap } from '../common/ModeMap'; 19import { Action } from '@ohos/common/src/main/ets/default/redux/actions/Action'; 20import { CameraWorker } from '@ohos/common/src/main/ets/default/worker/CameraWorker'; 21import { EventBus } from '@ohos/common/src/main/ets/default/worker/eventbus/EventBus'; 22import { EventBusManager } from '@ohos/common/src/main/ets/default/worker/eventbus/EventBusManager'; 23import { Dispatch, OhCombinedState } from '@ohos/common/src/main/ets/default/redux/store'; 24import { getStore } from '@ohos/common/src/main/ets/default/redux/store'; 25import { Log } from '@ohos/common/src/main/ets/default/utils/Log'; 26import { MoreList } from '@ohos/common/src/main/ets/default/featurecommon/moreList/moreList'; 27import { 28 PersistType, 29 PreferencesService 30} from '@ohos/common/src/main/ets/default/featurecommon/preferences/PreferencesService'; 31import { RdbStoreManager } from '@ohos/common/src/main/ets/default/setting/storage/RdbStoreManager'; 32import { TabBar } from '@ohos/common/src/main/ets/default/featurecommon/tabbar/TabBar'; 33import { ZoomView } from '@ohos/common/src/main/ets/default/featurecommon/zoomview/ZoomView'; 34import { Control } from './Control'; 35import { FootBar } from './FootBar'; 36import { PreviewArea } from './PreviewArea'; 37import { SettingView } from './SettingView'; 38import abilityAccessCtrl, { Permissions } from '@ohos.abilityAccessCtrl'; 39import { CameraId } from '@ohos/common/src/main/ets/default/setting/settingitem/CameraId'; 40import { BusinessError } from '@ohos.base'; 41import ability from '@ohos.ability.ability'; 42import { GlobalContext } from '@ohos/common/src/main/ets/default/utils/GlobalContext'; 43 44CameraWorker.getInstance(new ModeMap()); 45 46PersistentStorage.PersistProp("storageCameraId", ""); 47 48class StateStruct { 49 footBarHeight: number = 0; 50 permissionFlag: boolean = false; 51 mode: string = ''; 52 curMode: string = ''; 53 isShowtimeLapse: boolean = false; 54 videoState: string = ''; 55 isShowMoreList: boolean = false; 56 isThirdPartyCall: boolean = false; 57 showZoomLabelValue: boolean = true; 58 isShowPinch: boolean = false; 59 isShowPageView: boolean = false; 60 isInitiated: boolean = false; 61 curCameraPosition: CameraId = CameraId.BACK 62} 63 64class IndexDispatcher { 65 private mDispatch: Dispatch = (data) => data; 66 67 public setDispatch(dispatch: Dispatch) { 68 this.mDispatch = dispatch; 69 } 70 71 public initFootBarHeight(footBarHeight: number): void { 72 this.mDispatch(Action.initFootBarHeight(footBarHeight)); 73 } 74 75 public setPermissionFlag(permissionFlag: boolean): void { 76 Log.info(`CameraApp setPermissionFlag: ${permissionFlag}`); 77 this.mDispatch(Action.setPermissionFlag(permissionFlag)); 78 } 79 80 public initAction(action: string): void { 81 this.mDispatch(Action.initAction(action)); 82 } 83 84 public initCameraPosition(cameraPosition: string): void { 85 this.mDispatch(Action.setCameraPosition(cameraPosition)); 86 } 87 88 public initMode(mode: string): void { 89 this.mDispatch(Action.initMode(mode)); 90 } 91 92 public changeTimeLapse(isShowtimeLapse: boolean): void { 93 this.mDispatch(Action.changeTimeLapse(isShowtimeLapse)); 94 } 95 96 public stopRecording(): void { 97 this.mDispatch(Action.stopRecording()); 98 this.mDispatch(Action.updateVideoState('beforeTakeVideo')); 99 this.mDispatch(Action.updateBigVideoTimerVisible(false)); 100 this.mDispatch(Action.updateSmallVideoTimerVisible(false)); 101 } 102 103 public resetRecordingTime(): void { 104 this.mDispatch(Action.updateRecordingTime(0)); 105 this.mDispatch(Action.updateRecordingTimeDisplay('00:00')); 106 } 107 108 public hideSettingView(): void { 109 this.mDispatch(Action.showSettingView(false)); 110 } 111 112 public updateModeIndex(index: number): void { 113 this.mDispatch(Action.updateModeIndex(index)); 114 } 115 116 public faCall(isFaCall: boolean): void { 117 this.mDispatch(Action.faCall(isFaCall)); 118 } 119 120 public thirdPartyCall(isThirdPartyCall: boolean, action: string): void { 121 this.mDispatch(Action.thirdPartyCall(isThirdPartyCall, action)); 122 } 123} 124 125 126@Entry 127@Component 128struct Index { 129 appEventBus: EventBus = EventBusManager.getInstance().getEventBus(); 130 @State state: StateStruct = new StateStruct(); 131 protected mPreferencesService: PreferencesService = PreferencesService.getInstance(); 132 private TAG: string = '[Index]:'; 133 private modeArray: Array<string> = ['MULTI', 'PHOTO', 'VIDEO']; 134 private mAction: IndexDispatcher = new IndexDispatcher(); 135 136 aboutToAppear(): void { 137 Log.info(`${this.TAG} aboutToAppear E`); 138 let dbStore: RdbStoreManager = RdbStoreManager.getInstance(); 139 dbStore.initRdbConfig(); 140 getStore().subscribe((state: OhCombinedState) => { 141 this.state = { 142 footBarHeight: state.contextReducer.footBarHeight, 143 permissionFlag: state.contextReducer.permissionFlag, 144 mode: state.modeReducer.mode, 145 curMode: state.modeReducer.curMode, 146 isShowtimeLapse: state.settingReducer.isShowtimeLapse, 147 videoState: state.recordReducer.videoState, 148 isShowMoreList: state.modeReducer.isShowMoreList, 149 isThirdPartyCall: state.contextReducer.isThirdPartyCall, 150 showZoomLabelValue: state.zoomReducer.showZoomLabelValue, 151 isShowPinch: state.zoomReducer.isShowPinch, 152 isShowPageView: state.settingReducer.isShowSettingView, 153 isInitiated: state.modeReducer.isInitiated, 154 curCameraPosition: state.cameraReducer.curCameraPosition, 155 }; 156 }, (dispatch: Dispatch) => { 157 this.mAction.setDispatch(dispatch); 158 }) 159 display.getDefaultDisplay().then((dis) => { 160 Log.info(`${this.TAG} dis data = ${JSON.stringify(dis)}`); 161 let footBarHeight: number = 0; 162 if (deviceInfo.deviceType === "default") { 163 footBarHeight = px2vp(dis.width) * (4 / 3) - 160; 164 } else { 165 footBarHeight = px2vp(dis.width) * (4 / 3) - 82; 166 } 167 this.mAction.initFootBarHeight(footBarHeight); 168 }) 169 170 if (!this.state.permissionFlag) { 171 let permissionList: Array<Permissions> = [ 172 "ohos.permission.MEDIA_LOCATION", 173 "ohos.permission.READ_IMAGEVIDEO", 174 "ohos.permission.WRITE_IMAGEVIDEO", 175 "ohos.permission.CAMERA", 176 "ohos.permission.MICROPHONE", 177 "ohos.permission.DISTRIBUTED_DATASYNC", 178 "ohos.permission.LOCATION", 179 "ohos.permission.LOCATION_IN_BACKGROUND", 180 "ohos.permission.APPROXIMATELY_LOCATION" 181 ]; 182 Log.info(`${this.TAG} permissions need to require from user: ${JSON.stringify(permissionList)}`); 183 let atManager = abilityAccessCtrl.createAtManager(); 184 try { 185 atManager.requestPermissionsFromUser(GlobalContext.get().getCameraAbilityContext(), permissionList).then((data) => { 186 Log.info(`${this.TAG} data permissions: ${JSON.stringify(data.permissions)}`); 187 Log.info(`${this.TAG} data authResult: ${JSON.stringify(data.authResults)}`); 188 let sum = 0 189 for (let i = 0; i < data.authResults.length; i++) { 190 sum += data.authResults[i]; 191 } 192 if (sum >= 0) { 193 GlobalContext.get().setObject('permissionFlag', true); 194 this.mAction.setPermissionFlag(true); 195 } else { 196 GlobalContext.get().setObject('permissionFlag', false); 197 this.mAction.setPermissionFlag(false); 198 } 199 Log.info(`${this.TAG} request permissions result: ${GlobalContext.get().getT<boolean>('permissionFlag')}`); 200 }, (err: BusinessError) => { 201 Log.error(`${this.TAG} Failed to start ability err code: ${err.code}`); 202 }) 203 } catch (error) { 204 Log.info(`${this.TAG} catch error: ${JSON.stringify(error)}`); 205 } 206 } 207 208 if (GlobalContext.get().getCameraFormParam() != undefined) { 209 this.mAction.initAction(GlobalContext.get().getCameraFormParam().action); 210 this.mAction.initMode(GlobalContext.get().getCameraFormParam().mode); 211 GlobalContext.get().setCameraFormParam(undefined); 212 } 213 214 GlobalContext.get().setObject('stopCameraRecording', () => { 215 this.stopCameraRecording(); 216 }) 217 218 if (!this.state.isInitiated) { 219 let initIndex: number = this.mPreferencesService.getModeValue(PersistType.FOR_AWHILE, 1); 220 Log.info(`${this.TAG} initModeIndex: ${initIndex}`); 221 this.mAction.initMode(this.modeArray[initIndex]); 222 this.mAction.updateModeIndex(initIndex); 223 } 224 225 Log.info(`${this.TAG} aboutToAppear X`); 226 } 227 228 onPageShow(): void { 229 Log.info(`${this.TAG} onPageShow this.permissionFlag: ${this.state.permissionFlag} permissionFlag: ${GlobalContext.get().getT<boolean>('permissionFlag')}`); 230 this.mAction.setPermissionFlag(GlobalContext.get().getT<boolean>('permissionFlag')); 231 let curCameraId = AppStorage.Get<string>('storageCameraId'); 232 if (curCameraId) this.mAction.initCameraPosition(curCameraId); 233 this.mAction.resetRecordingTime(); 234 Log.info(`${this.TAG} onPageShow X`); 235 } 236 237 aboutToDisappear(): void { 238 Log.info(`${this.TAG} aboutToDisappear E`); 239 } 240 241 onBackPress(): boolean { 242 Log.info(`${this.TAG} onBackPress E`); 243 if (this.state.isShowPageView) { 244 this.mAction.hideSettingView(); 245 return true; 246 } else if (this.state.isShowtimeLapse) { 247 this.mAction.changeTimeLapse(false); 248 return true 249 } else if (this.state.isThirdPartyCall) { 250 this.terminateSelfWithResult(); 251 } else { 252 if (this.state.videoState === 'startTakeVideo' || this.state.videoState === 'pauseTakeVideo') { 253 this.mAction.stopRecording(); 254 return true; 255 } 256 Log.info(`${this.TAG} onBackPress X`); 257 return false; 258 } 259 return false; 260 } 261 262 onPageHide(): void { 263 Log.info(`${this.TAG} onPageHide E`); 264 this.stopCameraRecording(); 265 Log.info(`${this.TAG} onPageHide X`); 266 } 267 268 public stopCameraRecording() { 269 Log.info(`${this.TAG} stopCameraRecording E`); 270 if (this.state.isShowtimeLapse) { 271 this.mAction.changeTimeLapse(false); 272 } 273 if (this.state.videoState === 'startTakeVideo' || this.state.videoState === 'pauseTakeVideo') { 274 this.mAction.stopRecording(); 275 } 276 Log.info(`${this.TAG} stopCameraRecording X`); 277 } 278 279 terminateSelfWithResult() { 280 Log.info(`${this.TAG} terminateSelfWithResult start`); 281 let abilityResult: ability.AbilityResult = { 282 "resultCode": 200, 283 "want": { 284 "parameters": { 285 "resourceUri": "", 286 "width": "", 287 "height": "" 288 }, 289 "bundleName": "com.ohos.camera", 290 "abilityName": "com.ohos.camera.MainAbility" 291 } 292 }; 293 294 GlobalContext.get().getCameraAbilityContext().terminateSelfWithResult(abilityResult, (error:BusinessError) => { 295 if (error) { 296 Log.error(`${this.TAG} Operation failed. Cause: ${error}`); 297 return; 298 } 299 Log.info(`${this.TAG} Operation succeeded`); 300 }) 301 } 302 303 build() { 304 Stack({ alignContent: Alignment.Top }) { 305 Stack() { 306 PreviewArea() 307 }.width('100%').position({ y: 48 }) 308 309 Stack() { 310 if (deviceInfo.deviceType !== "default" && this.state.videoState === "beforeTakeVideo" && !this.state.isShowtimeLapse && this.state.showZoomLabelValue) { 311 TabBar({ onBackClicked: () => this.onBackClicked() }); 312 } 313 }.width('100%').height(48).position({ x: '0', y: '0' }) 314 315 if (this.state.isShowMoreList && this.state.showZoomLabelValue) { 316 MoreList() 317 } 318 Stack({ alignContent: Alignment.Bottom }) { 319 Column() { 320 if (this.state.mode === "PHOTO" || this.state.mode === "VIDEO") { 321 if (deviceInfo.deviceType !== "default" && this.state.curCameraPosition !== 'FRONT') { 322 Column() { 323 ZoomView() 324 } 325 .visibility(!this.state.isShowtimeLapse && !this.state.isShowPinch ? Visibility.Visible : Visibility.Hidden) 326 } 327 } 328 if (this.state.videoState === "beforeTakeVideo" && this.state.showZoomLabelValue) { 329 Column() { 330 Control() 331 } 332 .visibility((!this.state.isShowtimeLapse && this.state.showZoomLabelValue) ? Visibility.Visible : Visibility.Hidden) 333 .width('100%') 334 } 335 Column() { 336 FootBar() 337 } 338 .visibility((!this.state.isShowtimeLapse && this.state.showZoomLabelValue) ? Visibility.Visible : Visibility.Hidden) 339 } 340 }.width('100%').height(302).position({ y: this.state.footBarHeight }) 341 .visibility(!this.state.isShowtimeLapse ? Visibility.Visible : Visibility.Hidden) 342 343 if (this.state.isShowPageView) { 344 SettingView().width('100%').height('100%') 345 } 346 }.width('100%').height('100%').backgroundColor('#000') 347 } 348 349 private onBackClicked(): void { 350 Log.info(`${this.TAG} onBackClicked E`); 351 this.terminateSelfWithResult(); 352 } 353}