import { TVA_CONFIG, updateSettings } from '../scripts/settings.js';
|
|
import { showPathSelectCategoryDialog, showPathSelectConfigForm } from './dialogs.js';
|
|
|
|
export class ForgeSearchPaths extends FormApplication {
|
|
constructor() {
|
|
super({}, {});
|
|
}
|
|
|
|
static get defaultOptions() {
|
|
return mergeObject(super.defaultOptions, {
|
|
id: 'token-variants-search-paths',
|
|
classes: ['sheet'],
|
|
template: 'modules/token-variants/templates/forgeSearchPaths.html',
|
|
resizable: true,
|
|
minimizable: false,
|
|
closeOnSubmit: false,
|
|
title: game.i18n.localize('token-variants.settings.search-paths.Name'),
|
|
width: 592,
|
|
height: 'auto',
|
|
scrollY: ['ol.token-variant-table'],
|
|
dragDrop: [{ dragSelector: null, dropSelector: null }],
|
|
});
|
|
}
|
|
|
|
async getData(options) {
|
|
if (!this.object.paths) this.object.paths = await this._getPaths();
|
|
|
|
const paths = this.object.paths.map((path) => {
|
|
const r = {};
|
|
r.text = path.text;
|
|
r.cache = path.cache;
|
|
r.share = path.share;
|
|
r.types = path.types.join(',');
|
|
r.config = JSON.stringify(path.config ?? {});
|
|
return r;
|
|
});
|
|
|
|
const data = super.getData(options);
|
|
data.paths = paths;
|
|
data.apiKey = this.apiKey;
|
|
return data;
|
|
}
|
|
|
|
async _getPaths() {
|
|
const forgePaths = deepClone(TVA_CONFIG.forgeSearchPaths) || {};
|
|
this.userId = typeof ForgeAPI !== 'undefined' ? await ForgeAPI.getUserId() : 'tempUser'; // TODO
|
|
this.apiKey = forgePaths[this.userId]?.apiKey;
|
|
return forgePaths[this.userId]?.paths || [];
|
|
}
|
|
|
|
/**
|
|
* @param {JQuery} html
|
|
*/
|
|
activateListeners(html) {
|
|
super.activateListeners(html);
|
|
html.find('a.create-path').click(this._onCreatePath.bind(this));
|
|
$(html).on('click', 'a.select-category', showPathSelectCategoryDialog.bind(this));
|
|
$(html).on('click', 'a.select-config', showPathSelectConfigForm.bind(this));
|
|
html.find('a.delete-path').click(this._onDeletePath.bind(this));
|
|
html.find('button.reset').click(this._onReset.bind(this));
|
|
html.find('button.update').click(this._onUpdate.bind(this));
|
|
$(html).on('click', '.path-image.source-icon a', this._onBrowseFolder.bind(this));
|
|
}
|
|
|
|
/**
|
|
* Open a FilePicker so the user can select a local folder to use as an image source
|
|
*/
|
|
async _onBrowseFolder(event) {
|
|
const pathInput = $(event.target).closest('.table-row').find('.path-text input');
|
|
|
|
new FilePicker({
|
|
type: 'folder',
|
|
activeSource: 'forgevtt',
|
|
current: pathInput.val(),
|
|
callback: (path, fp) => {
|
|
if (fp.activeSource !== 'forgevtt') {
|
|
ui.notifications.warn("Token Variant Art: Only 'Assets Library' paths are supported");
|
|
} else {
|
|
pathInput.val(fp.result.target);
|
|
}
|
|
},
|
|
}).render(true);
|
|
}
|
|
|
|
async _onCreatePath(event) {
|
|
event.preventDefault();
|
|
await this._onSubmit(event);
|
|
|
|
this.object.paths.push({
|
|
text: '',
|
|
cache: true,
|
|
share: true,
|
|
types: ['Portrait', 'Token', 'PortraitAndToken'],
|
|
});
|
|
this.render();
|
|
}
|
|
|
|
async _onDeletePath(event) {
|
|
event.preventDefault();
|
|
await this._onSubmit(event);
|
|
|
|
const li = event.currentTarget.closest('.table-row');
|
|
this.object.paths.splice(li.dataset.index, 1);
|
|
this.render();
|
|
}
|
|
|
|
_onReset(event) {
|
|
event.preventDefault();
|
|
this.object.paths = this._getPaths();
|
|
this.render();
|
|
}
|
|
|
|
async _onUpdate(event) {
|
|
event.preventDefault();
|
|
await this._onSubmit(event);
|
|
this._updatePaths();
|
|
}
|
|
|
|
async _updateObject(event, formData) {
|
|
const expanded = expandObject(formData);
|
|
expanded.paths = expanded.hasOwnProperty('paths') ? Object.values(expanded.paths) : [];
|
|
expanded.paths.forEach((path, index) => {
|
|
this.object.paths[index] = {
|
|
text: path.text,
|
|
cache: path.cache,
|
|
share: path.share,
|
|
source: path.source,
|
|
types: path.types.split(','),
|
|
};
|
|
if (path.config) {
|
|
try {
|
|
path.config = JSON.parse(path.config);
|
|
if (!isEmpty(path.config)) {
|
|
this.object.paths[index].config = path.config;
|
|
}
|
|
} catch (e) {}
|
|
}
|
|
});
|
|
this.apiKey = expanded.apiKey;
|
|
}
|
|
|
|
_cleanPaths() {
|
|
// Cleanup empty and duplicate paths
|
|
let uniquePaths = new Set();
|
|
let paths = this.object.paths.filter((path) => {
|
|
if (!path.text || uniquePaths.has(path.text)) return false;
|
|
uniquePaths.add(path.text);
|
|
return true;
|
|
});
|
|
return paths;
|
|
}
|
|
|
|
_updatePaths() {
|
|
if (this.userId) {
|
|
const forgePaths = deepClone(TVA_CONFIG.forgeSearchPaths) || {};
|
|
forgePaths[this.userId] = {
|
|
paths: this._cleanPaths(),
|
|
apiKey: this.apiKey,
|
|
};
|
|
|
|
if (game.user.isGM) {
|
|
updateSettings({ forgeSearchPaths: forgePaths });
|
|
} else {
|
|
// Workaround for forgeSearchPaths setting to be updated by non-GM clients
|
|
const message = {
|
|
handlerName: 'forgeSearchPaths',
|
|
args: forgePaths,
|
|
type: 'UPDATE',
|
|
};
|
|
game.socket?.emit('module.token-variants', message);
|
|
}
|
|
}
|
|
}
|
|
|
|
async close(options = {}) {
|
|
await this._onSubmit(event);
|
|
this._updatePaths();
|
|
return super.close(options);
|
|
}
|
|
}
|