77//! - Last used directory memory
88
99use dioxus:: prelude:: * ;
10- use native_dialog:: { FileDialog , MessageDialog , MessageType } ;
10+ use native_dialog:: FileDialog ;
1111use std:: path:: PathBuf ;
1212use tracing:: { debug, info, warn} ;
1313
@@ -20,43 +20,43 @@ pub struct FileFilter {
2020 pub extensions : & ' static [ & ' static str ] ,
2121}
2222
23- #[ allow( dead_code) ]
2423impl FileFilter {
25- /// Common filter for image files.
24+ /// Common filter for all files.
25+ pub const ALL : Self = Self {
26+ name : "All Files" ,
27+ extensions : & [ "*" ] ,
28+ } ;
29+
30+ // Test-only constants
31+ #[ cfg( test) ]
2632 pub const IMAGES : Self = Self {
2733 name : "Images" ,
2834 extensions : & [ "png" , "jpg" , "jpeg" , "gif" , "webp" , "bmp" , "ico" , "svg" ] ,
2935 } ;
3036
31- /// Common filter for document files.
37+ # [ cfg ( test ) ]
3238 pub const DOCUMENTS : Self = Self {
3339 name : "Documents" ,
3440 extensions : & [ "pdf" , "doc" , "docx" , "txt" , "rtf" , "odt" , "md" ] ,
3541 } ;
3642
37- /// Common filter for video files.
43+ # [ cfg ( test ) ]
3844 pub const VIDEOS : Self = Self {
3945 name : "Videos" ,
4046 extensions : & [ "mp4" , "mkv" , "avi" , "mov" , "webm" , "m4v" ] ,
4147 } ;
4248
43- /// Common filter for audio files.
49+ # [ cfg ( test ) ]
4450 pub const AUDIO : Self = Self {
4551 name : "Audio" ,
4652 extensions : & [ "mp3" , "wav" , "flac" , "ogg" , "m4a" , "aac" ] ,
4753 } ;
4854
49- /// Common filter for archive files.
55+ # [ cfg ( test ) ]
5056 pub const ARCHIVES : Self = Self {
5157 name : "Archives" ,
5258 extensions : & [ "zip" , "tar" , "gz" , "7z" , "rar" , "xz" ] ,
5359 } ;
54-
55- /// Common filter for all files.
56- pub const ALL : Self = Self {
57- name : "All Files" ,
58- extensions : & [ "*" ] ,
59- } ;
6060}
6161
6262/// Result of a file picker operation.
@@ -70,14 +70,14 @@ pub enum PickerResult {
7070 Error ( String ) ,
7171}
7272
73- #[ allow( dead_code) ]
73+
74+ // Test-only methods for PickerResult
75+ #[ cfg( test) ]
7476impl PickerResult {
75- /// Returns true if files were selected.
7677 pub fn has_selection ( & self ) -> bool {
7778 matches ! ( self , Self :: Selected ( files) if !files. is_empty( ) )
7879 }
7980
80- /// Returns the selected files, or an empty vec.
8181 pub fn files ( & self ) -> Vec < PathBuf > {
8282 match self {
8383 Self :: Selected ( files) => files. clone ( ) ,
@@ -113,19 +113,7 @@ impl Default for PickerConfig {
113113 }
114114}
115115
116- #[ allow( dead_code) ]
117116impl PickerConfig {
118- /// Create a config for single file selection.
119- pub fn single_file ( ) -> Self {
120- Self {
121- title : "Select File" . to_string ( ) ,
122- multiple : false ,
123- directory : false ,
124- filters : vec ! [ FileFilter :: ALL ] ,
125- start_directory : None ,
126- }
127- }
128-
129117 /// Create a config for multi-file selection.
130118 pub fn multiple_files ( ) -> Self {
131119 Self {
@@ -137,58 +125,48 @@ impl PickerConfig {
137125 }
138126 }
139127
140- /// Create a config for directory selection.
141- pub fn directory ( ) -> Self {
142- Self {
143- title : "Select Folder" . to_string ( ) ,
144- multiple : false ,
145- directory : true ,
146- filters : vec ! [ ] ,
147- start_directory : None ,
148- }
128+ /// Builder: set the title.
129+ pub fn with_title ( mut self , title : impl Into < String > ) -> Self {
130+ self . title = title. into ( ) ;
131+ self
149132 }
150133
151- /// Create a config for image file selection.
152- pub fn images ( ) -> Self {
134+ // Test-only builder methods
135+ #[ cfg( test) ]
136+ pub fn single_file ( ) -> Self {
153137 Self {
154- title : "Select Images " . to_string ( ) ,
155- multiple : true ,
138+ title : "Select File " . to_string ( ) ,
139+ multiple : false ,
156140 directory : false ,
157- filters : vec ! [ FileFilter :: IMAGES , FileFilter :: ALL ] ,
141+ filters : vec ! [ FileFilter :: ALL ] ,
158142 start_directory : None ,
159143 }
160144 }
161145
162- /// Create a config for document selection.
163- pub fn documents ( ) -> Self {
146+ # [ cfg ( test ) ]
147+ pub fn directory ( ) -> Self {
164148 Self {
165- title : "Select Documents " . to_string ( ) ,
166- multiple : true ,
167- directory : false ,
168- filters : vec ! [ FileFilter :: DOCUMENTS , FileFilter :: ALL ] ,
149+ title : "Select Folder " . to_string ( ) ,
150+ multiple : false ,
151+ directory : true ,
152+ filters : vec ! [ ] ,
169153 start_directory : None ,
170154 }
171155 }
172156
173- /// Builder: set the title.
174- pub fn with_title ( mut self , title : impl Into < String > ) -> Self {
175- self . title = title. into ( ) ;
176- self
177- }
178-
179- /// Builder: enable multiple selection.
157+ #[ cfg( test) ]
180158 pub fn with_multiple ( mut self , multiple : bool ) -> Self {
181159 self . multiple = multiple;
182160 self
183161 }
184162
185- /// Builder: set starting directory.
163+ # [ cfg ( test ) ]
186164 pub fn with_start_directory ( mut self , dir : PathBuf ) -> Self {
187165 self . start_directory = Some ( dir) ;
188166 self
189167 }
190168
191- /// Builder: add a file filter.
169+ # [ cfg ( test ) ]
192170 pub fn with_filter ( mut self , filter : FileFilter ) -> Self {
193171 self . filters . push ( filter) ;
194172 self
@@ -327,77 +305,6 @@ pub fn open_file_picker(config: &PickerConfig) -> PickerResult {
327305 }
328306}
329307
330- /// Open a save file dialog.
331- #[ allow( dead_code) ]
332- pub fn open_save_picker ( title : & str , default_name : & str , filters : & [ FileFilter ] ) -> PickerResult {
333- let start_dir = get_last_directory ( )
334- . or_else ( dirs:: download_dir)
335- . or_else ( dirs:: home_dir) ;
336-
337- debug ! (
338- target: "ui.drive.picker" ,
339- title = %title,
340- default_name = %default_name,
341- "Opening save picker"
342- ) ;
343-
344- let mut dialog = FileDialog :: new ( ) . set_filename ( default_name) ;
345-
346- if let Some ( ref dir) = start_dir {
347- dialog = dialog. set_location ( dir) ;
348- }
349-
350- for filter in filters {
351- dialog = dialog. add_filter ( filter. name , filter. extensions ) ;
352- }
353-
354- match dialog. show_save_single_file ( ) {
355- Ok ( Some ( path) ) => {
356- info ! ( target: "ui.drive.picker" , path = ?path, "Save location selected" ) ;
357- set_last_directory ( & path) ;
358- PickerResult :: Selected ( vec ! [ path] )
359- }
360- Ok ( None ) => {
361- debug ! ( target: "ui.drive.picker" , "Save picker cancelled" ) ;
362- PickerResult :: Cancelled
363- }
364- Err ( e) => {
365- warn ! ( target: "ui.drive.picker" , error = %e, "Save picker error" ) ;
366- PickerResult :: Error ( e. to_string ( ) )
367- }
368- }
369- }
370-
371- /// Show an error message dialog.
372- #[ allow( dead_code) ]
373- pub fn show_error_dialog ( title : & str , message : & str ) {
374- let _ = MessageDialog :: new ( )
375- . set_title ( title)
376- . set_text ( message)
377- . set_type ( MessageType :: Error )
378- . show_alert ( ) ;
379- }
380-
381- /// Show an info message dialog.
382- #[ allow( dead_code) ]
383- pub fn show_info_dialog ( title : & str , message : & str ) {
384- let _ = MessageDialog :: new ( )
385- . set_title ( title)
386- . set_text ( message)
387- . set_type ( MessageType :: Info )
388- . show_alert ( ) ;
389- }
390-
391- /// Show a confirmation dialog. Returns true if confirmed.
392- #[ allow( dead_code) ]
393- pub fn show_confirm_dialog ( title : & str , message : & str ) -> bool {
394- MessageDialog :: new ( )
395- . set_title ( title)
396- . set_text ( message)
397- . set_type ( MessageType :: Warning )
398- . show_confirm ( )
399- . unwrap_or ( false )
400- }
401308
402309/// File picker button component props.
403310#[ derive( Props , Clone , PartialEq ) ]
0 commit comments