const { HandlebarsApplicationMixin } = foundry.applications.api export default class CelestopolActorSheet extends HandlebarsApplicationMixin(foundry.applications.sheets.ActorSheetV2) { static SHEET_MODES = { EDIT: 0, PLAY: 1 } constructor(options = {}) { super(options) this.#dragDrop = this.#createDragDropHandlers() } #dragDrop /** @override */ static DEFAULT_OPTIONS = { classes: ["fvtt-celestopol", "actor"], position: { width: 900, height: "auto" }, form: { submitOnChange: true }, window: { resizable: true }, dragDrop: [{ dragSelector: '[data-drag="true"], .rollable', dropSelector: null }], actions: { editImage: CelestopolActorSheet.#onEditImage, toggleSheet: CelestopolActorSheet.#onToggleSheet, edit: CelestopolActorSheet.#onItemEdit, delete: CelestopolActorSheet.#onItemDelete, }, } _sheetMode = this.constructor.SHEET_MODES.PLAY get isPlayMode() { return this._sheetMode === this.constructor.SHEET_MODES.PLAY } get isEditMode() { return this._sheetMode === this.constructor.SHEET_MODES.EDIT } /** @override */ async _prepareContext() { return { fields: this.document.schema.fields, systemFields: this.document.system.schema.fields, actor: this.document, system: this.document.system, source: this.document.toObject(), isEditMode: this.isEditMode, isPlayMode: this.isPlayMode, isEditable: this.isEditable, } } /** @override */ _onRender(context, options) { this.#dragDrop.forEach(d => d.bind(this.element)) this.element.querySelectorAll(".rollable").forEach(el => { el.addEventListener("click", this._onRoll.bind(this)) }) } async _onRoll(event) { if (!this.isPlayMode) return const el = event.currentTarget const statId = el.dataset.statId const skillId = el.dataset.skillId if (!statId || !skillId) return await this.document.system.roll(statId, skillId) } #createDragDropHandlers() { return this.options.dragDrop.map(d => { d.permissions = { dragstart: this._canDragStart.bind(this), drop: this._canDragDrop.bind(this), } d.callbacks = { dragover: this._onDragOver.bind(this), drop: this._onDrop.bind(this), } return new foundry.applications.ux.DragDrop.implementation(d) }) } _canDragStart() { return this.isEditable } _canDragDrop() { return true } _onDragOver() {} async _onDrop(event) { if (!this.isEditable) return const data = foundry.applications.ux.TextEditor.implementation.getDragEventData(event) if (data.type === "Item") { const item = await fromUuid(data.uuid) if (item) return this._onDropItem(item) } } async _onDropItem(item) { await this.document.createEmbeddedDocuments("Item", [item.toObject()], { renderSheet: false }) } static async #onEditImage(event, target) { const attr = target.dataset.edit const current = foundry.utils.getProperty(this.document, attr) const fp = new FilePicker({ current, type: "image", callback: (path) => this.document.update({ [attr]: path }), top: this.position.top + 40, left: this.position.left + 10, }) return fp.browse() } static #onToggleSheet() { const modes = this.constructor.SHEET_MODES this._sheetMode = this.isEditMode ? modes.PLAY : modes.EDIT this.render() } static async #onItemEdit(event, target) { const uuid = target.getAttribute("data-item-uuid") const id = target.getAttribute("data-item-id") const item = uuid ? await fromUuid(uuid) : this.document.items.get(id) item?.sheet.render(true) } static async #onItemDelete(event, target) { const uuid = target.getAttribute("data-item-uuid") const item = await fromUuid(uuid) await item?.deleteDialog() } }