1
1
#![ allow( non_snake_case) ]
2
- //! Example: File Explorer
3
- //! -------------------------
4
- //!
5
- //! This is a fun little desktop application that lets you explore the file system.
6
- //!
7
- //! This example is interesting because it's mixing filesystem operations and GUI, which is typically hard for UI to do.
8
2
9
3
use dioxus:: prelude:: * ;
10
- use dioxus_desktop:: { Config , WindowBuilder } ;
11
-
4
+ use log:: LevelFilter ;
12
5
13
6
fn main ( ) {
14
- // simple_logger::init_with_level(log::Level::Debug).unwrap();
15
- dioxus_desktop:: launch_cfg (
16
- App ,
17
- Config :: default ( ) . with_window ( WindowBuilder :: new ( ) . with_resizable ( true ) . with_inner_size (
18
- dioxus_desktop:: wry:: application:: dpi:: LogicalSize :: new ( 400.0 , 800.0 ) ,
19
- ) ) ,
20
- ) ;
7
+ // Init debug
8
+ dioxus_logger:: init ( LevelFilter :: Info ) . expect ( "failed to init logger" ) ;
9
+
10
+ dioxus:: launch ( App ) ;
21
11
}
22
12
23
- fn App ( cx : Scope ) -> Element {
24
- let files = use_ref ( cx, Files :: new) ;
25
-
26
- render ! ( div {
27
- link { href: "https://fonts.googleapis.com/icon?family=Material+Icons" , rel: "stylesheet" }
28
- style { include_str!( "./style.css" ) }
29
- header {
30
- i { class: "material-icons icon-menu" , "menu" }
31
- h1 { "Files: " "{files.read().current()}" }
32
- span { }
33
- i { class: "material-icons" , onclick: move |_| files. write( ) . go_up( ) , "logout" }
34
- }
35
- main {
36
- files. read( ) . path_names. iter( ) . enumerate( ) . map( |( dir_id, path) | {
37
- let path_end = path. split( '/' ) . last( ) . unwrap_or( path. as_str( ) ) ;
38
- let icon_type = if path_end. contains( '.' ) {
39
- "description"
40
- } else {
41
- "folder"
42
- } ;
43
- rsx! (
44
- div { class: "folder" , key: "{path}" ,
13
+ #[ component]
14
+ fn App ( ) -> Element {
15
+ // Build cool things ✌️
16
+ let mut files = use_signal ( || Files :: new ( ) ) ;
17
+
18
+ rsx ! {
19
+ div {
20
+ link { href: "https://fonts.googleapis.com/icon?family=Material+Icons" , rel: "stylesheet" }
21
+ link { rel: "stylesheet" , href: "main.css" }
22
+ header {
23
+ i { class: "material-icons icon-menu" , "menu" }
24
+ h1 { "Files: " "{files.read().current()}" }
25
+ span { }
26
+ i { class: "material-icons" , onclick: move |_| files. write( ) . go_up( ) , "logout" }
27
+ }
28
+ main {
29
+ for ( dir_id, path) in files. read( ) . path_names. iter( ) . enumerate( ) {
30
+ div {
31
+ class: "folder" , key: "{path.name}" ,
45
32
i { class: "material-icons" ,
46
33
onclick: move |_| files. write( ) . enter_dir( dir_id) ,
47
- "{icon_type}"
34
+ // Change the icon
35
+ if path. is_directory { "folder" } else { "description" }
36
+ // The tooltip
48
37
p { class: "cooltip" , "0 folders / 0 files" }
49
38
}
50
- h1 { "{path_end}" }
51
- }
52
- )
53
- } )
54
- files. read( ) . err. as_ref( ) . map( |err| {
55
- rsx! (
56
- div {
57
- code { "{err}" }
58
- button { onclick: move |_| files. write( ) . clear_err( ) , "x" }
39
+ h1 { "{path.name}" }
59
40
}
60
- )
61
- } )
41
+ }
42
+ {
43
+ files. read( ) . err. as_ref( ) . map( |err| {
44
+ rsx! (
45
+ div {
46
+ code { "{err}" }
47
+ button { onclick: move |_| files. write( ) . clear_err( ) , "x" }
48
+ }
49
+ )
50
+ } )
51
+ }
52
+ }
62
53
}
54
+ }
55
+ }
63
56
64
- } )
57
+
58
+ #[ derive( Debug ) ]
59
+ struct File {
60
+ is_directory : bool ,
61
+ name : String ,
65
62
}
66
63
67
64
struct Files {
68
65
path_stack : Vec < String > ,
69
- path_names : Vec < String > ,
66
+ path_names : Vec < File > ,
70
67
err : Option < String > ,
71
68
}
72
69
73
70
impl Files {
74
71
fn new ( ) -> Self {
75
72
let mut files = Self {
76
- path_stack : vec ! [ "./ " . to_string( ) ] ,
73
+ path_stack : vec ! [ "." . to_string( ) ] ,
77
74
path_names : vec ! [ ] ,
78
75
err : None ,
79
76
} ;
@@ -84,26 +81,23 @@ impl Files {
84
81
}
85
82
86
83
fn reload_path_list ( & mut self ) {
87
- let cur_path = self . path_stack . last ( ) . unwrap ( ) ;
84
+ let cur_path = self . path_stack . join ( "/" ) ;
88
85
log:: info!( "Reloading path list for {:?}" , cur_path) ;
89
- let paths = match std:: fs:: read_dir ( cur_path) {
86
+ let paths = match std:: fs:: read_dir ( & cur_path) {
90
87
Ok ( e) => e,
91
- Err ( err) => { //Likely we're trying to open a file, so let's open it!
92
- match open:: that ( cur_path) {
93
- Ok ( _) => {
94
- log:: info!( "Opened file" ) ;
95
- return ;
96
- } ,
97
- Err ( err) => {
98
- let err = format ! ( "An error occurred: {:?}" , err) ;
99
- self . err = Some ( err) ;
100
- self . path_stack . pop ( ) ;
101
- return ;
102
- }
88
+ Err ( err) => { // Likely we're trying to open a file, so let's open it!
89
+ if let Ok ( _) = open:: that ( cur_path) {
90
+ log:: info!( "Opened file" ) ;
91
+ return ;
92
+ } else {
93
+ let err = format ! ( "An error occurred: {:?}" , err) ;
94
+ self . err = Some ( err) ;
95
+ self . path_stack . pop ( ) ;
96
+ return ;
103
97
}
104
-
105
98
}
106
99
} ;
100
+
107
101
let collected = paths. collect :: < Vec < _ > > ( ) ;
108
102
log:: info!( "Path list reloaded {:#?}" , collected) ;
109
103
@@ -112,8 +106,14 @@ impl Files {
112
106
self . path_names . clear ( ) ;
113
107
114
108
for path in collected {
109
+ let file = path. unwrap ( ) ;
115
110
self . path_names
116
- . push ( path. unwrap ( ) . path ( ) . display ( ) . to_string ( ) ) ;
111
+ . push (
112
+ File {
113
+ name : file. file_name ( ) . to_str ( ) . unwrap ( ) . to_string ( ) ,
114
+ is_directory : file. file_type ( ) . unwrap ( ) . is_dir ( ) ,
115
+ }
116
+ ) ;
117
117
}
118
118
log:: info!( "path names are {:#?}" , self . path_names) ;
119
119
}
@@ -127,13 +127,15 @@ impl Files {
127
127
128
128
fn enter_dir ( & mut self , dir_id : usize ) {
129
129
let path = & self . path_names [ dir_id] ;
130
- self . path_stack . push ( path. clone ( ) ) ;
130
+ self . path_stack . push ( path. name . to_string ( ) ) ;
131
+ println ! ( "{:#?}" , self . path_stack) ;
131
132
self . reload_path_list ( ) ;
132
133
}
133
134
134
- fn current ( & self ) -> & str {
135
- self . path_stack . last ( ) . unwrap ( )
135
+ fn current ( & self ) -> String {
136
+ self . path_stack . join ( "/" )
136
137
}
138
+
137
139
fn clear_err ( & mut self ) {
138
140
self . err = None ;
139
141
}
0 commit comments