Skip to content

Commit ea4c9a4

Browse files
toger5poljar
authored andcommitted
feat(widgets): Add the controlledMediaOutput url parameter to the VirtualElementCallWidgetOptions.
This is used to configure EC on devices that need to control media outputs on their own (android, ios). If set, EC will display a list of devices provided by the app.
1 parent ac2c7f4 commit ea4c9a4

File tree

2 files changed

+66
-14
lines changed

2 files changed

+66
-14
lines changed

bindings/matrix-sdk-ffi/src/widget.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -248,6 +248,11 @@ pub struct VirtualElementCallWidgetOptions {
248248
/// Sentry [environment](https://docs.sentry.io/concepts/key-terms/key-terms/)
249249
/// Supported since Element Call v0.9.0. Only used by the embedded package.
250250
pub sentry_environment: Option<String>,
251+
//// - `true`: The webview should show the list of media devices it detects using
252+
//// `enumerateDevices`.
253+
/// - `false`: the webview shows a a list of devices injected by the
254+
/// client. (used on ios & android)
255+
pub controlled_media_devices: bool,
251256
}
252257

253258
impl From<VirtualElementCallWidgetOptions> for matrix_sdk::widget::VirtualElementCallWidgetOptions {
@@ -271,6 +276,7 @@ impl From<VirtualElementCallWidgetOptions> for matrix_sdk::widget::VirtualElemen
271276
rageshake_submit_url: value.rageshake_submit_url,
272277
sentry_dsn: value.sentry_dsn,
273278
sentry_environment: value.sentry_environment,
279+
controlled_media_devices: value.controlled_media_devices,
274280
}
275281
}
276282
}

crates/matrix-sdk/src/widget/settings/element_call.rs

Lines changed: 60 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,7 @@ struct ElementCallParams {
7070
/// Supported since Element Call v0.9.0. Only used by the embedded package.
7171
sentry_environment: Option<String>,
7272
hide_screensharing: bool,
73+
controlled_media_devices: bool,
7374
}
7475

7576
/// Defines if a call is encrypted and which encryption system should be used.
@@ -193,6 +194,11 @@ pub struct VirtualElementCallWidgetOptions {
193194
/// Sentry [environment](https://docs.sentry.io/concepts/key-terms/key-terms/)
194195
/// This is only used by the embedded package of Element Call.
195196
pub sentry_environment: Option<String>,
197+
//// - `true`: The webview should show the list of media devices it detects using
198+
//// `enumerateDevices`.
199+
/// - `false`: the webview shows a a list of devices injected by the
200+
/// client. (used on ios & android)
201+
pub controlled_media_devices: bool,
196202
}
197203

198204
impl WidgetSettings {
@@ -253,6 +259,7 @@ impl WidgetSettings {
253259
sentry_environment: props.sentry_environment,
254260
rageshake_submit_url: props.rageshake_submit_url,
255261
hide_screensharing: props.hide_screensharing,
262+
controlled_media_devices: props.controlled_media_devices,
256263
};
257264

258265
let query =
@@ -288,6 +295,7 @@ mod tests {
288295
rageshake: bool,
289296
sentry: bool,
290297
intent: Option<Intent>,
298+
controlle_output: bool,
291299
) -> WidgetSettings {
292300
let mut props = VirtualElementCallWidgetOptions {
293301
element_call_url: "https://call.element.io".to_owned(),
@@ -298,6 +306,7 @@ mod tests {
298306
confine_to_room: Some(true),
299307
encryption: encryption.unwrap_or(EncryptionSystem::PerParticipantKeys),
300308
intent,
309+
controlled_media_devices: controlle_output,
301310
..VirtualElementCallWidgetOptions::default()
302311
};
303312

@@ -345,13 +354,13 @@ mod tests {
345354
}
346355

347356
#[test]
348-
fn new_virtual_element_call_widget_base_url() {
349-
let widget_settings = get_widget_settings(None, false, false, false, None);
357+
fn test_new_virtual_element_call_widget_base_url() {
358+
let widget_settings = get_widget_settings(None, false, false, false, None, false);
350359
assert_eq!(widget_settings.base_url().unwrap().as_str(), "https://call.element.io/");
351360
}
352361

353362
#[test]
354-
fn new_virtual_element_call_widget_raw_url() {
363+
fn test_new_virtual_element_call_widget_raw_url() {
355364
const CONVERTED_URL: &str = "
356365
https://call.element.io#\
357366
?userId=$matrix_user_id\
@@ -370,9 +379,10 @@ mod tests {
370379
&preload=true\
371380
&perParticipantE2EE=true\
372381
&hideScreensharing=false\
382+
&controlledMediaDevices=false\
373383
";
374384

375-
let mut url = get_widget_settings(None, false, false, false, None).raw_url().clone();
385+
let mut url = get_widget_settings(None, false, false, false, None, false).raw_url().clone();
376386
let mut gen = Url::parse(CONVERTED_URL).unwrap();
377387
assert_eq!(get_query_sets(&url).unwrap(), get_query_sets(&gen).unwrap());
378388
url.set_fragment(None);
@@ -383,8 +393,11 @@ mod tests {
383393
}
384394

385395
#[test]
386-
fn new_virtual_element_call_widget_id() {
387-
assert_eq!(get_widget_settings(None, false, false, false, None).widget_id(), WIDGET_ID);
396+
fn test_new_virtual_element_call_widget_id() {
397+
assert_eq!(
398+
get_widget_settings(None, false, false, false, None, false).widget_id(),
399+
WIDGET_ID
400+
);
388401
}
389402

390403
fn build_url_from_widget_settings(settings: WidgetSettings) -> String {
@@ -406,7 +419,7 @@ mod tests {
406419
}
407420

408421
#[test]
409-
fn new_virtual_element_call_widget_webview_url() {
422+
fn test_new_virtual_element_call_widget_webview_url() {
410423
const CONVERTED_URL: &str = "
411424
https://call.element.io#\
412425
?parentUrl=https%3A%2F%2Fcall.element.io\
@@ -423,9 +436,11 @@ mod tests {
423436
&clientId=io.my_matrix.client\
424437
&perParticipantE2EE=true\
425438
&hideScreensharing=false\
439+
&controlledMediaDevices=false\
426440
";
427-
let gen =
428-
build_url_from_widget_settings(get_widget_settings(None, false, false, false, None));
441+
let gen = build_url_from_widget_settings(get_widget_settings(
442+
None, false, false, false, None, false,
443+
));
429444

430445
let mut url = Url::parse(&gen).unwrap();
431446
let mut gen = Url::parse(CONVERTED_URL).unwrap();
@@ -438,7 +453,7 @@ mod tests {
438453
}
439454

440455
#[test]
441-
fn new_virtual_element_call_widget_webview_url_with_posthog_rageshake_sentry() {
456+
fn test_new_virtual_element_call_widget_webview_url_with_posthog_rageshake_sentry() {
442457
const CONVERTED_URL: &str = "
443458
https://call.element.io#\
444459
?parentUrl=https%3A%2F%2Fcall.element.io\
@@ -462,8 +477,11 @@ mod tests {
462477
&rageshakeSubmitUrl=https%3A%2F%2Frageshake.element.io\
463478
&sentryDsn=SENTRY_DSN\
464479
&sentryEnvironment=SENTRY_ENV\
480+
&controlledMediaDevices=false\
465481
";
466-
let gen = build_url_from_widget_settings(get_widget_settings(None, true, true, true, None));
482+
let gen = build_url_from_widget_settings(get_widget_settings(
483+
None, true, true, true, None, false,
484+
));
467485

468486
let mut url = Url::parse(&gen).unwrap();
469487
let mut gen = Url::parse(CONVERTED_URL).unwrap();
@@ -476,7 +494,7 @@ mod tests {
476494
}
477495

478496
#[test]
479-
fn password_url_props_from_widget_settings() {
497+
fn test_password_url_props_from_widget_settings() {
480498
{
481499
// PerParticipantKeys
482500
let url = build_url_from_widget_settings(get_widget_settings(
@@ -485,6 +503,7 @@ mod tests {
485503
false,
486504
false,
487505
None,
506+
false,
488507
));
489508
let query_set = get_query_sets(&Url::parse(&url).unwrap()).unwrap().1;
490509
let expected_elements = [("perParticipantE2EE".to_owned(), "true".to_owned())];
@@ -505,6 +524,7 @@ mod tests {
505524
false,
506525
false,
507526
None,
527+
false,
508528
));
509529
let query_set = get_query_sets(&Url::parse(&url).unwrap()).unwrap().1;
510530
let expected_elements = ("perParticipantE2EE".to_owned(), "false".to_owned());
@@ -523,6 +543,7 @@ mod tests {
523543
false,
524544
false,
525545
None,
546+
false,
526547
));
527548
let query_set = get_query_sets(&Url::parse(&url).unwrap()).unwrap().1;
528549
let expected_elements = [("password".to_owned(), "this_surely_is_save".to_owned())];
@@ -538,11 +559,34 @@ mod tests {
538559
}
539560

540561
#[test]
541-
fn intent_url_props_from_widget_settings() {
562+
fn test_controlled_output_url_props_from_widget_settings() {
563+
{
564+
// PerParticipantKeys
565+
let url = build_url_from_widget_settings(get_widget_settings(
566+
Some(EncryptionSystem::PerParticipantKeys),
567+
false,
568+
false,
569+
false,
570+
None,
571+
true,
572+
));
573+
let controlled_media_element = ("controlledMediaDevices".to_owned(), "true".to_owned());
574+
let query_set = get_query_sets(&Url::parse(&url).unwrap()).unwrap().1;
575+
assert!(
576+
query_set.contains(&controlled_media_element),
577+
"The query elements: \n{:?}\nDid not contain: \n{:?}",
578+
query_set,
579+
controlled_media_element
580+
);
581+
}
582+
}
583+
584+
#[test]
585+
fn test_intent_url_props_from_widget_settings() {
542586
{
543587
// no intent
544588
let url = build_url_from_widget_settings(get_widget_settings(
545-
None, false, false, false, None,
589+
None, false, false, false, None, false,
546590
));
547591
let query_set = get_query_sets(&Url::parse(&url).unwrap()).unwrap().1;
548592

@@ -565,6 +609,7 @@ mod tests {
565609
false,
566610
false,
567611
Some(Intent::JoinExisting),
612+
false,
568613
));
569614
let query_set = get_query_sets(&Url::parse(&url).unwrap()).unwrap().1;
570615
let expected_elements = ("intent".to_owned(), "join_existing".to_owned());
@@ -594,6 +639,7 @@ mod tests {
594639
false,
595640
false,
596641
Some(Intent::StartCall),
642+
false,
597643
));
598644
let query_set = get_query_sets(&Url::parse(&url).unwrap()).unwrap().1;
599645

0 commit comments

Comments
 (0)