file_explorer.rs 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103
  1. //! Example: File Explorer
  2. //! -------------------------
  3. //!
  4. //! This is a fun little desktop application that lets you explore the file system.
  5. //!
  6. //! This example is interesting because it's mixing filesystem operations and GUI, which is typically hard for UI to do.
  7. //!
  8. //! It also uses `use_ref` to maintain a model, rather than `use_state`. That way,
  9. //! we dont need to clutter our code with `read` commands.
  10. use dioxus::prelude::*;
  11. fn main() {
  12. dioxus::desktop::launch_cfg(app, |c| {
  13. c.with_window(|w| {
  14. w.with_resizable(true)
  15. .with_inner_size(dioxus::desktop::tao::dpi::LogicalSize::new(400.0, 800.0))
  16. })
  17. });
  18. }
  19. fn app(cx: Scope) -> Element {
  20. let files = use_ref(&cx, Files::new);
  21. cx.render(rsx!(
  22. h1 { "Files: " }
  23. h3 { "Cur dir: " [files.read().current()] }
  24. button { onclick: move |_| files.write().go_up(), "go up" }
  25. ol {
  26. files.read().path_names.iter().enumerate().map(|(dir_id, path)| rsx!(
  27. li { key: "{path}",
  28. a { href: "#", onclick: move |_| files.write().enter_dir(dir_id),
  29. "{path}",
  30. }
  31. }
  32. ))
  33. }
  34. files.read().err.as_ref().map(|err| rsx!(
  35. div {
  36. code { "{err}" }
  37. button { onclick: move |_| files.write().clear_err(), "x" }
  38. }
  39. ))
  40. ))
  41. }
  42. struct Files {
  43. path_stack: Vec<String>,
  44. path_names: Vec<String>,
  45. err: Option<String>,
  46. }
  47. impl Files {
  48. fn new() -> Self {
  49. let mut files = Self {
  50. path_stack: vec!["./".to_string()],
  51. path_names: vec![],
  52. err: None,
  53. };
  54. files.reload_path_list();
  55. files
  56. }
  57. fn reload_path_list(&mut self) {
  58. let paths = match std::fs::read_dir(self.path_stack.last().unwrap()) {
  59. Ok(e) => e,
  60. Err(err) => {
  61. self.err = Some(format!("An error occured: {:?}", err));
  62. self.path_stack.pop();
  63. return;
  64. }
  65. };
  66. // clear the current state
  67. self.clear_err();
  68. self.path_names.clear();
  69. self.path_names
  70. .extend(paths.map(|path| path.unwrap().path().display().to_string()));
  71. }
  72. fn go_up(&mut self) {
  73. if self.path_stack.len() > 1 {
  74. self.path_stack.pop();
  75. }
  76. self.reload_path_list();
  77. }
  78. fn enter_dir(&mut self, dir_id: usize) {
  79. let path = &self.path_names[dir_id];
  80. self.path_stack.push(path.clone());
  81. self.reload_path_list();
  82. }
  83. fn current(&self) -> &str {
  84. self.path_stack.last().unwrap()
  85. }
  86. fn clear_err(&mut self) {
  87. self.err = None;
  88. }
  89. }