Skip to content

Commit

Permalink
feat(player): add live stream support to default layout
Browse files Browse the repository at this point in the history
  • Loading branch information
mihar-22 committed Oct 1, 2023
1 parent 757841d commit 622d812
Show file tree
Hide file tree
Showing 23 changed files with 372 additions and 188 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -43,17 +43,17 @@
--media-tooltip-exit-animation: vds-tooltip-exit 0.2s ease-out;

/* Live Indicator. */
--media-live-indicator-bg: #8a8a8a;
--media-live-indicator-border-radius: 2px;
--media-live-indicator-color: #161616;
--media-live-indicator-edge-bg: #dc2626;
--media-live-indicator-edge-color: #f5f5f5;
--media-live-indicator-font-size: 12px;
--media-live-indicator-font-weight: 600;
--media-live-indicator-height: 40px;
--media-live-indicator-letter-spacing: 1.5px;
--media-live-indicator-padding: 1px 4px;
--media-live-indicator-width: 40px;
--media-live-button-bg: #8a8a8a;
--media-live-button-border-radius: 2px;
--media-live-button-color: #161616;
--media-live-button-edge-bg: #dc2626;
--media-live-button-edge-color: #f5f5f5;
--media-live-button-font-size: 12px;
--media-live-button-font-weight: 600;
--media-live-button-height: 40px;
--media-live-button-letter-spacing: 1.5px;
--media-live-button-padding: 1px 4px;
--media-live-button-width: 40px;

/* Captions. */
--media-captions-padding: 1%;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
import * as React from 'react';

import { Captions } from '../../ui/captions';
import * as Controls from '../../ui/controls';
import { DefaultAudioMenus } from './audio-menus';
import {
DefaultCaptionButton,
DefaultChapterTitle,
DefaultMuteButton,
DefaultPlayButton,
DefaultSeekButton,
DefaultTimeInfo,
DefaultTimeSlider,
DefaultVolumeSlider,
} from './shared-layout';

/* -------------------------------------------------------------------------------------------------
* DefaultAudioLayoutLarge
* -----------------------------------------------------------------------------------------------*/

function DefaultAudioLayoutLarge() {
return (
<>
<Captions className="vds-captions" />
<Controls.Root className="vds-controls">
<Controls.Group className="vds-controls-group">
<DefaultTimeSlider />
</Controls.Group>
<Controls.Group className="vds-controls-group">
<DefaultSeekButton seconds={-10} tooltip="top start" />
<DefaultPlayButton tooltip="top center" />
<DefaultSeekButton seconds={10} tooltip="top center" />
<DefaultTimeInfo />
<DefaultChapterTitle />
<DefaultMuteButton tooltip="top center" />
<DefaultVolumeSlider />
<DefaultCaptionButton tooltip="top center" />
<DefaultAudioMenus />
</Controls.Group>
</Controls.Root>
</>
);
}

DefaultAudioLayoutLarge.displayName = 'DefaultAudioLayoutLarge';
export { DefaultAudioLayoutLarge };
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
import * as React from 'react';

import { useMediaState } from '../../../hooks/use-media-state';
import { Captions } from '../../ui/captions';
import * as Controls from '../../ui/controls';
import { Time } from '../../ui/time';
import { DefaultAudioMenus } from './audio-menus';
import {
DefaultCaptionButton,
DefaultChapterTitle,
DefaultLiveButton,
DefaultMuteButton,
DefaultPlayButton,
DefaultSeekButton,
DefaultTimeSlider,
} from './shared-layout';

/* -------------------------------------------------------------------------------------------------
* DefaultAudioLayoutSmall
* -----------------------------------------------------------------------------------------------*/

function DefaultAudioLayoutSmall() {
return (
<>
<Captions className="vds-captions" />
<Controls.Root className="vds-controls">
<Controls.Group className="vds-controls-group">
<DefaultLivePlayButton />
<DefaultMuteButton tooltip="top start" />
<DefaultLiveButton />
<DefaultChapterTitle />
<DefaultCaptionButton tooltip="top center" />
<DefaultAudioMenus />
</Controls.Group>

<Controls.Group className="vds-controls-group">
<DefaultTimeSlider />
</Controls.Group>

<DefaultTimeControlsGroup />
<DefaultBottomControlsGroup />
</Controls.Root>
</>
);
}

DefaultAudioLayoutSmall.displayName = 'DefaultAudioLayoutSmall';
export { DefaultAudioLayoutSmall };

/* -------------------------------------------------------------------------------------------------
* DefaultLivePlayButton
* -----------------------------------------------------------------------------------------------*/

function DefaultLivePlayButton() {
const live = useMediaState('live'),
canSeek = useMediaState('canSeek');
return live && !canSeek ? <DefaultPlayButton tooltip="top start" /> : null;
}

DefaultLivePlayButton.displayName = 'DefaultLivePlayButton';

/* -------------------------------------------------------------------------------------------------
* DefaultTimeControlsGroup
* -----------------------------------------------------------------------------------------------*/

function DefaultTimeControlsGroup() {
const live = useMediaState('live');
return !live ? (
<Controls.Group className="vds-controls-group">
<Time className="vds-time" type="current" />
<div className="vds-controls-spacer" />
<Time className="vds-time" type="duration" />
</Controls.Group>
) : null;
}

DefaultTimeControlsGroup.displayName = 'DefaultTimeControlsGroup';

/* -------------------------------------------------------------------------------------------------
* DefaultBottomControlsGroup
* -----------------------------------------------------------------------------------------------*/

function DefaultBottomControlsGroup() {
const canSeek = useMediaState('canSeek');
return canSeek ? (
<Controls.Group className="vds-controls-group">
<div className="vds-controls-spacer" />
<DefaultSeekButton seconds={-10} tooltip="top center" />
<DefaultPlayButton tooltip="top center" />
<DefaultSeekButton seconds={10} tooltip="top center" />
<div className="vds-controls-spacer" />
</Controls.Group>
) : null;
}

DefaultBottomControlsGroup.displayName = 'DefaultBottomControlsGroup';
112 changes: 3 additions & 109 deletions packages/react/src/components/layouts/default/audio-layout.tsx
Original file line number Diff line number Diff line change
@@ -1,23 +1,6 @@
import * as React from 'react';

import { Captions } from '../../ui/captions';
import * as Controls from '../../ui/controls';
import { Time } from '../../ui/time';
import { DefaultLayoutContext } from './context';
import {
createDefaultMediaLayout,
DefaultCaptionButton,
DefaultChaptersMenu,
DefaultChapterTitle,
DefaultMuteButton,
DefaultPlayButton,
DefaultSeekButton,
DefaultSettingsMenu,
DefaultTimeGroup,
DefaultTimeSlider,
DefaultVolumeSlider,
type DefaultMediaLayoutProps,
} from './shared-layout';
import { DefaultAudioLayoutLarge } from './audio-layout-large';
import { DefaultAudioLayoutSmall } from './audio-layout-small';
import { createDefaultMediaLayout, type DefaultMediaLayoutProps } from './shared-layout';

/* -------------------------------------------------------------------------------------------------
* DefaultAudioLayout
Expand Down Expand Up @@ -49,92 +32,3 @@ const DefaultAudioLayout = createDefaultMediaLayout({

DefaultAudioLayout.displayName = 'DefaultAudioLayout';
export { DefaultAudioLayout };

/* -------------------------------------------------------------------------------------------------
* DefaultAudioLayoutLarge
* -----------------------------------------------------------------------------------------------*/

function DefaultAudioLayoutLarge() {
return (
<>
<Captions className="vds-captions" />
<Controls.Root className="vds-controls">
<Controls.Group className="vds-controls-group">
<DefaultTimeSlider />
</Controls.Group>
<Controls.Group className="vds-controls-group">
<DefaultSeekButton seconds={-10} tooltip="top start" />
<DefaultPlayButton tooltip="top center" />
<DefaultSeekButton seconds={10} tooltip="top center" />
<DefaultTimeGroup />
<DefaultChapterTitle />
<DefaultMuteButton tooltip="top center" />
<DefaultVolumeSlider />
<DefaultCaptionButton tooltip="top center" />
<DefaultAudioMenus />
</Controls.Group>
</Controls.Root>
</>
);
}

DefaultAudioLayoutLarge.displayName = 'DefaultAudioLayoutLarge';
export { DefaultAudioLayoutLarge };

/* -------------------------------------------------------------------------------------------------
* DefaultAudioLayoutSmall
* -----------------------------------------------------------------------------------------------*/

function DefaultAudioLayoutSmall() {
return (
<>
<Captions className="vds-captions" />
<Controls.Root className="vds-controls">
<Controls.Group className="vds-controls-group">
<DefaultMuteButton tooltip="top start" />
<DefaultChapterTitle />
<DefaultCaptionButton tooltip="top center" />
<DefaultAudioMenus />
</Controls.Group>

<Controls.Group className="vds-controls-group">
<DefaultTimeSlider />
</Controls.Group>

<Controls.Group className="vds-controls-group">
<Time className="vds-time" type="current" />
<div className="vds-controls-spacer" />
<Time className="vds-time" type="duration" />
</Controls.Group>

<Controls.Group className="vds-controls-group">
<div className="vds-controls-spacer" />
<DefaultSeekButton seconds={-10} tooltip="top center" />
<DefaultPlayButton tooltip="top center" />
<DefaultSeekButton seconds={10} tooltip="top center" />
<div className="vds-controls-spacer" />
</Controls.Group>
</Controls.Root>
</>
);
}

DefaultAudioLayoutSmall.displayName = 'DefaultAudioLayoutSmall';
export { DefaultAudioLayoutSmall };

/* -------------------------------------------------------------------------------------------------
* DefaultAudioMenus
* -----------------------------------------------------------------------------------------------*/

function DefaultAudioMenus() {
const { isSmallLayout, noModal } = React.useContext(DefaultLayoutContext),
placement = noModal ? 'top end' : !isSmallLayout ? 'top end' : null;
return (
<>
<DefaultChaptersMenu tooltip="top" placement={placement} portalClass="vds-audio-layout" />
<DefaultSettingsMenu tooltip="top end" placement={placement} portalClass="vds-audio-layout" />
</>
);
}

DefaultAudioMenus.displayName = 'DefaultAudioMenus';
22 changes: 22 additions & 0 deletions packages/react/src/components/layouts/default/audio-menus.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import * as React from 'react';

import { DefaultLayoutContext } from './context';
import { DefaultChaptersMenu, DefaultSettingsMenu } from './shared-layout';

/* -------------------------------------------------------------------------------------------------
* DefaultAudioMenus
* -----------------------------------------------------------------------------------------------*/

function DefaultAudioMenus() {
const { isSmallLayout, noModal } = React.useContext(DefaultLayoutContext),
placement = noModal ? 'top end' : !isSmallLayout ? 'top end' : null;
return (
<>
<DefaultChaptersMenu tooltip="top" placement={placement} portalClass="vds-audio-layout" />
<DefaultSettingsMenu tooltip="top end" placement={placement} portalClass="vds-audio-layout" />
</>
);
}

DefaultAudioMenus.displayName = 'DefaultAudioMenus';
export { DefaultAudioMenus };
33 changes: 31 additions & 2 deletions packages/react/src/components/layouts/default/shared-layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import { usePlayerQuery } from '../../../hooks/use-player-query';
import type { PrimitivePropsWithRef } from '../../primitives/nodes';
import { CaptionButton } from '../../ui/buttons/caption-button';
import { FullscreenButton } from '../../ui/buttons/fullscreen-button';
import { LiveButton } from '../../ui/buttons/live-button';
import { MuteButton } from '../../ui/buttons/mute-button';
import { PIPButton } from '../../ui/buttons/pip-button';
import { PlayButton } from '../../ui/buttons/play-button';
Expand Down Expand Up @@ -141,11 +142,11 @@ export const createDefaultMediaLayout = ({
) => {
const $canLoad = useMediaState('canLoad'),
$viewType = useMediaState('viewType'),
isMatch = $viewType === type,
$streamType = useMediaState('streamType'),
isMatch = $viewType === type && $streamType !== 'unknown',
isForcedLayout = typeof smallLayoutWhen === 'boolean',
isSmallLayoutMatch = usePlayerQuery(isString(smallLayoutWhen) ? smallLayoutWhen : ''),
isSmallLayout = isForcedLayout ? smallLayoutWhen : isSmallLayoutMatch;

return (
<div
{...props}
Expand Down Expand Up @@ -426,6 +427,22 @@ function DefaultChapterTitle() {
DefaultChapterTitle.displayName = 'DefaultChapterTitle';
export { DefaultChapterTitle };

/* -------------------------------------------------------------------------------------------------
* DefaultLiveButton
* -----------------------------------------------------------------------------------------------*/

function DefaultLiveButton() {
const live = useMediaState('live');
return live ? (
<LiveButton className="vds-live-button">
<span className="vds-live-button-text">LIVE</span>
</LiveButton>
) : null;
}

DefaultLiveButton.displayName = 'DefaultLiveButton';
export { DefaultLiveButton };

/* -------------------------------------------------------------------------------------------------
* DefaultTimeGroup
* -----------------------------------------------------------------------------------------------*/
Expand All @@ -443,6 +460,18 @@ function DefaultTimeGroup() {
DefaultTimeGroup.displayName = 'DefaultTimeGroup';
export { DefaultTimeGroup };

/* -------------------------------------------------------------------------------------------------
* DefaultTimeInfo
* -----------------------------------------------------------------------------------------------*/

function DefaultTimeInfo() {
const live = useMediaState('live');
return live ? <DefaultLiveButton /> : <DefaultTimeGroup />;
}

DefaultTimeInfo.displayName = 'DefaultTimeInfo';
export { DefaultTimeInfo };

/* -------------------------------------------------------------------------------------------------
* DefaultChaptersMenu
* -----------------------------------------------------------------------------------------------*/
Expand Down
Loading

0 comments on commit 622d812

Please sign in to comment.