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 { Action } from '@ohos/common/src/main/ets/default/redux/actions/Action'; 17import { ComponentPosition } from '@ohos/common/src/main/ets/default/utils/ComponentPosition'; 18import { EventBus } from '@ohos/common/src/main/ets/default/worker/eventbus/EventBus'; 19import { EventBusManager } from '@ohos/common/src/main/ets/default/worker/eventbus/EventBusManager'; 20import { Dispatch, OhCombinedState } from '@ohos/common/src/main/ets/default/redux/store'; 21import { getStore } from '@ohos/common/src/main/ets/default/redux/store'; 22import { Log } from '@ohos/common/src/main/ets/default/utils/Log'; 23import { 24 PersistType, 25 PreferencesService 26} from '@ohos/common/src/main/ets/default/featurecommon/preferences/PreferencesService'; 27import { SettingManager } from '@ohos/common/src/main/ets/default/setting/SettingManager'; 28 29class StateStruct { 30 isThirdPartyCall: boolean = false; 31 isFaCall: boolean = false; 32 action: string = ''; 33 uiEnable: boolean = true; 34 modeIndex: number = 0; 35 mode: string = 'PHOTO'; 36 isShowMoreList: boolean = false; 37} 38 39class ControlDispatcher { 40 private mDispatch: Dispatch = (data) => data; 41 42 public setDispatch(dispatch: Dispatch) { 43 this.mDispatch = dispatch; 44 } 45 46 public changeToMode(mode: string): void { 47 this.mDispatch(Action.uiState(false)); 48 this.mDispatch(Action.changeMode(mode)); 49 this.mDispatch(Action.updateShowBigTextFlag(true)); 50 } 51 52 public updateModeIndex(index: number): void { 53 this.mDispatch(Action.updateModeIndex(index)); 54 } 55 56 public updateShowMoreList(isShowMoreList: boolean): void { 57 this.mDispatch(Action.updateShowMoreList(isShowMoreList)); 58 } 59 60 public thirdPartyCall(isThirdPartyCall: boolean, action: string): void { 61 this.mDispatch(Action.thirdPartyCall(isThirdPartyCall, action)); 62 } 63 64 public initAction(action: string): void { 65 this.mDispatch(Action.initAction(action)); 66 } 67 68 public initMode(mode: string): void { 69 this.mDispatch(Action.initMode(mode)); 70 } 71 72 public updateListStatus(enable: boolean): void { 73 this.mDispatch(Action.uiState(enable)); 74 } 75 76 public changeXComponentSize(xComponentWidth: number, xComponentHeight: number): void { 77 this.mDispatch(Action.changeXComponentSize(xComponentWidth, xComponentHeight)); 78 } 79} 80 81class ScreenSizeType { 82 width: number = 0; 83 height: number = 0; 84} 85 86class SwipeModeIndexStruct { 87 swipeModeIndex: number = 0; 88} 89 90@Component 91export struct ControlLand { 92 private TAG: string = '[ControlLand]:'; 93 appEventBus: EventBus = EventBusManager.getInstance().getEventBus(); 94 private scroller: Scroller = new Scroller(); 95 private settingManager = SettingManager.getInstance(); 96 private modeArray: Array<string> = ['PHOTO', 'VIDEO']; //, 'MORE' 97 private touchOff: boolean = true; 98 private scrollDistance: number = 0; 99 protected mPreferencesService: PreferencesService = PreferencesService.getInstance(); 100 @State state: StateStruct = new StateStruct(); 101 private mAction: ControlDispatcher = new ControlDispatcher(); 102 @State startScroll: number = 0; 103 @State endScroll: number = 0; 104 @State index: number = 0; 105 @Link screenSize: ScreenSizeType; 106 107 aboutToAppear(): void { 108 Log.info(`${this.TAG} aboutToAppear E`) 109 getStore().subscribe((state: OhCombinedState) => { 110 this.state = { 111 isThirdPartyCall: state.contextReducer.isThirdPartyCall, 112 isFaCall: state.contextReducer.isFaCall, 113 action: state.contextReducer.action, 114 uiEnable: state.contextReducer.uiEnable, 115 modeIndex: state.modeReducer.modeIndex, 116 mode: state.modeReducer.mode, 117 isShowMoreList: state.modeReducer.isShowMoreList 118 }; 119 }, (dispatch: Dispatch) => { 120 this.mAction.setDispatch(dispatch); 121 }); 122 this.appEventBus.on(Action.ACTION_SWIPE_MODE, (data: SwipeModeIndexStruct) => this.swipeChangeMode(data)); 123 Log.info(`${this.TAG} aboutToAppear X`) 124 } 125 126 aboutToDisappear(): void { 127 Log.info(`${this.TAG} aboutToDisappear E`) 128 this.appEventBus.off(Action.ACTION_SWIPE_MODE, (data: SwipeModeIndexStruct) => this.swipeChangeMode(data)) 129 Log.info(`${this.TAG} aboutToDisappear X`) 130 } 131 132 private changeToMode(modeIndex: number, callType?: string): void { 133 Log.info(`${this.TAG} changeToMode modeIndex: ${modeIndex} E`); 134 this.scroller.scrollToIndex(modeIndex) 135 if (callType === 'begin') return; 136 if (this.modeArray[modeIndex] !== this.state.mode) { 137 Log.info(`${this.TAG} this.state.changeToMode(${this.modeArray[modeIndex]})`); 138 this.mAction.changeToMode(this.modeArray[modeIndex]) 139 let xComponentSize = this.settingManager.getPreviewDisplaySize(this.state.mode) 140 this.mAction.changeXComponentSize(xComponentSize.width, xComponentSize.height) 141 this.mPreferencesService.putModeValue(PersistType.FOR_AWHILE, modeIndex) 142 this.mPreferencesService.flushMode() 143 } 144 Log.info(`${this.TAG} changeToMode X`); 145 } 146 147 private getModeFontWeight(modeIndex: number): FontWeight { 148 if (this.state.mode === this.modeArray[modeIndex]) { 149 return FontWeight.Bold 150 } else { 151 return FontWeight.Regular 152 } 153 } 154 155 private swipeChangeMode(data: SwipeModeIndexStruct): void { 156 this.changeToMode(data.swipeModeIndex) 157 } 158 159 private scrollSwitchMode(callType: string): void { 160 if (this.index == 1 && Math.abs(this.scrollDistance) <= px2vp(20)) { 161 this.changeToMode(1, callType) 162 } 163 if (this.index == 1 && (this.scrollDistance) > px2vp(20)) { 164 this.changeToMode(0, callType) 165 } 166 if (this.index == 1 && (this.scrollDistance) < px2vp(-20)) { 167 this.changeToMode(2, callType) 168 } 169 if (this.index == 0 && (this.scrollDistance > px2vp(-25))) { 170 this.changeToMode(0, callType) 171 } 172 if (this.index == 0 && this.scrollDistance >= px2vp(-50) && this.scrollDistance <= px2vp(-25)) { 173 this.changeToMode(1, callType) 174 } 175 if (this.index == 0 && this.scrollDistance < px2vp(-50)) { 176 this.changeToMode(2, callType) 177 } 178 if (this.index == 2 && (this.scrollDistance < px2vp(25))) { 179 this.changeToMode(2, callType) 180 } 181 if (this.index == 2 && this.scrollDistance >= px2vp(25) && this.scrollDistance <= px2vp(50)) { 182 this.changeToMode(1, callType) 183 } 184 if (this.index == 2 && this.scrollDistance > px2vp(50)) { 185 this.changeToMode(0, callType) 186 } 187 } 188 189 build() { 190 Stack({ alignContent: Alignment.TopStart }) { 191 Flex({ direction: FlexDirection.Row, alignItems: ItemAlign.Center, justifyContent: FlexAlign.End }) { 192 if ((this.state.isThirdPartyCall || this.state.isFaCall) && this.state.mode === 'PHOTO') { 193 Flex({ direction: FlexDirection.Row, alignItems: ItemAlign.Center, justifyContent: FlexAlign.End }) { 194 Text($r('app.string.photo_mode')) 195 .fontSize($r('sys.float.ohos_id_text_size_body1')) 196 .fontColor(Color.White) 197 .fontWeight(FontWeight.Bold) 198 }.layoutWeight(1).height('100%') 199 } else if ((this.state.isThirdPartyCall || this.state.isFaCall) && this.state.mode === 'VIDEO') { 200 Flex({ direction: FlexDirection.Row, alignItems: ItemAlign.Center, justifyContent: FlexAlign.End }) { 201 Text($r('app.string.video_mode')) 202 .fontSize($r('sys.float.ohos_id_text_size_body1')) 203 .fontColor(Color.White) 204 .fontWeight(FontWeight.Bold) 205 }.layoutWeight(1).height('100%') 206 } else { 207 List({ initialIndex: this.state.modeIndex, scroller: this.scroller }) { 208 if (ComponentPosition.isUnfoldControl(this.screenSize.width, this.screenSize.height)) { 209 ListItem() { 210 }.width('100%').height(32) 211 } 212 ListItem() { 213 }.width('100%').height(32) 214 215 ListItem() { 216 Flex({ direction: FlexDirection.Row, alignItems: ItemAlign.Center, justifyContent: FlexAlign.End }) { 217 Text($r('app.string.multi_mode')) 218 .fontSize($r('sys.float.ohos_id_text_size_body1')) 219 .fontColor(Color.White) 220 .enabled(this.state.uiEnable) 221 .onClick(async () => { 222 this.changeToMode(0) 223 }) 224 .fontWeight(this.getModeFontWeight(0)) 225 }.width('100%').height('100%') 226 }.width('100%').height(32) 227 228 ListItem() { 229 Flex({ direction: FlexDirection.Row, alignItems: ItemAlign.Center, justifyContent: FlexAlign.End }) { 230 Text($r('app.string.photo_mode')) 231 .fontSize($r('sys.float.ohos_id_text_size_body1')) 232 .fontColor(Color.White) 233 .enabled(this.state.uiEnable) 234 .onClick(async () => { 235 this.changeToMode(1) 236 }) 237 .fontWeight(this.getModeFontWeight(1)) 238 }.width('100%').height('100%') 239 }.width('100%').height(32) 240 241 ListItem() { 242 Flex({ direction: FlexDirection.Row, alignItems: ItemAlign.Center, justifyContent: FlexAlign.End }) { 243 Text($r('app.string.video_mode')) 244 .fontSize($r('sys.float.ohos_id_text_size_body1')) 245 .fontColor(Color.White) 246 .enabled(this.state.uiEnable) 247 .onClick(async () => { 248 this.changeToMode(2) 249 }) 250 .fontWeight(this.getModeFontWeight(2)) 251 }.width('100%').height('100%') 252 }.width('100%').height(32) 253 254 ListItem() { 255 }.width('100%').height(32) 256 257 ListItem() { 258 }.width('100%').height(32) 259 } 260 .layoutWeight(1) 261 .height('100%') 262 .edgeEffect(EdgeEffect.None) 263 .chainAnimation(false) 264 .onScrollIndex((firstIndex: number, lastIndex: number) => { 265 Log.info(`${this.TAG} Control scroll index first: ${firstIndex}, last: ${lastIndex}`); 266 this.mAction.updateModeIndex(firstIndex) 267 Log.info(`${this.TAG} onScrollIndex this.state.modeIndex: ${this.state.modeIndex}`); 268 }) 269 // .onScrollBegin(() => { 270 // if (!this.touchOff) this.scrollSwitchMode('begin') 271 // }) 272 .enabled(this.state.uiEnable) 273 .onTouch((event: TouchEvent) => { 274 if (event.type === TouchType.Down) { 275 this.touchOff = true 276 this.index = this.modeArray.indexOf(this.state.mode) 277 this.startScroll = event.touches[0].screenY 278 } 279 if (event.type === TouchType.Up) { 280 this.endScroll = event.touches[0].screenY 281 this.scrollDistance = px2vp(this.endScroll - this.startScroll) 282 this.touchOff = false 283 this.scrollSwitchMode('touch') 284 } 285 }) 286 } 287 Flex({ direction: FlexDirection.Column, alignItems: ItemAlign.Start, justifyContent: FlexAlign.Center }) { 288 Column() { 289 }.borderRadius(3).width(6).height(6).backgroundColor('#007DFF') 290 291 // .shadow({radius: 5, color: 'argb(#7F000000)', offsetX: 0, offsetY: 0}) 292 }.width(18).height('100%').margin({ left: 8 }) 293 }.width('100%').height('100%') 294 }.width(98).height(ComponentPosition.getControlHeight(this.screenSize.width, this.screenSize.height)).zIndex(2) 295 } 296}