Skip to content

Commit

Permalink
Merge branch 'main' of github.com:guardian/dotcom-rendering into e2e/…
Browse files Browse the repository at this point in the history
…layout-audio-page

# Conflicts:
#	dotcom-rendering/src/components/AudioPlayer/AudioPlayer.tsx
#	dotcom-rendering/src/components/AudioPlayer/components/Playback.tsx
#	dotcom-rendering/src/components/Picture.tsx
  • Loading branch information
sndrs committed Oct 24, 2024
2 parents 75d7c44 + 9fcf2ca commit 81c429b
Show file tree
Hide file tree
Showing 35 changed files with 784 additions and 505 deletions.
91 changes: 35 additions & 56 deletions dotcom-rendering/src/components/AudioPlayer/AudioPlayer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ import { CurrentTime, Duration } from './components/time';
import { Volume } from './components/Volume';
import { Wrapper } from './components/Wrapper';

// ********************* ophan stuff *********************

// possible events for audio in ophan
type AudioEvents = TAudioEventType extends `audio:content:${infer E}`
? E
Expand All @@ -21,6 +23,21 @@ type AudioProgressEvents = Extract<
? N
: never;

const reportAudioEvent = (mediaId: string, eventName: AudioEvents) => {
const audioEvent: AudioEvent = {
id: mediaId,
eventType: `audio:content:${eventName}`,
};

void getOphan('Web').then((ophan) => {
ophan.record({
audio: audioEvent,
});
});
};

// ********************* Component *********************

type AudioPlayerProps = {
/** The audio source you want to play. */
src: string;
Expand All @@ -47,31 +64,6 @@ export const AudioPlayer = ({
showVolumeControls = true,
mediaId,
}: AudioPlayerProps) => {
// ********************* ophan stuff *********************

// we'll send listening progress reports to ophan at these percentage points
// through playback (100% is handled by the 'ended' event)
const audioProgressEvents = useRef<Set<AudioProgressEvents>>(
new Set([25, 50, 75]),
);

// wrapper to send audio events to ophan
const reportAudioEvent = useCallback(
(eventName: AudioEvents) => {
const audioEvent: AudioEvent = {
id: mediaId,
eventType: `audio:content:${eventName}`,
};

void getOphan('Web').then((ophan) => {
ophan.record({
audio: audioEvent,
});
});
},
[mediaId],
);

// ********************* player *********************

// state for displaying feedback to the user
Expand All @@ -89,15 +81,15 @@ export const AudioPlayer = ({
// ref to the <audio /> element that handles playback
const audioRef = useRef<HTMLAudioElement>(null);

// ******************** events *********************
// ********************* ophan stuff *********************

const onWaiting = useCallback(() => {
setIsWaiting(true);
}, []);
// we'll send listening progress reports to ophan at these percentage points
// through playback (100% is handled by the 'ended' event)
const audioProgressEvents = useRef<Set<AudioProgressEvents>>(
new Set([25, 50, 75]),
);

const onCanPlay = useCallback(() => {
setIsWaiting(false);
}, []);
// ******************** events *********************

const onTimeupdate = useCallback(() => {
if (audioRef.current) {
Expand All @@ -115,30 +107,21 @@ export const AudioPlayer = ({
for (const stage of audioProgressEvents.current) {
if (newProgress >= stage) {
audioProgressEvents.current.delete(stage);
reportAudioEvent(String(stage) as AudioEvents);
reportAudioEvent(mediaId, String(stage) as AudioEvents);
}
}
}
}
}, [isPlaying, reportAudioEvent]);
}, [isPlaying, mediaId]);

const onPlay = useCallback(() => {
setIsPlaying(true);

if (isFirstPlay.current) {
isFirstPlay.current = false;

reportAudioEvent('play');
reportAudioEvent(mediaId, 'play');
}
}, [reportAudioEvent]);

const onPause = useCallback(() => {
setIsPlaying(false);
}, []);

const onEnded = useCallback(() => {
reportAudioEvent('end');
}, [reportAudioEvent]);
}, [mediaId]);

const onProgress = useCallback(() => {
if (audioRef.current) {
Expand Down Expand Up @@ -263,6 +246,12 @@ export const AudioPlayer = ({

const audio = audioRef.current;

const onPause = () => setIsPlaying(false);
const onEnded = () => reportAudioEvent(mediaId, 'end');

const onWaiting = () => setIsWaiting(true);
const onCanPlay = () => setIsWaiting(false);

audio.addEventListener('waiting', onWaiting);
audio.addEventListener('canplay', onCanPlay);
audio.addEventListener('timeupdate', onTimeupdate);
Expand All @@ -286,17 +275,7 @@ export const AudioPlayer = ({
audio.removeEventListener('error', onError);
audio.removeEventListener('progress', onProgress);
};
}, [
onTimeupdate,
onDurationChange,
onPlay,
onPause,
onEnded,
onError,
onWaiting,
onCanPlay,
onProgress,
]);
}, [onTimeupdate, onDurationChange, onPlay, onError, onProgress, mediaId]);

return (
<>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ Playback.Play = ({
} & ButtonProps) => {
return (
<button
aria-label="Play"
aria-label={isPlaying ? 'Pause' : 'Play'}
type="button"
css={[
buttonBaseCss,
Expand Down
1 change: 0 additions & 1 deletion dotcom-rendering/src/components/Byline.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,6 @@ const bylineStyles = (size: SmallHeadlineSize, isLabs: boolean) => {
if (isLabs) {
return css`
${textSansItalic24};
font-size: 24px;
line-height: 24px;
${until.desktop} {
${textSansItalic24};
Expand Down
19 changes: 10 additions & 9 deletions dotcom-rendering/src/components/Card/Card.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ const basicCardProps: CardProps = {
headlineText: 'Headline text',
trailText:
'The 29-year-old source behind the biggest intelligence leak in the NSA’s history explains his motives',
headlineSize: 'medium',
headlineSizes: { desktop: 'xsmall' },
kickerText: '',
webPublicationDate: new Date(Date.now() - 60 * 60 * 1000).toString(),
image: {
Expand Down Expand Up @@ -209,34 +209,35 @@ export default {
],
};

/** TODO : Update stories once initial chromatic check has passed on new font size scale */
export const WithDifferentHeadlineSizes = () => {
return (
<CardGroup>
<CardWrapper>
<Card
{...basicCardProps}
headlineSize="tiny"
headlineSizes={{ desktop: 'tiny' }}
headlineText="tiny"
/>
</CardWrapper>
<CardWrapper>
<Card
{...basicCardProps}
headlineSize="small"
headlineSizes={{ desktop: 'xxsmall' }}
headlineText="small"
/>
</CardWrapper>
<CardWrapper>
<Card
{...basicCardProps}
headlineSize="medium"
headlineSizes={{ desktop: 'xsmall' }}
headlineText="medium"
/>
</CardWrapper>
<CardWrapper>
<Card
{...basicCardProps}
headlineSize="large"
headlineSizes={{ desktop: 'small' }}
headlineText="large"
/>
</CardWrapper>
Expand Down Expand Up @@ -266,7 +267,7 @@ export const WithExternalLink = () => {
{...basicCardProps}
imagePositionOnDesktop="right"
kickerText="Instagram"
headlineSize="huge"
headlineSizes={{ desktop: 'medium', tablet: 'small' }}
headlineText="Follow The Guardian now"
isExternalLink={true}
/>
Expand Down Expand Up @@ -1103,7 +1104,7 @@ export const WithLetterDesign = () => {
<CardWrapper>
<Card
{...basicCardProps}
headlineSize="small"
headlineSizes={{ desktop: 'xxsmall' }}
headlineText="Culture"
format={{
display: ArticleDisplay.Standard,
Expand All @@ -1122,7 +1123,7 @@ export const WithLetterDesignAndShowQuotedHeadline = () => {
<CardWrapper>
<Card
{...basicCardProps}
headlineSize="small"
headlineSizes={{ desktop: 'xxsmall' }}
headlineText="Culture"
showQuotedHeadline={true}
format={{
Expand Down Expand Up @@ -1372,7 +1373,7 @@ export const DynamoWithSpecialPaletteVariations = () => {
containerType="dynamic/package"
isDynamo={true}
kickerText="Main kicker"
headlineSize="huge"
headlineSizes={{ desktop: 'medium', tablet: 'small' }}
imagePositionOnDesktop="bottom"
imagePositionOnMobile="bottom"
imageSize="large"
Expand Down
38 changes: 17 additions & 21 deletions dotcom-rendering/src/components/Card/Card.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ import type { MainMedia } from '../../types/mainMedia';
import type { OnwardsSource } from '../../types/onwards';
import { Avatar } from '../Avatar';
import { CardCommentCount } from '../CardCommentCount.importable';
import { CardHeadline } from '../CardHeadline';
import { CardHeadline, type ResponsiveFontSize } from '../CardHeadline';
import type { AspectRatio, Loading } from '../CardPicture';
import { CardPicture } from '../CardPicture';
import { Island } from '../Island';
Expand Down Expand Up @@ -62,9 +62,7 @@ export type Props = {
format: ArticleFormat;
absoluteServerTimes: boolean;
headlineText: string;
headlineSize?: SmallHeadlineSize;
headlineSizeOnMobile?: SmallHeadlineSize;
headlineSizeOnTablet?: SmallHeadlineSize;
headlineSizes?: ResponsiveFontSize;
showQuotedHeadline?: boolean;
byline?: string;
showByline?: boolean;
Expand Down Expand Up @@ -118,8 +116,6 @@ export type Props = {
isTagPage?: boolean;
/** Alows the consumer to set an aspect ratio on the image of 5:3 or 5:4 */
aspectRatio?: AspectRatio;
/** Alows the consumer to use a larger font size group for boost styling*/
boostedFontSizes?: boolean;
index?: number;
/** The Splash card in a flexible container gets a different visual treatment to other cards*/
isFlexSplash?: boolean;
Expand Down Expand Up @@ -267,9 +263,7 @@ export const Card = ({
linkTo,
format,
headlineText,
headlineSize,
headlineSizeOnMobile,
headlineSizeOnTablet,
headlineSizes,
showQuotedHeadline,
byline,
showByline,
Expand Down Expand Up @@ -313,7 +307,6 @@ export const Card = ({
absoluteServerTimes,
isTagPage = false,
aspectRatio,
boostedFontSizes,
index = 0,
isFlexSplash,
showTopBarDesktop = true,
Expand Down Expand Up @@ -544,9 +537,7 @@ export const Card = ({
<CardHeadline
headlineText={headlineText}
format={format}
size={headlineSize}
sizeOnMobile={headlineSizeOnMobile}
sizeOnTablet={headlineSizeOnTablet}
fontSizes={headlineSizes}
showQuotes={showQuotes}
kickerText={
format.design === ArticleDesign.LiveBlog &&
Expand All @@ -561,7 +552,6 @@ export const Card = ({
byline={byline}
showByline={showByline}
isExternalLink={isExternalLink}
boostedFontSizes={boostedFontSizes}
/>
{!isUndefined(starRating) ? (
<StarRatingComponent
Expand Down Expand Up @@ -665,15 +655,24 @@ export const Card = ({
imagePositionOnMobile={
imagePositionOnMobile
}
//** TODO: IMPROVE THIS MAPPING */
// image size defaults to small if not provided. However, if the headline size is large or greater, we want to assume the image is also large so that the play icon is correctly sized.
imageSize={
headlineSize === 'huge' ||
headlineSize === 'large' ||
headlineSize === 'ginormous'
[
'small',
'medium',
'large',
'xlarge',
'xxlarge',
].includes(
headlineSizes?.desktop ??
'',
)
? 'large'
: imageSize
}
enableAds={false}
aspectRatio={aspectRatio}
/>
</Island>
</div>
Expand Down Expand Up @@ -752,9 +751,7 @@ export const Card = ({
<CardHeadline
headlineText={headlineText}
format={format}
size={headlineSize}
sizeOnMobile={headlineSizeOnMobile}
sizeOnTablet={headlineSizeOnTablet}
fontSizes={headlineSizes}
showQuotes={showQuotes}
kickerText={
format.design ===
Expand All @@ -771,7 +768,6 @@ export const Card = ({
byline={byline}
showByline={showByline}
isExternalLink={isExternalLink}
boostedFontSizes={boostedFontSizes}
/>
{!isUndefined(starRating) ? (
<StarRatingComponent
Expand Down
11 changes: 7 additions & 4 deletions dotcom-rendering/src/components/Card/components/TrailText.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -58,10 +58,13 @@ export const TrailText = ({
fontStyles(trailTextSize),
padTop && topPadding,
]}
dangerouslySetInnerHTML={{
__html: text,
}}
/>
>
<div
dangerouslySetInnerHTML={{
__html: text,
}}
/>
</div>
);
return hideUntil ? (
<Hide until={hideUntil}>{trailText}</Hide>
Expand Down
Loading

0 comments on commit 81c429b

Please sign in to comment.