Skip to content
Open
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions src/main/SubtitleVideoArea.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,9 @@ const SubtitleVideoArea: React.FC<{
subtitleUrl={subtitleUrl}
first={true}
last={true}
isFullscreenPossible={false}
fullscreenPlayerIndex={undefined}
setFullscreenPlayerIndex={() => {}}
selectIsPlaying={selectIsPlaying}
selectIsMuted={selectIsMuted}
selectCurrentlyAtInSeconds={selectCurrentlyAtInSeconds}
Expand Down
109 changes: 87 additions & 22 deletions src/main/VideoPlayers.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -36,9 +36,11 @@ import { ActionCreatorWithPayload, AsyncThunk } from "@reduxjs/toolkit";

import { useTheme } from "../themes";

import { backgroundBoxStyle } from "../cssStyles";
import { backgroundBoxStyle, basicButtonStyle } from "../cssStyles";
import { BaseReactPlayerProps } from "react-player/base";
import { ErrorBox } from "@opencast/appkit";
import { LuFullscreen } from "react-icons/lu";
import { isSafari } from "react-device-detect";

const VideoPlayers: React.FC<{
refs?: React.MutableRefObject<(VideoPlayerForwardRef | null)[]>,
Expand All @@ -56,6 +58,7 @@ const VideoPlayers: React.FC<{
const videoCount = useAppSelector(selectVideoCount);

const [videoPlayers, setVideoPlayers] = useState<JSX.Element[]>([]);
const [fullscreenPlayerIndex, setFullscreenPlayerIndex] = useState<number | undefined>(undefined);

const videoPlayerAreaStyle = css({
display: "flex",
Expand All @@ -65,7 +68,9 @@ const VideoPlayers: React.FC<{
borderRadius: "5px",
gap: "10px",

maxHeight: maxHeightInPixel + "px",
maxHeight: fullscreenPlayerIndex === undefined
? maxHeightInPixel + "px"
: maxHeightInPixel * 2 + "px",
});

// Initialize video players
Expand All @@ -81,6 +86,9 @@ const VideoPlayers: React.FC<{
subtitleUrl={""}
first={i === 0}
last={i === videoCount - 1}
isFullscreenPossible={true}
fullscreenPlayerIndex={fullscreenPlayerIndex}
setFullscreenPlayerIndex={setFullscreenPlayerIndex}
selectIsPlaying={selectIsPlaying}
selectIsMuted={selectIsMuted}
selectVolume={selectVolume}
Expand All @@ -103,7 +111,7 @@ const VideoPlayers: React.FC<{
);
}
setVideoPlayers(videoPlayers);
}, [primaryIndex, refs, videoCount, videos]);
}, [primaryIndex, refs, videoCount, videos, fullscreenPlayerIndex]);


return (
Expand All @@ -125,6 +133,9 @@ interface VideoPlayerProps {
subtitleUrl: string,
first: boolean,
last: boolean,
isFullscreenPossible: boolean,
fullscreenPlayerIndex: number | undefined,
setFullscreenPlayerIndex: (index: number | undefined) => void,
selectIsPlaying: (state: RootState) => boolean,
selectIsMuted: (state: RootState) => boolean,
selectVolume: (state: RootState) => number,
Expand Down Expand Up @@ -167,6 +178,9 @@ export const VideoPlayer = React.forwardRef<VideoPlayerForwardRef, VideoPlayerPr
subtitleUrl,
first,
last,
isFullscreenPossible,
fullscreenPlayerIndex,
setFullscreenPlayerIndex,
selectCurrentlyAtInSeconds,
selectPreviewTriggered,
selectClickTriggered,
Expand Down Expand Up @@ -391,6 +405,7 @@ export const VideoPlayer = React.forwardRef<VideoPlayerForwardRef, VideoPlayerPr
}));

const reactPlayerStyle = css({
position: "relative", // For fullscreen button
aspectRatio: "16 / 9", // Hard-coded for now because there are problems with updating this value at runtime

overflow: "hidden", // Required for borderRadius to show
Expand All @@ -404,10 +419,39 @@ export const VideoPlayer = React.forwardRef<VideoPlayerForwardRef, VideoPlayerPr
},
});

const shouldHide = fullscreenPlayerIndex !== undefined && fullscreenPlayerIndex !== dataKey;

// Because of Safari and the fact that it is not able to read and occupy based on rendered aspect ratio,
// We need to toggle the display, in order for Safari to update itself!
const initialVideoPlayerWrapperDisplay = isSafari ? "none" : "flex";
const [videoPlayerWrapperDisplay, setVideoPlayerWrapperDisplay] = useState(initialVideoPlayerWrapperDisplay);

useEffect(() => {
if (ready && isSafari) {
const timeout = setTimeout(() => {
setVideoPlayerWrapperDisplay("flex");
}, 10);
return () => clearTimeout(timeout);
}
}, [ready]);

// Watch fullscreenPlayerIndex and toggle display briefly, in order for Safari to update itself!
useEffect(() => {
if (fullscreenPlayerIndex !== undefined && isSafari) {
setVideoPlayerWrapperDisplay("none");
const timeout = setTimeout(() => {
setVideoPlayerWrapperDisplay("flex");
}, 10);
return () => clearTimeout(timeout);
}
}, [fullscreenPlayerIndex]);

const videoPlayerWrapperStyles = css({
height: "100%",
width: "100%",
display: "flex",
display: shouldHide ? "none" : videoPlayerWrapperDisplay,

flexGrow: "1",

// For single video, center!
...(first && last) && { justifyContent: "center" },
Expand All @@ -420,30 +464,51 @@ export const VideoPlayer = React.forwardRef<VideoPlayerForwardRef, VideoPlayerPr

// For multi videos, in between, fit content and center!
...(!first && !last) && { justifyContent: "center", flexBasis: "fit-content" },

// If fullscreen, treat like single video
...fullscreenPlayerIndex !== undefined && { justifyContent: "center" },
});

const render = () => {
if (!errorState) {
return (
<div css={videoPlayerWrapperStyles}>
<ReactPlayer url={url}
css={[backgroundBoxStyle(theme), reactPlayerStyle]}
ref={ref}
width="unset"
height="100%"
playing={isPlaying}
volume={volume}
muted={!isPrimary || isMuted}
onProgress={onProgressCallback}
progressInterval={100}
onReady={onReadyCallback}
onPlay={onPlay}
onEnded={onEndedCallback}
onError={onErrorCallback}
tabIndex={-1}
config={playerConfig}
disablePictureInPicture
/>
{/* wrapper for positioning fullscreen button*/}
<div css={[backgroundBoxStyle(theme), reactPlayerStyle]}>
<ReactPlayer url={url}
// css={[backgroundBoxStyle(theme), reactPlayerStyle]} // moved to wrapper
ref={ref}
width="100%"
height="100%"
playing={isPlaying}
volume={volume}
muted={!isPrimary || isMuted}
onProgress={onProgressCallback}
progressInterval={100}
onReady={onReadyCallback}
onPlay={onPlay}
onEnded={onEndedCallback}
onError={onErrorCallback}
tabIndex={-1}
config={playerConfig}
disablePictureInPicture
/>
{isFullscreenPossible &&
<button css={[basicButtonStyle(theme), css({
position: "absolute",
bottom: "10px",
right: "10px",
})]}
onClick={() => {
if (fullscreenPlayerIndex === undefined) {
setFullscreenPlayerIndex(dataKey);
} else {
setFullscreenPlayerIndex(undefined);
}
}}
><LuFullscreen /></button>
}
</div>
</div>
);
} else {
Expand Down
Loading