fix(settings): reveal System-AI test result + refresh onboarding checklist
Some checks failed
Security / Security check (push) Failing after 1s

Two settings bugs the operator hit:

1. 'Test connection' appeared to do nothing. The result/error panel
   renders at the bottom of the System-AI editor's scrollable,
   600px-capped form, so on a tall dialog it lands below the fold —
   the footer button flickers 'Testing…' and nothing visible changes.
   The editor now holds a ScrollController and animates the content
   to reveal the outcome whenever a test result or error appears.

2. The welcome onboarding checklist kept 'connect System-AI'
   unchecked right after saving a working config. The checklist row
   opens the Settings dialog (an overlay, not a navigation), and on
   close the checklist never re-probed — so it showed the stale
   pre-config state. Both settings-opening rows (System-AI, MCP) now
   re-probe when the dialog closes; navigation-based rows already
   self-heal on return.

Studio suite green; flutter analyze clean.

Signed-off-by: flemming-it <stefan.a.flemming@googlemail.com>
This commit is contained in:
flemming-it 2026-07-13 14:15:17 +02:00
parent 708bb74fa7
commit 4ceb5bb567
2 changed files with 36 additions and 2 deletions

View file

@ -144,6 +144,7 @@ class _FaiSystemAiEditorState extends State<ChainSystemAiEditor> {
String? _modelsError;
AskAiResult? _testResult;
String? _error;
final _scrollController = ScrollController();
HardwareSnapshot? _hw;
CuratedSnapshot? _curated;
Map<String, CuratedModelInfo> _curatedById = const {};
@ -200,9 +201,26 @@ class _FaiSystemAiEditorState extends State<ChainSystemAiEditor> {
_endpoint.dispose();
_model.dispose();
_apiKeyEnv.dispose();
_scrollController.dispose();
super.dispose();
}
/// Reveal the test-result / error panel. It renders at the bottom
/// of a scrollable, height-capped form, so on a tall dialog it
/// lands below the fold the operator taps "Test connection",
/// the footer button flickers, and nothing *visible* changes.
/// Scroll it into view so the outcome is never missed.
void _revealBottom() {
WidgetsBinding.instance.addPostFrameCallback((_) {
if (!_scrollController.hasClients) return;
_scrollController.animateTo(
_scrollController.position.maxScrollExtent,
duration: const Duration(milliseconds: 250),
curve: Curves.easeOut,
);
});
}
void _onProviderChanged(_ProviderPreset p) {
setState(() {
_preset = p;
@ -255,6 +273,7 @@ class _FaiSystemAiEditorState extends State<ChainSystemAiEditor> {
_saving = false;
_error = e.toString();
});
_revealBottom();
}
}
@ -297,11 +316,13 @@ class _FaiSystemAiEditorState extends State<ChainSystemAiEditor> {
_testing = false;
_testResult = r;
});
_revealBottom();
} catch (e) {
setState(() {
_testing = false;
_error = e.toString();
});
_revealBottom();
}
}
@ -375,6 +396,7 @@ class _FaiSystemAiEditorState extends State<ChainSystemAiEditor> {
content: ConstrainedBox(
constraints: const BoxConstraints(maxWidth: 520, maxHeight: 600),
child: SingleChildScrollView(
controller: _scrollController,
child: Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.start,