chore: bump tracking ledger version to 1.3.0
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
|
||||
const MODULE_ID = "gowlers-tracking-ledger";
|
||||
const MODULE_VERSION = "1.2.1";
|
||||
const MODULE_VERSION = "1.3.0";
|
||||
const TRACK_SETTING = "actorSettings";
|
||||
const FLAG_SCOPE = "world";
|
||||
const MAX_HISTORY_ROWS = 100;
|
||||
@@ -2095,6 +2095,7 @@ class TrackingLedgerConfig extends FormApplication {
|
||||
this._pageMeta = { totalPages: 1, hasPrev: false, hasNext: false };
|
||||
this._actorRefs = null;
|
||||
this._filterDebounceTimer = null;
|
||||
this._pendingFilterCaret = null;
|
||||
}
|
||||
|
||||
get pageSize() {
|
||||
@@ -2248,6 +2249,10 @@ class TrackingLedgerConfig extends FormApplication {
|
||||
this._page = 0;
|
||||
TrackingLedgerConfig._lastFilter = this._filter;
|
||||
TrackingLedgerConfig._lastPage = this._page;
|
||||
const el = event.currentTarget;
|
||||
const selStart = Number.isFinite(el.selectionStart) ? el.selectionStart : (this._filter?.length ?? 0);
|
||||
const selEnd = Number.isFinite(el.selectionEnd) ? el.selectionEnd : selStart;
|
||||
this._pendingFilterCaret = { start: selStart, end: selEnd };
|
||||
|
||||
// Debounce render to preserve focus
|
||||
clearTimeout(this._filterDebounceTimer);
|
||||
@@ -2255,8 +2260,17 @@ class TrackingLedgerConfig extends FormApplication {
|
||||
this.render(false);
|
||||
}, 300);
|
||||
});
|
||||
// Keep focus on filter input after render
|
||||
filterInput.trigger("focus");
|
||||
// Keep focus/caret on filter input after render
|
||||
setTimeout(() => {
|
||||
const el = filterInput[0];
|
||||
if (!el) return;
|
||||
const caret = this._pendingFilterCaret;
|
||||
el.focus();
|
||||
const posStart = Number.isFinite(caret?.start) ? caret.start : el.value.length;
|
||||
const posEnd = Number.isFinite(caret?.end) ? caret.end : posStart;
|
||||
try { el.setSelectionRange(posStart, posEnd); } catch (e) { /* ignore */ }
|
||||
this._pendingFilterCaret = null;
|
||||
}, 0);
|
||||
|
||||
html.find("[data-page-size]").on("change", (event) => {
|
||||
const value = event.currentTarget.value;
|
||||
@@ -2399,38 +2413,21 @@ async function clearDocumentHistory(doc) {
|
||||
DAMAGE_DEALT_FLAG,
|
||||
ENCOUNTER_FLAG,
|
||||
];
|
||||
for (const key of flagKeys) {
|
||||
await Promise.all(
|
||||
flagKeys.map(async (key) => {
|
||||
try {
|
||||
await doc.unsetFlag(FLAG_SCOPE, key);
|
||||
} catch (err) {
|
||||
console.warn(`[GowlersTracking] Failed to clear flag ${key} for ${doc.name ?? doc.id}`, err);
|
||||
}
|
||||
}
|
||||
})
|
||||
);
|
||||
primeDocBaseline(doc);
|
||||
}
|
||||
|
||||
async function clearAllHistoriesWithProgress() {
|
||||
try {
|
||||
const targets = new Map();
|
||||
|
||||
// Core actors in the directory
|
||||
for (const actor of collectAllActorDocuments()) {
|
||||
const key = `actor:${actor.uuid ?? actor.id}`;
|
||||
if (!targets.has(key)) targets.set(key, { doc: actor, label: actor.name ?? actor.id });
|
||||
}
|
||||
|
||||
// Tokens on scenes (covers unlinked NPCs) and their embedded actor documents
|
||||
for (const token of collectAllTokens()) {
|
||||
const tokenKey = `token:${token.uuid ?? token.id}:${token.parent?.uuid ?? "scene"}`;
|
||||
if (!targets.has(tokenKey)) targets.set(tokenKey, { doc: token, label: token.name ?? token.id });
|
||||
|
||||
const tokenActor = token.actor;
|
||||
if (tokenActor) {
|
||||
const actorKey = `actor:${tokenActor.uuid ?? tokenActor.id}`;
|
||||
if (!targets.has(actorKey)) targets.set(actorKey, { doc: tokenActor, label: tokenActor.name ?? tokenActor.id });
|
||||
}
|
||||
}
|
||||
|
||||
const entries = Array.from(targets.values());
|
||||
const entries = collectClearTargets();
|
||||
if (!entries.length) {
|
||||
ui.notifications?.info?.("No actor or token histories found to clear.");
|
||||
return;
|
||||
@@ -2473,6 +2470,40 @@ async function clearAllHistoriesWithProgress() {
|
||||
}
|
||||
}
|
||||
|
||||
function collectClearTargets() {
|
||||
const targets = new Map();
|
||||
|
||||
// Core actors in the directory (player characters and linked NPCs)
|
||||
for (const actor of collectAllActorDocuments()) {
|
||||
const key = `actor:${actor.uuid ?? actor.id}`;
|
||||
if (!targets.has(key)) targets.set(key, { doc: actor, label: `${actor.name ?? actor.id} (Actor)` });
|
||||
}
|
||||
|
||||
// Tokens on scenes (covers unlinked NPCs and token-specific flags)
|
||||
for (const token of collectAllTokens()) {
|
||||
const tokenKey = `token:${token.uuid ?? token.id}:${token.parent?.uuid ?? "scene"}`;
|
||||
if (!targets.has(tokenKey)) {
|
||||
const sceneName = token.parent?.name ? ` - ${token.parent.name}` : "";
|
||||
targets.set(tokenKey, { doc: token, label: `${token.name ?? token.id}${sceneName} (Token)` });
|
||||
}
|
||||
|
||||
// Include the token's actor (unlinked actor copies need clearing too)
|
||||
const tokenActor = token.actor;
|
||||
if (tokenActor) {
|
||||
const actorKey = `actor:${tokenActor.uuid ?? tokenActor.id}`;
|
||||
if (!targets.has(actorKey)) targets.set(actorKey, { doc: tokenActor, label: `${tokenActor.name ?? tokenActor.id} (Actor)` });
|
||||
}
|
||||
}
|
||||
|
||||
return Array.from(targets.values());
|
||||
}
|
||||
|
||||
function primeDocBaseline(doc) {
|
||||
if (!doc) return;
|
||||
const actor = doc instanceof Actor ? doc : doc.actor;
|
||||
if (actor) primeActor(actor);
|
||||
}
|
||||
|
||||
function collectAllActorDocuments() {
|
||||
const actors = new Map();
|
||||
for (const a of game.actors.contents ?? []) {
|
||||
|
||||
Reference in New Issue
Block a user