import * as React from "react" import { ClipboardCopyIcon, CloudUploadIcon, CopyIcon, FolderIcon, FolderInputIcon, HeartIcon, InfoIcon, LinkIcon, PencilIcon, Trash2Icon, UploadIcon, } from "@workspace/ui/components/icon" import { useTranslate } from "@workspace/i18n" import { ContextMenu, ContextMenuContent, ContextMenuGroup, ContextMenuItem, ContextMenuLabel, ContextMenuSeparator, ContextMenuSub, ContextMenuSubContent, ContextMenuSubTrigger, ContextMenuTrigger, } from "@workspace/ui/components/context-menu" import { useMedia } from "./context" import { mediaMessages } from "./messages" import type { MediaAsset, MediaFolder, MediaId, MediaStorageTarget, } from "./types" import { formatMediaFileSize, getMediaFolderPath } from "./utils" export interface MediaContextMenuProps { asset?: MediaAsset children: React.ReactElement folders: readonly MediaFolder[] storageTargets: readonly MediaStorageTarget[] onDelete: (asset: MediaAsset) => void onDetails: (asset: MediaAsset) => void onFavorite: (asset: MediaAsset) => void onMove: (asset: MediaAsset, folderId: MediaId | null) => void onRename: (asset: MediaAsset) => void onUpload: (target: MediaStorageTarget) => void } function runAfterClose(action: VoidFunction) { window.setTimeout(action) } export function MediaContextMenu({ asset, children, folders, storageTargets, onDelete, onDetails, onFavorite, onMove, onRename, onUpload, }: MediaContextMenuProps) { const { adapter, notify } = useMedia() const t = useTranslate() const resolveUrl = React.useCallback( (item: MediaAsset) => adapter.resolveUrl?.(item) ?? item.url, [adapter] ) const localTargets = storageTargets.filter( (target) => target.kind === "local" ) const cloudTargets = storageTargets.filter( (target) => target.kind === "cloud" ) const copy = async (text: string, successMessage: string) => { try { await navigator.clipboard.writeText(text) notify?.({ message: successMessage, tone: "success" }) } catch { notify?.({ message: t(mediaMessages.copyFailed), tone: "error" }) } } return ( {asset ? ( <> runAfterClose(() => onDetails(asset))} > {t(mediaMessages.details)} onFavorite(asset)}> {asset.favorite ? t(mediaMessages.unfavorite) : t(mediaMessages.favoriteAction)} {t(mediaMessages.moveToFolder)} onMove(asset, null)} > {t(mediaMessages.unclassified)} {folders.map((folder) => ( onMove(asset, folder.id)} > {getMediaFolderPath(folder, folders)} ))} runAfterClose(() => onRename(asset))} > {t(mediaMessages.rename)} void copy(asset.name, t(mediaMessages.copyName))} > {t(mediaMessages.copyName)} void copy(resolveUrl(asset), t(mediaMessages.copyLink)) } > {t(mediaMessages.copyLink)} void copy( [ `${t(mediaMessages.fileName)}: ${asset.name}`, `${t(mediaMessages.type)}: ${asset.mimeType}`, `${t(mediaMessages.size)}: ${formatMediaFileSize(asset.sizeBytes)}`, `${t(mediaMessages.uploadedAt)}: ${new Date(asset.createdAt).toLocaleString()}`, `${t(mediaMessages.copyLink)}: ${resolveUrl(asset)}`, ].join("\n"), t(mediaMessages.copyInformation) ) } > {t(mediaMessages.copyInformation)} runAfterClose(() => onDelete(asset))} > {t(mediaMessages.delete)} ) : ( )} ) } function UploadItems({ cloudTargets, localTargets, onUpload, }: { cloudTargets: readonly MediaStorageTarget[] localTargets: readonly MediaStorageTarget[] onUpload: (target: MediaStorageTarget) => void }) { const t = useTranslate() return ( <> {localTargets.map((target) => ( ))} {cloudTargets.length > 1 ? ( <> {localTargets.length > 0 && } {t(mediaMessages.chooseStorage)} {cloudTargets.map((target) => ( ))} ) : ( cloudTargets.map((target) => ( )) )} ) } function UploadTargetItem({ target, onUpload, }: { target: MediaStorageTarget onUpload: (target: MediaStorageTarget) => void }) { const t = useTranslate() return ( onUpload(target)}> {target.kind === "local" ? : } {target.kind === "local" ? t(mediaMessages.serverUpload) : `${t(mediaMessages.cloudUpload)}: ${target.label}`} ) }