tauri_plugin_android_fs/
models.rs

1use serde::{Deserialize, Serialize};
2
3
4/// Path to represent a file or directory.
5/// 
6/// # Note
7/// For compatibility, an interconversion to [`tauri_plugin_fs::FilePath`] is implemented, such as follwing.  
8/// This is lossy and also not guaranteed to work properly with other plugins.  
9/// However, reading and writing files by official [`tauri_plugin_fs`] etc. should work well.  
10/// ```no_run
11/// use tauri_plugin_android_fs::FileUri;
12/// use tauri_plugin_fs::FilePath;
13/// 
14/// let uri: FileUri = unimplemented!();
15/// 
16/// let path: FilePath = uri.into();
17/// 
18/// let uri: FileUri = path.into();
19/// ```
20/// 
21/// # Typescript type
22/// You should use the following type because the inner value should not be used directly.  
23/// ```typescript
24/// type FileUri = any
25/// type FileUri = string
26/// ```
27#[derive(Debug, Clone, Hash, PartialEq, Eq, Deserialize, Serialize)]
28#[serde(rename_all = "camelCase")]
29pub struct FileUri {
30    pub(crate) uri: String,
31    pub(crate) document_top_tree_uri: Option<String>,
32}
33
34impl FileUri {
35
36    pub fn to_string(&self) -> crate::Result<String> {
37        serde_json::to_string(self).map_err(Into::into)
38    }
39
40    pub fn from_str(s: &str) -> crate::Result<Self> {
41        serde_json::from_str(s).map_err(Into::into)
42    }
43}
44
45impl From<&std::path::PathBuf> for FileUri {
46
47    fn from(value: &std::path::PathBuf) -> Self {
48        Self { uri: format!("file://{}", value.to_string_lossy()), document_top_tree_uri: None }
49    }
50}
51
52impl From<std::path::PathBuf> for FileUri {
53
54    fn from(ref value: std::path::PathBuf) -> Self {
55        value.into()
56    }
57}
58
59impl From<tauri_plugin_fs::FilePath> for FileUri {
60
61    fn from(value: tauri_plugin_fs::FilePath) -> Self {
62        match value {
63            tauri_plugin_fs::FilePath::Url(url) => Self { uri: url.to_string(), document_top_tree_uri: None },
64            tauri_plugin_fs::FilePath::Path(path_buf) => path_buf.into(),
65        }
66    }
67}
68
69impl From<FileUri> for tauri_plugin_fs::FilePath {
70
71    fn from(value: FileUri) -> Self {
72        let result: std::result::Result<_, std::convert::Infallible> = value.uri.parse();
73
74        // This will not cause panic. Because result err is infallible.
75        result.unwrap()
76    }
77}
78
79#[derive(Debug, Clone, Hash, PartialEq, Eq, Deserialize, Serialize)]
80#[serde(rename_all = "camelCase")]
81pub enum Entry {
82
83    #[non_exhaustive]
84    File {
85        uri: FileUri,
86        name: String,
87        last_modified: std::time::SystemTime,
88        len: u64,
89        mime_type: String,
90    },
91
92    #[non_exhaustive]
93    Dir {
94        uri: FileUri,
95        name: String,
96        last_modified: std::time::SystemTime,
97    }
98}
99
100/// Access mode
101#[derive(Debug, Clone, Copy, Hash, PartialEq, Eq, Deserialize, Serialize)]
102pub enum PersistableAccessMode {
103
104    /// Read access.
105    Read,
106
107    /// Write access.
108    Write,
109
110    /// Read-write access.
111    ReadAndWrite,
112}
113
114#[derive(Debug, Clone, Hash, PartialEq, Eq, Deserialize, Serialize)]
115pub enum PersistedUriPermission {
116    File {
117        uri: FileUri,
118        can_read: bool,
119        can_write: bool,
120    },
121    Dir {
122        uri: FileUri,
123        can_read: bool,
124        can_write: bool,
125    }
126}
127
128impl PersistedUriPermission {
129
130    pub fn uri(&self) -> &FileUri {
131        match self {
132            PersistedUriPermission::File { uri, .. } => uri,
133            PersistedUriPermission::Dir { uri, .. } => uri,
134        }
135    }
136
137    pub fn can_read(&self) -> bool {
138        match self {
139            PersistedUriPermission::File { can_read, .. } => *can_read,
140            PersistedUriPermission::Dir { can_read, .. } => *can_read,
141        }
142    }
143
144    pub fn can_write(&self) -> bool {
145        match self {
146            PersistedUriPermission::File { can_write, .. } => *can_write,
147            PersistedUriPermission::Dir { can_write, .. } => *can_write,
148        }
149    }
150
151    pub fn is_file(&self) -> bool {
152        matches!(self, PersistedUriPermission::File { .. })
153    }
154
155    pub fn is_dir(&self) -> bool {
156        matches!(self, PersistedUriPermission::Dir { .. })
157    }
158}
159
160/// Access mode
161#[derive(Debug, Clone, Copy, Hash, PartialEq, Eq, Deserialize, Serialize)]
162#[non_exhaustive]
163pub enum FileAccessMode {
164
165    /// Opens the file in read-only mode.
166    /// 
167    /// FileDescriptor mode: "r"
168    Read,
169
170    /// Opens the file in write-only mode.  
171    /// **This may or may not truncate.**
172    /// So please use `WriteTruncate` or `WriteAppend` instead.  
173    /// 
174    /// This is there just in case.
175    ///
176    /// FileDescriptor mode: "w"
177    #[deprecated = "This may or may not truncate existing contents. So please use WriteTruncate or WriteAppend instead."]
178    Write,
179
180    /// Opens the file in write-only mode.
181    /// The existing content is truncated (deleted), and new data is written from the beginning.
182    /// Creates a new file if it does not exist.
183    ///
184    /// FileDescriptor mode: "wt"
185    WriteTruncate,
186
187    /// Opens the file in write-only mode.
188    /// The existing content is preserved, and new data is appended to the end of the file.
189    /// Creates a new file if it does not exist.
190    /// 
191    /// FileDescriptor mode: "wa"
192    WriteAppend,
193
194    /// Opens the file in read-write mode.  
195    /// 
196    /// FileDescriptor mode: "rw"
197    ReadWrite,
198
199    /// Opens the file in read-write mode.
200    /// The existing content is truncated (deleted), and new data is written from the beginning.
201    /// Creates a new file if it does not exist.
202    ///
203    /// FileDescriptor mode: "rwt"
204    ReadWriteTruncate,
205}
206
207/// Filters for VisualMediaPicker.
208#[derive(Debug, Clone, Hash, PartialEq, Eq, Deserialize, Serialize)]
209#[non_exhaustive]
210pub enum VisualMediaTarget {
211
212    /// Allow only images to be selected.  
213    ImageOnly,
214
215    /// Allow only videos to be selected.  
216    VideoOnly,
217
218    /// Allow only images and videos to be selected.  
219    ImageAndVideo,
220}
221
222/// The application specific directory.  
223#[derive(Debug, Clone, Copy, Hash, PartialEq, Eq, Deserialize, Serialize)]
224#[non_exhaustive]
225pub enum PrivateDir {
226
227    /// The application specific persistent-data directory.  
228    /// 
229    /// The system prevents other apps and user from accessing these locations. 
230    /// In cases where the device is rooted or the user has special permissions, the user may be able to access this.   
231    ///  
232    /// These files will be deleted when the app is uninstalled and may also be deleted at the user’s request.  
233    /// 
234    /// ex: `/data/user/0/{app-package-name}/files`
235    Data,
236
237    /// The application specific cache directory.  
238    /// 
239    /// The system prevents other apps and user from accessing these locations. 
240    /// In cases where the device is rooted or the user has special permissions, the user may be able to access this.   
241    /// 
242    /// These files will be deleted when the app is uninstalled and may also be deleted at the user’s request. 
243    /// In addition, the system will automatically delete files in this directory as disk space is needed elsewhere on the device.  
244    /// 
245    /// ex: `/data/user/0/{app-package-name}/cache`
246    Cache,
247}
248
249#[derive(Debug, Clone, Copy, Hash, PartialEq, Eq, Deserialize, Serialize)]
250#[non_exhaustive]
251pub enum PublicDir {
252    
253    #[serde(untagged)]
254    Image(PublicImageDir),
255
256    #[serde(untagged)]
257    Video(PublicVideoDir),
258
259    #[serde(untagged)]
260    Audio(PublicAudioDir),
261
262    #[serde(untagged)]
263    GeneralPurpose(PublicGeneralPurposeDir),
264}
265
266/// Directory in which to place images that are available to other applications and users.  
267#[derive(Debug, Clone, Copy, Hash, PartialEq, Eq, Deserialize, Serialize)]
268#[non_exhaustive]
269pub enum PublicImageDir {
270
271    /// Standard directory in which to place pictures that are available to the user.  
272    /// 
273    /// ex: `~/Pictures`
274    Pictures,
275
276    /// The traditional location for pictures and videos when mounting the device as a camera.  
277    /// 
278    /// ex: `~/DCIM`
279    DCIM,
280}
281
282/// Directory in which to place videos that are available to other applications and users.  
283#[derive(Debug, Clone, Copy, Hash, PartialEq, Eq, Deserialize, Serialize)]
284#[non_exhaustive]
285pub enum PublicVideoDir {
286
287	/// Standard directory in which to place movies that are available to the user.  
288	/// 
289	/// ex: `~/Movies`
290	Movies,
291
292	/// The traditional location for pictures and videos when mounting the device as a camera.  
293	/// 
294	/// ex: `~/DCIM`
295	DCIM,
296}
297
298/// Directory in which to place audios that are available to other applications and users.  
299#[derive(Debug, Clone, Copy, Hash, PartialEq, Eq, Deserialize, Serialize)]
300#[non_exhaustive]
301pub enum PublicAudioDir {
302
303    /// Standard directory in which to place movies that are available to the user.  
304    /// 
305    /// ex: `~/Music`
306    Music,
307
308    /// Standard directory in which to place any audio files that should be in the list of alarms that the user can select (not as regular music).  
309    /// 
310    /// ex: `~/Alarms`
311    Alarms,
312
313    /// Standard directory in which to place any audio files that should be in the list of audiobooks that the user can select (not as regular music).  
314    /// 
315    /// This is not available on Android 9 (API level 28) and lower.  
316    /// 
317    /// ex: `~/Audiobooks`  
318    Audiobooks,
319
320    /// Standard directory in which to place any audio files that should be in the list of notifications that the user can select (not as regular music).  
321    /// 
322    /// ex: `~/Notifications`
323    Notifications,
324
325    /// Standard directory in which to place any audio files that should be in the list of podcasts that the user can select (not as regular music).  
326    /// 
327    /// ex: `~/Podcasts`
328    Podcasts,
329
330    /// Standard directory in which to place any audio files that should be in the list of ringtones that the user can select (not as regular music).  
331    /// 
332    /// ex: `~/Ringtones`
333    Ringtones,
334
335    /// Standard directory in which to place any audio files that should be in the list of voice recordings recorded by voice recorder apps that the user can select (not as regular music).   
336    /// 
337    /// This is not available on Android 11 (API level 30) and lower.  
338    /// 
339    /// ex: `~/Recordings`
340    Recordings,
341}
342
343/// Directory in which to place files that are available to other applications and users.  
344#[derive(Debug, Clone, Copy, Hash, PartialEq, Eq, Deserialize, Serialize)]
345#[non_exhaustive]
346pub enum PublicGeneralPurposeDir {
347
348    /// Standard directory in which to place documents that have been created by the user.  
349    /// 
350    /// ex: `~/Documents`
351    Documents,
352
353    /// Standard directory in which to place files that have been downloaded by the user.  
354    /// 
355    /// ex: `~/Download`  
356    Download,
357}
358
359
360macro_rules! impl_into_pubdir {
361    ($target: ident, $wrapper: ident) => {
362        impl From<$target> for PublicDir {
363            fn from(value: $target) -> Self {
364                Self::$wrapper(value)
365            }
366        }
367    };
368}
369impl_into_pubdir!(PublicImageDir, Image);
370impl_into_pubdir!(PublicVideoDir, Video);
371impl_into_pubdir!(PublicAudioDir, Audio);
372impl_into_pubdir!(PublicGeneralPurposeDir, GeneralPurpose);