import { useEffect, useMemo, useRef, useState } from 'react'; import { createPortal } from 'react-dom'; import { useTranslation } from 'react-i18next'; import { Link, useLocation, useParams } from 'react-router-dom'; import { useFloating, offset, size, autoUpdate, Placement } from '@floating-ui/react'; import { Comment } from '@plebbit/plebbit-react-hooks'; import Plebbit from '@plebbit/plebbit-js'; import { shouldShowSnow } from '../../lib/snow'; import { getHasThumbnail } from '../../lib/utils/media-utils'; import { getFormattedTimeAgo } from '../../lib/utils/time-utils'; import { isAllView, isSubscriptionsView } from '../../lib/utils/view-utils'; import { useDefaultSubplebbits } from '../../hooks/use-default-subplebbits'; import { getBoardPath } from '../../lib/utils/route-utils'; import useCatalogFiltersStore from '../../stores/use-catalog-filters-store'; import useCatalogStyleStore from '../../stores/use-catalog-style-store'; import useEditCommentPrivileges from '../../hooks/use-author-privileges'; import { useCommentMediaInfo } from '../../hooks/use-comment-media-info'; import useCountLinksInReplies from '../../hooks/use-count-links-in-replies'; import useFetchGifFirstFrame from '../../hooks/use-fetch-gif-first-frame'; import useHide from '../../hooks/use-hide'; import useWindowWidth from '../../hooks/use-window-width'; import useReplies from '../../hooks/use-replies'; import { ContentPreview } from '../../views/home/popular-threads-box'; import PostMenuDesktop from '../post-desktop/post-menu-desktop'; import styles from './catalog-row.module.css'; import _ from 'lodash'; import { selectPostMenuProps } from '../../lib/utils/post-menu-props'; interface CatalogPostMediaProps { cid: string; commentMediaInfo: any; isOutOfFeed?: boolean; linkWidth?: number; linkHeight?: number; } export const CatalogPostMedia = ({ cid, commentMediaInfo, linkWidth, linkHeight }: CatalogPostMediaProps) => { const { patternThumbnailUrl, thumbnail, type, url } = commentMediaInfo || {}; const iframeThumbnail = patternThumbnailUrl || thumbnail; const gifFrameUrl = useFetchGifFirstFrame(type === 'gif' ? url : undefined); const [isLoaded, setIsLoaded] = useState(false); const [hasError, setHasError] = useState(false); const handleLoad = () => setIsLoaded(true); const handleError = () => setHasError(true); const loadingStyle = { display: isLoaded ? 'block' : 'none' }; const { imageSize } = useCatalogStyleStore(); let displayWidth, displayHeight; const maxThumbnailSize = imageSize === 'Large' ? 250 : 150; if (linkWidth && linkHeight) { let scale = Math.min(1, maxThumbnailSize / Math.max(linkWidth, linkHeight)); displayWidth = `${linkWidth * scale}px`; displayHeight = `${linkHeight * scale}px`; } else { displayWidth = `${maxThumbnailSize}px`; displayHeight = `${maxThumbnailSize}px`; } if (type === 'audio') { displayWidth = 'unset'; displayHeight = 'unset'; } const maxWidth = imageSize === 'Large' ? '250px' : '150px'; const maxHeight = imageSize === 'Large' ? '250px' : '150px'; const CSSProperties = { '--width': displayWidth, '--height': displayHeight, '--maxWidth': maxWidth, '--maxHeight': maxHeight, } as React.CSSProperties; let thumbnailComponent: React.ReactNode = null; if (type === 'gif' && gifFrameUrl && !hasError) { thumbnailComponent = ; } else if (type === 'image' && !hasError) { thumbnailComponent = ; } else if (type === 'video' && !hasError) { thumbnailComponent = thumbnail ? ( ) : ( // show first frame of the video, as a workaround for Safari not loading thumbnails