From 1ba19ef3de55b5a947637d77afa0ecd5320df60c Mon Sep 17 00:00:00 2001 From: Silberengel Date: Fri, 22 May 2026 10:13:27 +0200 Subject: [PATCH] fix 30817 and allow full kind edits on new pots Make advanced editor to include tag editos Get rid of json editing --- .../AdvancedEventLabDialog.tsx | 65 ++-- .../AdvancedEventLabTagsEditor.tsx | 143 ++++++++ src/components/KindFilter/index.tsx | 2 +- src/components/Note/Highlight/index.tsx | 2 +- src/components/Note/index.tsx | 4 +- .../NoteOptions/EditOrCloneEventDialog.tsx | 32 +- src/components/NoteOptions/useMenuActions.tsx | 6 +- src/components/PostEditor/PostContent.tsx | 322 +++++++++++------- .../PostEditor/PostTextarea/Preview.tsx | 18 +- .../PostEditor/PostTextarea/index.tsx | 152 +-------- src/components/ReplyNoteList/index.tsx | 2 +- src/components/WebPreview/index.tsx | 6 +- src/constants.ts | 15 +- src/i18n/locales/cs.ts | 8 +- src/i18n/locales/de.ts | 8 +- src/i18n/locales/en.ts | 25 +- src/i18n/locales/es.ts | 8 +- src/i18n/locales/fr.ts | 8 +- src/i18n/locales/nl.ts | 8 +- src/i18n/locales/pl.ts | 8 +- src/i18n/locales/ru.ts | 8 +- src/i18n/locales/tr.ts | 8 +- src/i18n/locales/zh.ts | 8 +- src/lib/advanced-event-lab-slice.ts | 4 + src/lib/composer-extra-tags.test.ts | 26 ++ src/lib/composer-extra-tags.ts | 25 ++ src/lib/draft-event.ts | 13 +- src/lib/kind-description.ts | 4 +- src/lib/link.ts | 2 +- src/lib/markup-detection.ts | 2 +- src/lib/merged-search-note-preview.ts | 2 +- src/lib/nostr-spec-affected-kinds.test.ts | 24 ++ src/lib/nostr-spec-affected-kinds.ts | 20 ++ src/lib/read-aloud.ts | 2 +- src/pages/secondary/NotePage/index.tsx | 10 +- src/services/client-events.service.ts | 2 +- src/services/indexed-db.service.ts | 4 +- src/services/local-storage.service.ts | 6 +- src/services/mention-event-search.service.ts | 2 +- 39 files changed, 628 insertions(+), 386 deletions(-) create mode 100644 src/components/AdvancedEventLab/AdvancedEventLabTagsEditor.tsx create mode 100644 src/lib/composer-extra-tags.test.ts create mode 100644 src/lib/composer-extra-tags.ts create mode 100644 src/lib/nostr-spec-affected-kinds.test.ts create mode 100644 src/lib/nostr-spec-affected-kinds.ts diff --git a/src/components/AdvancedEventLab/AdvancedEventLabDialog.tsx b/src/components/AdvancedEventLab/AdvancedEventLabDialog.tsx index 01a95769..696d2bdb 100644 --- a/src/components/AdvancedEventLab/AdvancedEventLabDialog.tsx +++ b/src/components/AdvancedEventLab/AdvancedEventLabDialog.tsx @@ -53,6 +53,12 @@ import { useTranslation } from 'react-i18next' import { toast } from 'sonner' import { AdvancedEventLabMarkupToolbar } from './AdvancedEventLabMarkupToolbar' import { AdvancedEventLabPreviewPane } from './AdvancedEventLabPreviewPane' +import AdvancedEventLabTagsEditor, { + editableRowsToLabTags, + labTagsToEditableRows +} from './AdvancedEventLabTagsEditor' +import { newComposerTagRow, type ComposerExtraTagRow } from '@/lib/composer-extra-tags' +import { stripImwaldAttributionTags } from '@/lib/draft-event' import customEmojiService from '@/services/custom-emoji.service' import postEditorCache from '@/services/post-editor-cache.service' import type { TEmoji } from '@/types' @@ -182,8 +188,7 @@ export type AdvancedEventLabDialogProps = { formatToolbar?: ReactNode /** * When set, lab markup/tags are debounced to the post-editor draft store (same persistence as TipTap) - * so a **reload** can restore in-progress lab work. Closing without Apply (dismiss actions, including the cancel button, Escape, overlay) - * clears this draft so the next open is seeded from TipTap again. + * so a **reload** can restore in-progress lab work. The draft is kept on dismiss; clear happens on publish or composer Clear. */ draftPersistenceKey?: string | null /** Lab preview: resolve custom `:shortcode:` from this author's NIP-30 inventory when tags do not define them. */ @@ -239,13 +244,12 @@ export default function AdvancedEventLabDialog({ const labPersistTimerRef = useRef | null>(null) const previewDebounceTimerRef = useRef | null>(null) const schedulePreviewUpdateRef = useRef<(text: string) => void>(() => {}) - /** When true, closing is from Apply (draft already cleared); skip discard cleanup. */ - const skipClearLabDraftOnCloseRef = useRef(false) /** Debounce writes to the draft map; pagehide/beforeunload flush immediately to disk. */ const LAB_DRAFT_DEBOUNCE_MS = 500 const [previewDoc, setPreviewDoc] = useState('') const [labBodyTab, setLabBodyTab] = useState<'edit' | 'preview'>('edit') + const [labTagRows, setLabTagRows] = useState(() => [newComposerTagRow()]) /** Stable while payload matches; avoids remounting the editor when the parent passes a new `initial` object reference. */ const labEditorMountFingerprint = @@ -358,21 +362,14 @@ export default function AdvancedEventLabDialog({ const handleDialogOpenChange = useCallback( (next: boolean) => { if (!next) { - if (!skipClearLabDraftOnCloseRef.current) { - if (labPersistTimerRef.current) { - clearTimeout(labPersistTimerRef.current) - labPersistTimerRef.current = null - } - const key = draftPersistenceKeyRef.current - if (key) { - postEditorCache.clearAdvancedLabDraft(key) - } + const key = draftPersistenceKeyRef.current + if (key) { + flushLabDraftNow(key, true) } - skipClearLabDraftOnCloseRef.current = false } onOpenChange(next) }, - [onOpenChange] + [onOpenChange, flushLabDraftNow] ) const scheduleLabDraftPersist = useCallback(() => { @@ -395,6 +392,18 @@ export default function AdvancedEventLabDialog({ }, LAB_DRAFT_DEBOUNCE_MS) }, []) + const syncLabTagsFromRows = useCallback( + (rows: ComposerExtraTagRow[]) => { + setLabTagRows(rows) + const s = sliceRef.current + if (!s) return + s.tags = editableRowsToLabTags(rows) + scheduleLabDraftPersist() + bumpUndoUi() + }, + [scheduleLabDraftPersist, bumpUndoUi] + ) + const restoreSliceInEditor = useCallback( (slice: AdvancedEventLabSlice) => { const v = markupView.current @@ -403,7 +412,13 @@ export default function AdvancedEventLabDialog({ changes: { from: 0, to: v.state.doc.length, insert: slice.content }, selection: EditorSelection.cursor(0) }) - sliceRef.current = cloneLabSlice(slice) + const editable = stripImwaldAttributionTags(slice.tags) + sliceRef.current = { + kind: slice.kind, + content: slice.content, + tags: editable.map((row) => [...row]) + } + setLabTagRows(labTagsToEditableRows(editable)) setPreviewDoc(slice.content) scheduleLabDraftPersist() if (isLanguageToolConfigured()) requestAdvancedLabGrammarLint(v) @@ -614,12 +629,14 @@ export default function AdvancedEventLabDialog({ destroyEditors() + const editableTags = stripImwaldAttributionTags(initial.tags) const baseSlice: AdvancedEventLabSlice = { kind: initial.kind, content: initial.content, - tags: initial.tags.map((row) => [...row]) + tags: editableTags.map((row) => [...row]) } sliceRef.current = baseSlice + setLabTagRows(labTagsToEditableRows(editableTags)) setPreviewDoc(baseSlice.content) const markupLang: Extension = @@ -799,13 +816,14 @@ export default function AdvancedEventLabDialog({ const payload: AdvancedEventLabSlice = { kind, content, - tags: s.tags.map((row) => [...row]) + tags: editableRowsToLabTags(labTagRows) } - skipClearLabDraftOnCloseRef.current = true - onApply(payload) - if (draftPersistenceKeyRef.current) { - postEditorCache.clearAdvancedLabDraft(draftPersistenceKeyRef.current) + const key = draftPersistenceKeyRef.current + if (key) { + postEditorCache.setAdvancedLabDraft(key, payload) + postEditorCache.flushPersist() } + onApply(payload) if (undoSessionId) { clearLabCheckpointsSession(undoSessionId) labCheckpointsRef.current = [] @@ -947,7 +965,8 @@ export default function AdvancedEventLabDialog({
{formatToolbar}
) : null} -
+
+