Skip to content

Commit

Permalink
feat: APP-313 add video controls (#2461)
Browse files Browse the repository at this point in the history
Co-authored-by: Ralph <“[email protected]>
  • Loading branch information
r41ph and Ralph committed Sep 10, 2024
1 parent 7f0f673 commit c6f773e
Show file tree
Hide file tree
Showing 14 changed files with 149 additions and 66 deletions.
3 changes: 3 additions & 0 deletions tailwind.common.js
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,9 @@ module.exports = {
fontWeight: {
inherit: "inherit",
},
backgroundColor: {
transparent: 'transparent',
},
},
},
plugins: [],
Expand Down

This file was deleted.

16 changes: 0 additions & 16 deletions web-components/src/components/atoms/PlayButton/PlayButton.tsx

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import { Meta, StoryObj } from '@storybook/react';

import { PlayPauseButton } from './PlayPauseButton';

export default {
title: 'atoms/PlayPauseButton',
component: PlayPauseButton,
} as Meta<typeof PlayPauseButton>;

type Story = StoryObj<typeof PlayPauseButton>;

export const Play: Story = {
render: args => <PlayPauseButton {...args} />,
};

Play.args = {
playing: false,
};

export const Pause: Story = {
render: args => <PlayPauseButton {...args} />,
};

Pause.args = {
playing: true,
};
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import { Theme } from '@mui/material/styles';
import { makeStyles } from 'tss-react/mui';

export const usePlayButtonStyles = makeStyles()((theme: Theme) => ({
play: {
export const usePlayPauseButtonStyles = makeStyles()((theme: Theme) => ({
button: {
background: theme.palette.primary.main,
borderRadius: '50%',
width: theme.spacing(17.5),
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import { cn } from '../../../utils/styles/cn';
import { PauseIcon } from '../../icons/PauseIcon';
import PlayIcon from '../../icons/PlayIcon';
import { usePlayPauseButtonStyles } from './PlayPauseButton.styles';

type Props = {
className?: string;
playing?: boolean;
handlePlayPause?: () => void;
};

export const PlayPauseButton = ({
className,
playing = false,
handlePlayPause,
}: Props) => {
const { classes: styles } = usePlayPauseButtonStyles();
return (
<button
onClick={handlePlayPause ? handlePlayPause : undefined}
className="outline-none cursor-pointer bg-transparent border-none"
>
<div className={cn(styles.button, className)}>
{playing ? (
<PauseIcon width="100%" height="100%" />
) : (
<PlayIcon width="50%" height="50%" />
)}
</div>
</button>
);
};
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { Box } from '@mui/material';

import { PlayButton } from '../../atoms/PlayButton/PlayButton';
import { PlayPauseButton } from '../../atoms/PlayPauseButton/PlayPauseButton';
import OutlinedButton from '../../buttons/OutlinedButton';
import { Body } from '../../typography';
import MediaCard from '../MediaCard/MediaCard';
Expand Down Expand Up @@ -56,7 +56,7 @@ export default function ArticleCard({
elevation={1}
draftText={draftText}
>
{play && <PlayButton />}
{play && <PlayPauseButton />}
<Body size="sm" sx={{ flex: '1 0 auto', py: [2.5, 2], px: [4, 5] }}>
<Box component="span" sx={{ fontWeight: 'bold' }}>
{author}
Expand Down
21 changes: 21 additions & 0 deletions web-components/src/components/icons/PauseIcon.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
export const PauseIcon = (props: React.SVGProps<SVGSVGElement>) => (
<svg viewBox="0 0 70 70" {...props}>
<g id="Pause icon">
<circle
id="Ellipse 3"
cx="35"
cy="35"
r="35"
fill="white"
fill-opacity="0.9"
/>
<path
id="Union"
fill-rule="evenodd"
clip-rule="evenodd"
d="M32 20H25V50H32V20ZM45 20H38V50H45V20Z"
fill="#4FB573"
/>
</g>
</svg>
);
4 changes: 3 additions & 1 deletion web-components/src/components/icons/icons.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@ import { OpenInNewIcon } from './OpenInNewIcon';
import OrganizationIcon from './OrganizationIcon';
import { OtherDocumentsIcon } from './OtherDocumentsIcon';
import OutlinedCheckIcon from './OutlinedCheckIcon';
import { PauseIcon } from './PauseIcon';
import { PdfFileIcon } from './PdfFileIcon';
import PendingIcon from './PendingIcon';
import PhoneIcon from './PhoneIcon';
Expand Down Expand Up @@ -132,9 +133,9 @@ import VerifiedIcon from './VerifiedIcon';
import { VideoIcon } from './VideoIcon';
import WalletErrorIcon from './WalletErrorIcon';
import { WalletIcon } from './WalletIcon';
import WarningIcon from './WarningIcon';
import WhitepaperIcon from './WhitepaperIcon';
import ZoomIcon from './ZoomIcon';
import WarningIcon from './WarningIcon';

export default {
title: 'Icons',
Expand Down Expand Up @@ -306,6 +307,7 @@ export const allIcons = (): JSX.Element => (
/>
<LabeledIcon icon={<PinIcon fontSize="small" />} label="PinIcon" />
<LabeledIcon icon={<PlayIcon height={'20px'} />} label="PlayIcon" />
<LabeledIcon icon={<PauseIcon height={'50px'} />} label="PauseIcon" />
<LabeledIcon icon={<PlusIcon />} label="PlusIcon" />
<LabeledIcon icon={<PointerIcon />} label="PointerIcon" />
<LabeledIcon icon={<PrefinanceIcon />} label="PrefinanceIcon" />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,9 @@ import {
useTheme,
} from '@mui/material';
import { Feature } from 'geojson';
import { PlayPauseButton } from 'web-components/src/components/atoms/PlayPauseButton/PlayPauseButton';

import { cn } from '../../../../utils/styles/cn';
import { PlayButton } from '../../../atoms/PlayButton/PlayButton';
import ArrowDownIcon from '../../../icons/ArrowDownIcon';
import { DragIcon } from '../../../icons/DragIcon';
import EditIcon from '../../../icons/EditIcon';
Expand Down Expand Up @@ -124,7 +124,7 @@ export const FileDropFile = ({
'absolute top-0 left-0 bg-grey-700 rounded-[5px] overflow-hidden',
)}
/>
<PlayButton />
<PlayPauseButton />
</>
) : isPdf(mimeType) ? (
<PdfPreview
Expand Down
15 changes: 3 additions & 12 deletions web-components/src/components/organisms/Gallery/Gallery.tsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,10 @@
import { useState } from 'react';
import ReactPlayer from 'react-player/es6';
import { Box, SxProps, useTheme } from '@mui/material';
import { AnimatePresence, motion, PanInfo } from 'framer-motion';
import { wrap } from 'popmotion';

import { Theme } from '../../../theme/muiTheme';
import { sxToArray } from '../../../utils/mui/sxToArray';
import { PlayButton } from '../../atoms/PlayButton/PlayButton';
import { OpenInNewIcon } from '../../icons/OpenInNewIcon';
import {
isAudio,
Expand All @@ -20,6 +18,7 @@ import {
} from '../../inputs/new/FileDrop/FileDrop.utils';
import { PdfPreview } from '../PostFiles/components/PdfPreview';
import { TextOrIconFilePreview } from '../PostFiles/components/TextOrIconFilePreview';
import { VideoPreview } from '../PostFiles/components/VideoPreview';
import { FilesPreviews } from '../PostFiles/PostFiles.types';
import { getColors } from '../PostFiles/PostFiles.utils';
import { GalleryBottomBar } from './Gallery.BottomBar';
Expand Down Expand Up @@ -122,17 +121,9 @@ const Gallery = ({
<AnimatePresence initial={false} custom={direction}>
{allImages || isImage(item?.mimeType) ? (
<motion.img key={page} src={item?.url} {...motionSettings} />
) : isVideo(item?.mimeType) ? (
) : isVideo(item?.mimeType) && item?.url ? (
<motion.div key={page} {...motionSettings}>
<ReactPlayer url={item?.url} width="100%" height="100%" />
<a
target="_blank"
rel="noopener noreferrer"
href={item?.url}
className="outline-none cursor-pointer"
>
<PlayButton className="w-100 h-100 sm:top-[33%]" />
</a>
<VideoPreview url={item?.url} buttonClassName="lg:top-[42%]" />
</motion.div>
) : (
<motion.div key={page} {...motionSettings}>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,10 @@ import { useEffect, useRef, useState } from 'react';
import ReactPlayer from 'react-player/es6';
import { Slide } from '@mui/material';
import { Point } from 'geojson';
import { PlayPauseButton } from 'web-components/src/components/atoms/PlayPauseButton/PlayPauseButton';

import { UseStateSetter } from '../../../types/react/useState';
import { cn } from '../../../utils/styles/cn';
import { PlayButton } from '../../atoms/PlayButton/PlayButton';
import BreadcrumbIcon from '../../icons/BreadcrumbIcon';
import { Image } from '../../image';
import {
Expand Down Expand Up @@ -113,7 +113,7 @@ const PostFilesDrawer = ({
width="100%"
height="100%"
/>
<PlayButton className="w-[28px] h-[28px]" />
<PlayPauseButton className="w-[28px] h-[28px] top-[40%]" />
</div>
)}
<FileBody file={file} />
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
import ReactPlayer from 'react-player/es6';
import { Box } from '@mui/material';

import { cn } from '../../../../utils/styles/cn';
import { PlayButton } from '../../../atoms/PlayButton/PlayButton';
import {
isAudio,
isCsv,
Expand All @@ -18,6 +16,7 @@ import { PostFile } from '../PostFiles';
import { getColors } from '../PostFiles.utils';
import { PdfPreview } from './PdfPreview';
import { TextOrIconFilePreview } from './TextOrIconFilePreview';
import { VideoPreview } from './VideoPreview';

export type FileToPreview = Pick<PostFile, 'mimeType' | 'url' | 'name'>;
type Props = {
Expand Down Expand Up @@ -66,18 +65,8 @@ const FilePreview = ({
linearGradientClassName,
)}
/>
{video ? (
<>
<ReactPlayer url={url} width="100%" height="100%" />
<a
target="_blank"
rel="noopener noreferrer"
href={url}
className="outline-none cursor-pointer"
>
<PlayButton className="w-50 h-50" />
</a>
</>
{video && url ? (
<VideoPreview url={url} />
) : isPdf(mimeType) ? (
<PdfPreview
file={url}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
import { useState } from 'react';
import ReactPlayer from 'react-player/es6';
import { PlayPauseButton } from 'web-components/src/components/atoms/PlayPauseButton/PlayPauseButton';

export const VideoPreview = ({
url,
buttonClassName = '',
}: {
url: string;
buttonClassName?: string;
}) => {
const [playing, setPlaying] = useState(false);
const [hovered, setHovered] = useState(false);

const handlePlayPause = () => {
setPlaying(!playing);
};
const handleMouseEnter = () => {
setHovered(true);
};
const handleMouseLeave = () => {
setHovered(false);
};

return (
<div className="relative h-full">
<ReactPlayer
url={url}
width="100%"
height="100%"
playing={playing}
controls={false}
onEnded={() => setPlaying(false)}
/>
<div
className={`z-50 absolute top-0 left-0 w-full h-full flex justify-center items-center ${
playing ? 'transition-opacity duration-500 opacity-0' : ''
} ${playing && hovered ? 'hover:opacity-100' : ''}`}
onMouseEnter={playing ? handleMouseEnter : undefined}
onMouseLeave={playing ? handleMouseLeave : undefined}
>
<PlayPauseButton
playing={playing}
handlePlayPause={handlePlayPause}
className={buttonClassName}
/>
</div>
</div>
);
};

0 comments on commit c6f773e

Please sign in to comment.