Files
fvtt-chroniques-de-l-etrange/src/ui/apps/loksyu-app.js
T
2026-06-14 22:54:37 +02:00

147 lines
4.7 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/**
* Chroniques de l'Étrange — Système FoundryVTT
*
* Chroniques de l'Étrange est un jeu de rôle édité par Antre-Monde Éditions.
* Ce système FoundryVTT est une implémentation indépendante et n'est pas
* affilié à Antre-Monde Éditions,
* mais a été réalisé avec l'autorisation d'Antre-Monde Éditions.
*
* @author LeRatierBretonnien
* @copyright 20242026 LeRatierBretonnien
* @license CC BY-NC-SA 4.0 https://creativecommons.org/licenses/by-nc-sa/4.0/
*/
import { getLoksyuData, setLoksyuData } from "./singletons.js"
import { SYSTEM_ID } from "../../config/constants.js"
export class CDELoksyuApp extends foundry.applications.api.HandlebarsApplicationMixin(
foundry.applications.api.ApplicationV2
) {
static DEFAULT_OPTIONS = {
id: "cde-loksyu-app",
tag: "div",
window: {
title: "CDE.Loksyu",
icon: "fas fa-yin-yang",
resizable: false,
},
classes: ["cde-app", "cde-loksyu-standalone"],
position: { width: 520, height: "auto" },
actions: {
resetElement: CDELoksyuApp.#onResetElement,
resetAll: CDELoksyuApp.#onResetAll,
zoomVisual: CDELoksyuApp.#onZoomVisual,
},
}
static PARTS = {
main: {
template: `systems/${SYSTEM_ID}/templates/apps/cde-loksyu-app.html`,
},
}
/** @type {Function|null} bound hook handler */
_updateHook = null
/** @type {Function|null} updateSetting hook handler (for socket-propagated writes) */
_settingHook = null
/** Singleton accessor — open or bring to front */
static open() {
const existing = Array.from(foundry.applications.instances.values()).find(
(app) => app instanceof CDELoksyuApp
)
if (existing) { existing.bringToFront(); return existing }
const app = new CDELoksyuApp()
app.render(true)
return app
}
async _prepareContext() {
const sys = getLoksyuData()
const ELEMENTS = [
{ key: "wood", nameKey: "CDE.Wood", qualKey: "CDE.WoodQualities", img: `systems/${SYSTEM_ID}/images/cde_bois.webp` },
{ key: "fire", nameKey: "CDE.Fire", qualKey: "CDE.FireQualities", img: `systems/${SYSTEM_ID}/images/cde_feu.webp` },
{ key: "earth", nameKey: "CDE.Earth", qualKey: "CDE.EarthQualities", img: `systems/${SYSTEM_ID}/images/cde_terre.webp` },
{ key: "metal", nameKey: "CDE.Metal", qualKey: "CDE.MetalQualities", img: `systems/${SYSTEM_ID}/images/cde_metal.webp` },
{ key: "water", nameKey: "CDE.Water", qualKey: "CDE.WaterQualities", img: `systems/${SYSTEM_ID}/images/cde_eau.webp` },
]
return {
canEdit: game.user.isGM,
elements: ELEMENTS.map((el) => ({
...el,
yang: sys[el.key]?.yang ?? 0,
yin: sys[el.key]?.yin ?? 0,
})),
}
}
_onRender(context, options) {
super._onRender(context, options)
this.#bindInputs()
if (!this._updateHook) {
this._updateHook = Hooks.on("cde:loksyuUpdated", () => this.render())
}
if (!this._settingHook) {
this._settingHook = Hooks.on("updateSetting", (setting) => {
if (setting.key === `${SYSTEM_ID}.loksyuData`) this.render()
})
}
}
_onClose(options) {
if (this._updateHook !== null) {
Hooks.off("cde:loksyuUpdated", this._updateHook)
this._updateHook = null
}
if (this._settingHook !== null) {
Hooks.off("updateSetting", this._settingHook)
this._settingHook = null
}
super._onClose(options)
}
#bindInputs() {
const inputs = this.element?.querySelectorAll("input[data-field]")
if (!inputs?.length) return
inputs.forEach((input) => {
input.addEventListener("change", async (ev) => {
const field = ev.currentTarget.dataset.field
const val = parseInt(ev.currentTarget.value, 10)
if (!field || isNaN(val)) return
// field is like "wood.yin" or "fire.yang"
const [aspect, dim] = field.split(".")
if (!aspect || !dim) return
const data = getLoksyuData()
if (!data[aspect]) data[aspect] = { yin: 0, yang: 0 }
data[aspect][dim] = Math.max(0, val)
await setLoksyuData(data)
})
})
}
static async #onResetElement(event, target) {
const key = target.dataset.element
if (!key) return
const data = getLoksyuData()
data[key] = { yin: 0, yang: 0 }
await setLoksyuData(data)
}
static async #onResetAll(_event, _target) {
const KEYS = ["wood", "fire", "earth", "metal", "water"]
const data = getLoksyuData()
for (const k of KEYS) data[k] = { yin: 0, yang: 0 }
await setLoksyuData(data)
}
static #onZoomVisual(_event, target) {
new ImagePopout(target.src, {
title: game.i18n.localize("CDE.LoksyuDiagramTitle"),
shareable: false,
}).render(true)
}
}