import Link from "next/link"; import { ActionButton } from "@/components/ui/action-button"; import ActionConfirmingDialog from "@/components/ui/action-confirming-dialog"; import { Button } from "@/components/ui/button"; import { Collapsible, CollapsibleContent, CollapsibleTrigger, } from "@/components/ui/collapsible"; import FilePickerButton from "@/components/ui/file-picker-button"; import { toast } from "@/components/ui/use-toast"; import useUpload from "@/lib/hooks/upload-file"; import { Archive, Camera, ChevronsDownUp, Download, Image, Paperclip, Pencil, Plus, Trash2, } from "lucide-react"; import { useAttachBookmarkAsset, useDetachBookmarkAsset, useReplaceBookmarkAsset, } from "@hoarder/shared-react/hooks/bookmarks"; import { getAssetUrl } from "@hoarder/shared-react/utils/assetUtils"; import { BookmarkTypes, ZAssetType, ZBookmark, } from "@hoarder/shared/types/bookmarks"; import { humanFriendlyNameForAssertType, isAllowedToAttachAsset, isAllowedToDetachAsset, } from "@hoarder/trpc/lib/attachments"; export default function AttachmentBox({ bookmark }: { bookmark: ZBookmark }) { const typeToIcon: Record = { screenshot: , fullPageArchive: , bannerImage: , bookmarkAsset: , unknown: , }; const { mutate: attachAsset, isPending: isAttaching } = useAttachBookmarkAsset({ onSuccess: () => { toast({ description: "Attachment has been attached!", }); }, onError: (e) => { toast({ description: e.message, variant: "destructive", }); }, }); const { mutate: replaceAsset, isPending: isReplacing } = useReplaceBookmarkAsset({ onSuccess: () => { toast({ description: "Attachment has been replaced!", }); }, onError: (e) => { toast({ description: e.message, variant: "destructive", }); }, }); const { mutate: detachAsset, isPending: isDetaching } = useDetachBookmarkAsset({ onSuccess: () => { toast({ description: "Attachment has been detached!", }); }, onError: (e) => { toast({ description: e.message, variant: "destructive", }); }, }); const { mutate: uploadAsset } = useUpload({ onError: (e) => { toast({ description: e.error, variant: "destructive", }); }, }); bookmark.assets.sort((a, b) => a.assetType.localeCompare(b.assetType)); return ( Attachments {bookmark.assets.map((asset) => (
{typeToIcon[asset.assetType]}

{humanFriendlyNameForAssertType(asset.assetType)}

{isAllowedToAttachAsset(asset.assetType) && ( uploadAsset(file, { onSuccess: (resp) => { replaceAsset({ bookmarkId: bookmark.id, oldAssetId: asset.id, newAssetId: resp.assetId, }); }, }) } > )} {isAllowedToDetachAsset(asset.assetType) && ( ( detachAsset( { bookmarkId: bookmark.id, assetId: asset.id }, { onSettled: () => setDialogOpen(false) }, ) } > Delete )} > )}
))} {!bookmark.assets.some((asset) => asset.assetType == "bannerImage") && bookmark.content.type != BookmarkTypes.ASSET && ( uploadAsset(file, { onSuccess: (resp) => { attachAsset({ bookmarkId: bookmark.id, asset: { id: resp.assetId, assetType: "bannerImage", }, }); }, }) } > Attach a Banner )}
); }