rlobkit_dialogs/
picker.rs1use crate::{RlobKitMode, RlobKitType};
2use rlobkit_core::{PlatformDirectory, PlatformFile, RlobKitError};
3use std::path::{Path, PathBuf};
4
5#[derive(Debug, Clone, Default)]
6pub struct OpenFileOptions {
7 pub file_type: RlobKitType,
8 pub mode: RlobKitMode,
9 pub title: Option<String>,
10 pub initial_directory: Option<PathBuf>,
11}
12
13#[derive(Debug, Clone, Default)]
14pub struct SaveFileOptions {
15 pub suggested_name: Option<String>,
16 pub extension: Option<String>,
17 pub title: Option<String>,
18 pub initial_directory: Option<PathBuf>,
19 pub file_type: Option<RlobKitType>,
20 #[cfg(target_arch = "wasm32")]
21 pub data: Option<Vec<u8>>,
22}
23
24#[derive(Debug, Clone, Default)]
25pub struct OpenDirectoryOptions {
26 pub title: Option<String>,
27 pub initial_directory: Option<PathBuf>,
28}
29
30trait PlatformBackend {
31 async fn open_file_picker(opts: OpenFileOptions) -> Result<Option<Vec<PlatformFile>>, RlobKitError>;
32 async fn open_directory_picker(opts: OpenDirectoryOptions) -> Result<Option<PlatformDirectory>, RlobKitError>;
33 async fn open_file_saver(opts: SaveFileOptions) -> Result<Option<PlatformFile>, RlobKitError>;
34 fn write_file_from_path(target: &PlatformFile, source: &Path) -> Result<(), RlobKitError>;
35 fn read_file_to_path(source: &PlatformFile, dest: &Path) -> Result<(), RlobKitError>;
36}
37
38#[cfg(any(target_os = "windows", target_os = "macos", target_os = "linux"))]
39struct Backend;
40
41#[cfg(any(target_os = "windows", target_os = "macos", target_os = "linux"))]
42impl PlatformBackend for Backend {
43 async fn open_file_picker(opts: OpenFileOptions) -> Result<Option<Vec<PlatformFile>>, RlobKitError> {
44 crate::desktop::open_file_picker(opts).await
45 }
46
47 async fn open_directory_picker(opts: OpenDirectoryOptions) -> Result<Option<PlatformDirectory>, RlobKitError> {
48 crate::desktop::open_directory_picker(opts).await
49 }
50
51 async fn open_file_saver(opts: SaveFileOptions) -> Result<Option<PlatformFile>, RlobKitError> {
52 crate::desktop::open_file_saver(opts).await
53 }
54
55 fn write_file_from_path(target: &PlatformFile, source: &Path) -> Result<(), RlobKitError> {
56 crate::desktop::write_file_from_path(target, source)
57 }
58
59 fn read_file_to_path(source: &PlatformFile, dest: &Path) -> Result<(), RlobKitError> {
60 crate::desktop::read_file_to_path(source, dest)
61 }
62}
63
64#[cfg(target_arch = "wasm32")]
65struct Backend;
66
67#[cfg(target_arch = "wasm32")]
68impl PlatformBackend for Backend {
69 async fn open_file_picker(opts: OpenFileOptions) -> Result<Option<Vec<PlatformFile>>, RlobKitError> {
70 crate::wasm::open_file_picker(opts).await
71 }
72
73 async fn open_directory_picker(_opts: OpenDirectoryOptions) -> Result<Option<PlatformDirectory>, RlobKitError> {
74 Err(RlobKitError::UnsupportedOperation("Directory picker not supported on WASM".into()))
75 }
76
77 async fn open_file_saver(opts: SaveFileOptions) -> Result<Option<PlatformFile>, RlobKitError> {
78 crate::wasm::open_file_saver(opts).await
79 }
80
81 fn write_file_from_path(_target: &PlatformFile, _source: &Path) -> Result<(), RlobKitError> {
82 Err(RlobKitError::UnsupportedOperation("Filesystem copy is not supported on WASM".into()))
83 }
84
85 fn read_file_to_path(_source: &PlatformFile, _dest: &Path) -> Result<(), RlobKitError> {
86 Err(RlobKitError::UnsupportedOperation("Filesystem copy is not supported on WASM".into()))
87 }
88}
89
90#[cfg(target_os = "android")]
91struct Backend;
92
93#[cfg(target_os = "android")]
94impl PlatformBackend for Backend {
95 async fn open_file_picker(opts: OpenFileOptions) -> Result<Option<Vec<PlatformFile>>, RlobKitError> {
96 crate::android::open_file_picker(opts).await
97 }
98
99 async fn open_directory_picker(opts: OpenDirectoryOptions) -> Result<Option<PlatformDirectory>, RlobKitError> {
100 crate::android::open_directory_picker(opts).await
101 }
102
103 async fn open_file_saver(opts: SaveFileOptions) -> Result<Option<PlatformFile>, RlobKitError> {
104 crate::android::open_file_saver(opts).await
105 }
106
107 fn write_file_from_path(target: &PlatformFile, source: &Path) -> Result<(), RlobKitError> {
108 crate::android::write_file_from_path(target, source)
109 }
110
111 fn read_file_to_path(source: &PlatformFile, dest: &Path) -> Result<(), RlobKitError> {
112 crate::android::read_file_to_path(source, dest)
113 }
114}
115
116pub struct RlobKit;
117
118impl RlobKit {
119 pub async fn open_file_picker(
120 opts: OpenFileOptions,
121 ) -> Result<Option<Vec<PlatformFile>>, RlobKitError> {
122 Backend::open_file_picker(opts).await
123 }
124
125 pub async fn open_single_file(
126 file_type: RlobKitType,
127 ) -> Result<Option<PlatformFile>, RlobKitError> {
128 let result = Self::open_file_picker(OpenFileOptions {
129 file_type,
130 mode: RlobKitMode::Single,
131 ..Default::default()
132 })
133 .await?;
134 Ok(result.and_then(|v| v.into_iter().next()))
135 }
136
137 pub async fn open_directory_picker(
138 opts: OpenDirectoryOptions,
139 ) -> Result<Option<PlatformDirectory>, RlobKitError> {
140 Backend::open_directory_picker(opts).await
141 }
142
143 pub async fn open_file_saver(
144 opts: SaveFileOptions,
145 ) -> Result<Option<PlatformFile>, RlobKitError> {
146 Backend::open_file_saver(opts).await
147 }
148
149 pub fn write_file_from_path(
150 target: &PlatformFile,
151 source_path: &Path,
152 ) -> Result<(), RlobKitError> {
153 Backend::write_file_from_path(target, source_path)
154 }
155
156 pub fn read_file_to_path(source: &PlatformFile, dest_path: &Path) -> Result<(), RlobKitError> {
157 Backend::read_file_to_path(source, dest_path)
158 }
159
160 pub async fn save_bytes(
161 opts: SaveFileOptions,
162 data: &[u8],
163 ) -> Result<Option<PlatformFile>, RlobKitError> {
164 #[cfg(target_os = "android")]
165 {
166 let target = Self::open_file_saver(opts).await?;
167 if let Some(file) = &target {
168 file.write_bytes(data)?;
169 }
170 return Ok(target);
171 }
172
173 #[cfg(target_arch = "wasm32")]
174 {
175 let mut wasm_opts = opts;
176 wasm_opts.data = Some(data.to_vec());
177 return Self::open_file_saver(wasm_opts).await;
178 }
179
180 #[cfg(any(target_os = "windows", target_os = "macos", target_os = "linux"))]
181 {
182 let target = Self::open_file_saver(opts).await?;
183 if let Some(file) = &target {
184 file.write_bytes(data)?;
185 }
186 return Ok(target);
187 }
188
189 #[allow(unreachable_code)]
190 Err(RlobKitError::UnsupportedOperation(
191 "Unsupported platform".into(),
192 ))
193 }
194}