@@ -8,11 +8,8 @@ mod toggle_switch;
88
99use std:: collections:: { BTreeMap , BTreeSet } ;
1010use std:: time:: { Duration , SystemTime } ;
11- use std:: {
12- collections:: { HashMap , HashSet } ,
13- ops:: DerefMut ,
14- path:: PathBuf ,
15- } ;
11+ use std:: { collections:: { HashMap , HashSet } , fs, ops:: DerefMut , path:: PathBuf } ;
12+ use std:: path:: Path ;
1613
1714use anyhow:: { anyhow, Context , Result } ;
1815use eframe:: egui:: { Button , CollapsingHeader , RichText , Visuals } ;
@@ -34,6 +31,9 @@ use crate::Dirs;
3431use crate :: {
3532 integrate:: uninstall,
3633 is_drg_pak,
34+ is_valid_directory,
35+ copy_directory_contents,
36+ clear_directory,
3737 providers:: {
3838 ApprovalStatus , FetchProgress , ModInfo , ModSpecification , ModStore , ModioTags ,
3939 ProviderFactory , RequiredStatus ,
@@ -928,26 +928,28 @@ impl App {
928928 } ) ;
929929 ui. end_row ( ) ;
930930
931- let config_dir = & self . state . dirs . config_dir ;
932- ui. label ( "Config directory:" ) ;
933- if ui. link ( config_dir. display ( ) . to_string ( ) ) . clicked ( ) {
934- opener:: open ( config_dir) . ok ( ) ;
935- }
936- ui. end_row ( ) ;
931+ let edit_directory_field = |ui : & mut egui:: Ui , label : & str , path : & mut String , err : & mut Option < String > | {
932+ ui. horizontal ( |ui| {
933+ ui. label ( label) ;
934+ ui. text_edit_singleline ( path) ;
937935
938- let cache_dir = & self . state . dirs . cache_dir ;
939- ui . label ( "Cache directory:" ) ;
940- if ui . link ( cache_dir . display ( ) . to_string ( ) ) . clicked ( ) {
941- opener :: open ( cache_dir ) . ok ( ) ;
942- }
943- ui . end_row ( ) ;
936+ if ui . button ( "Browse" ) . clicked ( ) {
937+ if let Some ( selected_path ) = rfd :: FileDialog :: new ( ) . pick_folder ( ) {
938+ * path = selected_path . to_string_lossy ( ) . to_string ( ) ;
939+ * err = None ;
940+ }
941+ }
944942
945- let data_dir = & self . state . dirs . data_dir ;
946- ui. label ( "Data directory:" ) ;
947- if ui. link ( data_dir. display ( ) . to_string ( ) ) . clicked ( ) {
948- opener:: open ( data_dir) . ok ( ) ;
949- }
950- ui. end_row ( ) ;
943+ if let Some ( err_msg) = err {
944+ ui. label ( & * err_msg) ;
945+ }
946+ ui. end_row ( ) ;
947+ } ) ;
948+ } ;
949+
950+ edit_directory_field ( ui, "Config Directory:" , & mut window. config_dir , & mut window. config_dir_err ) ;
951+ edit_directory_field ( ui, "Cache Directory:" , & mut window. cache_dir , & mut window. cache_dir_err ) ;
952+ edit_directory_field ( ui, "Data Directory:" , & mut window. data_dir , & mut window. data_dir_err ) ;
951953
952954 ui. label ( "GUI theme:" ) ;
953955 ui. horizontal ( |ui| {
@@ -980,24 +982,91 @@ impl App {
980982 }
981983 } ) ;
982984
983- ui. with_layout ( egui:: Layout :: right_to_left ( Align :: TOP ) , |ui| {
984- if ui. add_enabled ( window. drg_pak_path_err . is_none ( ) , egui:: Button :: new ( "save" ) ) . clicked ( ) {
985+ ui. with_layout ( egui:: Layout :: right_to_left ( egui:: Align :: TOP ) , |ui| {
986+ let can_save = window. drg_pak_path_err . is_none ( )
987+ && window. config_dir_err . is_none ( )
988+ && window. cache_dir_err . is_none ( )
989+ && window. data_dir_err . is_none ( ) ;
990+
991+ if ui. add_enabled ( can_save, egui:: Button :: new ( "save" ) ) . clicked ( ) {
985992 try_save = true ;
986993 }
994+
987995 if let Some ( error) = & window. drg_pak_path_err {
988996 ui. colored_label ( ui. visuals ( ) . error_fg_color , error) ;
989997 }
998+ if let Some ( error) = & window. config_dir_err {
999+ ui. colored_label ( ui. visuals ( ) . error_fg_color , error) ;
1000+ }
1001+ if let Some ( error) = & window. cache_dir_err {
1002+ ui. colored_label ( ui. visuals ( ) . error_fg_color , error) ;
1003+ }
1004+ if let Some ( error) = & window. data_dir_err {
1005+ ui. colored_label ( ui. visuals ( ) . error_fg_color , error) ;
1006+ }
9901007 } ) ;
9911008
9921009 } ) ;
9931010 if try_save {
994- if let Err ( e) = is_drg_pak ( & window. drg_pak_path ) . context ( "Is not valid DRG pak" ) {
1011+ let mut has_error = false ;
1012+
1013+ if let Err ( e) = is_drg_pak ( & window. drg_pak_path ) {
9951014 window. drg_pak_path_err = Some ( e. to_string ( ) ) ;
996- } else {
997- self . state . config . drg_pak_path = Some ( PathBuf :: from (
998- self . settings_window . take ( ) . unwrap ( ) . drg_pak_path ,
999- ) ) ;
1000- self . state . config . save ( ) . unwrap ( ) ;
1015+ has_error = true ;
1016+ }
1017+ if let Err ( e) = is_valid_directory ( & window. config_dir ) {
1018+ window. config_dir_err = Some ( e) ;
1019+ has_error = true ;
1020+ }
1021+ if let Err ( e) = is_valid_directory ( & window. cache_dir ) {
1022+ window. cache_dir_err = Some ( e) ;
1023+ has_error = true ;
1024+ }
1025+ if let Err ( e) = is_valid_directory ( & window. data_dir ) {
1026+ window. data_dir_err = Some ( e) ;
1027+ has_error = true ;
1028+ }
1029+
1030+ if !has_error {
1031+ if let Some ( old_config_dir) = & self . state . config . config_dir {
1032+ if old_config_dir. to_string_lossy ( ) != window. config_dir {
1033+ if let Err ( e) = copy_directory_contents ( old_config_dir, Path :: new ( & window. config_dir ) ) {
1034+ window. config_dir_err = Some ( format ! ( "Failed to copy config directory: {}" , e) ) ;
1035+ has_error = true ;
1036+ }
1037+ }
1038+ }
1039+
1040+ if let Some ( old_data_dir) = & self . state . config . data_dir {
1041+ if old_data_dir. to_string_lossy ( ) != window. data_dir {
1042+ if let Err ( e) = copy_directory_contents ( old_data_dir, Path :: new ( & window. data_dir ) ) {
1043+ window. data_dir_err = Some ( format ! ( "Failed to copy data directory: {}" , e) ) ;
1044+ has_error = true ;
1045+ }
1046+ }
1047+ }
1048+
1049+ if let Some ( old_cache_dir) = & self . state . config . cache_dir {
1050+ if old_cache_dir. to_string_lossy ( ) != window. cache_dir {
1051+ if let Err ( e) = fs:: create_dir_all ( & window. cache_dir ) {
1052+ window. cache_dir_err = Some ( format ! ( "Failed to create new cache directory: {}" , e) ) ;
1053+ has_error = true ;
1054+ }
1055+ else if let Err ( e) = clear_directory ( old_cache_dir) {
1056+ window. cache_dir_err = Some ( format ! ( "Failed to clear cache directory: {}" , e) ) ;
1057+ has_error = true ;
1058+ }
1059+ }
1060+ }
1061+
1062+ if !has_error {
1063+ self . state . config . drg_pak_path = Some ( PathBuf :: from ( & window. drg_pak_path ) ) ;
1064+ self . state . config . config_dir = Some ( PathBuf :: from ( & window. config_dir ) ) ;
1065+ self . state . config . cache_dir = Some ( PathBuf :: from ( & window. cache_dir ) ) ;
1066+ self . state . config . data_dir = Some ( PathBuf :: from ( & window. data_dir ) ) ;
1067+
1068+ self . state . config . save ( ) . unwrap ( ) ;
1069+ }
10011070 }
10021071 } else if !open {
10031072 self . settings_window = None ;
@@ -1483,19 +1552,33 @@ impl WindowProviderParameters {
14831552struct WindowSettings {
14841553 drg_pak_path : String ,
14851554 drg_pak_path_err : Option < String > ,
1555+ config_dir : String ,
1556+ config_dir_err : Option < String > ,
1557+ cache_dir : String ,
1558+ cache_dir_err : Option < String > ,
1559+ data_dir : String ,
1560+ data_dir_err : Option < String > ,
14861561}
14871562
14881563impl WindowSettings {
14891564 fn new ( state : & State ) -> Self {
1490- let path = state
1491- . config
1492- . drg_pak_path
1493- . as_ref ( )
1494- . map ( |p| p. to_string_lossy ( ) . to_string ( ) )
1495- . unwrap_or_default ( ) ;
14961565 Self {
1497- drg_pak_path : path,
1566+ drg_pak_path : state. config . drg_pak_path . as_ref ( )
1567+ . map ( |p| p. to_string_lossy ( ) . to_string ( ) )
1568+ . unwrap_or_default ( ) ,
14981569 drg_pak_path_err : None ,
1570+ config_dir : state. config . config_dir . as_ref ( )
1571+ . map ( |p| p. to_string_lossy ( ) . to_string ( ) )
1572+ . unwrap_or_default ( ) ,
1573+ config_dir_err : None ,
1574+ cache_dir : state. config . cache_dir . as_ref ( )
1575+ . map ( |p| p. to_string_lossy ( ) . to_string ( ) )
1576+ . unwrap_or_default ( ) ,
1577+ cache_dir_err : None ,
1578+ data_dir : state. config . data_dir . as_ref ( )
1579+ . map ( |p| p. to_string_lossy ( ) . to_string ( ) )
1580+ . unwrap_or_default ( ) ,
1581+ data_dir_err : None ,
14991582 }
15001583 }
15011584}
0 commit comments