diff --git a/CHANGELOG.md b/CHANGELOG.md index 140b62c..5ab46c3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,13 @@ # Changelog +## 0.23.0 + +- Run tab file inputs accept a host-injected native file picker + (`FlowEditorPage.onPickFile`, new `PickedFileData` / + `PickFileCallback` contract). The manual path-entry dialog remains + only as the no-host fallback — typing an absolute path by hand is + a last resort, not an input method. + All notable changes to `chain_studio_flow_editor` recorded here. Studio bumps its `pubspec.yaml` git ref to a specific release of this package on every editor change. diff --git a/lib/chain_studio_flow_editor.dart b/lib/chain_studio_flow_editor.dart index e824140..ae637b8 100644 --- a/lib/chain_studio_flow_editor.dart +++ b/lib/chain_studio_flow_editor.dart @@ -40,6 +40,8 @@ export 'src/run_driver.dart' show FlowRunDriver, FlowRunEvent, + PickedFileData, + PickFileCallback, StepStarted, StepCompleted, StepFailed, diff --git a/lib/src/flow_editor_page.dart b/lib/src/flow_editor_page.dart index 176c681..9b63e6c 100644 --- a/lib/src/flow_editor_page.dart +++ b/lib/src/flow_editor_page.dart @@ -101,6 +101,11 @@ class FlowEditorPage extends StatefulWidget { /// silent — no install button offered. final List storeCapabilities; + /// Host-side native file picker for the Run tab's file inputs. + /// Studio passes a real file dialog; null keeps the manual + /// path-entry fallback. + final PickFileCallback? onPickFile; + /// The host's active workspace/project slug (empty = "all /// projects", no active workspace). Used only to flag a /// mismatch when the open flow file declares a *different* @@ -126,6 +131,7 @@ class FlowEditorPage extends StatefulWidget { this.storeCapabilities = const [], this.activeProject = '', this.onSwitchToFileProject, + this.onPickFile, }); @override @@ -658,6 +664,7 @@ outputs: controller: _controller, strings: _l, driver: widget.runDriver, + onPickFile: widget.onPickFile, ), ], ), diff --git a/lib/src/run_driver.dart b/lib/src/run_driver.dart index 413b4b9..d66db9d 100644 --- a/lib/src/run_driver.dart +++ b/lib/src/run_driver.dart @@ -19,6 +19,19 @@ import 'dart:typed_data'; +/// A file chosen by the host's native picker for a flow file input. +class PickedFileData { + final String fileName; + final Uint8List bytes; + const PickedFileData({required this.fileName, required this.bytes}); +} + +/// Host-side native file picker. Returns null when the operator +/// cancels. When a host does not supply one, the Run tab falls back +/// to its manual path-entry dialog. +typedef PickFileCallback = Future Function(); + + abstract class FlowRunDriver { /// Trigger a run of [flowName] with the supplied inputs. /// Text + file inputs come in separate maps so the host diff --git a/lib/src/widgets/run_tab.dart b/lib/src/widgets/run_tab.dart index 692276e..26c6032 100644 --- a/lib/src/widgets/run_tab.dart +++ b/lib/src/widgets/run_tab.dart @@ -36,11 +36,17 @@ class RunTab extends StatefulWidget { final FlowEditorController controller; final FlowEditorStrings strings; final FlowRunDriver? driver; + + /// Host-side native file picker; null keeps the manual + /// path-entry fallback dialog. + final PickFileCallback? onPickFile; + const RunTab({ super.key, required this.controller, required this.strings, this.driver, + this.onPickFile, }); @override @@ -469,11 +475,21 @@ class _RunTabState extends State { } Future _pickFile(String name) async { - // For 0.2.0 the editor relies on the host to inject a - // file-picker via callback; minimal version uses - // dart:io directly for desktop. Studio uses file_picker; - // we fall back to a manual path entry dialog if no host - // picker is available. + // Host-injected native picker first — typing an absolute path + // by hand is a last resort, not an input method. + final hostPick = widget.onPickFile; + if (hostPick != null) { + final picked = await hostPick(); + if (picked == null || !mounted) return; + setState(() { + _fileInputs[name] = _FilePick( + fileName: picked.fileName, + bytes: picked.bytes, + ); + }); + return; + } + // Fallback without a host picker: manual path entry. final controller = TextEditingController(); final ctx = context; final result = await showDialog( diff --git a/pubspec.yaml b/pubspec.yaml index c52f572..b3110fd 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,6 +1,6 @@ name: chain_studio_flow_editor description: Swappable inline YAML editor for F∆I Studio flows. -version: 0.22.0 +version: 0.23.0 publish_to: 'none' repository: https://git.flemming.ai/fai/studio-flow-editor