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_NEVER = 'never';
|
||||
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) {
|
||||
if (resourceGroupId) {
|
||||
@ -86,6 +105,7 @@ export function findResourcesByDocId (id) {
|
||||
export async function removeResourceGroup (resourceGroupId) {
|
||||
await _execDB(TYPE_RESOURCE, 'remove', {resourceGroupId}, {multi: true});
|
||||
await _execDB(TYPE_CONFIG, 'remove', {resourceGroupId}, {multi: true});
|
||||
_notifyChange();
|
||||
}
|
||||
|
||||
export async function insertResource (resource) {
|
||||
@ -94,17 +114,20 @@ export async function insertResource (resource) {
|
||||
h.update(resource.id);
|
||||
const newResource = Object.assign({}, resource, {_id: `rs_${h.digest('hex')}`});
|
||||
await _execDB(TYPE_RESOURCE, 'insert', newResource);
|
||||
_notifyChange();
|
||||
return newResource;
|
||||
}
|
||||
|
||||
export async function updateResource (resource, ...patches) {
|
||||
const newDoc = Object.assign({}, resource, ...patches);
|
||||
await _execDB(TYPE_RESOURCE, 'update', {_id: resource._id}, newDoc, {multi: true});
|
||||
_notifyChange();
|
||||
return newDoc;
|
||||
}
|
||||
|
||||
export function removeResource (resource) {
|
||||
return _execDB(TYPE_RESOURCE, 'remove', {_id: resource._id}, {multi: true});
|
||||
export async function removeResource (resource) {
|
||||
await _execDB(TYPE_RESOURCE, 'remove', {_id: resource._id}, {multi: true});
|
||||
_notifyChange();
|
||||
}
|
||||
|
||||
// ~~~~~~ //
|
||||
@ -196,6 +219,7 @@ export function initDB (config, forceReset) {
|
||||
// ~~~~~~~ //
|
||||
|
||||
let _database = null;
|
||||
|
||||
function _getDB (type, config = {}) {
|
||||
initDB(config);
|
||||
return _database[type];
|
||||
|
@ -111,24 +111,17 @@ class Modal extends PureComponent {
|
||||
this.props.onHide && this.props.onHide();
|
||||
}
|
||||
|
||||
componentDidMount () {
|
||||
this._node.addEventListener('keydown', this._handleKeyDown);
|
||||
}
|
||||
|
||||
componentWillUnmount () {
|
||||
if (this._node) {
|
||||
this._node.removeEventListener('keydown', this._handleKeyDown);
|
||||
}
|
||||
}
|
||||
|
||||
render () {
|
||||
const {tall, wide, noEscape, className, children} = this.props;
|
||||
const {open, zIndex, forceRefreshCounter} = this.state;
|
||||
|
||||
if (!open) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const classes = classnames(
|
||||
'modal',
|
||||
className,
|
||||
{'modal--open': open},
|
||||
{'modal--fixed-height': tall},
|
||||
{'modal--noescape': noEscape},
|
||||
{'modal--wide': wide},
|
||||
@ -141,6 +134,7 @@ class Modal extends PureComponent {
|
||||
|
||||
return (
|
||||
<div ref={this._setModalRef}
|
||||
onKeyDown={this._handleKeyDown}
|
||||
tabIndex="-1"
|
||||
className={classes}
|
||||
style={styles}
|
||||
|
@ -27,7 +27,7 @@ const BASE_CODEMIRROR_OPTIONS = {
|
||||
placeholder: 'Start Typing...',
|
||||
foldGutter: true,
|
||||
height: 'auto',
|
||||
autoRefresh: 500,
|
||||
autoRefresh: 2000,
|
||||
lineWrapping: true,
|
||||
scrollbarStyle: 'native',
|
||||
lint: true,
|
||||
|
@ -19,8 +19,11 @@ class SyncDropdown extends PureComponent {
|
||||
|
||||
this.state = {
|
||||
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 () {
|
||||
const {syncData} = this.state;
|
||||
const resourceGroupId = syncData.resourceGroupId;
|
||||
const resourceGroupId = this.state;
|
||||
|
||||
// Set loading state
|
||||
this.setState({loading: true});
|
||||
@ -73,15 +75,13 @@ class SyncDropdown extends PureComponent {
|
||||
const numClean = all.length - dirty.length;
|
||||
const syncPercent = all.length === 0 ? 100 : parseInt(numClean / all.length * 1000) / 10;
|
||||
|
||||
const syncData = {
|
||||
if (this._isMounted) {
|
||||
this.setState({
|
||||
resourceGroupId,
|
||||
syncPercent,
|
||||
syncMode: config.syncMode,
|
||||
name: workspace.name
|
||||
};
|
||||
|
||||
if (this._isMounted) {
|
||||
this.setState({syncData});
|
||||
workspaceName: workspace.name
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@ -90,29 +90,26 @@ class SyncDropdown extends PureComponent {
|
||||
await this._reloadData();
|
||||
}
|
||||
|
||||
async componentWillMount () {
|
||||
this._interval = setInterval(this._reloadData, 500);
|
||||
async componentDidMount () {
|
||||
this._isMounted = true;
|
||||
syncStorage.onChange(this._reloadData);
|
||||
await this._reloadData();
|
||||
}
|
||||
|
||||
componentDidMount () {
|
||||
this._isMounted = true;
|
||||
}
|
||||
|
||||
componentWillUnmount () {
|
||||
clearInterval(this._interval);
|
||||
syncStorage.offChange(this._reloadData);
|
||||
this._isMounted = false;
|
||||
}
|
||||
|
||||
async componentDidUpdate () {
|
||||
const {syncData} = this.state;
|
||||
const {resourceGroupId, syncMode} = this.state;
|
||||
|
||||
if (!syncData) {
|
||||
if (!resourceGroupId) {
|
||||
return;
|
||||
}
|
||||
|
||||
// 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) {
|
||||
this._hasPrompted = true;
|
||||
await this._handleShowSyncModePrompt();
|
||||
@ -138,14 +135,14 @@ class SyncDropdown extends PureComponent {
|
||||
|
||||
render () {
|
||||
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
|
||||
if (!loggedIn) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (!syncData) {
|
||||
if (!resourceGroupId) {
|
||||
return (
|
||||
<div className={className}>
|
||||
<button className="btn btn--compact wide" disabled>
|
||||
@ -154,7 +151,7 @@ class SyncDropdown extends PureComponent {
|
||||
</div>
|
||||
);
|
||||
} else {
|
||||
const {syncMode, syncPercent} = syncData;
|
||||
const {syncMode, syncPercent} = this.state;
|
||||
return (
|
||||
<div className={className}>
|
||||
<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) {
|
||||
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 () {
|
||||
const {
|
||||
searchString,
|
||||
@ -219,7 +217,7 @@ class RequestSwitcherModal extends PureComponent {
|
||||
const requestGroups = workspaceChildren.filter(d => d.type === models.requestGroup.type);
|
||||
|
||||
return (
|
||||
<Modal ref={this._setModalRef} dontFocus tall>
|
||||
<Modal ref={this._setModalRef} dontFocus tall onKeyDown={this._handleKeydown}>
|
||||
<ModalHeader hideCloseButton>
|
||||
<div className="pull-right txt-sm pad-right">
|
||||
<span className="monospace">tab</span> or
|
||||
|
@ -7,7 +7,6 @@ class ResponseTimer extends PureComponent {
|
||||
super(props);
|
||||
this._interval = null;
|
||||
this.state = {
|
||||
show: false,
|
||||
elapsedTime: 0
|
||||
};
|
||||
}
|
||||
@ -16,24 +15,27 @@ class ResponseTimer extends PureComponent {
|
||||
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(() => {
|
||||
const {loadStartTime} = this.props;
|
||||
if (loadStartTime > 0) {
|
||||
// Show and update if needed
|
||||
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);
|
||||
}
|
||||
this.setState({elapsedTime});
|
||||
}, 100);
|
||||
}
|
||||
|
||||
render () {
|
||||
const {handleCancel} = this.props;
|
||||
const {show, elapsedTime} = this.state;
|
||||
const {handleCancel, loadStartTime} = this.props;
|
||||
const {elapsedTime} = this.state;
|
||||
|
||||
const show = loadStartTime > 0;
|
||||
|
||||
return (
|
||||
<div className={classnames('overlay theme--overlay', {'overlay--hidden': !show})}>
|
||||
|
@ -23,6 +23,8 @@ class Plugins extends React.PureComponent {
|
||||
isRefreshingPlugins: boolean
|
||||
};
|
||||
|
||||
_isMounted: boolean;
|
||||
|
||||
constructor (props: any) {
|
||||
super(props);
|
||||
this.state = {
|
||||
@ -75,14 +77,22 @@ class Plugins extends React.PureComponent {
|
||||
const delta = Date.now() - start;
|
||||
await delay(500 - delta);
|
||||
|
||||
this.setState({plugins, isRefreshingPlugins: false});
|
||||
trackEvent('Plugins', 'Refresh');
|
||||
|
||||
if (this._isMounted) {
|
||||
this.setState({plugins, isRefreshingPlugins: false});
|
||||
}
|
||||
}
|
||||
|
||||
componentDidMount () {
|
||||
this._isMounted = true;
|
||||
this._handleRefreshPlugins();
|
||||
}
|
||||
|
||||
componentWillUnmount () {
|
||||
this._isMounted = false;
|
||||
}
|
||||
|
||||
render () {
|
||||
const {plugins, error, isInstallingFromNpm, isRefreshingPlugins} = this.state;
|
||||
|
||||
|
@ -3,22 +3,13 @@
|
||||
|
||||
.modal {
|
||||
// Hidden state
|
||||
opacity: 0;
|
||||
z-index: -999999; // Component updates this manually
|
||||
|
||||
transition: opacity 250ms;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: -99999px;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
padding: @padding-lg;
|
||||
|
||||
&.modal--open {
|
||||
opacity: 1;
|
||||
left: 0;
|
||||
}
|
||||
|
||||
&:focus {
|
||||
outline: 0;
|
||||
}
|
||||
@ -33,15 +24,11 @@
|
||||
}
|
||||
|
||||
.modal__content__wrapper {
|
||||
top: 1rem;
|
||||
width: @modal-width;
|
||||
height: 100%;
|
||||
max-width: 100%;
|
||||
max-height: 100%;
|
||||
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
|
||||
pointer-events: none;
|
||||
@ -51,11 +38,6 @@
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
&.modal--open .modal__content__wrapper {
|
||||
transform: scale(1);
|
||||
top: 0;
|
||||
}
|
||||
|
||||
&.modal--wide .modal__content__wrapper {
|
||||
width: @modal-width-wide;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user