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>
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>
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>