diff --git a/CHANGELOG.md b/CHANGELOG.md index eb59846..69d87fb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,8 +7,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +## [1.3.11] - 2025-01-15 + ### Fixed -- Restored compatibility with PopOut! by cloning sidebar base options before overriding defaults so Combat Tracker and other stock tabs keep their pop-out buttons when realtime sync is enabled. +- When syncing existing Session Recaps via the "Sync with Archivist" button, the `sessionDate` flag is now properly detected and updated when the `session_date` changes in Archivist, ensuring correct date display and chronological sorting in the Recaps folder. ## [1.3.10] - 2025-01-15 diff --git a/module.json b/module.json index 5943425..cba0cb1 100644 --- a/module.json +++ b/module.json @@ -8,7 +8,7 @@ "email": "cameron.b.llewellyn@gmail.com" } ], - "version": "1.3.10", + "version": "1.3.11", "compatibility": { "minimum": "13.341", "verified": "13.346" diff --git a/package.json b/package.json index 6d15706..21fa292 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "archivist-sync", - "version": "1.3.10", + "version": "1.3.11", "description": "A simple Foundry VTT module for fetching world data from an API endpoint using an API key.", "type": "module", "scripts": { diff --git a/scripts/dialogs/sync-dialog.js b/scripts/dialogs/sync-dialog.js index 298a0fa..81fb955 100644 --- a/scripts/dialogs/sync-dialog.js +++ b/scripts/dialogs/sync-dialog.js @@ -214,6 +214,50 @@ export class SyncDialog extends foundry.applications.api.HandlebarsApplicationMi } } + // Reorder all recaps after any sessionDate changes (from diffs or imports) + const hasRecapDiffs = selectedDiffs.some( + (d) => d.type === 'Session' && d.changes?.sessionDate + ); + if (hasRecapDiffs || selectedImports.some((i) => i.type === 'Session')) { + try { + const recapsFolderId = await Utils.ensureJournalFolder('Recaps'); + const entries = (game.journal?.contents || []) + .filter((j) => (j.folder?.id || null) === (recapsFolderId || null)) + .filter( + (j) => + String( + (j.getFlag(CONFIG.MODULE_ID, 'archivist') || {}).sheetType || + '' + ) === 'recap' + ); + const withDates = entries.map((j) => ({ + j, + dateMs: (() => { + const iso = String( + j.getFlag(CONFIG.MODULE_ID, 'sessionDate') || '' + ).trim(); + const t = iso ? new Date(iso).getTime() : NaN; + return Number.isFinite(t) ? t : Number.POSITIVE_INFINITY; // undated go to end + })(), + })); + withDates.sort((a, b) => a.dateMs - b.dateMs); + let index = 0; + for (const { j } of withDates) { + const desired = index * 1000; + index += 1; + if (j.sort !== desired) { + try { + await j.update({ sort: desired }, { render: false }); + } catch (_) { + /* ignore */ + } + } + } + } catch (_) { + /* ignore ordering failures */ + } + } + ui.notifications?.info?.('Archivist sync applied.'); // Force-refresh core directories and any open Archivist windows so UI reflects new docs await this._refreshUIAfterSync?.(); @@ -420,6 +464,20 @@ export class SyncDialog extends foundry.applications.api.HandlebarsApplicationMi if (flagImg !== archImg) changes.image = { from: flagImg, to: archImg }; } + // Session date diff: compare Archivist session_date with Foundry sessionDate flag + if (type === 'Session' && arch.session_date) { + try { + const currentDate = String( + j.getFlag(CONFIG.MODULE_ID, 'sessionDate') || '' + ).trim(); + const archDate = String(arch.session_date || '').trim(); + if (archDate && currentDate !== archDate) { + changes.sessionDate = { from: currentDate || null, to: archDate }; + } + } catch (_) { + /* ignore */ + } + } // Links diff: only outgoing links (from_id == this sheet's archivistId), ignore alias try { const wantList = outgoing.get(archId) || []; @@ -586,6 +644,35 @@ export class SyncDialog extends foundry.applications.api.HandlebarsApplicationMi await j.setFlag(CONFIG.MODULE_ID, 'archivist', nextFlags); // Hub image flag removed } + if (changes.sessionDate) { + // Update sessionDate flag to match Archivist session_date (same as world setup) + const archDate = String(changes.sessionDate.to || '').trim(); + if (archDate) { + try { + await j.setFlag( + CONFIG.MODULE_ID, + 'sessionDate', + archDate + ); + // Also update sort order if this is a recap in the Recaps folder + const sheetType = String( + (j.getFlag(CONFIG.MODULE_ID, 'archivist') || {}).sheetType || '' + ).toLowerCase(); + if (sheetType === 'recap' || sheetType === 'session') { + try { + const sortValue = new Date(archDate).getTime(); + if (Number.isFinite(sortValue)) { + await j.update({ sort: sortValue }, { render: false }); + } + } catch (_) { + /* ignore sort update failures */ + } + } + } catch (_) { + /* ignore */ + } + } + } if (changes.links) { const buckets = { character: 'characters', diff --git a/templates/sync-dialog.hbs b/templates/sync-dialog.hbs index fa2b7ce..c70f7a1 100644 --- a/templates/sync-dialog.hbs +++ b/templates/sync-dialog.hbs @@ -29,6 +29,7 @@