import React, { useState, useEffect } from "react"; import { useTranslation } from "react-i18next"; import { X, ShieldAlert } from "lucide-react"; import { updateAnnotation, updateHighlight, updateBookmark, sessionAtom, getUserTags, getTrendingTags, } from "../../api/client"; import type { AnnotationItem, ContentLabelValue } from "../../types"; import TagInput from "../ui/TagInput"; const SELF_LABEL_VALUES: ContentLabelValue[] = [ "sexual", "nudity", "violence", "gore", "spam", "misleading", ]; const HIGHLIGHT_COLORS = [ { value: "yellow", bg: "bg-yellow-400", ring: "ring-yellow-500" }, { value: "green", bg: "bg-green-400", ring: "ring-green-500" }, { value: "blue", bg: "bg-blue-400", ring: "ring-blue-500" }, { value: "red", bg: "bg-red-400", ring: "ring-red-500" }, ]; interface EditItemModalProps { isOpen: boolean; onClose: () => void; item: AnnotationItem; type: "annotation" | "highlight" | "bookmark"; onSaved?: (item: AnnotationItem) => void; } export default function EditItemModal({ isOpen, onClose, item, type, onSaved, }: EditItemModalProps) { if (!isOpen) return null; return ( ); } function EditItemModalContent({ item, type, onClose, onSaved, }: Omit) { const { t } = useTranslation(); const [text, setText] = useState(item.body?.value || ""); const [tags, setTags] = useState(item.tags || []); const [tagSuggestions, setTagSuggestions] = useState([]); const [color, setColor] = useState(item.color || "yellow"); const [title, setTitle] = useState(item.title || item.target?.title || ""); const [description, setDescription] = useState(item.description || ""); const existingLabels = (item.labels || []) .filter((l) => l.src === item.author?.did) .map((l) => l.val as ContentLabelValue); const [selfLabels, setSelfLabels] = useState(existingLabels); const [showLabelPicker, setShowLabelPicker] = useState( existingLabels.length > 0, ); const [saving, setSaving] = useState(false); const [error, setError] = useState(null); useEffect(() => { const session = sessionAtom.get(); if (session?.did) { Promise.all([ getUserTags(session.did).catch(() => [] as string[]), getTrendingTags(50) .then((tags) => tags.map((t) => t.tag)) .catch(() => [] as string[]), ]).then(([userTags, trendingTags]) => { const seen = new Set(userTags); const merged = [...userTags]; for (const t of trendingTags) { if (!seen.has(t)) { merged.push(t); seen.add(t); } } setTagSuggestions(merged); }); } }, []); const toggleLabel = (val: ContentLabelValue) => { setSelfLabels((prev) => prev.includes(val) ? prev.filter((l) => l !== val) : [...prev, val], ); }; const handleSave = async () => { setSaving(true); setError(null); let success = false; const labels = selfLabels.length > 0 ? selfLabels : []; try { if (type === "annotation") { success = await updateAnnotation( item.uri, text, tags.length > 0 ? tags : undefined, labels, ); } else if (type === "highlight") { success = await updateHighlight( item.uri, color, tags.length > 0 ? tags : undefined, labels, ); } else if (type === "bookmark") { success = await updateBookmark( item.uri, title || undefined, description || undefined, tags.length > 0 ? tags : undefined, labels, ); } } catch (e) { console.error("Edit save error:", e); setError(e instanceof Error ? e.message : t("editItem.failedSave")); setSaving(false); return; } setSaving(false); if (!success) { setError(t("editItem.failedSave")); return; } const updated = { ...item }; if (type === "annotation") { updated.body = { type: "TextualBody", value: text, format: "text/plain" }; } else if (type === "highlight") { updated.color = color; } else if (type === "bookmark") { updated.title = title; updated.description = description; } updated.tags = tags; const otherLabels = (item.labels || []).filter( (l) => l.src !== item.author?.did, ); const newSelfLabels = selfLabels.map((val) => ({ val, src: item.author?.did || "", scope: "content" as const, })); updated.labels = [...otherLabels, ...newSelfLabels]; onSaved?.(updated); onClose(); }; return (
e.stopPropagation()} >

{type === "annotation" ? t("editItem.editAnnotation") : type === "highlight" ? t("editItem.editHighlight") : t("editItem.editBookmark")}

{type === "annotation" && (