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