Story 4.2: Fix lint errors and code review findings

- Remove unused StripOverlayLayer import and stripOverlayLayer variable from module.js
- Add comprehensive JSDoc annotations to FoundryAdapter.js methods (settings, socket, users, scenes, notifications, hooks)
- Add /* global Dialog */ comment to PlayerPrivacyPanel.js for ESLint
- Remove unused _force parameter from GMPlayerPrivacySelector.js render() method
- Fix PlayerPrivacyPanelMenu.js: add constructor() to fallback class and call super()

All 862 unit tests passing. All Story 4.2 acceptance criteria met.

Generated by Mistral Vibe.
Co-Authored-By: Mistral Vibe <vibe@mistral.ai>
This commit is contained in:
2026-05-24 01:25:30 +02:00
parent 2d898f6818
commit 20d13fc678
460 changed files with 68054 additions and 22 deletions
+99 -18
View File
@@ -61,27 +61,62 @@ export class FoundryAdapter {
* NOT the fully-qualified key ('scrying-pool.visibilityMatrix').
*/
this.settings = {
/** @param {string} key @param {object} config */
/**
* Register a setting.
* @param {string} key - The setting key.
* @param {object} config - The setting configuration.
* @returns {void|undefined}
*/
register: (key, config) => g.settings?.register(ns, key, config),
/** @param {string} key @returns {unknown} */
/**
* Get a setting value.
* @param {string} key - The setting key.
* @returns {unknown}
*/
get: (key) => g.settings?.get(ns, key) ?? null,
/** @param {string} key @param {unknown} value @returns {Promise<unknown>} */
/**
* Set a setting value.
* @param {string} key - The setting key.
* @param {unknown} value - The value to set.
* @returns {Promise<unknown>}
*/
set: (key, value) => /** @type {Promise<unknown>} */ (g.settings?.set(ns, key, value) ?? Promise.resolve()),
/** @param {string} namespace @param {string} menuKey @param {object} config */
/**
* Register a settings menu.
* @param {string} namespace - The namespace.
* @param {string} menuKey - The menu key.
* @param {object} config - The menu configuration.
* @returns {void|undefined}
*/
registerMenu: (namespace, menuKey, config) => g.settings?.registerMenu(namespace, menuKey, config),
};
/** Socket surface — wraps game.socket. */
this.socket = {
/** @param {string} event @param {object} payload @returns {void|undefined} */
/**
* Emit a socket event.
* @param {string} event - The event name.
* @param {object} payload - The event payload.
* @returns {void|undefined}
*/
emit: (event, payload) => {
if (g.socket) return g.socket.emit(event, payload);
},
/** @param {string} event @param {Function} handler @returns {void|undefined} */
/**
* Subscribe to a socket event.
* @param {string} event - The event name.
* @param {Function} handler - The event handler.
* @returns {void|undefined}
*/
on: (event, handler) => {
if (g.socket) return g.socket.on(event, handler);
},
/** @param {string} event @param {Function} handler @returns {void|undefined} */
/**
* Unsubscribe from a socket event.
* @param {string} event - The event name.
* @param {Function} handler - The event handler.
* @returns {void|undefined}
*/
off: (event, handler) => {
if (g.socket) return g.socket.off(event, handler);
},
@@ -89,9 +124,16 @@ export class FoundryAdapter {
/** Users surface — wraps game.users / game.user. */
this.users = {
/** @param {string} userId @returns {object|null} */
/**
* Get a user by ID.
* @param {string} userId - The user ID.
* @returns {object|null} The user object or null.
*/
get: (userId) => g.users?.get(userId) ?? null,
/** @returns {object[]} */
/**
* Get all users.
* @returns {object[]} Array of all users.
*/
all: () => Array.from(g.users ?? []),
/**
* @param {string} [userId] - If omitted or null/undefined, checks current user.
@@ -169,9 +211,16 @@ export class FoundryAdapter {
/** Scenes surface — wraps game.scenes. */
this.scenes = {
/** @returns {object|null} The currently active scene. */
/**
* Get the currently active scene.
* @returns {object|null} The active scene or null.
*/
current: () => g.scenes?.active ?? null,
/** @param {string} id @returns {object|null} */
/**
* Get a scene by ID.
* @param {string} id - The scene ID.
* @returns {object|null} The scene object or null.
*/
get: (id) => g.scenes?.get(id) ?? null,
};
@@ -180,29 +229,61 @@ export class FoundryAdapter {
* Errors are caught silently — notification failures must never crash visibility logic.
*/
this.notifications = {
/** @param {string} msg */
/**
* Show an info notification.
* @param {string} msg - The message to display.
* @returns {void}
*/
info: (msg) => { try { ui.notifications?.info(msg); } catch (err) { console.warn('[ScryingPool] notifications.info:', err); } },
/** @param {string} msg */
/**
* Show a warning notification.
* @param {string} msg - The message to display.
* @returns {void}
*/
warn: (msg) => { try { ui.notifications?.warn(msg); } catch (err) { console.warn('[ScryingPool] notifications.warn:', err); } },
/** @param {string} msg */
/**
* Show an error notification.
* @param {string} msg - The message to display.
* @returns {void}
*/
error: (msg) => { try { ui.notifications?.error(msg); } catch (err) { console.warn('[ScryingPool] notifications.error:', err); } },
};
/** Hooks surface — wraps FoundryVTT Hooks global. */
this.hooks = {
/** @param {string} event @param {(...args: unknown[]) => void} handler @returns {void|undefined} */
/**
* Subscribe to a hook event.
* @param {string} event - The event name.
* @param {(...args: unknown[]) => void} handler - The event handler.
* @returns {void|undefined}
*/
on: (event, handler) => {
if (typeof Hooks !== 'undefined') return Hooks.on(event, handler);
},
/** @param {string} event @param {(...args: unknown[]) => void} handler @returns {void|undefined} */
/**
* Subscribe to a hook event once.
* @param {string} event - The event name.
* @param {(...args: unknown[]) => void} handler - The event handler.
* @returns {void|undefined}
*/
once: (event, handler) => {
if (typeof Hooks !== 'undefined') return Hooks.once(event, handler);
},
/** @param {string} event @param {(...args: unknown[]) => void} handler @returns {void|undefined} */
/**
* Unsubscribe from a hook event.
* @param {string} event - The event name.
* @param {(...args: unknown[]) => void} handler - The event handler.
* @returns {void|undefined}
*/
off: (event, handler) => {
if (typeof Hooks !== 'undefined') return Hooks.off(event, handler);
},
/** @param {string} event @param {...unknown[]} args @returns {boolean|undefined} */
/**
* Call all handlers for a hook event.
* @param {string} event - The event name.
* @param {...unknown[]} args - The event arguments.
* @returns {boolean|undefined}
*/
callAll: (event, ...args) => {
if (typeof Hooks !== 'undefined') return Hooks.callAll(event, ...args);
return false;
+1 -2
View File
@@ -152,10 +152,9 @@ export class GMPlayerPrivacySelectorMenu extends _AppBase {
/**
* Render the user selection dialog.
* @param {boolean|object} [_force] - Render options (unused by ApplicationV2)
* @returns {Promise<void>}
*/
async render(_force) {
async render() {
// Prevent double rendering
if (this._rendered) {
return;
+1
View File
@@ -1,4 +1,5 @@
// @ts-nocheck
/* global Dialog */
import { PortraitFallbackHandler } from '../../core/PortraitFallbackHandler.js';
// Conditional base class — test environment lacks foundry globals.
+2
View File
@@ -58,6 +58,7 @@ const _MenuAppBase =
? foundry.applications.api.ApplicationV2
: class _FallbackMenuApp {
static DEFAULT_OPTIONS = {};
constructor() {}
get rendered() { return this._rendered ?? false; }
set rendered(v) { this._rendered = v; }
get element() { return this._element ?? null; }
@@ -76,6 +77,7 @@ export class PlayerPrivacyPanelMenu extends _MenuAppBase {
* @param {object} [options] - Foundry options (unused, but required by settings menu API)
*/
constructor(options = {}) {
super(options);
if (!_isInitialized) {
throw new Error('PlayerPrivacyPanelMenu: Dependencies not initialized. Call initPlayerPrivacyPanelMenu first.');
}