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