diff --git a/packages/insomnia-app/app/ui/components/dropdowns/preview-mode-dropdown.tsx b/packages/insomnia-app/app/ui/components/dropdowns/preview-mode-dropdown.tsx index b5334757f1..d20ab1394b 100644 --- a/packages/insomnia-app/app/ui/components/dropdowns/preview-mode-dropdown.tsx +++ b/packages/insomnia-app/app/ui/components/dropdowns/preview-mode-dropdown.tsx @@ -7,6 +7,7 @@ import { Dropdown, DropdownButton, DropdownDivider, DropdownItem } from '../base interface Props { download: (pretty: boolean) => any; fullDownload: (pretty: boolean) => any; + copyToClipboard: () => any; updatePreviewMode: Function; previewMode: string; showPrettifyOption?: boolean; @@ -29,6 +30,11 @@ class PreviewModeDropdown extends PureComponent { download(false); } + async _handleCopyRawResponse() { + const { copyToClipboard } = this.props; + copyToClipboard(); + } + renderPreviewMode(mode: string) { const { previewMode } = this.props; return ( @@ -50,6 +56,10 @@ class PreviewModeDropdown extends PureComponent { Preview Mode {PREVIEW_MODES.map(this.renderPreviewMode)} Actions + + + Copy raw response + Save Raw Response diff --git a/packages/insomnia-app/app/ui/components/panes/response-pane.tsx b/packages/insomnia-app/app/ui/components/panes/response-pane.tsx index 77e1ec7de0..77caabd356 100644 --- a/packages/insomnia-app/app/ui/components/panes/response-pane.tsx +++ b/packages/insomnia-app/app/ui/components/panes/response-pane.tsx @@ -1,6 +1,6 @@ import { autoBindMethodsForReact } from 'class-autobind-decorator'; import classnames from 'classnames'; -import { remote } from 'electron'; +import { clipboard, remote } from 'electron'; import fs from 'fs'; import { json as jsonPrettify } from 'insomnia-prettify'; import mime from 'mime-types'; @@ -167,6 +167,17 @@ class ResponsePane extends PureComponent { } } + async _handleCopyResponseToClipboard() { + if (!this.props.response) { + return; + } + + const bodyBuffer = models.response.getBodyBuffer(this.props.response); + if (bodyBuffer) { + clipboard.writeText(bodyBuffer.toString('utf8')); + } + } + _handleTabSelect(index: number, lastIndex: number) { if (this._responseViewer != null && index === 0 && index !== lastIndex) { // Fix for CodeMirror editor not updating its content. @@ -257,6 +268,7 @@ class ResponsePane extends PureComponent { previewMode={previewMode} updatePreviewMode={handleSetPreviewMode} showPrettifyOption={response.contentType.includes('json')} + copyToClipboard={this._handleCopyResponseToClipboard} /> diff --git a/packages/insomnia-app/app/ui/components/viewers/response-viewer.tsx b/packages/insomnia-app/app/ui/components/viewers/response-viewer.tsx index deb859a762..724b9fc73d 100644 --- a/packages/insomnia-app/app/ui/components/viewers/response-viewer.tsx +++ b/packages/insomnia-app/app/ui/components/viewers/response-viewer.tsx @@ -47,6 +47,8 @@ interface State { blockingBecauseTooLarge: boolean; bodyBuffer: Buffer | null; error: string; + hugeResponse: boolean; + largeResponse: boolean; } @autoBindMethodsForReact(AUTOBIND_CFG) @@ -57,6 +59,8 @@ class ResponseViewer extends Component { blockingBecauseTooLarge: false, bodyBuffer: null, error: '', + hugeResponse: false, + largeResponse: false, }; refresh() { @@ -91,13 +95,15 @@ class ResponseViewer extends Component { } _maybeLoadResponseBody(props: Props, forceShow?: boolean) { - // Block the response if it's too large - const responseIsTooLarge = props.bytes > LARGE_RESPONSE_MB * 1024 * 1024; + const { bytes } = props; + const largeResponse = bytes > LARGE_RESPONSE_MB * 1024 * 1024; + const hugeResponse = bytes > HUGE_RESPONSE_MB * 1024 * 1024; - if (!forceShow && !alwaysShowLargeResponses && responseIsTooLarge) { - this.setState({ - blockingBecauseTooLarge: true, - }); + this.setState({ largeResponse, hugeResponse }); + + // Block the response if it's too large + if (!forceShow && !alwaysShowLargeResponses && largeResponse) { + this.setState({ blockingBecauseTooLarge: true }); } else { try { const bodyBuffer = props.getBody(); @@ -193,13 +199,14 @@ class ResponseViewer extends Component { this._selectableView?.focus(); - this._selectableView?.selectAll(); + if (!this.state.largeResponse) { + this._selectableView?.selectAll(); + } }); } _renderView() { const { - bytes, disableHtmlPreviewJs, disablePreviewLinks, download, @@ -227,13 +234,12 @@ class ResponseViewer extends Component { ); } - const wayTooLarge = bytes > HUGE_RESPONSE_MB * 1024 * 1024; - const { blockingBecauseTooLarge } = this.state; + const { blockingBecauseTooLarge, hugeResponse } = this.state; if (blockingBecauseTooLarge) { return (
- {wayTooLarge ? ( + {hugeResponse ? (

Responses over {HUGE_RESPONSE_MB}MB cannot be shown