|
- import * as React from "react";
- import {createRef, useEffect, useState} from "react";
-
- import "./photo-viewer.scss"
- import {ArrowLeft, ArrowRight, Close} from "@mui/icons-material";
- import {useCurrentInstance} from "../../services/current-instance/use-current-instance";
-
- export function PhotoViewer() {
- const {selectedAlbum, selectedPhotoIndex, setSelectedPhotoIndex} = useCurrentInstance();
- const [touchStartX, setTouchStartX] = useState();
- const [offset, setOffset] = useState(0);
- const elPhotoViewer = createRef();
-
- const hasNext = selectedPhotoIndex < (selectedAlbum?.photos.length || 0) - 1;
- const hasPrevious = selectedPhotoIndex > 0;
-
- useEffect(() => {
- if (elPhotoViewer.current) {
- elPhotoViewer.current.focus();
- }
- }, [elPhotoViewer]);
-
- const handleClick = (e) => {
- if (e.target === elPhotoViewer.current) {
- setSelectedPhotoIndex(-1);
- }
- }
-
- const handleGoPrevious = () => {
- if (hasPrevious) {
- setSelectedPhotoIndex(selectedPhotoIndex - 1);
- }
- }
- const handleGoNext = () => {
- if (hasNext) {
- setSelectedPhotoIndex(selectedPhotoIndex + 1);
- }
- }
- const handleClose = () => {
- setSelectedPhotoIndex(-1);
- }
- const handleKeyUp = (e) => {
- switch (e.code) {
- case "ArrowLeft":
- handleGoPrevious();
- break;
- case "ArrowRight":
- handleGoNext();
- break;
- case "Escape":
- setSelectedPhotoIndex(-1);
- break;
- default:
- break;
- }
- }
- const handleTouchStart = (/** TouchEvent **/e) => {
- if (e.touches.length === 1) {
- //just one finger touched
- setTouchStartX(e.touches.item(0).clientX);
- } else {
- //a second finger hit the screen, abort the touch
- setTouchStartX(null);
- }
- }
-
- const handleTouchMove = (/** TouchEvent **/e) => {
- if (e.touches.length === 1) {
- const end = e.changedTouches.item(0).clientX;
- setOffset(end - touchStartX);
- } else {
- setTouchStartX(null);
- setOffset(0);
- }
- }
- const handleTouchEnd = (/** TouchEvent **/e) => {
- const minOffset = 100; //at least 100px are a swipe
- if (touchStartX) {
- //the only finger that hit the screen left it
- const end = e.changedTouches.item(0).clientX;
- if (end > touchStartX + minOffset) {
- //a left -> right swipe
- handleGoPrevious();
- } else if (end < touchStartX - minOffset) {
- //a right -> left swipe
- handleGoNext();
- }
- }
- setOffset(0);
- }
- const previousPhotoStyle = {
- right: `calc(100% + ${15 - offset}px)`
- }
- const nextPhotoStyle = {
- left: `calc(100% - ${-offset}px)`
- }
- const photoStyle = {
- marginLeft: `${offset}px`
- }
- return <>
- {selectedPhotoIndex >= 0 ?
- <div tabIndex={1} ref={elPhotoViewer} id="photoViewer" onClick={handleClick} onKeyUp={handleKeyUp}
- onTouchStart={handleTouchStart} onTouchEnd={handleTouchEnd} onTouchMove={handleTouchMove}>
- <div className="body-overlay"></div>
- <div className="goto-btn goto-btn--previous" onClick={handleGoPrevious}>
- {hasPrevious && <ArrowLeft/>}
- </div>
- <div id="photoSlider">
- {hasPrevious &&
- <div className="photo photo--placeholder photo--previous" style={previousPhotoStyle}>
- <img src={`${selectedAlbum.photos[selectedPhotoIndex - 1].url}`}
- alt={selectedAlbum.photos[selectedPhotoIndex - 1].name}/>
- </div>}
- <div className="photo photo--invisible">
- <img src={`${selectedAlbum.photos[selectedPhotoIndex].url}`}
- alt={selectedAlbum.photos[selectedPhotoIndex].name}/>
- </div>
- <div className="photo photo--placeholder" style={photoStyle}>
- <img src={`${selectedAlbum.photos[selectedPhotoIndex].url}`}
- alt={selectedAlbum.photos[selectedPhotoIndex].name}/>
- </div>
- {hasNext && <div className="photo photo--placeholder photo--next" style={nextPhotoStyle}>
- <img src={`${selectedAlbum.photos[selectedPhotoIndex + 1].url}`}
- alt={selectedAlbum.photos[selectedPhotoIndex + 1].name}/>
- </div>}
- </div>
- <div className="goto-btn goto-btn--next" onClick={handleGoNext}>
- {hasNext && <ArrowRight/>}
- </div>
-
- <div className="close-btn" onClick={handleClose}>
- {hasNext && <Close/>}
- </div>
- </div> : null}
- </>
- }
|