1
0
mirror of https://github.com/flarum/core.git synced 2025-10-12 15:34:26 +02:00

Extract ModalManagerState from ModalManager (#2162)

This commit is contained in:
Alexander Skvortsov
2020-06-30 19:59:16 -04:00
committed by GitHub
parent 4f181c84fc
commit 44376cef61
17 changed files with 130 additions and 111 deletions

View File

@@ -9,6 +9,11 @@ import Button from './Button';
* @abstract
*/
export default class Modal extends Component {
/**
* Determine whether or not the modal should be dismissible via an 'x' button.
*/
static isDismissible = true;
init() {
/**
* Attributes for an alert component to show below the header.
@@ -18,6 +23,16 @@ export default class Modal extends Component {
this.alertAttrs = null;
}
config(isInitialized, context) {
if (isInitialized) return;
this.props.onshow(() => this.onready());
context.onunload = () => {
this.props.onhide();
};
}
view() {
if (this.alertAttrs) {
this.alertAttrs.dismissible = false;
@@ -26,7 +41,7 @@ export default class Modal extends Component {
return (
<div className={'Modal modal-dialog ' + this.className()}>
<div className="Modal-content">
{this.isDismissible() ? (
{this.constructor.isDismissible ? (
<div className="Modal-close App-backControl">
{Button.component({
icon: 'fas fa-times',
@@ -52,15 +67,6 @@ export default class Modal extends Component {
);
}
/**
* Determine whether or not the modal should be dismissible via an 'x' button.
*
* @return {Boolean}
*/
isDismissible() {
return true;
}
/**
* Get the class name to apply to the modal.
*
@@ -105,7 +111,7 @@ export default class Modal extends Component {
* Hide the modal.
*/
hide() {
app.modal.close();
this.props.onhide();
}
/**

View File

@@ -1,5 +1,4 @@
import Component from '../Component';
import Modal from './Modal';
/**
* The `ModalManager` component manages a modal dialog. Only one modal dialog
@@ -8,12 +7,17 @@ import Modal from './Modal';
*/
export default class ModalManager extends Component {
init() {
this.showing = false;
this.component = null;
this.state = this.props.state;
}
view() {
return <div className="ModalManager modal fade">{this.component && this.component.render()}</div>;
const modal = this.state.modal;
return (
<div className="ModalManager modal fade">
{modal ? modal.componentClass.component({ ...modal.attrs, onshow: this.animateShow.bind(this), onhide: this.animateHide.bind(this) }) : ''}
</div>
);
}
config(isInitialized, context) {
@@ -24,29 +28,17 @@ export default class ModalManager extends Component {
// to be retained across route changes.
context.retain = true;
this.$().on('hidden.bs.modal', this.clear.bind(this)).on('shown.bs.modal', this.onready.bind(this));
// Ensure the modal state is notified about a closed modal, even when the
// DOM-based Bootstrap JavaScript code triggered the closing of the modal,
// e.g. via ESC key or a click on the modal backdrop.
this.$().on('hidden.bs.modal', this.state.close.bind(this.state));
}
/**
* Show a modal dialog.
*
* @param {Modal} component
* @public
*/
show(component) {
if (!(component instanceof Modal)) {
throw new Error('The ModalManager component can only show Modal components');
}
animateShow(readyCallback) {
const dismissible = !!this.state.modal.componentClass.isDismissible;
clearTimeout(this.hideTimeout);
this.showing = true;
this.component = component;
m.redraw(true);
const dismissible = !!this.component.isDismissible();
this.$()
.one('shown.bs.modal', readyCallback)
.modal({
backdrop: dismissible || 'static',
keyboard: dismissible,
@@ -54,50 +46,7 @@ export default class ModalManager extends Component {
.modal('show');
}
/**
* Close the modal dialog.
*
* @public
*/
close() {
if (!this.showing) return;
// Don't hide the modal immediately, because if the consumer happens to call
// the `show` method straight after to show another modal dialog, it will
// cause Bootstrap's modal JS to misbehave. Instead we will wait for a tiny
// bit to give the `show` method the opportunity to prevent this from going
// ahead.
this.hideTimeout = setTimeout(() => {
this.$().modal('hide');
this.showing = false;
});
}
/**
* Clear content from the modal area.
*
* @protected
*/
clear() {
if (this.component) {
this.component.onhide();
}
this.component = null;
app.current.retain = false;
m.lazyRedraw();
}
/**
* When the modal dialog is ready to be used, tell it!
*
* @protected
*/
onready() {
if (this.component && this.component.onready) {
this.component.onready(this.$());
}
animateHide() {
this.$().modal('hide');
}
}