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