Skip to content

Conversation

@yujonglee
Copy link
Contributor

@yujonglee yujonglee commented Aug 26, 2025

Summary by cubic

Replaced the wezterm-based notification path with a native macOS implementation using Swift, and introduced a small cross-crate interface. This adds a single show_notification command, removes permission-related flows, and simplifies dependencies.

  • New Features

    • New notification-interface crate with a shared Notification type (title, message, url, timeout).
    • New notification-macos crate using swift-rs with a custom Swift UI panel; includes an example.
    • Plugin: added show_notification command and default permission; removed permission/settings commands.
    • Desktop settings now show a test notification immediately on enable.
  • Migration

    • Replace hypr-notification2 with hypr-notification.
    • Remove calls to openNotificationSettings, requestNotificationPermission, checkNotificationPermission; use showNotification instead.
    • Frontend bindings changed: Notification now includes timeout as Duration.
    • macOS builds require Swift toolchain (Swift 5.9+) and macOS 14.2+; Swift linking runs only on macOS.

@coderabbitai
Copy link

coderabbitai bot commented Aug 26, 2025

Caution

Review failed

The pull request is closed.

📝 Walkthrough

Walkthrough

Replaces the old notification2 crate with a split interface/macos implementation, rewires the notification crate to re-export the new macOS backend, updates the Tauri plugin to expose a show_notification command and new bindings, adjusts permissions, and simplifies the desktop UI to directly trigger test notifications without permission flows.

Changes

Cohort / File(s) Summary of changes
Workspace manifest updates
Cargo.toml
Remove hypr-notification2; add hypr-notification-interface and hypr-notification-macos.
Notification crate wiring
crates/notification/Cargo.toml, crates/notification/src/lib.rs
Replace Objective-C deps with hypr-notification-macos on macOS; re-export macOS items directly.
Remove legacy notification2 crate
crates/notification2/*
Delete crate, including public API for permission/check/settings and show wrapper.
Notification interface crate (new)
crates/notification-interface/Cargo.toml, crates/notification-interface/src/lib.rs
Add Notification struct (title, message, optional url/timeout) with serde/specta derives.
macOS implementation crate (new)
crates/notification-macos/Cargo.toml, crates/notification-macos/build.rs, crates/notification-macos/src/lib.rs, crates/notification-macos/examples/test_notification.rs
Add macOS backend using swift-rs; build script links Swift; expose show(&Notification) bridging to Swift; example demonstrates usage.
Swift notification library (new)
crates/notification-macos/swift-lib/*
Add Swift Package (tools 5.9) static lib with UI and C ABI _show_notification; include ignore and resolved files.
Tauri plugin: Rust
plugins/notification/src/{commands.rs,ext.rs,lib.rs,worker.rs}, plugins/notification/Cargo.toml, plugins/notification/build.rs
Add show_notification command and trait method; remove permission/settings commands and hypr-notification2 usage; switch runtime calls to hypr-notification. Update command list and dependency rename.
Tauri plugin: JS bindings
plugins/notification/js/bindings.gen.ts
Add showNotification(v: Notification); remove permission-related APIs; add Duration and Notification types.
Tauri plugin: permissions
plugins/notification/permissions/{default.toml,schemas/schema.json,autogenerated/...}
Add allow/deny for show_notification; include in default set; update reference docs.
Desktop app UI
apps/desktop/src/components/settings/views/notifications.tsx
Remove async permission requests; directly set flags and call showNotification with a fixed test payload when enabled.

Sequence Diagram(s)

sequenceDiagram
  autonumber
  participant UI as Desktop UI (React)
  participant JS as Plugin JS (bindings.gen.ts)
  participant Tauri as Tauri Commands (Rust)
  participant Ext as Plugin Ext
  participant Notif as hypr_notification
  participant Mac as hypr_notification_macos (Rust)
  participant Swift as Swift _show_notification

  UI->>JS: showNotification(Notification)
  JS->>Tauri: plugin:notification|show_notification { v }
  Tauri->>Ext: commands::show_notification(app, v)
  Ext->>Notif: show(&Notification)
  Note over Notif,Mac: macOS only path
  Notif->>Mac: show(&Notification)
  Mac->>Swift: _show_notification(title, message, url, has_url, timeout)
  Swift-->>UI: Displays macOS notification (async)
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Possibly related PRs

Tip

🔌 Remote MCP (Model Context Protocol) integration is now available!

Pro plan users can now connect to remote MCP servers from the Integrations page. Connect with popular remote MCPs such as Notion and Linear to add more context to your reviews and chats.


📜 Recent review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

💡 Knowledge Base configuration:

  • MCP integration is disabled by default for public repositories
  • Jira integration is disabled by default for public repositories
  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 0a5f65f and f918054.

⛔ Files ignored due to path filters (1)
  • Cargo.lock is excluded by !**/*.lock
📒 Files selected for processing (29)
  • Cargo.toml (1 hunks)
  • apps/desktop/src/components/settings/views/notifications.tsx (2 hunks)
  • crates/notification-interface/Cargo.toml (1 hunks)
  • crates/notification-interface/src/lib.rs (1 hunks)
  • crates/notification-macos/Cargo.toml (1 hunks)
  • crates/notification-macos/build.rs (1 hunks)
  • crates/notification-macos/examples/test_notification.rs (1 hunks)
  • crates/notification-macos/src/lib.rs (1 hunks)
  • crates/notification-macos/swift-lib/.gitignore (1 hunks)
  • crates/notification-macos/swift-lib/Package.resolved (1 hunks)
  • crates/notification-macos/swift-lib/Package.swift (1 hunks)
  • crates/notification-macos/swift-lib/src/lib.swift (1 hunks)
  • crates/notification/Cargo.toml (1 hunks)
  • crates/notification/src/lib.rs (1 hunks)
  • crates/notification/src/macos.rs (0 hunks)
  • crates/notification2/Cargo.toml (0 hunks)
  • crates/notification2/src/lib.rs (0 hunks)
  • crates/notification2/src/macos.rs (0 hunks)
  • plugins/notification/Cargo.toml (1 hunks)
  • plugins/notification/build.rs (1 hunks)
  • plugins/notification/js/bindings.gen.ts (2 hunks)
  • plugins/notification/permissions/autogenerated/commands/show_notification.toml (1 hunks)
  • plugins/notification/permissions/autogenerated/reference.md (2 hunks)
  • plugins/notification/permissions/default.toml (1 hunks)
  • plugins/notification/permissions/schemas/schema.json (2 hunks)
  • plugins/notification/src/commands.rs (1 hunks)
  • plugins/notification/src/ext.rs (3 hunks)
  • plugins/notification/src/lib.rs (1 hunks)
  • plugins/notification/src/worker.rs (1 hunks)
✨ Finishing Touches
  • 📝 Generate Docstrings
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch different-notif

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:

‼️ IMPORTANT
Auto-reply has been disabled for this repository in the CodeRabbit settings. The CodeRabbit bot will not respond to your replies unless it is explicitly tagged.

  • 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.
  • 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 the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

CodeRabbit Commands (Invoked using PR/Issue comments)

Type @coderabbitai help to get the list of available commands.

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.

Status, Documentation and Community

  • Visit our Status Page to check the current availability of CodeRabbit.
  • 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.

@yujonglee yujonglee merged commit 0612f68 into main Aug 26, 2025
4 of 7 checks passed
@yujonglee yujonglee deleted the different-notif branch August 26, 2025 23:43
Copy link

@cubic-dev-ai cubic-dev-ai bot left a comment

Choose a reason for hiding this comment

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

8 issues found across 30 files

React with 👍 or 👎 to teach cubic. You can also tag @cubic-dev-ai to give feedback, ask questions, or re-run the review.

}
}
// Also a local monitor to handle when app is active (faster updates)
NSEvent.addLocalMonitorForEvents(matching: [.mouseMoved, .leftMouseDragged, .rightMouseDragged])
Copy link

Choose a reason for hiding this comment

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

Local NSEvent monitor is never removed; store the returned token and remove it when no notifications remain.

Prompt for AI agents
Address the following comment on crates/notification-macos/swift-lib/src/lib.swift at line 681:

<comment>Local NSEvent monitor is never removed; store the returned token and remove it when no notifications remain.</comment>

<file context>
@@ -0,0 +1,735 @@
+import AVFoundation
+import Cocoa
+import SwiftRs
+
+// MARK: - Notification Instance
+class NotificationInstance {
+  let id = UUID()
+  let panel: NSPanel
+  let clickableView: ClickableView
</file context>


private func manageNotificationLimit() {
// Remove oldest notifications if we exceed the limit
while activeNotifications.count >= maxNotifications {
Copy link

Choose a reason for hiding this comment

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

Infinite loop: using while here spins because dismiss() updates activeNotifications asynchronously after animation; count never decreases during the loop.

Prompt for AI agents
Address the following comment on crates/notification-macos/swift-lib/src/lib.swift at line 313:

<comment>Infinite loop: using while here spins because dismiss() updates activeNotifications asynchronously after animation; count never decreases during the loop.</comment>

<file context>
@@ -0,0 +1,735 @@
+import AVFoundation
+import Cocoa
+import SwiftRs
+
+// MARK: - Notification Instance
+class NotificationInstance {
+  let id = UUID()
+  let panel: NSPanel
+  let clickableView: ClickableView
</file context>

title: "Meeting detected".to_string(),
message: "Click here to start writing a note".to_string(),
url: Some("hypr://hyprnote.com/notification".to_string()),
// let notif = hypr_notification2::Notification {
Copy link

Choose a reason for hiding this comment

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

Stale comment references hypr_notification2; update to hypr_notification (or remove) to avoid confusion.

Prompt for AI agents
Address the following comment on plugins/notification/src/ext.rs at line 105:

<comment>Stale comment references `hypr_notification2`; update to `hypr_notification` (or remove) to avoid confusion.</comment>

<file context>
@@ -101,14 +102,19 @@ impl&lt;R: tauri::Runtime, T: tauri::Manager&lt;R&gt;&gt; NotificationPluginExt&lt;R&gt; for T {
     #[tracing::instrument(skip(self))]
     fn start_detect_notification(&amp;self) -&gt; Result&lt;(), Error&gt; {
         let cb = hypr_detect::new_callback(move |bundle_id| {
-            let notif = hypr_notification2::Notification {
-                title: &quot;Meeting detected&quot;.to_string(),
-                message: &quot;Click here to start writing a note&quot;.to_string(),
-                url: Some(&quot;hypr://hyprnote.com/notification&quot;.to_string()),
+            // let notif = hypr_notification2::Notification {
+            //     title: &quot;Meeting detected&quot;.to_string(),
</file context>
Suggested change
// let notif = hypr_notification2::Notification {
// let notif = hypr_notification::Notification {

@@ -0,0 +1,13 @@
fn main() {
#[cfg(target_os = "macos")]
Copy link

Choose a reason for hiding this comment

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

Using #[cfg(target_os = "macos")] in a build.rs checks the host OS, not the Cargo target; this can misbehave during cross-compilation. Prefer branching on CARGO_CFG_TARGET_OS to make the build script target-aware.

Prompt for AI agents
Address the following comment on crates/notification-macos/build.rs at line 2:

<comment>Using #[cfg(target_os = &quot;macos&quot;)] in a build.rs checks the host OS, not the Cargo target; this can misbehave during cross-compilation. Prefer branching on CARGO_CFG_TARGET_OS to make the build script target-aware.</comment>

<file context>
@@ -0,0 +1,13 @@
+fn main() {
+    #[cfg(target_os = &quot;macos&quot;)]
+    {
+        swift_rs::SwiftLinker::new(&quot;14.2&quot;)
</file context>

@@ -1,2 +1,2 @@
#[cfg(target_os = "macos")]
pub mod macos;
pub use hypr_notification_macos::*;
Copy link

Choose a reason for hiding this comment

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

Re-exporting the entire external crate at the root breaks the previous notification::macos::... API and pollutes the root namespace; alias the crate to preserve the module path.

Prompt for AI agents
Address the following comment on crates/notification/src/lib.rs at line 2:

<comment>Re-exporting the entire external crate at the root breaks the previous `notification::macos::...` API and pollutes the root namespace; alias the crate to preserve the module path.</comment>

<file context>
@@ -1,2 +1,2 @@
 #[cfg(target_os = &quot;macos&quot;)]
-pub mod macos;
+pub use hypr_notification_macos::*;
</file context>
Suggested change
pub use hypr_notification_macos::*;
pub use hypr_notification_macos as macos;

pub struct Notification {
pub title: String,
pub message: String,
pub url: Option<String>,
Copy link

Choose a reason for hiding this comment

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

Use a typed URL (e.g., url::Url) instead of String to validate and prevent malformed URLs in the public interface.

Prompt for AI agents
Address the following comment on crates/notification-interface/src/lib.rs at line 5:

<comment>Use a typed URL (e.g., url::Url) instead of String to validate and prevent malformed URLs in the public interface.</comment>

<file context>
@@ -0,0 +1,7 @@
+#[derive(Debug, serde::Serialize, serde::Deserialize, specta::Type)]
+pub struct Notification {
+    pub title: String,
+    pub message: String,
+    pub url: Option&lt;String&gt;,
+    pub timeout: Option&lt;std::time::Duration&gt;,
+}
</file context>

pub title: String,
pub message: String,
pub url: Option<String>,
pub timeout: Option<std::time::Duration>,
Copy link

Choose a reason for hiding this comment

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

Represent duration with a primitive (e.g., milliseconds as u64) to avoid interop ambiguity when exporting to TS/JSON via specta.

Prompt for AI agents
Address the following comment on crates/notification-interface/src/lib.rs at line 6:

<comment>Represent duration with a primitive (e.g., milliseconds as u64) to avoid interop ambiguity when exporting to TS/JSON via specta.</comment>

<file context>
@@ -0,0 +1,7 @@
+#[derive(Debug, serde::Serialize, serde::Deserialize, specta::Type)]
+pub struct Notification {
+    pub title: String,
+    pub message: String,
+    pub url: Option&lt;String&gt;,
+    pub timeout: Option&lt;std::time::Duration&gt;,
+}
</file context>

}

#[tracing::instrument(skip(self))]
fn show_notification(&self, v: hypr_notification::Notification) -> Result<(), Error> {
Copy link

Choose a reason for hiding this comment

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

Instrumented function may log notification contents (potential PII). Add the parameter to skip list to avoid logging sensitive fields.

Prompt for AI agents
Address the following comment on plugins/notification/src/ext.rs at line 29:

<comment>Instrumented function may log notification contents (potential PII). Add the parameter to skip list to avoid logging sensitive fields.</comment>

<file context>
@@ -18,19 +19,19 @@ pub trait NotificationPluginExt&lt;R: tauri::Runtime&gt; {
 
     fn start_detect_notification(&amp;self) -&gt; Result&lt;(), Error&gt;;
     fn stop_detect_notification(&amp;self) -&gt; Result&lt;(), Error&gt;;
-
-    fn open_notification_settings(&amp;self) -&gt; Result&lt;(), Error&gt;;
-    fn request_notification_permission(&amp;self) -&gt; Result&lt;(), Error&gt;;
-    fn check_notification_permission(
-        &amp;self,
-    ) -&gt; impl Future&lt;Output = Result&lt;hypr_notification2::NotificationPermission, Error&gt;&gt;;
</file context>
Suggested change
#[tracing::instrument(skip(self))]
#[tracing::instrument(skip(self, v))]

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.

2 participants