Commit Graph

3 Commits

Author SHA1 Message Date
Cursor Agent 61c78d0588 feat: table delete button, SSE status indicator, table editor UI polish
Five improvements:

1. Delete table button: A trash icon appears to the left of the edit
   pencil on rendered tables (on hover). Clicking it opens a confirmation
   dialog before removing the entire table from the memo content.

2. SSE connection status indicator: A small colored dot in the sidebar
   navigation (above the user menu) shows the live-refresh connection
   status:
   - Green = connected, live updates active
   - Yellow (pulsing) = connecting
   - Red = disconnected, updates not live
   Hover tooltip explains the current state. Uses useSyncExternalStore
   for efficient re-renders from a singleton status store.

3. Always-visible action buttons: Sort and delete buttons in the table
   editor are now always visible at 40% opacity (previously hidden until
   hover). They become fully opaque on hover for better discoverability.

4. Larger table editor dialog: Fixed size of 56rem x 44rem (capped to
   viewport) so the dialog is spacious regardless of table dimensions.
   The table area scrolls within the fixed frame.

5. Monospace font in table editor: All cell inputs use Fira Code with
   fallbacks to Fira Mono, JetBrains Mono, Cascadia Code, Consolas,
   and system monospace for better alignment when editing tabular data.

Co-authored-by: milvasic <milvasic@users.noreply.github.com>
2026-02-06 23:13:09 +00:00
Cursor Agent bab7a53d7a feat: extend live refresh to sync reactions across instances
Add SSE event broadcasting for reaction changes so that when a user
adds or removes a reaction on one device, all other open instances
see the update in real-time.

Backend:
- Rename MemoEvent/MemoEventType to SSEEvent/SSEEventType for generality
- Add reaction.upserted and reaction.deleted event types
- Broadcast events from UpsertMemoReaction and DeleteMemoReaction,
  using the reaction's ContentID (memo name) as the event name

Frontend:
- Handle reaction.upserted and reaction.deleted SSE events by
  invalidating the affected memo detail cache and memo lists
- Rename internal handler to handleSSEEvent to reflect broader scope

Co-authored-by: milvasic <milvasic@users.noreply.github.com>
2026-02-06 21:41:44 +00:00
Cursor Agent 8c743c72ba feat: add live memo refresh via Server-Sent Events (SSE)
Implement real-time memo synchronization across all open browser instances
using Server-Sent Events (SSE). When a memo is created, updated, or
deleted on one device, all other connected clients receive the change
notification and automatically refresh their data.

Backend changes:
- Add SSEHub (pub/sub) for broadcasting memo change events to connected clients
- Add SSE HTTP endpoint at /api/v1/sse with Bearer token authentication
  (supports both Authorization header and query parameter for EventSource)
- Broadcast memo.created, memo.updated, and memo.deleted events from
  the memo service after successful operations
- Include SSEHub in APIV1Service and wire it into server initialization
- Update test helper to include SSEHub to prevent nil pointer panics

Frontend changes:
- Add useLiveMemoRefresh hook that connects to SSE endpoint using fetch
  ReadableStream (supports custom auth headers unlike native EventSource)
- Automatically invalidate React Query caches on received events:
  - memo.created: invalidate memo lists + user stats
  - memo.updated: invalidate specific memo detail + memo lists
  - memo.deleted: remove memo from cache + invalidate lists + user stats
- Exponential backoff reconnection (1s to 30s) on connection failures
- Integrate hook in AppInitializer for app-wide live refresh
- Add SSE-specific Vite dev proxy config with no timeout for streaming

Co-authored-by: milvasic <milvasic@users.noreply.github.com>
2026-02-06 21:18:21 +00:00