From 96bc6430f77135d555755914def22dc1cabcaa4d Mon Sep 17 00:00:00 2001 From: imran Date: Sat, 11 Nov 2023 19:40:18 +0100 Subject: [PATCH] fix CORS attribute missing bug --- src/components/GalleryItem/GalleryItem.tsx | 105 ++++++++++-------- .../GalleryItem/GalleryItem.types.ts | 3 + src/components/GalleryItem/ImageItem.tsx | 26 +++-- src/components/GalleryItem/SolidColorItem.tsx | 20 ++-- src/components/GalleryItem/VideoItem.tsx | 38 ++++--- src/core/VideoItemMaterial.ts | 10 +- src/core/index.ts | 2 +- 7 files changed, 122 insertions(+), 82 deletions(-) diff --git a/src/components/GalleryItem/GalleryItem.tsx b/src/components/GalleryItem/GalleryItem.tsx index 86590be..543c676 100644 --- a/src/components/GalleryItem/GalleryItem.tsx +++ b/src/components/GalleryItem/GalleryItem.tsx @@ -1,66 +1,75 @@ import { GALLERY_ITEM_NO_PROVIDER_FLAG, GalleryItemProps } from "./GalleryItem.types"; -import { useContext, useMemo } from "react"; +import React, { useContext, useEffect, useMemo } from "react"; import useGallery from "../Gallery/useGallery"; import { CylinderGeometry, Mesh } from "three"; import { CSG } from "three-csg-ts"; import GalleryItemContext from "./GalleryItemContext"; +import GalleryItemMaterial from "../../core/GalleryItemMaterial"; -const GalleryItem = ({ material, children }: GalleryItemProps) => { - const itemData = useContext(GalleryItemContext); - if (itemData === GALLERY_ITEM_NO_PROVIDER_FLAG) { - throw new Error("GalleryItem must be a child of Gallery"); - } +const GalleryItem = React.forwardRef( + ({ material, children }, ref) => { + const itemData = useContext(GalleryItemContext); + if (itemData === GALLERY_ITEM_NO_PROVIDER_FLAG) { + throw new Error("GalleryItem must be a child of Gallery"); + } - const { outerRadius, height, radialSegments, heightSegments, sectionAngle, innerRadius } = - useGallery().item; + const { outerRadius, height, radialSegments, heightSegments, sectionAngle, innerRadius } = + useGallery().item; - const generatedMaterial = useMemo(() => { - return material.generate(); - }, [material]); + const generatedMaterial = useMemo(() => { + return material.generate(); + }, [material]); - const mesh = useMemo(() => { - const outerGeometry = new CylinderGeometry( - outerRadius, + useEffect(() => { + if (ref && typeof ref === "object" && "current" in ref) { + (ref as React.MutableRefObject).current = material; + } + }, [material]); + + const mesh = useMemo(() => { + const outerGeometry = new CylinderGeometry( + outerRadius, + outerRadius, + height, + radialSegments, + heightSegments, + false, + itemData.itemIndex * sectionAngle, + sectionAngle, + ); + const outerMesh = new Mesh(outerGeometry); + + const innerGeometry = new CylinderGeometry( + innerRadius, + innerRadius, + height, + radialSegments, + heightSegments, + false, + itemData.itemIndex * sectionAngle, + sectionAngle, + ); + const innerMesh = new Mesh(innerGeometry); + innerMesh.position.y = -0.01; // Offset to prevent z-fighting + + // Perform CSG subtraction to hollow out the segment + const finalMesh = CSG.subtract(outerMesh, innerMesh); + finalMesh.material = generatedMaterial; + + return finalMesh; + }, [ outerRadius, height, radialSegments, heightSegments, - false, - itemData.itemIndex * sectionAngle, sectionAngle, - ); - const outerMesh = new Mesh(outerGeometry); - - const innerGeometry = new CylinderGeometry( - innerRadius, innerRadius, - height, - radialSegments, - heightSegments, - false, - itemData.itemIndex * sectionAngle, - sectionAngle, - ); - const innerMesh = new Mesh(innerGeometry); - innerMesh.position.y = -0.01; // Offset to prevent z-fighting - - // Perform CSG subtraction to hollow out the segment - const finalMesh = CSG.subtract(outerMesh, innerMesh); - finalMesh.material = generatedMaterial; - - return finalMesh; - }, [ - outerRadius, - height, - radialSegments, - heightSegments, - sectionAngle, - innerRadius, - material, - itemData.itemIndex, - ]); + material, + itemData.itemIndex, + ]); - return {children}; -}; + return {children}; + }, +); export default GalleryItem; diff --git a/src/components/GalleryItem/GalleryItem.types.ts b/src/components/GalleryItem/GalleryItem.types.ts index b298516..ffb2024 100644 --- a/src/components/GalleryItem/GalleryItem.types.ts +++ b/src/components/GalleryItem/GalleryItem.types.ts @@ -24,4 +24,7 @@ export type ImageItemProps = PropsWithChildren<{ export type VideoItemProps = PropsWithChildren<{ src: string; autoplay?: boolean; + muted?: boolean; + loop?: boolean; + crossOrigin?: "anonymous" | "use-credentials" | "" | null; }>; diff --git a/src/components/GalleryItem/ImageItem.tsx b/src/components/GalleryItem/ImageItem.tsx index c81edc3..068e383 100644 --- a/src/components/GalleryItem/ImageItem.tsx +++ b/src/components/GalleryItem/ImageItem.tsx @@ -1,18 +1,24 @@ import React, { useMemo } from "react"; import { ImageItemProps } from "./GalleryItem.types"; -import { ImageItemMaterial } from "../../core"; +import { ImageItemMaterial, GalleryItemMaterial } from "../../core"; import GalleryItem from "./GalleryItem"; -const ImageItem: React.FC = ({ src, texture, children }) => { - if (!src && !texture) { - throw new Error("Either src or texture must be provided"); - } +const ImageItem = React.forwardRef( + ({ src, texture, children }, ref) => { + if (!src && !texture) { + throw new Error("Either src or texture must be provided"); + } - const material = useMemo(() => { - return new ImageItemMaterial(texture ?? src!); - }, [src, texture]); + const material = useMemo(() => { + return new ImageItemMaterial(texture ?? src!); + }, [src, texture]); - return {children}; -}; + return ( + + {children} + + ); + }, +); export default ImageItem; diff --git a/src/components/GalleryItem/SolidColorItem.tsx b/src/components/GalleryItem/SolidColorItem.tsx index 0e5d60d..dc31d5d 100644 --- a/src/components/GalleryItem/SolidColorItem.tsx +++ b/src/components/GalleryItem/SolidColorItem.tsx @@ -1,14 +1,20 @@ import React, { useMemo } from "react"; import { SolidColorItemProps } from "./GalleryItem.types"; -import { SolidColorItemMaterial } from "../../core"; +import { SolidColorItemMaterial, GalleryItemMaterial } from "../../core"; import GalleryItem from "./GalleryItem"; -const SolidColorItem: React.FC = ({ color, children }) => { - const material = useMemo(() => { - return new SolidColorItemMaterial(color); - }, [color]); +const SolidColorItem = React.forwardRef( + ({ color, children }, ref) => { + const material = useMemo(() => { + return new SolidColorItemMaterial(color); + }, [color]); - return {children}; -}; + return ( + + {children} + + ); + }, +); export default SolidColorItem; diff --git a/src/components/GalleryItem/VideoItem.tsx b/src/components/GalleryItem/VideoItem.tsx index eadf5a6..30f5572 100644 --- a/src/components/GalleryItem/VideoItem.tsx +++ b/src/components/GalleryItem/VideoItem.tsx @@ -1,21 +1,33 @@ import React, { useLayoutEffect, useMemo } from "react"; import { VideoItemProps } from "./GalleryItem.types"; -import { VideoItemMaterial } from "../../core"; +import { VideoItemMaterial, GalleryItemMaterial } from "../../core"; import GalleryItem from "./GalleryItem"; -const VideoItem: React.FC = ({ src, children, autoplay = true }) => { - const material = useMemo(() => { - return new VideoItemMaterial(src); - }, [src]); +const VideoItem = React.forwardRef( + ({ src, children, autoplay = true, muted = true, loop = true, crossOrigin }, ref) => { + const material = useMemo(() => { + return new VideoItemMaterial(src, crossOrigin ?? undefined); + }, [src, crossOrigin]); - useLayoutEffect(() => { - // Play video if autoplay is enabled - if (material.getVideo() && autoplay) { - material.getVideo()?.play(); - } - }, [material]); + useLayoutEffect(() => { + if (material.getVideo()) { + const video = material.getVideo()!; + video.muted = muted; + video.loop = loop; - return {children}; -}; + if (autoplay) { + // Play video if autoplay is enabled + video.play(); + } + } + }, [material]); + + return ( + + {children} + + ); + }, +); export default VideoItem; diff --git a/src/core/VideoItemMaterial.ts b/src/core/VideoItemMaterial.ts index 34571db..70f13bf 100644 --- a/src/core/VideoItemMaterial.ts +++ b/src/core/VideoItemMaterial.ts @@ -5,9 +5,11 @@ class VideoItemMaterial implements GalleryItemMaterial { protected readonly source: string; protected texture: VideoTexture | undefined; protected video: HTMLVideoElement | undefined; + protected crossOrigin: string | undefined; - constructor(source: string) { + constructor(source: string, crossOrigin?: string) { this.source = source; + this.crossOrigin = crossOrigin; } protected initVideo(): void { @@ -20,8 +22,10 @@ class VideoItemMaterial implements GalleryItemMaterial { } this.video.src = this.source; - this.video.loop = true; - this.video.muted = true; + if (this.crossOrigin) { + this.video.crossOrigin = this.crossOrigin; + } + this.video.load(); } diff --git a/src/core/index.ts b/src/core/index.ts index 380a431..5e29e9e 100644 --- a/src/core/index.ts +++ b/src/core/index.ts @@ -1,4 +1,4 @@ -export * as GalleryItemMaterial from "./GalleryItemMaterial"; +export type { default as GalleryItemMaterial } from "./GalleryItemMaterial"; export { default as ImageItemMaterial } from "./ImageItemMaterial"; export { default as SolidColorItemMaterial } from "./SolidColorItemMaterial"; export { default as VideoItemMaterial } from "./VideoItemMaterial";