Add drag reorder and clipboard operations to workflow editing #13

Closed
opened 2026-09-16 10:46:19 +02:00 by morten-olsen · 1 comment
Owner

Context

The workflow editor is intentionally a vertically ordered route with indented branch lanes, not a free-form canvas. Its current move-up/move-down controls make route editing slow, and rebuilding a similarly configured node manually is error-prone.

Scope

  • Add touch-friendly drag-and-drop reordering for action stations in the workflow route. A drag must move a node within its ordered route/lane; it is not a free-positioning canvas feature.
  • Show a clear drag handle and drop affordances that work with the existing single-column route, branch lanes, scrolling, large-font layouts, and accessibility semantics.
  • Preserve the node identity, configuration, and valid topology when reordering. The edit layer must use the existing graph/workflow mutation seam and reject drops that would create an invalid graph or violate route/branch ordering constraints.
  • Add copy, cut, and paste commands to a node's editing affordance.
    • Copy creates an in-app clipboard snapshot without mutating the workflow.
    • Cut places a snapshot in that clipboard and removes the selected node through the existing safe node-removal behavior.
    • Paste inserts a new node at an explicit route/branch insertion point with a fresh node identity.
  • Preserve copied node configuration and internal semantics. Never silently retain an invalid connection or output reference when pasting into a different workflow or route; validate the pasted node in its destination and surface actionable diagnostics for values that need reconfiguration.
  • Keep the clipboard internal to Macros rather than exporting complete workflow-node configuration to the system clipboard. This avoids accidental sharing of sensitive configuration and lets the secret manager enforce its assignment model.
  • Maintain the existing add/remove and branch protections; in particular, paste/cut/reorder must not bypass protection against removing connected switch branches or leave dangling graph connections.

Non-goals

  • Do not add a pan-and-zoom canvas, arbitrary node coordinates, or a second graph-editor interaction model.
  • Do not add multi-node/subgraph selection, copy, or paste in this issue.
  • Do not add undo/redo or cross-device clipboard synchronization in this issue.
  • Do not copy secret material or automatically widen a secret assignment when a node is pasted.

Acceptance

  • A user can drag an action within a valid route/branch lane and observes the route reorder immediately; save and reload preserve the resulting execution order.
  • A drop that would violate workflow graph or branch-ordering rules is unavailable or rejected with an actionable explanation, and leaves the draft unchanged.
  • Copy followed by paste creates an independent new node with a new identity at the chosen insertion point while retaining valid configuration from the source.
  • Cut removes the node through the normal safe-removal path, and paste can place an equivalent new node at a valid destination.
  • Pasting into a context where an output reference, connection, or scoped secret assignment is not valid does not persist a broken workflow; the editor identifies what requires reconfiguration.
  • Clipboard operations do not place workflow configuration or secret material on the Android system clipboard.
  • Focused tests cover route reorder persistence and execution order, safe cut behavior, fresh pasted IDs, destination validation, protected branch behavior, and invalid-drop no-op behavior.
## Context The workflow editor is intentionally a vertically ordered route with indented branch lanes, not a free-form canvas. Its current move-up/move-down controls make route editing slow, and rebuilding a similarly configured node manually is error-prone. ## Scope - Add touch-friendly drag-and-drop reordering for action stations in the workflow route. A drag must move a node within its ordered route/lane; it is not a free-positioning canvas feature. - Show a clear drag handle and drop affordances that work with the existing single-column route, branch lanes, scrolling, large-font layouts, and accessibility semantics. - Preserve the node identity, configuration, and valid topology when reordering. The edit layer must use the existing graph/workflow mutation seam and reject drops that would create an invalid graph or violate route/branch ordering constraints. - Add copy, cut, and paste commands to a node's editing affordance. - Copy creates an in-app clipboard snapshot without mutating the workflow. - Cut places a snapshot in that clipboard and removes the selected node through the existing safe node-removal behavior. - Paste inserts a new node at an explicit route/branch insertion point with a fresh node identity. - Preserve copied node configuration and internal semantics. Never silently retain an invalid connection or output reference when pasting into a different workflow or route; validate the pasted node in its destination and surface actionable diagnostics for values that need reconfiguration. - Keep the clipboard internal to Macros rather than exporting complete workflow-node configuration to the system clipboard. This avoids accidental sharing of sensitive configuration and lets the secret manager enforce its assignment model. - Maintain the existing add/remove and branch protections; in particular, paste/cut/reorder must not bypass protection against removing connected switch branches or leave dangling graph connections. ## Non-goals - Do not add a pan-and-zoom canvas, arbitrary node coordinates, or a second graph-editor interaction model. - Do not add multi-node/subgraph selection, copy, or paste in this issue. - Do not add undo/redo or cross-device clipboard synchronization in this issue. - Do not copy secret material or automatically widen a secret assignment when a node is pasted. ## Acceptance - A user can drag an action within a valid route/branch lane and observes the route reorder immediately; save and reload preserve the resulting execution order. - A drop that would violate workflow graph or branch-ordering rules is unavailable or rejected with an actionable explanation, and leaves the draft unchanged. - Copy followed by paste creates an independent new node with a new identity at the chosen insertion point while retaining valid configuration from the source. - Cut removes the node through the normal safe-removal path, and paste can place an equivalent new node at a valid destination. - Pasting into a context where an output reference, connection, or scoped secret assignment is not valid does not persist a broken workflow; the editor identifies what requires reconfiguration. - Clipboard operations do not place workflow configuration or secret material on the Android system clipboard. - Focused tests cover route reorder persistence and execution order, safe cut behavior, fresh pasted IDs, destination validation, protected branch behavior, and invalid-drop no-op behavior.
Author
Owner

Implemented in e4f3978 (committed locally, push blocked on a 1Password approval). Delivered together with #25 and #26, which share the same foundation.

Route projection. WorkflowRoute projects the graph as a trunk of steps with a lane per branch port; structural editing is now a list operation on a lane (withActionAt, withStepMoved, withoutStep, withPastedStep), and every op returns RouteEdit.Applied(workflow, notices) or RouteEdit.Rejected(reason) so a refusal is explained rather than absorbed. Edges the projection does not describe are preserved untouched, and steps no trigger reaches are surfaced as "NOT ON THE ROUTE" instead of being hidden.

Drag reordering. MacrosDraggableStep / rememberLaneDragState in the design system: long-press on a handle (so the route still scrolls), tonal lift, drop-line marking the target gap, edge auto-scroll, targets resolved from real measured row heights for large-font layouts, clamped to the lane. The drag is always a move within one lane, per the one-handed route rule; Move up / Move down stay in the overflow menu as the accessible path.

Clipboard. Copy / Cut / Paste on each step plus a Paste control at each lane end. The clipboard is in-app state (MacrosUiState.clipboard), never Android's system clipboard. Paste mints a fresh node identity, keeps configuration the destination can honour, and clears values whose source is not upstream — naming each one ("… needs a source on this route"); a pasted switch keeps its rule IDs so its lanes survive, with conditions reset if they referenced unavailable outputs. Cut goes through the ordinary safe-removal path, so a switch still holding branch steps refuses and says so.

Non-goals respected: no canvas, no multi-node selection, no undo/redo, no cross-device clipboard, no secret copying.

Verification. task ci:quality green. Engine tests in WorkflowRouteTest cover projection, join insertion, in-lane reorder persistence, invalid-drop no-op, protected branch removal, fresh pasted IDs and destination repair; DefaultAutomationEngineTest covers join execution. On emulator-5554: dragged a step within a branch lane, reordered the trunk, refused an invalid move with an explanation, copied a step and pasted it into the fallback lane, added a step after the switch, then saved, reopened and ran the automation to Completed.

Implemented in `e4f3978` (committed locally, push blocked on a 1Password approval). Delivered together with #25 and #26, which share the same foundation. **Route projection.** `WorkflowRoute` projects the graph as a trunk of steps with a lane per branch port; structural editing is now a list operation on a lane (`withActionAt`, `withStepMoved`, `withoutStep`, `withPastedStep`), and every op returns `RouteEdit.Applied(workflow, notices)` or `RouteEdit.Rejected(reason)` so a refusal is explained rather than absorbed. Edges the projection does not describe are preserved untouched, and steps no trigger reaches are surfaced as "NOT ON THE ROUTE" instead of being hidden. **Drag reordering.** `MacrosDraggableStep` / `rememberLaneDragState` in the design system: long-press on a handle (so the route still scrolls), tonal lift, drop-line marking the target gap, edge auto-scroll, targets resolved from real measured row heights for large-font layouts, clamped to the lane. The drag is always a move within one lane, per the one-handed route rule; Move up / Move down stay in the overflow menu as the accessible path. **Clipboard.** Copy / Cut / Paste on each step plus a **Paste** control at each lane end. The clipboard is in-app state (`MacrosUiState.clipboard`), never Android's system clipboard. Paste mints a fresh node identity, keeps configuration the destination can honour, and clears values whose source is not upstream — naming each one ("… needs a source on this route"); a pasted switch keeps its rule IDs so its lanes survive, with conditions reset if they referenced unavailable outputs. Cut goes through the ordinary safe-removal path, so a switch still holding branch steps refuses and says so. Non-goals respected: no canvas, no multi-node selection, no undo/redo, no cross-device clipboard, no secret copying. **Verification.** `task ci:quality` green. Engine tests in `WorkflowRouteTest` cover projection, join insertion, in-lane reorder persistence, invalid-drop no-op, protected branch removal, fresh pasted IDs and destination repair; `DefaultAutomationEngineTest` covers join execution. On emulator-5554: dragged a step within a branch lane, reordered the trunk, refused an invalid move with an explanation, copied a step and pasted it into the fallback lane, added a step after the switch, then saved, reopened and ran the automation to Completed.
Sign in to join this conversation.
No labels
bug
enhancement
feature
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
incubator/macros#13
No description provided.