Bug of the UXP progress bar? Why is the progress bar window never displayed?

require("photoshop").core.executeAsModal(async(executionContext) => {
    let suspensionID = await executionContext.hostControl.suspendHistory({
        "documentID": app.activeDocument.id,
        "name": 'Test Progress'
    });
    await require("photoshop").action.batchPlay([{
        "_obj": "copyToLayer"
    }, {
        _obj: "surfaceBlur",
        radius: {
            _unit: "pixelsUnit",
            _value: 100
        },
        threshold: 15
    }], {});
    await app.activeDocument.layers.forEach((layer) => {
        layer.visible = false;
    });
    await executionContext.hostControl.resumeHistory(suspensionID);
}, {
    commandName: "Test Progress Bar"
});

When running this era, the running time is obviously more than 2 seconds, but why doesn’t the progress bar window appear halfway?
Not only the “surfaceBlur” function, but also other C++ plug-ins will not appear when the progress bar window, is this a Bug of UXP? @kerrishotts

Not sure if this is related but on my machine surface blur uses all CPU cores at once. So there might not be resources left to show a dialog. Can you try filters that can use only a single CPU core?

I wonder if the problem isn’t so much resources but the filter thread(s) not yielding to the gui thread :thinking: If it’s a deal breaker maybe a temporary work around might be to show your own message dialog, call batchPlay and close the dialog once done?

It’s safe to say that things are definitely not that simple. Maybe the pixels of the photos you test are too small. With photos with more than 20 million pixels, the average computer processing time will be more than 2 seconds, but you still can’t see the progress bar window.
However, I changed the code to the following so that I could see the progress bar window:

require("photoshop").core.executeAsModal(async(executionContext) => {
    // let suspensionID = await executionContext.hostControl.suspendHistory({
    //     "documentID": app.activeDocument.id,
    //     "name": 'Test Progress'
    // });
    // await require("photoshop").action.batchPlay([{
    require("photoshop").action.batchPlay([{
        "_obj": "copyToLayer"
    }, {
        _obj: "surfaceBlur",
        radius: {
            _unit: "pixelsUnit",
            _value: 100
        },
        threshold: 15
    }], {});
    // await app.activeDocument.layers.forEach((layer) => {
    //     layer.visible = false;
    // });
    // await executionContext.hostControl.resumeHistory(suspensionID);
}, {
    commandName: "Test Progress Bar"
});

In this code, the history merge operation and the await before the batchPlay are canceled, and the steps performed after the batchPlay are cancelled. if you don’t, you won’t see the progress bar window no matter how long you run. Why?

What happens if you await executeAsModal()? :thinking: Just guessing here

1 Like

This question is not important enough?

@kaibei that’s a bit rude

You’re right. We should continue to wait patiently and be more patient.

Or let someone know if their suggestion made any difference or not

1 Like

Is the help of three people not good enough for you? Three people who have given their time freely to do so I might add.

1 Like

Are we here to chat? There is no progress bar during a long run, which can cause the user to crash.
1: I think this is the place to solve the problem. Does the problem exist?
2: if the problem exists, is there a way to solve it? Don’t chat.

Sure, but don’t be a dick about it

1 Like

LOL. I just tested your code and I get a progress bar.

I got a progress bar with a 24 core i9. That said, CPU didn’t dip below 90% for whole process.

I can see the progress bar with the code sent for the second time, and I can never see the progress bar with the code sent for the first time. Did you test it with the code sent for the first time? Thank you.

I’ve been experimenting and I’m starting to lean towards a bug.
In a nutshell, if I re-run the surface blur a second time within the same executeAsModal the progress bar appears for the second run and with the custom commandName, but it doesn’t move. Otherwise no progress bar is displayed (apart from a millisecond flash of it at the end).
The batchplay descriptors execute and the history suspension works fine.
If I hit escape during the first surface blur, the second one starts and the progress bar appears (but still doesn’t move).
This is my test code and the console output - note the time logging. If the surface blur only runs once the total time is correct and matches “Run A”, if run twice it seems to ignore “Run B”.

async function test() {
  try {
    // Helper functions
    const getTime = (start, end) => {
      const diff = end - start;
      const seconds = Math.floor((diff / 1000) % 60);
      return seconds === 0 ? "<1" : seconds;
    };

    const surfaceBlur = async () => {
      await batchPlay(
        [
          {
            _obj: "copyToLayer",
          },
          {
            _obj: "surfaceBlur",
            radius: {
              _unit: "pixelsUnit",
              _value: 100,
            },
            threshold: 15,
          },
        ],
        {}
      );
    };

    const invertLayerVisibilty = async () => {
      app.activeDocument.layers.forEach((h) => (h.visible = !h.visible));
    };

    // Main function
    const modalStart = new Date();

    await core.executeAsModal(
      async (executionContext) => {
        let hostControl = executionContext.hostControl;
        let documentID = app.activeDocument.id;
        let suspensionID = await hostControl.suspendHistory({
          documentID: documentID,
          name: "Custom Command",
        });

        const startA = new Date();
        // No progress bar for following 3 function calls
        await surfaceBlur();
        await invertLayerVisibilty();
        // Flip layers back to visible so next surface blur has pixel data to use
        await invertLayerVisibilty();

        const endA = new Date();
        console.log(`Run A took ${getTime(startA, endA)} seconds`);

        const startB = new Date();

        // this will display progress bar with custom command name but progress bar does not move

        await surfaceBlur();
        const endB = new Date();
        console.log(`Run B took ${getTime(startB, endB)} seconds`);

        await hostControl.resumeHistory(suspensionID);
      },
      { commandName: "executeAsModal" }
    );

    const modalEnd = new Date();

    console.log(`Process took ${getTime(modalStart, modalEnd)} seconds`);
  } catch (error) {
    console.error(error);
  }
}

Also keep in mind that you can update progress bar explicitly and control percentage and message by yourself. https://developer.adobe.com/photoshop/uxp/2022/ps_reference/media/executeasmodal/#progress-bar

I tried adding arbitrary progress updates within the main function with no success.
I also tried nesting each function call wrapped within a secondary executeAsModal and nada - no progress bar.

Based on the logged 45 second process time of running a single surface blur batchPlay command there should be a progress bar no?
I’m also confused why a second call to the same function renders a broken progress bar when the first didn’t.

I’m going to test it tomorrow with a known working example that takes >2 seconds but is bunch of resize/save functions rather than a single CPU intensive descriptor.

It’s less a case of “why isn’t the progress UI updating?” and more “I’m not getting a progress bar at all!”

Yes, there is no progress bar is displayed (apart from a millisecond flash of it at the end).

I’m not getting a progress bar at all! Why?