Notechondria

Version: 0.1.53 Build Date: 2026-04-21T18:00

What's Changed

File-size enforcement — editor_app under the §1.5 cap

  • 0.1.52 codified the 1000-line ceiling but only chipped at editor_app/lib/app_shell.dart (5000 lines at the start of this round). This round brings every file in frontend/editor_app/lib/ under the cap by carving 23 per-concern extensions on _AppShellState out into core/*.dart part files. The pattern matches the proof-of-concept core/local_trash.dart that 0.1.52 shipped: each extension captures a cohesive cluster of methods and routes mutations through a shared _refresh() wrapper since Dart extensions can't call the protected setState directly.

  • app_shell.dart shrinks 5000 → 552. New core/ part files: auth_actions.dart (auth ActionFeedback wrappers), auth_flows.dart (OAuth + session-restore + deep-link), build_helpers.dart (compact / wide scaffold + body/page builders), category_actions.dart (course CRUD), course_helpers.dart (read-side projections), draft_helpers.dart (offline draft store), draft_sync.dart (push/pull conflict dialog), http_client.dart (HttpNotechondriaClient), http_client_internals.dart (HTTP plumbing), initial_data.dart (cold-boot orchestrator), load_local_state.dart (_loadLocalState), local_archive_io.dart (.nchron import/export), local_course_builders.dart (build/promote local course), local_persist.dart (_persistLocal*), local_starter.dart (first-run Inbox), logging.dart (_log/_appendUiLog/_timed), maintenance_actions.dart (recycle-bin/sync/clear), note_crud.dart, note_loading.dart, note_sessions.dart, session.dart (_applyAuthPayload/_logout), settings_actions.dart, settings_helpers.dart. Settings module also splits: modules/settings_build.dart, modules/settings_pages.dart, modules/settings_sections.dart, modules/note_editor_attachments.dart, modules/note_editor_widgets.dart.

  • core/client.dart 1291 → 195 + 850 + 273 lines: the abstract NotechondriaClient interface stays where it was; the concrete HttpNotechondriaClient moves into a new core/http_client.dart, and the private HTTP plumbing (_send, _decode, _headers, _shapedErrorMessage, _get/_post/_patch/_delete) moves into core/http_client_internals.dart as an extension on the concrete class. Extensions can't satisfy abstract method contracts, but they can hold private helpers — that asymmetry is what makes the split possible without changing the public API.

  • modules/settings.dart 1781 → 625; modules/note_editor.dart 1472 → 785. Each split into per-section extensions on the relevant State class.

Files Changed

  • frontend/editor_app/lib/app_shell.dart — 5000 → 552 lines. Replaces 4700+ lines of inline state methods with a TOC comment block enumerating each new extension, the _refresh() wrapper, and the _showMessage() snackbar utility. Class declaration itself stays minimal; per-concern extensions add the actual logic.
  • 23 new core/*.dart files plus 4 new modules/*.dart files (see commit body for full list). Every file is under 1000 lines.
  • frontend/editor_app/lib/main.dartpart directives expanded to register all the new core/ + modules/ partials.

Notes

  • This is the first time the §1.5 cap is fully met for one of the three apps. planner_app and portal_app remain over-cap; the next round (cross-app dedup via shared mixins) tackles them and promotes the duplicated chunks up into notechondria_shared rather than copy-pasting editor_app's pattern verbatim.
  • flutter analyze clean, smoke test passes. No behavior changes — every method body is preserved verbatim; only its physical location moved.