3
0
mirror of https://github.com/Qortal/q-tube.git synced 2025-02-11 09:45:51 +00:00

Videoplayer updates:

VideoPlayer tooltips moved below buttons to avoid interfering with clicking on progress slider. Slider raised 2px and is thicker for the same reason.

Clicking on progress slider doesn't force the video to start playing.

Changed colors on Volume Slider so it is easier to see on Desktop and especially Mobile

Volume slider removed on mobile

Buggy feature that did picture in picture when leaving video while playing has been removed

If on Mobile, video title has bigger topMargin to prevent video clipping into it on some Mobile devices.
This commit is contained in:
Qortal Dev 2025-01-03 16:03:43 -07:00
parent 823365998a
commit c6605060db
7 changed files with 90 additions and 77 deletions

View File

@ -10,8 +10,7 @@ import {
ProgressSlider,
ReloadButton,
VideoTime,
VolumeButton,
VolumeSlider,
VolumeControl,
} from "./VideoControls.tsx";
export const MobileControlsBar = () => {
@ -54,10 +53,6 @@ export const MobileControlsBar = () => {
},
}}
>
<MenuItem>
<VolumeButton />
<VolumeSlider width={"100%"} />
</MenuItem>
<MenuItem>
<ObjectFitButton />
</MenuItem>

View File

@ -1,4 +1,4 @@
import { IconButton, Slider, Typography } from "@mui/material";
import { Box, IconButton, Slider, Typography } from "@mui/material";
import { fontSizeExSmall, fontSizeSmall } from "../../../../constants/Misc.ts";
import { CustomFontTooltip } from "../../../../utils/CustomFontTooltip.tsx";
import { formatTime } from "../../../../utils/numberFunctions.ts";
@ -18,7 +18,7 @@ import { useSignalEffect } from "@preact/signals-react";
export const PlayButton = () => {
const { togglePlay, playing } = useVideoContext();
return (
<CustomFontTooltip title="Pause/Play (Spacebar)" placement="top" arrow>
<CustomFontTooltip title="Pause/Play (Spacebar)" placement="bottom" arrow>
<IconButton
sx={{
color: "white",
@ -34,7 +34,7 @@ export const PlayButton = () => {
export const ReloadButton = () => {
const { reloadVideo } = useVideoContext();
return (
<CustomFontTooltip title="Reload Video (R)" placement="top" arrow>
<CustomFontTooltip title="Reload Video (R)" placement="bottom" arrow>
<IconButton
sx={{
color: "white",
@ -57,7 +57,7 @@ export const ProgressSlider = () => {
max={videoRef.current?.duration || 100}
sx={{
position: "absolute",
bottom: "40px",
bottom: "42px",
color: "#00abff",
padding: "0px",
// prevents the slider from jumping up 20px in certain mobile conditions
@ -69,7 +69,8 @@ export const ProgressSlider = () => {
height: "16px",
},
"& .MuiSlider-thumb::after": { width: "20px", height: "20px" },
"& .MuiSlider-rail": { opacity: 0.5 },
"& .MuiSlider-rail": { opacity: 0.5, height: "6px" },
"& .MuiSlider-track": { height: "6px", border: "0px" },
}}
/>
);
@ -81,7 +82,7 @@ export const VideoTime = () => {
return (
<CustomFontTooltip
title="Seek video in 10% increments (0-9)"
placement="top"
placement="bottom"
arrow
>
<Typography
@ -102,12 +103,12 @@ export const VideoTime = () => {
);
};
export const VolumeButton = () => {
const VolumeButton = () => {
const { isMuted, toggleMute } = useVideoContext();
return (
<CustomFontTooltip
title="Toggle Mute (M), Raise (UP), Lower (DOWN)"
placement="top"
placement="bottom"
arrow
>
<IconButton
@ -122,8 +123,13 @@ export const VolumeButton = () => {
);
};
export const VolumeSlider = ({ width }: { width: string }) => {
const VolumeSlider = ({ width }: { width: string }) => {
const { volume, onVolumeChange } = useVideoContext();
let color = "";
if (volume.value <= 0.5) color = "green";
else if (volume.value <= 0.75) color = "yellow";
else color = "red";
return (
<Slider
value={volume.value}
@ -134,18 +140,36 @@ export const VolumeSlider = ({ width }: { width: string }) => {
sx={{
width,
marginRight: "10px",
"& .MuiSlider-thumb::after": { width: "25px", height: "25px" },
color,
"& .MuiSlider-thumb": {
backgroundColor: "#fff",
width: "16px",
height: "16px",
},
"& .MuiSlider-thumb::after": { width: "16px", height: "16px" },
"& .MuiSlider-rail": { opacity: 0.5, height: "6px" },
"& .MuiSlider-track": { height: "6px", border: "0px" },
}}
/>
);
};
export const VolumeControl = ({ sliderWidth }: { sliderWidth: string }) => {
return (
<Box
sx={{ display: "flex", gap: "5px", alignItems: "center", width: "100%" }}
>
<VolumeButton />
<VolumeSlider width={sliderWidth} />
</Box>
);
};
export const PlaybackRate = () => {
const { playbackRate, increaseSpeed, isScreenSmall } = useVideoContext();
return (
<CustomFontTooltip
title="Video Speed. Increase (+ or >), Decrease (- or <)"
placement="top"
placement="bottom"
arrow
>
<IconButton
@ -170,7 +194,11 @@ export const PictureInPictureButton = () => {
return (
<>
{!isFullscreen.value && (
<CustomFontTooltip title="Picture in Picture (P)" placement="top" arrow>
<CustomFontTooltip
title="Picture in Picture (P)"
placement="bottom"
arrow
>
<IconButton
sx={{
color: "white",
@ -189,7 +217,7 @@ export const PictureInPictureButton = () => {
export const ObjectFitButton = () => {
const { toggleObjectFit } = useVideoContext();
return (
<CustomFontTooltip title="Toggle Aspect Ratio (O)" placement="top" arrow>
<CustomFontTooltip title="Toggle Aspect Ratio (O)" placement="bottom" arrow>
<IconButton
sx={{
color: "white",
@ -206,7 +234,7 @@ export const ObjectFitButton = () => {
export const FullscreenButton = () => {
const { toggleFullscreen } = useVideoContext();
return (
<CustomFontTooltip title="Toggle Fullscreen (F)" placement="top" arrow>
<CustomFontTooltip title="Toggle Fullscreen (F)" placement="bottom" arrow>
<IconButton
sx={{
color: "white",

View File

@ -11,17 +11,15 @@ import {
ProgressSlider,
ReloadButton,
VideoTime,
VolumeButton,
VolumeSlider,
VolumeControl,
} from "./VideoControls.tsx";
import { useSignalEffect } from "@preact/signals-react";
export const VideoControlsBar = () => {
const { from, canPlay, showControlsFullScreen, isScreenSmall, progress } =
useVideoContext();
const showMobileControls = isScreenSmall && canPlay.value;
const controlsHeight = "40px";
const controlsHeight = "42px";
const controlGroupSX = {
display: "flex",
gap: "5px",
@ -46,8 +44,7 @@ export const VideoControlsBar = () => {
<ProgressSlider />
<VolumeButton />
<VolumeSlider width={"100px"} />
<VolumeControl sliderWidth={"100px"} />
<VideoTime />
</Box>

View File

@ -147,11 +147,6 @@ export const useVideoPlayerState = (props: VideoPlayerProps, ref: any) => {
if (!videoRef.current) return;
videoRef.current.currentTime = value as number;
progress.value = value as number;
if (!playing.value) {
await videoRef.current.play();
playing.value = true;
}
};
const handleEnded = () => {
@ -198,9 +193,7 @@ export const useVideoPlayerState = (props: VideoPlayerProps, ref: any) => {
const target = event?.target;
if (target) {
target.pause();
if (playing.value) {
playing.value = false;
}
if (playing.value) playing.value = false;
}
};

View File

@ -445,21 +445,21 @@ export const VideoPlayerGlobal: React.FC<VideoPlayerProps> = ({
}
};
useEffect(() => {
if (element) {
const oldElement = document.getElementById("videoPlayer");
if (oldElement && oldElement?.parentNode) {
oldElement?.parentNode.replaceChild(element, oldElement);
videoRef.current = element;
setPlaying(true);
setCanPlay(true);
setStartPlay(true);
//videoRef?.current?.addEventListener("click", () => {});
videoRef?.current?.addEventListener("timeupdate", updateProgress);
videoRef?.current?.addEventListener("ended", handleEnded);
}
}
}, [element]);
// useEffect(() => {
// if (element) {
// const oldElement = document.getElementById("videoPlayer");
// if (oldElement && oldElement?.parentNode) {
// oldElement?.parentNode.replaceChild(element, oldElement);
// videoRef.current = element;
// setPlaying(true);
// setCanPlay(true);
// setStartPlay(true);
// //videoRef?.current?.addEventListener("click", () => {});
// videoRef?.current?.addEventListener("timeupdate", updateProgress);
// videoRef?.current?.addEventListener("ended", handleEnded);
// }
// }
// }, [element]);
return (
<VideoContainer
@ -483,9 +483,9 @@ export const VideoPlayerGlobal: React.FC<VideoPlayerProps> = ({
}}
></CloseIcon>
</div>
<div onClick={togglePlay}>
<VideoElement id="videoPlayer" />
</div>
{/*<div onClick={togglePlay}>*/}
{/* <VideoElement id="videoPlayer" />*/}
{/*</div>*/}
<ControlsContainer
style={{
bottom: from === "create" ? "15px" : 0,

View File

@ -121,7 +121,7 @@ export const VideoContent = () => {
color="textPrimary"
sx={{
textAlign: "start",
marginTop: "10px",
marginTop: isScreenSmall ? "20px" : "10px",
}}
>
{videoData?.title}

View File

@ -228,30 +228,30 @@ const GlobalWrapper: React.FC<Props> = ({ children, setTheme }) => {
/>
<EditVideo />
<EditPlaylist />
<Rnd
onDragStart={onDragStart}
onDragStop={onDragStop}
style={{
display: videoPlaying ? "block" : "none",
position: "fixed",
height: "auto",
width: 350,
zIndex: 1000,
maxWidth: 800,
}}
default={{
x: 0,
y: 60,
width: 350,
height: "auto",
}}
// eslint-disable-next-line @typescript-eslint/no-empty-function
onDrag={() => {}}
>
{videoPlaying && (
<VideoPlayerGlobal checkIfDrag={checkIfDrag} element={videoPlaying} />
)}
</Rnd>
{/*<Rnd*/}
{/* onDragStart={onDragStart}*/}
{/* onDragStop={onDragStop}*/}
{/* style={{*/}
{/* display: videoPlaying ? "block" : "none",*/}
{/* position: "fixed",*/}
{/* height: "auto",*/}
{/* width: 350,*/}
{/* zIndex: 1000,*/}
{/* maxWidth: 800,*/}
{/* }}*/}
{/* default={{*/}
{/* x: 0,*/}
{/* y: 60,*/}
{/* width: 350,*/}
{/* height: "auto",*/}
{/* }}*/}
{/* // eslint-disable-next-line @typescript-eslint/no-empty-function*/}
{/* onDrag={() => {}}*/}
{/*>*/}
{/* {videoPlaying && (*/}
{/* <VideoPlayerGlobal checkIfDrag={checkIfDrag} element={videoPlaying} />*/}
{/* )}*/}
{/*</Rnd>*/}
{children}
</>