import {Registry} from "tc-shared/events"; import * as React from "react"; import * as ReactDOM from "react-dom"; import {AbstractModal, ModalController, ModalEvents, ModalOptions, ModalState} from "tc-shared/ui/react-elements/ModalDefinitions"; import {InternalModalRenderer} from "tc-shared/ui/react-elements/internal-modal/Renderer"; export class InternalModalController implements ModalController { readonly events: Registry; readonly modalInstance: InstanceType; private initializedPromise: Promise; private domElement: Element; private refModal: React.RefObject; private modalState_: ModalState = ModalState.HIDDEN; constructor(instance: InstanceType) { this.modalInstance = instance; this.events = new Registry(); this.initialize(); } getOptions(): Readonly { /* FIXME! */ return {}; } getEvents(): Registry { return this.events; } getState() { return this.modalState_; } private initialize() { this.refModal = React.createRef(); this.domElement = document.createElement("div"); const element = React.createElement(InternalModalRenderer, { ref: this.refModal, modal: this.modalInstance, onClose: () => this.destroy() }); document.body.appendChild(this.domElement); this.initializedPromise = new Promise(resolve => { ReactDOM.render(element, this.domElement, () => setTimeout(resolve, 0)); }); this.modalInstance["onInitialize"](); } async show() : Promise { await this.initializedPromise; if(this.modalState_ === ModalState.DESTROYED) throw tr("modal has been destroyed"); else if(this.modalState_ === ModalState.SHOWN) return; this.refModal.current?.setState({ show: true }); this.modalState_ = ModalState.SHOWN; this.modalInstance["onOpen"](); this.events.fire("open"); } async hide() : Promise { await this.initializedPromise; if(this.modalState_ === ModalState.DESTROYED) throw tr("modal has been destroyed"); else if(this.modalState_ === ModalState.HIDDEN) return; this.refModal.current?.setState({ show: false }); this.modalState_ = ModalState.HIDDEN; this.modalInstance["onClose"](); this.events.fire("close"); return new Promise(resolve => setTimeout(resolve, 500)); } destroy() { if(this.modalState_ === ModalState.SHOWN) { this.hide().then(() => this.destroy()); return; } ReactDOM.unmountComponentAtNode(this.domElement); this.domElement.remove(); this.domElement = undefined; this.modalState_ = ModalState.DESTROYED; this.modalInstance["onDestroy"](); this.events.fire("destroy"); } } export abstract class InternalModal extends AbstractModal {}