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    /// FileDescriptor mode: "w"
175    #[deprecated = "This may or may not truncate existing contents. So please use WriteTruncate or WriteAppend instead."]
176    Write,
177
178    /// Opens the file in write-only mode.
179    /// The existing content is truncated (deleted), and new data is written from the beginning.
180    /// Creates a new file if it does not exist.
181    ///
182    /// FileDescriptor mode: "wt"
183    WriteTruncate,
184
185    /// Opens the file in write-only mode.
186    /// The existing content is preserved, and new data is appended to the end of the file.
187    /// Creates a new file if it does not exist.
188    /// 
189    /// FileDescriptor mode: "wa"
190    WriteAppend,
191
192    /// Opens the file in read-write mode.  
193    /// 
194    /// FileDescriptor mode: "rw"
195    ReadWrite,
196
197    /// Opens the file in read-write mode.
198    /// The existing content is truncated (deleted), and new data is written from the beginning.
199    /// Creates a new file if it does not exist.
200    ///
201    /// FileDescriptor mode: "rwt"
202    ReadWriteTruncate,
203}
204
205/// Filters for VisualMediaPicker.
206#[derive(Debug, Clone, Hash, PartialEq, Eq, Deserialize, Serialize)]
207#[non_exhaustive]
208pub enum VisualMediaTarget {
209
210    /// Allow only images to be selected.  
211    ImageOnly,
212
213    /// Allow only videos to be selected.  
214    VideoOnly,
215
216    /// Allow only images and videos to be selected.  
217    ImageAndVideo,
218}
219
220/// The application specific directory.  
221#[derive(Debug, Clone, Copy, Hash, PartialEq, Eq, Deserialize, Serialize)]
222#[non_exhaustive]
223pub enum PrivateDir {
224
225    /// The application specific persistent-data directory.  
226    /// 
227    /// The system prevents other apps and user from accessing these locations. 
228    /// In cases where the device is rooted or the user has special permissions, the user may be able to access this.   
229    ///  
230    /// These files will be deleted when the app is uninstalled and may also be deleted at the user’s request.  
231    /// 
232    /// ex: `/data/user/0/{app-package-name}/files`
233    Data,
234
235    /// The application specific cache directory.  
236    /// 
237    /// The system prevents other apps and user from accessing these locations. 
238    /// In cases where the device is rooted or the user has special permissions, the user may be able to access this.   
239    /// 
240    /// These files will be deleted when the app is uninstalled and may also be deleted at the user’s request. 
241    /// In addition, the system will automatically delete files in this directory as disk space is needed elsewhere on the device.  
242    /// 
243    /// ex: `/data/user/0/{app-package-name}/cache`
244    Cache,
245}
246
247#[derive(Debug, Clone, Copy, Hash, PartialEq, Eq, Deserialize, Serialize)]
248#[non_exhaustive]
249pub enum PublicDir {
250    
251    #[serde(untagged)]
252    Image(PublicImageDir),
253
254    #[serde(untagged)]
255    Video(PublicVideoDir),
256
257    #[serde(untagged)]
258    Audio(PublicAudioDir),
259
260    #[serde(untagged)]
261    GeneralPurpose(PublicGeneralPurposeDir),
262}
263
264/// Directory in which to place images that are available to other applications and users.  
265#[derive(Debug, Clone, Copy, Hash, PartialEq, Eq, Deserialize, Serialize)]
266#[non_exhaustive]
267pub enum PublicImageDir {
268
269    /// Standard directory in which to place pictures that are available to the user.  
270    /// 
271    /// ex: `~/Pictures`
272    Pictures,
273
274    /// The traditional location for pictures and videos when mounting the device as a camera.  
275    /// 
276    /// ex: `~/DCIM`
277    DCIM,
278}
279
280/// Directory in which to place videos that are available to other applications and users.  
281#[derive(Debug, Clone, Copy, Hash, PartialEq, Eq, Deserialize, Serialize)]
282#[non_exhaustive]
283pub enum PublicVideoDir {
284
285	/// Standard directory in which to place movies that are available to the user.  
286	/// 
287	/// ex: `~/Movies`
288	Movies,
289
290	/// The traditional location for pictures and videos when mounting the device as a camera.  
291	/// 
292	/// ex: `~/DCIM`
293	DCIM,
294}
295
296/// Directory in which to place audios that are available to other applications and users.  
297#[derive(Debug, Clone, Copy, Hash, PartialEq, Eq, Deserialize, Serialize)]
298#[non_exhaustive]
299pub enum PublicAudioDir {
300
301    /// Standard directory in which to place movies that are available to the user.  
302    /// 
303    /// ex: `~/Music`
304    Music,
305
306    /// 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).  
307    /// 
308    /// ex: `~/Alarms`
309    Alarms,
310
311    /// 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).  
312    /// 
313    /// This is not available on Android 9 (API level 28) and lower.  
314    /// 
315    /// ex: `~/Audiobooks`  
316    Audiobooks,
317
318    /// 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).  
319    /// 
320    /// ex: `~/Notifications`
321    Notifications,
322
323    /// 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).  
324    /// 
325    /// ex: `~/Podcasts`
326    Podcasts,
327
328    /// 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).  
329    /// 
330    /// ex: `~/Ringtones`
331    Ringtones,
332
333    /// 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).   
334    /// 
335    /// This is not available on Android 11 (API level 30) and lower.  
336    /// 
337    /// ex: `~/Recordings`
338    Recordings,
339}
340
341/// Directory in which to place files that are available to other applications and users.  
342#[derive(Debug, Clone, Copy, Hash, PartialEq, Eq, Deserialize, Serialize)]
343#[non_exhaustive]
344pub enum PublicGeneralPurposeDir {
345
346    /// Standard directory in which to place documents that have been created by the user.  
347    /// 
348    /// ex: `~/Documents`
349    Documents,
350
351    /// Standard directory in which to place files that have been downloaded by the user.  
352    /// 
353    /// ex: `~/Download`  
354    Download,
355}
356
357
358macro_rules! impl_into_pubdir {
359    ($target: ident, $wrapper: ident) => {
360        impl From<$target> for PublicDir {
361            fn from(value: $target) -> Self {
362                Self::$wrapper(value)
363            }
364        }
365    };
366}
367impl_into_pubdir!(PublicImageDir, Image);
368impl_into_pubdir!(PublicVideoDir, Video);
369impl_into_pubdir!(PublicAudioDir, Audio);
370impl_into_pubdir!(PublicGeneralPurposeDir, GeneralPurpose);