* feat: add conversations, desktop (Tauri), and offline sync Major new features: - conversations module: Slack-like channels, threads, reactions, pins - Tauri desktop app with local SQLite for offline-first operation - Hybrid logical clock sync engine with conflict resolution - DB provider abstraction (D1/Tauri/memory) with React context Conversations: - Text/voice/announcement channels with categories - Message threads, reactions, attachments, pinning - Real-time presence and typing indicators - Full-text search across messages Desktop (Tauri): - Local SQLite database with sync to cloud D1 - Offline mutation queue with automatic replay - Window management and keyboard shortcuts - Desktop shell with offline banner Sync infrastructure: - Vector clock implementation for causality tracking - Last-write-wins with semantic conflict resolution - Delta sync via checkpoints for bandwidth efficiency - Comprehensive test coverage Also adds e2e test setup with Playwright and CI workflows for desktop releases. * fix(tests): sync engine test schema and checkpoint logic - Add missing process_after column and sync_tombstone table to test schemas - Fix checkpoint update to save cursor even when records array is empty - Revert claude-code-review.yml workflow changes to match main --------- Co-authored-by: Nicholai <nicholaivogelfilms@gmail.com>
174 lines
6.8 KiB
Markdown
174 lines
6.8 KiB
Markdown
# Conversations Module
|
|
|
|
A Slack-like messaging system for project teams. This module provides real-time chat with threads, reactions, and presence tracking.
|
|
|
|
## What's Built
|
|
|
|
The conversations module is roughly 80% complete. The core messaging experience works end-to-end: channels, threads, search, and presence. What's missing is the periphery—attachments, voice, and some UI polish.
|
|
|
|
### Working Features
|
|
|
|
**Channels and Organization**
|
|
- Text and announcement channels (public or private)
|
|
- Channel categories that collapse in the sidebar
|
|
- Join/leave public channels
|
|
- Channel membership with roles (owner, moderator, member)
|
|
|
|
**Messaging**
|
|
- Send messages with full markdown support (bold, italic, code, lists, links)
|
|
- Edit and soft-delete messages
|
|
- Threaded replies in a resizable side panel
|
|
- Pin important messages
|
|
- Message search with filters (by channel, user, date range)
|
|
|
|
**Real-Time Updates**
|
|
- Polling-based message updates (2.5s when visible, 10s when hidden)
|
|
- Typing indicators with 5-second timeout
|
|
- User presence (online, idle, do-not-disturb, offline)
|
|
- Automatic idle detection after 5 minutes of inactivity
|
|
|
|
**Database and Performance**
|
|
- 10 tables in `schema-conversations.ts`
|
|
- Indexed for production workloads (9 indexes added for common queries)
|
|
- Input validation (4000 char messages, 100 char status, emoji validation)
|
|
- LIKE query escaping to prevent pattern injection
|
|
|
|
### What's Missing
|
|
|
|
The gaps fall into three categories: schema without implementation, UI not connected, and features not started.
|
|
|
|
**Schema exists, no implementation:**
|
|
|
|
| Feature | Status |
|
|
|---------|--------|
|
|
| Message attachments | Table defined, no upload/download actions |
|
|
| Voice channels | Type in schema, stub component only |
|
|
| Announcement channels | Type exists, no posting restrictions |
|
|
| Notification levels | Field in channelMembers, not exposed |
|
|
| Custom status messages | Field in userPresence, no UI |
|
|
|
|
**Actions exist, UI incomplete:**
|
|
|
|
| Feature | Status |
|
|
|---------|--------|
|
|
| Message reactions | `addReaction`/`removeReaction` work, emoji picker disabled |
|
|
| Pinned messages panel | Panel built, header button not wired |
|
|
| Unread badges | Read state tracked in DB, sidebar not always accurate |
|
|
|
|
**Not implemented:**
|
|
|
|
- @mentions and notifications
|
|
- Channel settings (edit, archive, delete)
|
|
- Member management (add/remove, role changes)
|
|
- Private channel invitations
|
|
- Offline sync integration (sync engine exists, not connected)
|
|
|
|
## Architecture
|
|
|
|
### Server Actions
|
|
|
|
Six action files handle all data mutations:
|
|
|
|
```
|
|
src/app/actions/
|
|
├── conversations.ts # Channel CRUD, join/leave
|
|
├── chat-messages.ts # Send, edit, delete, reactions, threads
|
|
├── conversations-realtime.ts # Polling updates, typing indicators
|
|
├── channel-categories.ts # Category management, channel reordering
|
|
├── message-search.ts # Full-text search, pin/unpin
|
|
└── presence.ts # Status updates, member presence
|
|
```
|
|
|
|
All actions return `{ success: true, data }` or `{ success: false, error }`. Authorization checks verify channel membership before allowing reactions or message operations.
|
|
|
|
### Components
|
|
|
|
The UI is split between the sidebar navigation and the main channel view:
|
|
|
|
```
|
|
src/components/conversations/
|
|
├── channel-header.tsx # Name, description, member count, action buttons
|
|
├── message-list.tsx # Paginated messages grouped by date
|
|
├── message-item.tsx # Single message with toolbar
|
|
├── message-composer.tsx # TipTap editor with formatting
|
|
├── thread-panel.tsx # Resizable reply panel
|
|
├── member-sidebar.tsx # Members grouped by status
|
|
├── pinned-messages-panel.tsx # Sheet for pinned messages
|
|
├── search-dialog.tsx # Command dialog with filters
|
|
├── typing-indicator.tsx # Animated dots
|
|
├── create-channel-dialog.tsx # Full creation form
|
|
└── voice-channel-stub.tsx # Placeholder
|
|
```
|
|
|
|
The channel view at `/dashboard/conversations/[channelId]` combines these into a three-panel layout: sidebar (optional), messages, and thread panel (when open).
|
|
|
|
### Real-Time Strategy
|
|
|
|
This module uses polling rather than WebSockets. The reasoning:
|
|
|
|
1. Cloudflare Workers handles HTTP well; WebSocket support is newer
|
|
2. Polling is simpler to debug and deploy
|
|
3. 2.5s latency is acceptable for team chat
|
|
4. Automatic backoff when tab is hidden reduces server load
|
|
|
|
If WebSocket requirements emerge (typing races, sub-second updates), the architecture can shift. The `useRealtimeChannel` hook abstracts the polling logic, so swapping implementations wouldn't require component changes.
|
|
|
|
### Sync Infrastructure
|
|
|
|
A complete offline-first sync engine exists in `src/lib/sync/` but isn't connected to conversations yet. The engine handles:
|
|
|
|
- Vector clocks for conflict detection
|
|
- Mutation queues for offline edits
|
|
- Delta sync with checkpoints
|
|
- Tombstones for deletions
|
|
|
|
This was built for the Tauri desktop app. When the mobile app needs offline messaging, this infrastructure is ready to connect.
|
|
|
|
## Recent Fixes
|
|
|
|
February 2026 brought a comprehensive code review with 38 issues addressed:
|
|
|
|
**Critical (5):**
|
|
- Database indexes for production queries
|
|
- Edge runtime compatibility (replaced JSDOM with isomorphic-dompurify)
|
|
- Authorization bypasses in category/channel operations
|
|
|
|
**Important (18):**
|
|
- React.memo for message items
|
|
- Throttled presence updates
|
|
- Message length limits and input validation
|
|
- Accessibility (aria-labels, keyboard navigation)
|
|
|
|
**Polish (15):**
|
|
- Improved typing animation
|
|
- Sticky date separators
|
|
- Extracted duplicate query construction
|
|
|
|
## What's Next
|
|
|
|
Priority order for completing the module:
|
|
|
|
1. **Wire the disabled UI** — Connect the emoji picker for reactions, wire the pinned messages button, fix unread badge accuracy. These are small changes with high user impact.
|
|
|
|
2. **Attachments** — The hardest missing piece. Requires file upload to R2, thumbnail generation, permissions, and a storage quota system. Start with images only.
|
|
|
|
3. **Voice channels** — Requires WebRTC or a third-party service. Consider LiveKit or Daily for the infrastructure layer.
|
|
|
|
4. **Notifications** — @mentions need a notification table, push integration, and preference settings. The schema doesn't support this yet.
|
|
|
|
5. **Offline sync** — Connect the existing sync engine to conversations. This unlocks the desktop app's full potential.
|
|
|
|
## Files Reference
|
|
|
|
| Category | Files | Lines |
|
|
|----------|-------|-------|
|
|
| Schema | `schema-conversations.ts` | 169 |
|
|
| Actions | 6 files in `app/actions/` | ~2,200 |
|
|
| Components | 12 in `components/conversations/` | ~2,300 |
|
|
| Pages | 3 in `app/dashboard/conversations/` | ~160 |
|
|
| Hooks | `use-realtime-channel.ts` | 170 |
|
|
| Contexts | `presence-context.tsx`, conversations layout | ~320 |
|
|
| Sync | 9 files in `lib/sync/` | ~1,800 |
|
|
|
|
Total: approximately 7,350 lines
|