All user data for FoundryVTT. Includes worlds, systems, modules, and any asset in the "foundryuserdata" directory. Does NOT include the FoundryVTT installation itself.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

180 lines
5.3 KiB

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);
}
}