99using GeneralUpdate . Tool . Avalonia . Common ;
1010using GeneralUpdate . Tool . Avalonia . Models ;
1111using Newtonsoft . Json ;
12+ using Nlnet . Avalonia . Controls ;
1213
1314namespace GeneralUpdate . Tool . Avalonia . ViewModels ;
1415
@@ -19,7 +20,7 @@ public class ExtensionViewModel : ObservableObject
1920
2021 private ExtensionConfigModel ? _configModel ;
2122 private AsyncRelayCommand ? _generateCommand ;
22- private AsyncRelayCommand < string > ? _selectFolderCommand ;
23+ private AsyncRelayCommand < string ? > ? _selectFolderCommand ;
2324 private RelayCommand ? _loadedCommand ;
2425 private RelayCommand ? _clearCommand ;
2526 private AsyncRelayCommand ? _selectDependenciesCommand ;
@@ -38,9 +39,9 @@ public RelayCommand LoadedCommand
3839 get { return _loadedCommand ??= new RelayCommand ( LoadedAction ) ; }
3940 }
4041
41- public AsyncRelayCommand < string > SelectFolderCommand
42+ public AsyncRelayCommand < string ? > SelectFolderCommand
4243 {
43- get => _selectFolderCommand ??= new AsyncRelayCommand < string > ( SelectFolderAction ) ;
44+ get => _selectFolderCommand ??= new AsyncRelayCommand < string ? > ( SelectFolderAction ) ;
4445 }
4546
4647 public AsyncRelayCommand GenerateCommand
@@ -91,7 +92,10 @@ public string? NewCustomPropertyKey
9192 get => _newCustomPropertyKey ;
9293 set
9394 {
94- SetProperty ( ref _newCustomPropertyKey , value ) ;
95+ if ( SetProperty ( ref _newCustomPropertyKey , value ) )
96+ {
97+ AddCustomPropertyCommand . NotifyCanExecuteChanged ( ) ;
98+ }
9599 }
96100 }
97101
@@ -100,7 +104,10 @@ public string? NewCustomPropertyValue
100104 get => _newCustomPropertyValue ;
101105 set
102106 {
103- SetProperty ( ref _newCustomPropertyValue , value ) ;
107+ if ( SetProperty ( ref _newCustomPropertyValue , value ) )
108+ {
109+ AddCustomPropertyCommand . NotifyCanExecuteChanged ( ) ;
110+ }
104111 }
105112 }
106113
@@ -159,26 +166,42 @@ private void ResetAction()
159166 NewCustomPropertyValue = string . Empty ;
160167 }
161168
162- private async Task SelectFolderAction ( string value )
169+ private async Task SelectFolderAction ( string ? value )
163170 {
164171 try
165172 {
173+ if ( string . IsNullOrWhiteSpace ( value ) )
174+ {
175+ await MessageBox . ShowAsync ( "Invalid folder selection parameter" , "Error" , Buttons . OK ) ;
176+ return ;
177+ }
178+
166179 var folders = await Storage . Instance . SelectFolderDialog ( ) ;
167180 if ( ! folders . Any ( ) ) return ;
168181
169182 var folder = folders . First ( ) ;
183+ if ( folder ? . Path ? . LocalPath == null )
184+ {
185+ await MessageBox . ShowAsync ( "Selected folder path is invalid" , "Error" , Buttons . OK ) ;
186+ return ;
187+ }
188+
170189 switch ( value )
171190 {
172191 case "ExtensionDirectory" :
173- ConfigModel . ExtensionDirectory = folder ! . Path . LocalPath ;
192+ ConfigModel . ExtensionDirectory = folder . Path . LocalPath ;
174193 break ;
175194 case "ExportPath" :
176- ConfigModel . Path = folder ! . Path . LocalPath ;
195+ ConfigModel . Path = folder . Path . LocalPath ;
196+ break ;
197+ default :
198+ await MessageBox . ShowAsync ( $ "Unknown folder selection type: { value } ", "Error" , Buttons . OK ) ;
177199 break ;
178200 }
179201 }
180- catch ( Exception e )
202+ catch ( Exception ex )
181203 {
204+ await MessageBox . ShowAsync ( $ "Failed to select folder: { ex . Message } ", "Error" , Buttons . OK ) ;
182205 }
183206 }
184207
@@ -192,26 +215,31 @@ private async Task GeneratePackageAction()
192215 // Validate input
193216 if ( string . IsNullOrWhiteSpace ( ConfigModel . Name ) )
194217 {
195- //eventAggregator.PublishWarning ("Extension name is required");
218+ await MessageBox . ShowAsync ( "Extension name is required" , "Validation Error" , Buttons . OK ) ;
196219 return ;
197220 }
198221
199222 if ( string . IsNullOrWhiteSpace ( ConfigModel . Version ) )
200223 {
201- //eventAggregator.PublishWarning("Extension version is required");
224+ await MessageBox . ShowAsync ( "Extension version is required" , "Validation Error" , Buttons . OK ) ;
225+ return ;
226+ }
227+
228+ if ( string . IsNullOrWhiteSpace ( ConfigModel . ExtensionDirectory ) )
229+ {
230+ await MessageBox . ShowAsync ( "Extension directory is required" , "Validation Error" , Buttons . OK ) ;
202231 return ;
203232 }
204233
205- if ( string . IsNullOrWhiteSpace ( ConfigModel . ExtensionDirectory ) ||
206- ! Directory . Exists ( ConfigModel . ExtensionDirectory ) )
234+ if ( ! Directory . Exists ( ConfigModel . ExtensionDirectory ) )
207235 {
208- //eventAggregator.PublishWarning( "Extension directory is invalid" );
236+ await MessageBox . ShowAsync ( $ "Extension directory does not exist: { ConfigModel . ExtensionDirectory } " , "Validation Error" , Buttons . OK ) ;
209237 return ;
210238 }
211239
212240 if ( string . IsNullOrWhiteSpace ( ConfigModel . Path ) )
213241 {
214- //eventAggregator.PublishWarning ("Export path is required");
242+ await MessageBox . ShowAsync ( "Export path is required" , "Validation Error" , Buttons . OK ) ;
215243 return ;
216244 }
217245
@@ -232,8 +260,6 @@ private async Task GeneratePackageAction()
232260 var zipFileName = $ "{ sanitizedName } _{ sanitizedVersion } .zip";
233261 var zipFilePath = Path . Combine ( exportDirectory , zipFileName ) ;
234262
235- //eventAggregator.PublishSuccess("Starting extension compression...");
236-
237263 // Compress the extension directory into a zip file
238264 await ZipUtility . CompressDirectoryAsync (
239265 ConfigModel . ExtensionDirectory ,
@@ -248,19 +274,32 @@ await ZipUtility.CompressDirectoryAsync(
248274 var platformValue = ConfigModel . Platform ? . Value ?? 0 ;
249275 var targetPlatform = MapPlatformValue ( platformValue ) ;
250276 ConfigModel . Platform = new PlatformModel { DisplayName = targetPlatform . ToString ( ) , Value = platformValue } ;
277+
251278 // Get file info for the zip
252279 var fileInfo = new FileInfo ( zipFilePath ) ;
253280 ConfigModel . FileSize = fileInfo . Length ;
281+
254282 // Serialize manifest to JSON
255- var manifestJson = JsonConvert . SerializeObject ( ConfigModel ) ;
283+ var manifestJson = JsonConvert . SerializeObject ( ConfigModel , Formatting . Indented ) ;
256284 if ( ! string . IsNullOrEmpty ( manifestJson ) )
257285 {
258286 // Add manifest.json to the zip file
259287 await ZipUtility . AddFileToZipAsync ( zipFilePath , "manifest.json" , manifestJson ) ;
260288 }
289+
290+ await MessageBox . ShowAsync ( $ "Extension package created successfully at:\n { zipFilePath } ", "Success" , Buttons . OK ) ;
291+ }
292+ catch ( UnauthorizedAccessException ex )
293+ {
294+ await MessageBox . ShowAsync ( $ "Access denied: { ex . Message } \n Please check file permissions.", "Error" , Buttons . OK ) ;
295+ }
296+ catch ( IOException ex )
297+ {
298+ await MessageBox . ShowAsync ( $ "I/O error: { ex . Message } ", "Error" , Buttons . OK ) ;
261299 }
262300 catch ( Exception ex )
263301 {
302+ await MessageBox . ShowAsync ( $ "Failed to generate package: { ex . Message } ", "Error" , Buttons . OK ) ;
264303 }
265304 }
266305
@@ -276,15 +315,22 @@ private void AddCustomPropertyAction()
276315 {
277316 try
278317 {
279- if ( string . IsNullOrWhiteSpace ( NewCustomPropertyKey ) ||
280- string . IsNullOrWhiteSpace ( NewCustomPropertyValue ) )
318+ if ( string . IsNullOrWhiteSpace ( NewCustomPropertyKey ) )
281319 {
320+ MessageBox . Show ( "Property key cannot be empty" , "Validation Error" , Buttons . OK ) ;
321+ return ;
322+ }
323+
324+ if ( string . IsNullOrWhiteSpace ( NewCustomPropertyValue ) )
325+ {
326+ MessageBox . Show ( "Property value cannot be empty" , "Validation Error" , Buttons . OK ) ;
282327 return ;
283328 }
284329
285330 // Check if key already exists
286331 if ( ConfigModel . CustomProperties . ContainsKey ( NewCustomPropertyKey ) )
287332 {
333+ MessageBox . Show ( $ "Property key '{ NewCustomPropertyKey } ' already exists", "Validation Error" , Buttons . OK ) ;
288334 return ;
289335 }
290336
@@ -302,9 +348,12 @@ private void AddCustomPropertyAction()
302348 NewCustomPropertyKey = string . Empty ;
303349 NewCustomPropertyValue = string . Empty ;
304350
351+ // Notify command to re-evaluate its CanExecute state
352+ AddCustomPropertyCommand . NotifyCanExecuteChanged ( ) ;
305353 }
306354 catch ( Exception ex )
307355 {
356+ MessageBox . Show ( $ "Failed to add custom property: { ex . Message } ", "Error" , Buttons . OK ) ;
308357 }
309358 }
310359
@@ -314,21 +363,28 @@ private void RemoveCustomPropertyAction(CustomPropertyModel? property)
314363 {
315364 if ( property == null )
316365 {
366+ MessageBox . Show ( "No property selected to remove" , "Validation Error" , Buttons . OK ) ;
367+ return ;
368+ }
369+
370+ if ( string . IsNullOrWhiteSpace ( property . Key ) )
371+ {
372+ MessageBox . Show ( "Property key is invalid" , "Validation Error" , Buttons . OK ) ;
317373 return ;
318374 }
319375
320- // Remove from dictionary - use TryGetValue for safety
376+ // Remove from dictionary
321377 if ( ConfigModel . CustomProperties . ContainsKey ( property . Key ) )
322378 {
323379 ConfigModel . CustomProperties . Remove ( property . Key ) ;
324380 }
325381
326382 // Remove from observable collection
327383 CustomPropertiesCollection . Remove ( property ) ;
328-
329384 }
330385 catch ( Exception ex )
331386 {
387+ MessageBox . Show ( $ "Failed to remove custom property: { ex . Message } ", "Error" , Buttons . OK ) ;
332388 }
333389 }
334390
0 commit comments