file_upload.rs 2.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100
  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(not(any(
  14. target_os = "windows",
  15. target_os = "macos",
  16. target_os = "linux",
  17. target_os = "dragonfly",
  18. target_os = "freebsd",
  19. target_os = "netbsd",
  20. target_os = "openbsd"
  21. )))]
  22. pub(crate) fn get_file_event(_request: &FileDialogRequest) -> Vec<PathBuf> {
  23. vec![]
  24. }
  25. #[cfg(any(
  26. target_os = "windows",
  27. target_os = "macos",
  28. target_os = "linux",
  29. target_os = "dragonfly",
  30. target_os = "freebsd",
  31. target_os = "netbsd",
  32. target_os = "openbsd"
  33. ))]
  34. pub(crate) fn get_file_event(request: &FileDialogRequest) -> Vec<PathBuf> {
  35. let mut dialog = rfd::FileDialog::new();
  36. let filters: Vec<_> = request
  37. .accept
  38. .as_deref()
  39. .unwrap_or_default()
  40. .split(',')
  41. .filter_map(|s| Filters::from_str(s).ok())
  42. .collect();
  43. let file_extensions: Vec<_> = filters
  44. .iter()
  45. .flat_map(|f| f.as_extensions().into_iter())
  46. .collect();
  47. dialog = dialog.add_filter("name", file_extensions.as_slice());
  48. let files: Vec<_> = if request.multiple {
  49. dialog.pick_files().into_iter().flatten().collect()
  50. } else {
  51. dialog.pick_file().into_iter().collect()
  52. };
  53. files
  54. }
  55. enum Filters {
  56. Extension(String),
  57. Mime(String),
  58. Audio,
  59. Video,
  60. Image,
  61. }
  62. impl Filters {
  63. fn as_extensions(&self) -> Vec<&str> {
  64. match self {
  65. Filters::Extension(extension) => vec![extension.as_str()],
  66. Filters::Mime(_) => vec![],
  67. Filters::Audio => vec!["mp3", "wav", "ogg"],
  68. Filters::Video => vec!["mp4", "webm"],
  69. Filters::Image => vec!["png", "jpg", "jpeg", "gif", "webp"],
  70. }
  71. }
  72. }
  73. impl FromStr for Filters {
  74. type Err = String;
  75. fn from_str(s: &str) -> Result<Self, Self::Err> {
  76. if let Some(extension) = s.strip_prefix('.') {
  77. Ok(Filters::Extension(extension.to_string()))
  78. } else {
  79. match s {
  80. "audio/*" => Ok(Filters::Audio),
  81. "video/*" => Ok(Filters::Video),
  82. "image/*" => Ok(Filters::Image),
  83. _ => Ok(Filters::Mime(s.to_string())),
  84. }
  85. }
  86. }
  87. }