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 { EventBus } from '@ohos/common/src/main/ets/default/worker/eventbus/EventBus'; 18import { EventBusManager } from '@ohos/common/src/main/ets/default/worker/eventbus/EventBusManager'; 19import { Dispatch, getStore, OhCombinedState } from '@ohos/common/src/main/ets/default/redux/store'; 20import { Log } from '@ohos/common/src/main/ets/default/utils/Log'; 21import { GlobalContext } from '@ohos/common/src/main/ets/default/utils/GlobalContext'; 22 23class StateStruct { 24 recordingTime: number = 0; 25 recordingTimeDisplay: string = ''; 26 isRecordingPaused: boolean = false; 27 isRecordingSpotVisible: boolean = true; 28 isThirdPartyCall: boolean = false; 29} 30 31class SmallVideoTimerDispatcher { 32 private mDispatch: Dispatch = (data) => data; 33 34 public setDispatch(dispatch: Dispatch) { 35 this.mDispatch = dispatch; 36 } 37 38 public updateSpotVisible(visible: boolean): void { 39 this.mDispatch(Action.updateRecordingSpotVisible(visible)); 40 } 41 42 public updateRecordingTime(recordingTime: number): void { 43 this.mDispatch(Action.updateRecordingTime(recordingTime)); 44 } 45 46 public updateRecordingTimeDisplay(timeDisplay: string): void { 47 this.mDispatch(Action.updateRecordingTimeDisplay(timeDisplay)); 48 } 49 50 public stopRecording(): void { 51 this.mDispatch(Action.stopRecording()) 52 this.mDispatch(Action.updateVideoState('beforeTakeVideo')) 53 this.mDispatch(Action.updateBigVideoTimerVisible(false)) 54 this.mDispatch(Action.updateSmallVideoTimerVisible(false)) 55 this.mDispatch(Action.updateScreenStatus(false)) 56 } 57} 58 59@Component 60export struct SmallVideoTimer { 61 private TAG: string = '[SmallVideoTimer]'; 62 private timer: number = 0; 63 private timerTick: number = 0; 64 private appEventBus: EventBus = EventBusManager.getInstance().getEventBus(); 65 @State state: StateStruct = new StateStruct(); 66 private mAction: SmallVideoTimerDispatcher = new SmallVideoTimerDispatcher(); 67 68 private async onRecordPausedSmall() { 69 Log.info(`${this.TAG} onRecordPaused timer id: ${this.timer} E`) 70 clearInterval(this.timer) 71 Log.info(`${this.TAG} onRecordPaused X`) 72 } 73 74 private async onRecordResumedSmall() { 75 Log.info(`${this.TAG} onRecordResumed E`) 76 this.setIntervalTimer() 77 Log.info(`${this.TAG} onRecordResumed timer id: ${this.timer} X`) 78 } 79 80 aboutToAppear(): void { 81 Log.info(`${this.TAG} aboutToAppear E`) 82 getStore().subscribe((state: OhCombinedState) => { 83 this.state = { 84 recordingTime: state.recordReducer.recordingTime, 85 recordingTimeDisplay: state.recordReducer.recordingTimeDisplay, 86 isRecordingPaused: state.recordReducer.isRecordingPaused, 87 isRecordingSpotVisible: state.recordReducer.isRecordingSpotVisible, 88 isThirdPartyCall: state.contextReducer.isThirdPartyCall, 89 }; 90 }, (dispatch: Dispatch) => { 91 this.mAction.setDispatch(dispatch); 92 }); 93 94 this.setIntervalTimer() 95 this.appEventBus.on(Action.ACTION_RECORD_PAUSE, () => this.onRecordPausedSmall()) 96 this.appEventBus.on(Action.ACTION_RECORD_RESUME, () => this.onRecordResumedSmall()) 97 Log.info(`${this.TAG} aboutToAppear X`) 98 } 99 100 aboutToDisappear(): void { 101 Log.info(`${this.TAG} aboutToDisappear E`) 102 this.appEventBus.off(Action.ACTION_RECORD_PAUSE, () => this.onRecordPausedSmall()) 103 this.appEventBus.off(Action.ACTION_RECORD_RESUME, () => this.onRecordResumedSmall()) 104 clearInterval(this.timer) 105 Log.info(`${this.TAG} aboutToDisappear X`) 106 } 107 108 private setIntervalTimer(): void { 109 clearInterval(this.timer) 110 this.timer = setInterval(() => { 111 this.timerTick++ 112 if (this.timerTick % 2 === 0) { 113 this.mAction.updateRecordingTime(this.state.recordingTime + 1) 114 let shownSec = '00' 115 let shownMin = '00' 116 let sec = this.state.recordingTime % 60 117 if (sec < 10) { 118 shownSec = `0${sec}` 119 } else { 120 shownSec = `${sec}` 121 } 122 let minute = Math.floor(this.state.recordingTime / 60) 123 if (minute < 10) { 124 shownMin = `0${minute}` 125 } else { 126 shownMin = `${minute}` 127 } 128 this.mAction.updateRecordingTimeDisplay(`${shownMin}:${shownSec}`) 129 } 130 this.mAction.updateSpotVisible(!this.state.isRecordingSpotVisible) 131 if (this.state.isThirdPartyCall && GlobalContext.get().getCameraAbilityWant().parameters?.videoDuration) { 132 try { 133 let videoDuration: number = Number.parseInt(GlobalContext.get().getCameraAbilityWant().parameters?.videoDuration as string) 134 Log.info(`${this.TAG} videoDuration is ${videoDuration}`); 135 if (this.state.recordingTime >= videoDuration) { 136 this.mAction.stopRecording(); 137 } 138 } catch (error) { 139 Log.info(`${this.TAG} picker videoDuration --> ${JSON.stringify(error)}}`) 140 } 141 } 142 }, 500) 143 } 144 145 build() { 146 Flex({ direction: FlexDirection.Row, alignItems: ItemAlign.Center, justifyContent: FlexAlign.Center }) { 147 Flex({ direction: FlexDirection.Row, alignItems: ItemAlign.Center, justifyContent: FlexAlign.End }) { 148 if (this.state.isRecordingPaused) { 149 Image($r('app.media.ic_video_recording')).width(12).height(12).fillColor(Color.White) 150 } else { 151 if (this.state.isRecordingSpotVisible) { 152 Column() { 153 } 154 .width(12) 155 .height(12) 156 .backgroundColor('#FF0000') 157 .borderRadius(6) 158 .visibility(Visibility.Visible) 159 } else { 160 Column() { 161 } 162 .width(12) 163 .height(12) 164 .backgroundColor('#FF0000') 165 .borderRadius(6) 166 .visibility(Visibility.Hidden) 167 } 168 } 169 Text(`${this.state.recordingTimeDisplay.split(':')[0]}`) 170 .margin({ left: 8 }) 171 .fontSize('28fp') 172 .fontWeight(300) 173 .fontColor('#FFFFFF') 174 }.layoutWeight(1) 175 176 Text(':').fontSize('28fp').fontWeight(300).fontColor('#FFFFFF') 177 Text(`${this.state.recordingTimeDisplay.split(':')[1]}`) 178 .fontSize('28fp') 179 .fontWeight(300) 180 .fontColor('#FFFFFF') 181 .textAlign(TextAlign.Start) 182 .align(Alignment.Start) 183 .layoutWeight(1) 184 }.width('100%').height(48) 185 } 186}