11use crate :: app:: navigation_result:: NavigationActionResult ;
22use crate :: app:: state:: { NodeType , SessionState , TreeNode } ;
33use crate :: fs:: current_dir:: {
4- is_filesystem_root, list_current_directory_with_visibility, parent_path,
4+ directory_access_error_message, is_filesystem_root, list_current_directory_with_visibility,
5+ parent_path,
56} ;
67use anyhow:: Result ;
78use std:: path:: { Path , PathBuf } ;
89
910const MAX_DIR_ENTRIES : usize = 2000 ;
1011
12+ fn replace_directory_entries (
13+ state : & mut SessionState ,
14+ nodes : & mut Vec < TreeNode > ,
15+ entries : Vec < TreeNode > ,
16+ preferred : Option < & PathBuf > ,
17+ ) {
18+ state. clear_current_dir_error ( ) ;
19+ * nodes = entries;
20+ state. restore_or_default_selection ( nodes, preferred) ;
21+ state. update_selected_path ( nodes) ;
22+ }
23+
24+ fn set_current_directory_error (
25+ state : & mut SessionState ,
26+ nodes : & mut Vec < TreeNode > ,
27+ message : String ,
28+ ) {
29+ state. set_current_dir_error ( message) ;
30+ nodes. clear ( ) ;
31+ state. selected_index = 0 ;
32+ state. set_selected_path ( state. current_path . clone ( ) ) ;
33+ }
34+
1135fn absolute_current_path ( path : & Path ) -> PathBuf {
1236 if path. is_absolute ( ) {
1337 return path. to_path_buf ( ) ;
@@ -75,13 +99,19 @@ pub fn enter_selected_directory(
7599
76100 let target = node. path . clone ( ) ;
77101 let entries =
78- list_current_directory_with_visibility ( & target, MAX_DIR_ENTRIES , state. show_hidden ) ?;
102+ match list_current_directory_with_visibility ( & target, MAX_DIR_ENTRIES , state. show_hidden ) {
103+ Ok ( entries) => entries,
104+ Err ( error) => {
105+ return Ok ( NavigationActionResult :: blocked (
106+ "enter_directory" ,
107+ state. current_path . clone ( ) ,
108+ directory_access_error_message ( & error) ,
109+ ) ) ;
110+ }
111+ } ;
79112 state. last_child_path = Some ( target. clone ( ) ) ;
80113 state. current_path = target. clone ( ) ;
81- * nodes = entries;
82- state. selected_index = 0 ;
83- state. revalidate_selection ( nodes) ;
84- state. update_selected_path ( nodes) ;
114+ replace_directory_entries ( state, nodes, entries, None ) ;
85115
86116 Ok ( NavigationActionResult :: changed (
87117 "enter_directory" ,
@@ -114,11 +144,18 @@ pub fn go_to_parent_directory(
114144
115145 let previous_child = current_path;
116146 let entries =
117- list_current_directory_with_visibility ( & parent, MAX_DIR_ENTRIES , state. show_hidden ) ?;
147+ match list_current_directory_with_visibility ( & parent, MAX_DIR_ENTRIES , state. show_hidden ) {
148+ Ok ( entries) => entries,
149+ Err ( error) => {
150+ return Ok ( NavigationActionResult :: blocked (
151+ "go_parent" ,
152+ state. current_path . clone ( ) ,
153+ directory_access_error_message ( & error) ,
154+ ) ) ;
155+ }
156+ } ;
118157 state. current_path = parent. clone ( ) ;
119- * nodes = entries;
120- state. restore_or_default_selection ( nodes, Some ( & previous_child) ) ;
121- state. update_selected_path ( nodes) ;
158+ replace_directory_entries ( state, nodes, entries, Some ( & previous_child) ) ;
122159
123160 Ok ( NavigationActionResult :: changed (
124161 "go_parent" ,
@@ -132,14 +169,23 @@ pub fn refresh_current_directory(
132169 nodes : & mut Vec < TreeNode > ,
133170) -> Result < NavigationActionResult > {
134171 let previous_selected_path = nodes. get ( state. selected_index ) . map ( |n| n. path . clone ( ) ) ;
135- let entries = list_current_directory_with_visibility (
172+ let entries = match list_current_directory_with_visibility (
136173 & state. current_path ,
137174 MAX_DIR_ENTRIES ,
138175 state. show_hidden ,
139- ) ?;
140- * nodes = entries;
141- state. restore_or_default_selection ( nodes, previous_selected_path. as_ref ( ) ) ;
142- state. update_selected_path ( nodes) ;
176+ ) {
177+ Ok ( entries) => entries,
178+ Err ( error) => {
179+ let message = directory_access_error_message ( & error) ;
180+ set_current_directory_error ( state, nodes, message. clone ( ) ) ;
181+ return Ok ( NavigationActionResult :: blocked (
182+ "refresh_current_dir" ,
183+ state. current_path . clone ( ) ,
184+ message,
185+ ) ) ;
186+ }
187+ } ;
188+ replace_directory_entries ( state, nodes, entries, previous_selected_path. as_ref ( ) ) ;
143189
144190 Ok ( NavigationActionResult :: changed (
145191 "refresh_current_dir" ,
0 commit comments