diff --git a/src/macros_new/gowlers-tracking-ledger/foundry.gowlershome.dyndns.org/modules/gowlers-tracking-ledger/scripts/gowlers-tracking-ledger.js b/src/macros_new/gowlers-tracking-ledger/foundry.gowlershome.dyndns.org/modules/gowlers-tracking-ledger/scripts/gowlers-tracking-ledger.js index 8d1d30c8..b84bb121 100644 --- a/src/macros_new/gowlers-tracking-ledger/foundry.gowlershome.dyndns.org/modules/gowlers-tracking-ledger/scripts/gowlers-tracking-ledger.js +++ b/src/macros_new/gowlers-tracking-ledger/foundry.gowlershome.dyndns.org/modules/gowlers-tracking-ledger/scripts/gowlers-tracking-ledger.js @@ -1,6 +1,6 @@ const MODULE_ID = "gowlers-tracking-ledger"; -const MODULE_VERSION = "0.1.23"; +const MODULE_VERSION = "0.1.25"; const TRACK_SETTING = "actorSettings"; const FLAG_SCOPE = "world"; const MAX_HISTORY_ROWS = 100; @@ -80,14 +80,42 @@ const ledgerState = { lastCombatEndTime: 0, // Timestamp when combat ended openDialogs: new Map(), // actorId -> dialog instance (for live updates) recentMessages: [], // Array of recent message metadata: { message, timestamp, source } + historyPageState: new Map(), // actorId -> { [tabId]: { page, pageSize } } + historyTabState: new Map(), // actorId -> active tab id }; +function getHistoryPageState(actorId, tabId) { + if (!actorId || !tabId) return { page: 1, pageSize: 10 }; + const perActor = ledgerState.historyPageState.get(actorId) ?? {}; + return perActor[tabId] ?? { page: 1, pageSize: 10 }; +} + +function setHistoryPageState(actorId, tabId, page, pageSize) { + if (!actorId || !tabId) return; + const perActor = ledgerState.historyPageState.get(actorId) ?? {}; + perActor[tabId] = { + page: Math.max(1, Number.isFinite(page) ? page : 1), + pageSize: pageSize === "all" ? "all" : (Number(pageSize) > 0 ? Number(pageSize) : 10), + }; + ledgerState.historyPageState.set(actorId, perActor); +} + +function getActiveHistoryTab(actorId, fallback = "hp") { + if (!actorId) return fallback; + return ledgerState.historyTabState.get(actorId) ?? fallback; +} + +function setActiveHistoryTab(actorId, tabId) { + if (!actorId || !tabId) return; + ledgerState.historyTabState.set(actorId, tabId); +} + // Global tab switching function for history dialog -window.switchHistoryTab = function(tabId) { +window.switchHistoryTab = function(tabId, el = null) { console.log("[GowlersTracking] Tab switched to:", tabId); // Find the root element using the data-history-root attribute - const root = document.querySelector('[data-history-root]'); + const root = el?.closest?.('[data-history-root]') ?? document.querySelector('[data-history-root]'); if (!root) { console.warn("[GowlersTracking] History root element not found"); return; @@ -118,6 +146,11 @@ window.switchHistoryTab = function(tabId) { } else { console.warn("[GowlersTracking] Tab panel not found for:", tabId); } + + const actorId = root?.getAttribute('data-history-root'); + if (actorId) { + setActiveHistoryTab(actorId, tabId); + } }; // Global function for history dialog pagination navigation @@ -125,14 +158,14 @@ window.historyPageNav = function(button, direction) { const panel = button.closest('[data-history-panel]'); if (!panel) return; - const currentPage = parseInt(panel.getAttribute('data-page') || '1'); const pageInfo = panel.querySelector('[data-page-info]'); if (!pageInfo) return; const pageMatch = pageInfo.textContent.match(/Page (\d+) \/ (\d+)/); if (!pageMatch) return; - const totalPages = parseInt(pageMatch[2]); + const totalPages = parseInt(pageMatch[2]) || 1; + const currentPage = parseInt(panel.getAttribute('data-page') || pageMatch[1] || '1'); let newPage = currentPage; if (direction === 'next' && currentPage < totalPages) { @@ -145,8 +178,18 @@ window.historyPageNav = function(button, direction) { panel.setAttribute('data-page', newPage); console.log("[GowlersTracking] History pagination - moving to page:", newPage); - // Rebuild the table with new page const root = panel.closest('[data-history-root]'); + const actorId = root?.getAttribute('data-history-root'); + const tabId = panel.getAttribute('data-history-panel'); + + const pageSizeAttr = panel.getAttribute('data-page-size') || '10'; + const pageSize = pageSizeAttr === 'all' ? 'all' : Number(pageSizeAttr) || 10; + if (actorId && tabId) { + setHistoryPageState(actorId, tabId, newPage, pageSize); + refreshOpenDialogs(actorId); + } + + // Rebuild the table with new page if (root) { const app = root.closest('.app, .window-app, .dialog, [role="dialog"]'); if (app && app.__vue__?.constructor?.name === 'Dialog') { @@ -167,10 +210,18 @@ window.historyChangePageSize = function(select) { panel.setAttribute('data-page', '1'); panel.setAttribute('data-page-size', pageSize); + const root = panel.closest('[data-history-root]'); + const actorId = root?.getAttribute('data-history-root'); + const tabId = panel.getAttribute('data-history-panel'); + const normalizedSize = pageSize === 'all' ? 'all' : (Number(pageSize) > 0 ? Number(pageSize) : 10); + if (actorId && tabId) { + setHistoryPageState(actorId, tabId, 1, normalizedSize); + refreshOpenDialogs(actorId); + } + console.log("[GowlersTracking] History page size changed to:", pageSize); // Re-render dialog - const root = panel.closest('[data-history-root]'); if (root) { const app = root.closest('.app, .window-app, .dialog, [role="dialog"]'); if (app && app.__vue__?.constructor?.name === 'Dialog') { @@ -193,8 +244,9 @@ function refreshOpenDialogs(actorId) { const actor = game.actors.get(actorId); if (!actor) return; - // Rebuild content - const content = buildHistoryContent(actor, "hp"); + // Rebuild content using the last active tab for this actor + const activeTab = getActiveHistoryTab(actorId, "hp"); + const content = buildHistoryContent(actor, activeTab); dialog.data.content = content; // Re-render the dialog @@ -814,18 +866,7 @@ function buildXpBreakdownTooltip(actor, xpEntry) { let breakdown = []; if (encounter.participants && encounter.participants.length > 0) { // Resolve participant UUIDs/IDs to actor names - const participantNames = encounter.participants.slice(0, 2).map(p => { - // Try to resolve UUID or actor ID to name - if (p.startsWith("Actor.")) { - const participantActor = fromUuidSync(p); - return participantActor?.name || p.slice(0, 8); - } else if (typeof p === "string" && p.length > 20) { - // Likely a UUID - try to resolve - const participantActor = game.actors.get(p); - return participantActor?.name || p.slice(0, 8); - } - return p; // Already a name - }); + const participantNames = encounter.participants.slice(0, 2).map(resolveParticipantName); const participantsStr = participantNames.join(", "); const more = encounter.participants.length > 2 ? ` +${encounter.participants.length - 2} more` : ""; @@ -847,8 +888,9 @@ function buildXpBreakdownTooltip(actor, xpEntry) { } function buildHistoryContent(actor, tabArg) { - const initialTab = tabArg ?? "hp"; // Explicitly capture the tab parameter + const initialTab = tabArg ?? getActiveHistoryTab(actor.id, "hp"); // Explicitly capture the tab parameter console.log("[GowlersTracking] buildHistoryContent called with initialTab:", initialTab); + setActiveHistoryTab(actor.id, initialTab); const canConfigure = game.user?.isGM; const configs = [ { @@ -914,7 +956,7 @@ function buildHistoryContent(actor, tabArg) { .map( (cfg) => { const isActive = cfg.id === initialTab ? "active" : ""; - return ``; + return ``; } ) .join(""); @@ -924,19 +966,25 @@ function buildHistoryContent(actor, tabArg) { const entries = actor.getFlag(FLAG_SCOPE, cfg.flag) ?? []; const display = cfg.id === initialTab ? "block" : "none"; const isActive = cfg.id === initialTab ? "active" : ""; - const rowsPerPage = 10; // Default rows per page for history dialog - const totalPages = Math.ceil(entries.length / rowsPerPage); - return `