Skip to content

Commit fa2ad28

Browse files
committed
Refactor Compendium Browser to use a Predicate for filtering entries
1 parent 23eb7af commit fa2ad28

File tree

18 files changed

+507
-628
lines changed

18 files changed

+507
-628
lines changed

src/module/actor/character/sheet.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1291,7 +1291,6 @@ class CharacterSheetPF2e<TActor extends CharacterPF2e> extends CreatureSheetPF2e
12911291
const category = filter.checkboxes.category;
12921292
for (const value of featFilters.categories ?? []) {
12931293
category.isExpanded = true;
1294-
category.options[value].selected = true;
12951294
category.selected.push(value);
12961295
}
12971296

src/module/actor/party/kingdom/sheet.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -454,7 +454,6 @@ class KingdomSheetPF2e extends ActorSheetPF2e<PartyPF2e> {
454454
levels.isExpanded = levels.to !== levels.max;
455455

456456
// Set category
457-
filter.checkboxes.category.options["kingdom-feat"].selected = true;
458457
filter.checkboxes.category.selected.push("kingdom-feat");
459458
filter.checkboxes.category.isExpanded = true;
460459

src/module/actor/sheet/base.ts

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -950,8 +950,7 @@ abstract class ActorSheetPF2e<TActor extends ActorPF2e> extends fav1.sheets.Acto
950950

951951
for (const itemType of checkboxesFilterCodes) {
952952
const checkbox = checkboxes.itemTypes;
953-
if (objectHasKey(checkbox.options, itemType)) {
954-
checkbox.options[itemType].selected = true;
953+
if (checkbox.options.some((o) => o.value === itemType)) {
955954
checkbox.selected.push(itemType);
956955
checkbox.isExpanded = true;
957956
}

src/module/apps/compendium-browser/browser.ts

Lines changed: 5 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -198,7 +198,6 @@ class CompendiumBrowser extends SvelteApplicationMixin(fa.api.ApplicationV2) {
198198
types.selected = [];
199199
for (const type in types.options) {
200200
if (options.types?.includes(type as ActionType)) {
201-
types.options[type].selected = true;
202201
types.selected.push(type);
203202
}
204203
}
@@ -209,9 +208,10 @@ class CompendiumBrowser extends SvelteApplicationMixin(fa.api.ApplicationV2) {
209208
: [];
210209

211210
if (options.categories?.length) {
212-
const optionsToSwitch = R.pick(filter.checkboxes.category.options, options.categories);
213-
Object.values(optionsToSwitch).forEach((o) => (o.selected = true));
214-
filter.checkboxes.category.selected = Object.keys(optionsToSwitch);
211+
const categoryFilters = R.filter(options.categories, R.isTruthy).map((value) => ({ value }));
212+
filter.checkboxes.category.selected = filter.checkboxes.category.options
213+
.filter((c) => categoryFilters.some((f) => f.value === c.value))
214+
.map((c) => c.value);
215215
}
216216

217217
actionTab.open({ filter });
@@ -222,30 +222,25 @@ class CompendiumBrowser extends SvelteApplicationMixin(fa.api.ApplicationV2) {
222222
const filter = await spellTab.getFilterData();
223223
const traditions = filter.checkboxes.traditions;
224224

225-
if (category && filter.checkboxes.category.options[category]) {
226-
filter.checkboxes.category.options[category].selected = true;
225+
if (category && filter.checkboxes.category.options.some((o) => o.value === category)) {
227226
filter.checkboxes.category.selected.push(category);
228227
}
229228

230229
if (entry.category === "ritual" || entry.isFocusPool) {
231-
filter.checkboxes.category.options[entry.category].selected = true;
232230
filter.checkboxes.category.selected.push(entry.category);
233231
}
234232

235233
if (maxRank) {
236234
const ranks = Array.from(Array(maxRank).keys()).map((l) => String(l + 1));
237235
for (const rank of ranks) {
238-
filter.checkboxes.rank.options[rank].selected = true;
239236
filter.checkboxes.rank.selected.push(rank);
240237
}
241238
if (["prepared", "spontaneous", "innate"].includes(entry.category) && !category) {
242-
filter.checkboxes.category.options["spell"].selected = true;
243239
filter.checkboxes.category.selected.push("spell");
244240
}
245241
}
246242

247243
if (entry.tradition && !entry.isFocusPool && entry.category !== "ritual") {
248-
traditions.options[entry.tradition].selected = true;
249244
traditions.selected.push(entry.tradition);
250245
}
251246

src/module/apps/compendium-browser/components/filters.svelte

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -32,9 +32,6 @@
3232
): () => void {
3333
return () => {
3434
if ("selected" in data) {
35-
for (const opt of data.selected) {
36-
data.options[opt].selected = false;
37-
}
3835
data.selected = [];
3936
} else if ("from" in data) {
4037
data.from = data.min;
@@ -91,8 +88,8 @@
9188
<div class="select-container">
9289
<select bind:value={filter.selects[key].selected} data-key={key}>
9390
<option value="">-</option>
94-
{#each R.entries(data.options) as [key, label]}
95-
<option value={key}>{game.i18n.localize(label)}</option>
91+
{#each data.options as option}
92+
<option value={option.value}>{game.i18n.localize(option.label)}</option>
9693
{/each}
9794
</select>
9895
</div>

src/module/apps/compendium-browser/components/filters/checkboxes.svelte

Lines changed: 8 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,17 @@
11
<script lang="ts">
2-
import * as R from "remeda";
32
import { slide } from "svelte/transition";
4-
import type { CheckboxData, CheckboxOption } from "../../tabs/data.ts";
3+
import type { CheckboxData } from "../../tabs/data.ts";
54
65
const { checkbox = $bindable(), searchable }: { checkbox: CheckboxData; searchable?: boolean } = $props();
76
let searchTerm = $state("");
87
9-
function onChangeCheckbox(
10-
event: Event & { currentTarget: HTMLInputElement },
11-
data: { name: string; option: CheckboxOption },
12-
): void {
8+
function onChangeCheckbox(event: Event & { currentTarget: HTMLInputElement }, value: string): void {
139
const checked = event.currentTarget.checked;
1410
if (checked) {
15-
checkbox.selected.push(data.name);
11+
checkbox.selected.push(value);
1612
} else {
17-
checkbox.selected = checkbox.selected.filter((name) => name !== data.name);
13+
checkbox.selected = checkbox.selected.filter((v) => v !== value);
1814
}
19-
data.option.selected = checked;
2015
}
2116
2217
const onSearchSource = fu.debounce((event: Event) => {
@@ -35,16 +30,15 @@
3530
oninput={onSearchSource}
3631
/>
3732
{/if}
38-
{#each R.entries(checkbox.options) as [name, option]}
39-
{#if !searchable || !searchTerm || option.selected || option.label
33+
{#each checkbox.options as option}
34+
{#if !searchable || !searchTerm || checkbox.selected.includes(option.value) || option.label
4035
.toLocaleLowerCase(game.i18n.lang)
4136
.includes(searchTerm)}
4237
<label>
4338
<input
4439
type="checkbox"
45-
{name}
46-
checked={option.selected}
47-
onchange={(event) => onChangeCheckbox(event, { name, option })}
40+
checked={checkbox.selected.includes(option.value)}
41+
onchange={(event) => onChangeCheckbox(event, option.value)}
4842
/>
4943
{game.i18n.localize(option.label)}
5044
</label>

src/module/apps/compendium-browser/components/filters/level.svelte

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -12,14 +12,10 @@
1212
const name = event.currentTarget.name;
1313
const value = Math.clamp(Number(event.currentTarget.value), level.min, level.max);
1414
if (name === "from") {
15-
if (value > level.to) {
16-
level.to = value;
17-
}
15+
if (value > level.to) level.to = value;
1816
level.from = value;
1917
} else if (name === "to") {
20-
if (value < level.from) {
21-
level.from = value;
22-
}
18+
if (value < level.from) level.from = value;
2319
level.to = value;
2420
}
2521
level.changed = level.from !== level.min || level.to !== level.max;

src/module/apps/compendium-browser/components/filters/traits.svelte

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
traits: TraitData;
1212
}
1313
const { traits = $bindable() }: Props = $props();
14-
const exclude = $state(new SvelteSet<string>());
14+
const exclude = new SvelteSet<string>();
1515
1616
function onChangeConjunction(event: Event & { currentTarget: HTMLInputElement }): void {
1717
const value = event.currentTarget.value;
@@ -54,7 +54,7 @@
5454
selection={traitSelection}
5555
onChange={onChangeTraits}
5656
placeholder={game.i18n.localize("PF2E.SelectLabel")}
57-
value={traits.selected.map((s) => s.value)}
57+
value={traits.selected.map((t) => t.value)}
5858
/>
5959
<div class="filter-conjunction">
6060
<label class="checkbox">
@@ -102,6 +102,7 @@
102102
aria-label="deslect"
103103
data-action="deselect"
104104
use:itemAction={opt}
105+
onclick={() => exclude.delete(opt.value)}
105106
>
106107
<svg height="16" width="16" viewBox="0 0 20 20" aria-hidden="true" focusable="false">
107108
<path

src/module/apps/compendium-browser/tabs/action.ts

Lines changed: 39 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ export class CompendiumBrowserActionTab extends CompendiumBrowserTab {
1212

1313
/* MiniSearch */
1414
override searchFields = ["name", "originalName"];
15-
override storeFields = ["type", "name", "img", "uuid", "traits", "source", "category", "actionType"];
15+
override storeFields = ["name", "originalName", "img", "uuid", "domains"];
1616

1717
constructor(browser: CompendiumBrowser) {
1818
super(browser);
@@ -43,34 +43,41 @@ export class CompendiumBrowserActionTab extends CompendiumBrowserTab {
4343
)) {
4444
console.debug(`PF2e System | Compendium Browser | ${pack.metadata.label} - Loading`);
4545
for (const actionData of index) {
46-
if (actionData.type === "action") {
47-
if (!this.hasAllIndexFields(actionData, indexFields)) {
48-
console.warn(
49-
`Action '${actionData.name}' does not have all required data fields. Consider unselecting pack '${pack.metadata.label}' in the compendium browser settings.`,
50-
);
51-
continue;
52-
}
53-
// update icons for any passive actions
54-
if (actionData.system.actionType.value === "passive") actionData.img = getActionIcon("passive");
46+
if (actionData.type !== "action") continue;
47+
if (!this.hasAllIndexFields(actionData, indexFields)) {
48+
console.warn(
49+
`Action '${actionData.name}' does not have all required data fields. Consider unselecting pack '${pack.metadata.label}' in the compendium browser settings.`,
50+
);
51+
continue;
52+
}
53+
const domains = new Set<string>();
54+
const system = actionData.system;
55+
// update icons for any passive actions
56+
if (system.actionType.value === "passive") actionData.img = getActionIcon("passive");
57+
domains.add(`action-type:${system.actionType.value}`);
5558

56-
// Prepare publication source
57-
const { system } = actionData;
58-
const pubSource = String(system.publication?.title ?? system.source?.value ?? "").trim();
59-
const sourceSlug = sluggify(pubSource);
60-
if (pubSource) publications.add(pubSource);
59+
for (const trait of system.traits.value) {
60+
domains.add(`trait:${trait.replace(/^hb_/, "")}`);
61+
}
6162

62-
actions.push({
63-
type: actionData.type,
64-
name: actionData.name,
65-
originalName: actionData.originalName, // Added by Babele
66-
img: actionData.img,
67-
uuid: actionData.uuid,
68-
traits: actionData.system.traits.value.map((t: string) => t.replace(/^hb_/, "")),
69-
actionType: actionData.system.actionType.value,
70-
category: actionData.system.category,
71-
source: sourceSlug,
72-
});
63+
// Prepare publication source
64+
const pubSource = String(system.publication?.title ?? system.source?.value ?? "").trim();
65+
const sourceSlug = sluggify(pubSource);
66+
if (pubSource) {
67+
publications.add(pubSource);
68+
domains.add(`source:${sourceSlug}`);
7369
}
70+
71+
domains.add(`type:${actionData.type}`);
72+
domains.add(`category:${system.category}`);
73+
74+
actions.push({
75+
name: actionData.name,
76+
originalName: actionData.originalName, // Added by Babele
77+
img: actionData.img,
78+
uuid: actionData.uuid,
79+
domains,
80+
});
7481
}
7582
}
7683

@@ -79,56 +86,36 @@ export class CompendiumBrowserActionTab extends CompendiumBrowserTab {
7986

8087
// Set Filters
8188
this.filterData.traits.options = this.generateMultiselectOptions(CONFIG.PF2E.actionTraits);
82-
this.filterData.checkboxes.types.options = this.generateCheckboxOptions(CONFIG.PF2E.actionTypes);
83-
this.filterData.checkboxes.category.options = this.generateCheckboxOptions(
89+
this.filterData.checkboxes.types.options = this.generateOptions(CONFIG.PF2E.actionTypes);
90+
this.filterData.checkboxes.category.options = this.generateOptions(
8491
R.pick(CONFIG.PF2E.actionCategories, ["familiar"]),
8592
);
8693
this.filterData.source.options = this.generateSourceCheckboxOptions(publications);
8794

8895
console.debug("PF2e System | Compendium Browser | Finished loading actions");
8996
}
9097

91-
protected override filterIndexData(entry: CompendiumBrowserIndexData): boolean {
92-
const { checkboxes, source, traits } = this.filterData;
93-
94-
// Types
95-
if (checkboxes.types.selected.length) {
96-
if (!checkboxes.types.selected.includes(entry.actionType)) return false;
97-
}
98-
// Categories
99-
if (checkboxes.category.selected.length) {
100-
const selected = checkboxes.category.selected;
101-
if (!selected.includes(entry.category)) return false;
102-
}
103-
// Traits
104-
if (!this.filterTraits(entry.traits, traits.selected, traits.conjunction)) return false;
105-
// Source
106-
if (source.selected.length) {
107-
if (!source.selected.includes(entry.source)) return false;
108-
}
109-
return true;
110-
}
111-
11298
protected override prepareFilterData(): ActionFilters {
11399
return {
114100
checkboxes: {
115101
types: {
116102
isExpanded: true,
117103
label: "PF2E.ActionActionTypeLabel",
118-
options: {},
104+
options: [],
105+
optionPrefix: "action-type",
119106
selected: [],
120107
},
121108
category: {
122109
isExpanded: true,
123110
label: "PF2E.CompendiumBrowser.Filter.Categories",
124-
options: {},
111+
options: [],
125112
selected: [],
126113
},
127114
},
128115
source: {
129116
isExpanded: false,
130117
label: "PF2E.CompendiumBrowser.Filter.Source",
131-
options: {},
118+
options: [],
132119
selected: [],
133120
},
134121
traits: {

0 commit comments

Comments
 (0)