Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
ff7024e
Feature: Firewall app
BornToBeRoot Apr 11, 2026
c3bccb0
Update Source/NETworkManager.Models/Firewall/FirewallRule.cs
BornToBeRoot Apr 11, 2026
7cf2ffd
Fix XML doc comments for Id/Name properties in FirewallRule.cs
Copilot Apr 11, 2026
0ea864c
Feature: Add translation
BornToBeRoot Apr 11, 2026
ff78d29
Feature: Add translation and export
BornToBeRoot Apr 11, 2026
271346e
Merge branch 'main' into feature/firewall-app-base
BornToBeRoot Apr 11, 2026
7058281
Feature: Add network profile to networkinterfaceview
BornToBeRoot Apr 11, 2026
2252908
Docs: #3383
BornToBeRoot Apr 11, 2026
e5d3ae4
Merge branch 'main' into feature/firewall-app-base
BornToBeRoot Apr 18, 2026
e04039e
Merge branch 'main' into feature/firewall-app-base
BornToBeRoot Apr 18, 2026
77d086b
Chore: Hide firewall settings/profile
BornToBeRoot Apr 18, 2026
0761db4
Chore: Refactor the UI
BornToBeRoot Apr 19, 2026
ad07dc6
Feature: UI & Copy data
BornToBeRoot Apr 19, 2026
57a2863
Chore: UI redesign
BornToBeRoot Apr 19, 2026
d90969f
Docs: Discovery Protocol
BornToBeRoot Apr 19, 2026
00ed305
Update package.json
BornToBeRoot Apr 19, 2026
aacad1a
Update yarn.lock
BornToBeRoot Apr 19, 2026
70b404e
Feature: Enable/Disable/Delete Firewall rule
BornToBeRoot Apr 19, 2026
a144800
Feature: Open Hosts File Editor
BornToBeRoot Apr 19, 2026
b92a304
Feature: Firewall add / edit firewall rule
BornToBeRoot Apr 19, 2026
fa13f29
Chore: Adjust strings
BornToBeRoot Apr 19, 2026
6761e73
Feature: Firewall edit/del + docs
BornToBeRoot Apr 19, 2026
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
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
using System;
using System.Globalization;
using System.Windows.Data;
using NETworkManager.Localization;
using NETworkManager.Models.Firewall;

namespace NETworkManager.Converters;

/// <summary>
/// Convert <see cref="FirewallInterfaceType" /> to translated <see cref="string" /> or vice versa.
/// </summary>
public sealed class FirewallInterfaceTypeToStringConverter : IValueConverter
{
/// <summary>
/// Convert <see cref="FirewallInterfaceType" /> to translated <see cref="string" />.
/// </summary>
/// <param name="value">Object from type <see cref="FirewallInterfaceType" />.</param>
/// <param name="targetType"></param>
/// <param name="parameter"></param>
/// <param name="culture"></param>
/// <returns>Translated <see cref="FirewallInterfaceType" />.</returns>
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
return value is not FirewallInterfaceType interfaceType
? "-/-"
: ResourceTranslator.Translate(ResourceIdentifier.FirewallInterfaceType, interfaceType);
}

/// <summary>
/// !!! Method not implemented !!!
/// </summary>
/// <param name="value"></param>
/// <param name="targetType"></param>
/// <param name="parameter"></param>
/// <param name="culture"></param>
/// <returns></returns>
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Windows.Data;
using NETworkManager.Localization.Resources;

namespace NETworkManager.Converters;

/// <summary>
/// Convert a <see cref="bool" /> array (Domain, Private, Public) representing firewall network
/// profiles to a localized <see cref="string" />, or vice versa.
/// </summary>
public sealed class FirewallNetworkProfilesToStringConverter : IValueConverter
{
/// <summary>
/// Convert a <see cref="bool" /> array (Domain, Private, Public) to a localized <see cref="string" />.
/// Returns <c>null</c> when all three profiles are active so that a <c>TargetNullValue</c> binding
/// can supply the translated "Any" label.
/// </summary>
/// <param name="value">A <see cref="bool" /> array with exactly three elements.</param>
/// <param name="targetType"></param>
/// <param name="parameter"></param>
/// <param name="culture"></param>
/// <returns>Localized, comma-separated profile list (e.g. "Domain, Private, Public").</returns>
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
if (value is not bool[] { Length: 3 } profiles)
return "-/-";

var names = new List<string>(3);
if (profiles[0]) names.Add(Strings.Domain);
if (profiles[1]) names.Add(Strings.Private);
if (profiles[2]) names.Add(Strings.Public);

return names.Count == 0 ? "-" : string.Join(", ", names);
Comment on lines +17 to +35
Copy link

Copilot AI Apr 19, 2026

Choose a reason for hiding this comment

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

The XML docs say this converter “Returns null when all three profiles are active … so that a TargetNullValue binding can supply the translated ‘Any’ label”, but the implementation never returns null and also returns "-" when no profiles are selected. Given the firewall PowerShell layer treats both all-true and all-false as Any, the converter should likely return a localized “Any” (or null to use TargetNullValue) for those cases to avoid misleading UI/exports.

Suggested change
/// Returns <c>null</c> when all three profiles are active so that a <c>TargetNullValue</c> binding
/// can supply the translated "Any" label.
/// </summary>
/// <param name="value">A <see cref="bool" /> array with exactly three elements.</param>
/// <param name="targetType"></param>
/// <param name="parameter"></param>
/// <param name="culture"></param>
/// <returns>Localized, comma-separated profile list (e.g. "Domain, Private, Public").</returns>
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
if (value is not bool[] { Length: 3 } profiles)
return "-/-";
var names = new List<string>(3);
if (profiles[0]) names.Add(Strings.Domain);
if (profiles[1]) names.Add(Strings.Private);
if (profiles[2]) names.Add(Strings.Public);
return names.Count == 0 ? "-" : string.Join(", ", names);
/// Returns <c>null</c> when all three profiles are active, or when none are active, so that a
/// <c>TargetNullValue</c> binding can supply the translated "Any" label.
/// </summary>
/// <param name="value">A <see cref="bool" /> array with exactly three elements.</param>
/// <param name="targetType"></param>
/// <param name="parameter"></param>
/// <param name="culture"></param>
/// <returns>
/// Localized, comma-separated profile list (e.g. "Domain, Private, Public"), or <c>null</c> for
/// profile combinations that represent "Any".
/// </returns>
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
if (value is not bool[] { Length: 3 } profiles)
return "-/-";
var allProfilesActive = profiles[0] && profiles[1] && profiles[2];
var noProfilesActive = !profiles[0] && !profiles[1] && !profiles[2];
if (allProfilesActive || noProfilesActive)
return null;
var names = new List<string>(3);
if (profiles[0]) names.Add(Strings.Domain);
if (profiles[1]) names.Add(Strings.Private);
if (profiles[2]) names.Add(Strings.Public);
return string.Join(", ", names);

Copilot uses AI. Check for mistakes.
}

/// <summary>
/// !!! Method not implemented !!!
/// </summary>
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
using System;
using System.Globalization;
using System.Windows.Data;
using NETworkManager.Localization;
using NETworkManager.Models.Firewall;

namespace NETworkManager.Converters;

/// <summary>
/// Convert <see cref="FirewallProtocol" /> to translated <see cref="string" /> or vice versa.
/// </summary>
public sealed class FirewallProtocolToStringConverter : IValueConverter
{
/// <summary>
/// Convert <see cref="FirewallProtocol" /> to translated <see cref="string" />.
/// </summary>
/// <param name="value">Object from type <see cref="FirewallProtocol" />.</param>
/// <param name="targetType"></param>
/// <param name="parameter"></param>
/// <param name="culture"></param>
/// <returns>Translated <see cref="FirewallProtocol" />.</returns>
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
return value is not FirewallProtocol protocol
? "-/-"
: ResourceTranslator.Translate(ResourceIdentifier.FirewallProtocol, protocol);
}

/// <summary>
/// !!! Method not implemented !!!
/// </summary>
/// <param name="value"></param>
/// <param name="targetType"></param>
/// <param name="parameter"></param>
/// <param name="culture"></param>
/// <returns></returns>
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
using System;
using System.Globalization;
using System.Windows.Data;
using NETworkManager.Localization;
using NETworkManager.Models.Firewall;

namespace NETworkManager.Converters;

/// <summary>
/// Convert <see cref="FirewallRuleAction" /> to translated <see cref="string" /> or vice versa.
/// </summary>
public sealed class FirewallRuleActionToStringConverter : IValueConverter
{
/// <summary>
/// Convert <see cref="FirewallRuleAction" /> to translated <see cref="string" />.
/// </summary>
/// <param name="value">Object from type <see cref="FirewallRuleAction" />.</param>
/// <param name="targetType"></param>
/// <param name="parameter"></param>
/// <param name="culture"></param>
/// <returns>Translated <see cref="FirewallRuleAction" />.</returns>
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
return value is not FirewallRuleAction action
? "-/-"
: ResourceTranslator.Translate(ResourceIdentifier.FirewallRuleAction, action);
}

/// <summary>
/// !!! Method not implemented !!!
/// </summary>
/// <param name="value"></param>
/// <param name="targetType"></param>
/// <param name="parameter"></param>
/// <param name="culture"></param>
/// <returns></returns>
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
using System;
using System.Globalization;
using System.Windows.Data;
using NETworkManager.Localization;
using NETworkManager.Models.Firewall;

namespace NETworkManager.Converters;

/// <summary>
/// Convert <see cref="FirewallRuleDirection" /> to translated <see cref="string" /> or vice versa.
/// </summary>
public sealed class FirewallRuleDirectionToStringConverter : IValueConverter
{
/// <summary>
/// Convert <see cref="FirewallRuleDirection" /> to translated <see cref="string" />.
/// </summary>
/// <param name="value">Object from type <see cref="FirewallRuleDirection" />.</param>
/// <param name="targetType"></param>
/// <param name="parameter"></param>
/// <param name="culture"></param>
/// <returns>Translated <see cref="FirewallRuleDirection" />.</returns>
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
return value is not FirewallRuleDirection direction
? "-/-"
: ResourceTranslator.Translate(ResourceIdentifier.FirewallRuleDirection, direction);
}

/// <summary>
/// !!! Method not implemented !!!
/// </summary>
/// <param name="value"></param>
/// <param name="targetType"></param>
/// <param name="parameter"></param>
/// <param name="culture"></param>
/// <returns></returns>
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
using System;
using System.Globalization;
using System.Windows.Data;
using NETworkManager.Localization.Resources;
using NETworkManager.Models.Network;

namespace NETworkManager.Converters;

/// <summary>
/// Convert <see cref="NetworkProfile" /> to a localized <see cref="string" /> or vice versa.
/// </summary>
public sealed class NetworkProfileToStringConverter : IValueConverter
{
/// <summary>
/// Convert <see cref="NetworkProfile" /> to a localized <see cref="string" />.
/// </summary>
/// <param name="value">Object from type <see cref="NetworkProfile" />.</param>
/// <param name="targetType"></param>
/// <param name="parameter"></param>
/// <param name="culture"></param>
/// <returns>Localized <see cref="string" /> representing the network profile.</returns>
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
return value is not NetworkProfile profile
? "-/-"
: profile switch
{
NetworkProfile.Domain => Strings.Domain,
NetworkProfile.Private => Strings.Private,
NetworkProfile.Public => Strings.Public,
_ => "-/-"
};
}

/// <summary>
/// !!! Method not implemented !!!
/// </summary>
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}
6 changes: 5 additions & 1 deletion Source/NETworkManager.Localization/ResourceIdentifier.cs
Original file line number Diff line number Diff line change
Expand Up @@ -22,5 +22,9 @@ public enum ResourceIdentifier
TcpState,
Theme,
TimeUnit,
WiFiConnectionStatus
WiFiConnectionStatus,
FirewallProtocol,
FirewallInterfaceType,
FirewallRuleDirection,
FirewallRuleAction
}

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
Expand Up @@ -342,4 +342,10 @@
<data name="ExampleFqdnOrIPAddressPublic" xml:space="preserve">
<value>borntoberoot.net or 1.1.1.1</value>
</data>
<data name="ExampleFirewallRuleName" xml:space="preserve">
<value>MyApp - HTTP</value>
</data>
<data name="ExampleFirewallAddresses" xml:space="preserve">
<value>10.0.0.0/8; LocalSubnet</value>
</data>
</root>
Loading
Loading