Files
client/plans/event-management-edit-repost.md
2026-04-17 16:52:51 -04:00

6.0 KiB

Event Management: Edit & Repost Feature

Overview

Add the ability to edit and repost events from the Event Detail panel in event-management.html. The raw JSON in #preEventJson becomes an editable <textarea>, and for encrypted events, the decrypted content in #preDecryptedContent also becomes an editable <textarea>. On repost, the page re-encrypts (if needed), re-signs, and publishes the updated event.

Current Architecture

flowchart TD
    A[Select event in middle column] --> B[renderDetail populates preEventJson]
    B --> C{isLikelyEncryptedEvent?}
    C -- yes --> D[autoDecryptDetailEvent]
    D --> E[Display decrypted text in preDecryptedContent]
    C -- no --> F[Show 'Content does not appear encrypted']

Proposed Architecture

flowchart TD
    A[Select event in middle column] --> B[renderDetail populates txtEventJson textarea]
    B --> C{isLikelyEncryptedEvent?}
    C -- yes --> D[autoDecryptDetailEvent]
    D --> E[Display decrypted text in txtDecryptedContent textarea - editable]
    C -- no --> F[Show 'Content does not appear encrypted' - textarea hidden/readonly]

    G[User clicks 'Edit & Repost'] --> H{Was content encrypted?}
    H -- yes --> I[Read txtDecryptedContent plaintext]
    I --> J[Detect original encryption method - NIP-04 or NIP-44]
    J --> K[Re-encrypt plaintext using same method + peer pubkey]
    K --> L[Inject encrypted content into event JSON]
    H -- no --> L
    L --> M[Parse txtEventJson to get kind, tags, content]
    M --> N[Build unsigned event with fresh created_at]
    N --> O[publishEvent via NDK worker - auto-signs]
    O --> P[Update UI: status message, refresh kind list]

Detailed Changes

1. HTML: Convert <pre> elements to <textarea> elements

File: event-management.html

  • Replace <pre id="preEventJson"> (line 294) with <textarea id="txtEventJson"> styled identically (monospace, same border/background)
  • Replace <pre id="preDecryptedContent"> (line 296) with <textarea id="txtDecryptedContent"> styled identically
  • Add an "Edit & Repost" button to the existing .btnRow in the detail panel (line 287-293), next to the existing buttons

2. CSS: Style the new textareas

  • Add styles for #txtEventJson and #txtDecryptedContent that match the existing #preEventJson / #preDecryptedContent styles
  • Both textareas should be resizable vertically, use monospace font, and have the same border/background treatment
  • The decrypted textarea should be visually distinct when editable vs when showing non-encrypted placeholder text

3. JavaScript: Track encryption metadata

When autoDecryptDetailEvent succeeds, store the encryption context so we can re-encrypt on repost:

  • lastDecryptResult — object storing { method: 'NIP-04'|'NIP-44', peerPubkey: string, plaintext: string } from the last successful decrypt
  • Reset this to null whenever a new event is selected or when no encryption is detected

4. JavaScript: Wire up the Edit & Repost button

The btnEditRepost click handler:

  1. Parse the JSON from txtEventJson.value — extract kind, tags, content
  2. Check if decrypted content was edited:
    • If lastDecryptResult is set (event was encrypted) AND txtDecryptedContent.value differs from lastDecryptResult.plaintext:
      • Re-encrypt using the detected method:
        • NIP-04: await window.nostr.nip04.encrypt(peerPubkey, newPlaintext)
        • NIP-44: await window.nostr.nip44.encrypt(peerPubkey, newPlaintext)
      • Replace the content field in the parsed JSON with the new ciphertext
    • If the user edited the raw JSON content field directly (and it differs from the original), use that as-is (user is responsible for providing valid ciphertext or plaintext)
  3. Build the unsigned event:
    const draft = {
      kind: parsedEvent.kind,
      created_at: Math.floor(Date.now() / 1000),
      tags: parsedEvent.tags,
      content: finalContent
    };
    
  4. Publish via publishEvent(draft) — the NDK worker handles signing automatically
  5. Update UI:
    • Show status in divKindsStatus
    • Optionally refresh the kind from relays to see the new event appear
    • Update currentDetailEvent and re-render

5. JavaScript: Update element references

  • Update all references from preEventJsontxtEventJson and preDecryptedContenttxtDecryptedContent
  • Update renderDetail() to set .value instead of .textContent
  • Update setDecryptedOutput() to set .value instead of .textContent
  • Update btnCopyEventJson handler to read from .value

6. JavaScript: Confirmation dialog

Before publishing, show a window.confirm() dialog:

  • For encrypted events: "Re-encrypt and publish updated event (kind X)?"
  • For non-encrypted events: "Publish updated event (kind X) with fresh timestamp?"

7. Edge Cases

  • Non-replaceable kinds (kind 1, etc.): Publishing creates a brand new event. The confirm dialog should warn that this creates a new event, not a replacement.
  • Replaceable kinds (0, 3, 10000-19999): Publishing with same pubkey supersedes the old one automatically.
  • Parameterized replaceable kinds (30000-39999): Must preserve the d tag to replace the correct event.
  • Missing signer: If window.nostr.signEvent is unavailable, show an error.
  • Encryption unavailable: If the event was NIP-44 encrypted but window.nostr.nip44.encrypt is missing, show an error before attempting.
  • Parse errors: If the user enters invalid JSON in the textarea, catch and display the error.

Files Modified

File Changes
event-management.html HTML: swap <pre><textarea>, add Edit & Repost button. CSS: textarea styles. JS: new button handler, updated element refs, encryption tracking

No New Files

All changes are contained within the single event-management.html file since the page is self-contained with inline <script> and <style>.