Skip to content

Commit be26afb

Browse files
authored
Merge pull request #15732 from guardian/doml/sh-video-refactor
Minor self-hosted video refactor
2 parents 80315a4 + 9bb6f54 commit be26afb

3 files changed

Lines changed: 54 additions & 47 deletions

File tree

dotcom-rendering/src/components/SelfHostedVideo.island.tsx

Lines changed: 35 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -377,7 +377,10 @@ export const SelfHostedVideo = ({
377377

378378
const shouldLoop = isLoop || isCinemagraph;
379379

380-
const showProgressBar = !hideProgressBar && !isCinemagraph;
380+
const showProgressBar =
381+
!hideProgressBar && !isCinemagraph && playerState !== 'NOT_STARTED';
382+
383+
const showIcons = !isCinemagraph && playerState !== 'NOT_STARTED';
381384

382385
const iconSize = isDefault ? 'large' : 'small';
383386

@@ -454,6 +457,13 @@ export const SelfHostedVideo = ({
454457
}
455458
};
456459

460+
const updateCurrentTime = (newTime: number) => {
461+
if (vidRef.current) {
462+
vidRef.current.currentTime = newTime;
463+
setCurrentTime(newTime);
464+
}
465+
};
466+
457467
const FallbackImageComponent = (
458468
<CardPicture
459469
mainImage={fallbackImage}
@@ -635,6 +645,7 @@ export const SelfHostedVideo = ({
635645

636646
const track = video.textTracks[0];
637647
if (!track?.cues) return;
648+
638649
const pxFromBottom = space[3];
639650
const videoHeight = video.getBoundingClientRect().height;
640651
const percentFromTop =
@@ -706,8 +717,8 @@ export const SelfHostedVideo = ({
706717
const handleFullscreenClick = (event: React.SyntheticEvent) => {
707718
void submitClickComponentEvent(event.currentTarget, renderingTarget);
708719
event.stopPropagation(); // Don't pause the video
709-
const video = vidRef.current;
710720

721+
const video = vidRef.current;
711722
if (!video) return;
712723

713724
if (shouldUseWebkitFullscreen(video)) {
@@ -772,27 +783,31 @@ export const SelfHostedVideo = ({
772783
};
773784

774785
const seekForward = () => {
775-
if (vidRef.current) {
776-
const newTime = Math.min(
777-
vidRef.current.currentTime + 1,
778-
vidRef.current.duration,
779-
);
786+
const video = vidRef.current;
787+
if (!video) return;
780788

781-
vidRef.current.currentTime = newTime;
782-
setCurrentTime(newTime);
783-
}
789+
const increment = 1;
790+
const newTime = Math.min(video.currentTime + increment, video.duration);
791+
792+
updateCurrentTime(newTime);
784793
};
785794

786795
const seekBackward = () => {
787-
if (vidRef.current) {
788-
// Allow the user to cycle to the end of the video using the arrow keys
789-
const newTime =
790-
(((vidRef.current.currentTime - 1) % vidRef.current.duration) +
791-
vidRef.current.duration) %
792-
vidRef.current.duration;
796+
const video = vidRef.current;
797+
if (!video) return;
793798

794-
vidRef.current.currentTime = newTime;
795-
setCurrentTime(newTime);
799+
const increment = 1;
800+
const newTime = Math.max(video.currentTime - increment, 0);
801+
802+
updateCurrentTime(newTime);
803+
};
804+
805+
const handleTimeUpdate = () => {
806+
const video = vidRef.current;
807+
if (!video) return;
808+
809+
if (playerState === 'PLAYING') {
810+
setCurrentTime(video.currentTime);
796811
}
797812
};
798813

@@ -920,17 +935,15 @@ export const SelfHostedVideo = ({
920935
posterImage={optimisedPosterImage}
921936
FallbackImageComponent={FallbackImageComponent}
922937
currentTime={currentTime}
923-
setCurrentTime={setCurrentTime}
924938
ref={vidRef}
925-
isPlayable={isPlayable}
926-
playerState={playerState}
927939
isMuted={isMuted}
928940
handleLoadedMetadata={handleLoadedMetadata}
929941
handleLoadedData={handleLoadedData}
930942
handleCanPlay={handleCanPlay}
931943
handlePlaying={handlePlaying}
932944
handlePlayPauseClick={handlePlayPauseClick}
933945
handleAudioClick={handleAudioClick}
946+
handleTimeUpdate={handleTimeUpdate}
934947
handleKeyDown={handleKeyDown}
935948
handlePause={handlePause}
936949
handleFullscreenClick={handleFullscreenClick}
@@ -943,7 +956,7 @@ export const SelfHostedVideo = ({
943956
showSubtitles={!isCinemagraph}
944957
subtitleSource={subtitleSource}
945958
subtitleSize={subtitleSize}
946-
showIcons={!isCinemagraph}
959+
showIcons={showIcons}
947960
controlsPosition={controlsPosition}
948961
activeCue={activeCue}
949962
shouldLoop={shouldLoop}

dotcom-rendering/src/components/SelfHostedVideo.stories.tsx

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,6 @@ export const Loop: Story = {
4848
sources: loop54Card.mainMedia.sources,
4949
aspectRatio: loop54Card.mainMedia.aspectRatio,
5050
uniqueId: 'test-video-1',
51-
atomId: 'test-atom-1',
5251
videoStyle: 'Loop',
5352
posterImage:
5453
'https://media.guim.co.uk/9bdb802e6da5d3fd249b5060f367b3a817965f0c/0_0_1800_1080/master/1800.jpg',

dotcom-rendering/src/components/SelfHostedVideoPlayer.tsx

Lines changed: 19 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -6,12 +6,7 @@ import {
66
textSans20,
77
} from '@guardian/source/foundations';
88
import type { IconProps } from '@guardian/source/react-components';
9-
import type {
10-
Dispatch,
11-
ReactElement,
12-
SetStateAction,
13-
SyntheticEvent,
14-
} from 'react';
9+
import type { ReactElement, SyntheticEvent } from 'react';
1510
import { forwardRef } from 'react';
1611
import type { ActiveCue } from '../lib/useSubtitles';
1712
import type { Source } from '../lib/video';
@@ -66,12 +61,15 @@ const playIconStyles = css`
6661
padding: 0;
6762
`;
6863

69-
const iconsContainerStyles = (position: ControlsPosition) => css`
64+
const iconsContainerStyles = css`
7065
position: absolute;
7166
display: flex;
7267
flex-direction: column;
7368
gap: ${space[2]}px;
7469
right: ${space[2]}px;
70+
`;
71+
72+
const iconsPositionStyles = (position: ControlsPosition) => css`
7573
/* Take into account the progress bar height */
7674
${position === 'bottom' && `bottom: ${space[3]}px;`}
7775
${position === 'top' && `top: ${space[2]}px;`}
@@ -106,10 +104,7 @@ export type Props = {
106104
aspectRatio: number;
107105
videoStyle: VideoPlayerFormat;
108106
FallbackImageComponent: ReactElement;
109-
isPlayable: boolean;
110-
playerState: PlayerStates;
111107
currentTime: number;
112-
setCurrentTime: Dispatch<SetStateAction<number>>;
113108
isMuted: boolean;
114109
handleLoadedMetadata: (event: SyntheticEvent) => void;
115110
handleLoadedData: (event: SyntheticEvent) => void;
@@ -118,6 +113,7 @@ export type Props = {
118113
handlePlayPauseClick: (event: SyntheticEvent) => void;
119114
handleAudioClick: (event: SyntheticEvent) => void;
120115
handleKeyDown: (event: React.KeyboardEvent<HTMLVideoElement>) => void;
116+
handleTimeUpdate: (event: SyntheticEvent<HTMLVideoElement>) => void;
121117
handlePause: (event: SyntheticEvent) => void;
122118
handleFullscreenClick?: (event: SyntheticEvent) => void;
123119
onError: (event: SyntheticEvent<HTMLVideoElement>) => void;
@@ -160,10 +156,7 @@ export const SelfHostedVideoPlayer = forwardRef(
160156
videoStyle,
161157
FallbackImageComponent,
162158
posterImage,
163-
isPlayable,
164-
playerState,
165159
currentTime,
166-
setCurrentTime,
167160
isMuted,
168161
handleLoadedMetadata,
169162
handleLoadedData,
@@ -172,6 +165,7 @@ export const SelfHostedVideoPlayer = forwardRef(
172165
handlePlayPauseClick,
173166
handleAudioClick,
174167
handleKeyDown,
168+
handleTimeUpdate,
175169
handlePause,
176170
handleFullscreenClick,
177171
onError,
@@ -198,7 +192,7 @@ export const SelfHostedVideoPlayer = forwardRef(
198192

199193
const showSubtitles = canShowSubtitles && !!subtitleSource;
200194
const showProgressBar = canShowProgressBar && currentRefExists;
201-
const showIcons = canShowIcons && currentRefExists && isPlayable;
195+
const showIcons = canShowIcons && currentRefExists;
202196

203197
const dataLinkName = `gu-video-${videoStyle}-${
204198
showPlayIcon ? 'play' : 'pause'
@@ -232,22 +226,18 @@ export const SelfHostedVideoPlayer = forwardRef(
232226
onCanPlay={handleCanPlay}
233227
onCanPlayThrough={handleCanPlay}
234228
onPlaying={handlePlaying}
235-
onTimeUpdate={() => {
236-
if (currentRefExists && playerState === 'PLAYING') {
237-
setCurrentTime(ref.current!.currentTime);
238-
}
239-
}}
229+
onTimeUpdate={handleTimeUpdate}
240230
onPause={handlePause}
241231
onClick={handlePlayPauseClick}
242232
onKeyDown={handleKeyDown}
243233
onError={onError}
244234
>
245-
{sources.map((source) => (
235+
{sources.map(({ src, mimeType }) => (
246236
<source
247-
key={source.mimeType}
237+
key={mimeType}
248238
/* The start time is set to 1ms so that Safari will autoplay the video */
249-
src={`${source.src}#t=0.001`}
250-
type={source.mimeType}
239+
src={`${src}#t=0.001`}
240+
type={mimeType}
251241
/>
252242
))}
253243
{showSubtitles && (
@@ -287,7 +277,12 @@ export const SelfHostedVideoPlayer = forwardRef(
287277
/>
288278
)}
289279
{showIcons && (
290-
<div css={iconsContainerStyles(controlsPosition)}>
280+
<div
281+
css={[
282+
iconsContainerStyles,
283+
iconsPositionStyles(controlsPosition),
284+
]}
285+
>
291286
{showFullscreenIcon && (
292287
<FullscreenIcon
293288
handleClick={handleFullscreenClick}

0 commit comments

Comments
 (0)