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:
parent
c4d3751e85
commit
42f271679c
4 changed files with 49 additions and 1 deletions
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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,
|
||||||
|
),
|
||||||
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue