file_upload.rs 2.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384
  1. #![allow(unused)]
  2. use serde::Deserialize;
  3. use std::{path::PathBuf, str::FromStr};
  4. #[derive(Debug, Deserialize)]
  5. pub(crate) struct FileDialogRequest {
  6. #[serde(default)]
  7. accept: Option<String>,
  8. multiple: bool,
  9. pub event: String,
  10. pub target: usize,
  11. pub bubbles: bool,
  12. }
  13. #[cfg(target_os = "ios")]
  14. pub(crate) fn get_file_event(_request: &FileDialogRequest) -> Vec<PathBuf> {
  15. vec![]
  16. }
  17. #[cfg(not(target_os = "ios"))]
  18. pub(crate) fn get_file_event(request: &FileDialogRequest) -> Vec<PathBuf> {
  19. let mut dialog = rfd::FileDialog::new();
  20. let filters: Vec<_> = request
  21. .accept
  22. .as_deref()
  23. .unwrap_or_default()
  24. .split(',')
  25. .filter_map(|s| Filters::from_str(s).ok())
  26. .collect();
  27. let file_extensions: Vec<_> = filters
  28. .iter()
  29. .flat_map(|f| f.as_extensions().into_iter())
  30. .collect();
  31. dialog = dialog.add_filter("name", file_extensions.as_slice());
  32. let files: Vec<_> = if request.multiple {
  33. dialog.pick_files().into_iter().flatten().collect()
  34. } else {
  35. dialog.pick_file().into_iter().collect()
  36. };
  37. files
  38. }
  39. enum Filters {
  40. Extension(String),
  41. Mime(String),
  42. Audio,
  43. Video,
  44. Image,
  45. }
  46. impl Filters {
  47. fn as_extensions(&self) -> Vec<&str> {
  48. match self {
  49. Filters::Extension(extension) => vec![extension.as_str()],
  50. Filters::Mime(_) => vec![],
  51. Filters::Audio => vec!["mp3", "wav", "ogg"],
  52. Filters::Video => vec!["mp4", "webm"],
  53. Filters::Image => vec!["png", "jpg", "jpeg", "gif", "webp"],
  54. }
  55. }
  56. }
  57. impl FromStr for Filters {
  58. type Err = String;
  59. fn from_str(s: &str) -> Result<Self, Self::Err> {
  60. if let Some(extension) = s.strip_prefix('.') {
  61. Ok(Filters::Extension(extension.to_string()))
  62. } else {
  63. match s {
  64. "audio/*" => Ok(Filters::Audio),
  65. "video/*" => Ok(Filters::Video),
  66. "image/*" => Ok(Filters::Image),
  67. _ => Ok(Filters::Mime(s.to_string())),
  68. }
  69. }
  70. }
  71. }