feat(usage): split throttle thresholds per bucket, add draggable gauge markers
This commit is contained in:
@@ -390,7 +390,8 @@
|
||||
</ScrollViewer>
|
||||
</TabItem>
|
||||
|
||||
<TabItem Header="{loc:Tr settings.onlineInbox.tabHeader}">
|
||||
<TabItem Header="{loc:Tr settings.onlineInbox.tabHeader}"
|
||||
IsVisible="{Binding ShowOnlineInbox}">
|
||||
<ScrollViewer>
|
||||
<StackPanel Spacing="14" Margin="0,8,0,0">
|
||||
|
||||
|
||||
@@ -8,6 +8,7 @@ public partial class SettingsModalView : Window
|
||||
public SettingsModalView()
|
||||
{
|
||||
InitializeComponent();
|
||||
|
||||
}
|
||||
|
||||
protected override void OnDataContextChanged(EventArgs e)
|
||||
|
||||
@@ -18,19 +18,6 @@
|
||||
<KeyBinding Gesture="Escape" Command="{Binding CloseCommand}"/>
|
||||
</Window.KeyBindings>
|
||||
|
||||
<Window.Styles>
|
||||
<Style Selector="ProgressBar.usage-gauge">
|
||||
<Setter Property="Height" Value="10"/>
|
||||
<Setter Property="CornerRadius" Value="4"/>
|
||||
<Setter Property="Minimum" Value="0"/>
|
||||
<Setter Property="Maximum" Value="100"/>
|
||||
<Setter Property="Foreground" Value="{DynamicResource AccentBrush}"/>
|
||||
</Style>
|
||||
<Style Selector="ProgressBar.usage-gauge.warn">
|
||||
<Setter Property="Foreground" Value="{DynamicResource StatusReviewBrush}"/>
|
||||
</Style>
|
||||
</Window.Styles>
|
||||
|
||||
<ctl:ModalShell Title="{loc:Tr modals.usageMonitor.title}" CloseCommand="{Binding CloseCommand}">
|
||||
<DockPanel>
|
||||
|
||||
@@ -82,19 +69,60 @@
|
||||
<ItemsControl.ItemTemplate>
|
||||
<DataTemplate x:DataType="vm:UsageGaugeRowViewModel">
|
||||
<Border Background="{DynamicResource DeepBrush}" BorderBrush="{DynamicResource LineBrush}"
|
||||
BorderThickness="1" CornerRadius="6" Padding="12,10" Margin="0,0,10,10" Width="240">
|
||||
BorderThickness="1" CornerRadius="6" Padding="12,10" Margin="0,0,10,10" Width="270">
|
||||
<StackPanel Spacing="6">
|
||||
<StackPanel Orientation="Horizontal" Spacing="6">
|
||||
<TextBlock Classes="eyebrow" Text="{Binding Label}"/>
|
||||
<TextBlock Classes="meta" Text="{Binding Percent, StringFormat={}{0:0}%}" HorizontalAlignment="Right"/>
|
||||
</StackPanel>
|
||||
<Grid Height="10">
|
||||
<ProgressBar Classes="usage-gauge" Classes.warn="{Binding IsWarnSeverity}" Value="{Binding Percent}"/>
|
||||
<Canvas IsHitTestVisible="False">
|
||||
<Rectangle Canvas.Left="{Binding ThresholdMarkerLeftPx}" Width="2" Height="10"
|
||||
Fill="{DynamicResource TextDimBrush}"
|
||||
IsVisible="{Binding ThresholdPercent, Converter={x:Static conv:ObjectConverters.IsNotNull}}"/>
|
||||
</Canvas>
|
||||
<ctl:UsageGaugeBar Height="16"
|
||||
Percent="{Binding Percent}"
|
||||
IsWarn="{Binding IsWarnSeverity}"
|
||||
SoftPct="{Binding SoftPct, Mode=TwoWay}"
|
||||
HardPct="{Binding HardPct, Mode=TwoWay}"
|
||||
GatePct="{Binding GatePct, Mode=TwoWay}"
|
||||
CommitCommand="{Binding CommitCommand}"
|
||||
TrackBrush="{DynamicResource LineBrush}"
|
||||
FillBrush="{DynamicResource AccentBrush}"
|
||||
WarnFillBrush="{DynamicResource StatusReviewBrush}"
|
||||
SoftMarkerBrush="{DynamicResource TextDimBrush}"
|
||||
HardMarkerBrush="{DynamicResource StatusReviewBrush}"
|
||||
GateMarkerBrush="{DynamicResource StatusErrorBrush}"
|
||||
ToolTip.Tip="{loc:Tr modals.usageMonitor.dragHint}"/>
|
||||
|
||||
<!-- Legend doubles as the numeric editor: swatch colours match the bar's markers,
|
||||
and each box commits on Enter / focus loss (handlers in the code-behind). -->
|
||||
<Grid ColumnDefinitions="10,*,62" RowDefinitions="Auto,Auto,Auto"
|
||||
IsVisible="{Binding IsAdjustable}" Margin="0,2,0,0">
|
||||
<Rectangle Grid.Row="0" Grid.Column="0" Width="10" Height="3" RadiusX="1.5" RadiusY="1.5"
|
||||
VerticalAlignment="Center" Fill="{DynamicResource TextDimBrush}"/>
|
||||
<TextBlock Grid.Row="0" Grid.Column="1" Classes="meta" Margin="6,0,4,0"
|
||||
VerticalAlignment="Center" Text="{loc:Tr modals.usageMonitor.legendSoft}"/>
|
||||
<NumericUpDown Grid.Row="0" Grid.Column="2" Tag="soft"
|
||||
Value="{Binding SoftPct, Mode=TwoWay, Converter={StaticResource KeepLastNumber}}"
|
||||
Minimum="0" Maximum="100" Increment="5" FormatString="0"
|
||||
ShowButtonSpinner="False" FontSize="12" Padding="6,2"
|
||||
LostFocus="OnStageBoxCommit" KeyDown="OnStageBoxKeyDown"/>
|
||||
|
||||
<Rectangle Grid.Row="1" Grid.Column="0" Width="10" Height="3" RadiusX="1.5" RadiusY="1.5"
|
||||
VerticalAlignment="Center" Fill="{DynamicResource StatusReviewBrush}"/>
|
||||
<TextBlock Grid.Row="1" Grid.Column="1" Classes="meta" Margin="6,0,4,0"
|
||||
VerticalAlignment="Center" Text="{loc:Tr modals.usageMonitor.legendHard}"/>
|
||||
<NumericUpDown Grid.Row="1" Grid.Column="2" Tag="hard"
|
||||
Value="{Binding HardPct, Mode=TwoWay, Converter={StaticResource KeepLastNumber}}"
|
||||
Minimum="0" Maximum="100" Increment="5" FormatString="0"
|
||||
ShowButtonSpinner="False" FontSize="12" Padding="6,2"
|
||||
LostFocus="OnStageBoxCommit" KeyDown="OnStageBoxKeyDown"/>
|
||||
|
||||
<Rectangle Grid.Row="2" Grid.Column="0" Width="10" Height="3" RadiusX="1.5" RadiusY="1.5"
|
||||
VerticalAlignment="Center" Fill="{DynamicResource StatusErrorBrush}"/>
|
||||
<TextBlock Grid.Row="2" Grid.Column="1" Classes="meta" Margin="6,0,4,0"
|
||||
VerticalAlignment="Center" Text="{loc:Tr modals.usageMonitor.legendGate}"/>
|
||||
<NumericUpDown Grid.Row="2" Grid.Column="2" Tag="gate"
|
||||
Value="{Binding GatePct, Mode=TwoWay, Converter={StaticResource KeepLastNumber}}"
|
||||
Minimum="0" Maximum="100" Increment="5" FormatString="0"
|
||||
ShowButtonSpinner="False" FontSize="12" Padding="6,2"
|
||||
LostFocus="OnStageBoxCommit" KeyDown="OnStageBoxKeyDown"/>
|
||||
</Grid>
|
||||
<TextBlock Classes="meta" Text="{Binding ResetText}" IsVisible="{Binding ResetText, Converter={x:Static conv:StringConverters.IsNotNullOrEmpty}}"/>
|
||||
</StackPanel>
|
||||
|
||||
@@ -1,8 +1,36 @@
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Input;
|
||||
using Avalonia.Interactivity;
|
||||
using ClaudeDo.Ui.ViewModels.Modals;
|
||||
|
||||
namespace ClaudeDo.Ui.Views.Modals;
|
||||
|
||||
public partial class UsageMonitorModalView : Window
|
||||
{
|
||||
public UsageMonitorModalView() => InitializeComponent();
|
||||
|
||||
/// <summary>
|
||||
/// Persists a stage typed into a gauge's legend box. `NumericUpDown` has no commit command, so
|
||||
/// the box's <c>Tag</c> names the stage and the row's matching command does the clamp + save.
|
||||
/// </summary>
|
||||
private void OnStageBoxCommit(object? sender, RoutedEventArgs e)
|
||||
{
|
||||
if (sender is not Control { Tag: string stage, DataContext: UsageGaugeRowViewModel row }) return;
|
||||
|
||||
var command = stage switch
|
||||
{
|
||||
"soft" => row.CommitSoftCommand,
|
||||
"hard" => row.CommitHardCommand,
|
||||
_ => row.CommitGateCommand,
|
||||
};
|
||||
|
||||
if (command.CanExecute(null)) command.Execute(null);
|
||||
}
|
||||
|
||||
private void OnStageBoxKeyDown(object? sender, KeyEventArgs e)
|
||||
{
|
||||
if (e.Key != Key.Enter) return;
|
||||
OnStageBoxCommit(sender, e);
|
||||
e.Handled = true;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user