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

VideoPlayer Bugfixes

Videoplayer doesn't set fill ObjectFit when fullscreen.

Added ObjectFit button

Volume slider doesn't clip into video time label

Volume and Progress sliders have a smaller click range so they don't override other video buttons.

Usernames in the videolist component now show ellipses when they overflow

Hyperlink color throughout the app changed so they are easier to see
This commit is contained in:
Qortal Dev 2025-01-02 16:11:45 -07:00
parent 1cfdb7a7bf
commit d4f5c7a8ee
9 changed files with 98 additions and 69 deletions

View File

@ -3,6 +3,7 @@ import { Box, IconButton, Menu, MenuItem } from "@mui/material";
import { useVideoContext } from "./VideoContext.ts"; import { useVideoContext } from "./VideoContext.ts";
import { import {
FullscreenButton, FullscreenButton,
ObjectFitButton,
PictureInPictureButton, PictureInPictureButton,
PlaybackRate, PlaybackRate,
PlayButton, PlayButton,
@ -55,7 +56,10 @@ export const MobileControlsBar = () => {
> >
<MenuItem> <MenuItem>
<VolumeButton /> <VolumeButton />
<VolumeSlider /> <VolumeSlider width={"100%"} />
</MenuItem>
<MenuItem>
<ObjectFitButton />
</MenuItem> </MenuItem>
<MenuItem> <MenuItem>
<PictureInPictureButton /> <PictureInPictureButton />

View File

@ -209,11 +209,11 @@ export const useVideoControlsState = (
} }
}; };
const setStretchVideoSetting = (value: "contain" | "fill") => { const setObjectFit = (value: "contain" | "fill") => {
videoObjectFit.value = value; videoObjectFit.value = value;
}; };
const toggleStretchVideoSetting = () => { const toggleObjectFit = () => {
videoObjectFit.value = videoObjectFit.value =
videoObjectFit.value === "contain" ? "fill" : "contain"; videoObjectFit.value === "contain" ? "fill" : "contain";
}; };
@ -226,7 +226,7 @@ export const useVideoControlsState = (
switch (e.key) { switch (e.key) {
case "o": case "o":
toggleStretchVideoSetting(); toggleObjectFit();
break; break;
case Key.Add: case Key.Add:
@ -364,6 +364,7 @@ export const useVideoControlsState = (
showControlsFullScreen, showControlsFullScreen,
setPlaying, setPlaying,
isFullscreen, isFullscreen,
setStretchVideoSetting, toggleObjectFit,
setObjectFit,
}; };
}; };

View File

@ -3,6 +3,7 @@ import { fontSizeExSmall, fontSizeSmall } from "../../../../constants/Misc.ts";
import { CustomFontTooltip } from "../../../../utils/CustomFontTooltip.tsx"; import { CustomFontTooltip } from "../../../../utils/CustomFontTooltip.tsx";
import { formatTime } from "../../../../utils/numberFunctions.ts"; import { formatTime } from "../../../../utils/numberFunctions.ts";
import { useVideoContext } from "./VideoContext.ts"; import { useVideoContext } from "./VideoContext.ts";
import AspectRatioIcon from "@mui/icons-material/AspectRatio";
import { import {
Fullscreen, Fullscreen,
Pause, Pause,
@ -48,7 +49,6 @@ export const ReloadButton = () => {
export const ProgressSlider = () => { export const ProgressSlider = () => {
const { progress, onProgressChange, videoRef } = useVideoContext(); const { progress, onProgressChange, videoRef } = useVideoContext();
const sliderThumbSize = "16px";
return ( return (
<Slider <Slider
value={progress.value} value={progress.value}
@ -65,9 +65,10 @@ export const ProgressSlider = () => {
"& .MuiSlider-thumb": { "& .MuiSlider-thumb": {
backgroundColor: "#fff", backgroundColor: "#fff",
width: sliderThumbSize, width: "16px",
height: sliderThumbSize, height: "16px",
}, },
"& .MuiSlider-thumb::after": { width: "20px", height: "20px" },
"& .MuiSlider-rail": { opacity: 0.5 }, "& .MuiSlider-rail": { opacity: 0.5 },
}} }}
/> />
@ -112,6 +113,7 @@ export const VolumeButton = () => {
<IconButton <IconButton
sx={{ sx={{
color: "white", color: "white",
marginRight: "10px",
}} }}
onClick={toggleMute} onClick={toggleMute}
> >
@ -121,7 +123,7 @@ export const VolumeButton = () => {
); );
}; };
export const VolumeSlider = () => { export const VolumeSlider = ({ width }: { width: string }) => {
const { volume, onVolumeChange } = useVideoContext(); const { volume, onVolumeChange } = useVideoContext();
return ( return (
<Slider <Slider
@ -131,7 +133,9 @@ export const VolumeSlider = () => {
max={1} max={1}
step={0.01} step={0.01}
sx={{ sx={{
width: "100px", width,
marginRight: "10px",
"& .MuiSlider-thumb::after": { width: "25px", height: "25px" },
}} }}
/> />
); );
@ -183,6 +187,23 @@ export const PictureInPictureButton = () => {
); );
}; };
export const ObjectFitButton = () => {
const { toggleObjectFit } = useVideoContext();
return (
<CustomFontTooltip title="Toggle Aspect Ratio (O)" placement="top" arrow>
<IconButton
sx={{
color: "white",
paddingRight: "0px",
}}
onClick={() => toggleObjectFit()}
>
<AspectRatioIcon />
</IconButton>
</CustomFontTooltip>
);
};
export const FullscreenButton = () => { export const FullscreenButton = () => {
const { toggleFullscreen } = useVideoContext(); const { toggleFullscreen } = useVideoContext();
return ( return (

View File

@ -4,6 +4,7 @@ import { MobileControlsBar } from "./MobileControlsBar.tsx";
import { useVideoContext } from "./VideoContext.ts"; import { useVideoContext } from "./VideoContext.ts";
import { import {
FullscreenButton, FullscreenButton,
ObjectFitButton,
PictureInPictureButton, PictureInPictureButton,
PlaybackRate, PlaybackRate,
PlayButton, PlayButton,
@ -46,12 +47,13 @@ export const VideoControlsBar = () => {
<ProgressSlider /> <ProgressSlider />
<VolumeButton /> <VolumeButton />
<VolumeSlider /> <VolumeSlider width={"100px"} />
<VideoTime /> <VideoTime />
</Box> </Box>
<Box sx={controlGroupSX}> <Box sx={controlGroupSX}>
<PlaybackRate /> <PlaybackRate />
<ObjectFitButton />
<PictureInPictureButton /> <PictureInPictureButton />
<FullscreenButton /> <FullscreenButton />
</Box> </Box>

View File

@ -103,7 +103,7 @@ export const VideoPlayer = forwardRef<videoRefType, VideoPlayerProps>(
preload="metadata" preload="metadata"
style={{ style={{
...videoStyles?.video, ...videoStyles?.video,
objectFit: isFullscreen ? "fill" : videoObjectFit.value, objectFit: videoObjectFit.value,
height: height:
isFullscreen.value && showControlsFullScreen.value isFullscreen.value && showControlsFullScreen.value
? "calc(100vh - 40px)" ? "calc(100vh - 40px)"

View File

@ -67,7 +67,7 @@
height: 100%; height: 100%;
} }
a:link { color: #8AB4F8}
.test-grid { .test-grid {
display: grid; display: grid;

View File

@ -174,18 +174,17 @@ export const VideoContent = () => {
cursor: !descriptionHeight cursor: !descriptionHeight
? "default" ? "default"
: isExpandedDescription : isExpandedDescription
? "default" ? "default"
: "pointer", : "pointer",
position: "relative", position: "relative",
marginBottom: "30px", marginBottom: "30px",
}} }}
className={ className={
!descriptionHeight !descriptionHeight
? "" ? ""
: isExpandedDescription : isExpandedDescription
? "" ? ""
: "hover-click" : "hover-click"
} }
> >
{descriptionHeight && !isExpandedDescription && ( {descriptionHeight && !isExpandedDescription && (
@ -210,8 +209,8 @@ export const VideoContent = () => {
height: !descriptionHeight height: !descriptionHeight
? "auto" ? "auto"
: isExpandedDescription : isExpandedDescription
? "auto" ? "auto"
: "200px", : "200px",
overflow: "hidden", overflow: "hidden",
}} }}
> >

View File

@ -110,6 +110,7 @@ export const NameContainer = styled(Box)(({ theme }) => ({
alignItems: "center", alignItems: "center",
gap: "10px", gap: "10px",
marginBottom: "2px", marginBottom: "2px",
width: "100%",
})); }));
export const VideoManagerRow = styled(Box)(({ theme }) => ({ export const VideoManagerRow = styled(Box)(({ theme }) => ({

View File

@ -11,38 +11,38 @@ const commonThemeOptions = {
"Oxygen", "Oxygen",
"Catamaran", "Catamaran",
"Cairo", "Cairo",
"Arial" "Arial",
].join(","), ].join(","),
h1: { h1: {
fontSize: "2rem", fontSize: "2rem",
fontWeight: 600 fontWeight: 600,
}, },
h2: { h2: {
fontSize: "1.75rem", fontSize: "1.75rem",
fontWeight: 500 fontWeight: 500,
}, },
h3: { h3: {
fontSize: "1.5rem", fontSize: "1.5rem",
fontWeight: 500 fontWeight: 500,
}, },
h4: { h4: {
fontSize: "1.25rem", fontSize: "1.25rem",
fontWeight: 500 fontWeight: 500,
}, },
h5: { h5: {
fontSize: "1rem", fontSize: "1rem",
fontWeight: 500 fontWeight: 500,
}, },
h6: { h6: {
fontSize: "0.875rem", fontSize: "0.875rem",
fontWeight: 500 fontWeight: 500,
}, },
body1: { body1: {
fontSize: "23px", fontSize: "23px",
fontFamily: "Raleway", fontFamily: "Raleway",
fontWeight: 400, fontWeight: 400,
lineHeight: 1.5, lineHeight: 1.5,
letterSpacing: "0.5px" letterSpacing: "0.5px",
}, },
body2: { body2: {
@ -50,12 +50,12 @@ const commonThemeOptions = {
fontFamily: "Raleway, Arial", fontFamily: "Raleway, Arial",
fontWeight: 400, fontWeight: 400,
lineHeight: 1.4, lineHeight: 1.4,
letterSpacing: "0.2px" letterSpacing: "0.2px",
} },
}, },
spacing: 8, spacing: 8,
shape: { shape: {
borderRadius: 4 borderRadius: 4,
}, },
breakpoints: { breakpoints: {
values: { values: {
@ -63,8 +63,8 @@ const commonThemeOptions = {
sm: 600, sm: 600,
md: 900, md: 900,
lg: 1200, lg: 1200,
xl: 1536 xl: 1536,
} },
}, },
components: { components: {
MuiButton: { MuiButton: {
@ -73,16 +73,16 @@ const commonThemeOptions = {
backgroundColor: "inherit", backgroundColor: "inherit",
transition: "filter 0.3s ease-in-out", transition: "filter 0.3s ease-in-out",
"&:hover": { "&:hover": {
filter: "brightness(1.1)" filter: "brightness(1.1)",
} },
} },
}, },
defaultProps: { defaultProps: {
disableElevation: true, disableElevation: true,
disableRipple: true disableRipple: true,
} },
} },
} },
}; };
const lightTheme = createTheme({ const lightTheme = createTheme({
@ -92,21 +92,22 @@ const lightTheme = createTheme({
primary: { primary: {
main: "#ffffff", main: "#ffffff",
dark: "#F5F5F5", dark: "#F5F5F5",
light: "#FCFCFC" light: "#FCFCFC",
}, },
secondary: { secondary: {
main: "#417Ed4", main: "#417Ed4",
dark: "#3e74c1" dark: "#3e74c1",
}, },
background: { background: {
default: "#fcfcfc", default: "#fcfcfc",
paper: "#F5F5F5" paper: "#F5F5F5",
}, },
text: { text: {
primary: "#000000", primary: "#000000",
secondary: "#525252" secondary: "#525252",
} },
}, },
components: { components: {
MuiCard: { MuiCard: {
styleOverrides: { styleOverrides: {
@ -118,19 +119,19 @@ const lightTheme = createTheme({
"&:hover": { "&:hover": {
cursor: "pointer", cursor: "pointer",
boxShadow: boxShadow:
"rgba(0, 0, 0, 0.1) 0px 4px 6px -1px, rgba(0, 0, 0, 0.06) 0px 2px 4px -1px;" "rgba(0, 0, 0, 0.1) 0px 4px 6px -1px, rgba(0, 0, 0, 0.06) 0px 2px 4px -1px;",
} },
} },
} },
}, },
MuiIcon: { MuiIcon: {
defaultProps: { defaultProps: {
style: { style: {
color: "#000000" color: "#000000",
} },
} },
} },
} },
}); });
const darkTheme = createTheme({ const darkTheme = createTheme({
@ -140,22 +141,22 @@ const darkTheme = createTheme({
primary: { primary: {
main: "#2e3d60", main: "#2e3d60",
dark: "#1a2744", dark: "#1a2744",
light: "#353535" light: "#353535",
}, },
secondary: { secondary: {
main: "#417Ed4", main: "#417Ed4",
dark: "#3e74c1" dark: "#3e74c1",
}, },
background: { background: {
default: "#111111", default: "#111111",
paper: "#1A1C1E" paper: "#1A1C1E",
}, },
text: { text: {
primary: "#ffffff", primary: "#ffffff",
secondary: "#b3b3b3" secondary: "#b3b3b3",
} },
}, },
components: { components: {
MuiCard: { MuiCard: {
styleOverrides: { styleOverrides: {
@ -166,19 +167,19 @@ const darkTheme = createTheme({
"&:hover": { "&:hover": {
cursor: "pointer", cursor: "pointer",
boxShadow: boxShadow:
" 0px 3px 4px 0px hsla(0,0%,0%,0.14), 0px 3px 3px -2px hsla(0,0%,0%,0.12), 0px 1px 8px 0px hsla(0,0%,0%,0.2);" " 0px 3px 4px 0px hsla(0,0%,0%,0.14), 0px 3px 3px -2px hsla(0,0%,0%,0.12), 0px 1px 8px 0px hsla(0,0%,0%,0.2);",
} },
} },
} },
}, },
MuiIcon: { MuiIcon: {
defaultProps: { defaultProps: {
style: { style: {
color: "#ffffff" color: "#ffffff",
} },
} },
} },
} },
}); });
export { lightTheme, darkTheme }; export { lightTheme, darkTheme };