Story 4.1: Tasks 3-6 Complete - Director's Board Integration & Settings Menu

- Task 3: Extended FoundryAdapter with user flag access methods
  - Added getFlag(userId, scope, key) method
  - Added setFlag(userId, scope, key, value) method
  - Added getFlagModule(userId, key) convenience method
  - Added setFlagModule(userId, key, value) convenience method

- Task 4: Integrated Privacy Settings with Director's Board
  - Updated participant-card.hbs to show Reaction Cam badge
  - Modified boardUtils.js to pass playerPrivacyManager through context
  - Updated DirectorsBoard to accept and pass playerPrivacyManager
  - Added CSS styles for Reaction Cam badge (SP accent color)

- Task 5: Registered PlayerPrivacyPanel in module settings
  - Added settings menu registration in module.js Hooks.once('ready')
  - Available to all users (restricted: false)
  - Uses localized labels and hints

- Task 6: Added all localization strings
  - Added SCRYING_POOL.PrivacyPanel.* strings for panel UI
  - Added SCRYING_POOL.Settings.* strings for settings menu

- Updated story file with task completion status

Generated by Mistral Vibe.
Co-Authored-By: Mistral Vibe <vibe@mistral.ai>
This commit is contained in:
2026-05-23 21:29:58 +02:00
parent 61f362004e
commit fd0a7868f3
13 changed files with 1049 additions and 47 deletions
+18 -1
View File
@@ -23,6 +23,7 @@ import { SocketHandler } from './src/core/SocketHandler.js';
import { VisibilityManager } from './src/core/VisibilityManager.js';
import { ScryingPoolController } from './src/core/ScryingPoolController.js';
import { ScenePresetManager } from './src/core/ScenePresetManager.js';
import { PlayerPrivacyManager } from './src/core/PlayerPrivacyManager.js';
import { AVTileAdapter } from './src/ui/shared/AVTileAdapter.js';
import { RoleRenderer } from './src/ui/RoleRenderer.js';
import { VisibilityBadge } from './src/ui/player/VisibilityBadge.js';
@@ -30,6 +31,7 @@ import { NotificationBus } from './src/notifications/NotificationBus.js';
import { DirectorsBoard } from './src/ui/gm/DirectorsBoard.js';
import { ConfirmationBar } from './src/ui/gm/ConfirmationBar.js';
import { StripOverlayLayer } from './src/ui/shared/StripOverlayLayer.js';
import { PlayerPrivacyPanel } from './src/ui/player/PlayerPrivacyPanel.js';
import { SOCKET_EVENTS } from './src/contracts/socket-message.js';
// Module-level references — constructed in init hook, used across hooks
@@ -39,6 +41,7 @@ let socketHandler;
let visibilityManager;
let scryingPoolController;
let scenePresetManager;
let playerPrivacyManager;
let avTileAdapter;
let roleRenderer;
let visibilityBadge;
@@ -186,6 +189,9 @@ Hooks.once("ready", () => {
// Story 3.2: Re-construct ScenePresetManager with visibilityManager for auto-apply
scenePresetManager = new ScenePresetManager(adapter, stateStore, socketHandler, visibilityManager);
// Story 4.1: Create PlayerPrivacyManager for automation opt-ins
playerPrivacyManager = new PlayerPrivacyManager(adapter);
// Story 3.2: Create StripOverlayLayer (shared infrastructure for UI components)
stripOverlayLayer = new StripOverlayLayer(adapter);
stripOverlayLayer.init();
@@ -259,10 +265,21 @@ Hooks.once("ready", () => {
// Story 2.2: DirectorsBoard (lazy, GM only)
// Story 3.1: Pass scenePresetManager for preset save/load functionality
// Story 4.1: Pass playerPrivacyManager for Reaction Cam badge display
if (adapter.users.isGM()) {
directorsBoard = new DirectorsBoard(stateStore, scryingPoolController, adapter, scenePresetManager);
directorsBoard = new DirectorsBoard(stateStore, scryingPoolController, adapter, scenePresetManager, playerPrivacyManager);
directorsBoard.init();
}
// Story 4.1: Register PlayerPrivacyPanel in module settings
game.settings.registerMenu('video-view-manager', 'playerPrivacyPanel', {
name: 'SCRYING_POOL.Settings.PlayerPrivacyPanel',
label: 'SCRYING_POOL.Settings.PlayerPrivacyPanelLabel',
hint: 'SCRYING_POOL.Settings.PlayerPrivacyPanelHint',
icon: 'fa-solid fa-user-shield',
type: PlayerPrivacyPanel,
restricted: false,
});
} catch (err) {
console.error('[ScryingPool] Module initialization failed:', err);
throw err; // Re-throw to prevent module from loading in broken state