diff --git a/desktop/src/gui/widgets.rs b/desktop/src/gui/widgets.rs index 7c74f3695d64..42db70d49eb0 100644 --- a/desktop/src/gui/widgets.rs +++ b/desktop/src/gui/widgets.rs @@ -2,13 +2,13 @@ use crate::gui::text; use crate::util::pick_file; use egui::{TextEdit, Ui}; use std::path::Path; -use std::sync::Weak; +use std::sync::{Arc, Mutex, MutexGuard, Weak}; use unic_langid::LanguageIdentifier; use url::Url; pub struct PathOrUrlField { window: Weak, - value: String, + value: Arc>, result: Option, hint: &'static str, } @@ -24,7 +24,7 @@ impl PathOrUrlField { if let Ok(path) = default.to_file_path() { return Self { window, - value: path.to_string_lossy().to_string(), + value: Arc::new(Mutex::new(path.to_string_lossy().to_string())), result: Some(default), hint, }; @@ -33,7 +33,7 @@ impl PathOrUrlField { return Self { window, - value: default.to_string(), + value: Arc::new(Mutex::new(default.to_string())), result: Some(default), hint, }; @@ -41,12 +41,16 @@ impl PathOrUrlField { Self { window, - value: "".to_string(), + value: Arc::new(Mutex::new("".to_string())), result: None, hint, } } + fn lock_value(value: &Arc>) -> MutexGuard<'_, String> { + value.lock().expect("Non-poisoned value") + } + pub fn ui(&mut self, locale: &LanguageIdentifier, ui: &mut Ui) -> &mut Self { ui.with_layout(egui::Layout::right_to_left(egui::Align::Center), |ui| { if ui.button(text(locale, "browse")).clicked() { @@ -61,12 +65,16 @@ impl PathOrUrlField { }); if let Some(path) = pick_file(true, dir, self.window.upgrade()) { - self.value = path.to_string_lossy().to_string(); + let mut value_lock = Self::lock_value(&self.value); + *value_lock = path.to_string_lossy().to_string(); } } + + let mut value_locked = Self::lock_value(&self.value); + let mut value = value_locked.clone(); ui.add_sized( ui.available_size(), - TextEdit::singleline(&mut self.value) + TextEdit::singleline(&mut value) .hint_text(self.hint) .text_color_opt(if self.result.is_none() { Some(ui.style().visuals.error_fg_color) @@ -74,13 +82,15 @@ impl PathOrUrlField { None }), ); + *value_locked = value; }); - let path = Path::new(&self.value); + let value = Self::lock_value(&self.value).clone(); + let path = Path::new(&value); self.result = if path.is_file() { Url::from_file_path(path).ok() } else { - Url::parse(&self.value).ok() + Url::parse(&value).ok() }; self