Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update variables in progress component to refs to maintain accuracy with canvas updates #587

Merged
merged 4 commits into from
Jul 26, 2024
Merged
Show file tree
Hide file tree
Changes from 3 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: 1 addition & 2 deletions src/components/MediaPlayer/MediaPlayer.js
Original file line number Diff line number Diff line change
Expand Up @@ -263,7 +263,6 @@ const MediaPlayer = ({
timeFragment = { start: 0, end: duration };
}
timeFragment.altStart = timeFragment.start;
timeFragment.duration = duration;
manifestDispatch({
canvasTargets: [timeFragment],
type: 'canvasTargets',
Expand Down Expand Up @@ -364,7 +363,7 @@ const MediaPlayer = ({
srcIndex,
targets,
currentTime: currentTime || 0,
nextItemClicked
nextItemClicked,
},
videoJSCurrentTime: { srcIndex, targets, currentTime: currentTime || 0 },
},
Expand Down
20 changes: 19 additions & 1 deletion src/components/MediaPlayer/VideoJS/VideoJSPlayer.js
Original file line number Diff line number Diff line change
Expand Up @@ -300,7 +300,7 @@ function VideoJSPlayer({
}));
}

playerRef.current.markers.removeAll();
playerRef.current.markers?.removeAll();
playerRef.current.markers.add([
...(fragmentMarker ? [fragmentMarker] : []),
...searchMarkers,
Expand Down Expand Up @@ -339,6 +339,7 @@ function VideoJSPlayer({
player.src(options.sources);
player.poster(options.poster);
player.canvasIndex = cIndexRef.current;
player.canvasDuration = canvasDurationRef.current;
player.srcIndex = srcIndex;
player.targets = targets;
player.canvasIsEmpty = canvasIsEmptyRef.current;
Expand Down Expand Up @@ -466,6 +467,11 @@ function VideoJSPlayer({
console.log('Player loadedmetadata');

player.duration(canvasDurationRef.current);
/**
* Set property canvasDuration in the player to use in videoJSProgress component.
* This updates the property when player.src() is updates.
*/
player.canvasDuration = canvasDurationRef.current;

// Reveal player once metadata is loaded
player.removeClass('vjs-disabled');
Expand Down Expand Up @@ -543,7 +549,16 @@ function VideoJSPlayer({
player.muted(startMuted);
player.volume(startVolume);
player.srcIndex = srcIndex;
player.duration(canvasDurationRef.current);

/**
* Set property canvasDuration in the player to use in videoJSProgress component.
* Video.js' in-built duration function doesn't seem to update as fast as
* we expect to be used in videoJSProgress component.
* Setting this in the ready callback makes sure this is updated to the
* correct value before 'loadstart' event is fired in videoJSProgress component.
*/
player.canvasDuration = canvasDurationRef.current;
if (enableTitleLink) { player.canvasLink = canvasLinkRef.current; }
// Need to set this once experimentalSvgIcons option in Video.js options was enabled
player.getChild('controlBar').qualitySelector.setIcon('cog');
Expand Down Expand Up @@ -758,6 +773,7 @@ function VideoJSPlayer({

// Remove all the existing structure related markers in the player
if (playerRef.current && playerRef.current.markers) {
playerRef.current.pause();
playerRef.current.markers.removeAll();
}
if (hasMultiItems) {
Expand Down Expand Up @@ -810,6 +826,7 @@ function VideoJSPlayer({
}
}
}
playerRef.current.play();
}), [cIndexRef.current]);

/**
Expand All @@ -825,6 +842,7 @@ function VideoJSPlayer({
const player = playerRef.current;
if (player !== null && isReadyRef.current) {
let playerTime = player.currentTime() ?? currentTimeRef.current;

if (hasMultiItems && srcIndexRef.current > 0) {
playerTime = playerTime + targets[srcIndexRef.current].altStart;
}
Expand Down
69 changes: 41 additions & 28 deletions src/components/MediaPlayer/VideoJS/components/js/VideoJSProgress.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,10 @@ const vjsComponent = videojs.getComponent('Component');
* Custom component to show progress bar in the player, modified
* to display multiple items in a single canvas
* @param {Object} props
* @param {Number} props.duration canvas duration
* @param {Array} props.targets set of start and end times for
* items in the current canvas
* @param {Function} nextItemClicked callback func to trigger state
* changes in the parent component
* @param {Number} props.srcIndex index for current src when multiple sources are present
* @param {Array} props.targets set of start and end times for items in the current canvas
* @param {Number} props.currentTime initial current time set as needed, defaults to 0
* @param {Function} props.nextItemClicked callback func to next source in Canvas
*/
class VideoJSProgress extends vjsComponent {
constructor(player, options) {
Expand Down Expand Up @@ -49,7 +48,8 @@ class VideoJSProgress extends vjsComponent {
/** Build progress bar elements from the options */
initProgressBar() {
const { targets, srcIndex } = this.options;
const { start, end, duration } = targets[srcIndex];
const { start, end } = targets[srcIndex];
const duration = this.player.canvasDuration;
let startTime = start,
endTime = end;

Expand Down Expand Up @@ -205,9 +205,6 @@ function ProgressBar({
const sliderRangeRef = React.useRef();
const [tLeft, setTLeft] = React.useState([]);
const [tRight, setTRight] = React.useState([]);
const [canvasTimes, setCanvasTimes] = React.useState(times);
const [activeSrcIndex, setActiveSrcIndex] = React.useState(0);
const [canvasTargets, setCanvasTargets] = React.useState(targets);
const isMultiSourced = targets.length > 1 ? true : false;

let initTimeRef = React.useRef(initCurrentTime);
Expand All @@ -219,6 +216,18 @@ function ProgressBar({
progressRef.current = p;
_setProgress(p);
};
let canvasTimesRef = React.useRef(times);
const setCanvasTimes = (c) => {
canvasTimesRef.current = c;
};
let activeSrcIndexRef = React.useRef(0);
const setActiveSrcIndex = (i) => {
activeSrcIndexRef.current = i;
};
let canvasTargetsRef = React.useRef(targets);
const setCanvasTargets = (t) => {
canvasTargetsRef.current = t;
};

let playerEventListener;

Expand All @@ -234,8 +243,8 @@ function ProgressBar({
sliderRangeRef.current.offsetHeight * 6 + // deduct 6 x height of progress bar element
'px';
}
const right = canvasTargets.filter((_, index) => index > srcIndex);
const left = canvasTargets.filter((_, index) => index < srcIndex);
const right = canvasTargetsRef.current.filter((_, index) => index > srcIndex);
const left = canvasTargetsRef.current.filter((_, index) => index < srcIndex);
setTRight(right);
setTLeft(left);

Expand Down Expand Up @@ -274,17 +283,20 @@ function ProgressBar({

React.useEffect(() => {
setCanvasTargets(targets);
setCanvasTimes(targets[srcIndex]);
const cTimes = targets[srcIndex];
setCanvasTimes(cTimes);
setActiveSrcIndex(srcIndex);

const right = canvasTargets.filter((_, index) => index > srcIndex);
const left = canvasTargets.filter((_, index) => index < srcIndex);
const right = canvasTargetsRef.current.filter((_, index) => index > srcIndex);
const left = canvasTargetsRef.current.filter((_, index) => index < srcIndex);
setTRight(right);
setTLeft(left);

const curTime = player.currentTime();
setProgress(curTime);
setCurrentTime(curTime + canvasTimes.altStart);
setProgress(cTimes.start);
setInitTime(cTimes.start);

setCurrentTime(cTimes.start);
player.currentTime(cTimes.start);
Dananji marked this conversation as resolved.
Show resolved Hide resolved

/**
* Using a time interval instead of 'timeupdate event in VideoJS, because Safari
Expand All @@ -305,7 +317,8 @@ function ProgressBar({
}, 100);

// Get the pixel ratio for the range
const ratio = sliderRangeRef.current.offsetWidth / (canvasTimes.end - canvasTimes.start);
const ratio = sliderRangeRef.current.offsetWidth /
(canvasTimesRef.current.end - canvasTimesRef.current.start);

// Convert current progress to pixel values
let leftWidth = progressRef.current * ratio;
Expand All @@ -328,7 +341,7 @@ function ProgressBar({
timeToolRef.current.innerHTML = formatTooltipTime(currentTime);

handleTimeUpdate(initTimeRef.current);
}, [player.src(), targets]);
}, [player.src(), player.canvasIndex, targets]);

/**
* A wrapper function around the time update interval, to cancel
Expand Down Expand Up @@ -419,7 +432,7 @@ function ProgressBar({
let time =
(offsetx / e.target.clientWidth) * (e.target.max - e.target.min)
;
if (index != undefined) time += canvasTargets[index].altStart;
if (index != undefined) time += canvasTargetsRef.current[index].altStart;
return time;
}
};
Expand All @@ -433,9 +446,9 @@ function ProgressBar({
() => {
let time = currentTime;

if (activeSrcIndex > 0) time -= targets[activeSrcIndex].altStart;
if (activeSrcIndexRef.current > 0) time -= targets[activeSrcIndexRef.current].altStart;

const { start, end } = canvasTimes;
const { start, end } = canvasTimesRef.current;
if (time >= start && time <= end) {
player.currentTime(time);
setProgress(time);
Expand Down Expand Up @@ -492,20 +505,20 @@ function ProgressBar({

// Deduct the duration of the preceding ranges
if (clickedSrcIndex > 0) {
time -= canvasTargets[clickedSrcIndex - 1].duration;
time -= canvasTargetsRef.current[clickedSrcIndex - 1].duration;
}
nextItemClicked(clickedSrcIndex, time);
};

const calculateTotalDuration = () => {
// You could fetch real durations via the metadata of each video if needed
let duration = canvasTargets.reduce((acc, t) => acc + t.duration, 0);
if (isNaN(duration)) { duration = canvasTargets[0].end; }
let duration = canvasTargetsRef.current.reduce((acc, t) => acc + t.duration, 0);
if (isNaN(duration)) { duration = canvasTargetsRef.current[0].end; }
return duration;
};

const formatTooltipTime = (time) => {
const { start, end } = canvasTimes;
const { start, end } = canvasTimesRef.current;
if (isMultiSourced) {
return timeToHHmmss(time);
} else {
Expand Down Expand Up @@ -580,9 +593,9 @@ function ProgressBar({
<input
type="range"
aria-label="Progress bar"
aria-valuemax={canvasTimes.end} aria-valuemin={canvasTimes.start}
aria-valuemax={canvasTimesRef.current.end} aria-valuemin={canvasTimesRef.current.start}
aria-valuenow={progress}
max={canvasTimes.end} min={canvasTimes.start}
max={canvasTimesRef.current.end} min={canvasTimesRef.current.start}
value={progress}
role="slider"
data-srcindex={srcIndex}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@
align-items: center;
min-width: 4em;
touch-action: none;
height: 1em;
margin-top: 1.1em;
}

.vjs-progress-holder {
Expand Down Expand Up @@ -132,7 +134,6 @@
}

.block-stripes {
height: inherit;
color: white;
background: repeating-linear-gradient(45deg,
$primaryDarker,
Expand Down