chain-studio/lib/pages/flows.dart
flemming-it c1c60d5434
Some checks failed
Security / Security check (push) Failing after 1s
feat(studio): rich theme picker (presets + custom colour) + editor 0.11.0
Settings dialog's Theme Plugin section is now a grid of
swatched tiles:

- Built-in (none) — falls back to FaiTheme.light/.dark
- One tile per installed studio.theme.* plugin, each
  showing the plugin's primary/secondary/tertiary as
  live colour dots. Tile loads its preview lazily so a
  dozen installed themes don't block the picker.
- Custom — opens a colour-picker dialog with 12 curated
  Material presets + a hex input + live preview. Selecting
  applies ColorScheme.fromSeed for both brightnesses.

main.dart's _pluginThemes parses a 'custom:#RRGGBB' sigil
in the same notifier slot as plugin capability ids, so the
existing persistence + restoration paths cover the custom
case with no new state.

Bumps editor to 0.11.0 (type-checked port connections +
dynamic card width fix + card-height border allowance) and
Studio to 0.58.0.

Signed-off-by: flemming-it <stefan.a.flemming@googlemail.com>
2026-06-02 01:29:34 +02:00

79 lines
2.6 KiB
Dart

// FlowsPage — Studio's flow surface. Thin host wrapper around
// the swappable fai_studio_flow_editor package: loads the
// hub's installed capabilities, hands them + a Studio-side
// FlowRunDriver to the editor, and lets the editor own
// everything else (file list, three-tab body, properties
// panel, run progress, …).
//
// Pre-0.52 versions split file-listing and run-dialog state
// across this page. v0.52 moves all of that into the editor
// package so a swap is one pubspec change — Studio doesn't
// need to know what's inside the editor any more.
import 'package:fai_studio_flow_editor/fai_studio_flow_editor.dart';
import 'package:flutter/material.dart';
import '../data/flow_run_driver.dart';
import '../data/hub.dart';
class FlowsPage extends StatefulWidget {
/// Pre-load this flow when the editor first builds. Studio
/// keeps the parameter so the Cmd+K palette + welcome page
/// can deep-link straight into a specific flow.
final String? initialFlowName;
const FlowsPage({super.key, this.initialFlowName});
@override
State<FlowsPage> createState() => _FlowsPageState();
}
class _FlowsPageState extends State<FlowsPage> {
late Future<List<String>> _capabilities;
late final StudioFlowRunDriver _driver;
@override
void initState() {
super.initState();
_driver = StudioFlowRunDriver();
_capabilities = _loadCapabilities();
}
/// Pulls the capability identifiers the picker dialog
/// offers when adding a step. `<capability>@<version>` so
/// the operator can see exactly what they'll be wiring in,
/// matching the format the `use:` field expects. Soft-fails
/// to an empty list if the hub is unreachable — the editor
/// falls back to a free-form text field in that case.
Future<List<String>> _loadCapabilities() async {
try {
final caps = await HubService.instance.allCapabilities();
final entries =
caps.map((c) => '${c.capability}@${c.version}').toSet().toList()
..sort();
return entries;
} catch (_) {
return const <String>[];
}
}
@override
Widget build(BuildContext context) {
final locale = Localizations.localeOf(context);
final editorLocale = locale.languageCode == 'de'
? FlowEditorLocale.de
: FlowEditorLocale.en;
return FutureBuilder<List<String>>(
future: _capabilities,
builder: (context, snap) {
final caps = snap.data ?? const <String>[];
return FlowEditorPage(
initialFlowName: widget.initialFlowName,
locale: editorLocale,
runDriver: _driver,
availableCapabilities: caps,
);
},
);
}
}