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 { getStore, OhCombinedState } from '@ohos/common/src/main/ets/default/redux/store' 20import { Log } from '@ohos/common/src/main/ets/default/utils/Log' 21 22let localState = (state: OhCombinedState) => { 23 return { 24 recordingTime: state.RecordReducer.recordingTime, 25 recordingTimeDisplay: state.RecordReducer.recordingTimeDisplay, 26 isRecordingPaused: state.RecordReducer.isRecordingPaused, 27 isRecordingSpotVisible: state.RecordReducer.isRecordingSpotVisible, 28 } 29} 30 31let localDispatcher = (dispatch) => { 32 return { 33 updateSpotVisible: (visible: boolean) => { 34 dispatch(Action.updateRecordingSpotVisible(visible)) 35 }, 36 updateRecordingTime: (recordingTime: number) => { 37 dispatch(Action.updateRecordingTime(recordingTime)) 38 }, 39 updateRecordingTimeDisplay: (timeDisplay: string) => { 40 dispatch(Action.updateRecordingTimeDisplay(timeDisplay)) 41 } 42 } 43} 44 45class StateStruct { 46 recordingTime 47 recordingTimeDisplay 48 isRecordingPaused 49 isRecordingSpotVisible 50 updateSpotVisible: Function 51 updateRecordingTime: Function 52 updateRecordingTimeDisplay: Function 53} 54 55@Component 56export struct SmallVideoTimer { 57 private TAG: string = '[SmallVideoTimer]' 58 private timer: number = 0 59 private timerTick: number = 0 60 private appEventBus: EventBus = EventBusManager.getInstance().getEventBus() 61 @State state: StateStruct = new StateStruct() 62 63 private async onRecordPausedSmall(data) { 64 Log.info(`${this.TAG} onRecordPaused timer id: ${this.timer} E`) 65 clearInterval(this.timer) 66 Log.info(`${this.TAG} onRecordPaused X`) 67 } 68 69 private async onRecordResumedSmall(data) { 70 Log.info(`${this.TAG} onRecordResumed E`) 71 this.setIntervalTimer() 72 Log.info(`${this.TAG} onRecordResumed timer id: ${this.timer} X`) 73 } 74 75 aboutToAppear(): void { 76 Log.info(`${this.TAG} aboutToAppear E`) 77 getStore().connect(localState, localDispatcher)(this.state) 78 this.setIntervalTimer() 79 this.appEventBus.on(Action.ACTION_RECORD_PAUSE, this.onRecordPausedSmall.bind(this)) 80 this.appEventBus.on(Action.ACTION_RECORD_RESUME, this.onRecordResumedSmall.bind(this)) 81 Log.info(`${this.TAG} aboutToAppear X`) 82 } 83 84 aboutToDisappear(): void { 85 Log.info(`${this.TAG} aboutToDisappear E`) 86 this.appEventBus.off(Action.ACTION_RECORD_PAUSE, this.onRecordPausedSmall.bind(this)) 87 this.appEventBus.off(Action.ACTION_RECORD_RESUME, this.onRecordResumedSmall.bind(this)) 88 clearInterval(this.timer) 89 Log.info(`${this.TAG} aboutToDisappear X`) 90 } 91 92 private setIntervalTimer() { 93 clearInterval(this.timer) 94 this.timer = setInterval(() => { 95 this.timerTick++ 96 if (this.timerTick % 2 === 0) { 97 this.state.updateRecordingTime(this.state.recordingTime + 1) 98 let shownSec = '00' 99 let shownMin = '00' 100 let sec = this.state.recordingTime % 60 101 if (sec < 10) { 102 shownSec = `0${sec}` 103 } else { 104 shownSec = `${sec}` 105 } 106 let minute = Math.floor(this.state.recordingTime / 60) 107 if (minute < 10) { 108 shownMin = `0${minute}` 109 } else { 110 shownMin = `${minute}` 111 } 112 this.state.updateRecordingTimeDisplay(`${shownMin}:${shownSec}`) 113 } 114 this.state.updateSpotVisible(!this.state.isRecordingSpotVisible) 115 }, 500) 116 } 117 118 build() { 119 Flex({ direction: FlexDirection.Row, alignItems: ItemAlign.Center, justifyContent: FlexAlign.Center }) { 120 Flex({ direction: FlexDirection.Row, alignItems: ItemAlign.Center, justifyContent: FlexAlign.End }) { 121 if (this.state.isRecordingPaused) { 122 Image($r('app.media.ic_video_recording')).width(12).height(12).fillColor(Color.White) 123 } else { 124 if (this.state.isRecordingSpotVisible) { 125 Column() { 126 } 127 .width(12) 128 .height(12) 129 .backgroundColor('#FF0000') 130 .borderRadius(6) 131 .visibility(Visibility.Visible) 132 } else { 133 Column() { 134 } 135 .width(12) 136 .height(12) 137 .backgroundColor('#FF0000') 138 .borderRadius(6) 139 .visibility(Visibility.Hidden) 140 } 141 } 142 Text(`${this.state.recordingTimeDisplay.split(':')[0]}`) 143 .margin({ left: 8 }) 144 .fontSize('28fp') 145 .fontWeight(300) 146 .fontColor('#FFFFFF') 147 //TODO 需要确认UX样式 148 // Text(this.showMinute).margin({ left: 8 }).fontSize('28fp').fontWeight(300).fontColor('#FFFFFF') 149 }.layoutWeight(1) 150 151 Text(":").fontSize('28fp').fontWeight(300).fontColor('#FFFFFF') 152 Text(`${this.state.recordingTimeDisplay.split(':')[1]}`) 153 .fontSize('28fp') 154 .fontWeight(300) 155 .fontColor('#FFFFFF') 156 .textAlign(TextAlign.Start) 157 .align(Alignment.Start) 158 .layoutWeight(1) 159 // Text(this.showSecond).fontSize('28fp').fontWeight(300).fontColor('#FFFFFF').textAlign(TextAlign.Start).layoutWeight(1) 160 }.width('100%').height(48) 161 } 162}