@@ -26,9 +26,9 @@ use super::{url_params, WidgetSettings};
26
26
27
27
#[ derive( Serialize ) ]
28
28
#[ serde( rename_all = "camelCase" ) ]
29
- /// Parameters for the Element Call widget.
29
+ /// Serialization struct for URL parameters for the Element Call widget.
30
30
/// These are documented at https://github.com/element-hq/element-call/blob/livekit/docs/url-params.md
31
- struct ElementCallParams {
31
+ struct ElementCallUrlParams {
32
32
user_id : String ,
33
33
room_id : String ,
34
34
widget_id : String ,
@@ -44,13 +44,13 @@ struct ElementCallParams {
44
44
/// compatibility. Set to `true` if intent is `Intent::StartCall`.
45
45
skip_lobby : Option < bool > ,
46
46
confine_to_room : bool ,
47
- app_prompt : bool ,
47
+ app_prompt : Option < bool > ,
48
48
/// Supported since Element Call v0.13.0.
49
- header : HeaderStyle ,
49
+ header : Option < HeaderStyle > ,
50
50
/// Deprecated since Element Call v0.13.0. Included for backwards
51
51
/// compatibility. Use header: "standard"|"none" instead.
52
52
hide_header : Option < bool > ,
53
- preload : bool ,
53
+ preload : Option < bool > ,
54
54
/// Deprecated since Element Call v0.9.0. Included for backwards
55
55
/// compatibility. Set to the same as `posthog_user_id`.
56
56
analytics_id : Option < String > ,
@@ -59,7 +59,7 @@ struct ElementCallParams {
59
59
font_scale : Option < f64 > ,
60
60
font : Option < String > ,
61
61
#[ serde( rename = "perParticipantE2EE" ) ]
62
- per_participant_e2ee : bool ,
62
+ per_participant_e2ee : Option < bool > ,
63
63
password : Option < String > ,
64
64
/// Supported since Element Call v0.8.0.
65
65
intent : Option < Intent > ,
@@ -73,8 +73,10 @@ struct ElementCallParams {
73
73
sentry_dsn : Option < String > ,
74
74
/// Supported since Element Call v0.9.0. Only used by the embedded package.
75
75
sentry_environment : Option < String > ,
76
- hide_screensharing : bool ,
77
- controlled_media_devices : bool ,
76
+ /// Supported since Element Call v0.9.0.
77
+ hide_screensharing : Option < bool > ,
78
+ /// Supported since Element Call v0.13.0.
79
+ controlled_audio_devices : Option < bool > ,
78
80
/// Supported since Element Call v0.14.0.
79
81
send_notification_type : Option < NotificationType > ,
80
82
}
@@ -110,6 +112,11 @@ pub enum Intent {
110
112
StartCall ,
111
113
/// The user wants to join an existing call.
112
114
JoinExisting ,
115
+ /// The user wants to join an existing call that is a "Direct Message" (DM)
116
+ /// room.
117
+ JoinExistingDM ,
118
+ /// The user wants to start a call in a "Direct Message" (DM) room.
119
+ StartCallDM ,
113
120
}
114
121
115
122
/// Defines how (if) element-call renders a header.
@@ -126,40 +133,34 @@ pub enum HeaderStyle {
126
133
}
127
134
128
135
/// Types of call notifications.
129
- #[ derive( Debug , PartialEq , Serialize , uniffi:: Enum , Clone ) ]
136
+ #[ derive( Debug , PartialEq , Serialize , uniffi:: Enum , Clone , Default ) ]
130
137
#[ serde( rename_all = "snake_case" ) ]
131
138
pub enum NotificationType {
132
- /// The receiving client should display a visual notification.
139
+ /// The receiving client should display a visual notification.
140
+ #[ default]
133
141
Notification ,
134
142
/// The receiving client should ring with an audible sound.
135
143
Ring ,
136
144
}
137
145
138
- /// Properties to create a new virtual Element Call widget.
146
+ /// Configuration parameters, to create a new virtual Element Call widget.
147
+ ///
148
+ /// If `intent` is provided the appropriate default values for all other
149
+ /// parameters will be used by element call.
150
+ /// In most cases its enough to only set the intent. Use the other properties
151
+ /// only if you want to deviate from the `intent` defaults.
152
+ ///
153
+ /// Set [`docs/url-params.md`](https://github.com/element-hq/element-call/blob/livekit/docs/url-params.md)
154
+ /// to find out more about the parameters and their defaults.
139
155
#[ derive( Debug , Default , uniffi:: Record , Clone ) ]
140
- pub struct VirtualElementCallWidgetOptions {
141
- /// The url to the app .
142
- ///
143
- /// E.g. <https://call.element.io>, <https://call.element.dev>, <https://call.element.dev/room>
144
- pub element_call_url : String ,
156
+ pub struct VirtualElementCallWidgetConfig {
157
+ /// The intent of showing the call .
158
+ /// If the user wants to start a call or join an existing one.
159
+ /// Controls if the lobby is skipped or not.
160
+ pub intent : Option < Intent > ,
145
161
146
- /// The widget id.
147
- pub widget_id : String ,
148
-
149
- /// The url that is used as the target for the PostMessages sent
150
- /// by the widget (to the client).
151
- ///
152
- /// For a web app client this is the client url. In case of using other
153
- /// platforms the client most likely is setup up to listen to
154
- /// postmessages in the same webview the widget is hosted. In this case
155
- /// the `parent_url` is set to the url of the webview with the widget. Be
156
- /// aware that this means that the widget will receive its own postmessage
157
- /// messages. The `matrix-widget-api` (js) ignores those so this works but
158
- /// it might break custom implementations.
159
- ///
160
- /// Defaults to `element_call_url` for the non-iframe (dedicated webview)
161
- /// usecase.
162
- pub parent_url : Option < String > ,
162
+ /// Skip the lobby when joining a call.
163
+ pub skip_lobby : Option < bool > ,
163
164
164
165
/// Whether the branding header of Element call should be shown or if a
165
166
/// mobile header navbar should be render.
@@ -179,11 +180,6 @@ pub struct VirtualElementCallWidgetOptions {
179
180
/// Default: `false`
180
181
pub preload : Option < bool > ,
181
182
182
- /// The font scale which will be used inside element call.
183
- ///
184
- /// Default: `1`
185
- pub font_scale : Option < f64 > ,
186
-
187
183
/// Whether element call should prompt the user to open in the browser or
188
184
/// the app.
189
185
///
@@ -195,6 +191,53 @@ pub struct VirtualElementCallWidgetOptions {
195
191
/// Default: `true`
196
192
pub confine_to_room : Option < bool > ,
197
193
194
+ /// Do not show the screenshare button.
195
+ pub hide_screensharing : Option < bool > ,
196
+
197
+ /// Make the audio devices be controlled by the os instead of the
198
+ /// element-call webview.
199
+ pub controlled_audio_devices : Option < bool > ,
200
+
201
+ /// Whether and what type of notification Element Call should send, when
202
+ /// starting a call.
203
+ pub send_notification_type : Option < NotificationType > ,
204
+ }
205
+
206
+ /// Properties to create a new virtual Element Call widget.
207
+ ///
208
+ /// All these are required to start the widget in the first place.
209
+ /// This is different from the `VirtualElementCallWidgetConfiguration` which
210
+ /// configures the widgets behavior.
211
+ #[ derive( Debug , Default , uniffi:: Record , Clone ) ]
212
+ pub struct VirtualElementCallWidgetProperties {
213
+ /// The url to the app.
214
+ ///
215
+ /// E.g. <https://call.element.io>, <https://call.element.dev>, <https://call.element.dev/room>
216
+ pub element_call_url : String ,
217
+
218
+ /// The widget id.
219
+ pub widget_id : String ,
220
+
221
+ /// The url that is used as the target for the PostMessages sent
222
+ /// by the widget (to the client).
223
+ ///
224
+ /// For a web app client this is the client url. In case of using other
225
+ /// platforms the client most likely is setup up to listen to
226
+ /// postmessages in the same webview the widget is hosted. In this case
227
+ /// the `parent_url` is set to the url of the webview with the widget. Be
228
+ /// aware that this means that the widget will receive its own postmessage
229
+ /// messages. The `matrix-widget-api` (js) ignores those so this works but
230
+ /// it might break custom implementations.
231
+ ///
232
+ /// Defaults to `element_call_url` for the non-iframe (dedicated webview)
233
+ /// usecase.
234
+ pub parent_url : Option < String > ,
235
+
236
+ /// The font scale which will be used inside element call.
237
+ ///
238
+ /// Default: `1`
239
+ pub font_scale : Option < f64 > ,
240
+
198
241
/// The font to use, to adapt to the system font.
199
242
pub font : Option < String > ,
200
243
@@ -203,14 +246,6 @@ pub struct VirtualElementCallWidgetOptions {
203
246
/// Use `EncryptionSystem::Unencrypted` to disable encryption.
204
247
pub encryption : EncryptionSystem ,
205
248
206
- /// The intent of showing the call.
207
- /// If the user wants to start a call or join an existing one.
208
- /// Controls if the lobby is skipped or not.
209
- pub intent : Option < Intent > ,
210
-
211
- /// Do not show the screenshare button.
212
- pub hide_screensharing : bool ,
213
-
214
249
/// Can be used to pass a PostHog id to element call.
215
250
pub posthog_user_id : Option < String > ,
216
251
/// The host of the posthog api.
@@ -230,14 +265,6 @@ pub struct VirtualElementCallWidgetOptions {
230
265
/// Sentry [environment](https://docs.sentry.io/concepts/key-terms/key-terms/)
231
266
/// This is only used by the embedded package of Element Call.
232
267
pub sentry_environment : Option < String > ,
233
- //// - `true`: The webview should show the list of media devices it detects using
234
- //// `enumerateDevices`.
235
- /// - `false`: the webview shows a a list of devices injected by the
236
- /// client. (used on ios & android)
237
- pub controlled_media_devices : bool ,
238
- /// Whether and what type of notification Element Call should send, when
239
- /// starting a call.
240
- pub send_notification_type : Option < NotificationType > ,
241
268
}
242
269
243
270
impl WidgetSettings {
@@ -255,17 +282,13 @@ impl WidgetSettings {
255
282
/// * `props` - A struct containing the configuration parameters for a
256
283
/// element call widget.
257
284
pub fn new_virtual_element_call_widget (
258
- props : VirtualElementCallWidgetOptions ,
285
+ props : VirtualElementCallWidgetProperties ,
286
+ config : VirtualElementCallWidgetConfig ,
259
287
) -> Result < Self , url:: ParseError > {
260
288
let mut raw_url: Url = Url :: parse ( & props. element_call_url ) ?;
261
289
262
- let skip_lobby = if props. intent . as_ref ( ) . is_some_and ( |x| x == & Intent :: StartCall ) {
263
- Some ( true )
264
- } else {
265
- None
266
- } ;
267
290
#[ allow( deprecated) ]
268
- let query_params = ElementCallParams {
291
+ let query_params = ElementCallUrlParams {
269
292
user_id : url_params:: USER_ID . to_owned ( ) ,
270
293
room_id : url_params:: ROOM_ID . to_owned ( ) ,
271
294
widget_id : url_params:: WIDGET_ID . to_owned ( ) ,
@@ -277,30 +300,30 @@ impl WidgetSettings {
277
300
base_url : url_params:: HOMESERVER_URL . to_owned ( ) ,
278
301
279
302
parent_url : props. parent_url . unwrap_or ( props. element_call_url . clone ( ) ) ,
280
- confine_to_room : props . confine_to_room . unwrap_or ( true ) ,
281
- app_prompt : props . app_prompt . unwrap_or_default ( ) ,
282
- header : props . header . unwrap_or_default ( ) ,
283
- hide_header : props . hide_header ,
284
- preload : props . preload . unwrap_or_default ( ) ,
303
+ confine_to_room : config . confine_to_room . unwrap_or ( true ) ,
304
+ app_prompt : config . app_prompt ,
305
+ header : config . header ,
306
+ hide_header : config . hide_header ,
307
+ preload : config . preload ,
285
308
font_scale : props. font_scale ,
286
309
font : props. font ,
287
- per_participant_e2ee : props. encryption == EncryptionSystem :: PerParticipantKeys ,
310
+ per_participant_e2ee : Some ( props. encryption == EncryptionSystem :: PerParticipantKeys ) ,
288
311
password : match props. encryption {
289
312
EncryptionSystem :: SharedSecret { secret } => Some ( secret) ,
290
313
_ => None ,
291
314
} ,
292
- intent : props . intent ,
293
- skip_lobby,
315
+ intent : config . intent ,
316
+ skip_lobby : config . skip_lobby ,
294
317
analytics_id : props. posthog_user_id . clone ( ) ,
295
318
posthog_user_id : props. posthog_user_id ,
296
319
posthog_api_host : props. posthog_api_host ,
297
320
posthog_api_key : props. posthog_api_key ,
298
321
sentry_dsn : props. sentry_dsn ,
299
322
sentry_environment : props. sentry_environment ,
300
323
rageshake_submit_url : props. rageshake_submit_url ,
301
- hide_screensharing : props . hide_screensharing ,
302
- controlled_media_devices : props . controlled_media_devices ,
303
- send_notification_type : props . send_notification_type ,
324
+ hide_screensharing : config . hide_screensharing ,
325
+ controlled_media_devices : config . controlled_media_devices ,
326
+ send_notification_type : config . send_notification_type ,
304
327
} ;
305
328
306
329
let query =
@@ -326,7 +349,10 @@ mod tests {
326
349
use ruma:: api:: client:: profile:: get_profile;
327
350
use url:: Url ;
328
351
329
- use crate :: widget:: { ClientProperties , Intent , WidgetSettings } ;
352
+ use crate :: widget:: {
353
+ settings:: element_call:: VirtualElementCallWidgetConfig , ClientProperties , Intent ,
354
+ WidgetSettings ,
355
+ } ;
330
356
331
357
const WIDGET_ID : & str = "1/@#w23" ;
332
358
@@ -336,36 +362,28 @@ mod tests {
336
362
rageshake : bool ,
337
363
sentry : bool ,
338
364
intent : Option < Intent > ,
339
- controlle_output : bool ,
365
+ controlled_output : bool ,
340
366
) -> WidgetSettings {
341
- let mut props = VirtualElementCallWidgetOptions {
367
+ let props = VirtualElementCallWidgetProperties {
342
368
element_call_url : "https://call.element.io" . to_owned ( ) ,
343
369
widget_id : WIDGET_ID . to_owned ( ) ,
344
- preload : Some ( true ) ,
345
- app_prompt : Some ( true ) ,
346
- confine_to_room : Some ( true ) ,
370
+ posthog_user_id : posthog. then ( || "POSTHOG_USER_ID" . to_owned ( ) ) ,
371
+ posthog_api_host : posthog. then ( || "posthog.element.io" . to_owned ( ) ) ,
372
+ posthog_api_key : posthog. then ( || "POSTHOG_KEY" . to_owned ( ) ) ,
373
+ rageshake_submit_url : rageshake. then ( || "https://rageshake.element.io" . to_owned ( ) ) ,
374
+ sentry_dsn : sentry. then ( || "SENTRY_DSN" . to_owned ( ) ) ,
375
+ sentry_environment : sentry. then ( || "SENTRY_ENV" . to_owned ( ) ) ,
347
376
encryption : encryption. unwrap_or ( EncryptionSystem :: PerParticipantKeys ) ,
348
- intent,
349
- controlled_media_devices : controlle_output,
350
- ..VirtualElementCallWidgetOptions :: default ( )
377
+ ..VirtualElementCallWidgetProperties :: default ( )
351
378
} ;
352
379
353
- if posthog {
354
- props. posthog_user_id = Some ( "POSTHOG_USER_ID" . to_owned ( ) ) ;
355
- props. posthog_api_host = Some ( "posthog.element.io" . to_owned ( ) ) ;
356
- props. posthog_api_key = Some ( "POSTHOG_KEY" . to_owned ( ) ) ;
357
- }
358
-
359
- if rageshake {
360
- props. rageshake_submit_url = Some ( "https://rageshake.element.io" . to_owned ( ) ) ;
361
- }
362
-
363
- if sentry {
364
- props. sentry_dsn = Some ( "SENTRY_DSN" . to_owned ( ) ) ;
365
- props. sentry_environment = Some ( "SENTRY_ENV" . to_owned ( ) ) ;
366
- }
380
+ let config = VirtualElementCallWidgetConfig {
381
+ controlled_media_devices : Some ( controlled_output) ,
382
+ intent,
383
+ ..VirtualElementCallWidgetConfig :: default ( )
384
+ } ;
367
385
368
- WidgetSettings :: new_virtual_element_call_widget ( props)
386
+ WidgetSettings :: new_virtual_element_call_widget ( props, config )
369
387
. expect ( "could not parse virtual element call widget" )
370
388
}
371
389
@@ -385,7 +403,7 @@ mod tests {
385
403
386
404
use serde_html_form:: from_str;
387
405
388
- use super :: { EncryptionSystem , VirtualElementCallWidgetOptions } ;
406
+ use super :: { EncryptionSystem , VirtualElementCallWidgetProperties } ;
389
407
390
408
fn get_query_sets ( url : & Url ) -> Option < ( QuerySet , QuerySet ) > {
391
409
let fq = from_str :: < QuerySet > ( url. fragment_query ( ) . unwrap_or_default ( ) ) . ok ( ) ?;
0 commit comments