pl-fe: video/audio player improvements
Signed-off-by: nicole mikołajczyk <git@mkljczk.pl>
This commit is contained in:
@ -1,5 +1,5 @@
|
||||
import throttle from 'lodash/throttle';
|
||||
import React, { useRef } from 'react';
|
||||
import React, { useCallback, useRef } from 'react';
|
||||
|
||||
import { getPointerPosition } from 'pl-fe/features/video';
|
||||
|
||||
@ -33,7 +33,7 @@ const Slider: React.FC<ISlider> = ({ value, onChange }) => {
|
||||
document.removeEventListener('touchend', handleMouseUp, true);
|
||||
};
|
||||
|
||||
const handleMouseSlide = throttle(e => {
|
||||
const handleMouseSlide = useCallback(throttle(e => {
|
||||
if (node.current) {
|
||||
const { x } = getPointerPosition(node.current, e);
|
||||
|
||||
@ -49,7 +49,7 @@ const Slider: React.FC<ISlider> = ({ value, onChange }) => {
|
||||
onChange(slideamt);
|
||||
}
|
||||
}
|
||||
}, 60);
|
||||
}, 60), [node.current]);
|
||||
|
||||
return (
|
||||
<div
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
import throttle from 'lodash/throttle';
|
||||
import React, { useRef } from 'react';
|
||||
import React, { useCallback, useRef } from 'react';
|
||||
|
||||
import { getPointerPosition } from 'pl-fe/features/video';
|
||||
|
||||
@ -35,7 +35,7 @@ const StepSlider: React.FC<IStepSlider> = ({ value, steps, onChange }) => {
|
||||
document.removeEventListener('touchend', handleMouseUp, true);
|
||||
};
|
||||
|
||||
const handleMouseSlide = throttle(e => {
|
||||
const handleMouseSlide = useCallback(throttle(e => {
|
||||
if (node.current) {
|
||||
const { x } = getPointerPosition(node.current, e);
|
||||
|
||||
@ -52,7 +52,7 @@ const StepSlider: React.FC<IStepSlider> = ({ value, steps, onChange }) => {
|
||||
onChange(slideamt);
|
||||
}
|
||||
}
|
||||
}, 60);
|
||||
}, 60), [node.current]);
|
||||
|
||||
return (
|
||||
<div
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
import clsx from 'clsx';
|
||||
import debounce from 'lodash/debounce';
|
||||
import throttle from 'lodash/throttle';
|
||||
import React, { useEffect, useLayoutEffect, useRef, useState } from 'react';
|
||||
import React, { useCallback, useEffect, useLayoutEffect, useRef, useState } from 'react';
|
||||
import { defineMessages, useIntl } from 'react-intl';
|
||||
|
||||
import Icon from 'pl-fe/components/icon';
|
||||
@ -66,7 +66,6 @@ const Audio: React.FC<IAudio> = (props) => {
|
||||
const [muted, setMuted] = useState(false);
|
||||
const [volume, setVolume] = useState(0.5);
|
||||
const [dragging, setDragging] = useState(false);
|
||||
const [hovered, setHovered] = useState(false);
|
||||
|
||||
const visualizer = useRef<Visualizer>(new Visualizer(TICK_SIZE));
|
||||
const audioContext = useRef<AudioContext | null>(null);
|
||||
@ -149,13 +148,23 @@ const Audio: React.FC<IAudio> = (props) => {
|
||||
}
|
||||
};
|
||||
|
||||
const toggleMute = () => {
|
||||
const nextMuted = !muted;
|
||||
|
||||
setMuted(nextMuted);
|
||||
|
||||
const handleVolumeChange = () => {
|
||||
if (audio.current) {
|
||||
setVolume(audio.current.volume);
|
||||
setMuted(audio.current.muted);
|
||||
}
|
||||
};
|
||||
|
||||
const toggleMute = () => {
|
||||
if (audio.current) {
|
||||
const nextMuted = !audio.current.muted;
|
||||
const nextVolume = nextMuted ? 0 : 1;
|
||||
|
||||
setVolume(nextVolume);
|
||||
setMuted(nextMuted);
|
||||
|
||||
audio.current.muted = nextMuted;
|
||||
audio.current.volume = nextVolume;
|
||||
}
|
||||
};
|
||||
|
||||
@ -202,7 +211,7 @@ const Audio: React.FC<IAudio> = (props) => {
|
||||
audio.current?.play();
|
||||
};
|
||||
|
||||
const handleMouseMove = throttle((e) => {
|
||||
const handleMouseMove = useCallback(throttle((e) => {
|
||||
if (audio.current && seek.current) {
|
||||
const { x } = getPointerPosition(seek.current, e);
|
||||
const currentTime = audio.current.duration * x;
|
||||
@ -212,7 +221,7 @@ const Audio: React.FC<IAudio> = (props) => {
|
||||
audio.current.currentTime = currentTime;
|
||||
}
|
||||
}
|
||||
}, 15);
|
||||
}, 15), [audio.current, seek.current]);
|
||||
|
||||
const handleTimeUpdate = () => {
|
||||
if (audio.current) {
|
||||
@ -221,18 +230,22 @@ const Audio: React.FC<IAudio> = (props) => {
|
||||
}
|
||||
};
|
||||
|
||||
const handleMouseVolSlide = throttle(e => {
|
||||
const handleMouseVolSlide = useCallback(throttle(e => {
|
||||
if (audio.current && slider.current) {
|
||||
const { x } = getPointerPosition(slider.current, e);
|
||||
|
||||
if (!isNaN(x)) {
|
||||
setVolume(x);
|
||||
audio.current.volume = x;
|
||||
const volume = Math.max(0, Math.min(1, x));
|
||||
|
||||
setVolume(volume);
|
||||
setMuted(volume === 0);
|
||||
audio.current.volume = volume;
|
||||
audio.current.muted = volume === 0;
|
||||
}
|
||||
}
|
||||
}, 15);
|
||||
}, 60), [audio.current, slider.current]);
|
||||
|
||||
const handleScroll = throttle(() => {
|
||||
const handleScroll = useCallback(throttle(() => {
|
||||
if (!canvas.current || !audio.current) {
|
||||
return;
|
||||
}
|
||||
@ -249,15 +262,7 @@ const Audio: React.FC<IAudio> = (props) => {
|
||||
|
||||
setPaused(true);
|
||||
}
|
||||
}, 150, { trailing: true });
|
||||
|
||||
const handleMouseEnter = () => {
|
||||
setHovered(true);
|
||||
};
|
||||
|
||||
const handleMouseLeave = () => {
|
||||
setHovered(false);
|
||||
};
|
||||
}, 150, { trailing: true }), [canvas.current, audio.current, paused]);
|
||||
|
||||
const handleLoadedData = () => {
|
||||
if (audio.current) {
|
||||
@ -432,8 +437,6 @@ const Audio: React.FC<IAudio> = (props) => {
|
||||
width: '100%',
|
||||
height: fullscreen ? '100%' : (height || props.height),
|
||||
}}
|
||||
onMouseEnter={handleMouseEnter}
|
||||
onMouseLeave={handleMouseLeave}
|
||||
tabIndex={0}
|
||||
onKeyDown={handleKeyDown}
|
||||
onClick={e => e.stopPropagation()}
|
||||
@ -445,6 +448,7 @@ const Audio: React.FC<IAudio> = (props) => {
|
||||
onPlay={handlePlay}
|
||||
onPause={handlePause}
|
||||
onProgress={handleProgress}
|
||||
onVolumeChange={handleVolumeChange}
|
||||
onLoadedData={handleLoadedData}
|
||||
crossOrigin='anonymous'
|
||||
/>
|
||||
@ -493,11 +497,7 @@ const Audio: React.FC<IAudio> = (props) => {
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className={clsx(
|
||||
'video-player__controls video-player__controls--visible',
|
||||
// { 'video-player__controls--visible': paused || hovered },
|
||||
)}
|
||||
>
|
||||
<div className='video-player__controls video-player__controls--visible'>
|
||||
<div className='mx-[-5px] my-0 flex justify-between'>
|
||||
<div className='video-player__buttons left'>
|
||||
|
||||
|
||||
@ -199,27 +199,20 @@ const Video: React.FC<IVideo> = ({
|
||||
document.removeEventListener('touchend', handleVolumeMouseUp, true);
|
||||
};
|
||||
|
||||
const handleMouseVolSlide = throttle(e => {
|
||||
if (slider.current) {
|
||||
const handleMouseVolSlide = useCallback(throttle(e => {
|
||||
if (video.current && slider.current) {
|
||||
const { x } = getPointerPosition(slider.current, e);
|
||||
|
||||
if (!isNaN(x)) {
|
||||
let slideamt = x;
|
||||
const volume = Math.max(0, Math.min(1, x));
|
||||
|
||||
if (x > 1) {
|
||||
slideamt = 1;
|
||||
} else if (x < 0) {
|
||||
slideamt = 0;
|
||||
}
|
||||
|
||||
if (video.current) {
|
||||
video.current.volume = slideamt;
|
||||
}
|
||||
|
||||
setVolume(slideamt);
|
||||
setVolume(volume);
|
||||
setMuted(volume === 0);
|
||||
video.current.volume = volume;
|
||||
video.current.muted = volume === 0;
|
||||
}
|
||||
}
|
||||
}, 60);
|
||||
}, 60), [video.current, slider.current]);
|
||||
|
||||
const handleMouseDown: React.MouseEventHandler = e => {
|
||||
const wasPlaying = !paused;
|
||||
@ -248,7 +241,7 @@ const Video: React.FC<IVideo> = ({
|
||||
};
|
||||
|
||||
|
||||
const handleMouseMove = throttle(e => {
|
||||
const handleMouseMove = useCallback(throttle(e => {
|
||||
if (seek.current && video.current) {
|
||||
const { x } = getPointerPosition(seek.current, e);
|
||||
const currentTime = Math.floor(video.current.duration * x);
|
||||
@ -258,7 +251,7 @@ const Video: React.FC<IVideo> = ({
|
||||
setCurrentTime(currentTime);
|
||||
}
|
||||
}
|
||||
}, 60);
|
||||
}, 60), [seek.current, video.current]);
|
||||
|
||||
const seekBy = (time: number) => {
|
||||
if (video.current) {
|
||||
@ -387,9 +380,14 @@ const Video: React.FC<IVideo> = ({
|
||||
|
||||
const toggleMute = () => {
|
||||
if (video.current) {
|
||||
const muted = !video.current.muted;
|
||||
setMuted(!muted);
|
||||
video.current.muted = muted;
|
||||
const nextMuted = !video.current.muted;
|
||||
const nextVolume = nextMuted ? 0 : 1;
|
||||
|
||||
setVolume(nextVolume);
|
||||
setMuted(nextMuted);
|
||||
|
||||
video.current.muted = nextMuted;
|
||||
video.current.volume = nextVolume;
|
||||
}
|
||||
};
|
||||
|
||||
@ -538,10 +536,10 @@ const Video: React.FC<IVideo> = ({
|
||||
<Icon src={muted ? require('@phosphor-icons/core/regular/speaker-x.svg') : require('@phosphor-icons/core/regular/speaker-high.svg')} />
|
||||
</button>
|
||||
|
||||
<div className={clsx('video-player__volume')} onMouseDown={handleVolumeMouseDown} ref={slider}>
|
||||
<div className='video-player__volume' onMouseDown={handleVolumeMouseDown} ref={slider}>
|
||||
<div className='video-player__volume__current' style={{ width: `${volume * 100}%` }} />
|
||||
<span
|
||||
className={clsx('video-player__volume__handle')}
|
||||
className='video-player__volume__handle'
|
||||
tabIndex={0}
|
||||
style={{ left: `${volume * 100}%` }}
|
||||
/>
|
||||
|
||||
Reference in New Issue
Block a user