Media Viewer: Fix seeking on mobile (#1736)

This commit is contained in:
Alexander Zinchuk 2022-03-02 14:09:02 +02:00
parent 5c8c9d2672
commit cb37404b8c
3 changed files with 33 additions and 9 deletions

View File

@ -178,8 +178,9 @@ const MediaViewerSlides: FC<OwnProps> = ({
return captureEvents(containerRef.current, {
isNotPassive: true,
excludedClosestSelector: '.VideoPlayerControls, .MediaViewerFooter',
onCapture: () => {
excludedClosestSelector: '.MediaViewerFooter',
onCapture: (e) => {
if (checkIfControlTarget(e)) return;
lastGestureTime = Date.now();
if (arePropsShallowEqual(transformRef.current, { x: 0, y: 0, scale: 1 })) {
if (!activeSlideRef.current) return;
@ -193,6 +194,7 @@ const MediaViewerSlides: FC<OwnProps> = ({
dragOffsetX,
dragOffsetY,
}) => {
if (checkIfControlTarget(event)) return;
// Avoid conflicts with swipe-to-back gestures
if (IS_IOS) {
const { pageX } = (captureEvent as RealTouchEvent).touches[0];
@ -553,3 +555,20 @@ export default memo(MediaViewerSlides);
function getAnimationStyle(x = 0, y = 0, scale = 1) {
return `transform: translate3d(${x.toFixed(3)}px, ${y.toFixed(3)}px, 0px) scale(${scale.toFixed(3)});`;
}
function checkIfInsideSelector(element: HTMLElement, selector: string) {
if (!element) return false;
if (element.matches(selector)) return true;
return Boolean(element.closest(selector));
}
function checkIfControlTarget(e: TouchEvent | MouseEvent) {
const target = e.target as HTMLElement;
if (checkIfInsideSelector(target, '.VideoPlayerControls')) {
if (checkIfInsideSelector(target, '.play, .fullscreen')) {
return true;
}
e.preventDefault();
return true;
}
}

View File

@ -18,7 +18,7 @@
@media (max-width: 600px) {
position: fixed;
padding: 1.25rem 0.5rem 0.75rem;
padding: 2.25rem 0.5rem 0.75rem;
background: none;
z-index: var(--z-media-viewer);
}
@ -110,6 +110,10 @@
touch-action: none;
cursor: pointer;
@media (max-width: 600px) {
top: 1rem;
}
&-track {
position: absolute;
top: 50%;

View File

@ -52,12 +52,13 @@ const VideoPlayerControls: FC<IProps> = ({
}) => {
// eslint-disable-next-line no-null/no-null
const seekerRef = useRef<HTMLDivElement>(null);
const isSeeking = useRef<boolean>(false);
const isSeekingRef = useRef<boolean>(false);
const isSeeking = isSeekingRef.current;
useEffect(() => {
let timeout: number | undefined;
if (!isVisible || !isPlayed) {
if (!isVisible || !isPlayed || isSeeking) {
if (timeout) window.clearTimeout(timeout);
return;
}
@ -67,7 +68,7 @@ const VideoPlayerControls: FC<IProps> = ({
return () => {
if (timeout) window.clearTimeout(timeout);
};
}, [isPlayed, isVisible, setVisibility]);
}, [isPlayed, isVisible, isSeeking, setVisibility]);
useEffect(() => {
if (isVisible) {
@ -83,7 +84,7 @@ const VideoPlayerControls: FC<IProps> = ({
const lang = useLang();
const handleSeek = useCallback((e: MouseEvent | TouchEvent) => {
if (isSeeking.current && seekerRef.current) {
if (isSeekingRef.current && seekerRef.current) {
const {
width,
left,
@ -94,12 +95,12 @@ const VideoPlayerControls: FC<IProps> = ({
}, [duration, onSeek]);
const handleStartSeek = useCallback((e: MouseEvent | TouchEvent) => {
isSeeking.current = true;
isSeekingRef.current = true;
handleSeek(e);
}, [handleSeek]);
const handleStopSeek = useCallback(() => {
isSeeking.current = false;
isSeekingRef.current = false;
}, []);
useEffect(() => {