-
Notifications
You must be signed in to change notification settings - Fork 5
/
VideoPage.tsx
135 lines (126 loc) · 4.22 KB
/
VideoPage.tsx
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
import {Box, Spacer, Stack, Text} from '@chakra-ui/layout'
import {Button} from '@chakra-ui/react'
import {navigate, Redirect, routes} from '@redwoodjs/router'
import {MetaTags} from '@redwoodjs/web'
import {requestMediaPermissions} from 'mic-check'
import {useCallback, useContext, useEffect, useRef, useState} from 'react'
import ReactPlayer from 'react-player'
import Webcam from 'react-webcam'
import {RLink} from 'src/components/links'
import {maybeCidToUrl} from 'src/components/SquareBox'
import UserContext from 'src/layouts/UserContext'
import {signUpSlice} from 'src/state/signUpSlice'
import {useAppDispatch, useAppSelector} from 'src/state/store'
const VideoPage = ({mockRecording = false}) => {
const {ethereumAddress} = useContext(UserContext)
if (!ethereumAddress) return <Redirect to={routes.signUpIntro()} />
const {photo, video} = useAppSelector((state) => state.signUp)
if (!photo) return <Redirect to={routes.signUpPhoto()} />
// Make sure we have camera permissions
useEffect(() => {
requestMediaPermissions().catch(() => navigate(routes.signUpAllowCamera()))
}, [])
const webcamRef = useRef<Webcam>(null)
const dispatch = useAppDispatch()
const [recording, setRecording] = useState(mockRecording)
const mediaRecorderRef = React.useRef<MediaRecorder>(null)
const startRecording = useCallback(async () => {
setRecording(true)
// @ts-expect-error TODO: why are we assigning to a supposedly readonly ref
// here? Just copied the example from
// https://codepen.io/mozmorris/pen/yLYKzyp?editors=0010
mediaRecorderRef.current = new MediaRecorder(webcam.current.stream, {
mimeType: 'video/webm',
})
mediaRecorderRef.current.addEventListener('dataavailable', ({data}) => {
// Create a copy of the blob with the mime type set to 'video/webm'.
// Without this at least on MacOS/Chrome I get a mime type of
// video/x-matroska;codecs=avc1,opus, which Infura refuses to accept
// as a valid mime-type when uploading the video.
const video = data.slice(0, data.size, 'video/webm')
dispatch(signUpSlice.actions.setVideo(URL.createObjectURL(video)))
})
mediaRecorderRef.current.start()
}, [webcamRef.current, setRecording, mediaRecorderRef.current])
const stopRecording = useCallback(() => {
mediaRecorderRef.current?.stop()
setRecording(false)
}, [mediaRecorderRef, setRecording])
return (
<Stack spacing="6" flex="1">
<Box background="black" width="100%">
{video ? (
<ReactPlayer
url={maybeCidToUrl(video)}
controls
width="100%"
height="100%"
/>
) : (
<Webcam
videoConstraints={{facingMode: 'user', width: 1280, height: 720}}
audio
muted
mirrored
ref={webcamRef}
/>
)}
</Box>
<Spacer display={['initial', 'none']} />
<MetaTags title="Record Video" />
{!recording && !video && (
<>
<Text>
Ready to be sworn in? Just read the words on the next screen.
</Text>
<Button
onClick={startRecording}
colorScheme="purple"
alignSelf="center"
>
I'm ready, start recording
</Button>
</>
)}
{recording && (
<>
<Text>
Say this:
<br />
<strong>
"I swear that this is my first time registering on Zorro"
</strong>
</Text>
<Button
onClick={stopRecording}
colorScheme="purple"
alignSelf="center"
>
Stop recording
</Button>
</>
)}
{video && !recording && (
<>
<Button
colorScheme="purple"
onClick={() => dispatch(signUpSlice.actions.setVideo(undefined))}
alignSelf="center"
>
Redo video
</Button>
<Button
as={RLink}
href={routes.signUpEmail()}
colorScheme="purple"
alignSelf="center"
px="12"
>
Continue
</Button>
</>
)}
</Stack>
)
}
export default VideoPage