living-together/source/Context/Popups.ts
2022-03-21 23:29:46 +08:00

126 lines
2.6 KiB
TypeScript

import { ReactNode } from "react";
import { Emitter } from "@Model/Emitter";
type IPopupConstructor = new (controller: PopupController, id: string) => Popup;
/**
* 弹窗类型
*/
class Popup {
/**
* 是否关闭
*/
public isClose: boolean = false;
/**
* 唯一标识符
*/
public id: string;
/**
* 控制器
*/
public controller: PopupController;
/**
* 渲染层级
*/
public index: number = Infinity;
/**
* react 节点
*/
public reactNode: ReactNode;
/**
* 渲染函数
*/
public rendererFunction: undefined | ((p: Popup) => ReactNode);
/**
* 渲染节点
*/
public render(): ReactNode {
if (this.rendererFunction) {
this.reactNode = this.rendererFunction(this);
}
return this.reactNode;
};
public constructor(controller: PopupController, id: string) {
this.controller = controller;
this.id = id;
}
}
interface IPopupControllerEvent {
popupChange: void;
}
/**
* 弹窗模型
*/
class PopupController extends Emitter<IPopupControllerEvent> {
/**
* ID 序列号
*/
private idIndex = 0;
/**
* 弹窗列表
*/
public popups: Popup[] = [];
/**
* 排序并重置序号
*/
public sortPopup() {
this.popups = this.popups.sort((a, b) => a.index - b.index);
this.popups = this.popups.map((popup, index) => {
popup.index = (index + 1);
return popup;
});
}
/**
* 实例化并开启一个弹窗
*/
public showPopup<P extends IPopupConstructor>(popup?: P): Popup {
let newPopup = new (popup ?? Popup)(this, `P-${this.idIndex ++}`);
this.popups.push(newPopup);
this.emit("popupChange");
return newPopup;
}
/**
* 关闭一个弹窗
*/
public closePopup(popup: Popup | string): Popup | undefined {
let id: string;
if (popup instanceof Popup) {
id = popup.id;
} else {
id = popup;
}
let closePopup: Popup | undefined;
this.popups = this.popups.filter(
currentPopup => {
let isDelete = currentPopup.id === id;
if (isDelete) {
closePopup = currentPopup;
return false;
} else {
return true;
}
}
);
if (closePopup) {
this.emit("popupChange");
}
return closePopup;
}
}
export { Popup, PopupController }