Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Video component #28

Merged
merged 23 commits into from
Sep 18, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
c621255
Temporary commit
Sep 16, 2019
f548109
Needed to bind parents to the component
Sep 17, 2019
53ed13c
Updating styling
Sep 17, 2019
20314be
Updating snapshots
Sep 17, 2019
2fe4f7e
Removing css for prog bar
Sep 17, 2019
b63fac3
Update packages/components/PreviewCanvas/Controls.js
emettely Sep 17, 2019
10b7332
Update packages/components/PreviewCanvas/ProgressBar.js
emettely Sep 17, 2019
d9ce5f1
Update packages/components/PreviewCanvas/Filler.js
emettely Sep 17, 2019
9dfaa9f
Update packages/components/PreviewCanvas/ProgressBar.js
emettely Sep 17, 2019
4ed4a15
Update packages/components/PreviewCanvas/VideoContextPreview/Canvas.js
emettely Sep 17, 2019
e4abfff
Update packages/components/PreviewCanvas/VideoContextPreview/VideoCon…
emettely Sep 17, 2019
04d89a7
Update packages/components/PreviewCanvas/VideoContextPreview/VideoCon…
emettely Sep 17, 2019
fca8ada
Update packages/components/PreviewCanvas/VideoContextPreview/index.js
emettely Sep 17, 2019
df8f48f
Update packages/components/PreviewCanvas/stories/index.stories.js
emettely Sep 17, 2019
55479e2
Update packages/components/PreviewCanvas/stories/index.stories.js
emettely Sep 17, 2019
3ed121c
Update packages/components/PreviewCanvas/Controls.js
emettely Sep 18, 2019
fe54fd1
Update packages/components/PreviewCanvas/VideoContextPreview/Canvas.js
emettely Sep 18, 2019
7828a97
Update packages/components/PreviewCanvas/VideoContextPreview/VideoCon…
emettely Sep 18, 2019
15602ee
Update packages/components/PreviewCanvas/VideoContextPreview/VideoCon…
emettely Sep 18, 2019
c427025
Update packages/components/PreviewCanvas/VideoContextPreview/VideoCon…
emettely Sep 18, 2019
460fd09
Update packages/components/PreviewCanvas/VideoContextPreview/VideoCon…
emettely Sep 18, 2019
f6f0810
Update packages/components/PreviewCanvas/VideoContextPreview/VideoCon…
emettely Sep 18, 2019
bce4df0
Update packages/components/PreviewCanvas/VideoContextPreview/VideoCon…
emettely Sep 18, 2019
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
67 changes: 67 additions & 0 deletions packages/components/PreviewCanvas/Controls.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
import React, { useState } from 'react';
import Button from 'react-bootstrap/Button';
import Col from 'react-bootstrap/Col';
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import { faPlay, faPause, faStop } from '@fortawesome/free-solid-svg-icons';
import PropTypes from 'prop-types';

const playIcon = <FontAwesomeIcon icon={ faPlay } />;
const pauseIcon = <FontAwesomeIcon icon={ faPause } />;
const stopIcon = <FontAwesomeIcon icon={ faStop } />;

const Controls = (props) => {

const [ isPlaying, setIsPlaying ] = useState(false);

const handlePlay = () => {
props.handlePlay();
setIsPlaying(true);
};

const handlePause = () => {
props.handlePause();
setIsPlaying(false);
};

const handleStop = () => {
props.handleStop();
setIsPlaying(false);
};

return (
<>
<Col sm={ 6 }>
sm={ 6 } md={ 6 } ld={ 6 } xl={ 6 }
>
<Button
size="sm"
block
variant="outline-secondary"
onClick={ isPlaying ? handlePause : handlePlay }
>
{ isPlaying ? pauseIcon : playIcon }
</Button>
</Col>
<Col
sm={ 6 }
>
<Button
size="sm"
block
variant="outline-secondary"
onClick={ handleStop }
>
{ stopIcon }
</Button>
</Col>
</>
);
};

export default Controls;

Controls.propTypes = {
handleStop: PropTypes.any,
handlePlay: PropTypes.any,
handlePause: PropTypes.any
};
12 changes: 12 additions & 0 deletions packages/components/PreviewCanvas/Filler.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import React from 'react';

const Filler = (props) => {
return <div style={ {
width: `${ props.percentage }%`,
background: 'red',
height: '100%',
borderRadius: 'inherit'
} } />;
};

export default Filler;
19 changes: 19 additions & 0 deletions packages/components/PreviewCanvas/ProgressBar.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import React from 'react';
import Filler from './Filler';

const ProgressBar = (props) => {

return (
<div onClick={ props.onClick }
style={ {
position: 'relative',
height: '12px',
width: '100%',
opacity: '1'
} } >
<Filler percentage={ props.percentage }></Filler>
</div>

);
};
export default ProgressBar;
20 changes: 20 additions & 0 deletions packages/components/PreviewCanvas/VideoContextPreview/Canvas.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import React, { useRef, useEffect, useState } from 'react';

const Canvas = (props) => {
const ref = props.ref;


useEffect(() => {
if (props.videoContextRef && props.videoContext) {

loadPlaylist();
}
}, [ props.videoContextRef ]);

return (<canvas ref={ props.videoContextRef } width={ props.width } height={ props.height } />);
};
Canvas.defaultProps = {
playlist : [],
};

export default Canvas;
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
import React, { useState, useRef, useEffect, useLayoutEffect } from 'react';
import ProgressBar from '../ProgressBar';
import PropTypes from 'prop-types';

const getPercentage = (currentTime, duration) => currentTime / duration * 100;

const VideoContextProgressBar = (props) => {
const ref = useRef();

const [ percentage, setPercentage ] = useState(0);
const [ videoContext, setVideoContext ] = useState();
const [ width, setWidth ] = useState(0);

const handleClick = ({ nativeEvent: { offsetX } }) => {
videoContext.currentTime = (offsetX / width) * videoContext.duration;
const percent = getPercentage(videoContext.currentTime, videoContext.duration);
setPercentage(percent);
};

useLayoutEffect(() => {
if (ref.current) {
setWidth(ref.current.offsetWidth);
}
}, [ ref ]);

useEffect(() => {
const fillerAnimation = () => {
const percent = getPercentage(videoContext.currentTime, videoContext.duration);
setPercentage(percent);
requestAnimationFrame(fillerAnimation);
};

setVideoContext(props.videoContext);

if (videoContext) {
fillerAnimation();
}
}, [ props.videoContext, videoContext ]);

return (
<div ref={ ref } style={ { width:'100%' } }>
<ProgressBar onClick={ handleClick } percentage={ percentage } />
</div>
);
};

VideoContextProgressBar.propTypes = {
videoContext: PropTypes.any
};

export default VideoContextProgressBar;
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import React from 'react';
import { shallow, mount } from 'enzyme';
import VideoContextProgressBar from './VideoContextProgressBar';

describe('VideoContextProgressBar', () => {
const mockVideoContext = {};

it('should render shallowly', () => { const component = shallow(<VideoContextProgressBar videoContext={ mockVideoContext } />);
expect(component).toMatchSnapshot();
});

it('should fully render', () => {
const component = mount(<VideoContextProgressBar videoContext={ mockVideoContext }/>);
expect(component).toMatchSnapshot();

component.unmount();
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`VideoContextProgressBar should be possible to activate button with Spacebar 1`] = `
<VideoContextProgressBar
videoContext={Object {}}
>
<div
style={
Object {
"width": "100%",
}
}
>
<ProgressBar
onClick={[Function]}
percentage={NaN}
>
<div
onClick={[Function]}
style={
Object {
"height": "12px",
"opacity": "1",
"position": "relative",
"width": "100%",
}
}
>
<Filler
percentage={NaN}
>
<div
style={
Object {
"background": "red",
"borderRadius": "inherit",
"height": "100%",
"width": "NaN%",
}
}
/>
</Filler>
</div>
</ProgressBar>
</div>
</VideoContextProgressBar>
`;

exports[`VideoContextProgressBar should render correctly 1`] = `
<div
style={
Object {
"width": "100%",
}
}
>
<ProgressBar
onClick={[Function]}
percentage={0}
/>
</div>
`;
85 changes: 85 additions & 0 deletions packages/components/PreviewCanvas/VideoContextPreview/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
import React, { useState, useEffect } from 'react';
import VideoContextProgressBar from './VideoContextProgressBar';
import Controls from '../Controls';
import Row from 'react-bootstrap/Row';
import PropTypes from 'prop-types';
import VideoContext from 'videocontext';

const VideoContextPreview = (props) => {
const [ videoContext, setVideoContext ] = useState();

const updateVideoContext = (media) => {
media.forEach(({ type, sourceStart, start, duration, src }) => {
const node = videoContext[type](src, sourceStart);
node.startAt(start);
node.stopAt(start + duration);
node.connect(videoContext.destination);
});

};

const handleStop = () => {
videoContext.pause();
setVideoContext(vc => {
vc.currentTime = 0;

return vc;
});
};

useEffect(() => {
if (props.canvasRef && props.canvasRef.current) {
setVideoContext(new VideoContext(props.canvasRef.current));
}

}, [ props.canvasRef ]);

if (videoContext) {
updateVideoContext(props.playlist);

}

return (
<>
<Row
className={ 'justify-content-center' }
style={ { backgroundColor: 'black' } }
>
<canvas
ref={ props.canvasRef }
width={ props.width }
height={ props.height }
/>
</Row>
<Row
className={ 'justify-content-center' }
style={ { backgroundColor: 'lightgrey' } }
>
<VideoContextProgressBar videoContext={ videoContext }/>
</Row>
<Row style={ { marginTop: '0.4em' } }>
<Controls
handlePlay={ videoContext ? () => videoContext.play() : console.log('handlePlay') }
handlePause={ videoContext ? () => videoContext.pause() : console.log('handlePause') }
handleStop={ videoContext ? () => handleStop() : console.log('handleStop') }
/>
</Row>
</>
);
};

VideoContextPreview.propTypes = {
canvasRef: PropTypes.any,
height: PropTypes.number,
playlist: PropTypes.array,
videoContext: PropTypes.any,
width: PropTypes.number
};

VideoContextPreview.defaultProps = {
playlist: [],
width : 640,
height : 360,
};

export default VideoContextPreview;
20 changes: 20 additions & 0 deletions packages/components/PreviewCanvas/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
/* eslint-disable react/prop-types */
import React, { useRef } from 'react';
import VideoContextPreview from './VideoContextPreview';

const PreviewCanvas = (props) => {
const canvasRef = useRef();

return (
<VideoContextPreview
canvasRef={ canvasRef }
playlist={ props.playlist }
/>
);
};

PreviewCanvas.defaultProps = {
playlist: []
};

export default PreviewCanvas;
18 changes: 18 additions & 0 deletions packages/components/PreviewCanvas/stories/index.stories.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import React from 'react';

import { storiesOf } from '@storybook/react';
import PreviewCanvas from '../index.js';

const playlist = [
{ type:'video', start:0, sourceStart: 30, duration:10, src:'https://download.ted.com/talks/MorganVague_2018X.mp4' },
{ type:'video', start:10, sourceStart: 40, duration:10, src:'https://download.ted.com/talks/IvanPoupyrev_2019.mp4' },
{ type:'video', start:20, sourceStart: 50, duration:10, src:'https://download.ted.com/talks/KateDarling_2018S-950k.mp4' },

];

storiesOf('PreviewCanvas', module)
.add('VideoContext', () =>
<PreviewCanvas
playlist={ playlist }
/>
);