Skip to content

Conversation

@leaanthony
Copy link
Member

@leaanthony leaanthony commented Dec 22, 2025

Summary

Implements NSMenuDelegate to enable real-time menu updates while the system tray menu is open on macOS. Previously, menu.Update() calls would not refresh the displayed menu until it was closed and reopened.

Also implements onMenuOpen and onMenuClose callbacks for macOS, bringing it to parity with Windows and Linux.

Changes

  • Added MenuDelegate class implementing NSMenuDelegate protocol
  • Implemented menuNeedsUpdate:, menuWillOpen:, and menuDidClose: delegate methods
  • Added nsMenuDelegate field to macosSystemTray struct
  • Updated setMenu() to create and attach delegate to NSMenu
  • Updated run() to set up delegate during initialization
  • Added Go callback exports systrayMenuOpenCallback and systrayMenuCloseCallback

How it works

  1. MenuDelegate is attached to the NSMenu when menu is set
  2. When menu.Update() is called, NSMenu is rebuilt in-place
  3. macOS calls menuNeedsUpdate: before display and periodically
  4. menuWillOpen: triggers onMenuOpen callback
  5. menuDidClose: triggers onMenuClose callback

Platform parity

Feature macOS Linux Windows
Real-time menu updates ✅ Now supported ✅ DBus signals ✅ Win32 APIs
onMenuOpen callback ✅ Now supported
onMenuClose callback ✅ Now supported

Fixes #4719

🤖 Generated with Claude Code

Summary by CodeRabbit

  • New Features

    • Added system tray menu open/close callbacks on macOS for feature parity with Windows and Linux.
  • Bug Fixes

    • Fixed macOS system tray menu to support real-time item updates while the menu is open.
    • Fixed window position inconsistency on macOS when saving and restoring application state.

✏️ Tip: You can customize this high-level summary in your review settings.

Implements NSMenuDelegate to enable real-time menu updates while the
system tray menu is open on macOS. Previously, menu.Update() calls
would not refresh the displayed menu until it was closed and reopened.

Changes:
- Added MenuDelegate class implementing NSMenuDelegate protocol
- Implemented menuNeedsUpdate: and menuWillOpen: delegate methods
- Added nsMenuDelegate field to macosSystemTray struct
- Updated setMenu() to create and attach delegate to NSMenu
- Updated run() to set up delegate during initialization

Fixes #4630

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
@coderabbitai
Copy link
Contributor

coderabbitai bot commented Dec 22, 2025

Walkthrough

Adds a macOS NSMenuDelegate implementation and wires it to the Go system tray so menus receive lifecycle callbacks for real-time in-place updates; introduces delegate creation/attachment C functions and Go-side delegate pointer and callbacks for onMenuOpen/onMenuClose.

Changes

Cohort / File(s) Change Summary
Changelog
v3/UNRELEASED_CHANGELOG.md
Added entries documenting macOS systray real-time menu update fix and new onMenuOpen/onMenuClose parity.
Go: system tray integration
v3/pkg/application/systemtray_darwin.go
Added nsMenuDelegate unsafe.Pointer to macosSystemTray; setMenu now initializes/assigns delegate on main thread; run() attaches delegate and registers exported C callbacks for menu open/close.
Go: macOS menu logic
v3/pkg/application/menu_darwin.go
Implemented in-place menu updates (updateMenuInPlace) to preserve native item IDs and support real-time updates while menu is open.
Objective‑C header
v3/pkg/application/systemtray_darwin.h
Added MenuDelegate @interface conforming to NSMenuDelegate and declarations for createMenuDelegate(void*, long) and setMenuDelegate(void*, void*).
Objective‑C implementation
v3/pkg/application/systemtray_darwin.m
Implemented MenuDelegate with menuNeedsUpdate:, menuWillOpen:, menuDidClose:; added createMenuDelegate and setMenuDelegate functions; calls out duplicate declarations present.
Example: realtime systray
v3/examples/systray-realtime-update/* (README.md, go.mod, main.go)
New example demonstrating in-place, real-time menu updates, timestamp ticker, checkbox-driven status item, and open/close callbacks.

Sequence Diagram

sequenceDiagram
    participant Go as Go code
    participant Tray as macosSystemTray
    participant ObjC as MenuDelegate (Obj‑C)
    participant NSMenu as NSMenu (Cocoa)

    Note over Go,Tray: Initialization
    Go->>Tray: run() create NSStatusItem & NSMenu
    Tray->>ObjC: createMenuDelegate(menuPtr, trayID)
    ObjC-->>Tray: delegate pointer
    Tray->>NSMenu: setMenuDelegate(nsMenu, delegate)

    Note over NSMenu,ObjC: User opens menu
    NSMenu->>ObjC: menuWillOpen:(menu)
    ObjC->>Go: systrayMenuOpenCallback(trayID)
    Go->>Tray: onMenuOpen handler

    Note over NSMenu,ObjC: While open - updates
    Go->>Tray: setMenu/updateMenuInPlace() (main thread)
    Tray->>NSMenu: update items (preserve IDs)
    NSMenu->>ObjC: menuNeedsUpdate:(menu)
    ObjC->>Go: trigger update callback

    Note over NSMenu,ObjC: Menu closed
    NSMenu->>ObjC: menuDidClose:(menu)
    ObjC->>Go: systrayMenuCloseCallback(trayID)
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs

Suggested labels

MacOS, Bug, v3-alpha, Documentation, size:S

Poem

"I’m a rabbit in the Cocoa glade,
I hop where NSMenu callbacks are made.
With delegates set and IDs kept true,
menu clicks survive my hopping too.
Hooray — real‑time updates for you!" 🐇✨

🚥 Pre-merge checks | ✅ 2 | ❌ 3
❌ Failed checks (1 warning, 2 inconclusive)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 75.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
Description check ❓ Inconclusive The PR description provides a comprehensive summary of changes, implementation details, and platform parity comparison, but lacks issue reference format and testing checklist completion required by the template. Add 'Fixes #4719' at the top of the Description section and complete the testing checklist (select at least one platform and provide wails doctor output).
Linked Issues check ❓ Inconclusive The PR implements NSMenuDelegate with onMenuOpen/onMenuClose callbacks and in-place menu updates, directly addressing issue #4719's requirement for real-time menu updates without breaking click handlers. Verify that the reported 'MenuItem not found' warning and SetMenu ineffectiveness issues are fully resolved through testing, as comments indicate these issues may persist.
✅ Passed checks (2 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly summarizes the main objective: implementing NSMenuDelegate for real-time macOS system tray menu updates, which is the primary focus of the changeset.
Out of Scope Changes check ✅ Passed All code changes directly relate to implementing real-time macOS system tray menu updates and callbacks specified in issue #4719, plus a new example demonstrating the feature.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing touches
  • 📝 Generate docstrings

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (2)
v3/pkg/application/systemtray_darwin.go (1)

114-118: Delegate's menuPtr may become stale on subsequent menu changes.

The delegate is created once (when nsMenuDelegate == nil) with the current s.nsMenu pointer. If setMenu is called again with a different menu, the delegate retains the old menuPtr reference. While the current delegate implementation doesn't use menuPtr, this could cause issues if future changes rely on it.

Consider updating menuPtr on every call or documenting this limitation:

🔎 Suggested fix
 		// Set up the delegate if not already done
 		if s.nsMenuDelegate == nil {
 			s.nsMenuDelegate = C.createMenuDelegate(s.nsMenu, C.long(s.id))
+		} else {
+			// Update the delegate's menuPtr if menu changed
+			C.updateMenuDelegatePtr(s.nsMenuDelegate, s.nsMenu)
 		}
 		C.setMenuDelegate(s.nsMenu, s.nsMenuDelegate)

This would require adding an updateMenuDelegatePtr function in the Objective-C layer.

v3/pkg/application/systemtray_darwin.m (1)

262-267: Consider delegate lifecycle management.

The MenuDelegate is allocated with [[MenuDelegate alloc] init] but there's no corresponding release when the system tray is destroyed. While the delegate likely lives for the application lifetime, if system trays can be dynamically created/destroyed, this could leak memory.

If needed, store the delegate reference and release it in systemTrayDestroy:

// In systemTrayDestroy, if delegate is tracked:
// [delegate release];
📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 0271c9e and 0742b75.

📒 Files selected for processing (4)
  • v3/UNRELEASED_CHANGELOG.md
  • v3/pkg/application/systemtray_darwin.go
  • v3/pkg/application/systemtray_darwin.h
  • v3/pkg/application/systemtray_darwin.m
🧰 Additional context used
🧠 Learnings (1)
📚 Learning: 2025-01-24T22:41:18.566Z
Learnt from: leaanthony
Repo: wailsapp/wails PR: 4031
File: v3/pkg/application/menu.go:199-202
Timestamp: 2025-01-24T22:41:18.566Z
Learning: In the Wails menu system (v3/pkg/application/menu.go), shared state between menus is intentionally designed and desirable. Methods like `Append()` and `Prepend()` should maintain shared references to menu items rather than creating deep copies.

Applied to files:

  • v3/pkg/application/systemtray_darwin.go
🪛 LanguageTool
v3/UNRELEASED_CHANGELOG.md

[style] ~26-~26: This phrase is redundant (‘OS’ stands for ‘operating system’). Use simply “macOS”.
Context: ... --> ## Fixed - Fix macOS system tray menu real-time updates using NSMen...

(ACRONYM_TAUTOLOGY)

⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (5)
  • GitHub Check: Run Go Tests v3 (ubuntu-latest, 1.24)
  • GitHub Check: Run Go Tests v3 (windows-latest, 1.24)
  • GitHub Check: semgrep-cloud-platform/scan
  • GitHub Check: Analyze (go)
  • GitHub Check: Cloudflare Pages
🔇 Additional comments (7)
v3/UNRELEASED_CHANGELOG.md (1)

26-26: LGTM!

The changelog entry clearly describes the fix and references the correct issue number. Note: The static analysis warning about "macOS" is a false positive—"macOS" is Apple's official branding and is correct here.

v3/pkg/application/systemtray_darwin.go (2)

48-48: LGTM!

The new nsMenuDelegate field appropriately holds the Objective-C delegate reference using unsafe.Pointer for CGo interop.


188-190: LGTM!

The delegate setup during initial run() is correctly placed after menu.Update() ensures the nsMenu pointer is valid.

v3/pkg/application/systemtray_darwin.h (2)

10-13: LGTM!

The MenuDelegate interface declaration correctly adopts NSMenuDelegate protocol with appropriate properties for CGo interop.


30-31: LGTM!

Function declarations are well-defined and match the implementation signatures.

v3/pkg/application/systemtray_darwin.m (2)

19-32: Clarify the real-time update mechanism.

Both delegate methods are effectively no-ops. The comment says "The Go side will handle the actual menu rebuilding through menu.Update()" but there's no callback to Go from these methods.

Could you clarify: does simply having a delegate attached cause macOS to refresh the menu display when the underlying NSMenu items change? If the intent is for menuNeedsUpdate: to trigger Go-side updates, a callback would be needed.


270-274: LGTM!

The setMenuDelegate function correctly casts and assigns the delegate to the NSMenu.

@cloudflare-workers-and-pages
Copy link

cloudflare-workers-and-pages bot commented Dec 22, 2025

Deploying wails with  Cloudflare Pages  Cloudflare Pages

Latest commit: 0cd2bef
Status: ✅  Deploy successful!
Preview URL: https://d3ae43ca.wails.pages.dev
Branch Preview URL: https://fix-systemtray-menu-realtime.wails.pages.dev

View logs

Adds NSMenuDelegate methods menuWillOpen: and menuDidClose: to call the
existing onMenuOpen and onMenuClose callbacks on SystemTray, bringing
macOS to parity with Windows and Linux implementations.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
@johnmaguire
Copy link

In #4719, I reported two behaviors:

  1. When updating the menu, clicking a menu item from the prior render does not work. This behavior persists when using this branch:
Scheduling update in 5 seconds
Update scheduled
5:06PM INF Binding call complete: id=Mu9FLGqqYsU4r1kNshHHI method=main.UpdateService.Update args=[5] result=""
Updating menu...
5:06PM WRN MenuItem #1 not found
5:06PM INF Menu 1 clicked!
  1. When using SetMenu to replace the menu entirely previously I observed that nothing happened. This behavior persists.
leaanthony and others added 2 commits January 25, 2026 13:10
Previously, updating a systray menu while it was open would break click
handlers because Menu.Update() destroyed and recreated all menu items
with new IDs. The visible menu still referenced old IDs, causing
"MenuItem #X not found" errors when clicked.

This fix modifies macosMenu.update() to update existing menu items
in-place using the existing C setter functions (setMenuItemLabel,
setMenuItemDisabled, etc.) instead of clearing and rebuilding the
entire menu. This preserves the menuItemID baked into each NSMenuItem.

Fixes #4719

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🤖 Fix all issues with AI agents
In `@v3/pkg/application/systemtray_darwin.m`:
- Around line 268-279: The MenuDelegate allocated in createMenuDelegate is never
released; add a new C function (e.g., releaseMenuDelegate(void* delegate)) that
calls [(MenuDelegate *)delegate release] (or CFBridgingRelease equivalent) to
free the object, update setMenuDelegate usage to expect that delegates are
managed externally, and call this releaseMenuDelegate from the Go destroy() path
and from the setMenu(nil) branch where menus are cleared so the retained
MenuDelegate instances are properly freed.

In `@v3/UNRELEASED_CHANGELOG.md`:
- Line 26: The changelog entry "Fix macOS system tray menu real-time updates
using NSMenuDelegate" references the wrong issue number (`#4630`); verify the PR
description and, if it indeed fixes issue `#4719`, update that changelog line to
reference `#4719` instead of `#4630` and ensure any related cross-references in the
same changelog are consistent.
🧹 Nitpick comments (1)
v3/pkg/application/menu_darwin.go (1)

93-120: In-place update doesn't handle menu structure changes.

The implementation correctly updates existing item properties, but items added after initial menu creation (where item.impl == nil) are silently skipped. This limitation is documented in the comment, but it could lead to confusion if users expect dynamically added items to appear.

Additionally, separator items don't have an impl set (they're added directly via C.addMenuSeparator), so any separator-related changes would also be skipped.

Consider documenting this limitation in the public API or logging a warning when items are skipped.

Comment on lines +268 to +279
void* createMenuDelegate(void* menuPtr, long trayID) {
MenuDelegate *delegate = [[MenuDelegate alloc] init];
delegate.menuPtr = menuPtr;
delegate.trayID = trayID;
return (void*)delegate;
}

// Set the delegate on a menu
void setMenuDelegate(void* nsMenu, void* delegate) {
NSMenu *menu = (NSMenu *)nsMenu;
MenuDelegate *menuDelegate = (MenuDelegate *)delegate;
[menu setDelegate:menuDelegate];
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

cd v3 && git ls-files | grep -E "(systemtray|tray)" | head -20

Repository: wailsapp/wails

Length of output: 778


🏁 Script executed:

wc -l v3/pkg/application/systemtray_darwin.m

Repository: wailsapp/wails

Length of output: 100


🏁 Script executed:

cat -n v3/pkg/application/systemtray_darwin.m | sed -n '260,290p'

Repository: wailsapp/wails

Length of output: 839


🏁 Script executed:

# Search for all uses of createMenuDelegate, setMenuDelegate, MenuDelegate
rg -n 'createMenuDelegate|setMenuDelegate|MenuDelegate|destroyMenuDelegate' v3/pkg/application/

Repository: wailsapp/wails

Length of output: 1441


🏁 Script executed:

# Check if there's a Go file that calls these functions
fd '\.go$' v3/pkg/application/ | head -20

Repository: wailsapp/wails

Length of output: 864


🏁 Script executed:

cat -n v3/pkg/application/systemtray_darwin.go | sed -n '45,55p'

Repository: wailsapp/wails

Length of output: 429


🏁 Script executed:

cat -n v3/pkg/application/systemtray_darwin.go | sed -n '130,220p'

Repository: wailsapp/wails

Length of output: 3354


🏁 Script executed:

# Check if there's any cleanup or Close method
rg -n 'Close|Cleanup|dealloc|release' v3/pkg/application/systemtray_darwin.go

Repository: wailsapp/wails

Length of output: 227


🏁 Script executed:

# Check the full struct and any methods
ast-grep --pattern 'type $_ struct {
  $$$
  nsMenuDelegate $_
  $$$
}'

Repository: wailsapp/wails

Length of output: 1045


🏁 Script executed:

# Check if delegate is ever reassigned
cat -n v3/pkg/application/systemtray_darwin.go | grep -A 5 -B 5 'nsMenuDelegate'

Repository: wailsapp/wails

Length of output: 1390


🏁 Script executed:

# Search for Close, Hide, Stop, or cleanup methods for macosSystemTray
rg -n 'func.*macosSystemTray.*\)' v3/pkg/application/systemtray_darwin.go | head -30

Repository: wailsapp/wails

Length of output: 919


🏁 Script executed:

# Check the full file for any cleanup/deallocation
cat -n v3/pkg/application/systemtray_darwin.go | tail -100

Repository: wailsapp/wails

Length of output: 3325


🏁 Script executed:

# Check if there's a SystemTray interface that defines required methods
rg -n 'type SystemTray' v3/pkg/application/system_tray_manager.go

Repository: wailsapp/wails

Length of output: 91


🏁 Script executed:

# Look for Close/Hide/Stop method on macosSystemTray
rg -A 10 'func \(s \*macosSystemTray\) (Close|Hide|Stop|destroy)' v3/pkg/application/systemtray_darwin.go

Repository: wailsapp/wails

Length of output: 575


🏁 Script executed:

# Check systemTrayDestroy implementation in the .m file
rg -A 20 'void systemTrayDestroy' v3/pkg/application/systemtray_darwin.m

Repository: wailsapp/wails

Length of output: 1095


🏁 Script executed:

# Check if there are any other NSMenu delegate patterns in the codebase
rg -n 'setDelegate' v3/pkg/application/

Repository: wailsapp/wails

Length of output: 554


🏁 Script executed:

# Check MenuDelegate dealloc or other cleanup
rg -B 5 -A 15 '@implementation MenuDelegate' v3/pkg/application/systemtray_darwin.m

Repository: wailsapp/wails

Length of output: 561


🏁 Script executed:

# Check if MenuDelegate has a dealloc method
rg -A 10 'dealloc' v3/pkg/application/systemtray_darwin.m

Repository: wailsapp/wails

Length of output: 40


🏁 Script executed:

# Look at the complete systemtray_darwin.m to see full MenuDelegate
cat -n v3/pkg/application/systemtray_darwin.m | sed -n '1,40p'

Repository: wailsapp/wails

Length of output: 1308


🏁 Script executed:

# Check if there's any reference counting or memory management in the header
cat -n v3/pkg/application/systemtray_darwin.h

Repository: wailsapp/wails

Length of output: 1567


🏁 Script executed:

# Check if there are multiple delegate creations and assignments in run()
cat -n v3/pkg/application/systemtray_darwin.go | sed -n '192,215p'

Repository: wailsapp/wails

Length of output: 1028


🏁 Script executed:

# Verify: Does NSMenu retain delegate in Cocoa documentation context?
# Check how other delegates are managed in the codebase
rg -B 5 -A 5 'appDelegate|windowDelegate' v3/pkg/application/systemtray_darwin.go

Repository: wailsapp/wails

Length of output: 40


🏁 Script executed:

# Look at application_darwin.go to see how appDelegate is managed
rg -B 3 -A 10 'appDelegate.*release' v3/pkg/application/application_darwin.go

Repository: wailsapp/wails

Length of output: 312


🏁 Script executed:

# Check if setMenu is called after initial run
rg -n 'setMenu' v3/pkg/application/systemtray_darwin.go

Repository: wailsapp/wails

Length of output: 214


🏁 Script executed:

# Verify the flow: does setMenu get called multiple times or only once per tray?
cat -n v3/pkg/application/systemtray_darwin.go | sed -n '123,142p'

Repository: wailsapp/wails

Length of output: 697


🏁 Script executed:

# Final check: Confirm NSMenu delegate is weak reference by checking if any release happens
rg -n 'MenuDelegate.*release|release.*MenuDelegate' v3/pkg/application/

Repository: wailsapp/wails

Length of output: 40


🏁 Script executed:

# Also check if there's any autorelease or cleanup in setMenu for old delegates
cat -n v3/pkg/application/systemtray_darwin.go | sed -n '206,215p'

Repository: wailsapp/wails

Length of output: 433


Add memory cleanup for MenuDelegate to prevent leaks.

createMenuDelegate allocates a retained MenuDelegate object, but destroy() and setMenu(nil) never release it. NSMenu holds only a weak reference to its delegate, so the Go-side code is responsible for cleanup. Add a release function and call it in the destroy path and when menus are cleared.

Suggested implementation
+// Release a menu delegate
+void destroyMenuDelegate(void* delegate) {
+    if (delegate != NULL) {
+        MenuDelegate *menuDelegate = (MenuDelegate *)delegate;
+        [menuDelegate release];
+    }
+}

Then in systemtray_darwin.go destroy():

 func (s *macosSystemTray) destroy() {
+	if s.nsMenuDelegate != nil {
+		C.destroyMenuDelegate(s.nsMenuDelegate)
+		s.nsMenuDelegate = nil
+	}
     C.systemTrayDestroy(s.nsStatusItem)
 }

And in setMenu() when clearing:

 func (s *macosSystemTray) setMenu(menu *Menu) {
     s.menu = menu
     if menu == nil {
+        if s.nsMenuDelegate != nil {
+            C.destroyMenuDelegate(s.nsMenuDelegate)
+            s.nsMenuDelegate = nil
+        }
         s.nsMenu = nil
         return
     }
🤖 Prompt for AI Agents
In `@v3/pkg/application/systemtray_darwin.m` around lines 268 - 279, The
MenuDelegate allocated in createMenuDelegate is never released; add a new C
function (e.g., releaseMenuDelegate(void* delegate)) that calls [(MenuDelegate
*)delegate release] (or CFBridgingRelease equivalent) to free the object, update
setMenuDelegate usage to expect that delegates are managed externally, and call
this releaseMenuDelegate from the Go destroy() path and from the setMenu(nil)
branch where menus are cleared so the retained MenuDelegate instances are
properly freed.

## Fixed
<!-- Bug fixes -->
- Fix macOS system tray menu real-time updates using NSMenuDelegate (#4630)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Incorrect issue number referenced.

The changelog references #4630, but the PR description states this fixes issue #4719. Please verify and correct the issue number.

Proposed fix (if `#4719` is correct)
-- Fix macOS system tray menu real-time updates using NSMenuDelegate (`#4630`)
+- Fix macOS system tray menu real-time updates using NSMenuDelegate (`#4719`)
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
- Fix macOS system tray menu real-time updates using NSMenuDelegate (#4630)
- Fix macOS system tray menu real-time updates using NSMenuDelegate (`#4719`)
🧰 Tools
🪛 LanguageTool

[style] ~26-~26: This phrase is redundant (‘OS’ stands for ‘operating system’). Use simply “macOS”.
Context: ... --> ## Fixed - Fix macOS system tray menu real-time updates using NSMen...

(ACRONYM_TAUTOLOGY)

🤖 Prompt for AI Agents
In `@v3/UNRELEASED_CHANGELOG.md` at line 26, The changelog entry "Fix macOS system
tray menu real-time updates using NSMenuDelegate" references the wrong issue
number (`#4630`); verify the PR description and, if it indeed fixes issue `#4719`,
update that changelog line to reference `#4719` instead of `#4630` and ensure any
related cross-references in the same changelog are consistent.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

3 participants