From 56f7d64f07528706757b23f2b36bf4c18290b545 Mon Sep 17 00:00:00 2001 From: mika kuns Date: Thu, 6 Aug 2026 10:20:53 +0200 Subject: [PATCH] fix(ui): stop NumericUpDown from writing null into non-nullable settings Clearing the text box to type a new value sets Value to null, which the TwoWay binding then wrote into an int/decimal target -- InvalidCastException on the normal way of editing eight settings fields. KeepLastNumberConverter maps that null to BindingOperations.DoNothing so the source keeps its last value. --- src/ClaudeDo.App/App.axaml | 1 + .../Converters/KeepLastNumberConverter.cs | 24 +++++++++++++++++++ .../Views/Modals/SettingsModalView.axaml | 16 ++++++------- 3 files changed, 33 insertions(+), 8 deletions(-) create mode 100644 src/ClaudeDo.Ui/Converters/KeepLastNumberConverter.cs diff --git a/src/ClaudeDo.App/App.axaml b/src/ClaudeDo.App/App.axaml index aea3954b..8dc920a7 100644 --- a/src/ClaudeDo.App/App.axaml +++ b/src/ClaudeDo.App/App.axaml @@ -22,6 +22,7 @@ + diff --git a/src/ClaudeDo.Ui/Converters/KeepLastNumberConverter.cs b/src/ClaudeDo.Ui/Converters/KeepLastNumberConverter.cs new file mode 100644 index 00000000..77f26bcb --- /dev/null +++ b/src/ClaudeDo.Ui/Converters/KeepLastNumberConverter.cs @@ -0,0 +1,24 @@ +using System.Globalization; +using Avalonia.Data; +using Avalonia.Data.Converters; + +namespace ClaudeDo.Ui.Converters; + +/// +/// For NumericUpDown.Value bound to a non-nullable numeric property. The control's Value is +/// decimal? and goes null the moment the text box is empty — which is exactly what happens +/// while the user clears a value to type a new one. Writing that null into an int/decimal +/// target throws , so swallow it and leave the source untouched +/// until a real number arrives. +/// +public class KeepLastNumberConverter : IValueConverter +{ + public object? Convert(object? value, Type targetType, object? parameter, CultureInfo culture) + => value is null ? null : System.Convert.ToDecimal(value, culture); + + public object? ConvertBack(object? value, Type targetType, object? parameter, CultureInfo culture) + { + if (value is null) return BindingOperations.DoNothing; + return System.Convert.ChangeType(value, Nullable.GetUnderlyingType(targetType) ?? targetType, culture); + } +} diff --git a/src/ClaudeDo.Ui/Views/Modals/SettingsModalView.axaml b/src/ClaudeDo.Ui/Views/Modals/SettingsModalView.axaml index 04080652..55ce88db 100644 --- a/src/ClaudeDo.Ui/Views/Modals/SettingsModalView.axaml +++ b/src/ClaudeDo.Ui/Views/Modals/SettingsModalView.axaml @@ -135,7 +135,7 @@ - - - - - @@ -234,7 +234,7 @@ - @@ -384,7 +384,7 @@ + Value="{Binding Prime.DailyPrepMaxTasks, Mode=TwoWay, Converter={StaticResource KeepLastNumber}}"/> @@ -466,7 +466,7 @@ -