Skip to content

Commit 3585894

Browse files
authored
Merge pull request #74 from keyxmakerx/claude/chronicle-sheet-sync-j2m9s4
fix(dashboard): reliably reopen after close
2 parents 96f0821 + 2c58f2c commit 3585894

1 file changed

Lines changed: 31 additions & 8 deletions

File tree

scripts/module.mjs

Lines changed: 31 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,27 @@ let dashboard = null;
3030
/** @type {HTMLElement|null} Sidebar status indicator, re-attached on re-render. */
3131
let _statusIndicatorEl = null;
3232

33+
/**
34+
* Open the Sync Dashboard, recreating the singleton if it isn't currently
35+
* rendered. An ApplicationV2 instance can be left in a non-re-renderable state
36+
* after a close (notably when the close interrupts an in-flight render), which
37+
* made the dashboard intermittently fail to reopen. Mirrors the SyncCalendar
38+
* singleton helper: bring an already-open window to the front; otherwise build,
39+
* (re)bind, and render a fresh instance. `bind()` only sets a reference, so
40+
* recreating leaks nothing.
41+
* @returns {SyncDashboard|null}
42+
*/
43+
function openDashboard() {
44+
if (dashboard && dashboard.rendered) {
45+
dashboard.bringToFront?.();
46+
return dashboard;
47+
}
48+
dashboard = new SyncDashboard();
49+
if (syncManager) dashboard.bind(syncManager);
50+
dashboard.render({ force: true });
51+
return dashboard;
52+
}
53+
3354
/**
3455
* Module initialization — register settings.
3556
* This runs before the game is fully ready.
@@ -207,9 +228,9 @@ async function _runtimeValidateDescriptor() {
207228
Hooks.on('getSceneControlButtons', (controls) => {
208229
if (!game.user.isGM) return;
209230

210-
const openDashboard = () => {
211-
if (dashboard) dashboard.render({ force: true });
212-
};
231+
// openDashboard() is the module-level helper above: it recreates the
232+
// dashboard when a prior close left the instance non-re-renderable, fixing
233+
// the intermittent "can't reopen the dashboard" bug.
213234
// FM-CAL-DASHBOARD-LINK: surface SyncCalendarApplication as a second
214235
// tool in the Chronicle Sync scene-control group. The singleton helper
215236
// is GM-only by contract; the outer GM guard above is also enforced.
@@ -342,15 +363,15 @@ function _addStatusIndicator() {
342363
if (syncManager.api.state === 'disconnected') {
343364
syncManager.api.connect();
344365
ui.notifications.info('Chronicle: Reconnecting...');
345-
} else if (dashboard) {
346-
dashboard.render({ force: true });
366+
} else {
367+
openDashboard();
347368
}
348369
});
349370

350371
// Right-click always opens the dashboard (even when disconnected).
351372
indicator.addEventListener('contextmenu', (e) => {
352373
e.preventDefault();
353-
if (dashboard) dashboard.render({ force: true });
374+
openDashboard();
354375
});
355376

356377
// Flash the dot briefly when a WS message arrives (activity indicator).
@@ -431,9 +452,11 @@ Hooks.once('ready', () => {
431452
if (module) {
432453
module.api = {
433454
syncManager,
434-
dashboard,
455+
// Getter (not a snapshot): openDashboard() may recreate the instance, so
456+
// expose the live reference rather than the one captured at ready time.
457+
get dashboard() { return dashboard; },
435458
getAPI: () => syncManager?.api,
436-
openDashboard: () => dashboard?.render({ force: true }),
459+
openDashboard: () => openDashboard(),
437460
// Version-independent diagnostics escape hatch. Lets an operator always
438461
// produce the System Debug snapshot from the console even if the toolbar
439462
// button or sidebar indicator regress on a Foundry upgrade. DOM-

0 commit comments

Comments
 (0)