Story 3.2 done

This commit is contained in:
2026-05-23 18:23:48 +02:00
parent d175f92806
commit a1e8886fce
66 changed files with 18258 additions and 1650 deletions
+93
View File
@@ -6,6 +6,7 @@ import { PresetSaveDialog } from './PresetSaveDialog.js';
import { PresetLoadDialog } from './PresetLoadDialog.js';
import { PresetExportDialog } from './PresetExportDialog.js';
import { PresetImportDialog } from './PresetImportDialog.js';
import { ScenePresetPanel } from './ScenePresetPanel.js';
// Conditional base class — test environment lacks foundry globals.
// At module load time in tests, foundry is undefined → fallback class is used.
@@ -86,11 +87,27 @@ export class DirectorsBoard extends _AppBase {
this._exportDialog = null;
/** @type {PresetImportDialog|null} Reference to open import dialog for cleanup */
this._importDialog = null;
/** @type {ScenePresetPanel|null} Reference to scene preset panel for cleanup */
this._presetPanel = null;
// Load saved position from user flags
this._loadPosition();
}
/**
* Returns the ScenePresetPanel instance, creating it lazily if needed.
* Story 3.2: Scene Auto-Apply & ConfirmationBar
* @returns {ScenePresetPanel} The panel instance.
* @private
*/
_getPresetPanel() {
if (!this._presetPanel) {
this._presetPanel = new ScenePresetPanel(this._adapter, this._scenePresetManager);
this._presetPanel.init();
}
return this._presetPanel;
}
/** Loads saved window position from GM user flag. */
_loadPosition() {
try {
@@ -119,6 +136,12 @@ export class DirectorsBoard extends _AppBase {
Hooks.off('scrying-pool:stateChanged', this._hookId);
this._hookId = null;
}
// Story 3.2: Tear down ScenePresetPanel
if (this._presetPanel) {
this._presetPanel.teardown();
this._presetPanel = null;
}
}
/** Opens the board if closed; closes it if open (singleton toggle behaviour). */
@@ -316,12 +339,32 @@ export class DirectorsBoard extends _AppBase {
async _prepareContext() {
const base = buildBoardContext(this._stateStore, this._controller, this._adapter);
const presetCount = this._scenePresetManager?.list?.().length ?? 0;
// Get auto-apply config for current scene (Story 3.2)
let autoApplyConfig = { enabled: false, presetName: null, preDelay: 0 };
try {
const scenes = this._adapter.scenes;
const currentScene = scenes?.current?.();
if (currentScene) {
const flagData = this._scenePresetManager?._getSceneFlagData?.(currentScene);
autoApplyConfig = this._scenePresetManager?._getAutoApplyConfig?.(flagData) ?? autoApplyConfig;
}
} catch (err) {
console.warn('[ScryingPool] Failed to get auto-apply config for context:', err);
}
return {
...base,
hasUndo: this._undoSnapshot !== null,
hasRestore: this._spotlightSnapshot !== null,
presetCount,
hasPresets: presetCount > 0,
// Story 3.2: Auto-apply configuration
hasScene: !!this._adapter.scenes?.current?.(),
autoApplyEnabled: autoApplyConfig.enabled,
autoApplyPresetName: autoApplyConfig.presetName,
autoApplyPreDelay: autoApplyConfig.preDelay,
presets: this._scenePresetManager?.list?.() ?? [],
};
}
@@ -362,6 +405,8 @@ export class DirectorsBoard extends _AppBase {
case 'load-preset': this._onLoadPreset(); break;
case 'export-presets': this._onExportPresets(); break;
case 'import-presets': this._onImportPresets(); break;
// Story 3.2: Scene auto-apply panel toggle
case 'toggle-preset-panel': this._togglePresetPanel(); break;
}
};
this._focusinHandler = (e) => {
@@ -374,6 +419,43 @@ export class DirectorsBoard extends _AppBase {
root.addEventListener('click', this._clickHandler);
root.addEventListener('focusin', this._focusinHandler);
root.addEventListener('keydown', this._keydownHandler);
// Story 3.2: Append ScenePresetPanel to DOM and refresh
this._appendPresetPanel(root);
this._refreshPresetPanel();
}
/**
* Appends the ScenePresetPanel to the DirectorsBoard DOM.
* Story 3.2: Scene Auto-Apply & ConfirmationBar
* @param {HTMLElement} root - The DirectorsBoard root element.
* @private
*/
_appendPresetPanel(root) {
const panel = this._getPresetPanel();
if (!panel || !panel.element) return;
// Find where to insert the panel (after content, before footer)
const content = root.querySelector('.directors-board__content');
if (content) {
// Insert after content
content.after(panel.element);
} else {
// Fallback: prepend to root
root.prepend(panel.element);
}
}
/**
* Refreshes the ScenePresetPanel content.
* Story 3.2: Scene Auto-Apply & ConfirmationBar
* @private
*/
_refreshPresetPanel() {
const panel = this._getPresetPanel();
if (panel) {
panel._refresh?.();
}
}
/**
@@ -490,6 +572,17 @@ export class DirectorsBoard extends _AppBase {
}
}
/**
* Toggles the ScenePresetPanel visibility.
* Story 3.2: Scene Auto-Apply & ConfirmationBar
*/
_togglePresetPanel() {
const panel = this._getPresetPanel();
if (panel) {
panel.toggle();
}
}
/**
* Opens the PresetSaveDialog for saving the current visibility matrix as a preset.
*/