feat(editor): graph-pulse on errors + store-aware install / add-source
Three connected improvements to the analyzer-driven diagnostics:
- **Pulsing halo on broken graph nodes**. Every step / pseudo-
node (inputs / outputs) carrying an analyzer issue now
breathes a red (error) or amber (warning) halo on the graph
tab — operator sees the problem on the canvas without
flipping to text. Honours prefers-reduced-motion: reduce-
motion users get a static halo at the same intensity. The
canvas reads severity via a new `stepIssueSeverity` map on
FlowEditorController; pseudo-nodes use `__inputs__` /
`__outputs__` sentinel ids.
- **Store-aware install button**. The analyzer now takes a
second closure, `storeCapabilities`, listing what the public
store can install. Unknown-capability issues only carry the
"Install …" quick-fix when the bare cap is in that list;
otherwise the issue carries an "Add source for …" fix
instead. Resolves the asymmetry the operator reported: the
Store didn't show `htw.digiscout/onet.lookup` but the editor
happily offered to install it (and would have failed). The
install path no longer lies about itself.
- **Did-you-mean suggestion**. When the unknown cap is within
edit-distance two of an installed or store cap (different
spelling — distance-0 stays hidden because that's an install
case, not a typo), the analyzer emits a `ReplaceLineValueFix`
suggesting the closest match. Preserves the version
constraint by reusing the installed spec when present
(e.g. `text.echi@^0.1` → `text.echo@^0.1`).
New public surface:
- `AddModuleSourceFix` + `AddModuleSourceCallback`
- `FlowEditorPage.storeCapabilities` + `onAddModuleSource`
- `FlowAnalyzer.stepSeverity` + the `kInputsNodeId` /
`kOutputsNodeId` sentinels
- `FlowIssueSeverity` enum + `FlowNode.issueSeverity`
Tests:
- Install fix only when in store
- AddModuleSourceFix as fallback when not in store
- Did-you-mean replaces install when a near miss exists
- stepSeverity populated for both step ids and pseudo-nodes
All 36 editor tests green. Bumped to 0.18.0.
Signed-off-by: flemming-it <sf@flemming.it>
This commit is contained in:
parent
f43c1ac6cf
commit
efdfa7dd79
10 changed files with 497 additions and 45 deletions
|
|
@ -33,6 +33,7 @@
|
|||
// InteractiveViewer.
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_code_editor/flutter_code_editor.dart' show IssueType;
|
||||
|
||||
import '../editor_controller.dart';
|
||||
import '../editor_style.dart';
|
||||
|
|
@ -875,6 +876,13 @@ class _FlowCanvasState extends State<FlowCanvas>
|
|||
outputLabels.length,
|
||||
);
|
||||
final cardWidth = _stepWidth(step);
|
||||
// Analyzer severity for this step — if its YAML carries an
|
||||
// unknown-capability error or a typed-input warning, we
|
||||
// tag the node so FlowNode renders a pulsing halo. The
|
||||
// running pulse takes priority when both are active; the
|
||||
// node never combines run-glow + error-halo on the same
|
||||
// surface (would mush the colour).
|
||||
final issueSeverity = _issueSeverityFor(step.id);
|
||||
return Positioned(
|
||||
left: pos.x,
|
||||
top: pos.y,
|
||||
|
|
@ -891,14 +899,12 @@ class _FlowCanvasState extends State<FlowCanvas>
|
|||
selected: selected,
|
||||
status: status,
|
||||
elevated: _style.nodeShadows,
|
||||
// Breathing-pulse on running steps when the active
|
||||
// style allows flow animation. The canvas's existing
|
||||
// _flowAnim ticks 0..1 during runs and is gated on
|
||||
// the same accessibility / style preferences, so we
|
||||
// can route it straight through.
|
||||
pulse: _style.flowAnimation && status == FlowNodeStatus.running
|
||||
? _flowAnim
|
||||
: null,
|
||||
issueSeverity: status == FlowNodeStatus.running
|
||||
? null
|
||||
: issueSeverity,
|
||||
onTap: () => widget.controller.selectStep(step.id),
|
||||
onDrag: (delta) => _applyDrag(step.id, pos, delta, cardHeight),
|
||||
onContextMenu: (globalPos) => _showStepContextMenu(step, globalPos),
|
||||
|
|
@ -930,10 +936,11 @@ class _FlowCanvasState extends State<FlowCanvas>
|
|||
portSide: portSide,
|
||||
inputPortLabels: labels,
|
||||
selected: selected,
|
||||
// Endpoints are selectable too — selecting opens
|
||||
// the inputs / outputs editor in the properties
|
||||
// panel so the operator can rename, retype, or add
|
||||
// entries graphically instead of editing YAML.
|
||||
// Endpoints carry the same issue-halo treatment as
|
||||
// step nodes — the analyzer uses `__inputs__` /
|
||||
// `__outputs__` sentinel ids so an `Unknown input type`
|
||||
// warning lights up the matching endpoint card.
|
||||
issueSeverity: _issueSeverityFor(nodeId),
|
||||
onTap: () => widget.controller.selectStep(nodeId),
|
||||
onDrag: (delta) => _applyDrag(
|
||||
nodeId,
|
||||
|
|
@ -945,6 +952,18 @@ class _FlowCanvasState extends State<FlowCanvas>
|
|||
);
|
||||
}
|
||||
|
||||
/// Map the controller's per-step issue severity (from the
|
||||
/// YAML analyzer) onto the FlowNode's enum. Returns null
|
||||
/// when the step has no issues so the node renders normally.
|
||||
FlowIssueSeverity? _issueSeverityFor(String stepId) {
|
||||
final raw = widget.controller.stepIssueSeverity[stepId];
|
||||
return switch (raw) {
|
||||
IssueType.error => FlowIssueSeverity.error,
|
||||
IssueType.warning => FlowIssueSeverity.warning,
|
||||
_ => null,
|
||||
};
|
||||
}
|
||||
|
||||
/// Single drag entry point used by every node on the
|
||||
/// canvas. Converts a screen-space delta to canvas-space
|
||||
/// (via the current InteractiveViewer scale), clamps the
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue