Skip to content

Conversation

@popaprozac
Copy link

@popaprozac popaprozac commented Dec 30, 2025

Description

Looking back at the implementation, especially for requesting macOS notification authorization it was done in a blocking way which doesn't make sense. We should register a callback so the user can authorize/deny the request async.

Updated the service name for imports.

Will be updating notifications docs and examples asap. I should probably update this in the v2 PR too 😅

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

Please paste the output of wails doctor. If you are unable to run this command, please describe your environment in as much detail as possible.

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

  • Refactor
    • Notification authorization methods now use asynchronous callback-based patterns instead of synchronous return values across platforms.
  • Documentation
    • Notification docs updated to show callback usage and platform-specific behavior (Windows/Linux invoke callbacks immediately; macOS uses async flow).
  • Changelog
    • Noted change: authorization methods updated to callbacks for macOS.

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

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Dec 30, 2025

Walkthrough

Notification authorization methods were changed from synchronous return values to asynchronous callback-based signatures across the NotificationService and all platform implementations; the service identifier path was updated to the new package location.

Changes

Cohort / File(s) Summary
Service Interface & Wrapper
v3/pkg/services/notifications/notifications.go
platformNotifier and NotificationService methods RequestNotificationAuthorization and CheckNotificationAuthorization now accept callback func(bool, error) instead of returning (bool, error). ServiceName() updated to the new package path.
Darwin implementation
v3/pkg/services/notifications/notifications_darwin.go
Synchronous, timeout-based authorization calls replaced by async callback-based methods; callbacks invoked from goroutines; nil callback guards and channel cleanup added.
iOS implementation
v3/pkg/services/notifications/notifications_ios.go
Methods updated to accept callback and invoke it (typically with true, nil) instead of returning values synchronously.
Linux implementation
v3/pkg/services/notifications/notifications_linux.go
Methods converted to callback form and invoke callback immediately with (true, nil) when provided; comments updated to note macOS-specific behavior.
Windows implementation
v3/pkg/services/notifications/notifications_windows.go
Stub methods converted to callback pattern and invoke callback immediately with (true, nil) when non-nil.
Docs & Changelog
docs/src/content/docs/features/notifications/overview.mdx, v3/UNRELEASED_CHANGELOG.md
Documentation and changelog updated to reflect callback-based API and new package path.

Sequence Diagram(s)

%%{init: {"themeVariables": {"actorBackground":"#E8F5E9","actorBorder":"#2E7D32","noteBackground":"#FFF3E0","noteBorder":"#FB8C00"}}}%%
sequenceDiagram
    participant App as Client
    participant NS as NotificationService
    participant PN as platformNotifier
    participant OS as PlatformOS

    App->>NS: RequestNotificationAuthorization(callback)
    NS->>PN: RequestNotificationAuthorization(callback)
    note right of PN `#FFF3E0`: Platform-specific work\n(may be async)
    PN->>OS: ask system for permission
    OS-->>PN: result (async)
    PN-->>NS: invoke callback(authorized, err)
    NS-->>App: callback invoked with (authorized, err)
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

Suggested labels

v3, v3-alpha, Documentation, size:L

Suggested reviewers

  • leaanthony

Poem

🐰 I swapped returns for tiny hops of sound,
Callbacks scattered softly all around,
Darwin, Windows, Linux sing in tune,
iOS hums beneath the moon,
Notifications dance — a joyous bound! 🥕✨

Pre-merge checks and finishing touches

❌ Failed checks (2 warnings)
Check name Status Explanation Resolution
Description check ⚠️ Warning The description addresses the motivation for the change and marks it as a breaking change requiring documentation updates. However, critical checklist items remain incomplete: no issue is referenced, tests are not added, and unit tests status is unchecked. Add 'Fixes #' to reference the related issue. Complete the remaining checklist items, particularly adding tests and confirming unit tests pass locally with the changes.
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (1 passed)
Check name Status Explanation
Title check ✅ Passed The title 'Refactor(v3): macOS async notification methods' accurately describes the main change—converting macOS notification authorization methods from synchronous to asynchronous callback-based implementation.
✨ 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 (1)
v3/pkg/services/notifications/notifications_darwin.go (1)

102-103: Redundant cleanup call is safe but potentially confusing.

GetChannel (called via captureResult) already removes the channel from the map before sending the result. The cleanupChannel(id) call here will find the channel absent and do nothing. The comment acknowledges this ("GetChannel may have already removed it"), so this is intentional defensive coding.

🔎 Optional: Remove redundant cleanup or clarify flow

If captureResult always removes the channel via GetChannel, this cleanup is truly redundant. You could either:

  1. Remove the cleanupChannel(id) call since it's a no-op in the success path
  2. Keep it for defensive purposes (current approach) but ensure the comment is accurate

Current approach is fine for safety.

📜 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 184b916.

📒 Files selected for processing (5)
  • v3/pkg/services/notifications/notifications.go
  • v3/pkg/services/notifications/notifications_darwin.go
  • v3/pkg/services/notifications/notifications_ios.go
  • v3/pkg/services/notifications/notifications_linux.go
  • v3/pkg/services/notifications/notifications_windows.go
🧰 Additional context used
🧠 Learnings (5)
📓 Common learnings
Learnt from: popaprozac
Repo: wailsapp/wails PR: 4098
File: v3/pkg/services/notifications/notifications_darwin.go:39-46
Timestamp: 2025-03-23T00:41:39.612Z
Learning: For the macOS notifications implementation in Wails, an early panic is used when the bundle identifier check fails rather than returning an error, because the Objective-C code would crash later anyway. The panic provides clear instructions to developers about bundling and signing requirements.
Learnt from: popaprozac
Repo: wailsapp/wails PR: 4098
File: v3/pkg/services/notifications/notifications_windows.go:0-0
Timestamp: 2025-03-24T06:54:22.127Z
Learning: popaprozac prefers to focus on getting the Notifications API functionality working first and may consider code cleanup/refactoring for payload encoding logic in notifications_windows.go at a later time.
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.
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.
📚 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/notifications/notifications_darwin.go
  • v3/pkg/services/notifications/notifications_windows.go
  • v3/pkg/services/notifications/notifications.go
  • v3/pkg/services/notifications/notifications_ios.go
  • v3/pkg/services/notifications/notifications_linux.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/notifications/notifications_darwin.go
  • v3/pkg/services/notifications/notifications_windows.go
  • v3/pkg/services/notifications/notifications.go
  • v3/pkg/services/notifications/notifications_ios.go
  • v3/pkg/services/notifications/notifications_linux.go
📚 Learning: 2025-03-24T06:54:22.127Z
Learnt from: popaprozac
Repo: wailsapp/wails PR: 4098
File: v3/pkg/services/notifications/notifications_windows.go:0-0
Timestamp: 2025-03-24T06:54:22.127Z
Learning: popaprozac prefers to focus on getting the Notifications API functionality working first and may consider code cleanup/refactoring for payload encoding logic in notifications_windows.go at a later time.

Applied to files:

  • v3/pkg/services/notifications/notifications_darwin.go
  • v3/pkg/services/notifications/notifications_windows.go
📚 Learning: 2025-04-29T23:54:07.488Z
Learnt from: popaprozac
Repo: wailsapp/wails PR: 4256
File: v2/internal/frontend/desktop/linux/notifications.go:27-28
Timestamp: 2025-04-29T23:54:07.488Z
Learning: In Wails v2, unlike v3-alpha which has a `ServiceShutdown` method for services, there is no standardized teardown pattern for frontend implementations. When implementing features that require cleanup (like goroutines or resources), add explicit cleanup methods (e.g., `CleanupNotifications()`) that handle resource release, context cancellation, and connection closure.

Applied to files:

  • v3/pkg/services/notifications/notifications_windows.go
  • v3/pkg/services/notifications/notifications.go
🧬 Code graph analysis (5)
v3/pkg/services/notifications/notifications_darwin.go (1)
v3/examples/notifications/frontend/bindings/github.com/wailsapp/wails/v3/pkg/services/notifications/notificationservice.ts (2)
  • RequestNotificationAuthorization (52-54)
  • CheckNotificationAuthorization (17-19)
v3/pkg/services/notifications/notifications_windows.go (1)
v3/examples/notifications/frontend/bindings/github.com/wailsapp/wails/v3/pkg/services/notifications/notificationservice.ts (2)
  • RequestNotificationAuthorization (52-54)
  • CheckNotificationAuthorization (17-19)
v3/pkg/services/notifications/notifications.go (2)
v3/examples/notifications/frontend/bindings/github.com/wailsapp/wails/v3/pkg/services/notifications/notificationservice.ts (2)
  • RequestNotificationAuthorization (52-54)
  • CheckNotificationAuthorization (17-19)
v3/examples/notifications/frontend/bindings/github.com/wailsapp/wails/v3/pkg/services/notifications/index.ts (1)
  • NotificationService (6-6)
v3/pkg/services/notifications/notifications_ios.go (1)
v3/examples/notifications/frontend/bindings/github.com/wailsapp/wails/v3/pkg/services/notifications/notificationservice.ts (2)
  • RequestNotificationAuthorization (52-54)
  • CheckNotificationAuthorization (17-19)
v3/pkg/services/notifications/notifications_linux.go (1)
v3/examples/notifications/frontend/bindings/github.com/wailsapp/wails/v3/pkg/services/notifications/notificationservice.ts (2)
  • RequestNotificationAuthorization (52-54)
  • CheckNotificationAuthorization (17-19)
⏰ 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/notifications/notifications_ios.go (1)

38-50: LGTM! iOS stub implementation correctly adopts the callback-based API.

The nil guards prevent potential panics, and immediately invoking callbacks with (true, nil) is appropriate stub behavior for iOS where native bridge implementation is pending.

v3/pkg/services/notifications/notifications_windows.go (1)

154-168: LGTM! Windows stub correctly implements the callback-based API.

The nil guards and immediate callback invocation with (true, nil) are appropriate since user authorization is macOS-specific. The comments accurately document this behavior.

v3/pkg/services/notifications/notifications_darwin.go (2)

88-106: Async callback pattern looks good, but goroutine may leak if native code fails to respond.

The removal of timeouts is intentional for user-facing authorization dialogs, but if the Objective-C callback never fires (e.g., due to a bug or edge case), the goroutine will block indefinitely on <-resultCh.

Consider whether this is acceptable given the PR's goal of removing timeouts, or if a safeguard (like a very long timeout with error callback) might be warranted for robustness.


108-126: CheckNotificationAuthorization follows the same async pattern - consistent implementation.

Same considerations apply as RequestNotificationAuthorization. The async callback approach is appropriate for the refactor goals.

v3/pkg/services/notifications/notifications_linux.go (1)

99-113: LGTM! Linux stub correctly implements the callback-based API.

The nil guards and immediate callback invocation with (true, nil) are appropriate since authorization is macOS-specific. Consistent with Windows and iOS implementations.

v3/pkg/services/notifications/notifications.go (3)

29-30: Interface updated to callback-based pattern - breaking change for implementers.

The platformNotifier interface now requires callback-based signatures. All platform implementations in this PR correctly implement the new signatures. This is a clean interface change.


111-113: Unable to verify ServiceName path change claim without codebase access.

The review comment asserts that the ServiceName path changed and represents a breaking change, but the repository could not be accessed for verification. Without being able to examine the codebase history and service registration patterns, I cannot confirm:

  • What the previous service path was (if one existed)
  • Whether this is actually a change or new code
  • If existing code hardcodes references that need updates
  • Whether this change is documented as breaking in the PR context

The review should clarify what the old path was and demonstrate concrete instances where code references it.


149-155: Verify callback parameter compatibility with Wails v3 binding generator.

The review concern is technically valid: Wails v3 binding generation does not support callback function types (func(bool, error)) as method parameters—these cannot be serialized across the bridge. The framework instead requires event-based patterns using runtime.On/Once for asynchronous callbacks. Confirm whether the actual method signatures currently accept callbacks (incompatible) or have been refactored to use return values or event-based patterns (compatible). If callbacks are present, they must be replaced with the event-driven approach per Wails v3's binding constraints.

@popaprozac
Copy link
Author

@coderabbitai review

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Dec 30, 2025

✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

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 (3)
v3/UNRELEASED_CHANGELOG.md (1)

23-23: Clarify that the API change affects all platforms.

The changelog entry states "on macOS" but the method signatures changed across all platforms (darwin, iOS, Linux, Windows) to use callbacks. While the async behavior is primarily relevant for macOS, the breaking API change affects all platform implementations.

🔎 Suggested clarification
-- Update notifications authorization methods on macOS to callbacks
+- Update notification authorization methods to use callbacks (breaking change)

Or, if you prefer to emphasize the macOS motivation:

-- Update notifications authorization methods on macOS to callbacks
+- Update notification authorization methods to async callbacks for macOS (all platforms affected)
docs/src/content/docs/features/notifications/overview.mdx (2)

37-63: LGTM! Consider clarifying platform-specific requirements vs API design.

The callback-based authorization flow is correctly documented with proper error handling. The nested callback pattern appropriately demonstrates the async authorization workflow.

One minor suggestion: Line 37 could be slightly clearer by separating the macOS-specific requirement from the cross-platform API design. For example: "Notifications on macOS require user authorization. The authorization methods use callbacks on all platforms:" This would clarify that while the requirement is macOS-specific, the callback-based API is used consistently across platforms.


236-239: Consider clarifying cross-platform availability in API descriptions.

The API reference descriptions mention "(macOS)" which might suggest these methods are macOS-only. Consider clarifying that:

  • These methods are available on all platforms
  • The asynchronous behavior is primarily for macOS
  • Windows/Linux invoke callbacks immediately (as noted in line 65)
🔎 Suggested enhancement
-| `RequestNotificationAuthorization(callback func(bool, error))` | Requests permission to display notifications (macOS). Callback is invoked asynchronously when the user responds. |
-| `CheckNotificationAuthorization(callback func(bool, error))`   | Checks current notification authorization status (macOS). Callback is invoked asynchronously with the result. |
+| `RequestNotificationAuthorization(callback func(bool, error))` | Requests permission to display notifications. Callback is invoked asynchronously on macOS when the user responds; immediately on Windows/Linux. |
+| `CheckNotificationAuthorization(callback func(bool, error))`   | Checks current notification authorization status. Callback is invoked asynchronously on macOS; immediately on Windows/Linux with `authorized = true`. |
📜 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 184b916 and eebc859.

📒 Files selected for processing (3)
  • docs/src/content/docs/features/notifications/overview.mdx
  • v3/UNRELEASED_CHANGELOG.md
  • v3/pkg/services/notifications/notifications_darwin.go
🚧 Files skipped from review as they are similar to previous changes (1)
  • v3/pkg/services/notifications/notifications_darwin.go
🧰 Additional context used
🧠 Learnings (4)
📓 Common learnings
Learnt from: popaprozac
Repo: wailsapp/wails PR: 4098
File: v3/pkg/services/notifications/notifications_windows.go:0-0
Timestamp: 2025-03-24T06:54:22.127Z
Learning: popaprozac prefers to focus on getting the Notifications API functionality working first and may consider code cleanup/refactoring for payload encoding logic in notifications_windows.go at a later time.
Learnt from: popaprozac
Repo: wailsapp/wails PR: 4098
File: v3/pkg/services/notifications/notifications_darwin.go:39-46
Timestamp: 2025-03-23T00:41:39.612Z
Learning: For the macOS notifications implementation in Wails, an early panic is used when the bundle identifier check fails rather than returning an error, because the Objective-C code would crash later anyway. The panic provides clear instructions to developers about bundling and signing requirements.
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.
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.
📚 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:

  • docs/src/content/docs/features/notifications/overview.mdx
📚 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:

  • docs/src/content/docs/features/notifications/overview.mdx
📚 Learning: 2025-12-29T08:02:06.122Z
Learnt from: popaprozac
Repo: wailsapp/wails PR: 4839
File: docs/src/content/docs/reference/window.mdx:616-620
Timestamp: 2025-12-29T08:02:06.122Z
Learning: In Wails v3, document window creation using app.Window.New() and app.Window.NewWithOptions(...). Do not show or reference app.NewWebviewWindow() or app.NewWebviewWindowWithOptions(...). The Application struct exposes a Window field of type *WindowManager that provides these methods. When updating docs, replace examples accordingly and mention that WindowManager methods create and configure new windows.

Applied to files:

  • docs/src/content/docs/features/notifications/overview.mdx
🔇 Additional comments (1)
docs/src/content/docs/features/notifications/overview.mdx (1)

65-65: Excellent clarification of cross-platform behavior.

This note clearly explains how Windows and Linux handle the callback-based API, helping developers understand the behavior differences while maintaining API consistency.

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

Labels

None yet

1 participant