This repository has been archived on 2026-06-02. You can view files and clone it. You cannot open issues or pull requests or push a commit.
bvandeusen 0f05f47eef feat(design): foundation port — dusty violet, warm parchment, action tokens
Mirrors the web frontend's design-system foundation pass (shipped on web
2026-04-27 in 7a9a8b7) for the Flutter app. Single-file change to
lib/core/theme.dart — most widgets read colorScheme.primary so the
palette flip alone covers a large surface.

Palette swap
- dark: cool grey #0F0F14 / #16161F → Obsidian #14171A / Iron #1E2228
  with Slate #2C313A and Pewter #3F4651 borders; Parchment #E8E4D8
  primary text, Vellum #C2BFB4 secondary
- light: white-and-cool-blue → warm parchment #F5F1E8 page / #FBF8F0
  cards / #EFEAE0 inset; deep ink #14171A text; warm pewter #D9D6CE
  borders
- primary (both modes): indigo #7C3AED → dusty violet #5B4A8A
- error: indigo-red pair → terracotta #C04A1F (semantic Error per the
  doc; distinct from destructive Oxblood used for delete buttons)

Action token ThemeExtension
- New ActionColors extension exposes Moss / Bronze / Oxblood / Pewter
  outside the ColorScheme so widgets can read them via
  Theme.of(context).extension<ActionColors>()!.primary etc.
- Hybrid rule: ColorScheme.primary stays the dusty-violet brand accent
  (Send buttons, empty-state CTAs); action buttons (Save / Cancel /
  Delete / ghost) use the ActionColors palette. No widget refactors in
  this commit — extension is defined for surface-phase work to consume.

Typography
- Inter loaded for body / labels / titleMedium-and-below (was system
  default)
- Fraunces still loaded for display / headline / titleLarge — only at
  ≥18px per the doc rule
- JetBrains Mono available for code at call sites via
  GoogleFonts.jetBrainsMono() (Flutter has no mono TextTheme slot)

GradientButton
- Brand-moment CTA equivalent of the web's --gradient-cta. Colors
  swapped from indigo gradient to dusty-violet (#5B4A8A → #3F3560);
  glow shadow rgba updated to match.

Out of scope (deferred to later surface-phase work)
- Per-screen button reclassification (Save → Moss FilledButton, Delete
  → Oxblood, etc.) — the ActionColors extension exists, no widgets
  reach for it yet
- Lucide icon migration — separate task, requires picking a
  flutter_lucide / lucide_icons package
- Input border radius (currently 24 / pill, doc says 8) — leave for
  surface phase
- Voice/tone copy touchups
- Chat bubble Illuminated Transcript pattern (assistant left-edge
  accent + glow) — not yet ported to ChatMessageBubble

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-04-28 08:30:55 -04:00
2026-02-28 21:28:53 -05:00

Fabled — Android App

Native Android client for FabledAssistant, a self-hosted AI second-brain and productivity assistant.

Features

  • Daily Briefing — the primary screen; opens on launch. Shows your AI-compiled morning digest (tasks, calendar, weather, RSS) with a full conversation you can reply to inline. Refresh manually or browse past briefings from the overflow menu.
  • Quick Capture — always-visible input bar above all tabs. Type a note or task and submit; multiple captures queue sequentially so the input is never blocked. Falls back to offline persistence when the server is unreachable.
  • Knowledge — unified browsable feed of notes, people, places, lists, and tasks across six filter tabs. Tag filters, inline search (debounced), and two-tier pagination (ID list → batch hydration). Tasks load from /api/tasks directly and are fully integrated with the knowledge feed.
  • Chat — streaming AI conversations with real-time SSE display, including live tool-use status notifications (e.g. "Calling create_note…"). Tap + to start a new conversation or open an existing one.
  • Calendar — month strip + daily agenda view backed by the server's internal event store. Full event CRUD with a modal form: title, all-day toggle, start/end date+time pickers, repeat (None/Daily/Weekly/Monthly/Yearly), description, location, and colour chips. Custom RRULE strings are preserved read-only.
  • News — RSS article feed with per-feed filtering and reactions. Tap "Discuss" to open any article in a new chat conversation.
  • Projects — browse and edit projects; tap a project to see its milestone-grouped task list.
  • Voice I/O — tap the microphone in the capture bar or chat to dictate. Server-side STT transcribes audio; TTS reads assistant replies aloud in voice mode.
  • Note & task editing — full Markdown editor for notes, task editor with due date, priority, project, and milestone assignment.
  • OAuth / SSO — authenticates via your server's OIDC provider; local username/password login also supported if enabled server-side.
  • Session persistence — stays logged in across restarts via a persistent cookie jar.
  • Auto-refresh — data refreshes automatically when the app returns to the foreground (throttled to once per 5 minutes) and when switching between shell tabs.
  • Auto-update — checks your Forgejo releases on launch and prompts to download and install new APKs in-app.

Requirements

  • A running FabledAssistant server (self-hosted)
  • Android 5.0+ (API 21)

Getting Started

Prerequisites

  • Flutter 3.x SDK
  • Android Studio (for Android SDK and emulator)
  • JDK 17

Setup

flutter pub get
flutter run

On first launch, enter your FabledAssistant server URL (e.g. https://fabled.example.com) and sign in.

Architecture

lib/
├── main.dart                        # Entry point; resolves async deps before runApp
├── app.dart                         # GoRouter + auth guards + 3-tab shell + auto-refresh
├── core/
│   ├── constants.dart               # Route name constants
│   ├── exceptions.dart              # AppException hierarchy
│   └── theme.dart                   # Custom slate-indigo ColorScheme + Fraunces typography
├── data/
│   ├── api/                         # Dio HTTP layer (one class per resource)
│   │   ├── chat_api.dart            # SSE streaming; typed ChatStreamEvent (text/status)
│   │   ├── events_api.dart          # Calendar event CRUD
│   │   ├── knowledge_api.dart       # Two-tier paginated knowledge feed
│   │   ├── news_api.dart            # RSS feed + reactions
│   │   └── voice_api.dart           # STT + TTS endpoints
│   ├── models/                      # Plain Dart models with fromJson/toJson
│   │   ├── calendar_event.dart      # CalendarEvent + dateOnly() helper
│   │   ├── knowledge_item.dart      # KnowledgeItem (notes/tasks unified)
│   │   └── message.dart             # Chat message with streaming status
│   └── repositories/                # Thin wrappers over API classes
├── providers/                       # Riverpod providers (state + dependency wiring)
│   ├── briefing_provider.dart       # Today's briefing — optimistic UI, SSE, polling
│   ├── calendar_provider.dart       # CalendarNotifier: month navigation + event CRUD
│   ├── chat_provider.dart           # Conversations + streaming messages + status
│   ├── knowledge_provider.dart      # Two-tier pagination; delegates tasks to TasksApi
│   ├── news_provider.dart           # NewsNotifier + FeedsNotifier
│   └── capture_work_queue_provider.dart  # Sequential in-memory capture queue
├── screens/
│   ├── briefing/                    # BriefingScreen + BriefingHistoryScreen
│   ├── calendar/                    # CalendarScreen (TableCalendar) + EventFormSheet
│   ├── chat/                        # ConversationsTabScreen + ChatScreen
│   ├── knowledge/                   # KnowledgeScreen (6-tab feed + search + tag filters)
│   ├── library/                     # ProjectTasksScreen (milestone-grouped task list)
│   ├── news/                        # NewsScreen (feed filter + reactions + discuss)
│   ├── notes/                       # NoteDetailScreen + NoteEditScreen
│   ├── projects/                    # ProjectsScreen + ProjectEditScreen
│   ├── tasks/                       # TaskEditScreen
│   └── settings/ auth/ setup/ splash/
└── widgets/
    ├── chat_message_bubble.dart     # Shared bubble (Chat + Briefing); shows tool status
    ├── knowledge_item_card.dart     # Card for notes, people, places, lists, tasks
    ├── news_card.dart               # RSS article card with reactions
    └── voice_mic_button.dart        # Animated mic button (capture bar + chat)

Key packages: flutter_riverpod, go_router, dio + cookie_jar, google_fonts, flutter_markdown_plus, table_calendar, record, just_audio

Building a Release APK

flutter build apk --release

The APK will be at build/app/outputs/flutter-apk/app-release.apk.

CI / CD

CI and build are defined in a single workflow (.forgejo/workflows/ci.yml) running on the shared py3.12-node22 act runner with the ghcr.io/cirruslabs/flutter:stable container.

Trigger Analyze + Test Build APK Release
PR
Push dev ✓ (artifact fabledapp-dev-<sha>)
Push main
Tag v* ✓ (artifact fabledapp-<sha>) ✓ Forgejo Release + APK attached

The build job has needs: [analyze] — a failed analyze or test blocks the APK build.

To cut a release:

git tag v26.04.06 && git push origin v26.04.06

Requires a RELEASE_TOKEN secret (Forgejo PAT with write:repository scope) set in repo Settings → Secrets → Actions.

S
Description
mobile app to connect to the fabled assistant
Readme 2.6 MiB
Languages
Dart 87.9%
C++ 5.7%
CMake 4.2%
Swift 0.7%
Shell 0.5%
Other 1%