Story 4.1 completed

This commit is contained in:
2026-05-23 23:00:07 +02:00
parent fd0a7868f3
commit de1b33c453
10 changed files with 574 additions and 25 deletions
+123
View File
@@ -0,0 +1,123 @@
/**
* Player Privacy Panel Menu Wrapper
*
* Wrapper class that adapts PlayerPrivacyPanel to FoundryVTT's settings menu system.
* The settings menu system expects a constructor that accepts options,
* but PlayerPrivacyPanel requires DI dependencies. This wrapper handles that.
*/
import { PlayerPrivacyPanel } from './PlayerPrivacyPanel.js';
/**
* Static references to DI dependencies (set during module initialization).
*/
let _adapter = null;
let _playerPrivacyManager = null;
/**
* Flag to track if dependencies have been initialized.
*/
let _isInitialized = false;
/**
* Initialize static dependencies.
* Called once during module initialization.
* @param {import('../../foundry/FoundryAdapter.js').FoundryAdapter} adapter
* @param {import('../../core/PlayerPrivacyManager.js').PlayerPrivacyManager} playerPrivacyManager
*/
export function initPlayerPrivacyPanelMenu(adapter, playerPrivacyManager) {
if (!adapter || typeof adapter !== 'object') {
throw new TypeError('initPlayerPrivacyPanelMenu: adapter is required');
}
if (!playerPrivacyManager || typeof playerPrivacyManager !== 'object') {
throw new TypeError('initPlayerPrivacyPanelMenu: playerPrivacyManager is required');
}
_adapter = adapter;
_playerPrivacyManager = playerPrivacyManager;
_isInitialized = true;
}
/**
* Check if dependencies have been initialized.
* @returns {boolean}
*/
export function isInitialized() {
return _isInitialized;
}
/**
* PlayerPrivacyPanelMenu - Wrapper for Foundry settings menu.
* When instantiated by Foundry, it creates a PlayerPrivacyPanel with the current user as target.
*/
export class PlayerPrivacyPanelMenu {
/**
* @param {object} [options] - Foundry options (unused, but required by settings menu API)
*/
constructor(options = {}) {
if (!_isInitialized) {
throw new Error('PlayerPrivacyPanelMenu: Dependencies not initialized. Call initPlayerPrivacyPanelMenu first.');
}
// Get the current user's ID
const currentUser = _adapter.users.current?.();
if (!currentUser?.id) {
throw new Error('PlayerPrivacyPanelMenu: Cannot determine current user ID');
}
// Validate that id is a non-empty string
if (typeof currentUser.id !== 'string' || currentUser.id.length === 0) {
throw new TypeError('PlayerPrivacyPanelMenu: current user ID must be a non-empty string');
}
// Create the actual panel with DI
this._panel = new PlayerPrivacyPanel(
_adapter,
_playerPrivacyManager,
currentUser.id,
options
);
}
/**
* Delegate render to the inner panel.
* @param {boolean|object} [force] - Render options
* @returns {Promise<void>}
*/
async render(force) {
return this._panel.render(force);
}
/**
* Delegate close to the inner panel.
* @returns {Promise<void>}
*/
async close() {
return this._panel.close();
}
/**
* Get the inner panel.
* @returns {PlayerPrivacyPanel}
*/
get panel() {
return this._panel;
}
// Delegate all other properties/methods to the inner panel
/**
* Get rendered state from inner panel.
* @returns {boolean}
*/
get rendered() {
return this._panel.rendered;
}
/**
* Get element from inner panel.
* @returns {HTMLElement|null}
*/
get element() {
return this._panel.element;
}
}