Skip to content

Commit 979e15b

Browse files
authored
Merge branch 'main' into jm/feat-improve-sign-in-gate-click-tracking
2 parents 80aadde + 09e3da2 commit 979e15b

18 files changed

+408
-60
lines changed

dotcom-rendering/src/components/Card/Card.tsx

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ import { CardPicture } from '../CardPicture';
4242
import { Island } from '../Island';
4343
import { LatestLinks } from '../LatestLinks.importable';
4444
import { LoopVideo } from '../LoopVideo.importable';
45+
import type { SubtitleSize } from '../LoopVideoPlayer';
4546
import { Pill } from '../Pill';
4647
import { SlideshowCarousel } from '../SlideshowCarousel.importable';
4748
import { Snap } from '../Snap';
@@ -156,6 +157,7 @@ export type Props = {
156157
trailTextSize?: TrailTextSize;
157158
/** A kicker image is seperate to the main media and renders as part of the kicker */
158159
showKickerImage?: boolean;
160+
subtitleSize?: SubtitleSize;
159161
/** Determines if the headline should be positioned within the content or outside the content */
160162
headlinePosition?: 'inner' | 'outer';
161163
/** Feature flag for the labs redesign work */
@@ -405,6 +407,7 @@ export const Card = ({
405407
showKickerImage = false,
406408
headlinePosition = 'inner',
407409
showLabsRedesign = false,
410+
subtitleSize = 'small',
408411
enableLoopVideoCORS = false,
409412
}: Props) => {
410413
const hasSublinks = supportingContent && supportingContent.length > 0;
@@ -953,6 +956,10 @@ export const Card = ({
953956
fallbackImageAlt={media.imageAltText}
954957
fallbackImageAspectRatio="5:4"
955958
linkTo={linkTo}
959+
subtitleSource={
960+
media.mainMedia.subtitleSource
961+
}
962+
subtitleSize={subtitleSize}
956963
enableLoopVideoCORS={enableLoopVideoCORS}
957964
/>
958965
</Island>

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -323,6 +323,7 @@ export const SplashBoostLevels: Story = {
323323

324324
return (
325325
<>
326+
<Section title="Default" boostLevel="default" />
326327
<Section title="Boosted" boostLevel="boost" />
327328
<Section title="Mega boosted" boostLevel="megaboost" />
328329
<Section title="Giga boosted" boostLevel="gigaboost" />

dotcom-rendering/src/components/FlexibleGeneral.tsx

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ import type { ResponsiveFontSize } from './CardHeadline';
2121
import type { Loading } from './CardPicture';
2222
import { FeatureCard } from './FeatureCard';
2323
import { FrontCard } from './FrontCard';
24+
import type { SubtitleSize } from './LoopVideoPlayer';
2425
import type { Alignment } from './SupportingContent';
2526

2627
type Props = {
@@ -157,6 +158,7 @@ type BoostedSplashProperties = {
157158
supportingContentAlignment: Alignment;
158159
liveUpdatesAlignment: Alignment;
159160
trailTextSize: TrailTextSize;
161+
subtitleSize: SubtitleSize;
160162
avatarUrl?: string;
161163
};
162164

@@ -187,6 +189,7 @@ const decideSplashCardProperties = (
187189
supportingContentLength >= 4 ? 'horizontal' : 'vertical',
188190
liveUpdatesAlignment: 'vertical',
189191
trailTextSize: 'regular',
192+
subtitleSize: 'medium',
190193
};
191194
case 'boost':
192195
return {
@@ -202,6 +205,7 @@ const decideSplashCardProperties = (
202205
supportingContentLength >= 4 ? 'horizontal' : 'vertical',
203206
liveUpdatesAlignment: 'vertical',
204207
trailTextSize: 'regular',
208+
subtitleSize: 'medium',
205209
};
206210
case 'megaboost':
207211
return {
@@ -218,6 +222,7 @@ const decideSplashCardProperties = (
218222
supportingContentAlignment: 'horizontal',
219223
liveUpdatesAlignment: 'horizontal',
220224
trailTextSize: 'large',
225+
subtitleSize: 'large',
221226
};
222227
case 'gigaboost':
223228
return {
@@ -234,6 +239,7 @@ const decideSplashCardProperties = (
234239
supportingContentAlignment: 'horizontal',
235240
liveUpdatesAlignment: 'horizontal',
236241
trailTextSize: 'large',
242+
subtitleSize: 'large',
237243
};
238244
}
239245
};
@@ -298,6 +304,7 @@ const SplashCardLayout = ({
298304
supportingContentAlignment,
299305
liveUpdatesAlignment,
300306
trailTextSize,
307+
subtitleSize,
301308
} = decideSplashCardProperties(
302309
card.boostLevel ?? 'default',
303310
card.supportingContent?.length ?? 0,
@@ -347,6 +354,7 @@ const SplashCardLayout = ({
347354
trailTextSize={trailTextSize}
348355
canPlayInline={true}
349356
showKickerImage={card.format.design === ArticleDesign.Audio}
357+
subtitleSize={subtitleSize}
350358
headlinePosition={card.showLivePlayable ? 'outer' : 'inner'}
351359
showLabsRedesign={showLabsRedesign}
352360
enableLoopVideoCORS={enableLoopVideoCORS}
@@ -361,6 +369,7 @@ type BoostedCardProperties = {
361369
mediaSize: MediaSizeType;
362370
liveUpdatesPosition: Position;
363371
supportingContentAlignment: Alignment;
372+
subtitleSize: SubtitleSize;
364373
};
365374

366375
/**
@@ -384,6 +393,7 @@ const decideCardProperties = (
384393
liveUpdatesPosition: 'outer',
385394
supportingContentAlignment:
386395
supportingContentLength >= 2 ? 'horizontal' : 'vertical',
396+
subtitleSize: 'medium',
387397
};
388398
case 'boost':
389399
default:
@@ -397,6 +407,7 @@ const decideCardProperties = (
397407
liveUpdatesPosition: 'inner',
398408
supportingContentAlignment:
399409
supportingContentLength >= 2 ? 'horizontal' : 'vertical',
410+
subtitleSize: 'small',
400411
};
401412
}
402413
};
@@ -440,6 +451,7 @@ const FullWidthCardLayout = ({
440451
mediaSize,
441452
supportingContentAlignment,
442453
liveUpdatesPosition,
454+
subtitleSize,
443455
} = decideCardProperties(
444456
card.supportingContent?.length ?? 0,
445457
card.boostLevel,
@@ -505,6 +517,7 @@ const FullWidthCardLayout = ({
505517
canPlayInline={true}
506518
showKickerImage={card.format.design === ArticleDesign.Audio}
507519
showLabsRedesign={showLabsRedesign}
520+
subtitleSize={subtitleSize}
508521
enableLoopVideoCORS={enableLoopVideoCORS}
509522
/>
510523
</LI>

dotcom-rendering/src/components/FlexibleSpecial.tsx

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ import { UL } from './Card/components/UL';
1919
import type { ResponsiveFontSize } from './CardHeadline';
2020
import type { Loading } from './CardPicture';
2121
import { FrontCard } from './FrontCard';
22+
import type { SubtitleSize } from './LoopVideoPlayer';
2223
import type { Alignment } from './SupportingContent';
2324

2425
type Props = {
@@ -43,6 +44,7 @@ type BoostProperties = {
4344
supportingContentAlignment: Alignment;
4445
liveUpdatesAlignment: Alignment;
4546
trailTextSize: TrailTextSize;
47+
subtitleSize: SubtitleSize;
4648
};
4749

4850
/**
@@ -71,6 +73,7 @@ const determineCardProperties = (
7173
supportingContentLength >= 3 ? 'horizontal' : 'vertical',
7274
liveUpdatesAlignment: 'vertical',
7375
trailTextSize: 'regular',
76+
subtitleSize: 'medium',
7477
};
7578
case 'boost':
7679
return {
@@ -86,6 +89,7 @@ const determineCardProperties = (
8689
supportingContentLength >= 3 ? 'horizontal' : 'vertical',
8790
liveUpdatesAlignment: 'vertical',
8891
trailTextSize: 'regular',
92+
subtitleSize: 'medium',
8993
};
9094
case 'megaboost':
9195
return {
@@ -100,6 +104,7 @@ const determineCardProperties = (
100104
supportingContentAlignment: 'horizontal',
101105
liveUpdatesAlignment: 'horizontal',
102106
trailTextSize: 'large',
107+
subtitleSize: 'large',
103108
};
104109
case 'gigaboost':
105110
return {
@@ -114,6 +119,7 @@ const determineCardProperties = (
114119
supportingContentAlignment: 'horizontal',
115120
liveUpdatesAlignment: 'horizontal',
116121
trailTextSize: 'large',
122+
subtitleSize: 'large',
117123
};
118124
}
119125
};
@@ -159,6 +165,7 @@ export const OneCardLayout = ({
159165
supportingContentAlignment,
160166
liveUpdatesAlignment,
161167
trailTextSize,
168+
subtitleSize,
162169
} = determineCardProperties(
163170
card.boostLevel ?? 'default',
164171
card.supportingContent?.length ?? 0,
@@ -199,6 +206,7 @@ export const OneCardLayout = ({
199206
showKickerImage={card.format.design === ArticleDesign.Audio}
200207
headlinePosition={isSplashCard ? 'outer' : 'inner'}
201208
showLabsRedesign={showLabsRedesign}
209+
subtitleSize={subtitleSize}
202210
enableLoopVideoCORS={enableLoopVideoCORS}
203211
/>
204212
</LI>

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

Lines changed: 40 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import { css } from '@emotion/react';
22
import { log, storage } from '@guardian/libs';
3+
import { space } from '@guardian/source/foundations';
34
import { SvgAudio, SvgAudioMute } from '@guardian/source/react-components';
45
import { useCallback, useEffect, useRef, useState } from 'react';
56
import {
@@ -11,15 +12,20 @@ import { getZIndex } from '../lib/getZIndex';
1112
import { generateImageURL } from '../lib/image';
1213
import { useIsInView } from '../lib/useIsInView';
1314
import { useShouldAdapt } from '../lib/useShouldAdapt';
15+
import { useSubtitles } from '../lib/useSubtitles';
1416
import type { CustomPlayEventDetail, Source } from '../lib/video';
1517
import {
1618
customLoopPlayAudioEventName,
1719
customYoutubePlayEventName,
1820
} from '../lib/video';
1921
import { CardPicture, type Props as CardPictureProps } from './CardPicture';
2022
import { useConfig } from './ConfigContext';
23+
import type {
24+
PLAYER_STATES,
25+
PlayerStates,
26+
SubtitleSize,
27+
} from './LoopVideoPlayer';
2128
import { LoopVideoPlayer } from './LoopVideoPlayer';
22-
import type { PLAYER_STATES, PlayerStates } from './LoopVideoPlayer';
2329
import { ophanTrackerWeb } from './YoutubeAtom/eventEmitters';
2430

2531
const videoContainerStyles = css`
@@ -117,6 +123,8 @@ type Props = {
117123
fallbackImageAlt: CardPictureProps['alt'];
118124
fallbackImageAspectRatio: CardPictureProps['aspectRatio'];
119125
linkTo: string;
126+
subtitleSource?: string;
127+
subtitleSize: SubtitleSize;
120128
/** Feature flag for the enabling CORS loading on looping video */
121129
enableLoopVideoCORS?: boolean;
122130
};
@@ -134,6 +142,8 @@ export const LoopVideo = ({
134142
fallbackImageAlt,
135143
fallbackImageAspectRatio,
136144
linkTo,
145+
subtitleSource,
146+
subtitleSize,
137147
enableLoopVideoCORS = false,
138148
}: Props) => {
139149
const adapted = useShouldAdapt();
@@ -168,6 +178,12 @@ export const LoopVideo = ({
168178
threshold: VISIBILITY_THRESHOLD,
169179
});
170180

181+
const activeCue = useSubtitles({
182+
video: vidRef.current,
183+
playerState,
184+
currentTime,
185+
});
186+
171187
const playVideo = useCallback(async () => {
172188
const video = vidRef.current;
173189
if (!video) return;
@@ -489,6 +505,25 @@ export const LoopVideo = ({
489505
return FallbackImageComponent;
490506
}
491507

508+
const handleLoadedMetadata = () => {
509+
const video = vidRef.current;
510+
if (!video) return;
511+
512+
const track = video.textTracks[0];
513+
if (!track?.cues) return;
514+
const pxFromBottom = space[3];
515+
const videoHeight = video.getBoundingClientRect().height;
516+
const percentFromTop =
517+
((videoHeight - pxFromBottom) / videoHeight) * 100;
518+
519+
for (const cue of Array.from(track.cues)) {
520+
if (cue instanceof VTTCue) {
521+
cue.snapToLines = false;
522+
cue.line = percentFromTop;
523+
}
524+
}
525+
};
526+
492527
const handleLoadedData = () => {
493528
if (vidRef.current) {
494529
setHasAudio(doesVideoHaveAudio(vidRef.current));
@@ -628,6 +663,7 @@ export const LoopVideo = ({
628663
isPlayable={isPlayable}
629664
playerState={playerState}
630665
isMuted={isMuted}
666+
handleLoadedMetadata={handleLoadedMetadata}
631667
handleLoadedData={handleLoadedData}
632668
handleCanPlay={handleCanPlay}
633669
handlePlayPauseClick={handlePlayPauseClick}
@@ -638,6 +674,9 @@ export const LoopVideo = ({
638674
AudioIcon={hasAudio ? AudioIcon : null}
639675
preloadPartialData={preloadPartialData}
640676
showPlayIcon={showPlayIcon}
677+
subtitleSource={subtitleSource}
678+
subtitleSize={subtitleSize}
679+
activeCue={activeCue}
641680
enableLoopVideoCORS={enableLoopVideoCORS}
642681
/>
643682
</figure>

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ const meta = {
1212
parameters: {
1313
chromatic: {
1414
viewports: [breakpoints.mobile, breakpoints.wide],
15+
disableSnapshot: true,
1516
},
1617
},
1718
} satisfies Meta<typeof LoopVideo>;

0 commit comments

Comments
 (0)