1- use druid:: { AppLauncher , Data , Env , Lens , LocalizedString , Selector , SingleUse , Target , Widget , WidgetExt , WindowDesc } ;
2- use std:: path:: { Path , PathBuf } ;
3- use std:: sync:: { Arc , Mutex } ;
4- use walkdir:: WalkDir ;
5- use std:: env;
1+ use druid:: { widget, AppLauncher , Data , Lens , LocalizedString , Widget , WidgetExt , WindowDesc } ;
2+ use regex:: Regex ;
3+
64
75
6+ use std:: path:: { Path , PathBuf } ;
7+ use std:: sync:: { mpsc, Arc , Mutex } ;
8+ use std:: thread;
9+ use walkdir:: WalkDir ;
810
911#[ derive( Clone , Data , Lens ) ]
1012struct AppState {
@@ -14,43 +16,79 @@ struct AppState {
1416 result : String ,
1517}
1618
19+ #[ derive( Clone , Data , Lens ) ]
20+ struct SearchUpdate {
21+ result : String ,
22+ }
23+
1724fn build_ui ( ) -> impl Widget < AppState > {
18- druid:: widget:: Flex :: column ( )
19- . with_child ( druid:: widget:: TextBox :: new ( ) . lens ( AppState :: search_term) )
20- . with_child ( druid:: widget:: Button :: new ( "Search" ) . on_click ( |_, data : & mut AppState , _| {
21- let root_path = data. root_path . lock ( ) . unwrap ( ) . clone ( ) ;
22- let search_term = data. search_term . clone ( ) ;
23-
24- let result = search_files ( & root_path, & search_term) ;
25- data. result = result;
26- } ) )
27- . with_child ( druid:: widget:: Label :: new ( |data : & AppState , _env : & _ | data. result . clone ( ) ) )
25+ let label = widget:: Label :: new ( |data : & AppState , _env : & _ | data. result . clone ( ) ) . with_text_size ( 20.0 ) ;
26+
27+ let scrollable_label = druid:: widget:: Scroll :: new ( label) ;
28+
29+ widget:: Flex :: column ( )
30+ . with_child ( widget:: TextBox :: new ( ) . lens ( AppState :: search_term) )
31+ . with_child (
32+ widget:: Button :: new ( "Search" ) . on_click ( |_, data : & mut AppState , _| {
33+ let root_path = data. root_path . lock ( ) . unwrap ( ) . clone ( ) ;
34+ let search_term = data. search_term . clone ( ) ;
35+
36+ let ( tx, rx) = mpsc:: channel ( ) ;
37+ let tx_copy = tx. clone ( ) ;
38+
39+ thread:: spawn ( move || {
40+ let result = search_files ( & root_path, & search_term, Some ( tx) ) ;
41+ let _ = tx_copy. send ( SearchUpdate { result } ) ;
42+ } ) ;
43+
44+ let mut result = String :: new ( ) ;
45+ for update in rx. iter ( ) {
46+ result. push_str ( & update. result ) ;
47+ data. result = result. clone ( ) ;
48+ }
49+ } ) ,
50+ )
51+ . with_child ( scrollable_label)
2852}
2953
30- fn search_files ( root_path : & Path , search_term : & str ) -> String {
54+ fn search_files (
55+ root_path : & Path ,
56+ search_term : & str ,
57+ tx : Option < mpsc:: Sender < SearchUpdate > > ,
58+ ) -> String {
3159 let mut result = String :: new ( ) ;
60+ let search_term_regex = Regex :: new ( & format ! ( r"(?i){}" , search_term) ) . expect ( "Invalid regex" ) ;
3261
33- for entry in WalkDir :: new ( root_path) {
34- if let Ok ( entry) = entry {
35- let path = entry. path ( ) ;
36- if path. is_file ( ) {
37- if let Some ( file_name) = path. file_name ( ) {
38- if file_name. to_string_lossy ( ) . contains ( search_term) {
39- result. push_str ( & format ! ( "{}\n " , path. display( ) ) ) ;
40- }
41- }
62+ WalkDir :: new ( root_path)
63+ . into_iter ( )
64+ . filter_map ( |entry| entry. ok ( ) )
65+ . filter ( |entry| entry. path ( ) . is_file ( ) )
66+ . filter ( |entry| {
67+ entry
68+ . file_name ( )
69+ . to_str ( )
70+ . map ( |name| search_term_regex. is_match ( name) )
71+ . unwrap_or ( false )
72+ } )
73+ . for_each ( |entry| {
74+ let found_path = format ! ( "{}\n " , entry. path( ) . display( ) ) ;
75+ result. push_str ( & found_path) ;
76+ if let Some ( tx) = & tx {
77+ let _ = tx. send ( SearchUpdate {
78+ result : found_path. clone ( ) ,
79+ } ) ;
4280 }
43- }
44- }
81+ } ) ;
4582
4683 result
4784}
4885
86+
4987fn main ( ) {
5088 let main_window = WindowDesc :: new ( build_ui ( ) )
51- . title ( LocalizedString :: new ( "File Explorer" ) ) ;
89+ . title ( LocalizedString :: new ( "File Explorer" ) ) ;
5290
53- let root_path = Arc :: new ( Mutex :: new ( env:: current_dir ( ) . unwrap ( ) ) ) ;
91+ let root_path = Arc :: new ( Mutex :: new ( std :: env:: current_dir ( ) . unwrap ( ) ) ) ;
5492
5593 let app_state = AppState {
5694 root_path : root_path. clone ( ) ,
@@ -62,4 +100,4 @@ fn main() {
62100 . log_to_console ( )
63101 . launch ( app_state)
64102 . expect ( "Failed to launch application" ) ;
65- }
103+ }
0 commit comments