mirror of
https://github.com/Kong/insomnia
synced 2024-11-07 22:30:15 +00:00
Refactor to minimize re-rendering of certain aspects
This commit is contained in:
parent
32ef288c6e
commit
10a241b600
@ -12,6 +12,25 @@ export const SYNC_MODE_OFF = 'paused';
|
|||||||
export const SYNC_MODE_ON = 'active';
|
export const SYNC_MODE_ON = 'active';
|
||||||
export const SYNC_MODE_NEVER = 'never';
|
export const SYNC_MODE_NEVER = 'never';
|
||||||
export const SYNC_MODE_UNSET = 'unset';
|
export const SYNC_MODE_UNSET = 'unset';
|
||||||
|
let changeListeners = [];
|
||||||
|
|
||||||
|
export function onChange (callback) {
|
||||||
|
changeListeners.push(callback);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function offChange (callback) {
|
||||||
|
changeListeners = changeListeners.filter(l => l !== callback);
|
||||||
|
}
|
||||||
|
|
||||||
|
let _changeTimeout = null;
|
||||||
|
function _notifyChange () {
|
||||||
|
clearTimeout(_changeTimeout);
|
||||||
|
_changeTimeout = setTimeout(() => {
|
||||||
|
for (const fn of changeListeners) {
|
||||||
|
fn();
|
||||||
|
}
|
||||||
|
}, 200);
|
||||||
|
}
|
||||||
|
|
||||||
export function allActiveResources (resourceGroupId = null) {
|
export function allActiveResources (resourceGroupId = null) {
|
||||||
if (resourceGroupId) {
|
if (resourceGroupId) {
|
||||||
@ -86,6 +105,7 @@ export function findResourcesByDocId (id) {
|
|||||||
export async function removeResourceGroup (resourceGroupId) {
|
export async function removeResourceGroup (resourceGroupId) {
|
||||||
await _execDB(TYPE_RESOURCE, 'remove', {resourceGroupId}, {multi: true});
|
await _execDB(TYPE_RESOURCE, 'remove', {resourceGroupId}, {multi: true});
|
||||||
await _execDB(TYPE_CONFIG, 'remove', {resourceGroupId}, {multi: true});
|
await _execDB(TYPE_CONFIG, 'remove', {resourceGroupId}, {multi: true});
|
||||||
|
_notifyChange();
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function insertResource (resource) {
|
export async function insertResource (resource) {
|
||||||
@ -94,17 +114,20 @@ export async function insertResource (resource) {
|
|||||||
h.update(resource.id);
|
h.update(resource.id);
|
||||||
const newResource = Object.assign({}, resource, {_id: `rs_${h.digest('hex')}`});
|
const newResource = Object.assign({}, resource, {_id: `rs_${h.digest('hex')}`});
|
||||||
await _execDB(TYPE_RESOURCE, 'insert', newResource);
|
await _execDB(TYPE_RESOURCE, 'insert', newResource);
|
||||||
|
_notifyChange();
|
||||||
return newResource;
|
return newResource;
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function updateResource (resource, ...patches) {
|
export async function updateResource (resource, ...patches) {
|
||||||
const newDoc = Object.assign({}, resource, ...patches);
|
const newDoc = Object.assign({}, resource, ...patches);
|
||||||
await _execDB(TYPE_RESOURCE, 'update', {_id: resource._id}, newDoc, {multi: true});
|
await _execDB(TYPE_RESOURCE, 'update', {_id: resource._id}, newDoc, {multi: true});
|
||||||
|
_notifyChange();
|
||||||
return newDoc;
|
return newDoc;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function removeResource (resource) {
|
export async function removeResource (resource) {
|
||||||
return _execDB(TYPE_RESOURCE, 'remove', {_id: resource._id}, {multi: true});
|
await _execDB(TYPE_RESOURCE, 'remove', {_id: resource._id}, {multi: true});
|
||||||
|
_notifyChange();
|
||||||
}
|
}
|
||||||
|
|
||||||
// ~~~~~~ //
|
// ~~~~~~ //
|
||||||
@ -196,6 +219,7 @@ export function initDB (config, forceReset) {
|
|||||||
// ~~~~~~~ //
|
// ~~~~~~~ //
|
||||||
|
|
||||||
let _database = null;
|
let _database = null;
|
||||||
|
|
||||||
function _getDB (type, config = {}) {
|
function _getDB (type, config = {}) {
|
||||||
initDB(config);
|
initDB(config);
|
||||||
return _database[type];
|
return _database[type];
|
||||||
|
@ -111,24 +111,17 @@ class Modal extends PureComponent {
|
|||||||
this.props.onHide && this.props.onHide();
|
this.props.onHide && this.props.onHide();
|
||||||
}
|
}
|
||||||
|
|
||||||
componentDidMount () {
|
|
||||||
this._node.addEventListener('keydown', this._handleKeyDown);
|
|
||||||
}
|
|
||||||
|
|
||||||
componentWillUnmount () {
|
|
||||||
if (this._node) {
|
|
||||||
this._node.removeEventListener('keydown', this._handleKeyDown);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
render () {
|
render () {
|
||||||
const {tall, wide, noEscape, className, children} = this.props;
|
const {tall, wide, noEscape, className, children} = this.props;
|
||||||
const {open, zIndex, forceRefreshCounter} = this.state;
|
const {open, zIndex, forceRefreshCounter} = this.state;
|
||||||
|
|
||||||
|
if (!open) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
const classes = classnames(
|
const classes = classnames(
|
||||||
'modal',
|
'modal',
|
||||||
className,
|
className,
|
||||||
{'modal--open': open},
|
|
||||||
{'modal--fixed-height': tall},
|
{'modal--fixed-height': tall},
|
||||||
{'modal--noescape': noEscape},
|
{'modal--noescape': noEscape},
|
||||||
{'modal--wide': wide},
|
{'modal--wide': wide},
|
||||||
@ -141,6 +134,7 @@ class Modal extends PureComponent {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<div ref={this._setModalRef}
|
<div ref={this._setModalRef}
|
||||||
|
onKeyDown={this._handleKeyDown}
|
||||||
tabIndex="-1"
|
tabIndex="-1"
|
||||||
className={classes}
|
className={classes}
|
||||||
style={styles}
|
style={styles}
|
||||||
|
@ -27,7 +27,7 @@ const BASE_CODEMIRROR_OPTIONS = {
|
|||||||
placeholder: 'Start Typing...',
|
placeholder: 'Start Typing...',
|
||||||
foldGutter: true,
|
foldGutter: true,
|
||||||
height: 'auto',
|
height: 'auto',
|
||||||
autoRefresh: 500,
|
autoRefresh: 2000,
|
||||||
lineWrapping: true,
|
lineWrapping: true,
|
||||||
scrollbarStyle: 'native',
|
scrollbarStyle: 'native',
|
||||||
lint: true,
|
lint: true,
|
||||||
|
@ -19,8 +19,11 @@ class SyncDropdown extends PureComponent {
|
|||||||
|
|
||||||
this.state = {
|
this.state = {
|
||||||
loggedIn: null,
|
loggedIn: null,
|
||||||
syncData: null,
|
loading: false,
|
||||||
loading: false
|
resourceGroupId: null,
|
||||||
|
syncMode: null,
|
||||||
|
syncPercent: 0,
|
||||||
|
workspaceName: ''
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -33,8 +36,7 @@ class SyncDropdown extends PureComponent {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async _handleSyncResourceGroupId () {
|
async _handleSyncResourceGroupId () {
|
||||||
const {syncData} = this.state;
|
const resourceGroupId = this.state;
|
||||||
const resourceGroupId = syncData.resourceGroupId;
|
|
||||||
|
|
||||||
// Set loading state
|
// Set loading state
|
||||||
this.setState({loading: true});
|
this.setState({loading: true});
|
||||||
@ -73,15 +75,13 @@ class SyncDropdown extends PureComponent {
|
|||||||
const numClean = all.length - dirty.length;
|
const numClean = all.length - dirty.length;
|
||||||
const syncPercent = all.length === 0 ? 100 : parseInt(numClean / all.length * 1000) / 10;
|
const syncPercent = all.length === 0 ? 100 : parseInt(numClean / all.length * 1000) / 10;
|
||||||
|
|
||||||
const syncData = {
|
|
||||||
resourceGroupId,
|
|
||||||
syncPercent,
|
|
||||||
syncMode: config.syncMode,
|
|
||||||
name: workspace.name
|
|
||||||
};
|
|
||||||
|
|
||||||
if (this._isMounted) {
|
if (this._isMounted) {
|
||||||
this.setState({syncData});
|
this.setState({
|
||||||
|
resourceGroupId,
|
||||||
|
syncPercent,
|
||||||
|
syncMode: config.syncMode,
|
||||||
|
workspaceName: workspace.name
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -90,29 +90,26 @@ class SyncDropdown extends PureComponent {
|
|||||||
await this._reloadData();
|
await this._reloadData();
|
||||||
}
|
}
|
||||||
|
|
||||||
async componentWillMount () {
|
async componentDidMount () {
|
||||||
this._interval = setInterval(this._reloadData, 500);
|
this._isMounted = true;
|
||||||
|
syncStorage.onChange(this._reloadData);
|
||||||
await this._reloadData();
|
await this._reloadData();
|
||||||
}
|
}
|
||||||
|
|
||||||
componentDidMount () {
|
|
||||||
this._isMounted = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
componentWillUnmount () {
|
componentWillUnmount () {
|
||||||
clearInterval(this._interval);
|
syncStorage.offChange(this._reloadData);
|
||||||
this._isMounted = false;
|
this._isMounted = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
async componentDidUpdate () {
|
async componentDidUpdate () {
|
||||||
const {syncData} = this.state;
|
const {resourceGroupId, syncMode} = this.state;
|
||||||
|
|
||||||
if (!syncData) {
|
if (!resourceGroupId) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Sync has not yet been configured for this workspace, so prompt the user to do so
|
// Sync has not yet been configured for this workspace, so prompt the user to do so
|
||||||
const isModeUnset = !syncData.syncMode || syncData.syncMode === syncStorage.SYNC_MODE_UNSET;
|
const isModeUnset = !syncMode || syncMode === syncStorage.SYNC_MODE_UNSET;
|
||||||
if (isModeUnset && !this._hasPrompted) {
|
if (isModeUnset && !this._hasPrompted) {
|
||||||
this._hasPrompted = true;
|
this._hasPrompted = true;
|
||||||
await this._handleShowSyncModePrompt();
|
await this._handleShowSyncModePrompt();
|
||||||
@ -138,14 +135,14 @@ class SyncDropdown extends PureComponent {
|
|||||||
|
|
||||||
render () {
|
render () {
|
||||||
const {className} = this.props;
|
const {className} = this.props;
|
||||||
const {syncData, loading, loggedIn} = this.state;
|
const {resourceGroupId, loading, loggedIn} = this.state;
|
||||||
|
|
||||||
// Don't show the sync menu unless we're logged in
|
// Don't show the sync menu unless we're logged in
|
||||||
if (!loggedIn) {
|
if (!loggedIn) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!syncData) {
|
if (!resourceGroupId) {
|
||||||
return (
|
return (
|
||||||
<div className={className}>
|
<div className={className}>
|
||||||
<button className="btn btn--compact wide" disabled>
|
<button className="btn btn--compact wide" disabled>
|
||||||
@ -154,7 +151,7 @@ class SyncDropdown extends PureComponent {
|
|||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
const {syncMode, syncPercent} = syncData;
|
const {syncMode, syncPercent} = this.state;
|
||||||
return (
|
return (
|
||||||
<div className={className}>
|
<div className={className}>
|
||||||
<Dropdown wide className="wide tall">
|
<Dropdown wide className="wide tall">
|
||||||
|
@ -25,6 +25,25 @@ class RequestSwitcherModal extends PureComponent {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_handleKeydown (e) {
|
||||||
|
const keyCode = e.keyCode;
|
||||||
|
|
||||||
|
if (keyCode === 38 || (keyCode === 9 && e.shiftKey)) {
|
||||||
|
// Up or Shift+Tab
|
||||||
|
this._setActiveIndex(this.state.activeIndex - 1);
|
||||||
|
} else if (keyCode === 40 || keyCode === 9) {
|
||||||
|
// Down or Tab
|
||||||
|
this._setActiveIndex(this.state.activeIndex + 1);
|
||||||
|
} else if (keyCode === 13) {
|
||||||
|
// Enter
|
||||||
|
this._activateCurrentIndex();
|
||||||
|
} else {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
e.preventDefault();
|
||||||
|
}
|
||||||
|
|
||||||
_setModalRef (n) {
|
_setModalRef (n) {
|
||||||
this.modal = n;
|
this.modal = n;
|
||||||
}
|
}
|
||||||
@ -186,27 +205,6 @@ class RequestSwitcherModal extends PureComponent {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
componentDidMount () {
|
|
||||||
ReactDOM.findDOMNode(this).addEventListener('keydown', e => {
|
|
||||||
const keyCode = e.keyCode;
|
|
||||||
|
|
||||||
if (keyCode === 38 || (keyCode === 9 && e.shiftKey)) {
|
|
||||||
// Up or Shift+Tab
|
|
||||||
this._setActiveIndex(this.state.activeIndex - 1);
|
|
||||||
} else if (keyCode === 40 || keyCode === 9) {
|
|
||||||
// Down or Tab
|
|
||||||
this._setActiveIndex(this.state.activeIndex + 1);
|
|
||||||
} else if (keyCode === 13) {
|
|
||||||
// Enter
|
|
||||||
this._activateCurrentIndex();
|
|
||||||
} else {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
e.preventDefault();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
render () {
|
render () {
|
||||||
const {
|
const {
|
||||||
searchString,
|
searchString,
|
||||||
@ -219,7 +217,7 @@ class RequestSwitcherModal extends PureComponent {
|
|||||||
const requestGroups = workspaceChildren.filter(d => d.type === models.requestGroup.type);
|
const requestGroups = workspaceChildren.filter(d => d.type === models.requestGroup.type);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Modal ref={this._setModalRef} dontFocus tall>
|
<Modal ref={this._setModalRef} dontFocus tall onKeyDown={this._handleKeydown}>
|
||||||
<ModalHeader hideCloseButton>
|
<ModalHeader hideCloseButton>
|
||||||
<div className="pull-right txt-sm pad-right">
|
<div className="pull-right txt-sm pad-right">
|
||||||
<span className="monospace">tab</span> or
|
<span className="monospace">tab</span> or
|
||||||
|
@ -7,7 +7,6 @@ class ResponseTimer extends PureComponent {
|
|||||||
super(props);
|
super(props);
|
||||||
this._interval = null;
|
this._interval = null;
|
||||||
this.state = {
|
this.state = {
|
||||||
show: false,
|
|
||||||
elapsedTime: 0
|
elapsedTime: 0
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@ -16,24 +15,27 @@ class ResponseTimer extends PureComponent {
|
|||||||
clearInterval(this._interval);
|
clearInterval(this._interval);
|
||||||
}
|
}
|
||||||
|
|
||||||
componentDidMount () {
|
componentWillReceiveProps (nextProps) {
|
||||||
|
const {loadStartTime} = nextProps;
|
||||||
|
|
||||||
|
if (loadStartTime <= 0) {
|
||||||
|
clearInterval(this._interval);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
clearInterval(this._interval); // Just to be sure
|
||||||
this._interval = setInterval(() => {
|
this._interval = setInterval(() => {
|
||||||
const {loadStartTime} = this.props;
|
const millis = Date.now() - loadStartTime - 200;
|
||||||
if (loadStartTime > 0) {
|
const elapsedTime = Math.round(millis / 100) / 10;
|
||||||
// Show and update if needed
|
this.setState({elapsedTime});
|
||||||
const millis = Date.now() - loadStartTime - 200;
|
|
||||||
const elapsedTime = Math.round(millis / 100) / 10;
|
|
||||||
this.setState({show: true, elapsedTime});
|
|
||||||
} else if (this.state.show) {
|
|
||||||
// Hide if needed after a small delay (so it doesn't disappear too quickly)
|
|
||||||
setTimeout(() => this.setState({show: false}), 200);
|
|
||||||
}
|
|
||||||
}, 100);
|
}, 100);
|
||||||
}
|
}
|
||||||
|
|
||||||
render () {
|
render () {
|
||||||
const {handleCancel} = this.props;
|
const {handleCancel, loadStartTime} = this.props;
|
||||||
const {show, elapsedTime} = this.state;
|
const {elapsedTime} = this.state;
|
||||||
|
|
||||||
|
const show = loadStartTime > 0;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={classnames('overlay theme--overlay', {'overlay--hidden': !show})}>
|
<div className={classnames('overlay theme--overlay', {'overlay--hidden': !show})}>
|
||||||
|
@ -23,6 +23,8 @@ class Plugins extends React.PureComponent {
|
|||||||
isRefreshingPlugins: boolean
|
isRefreshingPlugins: boolean
|
||||||
};
|
};
|
||||||
|
|
||||||
|
_isMounted: boolean;
|
||||||
|
|
||||||
constructor (props: any) {
|
constructor (props: any) {
|
||||||
super(props);
|
super(props);
|
||||||
this.state = {
|
this.state = {
|
||||||
@ -75,14 +77,22 @@ class Plugins extends React.PureComponent {
|
|||||||
const delta = Date.now() - start;
|
const delta = Date.now() - start;
|
||||||
await delay(500 - delta);
|
await delay(500 - delta);
|
||||||
|
|
||||||
this.setState({plugins, isRefreshingPlugins: false});
|
|
||||||
trackEvent('Plugins', 'Refresh');
|
trackEvent('Plugins', 'Refresh');
|
||||||
|
|
||||||
|
if (this._isMounted) {
|
||||||
|
this.setState({plugins, isRefreshingPlugins: false});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
componentDidMount () {
|
componentDidMount () {
|
||||||
|
this._isMounted = true;
|
||||||
this._handleRefreshPlugins();
|
this._handleRefreshPlugins();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
componentWillUnmount () {
|
||||||
|
this._isMounted = false;
|
||||||
|
}
|
||||||
|
|
||||||
render () {
|
render () {
|
||||||
const {plugins, error, isInstallingFromNpm, isRefreshingPlugins} = this.state;
|
const {plugins, error, isInstallingFromNpm, isRefreshingPlugins} = this.state;
|
||||||
|
|
||||||
|
@ -3,22 +3,13 @@
|
|||||||
|
|
||||||
.modal {
|
.modal {
|
||||||
// Hidden state
|
// Hidden state
|
||||||
opacity: 0;
|
|
||||||
z-index: -999999; // Component updates this manually
|
|
||||||
|
|
||||||
transition: opacity 250ms;
|
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top: 0;
|
top: 0;
|
||||||
left: -99999px;
|
left: 0;
|
||||||
right: 0;
|
right: 0;
|
||||||
bottom: 0;
|
bottom: 0;
|
||||||
padding: @padding-lg;
|
padding: @padding-lg;
|
||||||
|
|
||||||
&.modal--open {
|
|
||||||
opacity: 1;
|
|
||||||
left: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
&:focus {
|
&:focus {
|
||||||
outline: 0;
|
outline: 0;
|
||||||
}
|
}
|
||||||
@ -33,15 +24,11 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.modal__content__wrapper {
|
.modal__content__wrapper {
|
||||||
top: 1rem;
|
|
||||||
width: @modal-width;
|
width: @modal-width;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
max-width: 100%;
|
max-width: 100%;
|
||||||
max-height: 100%;
|
max-height: 100%;
|
||||||
margin: auto;
|
margin: auto;
|
||||||
position: relative;
|
|
||||||
transform: scale(0.95);
|
|
||||||
transition: transform 150ms ease-out, top 200ms ease-out;
|
|
||||||
|
|
||||||
// We want pointer events to pass through to the backdrop so we can close it
|
// We want pointer events to pass through to the backdrop so we can close it
|
||||||
pointer-events: none;
|
pointer-events: none;
|
||||||
@ -51,11 +38,6 @@
|
|||||||
height: 100%;
|
height: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
&.modal--open .modal__content__wrapper {
|
|
||||||
transform: scale(1);
|
|
||||||
top: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
&.modal--wide .modal__content__wrapper {
|
&.modal--wide .modal__content__wrapper {
|
||||||
width: @modal-width-wide;
|
width: @modal-width-wide;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user