Skip to content
Original file line number Diff line number Diff line change
Expand Up @@ -169,6 +169,9 @@ export function WorkflowSearchReplace() {
setActiveMatchId: state.setActiveMatchId,
}))
)
const prevQueryRef = useRef(query)
const prevIsOpenRef = useRef(false)
const afterReplaceIndexRef = useRef<number | null>(null)
const { data: workspaceCredentials } = useWorkspaceCredentials({ workspaceId, enabled: isOpen })

useRegisterGlobalCommands([
Expand Down Expand Up @@ -248,10 +251,7 @@ export function WorkflowSearchReplace() {
)

useEffect(() => {
if (!isOpen) {
usePanelEditorSearchStore.getState().setActiveSearchTarget(null)
return
}
if (!isOpen) return
searchInputRef.current?.focus()
searchInputRef.current?.select()
}, [isOpen])
Expand Down Expand Up @@ -311,10 +311,7 @@ export function WorkflowSearchReplace() {

return []
}, [activeMatch, hydratedMatches])
const eligibleMatchIds = useMemo(
() => replaceAllTargetMatches.map((match) => match.id),
[replaceAllTargetMatches]
)
const eligibleMatchIds = replaceAllTargetMatches.map((match) => match.id)
const controlTargetMatches = activeMatch ? [activeMatch] : []
const usesResourceReplacement = controlTargetMatches.some(isConstrainedResourceMatch)
const resourceReplacementContextKey =
Expand All @@ -324,23 +321,20 @@ export function WorkflowSearchReplace() {
const replacement = resourceReplacementContextKey
? (resourceReplacementByContext[resourceReplacementContextKey] ?? '')
: textReplacement
const handleReplacementChange = useCallback(
(nextReplacement: string) => {
if (!resourceReplacementContextKey) {
setReplacement(nextReplacement)
return
}
const handleReplacementChange = (nextReplacement: string) => {
if (!resourceReplacementContextKey) {
setReplacement(nextReplacement)
return
}

setResourceReplacementByContext((current) => ({
...current,
[resourceReplacementContextKey]: nextReplacement,
}))
},
[resourceReplacementContextKey, setReplacement]
)
const compatibleResourceOptions = useMemo(
() => getCompatibleResourceReplacementOptions(controlTargetMatches, resourceOptions),
[controlTargetMatches, resourceOptions]
setResourceReplacementByContext((current) => ({
...current,
[resourceReplacementContextKey]: nextReplacement,
}))
}
const compatibleResourceOptions = getCompatibleResourceReplacementOptions(
controlTargetMatches,
resourceOptions
)
const hasReplacement = replacement.trim().length > 0
const activeReplacementIssue = activeMatch
Expand All @@ -359,34 +353,51 @@ export function WorkflowSearchReplace() {
})
: 'No replaceable matches.'

const applySubflowUpdate = useCallback(
(update: WorkflowSearchReplaceSubflowUpdate) => {
if (update.fieldId === WORKFLOW_SEARCH_SUBFLOW_FIELD_IDS.iterations) {
if (typeof update.nextValue !== 'number') return
collaborativeUpdateIterationCount(update.blockId, update.blockType, update.nextValue)
return
}
const applySubflowUpdate = (update: WorkflowSearchReplaceSubflowUpdate) => {
if (update.fieldId === WORKFLOW_SEARCH_SUBFLOW_FIELD_IDS.iterations) {
if (typeof update.nextValue !== 'number') return
collaborativeUpdateIterationCount(update.blockId, update.blockType, update.nextValue)
return
}

collaborativeUpdateIterationCollection(
update.blockId,
update.blockType,
String(update.nextValue)
)
},
[collaborativeUpdateIterationCollection, collaborativeUpdateIterationCount]
)
collaborativeUpdateIterationCollection(
update.blockId,
update.blockType,
String(update.nextValue)
)
}

useEffect(() => {
if (!isOpen) return
if (!isOpen) {
prevIsOpenRef.current = false
usePanelEditorSearchStore.getState().setActiveSearchTarget(null)
return
}
Comment thread
waleedlatif1 marked this conversation as resolved.

const justOpened = !prevIsOpenRef.current
prevIsOpenRef.current = true
const queryChanged = prevQueryRef.current !== query
prevQueryRef.current = query

if (hydratedMatches.length === 0) {
afterReplaceIndexRef.current = null
if (activeMatchId) setActiveMatchId(null)
usePanelEditorSearchStore.getState().setActiveSearchTarget(null)
return
}

if (!activeMatchId || !hydratedMatches.some((match) => match.id === activeMatchId)) {
handleSelectMatch(hydratedMatches[0].id)
const replaceIndex = afterReplaceIndexRef.current
afterReplaceIndexRef.current = null

if (queryChanged || justOpened) {
handleSelectMatch(hydratedMatches[0].id)
Comment thread
waleedlatif1 marked this conversation as resolved.
} else if (replaceIndex !== null) {
handleSelectMatch(hydratedMatches[Math.min(replaceIndex, hydratedMatches.length - 1)].id)
} else {
setActiveMatchId(null)
usePanelEditorSearchStore.getState().setActiveSearchTarget(null)
}
return
}

Expand All @@ -401,14 +412,19 @@ export function WorkflowSearchReplace() {

const handleMoveActiveMatch = (delta: number) => {
if (hydratedMatches.length === 0) return
const currentIndex = activeMatchIndex >= 0 ? activeMatchIndex : 0
const nextIndex = (currentIndex + delta + hydratedMatches.length) % hydratedMatches.length
if (activeMatchIndex < 0) {
handleSelectMatch(hydratedMatches[delta > 0 ? 0 : hydratedMatches.length - 1].id)
return
}
const nextIndex = (activeMatchIndex + delta + hydratedMatches.length) % hydratedMatches.length
handleSelectMatch(hydratedMatches[nextIndex].id)
}

const handleApply = (matchIds: string[]) => {
const handleApply = (matchIds: string[], replaceActiveIndex?: number) => {
if (!workflowId || isApplying || searchReadOnly) return
if (replaceActiveIndex !== undefined) afterReplaceIndexRef.current = replaceActiveIndex
setIsApplying(true)
let committed = false

try {
const selectedIds = new Set(matchIds)
Expand Down Expand Up @@ -505,14 +521,16 @@ export function WorkflowSearchReplace() {
message: `Replaced ${replacedCount} field${replacedCount === 1 ? '' : 's'}.`,
workflowId,
})
committed = true
} finally {
setIsApplying(false)
if (!committed) afterReplaceIndexRef.current = null
}
}

const handleReplaceActive = () => {
if (!activeMatch) return
handleApply([activeMatch.id])
handleApply([activeMatch.id], activeMatchIndex)
}
Comment thread
waleedlatif1 marked this conversation as resolved.
Comment thread
waleedlatif1 marked this conversation as resolved.
Comment thread
waleedlatif1 marked this conversation as resolved.

const handleReplaceAll = () => {
Expand All @@ -522,7 +540,9 @@ export function WorkflowSearchReplace() {
const matchCountLabel =
hydratedMatches.length === 0
? 'No results'
: `${activeMatchIndex >= 0 ? activeMatchIndex + 1 : 1} of ${hydratedMatches.length}`
: activeMatchIndex >= 0
? `${activeMatchIndex + 1} of ${hydratedMatches.length}`
: `0 of ${hydratedMatches.length}`
return (
<div
role='dialog'
Expand Down Expand Up @@ -566,7 +586,7 @@ export function WorkflowSearchReplace() {
>
<ChevronRight
className={cn(
'h-[14px] w-[14px] text-[var(--text-icon)] transition-transform',
'size-[14px] text-[var(--text-icon)] transition-transform',
isReplaceExpanded && 'rotate-90'
)}
/>
Expand Down
Loading