docs: fabled app overhaul design spec

This commit is contained in:
2026-03-11 22:18:59 -04:00
parent ef4872e24a
commit 3bd9c64477
@@ -0,0 +1,253 @@
# Fabled App Overhaul — Design Spec
**Date:** 2026-03-11
**Project:** `/home/bvandeusen/Nextcloud/Projects/fabled_app`
## Goal
Reposition the Flutter Android app from a general-purpose mirror of the web app into a focused mobile companion: the Daily Briefing is the primary experience, Quick Capture is the secondary utility, and Notes/Tasks/Projects are a browsable library — secondary to both.
---
## Navigation & Shell
Three-tab shell replacing the current four-tab (Notes · Tasks · Projects · Chat) structure.
| Tab | Icon | Screen | Route |
|-----|------|--------|-------|
| Briefing | `Icons.wb_sunny_outlined` / `Icons.wb_sunny` | `BriefingScreen` | `/briefing` |
| Library | `Icons.library_books_outlined` / `Icons.library_books` | `LibraryScreen` | `/library` |
| Chat | `Icons.chat_bubble_outline` / `Icons.chat_bubble` | `ConversationsListScreen` (inline) | `/conversations` |
The `_QuickCaptureBar` remains pinned above the shell on all three tabs. The settings icon stays in the capture bar row.
**Briefing is the initial route** — the app opens directly to the briefing tab on every launch.
**Wide layout (≥ 600dp):** `NavigationRail` on the left (as today), same 3 destinations.
### Dead Code Removed
**Screens deleted:**
- `lib/screens/notes/notes_list_screen.dart`
- `lib/screens/tasks/tasks_list_screen.dart`
- `lib/screens/projects/project_list_screen.dart`
- `lib/screens/chat/conversations_list_screen.dart`
- `lib/screens/quick_capture/quick_capture_screen.dart`
**Screens kept:**
- `lib/screens/notes/note_detail_screen.dart`
- `lib/screens/notes/note_edit_screen.dart`
- `lib/screens/tasks/task_edit_screen.dart`
- `lib/screens/chat/chat_screen.dart`
- All auth, settings, setup, splash screens
---
## Theme
Custom `ColorScheme` matching the main web app's "Illuminated Transcript" palette, in `lib/core/theme.dart`. System light/dark preference respected.
### Dark theme
| Token | Value |
|-------|-------|
| `background` | `#111113` |
| `surface` | `#18181c` |
| `primary` | `#6366f1` |
| `onSurface` | `#e8e8f0` |
| `onSurfaceVariant` (muted) | `#8888a8` |
### Light theme
| Token | Value |
|-------|-------|
| `background` | `#f4f4f8` |
| `surface` | `#ffffff` |
| `primary` | `#4f46e5` |
| `onSurface` | `#18181c` |
| `onSurfaceVariant` (muted) | `#6b6b88` |
### Typography
- Add `google_fonts` to `pubspec.yaml`
- `headlineMedium`, `titleLarge`, `titleMedium``GoogleFonts.fraunces()`
- Body styles → system default (unchanged)
### Buttons & Cards
- Primary action buttons: `BoxDecoration` with `LinearGradient(135°, #6366f1, #4f46e5)`; applied to send buttons in capture bar and briefing reply bar
- Cards: `borderRadius: 14`, subtle elevation shadow, no explicit border
---
## BriefingScreen
**File:** `lib/screens/briefing/briefing_screen.dart`
The app's primary screen. Opens on launch.
### Layout
```
AppBar:
title: "Briefing" (Fraunces)
subtitle: today's date ("Wednesday, March 11")
actions: [↻ refresh button]
Body (scrollable column):
┌─ DigestCard ──────────────────────┐
│ ☀ Good morning — Mar 11 │
│ [first assistant message, │
│ truncated to 5 lines] │
│ [Show more ↓] │
└───────────────────────────────────┘
─── Conversation ───
[scrollable message list]
[streaming bubble while generating]
Bottom pinned:
[ Reply to your briefing… ] [➤]
```
### Digest Card
- Extracted widget: `lib/widgets/briefing_digest_card.dart`
- Shows the content of the first `assistant` message from today's conversation
- Truncated to 5 lines by default; `[Show more]` expands with `AnimatedSize`
- If no briefing exists yet: "No briefing yet today" placeholder + "Generate now" button
### Conversation
- Message bubbles reuse the same widget used in `ChatScreen`; extracted to `lib/widgets/chat_message_bubble.dart` (shared between both screens)
- User messages: right-aligned, primary colour container
- Assistant messages: left-aligned, surface container with left accent border (indigo, 2dp)
- Streaming: a streaming bubble appears at the bottom of the list while SSE is active
### Reply Bar
- Always visible (pinned to bottom, above system nav bar)
- Send button: indigo gradient, disabled when input is empty or streaming
- Submitting a reply uses the existing SSE chat endpoint with today's briefing `conversation_id`
### Overflow Menu (`···`)
- "View past briefings" → pushes `BriefingHistoryScreen` (simple date list, read-only — no reply bar)
### Refresh Button
- Calls `POST /api/briefing/trigger` with `{"slot": "compilation"}`
- Shows `CircularProgressIndicator` in the AppBar while in-flight
- Reloads conversation on completion
### New Files
- `lib/screens/briefing/briefing_screen.dart`
- `lib/screens/briefing/briefing_history_screen.dart`
- `lib/widgets/briefing_digest_card.dart`
- `lib/widgets/chat_message_bubble.dart` (extracted from ChatScreen)
- `lib/data/api/briefing_api.dart``getToday()`, `getMessages(id)`, `triggerSlot(slot)`
- `lib/data/models/briefing_conversation.dart``id`, `briefingDate`, `title`, `messages`
- `lib/providers/briefing_provider.dart``briefingTodayProvider` (AsyncNotifier)
---
## LibraryScreen
**File:** `lib/screens/library/library_screen.dart`
Unified browsing screen for notes, tasks, and projects.
### Layout
```
AppBar:
title: "Library"
actions: [🔍 search icon → expands inline search bar]
Filter pills (scrollable horizontal row):
[All] [Notes] [Tasks] [Projects]
Content:
Unified list sorted by updated_at desc
Each item: LibraryItemCard
FAB:
[+] → bottom sheet: "New note" | "New task"
```
### Filter Pills
| Pill | Content | Extra controls |
|------|---------|----------------|
| All | Notes + tasks interleaved | — |
| Notes | Notes only | — |
| Tasks | Tasks only | Secondary status row: Todo · In Progress · Done · All |
| Projects | Project cards | — |
### Item Cards (`lib/widgets/library_item_card.dart`)
- **Note:** title (Fraunces medium), 1-line body snippet, tag chips, relative timestamp
- **Task:** status checkbox (tappable → cycles `todo → in_progress → done` via `PATCH /api/tasks/:id/status`), title, due date, priority dot (high = red, medium = amber)
- **Project:** left colour strip matching project colour, title, active task count, milestone progress bar
### Search
- Tapping 🔍 slides an `AnimatedContainer` search bar into the AppBar
- Searches title + body across notes and tasks via `GET /api/notes?q=` (respects active filter pill)
- Dismisses with Escape / back gesture
### FAB
- Bottom sheet with two large tap targets: "New note" → `NoteEditScreen`, "New task" → `TaskEditScreen`
### New Files
- `lib/screens/library/library_screen.dart`
- `lib/widgets/library_item_card.dart`
---
## Quick Capture Queue
The `_QuickCaptureBar` in `app.dart` is updated to support multiple in-flight captures queued sequentially.
### Behaviour
- Input **never disables** while the worker is active (only disables on offline — existing behaviour)
- Submitting appends text to the work queue; the worker drains it one item at a time
- Each completion fires a snackbar (`"Note created: …"`)
- Queue depth > 0: prefix icon shows a badge `⋯ N`
- Worker active: a 2dp `LinearProgressIndicator` in indigo animates below the capture bar
### Implementation
- New `lib/providers/capture_work_queue_provider.dart``CaptureWorkQueueNotifier` (in-memory `List<String>` + async drain loop)
- Separate from the existing `captureQueueProvider` (which handles offline persistence); the two queues are distinct:
- **Work queue:** in-memory, drains sequentially while online
- **Offline queue:** persisted to SharedPreferences, drained on reconnect
- Network errors during work queue drain fall through to offline queue (existing logic)
---
## Files Created / Modified Summary
**New:**
- `lib/core/theme.dart`
- `lib/screens/briefing/briefing_screen.dart`
- `lib/screens/briefing/briefing_history_screen.dart`
- `lib/screens/library/library_screen.dart`
- `lib/widgets/briefing_digest_card.dart`
- `lib/widgets/chat_message_bubble.dart`
- `lib/widgets/library_item_card.dart`
- `lib/data/api/briefing_api.dart`
- `lib/data/models/briefing_conversation.dart`
- `lib/providers/briefing_provider.dart`
- `lib/providers/capture_work_queue_provider.dart`
**Modified:**
- `lib/app.dart` — new 3-tab shell, new routes, updated `_QuickCaptureBar`
- `lib/main.dart` — import `theme.dart`
- `lib/screens/chat/chat_screen.dart` — extract bubble widget
- `pubspec.yaml` — add `google_fonts`
**Deleted:**
- `lib/screens/notes/notes_list_screen.dart`
- `lib/screens/tasks/tasks_list_screen.dart`
- `lib/screens/projects/project_list_screen.dart`
- `lib/screens/chat/conversations_list_screen.dart`
- `lib/screens/quick_capture/quick_capture_screen.dart`
---
## Out of Scope
- iOS support — Android only, as today
- Workspace view — web-only feature
- Graph view — web-only feature
- Note editing from Library (tap → NoteDetailScreen → edit button, as today)
- Push notification handling in-app — handled by the OS notification tray