28479272d5
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>
60 lines
2.3 KiB
C#
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();
|
|
}
|