Skip to content

Commit

Permalink
Merge pull request #51 from Videodock/feat/trailer
Browse files Browse the repository at this point in the history
Feat / trailer
  • Loading branch information
ChristiaanScheermeijer authored Jun 17, 2021
2 parents 9bf4b08 + 06a9636 commit de1f4f7
Show file tree
Hide file tree
Showing 17 changed files with 248 additions and 165 deletions.
36 changes: 36 additions & 0 deletions src/components/Modal/Modal.module.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
@use '../../styles/variables';
@use '../../styles/theme';

.overlay {
position: fixed;
width: 100vw;
height: 100vh;
left: 0px;
top: 0px;
z-index: 1;
}
.backdrop {
width: inherit;
height: inherit;
background: rgba(0, 0, 0, 0.6);
}
.modalContainer {
position: absolute;
top: 0px;
left: 0px;
width: 100vw;
height: 100vh;
display: flex;
justify-content: center;
align-items: center;
}
.modal {
position: relative;
width: 80vw;
background-color: rgba(0, 0, 0, 0.9);
}
.close {
position: absolute;
right: 30px;
top: 30px;
}
16 changes: 16 additions & 0 deletions src/components/Modal/Modal.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import React from 'react';
import { render } from '@testing-library/react';

import Modal from './Modal';

describe('<Modal>', () => {
test('renders and matches snapshot', () => {
const { container } = render(
<Modal onClose={jest.fn()}>
<p>Test modal</p>
</Modal>,
);

expect(container).toMatchSnapshot();
});
});
43 changes: 43 additions & 0 deletions src/components/Modal/Modal.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
import React, { ReactFragment, useEffect } from 'react';
import { useTranslation } from 'react-i18next';

import IconButton from '../IconButton/IconButton';
import Close from '../../icons/Close';

import styles from './Modal.module.scss';

type Props = {
onClose: () => void;
children: ReactFragment;
};

const Modal: React.FC<Props> = ({ onClose, children }: Props) => {
const { t } = useTranslation('common');

useEffect(() => {
const onKeyDown = (event: KeyboardEvent) => event.keyCode === 27 && onClose();

document.body.style.overflow = 'hidden';
document.addEventListener('keydown', onKeyDown);
return () => {
document.body.style.overflow = 'scroll';
document.removeEventListener('keydown', onKeyDown);
};
}, [onClose]);

return (
<div className={styles.overlay} onClick={onClose}>
<div className={styles.backdrop} />
<div className={styles.modalContainer}>
<div className={styles.modal} onClick={(event) => event.stopPropagation()}>
<IconButton onClick={onClose} aria-label={t('close_modal')} className={styles.close}>
<Close />
</IconButton>
{children}
</div>
</div>
</div>
);
};

export default Modal;
48 changes: 48 additions & 0 deletions src/components/Modal/__snapshots__/Modal.test.tsx.snap
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`<Modal> renders and matches snapshot 1`] = `
<div>
<div
class="overlay"
>
<div
class="backdrop"
/>
<div
class="modalContainer"
>
<div
class="modal"
>
<div
aria-label="close_modal"
class="iconButton close"
role="button"
tabindex="0"
>
<svg
aria-hidden="true"
class="icon"
focusable="false"
viewBox="0 0 24 24"
xmlns="http://www.w3.org/2000/svg"
>
<g>
<path
d="M19 6.41L17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12z"
/>
<path
d="M0 0h24v24H0z"
fill="none"
/>
</g>
</svg>
</div>
<p>
Test modal
</p>
</div>
</div>
</div>
</div>
`;
10 changes: 10 additions & 0 deletions src/components/Video/Video.module.scss
Original file line number Diff line number Diff line change
Expand Up @@ -171,3 +171,13 @@
.playerInfo {
margin: 0px 30px;
}
.trailerMeta {
position: absolute;
z-index: 1;
left: 16px;
top: 16px;
&.hidden {
transition: opacity 0.6s ease;
opacity: 0;
}
}
3 changes: 3 additions & 0 deletions src/components/Video/Video.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,9 @@ describe('<Video>', () => {
enableSharing
isFavorited={false}
onFavoriteButtonClick={jest.fn()}
playTrailer={false}
onTrailerClick={jest.fn()}
onTrailerClose={jest.fn()}
/>,
);

Expand Down
36 changes: 29 additions & 7 deletions src/components/Video/Video.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import Play from '../../icons/Play';
import Button from '../Button/Button';
import IconButton from '../IconButton/IconButton';
import { formatDuration } from '../../utils/formatting';
import Modal from '../Modal/Modal';
import FavoriteBorder from '../../icons/FavoriteBorder';

import styles from './Video.module.scss';
Expand All @@ -23,6 +24,7 @@ type Poster = 'fading' | 'normal';

type Props = {
item: PlaylistItem;
trailerItem?: PlaylistItem;
play: boolean;
startPlay: () => void;
goBack: () => void;
Expand All @@ -32,11 +34,15 @@ type Props = {
enableSharing: boolean;
hasShared: boolean;
onShareClick: () => void;
playTrailer: boolean;
onTrailerClick: () => void;
onTrailerClose: () => void;
relatedShelf?: JSX.Element;
};

const Video: React.FC<Props> = ({
item,
trailerItem,
play,
startPlay,
goBack,
Expand All @@ -47,6 +53,9 @@ const Video: React.FC<Props> = ({
isFavorited,
onFavoriteButtonClick,
relatedShelf,
playTrailer,
onTrailerClick,
onTrailerClose,
}: Props) => {
const [isPlaying, setIsPlaying] = useState<boolean>(false);
const [mouseActive, setMouseActive] = useState(false);
Expand Down Expand Up @@ -95,13 +104,16 @@ const Video: React.FC<Props> = ({
/>
</div>
<div className={styles.otherButtons}>
<Button
label={t('video:trailer')}
aria-label={t('video:watch_trailer')}
startIcon={<PlayTrailer />}
onClick={() => null}
fullWidth={breakpoint < Breakpoint.sm}
/>
{trailerItem && (
<Button
label={t('video:trailer')}
aria-label={t('video:watch_trailer')}
startIcon={<PlayTrailer />}
onClick={onTrailerClick}
active={playTrailer}
fullWidth={breakpoint < Breakpoint.sm}
/>
)}
<Button
label={t('video:favorite')}
aria-label={isFavorited ? t('video:remove_from_favorites') : t('video:add_to_favorites')}
Expand Down Expand Up @@ -142,6 +154,16 @@ const Video: React.FC<Props> = ({
</div>
</div>
)}
{playTrailer && trailerItem && (
<Modal onClose={onTrailerClose}>
<div onMouseMove={mouseActivity} onClick={mouseActivity}>
<Cinema item={trailerItem} onComplete={onTrailerClose} isTrailer />
<div
className={classNames(styles.trailerMeta, styles.title, { [styles.hidden]: !mouseActive })}
>{`${item.title} - Trailer`}</div>
</div>
</Modal>
)}
</div>
);
};
Expand Down
25 changes: 0 additions & 25 deletions src/components/Video/__snapshots__/Video.test.tsx.snap
Original file line number Diff line number Diff line change
Expand Up @@ -62,31 +62,6 @@ exports[`<Video> renders and matches snapshot 1`] = `
<div
class="otherButtons"
>
<button
aria-label="video:watch_trailer"
class="button default outlined"
>
<div
class="startIcon"
>
<svg
aria-hidden="true"
class="icon"
focusable="false"
viewBox="0 0 24 24"
xmlns="http://www.w3.org/2000/svg"
>
<g>
<path
d="M19,19H5V5H19M19,3H5A2,2 0 0,0 3,5V19A2,2 0 0,0 5,21H19A2,2 0 0,0 21,19V5C21,3.89 20.1,3 19,3M10,8V16L15,12L10,8Z"
/>
</g>
</svg>
</div>
<span>
video:trailer
</span>
</button>
<button
aria-label="video:add_to_favorites"
class="button default outlined"
Expand Down
14 changes: 9 additions & 5 deletions src/containers/Cinema/Cinema.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,13 +14,16 @@ type Props = {
item: PlaylistItem;
onPlay?: () => void;
onPause?: () => void;
onComplete?: () => void;
isTrailer?: boolean;
};

const Cinema: React.FC<Props> = ({ item, onPlay, onPause }: Props) => {
const Cinema: React.FC<Props> = ({ item, onPlay, onPause, onComplete, isTrailer = false }: Props) => {
const config: Config = useContext(ConfigContext);
const [initialized, setInitialized] = useState(false);
const file = item.sources[0]?.file;
const file = item.sources?.[0]?.file;
const scriptUrl = `https://content.jwplatform.com/libraries/${config.player}.js`;
const enableWatchHistory = config.options.enableContinueWatching && !isTrailer;

const getProgress = (): VideoProgress | null => {
const player = window.jwplayer && (window.jwplayer('cinema') as jwplayer.JWPlayer);
Expand All @@ -32,15 +35,15 @@ const Cinema: React.FC<Props> = ({ item, onPlay, onPause }: Props) => {
return { duration, progress } as VideoProgress;
};
const { saveItem } = useWatchHistory();
useWatchHistoryListener(() => saveItem(item, getProgress));
useWatchHistoryListener(() => (enableWatchHistory ? saveItem(item, getProgress) : null));

useEffect(() => {
const getPlayer = () => window.jwplayer && (window.jwplayer('cinema') as jwplayer.JWPlayer);
const loadVideo = () => {
const player = getPlayer();
const { watchHistory } = watchHistoryStore.getRawState();
const watchHistoryItem = watchHistory.find(({ mediaid }) => mediaid === item.mediaid);
let applyWatchHistory = !!watchHistory;
let applyWatchHistory = !!watchHistory && enableWatchHistory;

player.setup({ file, image: item.image, title: item.title, autostart: 'viewable' });
player.on('play', () => onPlay && onPlay());
Expand All @@ -52,13 +55,14 @@ const Cinema: React.FC<Props> = ({ item, onPlay, onPause }: Props) => {
progress && duration && player.seek(duration * progress);
}
});
player.on('complete', () => onComplete && onComplete());
};

if (config.player && !initialized) {
getPlayer() ? loadVideo() : addScript(scriptUrl, loadVideo);
setInitialized(true);
}
}, [item, onPlay, onPause, config.player, file, scriptUrl, initialized]);
}, [item, onPlay, onPause, onComplete, config.player, file, scriptUrl, initialized, enableWatchHistory]);

return <div className={styles.Cinema} id="cinema" />;
};
Expand Down
Loading

0 comments on commit de1f4f7

Please sign in to comment.