Aedif / TokenVariants

GNU General Public License v3.0
17 stars 12 forks source link

Add a json source for load names and images #97

Closed p4535992 closed 1 year ago

p4535992 commented 1 year ago

So i add a json options source with this structure:

...
 {
    "name": "Alchemist's Fire",
    "path": "icons/consumables/potions/bottle-round-corked-yellow.webp",
    "tags": ["consumable", "alchemist", "fire"]
  },
  {
    "name": "Alchemist's supplies",
    "path": "icons/containers/bags/pouch-leather-green.webp",
    "tags": ["tool", "alchemist"]
  },
  {
    "name": "Alchemy Jug",
    "path": "icons/containers/kitchenware/jug-terracotta-orange.webp",
    "tags": ["consumable", "jug", "alchemy"]
  },
...

i found a way to integrate the tags (fuzzy is great)

NOTE There is a strange behavior that I can't identify if I load the example file "wowhead-data-2022-11-25.json" and search for the word "Shirt" on the actors portrait it works while on the items icons it doesn't... can you checkout that on your side ?

Aedif commented 1 year ago

Regarding the "Shirt" search failing for Items; I tested it and it works fine. I think you forgot to assign a category to the path:

image

Regarding the code itself, functionally it looks good to me, but there are a couple of usability imporvements you could add to the Search Paths window:

Since we're browsing for a file you could change

async _onBrowseFolder(event)

new FilePicker({
      type: 'folder',
      activeSource: activeSource,
      current: current,
      callback: (path, fp) => {
        pathInput.val(fp.result.target);
        if (fp.activeSource === 's3') {
          sourceInput.val(`s3:${fp.result.bucket}`);
        } else {
          sourceInput.val(fp.activeSource);
        }
      },
    }).render(true);

to

if (activeSource === 'json') {
      new FilePicker({
        type: 'text',
        activeSource: 'data',
        current: current,
        callback: (path, fp) => {
          pathInput.val(path);
        },
      }).render(true);
    } else {
      new FilePicker({
        type: 'folder',
        activeSource: activeSource,
        current: current,
        callback: (path, fp) => {
          pathInput.val(fp.result.target);
          if (fp.activeSource === 's3') {
            sourceInput.val(`s3:${fp.result.bucket}`);
          } else {
            sourceInput.val(fp.activeSource);
          }
        },
      }).render(true);
    }

Include the new json control in ``async _onCreatePath(event)```

        <div class="imgur-control">
            <a class="convert-imgur" title="Convert to Rolltable"><i class="fas fa-angle-double-left"></i></a>
        </div>
        <div class="json-control">
          <a class="convert-json" title="Convert to Rolltable"><i class="fas fa-angle-double-left"></i></a>
        </div>

And make use of a new icon for json paths

  async _onSearchSourceTextChange(event) {
    const image = this._pathIcon(event.target.value);
    const imgur = image === 'fas fa-info';
    const json = image === 'fas fa-brackets-curly';

    const imgurControl = $(event.currentTarget).closest('.table-row').find('.imgur-control');
    if (imgur) imgurControl.addClass('active');
    else imgurControl.removeClass('active');

    const jsonControl = $(event.currentTarget).closest('.table-row').find('.json-control');
    if (json) jsonControl.addClass('active');
    else jsonControl.removeClass('active');

    $(event.currentTarget).closest('.table-row').find('.path-image i').attr('class', image);
  }

  // Return icon appropriate for the path provided
  _pathIcon(source) {
    if (source.startsWith('s3')) {
      return 'fas fa-database';
    } else if (source.startsWith('rolltable')) {
      return 'fas fa-dice';
    } else if (source.startsWith('forgevtt') || source.startsWith('forge-bazaar')) {
      return 'fas fa-hammer';
    } else if (source.startsWith('imgur')) {
      return 'fas fa-info';
    } else if (source.startsWith('json')) {
      return 'fas fa-brackets-curly';
    }

    return 'fas fa-folder';
  }
Aedif commented 1 year ago

I guess another thing, if you want the Static Cache setting to work with 'tags', you'll need to adjust the saveCache and _readCacheFromFile functions

    for (const img of CACHED_IMAGES[c]) {
      if (img.tags) {
        data[c].push([img.path, img.name, img.tags]);
      } else if (getFileName(img.path) === img.name) {
        data[c].push(img.path);
      } else {
        data[c].push([img.path, img.name]);
      }
    }
        for (const img of json[category]) {
          if (Array.isArray(img)) {
            if (img.length === 3) {
              CACHED_IMAGES[category].push({ path: img[0], name: img[1], tags: img[2] });
            } else {
              CACHED_IMAGES[category].push({ path: img[0], name: img[1] });
            }
          } else {
            CACHED_IMAGES[category].push({ path: img, name: getFileName(img) });
          }
        }

Cache files save images as strings or arrays of either length 1 or 2. The logic needs to be slightly adjusted to support arrays of length 3 to accommodate the tags ^

Aedif commented 1 year ago

Anyway, I'll accept the pull and will make the slight adjustments myself since I already know what needs to be done. 👍 The actual core of the functionality appears to work fine.