const { ApplicationV2, HandlebarsApplicationMixin } = foundry.applications.api; export class SessionTrackerApp extends HandlebarsApplicationMixin(ApplicationV2) { static instance; constructor(options = {}) { super(options); } static DEFAULT_OPTIONS = { id: "session-tracker-app", tag: "aside", classes: ["session-tracker"], window: { frame: false, positioned: true, }, position: { width: "auto", height: "auto", }, actions: { increment: SessionTrackerApp.#onIncrement, decrement: SessionTrackerApp.#onDecrement, } }; static PARTS = { content: { template: "modules/fvtt-session-tracker/templates/session-tracker.hbs", }, }; static initialize() { this.instance = new SessionTrackerApp(); if (!game.settings.get("fvtt-session-tracker", "showTracker")) return; const pos = game.settings.get("fvtt-session-tracker", "position"); this.instance.render(true, { position: pos }); } async _prepareContext(options) { return { sessionNumber: game.settings.get("fvtt-session-tracker", "sessionCount"), scale: game.settings.get("fvtt-session-tracker", "scale"), isGM: game.user.isGM }; } static async #onIncrement(event, target) { if (!game.user.isGM) return; const current = game.settings.get("fvtt-session-tracker", "sessionCount"); await game.settings.set("fvtt-session-tracker", "sessionCount", current + 1); } static async #onDecrement(event, target) { if (!game.user.isGM) return; const current = game.settings.get("fvtt-session-tracker", "sessionCount"); if (current <= 1) return; await game.settings.set("fvtt-session-tracker", "sessionCount", current - 1); } // Drag and drop support for positioning _onRender(context, options) { if (!game.user.isGM) return; const dragHandle = this.element; let isDragging = false; let startX, startY, startLeft, startTop; dragHandle.addEventListener('mousedown', (e) => { if (e.button !== 0) return; // Only left click isDragging = true; startX = e.clientX; startY = e.clientY; const rect = this.element.getBoundingClientRect(); startLeft = rect.left; startTop = rect.top; this.element.style.cursor = 'grabbing'; }); window.addEventListener('mousemove', (e) => { if (!isDragging) return; const dx = e.clientX - startX; const dy = e.clientY - startY; const newLeft = startLeft + dx; const newTop = startTop + dy; this.element.style.left = `${newLeft}px`; this.element.style.top = `${newTop}px`; }); window.addEventListener('mouseup', () => { if (!isDragging) return; isDragging = false; this.element.style.cursor = 'move'; // Save position const rect = this.element.getBoundingClientRect(); const pos = { top: rect.top, left: rect.left }; // Update the application's position state this.position.top = pos.top; this.position.left = pos.left; // Save to settings for persistence across sessions game.settings.set("fvtt-session-tracker", "position", pos); }); } }