Updating the compendium filter to make it more snappy

This commit is contained in:
Litasa
2026-02-27 04:15:10 +00:00
parent aa203c546c
commit 2dd9ee19e9
17 changed files with 2327 additions and 639 deletions

View File

@@ -1,4 +1,4 @@
import { L5r5eHtmlMultiSelectElement } from "./misc/l5r5e-multiselect.js";
import { ItemCompendiumL5r5e } from "./compendium/l5r5e-item-compendium.js"
export default class HooksL5r5e {
/**
@@ -26,6 +26,8 @@ export default class HooksL5r5e {
) {
game.babele.setSystemTranslationsDir("babele"); // Since Babele v2.0.7
}
ItemCompendiumL5r5e.applyToPacks();
}
/**
@@ -245,236 +247,6 @@ export default class HooksL5r5e {
});
}
/**
* Compendium display (Add filters)
*/
static async renderCompendium(app, html, data) {
html = $(html); // basic patch for v13
if (app.collection.documentName === "Item") {
const content = await app.collection.getDocuments();
const sourcesInThisCompendium = new Set([]);
const filtersToShow = {
rank: false,
rarity: false,
source: false,
ring: false,
};
// Used to auto hide same values for a full compendium
const previousValue = {
rank: null,
rarity: null,
source: null,
ring: null,
};
// Cache
const header = html.find(".directory-header");
const entries = html.find(".directory-item");
// Add additional data to the entries to make it faster to lookup.
// Add Ring/rank/rarity information
for (const document of content) {
const entry = entries.filter(`[data-entry-id="${document.id}"]`);
// Hide filter if only one value of this type is found in the compendium
const autoDisplayFilter = (props, documentData = null) => {
documentData ??= document.system[props];
if (filtersToShow[props] || previousValue[props] === documentData) {
return;
}
filtersToShow[props] = previousValue[props] !== null && previousValue[props] !== documentData;
previousValue[props] = documentData;
};
if (document.system?.rank) {
autoDisplayFilter('rank');
entry.data("rank", document.system.rank);
}
if (document.system?.source_reference.source) {
autoDisplayFilter('source', document.system.source_reference.source);
sourcesInThisCompendium.add(document.system.source_reference.source);
entry.data("source", document.system.source_reference);
}
if (document.system?.ring) {
autoDisplayFilter('ring');
entry.data("ring", document.system.ring);
}
if (document.system?.rarity) {
autoDisplayFilter('rarity');
entry.data("rarity", document.system.rarity);
}
// Add ring/rank/rarity information on the item in the compendium view
if (document.system?.ring || document.system?.rarity || document.system?.rank) {
const ringRarityRank = await foundry.applications.handlebars.renderTemplate(`${CONFIG.l5r5e.paths.templates}compendium/ring-rarity-rank.html`, document.system);
entry.append(ringRarityRank);
}
}
// Setup filters
const officialContentSet = game.settings.get(CONFIG.l5r5e.namespace, "compendium-official-content-for-players");
const unofficialContentSet = game.settings.get(CONFIG.l5r5e.namespace, "compendium-unofficial-content-for-players");
const allCompendiumReferencesSet = game.settings.get(CONFIG.l5r5e.namespace, "all-compendium-references")
const hideEmptySourcesFromPlayers = game.settings.get(CONFIG.l5r5e.namespace, "compendium-hide-empty-sources-from-players");
const unavailableSourceForPlayersSet = new Set([...allCompendiumReferencesSet].filter((element) => {
if (CONFIG.l5r5e.sourceReference[element]) {
return officialContentSet.size > 0 ? !officialContentSet.has(element) : false;
}
return unofficialContentSet.size > 0 ? !unofficialContentSet.has(element) : false;
}));
// Create filter function
const applyCompendiumFilter = () => {
const userFilter = header.find("l5r5e-multi-select").val();
const rankFilter = header.find(".rank-filter .selected").data("rank");
const ringFilter = header.find(".ring-filter .selected").data("ring");
const rarityFilter = header.find(".rarity-filter .selected").data("rarity");
entries.each(function () {
const lineSource = $(this).data("source")?.source;
// We might have stuff in the compendium view that does not have a source (folders etc.) Ignore those.
if (lineSource === null || lineSource === undefined) {
return;
}
let shouldShow = true;
// Handle unavailable sources
if (unavailableSourceForPlayersSet.has(lineSource)) {
if (game.user.isGM) {
shouldShow &= true;
$(this)
.addClass("not-for-players")
.attr("data-tooltip", game.i18n.localize("l5r5e.compendium.not_for_players"));
} else {
shouldShow &= false;
}
}
// Handle empty sources
if (lineSource === "" && hideEmptySourcesFromPlayers) {
if (game.user.isGM) {
shouldShow &= true;
$(this)
.addClass("not-for-players")
.attr("data-tooltip", game.i18n.localize("l5r5e.compendium.not_for_players"));
} else {
shouldShow &= false;
}
}
// Apply filters
if (rankFilter) {
shouldShow &= $(this).data("rank") == rankFilter;
}
if (userFilter?.length) {
shouldShow &= userFilter.includes(lineSource);
}
if (ringFilter) {
shouldShow &= $(this).data("ring") == ringFilter;
}
if (rarityFilter >= 0) {
shouldShow &= $(this).data("rarity") == rarityFilter;
}
// Show or hide this entry based on the result
shouldShow ? $(this).show() : $(this).hide();
});
};
// Filter setup
const addFilter = async (filterType, templateFile, templateData) => {
if (!filtersToShow[filterType]) {
return;
}
const filterTemplate = await foundry.applications.handlebars.renderTemplate(
`${CONFIG.l5r5e.paths.templates}compendium/${templateFile}.html`,
templateData
);
header.append(filterTemplate);
header.find(`.${filterType}-filter`).children().each(function () {
$(this).on("click", (event) => {
const selected = $(event.target).hasClass("selected");
header.find(`.${filterType}-filter`).children().removeClass("selected");
$(event.target).toggleClass("selected", !selected);
applyCompendiumFilter();
});
});
};
// Add Rank, Rarity, Ring Filters
await Promise.all([
addFilter('rank' , 'rank-filter', { type: "rank", number: [1, 2, 3, 4, 5] }),
addFilter('rarity', 'rank-filter', { type: "rarity", number: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10] }),
addFilter('ring' , 'ring-filter', {}),
]);
if (filtersToShow.source) {
// Build the source select
const selectableSourcesArray = [...allCompendiumReferencesSet].map((reference) => ({
value: reference,
label: CONFIG.l5r5e.sourceReference[reference]?.label ?? reference,
translate: true,
group: CONFIG.l5r5e.sourceReference[reference]?.type.split(",")[0] ?? "l5r5e.multiselect.sources_categories.others",
disabled: !sourcesInThisCompendium.has(reference) || (!game.user.isGM && unavailableSourceForPlayersSet.has(reference))
}));
const filterSourcesBox = L5r5eHtmlMultiSelectElement.create({
name: "filter-sources",
options: selectableSourcesArray,
localize: true,
});
header.append(filterSourcesBox.outerHTML);
$("l5r5e-multi-select").on("change", applyCompendiumFilter);
// If gm add an extra button to easily filter the content to see the same stuff as a player
if (game.user.isGM && unavailableSourceForPlayersSet.size > 0) {
const buttonHTML = `<button type="button" class="gm" data-tooltip="${game.i18n.localize('l5r5e.multiselect.player_filter_tooltip')}">`
+ game.i18n.localize('l5r5e.multiselect.player_filter_label')
+ '</button>'
const filterPlayerViewArray = [...allCompendiumReferencesSet]
.filter((item) => !unavailableSourceForPlayersSet.has(item))
.filter((item) => sourcesInThisCompendium.has(item));
$(buttonHTML).appendTo($(header).find("l5r5e-multi-select")).click(function() {
header.find("l5r5e-multi-select")[0].value = filterPlayerViewArray;
});
}
}
// TODO: This delay is a workaround and should be addressed in another way.
// This is ugly but if we hide the content too early then it won't be hidden for some reason.
// Current guess is that the foundry search filter is doing something.
// Adding a delay here so that we hide the content. This will fail on slow computers/network...
setTimeout(() => {
applyCompendiumFilter();
}, 250);
return false;
}
}
static updateCompendium(pack, documents, options, userId) {
documents.forEach((document) => {
const inc_reference = document?.system?.source_reference?.source?.trim();
if (!!inc_reference) {
const references = game.settings.get(CONFIG.l5r5e.namespace, "all-compendium-references");
if (!references.includes(inc_reference)) {
references.push(inc_reference);
game.settings.set(CONFIG.l5r5e.namespace, "all-compendium-references", references);
}
}
});
}
/**
* DiceSoNice - Add L5R DicePresets
*/