UI/UX Part 07 — Calls & Realtime Media UX Architecture
Reusable P2P Communication Platform
Status: UI/UX architecture specification
UI Series: Part 07
Desktop UI: Dioxus
Android UI: Kotlin + Jetpack Compose
Core runtime: Rust
Primary purpose: define the complete user-facing call and realtime media experience across desktop and Android, including incoming/outgoing call UX, ringing, connecting, active-call controls, audio/video routing, screen sharing, reconnect states, call waiting, hold/resume, Picture-in-Picture, floating desktop call windows, media quality presentation, permissions, accessibility, lifecycle recovery, and the Rust presentation contract that drives both UIs.
1. Purpose
Realtime communication is one of the most failure-sensitive parts of the product.
A call UI must remain understandable when:
peer is ringing
peer accepts
media initializes slowly
network changes
video fails
audio route changes
camera permission is denied
Bluetooth connects/disconnects
screen sharing starts
call reconnects
another call arrives
app backgrounds
Activity recreates
desktop window closes
The governing principle is:
The UI represents one logical call session even while transport paths, codecs, surfaces, routes, and platform windows change underneath it.
2. Architectural Position
Rust Call Controller
│
├── CallState
├── Participant State
├── Media State
├── Security State
├── Reconnect State
└── Quality State
│
▼
Call Presentation Service
│
┌────┴─────┐
│ │
Dioxus Compose
Desktop Android
Platform services:
Desktop:
windows
audio-device chooser
screen capture
notifications
Android:
foreground service
PiP
audio route
camera/microphone permissions
notification actions
3. Core Call UX States
#![allow(unused)] fn main() { pub enum CallUiState { Incoming, OutgoingRinging, Negotiating, Connecting, Active, Reconnecting, Held, Ending, Ended, Failed, } }
These should map directly from Part 29 call semantics.
4. Call UI Must Not Infer State
Bad:
no media packets for 2 seconds
→ UI assumes call ended
Correct:
Rust CallController
→ state update
→ UI reflects state
5. Shared Call Snapshot
#![allow(unused)] fn main() { pub struct CallScreenSnapshot { pub call_id: CallId, pub state: CallUiState, pub peer: CallPeerView, pub kind: CallKind, pub duration: Option<Duration>, pub media: CallMediaView, pub controls: CallControlAvailability, pub quality: CallQualityView, pub security: CallSecurityView, } }
6. Incoming Call UX
Must show:
caller identity
avatar
audio/video type
verification state if relevant
Accept
Decline
Optional:
Message
Remind me later
later.
7. Caller Identity
Display comes from authenticated contact/account mapping.
Never trust arbitrary call-offer display name.
8. Unknown Caller
Clearly show:
Unknown caller
or:
Message request caller
with reduced trust visual language.
9. Incoming Call Security Warning
If identity changed/unverified:
Identity changed
should be visible before accept if security policy requires.
10. Incoming Video Call
Show:
Video call
but camera should not activate before user accepts.
11. Incoming Audio Call
No camera resources allocated.
12. Android Incoming Call UX
Potential surfaces:
heads-up notification
full-screen intent where policy/platform allows
lock-screen call UI
Compose full call screen
Actual use depends Android rules and user notification permission.
13. Desktop Incoming Call UX
Possible:
desktop notification
in-app banner
floating incoming-call window
if app is visible.
14. Ringing Priority
A valid incoming call should be visually prominent.
But rate limits prevent abuse.
15. Accept
User action:
Accept
routes to:
Rust CallController.accept(CallId)
UI does not directly start media.
16. Accept Video Call
If camera permission missing:
accept audio first
then request/enable camera
or:
request permission before full video accept
depending product policy.
Recommendation:
accept call with audio if possible
request camera immediately afterward
to reduce connection delay.
17. Decline
Routes to Rust.
UI transitions to:
Ended / declined
18. Answered Elsewhere
If another device answers:
call UI closes
with optional small message:
Answered on another device
19. Outgoing Call UX
States:
Calling…
Ringing…
Connecting…
These should remain distinct.
20. Calling vs Ringing
Calling…
means:
offer sent / waiting for remote ringing state
Ringing…
means:
remote is actively being alerted
if protocol exposes it.
21. Outgoing Cancel
User can cancel before active.
Action:
Cancel
22. Busy
Show:
Busy
then end screen.
23. Declined
Show:
Call declined
24. Timeout
Show:
No answer
not generic failure.
25. Unsupported
Example:
Video is unavailable on this device
Offer:
Try audio call
if possible.
26. Negotiating State
Usually brief.
Do not expose:
codec negotiation
key exchange
path probing
to ordinary users.
Show:
Connecting…
unless diagnostic mode.
27. Active Call Screen
Core regions:
participant/media area
status/duration
quality/reconnect indicator
control bar
optional secondary controls
28. Audio Call Layout
Main focus:
avatar
name
duration
status
Controls:
Mute
Speaker/Audio Route
Video
More
Hang Up
29. Video Call Layout
Main focus:
remote video
local preview
participant overlays
controls
30. Local Preview
Small picture-in-picture-style overlay.
Draggable where useful.
31. Local Preview Disable
If local camera off:
avatar/placeholder
32. Camera Flip
Android:
front ↔ rear
through semantic command.
Desktop:
select camera
instead.
33. Camera Selection
Desktop may expose device chooser.
Android usually offers:
front/rear
rather than raw camera list.
34. Mute
Mute button must clearly reflect state:
Muted
Unmuted
35. Mute Action
Routes to Rust.
Audio backend handles capture behavior.
36. Video Toggle
Enable video
Disable video
without restarting logical call.
37. Hang Up
Always easy to find.
Use visually distinct destructive control.
38. Audio Route
Potential routes:
Earpiece
Speaker
Bluetooth
Wired headset
USB
depending platform.
39. Android Audio Route UX
Use:
bottom sheet
or compact route selector.
40. Desktop Audio Device UX
Separate:
Input device
Output device
in call settings / device menu.
41. Audio Route Changes
Should not interrupt call UI.
Display small transient:
Bluetooth headset connected
if useful.
42. Bluetooth Disconnect
If route changes automatically:
Audio switched to speaker
small snackbar/banner.
43. Screen Share
State:
Off
Starting
Active
Stopping
44. Android Screen Share
Requires OS capture consent.
Flow:
tap Share Screen
→ platform permission/capture prompt
→ result
→ Rust call command
45. Desktop Screen Share
May offer:
Entire Screen
Window
Region
through native platform capture UI.
46. Screen Share Indicator
Always clearly visible while active.
47. Privacy While Sharing
Notification preview policy may switch to:
Generic
during active share.
48. Screen Share Priority
UI should make clear:
screen share is active
and provide easy stop control.
49. Camera + Screen Share
If both active:
screen main
camera thumbnail
or vice versa depending use case.
50. Media Layout Switching
Possible layouts:
Remote Focus
Screen Share Focus
Grid
Speaker Focus
51. 1:1 Video
Default:
remote video fills available space
local preview floating
52. Small Group Call
Grid layout.
53. Active Speaker
For group calls:
highlight active speaker
from Part 26 VAD/audio levels.
54. Speaker Highlight Accessibility
Do not use color only.
Use:
border
label
screen-reader state
55. Group Participant Tile
Shows:
avatar/video
name
mute
connection state
56. Participant List
Optional panel/sheet.
57. Group Controls
Potential:
Mute
Video
Screen Share
Participants
More
Hang Up / Leave
58. Host Controls
Future:
remove participant
mute request
lock room
only if user has role.
59. Call Waiting
If another call arrives:
incoming call banner/sheet
over active call.
Options:
Decline
End current & answer
Hold current & answer
if hold supported.
60. Hold
Active call may enter:
On hold
61. Local Hold UX
Show:
Call on hold
Resume
62. Remote Hold UX
Show:
Alice put the call on hold
if protocol exposes.
63. Resume
Returns to active call without creating new CallId.
64. Reconnecting
One of the most important states.
Show:
Reconnecting…
without immediately ending call.
65. Reconnecting Layout
Keep:
participant identity
duration
mute/hangup controls
Visible.
Video may freeze/placeholder.
66. Reconnect Quality
Do not show misleading video as live if frozen.
Overlay:
Connection interrupted
67. Reconnect Recovery
When resumed:
remove overlay
continue same call
68. Reconnect Failure
After backend grace window:
Call ended — connection lost
69. Direct/Relay Changes
Ordinary users should not see:
Switched to relay
unless diagnostics.
Call remains visually continuous.
70. Quality Indicator
Simple semantic classes:
Excellent
Good
Fair
Poor
Reconnecting
71. Quality UI
Use small icon or label.
Only surface prominently when poor.
72. Advanced Diagnostics
Optional sheet:
codec
resolution
FPS
RTT
loss
jitter
route
hardware/software codec
73. Do Not Overload Normal UI
No packet-loss graph in standard call screen.
74. Video Quality Adaptation
Resolution/FPS can change silently.
Avoid visual notifications for every adaptation.
75. Audio Degradation
If backend drops video to preserve audio:
Video paused due to connection
small banner.
76. Audio-Only Fallback
If video becomes unavailable:
call continues as audio
77. Camera Failure
Show:
Camera unavailable
with:
Retry
Switch camera
Continue audio
where applicable.
78. Microphone Failure
Show:
Microphone unavailable
and keep receive-only call if meaningful.
79. Permission Denied — Camera
Do not end audio call.
Show:
Camera permission is required for video
Open Settings / Not now
80. Permission Denied — Microphone
Incoming call may become listen-only if supported.
Otherwise show clear limitation.
81. Android Permission Timing
Request only when user invokes:
video
microphone
screen share
82. Desktop Device Permission
Handle OS permission if platform requires.
83. Android Foreground Service
Active call persists through:
Activity background
screen off
navigation
as platform permits.
84. Foreground Service Notification
Shows:
ongoing call
mute
hang up
where supported.
85. Compose Activity Recreation
Call survives:
rotation
theme change
window resize
86. Activity Reattachment
New call screen requests:
CallScreenSnapshot
from Rust.
87. PiP
Video call may enter Picture-in-Picture.
88. PiP Trigger
Could enter when:
user presses Home
if active video call.
89. PiP Content
Minimal:
remote video
call state
with system-supported actions where useful.
90. PiP Controls
Avoid too many.
Possible:
Mute
Hang up
91. Return from PiP
Compose reconstructs full call UI from Rust state.
92. Audio Call Background
No full-screen UI required.
Ongoing-call notification/compact app bar sufficient.
93. Desktop Minimized Call
When navigating away:
persistent call bar
in main window.
94. Desktop Floating Call Window
Optional compact floating window.
95. Floating Window Contents
remote video/avatar
mute
video
return
hang up
96. Desktop Close Call Window
Should not automatically hang up.
Use explicit:
Hang up
97. Desktop Main Window Close
If configured to hide to tray:
call continues
98. Desktop Quit During Call
Confirmation:
End call and quit?
99. Android Back During Call
Back:
leave full call screen
call continues.
100. Android Home
Call continues through foreground service.
101. App Process Death During Call
If process hosting Rust call dies:
call ends
unless separate persistent native/service process architecture preserves it.
UI must not pretend otherwise.
102. App Restart After Crash
Show:
Call ended unexpectedly
in history if known.
103. Call Duration
Starts at:
connected/active
not outgoing ring start.
104. Duration Timer
UI timer derives from:
connected_at
No backend event every second.
105. Timer Efficiency
One local timer per active call screen is fine.
106. Incoming Call Timeout
UI closes when backend says:
timeout
107. Missed Call
After timeout:
Missed call
notification/history.
108. Call End Screen
Brief summary:
Call ended
Duration
Call back
Optional.
109. End Reasons
User-facing mappings:
Declined
Busy
No answer
Connection lost
Call ended
Security problem
110. Do Not Show Internal Errors
Avoid:
QUIC stream reset 0x1f
in normal UI.
111. Security Failure
Strong message:
Call ended because identity could not be verified
Review security
if applicable.
112. Device Revoked Mid-Call
Show:
Call ended for security reasons
113. Encryption Indicator
Normal UI can show:
End-to-end encrypted
in call info/details.
Not giant lock icon during whole call.
114. Verified Contact
Optional subtle verification badge near name.
115. Call Recording
Future optional feature.
If enabled:
visible recording indicator
must never be hidden.
116. Recording Consent
Product/legal policy determines participant notification.
117. Call Captions
Future.
Could show live captions if local speech recognition exists.
118. Captions Accessibility
If added:
font size
contrast
speaker labels
119. Call Transcription
Not part of v1.
Do not upload audio to cloud silently.
120. Accessibility — Call Controls
Every control needs:
label
state
action
Examples:
Mute microphone, off
Turn camera off
End call
121. Android TalkBack
Control bar order should be logical and stable.
122. Desktop Screen Reader
Focused control announces state.
123. Keyboard Shortcuts Desktop
Potential:
Ctrl/Cmd+Shift+M → Mute
Ctrl/Cmd+Shift+V → Video
Ctrl/Cmd+Shift+S → Screen share
Ctrl/Cmd+Shift+H → Hang up
124. Shortcut Discoverability
Show in:
tooltips
menu
keyboard shortcut reference
125. Android Accessibility Actions
No feature should require:
drag-only
swipe-only
126. Large Touch Targets
Call controls must be easy to hit.
Especially:
Hang Up
Mute
127. Color Independence
Muted/connected/reconnecting states need:
icons
labels
shape
not color alone.
128. Large Font
Name/status/control labels must remain usable.
Video can shrink to preserve controls.
129. Landscape Android
Controls may move to side/bottom based on available space.
130. Tablet Call Layout
Potential:
large media region
participant panel
controls
131. Foldable Call Layout
Use hinge-aware placement.
132. Desktop Wide Layout
Can show:
video
participant list
chat side panel
if call-chat integration added.
133. In-Call Chat
Future optional.
Could expose existing conversation in side panel.
No separate message system.
134. Call + Conversation
Desktop can open conversation inspector beside call.
Android can offer:
Open chat
sheet/destination without ending call.
135. Media Device Selector Desktop
Can be in:
More
→ Audio & Video Settings
136. Device Selector Fields
Microphone
Speaker
Camera
137. Test Device Preview
Settings can provide local preview outside active call.
138. Android Device Selection
Camera:
front/rear
Audio:
route
No unnecessary low-level device list.
139. Screen Share Source Picker Desktop
Native/system-style picker preferred.
140. Share Stop
Persistent visible action.
141. Local Preview Mirroring
Front camera preview may be mirrored locally.
Remote stream should not necessarily be mirrored.
142. Camera Orientation
Android renderer adapts rotation without call restart.
143. Video Surface Loss
If Compose destination recreates:
show placeholder briefly
rebind Surface
call remains.
144. Desktop Renderer Rebind
Same principle for window changes.
145. Remote Video Freeze
Backend may report:
video stalled
UI overlays:
Video paused
without implying call ended.
146. Screen Off
Android audio call continues.
Video capture may pause according to policy/platform.
147. Battery Saver
If backend reduces video:
no alarming message
unless user-visible effect significant.
148. Thermal Event
If video disabled:
Video turned off to cool device
small banner.
149. Media Error Prioritization
Audio is more important.
UI should reflect:
Video unavailable, audio continues
rather than presenting full call failure.
150. Reconnect UX During Network Switch
Examples:
Wi-Fi → cellular
UI may briefly show:
Reconnecting…
only if media interruption noticeable.
151. Connectivity Indicator
Avoid showing raw transport names unless diagnostics.
152. Call Quality Details
Advanced panel can show:
Direct
Relay
LAN
Codec
Bitrate
Packet loss
RTT
153. User-Friendly Quality
Normal UI:
Good connection
Poor connection
only if needed.
154. Call Notifications
Part 31.
When app foreground but not on call screen:
incoming call banner/full-screen flow
155. Ongoing Call Notification
Android required by foreground service.
156. Notification Actions
Mute
Hang up
where safe.
157. Lock-Screen Call UX
Must not reveal sensitive identity details beyond notification privacy settings.
158. Unknown Caller Privacy
Could show:
Incoming call
with generic identity if user chooses strict preview privacy.
159. Call History Navigation
After missed/ended call:
tap event
→ call detail / conversation
160. Call Detail
Could show:
type
time
duration
end reason
call back
161. Call History Privacy
Call metadata is sensitive.
Follow local storage/preview policy.
162. Multi-Device Incoming Call
Several devices may ring.
UI state should handle:
answered elsewhere
declined elsewhere if policy
163. Local Device Priority
Optional future:
prefer active device
backend policy.
UI only renders outcome.
164. Call Transfer Between Devices
Future advanced feature.
Not v1.
Could allow:
Move call to phone
with secure handoff.
165. Call Handoff UX
If added:
choose device
confirm
new device connects
old device exits
166. Group Call Entry
Could start from:
group header
call history
active group call banner
167. Group Call Banner
If group call active:
3 people in call
Join
future if architecture supports.
168. Join Group Call
Rust validates membership/security.
169. Participant Joining
UI can show subtle:
Alice joined
170. Participant Leaving
Likewise.
171. Avoid Modal Spam
Do not show dialog for every group participant event.
172. Raised Hand
Future conference feature.
Not needed initially.
173. Moderator Controls
Future.
Keep architecture extensible.
174. Reactions in Call
Future lightweight ephemeral reactions.
Not v1.
175. Media Control Availability
Rust supplies:
#![allow(unused)] fn main() { pub struct CallControlAvailability { pub can_mute: bool, pub can_video: bool, pub can_switch_camera: bool, pub can_screen_share: bool, pub can_hold: bool, pub can_change_audio_route: bool, } }
176. UI Must Respect Capability
Do not show enabled video button if backend says unsupported.
177. Disabled Control
If useful, show disabled with explanation.
178. Hidden vs Disabled
Hide:
feature fundamentally unsupported
Disable:
temporarily unavailable
with reason.
179. Call Media View
#![allow(unused)] fn main() { pub struct CallMediaView { pub microphone_muted: bool, pub camera_enabled: bool, pub screen_share: ScreenShareView, pub audio_route: AudioRouteView, pub local_renderer: Option<RendererId>, pub remote_renderers: Vec<ParticipantRendererView>, } }
180. Call Quality View
#![allow(unused)] fn main() { pub struct CallQualityView { pub class: CallQualityClass, pub video_degraded: bool, pub audio_degraded: bool, } }
181. Security View
#![allow(unused)] fn main() { pub struct CallSecurityView { pub encrypted: bool, pub verified_peer: bool, pub warning: Option<SecurityWarningView>, } }
182. Call Events
#![allow(unused)] fn main() { pub enum CallUiEvent { StateChanged(CallUiState), MediaChanged(CallMediaView), QualityChanged(CallQualityView), ParticipantChanged(CallParticipantView), SecurityChanged(CallSecurityView), Ended(CallEndReasonView), } }
183. Event Granularity
Update only affected UI region.
184. Android ViewModel
Owns:
temporary sheet state
permission effects
PiP request
selected audio route sheet
local control focus
Rust owns call truth.
185. Dioxus Presenter
Owns:
floating window state
inspector visibility
control overlay visibility
selected participant tile
186. Control Overlay Auto-Hide
Video call can hide controls after inactivity.
187. Desktop Auto-Hide
Mouse move reveals.
Keyboard focus keeps visible.
188. Android Auto-Hide
Tap video reveals.
Do not hide while accessibility focus active.
189. Audio Call Controls
No auto-hide needed.
190. End Call Confirmation
Usually:
no confirmation
because hanging up is expected and reversible only by calling again.
Exception:
host ending call for everyone
may need confirmation.
191. Screen Share Start Confirmation
OS capture prompt provides confirmation.
192. Device Revocation Security Event
Call ends immediately if Rust policy says so.
UI does not override.
193. Call Reauthentication
If backend rekeys transparently:
no UI
unless security failure.
194. Accessibility Live Updates
Announce:
Call connected
Reconnecting
Call ended
Muted
carefully.
195. Avoid Excessive Announcements
Do not announce every bitrate change.
196. Call Status Region
Screen reader live region can report important state transitions.
197. Haptics Android
Use sparingly:
call accepted
mute toggle
hang up
according to platform norms.
198. Ring/Vibration
Controlled by notification/call policy.
199. Desktop Sound
Incoming ring through selected/system output.
200. Ring Output Device
May differ from call output in advanced settings.
201. Incoming Call Audio Focus Android
Platform call integration handles.
202. Call Volume
Use system communication volume where appropriate.
203. App Volume Controls
Do not reinvent OS volume control in v1.
204. Media Permission Education
If user denies:
explain why feature needs permission
without blocking unrelated functionality.
205. Camera Preview Before Call
Outgoing video call may show local preview optionally.
But do not delay call too much.
206. Pre-Call Screen
Future optional:
camera preview
mic selector
background
for conference-style calling.
Not required for simple 1:1 v1.
207. Initial v1 Call UX
Prioritize:
1:1 audio
1:1 video
incoming/outgoing
mute
video
route
camera switch
reconnect
PiP/background
desktop call bar/window
208. Defer Initially
large group grid
SFU-specific controls
call recording
live captions
background effects
virtual backgrounds
device handoff
complex moderator controls
209. Testing Matrix
Required:
incoming audio
incoming video
outgoing audio
outgoing video
decline
busy
timeout
active
mute
video toggle
camera switch
audio route
screen share
reconnecting
connection lost
answered elsewhere
permission denied
surface recreation
PiP
desktop window close
210. Android Tests
Verify:
Activity recreation
background/foreground
PiP
foreground service
notification accept
notification decline
camera permission
mic permission
Bluetooth route change
screen-share permission
TalkBack
large font
foldable
211. Desktop Tests
Verify:
floating call window
persistent call bar
window close
system tray
keyboard shortcuts
camera/audio device chooser
screen-share source picker
212. Reconnect Test
Kill Wi-Fi / switch network.
Expected:
same CallId
Reconnecting…
resume
213. Video Failure Test
Force video codec failure.
Expected:
audio continues
video warning/fallback
214. Surface Loss Test
Destroy/recreate renderer.
Call continues.
215. Permission Denied Test
Video denied.
Audio continues.
216. Bluetooth Disconnect Test
Route switches.
UI reflects new route.
217. Answered Elsewhere Test
Phone and desktop ring.
Desktop answers.
Phone exits incoming state.
218. Hold Test
Current call held/resumed without new call identity.
219. Call Waiting Test
Second call arrives.
Actions behave deterministically.
220. Accessibility Test
Full call flow must be possible without visual-only cues.
221. Rust Presentation API
#![allow(unused)] fn main() { pub trait CallPresentation { async fn snapshot( &self, call: CallId, ) -> Result<CallScreenSnapshot, UiError>; async fn accept( &self, call: CallId, ) -> Result<(), UiError>; async fn decline( &self, call: CallId, ) -> Result<(), UiError>; async fn hangup( &self, call: CallId, ) -> Result<(), UiError>; async fn set_muted( &self, call: CallId, muted: bool, ) -> Result<(), UiError>; async fn set_video( &self, call: CallId, enabled: bool, ) -> Result<(), UiError>; async fn set_hold( &self, call: CallId, held: bool, ) -> Result<(), UiError>; } }
222. Screen Share API
#![allow(unused)] fn main() { pub trait ScreenSharePresentation { async fn start( &self, call: CallId, source: ScreenShareSource, ) -> Result<(), UiError>; async fn stop( &self, call: CallId, ) -> Result<(), UiError>; } }
Platform adapter supplies source selection/permission.
223. Audio Route API
#![allow(unused)] fn main() { pub trait AudioRoutePresentation { async fn available_routes( &self, call: CallId, ) -> Result<Vec<AudioRouteView>, UiError>; async fn select_route( &self, call: CallId, route: AudioRouteId, ) -> Result<(), UiError>; } }
224. Camera API
#![allow(unused)] fn main() { pub trait CameraPresentation { async fn switch_camera( &self, call: CallId, ) -> Result<(), UiError>; } }
Desktop may expose explicit device selection.
225. Android Platform Effects
ViewModel may emit:
RequestCameraPermission
RequestMicrophonePermission
RequestScreenCapture
EnterPiP
OpenBluetoothSettings
226. Desktop Platform Effects
Presenter may emit:
OpenScreenSharePicker
OpenAudioDeviceMenu
CreateCallWindow
RaiseCallWindow
227. No Direct Platform Calls from Rust Domain
Rust can request semantic action.
Platform UI executes it.
228. Call UI Error Mapping
Examples:
PermissionRequired
MediaUnavailable
PeerUnavailable
SecurityBlocked
CallExpired
RouteUnavailable
229. Error Presentation
Permission:
contextual action
Media failure:
degrade if possible
Security:
strong warning
Expired call:
call ended/missed
230. Metrics
Safe local metrics:
call screen open latency
accept-to-audio time
first-video-frame time
PiP transition
reconnect duration
No media content.
231. Diagnostics Privacy
Do not log:
raw audio
video frames
private keys
232. Screenshot Testing
Required states:
incoming
outgoing ringing
connecting
active audio
active video
muted
video off
screen sharing
reconnecting
poor connection
permission denied
ended
group grid
PiP conceptual
dark mode
large font
RTL
233. UI/UX Part 07 Definition of Done
Part 07 is complete when:
- incoming/outgoing call states map directly from Rust call state
- caller identity is authenticated before normal trusted presentation
- audio/video calls have distinct but consistent layouts
- mute, video, camera switch, audio route, screen share, hold, and hangup are semantic Rust commands
- call remains one logical session through path, route, surface, and codec changes
- reconnecting is visible without prematurely ending call
- video failure can degrade to audio
- Android Activity recreation, PiP, foreground service, and notification actions are defined
- desktop persistent call bar and floating call window behavior are defined
- closing a call window does not automatically hang up
- accessibility, keyboard, TalkBack, large touch targets, large font, and reduced motion are explicit
- permissions are requested contextually and do not destroy call state
- group-call layout can evolve without changing 1:1 semantics
- normal UI hides low-level transport/codec details while diagnostics can expose them
- answer-elsewhere, call waiting, hold, device revocation, connection loss, surface loss, and Bluetooth route changes are tested
- raw media never flows through ordinary Dioxus/Compose state
- the exact Rust presentation APIs and platform effects are defined
234. Final Architecture
RUST CALL CONTROLLER
│
CallScreenSnapshot
│
┌────────────────┴────────────────┐
│ │
Dioxus Compose
│ │
Desktop Call Window Android Call Screen
Persistent Call Bar PiP / Foreground Service
│ │
└──────────────┬──────────────────┘
│
Semantic Commands
│
Mute / Video / Route / Share / Hold
│
Rust Media Runtime
Platform-owned mechanics:
Desktop:
windows
device menus
screen picker
Android:
permissions
foreground service
notification actions
PiP
system capture
Call truth remains:
CallId
CallState
MediaState
SecurityState
inside Rust.
235. Final Principle
The call UI should remain calm and stable even when the media system is adapting aggressively underneath it.
The right user-facing model is:
one call
+
clear participant identity
+
few reliable controls
+
graceful reconnect/degradation
+
platform-native background behavior
not:
one UI state per codec, transport path, or renderer implementation
That separation gives Dioxus desktop and Android Compose a polished realtime communication experience while preserving the transport-independent Rust call architecture.