• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1/*
2 * Copyright (c) 2022 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 router from "@system.router"
17
18import { Log } from '../../utils/Log'
19import getStore from '../../redux/store'
20import { Action } from '../../redux/actions/Action'
21import { EventBus } from '../../worker/eventbus/EventBus'
22import EventBusManager from '../../worker/eventbus/EventBusManager'
23import { SettingManager } from '../../setting/SettingManager'
24import Timer from '../../setting/settingitem/Timer'
25
26let localState = (state) => {
27  return {
28    uiEnable: state.ContextReducer.uiEnable,
29    shutterIcon: state.CameraReducer.shutterIcon,
30    captureBtnScale: state.CaptureReducer.captureBtnScale,
31    videoState: state.RecordReducer.videoState,
32    mode: state.ModeReducer.mode,
33    videoUri: state.CameraInitReducer.videoUri,
34    resourceUri: state.CameraInitReducer.resourceUri,
35    isThirdPartyCall: state.ContextReducer.isThirdPartyCall,
36    xComponentWidth: state.PreviewReducer.xComponentWidth,
37    xComponentHeight: state.PreviewReducer.xComponentHeight,
38  }
39}
40
41let localDispatcher = (dispatch) => {
42  return {
43    updateSmallVideoTimerVisible: (visible: boolean) => {
44      dispatch(Action.updateSmallVideoTimerVisible(visible))
45    },
46    updateShutterIcon: (icon: Resource) => {
47      dispatch(Action.updateShutterIcon(icon))
48    },
49    capture: () => {
50      dispatch(Action.updateShowFlashBlackFlag(true))
51      dispatch(Action.capture())
52    },
53    startRecording: () => {
54      dispatch(Action.startRecording())
55      dispatch(Action.updateVideoState('startTakeVideo'))
56      dispatch(Action.updateBigVideoTimerVisible(true))
57      dispatch(Action.updateScreenStatus(true))
58    },
59    pauseRecording: () => {
60      dispatch(Action.pauseRecording())
61      dispatch(Action.updateVideoState('pauseTakeVideo'))
62    },
63    resumeRecording: () => {
64      dispatch(Action.resumeRecording())
65      dispatch(Action.updateVideoState('startTakeVideo'))
66    },
67    stopRecording: () => {
68      dispatch(Action.stopRecording())
69      dispatch(Action.updateVideoState('beforeTakeVideo'))
70      dispatch(Action.updateBigVideoTimerVisible(false))
71      dispatch(Action.updateSmallVideoTimerVisible(false))
72      dispatch(Action.updateScreenStatus(false))
73    },
74    changeTimeLapse: (isShowtimeLapse: boolean) => {
75      dispatch(Action.changeTimeLapse(isShowtimeLapse))
76    }
77  }
78}
79
80@Component
81export struct ShutterButton {
82  private TAG: string = '[ShutterButton]:'
83  private appEventBus: EventBus = EventBusManager.getInstance().getEventBus()
84  private settingManager = SettingManager.getInstance()
85
86  type: ButtonType
87  stateEffect: boolean
88
89  @State state: any = {}
90  @State captureBtnScale: number = 1
91
92  aboutToAppear() {
93    Log.debug(`${this.TAG} aboutToAppear E`)
94    getStore().connect(localState, localDispatcher)(this.state)
95    this.appEventBus.on(Action.ACTION_CHANGE_MODE, this.changeShutterIcon.bind(this))
96    this.appEventBus.on(Action.ACTION_UPDATE_THUMBNAIL, this.onThumbnailUpdate.bind(this))
97    this.appEventBus.on(Action.ACTION_INIT_MODE, this.changeShutterIcon.bind(this))
98    this.refreshIcon(this.state.mode)
99    Log.debug(`${this.TAG} aboutToAppear X`)
100  }
101
102  aboutToDisappear(): void {
103    Log.debug(`${this.TAG} aboutToDisappear E`)
104    this.appEventBus.off(Action.ACTION_CHANGE_MODE, this.changeShutterIcon.bind(this))
105    this.appEventBus.off(Action.ACTION_UPDATE_THUMBNAIL, this.onThumbnailUpdate.bind(this))
106    Log.debug(`${this.TAG} aboutToDisappear X`)
107  }
108
109  private async onThumbnailUpdate(data) {
110    Log.info(`${this.TAG} onThumbnailUpdate data: ${JSON.stringify(data)} E`)
111    Log.info(`${this.TAG} onThumbnailUpdate resourceUri= ${JSON.stringify(this.state.resourceUri)} E`)
112    Log.info(`${this.TAG} onThumbnailUpdate isThirdPartyCall= ${this.state.isThirdPartyCall} E`)
113    Log.info(`${this.TAG} onThumbnailUpdate videoUri= ${this.state.videoUri} E`)
114    if (this.state.isThirdPartyCall) {
115      Log.info(`${this.TAG} onThumbnailUpdate start router to ThirdPreviewView`)
116      router.push({
117        uri: "pages/ThirdPreviewView",
118        params: {
119          width: this.state.xComponentWidth,
120          height: this.state.xComponentHeight,
121          mode: this.state.mode,
122          uri: this.state.resourceUri,
123          videoUri: this.state.videoUri,
124          callBundleName:globalThis.cameraAbilityWant?.parameters?.callBundleName
125        }
126      })
127    }
128    Log.info(`${this.TAG} onThumbnailUpdate this.state.thumbnail: ${JSON.stringify(this.state.thumbnail)} X`)
129  }
130
131  private async changeShutterIcon(data) {
132    Log.debug(`${this.TAG} resetShutterIcon E`)
133    this.refreshIcon(data.mode)
134    Log.debug(`${this.TAG} resetShutterIcon X`)
135  }
136
137  private async refreshIcon(mode: string) {
138    Log.debug(`${this.TAG} refreshIcon E`)
139    if (mode === 'PHOTO') {
140      this.state.updateShutterIcon($r('app.media.ic_circled_filled'))
141    } else if (mode === 'VIDEO') {
142      this.state.updateShutterIcon($r('app.media.take_video_normal'))
143    } else {
144      this.state.updateShutterIcon($r('app.media.ic_circled_filled'))
145    }
146    Log.debug(`${this.TAG} refreshIcon X`)
147  }
148
149  build() {
150    if (this.state.videoState === 'beforeTakeVideo') {
151      Stack({ alignContent: Alignment.Center }) {
152        if (this.state.mode === 'VIDEO') {
153          Image(this.state.shutterIcon)
154            .width(76).aspectRatio(1).enabled(this.state.uiEnable)
155            .onTouch((event: TouchEvent) => {
156              if (event.type === TouchType.Up) {
157                let timerLapse = this.settingManager.getTimeLapse()
158                Log.log(`${this.TAG} ShutterButton startRecording getValue= ${JSON.stringify(timerLapse)}`)
159                if (timerLapse && timerLapse.id !== Timer.RESOURCE_OFF.id) {
160                  Log.log('ShutterButton startRecording changeTimeLapse called')
161                  this.state.changeTimeLapse(true)
162                } else {
163                  Log.log('ShutterButton startRecording changeTimeLapse not called')
164                  this.state.startRecording()
165                }
166              }
167            })
168        } else {
169          Image($r('app.media.ic_circled')).fillColor(Color.White)
170          Image(this.state.shutterIcon).width(54).aspectRatio(1).fillColor(Color.White)
171            .scale({ x: this.captureBtnScale, y: this.captureBtnScale, z: this.captureBtnScale })
172            .enabled(this.state.uiEnable)
173            .onTouch((event: TouchEvent) => {
174              if (event.type === TouchType.Down) {
175                animateTo(
176                  { duration: 125, curve: Curve.Sharp, delay: 0 },
177                  () => { this.captureBtnScale = 0.85 })
178              } else if (event.type === TouchType.Up) {
179                animateTo(
180                  { duration: 125, curve: Curve.Sharp, delay: 0,
181                    onFinish: () => { this.captureBtnScale = 1 }},
182                  () => { this.captureBtnScale = 1 })
183                let timerLapse = this.settingManager.getTimeLapse()
184                Log.log(`${this.TAG} ShutterButton startRecording getValue= ${JSON.stringify(timerLapse)}`)
185                if (timerLapse && timerLapse.id !== Timer.RESOURCE_OFF.id) {
186                  Log.log('ShutterButton startRecording changeTimeLapse called')
187                  this.state.changeTimeLapse(true)
188                } else {
189                  Log.log('ShutterButton startRecording changeTimeLapse not called')
190                  this.state.capture()
191                }
192              }
193            })
194        }
195      }.width(76).aspectRatio(1).margin({ left: 48, right: 48 })
196    } else {
197      Column() {
198        Flex({ direction: FlexDirection.Row, alignItems: ItemAlign.Center, justifyContent: FlexAlign.Center }) {
199          Column() {
200            Image($r('app.media.ic_video_end'))
201              .width(20)
202              .aspectRatio(1)
203              .fillColor(Color.White)
204              .enabled(this.state.uiEnable)
205          }
206          .width(40)
207          .padding({ left: 10, right: 10 })
208          .margin({ right: 6 })
209          .enabled(this.state.uiEnable)
210          .onClick(() => {
211            this.state.stopRecording()
212          })
213
214          Column() {
215            if (this.state.videoState === 'startTakeVideo') {
216              Image($r('app.media.ic_video_recording'))
217                .width(20).aspectRatio(1).fillColor(Color.White)
218                .enabled(this.state.uiEnable)
219            } else if (this.state.videoState === 'pauseTakeVideo') {
220              Image($r('app.media.ic_video_pause')).width(20).aspectRatio(1).fillColor(Color.Red)
221                .enabled(this.state.uiEnable)
222            }
223          }
224          .width(40)
225          .padding({ left: 10, right: 10 })
226          .margin({ left: 6 })
227          .enabled(this.state.uiEnable)
228          .onClick(() => {
229              this.state.videoState === 'startTakeVideo' ? this.state.pauseRecording() : this.state.resumeRecording()
230          })
231        }.width('100%').height('100%')
232      }
233      .width(120).height(56).borderRadius(28)
234      .border({ width: 1, color: Color.White, style: BorderStyle.Solid })
235      .margin({ left: 24, right: 24 })
236    }
237  }
238}