diff --git a/lang/en.json b/lang/en.json index 86b4323c..c1a3582a 100755 --- a/lang/en.json +++ b/lang/en.json @@ -343,6 +343,9 @@ "requestSpotlight": "Request The Spotlight", "openCountdowns": "Countdowns" }, + "CompendiumBrowserSettings": { + "title": "Compendium Browser Settings" + }, "ContextMenu": { "disableEffect": "Disable Effect", "enableEffect": "Enable Effect", @@ -2787,6 +2790,7 @@ "ItemBrowser": { "title": "Daggerheart Compendium Browser", "hint": "Select a Folder in sidebar to start browsing through the compendium", + "browserSettings": "Browser Settings", "searchPlaceholder": "Search...", "columnName": "Name", "tooltipFilters": "Filters", @@ -2943,7 +2947,7 @@ "rulesOn": "Rules On", "rulesOff": "Rules Off", "remainingUses": "Uses refresh on {type}", - "rightClickExtand": "Right-Click to extand", + "rightClickExtend": "Right-Click to extend", "companionPartnerLevelBlock": "The companion needs an assigned partner to level up.", "configureAttribution": "Configure Attribution", "deleteItem": "Delete Item", diff --git a/module/applications/dialogs/CompendiumBrowserSettings.mjs b/module/applications/dialogs/CompendiumBrowserSettings.mjs new file mode 100644 index 00000000..f1b266a1 --- /dev/null +++ b/module/applications/dialogs/CompendiumBrowserSettings.mjs @@ -0,0 +1,135 @@ +const { ApplicationV2, HandlebarsApplicationMixin } = foundry.applications.api; + +export default class CompendiumBrowserSettings extends HandlebarsApplicationMixin(ApplicationV2) { + constructor() { + super(); + + this.browserSettings = game.settings + .get(CONFIG.DH.id, CONFIG.DH.SETTINGS.gameSettings.CompendiumBrowserSettings) + .toObject(); + } + + static DEFAULT_OPTIONS = { + tag: 'form', + classes: ['daggerheart', 'dialog', 'dh-style', 'views', 'compendium-brower-settings'], + window: { + icon: 'fa-solid fa-book', + title: 'DAGGERHEART.APPLICATIONS.CompendiumBrowserSettings.title' + }, + position: { + width: 500, + height: 'auto' + }, + actions: { + finish: CompendiumBrowserSettings.#finish + }, + form: { + handler: this.updateData, + submitOnChange: true, + submitOnClose: false + } + }; + + /** @override */ + static PARTS = { + main: { + id: 'main', + template: 'systems/daggerheart/templates/dialogs/compendiumBrowserSettingsDialog.hbs' + } + }; + + static #browserPackTypes = ['Actor', 'Item']; + + _attachPartListeners(partId, htmlElement, options) { + super._attachPartListeners(partId, htmlElement, options); + + for (const element of htmlElement.querySelectorAll('.source-input')) { + element.addEventListener('change', this.toggleSource.bind(this)); + } + } + + getPackageName = pack => (pack.metadata.packageType === 'world' ? 'world' : pack.metadata.packageName); + + async _prepareContext(_options) { + const context = await super._prepareContext(_options); + + const { excludedCompendiumPacks } = this.browserSettings; + context.packOptions = game.packs.reduce((acc, pack) => { + const { type, name, label, packageType, id } = pack.metadata; + if (!CompendiumBrowserSettings.#browserPackTypes.includes(type)) return acc; + + const packageName = this.getPackageName(pack); + if (!acc[packageName]) + acc[packageName] = { + label: + packageType === 'world' + ? game.i18n.localize('PACKAGE.Type.world') + : (game.modules.get(packageName)?.title ?? game.system.title), + types: {} + }; + if (!acc[packageName].types[type]) + acc[packageName].types[type] = { + label: game.i18n.localize(`DOCUMENT.${type}`), + checked: true, + packs: {} + }; + + if (id === 'daggerheart.ancestries') { + console.log('test'); + } + acc[packageName].types[type].packs[id] = { + label: label, + checked: !excludedCompendiumPacks[packageName]?.[id] + }; + acc[packageName].types[type].checked &&= acc[packageName].types[type].packs[id].checked; + + return acc; + }, {}); + + return context; + } + + static async updateData(_event, _, formData) { + const { excludedCompendiumPacks } = foundry.utils.expandObject(formData.object); + this.browserSettings.excludedCompendiumPacks = Object.keys(excludedCompendiumPacks).reduce( + (acc, packageKey) => { + const flattenedPack = foundry.utils.flattenObject(excludedCompendiumPacks[packageKey]); + acc[packageKey] = Object.keys(flattenedPack).reduce((acc, key) => { + acc[key] = !flattenedPack[key]; + return acc; + }, {}); + return acc; + }, + {} + ); + this.render(); + } + + toggleSource(event) { + event.stopPropagation(); + + const { excludedCompendiumPacks } = this.browserSettings; + const { source, type } = event.target.dataset; + + const allIncluded = !event.target.checked; + const packs = game.packs.filter(pack => this.getPackageName(pack) === source && pack.metadata.type === type); + for (const pack of packs) { + if (!excludedCompendiumPacks[source]) excludedCompendiumPacks[source] = {}; + + excludedCompendiumPacks[source][pack.metadata.id] = allIncluded; + } + + this.render(); + } + + static async #finish() { + const settings = game.settings.get(CONFIG.DH.id, CONFIG.DH.SETTINGS.gameSettings.CompendiumBrowserSettings); + await settings.updateSource(this.browserSettings); + await game.settings.set( + CONFIG.DH.id, + CONFIG.DH.SETTINGS.gameSettings.CompendiumBrowserSettings, + settings.toObject() + ); + this.close(); + } +} diff --git a/module/applications/dialogs/_module.mjs b/module/applications/dialogs/_module.mjs index 4eda8579..a479100a 100644 --- a/module/applications/dialogs/_module.mjs +++ b/module/applications/dialogs/_module.mjs @@ -16,3 +16,4 @@ export { default as ActionSelectionDialog } from './actionSelectionDialog.mjs'; export { default as GroupRollDialog } from './group-roll-dialog.mjs'; export { default as TagTeamDialog } from './tagTeamDialog.mjs'; export { default as RiskItAllDialog } from './riskItAllDialog.mjs'; +export { default as CompendiumBrowserSettingsDialog } from './CompendiumBrowserSettings.mjs'; diff --git a/module/applications/ui/itemBrowser.mjs b/module/applications/ui/itemBrowser.mjs index b35573f7..2f0520ac 100644 --- a/module/applications/ui/itemBrowser.mjs +++ b/module/applications/ui/itemBrowser.mjs @@ -35,7 +35,8 @@ export class ItemBrowser extends HandlebarsApplicationMixin(ApplicationV2) { selectFolder: this.selectFolder, expandContent: this.expandContent, resetFilters: this.resetFilters, - sortList: this.sortList + sortList: this.sortList, + openSettings: this.openSettings }, position: { left: 100, @@ -214,6 +215,10 @@ export class ItemBrowser extends HandlebarsApplicationMixin(ApplicationV2) { loadItems() { let loadTimeout = this.toggleLoader(true); + const excludedCompendiumPacks = game.settings.get( + CONFIG.DH.id, + CONFIG.DH.SETTINGS.gameSettings.CompendiumBrowserSettings + ).excludedCompendiumPacks; const promises = []; game.packs.forEach(pack => { @@ -227,7 +232,13 @@ export class ItemBrowser extends HandlebarsApplicationMixin(ApplicationV2) { Promise.all(promises).then(async result => { this.items = ItemBrowser.sortBy( - result.flatMap(r => r), + result + .flatMap(r => r) + .filter(x => { + const pack = game.packs.get(x.pack); + const packageName = pack.metadata.packageType === 'world' ? 'world' : pack.metadata.packageName; + return !excludedCompendiumPacks[packageName]?.[x.pack]; + }), 'name' ); @@ -512,6 +523,10 @@ export class ItemBrowser extends HandlebarsApplicationMixin(ApplicationV2) { itemListContainer.replaceChildren(...newOrder); } + static async openSettings() { + new game.system.api.applications.dialogs.CompendiumBrowserSettingsDialog().render({ force: true }); + } + _createDragProcess() { new foundry.applications.ux.DragDrop.implementation({ dragSelector: '.item-container', diff --git a/module/config/settingsConfig.mjs b/module/config/settingsConfig.mjs index 3d993949..d3f752bb 100644 --- a/module/config/settingsConfig.mjs +++ b/module/config/settingsConfig.mjs @@ -30,6 +30,7 @@ export const gameSettings = { LastMigrationVersion: 'LastMigrationVersion', TagTeamRoll: 'TagTeamRoll', SpotlightRequestQueue: 'SpotlightRequestQueue', + CompendiumBrowserSettings: 'CompendiumBrowserSettings' }; export const actionAutomationChoices = { diff --git a/module/data/_module.mjs b/module/data/_module.mjs index f7e25a4e..52fa689e 100644 --- a/module/data/_module.mjs +++ b/module/data/_module.mjs @@ -3,6 +3,7 @@ export { default as DhCombatant } from './combatant.mjs'; export { default as DhTagTeamRoll } from './tagTeamRoll.mjs'; export { default as DhRollTable } from './rollTable.mjs'; export { default as RegisteredTriggers } from './registeredTriggers.mjs'; +export { default as CompendiumBrowserSettings } from './compendiumBrowserSettings.mjs'; export * as countdowns from './countdowns.mjs'; export * as actions from './action/_module.mjs'; diff --git a/module/data/compendiumBrowserSettings.mjs b/module/data/compendiumBrowserSettings.mjs new file mode 100644 index 00000000..dc98d833 --- /dev/null +++ b/module/data/compendiumBrowserSettings.mjs @@ -0,0 +1,16 @@ +export default class CompendiumBrowserSettings extends foundry.abstract.DataModel { + static defineSchema() { + const fields = foundry.data.fields; + + return { + excludedCompendiumPacks: new fields.TypedObjectField( + new fields.TypedObjectField(new fields.BooleanField({ required: true, initial: true })) + ) + // excludedSources: new fields.ArrayField(new fields.StringField({ required: true, nullable: false })), + // excludedPacks: new fields.TypedObjectField(new fields.SchemaField({ + // attributionKeys: new fields.ArrayField(new fields.StringField({ required: true, nullable: false })), + // excluded: new fields.BooleanField({ required: true, initial: false }), + // })), + }; + } +} diff --git a/module/systemRegistration/settings.mjs b/module/systemRegistration/settings.mjs index 053325a8..49361877 100644 --- a/module/systemRegistration/settings.mjs +++ b/module/systemRegistration/settings.mjs @@ -7,7 +7,7 @@ import { DhHomebrewSettings, DhVariantRuleSettings } from '../applications/settings/_module.mjs'; -import { DhTagTeamRoll } from '../data/_module.mjs'; +import { CompendiumBrowserSettings, DhTagTeamRoll } from '../data/_module.mjs'; export const registerDHSettings = () => { registerMenuSettings(); @@ -142,6 +142,12 @@ const registerNonConfigSettings = () => { config: false, type: DhTagTeamRoll }); + + game.settings.register(CONFIG.DH.id, CONFIG.DH.SETTINGS.gameSettings.CompendiumBrowserSettings, { + scope: 'client', + config: false, + type: CompendiumBrowserSettings + }); }; /** diff --git a/styles/less/dialog/compendiumBrowserPackDialog/sheet.less b/styles/less/dialog/compendiumBrowserPackDialog/sheet.less new file mode 100644 index 00000000..0296b6ad --- /dev/null +++ b/styles/less/dialog/compendiumBrowserPackDialog/sheet.less @@ -0,0 +1,95 @@ +.daggerheart.dialog.dh-style.views.compendium-brower-settings { + --text-color: beige; + + .compendium-settings-label { + text-align: center; + display: flex; + flex-direction: column; + color: light-dark(@dark-blue, @golden); + font-size: var(--font-size-24); + font-family: @font-subtitle; + font-weight: bold; + } + + .pack-options-container { + display: flex; + flex-direction: column; + gap: 8px; + + .pack-option-container { + display: flex; + flex-direction: column; + gap: 8px; + + > label { + display: flex; + align-items: center; + font-size: var(--font-size-16); + font-family: @font-subtitle; + font-weight: bold; + + &::before { + content: ''; + flex: 1; + height: 2px; + background: linear-gradient(90deg, rgba(0, 0, 0, 0) 0%, @golden 100%); + margin-right: 8px; + } + &::after { + content: ''; + flex: 1; + height: 2px; + background: linear-gradient(90deg, @golden 0%, rgba(0, 0, 0, 0) 100%); + margin-left: 8px; + } + } + + .sources-container { + display: flex; + flex-direction: column; + gap: 8px; + color: var(--text-color); + + .source-container { + padding: 5px; + background: light-dark(@dark-blue-10, @golden-10); + display: flex; + flex-direction: column; + gap: 2px; + + .source-inner-container { + display: flex; + justify-content: space-between; + + .source-inner-label-container { + display: flex; + align-items: center; + gap: 4px; + } + } + + .packs-container { + display: grid; + grid-template-columns: 1fr 1fr; + gap: 4px; + padding-left: 24px; + + .pack-container { + display: flex; + align-items: center; + } + } + } + } + } + } + + footer { + margin-top: 8px; + display: flex; + + button { + flex: 1; + } + } +} diff --git a/styles/less/dialog/index.less b/styles/less/dialog/index.less index 733cdd1c..0c70df9f 100644 --- a/styles/less/dialog/index.less +++ b/styles/less/dialog/index.less @@ -43,3 +43,5 @@ @import './risk-it-all/sheet.less'; @import './character-reset/sheet.less'; + +@import './compendiumBrowserPackDialog/sheet.less'; diff --git a/styles/less/global/elements.less b/styles/less/global/elements.less index 713a4481..98c05348 100755 --- a/styles/less/global/elements.less +++ b/styles/less/global/elements.less @@ -52,6 +52,14 @@ } } + input[type='checkbox'] { + &:indeterminate { + &::before { + content: '\f0fe'; + } + } + } + input[type='checkbox'], input[type='radio'] { height: 20px; diff --git a/templates/dialogs/compendiumBrowserSettingsDialog.hbs b/templates/dialogs/compendiumBrowserSettingsDialog.hbs new file mode 100644 index 00000000..9fe27715 --- /dev/null +++ b/templates/dialogs/compendiumBrowserSettingsDialog.hbs @@ -0,0 +1,35 @@ +