From 8c9cad6d783846cd8de9a75b2a8cae10b708f9b3 Mon Sep 17 00:00:00 2001 From: Chirag Chandrashekhar Date: Wed, 1 Apr 2026 21:03:10 +0530 Subject: [PATCH] fix: cURL paste not updating request tab editors visually (#7610) * fix: cURL paste not updating request tab editors visually Remove the focus-based guard from PR#7098 that blocked editor value updates when the editor had focus. This caused cURL paste to not reflect in the request tab until switching tabs. Editors now always accept incoming prop values and preserve cursor position. Also set cursor to end of new URL after cURL paste using setTimeout. * fix: added optional chaining --------- Co-authored-by: Chirag Chandrashekhar --- .../src/components/CodeEditor/index.js | 16 +++------- .../src/components/MultiLineEditor/index.js | 21 +++++--------- .../RequestPane/QueryEditor/index.js | 13 +++------ .../components/RequestPane/QueryUrl/index.js | 14 +++++++++ .../src/components/SingleLineEditor/index.js | 29 +++++++------------ 5 files changed, 40 insertions(+), 53 deletions(-) diff --git a/packages/bruno-app/src/components/CodeEditor/index.js b/packages/bruno-app/src/components/CodeEditor/index.js index 95eaa8894..9a269c314 100644 --- a/packages/bruno-app/src/components/CodeEditor/index.js +++ b/packages/bruno-app/src/components/CodeEditor/index.js @@ -219,18 +219,10 @@ export default class CodeEditor extends React.Component { CodeMirror.signal(this.editor, 'change', this.editor); } if (this.props.value !== prevProps.value && this.props.value !== this.cachedValue && this.editor) { - // TODO: temporary fix for keeping cursor state when auto save and new line insertion collide PR#7098 - const nextValue = this.props.value ?? ''; - const currentValue = this.editor.getValue(); - // Skip updating only when focused and editable; read-only editors (e.g. response viewer) must always show new value - if (this.editor.hasFocus?.() && currentValue !== nextValue && !this.props.readOnly) { - this.cachedValue = currentValue; - } else { - const cursor = this.editor.getCursor(); - this.cachedValue = nextValue; - this.editor.setValue(nextValue); - this.editor.setCursor(cursor); - } + const cursor = this.editor.getCursor(); + this.cachedValue = String(this?.props?.value ?? ''); + this.editor.setValue(String(this.props.value) || ''); + this.editor.setCursor(cursor); } if (this.editor) { diff --git a/packages/bruno-app/src/components/MultiLineEditor/index.js b/packages/bruno-app/src/components/MultiLineEditor/index.js index 90e375742..45271f2cb 100644 --- a/packages/bruno-app/src/components/MultiLineEditor/index.js +++ b/packages/bruno-app/src/components/MultiLineEditor/index.js @@ -140,20 +140,13 @@ class MultiLineEditor extends Component { this.editor.setOption('readOnly', this.props.readOnly); } if (this.props.value !== prevProps.value && this.props.value !== this.cachedValue && this.editor) { - // TODO: temporary fix for keeping cursor state when auto save and new line insertion collide PR#7098 - const nextValue = String(this.props.value ?? ''); - const currentValue = this.editor.getValue(); - if (this.editor.hasFocus?.() && currentValue !== nextValue) { - this.cachedValue = currentValue; - } else { - const cursor = this.editor.getCursor(); - this.cachedValue = nextValue; - this.editor.setValue(nextValue); - this.editor.setCursor(cursor); - // Re-apply masking after setValue() since it destroys all CodeMirror marks - if (this.maskedEditor && this.maskedEditor.isEnabled()) { - this.maskedEditor.update(); - } + const cursor = this.editor.getCursor(); + this.cachedValue = String(this.props.value); + this.editor.setValue(String(this.props.value) || ''); + this.editor.setCursor(cursor); + // Re-apply masking after setValue() since it destroys all CodeMirror marks + if (this.maskedEditor && this.maskedEditor.isEnabled()) { + this.maskedEditor.update(); } } if (!isEqual(this.props.isSecret, prevProps.isSecret)) { diff --git a/packages/bruno-app/src/components/RequestPane/QueryEditor/index.js b/packages/bruno-app/src/components/RequestPane/QueryEditor/index.js index 6eb9f6f5a..1a936f5a1 100644 --- a/packages/bruno-app/src/components/RequestPane/QueryEditor/index.js +++ b/packages/bruno-app/src/components/RequestPane/QueryEditor/index.js @@ -152,15 +152,10 @@ export default class QueryEditor extends React.Component { CodeMirror.signal(this.editor, 'change', this.editor); } if (this.props.value !== prevProps.value && this.props.value !== this.cachedValue && this.editor) { - // TODO: temporary fix for keeping cursor state when auto save and new line insertion collide PR#7098 - const nextValue = this.props.value ?? ''; - const currentValue = this.editor.getValue(); - if (this.editor.hasFocus?.() && currentValue !== nextValue) { - this.cachedValue = currentValue; - } else { - this.cachedValue = nextValue; - this.editor.setValue(nextValue); - } + const cursor = this.editor.getCursor(); + this.cachedValue = String(this.props.value); + this.editor.setValue(String(this.props.value) || ''); + this.editor.setCursor(cursor); } if (this.props.theme !== prevProps.theme && this.editor) { diff --git a/packages/bruno-app/src/components/RequestPane/QueryUrl/index.js b/packages/bruno-app/src/components/RequestPane/QueryUrl/index.js index f1afcb9b6..2d59cb5e7 100644 --- a/packages/bruno-app/src/components/RequestPane/QueryUrl/index.js +++ b/packages/bruno-app/src/components/RequestPane/QueryUrl/index.js @@ -112,6 +112,13 @@ const QueryUrl = ({ item, collection, handleRun }) => { url: request.url })); + setTimeout(() => { + const editor = editorRef.current?.editor; + if (editor) { + editor.setCursor(0, request.url.length); + } + }, 0); + // Update method dispatch(updateRequestMethod({ method: request.method.toUpperCase(), // Convert to uppercase @@ -194,6 +201,13 @@ const QueryUrl = ({ item, collection, handleRun }) => { }) ); + setTimeout(() => { + const editor = editorRef.current?.editor; + if (editor) { + editor.setCursor(0, request.url.length); + } + }, 0); + // Update method if (request.method) { dispatch( diff --git a/packages/bruno-app/src/components/SingleLineEditor/index.js b/packages/bruno-app/src/components/SingleLineEditor/index.js index 626b7058f..e1f97676c 100644 --- a/packages/bruno-app/src/components/SingleLineEditor/index.js +++ b/packages/bruno-app/src/components/SingleLineEditor/index.js @@ -170,25 +170,18 @@ class SingleLineEditor extends Component { this.editor.setOption('theme', this.props.theme === 'dark' ? 'monokai' : 'default'); } if (this.props.value !== prevProps.value && this.props.value !== this.cachedValue && this.editor) { - // TODO: temporary fix for keeping cursor state when auto save and new line insertion collide PR#7098 - const nextValue = String(this.props.value ?? ''); - const currentValue = this.editor.getValue(); - if (this.editor.hasFocus?.() && currentValue !== nextValue && nextValue !== '') { - this.cachedValue = currentValue; - } else { - const cursor = this.editor.getCursor(); - this.cachedValue = nextValue; - this.editor.setValue(nextValue); - this.editor.setCursor(cursor); - // Re-apply masking after setValue() since it destroys all CodeMirror marks - if (this.maskedEditor && this.maskedEditor.isEnabled()) { - this.maskedEditor.update(); - } + const cursor = this.editor.getCursor(); + this.cachedValue = String(this.props.value); + this.editor.setValue(String(this.props.value) || ''); + this.editor.setCursor(cursor); + // Re-apply masking after setValue() since it destroys all CodeMirror marks + if (this.maskedEditor && this.maskedEditor.isEnabled()) { + this.maskedEditor.update(); + } - // Update newline markers after value change - if (this.props.showNewlineArrow) { - this._updateNewlineMarkers(); - } + // Update newline markers after value change + if (this.props.showNewlineArrow) { + this._updateNewlineMarkers(); } } if (!isEqual(this.props.isSecret, prevProps.isSecret)) {