Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions Source/NETworkManager.Utilities/SecureStringHelper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ public static class SecureStringHelper
public static string ConvertToString(SecureString secureString)
{
var valuePtr = IntPtr.Zero;

try
{
valuePtr = Marshal.SecureStringToGlobalAllocUnicode(secureString);
Expand Down
98 changes: 98 additions & 0 deletions Source/NETworkManager/DialogHelper.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
using MahApps.Metro.SimpleChildWindow;
using NETworkManager.Localization.Resources;
using NETworkManager.Settings;
using NETworkManager.Utilities;
using NETworkManager.ViewModels;
using NETworkManager.Views;
using System.Threading.Tasks;
using System.Windows;

namespace NETworkManager
{
/// <summary>
/// Helper class for showing dialog messages.
/// </summary>
public static class DialogHelper
{
/// <summary>
/// Displays a modal message dialog with an OK button, allowing the user to acknowledge the message before
/// continuing.
/// </summary>
/// <remarks>The dialog is shown as a child window of the specified parent. The method is
/// asynchronous and returns when the dialog is dismissed by the user.</remarks>
/// <param name="parentWindow">The parent window that will host the message dialog. Cannot be null.</param>
/// <param name="title">The title text displayed in the message dialog window. Cannot be null.</param>
/// <param name="message">The main message content shown in the dialog. Cannot be null.</param>
/// <param name="icon">The icon to display in the dialog, indicating the message type. Defaults to Info if not specified.</param>
/// <param name="buttonOKText">The text to display on the OK button. If null, a default value is used.</param>
/// <returns>A task that completes when the user closes the message dialog.</returns>
public static Task ShowOKMessageAsync(Window parentWindow, string title, string message, ChildWindowIcon icon = ChildWindowIcon.Info, string buttonOKText = null)
{
buttonOKText ??= Strings.OK;

var childWindow = new OKMessageChildWindow();

var childWindowViewModel = new OKMessageViewModel(_ =>
{
childWindow.IsOpen = false;
ConfigurationManager.Current.IsChildWindowOpen = false;
}, message, icon, buttonOKText);

childWindow.Title = title;

childWindow.DataContext = childWindowViewModel;

ConfigurationManager.Current.IsChildWindowOpen = true;

return parentWindow.ShowChildWindowAsync(childWindow);
}

/// <summary>
/// Displays an asynchronous modal dialog with OK and Cancel buttons, allowing the user to confirm or cancel an
/// action.
/// </summary>
/// <remarks>The dialog is shown as a child window of the specified parent. The method does not
/// return until the user closes the dialog. Custom button text and icon can be provided to tailor the dialog to
/// specific scenarios.</remarks>
/// <param name="parentWindow">The parent window that hosts the child dialog. Cannot be null.</param>
/// <param name="title">The title text displayed in the dialog window.</param>
/// <param name="message">The message content shown to the user in the dialog.</param>
/// <param name="icon">The icon displayed in the dialog to indicate the message type. Defaults to Info.</param>
/// <param name="buttonOKText">The text label for the OK button. If null, a default value is used.</param>
/// <param name="buttonCancelText">The text label for the Cancel button. If null, a default value is used.</param>
/// <returns>A task that represents the asynchronous operation. The task result is <see langword="true"/> if the user
/// clicks OK; otherwise, <see langword="false"/>.</returns>
public static async Task<bool> ShowOKCancelMessageAsync(Window parentWindow, string title, string message, ChildWindowIcon icon = ChildWindowIcon.Info, string buttonOKText = null, string buttonCancelText = null)
{
buttonOKText ??= Strings.OK;
buttonCancelText ??= Strings.Cancel;

var result = false;

var childWindow = new OKCancelMessageChildWindow();

var childWindowViewModel = new OKCancelMessageViewModel(_ =>
{
childWindow.IsOpen = false;
ConfigurationManager.Current.IsChildWindowOpen = false;

result = true;
},
_ =>
{
childWindow.IsOpen = false;
ConfigurationManager.Current.IsChildWindowOpen = false;
},
message, icon, buttonOKText, buttonCancelText);

childWindow.Title = title;
childWindow.DataContext = childWindowViewModel;

ConfigurationManager.Current.IsChildWindowOpen = true;

await parentWindow.ShowChildWindowAsync(childWindow);

return result;
}
}
}
2 changes: 1 addition & 1 deletion Source/NETworkManager/NETworkManager.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -141,7 +141,7 @@
<XamlRuntime>Wpf</XamlRuntime>
<SubType>Designer</SubType>
</Page>
<Page Update="Views\OKCancelInfoMessageChildWindow.xaml">
<Page Update="Views\OKCancelMessageChildWindow.xaml">
<Generator>MSBuild:Compile</Generator>
<XamlRuntime>Wpf</XamlRuntime>
<SubType>Designer</SubType>
Expand Down
76 changes: 23 additions & 53 deletions Source/NETworkManager/ProfileDialogManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
using NETworkManager.Models.PuTTY;
using NETworkManager.Models.RemoteDesktop;
using NETworkManager.Profiles;
using NETworkManager.Utilities;
using NETworkManager.ViewModels;
using NETworkManager.Views;
using System;
Expand Down Expand Up @@ -560,39 +561,24 @@ public static Task ShowCopyAsProfileDialog(Window parentWindow, IProfileManagerM
return parentWindow.ShowChildWindowAsync(childWindow);
}

public static Task ShowDeleteProfileDialog(Window parentWindow, IProfileManagerMinimal viewModel,
public static async Task ShowDeleteProfileDialog(Window parentWindow, IProfileManagerMinimal viewModel,
IList<ProfileInfo> profiles)
{
var childWindow = new OKCancelInfoMessageChildWindow();

OKCancelInfoMessageViewModel childWindowViewModel = new(_ =>
{
childWindow.IsOpen = false;
Settings.ConfigurationManager.Current.IsChildWindowOpen = false;

viewModel.OnProfileManagerDialogClose();

ProfileManager.RemoveProfiles(profiles);
}, _ =>
{
childWindow.IsOpen = false;
Settings.ConfigurationManager.Current.IsChildWindowOpen = false;

viewModel.OnProfileManagerDialogClose();
},
profiles.Count == 1 ? Strings.DeleteProfileMessage : Strings.DeleteProfilesMessage,
Strings.Delete
);

childWindow.Title = profiles.Count == 1 ? Strings.DeleteProfile : Strings.DeleteProfiles;
viewModel.OnProfileManagerDialogOpen();

childWindow.DataContext = childWindowViewModel;
var result = await DialogHelper.ShowOKCancelMessageAsync(parentWindow,
profiles.Count == 1 ? Strings.DeleteProfile : Strings.DeleteProfiles,
profiles.Count == 1 ? Strings.DeleteProfileMessage : Strings.DeleteProfilesMessage,
ChildWindowIcon.Info,
Strings.Delete);

viewModel.OnProfileManagerDialogOpen();
viewModel.OnProfileManagerDialogClose();

Settings.ConfigurationManager.Current.IsChildWindowOpen = true;
if (!result)
return;

return parentWindow.ShowChildWindowAsync(childWindow);
ProfileManager.RemoveProfiles(profiles);
}

#endregion
Expand Down Expand Up @@ -662,40 +648,24 @@ public static Task ShowEditGroupDialog(Window parentWindow, IProfileManagerMinim
return parentWindow.ShowChildWindowAsync(childWindow);
}

public static Task ShowDeleteGroupDialog(Window parentWindow, IProfileManagerMinimal viewModel,
public static async Task ShowDeleteGroupDialog(Window parentWindow, IProfileManagerMinimal viewModel,
GroupInfo group)
{
var childWindow = new OKCancelInfoMessageChildWindow();

OKCancelInfoMessageViewModel childWindowViewModel = new(_ =>
{
childWindow.IsOpen = false;
Settings.ConfigurationManager.Current.IsChildWindowOpen = false;

viewModel.OnProfileManagerDialogClose();

ProfileManager.RemoveGroup(group);
}, _ =>
{
childWindow.IsOpen = false;
Settings.ConfigurationManager.Current.IsChildWindowOpen = false;
viewModel.OnProfileManagerDialogOpen();

viewModel.OnProfileManagerDialogClose();
},
var result = await DialogHelper.ShowOKCancelMessageAsync(parentWindow,
Strings.DeleteGroup,
Strings.DeleteGroupMessage,
Strings.Delete
);

childWindow.Title = Strings.DeleteGroup;
ChildWindowIcon.Info,
Strings.Delete);

childWindow.DataContext = childWindowViewModel;
viewModel.OnProfileManagerDialogClose();

viewModel.OnProfileManagerDialogOpen();
if (!result)
return;

Settings.ConfigurationManager.Current.IsChildWindowOpen = true;

return parentWindow.ShowChildWindowAsync(childWindow);
ProfileManager.RemoveGroup(group);
}

#endregion
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -275,32 +275,19 @@ public async Task EditAWSProfile()
await _dialogCoordinator.ShowMetroDialogAsync(this, customDialog);
}

private Task DeleteAWSProfile()
private async Task DeleteAWSProfile()
{
var childWindow = new OKCancelInfoMessageChildWindow();
var result = await DialogHelper.ShowOKCancelMessageAsync(Application.Current.MainWindow,
Strings.DeleteAWSProfile,
Strings.DeleteAWSProfileMessage,
ChildWindowIcon.Info,
Strings.Delete);

var childWindowViewModel = new OKCancelInfoMessageViewModel(_ =>
{
childWindow.IsOpen = false;
ConfigurationManager.Current.IsChildWindowOpen = false;

SettingsManager.Current.AWSSessionManager_AWSProfiles.Remove(SelectedAWSProfile);
}, _ =>
{
childWindow.IsOpen = false;
ConfigurationManager.Current.IsChildWindowOpen = false;
},
Strings.DeleteAWSProfileMessage,
Strings.Delete
);
if (!result)
return;

childWindow.Title = Strings.DeleteAWSProfile;

childWindow.DataContext = childWindowViewModel;

ConfigurationManager.Current.IsChildWindowOpen = true;

return (Application.Current.MainWindow as MainWindow).ShowChildWindowAsync(childWindow);
SettingsManager.Current.AWSSessionManager_AWSProfiles.Remove(SelectedAWSProfile);
}

private async Task Configure()
Expand Down
32 changes: 9 additions & 23 deletions Source/NETworkManager/ViewModels/DNSLookupSettingsViewModel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -357,32 +357,18 @@ public async Task EditDNSServer()
await _dialogCoordinator.ShowMetroDialogAsync(this, customDialog);
}

private Task DeleteDNSServer()
private async Task DeleteDNSServer()
{
var childWindow = new OKCancelInfoMessageChildWindow();
var result = await DialogHelper.ShowOKCancelMessageAsync(Application.Current.MainWindow,
Strings.DeleteDNSServer,
Strings.DeleteDNSServerMessage,
ChildWindowIcon.Info,
Strings.Delete);

var childWindowViewModel = new OKCancelInfoMessageViewModel(_ =>
{
childWindow.IsOpen = false;
ConfigurationManager.Current.IsChildWindowOpen = false;

SettingsManager.Current.DNSLookup_DNSServers.Remove(SelectedDNSServer);
}, _ =>
{
childWindow.IsOpen = false;
ConfigurationManager.Current.IsChildWindowOpen = false;
},
Strings.DeleteDNSServerMessage,
Strings.Delete
);

childWindow.Title = Strings.DeleteDNSServer;

childWindow.DataContext = childWindowViewModel;

ConfigurationManager.Current.IsChildWindowOpen = true;
if (!result)
return;

return (Application.Current.MainWindow as MainWindow).ShowChildWindowAsync(childWindow);
SettingsManager.Current.DNSLookup_DNSServers.Remove(SelectedDNSServer);
}

#endregion
Expand Down
44 changes: 17 additions & 27 deletions Source/NETworkManager/ViewModels/HostsFileEditorViewModel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -391,38 +391,28 @@ private async Task DeleteEntryAction()
{
IsModifying = true;

var childWindow = new OKCancelInfoMessageChildWindow();

var childWindowViewModel = new OKCancelInfoMessageViewModel(async _ =>
{
childWindow.IsOpen = false;
ConfigurationManager.Current.IsChildWindowOpen = false;

var result = await HostsFileEditor.DeleteEntryAsync(SelectedResult);

if (result != HostsFileEntryModifyResult.Success)
await ShowErrorMessageAsync(result);

IsModifying = false;
}, _ =>
{
childWindow.IsOpen = false;
ConfigurationManager.Current.IsChildWindowOpen = false;

IsModifying = false;
},
var result = await DialogHelper.ShowOKCancelMessageAsync(Application.Current.MainWindow,
Strings.DeleteEntry,
string.Format(Strings.DeleteHostsFileEntryMessage, SelectedResult.IPAddress, SelectedResult.Hostname,
string.IsNullOrEmpty(SelectedResult.Comment) ? "" : $"# {SelectedResult.Comment}"),
ChildWindowIcon.Info,
Strings.Delete
);
);

childWindow.Title = Strings.DeleteEntry;

Copy link

Copilot AI Nov 11, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unnecessary blank line. There are two consecutive blank lines here where only one is needed.

Copilot uses AI. Check for mistakes.
childWindow.DataContext = childWindowViewModel;
if (!result)
{
IsModifying = false;
return;
}

ConfigurationManager.Current.IsChildWindowOpen = true;

Copy link

Copilot AI Nov 11, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unnecessary blank line. There are two consecutive blank lines here where only one is needed.

Copilot uses AI. Check for mistakes.
await (Application.Current.MainWindow as MainWindow).ShowChildWindowAsync(childWindow);
var modifyResult = await HostsFileEditor.DeleteEntryAsync(SelectedResult);

if (modifyResult != HostsFileEntryModifyResult.Success)
await ShowErrorMessageAsync(modifyResult);

IsModifying = false;
}

private bool ModifyEntry_CanExecute(object obj)
Expand Down Expand Up @@ -452,7 +442,7 @@ private async Task ShowErrorMessageAsync(HostsFileEntryModifyResult result)
{
childWindow.IsOpen = false;
ConfigurationManager.Current.IsChildWindowOpen = false;
}, message, Strings.OK, ChildWindowIcon.Error);
}, message, ChildWindowIcon.Error, Strings.OK);

childWindow.Title = Strings.Error;

Expand All @@ -479,7 +469,7 @@ private async Task RestartAsAdminAction()
{
childWindow.IsOpen = false;
ConfigurationManager.Current.IsChildWindowOpen = false;
}, ex.Message, Strings.OK, ChildWindowIcon.Error);
}, ex.Message, ChildWindowIcon.Error, Strings.OK);

childWindow.Title = Strings.Error;

Expand Down
Loading