Skip to content

Added UnifiedPush support#123

Open
TastelessVoid wants to merge 25 commits intoChoochmeque:mainfrom
TastelessVoid:unified-push-support
Open

Added UnifiedPush support#123
TastelessVoid wants to merge 25 commits intoChoochmeque:mainfrom
TastelessVoid:unified-push-support

Conversation

@TastelessVoid
Copy link
Copy Markdown

This implements UnifiedPush as backend for notifications, as some manufacturers, such as Fairphone don't have FCM/the required Google services for FCM installed and some users may prefer using a FOSS backend

Copilot AI review requested due to automatic review settings March 8, 2026 12:11
@codecov-commenter
Copy link
Copy Markdown

codecov-commenter commented Mar 8, 2026

Codecov Report

❌ Patch coverage is 33.33333% with 264 lines in your changes missing coverage. Please review.
✅ Project coverage is 56.25%. Comparing base (9ba6c26) to head (90e5d49).
⚠️ Report is 2 commits behind head on main.

Files with missing lines Patch % Lines
...app/tauri/notification/TauriNotificationManager.kt 0.00% 110 Missing ⚠️
.../java/app/tauri/notification/NotificationPlugin.kt 1.42% 69 Missing ⚠️
src/commands.rs 0.00% 36 Missing ⚠️
src/desktop.rs 0.00% 25 Missing ⚠️
...c/main/java/app/tauri/notification/Notification.kt 25.00% 15 Missing ⚠️
...i/notification/TauriUnifiedPushMessagingService.kt 93.22% 2 Missing and 2 partials ⚠️
.../main/java/app/tauri/notification/JSObjectUtils.kt 93.18% 0 Missing and 3 partials ⚠️
...java/app/tauri/notification/NotificationStorage.kt 60.00% 1 Missing and 1 partial ⚠️
Additional details and impacted files
@@             Coverage Diff              @@
##               main     #123      +/-   ##
============================================
- Coverage     57.90%   56.25%   -1.66%     
- Complexity       65      111      +46     
============================================
  Files            29       31       +2     
  Lines          5096     5475     +379     
  Branches        232      303      +71     
============================================
+ Hits           2951     3080     +129     
- Misses         2111     2355     +244     
- Partials         34       40       +6     
Flag Coverage Δ
android 29.79% <34.09%> (+1.62%) ⬆️
ios 78.60% <ø> (ø)
javascript 100.00% <100.00%> (ø)
macos 64.65% <100.00%> (-0.03%) ⬇️
rust 45.31% <7.57%> (-2.60%) ⬇️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR adds UnifiedPush as an optional backend for push notifications on Android, providing an alternative to FCM for devices without Google Play Services (e.g., Fairphone with de-Googled ROMs). It is gated behind a new unified-push Cargo feature flag that defaults to disabled.

Changes:

  • Adds 5 new Tauri commands (registerForUnifiedPush, unregisterFromUnifiedPush, getUnifiedPushDistributors, saveUnifiedPushDistributor, getUnifiedPushDistributor) implemented in Kotlin and exposed via the Rust/JS layer across all platforms (Android implementation, unsupported-platform stubs on iOS/macOS/desktop)
  • Adds Android receiver TauriUnifiedPushMessagingService to handle UnifiedPush lifecycle events (new endpoint, messages, unregistration, errors), plus a public UnifiedPushMessageHandler interface for custom message handling
  • Updates the build system, permissions, TypeScript API, and documentation to cover the new functionality

Reviewed changes

Copilot reviewed 25 out of 25 changed files in this pull request and generated 11 comments.

Show a summary per file
File Description
src/models.rs Adds UnifiedPushEndpointResponse, UnifiedPushDistributorsResponse, and UnifiedPushDistributorResponse Rust structs (feature-gated)
src/mobile.rs Implements the 5 new UnifiedPush methods on mobile, gated by #[cfg(feature = "unified-push")]
src/macos.rs Adds stub methods that return "only supported on Android" errors
src/desktop.rs Adds stub methods that return "not supported on desktop" errors
src/commands.rs Adds Tauri command handlers for the 5 UnifiedPush operations
src/lib.rs Registers the 5 new commands with the plugin
build.rs Writes enableUnifiedPush to android/build.properties based on the Cargo feature flag
android/build.gradle.kts Reads enableUnifiedPush property, adds BuildConfig.ENABLE_UNIFIED_PUSH, adds JitPack dependency
android/settings.gradle Adds JitPack Maven repository
android/src/main/AndroidManifest.xml Registers TauriUnifiedPushMessagingService as an exported broadcast receiver
android/src/main/java/.../NotificationPlugin.kt Implements the 5 UP commands, permission handling, and callbacks; adds getNotificationManager() helper
android/src/main/java/.../TauriUnifiedPushMessagingService.kt New BroadcastReceiver that dispatches UnifiedPush events to NotificationPlugin and runs the fallback notification path
android/src/main/java/.../UnifiedPushMessageHandler.kt New public interface for custom message handling
android/src/main/java/.../TauriNotificationManager.kt Adds ic_notification drawable and app icon as additional small-icon fallbacks
guest-js/index.ts Adds TS types, function implementations, event listeners, and exports for the full UnifiedPush API
permissions/default.toml Adds all 5 new allow-* permission identifiers to the default set
permissions/schemas/schema.json Adds allow/deny schema entries for the 5 new commands
permissions/autogenerated/reference.md Auto-generated permission reference updated
permissions/autogenerated/commands/*.toml New per-command permission files for the 5 new commands
Cargo.toml Adds unified-push feature declaration and updates crate description
README.md Adds UnifiedPush setup, usage, and API reference documentation

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

@TastelessVoid TastelessVoid marked this pull request as draft March 8, 2026 12:37
@TastelessVoid TastelessVoid marked this pull request as ready for review March 8, 2026 12:57
Copilot AI review requested due to automatic review settings March 8, 2026 12:57
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 26 out of 26 changed files in this pull request and generated 4 comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Copilot AI review requested due to automatic review settings March 8, 2026 13:08
…n.kt

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
TastelessVoid and others added 2 commits March 8, 2026 14:14
…essagingService.kt

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
…essagingService.kt

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 26 out of 26 changed files in this pull request and generated 4 comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Copilot AI review requested due to automatic review settings March 9, 2026 13:56
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 28 out of 28 changed files in this pull request and generated 5 comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Copilot AI review requested due to automatic review settings March 9, 2026 14:40
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 28 out of 28 changed files in this pull request and generated 5 comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

@TastelessVoid TastelessVoid marked this pull request as draft March 9, 2026 17:28
Copilot AI review requested due to automatic review settings March 10, 2026 01:57
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 33 out of 33 changed files in this pull request and generated 8 comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Copilot AI review requested due to automatic review settings March 10, 2026 12:47
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 38 out of 38 changed files in this pull request and generated 4 comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Copilot AI review requested due to automatic review settings March 10, 2026 13:56
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 35 out of 35 changed files in this pull request and generated 3 comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

… enhance security by stripping auth tokens from JSON
@TastelessVoid TastelessVoid marked this pull request as ready for review March 10, 2026 14:24
Copilot AI review requested due to automatic review settings March 10, 2026 14:24
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 35 out of 35 changed files in this pull request and generated 4 comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +53 to +54
private val avatarExecutor: java.util.concurrent.ExecutorService = java.util.concurrent.Executors.newFixedThreadPool(4) { runnable ->
Thread(runnable).apply { isDaemon = true; name = "avatar-download" }
Copy link

Copilot AI Mar 10, 2026

Choose a reason for hiding this comment

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

The TauriNotificationManager class creates a background thread-pool executor avatarExecutor on instantiation (line 53) for downloading avatar images, and exposes a destroy() method (line 233) to shut it down. However, destroy() is never called in NotificationPlugin — there is no override of any lifecycle method (e.g., onStop, onDestroy) that invokes manager.destroy(). This means the executor's threads will persist until the process terminates, and in long-running applications this could prevent proper resource cleanup.

Copilot uses AI. Check for mistakes.
Comment on lines +188 to +191
val raw = BitmapFactory.decodeStream(connection.inputStream)
connection.disconnect()
if (raw == null) return@Callable null
cropCircle(raw)
Copy link

Copilot AI Mar 10, 2026

Choose a reason for hiding this comment

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

The submitAvatarDownload function downloads remote avatar images via HTTP connections and streams the response directly into BitmapFactory.decodeStream without any size limit check (line 188). A malicious or misconfigured server could return an extremely large image, leading to an OutOfMemoryError or significant memory pressure. Consider adding a Content-Length check before decoding, or use BitmapFactory.Options with inSampleSize / inJustDecodeBounds to limit the decoded image size.

Copilot uses AI. Check for mistakes.
Comment on lines +212 to +226
private fun prefetchAvatars(msgStyle: MessagingStyleConfig): Map<String, Bitmap?> {
val authToken = msgStyle.authToken
// Collect all unique URLs that need downloading
val urlsToDownload = mutableSetOf<String>()
msgStyle.user.iconUrl?.let { urlsToDownload.add(it) }
for (msg in msgStyle.messages) {
msg.sender?.iconUrl?.let { urlsToDownload.add(it) }
}
if (urlsToDownload.isEmpty()) return emptyMap()

// Submit all downloads in parallel
val futures = urlsToDownload.associateWith { url -> submitAvatarDownload(url, authToken) }

// Resolve all futures (total wait is ~10s max, not N×10s)
return futures.mapValues { (_, future) -> resolveAvatarFuture(future) }
Copy link

Copilot AI Mar 10, 2026

Choose a reason for hiding this comment

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

The prefetchAvatars function calls resolveAvatarFuture (line 226) which blocks the calling thread for up to 10 seconds per batch. When this is called from buildNotification (which itself can be called on the main thread), this blocking network call can trigger an Android Application Not Responding (ANR) error. The notification-building path should either offload the entire operation to a background thread (e.g., using a coroutine or AsyncTask-style mechanism) before calling buildNotification, or the avatar download should happen entirely asynchronously and the notification should be updated once the download completes.

Copilot uses AI. Check for mistakes.
Comment on lines +59 to +90
#[command]
pub(crate) async fn unregister_from_unified_push<R: Runtime>(
_app: AppHandle<R>,
notification: State<'_, Notifications<R>>,
) -> Result<()> {
notification.unregister_from_unified_push()
}

#[command]
pub(crate) async fn get_unified_push_distributors<R: Runtime>(
_app: AppHandle<R>,
notification: State<'_, Notifications<R>>,
) -> Result<serde_json::Value> {
notification.get_unified_push_distributors()
}

#[command]
pub(crate) async fn save_unified_push_distributor<R: Runtime>(
_app: AppHandle<R>,
notification: State<'_, Notifications<R>>,
distributor: String,
) -> Result<()> {
notification.save_unified_push_distributor(distributor)
}

#[command]
pub(crate) async fn get_unified_push_distributor<R: Runtime>(
_app: AppHandle<R>,
notification: State<'_, Notifications<R>>,
) -> Result<serde_json::Value> {
notification.get_unified_push_distributor()
}
Copy link

Copilot AI Mar 10, 2026

Choose a reason for hiding this comment

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

The unregister_from_unified_push Rust command handler (in src/commands.rs, line 64) is declared as async but calls a synchronous method notification.unregister_from_unified_push(). While this works correctly, for consistency with other synchronous commands in the file (like cancel, create_channel etc. which are non-async), the async keyword is unnecessary here and also for get_unified_push_distributors (line 72), save_unified_push_distributor (line 81), and get_unified_push_distributor (line 89). These commands don't need to be async since their implementations return synchronously.

Copilot uses AI. Check for mistakes.
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.

3 participants