{"version":3,"file":"ImageWrapper-De8qcpgW.js","sources":["../../src/components/VideoPlayer.tsx","../../src/components/MediaWrappers/IpfsImageLoader.tsx","../../src/components/MediaWrappers/ImageWrapper.tsx"],"sourcesContent":["/* eslint-disable jsx-a11y/control-has-associated-label */\n/* eslint-disable jsx-a11y/media-has-caption */\nimport React, { useState } from 'react'\n\ninterface VideoPlayerProps extends React.VideoHTMLAttributes {\n fullImage?: boolean\n videoSrc: string\n}\n\nconst VideoPlayer: React.FC = ({ fullImage = false, videoSrc, ...props }) => {\n const containerStyle = {\n position: 'relative',\n display: 'inline-block',\n } as React.CSSProperties\n\n const videoStyle = {\n width: '100%',\n display: 'block',\n } as React.CSSProperties\n\n const playButtonContainerStyle = {\n position: 'absolute',\n top: '50%',\n left: '50%',\n transform: 'translate(-50%, -50%)',\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n width: '100%',\n height: '100%',\n } as React.CSSProperties\n\n const playButtonStyle = {\n backgroundColor: 'rgba(0, 0, 0, 0.5)',\n border: 'none',\n borderRadius: '50%',\n width: '60px',\n height: '60px',\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n cursor: 'pointer',\n outline: 'none',\n } as React.CSSProperties\n\n const playButtonIconStyle = {\n fill: '#fff',\n } as React.CSSProperties\n\n const [showPlayButton, setShowPlayButton] = useState(true)\n\n return (\n
\n \n {!fullImage && (\n
\n {showPlayButton ? (\n {\n e.stopPropagation()\n setShowPlayButton(false)\n document.querySelector('video')?.play()\n }}\n >\n \n \n \n \n ) : (\n {\n e.stopPropagation()\n setShowPlayButton(true)\n document.querySelector('video')?.pause()\n }}\n >\n \n \n \n \n )}\n
\n )}\n
\n )\n}\n\nexport default VideoPlayer\n","import { Box, Center, Text, useMantineTheme } from '@mantine/core'\nimport * as Sentry from '@sentry/react'\nimport React, { useCallback, useEffect, useState } from 'react'\n\nimport { getDb, IPFS_CACHE_DB_NAME, saveToDb } from '@/plugins/db/Db'\n\nimport placeholderImageOnLoad from '../../assets/webp_converted/imageOnload.webp'\nimport { ipfsDomains, processIpfsDomain } from '../../utils/utils'\nimport RootButton from '../Buttons/RootButton'\nimport Loading from '../Loading'\nimport VideoPlayer from '../VideoPlayer'\n\nconst timeoutImageLoad = 4000\n\ninterface IpfsImageLoaderProps extends React.ImgHTMLAttributes {\n fullImage?: boolean\n ipfsHash: string\n}\n\nconst IpfsImageLoader: React.FC = ({\n fullImage = false,\n ipfsHash,\n ...props\n}) => {\n const theme = useMantineTheme()\n const [imageUrl, setImageUrl] = useState(placeholderImageOnLoad)\n const [isVideo, setIsVideo] = useState(false)\n const [currentPrefixIndex, setCurrentPrefixIndex] = useState(0)\n const [loadError, setLoadError] = useState(false)\n const [loadingImg, setLoadingImg] = useState(false)\n const [retryCount, setRetryCount] = useState(0)\n\n const handleRetry = useCallback(\n (e: React.MouseEvent) => {\n e.preventDefault()\n\n // stop previous event propagation\n e.stopPropagation()\n\n // Reset prefix index if all prefixes have been exhausted\n setCurrentPrefixIndex(0)\n\n // Reset error state\n setLoadError(false)\n\n // Increment retry count\n setRetryCount(retryCount + 1)\n },\n [retryCount]\n )\n\n const handleError = useCallback(() => {\n setLoadError(true)\n }, [])\n\n const fetchImage = useCallback(async () => {\n // Get ipfs domain\n const ipfsDomain = ipfsDomains[currentPrefixIndex]\n\n // Dont fetch if ipfs domain prefix is undefined\n if (ipfsDomain === undefined) {\n return\n }\n\n // Construct url\n const url = processIpfsDomain(ipfsDomain, ipfsHash)\n setLoadingImg(true)\n\n // Get IndexedDB instance ipfs-cache\n const db = await getDb(IPFS_CACHE_DB_NAME)\n // check if db has table ipfs\n const hasIpfsTable = !!(await db?.table('ipfs').count())\n\n // Check if the image is already in the cache\n const cachedResponse = hasIpfsTable && (await db?.table('ipfs').get(ipfsHash))\n if (cachedResponse) {\n // Check if content type is video\n if (cachedResponse.data.type.includes('video')) {\n setIsVideo(true)\n }\n\n // if data content type is plain text, it means the image is not found. So, remove it from the cache and retry\n if (cachedResponse.data.type.includes('text')) {\n try {\n await db?.table('ipfs').delete(ipfsHash)\n } catch (error) {\n console.error('error', error)\n }\n fetchImage()\n return\n }\n\n setImageUrl(URL.createObjectURL(await cachedResponse.data))\n setLoadingImg(false)\n return\n }\n\n // Create a new AbortController for each attempt\n const controller = new AbortController()\n const { signal } = controller\n\n // Set a timeout for the fetch request\n const startTime = Date.now()\n const timeoutId = setTimeout(\n () => controller.abort(),\n (currentPrefixIndex + 1) * timeoutImageLoad\n )\n\n try {\n // If not, fetch the image from the IPFS URL\n const response = await fetch(url, { signal })\n if (!response.ok) {\n throw new Error(`Failed to fetch IPFS image: ${response.statusText}`)\n }\n const blob = await response.blob()\n\n // Check if content type is video\n if (blob.type.includes('video')) {\n setIsVideo(true)\n }\n\n // Set the image url\n setImageUrl(URL.createObjectURL(blob))\n\n // Save the image to IndexedDB\n console.log('saving IPFS Image to db', ipfsHash)\n await saveToDb(db, 'ipfs', { cid: ipfsHash, data: blob, timestamp: Date.now() })\n\n // on success, clear the timer and error state\n clearTimeout(timeoutId)\n setLoadError(false)\n } catch (error: any) {\n if (error.name === 'AbortError') {\n // check time elapsed in seconds\n const elapsedTime = Date.now() - startTime\n console.log('Request was aborted due to timeout after', elapsedTime / 1000, 'seconds')\n } else {\n console.error('Fetch failed:', error)\n Sentry.withScope(scope => {\n scope.setTag('ignore_error', 'true')\n })\n }\n // No need to clear the timeout here, as it’s already cleared if the fetch was aborted\n\n // Try another prefix\n if (currentPrefixIndex < ipfsDomains.length - 1) {\n setCurrentPrefixIndex(prev => prev + 1)\n } else {\n setLoadError(true)\n }\n }\n setLoadingImg(false)\n }, [currentPrefixIndex, ipfsHash])\n\n useEffect(() => {\n // Don't fetch if the image has already loaded\n if (imageUrl === placeholderImageOnLoad) {\n fetchImage()\n }\n }, [fetchImage])\n\n return (\n <>\n {loadingImg && (\n \n \n \n )}\n {!loadingImg &&\n (isVideo ? (\n \n ) : (\n \n ))}\n {loadError && (\n \n \n Failed to load image from IPFS. Please try again.\n \n \n Retry\n \n \n )}\n \n )\n}\n\nexport default IpfsImageLoader\n","import { Stack } from '@mantine/core'\nimport React, { useState } from 'react'\n\nimport { ipfsDomains } from '@/utils/utils'\n\nimport placeholderImageOnLoad from '../../assets/webp_converted/imageOnload.webp'\nimport IpfsImageLoader from './IpfsImageLoader'\n\nexport const SimpleImage: React.FC> = ({\n src,\n className,\n alt,\n style,\n}) => {\n const [loading, setLoading] = useState(true)\n const [error, setError] = useState(false)\n const [tries, setTries] = useState(0)\n\n return (\n {\n if (tries < 3) {\n setTries(tries + 1)\n setLoading(true)\n } else {\n setError(true)\n setLoading(false)\n }\n }}\n onLoad={() => {\n if (tries >= 3) {\n setError(true)\n } else {\n setError(false)\n }\n setLoading(false)\n }}\n />\n )\n}\n\ninterface ImageWrapperProps extends React.ImgHTMLAttributes {\n fullImage?: boolean\n onClick?: () => void\n}\n\nconst ImageWrapper: React.FC = ({\n fullImage = false,\n src,\n className,\n alt,\n style,\n onClick,\n ...props\n}) => {\n // check if the image is an ipfs image\n const isIpfsImage =\n (src && ipfsDomains.some(domain => src.startsWith(domain))) || src?.startsWith('ipfs://')\n\n return (\n \n {src && isIpfsImage ? (\n \n ) : (\n \n )}\n \n )\n}\n\nexport default ImageWrapper\n"],"names":["VideoPlayer","fullImage","videoSrc","props","containerStyle","videoStyle","playButtonContainerStyle","playButtonStyle","playButtonIconStyle","showPlayButton","setShowPlayButton","useState","jsxs","jsx","e","_a","timeoutImageLoad","IpfsImageLoader","ipfsHash","theme","useMantineTheme","imageUrl","setImageUrl","placeholderImageOnLoad","isVideo","setIsVideo","currentPrefixIndex","setCurrentPrefixIndex","loadError","setLoadError","loadingImg","setLoadingImg","retryCount","setRetryCount","handleRetry","useCallback","handleError","fetchImage","ipfsDomain","ipfsDomains","url","processIpfsDomain","db","getDb","IPFS_CACHE_DB_NAME","cachedResponse","error","controller","signal","startTime","timeoutId","response","blob","saveToDb","elapsedTime","Sentry.withScope","scope","prev","useEffect","Fragment","Box","Loading","Center","Text","RootButton","SimpleImage","src","className","alt","style","loading","setLoading","setError","tries","setTries","ImageWrapper","onClick","isIpfsImage","domain","Stack"],"mappings":"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"}