Move Layer to Front through batch-play works differently in PS 23.4.1

That’s very good explanation, thank you! I’ll have to edit dozens of functions now but at leas there is a light in the end of the tunnel :slight_smile:

My commands are all inside execModal() and all BPs are synchronous - no luck here :frowning:

Hmm, the issue seems to be with the filter dialog. It fails when I apply it but not when I cancel. I’ll log a ticket for investigation.

Yes, adding async/await does resolve the issue. I’d like to get a better handle on the situation and a better error for this type of situation.

Hi @simonhenke,

I’m trying to implement your solution for suspendHistory helper function. It works if I’m using only BP.

But… if I’m trying to do:

batchPlay
DOM
batchplay

or

batchPlay
DOM

I’m getting two history states. I have no idea what I’m doing wrong.

Could you please take a look at the code structure:


async function dbgrey() {

    const docexists = () => {
        return Boolean(app.documents?.length)
      }
      const dexists = docexists()
      
if (dexists === true) {

    suspendHistory(async () => {

        await batchPlay([

         // descriptor 1
         // descriptor 2
         // ...

            ], {});

        await app.activeDocument.activeLayers[0].moveAbove(await app.activeDocument.layers[0]);    

        await batchPlay(
            [

         // descriptor 1
         // descriptor 2
         // ...

            ], {});
        }, "Just one step")
}
else {  PhotoshopCore.showAlert({message: 'Open the document first'});}
}

document.getElementById("btndbgrey").addEventListener("click", dbgrey);

This is your helper that I’m using (I’ve removed “export”):

async function suspendHistory(fn, historyName = "(Plugin command)", commandName = "Waiting for plugin command...") {
    async function executeAsModal(executionContext) {
      const hostControl = executionContext.hostControl;
      const suspensionID = await hostControl.suspendHistory({
          "historyStateInfo": {
              "name": historyName,
              "target": { _ref: 'document', _enum: 'ordinal', _value: 'targetEnum' }
          }
      });
      try {
        fn(executionContext);  
      } catch(e) {console.error(e)}
     await hostControl.resumeHistory(suspensionID);
    }
    await require("photoshop").core.executeAsModal(executeAsModal, {commandName});
  }

I would be very grateful if you could tell me what I’m doing wrong.

I’m using PS 23.4.1 on Mac, API 2, Manifest 5

Thank you!

I think you’re missing await in suspendHistory():

await fn(executionContext);

I believe what happens, is right after you call the callback, also resumeHistory() is called before your function finishes

1 Like

@Karmalakas, You are right, thank you!

You can also do it in React. Here is an example:

import { app, constants, core } from "photoshop";
import React from "react";

const App = () => {
  const handleClick = async () => {
    try {
      await core.executeAsModal(
        async (executionContext) => {
          let hostControl = executionContext.hostControl;
          let suspensionID = await hostControl.suspendHistory({
            documentID: app.activeDocument.id,
            name: "Custom command",
          });
          const activeLayer = app.activeDocument.activeLayers[0];
          activeLayer?.move(
            app.activeDocument.layers[0],
            constants.ElementPlacement.PLACEBEFORE
          );
          hostControl.resumeHistory(suspensionID);
        },
        { commandName: "Moving layer to the front" }
      );
    } catch (error) {
      console.log(error);
    }
  };

  return <sp-button onClick={handleClick}>Move Layer to Front</sp-button>;
};

export default App;