33use std:: collections:: HashMap ;
44
55use iced:: widget:: Slider ;
6+ use iced:: widget:: Space ;
67use iced:: widget:: TextInput ;
78use iced:: widget:: checkbox;
89use iced:: widget:: radio;
@@ -11,7 +12,9 @@ use iced::widget::text_input;
1112use crate :: app:: Editable ;
1213use crate :: app:: SetConfigBufferFields ;
1314use crate :: app:: SetConfigThemeFields ;
15+ use crate :: commands:: Function ;
1416use crate :: config:: MainPage ;
17+ use crate :: config:: Shelly ;
1518use crate :: styles:: delete_button_style;
1619use crate :: styles:: settings_add_button_style;
1720use crate :: styles:: settings_checkbox_style;
@@ -231,16 +234,19 @@ pub fn settings_page(config: Config) -> Element<'static, Message> {
231234 let theme_clone = theme. clone ( ) ;
232235 let font_family = settings_item_column ( [
233236 settings_hint_text ( theme. clone ( ) , "Set Font family" ) ,
234- text_input ( "Font family" , & config. theme . font . unwrap_or ( "" . to_string ( ) ) )
235- . on_input ( move |input : String | {
236- Message :: SetConfig ( SetConfigFields :: SetThemeFields ( SetConfigThemeFields :: Font (
237- input,
238- ) ) )
239- } )
240- . on_submit ( Message :: WriteConfig ( false ) )
241- . width ( Length :: Fill )
242- . style ( move |_, _| settings_text_input_item_style ( & theme_clone) )
243- . into ( ) ,
237+ text_input (
238+ "Font family" ,
239+ & config. theme . font . clone ( ) . unwrap_or ( "" . to_string ( ) ) ,
240+ )
241+ . on_input ( move |input : String | {
242+ Message :: SetConfig ( SetConfigFields :: SetThemeFields ( SetConfigThemeFields :: Font (
243+ input,
244+ ) ) )
245+ } )
246+ . on_submit ( Message :: WriteConfig ( false ) )
247+ . width ( Length :: Fill )
248+ . style ( move |_, _| settings_text_input_item_style ( & theme_clone) )
249+ . into ( ) ,
244250 notice_item ( theme. clone ( ) , "What font rustcast should use" ) ,
245251 ] ) ;
246252
@@ -399,12 +405,18 @@ pub fn settings_page(config: Config) -> Element<'static, Message> {
399405 text_clr. into ( ) ,
400406 bg_clr. into ( ) ,
401407 settings_hint_text ( theme. clone ( ) , "Aliases" ) ,
402- aliases_item ( config. aliases , & theme) ,
408+ aliases_item ( config. aliases . clone ( ) , & theme) ,
403409 settings_hint_text ( theme. clone ( ) , "Modes" ) ,
404- modes_item ( config. modes , & theme) ,
410+ modes_item ( config. modes . clone ( ) , & theme) ,
411+ settings_hint_text ( theme. clone ( ) , "Search Directories" ) ,
412+ search_dirs_item ( & theme, config. search_dirs . clone ( ) ) ,
413+ Space :: new ( ) . height ( 30 ) . into ( ) ,
414+ settings_hint_text ( theme. clone ( ) , "Shell commands" ) ,
415+ shell_commands_item ( config. shells . clone ( ) , theme. clone ( ) ) ,
405416 Row :: from_iter ( [
406417 savebutton ( theme. clone ( ) ) ,
407418 default_button ( theme. clone ( ) ) ,
419+ copy_config_button ( config) ,
408420 wiki_button ( theme. clone ( ) ) ,
409421 ] )
410422 . spacing ( 5 )
@@ -450,18 +462,34 @@ fn default_button(theme: Theme) -> Element<'static, Message> {
450462
451463fn wiki_button ( theme : Theme ) -> Element < ' static , Message > {
452464 Button :: new (
453- Text :: new ( "Open the wiki " )
465+ Text :: new ( "Open file " )
454466 . align_x ( Alignment :: Center )
455467 . width ( Length :: Fill )
456468 . font ( theme. font ( ) ) ,
457469 )
458470 . style ( move |_, _| settings_save_button_style ( & theme) )
459471 . width ( Length :: Fill )
460- . on_press ( Message :: RunFunction (
461- crate :: commands:: Function :: OpenWebsite (
462- "https://github.com/RustCastLabs/rustcast/wiki" . to_string ( ) ,
472+ . on_press ( Message :: RunFunction ( crate :: commands:: Function :: OpenApp (
473+ std:: env:: var ( "HOME" ) . unwrap_or ( "" . to_string ( ) ) + "/.config/rustcast/config.toml" ,
474+ ) ) )
475+ . into ( )
476+ }
477+
478+ fn copy_config_button ( config : Box < Config > ) -> Element < ' static , Message > {
479+ let theme = config. theme . clone ( ) ;
480+ Button :: new (
481+ Text :: new ( "Copy config" )
482+ . align_x ( Alignment :: Center )
483+ . width ( Length :: Fill )
484+ . font ( theme. font ( ) ) ,
485+ )
486+ . style ( move |_, _| settings_save_button_style ( & theme) )
487+ . width ( Length :: Fill )
488+ . on_press ( Message :: RunFunction ( Function :: CopyToClipboard (
489+ crate :: clipboard:: ClipBoardContentType :: Text (
490+ toml:: to_string ( & config) . unwrap_or ( "" . to_string ( ) ) ,
463491 ) ,
464- ) )
492+ ) ) )
465493 . into ( )
466494}
467495
@@ -567,6 +595,47 @@ fn aliases_item(aliases: HashMap<String, String>, theme: &Theme) -> Element<'sta
567595 . into ( )
568596}
569597
598+ fn search_dirs_item ( theme : & Theme , search_dirs : Vec < String > ) -> Element < ' static , Message > {
599+ let theme_clone = theme. clone ( ) ;
600+ let search_dirs = search_dirs. clone ( ) ;
601+ Column :: from_iter ( [
602+ container (
603+ Column :: from_iter ( search_dirs. iter ( ) . map ( |dir| {
604+ let theme_clone_2 = theme. clone ( ) ;
605+ let directory = dir. clone ( ) ;
606+ container (
607+ Row :: from_iter ( [
608+ dir_picker_button ( directory, dir, theme_clone. clone ( ) ) . into ( ) ,
609+ Button :: new ( "Delete" )
610+ . on_press ( Message :: SetConfig ( SetConfigFields :: SearchDirs (
611+ Editable :: Delete ( dir. clone ( ) ) ,
612+ ) ) )
613+ . style ( move |_, _| delete_button_style ( & theme_clone_2) )
614+ . into ( ) ,
615+ ] )
616+ . spacing ( 10 )
617+ . align_y ( Alignment :: Center ) ,
618+ )
619+ . width ( Length :: Fill )
620+ . align_x ( Alignment :: Center )
621+ . into ( )
622+ } ) )
623+ . spacing ( 10 ) ,
624+ )
625+ . height ( Length :: Fill )
626+ . width ( Length :: Fill )
627+ . align_x ( Alignment :: Center )
628+ . align_y ( Alignment :: Center )
629+ . into ( ) ,
630+ dir_adder_button ( "+" , theme. to_owned ( ) ) . into ( ) ,
631+ ] )
632+ . spacing ( 10 )
633+ . height ( Length :: Fill )
634+ . width ( Length :: Fill )
635+ . align_x ( Alignment :: Center )
636+ . into ( )
637+ }
638+
570639fn text_input_cell ( text : String , theme : & Theme , placeholder : & str ) -> TextInput < ' static , Message > {
571640 text_input ( placeholder, & text)
572641 . font ( theme. font ( ) )
@@ -637,3 +706,212 @@ fn modes_item(modes: HashMap<String, String>, theme: &Theme) -> Element<'static,
637706 . align_x ( Alignment :: Center )
638707 . into ( )
639708}
709+
710+ fn dir_picker_button ( directory : String , dir : & str , theme : Theme ) -> Button < ' static , Message > {
711+ let home = std:: env:: var ( "HOME" ) . unwrap_or ( "/" . to_string ( ) ) ;
712+ Button :: new ( Text :: new ( dir. to_owned ( ) . replace ( & home, "~" ) ) )
713+ . on_press_with ( move || {
714+ rfd:: FileDialog :: new ( )
715+ . set_directory ( home. clone ( ) )
716+ . set_can_create_directories ( false )
717+ . pick_folder ( )
718+ . map ( |path| {
719+ let new = path. to_str ( ) . unwrap_or ( "" ) . to_string ( ) ;
720+ Message :: SetConfig ( SetConfigFields :: SearchDirs ( Editable :: Update {
721+ old : directory. clone ( ) ,
722+ new,
723+ } ) )
724+ } )
725+ . unwrap_or ( Message :: SetConfig ( SetConfigFields :: SearchDirs (
726+ Editable :: Update {
727+ old : directory. clone ( ) ,
728+ new : directory. clone ( ) ,
729+ } ,
730+ ) ) )
731+ } )
732+ . style ( move |_, _| settings_add_button_style ( & theme. clone ( ) ) )
733+ }
734+
735+ fn dir_adder_button ( dir : & str , theme : Theme ) -> Button < ' static , Message > {
736+ Button :: new ( Text :: new ( dir. to_owned ( ) ) )
737+ . on_press_with ( move || {
738+ rfd:: FileDialog :: new ( )
739+ . set_directory ( std:: env:: var ( "HOME" ) . unwrap_or ( "/" . to_string ( ) ) )
740+ . set_can_create_directories ( false )
741+ . pick_folder ( )
742+ . map ( |path| {
743+ let new = path. to_str ( ) . unwrap_or ( "" ) . to_string ( ) ;
744+ Message :: SetConfig ( SetConfigFields :: SearchDirs ( Editable :: Create ( new) ) )
745+ } )
746+ . unwrap_or ( Message :: SetConfig ( SetConfigFields :: SearchDirs (
747+ Editable :: Create ( String :: new ( ) ) ,
748+ ) ) )
749+ } )
750+ . style ( move |_, _| settings_add_button_style ( & theme. clone ( ) ) )
751+ }
752+
753+ fn shell_commands_item ( shells : Vec < Shelly > , theme : Theme ) -> Element < ' static , Message > {
754+ let mut col =
755+ Column :: from_iter ( shells. iter ( ) . map ( |x| x. editable_render ( theme. clone ( ) ) ) ) . spacing ( 30 ) ;
756+
757+ let theme_clone = theme. clone ( ) ;
758+
759+ col = col
760+ . push (
761+ Button :: new (
762+ Text :: new ( "+" )
763+ . align_x ( Alignment :: Center )
764+ . align_y ( Alignment :: Center ) ,
765+ )
766+ . style ( move |_, _| settings_add_button_style ( & theme_clone. clone ( ) ) )
767+ . on_press ( Message :: SetConfig ( SetConfigFields :: ShellCommands (
768+ Editable :: Create ( Shelly :: default ( ) ) ,
769+ ) ) ) ,
770+ )
771+ . width ( Length :: Fill )
772+ . align_x ( Alignment :: Center ) ;
773+
774+ col. into ( )
775+ }
776+
777+ impl Shelly {
778+ pub fn editable_render ( & self , theme : Theme ) -> Element < ' static , Message > {
779+ let shell = self . to_owned ( ) ;
780+ Column :: from_iter ( [
781+ tuple_row (
782+ shellcommand_hint_text ( theme. clone ( ) , "Display name" ) ,
783+ text_input_cell ( self . alias . clone ( ) , & theme, "Display Name" )
784+ . on_input ( {
785+ let shell = shell. clone ( ) ;
786+ move |input| {
787+ let old = shell. clone ( ) ;
788+ let mut new = old. clone ( ) ;
789+ new. alias = input;
790+ Message :: SetConfig ( SetConfigFields :: ShellCommands ( Editable :: Update {
791+ old,
792+ new,
793+ } ) )
794+ }
795+ } )
796+ . into ( ) ,
797+ )
798+ . into ( ) ,
799+ tuple_row (
800+ shellcommand_hint_text ( theme. clone ( ) , "Search name" ) ,
801+ text_input_cell ( self . alias_lc . clone ( ) , & theme, "Search Name" )
802+ . on_input ( {
803+ let shell = shell. clone ( ) ;
804+ move |input| {
805+ let old = shell. clone ( ) ;
806+ let mut new = old. clone ( ) ;
807+ new. alias_lc = input;
808+ Message :: SetConfig ( SetConfigFields :: ShellCommands ( Editable :: Update {
809+ old,
810+ new,
811+ } ) )
812+ }
813+ } )
814+ . into ( ) ,
815+ )
816+ . into ( ) ,
817+ tuple_row (
818+ shellcommand_hint_text ( theme. clone ( ) , "Command" ) ,
819+ text_input_cell ( self . command . clone ( ) , & theme, "Command" )
820+ . on_input ( {
821+ let shell = shell. clone ( ) ;
822+ move |input| {
823+ let old = shell. clone ( ) ;
824+ let mut new = old. clone ( ) ;
825+ new. command = input;
826+ Message :: SetConfig ( SetConfigFields :: ShellCommands ( Editable :: Update {
827+ old,
828+ new,
829+ } ) )
830+ }
831+ } )
832+ . into ( ) ,
833+ )
834+ . into ( ) ,
835+ tuple_row (
836+ shellcommand_hint_text ( theme. clone ( ) , "Icon File" ) ,
837+ text_input_cell (
838+ self . icon_path . clone ( ) . unwrap_or ( "" . to_string ( ) ) ,
839+ & theme,
840+ "Icon path" ,
841+ )
842+ . on_input ( {
843+ let shell = shell. clone ( ) ;
844+ move |input| {
845+ let old = shell. clone ( ) ;
846+ let mut new = old. clone ( ) ;
847+ new. icon_path = if input. is_empty ( ) { None } else { Some ( input) } ;
848+ Message :: SetConfig ( SetConfigFields :: ShellCommands ( Editable :: Update {
849+ old,
850+ new,
851+ } ) )
852+ }
853+ } )
854+ . into ( ) ,
855+ )
856+ . into ( ) ,
857+ tuple_row (
858+ shellcommand_hint_text ( theme. clone ( ) , "Hotkey" ) ,
859+ text_input_cell (
860+ self . hotkey . clone ( ) . unwrap_or ( "" . to_string ( ) ) ,
861+ & theme,
862+ "Hotkey" ,
863+ )
864+ . on_input ( {
865+ let shell = shell. clone ( ) ;
866+ move |input| {
867+ let old = shell. clone ( ) ;
868+ let mut new = old. clone ( ) ;
869+ new. hotkey = Some ( input) ;
870+ Message :: SetConfig ( SetConfigFields :: ShellCommands ( Editable :: Update {
871+ old,
872+ new,
873+ } ) )
874+ }
875+ } )
876+ . into ( ) ,
877+ )
878+ . into ( ) ,
879+ tuple_row (
880+ Button :: new ( "Delete" )
881+ . on_press ( Message :: SetConfig ( SetConfigFields :: ShellCommands (
882+ Editable :: Delete ( self . clone ( ) ) ,
883+ ) ) )
884+ . style ( {
885+ let theme = theme. clone ( ) ;
886+ move |_, _| delete_button_style ( & theme)
887+ } )
888+ . into ( ) ,
889+ notice_item ( theme. clone ( ) , "Icon path and hotkey are optional" ) ,
890+ )
891+ . into ( ) ,
892+ ] )
893+ . spacing ( 10 )
894+ . height ( Length :: Fill )
895+ . width ( Length :: Fill )
896+ . into ( )
897+ }
898+ }
899+
900+ fn tuple_row (
901+ left : Element < ' static , Message > ,
902+ right : Element < ' static , Message > ,
903+ ) -> Row < ' static , Message > {
904+ Row :: from_iter ( [ left, right] )
905+ . spacing ( 10 )
906+ . width ( Length :: Fill )
907+ }
908+
909+ fn shellcommand_hint_text ( theme : Theme , text : impl ToString ) -> Element < ' static , Message > {
910+ let text = text. to_string ( ) ;
911+
912+ Text :: new ( text)
913+ . font ( theme. font ( ) )
914+ . color ( theme. text_color ( 0.7 ) )
915+ . width ( WINDOW_WIDTH * 0.3 )
916+ . into ( )
917+ }
0 commit comments