Files
webhook-server/src/WebhookServer.Gui/Converters/Converters.cs
T
justin 28479272d5 Configurable bind addresses + display host in Server Settings
ServerConfig grows two fields:
- BindAddresses: list of IPs Kestrel binds to (empty = all interfaces,
  current behavior). Listening only on a subset is useful when the host
  has multiple NICs and the webhook should not be reachable on all of
  them.
- DisplayHost: the hostname/IP the GUI splices into the URL column and
  Copy URL button. Cosmetic; doesn't affect what the server accepts.

Server Settings dialog gains a "Network" section: a checkbox for "all
interfaces" plus per-NIC checkboxes auto-detected via NetworkInterface.
GetAllNetworkInterfaces, and an editable ComboBox for the display host
pre-populated with detected IPs and the machine name.

Listener restart fires on BindAddresses change but not on DisplayHost
change (cosmetic).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-08 09:27:18 -04:00

60 lines
2.3 KiB
C#

using System.Globalization;
using System.Windows.Data;
using System.Windows.Media;
namespace WebhookServer.Gui.Converters;
public sealed class NullToBoolConverter : IValueConverter
{
public object Convert(object? value, Type targetType, object? parameter, CultureInfo culture)
=> value is not null;
public object ConvertBack(object? value, Type targetType, object? parameter, CultureInfo culture)
=> throw new NotSupportedException();
}
public sealed class HookUrlConverter : IMultiValueConverter
{
public object Convert(object[] values, Type targetType, object? parameter, CultureInfo culture)
{
if (values.Length < 2) return "";
var slug = values[0] as string ?? "";
var baseUrl = values[1] as string ?? "";
if (string.IsNullOrEmpty(baseUrl) || string.IsNullOrEmpty(slug)) return "";
return $"{baseUrl.TrimEnd('/')}/hook/{slug}";
}
public object[] ConvertBack(object? value, Type[] targetTypes, object? parameter, CultureInfo culture)
=> throw new NotSupportedException();
}
public sealed class InvertBoolConverter : IValueConverter
{
public object Convert(object? value, Type targetType, object? parameter, CultureInfo culture)
=> value is bool b && !b;
public object ConvertBack(object? value, Type targetType, object? parameter, CultureInfo culture)
=> value is bool b && !b;
}
public sealed class StringEqualsConverter : IValueConverter
{
public object Convert(object? value, Type targetType, object? parameter, CultureInfo culture)
=> string.Equals(value as string, parameter as string, StringComparison.OrdinalIgnoreCase);
public object? ConvertBack(object? value, Type targetType, object? parameter, CultureInfo culture)
=> (value is bool b && b) ? parameter : Binding.DoNothing;
}
public sealed class BoolToBrushConverter : IValueConverter
{
public Brush TrueBrush { get; set; } = Brushes.SeaGreen;
public Brush FalseBrush { get; set; } = Brushes.IndianRed;
public object Convert(object? value, Type targetType, object? parameter, CultureInfo culture)
=> (value is bool b && b) ? TrueBrush : FalseBrush;
public object ConvertBack(object? value, Type targetType, object? parameter, CultureInfo culture)
=> throw new NotSupportedException();
}