Last active
October 6, 2020 19:08
-
-
Save alithom123/49aa5aef520f69092234ed67286b2049 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import React, { useState, useEffect, useContext, useRef } from "react" | |
import { | |
Text, | |
View, | |
TouchableOpacity, | |
Button, | |
StyleSheet, | |
Modal, | |
SafeAreaView, | |
Dimensions, | |
} from "react-native" | |
import { DevContext } from "../../context/context" | |
import { KCDefaultButton } from "../../components" | |
import { Camera } from "expo-camera" | |
import { Video } from "expo-av" | |
import theme from "../../constants/theme" | |
import { apiUploadContribution } from "../../api" | |
import { AuthContext } from "../../context/context" | |
import { | |
EvilIcons, | |
SimpleLineIcons, | |
Octicons, | |
MaterialIcons, | |
MaterialCommunityIcons, | |
Feather, | |
} from "@expo/vector-icons" | |
import { ThemeConsumer } from "react-native-elements" | |
export default AddVideoSimple = ({ navigation, route }) => { | |
const card = route.params.card | |
const { seeBgMode, getRandomColor } = useContext(DevContext) | |
const { user } = useContext(AuthContext) | |
const [hasPermission, setHasPermission] = useState(null) | |
const [type, setType] = useState(Camera.Constants.Type.back) | |
const [videoSource, setVideoSource] = useState(null) | |
const [isRecording, setIsRecording] = useState(false) | |
const [instructions, setInstructions] = useState( | |
`You'll have up to 60s to record your message.\n\n${card.instructions}` | |
) | |
const [modalVisible, setModalVisible] = useState(false) | |
const [sixtySecondTimer, setSixtySecondTimer] = useState(60) | |
//! You need a card variable in here. | |
// const [sixtySecondTimer, setSixtySecondTimer] = useState(60) // TODO: | |
// const [threeSecondTimer, setThreeSecondTimer] = useState(3) // TODO: | |
const cameraRef = useRef() | |
// let sixtyTimer = null | |
// TODO: MENTOR. Need help on these timers. I don't understand why they're not working. | |
/* const startSixtySecondTimer = () => { | |
console.log("startSixtySecondTimer") | |
sixtyTimer = setInterval(() => { | |
console.log(`another 1s in 60`) | |
setSixtySecondTimer(sixtySecondTimer - 1) | |
}, 1000) | |
} */ | |
/* const stopSixtySecondTimer = () => { | |
console.log(`canceling 60s timer`) | |
clearInterval(sixtyTimer) | |
} */ | |
/* useEffect(() => { | |
console.log("in useEffect") | |
if (sixtySecondTimer) { | |
console.log(`resetting instructions`) | |
setInstructions(`You have ${sixtySecondTimer}s left.`) | |
} | |
}, [sixtySecondTimer]) */ | |
const takePicture = async () => { | |
if (cameraRef.current) { | |
const options = { quality: 0.5, base64: true, skipProcessing: true } | |
const data = await cameraRef.current.takePictureAsync(options) | |
const source = data.uri | |
if (source) { | |
await cameraRef.current.pausePreview() | |
// setIsPreview(true) | |
console.log("picture source", source) | |
} | |
} | |
} | |
function countdown() { | |
console.log(timeRemaining) | |
console.log("timer in countdown = ", timer) | |
timeRemaining-- | |
setSixtySecondTimer(timeRemaining) | |
if (timeRemaining == 0) { | |
// clearInterval(timer) //? This needs to happen in stopRecordingVideo() ... how do I pass it there? | |
stopVideoRecording() // within this scope timer IS defined. But when you call stopVideoRecording from outside this function timer is undefined. | |
setSixtySecondTimer(60) | |
} | |
} | |
// console.log(`setting timer to null? Doesn't this happen on every render?`) | |
let timer | |
console.log(`timer = `, timer) | |
let timeRemaining | |
const recordVideo = async () => { | |
timeRemaining = 10 | |
timer = setInterval(countdown, 1000) | |
console.log(`in recordVideo timer = `, timer) | |
console.log(`recordVideo`) | |
if (cameraRef.current) { | |
try { | |
const videoRecordPromise = cameraRef.current.recordAsync() | |
if (videoRecordPromise) { | |
// startSixtySecondTimer() | |
setIsRecording(true) | |
// setIsVideoRecording(true) | |
// setInstructions(`timeRemaining`) | |
const data = await videoRecordPromise | |
const source = data.uri | |
if (source) { | |
// setIsPreview(true) | |
console.log("video source", source) | |
setModalVisible(true) | |
setVideoSource(source) | |
} | |
} | |
} catch (error) { | |
console.warn(error) | |
setModalVisible(true) //! Temporary | |
setVideoSource({}) //! Temporary | |
} | |
} | |
} | |
const stopVideoRecording = () => { | |
console.log("stopVideoRecording") | |
if (cameraRef.current) { | |
console.log("running") | |
// setIsPreview(false) | |
// setIsVideoRecording(false) | |
setIsRecording(false) | |
clearInterval(timer) //? This didn't work. | |
console.log(`trying to clear timer = `, timer) | |
cameraRef.current.stopRecording() | |
// stopSixtySecondTimer() | |
} | |
} | |
const handleAcceptVideo = () => { | |
const asyncWrap = async () => { | |
try { | |
console.log("in here") | |
const response = await apiUploadContribution( | |
"wrongnamedfield.mov", | |
videoSource, | |
card.id, | |
user.id, | |
"video", | |
"This is my video contribution!", | |
"Hello from Ali", | |
0 //! order, I want to get rid of this | |
) | |
console.log(`response from video upload`, response) | |
let updatedCard | |
if (response.data.doc) { | |
updatedCard = response.data.doc | |
} | |
console.log(`updatedCard`, updatedCard) | |
// navigation.navigate("ActiveStackShare", { card: updatedCard, videoUri: videoSource }) | |
navigation.navigate("ActiveStackPreview", { card: updatedCard }) | |
} catch (error) { | |
console.log("Error on handleAcceptVideo", error) | |
} | |
} | |
asyncWrap() | |
} | |
const handleRejectVideo = () => { | |
setModalVisible(false) | |
} | |
useEffect(() => { | |
;(async () => { | |
const { status } = await Camera.requestPermissionsAsync() | |
setHasPermission(status === "granted") | |
})() | |
}, []) | |
if (hasPermission === null) { | |
return <View /> | |
} | |
if (hasPermission === false) { | |
return <Text>No access to camera</Text> | |
} | |
return ( | |
<View style={styles.screen}> | |
<Modal | |
animationType="slide" | |
transparent={false} | |
visible={modalVisible} | |
onRequestClose={() => { | |
Alert.alert("Modal has been closed.") | |
}} | |
> | |
<SafeAreaView style={styles.modal}> | |
<Video | |
source={{ uri: videoSource }} | |
shouldPlay={true} | |
useNativeControls={true} | |
// onReadyForDisplay={{ naturalSize: { orientation: "landscape", width: 100, height: 100 } }} | |
style={styles.videoPlaybackScreen} | |
/> | |
<View style={styles.acceptVideoControls}> | |
<KCDefaultButton | |
title="Accept" | |
style={styles.acceptButton} | |
onPress={handleAcceptVideo} | |
/> | |
<KCDefaultButton | |
title="Cancel" | |
style={styles.rejectButton} | |
// onPress={() => setModalVisible(false)} | |
onPress={handleRejectVideo} | |
/> | |
</View> | |
</SafeAreaView> | |
</Modal> | |
<Camera ref={cameraRef} style={{ flex: 1, backgroundColor: "purple" }} type={type}> | |
<View | |
style={{ | |
flex: 1, | |
padding: 20, | |
// margin: 10, | |
// backgroundColor: "blue", | |
// opacity: 0.2, | |
flexDirection: "column", | |
}} | |
> | |
<View style={styles.recordDotContainer}> | |
{isRecording ? <View style={styles.recordDot} /> : null} | |
</View> | |
{!isRecording ? ( | |
<TouchableOpacity | |
style={{ | |
// flex: 0.1, | |
// backgroundColor: "red", | |
opacity: 0.5, | |
// alignSelf: "flex-end", | |
alignItems: "center", | |
}} | |
onPress={() => { | |
navigation.navigate("ActiveStackShare", { card }) | |
}} | |
> | |
<Text style={{ fontSize: 18, marginVertical: 10, color: "white" }}> Skip </Text> | |
</TouchableOpacity> | |
) : null} | |
</View> | |
<View style={styles.instructionsBar}> | |
<Text style={styles.instructionsBarText}>{instructions}</Text> | |
</View> | |
<View style={styles.videoControlBar}> | |
<TouchableOpacity | |
onPress={() => { | |
console.log(`hitting flip button button`) | |
type == Camera.Constants.Type.back | |
? setType(Camera.Constants.Type.front) | |
: setType(Camera.Constants.Type.back) | |
}} | |
> | |
<Feather name={"rotate-ccw"} size={24} /> | |
</TouchableOpacity> | |
<TouchableOpacity | |
// onPress={takePicture} // TODO: Click to record, not hold | |
// onLongPress={recordVideo} | |
// onPressOut={stopVideoRecording} | |
onPress={isRecording ? stopVideoRecording : recordVideo} | |
> | |
<View style={styles.recordButtonOuterCircle}> | |
<View style={styles.recordButtonInnerCircle}></View> | |
</View> | |
</TouchableOpacity> | |
{/* <Button title="Record"></Button> */} | |
<TouchableOpacity | |
onPress={() => { | |
navigation.goBack() | |
}} | |
> | |
{/* <Feather name={"x"} size={24} /> */} | |
<Text style={{ width: 30 }}>{`${sixtySecondTimer}s`}</Text> | |
</TouchableOpacity> | |
</View> | |
</Camera> | |
</View> | |
) | |
} | |
const styles = StyleSheet.create({ | |
screen: { flex: 1 }, | |
videoControlBar: { | |
flexDirection: "row", | |
justifyContent: "space-around", | |
alignItems: "center", | |
backgroundColor: theme.COLORS.PURPLE, | |
height: "15%", | |
}, | |
instructionsBar: { | |
alignItems: "center", | |
// margin: 20, | |
padding: 25, | |
// borderStyle: "solid", | |
// borderColor: "red", | |
// borderWidth: 1, | |
backgroundColor: "black", | |
opacity: 0.5, | |
// backgroundColor: "transparent", | |
}, | |
instructionsBarText: { | |
color: "white", | |
textAlign: "center", | |
}, | |
recordButtonOuterCircle: { | |
width: 64, | |
height: 64, | |
borderWidth: 4, | |
borderColor: "white", | |
// backgroundColor: "purple", | |
borderRadius: 32, | |
justifyContent: "center", | |
alignItems: "center", | |
}, | |
recordButtonInnerCircle: { | |
width: 52, | |
height: 52, | |
backgroundColor: theme.COLORS.RED, | |
borderRadius: 26, | |
}, | |
modal: { | |
// height: "100%", | |
flex: 1, | |
backgroundColor: theme.COLORS.GREY, | |
// height: 400, | |
}, | |
videoPlaybackScreen: { | |
flex: 1, | |
backgroundColor: "blue", | |
// width: Dimensions.get("window").width, | |
// height: Dimensions.get("window").height, | |
// height: 600, | |
// height: "100%", | |
// width: "100%", | |
}, | |
acceptVideoControls: { | |
flexDirection: "row", | |
justifyContent: "space-around", | |
// flex: 1, | |
// height: "15%", | |
}, | |
acceptButton: { | |
flex: 1, | |
backgroundColor: theme.COLORS.GREEN, | |
}, | |
rejectButton: { | |
flex: 1, | |
backgroundColor: theme.COLORS.RED, | |
}, | |
recordDot: { | |
borderRadius: 3, | |
height: 6, | |
width: 6, | |
backgroundColor: "#ff0000", | |
marginHorizontal: 5, | |
alignSelf: "flex-end", | |
}, | |
recordDotContainer: { | |
// backgroundColor: "green", | |
}, | |
}) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment