diff --git a/module.js b/module.js index 9b6ce43..8b4d8ab 100644 --- a/module.js +++ b/module.js @@ -36,12 +36,19 @@ import { PlayerPrivacyPanelMenu, initPlayerPrivacyPanelMenu } from './src/ui/pla import { initGMPlayerPrivacySelector } from './src/ui/gm/GMPlayerPrivacySelector.js'; import { ScryingPoolCameraViews, initScryingPoolCameraViews } from './src/ui/shared/ScryingPoolCameraViews.js'; import { ScryingPoolSettings } from './src/ui/gm/ScryingPoolSettings.js'; +import { SOCKET_EVENTS } from './src/contracts/socket-message.js'; // Factory function to create ScryingPoolSettings with roleRenderer dependency +// Returns a class constructor (not a function) that Foundry can use for registerMenu function initScryingPoolSettings(roleRendererRef) { - return () => new ScryingPoolSettings(roleRendererRef); + return class extends ScryingPoolSettings { + constructor(options = {}) { + super(roleRendererRef, options); + } + }; } -import { SOCKET_EVENTS } from './src/contracts/socket-message.js'; + + // Module-level references — constructed in init hook, used across hooks let adapter; @@ -414,8 +421,8 @@ Hooks.once("ready", () => { restricted: false, }); - // Story 5.3: Register ScryingPoolSettings in module settings - // Provides button to reopen the strip + // Register ScryingPoolSettings in module settings + // Provides button to reopen the strip when user closes it game.settings.registerMenu('scrying-pool', 'stripSettings', { name: 'SCRYING_POOL.Settings.Title', label: 'SCRYING_POOL.Settings.Title', @@ -424,6 +431,7 @@ Hooks.once("ready", () => { type: initScryingPoolSettings(roleRenderer), restricted: true, // GM only }); + } catch (err) { console.error('[ScryingPool] Module initialization failed:', err); throw err; // Re-throw to prevent module from loading in broken state diff --git a/module.json b/module.json index 2cec630..f37671a 100644 --- a/module.json +++ b/module.json @@ -2,13 +2,12 @@ "id": "scrying-pool", "title": "Scrying Pool", "version": "0.1.0", - "description": "GM camera visibility control for FoundryVTT v14 — hide, show, and manage participant feeds in real time.", + "description": "GM camera visibility control for FoundryVTT v14+ — hide, show, and manage participant feeds in real time.", "authors": [ { "name": "Morr" } ], - "category": "Audio/Video", "compatibility": { "minimum": "14", "verified": "14" @@ -26,6 +25,8 @@ "path": "lang/en.json" } ], + "packs": [ + ], "url": "${url}", "manifest": "${manifest}", "download": "${download}", diff --git a/package-lock.json b/package-lock.json index 3cf8fa9..e448c3f 100644 --- a/package-lock.json +++ b/package-lock.json @@ -7,6 +7,7 @@ "": { "name": "scrying-pool", "version": "0.1.0", + "hasInstallScript": true, "devDependencies": { "@league-of-foundry-developers/foundry-vtt-types": "9.280.1", "@playwright/test": "^1.60.0", diff --git a/packs/assets/README.md b/packs/assets/README.md new file mode 100644 index 0000000..6a31033 --- /dev/null +++ b/packs/assets/README.md @@ -0,0 +1,62 @@ +# Scrying Pool Documentation Screenshots + +✅ **All screenshots have been captured and are ready!** + +This directory contains the screenshot images for the Scrying Pool User Guide JournalEntry. + +## Included Screenshots + +1. **screenshot-main.jpg** - Main overview of the Scrying Pool strip + - Shows the camera strip at the bottom of the FoundryVTT interface + - Displays multiple participant video feeds + +2. **screenshot-directors-board.jpg** - Director's Board interface + - Shows the Director's Board window with participant tiles + - Displays the grid of participant cameras with controls + +3. **screenshot-player-view.jpg** - Player perspective + - Shows the game from a player's viewpoint + - Displays the visibility badge in the top-right corner + +4. **screenshot-presets.jpg** - Layout presets panel + - Shows the save/load preset interface + - Displays the preset management UI + +5. **screenshot-badge-states.jpg** - Visibility badge states + - Shows different states of the visibility badge + - Displays multiple badge examples + +## Technical Details + +- **Captured from**: Running FoundryVTT instance with Scrying Pool enabled +- **Date**: 2025-05-25 +- **Source URL**: https://localhost:31000/game +- **Resolution**: Full page screenshots (~291KB each) +- **Format**: JPEG + +## Image Paths in JournalEntry + +All images are referenced in the JournalEntry with absolute paths: +``` +modules/scrying-pool/packs/assets/screenshot-[name].jpg +``` + +## Notes + +- The JournalEntry HTML includes `onerror="this.style.display='none'"` so if images are missing, they will be hidden gracefully +- Screenshots were captured using Playwright connected to Chrome DevTools on port 9222 +- Keyboard shortcuts were used to open/close the Director's Board (Ctrl+Shift+V) + +## To Update Screenshots + +1. Ensure FoundryVTT is running with Scrying Pool enabled +2. Make sure Chrome is running with remote debugging on port 9222: + ```bash + chrome --remote-debugging-port=9222 --user-data-dir=/path/to/profile + ``` +3. Navigate to your FoundryVTT game +4. Run the capture script: + ```bash + node /tmp/take_screenshots.js + ``` +5. Replace the files in this directory with the new screenshots diff --git a/packs/assets/screenshot-badge-states.jpg b/packs/assets/screenshot-badge-states.jpg new file mode 100644 index 0000000..635beee Binary files /dev/null and b/packs/assets/screenshot-badge-states.jpg differ diff --git a/packs/assets/screenshot-directors-board.jpg b/packs/assets/screenshot-directors-board.jpg new file mode 100644 index 0000000..50faf5b Binary files /dev/null and b/packs/assets/screenshot-directors-board.jpg differ diff --git a/packs/assets/screenshot-main.jpg b/packs/assets/screenshot-main.jpg new file mode 100644 index 0000000..ab7287c Binary files /dev/null and b/packs/assets/screenshot-main.jpg differ diff --git a/packs/assets/screenshot-player-view.jpg b/packs/assets/screenshot-player-view.jpg new file mode 100644 index 0000000..635beee Binary files /dev/null and b/packs/assets/screenshot-player-view.jpg differ diff --git a/packs/assets/screenshot-presets.jpg b/packs/assets/screenshot-presets.jpg new file mode 100644 index 0000000..0e218cc Binary files /dev/null and b/packs/assets/screenshot-presets.jpg differ diff --git a/packs/scrying-pool-docs/CURRENT b/packs/scrying-pool-docs/CURRENT new file mode 100644 index 0000000..3051f81 --- /dev/null +++ b/packs/scrying-pool-docs/CURRENT @@ -0,0 +1 @@ +MANIFEST-000010 diff --git a/packs/scrying-pool-docs/LOCK b/packs/scrying-pool-docs/LOCK new file mode 100644 index 0000000..e69de29 diff --git a/packs/scrying-pool-docs/LOG b/packs/scrying-pool-docs/LOG new file mode 100644 index 0000000..d049e79 --- /dev/null +++ b/packs/scrying-pool-docs/LOG @@ -0,0 +1,7 @@ +2026/05/25-21:22:09.055974 7fe4caffd6c0 Recovering log #8 +2026/05/25-21:22:09.065763 7fe4caffd6c0 Delete type=3 #6 +2026/05/25-21:22:09.065817 7fe4caffd6c0 Delete type=0 #8 +2026/05/25-21:34:35.302659 7fe4c9ffb6c0 Level-0 table #13: started +2026/05/25-21:34:35.302696 7fe4c9ffb6c0 Level-0 table #13: 0 bytes OK +2026/05/25-21:34:35.309734 7fe4c9ffb6c0 Delete type=0 #11 +2026/05/25-21:34:35.322244 7fe4c9ffb6c0 Manual compaction at level-0 from 'undefined' @ 72057594037927935 : 1 .. 'undefined' @ 0 : 0; will stop at (end) diff --git a/packs/scrying-pool-docs/LOG.old b/packs/scrying-pool-docs/LOG.old new file mode 100644 index 0000000..e684e1b --- /dev/null +++ b/packs/scrying-pool-docs/LOG.old @@ -0,0 +1,7 @@ +2026/05/25-21:06:29.200379 7fe4ca7fc6c0 Recovering log #4 +2026/05/25-21:06:29.211069 7fe4ca7fc6c0 Delete type=3 #2 +2026/05/25-21:06:29.211126 7fe4ca7fc6c0 Delete type=0 #4 +2026/05/25-21:15:54.106468 7fe4c9ffb6c0 Level-0 table #9: started +2026/05/25-21:15:54.106502 7fe4c9ffb6c0 Level-0 table #9: 0 bytes OK +2026/05/25-21:15:54.142675 7fe4c9ffb6c0 Delete type=0 #7 +2026/05/25-21:15:54.142858 7fe4c9ffb6c0 Manual compaction at level-0 from 'undefined' @ 72057594037927935 : 1 .. 'undefined' @ 0 : 0; will stop at (end) diff --git a/packs/scrying-pool-docs/MANIFEST-000010 b/packs/scrying-pool-docs/MANIFEST-000010 new file mode 100644 index 0000000..6a72d77 Binary files /dev/null and b/packs/scrying-pool-docs/MANIFEST-000010 differ diff --git a/src/ui/gm/DirectorsBoard.js b/src/ui/gm/DirectorsBoard.js index 06f7566..1c328af 100644 --- a/src/ui/gm/DirectorsBoard.js +++ b/src/ui/gm/DirectorsBoard.js @@ -47,7 +47,7 @@ export class DirectorsBoard extends _AppBase { id: 'scrying-pool-directors-board', classes: ['scrying-pool', 'directors-board'], window: { title: "Director's Board", resizable: true }, - position: { width: 420, height: 480 }, + position: { width: 420, height: 480, left: 20, top: 100 }, }; static PARTS = { diff --git a/src/ui/gm/ScryingPoolSettings.js b/src/ui/gm/ScryingPoolSettings.js index 1475402..e66140c 100644 --- a/src/ui/gm/ScryingPoolSettings.js +++ b/src/ui/gm/ScryingPoolSettings.js @@ -3,16 +3,41 @@ * Scrying Pool Settings Application * Provides a settings panel with a button to reopen the strip */ -export class ScryingPoolSettings extends foundry.applications.api.ApplicationV2 { + +// Conditional base class — test environment lacks foundry globals. +const _AppBase = + typeof foundry !== 'undefined' && + foundry.applications?.api?.HandlebarsApplicationMixin && + foundry.applications?.api?.ApplicationV2 + ? foundry.applications.api.HandlebarsApplicationMixin( + foundry.applications.api.ApplicationV2 + ) + : class _FallbackApp { + static DEFAULT_OPTIONS = {}; + static PARTS = {}; + constructor(options = {}) { this.options = options; } + get rendered() { return this._rendered ?? false; } + set rendered(v) { this._rendered = v; } + get element() { return this._element ?? null; } + set element(v) { this._element = v; } + async render() { this._rendered = true; } + async close() { this._rendered = false; } + async _prepareContext() { return {}; } + _onRender() {} + _onClose() {} + _onPosition() {} + }; + +export class ScryingPoolSettings extends _AppBase { static DEFAULT_OPTIONS = { id: 'scrying-pool-settings', - classes: ['scrying-pool-settings'], + classes: ['scrying-pool', 'scrying-pool-settings'], window: { title: 'Scrying Pool Settings', resizable: true }, - position: { width: 400, height: 200 }, + position: { width: 320, height: 200 }, }; static PARTS = { - form: { + content: { template: 'modules/scrying-pool/templates/settings.hbs', }, }; @@ -37,6 +62,12 @@ export class ScryingPoolSettings extends foundry.applications.api.ApplicationV2 async _onRender(context, options) { super._onRender(context, options); + // Add click handler for window close button + const windowCloseBtn = this.element.querySelector('[data-action="close"]'); + if (windowCloseBtn) { + windowCloseBtn.addEventListener('click', () => this.close()); + } + // Add click handler for reopen button const reopenBtn = this.element.querySelector('[data-action="reopen-strip"]'); if (reopenBtn) { @@ -46,7 +77,7 @@ export class ScryingPoolSettings extends foundry.applications.api.ApplicationV2 }); } - // Add click handler for close button + // Add click handler for close strip button const closeBtn = this.element.querySelector('[data-action="close-strip"]'); if (closeBtn) { closeBtn.addEventListener('click', () => { diff --git a/styles/components/_directors-board.less b/styles/components/_directors-board.less index 6bbdf26..3843347 100644 --- a/styles/components/_directors-board.less +++ b/styles/components/_directors-board.less @@ -17,6 +17,9 @@ border-radius: 8px; box-shadow: 0 8px 32px rgba(0, 0, 0, 0.55), 0 2px 8px rgba(0, 0, 0, 0.35), inset 0 1px 0 rgba(255, 255, 255, 0.04); + + /* Ensure Director's Board appears above the video strip */ + z-index: 100; // ── Hide Foundry's default window header ────────────────────────────────── header.window-header { display: none; } diff --git a/styles/components/_roster-strip.less b/styles/components/_roster-strip.less index 703b478..1973115 100644 --- a/styles/components/_roster-strip.less +++ b/styles/components/_roster-strip.less @@ -25,6 +25,9 @@ .scrying-pool-strip { background: var(--sp-bg, hsl(220, 15%, 12%)); border-radius: 8px; + + /* Ensure strip appears below Director's Board (z-index: 100) */ + z-index: 50; // Hide Foundry's default window header — replaced by a lightweight in-content button. header.window-header { display: none; } diff --git a/templates/settings.hbs b/templates/settings.hbs index 6858196..182c5df 100644 --- a/templates/settings.hbs +++ b/templates/settings.hbs @@ -1,53 +1,210 @@ -