UI/UX Part 13 — Notifications, Background & Incoming Call UX Architecture
Reusable P2P Communication Platform
Status: UI/UX architecture specification
UI Series: Part 13
Desktop UI: Dioxus
Android UI: Kotlin + Jetpack Compose
Core runtime: Rust
Primary purpose: define message, call, security, transfer, emergency, background wake, notification privacy, grouping, deduplication, deep-linking, foreground-vs-background behavior, and platform notification UX across desktop and Android.
1. Purpose
Notifications sit at the boundary between the communication product and the operating system.
They must work correctly when:
the app is foregrounded
the app is backgrounded
the Activity is destroyed
the desktop window is hidden
the desktop UI is closed but daemon remains
the device is locked
notification permission is denied
multiple devices receive the same event
a call arrives
a message arrives while viewing another conversation
a message arrives while already viewing that conversation
a security event occurs
a transfer finishes
emergency traffic arrives
The governing principle is:
Rust decides notification meaning and privacy; platform code decides how that meaning is presented through the operating system.
2. Architectural Position
Rust Event / Notification Policy
│
├── semantic event
├── urgency
├── privacy class
├── dedup key
├── actions
└── destination
│
▼
Notification Presentation Service
│
┌─────┴─────┐
│ │
Desktop Android
Adapter Adapter
│ │
Native OS NotificationManager
Notification Foreground Service
Tray Full-screen call surface
3. Notification Is Not Domain Truth
A notification is a projection.
Deleting/dismissing it must not delete:
message
call history
security event
transfer record
unless the notification action explicitly invokes such a command.
4. Notification Categories
Recommended:
#![allow(unused)] fn main() { pub enum NotificationCategory { Message, Mention, MessageRequest, IncomingCall, MissedCall, Security, Transfer, Backup, Emergency, System, } }
5. Notification Priority
#![allow(unused)] fn main() { pub enum NotificationUrgency { Passive, Normal, High, Critical, } }
Examples:
Passive → transfer complete
Normal → ordinary message
High → mention / incoming call
Critical → emergency / severe security event
6. Privacy Classes
#![allow(unused)] fn main() { pub enum NotificationPrivacy { Full, SenderOnly, Generic, Hidden, } }
7. Full Preview
May show:
Alice
See you at 5 PM
8. Sender-Only Preview
Shows:
Alice
New message
9. Generic Preview
Shows:
New message
without identity.
10. Hidden
No content-bearing notification.
May still update badge/count depending settings.
11. Lockscreen Privacy
Platform adapter combines:
Rust privacy policy
+
OS lockscreen policy
+
user setting
using the strictest effective result.
12. App Foreground State
Rust/platform tracks semantic presentation state:
Foreground
Background
Hidden
NoUI
Locked
13. Focused Conversation Suppression
If user is actively viewing the same conversation and relevant message is visible:
do not show redundant OS notification
Use:
in-app update
optional subtle banner
14. Different Conversation While Foreground
If user is in app but another conversation receives a message:
in-app banner
can be preferred over OS notification.
15. Background
Use OS notification according to policy.
16. Desktop Hidden to Tray
Treat as background for notification purposes.
17. Desktop Main Window Visible but Unfocused
Usually OS/native notification may still be useful.
Policy can distinguish:
visible + focused
visible + unfocused
hidden
18. Notification Policy Input
#![allow(unused)] fn main() { pub struct NotificationContext { pub app_visibility: AppVisibility, pub active_destination: Option<UiDestination>, pub device_locked: bool, pub notification_permission: NotificationPermissionState, } }
19. Notification Intent
#![allow(unused)] fn main() { pub struct NotificationIntent { pub id: NotificationId, pub category: NotificationCategory, pub urgency: NotificationUrgency, pub privacy: NotificationPrivacy, pub title: NotificationText, pub body: Option<NotificationText>, pub badge_delta: Option<i32>, pub destination: Option<UiDestination>, pub actions: Vec<NotificationActionView>, pub dedup_key: NotificationDedupKey, } }
20. Notification Text
Rust should provide semantic/localizable payloads where possible.
Do not force English strings from core.
Example:
#![allow(unused)] fn main() { pub enum NotificationText { MessageFrom { sender: DisplayName }, NewMessage, MissedCallFrom { sender: DisplayName }, SecurityAlert, } }
Platform/UI localizes.
21. Android Notification Channels
Recommended stable channels:
Messages
Mentions
Calls
Security
Transfers
Emergency
Background/System
22. Channel Stability
Once created, Android channel identity should remain stable across updates.
23. User-Controlled Channel Settings
Android users may change:
sound
vibration
importance
lock-screen visibility
The app should respect system ownership.
24. Android Notification Permission
Request contextually.
Do not request on first launch solely because permission exists.
25. Recommended Permission Timing
Ask when user enables or first meaningfully needs:
message alerts
background calling
with explanation.
26. Permission Denied
App remains usable.
Explain:
You may miss message and call alerts while the app is not open.
27. Permanently Denied
Offer:
Open Settings
28. Notification Permission Diagnostics
Settings/diagnostics can show:
Allowed
Denied
Blocked by system
29. Desktop Notification Permissions
Where desktop environment supports permission controls, adapter reports capability/state.
30. Message Notification
Normal message notification may show:
sender
conversation
preview
according to privacy mode.
31. Group Message Notification
Possible title:
Alice · Project Group
body:
New deadline is Friday
32. Mention Notification
May have higher urgency than normal group message.
33. Muted Conversation
No ordinary message notification.
Mentions may bypass only if user setting permits.
34. Message Request Notification
Privacy-conscious:
New message request
rather than automatically revealing unknown sender/content.
35. Unknown Attachment Notification
Do not show risky filename/content preview if privacy/security policy disallows.
36. Notification Grouping — Android
Group by conversation where possible.
Example:
Project Group
Alice: ...
Bob: ...
37. Notification Summary
For many conversations:
5 new messages from 3 conversations
38. Desktop Grouping
Native environment dependent.
If unsupported, keep dedup/burst control in application layer.
39. Notification Burst Coalescing
Rapid messages from same conversation should not produce disruptive sound for every event.
40. Burst Policy
Example:
first message → sound
subsequent messages within short window → update existing notification
41. Deduplication
Every logical notification event has stable dedup key.
#![allow(unused)] fn main() { pub enum NotificationDedupKey { Message(MessageId), Call(CallId), Security(SecurityEventId), Transfer(TransferId), Backup(BackupJobId), Emergency(EmergencyEventId), } }
42. Duplicate Delivery Paths
If same message arrives via:
direct
relay
DTN
only one notification.
43. Multi-Device Notification Semantics
Each user device may notify independently.
Cross-device suppression is optional advanced policy.
44. Read on Another Device
If message becomes read elsewhere:
local notification may be dismissed/updated
if synchronization arrives.
45. Answered Elsewhere
Incoming call notification must disappear when another device answers.
46. Declined Elsewhere
Policy may dismiss other ringing devices.
47. Deep-Link Routing
Notification action never routes using raw unvalidated string.
Flow:
notification
→ typed destination
→ Rust validates target still exists/authorized
→ navigate
48. Message Destination
Conversation(ConversationId)
optionally with:
MessageId
49. Call Destination
Call(CallId)
50. Security Destination
SecurityEvent(SecurityEventId)
51. Transfer Destination
Transfer(TransferId)
52. Cold Start — Android
Tap notification with app dead:
Activity starts
→ Rust runtime initializes
→ launch action retained
→ core Ready
→ validate destination
→ navigate
53. Pending Launch Action
#![allow(unused)] fn main() { pub enum PendingLaunchAction { OpenConversation { conversation: ConversationId, message: Option<MessageId>, }, OpenCall(CallId), OpenSecurityEvent(SecurityEventId), OpenTransfer(TransferId), OpenEmergency(EmergencyEventId), } }
54. Stale Destination
If target no longer exists:
show safe fallback
Example:
Message is no longer available
55. Android Background Wake
A push/wake signal is not trusted message content.
Correct flow:
Push wake
→ wake/schedule Rust
→ authenticate/fetch/process event
→ decide notification
56. Do Not Render Push Payload Directly
Hard rule for sensitive events.
57. Push as Hint
Push may contain:
opaque wake token
account/device routing hint
but not authoritative message body.
58. Background Catch-Up
When device wakes:
sync/fetch pending events
persist durably
evaluate notification policy
59. UI Not Required
Background receive must work without Compose Activity.
60. Background Event Persistence
Message is persisted before notification if possible.
Then notification tap always has durable target.
61. Background Retry
If wake cannot complete:
retry according to platform policy
without duplicate notification.
62. Android Process Death
Notification tap launches fresh process and reconstructs state from Rust durability.
63. Desktop Daemon Mode
Daemon can receive events and ask notification adapter to alert even if Dioxus UI is closed.
64. Desktop Embedded Mode
If core dies with UI, no background notifications until app running.
Product should communicate this in settings if relevant.
65. System Tray
Recommended desktop actions:
Open App
New Message
Active Call
Mute Notifications temporarily
Quit
66. Tray Badge
Optional unread count.
67. Dock/Taskbar Badge
Can show unread aggregate where platform supports.
68. Badge Count
Derived from durable unread state.
Not independently incremented by notification events.
69. Mark Read from Notification
Optional action:
Mark Read
Rust advances local/account read state according to semantics.
70. Reply from Notification
Future optional.
If implemented:
text input
→ authenticated app/service
→ Rust SendMessageCommand
No direct OS-to-network path bypassing Rust.
71. Notification Reply Security
Respect:
device lock
app lock
privacy setting
May disable quick reply on lock screen.
72. Incoming Call — Android
Critical flow:
wake signal
→ Rust authenticates call offer
→ CallState = Incoming
→ Android call notification / full-screen surface
73. Do Not Ring on Unauthenticated Push
Hard rule.
74. Incoming Call Notification
Shows:
caller identity
Audio call / Video call
Accept
Decline
according to privacy policy.
75. Full-Screen Incoming Call
Use only where Android platform policy permits and product qualifies.
Otherwise:
high-priority heads-up notification
76. Lock-Screen Call
Must respect privacy setting.
Strict mode:
Incoming call
without caller identity.
77. Accept from Notification
Flow:
PendingIntent
→ service/activity receiver
→ Rust CallController.accept(CallId)
→ foreground call service
→ optional full call UI
78. Decline from Notification
Can execute without launching full Activity where platform allows.
79. Dismiss Incoming Call Notification
Do not necessarily equal decline.
Recommendation:
swipe/dismiss → silence local alert
while backend call remains until timeout unless product explicitly maps dismissal to decline.
80. Silence Call
Optional action:
Silence
without rejecting peer.
81. Missed Call
After timeout/no answer:
Missed call from Alice
with:
Call back
Message
where allowed.
82. Call Answered Elsewhere
Remove missed-call possibility on current device if another device answered.
83. Desktop Incoming Call
If app visible:
in-app call surface
plus optional native notification if unfocused.
If hidden:
native notification
+
ring sound
+
optional floating incoming-call window
84. Desktop Accept
Raises/creates call window.
85. Desktop Decline
No need to open main app.
86. Ongoing Call Notification — Android
Foreground service notification persists while call active.
87. Ongoing Call Actions
Potential:
Mute
Hang Up
Return to Call
88. Ongoing Call Privacy
Lock-screen content can be generic.
89. Active Call + Incoming Message
Do not disrupt with loud notification by default.
Possible:
quiet heads-up/banner
90. Call Priority
Realtime call audio has priority over ordinary notification sounds.
91. Notification Sound During Call
Prefer:
soft/none
for ordinary messages.
Emergency/security policy may override.
92. Transfer Notifications
Notify only when useful.
Examples:
large transfer completed
transfer failed
waiting for action
Do not notify every small auto-downloaded image.
93. Active Transfer Notification Android
Long user-visible transfer may show ongoing progress.
94. Transfer Complete
Potential:
File downloaded
Open
95. Transfer Failure
Download failed
Retry
if retryable.
96. Backup Notification
Useful for:
backup failed
backup completed if user initiated
recovery attention required
Avoid noise for routine successful background backups unless user opted in.
97. Security Notification
Examples:
New device linked
Identity changed
Device revoked
Verification problem
Suspicious link attempt
98. Security Urgency
Meaningful security events should not be hidden inside ordinary message channel.
Use dedicated Security channel/category.
99. Security Preview
May intentionally show generic:
Security alert
Open the app to review
on lock screen.
100. Emergency Notifications
Part 17.
Critical emergency events may:
override ordinary mute policy
only if user/product policy explicitly allows.
101. Emergency Channel
Dedicated.
User should understand behavior in settings.
102. Emergency False Positive Prevention
Only authenticated, policy-approved emergency events reach critical notification UX.
103. Notification Settings
Recommended hierarchy:
Messages
Mentions
Calls
Requests
Security
Transfers
Emergency
Preview Privacy
Sound/Vibration
Quiet Hours
Per-Conversation Overrides
104. Android Settings Relationship
Some sound/importance controls live in Android system channels.
App should link:
Open Android Notification Settings
rather than pretending to override system state.
105. Desktop Settings
App can own more behavior directly.
106. Per-Conversation Notification Policy
#![allow(unused)] fn main() { pub enum ConversationNotificationPolicy { All, Mentions, Muted, } }
107. Mute Duration
Potential:
1 hour
8 hours
1 day
1 week
Forever
108. Quiet Hours
Optional local preference:
start
end
days
exceptions
109. Quiet Hours Exceptions
Potential:
Calls
Security
Emergency
Favorite contacts
Mentions
110. Timezone
Quiet hours use device/local configured time.
111. Device-Local Policy
Some notification preferences are device-specific.
Examples:
sound
vibration
lock-screen preview
quiet hours
112. Account-Wide Policy
Potentially sync:
conversation mute
mention policy
113. Do Not Sync OS Channel Configuration
Android channel sound/importance is platform/device-local.
114. Notification Preview Setting
Recommended:
Show sender and message
Show sender only
Show generic notification
115. Lock-Screen Override
Separate:
Hide previews on lock screen
116. App Lock Integration
If app locked:
strictest preview policy
can apply.
117. Screen Sharing Integration
While screen sharing:
temporarily hide notification previews
optional privacy setting.
118. Desktop Screen Share
Could suppress native popup previews while sharing.
119. Do Not Lose Events
Suppressing notification visual does not suppress durable event.
120. Foreground In-App Banner
For message in another conversation:
avatar
sender/group
preview
Tap to open
121. Banner Duration
Short and non-blocking.
122. Banner Stacking
Do not stack dozens.
Queue/coalesce.
123. In-App Security Banner
May persist until reviewed.
124. In-App Emergency Banner
May be persistent/high priority.
125. Notification Center Inside App
Optional future:
Activity / Alerts
for security/system events.
Not required for ordinary message notification history.
126. Desktop Notification Click
Routes to typed destination.
Raises existing single-instance window.
127. Single-Instance Integration
If desktop app already running:
notification click
→ existing instance
→ typed navigation
128. Desktop UI Closed but Daemon Running
Click notification:
launch/attach UI
→ validate destination
→ open target
129. Notification Action Capability
Rust provides allowed actions.
#![allow(unused)] fn main() { pub enum NotificationActionView { Open, MarkRead, Reply, AcceptCall, DeclineCall, RetryTransfer, ReviewSecurity, } }
130. UI Must Not Invent Actions
Example:
AcceptCall
only if Rust says call is still incoming.
131. Stale Action
If user taps Accept after call ended:
safe no-op
+
show call ended
132. Idempotency
Notification actions use stable command IDs/CallId/MessageId.
Repeated OS delivery does not duplicate action.
133. Notification Cancellation
Rust can emit:
Cancel NotificationId
when event no longer relevant.
134. Examples
message read elsewhere
call answered elsewhere
transfer completed and opened
security issue resolved
135. Notification Update
Existing notification can be updated rather than replaced.
136. Android Group Summary Update
Conversation notification updates with latest messages.
137. Desktop Burst Update
If native API supports replace-ID, reuse notification identity.
138. Background Work States
#![allow(unused)] fn main() { pub enum BackgroundUiState { Idle, Syncing, Receiving, Reconnecting, Paused, Degraded, } }
139. Normal Background Sync
Usually invisible.
140. Persistent Background Indicator
Do not keep permanent "syncing" notification for ordinary app operation unless Android foreground-service rules require a visible user-facing operation.
141. Long-Running User Operation
Examples:
active call
large transfer
explicit backup
may justify persistent notification.
142. Work Manager / Scheduler Boundary
Android scheduling mechanism is platform implementation.
Rust owns semantic job state.
143. Battery Saver
May delay non-critical background fetch.
UI generally does not warn unless messages are being delayed significantly.
144. Background Restricted
If Android has heavily restricted app:
Background delivery may be delayed
diagnostics/settings can explain.
145. Battery Optimization Education
Do not aggressively ask user to disable battery optimization on first launch.
Only surface if real delivery problems occur and platform permits guidance.
146. Push Token State
Not user-facing normally.
Diagnostics can show:
Registered
Unavailable
Error
147. No Push Provider Detail in Normal UX
Users do not need:
FCM token
APNs equivalent
in everyday UI.
148. Background Catch-Up Indicator
On returning after long offline period:
Syncing recent messages…
small status if catch-up takes noticeable time.
149. Local History First
Existing messages render immediately while background catch-up continues.
150. Notification-to-Read Semantics
Showing a notification does not mean message read.
151. Notification Tap
Opening conversation may later advance read cursor based on actual visibility.
152. Notification Dismissal
Does not mark read by default.
153. Mark Read Action
Explicit action only.
154. Notification Reply
If implemented, successful send does not necessarily mark all incoming messages read unless policy explicitly says.
155. Message Request Notification Tap
Opens request view, not trusted conversation directly.
156. Security Notification Tap
Opens security event details.
157. Emergency Notification Tap
Opens dedicated emergency surface.
158. Notification Accessibility
Title/body/actions must be meaningful without relying on icons.
159. Android TalkBack
Actions:
Accept call
Decline call
Mark read
must be clearly labeled.
160. Desktop Screen Reader
Native notification accessibility is OS-dependent; app in-focus banners must be fully accessible.
161. In-App Banner Focus
Do not steal keyboard focus for ordinary message banner.
162. Critical Alert Focus
Security/emergency may request attention but should still avoid disruptive forced focus unless policy demands.
163. Large Font
In-app banners/settings wrap cleanly.
164. RTL
Notification localized text and in-app banners support RTL.
165. Reduced Motion
Banner entrance/exit animations optional.
166. Color Independence
Urgency/security states use text/icon, not color only.
167. Notification Sound Accessibility
Visual/vibration alternatives should exist.
168. Vibration
Respect OS/user settings.
169. Desktop Quiet Mode
System Do Not Disturb should generally be respected.
170. Android Do Not Disturb
App must not bypass DND unless explicitly permitted and justified.
171. Critical/Emergency Override
Any bypass capability must be explicit, narrow, user-controlled, and platform-compliant.
172. Notification Telemetry
Do not log:
message body
sender name
notification preview text
by default.
173. Safe Metrics
Possible:
notification generated
notification suppressed due to foreground
notification permission state
tap/open latency
call answer latency
without identities/content.
174. Crash Reports
Redact notification contents.
175. Notification Presentation API
#![allow(unused)] fn main() { pub trait NotificationPresentation { async fn evaluate( &self, event: NotificationEvent, context: NotificationContext, ) -> Result<NotificationDecision, UiError>; async fn action( &self, notification: NotificationId, action: NotificationActionView, ) -> Result<NotificationActionResult, UiError>; async fn dismissed( &self, notification: NotificationId, ) -> Result<(), UiError>; } }
176. Notification Decision
#![allow(unused)] fn main() { pub enum NotificationDecision { Suppress, InApp(InAppNotificationView), System(NotificationIntent), Both { in_app: InAppNotificationView, system: NotificationIntent, }, } }
Use Both sparingly.
177. Notification Event
#![allow(unused)] fn main() { pub enum NotificationEvent { Message(MessageNotificationEvent), IncomingCall(IncomingCallNotificationEvent), MissedCall(MissedCallNotificationEvent), Security(SecurityNotificationEvent), Transfer(TransferNotificationEvent), Backup(BackupNotificationEvent), Emergency(EmergencyNotificationEvent), } }
178. Background Wake API
#![allow(unused)] fn main() { pub trait BackgroundWakePresentation { async fn process_wake( &self, wake: BackgroundWakeToken, ) -> Result<BackgroundWakeResult, UiError>; } }
Platform adapters never interpret private event content before Rust.
179. Notification Events to Platform
#![allow(unused)] fn main() { pub enum NotificationUiEvent { Show(NotificationIntent), Update(NotificationIntent), Cancel(NotificationId), BadgeChanged(u32), } }
180. Android Platform Adapter
Responsibilities:
channels
permission
NotificationManager
PendingIntent
foreground service notification
full-screen call eligibility
lock-screen visibility
system badge support
181. Compose ViewModel
Owns:
in-app banners
notification permission education UI
settings navigation effects
It does not own OS notification truth.
182. Desktop Adapter
Responsibilities:
native notifications
tray
taskbar/dock badge
single-instance activation
window raise
183. Dioxus Presenter
Owns:
in-app banner stack
notification settings presentation
tray-related UI state
184. No Direct OS Notification from Domain Actors
Hard boundary:
domain event
→ notification policy
→ platform adapter
185. Notification Settings Snapshot
#![allow(unused)] fn main() { pub struct NotificationSettingsView { pub message_policy: MessageNotificationPolicy, pub call_enabled: bool, pub request_enabled: bool, pub transfer_policy: TransferNotificationPolicy, pub security_enabled: bool, pub emergency_policy: EmergencyNotificationPolicy, pub preview_policy: NotificationPreviewPolicy, pub quiet_hours: Option<QuietHoursView>, } }
186. Per-Conversation Policy
Conversation settings override global message policy within allowed rules.
187. System-Level Conflict
If app says notifications enabled but Android channel disabled:
show system-disabled state
Open Android Settings
188. Permission Education Screen
Keep concise:
Allow notifications to receive message and call alerts while the app is closed.
189. Incoming Call Reliability Warning
If notification permission/call channel unavailable:
Incoming calls may not alert you when the app is in the background.
190. Diagnostics
Useful status:
Notification permission
Calls channel
Message channel
Push wake state
Background restriction
Foreground call service
Last successful background sync
191. Do Not Show Internal Tokens
No raw push token.
192. Notification History Debug
Developer mode can show:
NotificationId
category
decision
suppression reason
with content redacted.
193. Suppression Reasons
#![allow(unused)] fn main() { pub enum NotificationSuppressionReason { ActiveConversationVisible, ConversationMuted, QuietHours, AppLockedPolicy, PermissionDenied, Duplicate, AlreadyRead, AnsweredElsewhere, PolicyDisabled, } }
194. User-Friendly Diagnostics
Examples:
Muted
Notifications disabled by Android
Suppressed because conversation is open
195. Testing Matrix
Required:
foreground same conversation
foreground different conversation
background message
locked device
muted conversation
mention
message request
incoming call
accept from notification
decline from notification
missed call
answered elsewhere
transfer completion
security alert
emergency alert
permission denied
quiet hours
196. Android Tests
Verify:
runtime notification permission
channel disabled
cold-start notification tap
process death
foreground service call
heads-up call
full-screen call where allowed
lock-screen privacy
background wake
notification action idempotency
197. Desktop Tests
Verify:
focused window suppression
unfocused notification
hidden-to-tray notification
daemon-only delivery
notification click
single-instance activation
tray badge
taskbar/dock badge
198. Duplicate Event Test
Same MessageId via multiple transports:
one notification
199. Multi-Device Read Test
Read on phone:
desktop notification disappears/updates
if synchronized before user acts.
200. Answered Elsewhere Test
Incoming call on two devices.
One answers.
Other notification cancels immediately.
201. Stale Action Test
Tap Accept after call ended.
No crash/no new call.
202. Permission Denial Test
App stays usable.
Settings shows degraded background alerts.
203. Quiet Hours Test
Ordinary message suppressed.
Allowed exception still alerts.
204. Privacy Test
Strict lock-screen setting never exposes sender/message.
205. Screen Share Privacy Test
Preview suppression activates/restores correctly.
206. Background Wake Security Test
Forged push hint cannot produce trusted message/call notification without Rust authentication.
207. Accessibility Test
Incoming call and message actions are usable with screen reader.
208. Performance
Notification decision path should be lightweight.
Do not perform expensive search/index operations before ordinary notification.
209. Burst Performance
100-message burst should:
coalesce
avoid 100 sounds
avoid 100 platform objects
210. Background Energy
Wake only as often as required.
Batch non-urgent catch-up where possible.
211. Foreground Call Priority
Call media work outranks notification rendering.
212. Initial Production Scope
Ship:
message notifications
group/mention notifications
message requests
incoming call notification
accept/decline
missed call
security alerts
transfer failure/completion where useful
Android channels + runtime permission
foreground call service notification
desktop native notifications + tray
privacy previews
foreground suppression
deep links
deduplication
quiet/mute policies
Defer:
rich inline reply
complex notification history center
cross-device smart suppression heuristics
critical-alert DND bypass
advanced wearable integrations
unless explicitly required.
213. Definition of Done
UI/UX Part 13 is complete when:
- Rust decides notification semantics, privacy, urgency, deduplication, and actions
- platform adapters own OS-specific notification APIs
- same-conversation foreground messages do not produce redundant OS notifications
- message/group/mention/request notification behavior is explicit
- Android channels and runtime notification permission are defined
- lock-screen preview privacy has Full/SenderOnly/Generic/Hidden semantics
- background push/wake data is treated as a hint and authenticated by Rust before notification
- incoming calls never ring solely from unauthenticated push metadata
- accept/decline notification actions route through Rust CallController
- foreground-call service and ongoing-call notification behavior are defined
- desktop focused/unfocused/hidden/daemon notification behavior is defined
- notification clicks use typed validated destinations
- badge counts derive from durable unread state rather than notification counters
- dismissal does not imply read
- muting, mentions, quiet hours, security, transfer, backup, and emergency categories are distinct
- duplicate delivery and multi-device answered/read events can cancel/update notifications
- accessibility, lock-screen privacy, DND respect, RTL, and large font are explicit
- notification content is excluded from telemetry/crash logs by default
- notification/background-wake presentation APIs are defined
- cold-start, process-death, duplicate, stale-action, permission-denied, and privacy tests are specified
214. Final Architecture
RUST DOMAIN EVENTS
│
▼
Notification Policy Engine
│
┌──────────────────┼──────────────────┐
│ │ │
Meaning Privacy Actions
│ │ │
└──────────────────┼──────────────────┘
│
NotificationIntent
┌─────────┴─────────┐
│ │
Desktop Android
│ │
Native Notification NotificationManager
Tray / Badge Channels
Single Instance Foreground Service
Incoming Call Surface
Background receive:
Opaque Wake Hint
│
▼
Rust Authenticate / Sync
│
▼
Persist Durable Event
│
▼
Notification Policy
Never:
Push payload
→ directly display private message/call
215. Final Principle
Notifications should be useful without becoming a second, less-secure communication system.
The correct model is:
authenticated durable event
+
Rust privacy/policy decision
+
platform-native presentation
+
typed action/deep-link routing
not:
whatever the push payload says is shown to the user
This gives Dioxus desktop and Android Compose reliable foreground/background behavior while preserving the Rust core as the source of truth for messages, calls, security, and notification meaning.