mirror of
https://github.com/Kong/insomnia.git
synced 2026-10-25 16:19:20 -04:00
Refactor settings and store timeline separately
This commit is contained in:
1 parent
0601fc9582
commit
dce5f320c3
16 files changed
+424
-657
No files matched your search
@@ -85,7 +85,6 @@ type BaseRequest = {
|
||||
settingDisableRenderRequestBody: boolean,
|
||||
settingEncodeUrl: boolean,
|
||||
settingRebuildPath: boolean,
|
||||
settingMaxTimelineDataSize: number,
|
||||
};
|
||||
|
||||
export type Request = BaseModel & BaseRequest;
|
||||
@@ -109,7 +108,6 @@ export function init(): BaseRequest {
|
||||
settingDisableRenderRequestBody: false,
|
||||
settingEncodeUrl: true,
|
||||
settingRebuildPath: true,
|
||||
settingMaxTimelineDataSize: 1000,
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -37,8 +37,8 @@ type BaseResponse = {
|
||||
bytesContent: number,
|
||||
elapsedTime: number,
|
||||
headers: Array<ResponseHeader>,
|
||||
timeline: Array<ResponseTimelineEntry>,
|
||||
bodyPath: string, // Actual bodies are stored on the filesystem
|
||||
timelinePath: string, // Actual timelines are stored on the filesystem
|
||||
bodyCompression: 'zip' | null | '__NEEDS_MIGRATION__',
|
||||
error: string,
|
||||
requestVersionId: string | null,
|
||||
@@ -61,7 +61,7 @@ export function init(): BaseResponse {
|
||||
bytesContent: -1, // -1 means that it was legacy and this property didn't exist yet
|
||||
elapsedTime: 0,
|
||||
headers: [],
|
||||
timeline: [],
|
||||
timelinePath: '', // Actual timelines are stored on the filesystem
|
||||
bodyPath: '', // Actual bodies are stored on the filesystem
|
||||
bodyCompression: '__NEEDS_MIGRATION__', // For legacy bodies
|
||||
error: '',
|
||||
@@ -76,6 +76,7 @@ export function init(): BaseResponse {
|
||||
export async function migrate(doc: Object) {
|
||||
doc = await migrateBodyToFileSystem(doc);
|
||||
doc = await migrateBodyCompression(doc);
|
||||
doc = await migrateTimelineToFileSystem(doc);
|
||||
return doc;
|
||||
}
|
||||
|
||||
@@ -86,11 +87,12 @@ export async function hookDatabaseInit() {
|
||||
}
|
||||
|
||||
export function hookRemove(doc: Response) {
|
||||
if (!doc.bodyPath) {
|
||||
return;
|
||||
}
|
||||
|
||||
fs.unlinkSync(doc.bodyPath);
|
||||
fs.unlink(doc.bodyPath, () => {
|
||||
console.log(`[response] Delete body ${doc.bodyPath}`);
|
||||
});
|
||||
fs.unlink(doc.timelinePath, () => {
|
||||
console.log(`[response] Delete timeline ${doc.timelinePath}`);
|
||||
});
|
||||
}
|
||||
|
||||
export function getById(id: string) {
|
||||
@@ -160,6 +162,10 @@ export function getBodyBuffer<T>(response: Object, readFailureValue: ?T): Buffer
|
||||
return getBodyBufferFromPath(response.bodyPath || '', response.bodyCompression, readFailureValue);
|
||||
}
|
||||
|
||||
export function getTimeline(response: Object): Array<ResponseTimelineEntry> {
|
||||
return getTimelineFromPath(response.timelinePath || '');
|
||||
}
|
||||
|
||||
function getBodyStreamFromPath<T>(
|
||||
bodyPath: string,
|
||||
compression: string | null,
|
||||
@@ -208,11 +214,25 @@ function getBodyBufferFromPath<T>(
|
||||
}
|
||||
}
|
||||
|
||||
function getTimelineFromPath(timelinePath: string): Array<ResponseTimelineEntry> {
|
||||
// No body, so return empty Buffer
|
||||
if (!timelinePath) {
|
||||
return [];
|
||||
}
|
||||
|
||||
try {
|
||||
const rawBuffer = fs.readFileSync(timelinePath);
|
||||
return JSON.parse(rawBuffer.toString());
|
||||
} catch (err) {
|
||||
console.warn('Failed to read response body', err.message);
|
||||
return [];
|
||||
}
|
||||
}
|
||||
|
||||
async function migrateBodyToFileSystem(doc: Object) {
|
||||
if (doc.hasOwnProperty('body') && doc._id && !doc.bodyPath) {
|
||||
const bodyBuffer = Buffer.from(doc.body, doc.encoding || 'utf8');
|
||||
const root = getDataDirectory();
|
||||
const dir = path.join(root, 'responses');
|
||||
const dir = path.join(getDataDirectory(), 'responses');
|
||||
|
||||
mkdirp.sync(dir);
|
||||
|
||||
@@ -243,23 +263,46 @@ function migrateBodyCompression(doc: Object) {
|
||||
return doc;
|
||||
}
|
||||
|
||||
async function migrateTimelineToFileSystem(doc: Object) {
|
||||
if (doc.hasOwnProperty('timeline') && doc._id && !doc.timelinePath) {
|
||||
const dir = path.join(getDataDirectory(), 'responses');
|
||||
|
||||
mkdirp.sync(dir);
|
||||
const timelineStr = JSON.stringify(doc.timeline, null, '\t');
|
||||
const fsPath = doc.bodyPath + '.timeline';
|
||||
|
||||
try {
|
||||
fs.writeFileSync(fsPath, timelineStr);
|
||||
} catch (err) {
|
||||
console.warn('Failed to write response body to file', err.message);
|
||||
}
|
||||
|
||||
return db.docUpdate(doc, { timelinePath: fsPath });
|
||||
} else {
|
||||
return doc;
|
||||
}
|
||||
}
|
||||
|
||||
export async function cleanDeletedResponses() {
|
||||
const responsesDir = path.join(getDataDirectory(), 'responses');
|
||||
mkdirp.sync(responsesDir);
|
||||
|
||||
let files = fs.readdirSync(responsesDir);
|
||||
const files = fs.readdirSync(responsesDir);
|
||||
if (files.length === 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
let whitelistFiles = (await db.all(type)).map(res => {
|
||||
return res.bodyPath.slice(responsesDir.length + 1);
|
||||
});
|
||||
const whitelistFiles = [];
|
||||
for (const r of await db.all(type)) {
|
||||
whitelistFiles.push(r.bodyPath.slice(responsesDir.length + 1));
|
||||
whitelistFiles.push(r.timelinePath.slice(responsesDir.length + 1));
|
||||
}
|
||||
|
||||
for (let index = 0; index < files.length; index++) {
|
||||
if (whitelistFiles.indexOf(files[index]) === -1) {
|
||||
const bodyPath = path.join(responsesDir, files[index]);
|
||||
fs.unlinkSync(bodyPath);
|
||||
for (const filePath of files) {
|
||||
if (whitelistFiles.indexOf(filePath) >= 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
fs.unlinkSync(path.join(responsesDir, filePath));
|
||||
}
|
||||
}
|
||||
@@ -36,6 +36,7 @@ type BaseSettings = {
|
||||
fontInterface: string | null,
|
||||
fontSize: number,
|
||||
fontVariantLigatures: boolean,
|
||||
maxTimelineDataSizeKB: number,
|
||||
|
||||
// Feature flags
|
||||
enableSyncBeta: boolean,
|
||||
@@ -83,6 +84,7 @@ export function init(): BaseSettings {
|
||||
fontInterface: null,
|
||||
fontSize: 13,
|
||||
fontVariantLigatures: false,
|
||||
maxTimelineDataSizeKB: 10,
|
||||
enableSyncBeta: false,
|
||||
hotKeyRegistry: hotkeys.newDefaultRegistry(),
|
||||
};
|
||||
|
||||
@@ -6,6 +6,7 @@ import type { Settings } from '../models/settings';
|
||||
import type { RenderedRequest } from '../common/render';
|
||||
import { getRenderedRequestAndContext, RENDER_PURPOSE_SEND } from '../common/render';
|
||||
import mkdirp from 'mkdirp';
|
||||
import crypto from 'crypto';
|
||||
import clone from 'clone';
|
||||
import { parse as urlParse, resolve as urlResolve } from 'url';
|
||||
import { Curl } from 'insomnia-libcurl';
|
||||
@@ -56,7 +57,7 @@ import { urlMatchesCertHost } from './url-matches-cert-host';
|
||||
import aws4 from 'aws4';
|
||||
import { buildMultipart } from './multipart';
|
||||
|
||||
export type ResponsePatch = {
|
||||
export type ResponsePatch = {|
|
||||
statusMessage?: string,
|
||||
error?: string,
|
||||
url?: string,
|
||||
@@ -73,8 +74,8 @@ export type ResponsePatch = {
|
||||
parentId?: string,
|
||||
settingStoreCookies?: boolean,
|
||||
settingSendCookies?: boolean,
|
||||
timeline?: Array<ResponseTimelineEntry>,
|
||||
};
|
||||
timelinePath?: string,
|
||||
|};
|
||||
|
||||
// Time since user's last keypress to wait before making the request
|
||||
const MAX_DELAY_TIME = 1000;
|
||||
@@ -117,11 +118,13 @@ export async function _actuallySend(
|
||||
bodyPath: string | null,
|
||||
noPlugins: boolean = false,
|
||||
): Promise<void> {
|
||||
const timelinePath = await storeTimeline(timeline);
|
||||
|
||||
const responsePatchBeforeHooks = Object.assign(
|
||||
({
|
||||
timelinePath,
|
||||
parentId: renderedRequest._id,
|
||||
bodyCompression: null, // Will default to .zip otherwise
|
||||
timeline: timeline,
|
||||
bodyPath: bodyPath || '',
|
||||
settingSendCookies: renderedRequest.settingSendCookies,
|
||||
settingStoreCookies: renderedRequest.settingStoreCookies,
|
||||
@@ -253,7 +256,7 @@ export async function _actuallySend(
|
||||
if (infoType === Curl.info.debug.DATA_OUT) {
|
||||
if (content.length === 0) {
|
||||
// Sometimes this happens, but I'm not sure why. Just ignore it.
|
||||
} else if (content.length < renderedRequest.settingMaxTimelineDataSize) {
|
||||
} else if (content.length / 1024 < settings.maxTimelineDataSizeKB) {
|
||||
addTimeline(name, content);
|
||||
} else {
|
||||
addTimeline(name, `(${describeByteSize(content.length)} hidden)`);
|
||||
@@ -991,6 +994,26 @@ export function _getAwsAuthHeaders(
|
||||
.map(name => ({ name, value: signature.headers[name] }));
|
||||
}
|
||||
|
||||
function storeTimeline(timeline: Array<ResponseTimelineEntry>): Promise<string> {
|
||||
return new Promise((resolve, reject) => {
|
||||
const timelineStr = JSON.stringify(timeline, null, '\t');
|
||||
const timelineHash = crypto
|
||||
.createHash('sha1')
|
||||
.update(timelineStr)
|
||||
.digest('hex');
|
||||
const responsesDir = pathJoin(getDataDirectory(), 'responses');
|
||||
mkdirp.sync(responsesDir);
|
||||
const timelinePath = pathJoin(responsesDir, timelineHash + '.timeline');
|
||||
fs.writeFile(timelinePath, timelineStr, err => {
|
||||
if (err != null) {
|
||||
reject(err);
|
||||
} else {
|
||||
resolve(timelinePath);
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
document.addEventListener('keydown', (e: KeyboardEvent) => {
|
||||
if (e.ctrlKey || e.metaKey || e.altKey) {
|
||||
return;
|
||||
|
||||
@@ -313,67 +313,34 @@ class OneLineEditor extends PureComponent {
|
||||
if (showEditor) {
|
||||
return (
|
||||
<React.Fragment>
|
||||
{isVariableUncovered && (
|
||||
<CodeEditor
|
||||
ref={this._setEditorRef}
|
||||
defaultTabBehavior
|
||||
hideLineNumbers
|
||||
hideScrollbars
|
||||
noMatchBrackets
|
||||
noStyleActiveLine
|
||||
noLint
|
||||
singleLine
|
||||
tabIndex={0}
|
||||
id={id}
|
||||
type={type}
|
||||
mode={syntaxMode}
|
||||
placeholder={placeholder}
|
||||
onPaste={onPaste}
|
||||
onBlur={this._handleEditorBlur}
|
||||
onKeyDown={this._handleKeyDown}
|
||||
onFocus={this._handleEditorFocus}
|
||||
onMouseLeave={this._handleEditorMouseLeave}
|
||||
onChange={onChange}
|
||||
render={render}
|
||||
getRenderContext={getRenderContext}
|
||||
nunjucksPowerUserMode={nunjucksPowerUserMode}
|
||||
getAutocompleteConstants={getAutocompleteConstants}
|
||||
className={classnames('editor--single-line', className)}
|
||||
defaultValue={defaultValue}
|
||||
isVariableUncovered={isVariableUncovered}
|
||||
/>
|
||||
)}
|
||||
|
||||
{!isVariableUncovered && (
|
||||
<CodeEditor
|
||||
ref={this._setEditorRef}
|
||||
defaultTabBehavior
|
||||
hideLineNumbers
|
||||
hideScrollbars
|
||||
noMatchBrackets
|
||||
noStyleActiveLine
|
||||
noLint
|
||||
singleLine
|
||||
tabIndex={0}
|
||||
id={id}
|
||||
type={type}
|
||||
mode={syntaxMode}
|
||||
placeholder={placeholder}
|
||||
onPaste={onPaste}
|
||||
onBlur={this._handleEditorBlur}
|
||||
onKeyDown={this._handleKeyDown}
|
||||
onFocus={this._handleEditorFocus}
|
||||
onMouseLeave={this._handleEditorMouseLeave}
|
||||
onChange={onChange}
|
||||
render={render}
|
||||
getRenderContext={getRenderContext}
|
||||
nunjucksPowerUserMode={nunjucksPowerUserMode}
|
||||
getAutocompleteConstants={getAutocompleteConstants}
|
||||
className={classnames('editor--single-line', className)}
|
||||
defaultValue={defaultValue}
|
||||
isVariableUncovered={isVariableUncovered}
|
||||
/>
|
||||
)}
|
||||
<CodeEditor
|
||||
ref={this._setEditorRef}
|
||||
defaultTabBehavior
|
||||
hideLineNumbers
|
||||
hideScrollbars
|
||||
noMatchBrackets
|
||||
noStyleActiveLine
|
||||
noLint
|
||||
singleLine
|
||||
tabIndex={0}
|
||||
id={id}
|
||||
type={type}
|
||||
mode={syntaxMode}
|
||||
placeholder={placeholder}
|
||||
onPaste={onPaste}
|
||||
onBlur={this._handleEditorBlur}
|
||||
onKeyDown={this._handleKeyDown}
|
||||
onFocus={this._handleEditorFocus}
|
||||
onMouseLeave={this._handleEditorMouseLeave}
|
||||
onChange={onChange}
|
||||
render={render}
|
||||
getRenderContext={getRenderContext}
|
||||
nunjucksPowerUserMode={nunjucksPowerUserMode}
|
||||
getAutocompleteConstants={getAutocompleteConstants}
|
||||
className={classnames('editor--single-line', className)}
|
||||
defaultValue={defaultValue}
|
||||
isVariableUncovered={isVariableUncovered}
|
||||
/>
|
||||
</React.Fragment>
|
||||
);
|
||||
} else {
|
||||
|
||||
@@ -590,56 +590,29 @@ class GraphQLEditor extends React.PureComponent<Props, State> {
|
||||
)}
|
||||
</h2>
|
||||
<div className="graphql-editor__variables">
|
||||
{isVariableUncovered && (
|
||||
<CodeEditor
|
||||
dynamicHeight
|
||||
uniquenessKey={uniquenessKey ? uniquenessKey + '::variables' : undefined}
|
||||
debounceMillis={DEBOUNCE_MILLIS * 4}
|
||||
manualPrettify={false}
|
||||
fontSize={settings.editorFontSize}
|
||||
indentSize={settings.editorIndentSize}
|
||||
keyMap={settings.editorKeyMap}
|
||||
defaultValue={variables}
|
||||
className={className}
|
||||
render={render}
|
||||
getRenderContext={getRenderContext}
|
||||
getAutocompleteConstants={() => Object.keys(variableTypes || {})}
|
||||
lintOptions={{
|
||||
variableToType: variableTypes,
|
||||
}}
|
||||
nunjucksPowerUserMode={settings.nunjucksPowerUserMode}
|
||||
isVariableUncovered={isVariableUncovered}
|
||||
onChange={this._handleVariablesChange}
|
||||
mode="graphql-variables"
|
||||
lineWrapping={settings.editorLineWrapping}
|
||||
placeholder=""
|
||||
/>
|
||||
)}
|
||||
{!isVariableUncovered && (
|
||||
<CodeEditor
|
||||
dynamicHeight
|
||||
uniquenessKey={uniquenessKey ? uniquenessKey + '::variables' : undefined}
|
||||
debounceMillis={DEBOUNCE_MILLIS * 4}
|
||||
manualPrettify={false}
|
||||
fontSize={settings.editorFontSize}
|
||||
indentSize={settings.editorIndentSize}
|
||||
keyMap={settings.editorKeyMap}
|
||||
defaultValue={variables}
|
||||
className={className}
|
||||
render={render}
|
||||
getRenderContext={getRenderContext}
|
||||
getAutocompleteConstants={() => Object.keys(variableTypes || {})}
|
||||
lintOptions={{
|
||||
variableToType: variableTypes,
|
||||
}}
|
||||
nunjucksPowerUserMode={settings.nunjucksPowerUserMode}
|
||||
isVariableUncovered={isVariableUncovered}
|
||||
onChange={this._handleVariablesChange}
|
||||
mode="graphql-variables"
|
||||
lineWrapping={settings.editorLineWrapping}
|
||||
placeholder=""
|
||||
/>
|
||||
)}
|
||||
<CodeEditor
|
||||
dynamicHeight
|
||||
uniquenessKey={uniquenessKey ? uniquenessKey + '::variables' : undefined}
|
||||
debounceMillis={DEBOUNCE_MILLIS * 4}
|
||||
manualPrettify={false}
|
||||
fontSize={settings.editorFontSize}
|
||||
indentSize={settings.editorIndentSize}
|
||||
keyMap={settings.editorKeyMap}
|
||||
defaultValue={variables}
|
||||
className={className}
|
||||
render={render}
|
||||
getRenderContext={getRenderContext}
|
||||
getAutocompleteConstants={() => Object.keys(variableTypes || {})}
|
||||
lintOptions={{
|
||||
variableToType: variableTypes,
|
||||
}}
|
||||
nunjucksPowerUserMode={settings.nunjucksPowerUserMode}
|
||||
isVariableUncovered={isVariableUncovered}
|
||||
onChange={this._handleVariablesChange}
|
||||
mode="graphql-variables"
|
||||
lineWrapping={settings.editorLineWrapping}
|
||||
placeholder=""
|
||||
/>
|
||||
</div>
|
||||
<div className="pane__footer">
|
||||
<button className="pull-right btn btn--compact" onClick={this._handlePrettify}>
|
||||
|
||||
@@ -25,46 +25,24 @@ class RawEditor extends PureComponent {
|
||||
|
||||
return (
|
||||
<React.Fragment>
|
||||
{isVariableUncovered && (
|
||||
<CodeEditor
|
||||
manualPrettify
|
||||
uniquenessKey={uniquenessKey}
|
||||
fontSize={fontSize}
|
||||
indentSize={indentSize}
|
||||
indentWithTabs={indentWithTabs}
|
||||
keyMap={keyMap}
|
||||
defaultValue={content}
|
||||
className={className}
|
||||
render={render}
|
||||
getRenderContext={getRenderContext}
|
||||
nunjucksPowerUserMode={nunjucksPowerUserMode}
|
||||
isVariableUncovered={isVariableUncovered}
|
||||
onChange={onChange}
|
||||
mode={contentType}
|
||||
lineWrapping={lineWrapping}
|
||||
placeholder="..."
|
||||
/>
|
||||
)}
|
||||
{!isVariableUncovered && (
|
||||
<CodeEditor
|
||||
manualPrettify
|
||||
uniquenessKey={uniquenessKey}
|
||||
fontSize={fontSize}
|
||||
indentSize={indentSize}
|
||||
indentWithTabs={indentWithTabs}
|
||||
keyMap={keyMap}
|
||||
defaultValue={content}
|
||||
className={className}
|
||||
render={render}
|
||||
getRenderContext={getRenderContext}
|
||||
nunjucksPowerUserMode={nunjucksPowerUserMode}
|
||||
isVariableUncovered={isVariableUncovered}
|
||||
onChange={onChange}
|
||||
mode={contentType}
|
||||
lineWrapping={lineWrapping}
|
||||
placeholder="..."
|
||||
/>
|
||||
)}
|
||||
<CodeEditor
|
||||
manualPrettify
|
||||
uniquenessKey={uniquenessKey}
|
||||
fontSize={fontSize}
|
||||
indentSize={indentSize}
|
||||
indentWithTabs={indentWithTabs}
|
||||
keyMap={keyMap}
|
||||
defaultValue={content}
|
||||
className={className}
|
||||
render={render}
|
||||
getRenderContext={getRenderContext}
|
||||
nunjucksPowerUserMode={nunjucksPowerUserMode}
|
||||
isVariableUncovered={isVariableUncovered}
|
||||
onChange={onChange}
|
||||
mode={contentType}
|
||||
lineWrapping={lineWrapping}
|
||||
placeholder="..."
|
||||
/>
|
||||
</React.Fragment>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -99,42 +99,22 @@ class EnvironmentEditor extends React.PureComponent<Props, State> {
|
||||
|
||||
return (
|
||||
<div className="environment-editor">
|
||||
{isVariableUncovered && (
|
||||
<CodeEditor
|
||||
ref={this._setEditorRef}
|
||||
autoPrettify
|
||||
fontSize={editorFontSize}
|
||||
indentSize={editorIndentSize}
|
||||
lineWrapping={lineWrapping}
|
||||
keyMap={editorKeyMap}
|
||||
onChange={this._handleChange}
|
||||
defaultValue={JSON.stringify(environment)}
|
||||
nunjucksPowerUserMode={nunjucksPowerUserMode}
|
||||
isVariableUncovered={isVariableUncovered}
|
||||
render={render}
|
||||
getRenderContext={getRenderContext}
|
||||
mode="application/json"
|
||||
{...props}
|
||||
/>
|
||||
)}
|
||||
{!isVariableUncovered && (
|
||||
<CodeEditor
|
||||
ref={this._setEditorRef}
|
||||
autoPrettify
|
||||
fontSize={editorFontSize}
|
||||
indentSize={editorIndentSize}
|
||||
lineWrapping={lineWrapping}
|
||||
keyMap={editorKeyMap}
|
||||
onChange={this._handleChange}
|
||||
defaultValue={JSON.stringify(environment)}
|
||||
nunjucksPowerUserMode={nunjucksPowerUserMode}
|
||||
isVariableUncovered={isVariableUncovered}
|
||||
render={render}
|
||||
getRenderContext={getRenderContext}
|
||||
mode="application/json"
|
||||
{...props}
|
||||
/>
|
||||
)}
|
||||
<CodeEditor
|
||||
ref={this._setEditorRef}
|
||||
autoPrettify
|
||||
fontSize={editorFontSize}
|
||||
indentSize={editorIndentSize}
|
||||
lineWrapping={lineWrapping}
|
||||
keyMap={editorKeyMap}
|
||||
onChange={this._handleChange}
|
||||
defaultValue={JSON.stringify(environment)}
|
||||
nunjucksPowerUserMode={nunjucksPowerUserMode}
|
||||
isVariableUncovered={isVariableUncovered}
|
||||
render={render}
|
||||
getRenderContext={getRenderContext}
|
||||
mode="application/json"
|
||||
{...props}
|
||||
/>
|
||||
{error && <p className="notice error margin">{error}</p>}
|
||||
{!error && warning && <p className="notice warning margin">{warning}</p>}
|
||||
</div>
|
||||
|
||||
@@ -112,32 +112,17 @@ class RequestHeadersEditor extends React.PureComponent<Props> {
|
||||
|
||||
return bulk ? (
|
||||
<div className="tall">
|
||||
{isVariableUncovered && (
|
||||
<CodeEditor
|
||||
getRenderContext={handleGetRenderContext}
|
||||
render={handleRender}
|
||||
nunjucksPowerUserMode={nunjucksPowerUserMode}
|
||||
isVariableUncovered={isVariableUncovered}
|
||||
fontSize={editorFontSize}
|
||||
indentSize={editorIndentSize}
|
||||
lineWrapping={editorLineWrapping}
|
||||
onChange={this._handleBulkUpdate}
|
||||
defaultValue={this._getHeadersString()}
|
||||
/>
|
||||
)}
|
||||
{!isVariableUncovered && (
|
||||
<CodeEditor
|
||||
getRenderContext={handleGetRenderContext}
|
||||
render={handleRender}
|
||||
nunjucksPowerUserMode={nunjucksPowerUserMode}
|
||||
isVariableUncovered={isVariableUncovered}
|
||||
fontSize={editorFontSize}
|
||||
indentSize={editorIndentSize}
|
||||
lineWrapping={editorLineWrapping}
|
||||
onChange={this._handleBulkUpdate}
|
||||
defaultValue={this._getHeadersString()}
|
||||
/>
|
||||
)}
|
||||
<CodeEditor
|
||||
getRenderContext={handleGetRenderContext}
|
||||
render={handleRender}
|
||||
nunjucksPowerUserMode={nunjucksPowerUserMode}
|
||||
isVariableUncovered={isVariableUncovered}
|
||||
fontSize={editorFontSize}
|
||||
indentSize={editorIndentSize}
|
||||
lineWrapping={editorLineWrapping}
|
||||
onChange={this._handleBulkUpdate}
|
||||
defaultValue={this._getHeadersString()}
|
||||
/>
|
||||
</div>
|
||||
) : (
|
||||
<div className="pad-bottom scrollable-container">
|
||||
|
||||
@@ -68,52 +68,27 @@ class MarkdownEditor extends PureComponent {
|
||||
</TabList>
|
||||
<TabPanel className="react-tabs__tab-panel markdown-editor__edit">
|
||||
<div className="form-control form-control--outlined">
|
||||
{isVariableUncovered && (
|
||||
<CodeEditor
|
||||
ref={this._setEditorRef}
|
||||
hideGutters
|
||||
hideLineNumbers
|
||||
dynamicHeight={!tall}
|
||||
manualPrettify
|
||||
noStyleActiveLine
|
||||
mode={mode || 'text/x-markdown'}
|
||||
placeholder={placeholder}
|
||||
debounceMillis={300}
|
||||
keyMap={keyMap}
|
||||
fontSize={fontSize}
|
||||
lineWrapping={lineWrapping}
|
||||
indentSize={indentSize}
|
||||
defaultValue={markdown}
|
||||
render={handleRender}
|
||||
getRenderContext={handleGetRenderContext}
|
||||
nunjucksPowerUserMode={nunjucksPowerUserMode}
|
||||
isVariableUncovered={isVariableUncovered}
|
||||
onChange={this._handleChange}
|
||||
/>
|
||||
)}
|
||||
{!isVariableUncovered && (
|
||||
<CodeEditor
|
||||
ref={this._setEditorRef}
|
||||
hideGutters
|
||||
hideLineNumbers
|
||||
dynamicHeight={!tall}
|
||||
manualPrettify
|
||||
noStyleActiveLine
|
||||
mode={mode || 'text/x-markdown'}
|
||||
placeholder={placeholder}
|
||||
debounceMillis={300}
|
||||
keyMap={keyMap}
|
||||
fontSize={fontSize}
|
||||
lineWrapping={lineWrapping}
|
||||
indentSize={indentSize}
|
||||
defaultValue={markdown}
|
||||
render={handleRender}
|
||||
getRenderContext={handleGetRenderContext}
|
||||
nunjucksPowerUserMode={nunjucksPowerUserMode}
|
||||
isVariableUncovered={isVariableUncovered}
|
||||
onChange={this._handleChange}
|
||||
/>
|
||||
)}
|
||||
<CodeEditor
|
||||
ref={this._setEditorRef}
|
||||
hideGutters
|
||||
hideLineNumbers
|
||||
dynamicHeight={!tall}
|
||||
manualPrettify
|
||||
noStyleActiveLine
|
||||
mode={mode || 'text/x-markdown'}
|
||||
placeholder={placeholder}
|
||||
debounceMillis={300}
|
||||
keyMap={keyMap}
|
||||
fontSize={fontSize}
|
||||
lineWrapping={lineWrapping}
|
||||
indentSize={indentSize}
|
||||
defaultValue={markdown}
|
||||
render={handleRender}
|
||||
getRenderContext={handleGetRenderContext}
|
||||
nunjucksPowerUserMode={nunjucksPowerUserMode}
|
||||
isVariableUncovered={isVariableUncovered}
|
||||
onChange={this._handleChange}
|
||||
/>
|
||||
</div>
|
||||
<div className="txt-sm italic faint">Styling with Markdown is supported</div>
|
||||
</TabPanel>
|
||||
|
||||
@@ -135,42 +135,22 @@ class CodePromptModal extends PureComponent {
|
||||
) : (
|
||||
<div className="pad-sm pad-bottom tall">
|
||||
<div className="form-control form-control--outlined form-control--tall tall">
|
||||
{isVariableUncovered && (
|
||||
<CodeEditor
|
||||
hideLineNumbers
|
||||
className="tall"
|
||||
defaultValue={defaultValue}
|
||||
placeholder={placeholder}
|
||||
onChange={this._handleChange}
|
||||
nunjucksPowerUserMode={nunjucksPowerUserMode}
|
||||
isVariableUncovered={isVariableUncovered}
|
||||
getRenderContext={enableRender ? handleGetRenderContext : null}
|
||||
render={enableRender ? handleRender : null}
|
||||
mode={mode}
|
||||
keyMap={editorKeyMap}
|
||||
indentSize={editorIndentSize}
|
||||
fontSize={editorFontSize}
|
||||
lineWrapping={editorLineWrapping}
|
||||
/>
|
||||
)}
|
||||
{!isVariableUncovered && (
|
||||
<CodeEditor
|
||||
hideLineNumbers
|
||||
className="tall"
|
||||
defaultValue={defaultValue}
|
||||
placeholder={placeholder}
|
||||
onChange={this._handleChange}
|
||||
nunjucksPowerUserMode={nunjucksPowerUserMode}
|
||||
isVariableUncovered={isVariableUncovered}
|
||||
getRenderContext={enableRender ? handleGetRenderContext : null}
|
||||
render={enableRender ? handleRender : null}
|
||||
mode={mode}
|
||||
keyMap={editorKeyMap}
|
||||
indentSize={editorIndentSize}
|
||||
fontSize={editorFontSize}
|
||||
lineWrapping={editorLineWrapping}
|
||||
/>
|
||||
)}
|
||||
<CodeEditor
|
||||
hideLineNumbers
|
||||
className="tall"
|
||||
defaultValue={defaultValue}
|
||||
placeholder={placeholder}
|
||||
onChange={this._handleChange}
|
||||
nunjucksPowerUserMode={nunjucksPowerUserMode}
|
||||
isVariableUncovered={isVariableUncovered}
|
||||
getRenderContext={enableRender ? handleGetRenderContext : null}
|
||||
render={enableRender ? handleRender : null}
|
||||
mode={mode}
|
||||
keyMap={editorKeyMap}
|
||||
indentSize={editorIndentSize}
|
||||
fontSize={editorFontSize}
|
||||
lineWrapping={editorLineWrapping}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
|
||||
@@ -58,7 +58,7 @@ class ResponseDebugModal extends React.PureComponent<Props, State> {
|
||||
editorFontSize={settings.editorFontSize}
|
||||
editorIndentSize={settings.editorIndentSize}
|
||||
editorLineWrapping={settings.editorLineWrapping}
|
||||
timeline={response.timeline}
|
||||
response={response}
|
||||
/>
|
||||
) : (
|
||||
<div>No response found</div>
|
||||
|
||||
@@ -352,7 +352,7 @@ class ResponsePane extends React.PureComponent<Props> {
|
||||
<TabPanel className="react-tabs__tab-panel">
|
||||
<ErrorBoundary key={response._id} errorClassName="font-error pad text-center">
|
||||
<ResponseTimelineViewer
|
||||
timeline={response.timeline || []}
|
||||
response={response}
|
||||
editorLineWrapping={editorLineWrapping}
|
||||
editorFontSize={editorFontSize}
|
||||
editorIndentSize={editorIndentSize}
|
||||
|
||||
@@ -19,6 +19,7 @@ import type { Settings } from '../../../models/settings';
|
||||
import CheckForUpdatesButton from '../check-for-updates-button';
|
||||
import { setFont } from '../../../plugins/misc';
|
||||
import * as session from '../../../account/session';
|
||||
import Tooltip from '../tooltip';
|
||||
|
||||
type Props = {
|
||||
settings: Settings,
|
||||
@@ -69,7 +70,7 @@ class General extends React.PureComponent<Props, State> {
|
||||
this.props.handleToggleMenuBar(settings.autoHideMenuBar);
|
||||
}
|
||||
|
||||
async _handleToggleSyncBeta(e: SyntheticEvent<HTMLInputElement>) {
|
||||
async _handleUpdateSettingAndRestart(e: SyntheticEvent<HTMLInputElement>) {
|
||||
await this._handleUpdateSetting(e);
|
||||
const { app } = electron.remote || electron;
|
||||
app.relaunch();
|
||||
@@ -91,140 +92,91 @@ class General extends React.PureComponent<Props, State> {
|
||||
setFont(settings);
|
||||
}
|
||||
|
||||
renderBooleanSetting(label: string, name: string, help: string, forceRestart?: boolean) {
|
||||
const { settings } = this.props;
|
||||
|
||||
if (!settings.hasOwnProperty(name)) {
|
||||
throw new Error(`Invalid boolean setting name ${name}`);
|
||||
}
|
||||
|
||||
const onChange = forceRestart ? this._handleUpdateSettingAndRestart : this._handleUpdateSetting;
|
||||
|
||||
return (
|
||||
<div className="form-control form-control--thin">
|
||||
<label className="inline-block">
|
||||
{label}
|
||||
{help && (
|
||||
<HelpTooltip className="space-left">
|
||||
Configure the autocomplete popup delay in milliseconds (0 to disable)
|
||||
</HelpTooltip>
|
||||
)}
|
||||
{forceRestart && (
|
||||
<Tooltip message="Will restart app" className="space-left">
|
||||
<i className="fa fa-refresh super-duper-faint" />
|
||||
</Tooltip>
|
||||
)}
|
||||
<input type="checkbox" name={name} checked={settings[name]} onChange={onChange} />
|
||||
</label>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
renderTextSetting(label: string, name: string, help: string, props: Object) {
|
||||
const { settings } = this.props;
|
||||
|
||||
if (!settings.hasOwnProperty(name)) {
|
||||
throw new Error(`Invalid number setting name ${name}`);
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="form-control form-control--outlined">
|
||||
<label>
|
||||
{label}
|
||||
{help && (
|
||||
<HelpTooltip className="space-left">
|
||||
Configure the autocomplete popup delay in milliseconds (0 to disable)
|
||||
</HelpTooltip>
|
||||
)}
|
||||
<input
|
||||
type={props.type || 'text'}
|
||||
name={name}
|
||||
defaultValue={settings[name]}
|
||||
{...props}
|
||||
onChange={props.onChange || this._handleUpdateSetting}
|
||||
/>
|
||||
</label>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
renderNumberSetting(label: string, name: string, help: string, props: Object) {
|
||||
return this.renderTextSetting(label, name, help, { ...props, type: 'number' });
|
||||
}
|
||||
|
||||
render() {
|
||||
const { settings } = this.props;
|
||||
const { fonts } = this.state;
|
||||
return (
|
||||
<div>
|
||||
<div className="form-control form-control--thin">
|
||||
<label className="inline-block">
|
||||
Follow redirects automatically
|
||||
<input
|
||||
type="checkbox"
|
||||
name="followRedirects"
|
||||
checked={settings.followRedirects}
|
||||
onChange={this._handleUpdateSetting}
|
||||
/>
|
||||
</label>
|
||||
</div>
|
||||
|
||||
<div className="form-control form-control--thin">
|
||||
<label className="inline-block">
|
||||
Validate SSL Certificates
|
||||
<input
|
||||
type="checkbox"
|
||||
name="validateSSL"
|
||||
checked={settings.validateSSL}
|
||||
onChange={this._handleUpdateSetting}
|
||||
/>
|
||||
</label>
|
||||
</div>
|
||||
|
||||
<div className="form-control form-control--thin">
|
||||
<label className="inline-block">
|
||||
Show passwords in plain-text
|
||||
<input
|
||||
type="checkbox"
|
||||
name="showPasswords"
|
||||
checked={settings.showPasswords}
|
||||
onChange={this._handleUpdateSetting}
|
||||
/>
|
||||
</label>
|
||||
</div>
|
||||
|
||||
<div className="form-control form-control--thin">
|
||||
<label className="inline-block">
|
||||
Use bulk header editor by default
|
||||
<input
|
||||
type="checkbox"
|
||||
name="useBulkHeaderEditor"
|
||||
checked={settings.useBulkHeaderEditor}
|
||||
onChange={this._handleUpdateSetting}
|
||||
/>
|
||||
</label>
|
||||
</div>
|
||||
|
||||
<div className="form-control form-control--thin">
|
||||
<label className="inline-block">
|
||||
Always use vertical layout
|
||||
<input
|
||||
type="checkbox"
|
||||
name="forceVerticalLayout"
|
||||
checked={settings.forceVerticalLayout}
|
||||
onChange={this._handleUpdateSetting}
|
||||
/>
|
||||
</label>
|
||||
</div>
|
||||
|
||||
{!isMac() && (
|
||||
<div className="form-control form-control--thin">
|
||||
<label className="inline-block">
|
||||
Hide Menu Bar
|
||||
<input
|
||||
type="checkbox"
|
||||
name="autoHideMenuBar"
|
||||
checked={settings.autoHideMenuBar}
|
||||
onChange={this._handleToggleMenuBar}
|
||||
/>
|
||||
</label>
|
||||
<div className="row-fill row-fill--top">
|
||||
<div>
|
||||
{this.renderBooleanSetting('Force bulk header editor', 'useBulkHeaderEditor', '')}
|
||||
{this.renderBooleanSetting(
|
||||
'Vertical request/response layout',
|
||||
'forceVerticalLayout',
|
||||
'',
|
||||
)}
|
||||
</div>
|
||||
<div>
|
||||
{this.renderBooleanSetting('Reveal passwords', 'showPasswords', '')}
|
||||
{!isMac() && this.renderBooleanSetting('Hide menu bar', 'autoHideMenuBar', '')}
|
||||
{this.renderBooleanSetting('Raw template syntax', 'nunjucksPowerUserMode', '', true)}
|
||||
</div>
|
||||
)}
|
||||
|
||||
<div className="form-control form-control--thin">
|
||||
<label className="inline-block">
|
||||
Wrap Long Lines
|
||||
<input
|
||||
type="checkbox"
|
||||
name="editorLineWrapping"
|
||||
checked={settings.editorLineWrapping}
|
||||
onChange={this._handleUpdateSetting}
|
||||
/>
|
||||
</label>
|
||||
</div>
|
||||
|
||||
<div className="form-control form-control--thin">
|
||||
<label className="inline-block">
|
||||
Nunjucks Power User Mode{' '}
|
||||
<HelpTooltip>
|
||||
Disable tag editing interface in favor of raw Nunjucks syntax (requires restart)
|
||||
</HelpTooltip>
|
||||
<input
|
||||
type="checkbox"
|
||||
name="nunjucksPowerUserMode"
|
||||
checked={settings.nunjucksPowerUserMode}
|
||||
onChange={this._handleUpdateSetting}
|
||||
/>
|
||||
</label>
|
||||
</div>
|
||||
|
||||
<div className="form-control form-control--thin">
|
||||
<label className="inline-block">
|
||||
Indent With Tabs
|
||||
<input
|
||||
type="checkbox"
|
||||
name="editorIndentWithTabs"
|
||||
checked={settings.editorIndentWithTabs}
|
||||
onChange={this._handleUpdateSetting}
|
||||
/>
|
||||
</label>
|
||||
</div>
|
||||
|
||||
<div className="form-control form-control--thin">
|
||||
<label className="inline-block">
|
||||
Font Ligatures
|
||||
<input
|
||||
type="checkbox"
|
||||
name="fontVariantLigatures"
|
||||
checked={settings.fontVariantLigatures}
|
||||
onChange={this._handleFontLigatureChange}
|
||||
/>
|
||||
</label>
|
||||
</div>
|
||||
|
||||
<div className="form-row">
|
||||
<div className="form-control form-control--outlined pad-top-sm">
|
||||
<div className="row-fill row-fill--top pad-top-sm">
|
||||
<div className="form-control form-control--outlined">
|
||||
<label>
|
||||
Environment Highlight Color Style{' '}
|
||||
Environment Highlight Style{' '}
|
||||
<HelpTooltip>Configures the appearance of environment's color indicator</HelpTooltip>
|
||||
<select
|
||||
defaultValue={settings.environmentHighlightColorStyle}
|
||||
@@ -239,25 +191,30 @@ class General extends React.PureComponent<Props, State> {
|
||||
</select>
|
||||
</label>
|
||||
</div>
|
||||
<div className="form-control form-control--outlined pad-top-sm">
|
||||
<label>
|
||||
Autocomplete popup delay
|
||||
<HelpTooltip className="space-left">
|
||||
Configure the autocomplete popup delay in milliseconds (0 to disable)
|
||||
</HelpTooltip>
|
||||
<input
|
||||
type="number"
|
||||
name="autocompleteDelay"
|
||||
min={0}
|
||||
max={3000}
|
||||
defaultValue={settings.autocompleteDelay}
|
||||
onChange={this._handleUpdateSetting}
|
||||
/>
|
||||
</label>
|
||||
</div>
|
||||
{this.renderNumberSetting(
|
||||
'Autocomplete popup delay',
|
||||
'autocompleteDelay',
|
||||
'Configure the autocomplete popup delay in milliseconds (0 to disable)',
|
||||
{
|
||||
min: 0,
|
||||
max: 3000,
|
||||
},
|
||||
)}
|
||||
</div>
|
||||
|
||||
<div className="form-row">
|
||||
<hr className="pad-top" />
|
||||
|
||||
<h2>Font</h2>
|
||||
|
||||
<div className="row-fill row-fill--top">
|
||||
<div>
|
||||
{this.renderBooleanSetting('Indent with tabs', 'editorIndentWithTabs', '')}
|
||||
{this.renderBooleanSetting('Wrap text editor lines', 'editorLineWrapping', '')}
|
||||
</div>
|
||||
<div>{this.renderBooleanSetting('Font ligatures', 'fontVariantLigatures', '')}</div>
|
||||
</div>
|
||||
|
||||
<div className="form-row pad-top-sm">
|
||||
<div className="form-control form-control--outlined">
|
||||
<label>
|
||||
Interface Font
|
||||
@@ -280,19 +237,11 @@ class General extends React.PureComponent<Props, State> {
|
||||
)}
|
||||
</label>
|
||||
</div>
|
||||
<div className="form-control form-control--outlined">
|
||||
<label>
|
||||
Interface Font Size (px)
|
||||
<input
|
||||
type="number"
|
||||
name="fontSize"
|
||||
min={8}
|
||||
max={20}
|
||||
defaultValue={settings.fontSize}
|
||||
onChange={this._handleFontSizeChange}
|
||||
/>
|
||||
</label>
|
||||
</div>
|
||||
{this.renderNumberSetting('Interface Font Size (px)', 'fontSize', '', {
|
||||
min: 8,
|
||||
max: 20,
|
||||
onChange: this._handleFontSizeChange,
|
||||
})}
|
||||
</div>
|
||||
|
||||
<div className="form-row">
|
||||
@@ -320,36 +269,17 @@ class General extends React.PureComponent<Props, State> {
|
||||
)}
|
||||
</label>
|
||||
</div>
|
||||
<div className="form-control form-control--outlined">
|
||||
<label>
|
||||
Text Editor Font Size (px)
|
||||
<input
|
||||
type="number"
|
||||
name="editorFontSize"
|
||||
min={8}
|
||||
max={20}
|
||||
defaultValue={settings.editorFontSize}
|
||||
onChange={this._handleUpdateSetting}
|
||||
/>
|
||||
</label>
|
||||
</div>
|
||||
{this.renderNumberSetting('Editor Font Size (px)', 'editorFontSize', '', {
|
||||
min: 8,
|
||||
max: 20,
|
||||
})}
|
||||
</div>
|
||||
|
||||
<div className="form-row">
|
||||
<div className="form-control form-control--outlined">
|
||||
<label>
|
||||
Text Editor Indent Size
|
||||
<input
|
||||
type="number"
|
||||
name="editorIndentSize"
|
||||
min={1}
|
||||
max={16}
|
||||
defaultValue={settings.editorIndentSize}
|
||||
onChange={this._handleUpdateSetting}
|
||||
/>
|
||||
</label>
|
||||
</div>
|
||||
|
||||
{this.renderNumberSetting('Editor Indent Size', 'editorIndentSize', '', {
|
||||
min: 1,
|
||||
max: 16,
|
||||
})}
|
||||
<div className="form-control form-control--outlined">
|
||||
<label>
|
||||
Text Editor Key Map
|
||||
@@ -368,55 +298,24 @@ class General extends React.PureComponent<Props, State> {
|
||||
|
||||
<hr className="pad-top" />
|
||||
|
||||
<h2>Request Settings</h2>
|
||||
<h2>Network</h2>
|
||||
|
||||
<div className="form-row">
|
||||
<div className="form-control form-control--outlined">
|
||||
<label>
|
||||
Maximum Redirects
|
||||
<HelpTooltip className="space-left">(-1 for unlimited)</HelpTooltip>
|
||||
<input
|
||||
type="number"
|
||||
name="maxRedirects"
|
||||
min={-1}
|
||||
defaultValue={settings.maxRedirects}
|
||||
onChange={this._handleUpdateSetting}
|
||||
/>
|
||||
</label>
|
||||
</div>
|
||||
{this.renderBooleanSetting('Validate certificates', 'validateSSL', '')}
|
||||
{this.renderBooleanSetting('Follow redirects', 'followRedirects', '')}
|
||||
|
||||
<div className="form-control form-control--outlined">
|
||||
<label>
|
||||
Network Request Timeout
|
||||
<HelpTooltip className="space-left">
|
||||
Request timeout in milliseconds (0 for no timeout)
|
||||
</HelpTooltip>
|
||||
<input
|
||||
type="number"
|
||||
name="timeout"
|
||||
min={-1}
|
||||
defaultValue={settings.timeout}
|
||||
onChange={this._handleUpdateSetting}
|
||||
/>
|
||||
</label>
|
||||
</div>
|
||||
<div className="form-row pad-top-sm">
|
||||
{this.renderNumberSetting('Maximum Redirects', 'maxRedirects', '-1 for unlimited', {
|
||||
min: -1,
|
||||
})}
|
||||
{this.renderNumberSetting('Request Timeout', 'timeout', '-1 for infinite', { min: -1 })}
|
||||
</div>
|
||||
|
||||
<div className="form-control form-control--outlined">
|
||||
<label>
|
||||
Response History Limit
|
||||
<HelpTooltip className="space-left">
|
||||
Number of responses to keep for each request
|
||||
</HelpTooltip>
|
||||
<input
|
||||
type="number"
|
||||
name="maxHistoryResponses"
|
||||
min={1}
|
||||
defaultValue={settings.maxHistoryResponses}
|
||||
onChange={this._handleUpdateSetting}
|
||||
/>
|
||||
</label>
|
||||
</div>
|
||||
{this.renderNumberSetting(
|
||||
'Response History Limit',
|
||||
'maxHistoryResponses',
|
||||
'Number of responses to keep for each request (-1 for infinity)',
|
||||
{ min: -1 },
|
||||
)}
|
||||
|
||||
<hr className="pad-top" />
|
||||
|
||||
@@ -429,61 +328,26 @@ class General extends React.PureComponent<Props, State> {
|
||||
</HelpTooltip>
|
||||
</h2>
|
||||
|
||||
<div className="form-control form-control--thin">
|
||||
<label className="inline-block">
|
||||
Enable Proxy
|
||||
<input
|
||||
type="checkbox"
|
||||
name="proxyEnabled"
|
||||
checked={settings.proxyEnabled}
|
||||
onChange={this._handleUpdateSetting}
|
||||
/>
|
||||
</label>
|
||||
</div>
|
||||
{this.renderBooleanSetting('Enable proxy', 'proxyEnabled', '')}
|
||||
|
||||
<div className="form-row pad-top-sm">
|
||||
<div className="form-control form-control--outlined">
|
||||
<label>
|
||||
HTTP Proxy
|
||||
<input
|
||||
type="text"
|
||||
name="httpProxy"
|
||||
disabled={!settings.proxyEnabled}
|
||||
placeholder="localhost:8005"
|
||||
defaultValue={settings.httpProxy}
|
||||
onChange={this._handleUpdateSetting}
|
||||
/>
|
||||
</label>
|
||||
</div>
|
||||
<div className="form-control form-control--outlined">
|
||||
<label>
|
||||
HTTPS Proxy
|
||||
<input
|
||||
placeholder="localhost:8005"
|
||||
disabled={!settings.proxyEnabled}
|
||||
name="httpsProxy"
|
||||
type="text"
|
||||
defaultValue={settings.httpsProxy}
|
||||
onChange={this._handleUpdateSetting}
|
||||
/>
|
||||
</label>
|
||||
</div>
|
||||
<div className="form-control form-control--outlined">
|
||||
<label>
|
||||
No Proxy{' '}
|
||||
<HelpTooltip>
|
||||
Comma-separated list of hostnames that do not require a proxy to be contacted
|
||||
</HelpTooltip>
|
||||
<input
|
||||
placeholder="localhost,127.0.0.1"
|
||||
disabled={!settings.proxyEnabled}
|
||||
name="noProxy"
|
||||
type="text"
|
||||
defaultValue={settings.noProxy}
|
||||
onChange={this._handleUpdateSetting}
|
||||
/>
|
||||
</label>
|
||||
</div>
|
||||
{this.renderTextSetting('HTTP Proxy', 'httpProxy', '', {
|
||||
placeholder: 'localhost:8005',
|
||||
disabled: !settings.proxyEnabled,
|
||||
})}
|
||||
{this.renderTextSetting('HTTPS Proxy', 'httpsProxy', '', {
|
||||
placeholder: 'localhost:8005',
|
||||
disabled: !settings.proxyEnabled,
|
||||
})}
|
||||
{this.renderTextSetting(
|
||||
'No Proxy',
|
||||
'noProxy',
|
||||
'Comma-separated list of hostnames that do not require a proxy to be contacted',
|
||||
{
|
||||
placeholder: 'localhost,127.0.0.1',
|
||||
disabled: !settings.proxyEnabled,
|
||||
},
|
||||
)}
|
||||
</div>
|
||||
|
||||
{(isWindows() || isMac()) && (
|
||||
@@ -497,20 +361,11 @@ class General extends React.PureComponent<Props, State> {
|
||||
</div>
|
||||
<h2>Software Updates</h2>
|
||||
</div>
|
||||
<div className="form-control form-control--thin">
|
||||
<label className="inline-block">
|
||||
Automatically download and install updates
|
||||
<HelpTooltip className="space-left">
|
||||
If disabled, you will receive a notification when a new update is available
|
||||
</HelpTooltip>
|
||||
<input
|
||||
type="checkbox"
|
||||
name="updateAutomatically"
|
||||
checked={settings.updateAutomatically}
|
||||
onChange={this._handleUpdateSetting}
|
||||
/>
|
||||
</label>
|
||||
</div>
|
||||
{this.renderBooleanSetting(
|
||||
'Automatically download and install updates',
|
||||
'updateAutomatically',
|
||||
'If disabled, you will receive a notification when a new update is available',
|
||||
)}
|
||||
<div className="form-control form-control--outlined pad-top-sm">
|
||||
<label>
|
||||
Update Channel
|
||||
@@ -530,54 +385,30 @@ class General extends React.PureComponent<Props, State> {
|
||||
<React.Fragment>
|
||||
<hr className="pad-top" />
|
||||
<h2>Software Updates</h2>
|
||||
<div className="form-control form-control--thin">
|
||||
<label className="inline-block">
|
||||
Do not notify of new releases
|
||||
<input
|
||||
type="checkbox"
|
||||
name="disableUpdateNotification"
|
||||
checked={settings.disableUpdateNotification}
|
||||
onChange={this._handleUpdateSetting}
|
||||
/>
|
||||
</label>
|
||||
</div>
|
||||
{this.renderBooleanSetting(
|
||||
'Do not notify of new releases',
|
||||
'disableUpdateNotification',
|
||||
'',
|
||||
)}
|
||||
</React.Fragment>
|
||||
)}
|
||||
|
||||
<hr className="pad-top" />
|
||||
<h2>Plugins</h2>
|
||||
|
||||
<div className="form-control form-control--outlined">
|
||||
<label>
|
||||
Additional Plugin Path{' '}
|
||||
<HelpTooltip>Tell Insomnia to look for plugins in a different directory</HelpTooltip>
|
||||
<input
|
||||
placeholder="~/.insomnia:/other/path"
|
||||
name="pluginPath"
|
||||
type="text"
|
||||
defaultValue={settings.pluginPath}
|
||||
onChange={this._handleUpdateSetting}
|
||||
/>
|
||||
</label>
|
||||
</div>
|
||||
{this.renderTextSetting(
|
||||
'Additional Plugin Path',
|
||||
'pluginPath',
|
||||
'Tell Insomnia to look for plugins in a different directory',
|
||||
{ placeholder: '~/.insomnia:/other/path' },
|
||||
)}
|
||||
|
||||
<br />
|
||||
|
||||
{session.isLoggedIn() && (
|
||||
<React.Fragment>
|
||||
<hr />
|
||||
<div className="form-control form-control--thin">
|
||||
<label className="inline-block">
|
||||
Enable sync beta (will restart app){' '}
|
||||
<HelpTooltip>Enable the new sync beta features</HelpTooltip>
|
||||
<input
|
||||
type="checkbox"
|
||||
name="enableSyncBeta"
|
||||
checked={settings.enableSyncBeta}
|
||||
onChange={this._handleToggleSyncBeta}
|
||||
/>
|
||||
</label>
|
||||
</div>
|
||||
{this.renderBooleanSetting('Enable version control beta', 'enableSyncBeta', '', true)}
|
||||
</React.Fragment>
|
||||
)}
|
||||
</div>
|
||||
|
||||
@@ -2,12 +2,38 @@ import React, { PureComponent } from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { shell } from 'electron';
|
||||
import CodeEditor from '../codemirror/code-editor';
|
||||
import * as models from '../../../models';
|
||||
|
||||
class ResponseTimelineViewer extends PureComponent {
|
||||
_handleClickLink(link) {
|
||||
state = {
|
||||
timeline: [],
|
||||
timelineKey: '',
|
||||
};
|
||||
|
||||
static _handleClickLink(link) {
|
||||
shell.openExternal(link);
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
this.refreshTimeline();
|
||||
}
|
||||
|
||||
componentDidUpdate(prevProps) {
|
||||
const { response } = this.props;
|
||||
if (response._id !== prevProps.response._id) {
|
||||
this.refreshTimeline();
|
||||
}
|
||||
}
|
||||
|
||||
async refreshTimeline() {
|
||||
const { response } = this.props;
|
||||
const timeline = await models.response.getTimeline(response);
|
||||
this.setState({
|
||||
timeline,
|
||||
timelineKey: response._id,
|
||||
});
|
||||
}
|
||||
|
||||
renderRow(row, i, all) {
|
||||
const { name, value } = row;
|
||||
const previousName = i > 0 ? all[i - 1].name : '';
|
||||
@@ -56,16 +82,18 @@ class ResponseTimelineViewer extends PureComponent {
|
||||
}
|
||||
|
||||
render() {
|
||||
const { timeline, editorFontSize, editorIndentSize, editorLineWrapping } = this.props;
|
||||
const { editorFontSize, editorIndentSize, editorLineWrapping } = this.props;
|
||||
const { timeline, timelineKey } = this.state;
|
||||
const rows = timeline
|
||||
.map(this.renderRow)
|
||||
.filter(r => r !== null)
|
||||
.join('\n');
|
||||
return (
|
||||
<CodeEditor
|
||||
key={timelineKey}
|
||||
hideLineNumbers
|
||||
readOnly
|
||||
onClickLink={this._handleClickLink}
|
||||
onClickLink={ResponseTimelineViewer._handleClickLink}
|
||||
defaultValue={rows}
|
||||
fontSize={editorFontSize}
|
||||
indentSize={editorIndentSize}
|
||||
@@ -78,7 +106,7 @@ class ResponseTimelineViewer extends PureComponent {
|
||||
}
|
||||
|
||||
ResponseTimelineViewer.propTypes = {
|
||||
timeline: PropTypes.array.isRequired,
|
||||
response: PropTypes.object.isRequired,
|
||||
editorFontSize: PropTypes.number.isRequired,
|
||||
editorIndentSize: PropTypes.number.isRequired,
|
||||
editorLineWrapping: PropTypes.bool.isRequired,
|
||||
|
||||
@@ -367,6 +367,10 @@ blockquote {
|
||||
align-content: stretch;
|
||||
width: 100%;
|
||||
|
||||
&.row-fill--top {
|
||||
align-items: start;
|
||||
}
|
||||
|
||||
& > * {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user