0.1.120 — editor signed-out auth widget unified onto shared AuthHub

User directive verbatim:

"continue working on the unified auth hub."

The deferred work from 0.1.119: editor's signed-out account surface was duplicating what the shared AuthHub widget already provided. Portal + planner already used AuthHub (with the same Casdoor SSO pill / signup link / email-password fallback expander); editor hand-rolled its own copy in editor_app/lib/modules/settings_build.dart. This round drops the duplicate and routes editor through the shared widget.

Why the in-line copy existed

When the editor's settings page was first built (0.1.78ish), the AuthHub widget didn't yet exist in notechondria_shared. By the time AuthHub landed, editor had a working surface and nobody went back to consolidate. Maintenance cost showed up over the last several auth-flow rounds: every time the Casdoor primary CTA, signup link, or fallback expander needed a tweak, the change had to be made in two places (editor's _buildSignedOutAccount plus the shared AuthHub), with no compiler help to keep them in sync.

Symptoms across recent versions:

  • 0.1.103: signup wizard removed → had to delete the same code twice.
  • 0.1.108: Casdoor button always-shown → the gate had to be dropped in two places.
  • 0.1.116: "Login via third party" duplicate button removed → again, two edits.

After this round, all three apps render the same AuthHub body. A single edit in notechondria_shared/lib/src/components/ auth_dialogs.dart propagates everywhere.

What changed

frontend/editor_app/lib/modules/settings_build.dart

_buildSignedOutAccount(BuildContext) is now a one-liner:

Widget _buildSignedOutAccount(BuildContext context) {
  return AuthHub(
    apiBaseUrl: widget.apiBaseUrl,
    onLogin: widget.onLogin,
    onCasdoorLogin: widget.onCasdoorLogin,
    casdoorOrgLoginUrl: widget.casdoorOrgLoginUrl,
  );
}

AuthHub is exported by the shared package and already provides:

  • Continue with Casdoor SSO FilledButton (gated on onCasdoorLogin != null),
  • No account? Sign up via Casdoor link (gated on a non-empty casdoorOrgLoginUrl),
  • Use email / password instead expander → EmailPasswordDialog,
  • API-base host subtitle inside the login dialog so the user knows which backend they're authenticating to.

All of those previously had hand-rolled equivalents in editor.

Dead code removed

The following helpers are gone — they were called only by the old _buildSignedOutAccount body:

  • _OAuthPillButton class (the full-width OutlinedButton helper).
  • _legacyAuthBlock (the email/password fallback Column).
  • _openLoginDialog (the EmailPasswordDialog opener).
  • _apiBaseHostSubtitle (the host-derivation helper).
  • _casdoorBrowserLoginUrl getter.
  • _openCasdoorBrowserLogin method.
  • _showLegacyAuthFallback field on _SettingsPageState.
  • toggleLegacyAuthFallback method on _SettingsPageState.

Net: −190 lines from settings_build.dart and a tighter _SettingsPageState interface.

The signed-IN account surface was not unified — that's a settings-navigation menu (Personal information / Sign-in & Security / API settings list rows + logout), not an auth-choice surface, so it has no equivalent in AuthHub. Portal + planner have similar bespoke signed-in cards; unifying those would require a different kind of shared widget and isn't part of this round.

Bark notification rule

Per docs/AGENTS.md, after tests pass and before pushing the operator should send a silent push to every *.bark.env URL. That step was missed when 0.1.117–0.1.119 were pushed; the catchup notification for 0.1.119 was sent inline today before this round started, and 0.1.120's push notification fires after this commit lands.

Verification (per AGENTS.md / "use docker to test build")

  1. flutter analyze clean across the four Flutter packages — no new errors, no new warnings. The pre-existing _socialLinkError warning in planner is untouched.
  2. editor_app/lib/modules/settings_build.dart — visually inspected before / after; the SettingsState fields and the _SettingsPageBuildX extension callers all line up.
  3. AuthHub's existing portal + planner surfaces are unchanged (no edits to either app's settings code), so the only risk is regression on the editor's signed-out card. The render is byte-equivalent because AuthHub's body matches the editor's old in-line shape (Casdoor pill + signup link
    • fallback expander, in that order).

Files changed

  • frontend/editor_app/lib/modules/settings_build.dart_buildSignedOutAccount shrunk to an AuthHub(...) call; six helper methods + one private widget class deleted.
  • frontend/editor_app/lib/modules/settings.dart_showLegacyAuthFallback + toggleLegacyAuthFallback removed from _SettingsPageState.
  • VERSION, docs/SUMMARY.md, docs/versions/0.1.120.md.