feat(run): host-injected native file picker for flow file inputs
The Run tab asked the operator to type an absolute path into a text field — with no file dialog anywhere. FlowEditorPage now accepts an onPickFile callback (PickedFileData: name + bytes) that hosts wire to their native picker; the path-entry dialog remains only as the no-host fallback. 0.23.0. Signed-off-by: flemming-it <sf@flemming.it>
This commit is contained in:
parent
9e73036d0e
commit
ae09a55146
6 changed files with 52 additions and 6 deletions
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -40,6 +40,8 @@ export 'src/run_driver.dart'
|
|||
show
|
||||
FlowRunDriver,
|
||||
FlowRunEvent,
|
||||
PickedFileData,
|
||||
PickFileCallback,
|
||||
StepStarted,
|
||||
StepCompleted,
|
||||
StepFailed,
|
||||
|
|
|
|||
|
|
@ -101,6 +101,11 @@ class FlowEditorPage extends StatefulWidget {
|
|||
/// silent — no install button offered.
|
||||
final List<String> 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,
|
||||
),
|
||||
],
|
||||
),
|
||||
|
|
|
|||
|
|
@ -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<PickedFileData?> Function();
|
||||
|
||||
|
||||
abstract class FlowRunDriver {
|
||||
/// Trigger a run of [flowName] with the supplied inputs.
|
||||
/// Text + file inputs come in separate maps so the host
|
||||
|
|
|
|||
|
|
@ -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<RunTab> {
|
|||
}
|
||||
|
||||
Future<void> _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<String>(
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue