Skip to content

fix(v3): Dock ops sync and add GetBadge method - #4838

Merged
leaanthony merged 7 commits into
wailsapp:v3-alphafrom
popaprozac:fix/dock-sync-calls
Feb 9, 2026
Merged

leaanthony merged 7 commits into
wailsapp:v3-alphafrom
popaprozac:fix/dock-sync-calls

Conversation

@popaprozac

@popaprozac popaprozac commented Dec 29, 2025 •

Copy link
Copy Markdown
Contributor

Description

I found that I was seeing consistency issues dispatching dock tile calls async. Moved to sync calls and the intermittent issues were resolved. In SetBadge I included a check to ensure the dock tile is visible.

While working on this I found it is helpful to get back the currently set label. For example after restoring the dock tile you would want to re-add the previously set label. When you set the activation policy to hide the dock tile when it gets restored the dock tile is missing. You need to call RemoveBadge before/after switching policies to then set the badge again.

Type of change

Please select the option that is relevant.

  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to not work as expected)
  • This change requires a documentation update

How Has This Been Tested?

Please describe the tests that you ran to verify your changes. Provide instructions so we can reproduce. Please also list any relevant details for your test configuration using wails doctor.

  • Windows
  • macOS
  • Linux

If you checked Linux, please specify the distro and version.

Test Configuration

 Wails (v3.0.0-dev)  Wails Doctor

# System

┌──────────────────────────────────────────────────┐
| Name          | MacOS                            |
| Version       | 26.3                             |
| ID            | 25D5087f                         |
| Branding      | MacOS 26.3                       |
| Platform      | darwin                           |
| Architecture  | arm64                            |
| Apple Silicon | true                             |
| CPU           | Apple M4 Max                     |
| CPU 1         | Apple M4 Max                     |
| CPU 2         | Apple M4 Max                     |
| GPU           | 32 cores, Metal Support: Metal 4 |
| Memory        | 36 GB                            |
└──────────────────────────────────────────────────┘

# Build Environment

┌─────────────────────────────────────────────────────────┐
| Wails CLI    | v3.0.0-dev                               |
| Go Version   | go1.24.1                                 |
| Revision     | 3256041d8b0a3cd4559b37c83e06ced971049047 |
| Modified     | true                                     |
| -buildmode   | exe                                      |
| -compiler    | gc                                       |
| CGO_CFLAGS   |                                          |
| CGO_CPPFLAGS |                                          |
| CGO_CXXFLAGS |                                          |
| CGO_ENABLED  | 1                                        |
| CGO_LDFLAGS  |                                          |
| GOARCH       | arm64                                    |
| GOARM64      | v8.0                                     |
| GOOS         | darwin                                   |
| vcs          | git                                      |
| vcs.modified | true                                     |
| vcs.revision | 3256041d8b0a3cd4559b37c83e06ced971049047 |
| vcs.time     | 2025-12-29T02:52:26Z                     |
└─────────────────────────────────────────────────────────┘

# Dependencies

┌──────────────────────────────────────────────────────────────────────────────┐
| npm             | 10.9.2                                                     |
| *NSIS           | Not Installed. Install with `brew install makensis`.       |
| Xcode cli tools | 2416                                                       |
| docker          | *Docker version 28.5.1, build e180ab8 (daemon not running) |
|                                                                              |
└────────────────────────── * - Optional Dependency ───────────────────────────┘

# Checking for issues

 SUCCESS  No issues found

# Diagnosis

 SUCCESS  Your system is ready for Wails development!

Checklist:

  • I have updated website/src/pages/changelog.mdx with details of this PR
  • My code follows the general coding style of this project
  • I have performed a self-review of my own code
  • I have commented my code, particularly in hard-to-understand areas
  • I have made corresponding changes to the documentation
  • My changes generate no new warnings
  • I have added tests that prove my fix is effective or that my feature works
  • New and existing unit tests pass locally with my changes

Summary by CodeRabbit

  • New Features

    • Added a way to read the current app dock badge value across platforms.
  • Bug Fixes

    • Improved badge consistency and state tracking on macOS.
  • Documentation

    • Updated Dock service docs to document the new badge-read capability and cross-platform behavior.

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

@coderabbitai

coderabbitai Bot commented Dec 29, 2025 •

Copy link
Copy Markdown
Contributor

Walkthrough

Adds a public accessor GetBadge() *string to the Dock service and platform interface; macOS and Windows implementations now track and return badge state, while Linux and iOS implementations remain stubbed (nil). Documentation and changelog updated.

Changes

Cohort / File(s) Summary
Documentation & Changelog
docs/src/content/docs/features/platform/dock.mdx, v3/UNRELEASED_CHANGELOG.md
Documented and recorded the new GetBadge() method.
Public API & Interface
v3/pkg/services/dock/dock.go
Added GetBadge() *string to platformDock and DockService to delegate to platform implementations.
macOS Implementation
v3/pkg/services/dock/dock_darwin.go
Added mu sync.RWMutex and Badge *string to darwinDock; introduced setBadge, lifecycle hooks (Startup, Shutdown), NewWithOptions, and GetBadge() returning the current badge under read lock; badge set/remove now use setBadge.
Windows Implementation
v3/pkg/services/dock/dock_windows.go
Added Badge *string to windowsDock; constructors and badge methods updated to maintain state; added GetBadge() returning the stored badge.
Linux & iOS Stubs
v3/pkg/services/dock/dock_linux.go, v3/pkg/services/dock/badge_ios.go
Added GetBadge() stub implementations returning nil; iOS stub also normalizes SetCustomBadge to call SetBadge.

Sequence Diagram(s)

(omitted — change introduces a getter and platform-local state tracking; not a multi-component sequential flow)

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

  • [v3] macOS Dock Service #4451: Prior changes to the Dock service API and platform-specific badge implementations touching the same files and behavior.

Suggested labels

Enhancement, Documentation, v3, Windows, MacOS, Linux, v3-alpha, size:XXL, lgtm

Suggested reviewers

  • leaanthony

Poem

🐰 I hopped into the code today,
A tiny getter found its way.
macOS, Windows, Linux, iOS too,
A badge to peek — now that's brand new!
Hooray — a small change, big view ✨

Pre-merge checks and finishing touches

✅ Passed checks (3 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately summarizes both main changes: synchronizing dock operations and adding the GetBadge method.
Description check ✅ Passed The description covers the key changes, test configuration, and checklist items, though some non-critical sections are incomplete.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
✨ 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.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🧹 Nitpick comments (2)
v3/pkg/services/dock/badge_ios.go (1)

70-74: Consider returning d.Badge for consistency.

Once SetBadge/RemoveBadge maintain the Badge field, GetBadge should return d.Badge instead of nil to reflect the stored state, matching the pattern used in macOS and Windows implementations.

🔎 Suggested change
 func (d *iosDock) GetBadge() *string {
 	// iOS badge retrieval would go here via native bridge
-	return nil
+	return d.Badge
 }
v3/pkg/services/dock/dock_darwin.go (1)

86-95: Note: GetBadge returns "●" for empty labels.

SetBadge now converts empty labels to "●" (line 88) before storing in d.Badge. This means GetBadge() will return a pointer to "●" rather than "" when an empty label was set. While this matches the documented behavior, callers expecting to retrieve the original empty string will see "●" instead.

Consider whether storing the original label separately from the display label would better serve GetBadge consumers who may want to distinguish between an explicit "●" and an empty string.

📜 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 3256041 and 82eb40d.

📒 Files selected for processing (7)
  • docs/src/content/docs/features/platform/dock.mdx
  • v3/UNRELEASED_CHANGELOG.md
  • v3/pkg/services/dock/badge_ios.go
  • v3/pkg/services/dock/dock.go
  • v3/pkg/services/dock/dock_darwin.go
  • v3/pkg/services/dock/dock_linux.go
  • v3/pkg/services/dock/dock_windows.go
🧰 Additional context used
🧠 Learnings (2)
📚 Learning: 2025-03-24T20:22:56.233Z
Learnt from: popaprozac
Repo: wailsapp/wails PR: 4098
File: v3/pkg/services/notifications/notifications.go:46-55
Timestamp: 2025-03-24T20:22:56.233Z
Learning: In the notifications package, initialization of the `Service` struct is handled through platform-specific `New()` functions in each implementation file (darwin, windows, linux) rather than a generic constructor in the main package file.

Applied to files:

  • v3/pkg/services/dock/dock_darwin.go
  • v3/pkg/services/dock/badge_ios.go
📚 Learning: 2025-03-24T20:22:56.233Z
Learnt from: popaprozac
Repo: wailsapp/wails PR: 4098
File: v3/pkg/services/notifications/notifications.go:46-55
Timestamp: 2025-03-24T20:22:56.233Z
Learning: In the notifications package, initialization of the `Service` struct is handled through platform-specific `New()` functions in each implementation file (darwin, windows, linux) rather than a generic constructor in the main package file. Each platform implementation follows a singleton pattern using `notificationServiceOnce.Do()` and creates a global `NotificationService` variable that's accessed through a thread-safe `getNotificationService()` function.

Applied to files:

  • v3/pkg/services/dock/dock_darwin.go
  • v3/pkg/services/dock/badge_ios.go
🧬 Code graph analysis (3)
v3/pkg/services/dock/dock.go (3)
v3/examples/badge-custom/frontend/bindings/github.com/wailsapp/wails/v3/pkg/services/dock/index.ts (1)
  • DockService (6-6)
v3/examples/badge/frontend/bindings/github.com/wailsapp/wails/v3/pkg/services/dock/index.ts (1)
  • DockService (6-6)
v3/examples/dock/frontend/bindings/github.com/wailsapp/wails/v3/pkg/services/dock/index.ts (1)
  • DockService (6-6)
v3/pkg/services/dock/dock_darwin.go (4)
v3/pkg/services/dock/badge_ios.go (1)
  • New (18-24)
v3/pkg/services/dock/dock_linux.go (1)
  • New (16-20)
v3/pkg/services/dock/dock_windows.go (1)
  • New (39-45)
v3/pkg/services/dock/dock.go (1)
  • DockService (27-29)
v3/pkg/services/dock/badge_ios.go (5)
v3/pkg/services/dock/dock_darwin.go (1)
  • New (52-58)
v3/pkg/services/dock/dock_linux.go (1)
  • New (16-20)
v3/pkg/services/dock/dock_windows.go (1)
  • New (39-45)
v3/pkg/services/notifications/notifications_ios.go (1)
  • New (16-26)
v3/pkg/services/dock/dock.go (1)
  • DockService (27-29)
⏰ 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). (3)
  • GitHub Check: Run Go Tests v3 (macos-latest, 1.24)
  • GitHub Check: Run Go Tests v3 (ubuntu-latest, 1.24)
  • GitHub Check: Run Go Tests v3 (windows-latest, 1.24)
🔇 Additional comments (5)
v3/pkg/services/dock/dock_linux.go (1)

72-75: LGTM!

The no-op stub implementation is consistent with other Linux dock methods and appropriately documented.

v3/pkg/services/dock/dock.go (2)

23-23: LGTM!

The GetBadge method addition to the platformDock interface is clean and consistent with the existing interface design.


80-83: LGTM!

The GetBadge implementation follows the established delegation pattern used by other DockService methods.

v3/pkg/services/dock/dock_windows.go (1)

27-27: LGTM!

The badge state management is correctly implemented:

  • Field properly declared and initialized
  • State maintained in SetBadge, SetCustomBadge, and RemoveBadge
  • GetBadge provides clean accessor
  • All operations synchronized via application.InvokeSyncWithError

Also applies to: 52-52, 126-126, 188-188, 216-216, 403-405

v3/pkg/services/dock/dock_darwin.go (1)

22-28: Verify activation policy guard behavior with Badge field updates.

The C code now guards badge setting by checking the activation policy (line 24-28), returning early if not Regular. However, the Go code still updates d.Badge at line 94 regardless of whether the C code actually sets the badge.

This means GetBadge() might return a badge value that's not currently displayed on the dock. This could be intentional (to remember the badge for restoration when the policy changes back to Regular), but please verify this is the desired behavior.

Comment thread v3/pkg/services/dock/badge_ios.go
Comment thread v3/pkg/services/dock/dock_darwin.go

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 0

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
v3/pkg/services/dock/dock_darwin.go (1)

22-37: State inconsistency: policy guard silently fails but Go state is still updated.

The C setBadge function now includes a policy guard (lines 24-28) that silently returns when the dock icon is hidden. However, the Go SetBadge method (lines 95-98) unconditionally updates d.Badge regardless of whether the C function succeeded or returned early. This means GetBadge() can return a badge value that is not actually displayed on the dock.

Consider one of these approaches:

  1. Return an error from C and check it in Go before updating d.Badge
  2. Move the policy check to the Go layer before calling C
  3. Document that GetBadge() returns the "intended" badge, not necessarily the displayed one
🔎 Proposed fix: Move policy check to Go layer

This approach keeps state consistent by preventing the C call entirely when the policy check would fail:

 // SetBadge sets the badge label on the application icon.
 func (d *darwinDock) SetBadge(label string) error {
 	// Always pick a label (use "●" if empty), then allocate + free exactly once.
 	if label == "" {
 		label = "●" // Default badge character
 	}
+	
+	// Note: We cannot check activation policy from Go without CGO overhead,
+	// so we rely on the C function's policy guard. If the dock is hidden,
+	// we still update d.Badge to represent the "intended" badge state.
+	// Users must call SetBadge again after ShowAppIcon() to apply the badge.
+	
 	cLabel := C.CString(label)
 	defer C.free(unsafe.Pointer(cLabel))
 
 	C.setBadge(cLabel)
 	d.mu.Lock()
 	d.Badge = &label
 	d.mu.Unlock()
 	return nil
 }

Alternatively, document the behavior in the method comment to clarify that d.Badge stores the intended badge state.

🧹 Nitpick comments (1)
v3/pkg/services/dock/dock_darwin.go (1)

76-84: Consider documenting badge reapplication workflow.

The PR description mentions that workflows need to restore a badge after the dock tile is hidden and shown (e.g., when switching activation policies). Since ShowAppIcon() doesn't automatically reapply any stored badge, consider adding a comment to guide users:

 // ShowAppIcon shows the app icon in the macOS Dock.
+// Note: After showing the dock icon, you may need to call SetBadge again
+// to reapply any previously set badge, as changing activation policies clears the badge.
 func (d *darwinDock) ShowAppIcon() {
 	C.showDockIcon()
 }
📜 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 82eb40d and ae0e792.

📒 Files selected for processing (1)
  • v3/pkg/services/dock/dock_darwin.go
🧰 Additional context used
🧠 Learnings (2)
📚 Learning: 2025-03-24T20:22:56.233Z
Learnt from: popaprozac
Repo: wailsapp/wails PR: 4098
File: v3/pkg/services/notifications/notifications.go:46-55
Timestamp: 2025-03-24T20:22:56.233Z
Learning: In the notifications package, initialization of the `Service` struct is handled through platform-specific `New()` functions in each implementation file (darwin, windows, linux) rather than a generic constructor in the main package file. Each platform implementation follows a singleton pattern using `notificationServiceOnce.Do()` and creates a global `NotificationService` variable that's accessed through a thread-safe `getNotificationService()` function.

Applied to files:

  • v3/pkg/services/dock/dock_darwin.go
📚 Learning: 2025-03-24T20:22:56.233Z
Learnt from: popaprozac
Repo: wailsapp/wails PR: 4098
File: v3/pkg/services/notifications/notifications.go:46-55
Timestamp: 2025-03-24T20:22:56.233Z
Learning: In the notifications package, initialization of the `Service` struct is handled through platform-specific `New()` functions in each implementation file (darwin, windows, linux) rather than a generic constructor in the main package file.

Applied to files:

  • v3/pkg/services/dock/dock_darwin.go
🧬 Code graph analysis (1)
v3/pkg/services/dock/dock_darwin.go (4)
v3/pkg/services/dock/badge_ios.go (1)
  • New (18-24)
v3/pkg/services/dock/dock_linux.go (1)
  • New (16-20)
v3/pkg/services/dock/dock_windows.go (1)
  • New (39-45)
v3/pkg/services/dock/dock.go (1)
  • DockService (27-29)
⏰ 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). (3)
  • GitHub Check: Run Go Tests v3 (ubuntu-latest, 1.24)
  • GitHub Check: Run Go Tests v3 (windows-latest, 1.24)
  • GitHub Check: Run Go Tests v3 (macos-latest, 1.24)
🔇 Additional comments (5)
v3/pkg/services/dock/dock_darwin.go (5)

48-51: LGTM! Thread safety properly implemented.

The addition of sync.RWMutex and the Badge field addresses the data race issue identified in the previous review. Using a pointer to string (*string) correctly represents the optional badge state.


54-60: LGTM! Initialization is correct.

The initialization properly sets Badge: nil to represent no badge initially, consistent with the other platform implementations.


86-100: API behavior change: empty string now shows default badge.

The refactored logic now treats an empty string as a request to show the default badge "●" (lines 89-91), whereas previously an empty string might have cleared the badge. This is a subtle change in API behavior.

Please confirm this is the intended behavior. If so, consider documenting this in the method comment:

-// SetBadge sets the badge label on the application icon.
+// SetBadge sets the badge label on the application icon.
+// If label is empty, displays a default badge ("●"). Use RemoveBadge() to clear the badge.
 func (d *darwinDock) SetBadge(label string) error {

108-114: LGTM! RemoveBadge correctly clears both C and Go state.

The implementation properly clears the badge at both the C level and updates the Go state with appropriate mutex protection.


116-121: LGTM! GetBadge implementation is thread-safe.

The read lock usage is correct, allowing concurrent reads while preventing race conditions with SetBadge/RemoveBadge writes.

Note: Due to the policy guard behavior discussed earlier, this method may return a badge value that is not currently displayed if the dock icon was hidden when SetBadge was last called.

Comment thread v3/pkg/services/dock/dock_darwin.go Outdated

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 2

📜 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 ae0e792 and a2e30c8.

📒 Files selected for processing (2)
  • v3/pkg/services/dock/badge_ios.go
  • v3/pkg/services/dock/dock_darwin.go
🧰 Additional context used
🧠 Learnings (2)
📚 Learning: 2025-03-24T20:22:56.233Z
Learnt from: popaprozac
Repo: wailsapp/wails PR: 4098
File: v3/pkg/services/notifications/notifications.go:46-55
Timestamp: 2025-03-24T20:22:56.233Z
Learning: In the notifications package, initialization of the `Service` struct is handled through platform-specific `New()` functions in each implementation file (darwin, windows, linux) rather than a generic constructor in the main package file.

Applied to files:

  • v3/pkg/services/dock/dock_darwin.go
📚 Learning: 2025-03-24T20:22:56.233Z
Learnt from: popaprozac
Repo: wailsapp/wails PR: 4098
File: v3/pkg/services/notifications/notifications.go:46-55
Timestamp: 2025-03-24T20:22:56.233Z
Learning: In the notifications package, initialization of the `Service` struct is handled through platform-specific `New()` functions in each implementation file (darwin, windows, linux) rather than a generic constructor in the main package file. Each platform implementation follows a singleton pattern using `notificationServiceOnce.Do()` and creates a global `NotificationService` variable that's accessed through a thread-safe `getNotificationService()` function.

Applied to files:

  • v3/pkg/services/dock/dock_darwin.go
🧬 Code graph analysis (1)
v3/pkg/services/dock/dock_darwin.go (5)
v3/pkg/services/dock/badge_ios.go (1)
  • New (17-21)
v3/pkg/services/dock/dock_linux.go (1)
  • New (16-20)
v3/pkg/services/dock/dock_windows.go (1)
  • New (39-45)
v3/pkg/services/dock/dock.go (1)
  • DockService (27-29)
v3/examples/dock/frontend/bindings/github.com/wailsapp/wails/v3/pkg/services/dock/dockservice.ts (2)
  • ShowAppIcon (51-53)
  • SetBadge (36-38)
⏰ 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). (3)
  • GitHub Check: Run Go Tests v3 (macos-latest, 1.24)
  • GitHub Check: Run Go Tests v3 (windows-latest, 1.24)
  • GitHub Check: Run Go Tests v3 (ubuntu-latest, 1.24)
🔇 Additional comments (9)
v3/pkg/services/dock/badge_ios.go (1)

67-71: LGTM! GetBadge stub implementation is consistent with iOS platform pattern.

The stub returning nil appropriately indicates that badge state is not tracked on the Go side for iOS, pending native bridge implementation.

v3/pkg/services/dock/dock_darwin.go (8)

48-51: LGTM! Thread-safe state management properly implemented.

The sync.RWMutex and Badge *string field correctly address the data race concern from previous reviews. Using a pointer allows nil to represent the absence of a badge, and RWMutex is appropriate for potentially read-heavy access patterns.


54-66: LGTM! Constructor initialization is clear and consistent.

Explicit Badge: nil initialization makes the initial state obvious. NewWithOptions appropriately documents that badge options are not supported on macOS, consistent with the platform limitations noted in SetCustomBadge.


68-74: Lifecycle methods appropriately implement the platform interface.

No initialization or cleanup is required for macOS dock operations, so returning nil is correct.


82-86: Helpful documentation about badge persistence behavior.

The comment correctly explains that changing activation policies clears the badge, documenting the manual restore workflow that motivated adding GetBadge() (save badge → hide → show → restore badge).


88-101: LGTM! Helper method properly addresses maintainer feedback.

This private setBadge method successfully extracts the common pattern for badge updates (C string conversion, locking, state update) as requested in previous review comments. Memory management with defer C.free is correct.


113-116: LGTM! Appropriate fallback for platform limitations.

Delegating to SetBadge and ignoring the options parameter is the correct approach since macOS doesn't support custom badge styling. The comment clearly documents this limitation.


118-122: LGTM! Clean implementation leveraging the helper method.

Passing nil to setBadge appropriately represents badge removal, and the delegation simplifies the code.


124-129: LGTM! Thread-safe read access properly implemented.

Using RLock/RUnlock allows concurrent reads while maintaining safety, and returning the pointer directly enables the save/restore workflow described in the PR objectives.

Comment thread v3/pkg/services/dock/dock_darwin.go
Comment thread v3/pkg/services/dock/dock_darwin.go Outdated

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

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 (1)
v3/pkg/services/dock/dock_darwin.go (1)

117-123: LGTM! SetBadge correctly implements documented default behavior.

The empty string defaulting to "●" is clearly documented in the godoc comment above. The implementation correctly normalizes the input and delegates to the setBadge helper.

Optional: The inline comment on line 118 mentions "allocate + free exactly once," but that detail is handled inside setBadge. Consider simplifying to just // Use default badge "●" if empty for clarity.

📜 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 a2e30c8 and 7135be4.

📒 Files selected for processing (1)
  • v3/pkg/services/dock/dock_darwin.go
🧰 Additional context used
🧠 Learnings (2)
📚 Learning: 2025-02-24T06:08:55.645Z
Learnt from: popaprozac
Repo: wailsapp/wails PR: 4098
File: v3/pkg/services/notifications/notifications_windows.go:91-113
Timestamp: 2025-02-24T06:08:55.645Z
Learning: The JSON quote handling in Windows notifications' activation arguments (v3/pkg/services/notifications/notifications_windows.go) has a known limitation with single-quote collisions that needs to be addressed after initial testing.

Applied to files:

  • v3/pkg/services/dock/dock_darwin.go
📚 Learning: 2025-03-24T20:22:56.233Z
Learnt from: popaprozac
Repo: wailsapp/wails PR: 4098
File: v3/pkg/services/notifications/notifications.go:46-55
Timestamp: 2025-03-24T20:22:56.233Z
Learning: In the notifications package, initialization of the `Service` struct is handled through platform-specific `New()` functions in each implementation file (darwin, windows, linux) rather than a generic constructor in the main package file. Each platform implementation follows a singleton pattern using `notificationServiceOnce.Do()` and creates a global `NotificationService` variable that's accessed through a thread-safe `getNotificationService()` function.

Applied to files:

  • v3/pkg/services/dock/dock_darwin.go
🧬 Code graph analysis (1)
v3/pkg/services/dock/dock_darwin.go (4)
v3/pkg/services/dock/badge_ios.go (1)
  • New (17-21)
v3/pkg/services/dock/dock_linux.go (1)
  • New (16-20)
v3/pkg/services/dock/dock_windows.go (1)
  • New (39-45)
v3/pkg/services/dock/dock.go (1)
  • DockService (27-29)
⏰ 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). (3)
  • GitHub Check: Run Go Tests v3 (ubuntu-latest, 1.24)
  • GitHub Check: Run Go Tests v3 (windows-latest, 1.24)
  • GitHub Check: Run Go Tests v3 (macos-latest, 1.24)
🔇 Additional comments (8)
v3/pkg/services/dock/dock_darwin.go (8)

11-11: LGTM! Synchronous dispatch correctly addresses consistency issues.

The change from dispatch_async to dispatch_sync ensures operations complete before returning to the Go caller, which aligns with the PR's goal of addressing intermittent consistency issues. The activation policy check in setBadge correctly prevents badge operations when the dock icon is hidden, and the __block bool pattern properly returns success/failure status.

Also applies to: 17-17, 22-41


46-47: LGTM! Imports are necessary for synchronization and error handling.


53-56: LGTM! Mutex correctly protects badge state from concurrent access.

The sync.RWMutex and Badge field provide thread-safe state management, which is essential given that EventProcessor can dispatch event handlers concurrently.


59-65: LGTM! Constructor properly initializes the dock service.

Note: Badge: nil is technically redundant since nil is the zero value for *string, but the explicit initialization improves clarity.


87-88: LGTM! Helpful documentation about badge reapplication.

This comment clearly explains the need to reapply badges after activation policy changes, which directly supports the workflow described in the PR objectives.


93-111: LGTM! Well-designed helper that centralizes badge logic.

The setBadge helper correctly:

  • Manages C string memory with defer
  • Only updates internal Badge state when the C call succeeds
  • Protects state mutation with the mutex
  • Provides a single point of control for badge operations

This addresses the maintainer's suggestion to extract a private method for the badge-setting pattern.


131-133: LGTM! RemoveBadge cleanly delegates to the shared helper.

Reusing setBadge(nil) eliminates code duplication and ensures consistent error handling and locking across all badge operations.


135-140: LGTM! GetBadge provides thread-safe access to badge state.

The read lock correctly allows concurrent reads while preventing race conditions with writes. Returning *string properly represents the optional nature of the badge value (nil when no badge is set).

This addition supports the badge restoration workflow described in the PR objectives.

@sonarqubecloud

sonarqubecloud Bot commented Jan 5, 2026

Copy link
Copy Markdown

@leaanthony
leaanthony merged commit 1a5c6dc into wailsapp:v3-alpha Feb 9, 2026
65 checks passed
@leaanthony

Copy link
Copy Markdown
Member

Amazing stuff! 🙏

Grantmartin2002 pushed a commit to Grantmartin2002/wails that referenced this pull request Apr 29, 2026
* dock fixes and get method

* update changelog

* async -> sync

* cleanup iOS and darwin set call

* handle potential errors
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: Done

Development

Successfully merging this pull request may close these issues.

2 participants