Skip to content

Commit

Permalink
Add compact layout to video media player (#137)
Browse files Browse the repository at this point in the history
  • Loading branch information
sudhons authored Aug 2, 2024
1 parent 042613d commit c5bf591
Show file tree
Hide file tree
Showing 19 changed files with 398 additions and 223 deletions.
7 changes: 2 additions & 5 deletions .github/workflows/chromatic.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,5 @@ jobs:
node-version: 18
- name: Install dependencies
run: npm ci --unsafe-perm
- name: Publish to Chromatic
uses: chromaui/action@v1
with:
projectToken: ${{ secrets.CHROMATIC_PROJECT_TOKEN }}
buildScriptName: storybook:build
- name: Run tests
run: npm run test
51 changes: 6 additions & 45 deletions .storybook/stories/0-MediaPlayer.stories.tsx
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
import { Paper } from '@mui/material';
import { Meta, StoryFn } from '@storybook/react';
import * as React from 'react';
import { useToggle } from 'react-use';
import { makeStyles } from 'tss-react/mui';

import {
MediaPlayer,
MediaPlayerProps,
} from '../../src/components/media-player/MediaPlayer';
import { withDemoCard, withIntl, withPlayerTheme } from '../decorators';

const useStyles = makeStyles()(theme => ({
wrapper: {
height: theme.spacing(500),
Expand All @@ -33,31 +33,19 @@ const useStyles = makeStyles()(theme => ({

export const Basic: StoryFn<MediaPlayerProps> = args => {
const { classes } = useStyles();

return (
<div className={classes.wrapper}>
<MediaPlayer {...args} />
</div>
);
};

export const PIPModifiers: StoryFn<MediaPlayerProps> = args => {
const pipContainer = React.useRef<HTMLDivElement>(null);
const { classes } = useStyles();
const [collapse, toggleCollapse] = useToggle(true);

return (
<div className={classes.wrapper}>
<MediaPlayer
pipContainer={pipContainer}
pipPortalClassName={classes.pipLayout}
{...args}
collapse={collapse}
onToggleCollapse={toggleCollapse}
/>
<Paper elevation={3} ref={pipContainer} className={classes.pipContainer}>
PIP can be dragged only here
</Paper>
</div>
);
};

export default {
title: 'Media Player',
component: MediaPlayer,
Expand Down Expand Up @@ -87,33 +75,6 @@ export default {
defaultValue: { summary: undefined },
},
},
isPipEnabled: {
name: 'props.isPipEnabled',
description:
'Enables/disables all pip features(scrolling, entering/leaving PIP mode)',
table: {
type: { summary: 'boolean' },
defaultValue: { summary: true },
},
},
yAxisDistance: {
name: 'props.yAxisDistance',
description:
'Distance from window border bottom, on Y axis in `pixels`, for PIP player position initialization ',
table: {
type: { summary: 'number' },
defaultValue: { summary: 16 },
},
},
xAxisDistance: {
name: 'props.xAxisDistance',
description:
'Distance from window border right, on X axis in `pixels`, for PIP player position initialization',
table: {
type: { summary: 'number' },
defaultValue: { summary: 16 },
},
},
},
parameters: {
controls: { expanded: true },
Expand Down
11 changes: 0 additions & 11 deletions .storybook/stories/11-KaraokeMode.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -142,7 +142,6 @@ export const KaraokeMode: React.FC<KaraokeModeProps> = args => {
url={args.url}
onStoreUpdate={setMediaContext}
alarms={alarmRef.current}
isPipEnabled={args.isPipEnabled}
/>
<div>{timeStampsMemo}</div>
{createActiveSpan()}
Expand Down Expand Up @@ -176,15 +175,5 @@ export default {
defaultValue: { summary: 2 },
},
},
isPipEnabled: {
name: 'props.isPipEnabled',
description:
'Enables/disables all pip features(scrolling, entering/leaving PIP mode)',

table: {
type: { summary: 'boolean' },
defaultValue: { summary: true },
},
},
},
};
46 changes: 39 additions & 7 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@
"uuidv4": "^6.2.13"
},
"devDependencies": {
"@babel/plugin-proposal-private-property-in-object": "^7.21.11",
"@collaborne/github-badges": "^0.0.3",
"@emotion/react": "^11.10.5",
"@emotion/styled": "^11.10.5",
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import { IconButton } from '@mui/material';
import { PiArrowsInLineVertical, PiArrowsVertical } from 'react-icons/pi';

import { useOnHoveredControlElement } from '../../../hooks';

export interface CollapseIconButtonProps {
isCollapsed?: boolean;
onToggleCollapse: VoidFunction;
}

/**
* @category React Component
* @category UI Controls
*/
export function CollapseIconButton(props: CollapseIconButtonProps) {
const { onMouseEnter, onMouseLeave } = useOnHoveredControlElement();

const Icon = !props.isCollapsed ? PiArrowsInLineVertical : PiArrowsVertical;

return (
<IconButton
onMouseEnter={onMouseEnter}
onMouseLeave={onMouseLeave}
onClick={props.onToggleCollapse}
size="medium"
>
<Icon fontSize="medium" />
</IconButton>
);
}
2 changes: 1 addition & 1 deletion src/components/bottom-controls/useBottomControlsStyles.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { makeStyles } from 'tss-react/mui';

export const useBottomControlsStyles = makeStyles<{ isAudio: boolean }>()(
(theme, { isAudio }) => {
const bottomPadding = !isAudio ? theme.spacing(2) : 0;
const bottomPadding = !isAudio ? theme.spacing(1) : 0;
return {
bottomControls: {
display: 'flex',
Expand Down
9 changes: 0 additions & 9 deletions src/components/controls/Controls.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import { FC, ReactNode } from 'react';

import { useMediaStore } from '../../context';
import { CONTROLS } from '../../utils';

import { useControlsStyles } from './useControlsStyles';
Expand All @@ -21,18 +20,10 @@ export const Controls: FC<ControlProps> = ({
className,
'data-testid': dataTestId = CONTROLS,
}) => {
const showControls = useMediaStore(state => state.showControls);
const isAudio = useMediaStore(state => state.isAudio);

// Controls styles
const { classes, cx } = useControlsStyles();
const classNameControls = cx(classes.controls, className);

// Only <ProgressBar/> should be present if Controls components are not shown
if (!showControls && !isAudio) {
return null;
}

return (
<div className={classNameControls} data-testid={dataTestId}>
{children}
Expand Down
10 changes: 8 additions & 2 deletions src/components/controls/useControlsStyles.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,16 @@
import { makeStyles } from 'tss-react/mui';

export const useControlsStyles = makeStyles()({
export const useControlsStyles = makeStyles<{
isCollapsed?: boolean;
} | void>()((theme, { isCollapsed = false } = {}) => ({
controls: {
width: '100%',
height: '100%',
position: 'absolute',
pointerEvents: 'none',
...(isCollapsed && {
position: 'relative',
backgroundColor: theme.palette.common.black,
}),
},
});
}));
12 changes: 10 additions & 2 deletions src/components/media-container/MediaContainer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,10 @@ import { MediaPoster } from '../media-poster/MediaPoster';
import { Player } from '../player/Player';

import { useIsPlayerReadyHook } from './useIsPlayerReadyHook';
import { useMediaContainerStyles } from './useMediaContainerStyles';
import {
useFilePlayerStyles,
useMediaContainerStyles,
} from './useMediaContainerStyles';
import { useMouseActivityHook } from './useMouseActivityHook';
import { UsePipHook } from './UsePipHook';
import { useReactPlayerProps } from './useReactPlayerProps';
Expand Down Expand Up @@ -77,11 +80,16 @@ export const MediaContainer: FC<MediaContainerProps> = memo(
} = useMediaContainerStyles({
isAudio,
});
const { wrapper: playerWrapper } = useFilePlayerStyles({ isAudio }).classes;

const { isPlayerReady } = useIsPlayerReadyHook({ url });
const { onMouseEnter, onMouseLeave, onMouseMove } = useMouseActivityHook();
const { reactPlayerProps } = useReactPlayerProps();
const reactClassNames = cx(reactPlayer, reactPlayerClassName);
const reactClassNames = cx(
reactPlayer,
playerWrapper,
reactPlayerClassName,
);

const playerProps = {
url,
Expand Down
2 changes: 1 addition & 1 deletion src/components/media-container/useMediaContainerStyles.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ export const useMediaContainerStyles = makeStyles<{ isAudio: boolean }>()(
justifyContent: 'center',
backgroundSize: 'cover',
overflow: 'hidden',
height: isAudio ? theme.spacing(6.25) : 'unset',
height: isAudio ? theme.spacing(7.65) : 'unset',
borderRadius: isAudio ? theme.spacing(0.5, 0.5, 0, 0) : 'unset',
},
pipText: {
Expand Down
Loading

0 comments on commit c5bf591

Please sign in to comment.