Commit Graph

63 Commits

Author SHA1 Message Date
Claude
b5e1cffc91 fix: add EOSE indicator, mute all icons, and fix relay URL normalization bug
Critical fixes for ReqViewer relay state accuracy:

1. **URL Normalization Fix** (fixes mismatch with CONN):
   - Added normalizeRelayURL to normalize all relay URLs in finalRelays
   - RelayStateManager normalizes URLs (adds trailing slash, lowercase) but
     finalRelays did not, causing lookup failures in relayStates
   - Now normalizedRelays is used for all state lookups and passed to
     useReqTimelineEnhanced to ensure consistency
   - This fixes the bug where ReqViewer showed different connected relay
     counts than CONN viewer

2. **EOSE Indicator**:
   - Added back EOSE indicator to relay dropdown (was removed in UI redesign)
   - Shows subtle "EOSE" text when relay has sent End of Stored Events
   - Includes tooltip explaining "End of stored events received"

3. **Muted Icons** (per user request for subtlety):
   - Type indicators: blue-500/purple-500 → muted-foreground/60
   - Strategy header icons: all → muted-foreground/60
   - Section headers: green-500 → muted-foreground
   - Connection icons: green-500/yellow-500/red-500 → /70 opacity variants
   - Auth icons: same color reduction for consistency
   - Maintains semantic meaning while reducing visual noise

All 639 tests passing.
2025-12-22 17:53:24 +00:00
Claude
ce3a4a7322 fix: handle all relays disconnecting before EOSE (stuck in LOADING bug)
Critical Edge Case Fix:
Previously, when all relays disconnected before sending EOSE, the state
remained stuck in LOADING because overallEoseReceived stayed false.

Solution: Check if all relays are in terminal states
- Terminal states: eose, error, or disconnected
- If all terminal AND no overall EOSE yet, derive state from events:
  * No events → FAILED
  * Has events, all disconnected, streaming → OFFLINE
  * Has events, all disconnected, non-streaming → CLOSED
  * Some active, some terminal → PARTIAL

New Test Coverage (5 tests):
1. All relays disconnect before EOSE, no events → FAILED
2. All relays disconnect before EOSE, with events (streaming) → OFFLINE
3. All relays disconnect before EOSE, with events (non-streaming) → CLOSED
4. Some EOSE, others disconnect before EOSE → PARTIAL
5. Mix of EOSE and errors, all terminal → PARTIAL

This fixes the user-reported issue where disconnected relays show LOADING
instead of transitioning to appropriate terminal state.

Tests: 639/639 passing (added 5 new edge case tests)
2025-12-22 17:38:31 +00:00
Claude
1bb2727930 fix: remove unused variables and apply prettier formatting
- Remove unused connectedCount and relayStatesForReq variables
- Fix prettier formatting in ReqViewer.tsx
- All tests passing (634/634)
- Build successful
2025-12-22 16:25:42 +00:00
Claude
c60abe6df4 feat: implement production-grade REQ state machine with per-relay tracking
Core Infrastructure:
- Add ReqRelayState and ReqOverallState types for granular state tracking
- Implement deriveOverallState() state machine with 8 query states
- Create useReqTimelineEnhanced hook combining RelayStateManager + event tracking
- Add comprehensive unit tests (27 tests, all passing)

State Machine Logic:
- DISCOVERING: NIP-65 relay selection in progress
- CONNECTING: Waiting for first relay connection
- LOADING: Initial events loading
- LIVE: Streaming with active relays (only when actually connected!)
- PARTIAL: Some relays ok, some failed/disconnected
- OFFLINE: All relays disconnected after being live
- CLOSED: Query completed, all relays closed
- FAILED: All relays failed to connect

UI Updates:
- Single-word status indicators with detailed tooltips
- Condensed relay status into NIP-65 section (no duplicate lists)
- Per-relay subscription state badges (RECEIVING, EOSE, ERROR, OFFLINE)
- Event counts per relay
- Connection + Auth status integrated into single dropdown

Fixes Critical Bug:
- Solves "LIVE with 0 relays" issue (Scenario 5 from analysis)
- Distinguishes real EOSE from relay disconnections
- Accurate status for all 7 edge cases documented in analysis

Technical Approach:
- Hybrid: RelayStateManager for connections + event._relay for tracking
- Works around applesauce-relay catchError bug without forking
- No duplicate subscriptions
- Production-quality error handling

Tests: 27/27 passing including edge case scenarios
2025-12-22 16:18:15 +00:00
Alejandro Gómez
32c895e150 chore: lint fix 2025-12-22 13:25:38 +01:00
Claude
96216450f4 feat: add centralized nostr kind utilities
- Create src/lib/nostr-kinds.ts with:
  - Re-exports from nostr-tools/kinds (isRegularKind, isReplaceableKind, etc.)
  - New isParameterizedReplaceableKind() function
  - New isAddressableKind() for determining naddr vs nevent encoding
  - NIP-01 boundary constants with clarifying comments
  - getKindCategory() for display purposes

- Update KindRenderer.tsx to use shared utilities:
  - Replace inline range checks with helper functions
  - Fix "Regular Lists" -> "Replaceable Events" naming
  - Simplify redundant condition (isReplaceableKind includes kinds 0, 3)

- Update BaseEventRenderer.tsx to use isAddressableKind()

- Add comprehensive tests for all utilities
2025-12-22 11:58:46 +00:00
Alejandro Gómez
3346a2077d feat(req): add --view flag for list/compact display mode
- Add -v, --view <list|compact> flag to req command
- Remove UI toggle controls from ReqViewer header
- View mode is now set via command flag instead of runtime toggle
- Update man page with new flag documentation and example

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-21 20:29:32 +01:00
Alejandro Gómez
78a8c8e5b2 chore: apply prettier formatting fixes
🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-21 20:12:40 +01:00
Alejandro Gómez
f4d0e86f09 feat: complete spellbook UX overhaul with enhanced state tracking
- Redesign SpellbookDropdown with clear status indicators (ownership, storage)
- Add SpellbookStatus component showing you/other and local/published/network
- Enhance activeSpellbook type with source, localId, isPublished fields
- Fix PublishSpellbook action to properly yield events (caller handles side-effects)
- Add k tags extraction from REQ windows for kind-based filtering/discovery
- Update terminology from "Layout" to "Spellbook" consistently
- Add comprehensive tests for k tags and source tracking

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-21 19:19:24 +01:00
Alejandro Gómez
21335a5849 WIP 2025-12-21 18:08:10 +01:00
Alejandro Gómez
005605b385 feat: enhance preview route and add conflict resolution for spellbooks
Improve the preview route UX with better loading states, error handling, and metadata display. Add version comparison logic and conflict resolution dialog for handling local vs network spellbook conflicts.

Changes:
- Enhanced preview route in Home.tsx:
  - Add loading state with spinner while resolving actor
  - Add NIP-05 resolution timeout (10 seconds)
  - Display error banner for resolution failures
  - Show author name and creation date in preview banner
  - Add copy link button to share spellbook easily
  - Improve banner layout with metadata

- Add compareSpellbookVersions() in spellbook-manager.ts:
  - Detects conflicts between local and network versions
  - Compares timestamps, workspace counts, window counts
  - Identifies newer version and content differences
  - Returns structured comparison data

- Create ConflictResolutionDialog component:
  - Side-by-side comparison of local vs network versions
  - Shows metadata: timestamps, counts, author, publish status
  - Clear explanation of resolution choices
  - Accessible UI with proper button hierarchy

TypeScript compilation successful 

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-21 18:08:10 +01:00
Alejandro Gómez
d59a7aee8b feat: improve spellbook UX with active tracking and update capability
- Add activeSpellbook to GrimoireState
- Display active spellbook title in header with clear button
- Add 'Update Layout' and 'Save as new' to SpellbookDropdown
- Highlight active spellbook in dropdown list
- Add 'Manage Spells' link to dropdown
- Refine dropdown styles (muted hover, no accent color)
2025-12-21 18:08:10 +01:00
Alejandro Gómez
1836deee6c feat: add wallet status indicator and replace layout on apply
- Add WalletStatus component to TabBar
- Change loadSpellbook to replace current workspaces instead of merging
- Update SpellbooksViewer toast message
2025-12-21 18:07:55 +01:00
Alejandro Gómez
5d9ff3cf56 feat: implement Nostr Wallet Connect (NWC)
- Add applesauce-wallet-connect dependency
- Create WalletService for managing NWC connection
- Create WalletViewer component for UI
- Register 'wallet' command
- Fix build errors in spell/spellbook components due to applesauce-actions upgrade
2025-12-21 18:07:55 +01:00
Claude
a34fa2becd fix: apply linter formatting and fix useMemo dependencies 2025-12-21 14:28:12 +00:00
Claude
1519e30e5c feat: add repository state (kind 30618) visualization
Implement renderers for NIP-34 repository state announcements:
- Add helper functions in nip34-helpers.ts to parse HEAD refs, branches, and tags
- Create RepositoryStateRenderer for compact feed view showing push notifications
- Create RepositoryStateDetailRenderer for detailed view with all refs
- Register both renderers in the kind registry

Feed view shows: "pushed <commit> to <branch> in <repo>"
Detail view shows: HEAD info, all branches, all tags with copyable commit hashes
2025-12-21 12:35:23 +00:00
Alejandro Gómez
2987a37e65 feat: spells 2025-12-20 14:25:40 +01:00
Alejandro Gómez
812b719ea0 feat: debug command, simplify state 2025-12-18 23:32:00 +01:00
Alejandro Gómez
3f45cebaee feat: more flexible -e flag 2025-12-18 17:08:11 +01:00
Alejandro Gómez
f6f813d382 refactor: collapse migrations 2025-12-18 16:49:24 +01:00
Alejandro Gómez
f283ef6208 docs: improve 2025-12-18 16:25:34 +01:00
Alejandro Gómez
a6650ff6e1 fix: type errors 2025-12-18 16:00:56 +01:00
Alejandro Gómez
5cc97484b5 fix: improved balanced window algo 2025-12-18 15:45:34 +01:00
Alejandro Gómez
3fba62b316 ui: simpler streams 2025-12-18 15:29:01 +01:00
Alejandro Gómez
b57ff31907 feat: balance layout and kbd workspace navigation 2025-12-18 13:47:40 +01:00
Alejandro Gómez
1581e313f3 test: add comprehensive tests for grid layouts with odd numbers
Verify that grid preset correctly handles uneven window counts:
- 2 windows → 1×2 grid
- 3 windows → 1×3 single row
- 4 windows → 2×2 perfect grid
- 5 windows → 2×3 grid (last row expands to fill)
- 7 windows → 2×4 grid (last row expands)
- 9 windows → 3×3 perfect grid
- 11 windows → 3×4 grid (last row expands)

Key behaviors verified:
- No empty space (last row windows expand to 100% width)
- All windows preserved in layout
- Window order maintained (depth-first traversal)
- Works with any N ≥ 2 windows

Also tests:
- Side-by-side with 2-4 windows (and error for 5+)
- Main + Sidebar with various window counts
- Error handling for too few/many windows

All 22 tests pass ✓

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2025-12-18 13:20:38 +01:00
Alejandro Gómez
dd40a5baca feat: make layout presets adaptive to all windows
Major redesign of preset system from static templates to adaptive algorithms:

**Grid preset** (fully adaptive):
- Now arranges ALL windows in best-fit grid (2x2, 2x3, 3x3, etc.)
- Minimum: 2 windows (down from 4)
- Algorithm calculates optimal rows/cols for any N windows
- Examples:
  * 4 windows → 2×2 grid
  * 6 windows → 2×3 grid
  * 9 windows → 3×3 grid

**Side-by-side preset** (adaptive with limit):
- Arranges 2-4 windows in single horizontal row
- Maximum 4 windows (prevents unusably narrow splits)
- Equal splits: 50%, 33%, 25%
- Clear error message if >4 windows

**Main + Sidebar preset** (unchanged):
- Already worked correctly (intentionally hierarchical)
- One main window (70%) + sidebars stacked (30%)
- Adapts naturally to any N ≥ 2 windows

Architecture changes:
- Replace static MosaicNode templates with generate() functions
- Add minSlots/maxSlots instead of single slots field
- Implement buildHorizontalRow(), buildVerticalStack(), buildGridLayout()
- Remove fillLayoutTemplate() (no longer needed)
- Remove extra window stacking (all windows now equal)

Benefits:
- No arbitrary hierarchy (no "featured" vs "extra" windows)
- Matches tiling window manager patterns (Amethyst, yabai, etc.)
- More intuitive: "grid" grids ALL windows, not just first 4
- Better UX: Works with any number of windows in range

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2025-12-18 13:14:35 +01:00
Alejandro Gómez
f2599772f6 fix(ui): reorganize bottom bar and clarify preset requirements
Changes:
- Added TODO comment about IndexedDB unavailability in test runtime
- Moved layout preset selector to rightmost side of bottom bar
- Moved window settings button to rightmost side as well
- Removed per-workspace settings icon (now global button on right)
- Added spacer to separate workspace tabs from layout controls
- Changed preset descriptions to show "4+ windows" instead of "4 windows"
  to clarify that presets work with more windows than the minimum
- Changed dropdown alignment from "start" to "end" for right-aligned opening

The bottom bar now has clearer visual separation:
[Workspace Tabs] [+] ................ [Layout Presets] [Settings]

Generated with [Claude Code](https://claude.com/claude-code)
2025-12-18 12:27:54 +01:00
Alejandro Gómez
4db7e9690c refactor(layouts): simplify to global config + preserve windows + add UI dropdown
Simplified layout system based on user feedback:

**1. Global Layout Config (Simpler)**
- Moved layoutConfig from per-workspace to global state
- One configuration applies to all workspaces (easier to understand)
- Updated state migration v8→v9 to move config to global level
- Updated WorkspaceSettings UI to edit global config
- Renamed updateWorkspaceLayoutConfig → updateLayoutConfig

**2. Preserve Extra Windows (Fixed Bug)**
- Fixed applyPresetToLayout to keep windows beyond preset slots
- When applying 4-window grid to 6 windows, windows 5-6 are preserved
- Extra windows stacked vertically on right side (70/30 split)
- No more window loss when applying presets

**3. Layout Dropdown in TabBar (Better UX)**
- Added dropdown menu next to workspace tabs
- Shows all available presets with icons (Grid2X2, Columns2, Split)
- Displays window requirements and availability
- Disables presets that need more windows than available
- One-click preset application with toast feedback
- More accessible than /layout command

All tests passing (457 passed). State migration handles v6→v7→v8→v9 correctly.

Generated with [Claude Code](https://claude.com/claude-code)
2025-12-18 12:24:00 +01:00
Alejandro Gómez
52f39a8073 feat: add layout presets system with /layout command
Phase 3 implementation:
- Created layout-presets.ts with 3 built-in presets (side-by-side, main-sidebar, grid)
- Implemented fillLayoutTemplate() for recursive template filling with window IDs
- Added collectWindowIds() for depth-first traversal of layout trees
- Created applyPresetToLayout() to reorganize existing windows

- Created layout-parser.ts for /layout command argument parsing
- Added layout command to man.ts with documentation and examples

- Built LayoutViewer component with:
  * Visual preset gallery with diagrams
  * Window count validation
  * Apply preset functionality
  * Error handling for insufficient windows
  * Command-line preset specification support

- Wired LayoutViewer into WindowRenderer with lazy loading
- Added "layout" to AppId type definition
- Exposed applyPresetLayout in useGrimoire hook

Presets allow users to quickly reorganize multiple windows into
common layouts: 50/50 splits, 70/30 main+sidebar, or 2×2 grids.

Generated with [Claude Code](https://claude.com/claude-code)
2025-12-18 12:13:28 +01:00
Alejandro Gómez
cc6f8d646b feat(layouts): Phase 1 - workspace layout configuration system
Add per-workspace layout configuration with smart auto-balancing:

**Core Changes:**
- Add LayoutConfig interface to Workspace type with insertionMode, splitPercentage, insertionPosition
- Create layout-utils.ts with smart direction algorithm that auto-balances horizontal/vertical splits
- Update addWindow() to use workspace layoutConfig instead of hardcoded values
- Migrate state from v7→v8, adding layoutConfig to all workspaces with smart defaults

**Smart Direction Algorithm:**
- Analyzes layout tree to count horizontal vs vertical splits
- Automatically balances by favoring the less-common direction
- Defaults to horizontal (row) for first split
- Provides foundation for "Balanced (auto)" insertion mode

**Testing:**
- Add 30 comprehensive tests for layout-utils.ts (tree analysis, smart direction, window insertion)
- Add 30 tests for logic.ts addWindow() with different layout configs (row/column/smart modes)
- Update migration tests to verify v6→v7→v8 and v7→v8 paths

**Migration:**
- v7→v8 adds layoutConfig with defaults: smart mode, 50% split, second position
- All existing workspaces automatically get smart auto-balancing behavior

Implements orthogonal design: layout behavior = workspace settings (not command flags)
2025-12-18 11:59:45 +01:00
Alejandro Gómez
a066284825 chore: petrify 2025-12-18 10:19:52 +01:00
Alejandro Gómez
a7dd4635dc feat: kind schemas and better man pages 2025-12-18 10:18:53 +01:00
Alejandro Gómez
97c89142ae wip: live video events 2025-12-17 11:44:12 +01:00
Alejandro Gómez
63121f6233 feat: add title command line flag 2025-12-16 20:50:03 +01:00
Alejandro Gómez
6126f43e34 ui: aspect ratios, url styles in auth prompt 2025-12-16 17:28:50 +01:00
Alejandro Gómez
24d2640774 feat: since and until 2025-12-16 14:15:16 +01:00
Alejandro Gómez
6f05f414d3 feat: case insensitive names 2025-12-16 00:07:20 +01:00
Alejandro Gómez
f4a0d5e669 feat: -P filter tag 2025-12-15 23:42:19 +01:00
Alejandro Gómez
390290d2eb wip: skeletons 2025-12-15 22:19:28 +01:00
Alejandro Gómez
5dd885b888 feat: community NIPs 2025-12-15 15:42:11 +01:00
Alejandro Gómez
19cdde0110 feat: syntax highlighting 2025-12-15 13:11:59 +01:00
Alejandro Gómez
dab250260f fix: PR body rendering 2025-12-15 11:36:06 +01:00
Alejandro Gómez
c8a6bfacf4 feat: basic git stuff rendering 2025-12-14 23:57:17 +01:00
Alejandro Gómez
9496af6273 feat: better generic event detail relay list and JSON viewer 2025-12-14 16:41:43 +01:00
Alejandro Gómez
e5c871617e chore: cleanup, a11y and state migrations 2025-12-14 16:32:45 +01:00
Alejandro Gómez
6f17415340 feat: NIPS command 2025-12-14 15:14:14 +01:00
Alejandro Gómez
b8d05e40c7 feat: export to JSONL 2025-12-14 12:21:09 +01:00
Alejandro Gómez
bef7369de9 fix: normalize relay URLs 2025-12-14 12:00:55 +01:00
Alejandro Gómez
c21df2b420 ui: friendlier req viewer 2025-12-14 00:07:06 +01:00