Skip to content

feat(search-replace): search & replace, cut, deploy modal ui flicker#4507

Merged
icecrasher321 merged 12 commits intostagingfrom
feat/search-replace
May 8, 2026
Merged

feat(search-replace): search & replace, cut, deploy modal ui flicker#4507
icecrasher321 merged 12 commits intostagingfrom
feat/search-replace

Conversation

@icecrasher321
Copy link
Copy Markdown
Collaborator

@icecrasher321 icecrasher321 commented May 8, 2026

Summary

  • Search and Replace (Ctrl/Cmd F)
  • Cut (Ctrl/Cmd X)
  • Deploy Modal state UI flicker
  • Source code param should be "display resolved" code for useful traces/error messages

Type of Change

  • New feature

Testing

Tested manually

Checklist

  • Code follows project style guidelines
  • Self-reviewed my changes
  • Tests added/updated and passing
  • No new warnings introduced
  • I confirm that I have read and agree to the terms outlined in the Contributor License Agreement (CLA)

@vercel
Copy link
Copy Markdown

vercel Bot commented May 8, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

1 Skipped Deployment
Project Deployment Actions Updated (UTC)
docs Skipped Skipped May 8, 2026 3:17am

Request Review

@cursor
Copy link
Copy Markdown

cursor Bot commented May 8, 2026

PR Summary

Medium Risk
Adds new collaborative subblock-batch-update DB/socket operation (with optimistic expected-value checks) and wires it into undo/redo, which could affect concurrent edits and data consistency if edge cases are missed. UI shortcut remaps and deploy-button behavior changes are lower risk but touch frequently used interactions.

Overview
Adds an in-workflow Search and replace panel (opened via Mod+F or canvas context menu) that indexes text plus structured references (env vars, workflow refs, OAuth/KB/selector resources), navigates to the matched editor field, and applies replacements with validation, dependency clears, and locked/snapshot read-only handling.

Introduces a new realtime SUBBLOCK_OPERATIONS.BATCH_UPDATE / subblock-batch-update operation end-to-end: protocol schema + permissions, server-side transactional updates with lock/parent-lock guards and optional expectedValue conflict detection, client-side collaborative application, and undo/redo support.

Adds Cut support for blocks (Mod+X + block context menu), respecting protected/locked blocks, and tweaks deploy UI to avoid “syncing” flicker by adjusting disabled/labeling behavior and blocked messaging.

Reviewed by Cursor Bugbot for commit 304c50c. Configure here.

@greptile-apps
Copy link
Copy Markdown
Contributor

greptile-apps Bot commented May 8, 2026

Greptile Summary

This PR adds a floating Search & Replace panel (Cmd/Ctrl+F), a Cut operation (Cmd/Ctrl+X) with protected-block awareness, and fixes UI flicker in the deploy modal by removing the intermediate "Syncing" state. It is a large feature addition (~4500 lines) backed by a new search-replace library, Zustand store, collaborative batch-subblock operation, and unified undo/redo entry type.

  • Search & Replace: new indexWorkflowSearchMatches / buildWorkflowSearchReplacePlan pipeline with support for text, inline references (env vars, workflow refs), and structured resources (OAuth, knowledge base, selectors); replacement is applied atomically via collaborativeBatchSetSubblockValues with a single BATCH_UPDATE_SUBBLOCKS undo entry covering both subblock and subflow changes.
  • Cut: cutBlocksWithProtection mirrors the existing delete path — filters locked ancestors, copies non-protected blocks to clipboard, then batch-removes them; keyboard handler guards against active text selection.
  • Deploy modal: removes the isSyncing prop and the loading spinner; during settling the button now opens the modal instead of being disabled, eliminating the flicker.

Confidence Score: 5/5

The change is safe to merge; all three features are well-isolated and the collaborative plumbing follows established patterns throughout the codebase.

The core replacement pipeline builds a conflict-checked plan before touching any state, undo/redo inverse operations are correctly mirrored, and the server-side handler gates on the full ancestry lock chain via the shared isWorkflowBlockProtected. The only findings are a performance note and two minor style concerns; none affect correctness or data integrity.

apps/realtime/src/database/operations.ts — the new handleSubblockOperationTx is worth a second look for query batching on large replace-all operations.

Important Files Changed

Filename Overview
apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/search-replace/workflow-search-replace.tsx New Search & Replace panel component; replacement plan build, conflict detection, and undo integration look correct; isApplying guard is a no-op due to React 18 batching
apps/realtime/src/database/operations.ts Adds handleSubblockOperationTx for BATCH_UPDATE; consolidates isDbBlockProtected to shared isWorkflowBlockProtected; N+1 DB writes per subblock within the same transaction is a performance concern for large replacements
apps/sim/lib/workflows/search-replace/replacements.ts Core replacement planning logic; descending-offset ordering prevents range drift; comma-join without space in replaceStructuredValue alters stored format of comma-separated strings
apps/sim/hooks/use-collaborative-workflow.ts Adds collaborativeBatchSetSubblockValues and incoming BATCH_UPDATE handler; undo recording and socket queue integration follow established patterns
apps/sim/hooks/use-undo-redo.ts Adds recordBatchUpdateSubblocks, applyBatchFieldUndoRedo, and applySubflowUndoRedoUpdate; inverse operations and undo/redo cases look correctly mirrored
apps/sim/lib/workflows/search-replace/indexer.ts Match indexing for text, inline references, and structured resource references; structured metadata leaf filtering via STRUCTURED_METADATA_LEAF_KEYS is correct
apps/sim/app/workspace/[workspaceId]/w/[workflowId]/workflow.tsx Integrates WorkflowSearchReplace panel, adds Cut (Ctrl+X) handling with protected-block filtering, and refactors context-delete into shared removeBlocksWithProtection
apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/deploy/deploy.tsx Removes settling-state loader and stale button variant logic; allows opening the modal during deployment settling instead of blocking it; cleaner UX with no regression risk
apps/sim/executor/variables/resolver.ts Adds FUNCTION_BLOCK_DISPLAY_CODE_KEY and formatDisplayValueForCodeContext to produce correct shell-escaped display code for function blocks; logic reuses existing getShellQuoteContext
apps/realtime/src/handlers/subblocks.ts Replaces local one-level parent lock check with full ancestry traversal via isWorkflowBlockProtected; correctly fetches all workflow blocks in one query
apps/sim/stores/panel/editor/store.ts Adds activeSearchTarget for highlighting; correctly excluded from partialize so it remains ephemeral and will not cause stale-scroll on page reload

Sequence Diagram

sequenceDiagram
    participant U as User (Cmd+F)
    participant Panel as WorkflowSearchReplace
    participant Indexer as indexWorkflowSearchMatches
    participant Planner as buildWorkflowSearchReplacePlan
    participant Collab as collaborativeBatchSetSubblockValues
    participant UndoRedo as recordBatchUpdateSubblocks
    participant Queue as OperationQueue
    participant Server as handleSubblockOperationTx (DB)
    participant Other as Other Clients

    U->>Panel: open panel / type query
    Panel->>Indexer: index matches (text + resources)
    Indexer-->>Panel: WorkflowSearchMatch[]
    Panel->>Panel: hydrate resource labels (react-query)
    U->>Panel: click Replace / Replace All
    Panel->>Planner: buildWorkflowSearchReplacePlan(blocks, matches, ids)
    Planner-->>Panel: "{updates, subflowUpdates, conflicts}"
    alt conflicts present
        Panel-->>U: error notification
    else no conflicts
        Panel->>Collab: "collaborativeBatchSetSubblockValues(updates, {subflowUpdates})"
        Collab->>Collab: apply to SubBlockStore + WorkflowStore (local)
        Collab->>Queue: enqueue SUBBLOCK.BATCH_UPDATE
        Collab->>UndoRedo: recordBatchUpdateSubblocks(updates, subflowUpdates)
        Panel->>Panel: applySubflowUpdate per subflowUpdate
        Queue->>Server: persist BATCH_UPDATE in DB transaction
        Server-->>Queue: ack / error (rolls back on lock/mismatch)
        Queue->>Other: broadcast SUBBLOCK.BATCH_UPDATE
        Other->>Other: apply updates locally
    end
Loading

Reviews (4): Last reviewed commit: "fix padding" | Re-trigger Greptile

Comment thread apps/realtime/src/database/operations.ts Outdated
@icecrasher321
Copy link
Copy Markdown
Collaborator Author

@greptile

Comment thread apps/realtime/src/database/operations.ts
@icecrasher321
Copy link
Copy Markdown
Collaborator Author

@greptile

@icecrasher321
Copy link
Copy Markdown
Collaborator Author

@greptile

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant