diff --git a/ui/v2.5/src/components/Images/ImageList.tsx b/ui/v2.5/src/components/Images/ImageList.tsx index a468c2815..4149970b5 100644 --- a/ui/v2.5/src/components/Images/ImageList.tsx +++ b/ui/v2.5/src/components/Images/ImageList.tsx @@ -20,7 +20,7 @@ import { ImageWallItem } from "./ImageWallItem"; import { EditImagesDialog } from "./EditImagesDialog"; import { DeleteImagesDialog } from "./DeleteImagesDialog"; import "flexbin/flexbin.css"; -import Gallery from "react-photo-gallery"; +import Gallery, { RenderImageProps } from "react-photo-gallery"; import { ExportDialog } from "../Shared/ExportDialog"; import { objectTitle } from "src/core/files"; import { ConfigurationContext } from "src/hooks/Config"; @@ -54,6 +54,8 @@ const ImageWall: React.FC = ({ const { configuration } = useContext(ConfigurationContext); const uiConfig = configuration?.ui; + const containerRef = React.useRef(null); + let photos: { src: string; srcSet?: string | string[] | undefined; @@ -94,22 +96,45 @@ const ImageWall: React.FC = ({ return Math.round(columnCount); } - function targetRowHeight(containerWidth: number) { - let zoomHeight = 280; - breakpointZoomHeights.forEach((e) => { - if (containerWidth >= e.minWidth) { - zoomHeight = e.heights[zoomIndex]; - } - }); - return zoomHeight; - } + const targetRowHeight = useCallback( + (containerWidth: number) => { + let zoomHeight = 280; + breakpointZoomHeights.forEach((e) => { + if (containerWidth >= e.minWidth) { + zoomHeight = e.heights[zoomIndex]; + } + }); + return zoomHeight; + }, + [zoomIndex] + ); + + // set the max height as a factor of the targetRowHeight + // this allows some images to be taller than the target row height + // but prevents images from becoming too tall when there is a small number of items + const maxHeightFactor = 1.3; + + const renderImage = useCallback( + (props: RenderImageProps) => { + return ( + + ); + }, + [targetRowHeight] + ); return ( -
+
{photos.length ? ( = ( - props: IImageWallProps +export const ImageWallItem: React.FC = ( + props: RenderImageProps & IExtraProps ) => { + const height = Math.min(props.maxHeight, props.photo.height); + const zoomFactor = height / props.photo.height; + const width = props.photo.width * zoomFactor; + type style = Record; var imgStyle: style = { margin: props.margin, @@ -49,8 +43,8 @@ export const ImageWallItem: React.FC = ( key={props.photo.key} style={imgStyle} src={props.photo.src} - width={props.photo.width} - height={props.photo.height} + width={width} + height={height} alt={props.photo.alt} onClick={handleClick} /> diff --git a/ui/v2.5/src/components/Scenes/SceneMarkerWallPanel.tsx b/ui/v2.5/src/components/Scenes/SceneMarkerWallPanel.tsx index 5202b94d1..a1879a027 100644 --- a/ui/v2.5/src/components/Scenes/SceneMarkerWallPanel.tsx +++ b/ui/v2.5/src/components/Scenes/SceneMarkerWallPanel.tsx @@ -39,15 +39,23 @@ interface IMarkerPhoto { onError?: (photo: PhotoProps) => void; } -export const MarkerWallItem: React.FC> = ( - props: RenderImageProps -) => { +interface IExtraProps { + maxHeight: number; +} + +export const MarkerWallItem: React.FC< + RenderImageProps & IExtraProps +> = (props: RenderImageProps & IExtraProps) => { const { configuration } = useContext(ConfigurationContext); const playSound = configuration?.interface.soundOnPreview ?? false; const showTitle = configuration?.interface.wallShowTitle ?? false; const [active, setActive] = useState(false); + const height = Math.min(props.maxHeight, props.photo.height); + const zoomFactor = height / props.photo.height; + const width = props.photo.width * zoomFactor; + type style = Record; var divStyle: style = { margin: props.margin, @@ -79,8 +87,8 @@ export const MarkerWallItem: React.FC> = ( role="button" style={{ ...divStyle, - width: props.photo.width, - height: props.photo.height, + width, + height, }} > > = ( autoPlay={video} key={props.photo.key} src={props.photo.src} - width={props.photo.width} - height={props.photo.height} + width={width} + height={height} alt={props.photo.alt} onMouseEnter={() => setActive(true)} onMouseLeave={() => setActive(false)} @@ -163,6 +171,8 @@ const breakpointZoomHeights = [ const MarkerWall: React.FC = ({ markers, zoomIndex }) => { const history = useHistory(); + const containerRef = React.useRef(null); + const margin = 3; const direction = "row"; @@ -208,22 +218,41 @@ const MarkerWall: React.FC = ({ markers, zoomIndex }) => { return Math.round(columnCount); } - function targetRowHeight(containerWidth: number) { - let zoomHeight = 280; - breakpointZoomHeights.forEach((e) => { - if (containerWidth >= e.minWidth) { - zoomHeight = e.heights[zoomIndex]; - } - }); - return zoomHeight; - } + const targetRowHeight = useCallback( + (containerWidth: number) => { + let zoomHeight = 280; + breakpointZoomHeights.forEach((e) => { + if (containerWidth >= e.minWidth) { + zoomHeight = e.heights[zoomIndex]; + } + }); + return zoomHeight; + }, + [zoomIndex] + ); - const renderImage = useCallback((props: RenderImageProps) => { - return ; - }, []); + // set the max height as a factor of the targetRowHeight + // this allows some images to be taller than the target row height + // but prevents images from becoming too tall when there is a small number of items + const maxHeightFactor = 1.3; + + const renderImage = useCallback( + (props: RenderImageProps) => { + return ( + + ); + }, + [targetRowHeight] + ); return ( -
+
{photos.length ? ( ) => void; } -export const SceneWallItem: React.FC> = ( - props: RenderImageProps -) => { +interface IExtraProps { + maxHeight: number; +} + +export const SceneWallItem: React.FC< + RenderImageProps & IExtraProps +> = (props: RenderImageProps & IExtraProps) => { const intl = useIntl(); const { configuration } = useContext(ConfigurationContext); const playSound = configuration?.interface.soundOnPreview ?? false; const showTitle = configuration?.interface.wallShowTitle ?? false; + const height = Math.min(props.maxHeight, props.photo.height); + const zoomFactor = height / props.photo.height; + const width = props.photo.width * zoomFactor; + const [active, setActive] = useState(false); type style = Record; @@ -72,8 +80,8 @@ export const SceneWallItem: React.FC> = ( role="button" style={{ ...divStyle, - width: props.photo.width, - height: props.photo.height, + width, + height, }} > > = ( autoPlay={video} key={props.photo.key} src={props.photo.src} - width={props.photo.width} - height={props.photo.height} + width={width} + height={height} alt={props.photo.alt} onMouseEnter={() => setActive(true)} onMouseLeave={() => setActive(false)} @@ -146,6 +154,8 @@ const SceneWall: React.FC = ({ }) => { const history = useHistory(); + const containerRef = React.useRef(null); + const margin = 3; const direction = "row"; @@ -196,22 +206,41 @@ const SceneWall: React.FC = ({ return Math.round(columnCount); } - function targetRowHeight(containerWidth: number) { - let zoomHeight = 280; - breakpointZoomHeights.forEach((e) => { - if (containerWidth >= e.minWidth) { - zoomHeight = e.heights[zoomIndex]; - } - }); - return zoomHeight; - } + const targetRowHeight = useCallback( + (containerWidth: number) => { + let zoomHeight = 280; + breakpointZoomHeights.forEach((e) => { + if (containerWidth >= e.minWidth) { + zoomHeight = e.heights[zoomIndex]; + } + }); + return zoomHeight; + }, + [zoomIndex] + ); - const renderImage = useCallback((props: RenderImageProps) => { - return ; - }, []); + // set the max height as a factor of the targetRowHeight + // this allows some images to be taller than the target row height + // but prevents images from becoming too tall when there is a small number of items + const maxHeightFactor = 1.3; + + const renderImage = useCallback( + (props: RenderImageProps) => { + return ( + + ); + }, + [targetRowHeight] + ); return ( -
+
{photos.length ? (