feat(studio): wire flow editor quick-fix install handler
Some checks failed
Security / Security check (push) Failing after 1s

FlowsPage now passes onInstallCapability to the editor — the
editor's 'Install <cap>' button on an unknown-capability
diagnostic calls HubService.installModule, refreshes the
capability list, and returns it so the editor reanalyzes and
clears the issue.

On install failure: friendly SnackBar surfaces the error. The
operator never gets stuck on the analyzer reporting a
capability they just clicked to install.

Studio bumped to 0.64.0; editor path-override pulls in 0.17.0.

Signed-off-by: flemming-it <stefan.a.flemming@googlemail.com>
This commit is contained in:
flemming-it 2026-06-09 00:02:28 +02:00
parent d0e15ca385
commit 0cc527b07c
3 changed files with 41 additions and 2 deletions

View file

@ -27,7 +27,7 @@ import 'widgets/widgets.dart';
/// Studio's own build version. Bump on every UI commit so the
/// running app self-identifies visible in the sidebar header
/// and quick-glance proof that you're seeing the current build.
const String kStudioVersion = '0.63.0';
const String kStudioVersion = '0.64.0';
Future<void> main() async {
WidgetsFlutterBinding.ensureInitialized();

View file

@ -57,6 +57,44 @@ class _FlowsPageState extends State<FlowsPage> {
}
}
/// Quick-fix handler invoked when the operator clicks
/// `Install <capability>` on an analyzer issue. Parses the
/// editor-supplied `provider/name@version` spec into the
/// Hub's install API and returns the refreshed capability
/// list so the editor can re-analyze without waiting for the
/// parent widget rebuild.
Future<List<String>?> _onInstallCapability(String capability) async {
try {
// Editor passes the raw `use:` value (e.g.
// `text.classify@^1`). HubService.installModule resolves
// any version spec the hub's registry accepts.
await HubService.instance.installModule(source: capability);
final caps = await HubService.instance.allCapabilities();
final updated = caps
.map((c) => '${c.capability}@${c.version}')
.toSet()
.toList()
..sort();
if (mounted) {
// Refresh the cached capability future so subsequent
// FutureBuilder rebuilds also see the new list.
setState(() => _capabilities = Future.value(updated));
}
return updated;
} catch (e) {
if (mounted) {
ScaffoldMessenger.of(context).removeCurrentSnackBar();
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
content: Text('Install failed: $e'),
behavior: SnackBarBehavior.floating,
),
);
}
return null;
}
}
@override
Widget build(BuildContext context) {
final locale = Localizations.localeOf(context);
@ -72,6 +110,7 @@ class _FlowsPageState extends State<FlowsPage> {
locale: editorLocale,
runDriver: _driver,
availableCapabilities: caps,
onInstallCapability: _onInstallCapability,
);
},
);