Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 15 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -463,6 +463,21 @@ Registers the app for push notifications. On Android this retrieves the FCM devi
- Android: FCM device token
- Linux: UnifiedPush endpoint URL (the URL your backend POSTs payloads to)

On iOS the APNs token is returned to the caller but is not also emitted through
the generic Tauri event channel by default. Apps that intentionally handle the
raw token in JavaScript can opt into the legacy `push-token` event in
`tauri.conf.json`:
Comment on lines +466 to +469

```json
{
"plugins": {
"notifications": {
"exposePushTokenEvents": true
}
}
}
```

### `listDistributors()` **(Linux / UnifiedPush only)**
Lists every running UnifiedPush distributor by its D-Bus bus name (e.g. `org.unifiedpush.Distributor.ntfy`). Returns an empty array when none is installed — that's the signal to ask the user to install one from <https://unifiedpush.org/users/distributors/>.

Expand Down
4 changes: 3 additions & 1 deletion ios/Sources/AppDelegateSwizzler.swift
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,9 @@ final class PushForwarder: NSObject, UIApplicationDelegate {
didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
let hex = deviceToken.map { String(format: "%02x", $0) }.joined()
AppDelegateSwizzler.plugin?.handlePushTokenReceived(hex)
try? AppDelegateSwizzler.plugin?.trigger("push-token", data: ["token": hex])
if AppDelegateSwizzler.plugin?.exposePushTokenEvents == true {
try? AppDelegateSwizzler.plugin?.trigger("push-token", data: ["token": hex])
}
Comment on lines 79 to +82
AppDelegateSwizzler.callOriginalDidRegister(
self,
#selector(UIApplicationDelegate.application(_:didRegisterForRemoteNotificationsWithDeviceToken:)),
Expand Down
10 changes: 7 additions & 3 deletions ios/Sources/NotificationPlugin.swift
Original file line number Diff line number Diff line change
Expand Up @@ -163,11 +163,13 @@ struct SetPushMessageListenerActiveArgs: Decodable {

struct PluginConfig: Decodable {
let actionTypes: [ActionType]?
let exposePushTokenEvents: Bool?
}

class NotificationPlugin: Plugin {
let notificationHandler = NotificationHandler()
let notificationManager = NotificationManager()
var exposePushTokenEvents = false

#if ENABLE_PUSH_NOTIFICATIONS
// Completion handler for push token registration
Expand All @@ -185,9 +187,11 @@ class NotificationPlugin: Plugin {
public override func load(webview: WKWebView) {
super.load(webview: webview)

if let config = try? parseConfig(PluginConfig.self),
let actionTypes = config.actionTypes {
makeCategories(actionTypes)
if let config = try? parseConfig(PluginConfig.self) {
if let actionTypes = config.actionTypes {
makeCategories(actionTypes)
}
exposePushTokenEvents = config.exposePushTokenEvents ?? false
}

#if ENABLE_PUSH_NOTIFICATIONS
Expand Down
10 changes: 10 additions & 0 deletions ios/Tests/PluginTests/PluginTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,16 @@ final class NotificationTests: XCTestCase {
XCTAssertEqual(config.actionTypes?.first?.id, "sable-message")
XCTAssertEqual(config.actionTypes?.first?.actions.first?.id, "sable-reply")
XCTAssertEqual(config.actionTypes?.first?.actions.first?.input, true)
XCTAssertNil(config.exposePushTokenEvents)
}

func testPluginConfigCanExplicitlyExposePushTokenEvents() throws {
let config = try JSONDecoder().decode(
PluginConfig.self,
from: Data(#"{"exposePushTokenEvents":true}"#.utf8)
)

XCTAssertEqual(config.exposePushTokenEvents, true)
}

func testSetPushMessageListenerActiveArgsDecodes() throws {
Expand Down
6 changes: 6 additions & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,12 @@ pub struct PluginConfig {
/// `aps.category` is received before JavaScript initializes.
#[serde(default)]
pub action_types: Vec<ActionType>,
/// Emit the raw APNs registration token through the generic Tauri event
/// channel. Disabled by default because Rust callers already receive the
/// token from `register_for_push_notifications` and may keep it outside
/// the renderer trust boundary.
#[serde(default)]
pub expose_push_token_events: bool,
#[cfg(target_os = "windows")]
pub windows: WindowsConfig,
}
Expand Down