mirror of
https://github.com/purrgrammer/grimoire.git
synced 2026-04-08 14:37:04 +02:00
8c9ecd574cb2f8a0a70371ec0b27bfeb98a565b9
* refactor(editor): replace DOM manipulation with React node views and floating-ui - Convert all inline node views (emoji, blob attachment, event preview) from imperative document.createElement() to React components via ReactNodeViewRenderer - Replace tippy.js with @floating-ui/react-dom for suggestion popup positioning - Create useSuggestionRenderer hook bridging Tiptap suggestion callbacks to React state - Extract shared EmojiMention, SubmitShortcut, and inline node extensions to separate files - Extract types (EmojiTag, BlobAttachment, SerializedContent) to editor/types.ts - Extract serialization logic to editor/utils/serialize.ts - Remove redundant DOM keydown listener from RichEditor (handled by SubmitShortcut extension) - Remove tippy.js dependency (-1045 lines net, RichEditor 632→297, MentionEditor 1038→354) https://claude.ai/code/session_01CzeTFzSETs9wSPH2feDE6u * fix(editor): fix suggestion popover positioning, scrolling, and profile click behavior - Replace UserName component in ProfileSuggestionList with plain text display so clicking a suggestion autocompletes instead of opening their profile (UserName has an onClick that calls addWindow and stopPropagation) - Add react-virtuoso to ProfileSuggestionList for efficient lazy rendering of up to 20 search results with fixed item height scrolling - Add profile avatars with lazy loading and initial-letter fallback - Fix SuggestionPopover positioning with autoUpdate for scroll/resize tracking - Add size middleware to constrain popover max-height to available viewport space https://claude.ai/code/session_01CzeTFzSETs9wSPH2feDE6u * refactor(editor): convert emoji suggestion from grid to scrollable list with Virtuoso Replace the 8-column grid layout with a vertical list matching the profile suggestion style — each row shows the emoji preview alongside its :shortcode: name. Uses react-virtuoso with fixedItemHeight for lazy rendering and smooth keyboard-driven scrolling through large emoji sets. https://claude.ai/code/session_01CzeTFzSETs9wSPH2feDE6u * fix(editor): set mentionSuggestionChar to ':' for emoji nodes When backspacing over a mention-based node, Tiptap inserts the node's mentionSuggestionChar attribute as undo text. The EmojiMention extension inherits Mention's default of '@', so deleting an emoji left '@' instead of ':'. Fix by explicitly setting mentionSuggestionChar: ':' in the emoji command's attrs for both RichEditor and MentionEditor. https://claude.ai/code/session_01CzeTFzSETs9wSPH2feDE6u * test(editor): add comprehensive test suite for custom TipTap extensions Tests all 8 custom extensions using headless TipTap Editor instances in jsdom environment (TipTap has no official testing package): - EmojiMention: schema, renderText (unicode vs custom), mentionSuggestionChar attribute handling, backspace behavior regression test - BlobAttachmentRichNode/InlineNode: schema (block vs inline), attributes, renderText URL serialization, parseHTML selectors - NostrEventPreviewRichNode/InlineNode: schema, renderText encoding for note/nevent/naddr back to nostr: URIs - SubmitShortcut: Mod-Enter always submits, Enter behavior with enterSubmits flag - FilePasteHandler: media type filtering (image/video/audio), non-media rejection, mixed paste filtering, edge cases (no files, no callback) - NostrPasteHandler: bech32 regex matching (npub/note/nevent/naddr/nprofile), nostr: prefix handling, URL exclusion, node creation (mention vs preview), surrounding text preservation, multiple entities - Serialization: formatBlobSize, serializeRichContent (emoji tag extraction, blob dedup, address refs), serializeInlineContent (mention→nostr: URI, emoji→shortcode, blob→URL, event preview encoding) 90 new tests total. https://claude.ai/code/session_01CzeTFzSETs9wSPH2feDE6u * fix(editor): paste handler and serialization bugs found via adversarial testing NostrPasteHandler fixes: - Punctuation after bech32 now matches (npub1..., npub1...! etc.) Changed trailing lookahead from (?=$|\s) to (?=$|\s|[.,!?;:)\]}>]) - Fixed double-space between entities — unconditional " " after every entity caused doubled spaces. Now only adds trailing space when entity is at the very end of pasted text (for cursor positioning). - Tightened regex character class from [\w] to [a-z0-9] to match actual bech32 charset (rejects uppercase, underscore) - Wrapped dispatch in try/catch to handle block-node-at-inline-position errors gracefully (falls back to default paste) Serialization fix: - serializeRichContent now guards blob collection with `url && sha256` matching the defensive checks already in serializeInlineContent. Previously null sha256 would corrupt the dedup Set and null url would produce invalid BlobAttachment entries. Added 22 new edge case tests: - Paste handler: punctuation boundaries, double-space regression, malformed bech32 fallback, uppercase rejection, error resilience - Serialization: empty editor, null sha256/url blobs, invalid pubkey fallback, missing mention attrs, inline dedup, multi-paragraph https://claude.ai/code/session_01CzeTFzSETs9wSPH2feDE6u * fix(editor): raise suggestion search limits for profiles and emojis Both suggestion dropdowns use Virtuoso for virtualized rendering, so they can handle large result sets without performance issues. The previous limits (20 profiles, 24 emojis) were too restrictive — users with many custom emojis sharing a substring or large contact lists couldn't scroll to find the right match. Raised both limits to 200 to allow thorough browsing while still bounding the result set. https://claude.ai/code/session_01CzeTFzSETs9wSPH2feDE6u * refactor(chat): rework emoji picker to scrollable list with search Replace the fixed 1-row grid (8 emojis) with a scrollable virtualized list matching the editor's EmojiSuggestionList look & feel: - Search box at top with magnifying glass icon - Virtuoso-backed scrollable list (8 visible items, unlimited results) - Each row shows emoji icon + :shortcode: label - Keyboard navigation: arrow keys to select, Enter to confirm - Mouse hover highlights, click selects - Frequently used emojis still shown first when no search query - Narrower dialog (max-w-xs) for a compact picker feel https://claude.ai/code/session_01CzeTFzSETs9wSPH2feDE6u * fix: add address field to EmojiTag in editor types, fix GroupMessageOptions - Add optional `address` field to EmojiTag in editor/types.ts to match NIP-30 changes from main (30030 emoji set address) - Extend GroupMessageOptions with MetaTagOptions to fix type error in GroupMessageBlueprint's setMetaTags call Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * fix(editor): restore address attr, fix serialization, UserName, no-scroll - Restore `address` attribute in shared EmojiMention extension (emoji.ts) that was dropped during refactor — required for NIP-30 emoji set tracking - Extract `address` from emoji nodes in both serializeRichContent and serializeInlineContent so it makes it into published events - Fix MentionEditorProps.onSubmit signature: use EmojiTag[] (not the narrower inline type) so address field flows through to callers - Restore UserName component in ProfileSuggestionList for proper display with Grimoire member badges and supporter flame - Remove scrollbar when all items fit: set overflow:hidden on Virtuoso when items.length <= MAX_VISIBLE (profile list, emoji list, emoji picker dialog) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> --------- Co-authored-by: Claude <noreply@anthropic.com>
…
…
…
…
Grimoire
A Nostr protocol explorer and developer tool with a tiling window manager interface.
Features
- Tiling Windows - Each window is a Nostr "app" (profile viewer, event feed, NIP docs, etc.)
- Command Palette - Unix-style commands via
Cmd+Kto open apps and navigate - Multi-workspace - Virtual desktops with independent layouts
- Real-time - Reactive event subscriptions with automatic updates
Stack
React 19, TypeScript, Vite, TailwindCSS, Jotai, Dexie, Applesauce
Getting Started
npm install
npm run dev
Scripts
| Command | Description |
|---|---|
npm run dev |
Start dev server |
npm run build |
Build for production |
npm test |
Run tests in watch mode |
npm run lint |
Lint code |
npm run format |
Format code |
License
MIT
Languages
TypeScript
98.9%
CSS
0.8%
JavaScript
0.3%