Notechondria

Version: 0.1.84 Build Date: 2026-04-28T00:30

What's Changed

Two reported bugs from the Bugs section of docs/TODO.md. The first turned out to be three distinct problems wrapped in one report; the second is a card-layout polish for wide screens.

Bug — offline user has no default Inbox + can't get back to "All Notes"

The user reported: "When offline user view the site, there is no default inbox init. And when inbox clicked, it cannot goes back to view the public notes in 'All notes' page."

Investigation surfaced three coupled issues:

1. _ensureStarterWorkspace guard suppressed seeding silently

editor_app/lib/core/local_starter.dart _ensureStarterWorkspace short-circuited on _frontPage?.isNotEmpty == true. For previously-signed-in users now signed-out, _localCache['front_page'] was a cached cloud payload — non-empty, so seeding bailed even though they had no actual Inbox row in _courses to back it up. The user landed in offline mode with no usable default category.

  • Rewrote the guard to scan the actual Inbox presence (case-insensitive title match) across _courses + _localCourses rather than rely on the front-page cache. Robust against stale/empty cache payloads.
  • Body changed from "all-or-nothing first-run seed" to a thin wrapper around _seedStarterInboxAlongsideExisting (introduced in 0.1.77). That helper is additive — it appends an Inbox without clobbering any drafts the user already had, and seeds welcome drafts only when the new Inbox is empty.

2. Cold-boot auto-picked Inbox-as-default

load_local_state.dart ended with _selectedCourse ??= _chooseDefaultCourse(...), which on cold-start picked the cached frontPage.default_course (the user's cloud Inbox). After 0.1.83 made Inbox private, that view returned zero notes for non-owners. The user landed in their previously-cloud Inbox with 0 visible notes — looking broken — and had to navigate manually to "All Notes" to see anything.

  • Dropped the _chooseDefaultCourse auto-pick from cold-boot in editor_app/lib/core/load_local_state.dart. The user now lands on "All Notes" (no category selected) by default.
  • _loadInitialData (post-auth bootstrap) now only re-picks a default course if _selectedCourse was already non-null going in — i.e. the user explicitly tapped a category before the bootstrap fired. Otherwise leaves it null so the "All Notes" landing sticks across the cloud-fetch refresh too.

3. (User-perceived) Inbox is a trap

With #1 and #2 fixed, the navigation works as expected: cold-boot lands on All Notes (public feed for anon users); tapping Inbox enters the private local Inbox; tapping "All Notes" in the sidebar/drawer goes back. The "trap" feeling was a side effect of #2 — the user was implicitly trapped on cold-boot, not by the Inbox-tap itself.

Feature — horizontal cover layout on wide cards (4:6 split)

User report: "When in horizontal view, the image took too much vertical space. In horizontal view, move the cover image to the left, with ratio 4:6 for the cover image and card text area."

The 0.1.77 Bootstrap-card-style cover banner stacked the cover on top of the body at 21:9 aspect ratio, which on wide screens consumed a large vertical strip per card and pushed the text out of view.

  • _LearnerNoteCard in editor_app/lib/modules/learner.dart now wraps its child in a LayoutBuilder. When the card's available width is ≥ 600px AND the card has a cover banner, it switches to a horizontal Row layout: left side flex 4 (cover image, 4:6 aspect), right side flex 6 (body content). Below 600px, the card keeps the original vertical layout so phone-width and narrow drawer-list contexts stay compact.
  • Extracted the body content (avatar + title + state badge + preview lines + sync/status icon) into a new private _LearnerNoteCardBody widget so the parent card can render the same body inside either a vertical Column (under a banner) or a horizontal Row (next to a thumbnail) without duplicating the layout.
  • The 600px breakpoint roughly matches the editor's compact / wide scaffold transition, so cards reflow at the same visual moment the rest of the app does.

Files Changed

  • VERSION — 0.1.83 → 0.1.84.
  • frontend/editor_app/lib/core/local_starter.dart_ensureStarterWorkspace rewritten as a thin wrapper around _seedStarterInboxAlongsideExisting with a robust Inbox-presence guard.
  • frontend/editor_app/lib/core/load_local_state.dart — dropped the _chooseDefaultCourse auto-pick at cold boot.
  • frontend/editor_app/lib/core/initial_data.dart — post-auth bootstrap only re-picks a default course if one was already selected pre-bootstrap.
  • frontend/editor_app/lib/modules/learner.dartLayoutBuilder + horizontal/vertical switch + new _LearnerNoteCardBody widget.
  • docs/TODO.md — both bug entries removed (Bugs section now only carries the older Bitwarden-autofill audit item).

Notes

  • All four packages (editor / planner / portal / shared) pass flutter analyze (zero errors) and flutter test (smoke + the 12 deep-link regression tests from 0.1.83). Editor smoke test verified that cold-boot now lands on the "Welcome" draft inside the seeded Inbox — covering the 0.1.84 seeding path end-to-end.
  • §1.5 1000-LOC cap respected. Editor's learner.dart grew from 866 to 924 (the body extraction added ~60 lines of repeated field declarations + the new widget's boilerplate). Headroom remains; if a future round wants to drop the duplicated field list, the body widget could share its fields with the parent via a shared model class.
  • The 600px breakpoint for horizontal cards is hard-coded; if a future redesign changes the compact / wide scaffold threshold, search for >= 600 in _LearnerNoteCard and adjust to match.
  • Behavioral change: previously-signed-in users who signed out and reopened the editor will now land on "All Notes" instead of the (broken-feeling) cached Inbox view. Their stored cached cloud Inbox row is still in _courses and reachable via the sidebar — only the cold-boot landing view changed.