Commit Graph

5 Commits

Author SHA1 Message Date
bvandeusen 6ef658558a feat(offline): tier 2 phase 1 — Drift cache + read-through for notes
First slice of the tier 2 offline mode work tracked in Fable #147.
Notes are the only domain wired so far; this PR establishes the
shape and proves the round-trip end-to-end before extending to tasks
/ projects / events / etc. in phase 2.

Local store
- Adds drift ^2.20.0 + sqlite3_flutter_libs ^0.5.24 + path ^1.9.0
  runtime deps and drift_dev / build_runner dev deps.
- New lib/data/local/database.dart: FabledDatabase with CachedNotes
  (mirroring the Note model 1:1; tags stored as JSON-encoded text) and
  SyncMetadata (per-domain last_synced_at). Database file lives at
  $appDocs/fabled_cache.sqlite; opened lazily in a background isolate.
- fabledDatabaseProvider on the existing api_client_provider; closes
  the DB when the ProviderScope disposes.

Repository pattern
- NotesRepository now takes (NotesApi, FabledDatabase). Reads attempt
  the network first; on success the response is written to the cache.
  On NetworkException reads fall back to the cache (rethrowing if it
  is empty so fresh-install offline still surfaces the network error).
- Writes (create/update/delete) hit the server then sync the cache;
  offline write queueing is phase 3 and explicitly not wired here.
- AuthStatus.offline stays owned by AuthNotifier.verify()'s heartbeat;
  this repo deliberately doesn't poke that state.

OfflineBanner
- Reads notesRepository.lastSyncedAt(); when present, swaps
  "Offline — showing cached data." for "Offline — last sync X min
  ago." A 30s timer refreshes the relative-time string while the
  banner is mounted.
- Falls back to the generic message if no cache exists yet (fresh
  install offline).

Verification
- flutter analyze: No issues found

Out of scope (later phases per the task body)
- Tasks / projects / milestones / events / conversation list / journal
  day caching (phase 2 — same wrapper pattern, repeated)
- Generic write queue with conflict resolution on updated_at (phase 3)
- Read-only UI indicators on screens that depend on cached data
  (phase 4)
- Full offline chat (out of scope; needs a local model)
- RAG / search over cached content (out of scope)

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-04-28 21:08:06 -04:00
bvandeusen fc6c9648f9 fix(voice): eliminate dual-recorder conflict and defunct element crashes
VadHandler is now the sole mic owner — removed separate AudioRecorder that
caused audio focus contention on Android. Audio from onSpeechEnd is encoded
as WAV for Whisper. Provider switched to autoDispose to match widget lifecycle,
preventing defunct element assertions. Recording UI deferred until mic is open.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-17 08:04:03 -04:00
bvandeusen 79dce1a01c feat: wire discuss button in briefing RSS cards, cap cards at 3
Adds discussArticle() to BriefingApi and wires it through to the
RSS news cards in BriefingScreen so tapping Discuss opens a chat
conversation seeded with the article. Also caps RSS cards per
message at 3 to avoid overly long briefing threads.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-06 17:49:16 -04:00
bvandeusen d97f7b0ebd feat(knowledge): wire 4-tab shell, retire LibraryScreen, complete Knowledge View feature 2026-04-05 00:03:23 -04:00
bvandeusen 1fb792177e Add Flutter platform stubs for iOS, web, Linux, macOS, Windows
Auto-generated by flutter create; not currently targeted but kept for
future portability.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-28 21:29:24 -05:00