Hieromon / AutoConnect

An Arduino library for ESP8266/ESP32 WLAN configuration at runtime with the Web interface
https://hieromon.github.io/AutoConnect/
MIT License
911 stars 190 forks source link

AutoConnectAux menu() not working #581

Closed gw8484 closed 1 year ago

gw8484 commented 1 year ago

I need to dynamically show/hide the "Update" menu item. I am calling the menu() method on the AutoConnectAux object for AUTOCONNECT_URI_UPDATE (i.e. "/_ac/update") but it does not hide the "Update" menu item. the AutoConnect version is v1.4.2 on ESP32.

Hieromon commented 1 year ago

I'm not sure what you mean by using AutoConnectAux::menu function to show/hide the Update menu item of AutoConnect menu. The AutoConenctAux::menu function controls whether the AutoConnectAux itself is excluded from menu items, it does not affect the visibility of the Update menu item.

Ref: https://hieromon.github.io/AutoConnect/apiaux.html#menu

Set or reset the display as menu item for this AutoConnectAux. This function programmatically manipulates the menu parameter of the AutoConnectAux constructor.

Use AutoConnect::enableMenu/disableMenu to show/hide AutoConnect menu items.

gw8484 commented 1 year ago

I'm not sure what you mean by using AutoConnectAux::menu function to show/hide the Update menu item of AutoConnect menu. The AutoConenctAux::menu function controls whether the AutoConnectAux itself is excluded from menu items, it does not affect the visibility of the Update menu item.

Ref: https://hieromon.github.io/AutoConnect/apiaux.html#menu

Set or reset the display as menu item for this AutoConnectAux. This function programmatically manipulates the menu parameter of the AutoConnectAux constructor.

Use AutoConnect::enableMenu/disableMenu to show/hide AutoConnect menu items.

Thank you for the quick response. The AutoConnect::enableMenu()/disableMenu() methods work as expected. However, can you clarify the expected visible effects of calling the AutoConnectAux::menu() method? Below is the documentation (from https://hieromon.github.io/AutoConnect/apiaux.html#menu) and it states the menu item would "Show on the menu" or be "Hidden on the menu" depending on the method call parameter value. Is the documentation accurate?

**Set or reset the display as menu item for this AutoConnectAux. This function programmatically manipulates the menu parameter of the AutoConnectAux constructor.

Parameter true Show on the menu. false Hidden on the menu.**

Hieromon commented 1 year ago

https://hieromon.github.io/AutoConnect/apiaux.html#constructor

AutoConnectAux(const String& uri = String(""), const String& title = String(""), const bool menu = true, const AutoConnectElementVT addons = AutoConnectElementVT(), const bool responsive = true, const bool CORS = false)

menu: Specifies whether to display this page on menu.

https://hieromon.github.io/AutoConnect/apiaux.html#menu

Set or reset the display as menu item for this AutoConnectAux. This function programmatically manipulates the menu parameter of the AutoConnectAux constructor.

Set or reset the display as menu item for this AutoConnectAux.

How in the world can you read that as indicating an Update menu item? Can you clarify it?

Besides that, can you present your own code, which is the factor that opened this issue topic? Perhaps that code should show your understanding. I would like to know how you associate the Update menu item with the AutoConnectAux you supposedly declared. You didn't define AutoConnectAux with /_ac/update as the url on your own, did you? C++ class instances have nothing to do with class member variables.

gw8484 commented 1 year ago

I was going by the description of the parameter to the AutoConnectAux::menu() method:

true Show on the menu. false Hidden on the menu.

As mentioned in my first post, I used the AutoConnect::aux() method to obtain the AutoConnectAux object for the "Update" menu item. Here is the code snippet I was using to hide the menu item:

otaMenuItem = portal.aux(AUTOCONNECT_URI_UPDATE); otaMenuItem->menu(false);

I am just curious why it doesn't work. Thanks for your help.

Hieromon commented 1 year ago

You cannot use any of AutoConnect's public APIs to obtain instances of AutoConnect's built-in pages. They are protected from being accessed by user sketches.

More specifically, AutoConnectOTA is separated from the set of AutoConnectAuxes (which the AutoConnect class keeps in a list structure) that the user sketch attached. Thus, they are placed outside the search scope of AutoConnect::aux and AutoConnect::locate functions. This is an intentional specification to prevent built-in pages from being broken or thoughtlessly modified by user sketches.

You do not need to directly access to the embedded page instances generated internally by AutoConnect to control just the display of the Update menu item. It can be achieved by AutoConnect::enableMenu/disableMenu.

gw8484 commented 1 year ago

Thank you for the clarification about not obtaining instances of AC built-in pages. I didn't see such info in the API docs. I am currently using the following code to determine visibility of the "Update" menu item:

otaMenuItem = portal.aux(AUTOCONNECT_URI_UPDATE); visible=otaMenuItem->isMenu();

It's working very well but based on your clarification I would like to know if it's the proper way? If not, can you explain how to determine the visibility status of the "Update" menu item (and other built-in menu items)?

Hieromon commented 1 year ago

The details of the relationship between the AutoConnectAux and AutoConnectOTA classes are not documented. So you may be a little confused. The documentation states; AutoCoonectOTA is implemented using AutoConnectAux. But it does not mean that the AutoConnectOTA class inherits from the AutoConnectAux class.

The AutoConnectOTA class dynamically generates and contains an AutoConnectAux for the OTA UI page. Since the entity of this UI page is AutoConnectAux, it is detected by the AutoConnect::aux function. But it will pull out the only AutoConnectOTA UI page (i.e. AutoConnectAux), which is just a component. This is what I meant by comment that AutoConnectOTA is outside the search scope of AutoConnect::aux function.

And since the AutoConnect menu uses AutoConnectOTA's own functions to control the visibility of the AutoConnectOTA instance, the AutoConnectAux::menu() and AutoConnectAux::isMenu() contained in AutoConnectOTA have no effect. Its actual control is done by the _handleOTA function in AutoConnect::handleClient's internal logic.

https://github.com/Hieromon/AutoConnect/blob/81130776bb6fd7cf27db634bd90ae16a839f51d0/src/AutoConnectExtImpl.hpp#L264-L266

The AutoConnect::_ota in the above code is an AutoConnectOTA instance, not AutoConnectAux. AutoConnectOTA also has the menu function, but its input is copy of the AutoConnectConfig::menuItem value.

https://github.com/Hieromon/AutoConnect/blob/81130776bb6fd7cf27db634bd90ae16a839f51d0/src/AutoConnectOTA.h#L49

The AutoConnectOTA::_auxUpdate in the above code is the AutoConnectAux instance generated by AutoConnectOTA.

This means that the menu indicator for AutoConnectAux in AutoConnectOTA is overwritten in each handleClient loop. It then takes over from AutoConnectConfig.

Then, the AutoConnect::enableMenu and AutoConnect::disableMenu functions operate the AutoConnectConfig menu item switches given by the sketch.

https://github.com/Hieromon/AutoConnect/blob/81130776bb6fd7cf27db634bd90ae16a839f51d0/src/AutoConnectCore.hpp#L60-L61

Thus, the code to control the Update menu item according to the current AutoConnectOTA menu display state would look like this:

Get current Update menu item state

AutoConnect portal;

AutoConnectConfig& currentConfig = portal.getConfig();
bool menuUpdate = currentConfig.menuItems & AC_MENUITEM_UPDATE;

Enable/Disable the Update menu item

portal.enableMenu(AC_MENUITEM_UPDATE);

portal.disableMenu(AC_MENUITEM_UPDATE);
gw8484 commented 1 year ago

Thank you for the great explanation. I think if the AutoConnectAux API docs just stated not to use for built-in pages it would have prevented my confusion. Also, it would be nice if the AutoConnect API could add a menuState() method in the future to complement the enableMenu() and disableMenu() methods for built-in pages.

Thanks again for a nice library. Keep up the great work.