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

So no matter how I try, I still get that command is not available…
Here are my descriptors:

[
    {
        "_obj": "select",
        "_target": [{"_ref": "layer", "_id": 2}],
        "makeVisible": false
    },
    {
        "_obj": "make",
        "new": {"_class": "channel"},
        "at": {"_ref": "channel", "_enum": "channel", "_value": "mask"},
        "using": {"_enum": "userMaskEnabled", "_value": "revealAll"}
    },
    {
        "_obj": "select",
        "_target": [{"_ref": "layer", "_id": 3}],
        "makeVisible": false
    },
    {
        "_obj": "make",
        "new": {"_class": "channel"},
        "at": {"_ref": "channel", "_enum": "channel", "_value": "mask"},
        "using": {"_enum": "userMaskEnabled", "_value": "revealAll"}
    },
    {
        "_obj": "select",
        "_target": [{"_ref": "layer", "_id": 2}],
        "makeVisible": false
    },
    {
        "_obj": "select",
        "_target": [{"_ref": "layer", "_id": 3}],
        "makeVisible": false,
        "selectionModifier": {
            "_enum": "selectionModifierType",
            "_value": "addToSelection"
        }
    }
]

No matter if I execute them in a single BP or one by one I get the responses for them:

[
    {},
    {
        "_obj": "error",
        "message": "The command “Make” is not currently available.",
        "result": -25920,
        "failedDescriptor": {
            "_obj": "make",
            "new": {"_class": "channel"},
            "at": {"_ref": "channel", "_enum": "channel", "_value": "mask"},
            "using": {"_enum": "userMaskEnabled", "_value": "revealAll"}
        }
    },
    {},
    {
        "_obj": "error",
        "message": "The command “Make” is not currently available.",
        "result": -25920,
        "failedDescriptor": {
            "_obj": "make",
            "new": {"_class": "channel"},
            "at": {"_ref": "channel", "_enum": "channel", "_value": "mask"},
            "using": {"_enum": "userMaskEnabled", "_value": "revealAll"}
        }
    },
    {},
    {}
]

Have to note, that none of the layers have any masks while trying to create one. Also, as mentioned previously, very very rarely it works as expected - masks are created (both in a single BP and in a separate calls)

Win10
Ps 23.4.1
API v2
Manifest v4

I have same issue with mask creation.

So to sum up, two issues I’ve noticed:

  • Moving layers through BP works differently. (error popups when the layer is already on top when I’m trying to move it up. It didn’t before)
    {
                    _obj: "move",
                    _target: {
                        _ref: "layer",
                        _enum: "ordinal",
                        _value: "targetEnum"
                    },
                    to: {
                        _ref: "layer",
                        _enum: "ordinal",
                        _value: "front"
                    },
                    _options: {
                        dialogOptions: "dontDisplay"
                    }
                }
  • Error when I’m trying to create mask The command “Make” is not currently available.
        {
                    _obj: "make",
                    new: {
                        _class: "channel"
                    },
                    at: {
                        _ref: "channel",
                        _enum: "channel",
                        _value: "mask"
                    },
                    using: {
                        _enum: "userMaskEnabled",
                        _value: "revealAll"
                    },
                    _options: {
                        dialogOptions: "dontDisplay"
                    }
                }

This is the whole code that throws me an error during mask creation (Mac, PS 23.4.1, Api 2.0 Manifest version 5)



async function dustAndScratches() {

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


    await core.executeAsModal(() => {
    

        batchPlay(
            [
                {
                    "_obj": "select",
                    "_target": {
                        "_ref": "layer",
                        "_id": app.activeDocument.layers[0]._id
                    },
                    "_isCommand": true,
                    "_options": {}
                },
                {
                    _obj: "make",
                    _target: {
                        _ref: "layer"
                    },
                    _options: {
                        dialogOptions: "dontDisplay"
                    }
                },
                {
                    _obj: "mergeVisible",
                    duplicate: true,
                    _options: {
                        dialogOptions: "dontDisplay"
                    }
                },

                {
                    _obj: "set",
                    _target: {
                        _ref: "layer",
                        _enum: "ordinal",
                        _value: "targetEnum"
                    },
                    to: {
                        _obj: "layer",
                        name: "Dust and Scratches"
                    },
                    _options: {
                        dialogOptions: "dontDisplay"
                    }
                },
                {
                    _obj: "select",
                    _target: {
                        _ref: "menuItemClass",
                        _enum: "menuItemType",
                        _value: "view200Percent"
                    },
                    _options: {
                        dialogOptions: "dontDisplay"
                    }
                },
                {
                    _obj: "dustAndScratches",
                    _options: {
                        dialogOptions: "display"
                    }
                },
                {
                    _obj: "make",
                    new: {
                        _class: "channel"
                    },
                    at: {
                        _ref: "channel",
                        _enum: "channel",
                        _value: "mask"
                    },
                    using: {
                        _enum: "userMaskEnabled",
                        _value: "revealAll"
                    },
                    _options: {
                        dialogOptions: "dontDisplay"
                    }
                },
                {
                    _obj: "invert",
                    _options: {
                        dialogOptions: "dontDisplay"
                    }
                },
                {
                    _obj: "select",
                    _target: {
                        _ref: "channel",
                        _enum: "channel",
                        _value: "mask"
                    },
                    makeVisible: false,
                    _options: {
                        dialogOptions: "dontDisplay"
                    }
                },
                {
                    _obj: "select",
                    _target: {
                        _ref: "paintbrushTool"
                    },
                    _options: {
                        dialogOptions: "dontDisplay"
                    }
                },
                {
                    _obj: "reset",
                    _target: {
                        _ref: "color",
                        _property: "colors"
                    },
                    _options: {
                        dialogOptions: "dontDisplay"
                    }
                },
                {
                    _obj: "select",
                    _target: {
                        _ref: "menuItemClass",
                        _enum: "menuItemType",
                        _value: "fitOnScreen"
                    },
                    _options: {
                        dialogOptions: "dontDisplay"
                    }
                }
            ], {
                "historyStateInfo": {
                    "name": "Dust and Sctartches",
                    "target": {
                        "_ref": "document",
                        "_enum": "ordinal",
                        "_value": "targetEnum"
                    }
                }
            });
    })
}
else {  PhotoshopCore.showAlert({message: 'Open the document first'});}
}
document.querySelector("#btndustAndScratches").addEventListener("click", dustAndScratches);

Works fine for me in 10 out of 10 tries :thinking:
I’m on manifest version 4, maybe 5 is causing the issue.

Can’t test it right now as I’m getting
image
when changing to version 5. Not sure where in my project any code generation from strings might be, at least I’m not aware of any.

I’m still on v4 also


Some raw onclick maybe somewhere on a pure HTML element? :slight_smile:


Also if I have masks on these two layers and change commands from make to delete, they work just fine and masks are deleted

Also if I have masks on these two layers and change commands from make to delete , they work just fine and masks are deleted

I wonder wow the Photoshop Action would work comparing to script. (if it would give an error too).
I’ve tested action regarding moving layers and it was also not working on 23.4.1 but did on previous versions.

I’ve noticed interesting thing - Mask creation doesn’t work if it’s done on top layer. Id does work if there is another layer above :confused:

EDIT: this doesn’t apply to all functions which is even more confusing…

For me it doesn’t work either way

nope, I only have React components.
Also, I commented out my whole index.tsx and the error still occurs, maybe it’s related to some webpack or babel code :confused: So I guess I can’t move to manifest v.5 :sweat_smile:

@kerrishotts, could you please take a look on this? What was changed in 23.4.1 and how can we deal with that now?

out of curiosity I tried your code on my plugin which in API 2 Manifest 5, Photoshop 23.4.1 it worked well:
here is your whole code with what I changed

const ExecuteAsModal = require("photoshop").core.executeAsModal;

document
  .getElementById("btndustAndScratches")
  .addEventListener("click", async function () {
    await ExecuteAsModal(() => dustAndScratches());
  });
async function dustAndScratches() {
  const docexists = () => {
    return Boolean(app.documents?.length);
  };
  const exists = docexists();

  if (exists === true) {
    await batchPlay(
      [
        {
          _obj: "select",
          _target: {
            _ref: "layer",
            _id: app.activeDocument.layers[0]._id,
          },
          _isCommand: true,
          _options: {},
        },
        {
          _obj: "make",
          _target: {
            _ref: "layer",
          },
          _options: {
            dialogOptions: "dontDisplay",
          },
        },
        {
          _obj: "mergeVisible",
          duplicate: true,
          _options: {
            dialogOptions: "dontDisplay",
          },
        },

        {
          _obj: "set",
          _target: {
            _ref: "layer",
            _enum: "ordinal",
            _value: "targetEnum",
          },
          to: {
            _obj: "layer",
            name: "Dust and Scratches",
          },
          _options: {
            dialogOptions: "dontDisplay",
          },
        },
        {
          _obj: "select",
          _target: {
            _ref: "menuItemClass",
            _enum: "menuItemType",
            _value: "view200Percent",
          },
          _options: {
            dialogOptions: "dontDisplay",
          },
        },
        {
          _obj: "dustAndScratches",
          _options: {
            dialogOptions: "display",
          },
        },
        {
          _obj: "make",
          new: {
            _class: "channel",
          },
          at: {
            _ref: "channel",
            _enum: "channel",
            _value: "mask",
          },
          using: {
            _enum: "userMaskEnabled",
            _value: "revealAll",
          },
          _options: {
            dialogOptions: "dontDisplay",
          },
        },
        {
          _obj: "invert",
          _options: {
            dialogOptions: "dontDisplay",
          },
        },
        {
          _obj: "select",
          _target: {
            _ref: "channel",
            _enum: "channel",
            _value: "mask",
          },
          makeVisible: false,
          _options: {
            dialogOptions: "dontDisplay",
          },
        },
        {
          _obj: "select",
          _target: {
            _ref: "paintbrushTool",
          },
          _options: {
            dialogOptions: "dontDisplay",
          },
        },
        {
          _obj: "reset",
          _target: {
            _ref: "color",
            _property: "colors",
          },
          _options: {
            dialogOptions: "dontDisplay",
          },
        },
        {
          _obj: "select",
          _target: {
            _ref: "menuItemClass",
            _enum: "menuItemType",
            _value: "fitOnScreen",
          },
          _options: {
            dialogOptions: "dontDisplay",
          },
        },
      ],
      {
        historyStateInfo: {
          name: "Dust and Sctartches",
          target: {
            _ref: "document",
            _enum: "ordinal",
            _value: "targetEnum",
          },
        },
      }
    );
  } else {
    PhotoshopCore.showAlert({ message: "Open the document first" });
  }
}

edited to add missing Variable

Hi @Wanokuni

interesting, when I’m using your version of the function, nothing happens after clicking the button. I’m looking for a reason now.

Check for inline handlers – or, if you’re using webpack, check how your sourcemaps are being handled – default is to use eval – which will cause the issue.

If you’re using webpack, you can (for dev purposes), add allowCodeGenerationFromStrings: true to your requiredPermissions section in the manifest, and the error should go away.

Downgraded Ps to v23.3.2 (don’t have v23.4.0 on the list of Other versions) and it works perfectly

@kerrishotts, could you please ping someone? This really needs to be fixed (or at least some workaround given). As mentioned, same issue on v23.5 beta

@heewoo @samgannaway FYI ^^^^

1 Like

This is my code. It can activate layers. Maybe it can help you.

    await ActiveLayer()
    async function ActiveLayer() {

        let cl = await app.activeDocument.activeLayers[0];

        if (cl == undefined) {
            let layers = await require("photoshop").app.activeDocument.layers;
            await require("photoshop").core.executeAsModal(async () => {
                try {

                    await require("photoshop").action.batchPlay([{
                        "_obj": "select",
                        "_target": [{
                            "_ref": "layer",
                            "_id": layers[0]._id
                        }],
                        "_isCommand": true
                    }, ], {
                        "synchronousExecution": false
                    });
                } catch (e) {
                    console.error(e);
                }
            }, {
                commandName: "Test"
            });
        }
    }

Activation for me also works just fine. Even mask deletion works fine. Just not mask creation :frowning:

Still reading through this thread, but I’ve verified that we did have a change in behavior with the 23.4.1 update which will result in “command ‘Move’ not available” appearing when you attempt to run layer arrangements on documents with only one layer. We’ve got a bug logged and will investigate. A quick glance while scrolling down to the bottom of this thread and I get a sense there may be some other items which may have changed as well. Or there may be multiple ways in which the new behavior manifests. I’ll keep reading through the thread and continue testing.

hi @BrettN ,

We can workaround new “Move” logic, but the biggest issue from my perspective is unpredictable behaviour of mask creation. I think that it’s a bug. Once it works, next time it doesn’t. I can’t find the pattern at the moment. It occurs for sure on Mac (M1), API 2, Manifest 5.

Hi @Wanokuni, I Can confirm that everything works now! Did you change anything apart from the listener and its relation to html button? I can’t understand how this could affect mask creation that didn’t work before. Anyway, Thanks!

Hi @Adam Great it worked! Yes I have added an await to the batch play. from my understanding is that Photoshop will try to run commands as fast as possible without waiting for other commends to finish special after a dialog box, create a mask or moving a layer become a promise that doesn’t get fulfilled hope this make sense. I think @DavideBarranca explained this concept very well in this video https://www.youtube.com/watch?v=sf7YPWUppSM

1 Like