'use client'; import { memo, type ReactNode } from 'react'; import { Download, Image as ImageIcon, Loader2, Play, Trash2, Volume2 } from 'lucide-react'; import { Button } from '@/components/ui/button'; import { Badge } from '@/components/ui/badge'; import { DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuTrigger, } from '@/components/ui/dropdown-menu'; import { cn } from '@/lib/utils'; import type { AssetDownloadPreference, VideoAsset } from '@/components/video-page/types'; interface AssetListSectionProps { assets: VideoAsset[]; isLoadingAssets: boolean; focusedAssetId: string | null; bunnyProcessingByAssetId: Record; bunnyReadyByAssetId: Record; activeDownloadAssetId: string | null; deletingAssetIds: string[]; canDownloadAssets: boolean; hasMoreAssets: boolean; isLoadingMoreAssets: boolean; onViewAsset: (asset: VideoAsset) => void; onDownloadAsset: (asset: VideoAsset, preference?: AssetDownloadPreference) => void; onDeleteAsset: (assetId: string) => void; onLoadMoreAssets: () => void; renderAssetPreview: (asset: VideoAsset) => ReactNode; } /** * Three shapes of download. A Bunny video offers the original or the compressed * rendition; a voice note offers WAV (converted in the browser, because no * editing suite opens the WebM/Opus we store) or the file as recorded; * everything else is a single button. */ function AssetDownloadControl({ asset, isBusy, onDownloadAsset, }: { asset: VideoAsset; isBusy: boolean; onDownloadAsset: (asset: VideoAsset, preference?: AssetDownloadPreference) => void; }) { const options: { preference: AssetDownloadPreference; label: string; hint?: string }[] = asset.provider === 'BUNNY' && asset.kind !== 'AUDIO' ? [ { preference: 'original', label: 'Original' }, { preference: 'compressed', label: 'Compressed' }, ] : asset.provider === 'R2_AUDIO' ? [ { preference: 'wav', label: 'WAV', hint: 'for editing software' }, { preference: 'original', label: 'Original' }, ] : []; if (options.length === 0) { return ( ); } return ( {options.map((option) => ( onDownloadAsset(asset, option.preference)} > {option.label} {option.hint && ( {option.hint} )} ))} ); } export const AssetListSection = memo(function AssetListSection({ assets, isLoadingAssets, focusedAssetId, bunnyProcessingByAssetId, bunnyReadyByAssetId, activeDownloadAssetId, deletingAssetIds, canDownloadAssets, hasMoreAssets, isLoadingMoreAssets, onViewAsset, onDownloadAsset, onDeleteAsset, onLoadMoreAssets, renderAssetPreview, }: AssetListSectionProps) { if (isLoadingAssets) { return (
Loading assets...
); } if (assets.length === 0) { return (
No assets uploaded yet.
); } return (
{assets.map((asset) => { const isBunnyProcessing = asset.provider === 'BUNNY' && !!bunnyProcessingByAssetId[asset.id] && !bunnyReadyByAssetId[asset.id]; return (

{asset.displayName}

{isBunnyProcessing ? ( Processing ) : null}

{asset.uploadedByUser?.name || asset.uploadedByGuestName || 'Unknown'} •{' '} {new Date(asset.createdAt).toLocaleDateString()}

{canDownloadAssets && asset.provider !== 'YOUTUBE' && ( )} {asset.canDelete && ( )}
); })} {hasMoreAssets ? ( ) : null}
); });