1+ using Avalonia ;
2+ using Avalonia . Controls ;
3+ using Avalonia . Data ;
4+ using Avalonia . Interactivity ;
5+ using Avalonia . Markup . Xaml ;
6+ using Avalonia . Threading ;
7+ using HedgeModManager . Foundation ;
8+ using HedgeModManager . UI . ViewModels ;
9+ using System . ComponentModel ;
10+ using static HedgeModManager . UI . Languages . Language ;
11+
12+ namespace HedgeModManager . UI . Controls . Modals ;
13+
14+ public partial class ProfileManagerModal : WindowModal
15+ {
16+ public ProfileManagerViewModel ViewModel { get ; set ; }
17+
18+ public ProfileManagerModal ( )
19+ {
20+ ViewModel = new ( ) ;
21+ AvaloniaXamlLoader . Load ( this ) ;
22+ }
23+
24+ public string GenerateProfileName ( string baseName )
25+ {
26+ if ( ViewModel . MainWindowViewModel == null )
27+ return string . Empty ;
28+
29+ var profiles = ViewModel . MainWindowViewModel . Profiles ;
30+ string name = baseName ;
31+ while ( profiles . Any ( x => x . Name . Equals ( name , StringComparison . InvariantCultureIgnoreCase ) ) )
32+ name += " - Copy" ;
33+ return name ;
34+ }
35+
36+ private void OnLoaded ( object ? sender , RoutedEventArgs e )
37+ {
38+ ViewModel . MainWindowViewModel = DataContext as MainWindowViewModel ;
39+ if ( ViewModel . MainWindowViewModel != null )
40+ {
41+ ViewModel . SelectedProfile = ViewModel . MainWindowViewModel . SelectedProfile ;
42+ ViewModel . MainWindowViewModel . PropertyChanged += OnMainViewModelPropertyChanged ;
43+ }
44+ ViewModel . Update ( ) ;
45+ }
46+
47+ private void OnUnloaded ( object ? sender , RoutedEventArgs e )
48+ {
49+ if ( ViewModel . MainWindowViewModel != null )
50+ ViewModel . MainWindowViewModel . PropertyChanged -= OnMainViewModelPropertyChanged ;
51+ }
52+
53+ private void OnCloseClick ( object ? sender , RoutedEventArgs e )
54+ {
55+ Close ( ) ;
56+ }
57+
58+ private void OnDuplicateClick ( object ? sender , RoutedEventArgs e )
59+ {
60+ if ( ViewModel . MainWindowViewModel == null || ViewModel . SelectedProfile == null )
61+ return ;
62+
63+ if ( ViewModel . MainWindowViewModel . SelectedGame ? . Game is not ModdableGameGeneric game )
64+ return ;
65+
66+ var baseProfile = ViewModel . SelectedProfile ;
67+ var profile = new ModProfile ( GenerateProfileName ( baseProfile . Name ) , baseProfile . ModDBPath , baseProfile . FileName ) ;
68+ profile . FileName = profile . GenerateFileNameFromName ( ) ;
69+
70+ // Copy profile
71+ string modsPath = game . ModDatabase . Root ;
72+ string baseProfilePath = Path . Combine ( modsPath , baseProfile . FileName ) ;
73+ string newProfilePath = Path . Combine ( modsPath , profile . FileName ) ;
74+ if ( File . Exists ( baseProfilePath ) )
75+ {
76+ try
77+ {
78+ File . Copy ( baseProfilePath , newProfilePath , true ) ;
79+ }
80+ catch ( Exception ex )
81+ {
82+ Logger . Error ( $ "Failed to copy profile: { baseProfilePath } -> { newProfilePath } ") ;
83+ Logger . Error ( ex ) ;
84+ }
85+ }
86+
87+ ViewModel . MainWindowViewModel . Profiles . Add ( profile ) ;
88+ ViewModel . MainWindowViewModel . SelectedProfile = ViewModel . SelectedProfile = profile ;
89+ Dispatcher . UIThread . Invoke ( async ( ) => await ViewModel . MainWindowViewModel . SaveProfilesAsync ( game ) ) ;
90+ ViewModel . Update ( ) ;
91+ }
92+
93+ private void OnDeleteClick ( object ? sender , RoutedEventArgs e )
94+ {
95+ if ( ViewModel . MainWindowViewModel == null || ViewModel . SelectedProfile == null )
96+ return ;
97+
98+ var messageBox = new MessageBoxModal ( "Modal.Title.DeleteProfile" , Localize ( "Modal.Message.DeleteProfile" , ViewModel . SelectedProfile . Name ) ) ;
99+ messageBox . AddButton ( "Common.Button.No" , ( s , e ) => messageBox . Close ( ) ) ;
100+ messageBox . AddButton ( "Common.Button.Yes" , ( s , e ) =>
101+ {
102+ if ( ViewModel . MainWindowViewModel . SelectedGame ? . Game is not ModdableGameGeneric game )
103+ return ;
104+
105+ var profile = ViewModel . SelectedProfile ;
106+ string profilePath = Path . Combine ( game . ModDatabase . Root , profile . FileName ) ;
107+ if ( File . Exists ( profilePath ) )
108+ {
109+ try
110+ {
111+ File . Delete ( profilePath ) ;
112+ }
113+ catch ( Exception ex )
114+ {
115+ Logger . Error ( $ "Failed to delete profile: { profilePath } ") ;
116+ Logger . Error ( ex ) ;
117+ }
118+ }
119+
120+ int pos = ViewModel . MainWindowViewModel . Profiles . IndexOf ( ViewModel . SelectedProfile ) ;
121+ if ( pos == ViewModel . MainWindowViewModel . Profiles . Count - 1 )
122+ pos -= 1 ;
123+ ViewModel . MainWindowViewModel ? . Profiles . Remove ( ViewModel . SelectedProfile ) ;
124+ ViewModel . SelectedProfile = ViewModel . MainWindowViewModel ? . Profiles [ pos ] ;
125+ ViewModel . Update ( ) ;
126+ messageBox . Close ( ) ;
127+ } ) ;
128+ messageBox . SetDanger ( ) ;
129+ messageBox . Open ( ViewModel . MainWindowViewModel ) ;
130+ }
131+
132+ private void OnRenameClick ( object ? sender , RoutedEventArgs e )
133+ {
134+ if ( ViewModel . MainWindowViewModel == null || ViewModel . SelectedProfile == null )
135+ return ;
136+
137+ var modal = new ProfileRenameModal ( ViewModel . SelectedProfile ) ;
138+ modal . OnProfileRenamed = ( ) =>
139+ {
140+ ProfileListBox . Bind ( ListBox . ItemsSourceProperty , new Binding ( "Profiles" ) ) ;
141+ } ;
142+ modal . Open ( ViewModel . MainWindowViewModel ) ;
143+ ViewModel . Update ( ) ;
144+ }
145+
146+ private void OnSelectClick ( object ? sender , RoutedEventArgs e )
147+ {
148+ if ( ViewModel . MainWindowViewModel == null || ViewModel . SelectedProfile == null )
149+ return ;
150+
151+ ViewModel . MainWindowViewModel . SelectedProfile = ViewModel . SelectedProfile ;
152+ ViewModel . Update ( ) ;
153+ }
154+
155+ private void OnSelectionChanged ( object ? sender , SelectionChangedEventArgs e )
156+ {
157+ ViewModel . Update ( ) ;
158+ }
159+
160+ private void OnMainViewModelPropertyChanged ( object ? sender , PropertyChangedEventArgs e )
161+ {
162+ if ( e . PropertyName == nameof ( MainWindowViewModel . IsBusy ) )
163+ ViewModel ? . Update ( ) ;
164+ }
165+ }
0 commit comments