insomnia/packages/insomnia-app/app/ui/components/base/modal.tsx

195 lines
4.5 KiB
TypeScript
Raw Normal View History

import { autoBindMethodsForReact } from 'class-autobind-decorator';
import classnames from 'classnames';
2021-07-22 23:04:56 +00:00
import React, { CSSProperties, PureComponent, ReactNode } from 'react';
import { AUTOBIND_CFG } from '../../../common/constants';
import { hotKeyRefs } from '../../../common/hotkeys';
import { pressedHotKey } from '../../../common/hotkeys-listener';
import { KeydownBinder } from '../keydown-binder';
// Keep global z-index reference so that every modal will
// appear over top of an existing one.
let globalZIndex = 1000;
export interface ModalProps {
centered?: boolean;
tall?: boolean;
wide?: boolean;
skinny?: boolean;
noEscape?: boolean;
dontFocus?: boolean;
closeOnKeyCodes?: any[];
onShow?: Function;
onHide?: Function;
onCancel?: Function;
onKeyDown?: Function;
freshState?: boolean;
children?: ReactNode;
className?: string;
}
interface State {
open: boolean;
forceRefreshCounter: number;
zIndex: number;
}
@autoBindMethodsForReact(AUTOBIND_CFG)
export class Modal extends PureComponent<ModalProps, State> {
onHide: Function | null = null;
_node: HTMLDivElement | null = null;
state: State = {
open: false,
forceRefreshCounter: 0,
zIndex: globalZIndex,
};
async _handleKeyDown(event: KeyboardEvent) {
if (!this.state.open) {
return;
}
this.props.onKeyDown?.(event);
// Don't check for close keys if we don't want them
if (this.props.noEscape) {
return;
}
const closeOnKeyCodes = this.props.closeOnKeyCodes || [];
const pressedEscape = await pressedHotKey(event, hotKeyRefs.CLOSE_MODAL);
const pressedCloseButton = closeOnKeyCodes.find(c => c === event.keyCode);
// Pressed escape
if (pressedEscape || pressedCloseButton) {
event.preventDefault();
this.hide();
2021-07-30 03:32:08 +00:00
this.props.onCancel?.();
}
}
2018-06-25 17:42:50 +00:00
_handleClick(e) {
// Don't check for close keys if we don't want them
if (this.props.noEscape) {
return;
}
2016-04-07 03:09:14 +00:00
// Did we click a close button. Let's check a few parent nodes up as well
// because some buttons might have nested elements. Maybe there is a better
// way to check this?
let target = e.target;
let shouldHide = false;
2016-04-08 04:05:08 +00:00
2016-04-07 03:09:14 +00:00
for (let i = 0; i < 5; i++) {
2018-10-17 16:42:33 +00:00
if (target instanceof HTMLElement && target.hasAttribute('data-close-modal')) {
shouldHide = true;
2016-04-07 03:09:14 +00:00
break;
}
target = target.parentNode;
}
2016-04-08 04:05:08 +00:00
if (shouldHide) {
this.hide();
2021-07-30 03:32:08 +00:00
this.props.onCancel?.();
2016-04-07 03:27:45 +00:00
}
}
2016-11-23 23:57:34 +00:00
_setModalRef(n: HTMLDivElement) {
this._node = n;
}
show(options?: ModalProps) {
2018-06-25 17:42:50 +00:00
const { freshState } = this.props;
const { forceRefreshCounter } = this.state;
2016-11-29 21:28:22 +00:00
this.setState({
open: true,
zIndex: globalZIndex++,
forceRefreshCounter: forceRefreshCounter + (freshState ? 1 : 0),
2016-11-29 21:28:22 +00:00
});
this.props.onShow?.();
if (this.props.dontFocus) {
return;
}
Version Control (beta) (#1439) * VCS proof of concept underway! * Stuff * Some things * Replace deprecated Electron makeSingleInstance * Rename `window` variables so not to be confused with window object * Don't unnecessarily update request when URL does not change * Regenerate package-lock * Fix tests + ESLint * Publish - insomnia-app@1.0.49 - insomnia-cookies@0.0.12 - insomnia-httpsnippet@1.16.18 - insomnia-importers@2.0.13 - insomnia-libcurl@0.0.23 - insomnia-prettify@0.1.7 - insomnia-url@0.1.6 - insomnia-xpath@1.0.9 - insomnia-plugin-base64@1.0.6 - insomnia-plugin-cookie-jar@1.0.8 - insomnia-plugin-core-themes@1.0.5 - insomnia-plugin-default-headers@1.1.9 - insomnia-plugin-file@1.0.7 - insomnia-plugin-hash@1.0.7 - insomnia-plugin-jsonpath@1.0.12 - insomnia-plugin-now@1.0.11 - insomnia-plugin-os@1.0.13 - insomnia-plugin-prompt@1.1.9 - insomnia-plugin-request@1.0.18 - insomnia-plugin-response@1.0.16 - insomnia-plugin-uuid@1.0.10 * Broken but w/e * Some tweaks * Big refactor. Create local snapshots and push done * POC merging and a lot of improvements * Lots of work done on initial UI/UX * Fix old tests * Atomic writes and size-based batches * Update StageEntry definition once again to be better * Factor out GraphQL query logic * Merge algorithm, history modal, other minor things * Fix test * Merge, checkout, revert w/ user changes now work * Force UI to refresh when switching branches changes active request * Rough draft pull() and some cleanup * E2EE stuff and some refactoring * Add ability to share project with team and fixed tests * VCS now created in root component and better remote project handling * Remove unused definition * Publish - insomnia-account@0.0.2 - insomnia-app@1.1.1 - insomnia-cookies@0.0.14 - insomnia-httpsnippet@1.16.20 - insomnia-importers@2.0.15 - insomnia-libcurl@0.0.25 - insomnia-prettify@0.1.9 - insomnia-sync@0.0.2 - insomnia-url@0.1.8 - insomnia-xpath@1.0.11 - insomnia-plugin-base64@1.0.8 - insomnia-plugin-cookie-jar@1.0.10 - insomnia-plugin-core-themes@1.0.7 - insomnia-plugin-file@1.0.9 - insomnia-plugin-hash@1.0.9 - insomnia-plugin-jsonpath@1.0.14 - insomnia-plugin-now@1.0.13 - insomnia-plugin-os@1.0.15 - insomnia-plugin-prompt@1.1.11 - insomnia-plugin-request@1.0.20 - insomnia-plugin-response@1.0.18 - insomnia-plugin-uuid@1.0.12 * Move some deps around * Fix Flow errors * Update package.json * Fix eslint errors * Fix tests * Update deps * bootstrap insomnia-sync * TRy fixing appveyor * Try something else * Bump lerna * try powershell * Try again * Fix imports * Fixed errors * sync types refactor * Show remote projects in workspace dropdown * Improved pulling of non-local workspaces * Loading indicators and some tweaks * Clean up sync staging modal * Some sync improvements: - No longer store stage - Upgrade Electron - Sync UI/UX improvements * Fix snyc tests * Upgraded deps and hot loader tweaks (it's broken for some reason) * Fix tests * Branches dialog, network refactoring, some tweaks * Fixed merging when other branch is empty * A bunch of small fixes from real testing * Fixed pull merge logic * Fix tests * Some bug fixes * A few small tweaks * Conflict resolution and other improvements * Fix tests * Add revert changes * Deal with duplicate projects per workspace * Some tweaks and accessibility improvements * Tooltip accessibility * Fix API endpoint * Fix tests * Remove jest dep from insomnia-importers
2019-04-18 00:50:03 +00:00
// Allow instance-based onHide method
this.onHide = options?.onHide ?? null;
2021-07-30 03:32:08 +00:00
setTimeout(() => this._node?.focus());
}
2018-06-25 17:42:50 +00:00
toggle() {
if (this.state.open) {
this.hide();
} else {
this.show();
2016-04-09 19:24:33 +00:00
}
}
2018-06-25 17:42:50 +00:00
isOpen() {
return this.state.open;
}
2018-06-25 17:42:50 +00:00
hide() {
this.setState({
open: false,
});
2021-07-30 03:32:08 +00:00
this.props.onHide?.();
this.onHide?.();
2016-04-07 03:09:14 +00:00
}
2018-06-25 17:42:50 +00:00
render() {
const { tall, wide, skinny, noEscape, className, children, centered } = this.props;
2018-06-25 17:42:50 +00:00
const { open, zIndex, forceRefreshCounter } = this.state;
2016-04-07 03:09:14 +00:00
if (!open) {
return null;
}
2016-07-07 20:10:55 +00:00
const classes = classnames(
'modal',
'theme--dialog',
2016-07-07 20:10:55 +00:00
className,
{
'modal--fixed-height': tall,
},
{
'modal--noescape': noEscape,
},
{
'modal--wide': wide,
},
{
'modal--skinny': skinny,
},
2016-07-14 22:48:56 +00:00
);
const styles: CSSProperties = {};
2016-07-14 22:48:56 +00:00
if (open) {
styles.zIndex = zIndex;
}
2016-04-07 03:09:14 +00:00
return (
<KeydownBinder stopMetaPropagation scoped onKeydown={this._handleKeyDown}>
2018-06-25 17:42:50 +00:00
<div
ref={this._setModalRef}
tabIndex={-1}
2018-06-25 17:42:50 +00:00
className={classes}
style={styles}
Version Control (beta) (#1439) * VCS proof of concept underway! * Stuff * Some things * Replace deprecated Electron makeSingleInstance * Rename `window` variables so not to be confused with window object * Don't unnecessarily update request when URL does not change * Regenerate package-lock * Fix tests + ESLint * Publish - insomnia-app@1.0.49 - insomnia-cookies@0.0.12 - insomnia-httpsnippet@1.16.18 - insomnia-importers@2.0.13 - insomnia-libcurl@0.0.23 - insomnia-prettify@0.1.7 - insomnia-url@0.1.6 - insomnia-xpath@1.0.9 - insomnia-plugin-base64@1.0.6 - insomnia-plugin-cookie-jar@1.0.8 - insomnia-plugin-core-themes@1.0.5 - insomnia-plugin-default-headers@1.1.9 - insomnia-plugin-file@1.0.7 - insomnia-plugin-hash@1.0.7 - insomnia-plugin-jsonpath@1.0.12 - insomnia-plugin-now@1.0.11 - insomnia-plugin-os@1.0.13 - insomnia-plugin-prompt@1.1.9 - insomnia-plugin-request@1.0.18 - insomnia-plugin-response@1.0.16 - insomnia-plugin-uuid@1.0.10 * Broken but w/e * Some tweaks * Big refactor. Create local snapshots and push done * POC merging and a lot of improvements * Lots of work done on initial UI/UX * Fix old tests * Atomic writes and size-based batches * Update StageEntry definition once again to be better * Factor out GraphQL query logic * Merge algorithm, history modal, other minor things * Fix test * Merge, checkout, revert w/ user changes now work * Force UI to refresh when switching branches changes active request * Rough draft pull() and some cleanup * E2EE stuff and some refactoring * Add ability to share project with team and fixed tests * VCS now created in root component and better remote project handling * Remove unused definition * Publish - insomnia-account@0.0.2 - insomnia-app@1.1.1 - insomnia-cookies@0.0.14 - insomnia-httpsnippet@1.16.20 - insomnia-importers@2.0.15 - insomnia-libcurl@0.0.25 - insomnia-prettify@0.1.9 - insomnia-sync@0.0.2 - insomnia-url@0.1.8 - insomnia-xpath@1.0.11 - insomnia-plugin-base64@1.0.8 - insomnia-plugin-cookie-jar@1.0.10 - insomnia-plugin-core-themes@1.0.7 - insomnia-plugin-file@1.0.9 - insomnia-plugin-hash@1.0.9 - insomnia-plugin-jsonpath@1.0.14 - insomnia-plugin-now@1.0.13 - insomnia-plugin-os@1.0.15 - insomnia-plugin-prompt@1.1.11 - insomnia-plugin-request@1.0.20 - insomnia-plugin-response@1.0.18 - insomnia-plugin-uuid@1.0.12 * Move some deps around * Fix Flow errors * Update package.json * Fix eslint errors * Fix tests * Update deps * bootstrap insomnia-sync * TRy fixing appveyor * Try something else * Bump lerna * try powershell * Try again * Fix imports * Fixed errors * sync types refactor * Show remote projects in workspace dropdown * Improved pulling of non-local workspaces * Loading indicators and some tweaks * Clean up sync staging modal * Some sync improvements: - No longer store stage - Upgrade Electron - Sync UI/UX improvements * Fix snyc tests * Upgraded deps and hot loader tweaks (it's broken for some reason) * Fix tests * Branches dialog, network refactoring, some tweaks * Fixed merging when other branch is empty * A bunch of small fixes from real testing * Fixed pull merge logic * Fix tests * Some bug fixes * A few small tweaks * Conflict resolution and other improvements * Fix tests * Add revert changes * Deal with duplicate projects per workspace * Some tweaks and accessibility improvements * Tooltip accessibility * Fix API endpoint * Fix tests * Remove jest dep from insomnia-importers
2019-04-18 00:50:03 +00:00
aria-hidden={!open}
2021-08-07 08:03:56 +00:00
onClick={this._handleClick}
>
2018-10-17 16:42:33 +00:00
<div className="modal__backdrop overlay theme--transparent-overlay" data-close-modal />
<div className={classnames('modal__content__wrapper', { 'modal--centered': centered })}>
<div className="modal__content" key={forceRefreshCounter}>
{children}
</div>
</div>
2016-04-07 03:09:14 +00:00
</div>
</KeydownBinder>
);
2016-04-07 03:09:14 +00:00
}
}