focus-flow/apps/focus_flow_flutter/README.md
pyr0ball 383130ebdb chore: merge upstream Backlog Board feature from Ashley's instance
Merges 20 commits from Ashley's smolblocks.com instance (main branch),
bringing in the full Backlog Board screen (BacklogBoardController, board
columns/cards, task detail drawer, summary panel, search/filter/sort/group,
Break Up and Someday actions) plus the unified FocusFlowSection navigation
model.

Reconciled with our own in-flight work:
- Replaced our placeholder BacklogPane/createBacklogController wiring with
  Ashley's real BacklogBoardScreen/BacklogBoardController (same problem,
  more complete implementation - avoids two competing Backlog UIs).
- Adopted the FocusFlowSection-based Sidebar API in place of our bespoke
  SidebarScreen enum; the Settings nav item now intercepts
  FocusFlowSection.settings in _selectSection to open our Settings dialog
  instead of falling through to a placeholder screen.
- Gave every sidebar nav item a stable key (not just the active one) so the
  Settings dialog tests can still target it reliably.
- Kept our additive owner-settings read controller, Settings dialog, and
  timeline Break-up wiring; renamed the Today controller field to
  todayController throughout to match upstream's now-multi-controller
  naming.
- Fixed a test-only regression: backlog_board_screen_test.dart's standalone
  SchedulerCommandController construction needed the new `management` param.
- Added .gitleaks.toml allowlisting the local, gitignored
  .claude/settings.local.json path (recorded bash command patterns, not
  repo secrets) that was blocking commits.

Verified via focusflow-flutter-ci:3.44.4 (Flutter 3.44.4/Dart 3.12.2):
flutter analyze clean, dart format clean, 106/106 Flutter tests passing,
348/348 scheduler_core + scheduler_persistence_sqlite tests passing.

Closes: Circuit-Forge/focus-flow#9
2026-07-10 22:46:09 -07:00

185 lines
6 KiB
Markdown

<!-- SPDX-FileCopyrightText: 2026 FocusFlow contributors -->
<!-- SPDX-License-Identifier: AGPL-3.0-only -->
# FocusFlow Flutter
Flutter desktop app target for the FocusFlow UI work.
## Current Scope
The app launches into the compact Today timeline. Normal startup now opens an
on-disk SQLite database and bootstraps owner settings plus the default Home
project when they are missing.
cards. The sidebar Backlog navigation opens the board surface backed by public
scheduler application APIs. Backlog supports the four board buckets, search,
filters, sort/group controls, summary data, the right-anchored detail drawer,
task creation, scheduling, Break Up child-task creation, Someday tagging, and
non-destructive archive/remove from active Backlog.
Backlog notes, project edits, and freeform tag edits intentionally remain
read-only or non-mutating placeholders until the deferred metadata migration and
application command are implemented.
The sidebar Settings item and top bar Settings button both open a dialog bound
to persisted `OwnerSettings`/`BacklogStalenessSettings`, covering time zone, day
window, compact-mode toggle, and backlog staleness thresholds.
## Runtime Data
Normal runtime uses `lib/app/persistent_scheduler_composition.dart`, which reads
`SCHEDULER_SQLITE_PATH` from a Dart define. If no define is present, it uses the
local dev convention:
```text
~/ADHD_Scheduler/scheduler.sqlite
```
Static demo data still lives in `lib/app/demo_scheduler_composition.dart`, but
it is for deterministic widget/visual tests and explicit demo composition only.
It is not inserted during normal startup.
Widgets consume `TodayScreenData` from `lib/models/today_screen_models.dart`.
Scheduler core remains the source of truth for task state and Today ordering.
## Runtime Config
The app optionally reads a JSON config file from:
```text
~/ADHD_Scheduler/config.json
```
Override the config path with:
```sh
flutter run -d linux --dart-define=FOCUS_FLOW_CONFIG_PATH=/tmp/focus_flow_config.json
```
Supported optional keys:
```json
{
"Timezone": "UTC",
"LogLevel": "fine",
"LogfileLocation": "~/ADHD_Scheduler/debug/"
}
```
`Timezone` accepts a three-letter time-zone code without regard to character
case, such as `UTC`, `GMT`, `PST`, or `PDT`. Common daylight-saving pairs such
as `PST`/`PDT`, `MST`/`MDT`, `CST`/`CDT`, and `EST`/`EDT` are resolved once when
the config loads, so either seasonal abbreviation uses the correct current
offset for that zone during the app session. The setting is an app/UI reference
only: it controls wall-clock timeline display, selected-day startup, and
time-relative actions such as pushing a task to the next slot or tomorrow. Task
instants and all persistence data remain stored as UTC/GMT values.
`LogLevel` accepts `finest`, `finer`, `fine`, `debug`, `info`, `warn`, or
`error`.
`LogfileLocation` is treated as a directory, and the app writes
`focus_flow.log` inside it. If either key is absent or invalid, file logging is
not enabled and the app ignores that setting.
Verbose log levels can include automatic caller information without requiring
each call site to pass it manually. `finest` includes caller frames for every
written message. `fine`, `finer`, and `finest` include caller frames for
warnings and errors. This caller lookup is skipped when the configured level
does not require it.
For expensive debug/detail messages, pass a lazy closure so work is skipped when
the configured level would not write the log:
```dart
logger.debug(() => 'state=${expensiveStateDump()}');
```
## Package Boundary
Allowed app imports include public scheduler APIs such as:
```dart
import 'package:scheduler_core/scheduler_core.dart';
```
The persistent composition root may import
`package:scheduler_persistence_sqlite/sqlite.dart` and `dart:io` for runtime
path resolution. Widgets/controllers must not import scheduler `src/` files,
Drift, SQLite adapters, desktop notification implementations, backup/export
packages, or direct OS APIs. `test/forbidden_imports_test.dart` enforces that
boundary.
## Intentionally No-op
- Compact/Normal toggle (Settings persists the flag, but the Today pipeline
does not yet read it; see Forgejo issue #11).
- Show upcoming.
- Timeline card Schedule and Protect time icons.
- Backlog drawer project selector, add-tag control, and View day shortcut.
## Persistence Proof
Current focused tests prove:
- first run opens an empty SQLite file without seeded task rows,
- quick capture writes a backlog task,
- scheduling writes planned Today placement,
- done and not-done state persists,
- closing and reopening the same SQLite file reloads the task state.
Manual verification:
```sh
scripts/bootstrap_dev.sh
scripts/dev.sh --sqlite /tmp/focus_flow_persistence_plan_1.sqlite
```
Use the same `--sqlite` path after closing the app to confirm state persists. To
reset local dev data, close the app and delete the chosen `.sqlite` file. This is
only a dev reset; backup/restore UI remains out of scope.
## Commands
Run `scripts/bootstrap_dev.sh` once from the repository root to create the
default SQLite directory.
Run the desktop UI from this directory:
```sh
flutter pub get
flutter run -d linux
```
Replace `linux` with `macos` or `windows` on those hosts. The default database
path is `~/ADHD_Scheduler/scheduler.sqlite`. If Flutter reports that the
desktop project is not configured for that platform, generate the missing
runner from this directory:
```sh
flutter create --platforms=linux .
```
Use `--platforms=macos` or `--platforms=windows` for those hosts.
Use a disposable dev database when needed:
```sh
flutter run -d linux --dart-define=SCHEDULER_SQLITE_PATH=/tmp/focus_flow_dev.sqlite
```
Check the app from this directory:
```sh
flutter analyze
flutter test
```
Run these from `apps/focus_flow_flutter/`.
## Next Plans
- Give the Compact/Normal toggle real backing state (the live Today pipeline
has no compact-mode concept yet; see Forgejo issue #11).
- Add migration-backed notes, project edits, and freeform tags for Backlog
metadata.
- Add Shield/Recovery only in a later scope.