UXP Flyout Menu Manifest Error

,

I tried to implement the new flyout menu as documented in the recipes, however trying to run the script i get an error stating:

Error: Could not find panel menuItems in manifest

I’m not sure if i’m missing something or what, is there something more i need to implement to get it to recognize and render the flyout menu?

Heres my entry points:

entrypoints.setup({
    plugin: {
        create(plugin) {
            /* optional */ console.log("created")
        },
        destroy() {
            /* optional */ console.log("destroyed")
        },
    },
    panels: {
        index_AR: index_AR_Controller,
        menuItems: [
            { id: "setWarpFactor", label: "Warp Factor 1" },
            { id: "raiseShields", label: "Shields Up" },
            { id: "makeItSo", label: "Engage" },
        ],
        invokeMenu(id) {
            handleFlyout(id)
        },
    },
})

the handle flyout function:

function handleFlyout(id) {
    switch (id) {
        case "setWarpFactor": {
            console.log("Aye captain")
            break
        }
        case "raiseShields": {
            console.log("Shields at 40 percent")
            break
        }
        case "makeItSo": {
            console.log("Warp drive is offline")
            break
        }
    }
}

and my manifest entry points:

    "entrypoints": [
        {
            "type": "panel",
            "id": "index_AR",
            "label": {
                "default": "Index AR"
            },
            "minimumSize": {
                "width": 230,
                "height": 200
            },
            "maximumSize": {
                "width": 2000,
                "height": 2000
            },
            "preferredDockedSize": {
                "width": 230,
                "height": 250
            },
            "preferredFloatingSize": {
                "width": 230,
                "height": 250
            },
            "menuItems": [
                { "id": "setWarpFactor", "label": "Warp Factor 1" },
                { "id": "raiseShields", "label": "Shields Up" },
                { "id": "makeItSo", "label": "Engage" }
            ],
            "icons": [
                {
                    "width": 23,
                    "height": 23,
                    "path": "icons/indexBookIcon.png",
                    "scale": [1, 2],
                    "theme": ["all"],
                    "species": ["generic"]
                }
            ]
        }
    ],

Delete these lines from your manifest:

            "menuItems": [
                { "id": "setWarpFactor", "label": "Warp Factor 1" },
                { "id": "raiseShields", "label": "Shields Up" },
                { "id": "makeItSo", "label": "Engage" }
            ],

They don’t go there. You’ve already got them where they should go in the entrypoints.setup function. I think you’ll find that sorts it. Let us know if not.

Philip

it does not. i added them to the manifest after i got the error stated above. I just removed it and retried but i get the same error.

Did you try Validator for UXP? Does it show something? Validator for UXP - Visual Studio Marketplace

If this doesn’t show an error but the manifest is wrong I could fix validation rules.

Ah, OK

Having looked at it again, I think this may be the problem section:

    panels: {
        index_AR: index_AR_Controller,
        menuItems: [
            { id: "setWarpFactor", label: "Warp Factor 1" },
            { id: "raiseShields", label: "Shields Up" },
            { id: "makeItSo", label: "Engage" },
        ],
        invokeMenu(id) {
            handleFlyout(id)
        },
    },

The below shows typical structure:

	panels: {
		somePanel: {
			create(rootNode) {},
			destroy(rootNode) {},
			show(rootNode) {},
			hide(rootNode) {},
			menuItems: [],
			invokeMenu(id) {}
		},
		anotherPanel: {
			// ditto above
		}
	}

somePanel and anotherPanel in the above pseudocode are ids of the panels defined in your manifest, equivalent to your index_AR.

In your section, instead of the object containing create, destroy, show etc., you’re directing to index_AR_Controller. If that contains create, destroy, show, etc. then menuItems and invokeMenu(id) need to be moved into there.

This makes sense of the error message. Where you have put menuItems in the structure it is thinking that menuItems is another panel (like secondPanel in the pseudocode) and then telling you that you haven’t got a panel with the id of menuItems defined in your manifest.

If the above doesn’t help, perhaps you could share what you have in index_AR_Controller.

Philip

but index_AR_Controller is my PanelController, not an object.

const index_AR_Controller = new PanelController(() => <Home />, {
    id: "index_AR",
})

huh, i didnt think that would work but it did.

my new panelController

const index_AR_Controller = new PanelController(() => <Home />, {
    id: "index_AR",
    menuItems: [
        { id: "setWarpFactor", label: "Warp Factor 1" },
        { id: "raiseShields", label: "Shields Up" },
        { id: "makeItSo", label: "Engage" },
    ],
    invokeMenu(id) {
        handleFlyout(id)
    },
})

thanks for the guidance! the docs were not very clear, or perhaps a bit contradictory?

hmmm, but the invokeMenu doesn’t seem to work. im not getting the expected console logs

Unfortunately, it’s not unusual for the docs to be unclear! :wink:

To be fair, in this instance I think the docs have been written for a vanilla javascript setup. You are perhaps using React?

Personally I don’t use React so you may well stray into territory I don’t understand . . .

ah, i am using the react starter template, but generally vanilla js still works fine when used in a react project for the most point

i did grab the Validator extension when you recommended it here since now i know who made it. only error it pointed out in the manifest was it didnt like the array of objects for my host, i only had the one object for indesign so its now just that instead of an array

1 Like

I’m not immediately sure. The switch statement doesn’t look to be written quite how I’m used to writing it but even so . . .

If I were trying to debug it, I’d first put a console.log statement in the invokeMenu function, something like:

    invokeMenu(id) {
        console.log(`invoked: ${id}`);
        handleFlyout(id);
    },

If that didn’t fire, I’d know it hadn’t made the connection between the menuItems and the invokeMenu function.

If it did fire, I’d put another console.log statement at the top of the handleFlyout function to see whether it was getting that far, something like:

function handleFlyout(id) {
    console.log(`handled: ${id}`);

Just narrowing down the source of the problem.

I do notice that in a few places in your code you don’t include the colon at the end of a statement (e.g. after handleFlyout(id) in the invokeMenu function and in the switch statement). It might not make any difference, and might be me just being a bit OCD, but . . .

Philip

console logs didnt fire from within the invokeMenu or the handleFlyout, and adding the semi colons didn’t help by the way ( i basically never use semicolons any more for js as they aren’t needed )

I’ve found a hint as to what the next steps are by studying PanelController.jsx class component. inside all the create, show, hide functions reside, as well as a invokeMenu(id) function.

invokeMenu(id) {
    console.log(id)
    const menuItem = this[_menuItems].find((c) => c.id === id)
    console.log(menuItem)
    if (menuItem) {
        const handler = menuItem.oninvoke
        console.log(handler)
        if (handler) {
            handler()
        }
    }
}

console logs in that function do fire, but adding an oninvoke property to the menuItems objects

{ id: "version", label: `Plugin Version: ${version}`, oninvoke: () => console.log("version") },

throws a webpack error uxp://uxp-internal/domjs_scripts.js:2 Uncaught Error: Cannot find module 'path'

EDIT: it seems when writing the oinvoke property vscode accidentally imported an on from somewhere that threw the error. it all works now and if anyone else comes across this issue in the future here is what my index.jsx looks like:

import React from "react"

import { PanelController } from "./controllers/PanelController.jsx"

import { entrypoints } from "uxp"
import Home from "./panels/Home"

const version = require("uxp").versions.plugin

const index_AR_Controller = new PanelController(() => <Home />, {
    id: "index_AR",
    menuItems: [
        { id: "version", label: `Plugin Version: ${version}`, oninvoke: () => console.log("Version") },
        { id: "raiseShields", label: "Shields Up", oninvoke: () => console.log("Shields") },
        { id: "makeItSo", label: "Engage", oninvoke: () => console.log("Engage") },
    ],
})

entrypoints.setup({
    plugin: {
        create(plugin) {
            /* optional */ console.log("created")
        },
        destroy() {
            /* optional */ console.log("destroyed")
        },
    },
    panels: {
        index_AR: index_AR_Controller,
    },
})

Phew! :grinning:

Glad you got there