import { CoercableComponent, persistent, PersistentRef, Replace, setDefault, StyleValue } from "@/features/feature"; import { Link } from "@/features/links"; import { Computable, GetComputableType, GetComputableTypeWithDefault, processComputable, ProcessedComputable } from "@/util/computed"; import { createProxy } from "@/util/proxies"; import { createNanoEvents, Emitter } from "nanoevents"; import { globalBus, LayerEvents } from "./events"; import player from "./player"; export const layers: Record> = {}; window.layers = layers; export interface Position { x: number; y: number; } export interface LayerOptions { id: string; color?: Computable; display: Computable; classes?: Computable>; style?: Computable; name?: Computable; minimizable?: Computable; forceHideGoBack?: Computable; minWidth?: Computable; links?: Computable; } export interface BaseLayer { minimized: PersistentRef; emitter: Emitter; on: OmitThisParameter["on"]>; emit: (event: K, ...args: Parameters) => void; } export type Layer = Replace< T & BaseLayer, { color: GetComputableType; display: GetComputableType; classes: GetComputableType; style: GetComputableType; name: GetComputableTypeWithDefault; minWidth: GetComputableTypeWithDefault; minimizable: GetComputableTypeWithDefault; forceHideGoBack: GetComputableType; links: GetComputableType; } >; export type GenericLayer = Replace< Layer, { name: ProcessedComputable; minWidth: ProcessedComputable; minimizable: ProcessedComputable; } >; export function createLayer(options: T): Layer { const layer: T & Partial = options; const emitter = (layer.emitter = createNanoEvents()); layer.on = emitter.on; layer.emit = emitter.emit; layer.minimized = persistent(false); processComputable(layer as T, "color"); processComputable(layer as T, "display"); processComputable(layer as T, "name"); setDefault(layer, "name", options.id); processComputable(layer as T, "minWidth"); setDefault(layer, "minWidth", 600); processComputable(layer as T, "minimizable"); setDefault(layer, "minimizable", true); processComputable(layer as T, "links"); const proxy = createProxy((layer as unknown) as Layer); return proxy; } export function addLayer( layer: GenericLayer, player: { layers?: Record> } ): void { if (layer.id in layers) { console.error( "Attempted to add layer with same ID as existing layer", layer.id, layers[layer.id] ); return; } setDefault(player, "layers", {}); if (player.layers[layer.id] == null) { player.layers[layer.id] = {}; } layers[layer.id] = layer; globalBus.emit("addLayer", layer, player.layers[layer.id]); } export function getLayer(layerID: string): () => T { return () => layers[layerID] as T; } export function removeLayer(layer: GenericLayer): void { globalBus.emit("removeLayer", layer); delete layers[layer.id]; } export function reloadLayer(layer: GenericLayer): void { removeLayer(layer); // Re-create layer addLayer(layer, player); }