feat: per-row start button on runnable flows (0.21.2)

Flows without missing modules get a play button in the list that
opens them directly on the Run tab - one click from the list to
entering inputs and starting a run. Rows with missing modules keep
the install badge as their single actionable path.

Signed-off-by: flemming-it <sf@flemming.it>
This commit is contained in:
flemming-it 2026-07-11 10:02:55 +02:00
parent c4d3751e85
commit 42f271679c
4 changed files with 49 additions and 1 deletions

View file

@ -4,6 +4,15 @@ All notable changes to `chain_studio_flow_editor` recorded here.
Studio bumps its `pubspec.yaml` git ref to a specific release Studio bumps its `pubspec.yaml` git ref to a specific release
of this package on every editor change. of this package on every editor change.
## 0.21.2 — 2026-07-11
### Added
- **Per-row start button.** Runnable flows (no missing modules) get a
play button in the flow list that opens them directly on the Run
tab — one click from the list to entering inputs and starting
(usertest quick win).
## 0.21.1 — 2026-07-11 ## 0.21.1 — 2026-07-11
### Fixed ### Fixed

View file

@ -289,6 +289,17 @@ class _FlowEditorPageState extends State<FlowEditorPage>
return files; return files;
} }
/// Row-level start: open the flow and land directly on the Run
/// tab, where inputs + the start button live. One click from the
/// list to running a flow.
Future<void> _startFile(_FlowFile f) async {
await _openFile(f);
if (!mounted) return;
if (_controller.analyzerErrorCount == 0) {
_tabs.animateTo(2);
}
}
Future<void> _openByName(String name) async { Future<void> _openByName(String name) async {
final path = '${_defaultFlowsDir()}/$name.yaml'; final path = '${_defaultFlowsDir()}/$name.yaml';
final file = File(path); final file = File(path);
@ -551,6 +562,7 @@ outputs:
), ),
onOpen: _openFile, onOpen: _openFile,
onRefresh: _refreshFiles, onRefresh: _refreshFiles,
onStart: _startFile,
onInstallMissing: widget.onInstallCapability == null onInstallMissing: widget.onInstallCapability == null
? null ? null
: _installMissingCaps, : _installMissingCaps,
@ -1218,6 +1230,11 @@ class _FileList extends StatelessWidget {
final void Function(_FlowFile) onOpen; final void Function(_FlowFile) onOpen;
final VoidCallback onRefresh; final VoidCallback onRefresh;
/// Open the flow directly on the Run tab the per-row start
/// affordance the usertest asked for. Rows with missing modules
/// don't offer it (they can't run yet).
final void Function(_FlowFile) onStart;
/// Install the listed missing capabilities. `null` when the /// Install the listed missing capabilities. `null` when the
/// host wired no install handler the warning badge still /// host wired no install handler the warning badge still
/// renders, just without the one-click action. /// renders, just without the one-click action.
@ -1230,6 +1247,7 @@ class _FileList extends StatelessWidget {
required this.installedNames, required this.installedNames,
required this.onOpen, required this.onOpen,
required this.onRefresh, required this.onRefresh,
required this.onStart,
required this.onInstallMissing, required this.onInstallMissing,
}); });
@ -1401,6 +1419,25 @@ class _FileList extends StatelessWidget {
], ],
), ),
), ),
// Per-row start: one click from the list to the
// Run tab. Hidden while modules are missing
// the install badge is the actionable path then.
if (missing.isEmpty)
IconButton(
onPressed: () => onStart(f),
tooltip: strings.listStartTooltip,
icon: Icon(
Icons.play_arrow_rounded,
size: 20,
color: theme.colorScheme.primary,
),
visualDensity: VisualDensity.compact,
padding: EdgeInsets.zero,
constraints: const BoxConstraints(
minWidth: 32,
minHeight: 32,
),
),
], ],
), ),
), ),

View file

@ -18,6 +18,8 @@ class FlowEditorStrings {
String get run => _t('Run', 'Ausführen'); String get run => _t('Run', 'Ausführen');
String get refresh => _t('Refresh file list', 'Datei-Liste neu laden'); String get refresh => _t('Refresh file list', 'Datei-Liste neu laden');
String get listHeader => _t('FLOWS', 'FLOWS'); String get listHeader => _t('FLOWS', 'FLOWS');
String get listStartTooltip =>
_t('Open on the Run tab', 'Im Starten-Tab öffnen');
String get copy => _t('Copy', 'Kopieren'); String get copy => _t('Copy', 'Kopieren');
String get runOutput => _t('RUN OUTPUT', 'LAUF-ERGEBNIS'); String get runOutput => _t('RUN OUTPUT', 'LAUF-ERGEBNIS');
/// Toolbar title while no flow is open names the page, never /// Toolbar title while no flow is open names the page, never

View file

@ -1,6 +1,6 @@
name: chain_studio_flow_editor name: chain_studio_flow_editor
description: Swappable inline YAML editor for F∆I Studio flows. description: Swappable inline YAML editor for F∆I Studio flows.
version: 0.21.1 version: 0.21.2
publish_to: 'none' publish_to: 'none'
repository: https://git.flemming.ai/fai/studio-flow-editor repository: https://git.flemming.ai/fai/studio-flow-editor