dear_file_browser/
native.rs1use crate::core::{Backend, DialogMode, FileDialog, FileDialogError, Selection};
18
19#[cfg(feature = "tracing")]
20use tracing::trace;
21
22impl FileDialog {
23 fn to_rfd(&self) -> rfd::FileDialog {
24 let mut d = rfd::FileDialog::new();
25 if let Some(dir) = &self.start_dir {
26 d = d.set_directory(dir);
27 }
28 if let Some(name) = &self.default_name {
29 d = d.set_file_name(name);
30 }
31 for f in &self.filters {
32 let exts: Vec<&str> = f.extensions.iter().map(|s| s.as_str()).collect();
33 d = d.add_filter(&f.name, &exts);
34 }
35 d
36 }
37
38 pub fn open_blocking(self) -> Result<Selection, FileDialogError> {
40 match self.effective_backend() {
41 Backend::Native => self.open_blocking_native(),
42 Backend::ImGui => Err(FileDialogError::Unsupported),
43 Backend::Auto => unreachable!("resolved in effective_backend"),
44 }
45 }
46
47 fn open_blocking_native(self) -> Result<Selection, FileDialogError> {
48 #[cfg(feature = "tracing")]
49 trace!(?self.mode, "rfd blocking open");
50 let mut sel = Selection::default();
51 match self.mode {
52 DialogMode::OpenFile => {
53 if let Some(p) = self.to_rfd().pick_file() {
54 sel.paths.push(p);
55 }
56 }
57 DialogMode::OpenFiles => {
58 if let Some(v) = self.to_rfd().pick_files() {
59 sel.paths.extend(v);
60 }
61 }
62 DialogMode::PickFolder => {
63 if let Some(p) = self.to_rfd().pick_folder() {
64 sel.paths.push(p);
65 }
66 }
67 DialogMode::SaveFile => {
68 if let Some(p) = self.to_rfd().save_file() {
69 sel.paths.push(p);
70 }
71 }
72 }
73 if sel.paths.is_empty() {
74 Err(FileDialogError::Cancelled)
75 } else {
76 Ok(sel)
77 }
78 }
79
80 pub async fn open_async(self) -> Result<Selection, FileDialogError> {
82 use rfd::AsyncFileDialog as A;
83 #[cfg(feature = "tracing")]
84 trace!(?self.mode, "rfd async open");
85 let mut sel = Selection::default();
86 match self.mode {
87 DialogMode::OpenFile => {
88 let mut a = A::new();
89 if let Some(dir) = self.start_dir.as_deref() {
90 a = a.set_directory(dir);
91 }
92 if let Some(name) = self.default_name.as_deref() {
93 a = a.set_file_name(name);
94 }
95 let f = a.pick_file().await;
96 if let Some(h) = f {
97 sel.paths.push(h.path().to_path_buf());
98 }
99 }
100 DialogMode::OpenFiles => {
101 let mut a = A::new();
102 if let Some(dir) = self.start_dir.as_deref() {
103 a = a.set_directory(dir);
104 }
105 if let Some(name) = self.default_name.as_deref() {
106 a = a.set_file_name(name);
107 }
108 let v = a.pick_files().await;
109 if let Some(v) = v {
110 sel.paths
111 .extend(v.into_iter().map(|h| h.path().to_path_buf()));
112 }
113 }
114 DialogMode::PickFolder => {
115 let mut a = A::new();
116 if let Some(dir) = self.start_dir.as_deref() {
117 a = a.set_directory(dir);
118 }
119 let f = a.pick_folder().await;
120 if let Some(h) = f {
121 sel.paths.push(h.path().to_path_buf());
122 }
123 }
124 DialogMode::SaveFile => {
125 let mut a = A::new();
126 if let Some(dir) = self.start_dir.as_deref() {
127 a = a.set_directory(dir);
128 }
129 if let Some(name) = self.default_name.as_deref() {
130 a = a.set_file_name(name);
131 }
132 let f = a.save_file().await;
133 if let Some(h) = f {
134 sel.paths.push(h.path().to_path_buf());
135 }
136 }
137 }
138 if sel.paths.is_empty() {
139 Err(FileDialogError::Cancelled)
140 } else {
141 Ok(sel)
142 }
143 }
144}