Skip to content

Commit 39b4feb

Browse files
authored
Merge pull request #14175 from guardian/doml/loop-video-audio-youtube
Fix Looping video and Youtube video interactions
2 parents 47ca401 + d0f014b commit 39b4feb

File tree

8 files changed

+82
-20
lines changed

8 files changed

+82
-20
lines changed

dotcom-rendering/src/components/DynamicSlowMPU.tsx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,8 @@ const Card33_Card33_Card33 = ({
6868
* If you pass no bigs at all the top slice will not render and a special
6969
* 3 column layout is used for the remaining slice.
7070
*
71+
* @deprecated Adverts are no longer shown within containers. We no
72+
* longer use containers that reserve a space for an MPU advert.
7173
*/
7274
export const DynamicSlowMPU = ({
7375
groupedTrails,

dotcom-rendering/src/components/FixedMediumSlowXIIMPU.tsx

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -129,6 +129,10 @@ const Card50_Card50 = ({
129129
);
130130
};
131131

132+
/**
133+
* @deprecated Adverts are no longer shown within containers. We no
134+
* longer use containers that reserve a space for an MPU advert.
135+
*/
132136
export const FixedMediumSlowXIIMPU = ({
133137
trails,
134138
containerPalette,

dotcom-rendering/src/components/FixedSmallSlowVMPU.tsx

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,10 @@ type Props = {
1212
absoluteServerTimes: boolean;
1313
};
1414

15+
/**
16+
* @deprecated Adverts are no longer shown within containers. We no
17+
* longer use containers that reserve a space for an MPU advert.
18+
*/
1519
export const FixedSmallSlowVMPU = ({
1620
trails,
1721
containerPalette,

dotcom-rendering/src/components/FlexibleGeneral.tsx

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -525,9 +525,9 @@ const HalfWidthCardLayout = ({
525525
{cards.map((card, cardIndex) => {
526526
return (
527527
<LI
528+
key={card.url}
528529
stretch={false}
529530
percentage="50%"
530-
key={card.url}
531531
padSides={true}
532532
showDivider={cardIndex > 0}
533533
verticalDividerColour={palette(
@@ -614,6 +614,7 @@ export const FlexibleGeneral = ({
614614
case 'oneCardFullWidth':
615615
return (
616616
<FullWidthCardLayout
617+
key={row.cards[0]?.uniqueId}
617618
cards={row.cards}
618619
containerPalette={containerPalette}
619620
showAge={showAge}
@@ -624,7 +625,6 @@ export const FlexibleGeneral = ({
624625
isLastRow={i === groupedCards.length - 1}
625626
containerLevel={containerLevel}
626627
collectionId={collectionId}
627-
key={row.cards[0]?.uniqueId}
628628
/>
629629
);
630630

@@ -633,6 +633,7 @@ export const FlexibleGeneral = ({
633633
default:
634634
return (
635635
<HalfWidthCardLayout
636+
key={row.cards[0]?.uniqueId}
636637
cards={row.cards}
637638
containerPalette={containerPalette}
638639
showAge={showAge}
@@ -643,7 +644,6 @@ export const FlexibleGeneral = ({
643644
aspectRatio={aspectRatio}
644645
isLastRow={i === groupedCards.length - 1}
645646
containerLevel={containerLevel}
646-
key={row.cards[0]?.uniqueId}
647647
/>
648648
);
649649
}

dotcom-rendering/src/components/LoopVideo.importable.tsx

Lines changed: 28 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,11 @@ import { useEffect, useRef, useState } from 'react';
55
import { getZIndex } from '../lib/getZIndex';
66
import { useIsInView } from '../lib/useIsInView';
77
import { useShouldAdapt } from '../lib/useShouldAdapt';
8+
import type { CustomPlayEventDetail } from '../lib/video';
9+
import {
10+
customLoopPlayAudioEventName,
11+
customYoutubePlayEventName,
12+
} from '../lib/video';
813
import { useConfig } from './ConfigContext';
914
import type { PLAYER_STATES } from './LoopVideoPlayer';
1015
import { LoopVideoPlayer } from './LoopVideoPlayer';
@@ -14,16 +19,13 @@ const videoContainerStyles = css`
1419
position: relative;
1520
`;
1621

17-
type CustomPlayEventDetail = { uniqueId: string };
18-
const customPlayAudioEventName = 'looping-video:play-with-audio';
19-
2022
/**
2123
* Dispatches a custom play audio event so that other videos listening
2224
* for this event will be muted.
2325
*/
2426
export const dispatchCustomPlayAudioEvent = (uniqueId: string) => {
2527
document.dispatchEvent(
26-
new CustomEvent(customPlayAudioEventName, {
28+
new CustomEvent(customLoopPlayAudioEventName, {
2729
detail: { uniqueId },
2830
}),
2931
);
@@ -84,8 +86,8 @@ export const LoopVideo = ({
8486
setPrefersReducedMotion(userPrefersReducedMotion);
8587

8688
/**
87-
* Pause the current video when another video is played
88-
* Triggered by the CustomEvent sent by each player on play
89+
* Mutes the current video when another video is unmuted
90+
* Triggered by the CustomEvent sent by each player on unmuting
8991
*/
9092
const handleCustomPlayAudioEvent = (
9193
event: CustomEventInit<CustomPlayEventDetail>,
@@ -100,16 +102,33 @@ export const LoopVideo = ({
100102
}
101103
};
102104

105+
/**
106+
* Mute the current video when a Youtube video is played
107+
* Triggered by the CustomEvent in YoutubeAtomPlayer.
108+
*/
109+
const handleCustomPlayYoutubeEvent = () => {
110+
setIsMuted(true);
111+
};
112+
103113
document.addEventListener(
104-
customPlayAudioEventName,
114+
customLoopPlayAudioEventName,
105115
handleCustomPlayAudioEvent,
106116
);
117+
document.addEventListener(
118+
customYoutubePlayEventName,
119+
handleCustomPlayYoutubeEvent,
120+
);
107121

108-
return () =>
122+
return () => {
109123
document.removeEventListener(
110-
customPlayAudioEventName,
124+
customLoopPlayAudioEventName,
111125
handleCustomPlayAudioEvent,
112126
);
127+
document.removeEventListener(
128+
customYoutubePlayEventName,
129+
handleCustomPlayYoutubeEvent,
130+
);
131+
};
113132
}, [uniqueId]);
114133

115134
/**

dotcom-rendering/src/components/Treats.tsx

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -172,6 +172,7 @@ export const Treats = ({
172172
borderColour?: string;
173173
}) => {
174174
if (treats.length === 0) return null;
175+
175176
return (
176177
<ul
177178
css={css`
@@ -181,6 +182,7 @@ export const Treats = ({
181182
>
182183
{treats.map((treat, index) => {
183184
const [link] = treat.links;
185+
184186
if (link?.linkTo === '/crosswords' && link.text) {
185187
// Treats that link to /crosswords are special. If any
186188
// treat has this exact url then an svg of a crossword
@@ -229,7 +231,7 @@ export const Treats = ({
229231
}
230232

231233
return (
232-
<>
234+
<Fragment key={index}>
233235
{treat.links.map(({ text, linkTo }) => (
234236
<TextTreat
235237
key={linkTo}
@@ -239,7 +241,7 @@ export const Treats = ({
239241
borderColour={borderColour}
240242
/>
241243
))}
242-
</>
244+
</Fragment>
243245
);
244246
})}
245247
</ul>

dotcom-rendering/src/components/YoutubeAtom/YoutubeAtomPlayer.tsx

Lines changed: 33 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,11 @@ import {
1313
import { getVideoClient } from '../../lib/bridgetApi';
1414
import { getZIndex } from '../../lib/getZIndex';
1515
import { getAuthStatus } from '../../lib/identity';
16+
import type { CustomPlayEventDetail } from '../../lib/video';
17+
import {
18+
customLoopPlayAudioEventName,
19+
customYoutubePlayEventName,
20+
} from '../../lib/video';
1621
import type { AdTargeting } from '../../types/commercial';
1722
import type { RenderingTarget } from '../../types/renderingTarget';
1823
import type { google } from './ima';
@@ -39,9 +44,6 @@ type Props = {
3944
renderingTarget: RenderingTarget;
4045
};
4146

42-
type CustomPlayEventDetail = { uniqueId: string };
43-
const customPlayEventName = 'youtube-video:play';
44-
4547
type ProgressEvents = {
4648
hasSentPlayEvent: boolean;
4749
hasSent25Event: boolean;
@@ -129,7 +131,7 @@ const setAppsConfiguration = async (
129131
*/
130132
const dispatchCustomPlayEvent = (uniqueId: string) => {
131133
document.dispatchEvent(
132-
new CustomEvent(customPlayEventName, {
134+
new CustomEvent(customYoutubePlayEventName, {
133135
detail: { uniqueId },
134136
}),
135137
);
@@ -592,13 +594,38 @@ export const YoutubeAtomPlayer = ({
592594
* add listener for custom play event
593595
*/
594596
document.addEventListener(
595-
customPlayEventName,
597+
customYoutubePlayEventName,
596598
handleCustomPlayEvent,
597599
);
598600

599-
customListeners.current[customPlayEventName] =
601+
customListeners.current[customYoutubePlayEventName] =
600602
handleCustomPlayEvent;
601603

604+
/**
605+
* Pauses all playing videos when a looping video is unmuted. If a user is
606+
* watching a looping video with sound, any playing Youtube video is paused.
607+
*/
608+
const handleCustomPlayLoopAudioEvent = (
609+
event: CustomEventInit<CustomPlayEventDetail>,
610+
) => {
611+
if (event.detail) {
612+
const playerStatePromise =
613+
player.current?.getPlayerState();
614+
void playerStatePromise?.then((playerState) => {
615+
if (playerState === YT.PlayerState.PLAYING) {
616+
void player.current?.pauseVideo();
617+
}
618+
});
619+
}
620+
};
621+
622+
document.addEventListener(
623+
customLoopPlayAudioEventName,
624+
handleCustomPlayLoopAudioEvent,
625+
);
626+
customListeners.current[customLoopPlayAudioEventName] =
627+
handleCustomPlayLoopAudioEvent;
628+
602629
playerListeners.current.push(
603630
{ name: 'onReady', listener: onReadyListener },
604631
{ name: 'onStateChange', listener: onStateChangeListener },

dotcom-rendering/src/lib/video.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
export type CustomPlayEventDetail = { uniqueId: string };
2+
3+
export const customLoopPlayAudioEventName = 'looping-video:play-with-audio';
4+
export const customYoutubePlayEventName = 'youtube-video:play';

0 commit comments

Comments
 (0)