Opening files from path

Greetings,

I have come across an issue that I don’t know how to solve. I am trying to make a plugin, that will enable me to first select a file, I will get the file path and then open the file in photoshop with that said path. I managed to make a file dialog that gives me the path to the documents I want. The part that I am struggling with is the actual opening of the files from said path. I used alchemist to get some of the code and I can’t understand why parts aren’t working. I am not getting any error. Could it be that I forgot to put something in manifest? or is it just the code?

Here is my code:

async function runModalFunction() {
    console.log("start");
    await selectFile();
    await executeAsModal(actionCommands, {"commandName": "Action Commands"});
}
async function actionCommands() {
    console.log("actionCommands")
    const result = await batchPlay(
        [
            {
                _obj: "open",
                null: {
                    _path: startFilePath,
                    _kind: "local"
                },
                documentID: 78,
                template: false,
                _isCommand: true,
                _options: {
                    dialogOptions: "dontDisplay"
                }
            }
        ],
        {}
    );
    console.log("end of action commands")
}

As for how I get that said path:

const fs = window.require("uxp").storage.localFileSystem;
    const file = await fs.getFileForOpening();
    const token = await fs.createPersistentToken(file);

    const fileObject = {
        name: file.name,
        path: file.nativePath,
        token: token,
        entry: file,
    };
    const finalPath = fileObject.path;
    console.log(finalPath)
    startFilePath = finalPath;

Finally, here are my permissions in manifest:

"requiredPermissions": {
    "allowCodeGenerationFromStrings": true,
    "launchProcess": {
      "schemes": [
        "http",
        "https"
      ],
      "extensions": [
        ".svg",
        ".png"
      ]
    },
    "localFileSystem" : "request",
    "clipboard": "readAndWrite",
    "webview": {
      "allow": "yes",
      "domains": [
        "https://*.adobe.com",
        "https://*.google.com"
      ]
    }
  },

Is there a particular reason you use batchPlay to open a file instead of the API? It’s 10+ lines of code with batchPlay vs. two lines using the API:

// Open a file given entry (example from the documentation)
let entry = await require('uxp').storage.localFileSystem.getFileForOpening()
const document = await app.open(entry);
1 Like

My recollection is that you need to specify "interactive": true when using the file select dialog in executeAsModal.

await executeAsModal(actionCommands, {"commandName": "Action Commands", "interactive": true});

Additional edits:

  • As dotproduct pointed out, selectFile was outside its executeAsModal. The "interactive": true is for its higher-level executeAsModal.
  • Is the window. necessary here?
const fs = window.require("uxp").storage.localFileSystem;

From what I can tell from @M3mber’s code it looks like he’s doing the file selection before running executeAsModal. Again, apart from the fact that you can achieve all of this with 2 lines of code ( :wink:), @M3mber, can you confirm that when calling your function actionCommands(), your variable startFilePath contains something reasonable? I don’t see where you declare this, though it looks like a global variable. Might be a good idea to wrap your batchPlay call in a try/catch block to get some debug info.

1 Like

So, the main reason for me using batchplay is because of my lack of understanding. My main objective is to iterate over files in a directory one by one after a click of a button. Open them as well. Now, batchplay seemed more intuitive with the paths. I struggle to understand how to edit the returning object Promise<File|Array>. If you could give some pointers on that then that would be great!

startPath contains a file path that was created from the entry of getFileOpening(). As can be seen here in this code:

const fs = window.require("uxp").storage.localFileSystem;
    const file = await fs.getFileForOpening();
    const token = await fs.createPersistentToken(file);

    const fileObject = {
        name: file.name,
        path: file.nativePath,
        token: token,
        entry: file,
    };
    const finalPath = fileObject.path;
    console.log(finalPath)
    startFilePath = finalPath;

With the danger of sounding like a broken record ( :grin:), I would still strongly encourage you to use the UXP API for this. Opening a folder of files is something that can be easily done with just a few lines of code. In the age of UXP the idea would be to use the API as much as possible (at least in my humble opinion :wink:). It’s more readable, more maintainable and easier to debug. You can still use BatchPlay for functionality that isn’t easily available in the API. I’d suggest looking at the docs (in particular about file system access). It goes over ways to access an entire folder and how to access its files. Then it’s as simple as iterating over these files.

I’m not sure what you mean by batchPlay being more intuitive with the paths. I would humbly claim the opposite. Actually ‘_path’ in the batchPlay’s descriptor needs to be a token (which is a bit misleading). Maybe you can try passing that instead of the native path.

With the danger of sounding like a broken record ( :grin:), I would still strongly encourage you to use the UXP API for this.

:point_up_2:t2::100:%

1 Like