UNPKG

@launchmenu/core

Version:

An environment for visual keyboard controlled applets

196 lines 14.9 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.AbstractUILayer = void 0; const model_react_1 = require("model-react"); const UILayerMissingView_1 = require("./UILayerMissingView"); const uuid_1 = require("uuid"); const getContentAction_1 = require("../actions/types/content/getContentAction"); const catchAllKeyHandler_1 = require("../keyHandler/utils/catchAllKeyHandler"); /** * An abstract class that can be used as a foundation for a UILayer */ class AbstractUILayer { /** * Creates a new abstract UI layer * @param config The layer config */ constructor(config) { // An overlay element to show in case this layer has no data for a given section this.UIMissingData = { ID: uuid_1.v4(), contentView: UILayerMissingView_1.UIMissingView, menuView: UILayerMissingView_1.UIMissingView, fieldView: UILayerMissingView_1.UIMissingView, overlayGroup: UILayerMissingView_1.standardOverlayGroup, }; // Initialization management this.closers = []; this.context = new model_react_1.Field(null); /** * A cached getter for the absolute path */ this.absolutePath = new model_react_1.DataCacher(h => { var _a; const context = this.context.get(h); if (!context) return []; const UI = context.getUI(h); const index = UI.indexOf(this); const parent = index >= 0 ? UI[index - 1] : undefined; const current = (_a = parent === null || parent === void 0 ? void 0 : parent.getPath(h)) !== null && _a !== void 0 ? _a : []; return this.layerConfig.path.split("/").reduce((cur, node) => { if (node == ".") { // Add itself to the top path const top = cur[cur.length - 1]; if (top) return [ ...cur.slice(0, cur.length - 1), { name: top.name, layers: [...top.layers, this] }, ]; else return cur; } else if (node == "..") { // Remove the top element form the path return cur.slice(0, cur.length - 1); } else { // Add an element to the path return [...cur, { name: node, layers: [this] }]; } }, current); }); /** * Contents that are visible from the currently selected menu items */ this.menuItemContents = new model_react_1.DataCacher(h => this.getContentMenus(h).flatMap(menu => { const cursor = menu.getCursor(h); if (!cursor) return []; const cursorContents = getContentAction_1.getContentAction.get([cursor], h); const context = this.context.get(h); if (!context) return cursorContents.filter((item) => !(item instanceof Function)); else return cursorContents.map(item => item instanceof Function ? item(context) : item); })); this.layerConfig = { path: ".", showNodataOverlay: true, catchAllKeys: true, ...config, }; } /** * A callback for when the UI layer is opened * @param context The context that this layer was opened in * @param close A method to close this layer from the given context * @returns A callback for when this layer is closed (both when invoked by our close call, or closed external) */ async onOpen(context, close) { this.closers.push(close); const onClose = (await this.initialize(context, close)) || undefined; this.context.set(context); return async () => { this.context.set(null); const index = this.closers.indexOf(close); if (index >= 0) this.closers.splice(index, 1); await (onClose === null || onClose === void 0 ? void 0 : onClose()); }; } /** * Closes this UILayer from all contexts it's opened in */ closeAll() { this.closers.forEach(closer => closer()); } // Path management /** * Retrieves the path to show to the user representing this layer * @param hook The data hook to subscribe to changes * @returns The path */ getPath(hook) { return this.absolutePath.get(hook); } // Data management // TODO: add a system to not call the hook if nothing changed for a given stack (menu/field/content) /** * Retrieves the menu data * @param hook The data hook to subscribe to changes * @param extendData The data to add to * @returns The menu data of this layer */ getMenuData(hook, extendData = []) { return this.layerConfig.showNodataOverlay ? [this.UIMissingData, ...extendData] : extendData; } /** * Retrieves the field data * @param hook The data hook to subscribe to changes * @param extendData The data to add to * @returns The field data of this layer */ getFieldData(hook, extendData = []) { return this.layerConfig.showNodataOverlay ? [this.UIMissingData, ...extendData] : extendData; } /** * Retrieves the menus to obtain the menu item content for * @param hook The hook to subscribe to changes * @returns The menus to get the content for */ getContentMenus(hook) { return this.getMenuData(hook) .filter(({ menu, hideItemContent }) => menu && !hideItemContent) .map(({ menu }) => menu); } /** * Retrieves the content data * @param hook The data hook to subscribe to changes * @param extendData The data to add to * @returns The content data of this layer */ getContentData(hook, extendData = []) { const itemContents = [...extendData]; this.menuItemContents.get(hook).forEach(item => { // If data of other layers has been added directly, their menu item content may already be present (E.g. when using a MenuSearch layer in another layer) if (!itemContents.find(({ ID }) => ID == item.ID)) itemContents.push(item); }); return this.layerConfig.showNodataOverlay ? [this.UIMissingData, ...itemContents] : itemContents; } /** * Retrieves the key listener data * @param hook The data hook to subscribe to changes * @returns The key listener data of this layer */ getKeyHandlers(hook) { return [ ...(this.layerConfig.catchAllKeys ? [catchAllKeyHandler_1.catchAllKeyHandler] : []), ...this.getMenuData(hook).map(({ menuHandler }) => menuHandler), ...this.getFieldData(hook).map(({ fieldHandler }) => fieldHandler), ...this.getContentData(hook).map(({ contentHandler }) => contentHandler), ].filter((m) => !!m); } // Helpers /** * Checks whether this layer is on the top of the stack * @param hook The hook to subscribe to changes * @returns Whether this layer is on top */ isOnTop(hook) { const context = this.context.get(hook); if (!context) return false; const layers = context.getUI(hook); return layers[layers.length - 1] == this; } } exports.AbstractUILayer = AbstractUILayer; //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiQWJzdHJhY3RVSUxheWVyLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL3VpTGF5ZXJzL0Fic3RyYWN0VUlMYXllci50c3giXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7O0FBQUEsNkNBQXlEO0FBUXpELDZEQUF5RTtBQUN6RSwrQkFBZ0M7QUFDaEMsZ0ZBQTJFO0FBRTNFLCtFQUEwRTtBQUcxRTs7R0FFRztBQUNILE1BQXNCLGVBQWU7SUFnQmpDOzs7T0FHRztJQUNILFlBQW1CLE1BQTJCO1FBakI5QyxnRkFBZ0Y7UUFDdEUsa0JBQWEsR0FBRztZQUN0QixFQUFFLEVBQUUsU0FBSSxFQUFFO1lBQ1YsV0FBVyxFQUFFLGtDQUFhO1lBQzFCLFFBQVEsRUFBRSxrQ0FBYTtZQUN2QixTQUFTLEVBQUUsa0NBQWE7WUFDeEIsWUFBWSxFQUFFLHlDQUFvQjtTQUNyQyxDQUFDO1FBRUYsNEJBQTRCO1FBQ2xCLFlBQU8sR0FBbUIsRUFBRSxDQUFDO1FBQzdCLFlBQU8sR0FBRyxJQUFJLG1CQUFLLENBQUMsSUFBeUIsQ0FBQyxDQUFDO1FBNER6RDs7V0FFRztRQUNPLGlCQUFZLEdBQUcsSUFBSSx3QkFBVSxDQUFxQixDQUFDLENBQUMsRUFBRTs7WUFDNUQsTUFBTSxPQUFPLEdBQUcsSUFBSSxDQUFDLE9BQU8sQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLENBQUM7WUFDcEMsSUFBSSxDQUFDLE9BQU87Z0JBQUUsT0FBTyxFQUFFLENBQUM7WUFFeEIsTUFBTSxFQUFFLEdBQUcsT0FBTyxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUMsQ0FBQztZQUM1QixNQUFNLEtBQUssR0FBRyxFQUFFLENBQUMsT0FBTyxDQUFDLElBQUksQ0FBQyxDQUFDO1lBQy9CLE1BQU0sTUFBTSxHQUFHLEtBQUssSUFBSSxDQUFDLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxLQUFLLEdBQUcsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLFNBQVMsQ0FBQztZQUN0RCxNQUFN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