From a0b0411a48260ce9838e7244c3f87261be428766 Mon Sep 17 00:00:00 2001 From: Joaquin Pereyra Date: Sun, 8 Jun 2025 17:24:08 -0300 Subject: [PATCH] FEAT: PseudoDocument class --- module/data/_module.mjs | 1 + module/data/pseudo-documents/_module.mjs | 4 +- module/data/pseudo-documents/_types.d.ts | 8 +- .../data/pseudo-documents/pseudoDocument.mjs | 115 ++++++++++++++++++ 4 files changed, 126 insertions(+), 2 deletions(-) create mode 100644 module/data/pseudo-documents/pseudoDocument.mjs diff --git a/module/data/_module.mjs b/module/data/_module.mjs index 3a921b93..57e977a2 100644 --- a/module/data/_module.mjs +++ b/module/data/_module.mjs @@ -9,3 +9,4 @@ export { default as DhpEnvironment } from './environment.mjs'; export * as items from './item/_module.mjs'; export * as messages from './chat-message/_modules.mjs'; export * as fields from "./fields/_module.mjs"; +export * as PseudoDocuments from "./pseudo-documents/_module.mjs"; diff --git a/module/data/pseudo-documents/_module.mjs b/module/data/pseudo-documents/_module.mjs index 6009f7be..cb9376d2 100644 --- a/module/data/pseudo-documents/_module.mjs +++ b/module/data/pseudo-documents/_module.mjs @@ -1,5 +1,7 @@ import BasePseudoDocument from "./base.mjs"; +import PseudoDocument from "./pseudoDocument.mjs"; export { - BasePseudoDocument + BasePseudoDocument, + PseudoDocument } \ No newline at end of file diff --git a/module/data/pseudo-documents/_types.d.ts b/module/data/pseudo-documents/_types.d.ts index 541abede..e4b4db77 100644 --- a/module/data/pseudo-documents/_types.d.ts +++ b/module/data/pseudo-documents/_types.d.ts @@ -1,3 +1,4 @@ +import ApplicationV2 from '@client/applications/api/application.mjs'; import DataModel from '@common/abstract/data.mjs'; export type PseudoDocumentMetadata = { @@ -10,7 +11,7 @@ export type PseudoDocumentMetadata = { /* Record of document names of pseudo-documents and the path to the collection. */ embedded: Record; /* The class used to render this pseudo-document. */ - sheetClass?: PseudoDocumentSheet; + sheetClass?: ApplicationV2; /* The default image used for newly created documents. */ defaultArtwork: string; }; @@ -28,3 +29,8 @@ declare class BasePseudoDocument extends DataModel { /** An HTML text description for this pseudo-document */ description: string; } + +/** + * Data model for pseudo-documents. + */ +declare class PseudoDocument extends BasePseudoDocument {} diff --git a/module/data/pseudo-documents/pseudoDocument.mjs b/module/data/pseudo-documents/pseudoDocument.mjs new file mode 100644 index 00000000..dc057918 --- /dev/null +++ b/module/data/pseudo-documents/pseudoDocument.mjs @@ -0,0 +1,115 @@ +/** @import {PseudoDocument} from "./_types" */ +import BasePseudoDocument from "./base.mjs"; + + +const { ApplicationV2 } = foundry.applications.api; + +/** @implements {PseudoDocument}*/ +export default class PseudoDocument extends BasePseudoDocument { + /** + * Reference to the sheet of this pseudo-document. + * @type {ApplicationV2|null} + */ + get sheet() { + if (this._sheet) return this._sheet; + const cls = this.constructor.metadata.sheetClass ?? ApplicationV2; + if (!ApplicationV2.isPrototypeOf(cls)) { + return void ui.notifications.error("Daggerheart | Error on PseudoDocument | sheetClass must be ApplicationV2"); + } + + const sheet = new cls({ document: this }); + this._sheet = sheet; + } + + /* -------------------------------------------- */ + /* Static Properties */ + /* -------------------------------------------- */ + + /** + * Set of apps what should be re-render. + * @type {Set} + * @internal + */ + _apps = new Set(); + + /* -------------------------------------------- */ + + /** + * Existing sheets of a specific type for a specific document. + * @type {ApplicationV2 | null} + */ + _sheet = null; + + /* -------------------------------------------- */ + /* Display Methods */ + /* -------------------------------------------- */ + + /** + * Render all the Application instances which are connected to this PseudoDocument. + * @param {ApplicationRenderOptions} [options] Rendering options. + */ + render(options) { + for (const app of this._apps ?? []) { + app.render({ window: { title: app.title }, ...options }); + } + } + + /* -------------------------------------------- */ + + /** + * Register an application to respond to updates to a certain document. + * @param {ApplicationV2} app Application to update. + * @internal + */ + _registerApp(app) { + this._apps.add(app); + } + + /* -------------------------------------------- */ + + /** + * Remove an application from the render registry. + * @param {ApplicationV2} app Application to stop watching. + */ + _unregisterApp(app) { + this._apps.delete(app) + } + + + /* -------------------------------------------- */ + /* Drag and Drop */ + /* -------------------------------------------- */ + + /** + * Serialize salient information for this PseudoDocument when dragging it. + * @returns {object} An object of drag data. + */ + toDragData() { + const dragData = { type: this.documentName, data: this.toObject() }; + if (this.id) dragData.uuid = this.uuid; + return dragData; + } + + /* -------------------------------------------- */ + /* Dialog Methods */ + /* -------------------------------------------- */ + + /** + * Spawn a dialog for creating a new PseudoDocument. + * @param {object} [data] Data to pre-populate the document with. + * @param {object} context + * @param {foundry.documents.Item} context.parent A parent for the document. + * @param {string[]|null} [context.types] A list of types to restrict the choices to, or null for no restriction. + * @returns {Promise} + */ + static async createDialog(data = {}, { parent, types = null, ...options } = {}) { } + + + /** + * Present a Dialog form to confirm deletion of this PseudoDocument. + * @param {object} [options] Positioning and sizing options for the resulting dialog. + * @returns {Promise} A Promise which resolves to the deleted PseudoDocument. + */ + async deleteDialog(options = {}) { + } +} \ No newline at end of file