From e956f0c5afc777aee6d98d9bd947ef74b8f44454 Mon Sep 17 00:00:00 2001 From: chickenleaf Date: Wed, 26 Feb 2025 15:29:47 +0530 Subject: [PATCH] servoshell: Port SelectDevice dialog code to use egui instead of tinyfiledialogs (#35657) Signed-off-by: L Ashwin B --- ports/servoshell/desktop/app_state.rs | 41 ++--------------- ports/servoshell/desktop/dialog.rs | 66 ++++++++++++++++++++++++++- 2 files changed, 69 insertions(+), 38 deletions(-) diff --git a/ports/servoshell/desktop/app_state.rs b/ports/servoshell/desktop/app_state.rs index a704cf2fb8a..b6fbb1f2cd9 100644 --- a/ports/servoshell/desktop/app_state.rs +++ b/ports/servoshell/desktop/app_state.rs @@ -503,12 +503,10 @@ impl WebViewDelegate for RunningAppState { devices: Vec, response_sender: IpcSender>, ) { - let selected = platform_get_selected_devices(devices); - if let Err(e) = response_sender.send(selected) { - webview.send_error(format!( - "Failed to send GetSelectedBluetoothDevice response: {e}" - )); - } + self.add_dialog( + webview, + Dialog::new_device_selection_dialog(devices, response_sender), + ); } fn show_file_selection_dialog( @@ -583,34 +581,3 @@ impl WebViewDelegate for RunningAppState { self.inner().window.hide_ime(); } } - -#[cfg(target_os = "linux")] -fn platform_get_selected_devices(devices: Vec) -> Option { - std::thread::Builder::new() - .name("DevicePicker".to_owned()) - .spawn(move || { - let dialog_rows: Vec<&str> = devices.iter().map(|s| s.as_ref()).collect(); - let dialog_rows: Option<&[&str]> = Some(dialog_rows.as_slice()); - - match tinyfiledialogs::list_dialog("Choose a device", &["Id", "Name"], dialog_rows) { - Some(device) => { - // The device string format will be "Address|Name". We need the first part of it. - device.split('|').next().map(|s| s.to_string()) - }, - None => None, - } - }) - .unwrap() - .join() - .expect("Thread spawning failed") -} - -#[cfg(not(target_os = "linux"))] -fn platform_get_selected_devices(devices: Vec) -> Option { - for device in devices { - if let Some(address) = device.split('|').next().map(|s| s.to_string()) { - return Some(address); - } - } - None -} diff --git a/ports/servoshell/desktop/dialog.rs b/ports/servoshell/desktop/dialog.rs index 9d8e97d7d77..3b277b6a424 100644 --- a/ports/servoshell/desktop/dialog.rs +++ b/ports/servoshell/desktop/dialog.rs @@ -39,6 +39,11 @@ pub enum Dialog { message: String, request: Option, }, + SelectDevice { + devices: Vec, + selected_device_index: usize, + response_sender: IpcSender>, + }, } impl Dialog { @@ -110,6 +115,17 @@ impl Dialog { } } + pub fn new_device_selection_dialog( + devices: Vec, + response_sender: IpcSender>, + ) -> Self { + Dialog::SelectDevice { + devices, + selected_device_index: 0, + response_sender, + } + } + pub fn update(&mut self, ctx: &egui::Context) -> bool { match self { Dialog::File { @@ -230,7 +246,7 @@ impl Dialog { ref mut request, } => { let mut is_open = true; - Modal::new("input".into()).show(ctx, |ui| { + Modal::new("authentication".into()).show(ctx, |ui| { let mut frame = egui::Frame::default().inner_margin(10.0).begin(ui); frame.content_ui.set_min_width(150.0); @@ -302,6 +318,54 @@ impl Dialog { }); is_open }, + Dialog::SelectDevice { + devices, + selected_device_index, + response_sender, + } => { + let mut is_open = true; + let modal = Modal::new("device_picker".into()); + modal.show(ctx, |ui| { + let mut frame = egui::Frame::default().inner_margin(10.0).begin(ui); + frame.content_ui.set_min_width(150.0); + + frame.content_ui.heading("Choose a Device"); + frame.content_ui.add_space(10.0); + + egui::ComboBox::from_label("") + .selected_text(&devices[*selected_device_index + 1]) + .show_ui(&mut frame.content_ui, |ui| { + for i in (0..devices.len() - 1).step_by(2) { + let device_name = &devices[i + 1]; + ui.selectable_value(selected_device_index, i, device_name); + } + }); + + frame.end(ui); + + egui::Sides::new().show( + ui, + |_ui| {}, + |ui| { + if ui.button("Ok").clicked() { + if let Err(e) = response_sender + .send(Some(devices[*selected_device_index].clone())) + { + warn!("Failed to send device selection: {}", e); + } + is_open = false; + } + if ui.button("Cancel").clicked() { + if let Err(e) = response_sender.send(None) { + warn!("Failed to send cancellation: {}", e); + } + is_open = false; + } + }, + ); + }); + is_open + }, } } }