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 { CameraService } from '../../camera/CameraService'; 17import { CameraId } from '../../setting/settingitem/CameraId'; 18import { Log } from '../../utils/Log'; 19import EntryComponentForMulti from './EntryComponentForMulti'; 20import { Dispatch, getStore, OhCombinedState } from '../../redux/store'; 21import { Action } from '../../redux/actions/Action'; 22 23let storageCameraId: string = AppStorage.Link('storageCameraId') as string; 24 25class StateStruct { 26} 27 28class MultiCameraDispatcher { 29 public setDispatch(dispatch: Dispatch) { 30 this.mDispatch = dispatch; 31 } 32 33 public changeCameraPosition(cameraPosition: string): void { 34 this.mDispatch(Action.uiState(false)); 35 this.mDispatch(Action.switchCamera(cameraPosition)); 36 this.mDispatch(Action.resetZoomRatio(1)); 37 } 38 39 private mDispatch: Dispatch = (data) => data; 40} 41 42 43@CustomDialog 44export default struct MultiCameraDialog { 45 controller?: CustomDialogController; 46 @State state: StateStruct = new StateStruct(); 47 @State isShowMore: boolean = false; 48 @State gridColumns: number = 12; 49 @State useSizeTypeOffset: number = 4; 50 @Link deviceType: string; 51 @StorageLink('storageCameraId') storageCameraId: string = ''; 52 private TAG: string = '[MultiCameraDialog]:'; 53 private cameraService = CameraService.getInstance(); 54 private localList: string[] = [ 55 CameraId.FRONT, 56 CameraId.BACK 57 ]; 58 @State private moreList: string[] = []; 59 private mAction: MultiCameraDispatcher = new MultiCameraDispatcher(); 60 61 cancel: () => void = () => { 62 }; 63 64 confirm: () => void = () => { 65 }; 66 67 aboutToAppear() { 68 Log.info(`${this.TAG} aboutToAppear.`) 69 getStore().subscribe((state: OhCombinedState) => { 70 this.state = {}; 71 }, (dispatch: Dispatch) => { 72 this.mAction.setDispatch(dispatch); 73 }); 74 75 let localCameraInfo = this.cameraService.getLocalCameraMap() 76 if (!localCameraInfo.get('front')) { 77 this.localList.shift() 78 } else if (!localCameraInfo.get('back')) { 79 this.localList.pop() 80 } 81 if (this.deviceType === 'phone' || this.deviceType === 'default') { 82 this.gridColumns = 4 83 this.useSizeTypeOffset = 0 84 } else { 85 this.gridColumns = 12 86 this.useSizeTypeOffset = 4 87 } 88 } 89 90 build() { 91 Flex({ direction: FlexDirection.Column, alignItems: ItemAlign.Center, justifyContent: FlexAlign.Center }) { 92 GridContainer({ columns: this.gridColumns, gutter: 12, margin: 12 }) { 93 Column() { 94 Row() { 95 Text($r('app.string.select_camera')) 96 .fontSize($r('sys.float.ohos_id_text_size_dialog_tittle')) 97 .fontColor('#E6000000') 98 .opacity(0.9) 99 .fontWeight(FontWeight.Medium) 100 .opacity($r('sys.float.ohos_id_alpha_content_primary')) 101 } 102 .width('100%') 103 .height('56vp') 104 105 Row() { 106 Text($r('app.string.local_device')) 107 .fontSize($r('sys.float.ohos_id_text_size_body2')) 108 .fontColor('#99182431') 109 .fontWeight(FontWeight.Medium) 110 } 111 .width('100%') 112 .height('48vp') 113 .padding({ top: 20, bottom: 8 }) 114 115 List() { 116 ForEach(this.localList, (item: string) => { 117 ListItem() { 118 EntryComponentForMulti({ 119 item: item, 120 localList: this.localList.toString(), 121 onChange: (data: string) => this.onChange(data) 122 }) 123 } 124 .width('100%') 125 .height(48) 126 }) 127 } 128 .listDirection(Axis.Vertical) 129 .divider({ 130 strokeWidth: '1vp', 131 color: '#33182431', 132 startMargin: 0, 133 endMargin: 12 134 }) 135 136 Row() { 137 Text($r('app.string.more_devices')) 138 .fontSize($r('sys.float.ohos_id_text_size_body2')) 139 .fontColor('#99182431') 140 .fontWeight(FontWeight.Medium) 141 } 142 .width('100%') 143 .height('48vp') 144 .padding({ top: 20, bottom: 8 }) 145 146 if (this.isShowMore) { 147 List() { 148 ForEach(this.moreList, (item: string) => { 149 ListItem() { 150 EntryComponentForMulti({ 151 item: item, 152 localList: this.localList.toString(), 153 onChange: (data: string) => this.onChange(data) 154 }) 155 } 156 .width('100%') 157 .height(48) 158 }) 159 } 160 .listDirection(Axis.Vertical) 161 .divider({ 162 strokeWidth: 0.5, 163 color: '#33000000', 164 startMargin: 0, 165 endMargin: 12 166 }) 167 } 168 169 Column() { 170 Button({ type: ButtonType.Capsule, stateEffect: true }) { 171 Text($r('app.string.cancel')) 172 .fontSize($r('sys.float.ohos_id_text_size_sub_title2')) 173 .fontColor('#1095E8') 174 .fontWeight(FontWeight.Medium) 175 .height('100%') 176 .height('100%') 177 } 178 .width('100%') 179 .height('100%') 180 .backgroundColor('#00ffffff') 181 .onClick(() => { 182 if (this.controller) { 183 this.controller.close(); 184 } 185 }) 186 } 187 .height(56) 188 .width('100%') 189 .margin({ top: 8 }).padding({ bottom: 16 }) 190 } 191 .width('100%') 192 .backgroundColor(Color.White) 193 .padding({ left: 24, right: 24 }) 194 .borderRadius($r('sys.float.ohos_id_corner_radius_default_xl')) 195 .useSizeType({ 196 xs: { span: 4, offset: this.useSizeTypeOffset }, 197 sm: { span: 4, offset: this.useSizeTypeOffset }, 198 md: { span: 4, offset: this.useSizeTypeOffset }, 199 lg: { span: 4, offset: this.useSizeTypeOffset } 200 }) 201 }.width('100%') 202 } 203 } 204 205 private onChange(item: string): void { 206 Log.info(`${this.TAG} MultiCameraPosition ${JSON.stringify(item)}`) 207 if (item.includes('BACK')) { 208 this.storageCameraId = 'BACK' 209 } else if (item.includes('FRONT')) { 210 this.storageCameraId = 'FRONT' 211 } 212 this.mAction.changeCameraPosition(item); 213 this.cancel(); 214 if (this.controller) { 215 this.controller.close(); 216 } 217 } 218}