Skip to content

Instantly share code, notes, and snippets.

@johnwcassidy
Created Nov 3, 2020
Embed
What would you like to do?
A basic implementation of recoil in You.i Engine One
/**
* Basic You.i RN app demonstrating recoil
*/
import React, { Component, useEffect, useRef, useState } from "react";
import { AppRegistry, StyleSheet, Text, View } from "react-native";
import { Slider, Video } from "@youi/react-native-youi";
import { RecoilRoot, useRecoilState, atom } from "recoil";
const VideoCurrentTimeState = atom({
key: "videoPosition",
default: 0,
});
const VideoDurationState = atom({
key: "videoDuration",
default: 0,
});
const VideoComponent = React.forwardRef((props, ref) => {
const [ready, setReady] = useState(false);
const [, setVideoPosition] = useRecoilState(VideoCurrentTimeState);
const [, setVideoDuration] = useRecoilState(VideoDurationState);
useEffect(() => {
if (ready) {
ref?.current?.play();
}
}, [ready]);
const onDurationChanged = (duration) => {
setVideoDuration(duration);
};
const onCurrentTimeUpdated = (time) => {
setVideoPosition(time);
};
return (
<Video
style={{ flex: 1 }}
ref={ref}
source={{
type: "HLS",
uri:
"https://multiplatform-f.akamaihd.net/i/multi/april11/sintel/sintel-hd_,512x288_450_b,640x360_700_b,768x432_1000_b,1024x576_1400_m,.mp4.csmil/master.m3u8",
}}
onReady={() => setReady(true)}
onCurrentTimeUpdated={onCurrentTimeUpdated}
onDurationChanged={onDurationChanged}
/>
);
});
const ControlContainer = ({ onSeek }) => {
return (
<View style={styles.controls}>
<Text style={styles.headerText}>Sintel</Text>
<View style={styles.flexRow}>
<TimeElapsed />
<View style={{ flex: 1 }}>
<ScrollBar onSeek={onSeek} />
</View>
<TimeRemaining />
</View>
</View>
);
};
const ScrollBar = ({ onSeek }) => {
const [videoPosition] = useRecoilState(VideoCurrentTimeState);
const [videoDuration] = useRecoilState(VideoDurationState);
return (
<Slider
style={{ flex: 1 }}
maximumValue={videoDuration}
value={videoPosition}
onSlidingComplete={onSeek}
/>
);
};
const TimeElapsed = () => {
const [videoPosition] = useRecoilState(VideoCurrentTimeState);
function getTimestamp(videoPosition) {
const totalTimeInSeconds = videoPosition;
return `${new Date(totalTimeInSeconds).toISOString().substr(14, 5)}`;
}
return <Text style={styles.h1}>{getTimestamp(videoPosition)}</Text>;
};
const TimeRemaining = () => {
const [videoPosition] = useRecoilState(VideoCurrentTimeState);
const [videoDuration] = useRecoilState(VideoDurationState);
function getTimestamp(videoPosition, videoDuration) {
const totalTimeInSeconds = videoDuration - videoPosition;
return `${new Date(totalTimeInSeconds).toISOString().substr(14, 5)}`;
}
return (
<Text style={styles.h1}>{getTimestamp(videoPosition, videoDuration)}</Text>
);
};
export default YiReactApp = () => {
const videoRef = useRef(null);
const onSeekRequest = (seekTo) => {
videoRef?.current?.seek(Math.round(seekTo));
};
return (
<RecoilRoot>
<View style={styles.mainContainer}>
<VideoComponent ref={videoRef} />
<ControlContainer onSeek={onSeekRequest} />
</View>
</RecoilRoot>
);
};
const styles = StyleSheet.create({
mainContainer: {
backgroundColor: "#e6e7e7",
flex: 1,
},
controls: {
width: "100%",
position: "absolute",
bottom: 0,
backgroundColor: "rgba(00, 00, 00, 0.3)",
padding: 5,
},
headerText: {
fontSize: 48,
color: "#FFFFFF",
},
h1: {
fontSize: 18,
color: "#FFFFFF",
},
flexRow: {
flex: 1,
display: "flex",
flexDirection: "row",
alignItems: "center",
},
});
AppRegistry.registerComponent("YiReactApp", () => YiReactApp);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment