diff --git a/lang/en.json b/lang/en.json index c1a3582a..a5621bef 100755 --- a/lang/en.json +++ b/lang/en.json @@ -2123,7 +2123,9 @@ "configuration": "Configuration", "base": "Base", "triggers": "Triggers", - "deathMoves": "Deathmoves" + "deathMoves": "Deathmoves", + "sources": "Sources", + "packs": "Packs" }, "Tiers": { "singular": "Tier", diff --git a/module/applications/dialogs/CompendiumBrowserSettings.mjs b/module/applications/dialogs/CompendiumBrowserSettings.mjs index f1b266a1..ad89a688 100644 --- a/module/applications/dialogs/CompendiumBrowserSettings.mjs +++ b/module/applications/dialogs/CompendiumBrowserSettings.mjs @@ -10,7 +10,7 @@ export default class CompendiumBrowserSettings extends HandlebarsApplicationMixi } static DEFAULT_OPTIONS = { - tag: 'form', + tag: 'div', classes: ['daggerheart', 'dialog', 'dh-style', 'views', 'compendium-brower-settings'], window: { icon: 'fa-solid fa-book', @@ -21,21 +21,18 @@ export default class CompendiumBrowserSettings extends HandlebarsApplicationMixi height: 'auto' }, actions: { + toggleSource: CompendiumBrowserSettings.#toggleSource, finish: CompendiumBrowserSettings.#finish - }, - form: { - handler: this.updateData, - submitOnChange: true, - submitOnClose: false } }; /** @override */ static PARTS = { - main: { - id: 'main', - template: 'systems/daggerheart/templates/dialogs/compendiumBrowserSettingsDialog.hbs' - } + packs: { + id: 'packs', + template: 'systems/daggerheart/templates/dialogs/compendiumBrowserSettingsDialog/packs.hbs' + }, + footer: { template: 'systems/daggerheart/templates/dialogs/compendiumBrowserSettingsDialog/footer.hbs' } }; static #browserPackTypes = ['Actor', 'Item']; @@ -43,45 +40,36 @@ export default class CompendiumBrowserSettings extends HandlebarsApplicationMixi _attachPartListeners(partId, htmlElement, options) { super._attachPartListeners(partId, htmlElement, options); - for (const element of htmlElement.querySelectorAll('.source-input')) { - element.addEventListener('change', this.toggleSource.bind(this)); - } + for (const element of htmlElement.querySelectorAll('.pack-checkbox')) + element.addEventListener('change', this.toggleTypedPack.bind(this)); } - getPackageName = pack => (pack.metadata.packageType === 'world' ? 'world' : pack.metadata.packageName); - + /**@inheritdoc */ 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 excludedSourceData = this.browserSettings.excludedSources; + const excludedPackData = this.browserSettings.excludedPacks; + context.typePackCollections = game.packs.reduce((acc, pack) => { + const { type, label, packageType, packageName, id } = pack.metadata; + if (packageType === 'world' || !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: {} - }; + const sourceChecked = + !excludedSourceData[packageName] || + !excludedSourceData[packageName].excludedDocumentTypes.includes(type); + const sourceLabel = game.modules.get(packageName)?.title ?? game.system.title; + if (!acc[type]) acc[type] = { label: game.i18n.localize(`DOCUMENT.${type}s`), sources: {} }; + if (!acc[type].sources[packageName]) + acc[type].sources[packageName] = { label: sourceLabel, checked: sourceChecked, 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; + const checked = !excludedPackData[id] || !excludedPackData[id].excludedDocumentTypes.includes(type); + + acc[type].sources[packageName].packs.push({ + pack: id, + type, + label: id === game.system.id ? game.system.title : game.i18n.localize(label), + checked: checked + }); return acc; }, {}); @@ -89,35 +77,40 @@ export default class CompendiumBrowserSettings extends HandlebarsApplicationMixi 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) { + static #toggleSource(event, button) { event.stopPropagation(); - const { excludedCompendiumPacks } = this.browserSettings; - const { source, type } = event.target.dataset; + const target = button.closest('.source-enable-container'); + const { type, source } = target.dataset; + const currentlyExcluded = this.browserSettings.excludedSources[source] + ? this.browserSettings.excludedSources[source].excludedDocumentTypes.includes(type) + : false; - 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] = {}; + if (!this.browserSettings.excludedSources[source]) + this.browserSettings.excludedSources[source] = { excludedDocumentTypes: [] }; + this.browserSettings.excludedSources[source].excludedDocumentTypes = currentlyExcluded + ? this.browserSettings.excludedSources[source].excludedDocumentTypes.filter(x => x !== type) + : [...(this.browserSettings.excludedSources[source]?.excludedDocumentTypes ?? []), type]; - excludedCompendiumPacks[source][pack.metadata.id] = allIncluded; - } + target.classList.toggle('locked'); + target.closest('.source-container').querySelector('.checks-container').classList.toggle('collapsed'); + + // this.render(); + } + + toggleTypedPack(event) { + event.stopPropagation(); + + const { type, pack } = event.target.dataset; + const currentlyExcluded = this.browserSettings.excludedPacks[pack] + ? this.browserSettings.excludedPacks[pack].excludedDocumentTypes.includes(type) + : false; + + if (!this.browserSettings.excludedPacks[pack]) + this.browserSettings.excludedPacks[pack] = { excludedDocumentTypes: [] }; + this.browserSettings.excludedPacks[pack].excludedDocumentTypes = currentlyExcluded + ? this.browserSettings.excludedPacks[pack].excludedDocumentTypes.filter(x => x !== type) + : [...(this.browserSettings.excludedPacks[pack]?.excludedDocumentTypes ?? []), type]; this.render(); } diff --git a/module/applications/ui/itemBrowser.mjs b/module/applications/ui/itemBrowser.mjs index 2f0520ac..6869271a 100644 --- a/module/applications/ui/itemBrowser.mjs +++ b/module/applications/ui/itemBrowser.mjs @@ -215,10 +215,10 @@ export class ItemBrowser extends HandlebarsApplicationMixin(ApplicationV2) { loadItems() { let loadTimeout = this.toggleLoader(true); - const excludedCompendiumPacks = game.settings.get( + const browserSettings = game.settings.get( CONFIG.DH.id, CONFIG.DH.SETTINGS.gameSettings.CompendiumBrowserSettings - ).excludedCompendiumPacks; + ); const promises = []; game.packs.forEach(pack => { @@ -232,13 +232,7 @@ export class ItemBrowser extends HandlebarsApplicationMixin(ApplicationV2) { Promise.all(promises).then(async result => { this.items = ItemBrowser.sortBy( - 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]; - }), + result.flatMap(r => r).filter(r => !browserSettings.isEntryExcluded.bind(browserSettings)(r)), 'name' ); diff --git a/module/data/compendiumBrowserSettings.mjs b/module/data/compendiumBrowserSettings.mjs index dc98d833..9e8025dd 100644 --- a/module/data/compendiumBrowserSettings.mjs +++ b/module/data/compendiumBrowserSettings.mjs @@ -3,14 +3,33 @@ export default class CompendiumBrowserSettings extends foundry.abstract.DataMode const fields = foundry.data.fields; return { - excludedCompendiumPacks: new fields.TypedObjectField( - new fields.TypedObjectField(new fields.BooleanField({ required: true, initial: true })) + excludedSources: new fields.TypedObjectField( + new fields.SchemaField({ + excludedDocumentTypes: new fields.ArrayField( + new fields.StringField({ required: true, choices: CONST.SYSTEM_SPECIFIC_COMPENDIUM_TYPES }) + ) + }) + ), + excludedPacks: new fields.TypedObjectField( + new fields.SchemaField({ + excludedDocumentTypes: new fields.ArrayField( + new fields.StringField({ required: true, choices: CONST.SYSTEM_SPECIFIC_COMPENDIUM_TYPES }) + ) + }) ) - // 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 }), - // })), }; } + + isEntryExcluded(item) { + const pack = game.packs.get(item.pack); + if (!pack) return false; + + const excludedSourceData = this.excludedSources[pack.metadata.packageName]; + if (excludedSourceData && excludedSourceData.excludedDocumentTypes.includes(pack.metadata.type)) return true; + + const excludedPackData = this.excludedPacks[item.pack]; + if (excludedPackData && excludedPackData.excludedDocumentTypes.includes(pack.metadata.type)) return true; + + return false; + } } diff --git a/styles/less/dialog/compendiumBrowserPackDialog/sheet.less b/styles/less/dialog/compendiumBrowserPackDialog/sheet.less index 0296b6ad..cc10b0c0 100644 --- a/styles/less/dialog/compendiumBrowserPackDialog/sheet.less +++ b/styles/less/dialog/compendiumBrowserPackDialog/sheet.less @@ -1,22 +1,13 @@ .daggerheart.dialog.dh-style.views.compendium-brower-settings { - --text-color: beige; + --text-color: light-dark(@dark-blue, @beige); + color: var(--text-color); - .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 { + .types-container { display: flex; flex-direction: column; gap: 8px; - .pack-option-container { + .type-container { display: flex; flex-direction: column; gap: 8px; @@ -32,14 +23,14 @@ content: ''; flex: 1; height: 2px; - background: linear-gradient(90deg, rgba(0, 0, 0, 0) 0%, @golden 100%); + background: linear-gradient(90deg, rgba(0, 0, 0, 0) 0%, light-dark(@dark-blue, @golden) 100%); margin-right: 8px; } &::after { content: ''; flex: 1; height: 2px; - background: linear-gradient(90deg, @golden 0%, rgba(0, 0, 0, 0) 100%); + background: linear-gradient(90deg, light-dark(@dark-blue, @golden) 0%, rgba(0, 0, 0, 0) 100%); margin-left: 8px; } } @@ -48,11 +39,8 @@ 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; @@ -62,21 +50,42 @@ justify-content: space-between; .source-inner-label-container { + width: 100%; display: flex; align-items: center; + justify-content: space-between; gap: 4px; - } - } - .packs-container { - display: grid; - grid-template-columns: 1fr 1fr; - gap: 4px; - padding-left: 24px; + .source-enable-container { + width: 148px; + height: 24px; + padding: 2px 4px; + background-color: light-dark(@dark-blue, @golden); + border-radius: 6px; + position: relative; + display: flex; + align-items: center; - .pack-container { - display: flex; - align-items: center; + &.locked { + opacity: 0.4; + + .source-enable-label { + left: 74px; + } + } + + .source-enable-label { + width: 70px; + border-radius: 6px; + border: 1px solid light-dark(@dark-blue, @beige-50); + text-align: center; + background-color: light-dark(@golden, @beige); + color: black; + position: absolute; + left: 4px; + transition: left ease-in 0.4s; + } + } } } } @@ -84,6 +93,27 @@ } } + .checks-container { + display: grid; + grid-template-columns: 1fr 1fr; + gap: 4px; + transition: height 0.4s ease-in-out; + overflow: hidden; + + &.collapsed { + height: 0px; + } + + &.inner { + padding-left: 24px; + } + + .check-container { + display: flex; + align-items: center; + } + } + footer { margin-top: 8px; display: flex; diff --git a/styles/less/ui/chat/chat.less b/styles/less/ui/chat/chat.less index 8728fbda..1e723ed7 100644 --- a/styles/less/ui/chat/chat.less +++ b/styles/less/ui/chat/chat.less @@ -233,7 +233,7 @@ font-family: @font-subtitle; font-size: var(--font-size-18); font-weight: bold; - color: var(--text-color); + color: light-dark(@dark-blue, var(--text-color)); margin-bottom: -2px; } diff --git a/templates/dialogs/compendiumBrowserSettingsDialog.hbs b/templates/dialogs/compendiumBrowserSettingsDialog.hbs deleted file mode 100644 index 9fe27715..00000000 --- a/templates/dialogs/compendiumBrowserSettingsDialog.hbs +++ /dev/null @@ -1,35 +0,0 @@ -