fix: update menubar content in real time while menu is open#426
fix: update menubar content in real time while menu is open#426jundot merged 2 commits intojundot:mainfrom
Conversation
Two root causes were fixed: 1. NSTimer was registered under NSDefaultRunLoopMode only, which is suspended while the status-bar menu is open (macOS enters NSEventTrackingRunLoopMode). Changed to NSRunLoopCommonModes so healthCheck_ fires even during menu interaction. 2. _build_menu() replaces the entire NSMenu object via setMenu_(), which would close a currently-visible menu. Instead, when the menu is open we now call _refresh_menu_in_place(), which mutates the existing NSMenuItem objects in place (status header attributed title, server control button visibility via setHidden_, Admin Panel / Chat enabled state). Additional changes: - Adopt NSMenuDelegate; menuWillOpen_ always refreshes items before the menu is shown, so reopening also reflects the latest state instantly. - menuDidClose_ clears the _menu_is_open flag so _build_menu() is used for full rebuilds (stats submenu, etc.) when the menu is closed. - Server control section now always adds all three items (Stop / Force Restart / Start) and uses setHidden_ to show the relevant one, enabling in-place toggling without menu replacement. Co-Authored-By: Claude Sonnet 4.6 <[email protected]>
jundot
left a comment
There was a problem hiding this comment.
Thanks for the PR! The approach is solid. Found a few issues though.
_fetch_stats() freezes the menu while open
NSRunLoopCommonModes makes healthCheck_ fire during menu tracking on the main thread. _fetch_stats() does sync HTTP with 2s timeout, up to 3 calls worst case. This blocks the main thread for 6-8s every 5s while the menu is open.
Fix: skip _fetch_stats() when self._menu_is_open is True.
STOPPING state: all buttons hidden
ServerStatus has 6 values including STOPPING, but none of the three visibility conditions cover it. No control button shows up during STOPPING. Add ServerStatus.STOPPING to the Stop button's visibility tuple.
Button order reversed for UNRESPONSIVE
Original shows Force Restart first (the more important action), then Stop. The PR flips this. Was this intentional?
Minor: icon template state
_build_menu() calls setTemplate_(True) to gray out Admin/Chat icons when stopped. _refresh_menu_in_place() only toggles setEnabled_() without updating template state, so icon color can get out of sync.
Four issues raised in jundot#426: 1. Skip _fetch_stats() when menu is open to avoid blocking the main thread. _fetch_stats() makes up to 3 synchronous HTTP requests with 2s timeouts each, which could stall the UI for ~6s during menu event tracking. Stats are fetched on the next healthCheck_ cycle after the menu closes. 2. Add ServerStatus.STOPPING to the Stop Server button visibility condition in both _build_menu() and _refresh_menu_in_place(). The button was hidden during the STOPPING transition, leaving no control visible to the user. 3. Restore original button order: Force Restart appears before Stop Server (Force Restart is the primary action when UNRESPONSIVE). The previous commit had them in the wrong order. 4. Sync icon template state in _refresh_menu_in_place() by calling setTemplate_(True) on the Admin Panel and Chat icons after updating their enabled state, keeping icon rendering consistent with _build_menu(). Co-Authored-By: Claude Sonnet 4.6 <[email protected]>
|
Thanks for the thorough review! All four issues have been addressed in the follow-up commit (339922b):
|
* fix: update menubar content in real time while menu is open Two root causes were fixed: 1. NSTimer was registered under NSDefaultRunLoopMode only, which is suspended while the status-bar menu is open (macOS enters NSEventTrackingRunLoopMode). Changed to NSRunLoopCommonModes so healthCheck_ fires even during menu interaction. 2. _build_menu() replaces the entire NSMenu object via setMenu_(), which would close a currently-visible menu. Instead, when the menu is open we now call _refresh_menu_in_place(), which mutates the existing NSMenuItem objects in place (status header attributed title, server control button visibility via setHidden_, Admin Panel / Chat enabled state). Additional changes: - Adopt NSMenuDelegate; menuWillOpen_ always refreshes items before the menu is shown, so reopening also reflects the latest state instantly. - menuDidClose_ clears the _menu_is_open flag so _build_menu() is used for full rebuilds (stats submenu, etc.) when the menu is closed. - Server control section now always adds all three items (Stop / Force Restart / Start) and uses setHidden_ to show the relevant one, enabling in-place toggling without menu replacement. Co-Authored-By: Claude Sonnet 4.6 <[email protected]> * fix: address review feedback on menubar real-time update PR Four issues raised in #426: 1. Skip _fetch_stats() when menu is open to avoid blocking the main thread. _fetch_stats() makes up to 3 synchronous HTTP requests with 2s timeouts each, which could stall the UI for ~6s during menu event tracking. Stats are fetched on the next healthCheck_ cycle after the menu closes. 2. Add ServerStatus.STOPPING to the Stop Server button visibility condition in both _build_menu() and _refresh_menu_in_place(). The button was hidden during the STOPPING transition, leaving no control visible to the user. 3. Restore original button order: Force Restart appears before Stop Server (Force Restart is the primary action when UNRESPONSIVE). The previous commit had them in the wrong order. 4. Sync icon template state in _refresh_menu_in_place() by calling setTemplate_(True) on the Admin Panel and Chat icons after updating their enabled state, keeping icon rendering consistent with _build_menu(). Co-Authored-By: Claude Sonnet 4.6 <[email protected]> --------- Co-authored-by: EmotionalAmo <[email protected]> Co-authored-by: Claude Sonnet 4.6 <[email protected]>
|
@EmotionalAmo v0.3.0rc1 is out with your menubar fix included. https://github.com/jundot/omlx/releases/tag/v0.3.0rc1 — if you get a chance, please give it a test and let me know if anything looks off. thanks! |
* fix: update menubar content in real time while menu is open Two root causes were fixed: 1. NSTimer was registered under NSDefaultRunLoopMode only, which is suspended while the status-bar menu is open (macOS enters NSEventTrackingRunLoopMode). Changed to NSRunLoopCommonModes so healthCheck_ fires even during menu interaction. 2. _build_menu() replaces the entire NSMenu object via setMenu_(), which would close a currently-visible menu. Instead, when the menu is open we now call _refresh_menu_in_place(), which mutates the existing NSMenuItem objects in place (status header attributed title, server control button visibility via setHidden_, Admin Panel / Chat enabled state). Additional changes: - Adopt NSMenuDelegate; menuWillOpen_ always refreshes items before the menu is shown, so reopening also reflects the latest state instantly. - menuDidClose_ clears the _menu_is_open flag so _build_menu() is used for full rebuilds (stats submenu, etc.) when the menu is closed. - Server control section now always adds all three items (Stop / Force Restart / Start) and uses setHidden_ to show the relevant one, enabling in-place toggling without menu replacement. Co-Authored-By: Claude Sonnet 4.6 <[email protected]> * fix: address review feedback on menubar real-time update PR Four issues raised in jundot#426: 1. Skip _fetch_stats() when menu is open to avoid blocking the main thread. _fetch_stats() makes up to 3 synchronous HTTP requests with 2s timeouts each, which could stall the UI for ~6s during menu event tracking. Stats are fetched on the next healthCheck_ cycle after the menu closes. 2. Add ServerStatus.STOPPING to the Stop Server button visibility condition in both _build_menu() and _refresh_menu_in_place(). The button was hidden during the STOPPING transition, leaving no control visible to the user. 3. Restore original button order: Force Restart appears before Stop Server (Force Restart is the primary action when UNRESPONSIVE). The previous commit had them in the wrong order. 4. Sync icon template state in _refresh_menu_in_place() by calling setTemplate_(True) on the Admin Panel and Chat icons after updating their enabled state, keeping icon rendering consistent with _build_menu(). Co-Authored-By: Claude Sonnet 4.6 <[email protected]> --------- Co-authored-by: EmotionalAmo <[email protected]> Co-authored-by: Claude Sonnet 4.6 <[email protected]>
Fixes #425
Problem
After clicking "Start Server", the menu bar content (server status text, Admin Panel / Chat button enabled state) never updates while the menu is open. The user must close and reopen the menu to see the latest state. Even if the menu stays open, the content is completely frozen.
Root Causes
1.
NSTimerregistered underNSDefaultRunLoopModeonly (app.py:136)When the status-bar menu is open, macOS enters
NSEventTrackingRunLoopMode.NSDefaultRunLoopModeis suspended during this time, sohealthCheck_never fires and the menu content freezes completely.2.
_build_menu()replaces the entireNSMenuobject (app.py:490, 730)Even if the timer fired, calling
self.status_item.setMenu_(newMenu)while a menu is being displayed would close it — causing disruptive flicker and not the desired in-place update.Fix
Two complementary changes in
packaging/omlx_app/app.py:1.
NSRunLoopCommonModesRegister the health-check timer under
NSRunLoopCommonModesinstead ofNSDefaultRunLoopModeso it fires in all run-loop modes, including during menu interaction.2. In-place menu item updates via
_refresh_menu_in_place()Instead of replacing the
NSMenuobject, store references to the keyNSMenuItemobjects and mutate them directly:setAttributedTitle_()with updated color/textsetHidden_()to toggle Start / Stop / Force Restart visibilitysetEnabled_()based on running state3.
NSMenuDelegate—menuWillOpen_/menuDidClose_menuWillOpen_: always refreshes menu content right before it appears, so even without the timer the menu is never stale on open.menuDidClose_: clears the_menu_is_openflag sohealthCheck_uses_build_menu()(full rebuild with stats) when the menu is closed.Test Steps
menuWillOpen_)