mirror of
https://github.com/Qortal/qapp-core.git
synced 2025-06-19 03:11:20 +00:00
change to popover
This commit is contained in:
parent
793449f486
commit
ad2b56d95a
@ -1,4 +1,16 @@
|
|||||||
import { Box, IconButton, Popper, Slider, Typography } from "@mui/material";
|
import {
|
||||||
|
alpha,
|
||||||
|
Box,
|
||||||
|
ButtonBase,
|
||||||
|
Divider,
|
||||||
|
Fade,
|
||||||
|
IconButton,
|
||||||
|
Popover,
|
||||||
|
Popper,
|
||||||
|
Slider,
|
||||||
|
Typography,
|
||||||
|
useTheme,
|
||||||
|
} from "@mui/material";
|
||||||
export const fontSizeExSmall = "60%";
|
export const fontSizeExSmall = "60%";
|
||||||
export const fontSizeSmall = "80%";
|
export const fontSizeSmall = "80%";
|
||||||
import AspectRatioIcon from "@mui/icons-material/AspectRatio";
|
import AspectRatioIcon from "@mui/icons-material/AspectRatio";
|
||||||
@ -14,11 +26,14 @@ import {
|
|||||||
import { formatTime } from "../../utils/time.js";
|
import { formatTime } from "../../utils/time.js";
|
||||||
import { CustomFontTooltip } from "./CustomFontTooltip.js";
|
import { CustomFontTooltip } from "./CustomFontTooltip.js";
|
||||||
import { useCallback, useEffect, useRef, useState } from "react";
|
import { useCallback, useEffect, useRef, useState } from "react";
|
||||||
|
import SlowMotionVideoIcon from "@mui/icons-material/SlowMotionVideo";
|
||||||
const buttonPaddingBig = "6px";
|
const buttonPaddingBig = "6px";
|
||||||
const buttonPaddingSmall = "4px";
|
const buttonPaddingSmall = "4px";
|
||||||
|
import ArrowForwardIosIcon from "@mui/icons-material/ArrowForwardIos";
|
||||||
|
import ArrowBackIosIcon from "@mui/icons-material/ArrowBackIos";
|
||||||
|
import CheckIcon from "@mui/icons-material/Check";
|
||||||
|
|
||||||
export const PlayButton = ({togglePlay, isPlaying , isScreenSmall}: any) => {
|
export const PlayButton = ({ togglePlay, isPlaying, isScreenSmall }: any) => {
|
||||||
return (
|
return (
|
||||||
<CustomFontTooltip title="Pause/Play (Spacebar)" placement="bottom" arrow>
|
<CustomFontTooltip title="Pause/Play (Spacebar)" placement="bottom" arrow>
|
||||||
<IconButton
|
<IconButton
|
||||||
@ -34,7 +49,7 @@ export const PlayButton = ({togglePlay, isPlaying , isScreenSmall}: any) => {
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export const ReloadButton = ({reloadVideo, isScreenSmall}: any) => {
|
export const ReloadButton = ({ reloadVideo, isScreenSmall }: any) => {
|
||||||
return (
|
return (
|
||||||
<CustomFontTooltip title="Reload Video (R)" placement="bottom" arrow>
|
<CustomFontTooltip title="Reload Video (R)" placement="bottom" arrow>
|
||||||
<IconButton
|
<IconButton
|
||||||
@ -50,12 +65,12 @@ export const ReloadButton = ({reloadVideo, isScreenSmall}: any) => {
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export const ProgressSlider = ({progress, duration, playerRef}: any) => {
|
export const ProgressSlider = ({ progress, duration, playerRef }: any) => {
|
||||||
const sliderRef = useRef(null);
|
const sliderRef = useRef(null);
|
||||||
|
|
||||||
const [hoverX, setHoverX] = useState<number | null>(null);
|
const [hoverX, setHoverX] = useState<number | null>(null);
|
||||||
const [thumbnailUrl, setThumbnailUrl] = useState<string | null>(null);
|
const [thumbnailUrl, setThumbnailUrl] = useState<string | null>(null);
|
||||||
const [showDuration, setShowDuration] = useState(0)
|
const [showDuration, setShowDuration] = useState(0);
|
||||||
const onProgressChange = (_: any, value: number | number[]) => {
|
const onProgressChange = (_: any, value: number | number[]) => {
|
||||||
if (!playerRef.current) return;
|
if (!playerRef.current) return;
|
||||||
|
|
||||||
@ -69,8 +84,6 @@ export const ProgressSlider = ({progress, duration, playerRef}: any) => {
|
|||||||
const debounceTimeoutRef = useRef<any>(null);
|
const debounceTimeoutRef = useRef<any>(null);
|
||||||
const previousBlobUrlRef = useRef<string | null>(null);
|
const previousBlobUrlRef = useRef<string | null>(null);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
const handleMouseMove = (e: React.MouseEvent) => {
|
const handleMouseMove = (e: React.MouseEvent) => {
|
||||||
const slider = sliderRef.current;
|
const slider = sliderRef.current;
|
||||||
if (!slider) return;
|
if (!slider) return;
|
||||||
@ -79,10 +92,10 @@ export const ProgressSlider = ({progress, duration, playerRef}: any) => {
|
|||||||
const x = e.clientX - rect.left;
|
const x = e.clientX - rect.left;
|
||||||
const percent = x / rect.width;
|
const percent = x / rect.width;
|
||||||
const time = Math.min(Math.max(0, percent * duration), duration);
|
const time = Math.min(Math.max(0, percent * duration), duration);
|
||||||
console.log('hello100')
|
console.log("hello100");
|
||||||
setHoverX(e.clientX);
|
setHoverX(e.clientX);
|
||||||
|
|
||||||
setShowDuration(time)
|
setShowDuration(time);
|
||||||
if (debounceTimeoutRef.current) clearTimeout(debounceTimeoutRef.current);
|
if (debounceTimeoutRef.current) clearTimeout(debounceTimeoutRef.current);
|
||||||
|
|
||||||
// debounceTimeoutRef.current = setTimeout(() => {
|
// debounceTimeoutRef.current = setTimeout(() => {
|
||||||
@ -112,29 +125,31 @@ export const ProgressSlider = ({progress, duration, playerRef}: any) => {
|
|||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
const hoverAnchorRef = useRef<HTMLDivElement | null>(null);
|
const hoverAnchorRef = useRef<HTMLDivElement | null>(null);
|
||||||
if(hoverX){
|
if (hoverX) {
|
||||||
console.log('thumbnailUrl', thumbnailUrl, hoverX)
|
console.log("thumbnailUrl", thumbnailUrl, hoverX);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
console.log('duration', duration)
|
console.log("duration", duration);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Box position="relative" sx={{
|
<Box
|
||||||
width: '100%',
|
position="relative"
|
||||||
padding: '0px 10px'
|
sx={{
|
||||||
}}>
|
width: "100%",
|
||||||
|
padding: "0px 10px",
|
||||||
|
}}
|
||||||
|
>
|
||||||
<Box
|
<Box
|
||||||
ref={hoverAnchorRef}
|
ref={hoverAnchorRef}
|
||||||
sx={{
|
sx={{
|
||||||
position: 'absolute',
|
position: "absolute",
|
||||||
left: hoverX ?? -9999,
|
left: hoverX ?? -9999,
|
||||||
top: 0,
|
top: 0,
|
||||||
width: '1px',
|
width: "1px",
|
||||||
height: '1px',
|
height: "1px",
|
||||||
pointerEvents: 'none',
|
pointerEvents: "none",
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
<Slider
|
<Slider
|
||||||
ref={sliderRef}
|
ref={sliderRef}
|
||||||
onMouseMove={handleMouseMove}
|
onMouseMove={handleMouseMove}
|
||||||
@ -145,36 +160,53 @@ console.log('thumbnailUrl', thumbnailUrl, hoverX)
|
|||||||
max={duration || 100}
|
max={duration || 100}
|
||||||
step={0.1}
|
step={0.1}
|
||||||
sx={{
|
sx={{
|
||||||
|
|
||||||
color: "#00abff",
|
color: "#00abff",
|
||||||
padding: "0px",
|
padding: "0px",
|
||||||
borderRadius: '0px',
|
borderRadius: "0px",
|
||||||
height: '0px',
|
height: "0px",
|
||||||
"@media (pointer: coarse)": { padding: "0px" },
|
"@media (pointer: coarse)": { padding: "0px" },
|
||||||
"& .MuiSlider-thumb": {
|
"& .MuiSlider-thumb": {
|
||||||
backgroundColor: "red",
|
backgroundColor: "red",
|
||||||
width: "14px",
|
width: "14px",
|
||||||
height: "14px",
|
height: "14px",
|
||||||
},
|
},
|
||||||
"& .MuiSlider-thumb::after": { width: "14px", height: "14px", backgroundColor: 'red' },
|
"& .MuiSlider-thumb::after": {
|
||||||
"& .MuiSlider-rail": { opacity: 0.5, height: "6px", backgroundColor: '#73859f80' },
|
width: "14px",
|
||||||
"& .MuiSlider-track": { height: "6px", border: "0px" , backgroundColor: 'red'},
|
height: "14px",
|
||||||
|
backgroundColor: "red",
|
||||||
|
},
|
||||||
|
"& .MuiSlider-rail": {
|
||||||
|
opacity: 0.5,
|
||||||
|
height: "6px",
|
||||||
|
backgroundColor: "#73859f80",
|
||||||
|
},
|
||||||
|
"& .MuiSlider-track": {
|
||||||
|
height: "6px",
|
||||||
|
border: "0px",
|
||||||
|
backgroundColor: "red",
|
||||||
|
},
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
{hoverX !== null && (
|
{hoverX !== null && (
|
||||||
<Popper
|
<Popper
|
||||||
open
|
open
|
||||||
anchorEl={hoverAnchorRef.current} placement="top"
|
anchorEl={hoverAnchorRef.current}
|
||||||
|
placement="top"
|
||||||
|
|
||||||
disablePortal
|
disablePortal
|
||||||
modifiers={[{ name: "offset", options: { offset: [-20, 0] } }]}
|
modifiers={[{ name: "offset", options: { offset: [-10, 0] } }]}
|
||||||
|
|
||||||
|
|
||||||
|
>
|
||||||
|
<Box
|
||||||
|
sx={{
|
||||||
|
display: "flex",
|
||||||
|
flexDirection: "column",
|
||||||
|
alignItems: "center",
|
||||||
|
bgcolor: alpha("#181818", 0.75),
|
||||||
|
padding: '5px',
|
||||||
|
borderRadius: '5px'
|
||||||
|
}}
|
||||||
>
|
>
|
||||||
<Box sx={{
|
|
||||||
display: 'flex',
|
|
||||||
flexDirection: 'column',
|
|
||||||
alignItems: 'center'
|
|
||||||
}}>
|
|
||||||
{/* <Box
|
{/* <Box
|
||||||
sx={{
|
sx={{
|
||||||
width: 250,
|
width: 250,
|
||||||
@ -197,11 +229,15 @@ console.log('thumbnailUrl', thumbnailUrl, hoverX)
|
|||||||
style={{ width: "100%", height: "100%", objectFit: "cover" }}
|
style={{ width: "100%", height: "100%", objectFit: "cover" }}
|
||||||
/>
|
/>
|
||||||
</Box> */}
|
</Box> */}
|
||||||
<Typography sx={{
|
<Typography
|
||||||
fontSize: '0.8rom',
|
sx={{
|
||||||
textShadow: '0 0 5px rgba(0, 0, 0, 0.7)'
|
fontSize: "0.8rom",
|
||||||
|
textShadow: "0 0 5px rgba(0, 0, 0, 0.7)",
|
||||||
}}>{formatTime(showDuration)}</Typography>
|
fontFamily: "sans-serif"
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{formatTime(showDuration)}
|
||||||
|
</Typography>
|
||||||
</Box>
|
</Box>
|
||||||
</Popper>
|
</Popper>
|
||||||
)}
|
)}
|
||||||
@ -209,9 +245,7 @@ console.log('thumbnailUrl', thumbnailUrl, hoverX)
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export const VideoTime = ({progress, isScreenSmall, duration}: any) => {
|
export const VideoTime = ({ progress, isScreenSmall, duration }: any) => {
|
||||||
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<CustomFontTooltip
|
<CustomFontTooltip
|
||||||
title="Seek video in 10% increments (0-9)"
|
title="Seek video in 10% increments (0-9)"
|
||||||
@ -221,20 +255,21 @@ export const VideoTime = ({progress, isScreenSmall, duration}: any) => {
|
|||||||
<Typography
|
<Typography
|
||||||
sx={{
|
sx={{
|
||||||
fontSize: isScreenSmall ? fontSizeExSmall : fontSizeSmall,
|
fontSize: isScreenSmall ? fontSizeExSmall : fontSizeSmall,
|
||||||
color: 'white',
|
color: "white",
|
||||||
visibility: typeof duration !== 'number' ? 'hidden' : 'visible',
|
visibility: typeof duration !== "number" ? "hidden" : "visible",
|
||||||
whiteSpace: 'nowrap',
|
whiteSpace: "nowrap",
|
||||||
|
fontFamily: "sans-serif"
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{typeof duration === 'number' ? formatTime(progress) : ''}
|
{typeof duration === "number" ? formatTime(progress) : ""}
|
||||||
{' / '}
|
{" / "}
|
||||||
{typeof duration === 'number' ? formatTime(duration) : ''}
|
{typeof duration === "number" ? formatTime(duration) : ""}
|
||||||
</Typography>
|
</Typography>
|
||||||
</CustomFontTooltip>
|
</CustomFontTooltip>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
const VolumeButton = ({isMuted, toggleMute}: any) => {
|
const VolumeButton = ({ isMuted, toggleMute }: any) => {
|
||||||
return (
|
return (
|
||||||
<CustomFontTooltip
|
<CustomFontTooltip
|
||||||
title="Toggle Mute (M), Raise (UP), Lower (DOWN)"
|
title="Toggle Mute (M), Raise (UP), Lower (DOWN)"
|
||||||
@ -289,33 +324,173 @@ export const VolumeControl = ({ sliderWidth, onVolumeChange, volume }: any) => {
|
|||||||
sx={{ display: "flex", gap: "5px", alignItems: "center", width: "100%" }}
|
sx={{ display: "flex", gap: "5px", alignItems: "center", width: "100%" }}
|
||||||
>
|
>
|
||||||
<VolumeButton />
|
<VolumeButton />
|
||||||
<VolumeSlider width={sliderWidth} onVolumeChange={onVolumeChange} volume={volume} />
|
<VolumeSlider
|
||||||
|
width={sliderWidth}
|
||||||
|
onVolumeChange={onVolumeChange}
|
||||||
|
volume={volume}
|
||||||
|
/>
|
||||||
</Box>
|
</Box>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export const PlaybackRate = ({playbackRate, increaseSpeed, isScreenSmall}: any) => {
|
const speeds = [0.25, 0.5, 0.75, 1, 1.25, 1.5, 2, 2.5, 3];
|
||||||
|
|
||||||
|
export const PlaybackRate = ({
|
||||||
|
playbackRate,
|
||||||
|
increaseSpeed,
|
||||||
|
isScreenSmall,
|
||||||
|
onSelect,
|
||||||
|
}: any) => {
|
||||||
|
const [isOpen, setIsOpen] = useState(false);
|
||||||
|
const btnRef = useRef(null);
|
||||||
|
const theme = useTheme();
|
||||||
|
const onBack = () => {
|
||||||
|
setIsOpen(false);
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
<>
|
||||||
<CustomFontTooltip
|
<CustomFontTooltip
|
||||||
title="Video Speed. Increase (+ or >), Decrease (- or <)"
|
title="Video Speed. Increase (+ or >), Decrease (- or <)"
|
||||||
placement="bottom"
|
placement="bottom"
|
||||||
arrow
|
arrow
|
||||||
>
|
>
|
||||||
<IconButton
|
<IconButton
|
||||||
|
ref={btnRef}
|
||||||
sx={{
|
sx={{
|
||||||
color: "white",
|
color: "white",
|
||||||
fontSize: fontSizeSmall,
|
fontSize: fontSizeSmall,
|
||||||
padding: isScreenSmall ? buttonPaddingSmall : buttonPaddingBig,
|
padding: isScreenSmall ? buttonPaddingSmall : buttonPaddingBig,
|
||||||
}}
|
}}
|
||||||
onClick={() => increaseSpeed()}
|
onClick={() => setIsOpen(true)}
|
||||||
>
|
>
|
||||||
{playbackRate}x
|
<SlowMotionVideoIcon />
|
||||||
</IconButton>
|
</IconButton>
|
||||||
</CustomFontTooltip>
|
</CustomFontTooltip>
|
||||||
|
|
||||||
|
<Popover
|
||||||
|
open={isOpen}
|
||||||
|
anchorEl={btnRef.current}
|
||||||
|
onClose={() => setIsOpen(false)}
|
||||||
|
slots={{
|
||||||
|
transition: Fade,
|
||||||
|
}}
|
||||||
|
slotProps={{
|
||||||
|
transition: {
|
||||||
|
timeout: 200,
|
||||||
|
},
|
||||||
|
paper: {
|
||||||
|
sx: {
|
||||||
|
bgcolor: alpha("#181818", 0.98),
|
||||||
|
color: "white",
|
||||||
|
opacity: 0.9,
|
||||||
|
borderRadius: 2,
|
||||||
|
boxShadow: 5,
|
||||||
|
p: 1,
|
||||||
|
minWidth: 225,
|
||||||
|
height: 300,
|
||||||
|
overflow: "hidden",
|
||||||
|
display: "flex",
|
||||||
|
flexDirection: "column",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}}
|
||||||
|
anchorOrigin={{
|
||||||
|
vertical: "top",
|
||||||
|
horizontal: "center",
|
||||||
|
}}
|
||||||
|
transformOrigin={{
|
||||||
|
vertical: "bottom",
|
||||||
|
horizontal: "center",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Box
|
||||||
|
sx={{
|
||||||
|
padding: "5px 0px 10px 0px",
|
||||||
|
display: "flex",
|
||||||
|
gap: "10px",
|
||||||
|
width: "100%",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<ButtonBase onClick={onBack}>
|
||||||
|
<ArrowBackIosIcon
|
||||||
|
sx={{
|
||||||
|
fontSize: "1.15em",
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</ButtonBase>
|
||||||
|
<ButtonBase>
|
||||||
|
<Typography
|
||||||
|
onClick={onBack}
|
||||||
|
sx={{
|
||||||
|
fontSize: "0.85rem",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
Playback speed
|
||||||
|
</Typography>
|
||||||
|
</ButtonBase>
|
||||||
|
</Box>
|
||||||
|
<Divider />
|
||||||
|
<Box
|
||||||
|
sx={{
|
||||||
|
display: "flex",
|
||||||
|
flexDirection: "column",
|
||||||
|
flexGrow: 1,
|
||||||
|
overflow: "auto",
|
||||||
|
"::-webkit-scrollbar-track": {
|
||||||
|
backgroundColor: "transparent",
|
||||||
|
},
|
||||||
|
|
||||||
|
"::-webkit-scrollbar": {
|
||||||
|
width: "16px",
|
||||||
|
height: "10px",
|
||||||
|
},
|
||||||
|
|
||||||
|
"::-webkit-scrollbar-thumb": {
|
||||||
|
backgroundColor: theme.palette.primary.main,
|
||||||
|
borderRadius: "8px",
|
||||||
|
backgroundClip: "content-box",
|
||||||
|
border: "4px solid transparent",
|
||||||
|
transition: "0.3s background-color",
|
||||||
|
},
|
||||||
|
|
||||||
|
"::-webkit-scrollbar-thumb:hover": {
|
||||||
|
backgroundColor: theme.palette.primary.dark,
|
||||||
|
},
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{speeds?.map((speed) => {
|
||||||
|
const isSelected = speed === playbackRate;
|
||||||
|
return (
|
||||||
|
<ButtonBase
|
||||||
|
disabled={isSelected}
|
||||||
|
key={speed}
|
||||||
|
onClick={() => {
|
||||||
|
onSelect(speed)
|
||||||
|
setIsOpen(false)
|
||||||
|
}}
|
||||||
|
sx={{
|
||||||
|
px: 2,
|
||||||
|
py: 1,
|
||||||
|
"&:hover": {
|
||||||
|
backgroundColor: "rgba(255, 255, 255, 0.1)",
|
||||||
|
},
|
||||||
|
width: "100%",
|
||||||
|
justifyContent: "space-between",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Typography>{speed}</Typography>
|
||||||
|
{isSelected ? <CheckIcon /> : <ArrowForwardIosIcon />}
|
||||||
|
</ButtonBase>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</Box>
|
||||||
|
</Popover>
|
||||||
|
</>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export const ObjectFitButton = ({toggleObjectFit, isScreenSmall}: any) => {
|
export const ObjectFitButton = ({ toggleObjectFit, isScreenSmall }: any) => {
|
||||||
return (
|
return (
|
||||||
<CustomFontTooltip title="Toggle Aspect Ratio (O)" placement="bottom" arrow>
|
<CustomFontTooltip title="Toggle Aspect Ratio (O)" placement="bottom" arrow>
|
||||||
<IconButton
|
<IconButton
|
||||||
@ -331,8 +506,12 @@ export const ObjectFitButton = ({toggleObjectFit, isScreenSmall}: any) => {
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export const PictureInPictureButton = ({isFullscreen, toggleRef, togglePictureInPicture, isScreenSmall}: any) => {
|
export const PictureInPictureButton = ({
|
||||||
|
isFullscreen,
|
||||||
|
toggleRef,
|
||||||
|
togglePictureInPicture,
|
||||||
|
isScreenSmall,
|
||||||
|
}: any) => {
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
{!isFullscreen && (
|
{!isFullscreen && (
|
||||||
@ -357,8 +536,7 @@ export const PictureInPictureButton = ({isFullscreen, toggleRef, togglePictureIn
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export const FullscreenButton = ({toggleFullscreen, isScreenSmall}: any) => {
|
export const FullscreenButton = ({ toggleFullscreen, isScreenSmall }: any) => {
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<CustomFontTooltip title="Toggle Fullscreen (F)" placement="bottom" arrow>
|
<CustomFontTooltip title="Toggle Fullscreen (F)" placement="bottom" arrow>
|
||||||
<IconButton
|
<IconButton
|
||||||
|
@ -14,6 +14,7 @@ import {
|
|||||||
} from "./VideoControls";
|
} from "./VideoControls";
|
||||||
import { Ref } from "react";
|
import { Ref } from "react";
|
||||||
import SubtitlesIcon from '@mui/icons-material/Subtitles';
|
import SubtitlesIcon from '@mui/icons-material/Subtitles';
|
||||||
|
import { CustomFontTooltip } from "./CustomFontTooltip";
|
||||||
interface VideoControlsBarProps {
|
interface VideoControlsBarProps {
|
||||||
canPlay: boolean
|
canPlay: boolean
|
||||||
isScreenSmall: boolean
|
isScreenSmall: boolean
|
||||||
@ -36,9 +37,10 @@ interface VideoControlsBarProps {
|
|||||||
playbackRate: number
|
playbackRate: number
|
||||||
openSubtitleManager: ()=> void
|
openSubtitleManager: ()=> void
|
||||||
subtitleBtnRef: any
|
subtitleBtnRef: any
|
||||||
|
onSelectPlaybackRate: (rate: number)=> void;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const VideoControlsBar = ({subtitleBtnRef, showControls, playbackRate, increaseSpeed,decreaseSpeed, isFullScreen, showControlsFullScreen, reloadVideo, onVolumeChange, volume, isPlaying, canPlay, isScreenSmall, controlsHeight, playerRef, duration, progress, togglePlay, toggleFullscreen, extractFrames, openSubtitleManager}: VideoControlsBarProps) => {
|
export const VideoControlsBar = ({subtitleBtnRef, showControls, playbackRate, increaseSpeed,decreaseSpeed, isFullScreen, showControlsFullScreen, reloadVideo, onVolumeChange, volume, isPlaying, canPlay, isScreenSmall, controlsHeight, playerRef, duration, progress, togglePlay, toggleFullscreen, extractFrames, openSubtitleManager, onSelectPlaybackRate}: VideoControlsBarProps) => {
|
||||||
|
|
||||||
const showMobileControls = isScreenSmall && canPlay;
|
const showMobileControls = isScreenSmall && canPlay;
|
||||||
|
|
||||||
@ -96,12 +98,18 @@ export const VideoControlsBar = ({subtitleBtnRef, showControls, playbackRate, in
|
|||||||
</Box>
|
</Box>
|
||||||
|
|
||||||
<Box sx={{...controlGroupSX, marginLeft: 'auto'}}>
|
<Box sx={{...controlGroupSX, marginLeft: 'auto'}}>
|
||||||
<PlaybackRate playbackRate={playbackRate} increaseSpeed={increaseSpeed} decreaseSpeed={decreaseSpeed} />
|
<PlaybackRate onSelect={onSelectPlaybackRate} playbackRate={playbackRate} increaseSpeed={increaseSpeed} decreaseSpeed={decreaseSpeed} />
|
||||||
<ObjectFitButton />
|
{/* <ObjectFitButton /> */}
|
||||||
|
<CustomFontTooltip
|
||||||
|
title="Subtitles"
|
||||||
|
placement="bottom"
|
||||||
|
arrow
|
||||||
|
>
|
||||||
<IconButton ref={subtitleBtnRef} onClick={openSubtitleManager}>
|
<IconButton ref={subtitleBtnRef} onClick={openSubtitleManager}>
|
||||||
<SubtitlesIcon />
|
<SubtitlesIcon />
|
||||||
</IconButton>
|
</IconButton>
|
||||||
<PictureInPictureButton />
|
</CustomFontTooltip>
|
||||||
|
{/* <PictureInPictureButton /> */}
|
||||||
<FullscreenButton toggleFullscreen={toggleFullscreen} />
|
<FullscreenButton toggleFullscreen={toggleFullscreen} />
|
||||||
</Box>
|
</Box>
|
||||||
</Box>
|
</Box>
|
||||||
|
@ -206,6 +206,7 @@ export const VideoPlayer = ({
|
|||||||
status,
|
status,
|
||||||
percentLoaded,
|
percentLoaded,
|
||||||
showControlsFullScreen,
|
showControlsFullScreen,
|
||||||
|
onSelectPlaybackRate
|
||||||
} = useVideoPlayerController({
|
} = useVideoPlayerController({
|
||||||
autoPlay,
|
autoPlay,
|
||||||
playerRef,
|
playerRef,
|
||||||
@ -214,6 +215,27 @@ export const VideoPlayer = ({
|
|||||||
isPlayerInitialized,
|
isPlayerInitialized,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
console.log('isFullscreen', isFullscreen)
|
||||||
|
|
||||||
|
const enterFullscreen = useCallback(() => {
|
||||||
|
const ref = containerRef?.current as any;
|
||||||
|
if (!ref) return;
|
||||||
|
|
||||||
|
if (ref.requestFullscreen && !isFullscreen) {
|
||||||
|
ref.requestFullscreen();
|
||||||
|
}
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
const exitFullscreen = useCallback(() => {
|
||||||
|
document?.exitFullscreen();
|
||||||
|
}, [isFullscreen]);
|
||||||
|
|
||||||
|
const toggleFullscreen = useCallback(() => {
|
||||||
|
console.log('togglefull', isFullscreen)
|
||||||
|
isFullscreen ? exitFullscreen() : enterFullscreen();
|
||||||
|
}, [isFullscreen]);
|
||||||
|
|
||||||
|
|
||||||
const hotkeyHandlers = useMemo(
|
const hotkeyHandlers = useMemo(
|
||||||
() => ({
|
() => ({
|
||||||
reloadVideo,
|
reloadVideo,
|
||||||
@ -227,6 +249,7 @@ export const VideoPlayer = ({
|
|||||||
toggleMute,
|
toggleMute,
|
||||||
setProgressAbsolute,
|
setProgressAbsolute,
|
||||||
setAlwaysShowControls,
|
setAlwaysShowControls,
|
||||||
|
toggleFullscreen
|
||||||
}),
|
}),
|
||||||
[
|
[
|
||||||
reloadVideo,
|
reloadVideo,
|
||||||
@ -240,6 +263,7 @@ export const VideoPlayer = ({
|
|||||||
toggleMute,
|
toggleMute,
|
||||||
setProgressAbsolute,
|
setProgressAbsolute,
|
||||||
setAlwaysShowControls,
|
setAlwaysShowControls,
|
||||||
|
toggleFullscreen
|
||||||
]
|
]
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -346,22 +370,6 @@ export const VideoPlayer = ({
|
|||||||
};
|
};
|
||||||
}, [isPlayerInitialized]);
|
}, [isPlayerInitialized]);
|
||||||
|
|
||||||
const enterFullscreen = () => {
|
|
||||||
const ref = containerRef?.current as any;
|
|
||||||
if (!ref) return;
|
|
||||||
|
|
||||||
if (ref.requestFullscreen && !isFullscreen) {
|
|
||||||
ref.requestFullscreen();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const exitFullscreen = () => {
|
|
||||||
if (isFullscreen) document.exitFullscreen();
|
|
||||||
};
|
|
||||||
|
|
||||||
const toggleFullscreen = () => {
|
|
||||||
isFullscreen ? exitFullscreen() : enterFullscreen();
|
|
||||||
};
|
|
||||||
|
|
||||||
const canvasRef = useRef(null);
|
const canvasRef = useRef(null);
|
||||||
const videoRefForCanvas = useRef<any>(null);
|
const videoRefForCanvas = useRef<any>(null);
|
||||||
@ -744,6 +752,7 @@ export const VideoPlayer = ({
|
|||||||
duration={duration}
|
duration={duration}
|
||||||
progress={localProgress}
|
progress={localProgress}
|
||||||
openSubtitleManager={openSubtitleManager}
|
openSubtitleManager={openSubtitleManager}
|
||||||
|
onSelectPlaybackRate={onSelectPlaybackRate}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
|
@ -280,6 +280,7 @@ const togglePlay = useCallback(async () => {
|
|||||||
}
|
}
|
||||||
}, [togglePlay, isReady]);
|
}, [togglePlay, isReady]);
|
||||||
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
reloadVideo,
|
reloadVideo,
|
||||||
togglePlay,
|
togglePlay,
|
||||||
@ -299,6 +300,6 @@ const togglePlay = useCallback(async () => {
|
|||||||
isReady,
|
isReady,
|
||||||
resourceUrl,
|
resourceUrl,
|
||||||
startPlay,
|
startPlay,
|
||||||
status, percentLoaded, showControlsFullScreen
|
status, percentLoaded, showControlsFullScreen, onSelectPlaybackRate: updatePlaybackRate
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
@ -12,6 +12,7 @@ interface UseVideoControls {
|
|||||||
changeVolume: (delta: number) => void;
|
changeVolume: (delta: number) => void;
|
||||||
toggleMute: () => void;
|
toggleMute: () => void;
|
||||||
setProgressAbsolute: (percent: number) => void;
|
setProgressAbsolute: (percent: number) => void;
|
||||||
|
toggleFullscreen: ()=> void;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const useVideoPlayerHotKeys = (props: UseVideoControls) => {
|
export const useVideoPlayerHotKeys = (props: UseVideoControls) => {
|
||||||
@ -26,6 +27,7 @@ export const useVideoPlayerHotKeys = (props: UseVideoControls) => {
|
|||||||
changeVolume,
|
changeVolume,
|
||||||
toggleMute,
|
toggleMute,
|
||||||
setProgressAbsolute,
|
setProgressAbsolute,
|
||||||
|
toggleFullscreen
|
||||||
} = props;
|
} = props;
|
||||||
|
|
||||||
const handleKeyDown = useCallback((e: KeyboardEvent) => {
|
const handleKeyDown = useCallback((e: KeyboardEvent) => {
|
||||||
@ -46,6 +48,9 @@ export const useVideoPlayerHotKeys = (props: UseVideoControls) => {
|
|||||||
case "o":
|
case "o":
|
||||||
toggleObjectFit();
|
toggleObjectFit();
|
||||||
break;
|
break;
|
||||||
|
case "f":
|
||||||
|
toggleFullscreen();
|
||||||
|
break;
|
||||||
case "c":
|
case "c":
|
||||||
toggleAlwaysShowControls();
|
toggleAlwaysShowControls();
|
||||||
break;
|
break;
|
||||||
@ -127,6 +132,7 @@ export const useVideoPlayerHotKeys = (props: UseVideoControls) => {
|
|||||||
changeVolume,
|
changeVolume,
|
||||||
toggleMute,
|
toggleMute,
|
||||||
setProgressAbsolute,
|
setProgressAbsolute,
|
||||||
|
toggleFullscreen
|
||||||
]);
|
]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user