import type { ReactNode } from "react" import { Copy, Trash2, X } from "lucide-react" import type { ValueOf } from "@/types/utils" import { AlbumSource } from "#/types/cloudAlbum" import { CloudImportStatus } from "./cloud-import-status" import { AlbumDeleteDialog } from "./album-delete-dialog" import { AlbumInspectorDetails } from "./album-inspector-details" import { Button } from "@/components/ui/button" import { ScrollArea } from "@/components/ui/scroll-area" import { CloudImage } from "@/components/common/cloud-image" import { FloatingPanelSheetContent } from "@/components/common/floating-panel-sheet-content" import { Sheet, SheetDescription, SheetTitle } from "@/components/ui/sheet" import { cn } from "@/lib/utils" import { useTranslation } from "react-i18next" import { toast } from "sonner" import { albumAdapter } from "@/adapters/album" import { AlbumUrlRewriteDialog, type AlbumUrlRewriteChange, } from "./album-url-rewrite-dialog" import { AlbumSingleUrlInput } from "./album-single-url-input" import type { AlbumPhoto } from "./utils" import { getAlbumImageUrl } from "./utils" const INSPECTOR_ACTION_BUTTON_VARIANT = { DEFAULT: "default", DESTRUCTIVE: "destructive", } as const type InspectorActionButtonVariant = ValueOf type AlbumInspectorProps = { isOpen: boolean onOpenChange: (open: boolean) => void selectedIds: number[] selectedImages: AlbumPhoto[] // TODO(v3-post-launch): Restore tag + collection props when Gallery Tags/Collections UI returns. // selectedTags: string[] // collections: string[] // tagSuggestions: string[] // tagInput: string // onTagInputChange: (value: string) => void // onTagSubmit: () => void // onAddTag: (tag: string) => void // onRemoveTag: (tag: string) => void // onCollectionChange: (value: string) => void onDelete: () => Promise onPreviewOpen: (imageId: number) => void onUrlRewrite: (changes: AlbumUrlRewriteChange[]) => void albumSource?: AlbumSource } function InspectorActionButton({ icon, label, variant = INSPECTOR_ACTION_BUTTON_VARIANT.DEFAULT, disabled = false, onClick, }: { icon: ReactNode label: string variant?: InspectorActionButtonVariant disabled?: boolean onClick?: () => void }) { return ( ) } export function AlbumInspector({ isOpen, onOpenChange, selectedIds, selectedImages, // TODO(v3-post-launch): Restore tag + collection prop wiring when Gallery Tags/Collections UI returns. // selectedTags, // collections, // tagSuggestions, // tagInput, // onTagInputChange, // onTagSubmit, // onAddTag, // onRemoveTag, // onCollectionChange, onDelete, onPreviewOpen, onUrlRewrite, albumSource: _albumSource, }: AlbumInspectorProps) { const { t } = useTranslation() const canAct = selectedImages.length > 0 const handleCopy = async () => { if (!canAct) return try { const copiedLinks = await Promise.all( selectedImages.map(async (image) => { return albumAdapter.copyImageLink(image.raw) }) ) albumAdapter.copyBatchLinks(copiedLinks) toast.success( selectedImages.length > 1 ? t("BATCH_COPY_LINK_SUCCEED") : t("COPY_LINK_SUCCEED") ) } catch (error) { console.error("[Inspector] copy failed:", error) toast.error(t("OPERATION_FAILED")) } } // TODO(v3-post-launch): Restore inspector single/batch download handler when download action returns. // const handleDownload = () => { // if (!canAct) return // selectedImages.forEach((image, index) => { // const downloadUrl = getAlbumImageUrl(image) // const link = document.createElement("a") // link.href = downloadUrl // link.download = image.name || `image-${index + 1}` // link.rel = "noreferrer" // link.target = "_blank" // document.body.appendChild(link) // link.click() // link.remove() // }) // } return ( {t("ALBUM_INSPECTOR_TITLE")} {t("ALBUM_INSPECTOR_DESCRIPTION")}
{t("ALBUM_SELECTED_COUNT", { count: selectedIds.length, })}
} label={t("COPY")} onClick={handleCopy} /> {/* TODO(v3-post-launch): Restore inspector download action when feature scope is re-enabled. } label={t("ALBUM_EXPORT")} onClick={handleDownload} /> */} } label={t("DELETE")} variant="destructive" disabled={!canAct} /> } />
{selectedImages.length > 1 ? (
{selectedImages.slice(0, 4).map((image, index) => { const isOverflow = index === 3 && selectedImages.length > 4 return ( ) })}
) : selectedImages.length === 1 ? ( ) : (
{t("ALBUM_SELECTED_COUNT", { count: 0 })}
)}
{t("ALBUM_URL")}
{selectedIds.length === 1 ? ( selectedImages[0] ? ( ) : null ) : ( )}
{/* TODO(v3-post-launch): Restore collection editor in inspector when Collections feature returns.
{t("ALBUM_COLLECTION")}
*/} {_albumSource === AlbumSource.LOCAL && selectedImages.length > 0 ? ( ) : null} {selectedImages.length === 1 && selectedImages[0] ? ( ) : null} {/* TODO(v3-post-launch): Restore tags editor in inspector when Tags feature returns.
{t("ALBUM_TAGS")}
{selectedTags.length === 0 ? (
{t("ALBUM_TAG_SUGGESTIONS")}
) : ( selectedTags.map((tag) => ( #{tag} )) )}
{tagSuggestions.map((tag) => ( ))}
onTagInputChange(event.target.value)} onKeyDown={(event) => { if (event.key === "Enter") { event.preventDefault() onTagSubmit() } }} placeholder={t("ALBUM_ADD_TAG")} />
*/}
) }