Skip to content

[v3] Windows notifications improvements #4230

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Apr 23, 2025

Conversation

popaprozac
Copy link

@popaprozac popaprozac commented Apr 22, 2025

Description

Windows changes:

  • register COM stuff early to ensure toast callback is fired when app is relaunched
  • general cleanup

Minor changes on macOS:

  • create notification delegate on service startup

Updated the example to be easier to understand. Create the service, attach a callback, go!

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       | 15.4.1                           |
| ID            | 24E263                           |
| Branding      | Sequoia                          |
| 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 3 |
| Memory        | 36 GB                            |
└──────────────────────────────────────────────────┘

# Build Environment

┌─────────────────────────────────────────────────────────┐
| Wails CLI    | v3.0.0-dev                               |
| Go Version   | go1.24.1                                 |
| Revision     | e2dfdc5f18257d455069b2f557133c8e1a5cac9b |
| 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 | e2dfdc5f18257d455069b2f557133c8e1a5cac9b |
| vcs.time     | 2025-04-14T16:47:24Z                     |
└─────────────────────────────────────────────────────────┘

# Dependencies

┌────────────────────────────────────────────────────────────────────────┐
| npm             | 10.9.2                                               |
| *NSIS           | Not Installed. Install with `brew install makensis`. |
| Xcode cli tools | 2409                                                 |
|                                                                        |
└─────────────────────── * - 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

  • Bug Fixes
    • Improved reliability of notification handling on macOS and Windows platforms.
  • Chores
    • Cleaned up unused application event handlers and imports.
    • Enhanced internal initialization and registration processes for notifications on macOS and Windows.
  • Refactor
    • Simplified notification response handling and improved error reporting for notifications.

Sorry, something went wrong.

Copy link
Contributor

coderabbitai bot commented Apr 22, 2025

Walkthrough

This update refactors notification handling across both the example application and platform-specific services. In the example app, all startup notification logic is removed except for the notification response callback. On macOS, the notification service now calls a new delegate initialization function during startup and adds error handling for this step. The Windows notification service is enhanced to register the toast activator COM class factory, store the executable path, update the registry, and refactor activation callback logic. Several function declarations and signatures are updated or reordered, and imports are adjusted accordingly.

Changes

File(s) Change Summary
v3/examples/notifications/main.go Removed all notification logic from the app startup except for the notification response callback; removed related imports and event handler code; window creation now sets the window name explicitly.
v3/pkg/services/notifications/notifications_darwin.go Modified darwinNotifier.Startup to call a new delegate initialization function and handle errors if initialization fails.
v3/pkg/services/notifications/notifications_darwin.h, v3/pkg/services/notifications/notifications_darwin.m Added declaration and implementation for ensureDelegateInitialized; changed its return type to bool; reordered function declarations in the header file.
v3/pkg/services/notifications/notifications_windows.go Enhanced windowsNotifier with an exePath field, registry updates, COM class factory registration, refactored activation callback logic, and explicit activation type settings; adjusted imports.

Sequence Diagram(s)

Loading
sequenceDiagram
    participant App as Example App
    participant NotificationService as Platform Notification Service
    participant OS as Operating System

    App->>NotificationService: Register notification response callback
    Note over App,NotificationService: (All other app-side notification logic removed)

    Note over NotificationService: On Startup (macOS)
    NotificationService->>OS: Check notification availability & bundle ID
    NotificationService->>OS: Call ensureDelegateInitialized()
    OS-->>NotificationService: Return success or error

    Note over NotificationService: On Startup (Windows)
    NotificationService->>OS: Retrieve executable path
    NotificationService->>OS: Update registry with exe path
    NotificationService->>OS: Register COM class factory
    OS-->>NotificationService: Return success or error

Possibly related PRs

  • wailsapp/wails#4098: Introduced the Notifications API, including the darwinNotifier and windowsNotifier services, example app, and frontend bindings, which are directly built upon and modified by this PR.

Suggested reviewers

  • leaanthony

Poem

In the land of code, the bells no longer ring,
The startup’s now silent, no notifications spring.
Mac checks its delegate, Windows finds its path,
Registry keys and COM, all handled in a flash.
A callback remains, awaiting your reply—
With a hop and a log, the messages fly!
🐇✨


📜 Recent review details

Configuration used: .coderabbit.yaml
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 9fcede4 and 66ba876.

📒 Files selected for processing (1)
  • v3/pkg/services/notifications/notifications_windows.go (7 hunks)
🧰 Additional context used
🧠 Learnings (1)
v3/pkg/services/notifications/notifications_windows.go (1)
Learnt from: popaprozac
PR: wailsapp/wails#4230
File: v3/pkg/services/notifications/notifications_windows.go:132-136
Timestamp: 2025-04-22T22:47:26.411Z
Learning: The go-toast package in Wails handles COM initialization internally when using `SetAppData` and setting the activation callback in Windows notifications. Attempting to initialize COM again would result in an error indicating it's already initialized.
🔇 Additional comments (10)
v3/pkg/services/notifications/notifications_windows.go (10)

13-16: Appropriate import changes for COM component integration.

The addition of unsafe import is necessary for the Go linkname directive, and the explicit import of the wintoast subpackage allows direct access to COM-related functionality needed for proper toast activation.


29-29: Good addition of exePath field to support COM registration.

Storing the executable path is essential for proper toast activation in Windows, as it needs to be registered in both the registry and toast app data.


60-61: Proper use of linkname directive to access internal toast functionality.

The go:linkname directive is correctly used to access the registerClassFactory function from the wintoast package. This allows direct registration of the COM class factory without exposing it as a public API.


82-86: Robust executable path retrieval with proper error handling.

The code correctly retrieves the executable path and handles potential errors. This is crucial for Windows toast notifications to function properly when the application is relaunched.


88-98: Excellent implementation of registry key creation with proper error handling.

This code correctly creates and sets the CLSID registry entries needed for COM activation, with thorough error handling for both key creation and value setting. This addresses a previous review comment about ignored registry write errors.


100-105: Complete toast app data configuration with executable path.

The addition of the ActivationExe field ensures that Windows knows which executable to launch when a toast notification is activated, which is essential for properly handling notification callbacks.


114-131: Improved notification response handling logic.

The refactored code has a cleaner structure with the error case handled first, followed by success case in an else block. The extraction of user text is now better organized within the success flow.


138-141: COM factory registration is properly implemented.

The code correctly registers the COM class factory for toast activation. Based on the retrieved learning, COM initialization is already handled by the go-toast package when using SetAppData and setting the activation callback, so no explicit initialization is needed here.


176-176: Explicit ActivationType setting for consistent behavior.

Setting the ActivationType to toast.Foreground ensures that notifications consistently activate the application in the foreground when clicked, providing a better user experience.


211-211: Consistent ActivationType setting in action notifications.

The same explicit setting of ActivationType to toast.Foreground is applied here, ensuring consistent behavior across both simple and action-based notifications.

✨ 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
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Generate unit testing code for this file.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai generate unit testing code for this file.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and generate unit testing code.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR.
  • @coderabbitai generate sequence diagram to generate a sequence diagram of the changes in this PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

Sorry, something went wrong.

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

🧹 Nitpick comments (3)
v3/pkg/services/notifications/notifications_windows.go (3)

13-17: Blank import of unsafe – use regular import for clarity

unsafe has no side‑effects; the only reason it must appear in the import list is to satisfy the //go:linkname directive.
Using a blank identifier hides the real dependency and can be confusing when the file is read in isolation.
Prefer:

import "unsafe" // required for go:linkname

so the intent is explicit and static‑analysis tools still see a real reference.


29-29: exePath never changes after Startup – tag it as immutable

exePath is written once and thereafter only read.
Declare it as exePath string // immutable, set in Startup or even mark the field unexported and //nolint:structcheck if tooling complains.
This small hint prevents accidental writes in the future.


60-62: go:linkname is brittle across versions and modules

Linking against an unexported symbol in another module couples the two repos at the ABI level.
If go-toast refactors, you get a silent compile‑time break.
Consider asking the upstream project to export registerClassFactory or wrap the call behind a build‑tagged shim held in this repo so the surface is under your control.

📜 Review details

Configuration used: .coderabbit.yaml
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 421b75e and 9fcede4.

📒 Files selected for processing (5)
  • v3/examples/notifications/main.go (2 hunks)
  • v3/pkg/services/notifications/notifications_darwin.go (1 hunks)
  • v3/pkg/services/notifications/notifications_darwin.h (1 hunks)
  • v3/pkg/services/notifications/notifications_darwin.m (1 hunks)
  • v3/pkg/services/notifications/notifications_windows.go (7 hunks)
🧰 Additional context used
🧬 Code Graph Analysis (2)
v3/examples/notifications/main.go (2)
v3/internal/runtime/desktop/@wailsio/runtime/src/window.ts (1)
  • Name (267-269)
v3/pkg/services/notifications/notifications.go (1)
  • NotificationResult (105-108)
v3/pkg/services/notifications/notifications_windows.go (2)
v3/pkg/application/application.go (1)
  • Get (52-54)
v3/pkg/services/notifications/notifications.go (1)
  • NotificationResponse (92-101)
🔇 Additional comments (8)
v3/pkg/services/notifications/notifications_darwin.m (1)

94-108: Return type change enhances cross-language compatibility.

The function correctly uses dispatch_once to ensure thread-safe initialization of the notification delegate. The return type change from BOOL to bool better aligns with the C99 standard boolean type, making the interface more consistent with Go's boolean handling in CGO.

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

68-70: Good addition of delegate initialization error handling.

This change adds proper error handling for notification delegate initialization during startup. By checking the return value from ensureDelegateInitialized(), the code can now detect and report initialization failures, improving the service's reliability.

v3/pkg/services/notifications/notifications_darwin.h (1)

9-10: Function declaration order improved and new delegate initialization function added.

The reordering of function declarations and addition of ensureDelegateInitialized properly exposes the new initialization capability to the rest of the codebase. This aligns well with the implementation changes in the corresponding .m and .go files.

v3/examples/notifications/main.go (2)

54-54: Explicit window naming improves application structure.

Adding a specific name to the window ("main") helps with window identification and management, particularly when working with events or when the application might have multiple windows.


64-73: Notification handling simplified to focus on response callbacks.

The notification initialization and sending logic has been removed in favor of a more streamlined approach that only handles notification responses. This simplification:

  1. Makes the example clearer by focusing on a single responsibility
  2. Relies on the notification service's own initialization
  3. Properly handles errors and sends events to the frontend

This change aligns well with the PR objective to enhance notification handling and simplify usage.

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

108-125: Good: consolidated result construction

The new block neatly separates the error path from the happy path and reuses the existing NotificationResponse type.
This improves readability and avoids partial initialisation.


170-171: Explicit ActivationType improves intent

Setting ActivationType: toast.Foreground makes the behaviour crystal‑clear and guards against upstream default changes.
👍


205-206: Same commendation as above

Explicitly forcing foreground activation for action‑rich toasts keeps UX consistent across basic and advanced notifications.

popaprozac and others added 2 commits April 22, 2025 16:21

Verified

This commit was created on GitHub.com and signed with GitHub’s verified signature.
Copy link

@leaanthony leaanthony merged commit 685d810 into wailsapp:v3-alpha Apr 23, 2025
6 of 7 checks passed
@leaanthony
Copy link
Member

Thanks for this!!! 🙏

@coderabbitai coderabbitai bot mentioned this pull request Apr 29, 2025
15 tasks
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

2 participants