Looking for advice / direction on UXP approach - just placing files

Disclaimer: I am new and haven’t read through all the resources, so I am asking for broad advice on whether I should just “stick with what works” or take a shot at putting this into UXP.

I have a very amateur project linked here on GitHub:

With a demonstration video here on YouTube of the project using some example roadway signage icons:

The logo dropper application is just a website (html, css, js) that shows a series of images from a json object. The project shows how the json is prepared with some excel library (so you can export the json conveniently, but really that’s irrelevant).
If you got this far into the post, you probably are thinking, how is this better than explorer/finder, or even creative cloud libraries? Well there’s a couple reasons, primarily, svg and complex illustrations, eps files, PSDs without maximize compatibility, there are all kinds of reasons those other file menus don’t provide a great visual and they also have search methods that tend to focus on the filename or perhaps extension or date and size, but often times they don’t provide a metadata, or a thematic search. They also sometimes are slow as they may poll more of the disk(s) than they need for this task. Anyways, for me, I have found this far faster than using other methods to place logos, which I do a lot at work (like thousands of times per week at a minimum) so even those 1 second savings add up a real lot.

This webpage points to the result file from the image src (or an affiliated file as the case may be in order to display a pre rastered PSD for example) and then have it get placed in Photoshop by default, or Illustrator or grab the path.

This webpage is running in webview2 which as I understand it, is essentially Microsoft Edge (Chrome). Hence it has decent coverage for web compatibility, including SVG. I have read that at the present moment, there is somewhat limited SVG support for UXP, and I assume that is in order to keep it a smooth experience.
I am looking to see if it might be worthwhile for me to investigate porting it to UXP as I understand there would be a lot of front end adjustments needed in order to make sure the HTML was compatible and perhaps other conditions currently relied on in the js like DOMContentLoaded.

The way I had been placing logos before was mostly from my stream deck, which would run a vbs file that calls a jsx file and is able to pass parameters to it with DoAJavascript (the VBS approach was from somewhere on the PS community forums). It always worked great, but the big downside is, 1) it takes forever and an unpredictable amount of time, and 2) you have zero idea if Ps is in a modal/blocking state.

I noticed after reading up on UXP (or at least starting to) that .psjs was another way to name a scripting extension, which enabled access to require("photoshop") and the like by just running it, whereas a JSX file, running it, or at least iirc running it through the vbs file didn’t have access to require. However, even in a simple test, this proved to not be any faster than the jsx method, even when I used the same method recorded in Alchemist (which dispatches immediately).

I assume there just is too great a delay between the que of running a file with photoshop and it then getting to the point of taking that action. That is probably also why there was a great degree of randomness in the total time taken.

What appears to be working well enough is putting the logo placer script (using the old, ugly, and hard to read action descriptors syntax) into the scripts directory, and letting the AHK side that wraps the HTML be elevated to delete and redraft the script with the hardcoded path. That’s awful for many reasons, but it works pretty good and the file delete and rewrite only take a few hundred ms on the high side that I don’t even notice and the total time taken to place the image is pretty quick (usually under 550 ms). But its still a slight bit slower than the modern methods dispatched. Using code recorded by Alchemist 2.7, it gave me more or less the below (I just coded in a path and added a parameter if I recall correctly):

const {executeAsModal} = require("photoshop").core;
const {batchPlay} = require("photoshop").action;
const {localFileSystem: fs} = require("uxp").storage;
async function tokenify(url){
   return fs.createSessionToken(await fs.getEntryWithUrl("file:" + url));
}
async function actionCommands(filePath) {
    const result = await batchPlay(
        [
            {
                _obj: "placeEvent",
                ID: 8,
                null: {
                    _path: await tokenify(filePath),
                    _kind: "local"
                },
                freeTransformCenterState: {
                    _enum: "quadCenterState",
                    _value: "QCSAverage"
                },
                offset: {
                    _obj: "offset",
                    horizontal: {
                        _unit: "distanceUnit",
                        _value: 0
                    },
                    vertical: {
                        _unit: "distanceUnit",
                        _value: 0
                    }
                },
                antiAlias: true,
                _options: {
                    dialogOptions: "dontDisplay"
                }
            }
        ],
        {}
    );
}
async function runModalFunction(filePath) {
    await executeAsModal(() => actionCommands(filePath), {"commandName": "Action Commands"});
}
runModalFunction("C:/tmp/logos/SVG/TestLogoRectangular.svg");

So because if I figure out UXP, this dispatches immediately and it is a lot nicer to look at, and because I might be able to avoid hitting the hard drive for a write all together and I won’t have to run the AHK elevated, or provide sketchy access to the Photoshop scripts folder, all I am risking is learning something maybe.
I would like to know if I am better off trying to port the front end (the webpage), or just for simplicity because it might be easier and keep the weight off the UI, see if there is a good communication method between an outside source and UXP so that it can dispatch a simple method like that? I have seen some postmessage stuff but that seemed like it was to a webview2 inside of UXP and then maybe I also saw something about websockets and they can only receive (that might be the one to look at as all it needs is a file name). I appreciate any suggestions!

Seems like you already have a decent interface working in webview. I would try it in a UXP webview to see if everything works interface wise. If so, you can create a uxp plugin that shows that webview and listens for messages that trigger your imports or whatever you need to do.
One limitation with uxp webview is that it cannot load local files. So, you would either need to run that page on a webhost or run a server. Although the rumor is they may be opening up local files later this year.

1 Like

UXP can’t start the server either.

1 Like

@JasonM I have spun up a server for this interface (and its trivial string replacement to point to the local file - as I am showing a copy of the files on the server). To Jarda’s point, in my case I will just have the server running beforehand.

I see the webview example in the UXP Developer tools. In the manifest.json, should it be as simple as pointing “main”: “localhost” to point to the local server? In my case its hosted on port 80 on apache2. Appreciate any direction. Thank you!

actually, I think I need to have another look at this webview example in UDT as I had a network topology issue since resolved and once corrected, it seems to display everything just fine, probably should work soon