Support Backspace for remove actions in UI lists
Some checks are pending
release Linux / build (Release) (push) Waiting to run
release Linux / rpm (push) Blocked by required conditions
release macOS / build (Release) (push) Waiting to run
release Windows desktop (Avalonia UI) / build (Release) (push) Waiting to run
release Windows / build (Release) (push) Waiting to run

Changed key handling and menu input gestures to allow Backspace (in addition to Delete) for removing items in server, profile, and routing rule lists. This improves usability and consistency across both Avalonia and WPF views.
This commit is contained in:
2dust 2025-11-18 16:54:42 +08:00
parent 84f812c8ee
commit 2ebd2b28a8
15 changed files with 168 additions and 129 deletions

View file

@ -152,7 +152,10 @@
<DataGrid.ContextMenu>
<ContextMenu>
<MenuItem x:Name="menuAddChildServer" Header="{x:Static resx:ResUI.menuAddChildServer}" />
<MenuItem x:Name="menuRemoveChildServer" Header="{x:Static resx:ResUI.menuRemoveChildServer}" />
<MenuItem
x:Name="menuRemoveChildServer"
Header="{x:Static resx:ResUI.menuRemoveChildServer}"
InputGesture="Back" />
<MenuItem
x:Name="menuSelectAllChild"
Header="{x:Static resx:ResUI.menuSelectAll}"

View file

@ -132,6 +132,7 @@ public partial class AddGroupServerWindow : WindowBase<AddGroupServerViewModel>
break;
case Key.Delete:
case Key.Back:
ViewModel?.ChildRemoveAsync();
e.Handled = true;
break;

View file

@ -115,7 +115,7 @@
<MenuItem
x:Name="menuRemoveServer"
Header="{x:Static resx:ResUI.menuRemoveServer}"
InputGesture="Delete" />
InputGesture="Back" />
<MenuItem x:Name="menuRemoveDuplicateServer" Header="{x:Static resx:ResUI.menuRemoveDuplicateServer}" />
<MenuItem x:Name="menuRemoveInvalidServerResult" Header="{x:Static resx:ResUI.menuRemoveInvalidServerResult}" />
<Separator />

View file

@ -313,33 +313,37 @@ public partial class ProfilesView : ReactiveUserControl<ProfilesViewModel>
}
else
{
if (e.Key is Key.Enter or Key.Return)
switch (e.Key)
{
ViewModel?.SetDefaultServer();
}
else if (e.Key == Key.Delete)
{
ViewModel?.RemoveServerAsync();
}
else if (e.Key == Key.T)
{
ViewModel?.MoveServer(EMove.Top);
}
else if (e.Key == Key.U)
{
ViewModel?.MoveServer(EMove.Up);
}
else if (e.Key == Key.D)
{
ViewModel?.MoveServer(EMove.Down);
}
else if (e.Key == Key.B)
{
ViewModel?.MoveServer(EMove.Bottom);
}
else if (e.Key == Key.Escape)
{
ViewModel?.ServerSpeedtestStop();
case Key.Enter:
//case Key.Return:
ViewModel?.SetDefaultServer();
break;
case Key.Delete:
case Key.Back:
ViewModel?.RemoveServerAsync();
break;
case Key.T:
ViewModel?.MoveServer(EMove.Top);
break;
case Key.U:
ViewModel?.MoveServer(EMove.Up);
break;
case Key.D:
ViewModel?.MoveServer(EMove.Down);
break;
case Key.B:
ViewModel?.MoveServer(EMove.Bottom);
break;
case Key.Escape:
ViewModel?.ServerSpeedtestStop();
break;
}
}
}

View file

@ -187,7 +187,7 @@
<MenuItem
x:Name="menuRuleRemove"
Header="{x:Static resx:ResUI.menuRuleRemove}"
InputGesture="Delete" />
InputGesture="Back" />
<MenuItem
x:Name="menuRuleSelectAll"
Header="{x:Static resx:ResUI.menuSelectAll}"

View file

@ -140,25 +140,28 @@ public partial class RoutingRuleSettingWindow : WindowBase<RoutingRuleSettingVie
}
else
{
if (e.Key == Key.T)
switch (e.Key)
{
ViewModel?.MoveRule(EMove.Top);
}
else if (e.Key == Key.U)
{
ViewModel?.MoveRule(EMove.Up);
}
else if (e.Key == Key.D)
{
ViewModel?.MoveRule(EMove.Down);
}
else if (e.Key == Key.B)
{
ViewModel?.MoveRule(EMove.Bottom);
}
else if (e.Key == Key.Delete)
{
ViewModel?.RuleRemoveAsync();
case Key.T:
ViewModel?.MoveRule(EMove.Top);
break;
case Key.U:
ViewModel?.MoveRule(EMove.Up);
break;
case Key.D:
ViewModel?.MoveRule(EMove.Down);
break;
case Key.B:
ViewModel?.MoveRule(EMove.Bottom);
break;
case Key.Delete:
case Key.Back:
ViewModel?.RuleRemoveAsync();
break;
}
}
}

View file

@ -102,7 +102,7 @@
<MenuItem
x:Name="menuRoutingAdvancedRemove"
Header="{x:Static resx:ResUI.menuRoutingAdvancedRemove}"
InputGesture="Delete" />
InputGesture="Back" />
<MenuItem
x:Name="menuRoutingAdvancedSelectAll"
Header="{x:Static resx:ResUI.menuSelectAll}"

View file

@ -73,18 +73,27 @@ public partial class RoutingSettingWindow : WindowBase<RoutingSettingViewModel>
{
if (e.KeyModifiers is KeyModifiers.Control or KeyModifiers.Meta)
{
if (e.Key == Key.A)
switch (e.Key)
{
lstRoutings.SelectAll();
case Key.A:
lstRoutings.SelectAll();
break;
}
}
else if (e.Key is Key.Enter or Key.Return)
else
{
ViewModel?.RoutingAdvancedSetDefault();
}
else if (e.Key == Key.Delete)
{
ViewModel?.RoutingAdvancedRemoveAsync();
switch (e.Key)
{
case Key.Enter:
//case Key.Return:
ViewModel?.RoutingAdvancedSetDefault();
break;
case Key.Delete:
case Key.Back:
ViewModel?.RoutingAdvancedRemoveAsync();
break;
}
}
}

View file

@ -91,25 +91,28 @@ public partial class AddGroupServerWindow
}
else
{
if (e.Key == Key.T)
switch (e.Key)
{
ViewModel?.MoveServer(EMove.Top);
}
else if (e.Key == Key.U)
{
ViewModel?.MoveServer(EMove.Up);
}
else if (e.Key == Key.D)
{
ViewModel?.MoveServer(EMove.Down);
}
else if (e.Key == Key.B)
{
ViewModel?.MoveServer(EMove.Bottom);
}
else if (e.Key == Key.Delete)
{
ViewModel?.ChildRemoveAsync();
case Key.T:
ViewModel?.MoveServer(EMove.Top);
break;
case Key.U:
ViewModel?.MoveServer(EMove.Up);
break;
case Key.D:
ViewModel?.MoveServer(EMove.Down);
break;
case Key.B:
ViewModel?.MoveServer(EMove.Bottom);
break;
case Key.Delete:
case Key.Back:
ViewModel?.ChildRemoveAsync();
break;
}
}
}

View file

@ -138,7 +138,7 @@
x:Name="menuRemoveServer"
Height="{StaticResource MenuItemHeight}"
Header="{x:Static resx:ResUI.menuRemoveServer}"
InputGestureText="Delete" />
InputGestureText="Back" />
<MenuItem
x:Name="menuRemoveDuplicateServer"
Height="{StaticResource MenuItemHeight}"

View file

@ -292,33 +292,37 @@ public partial class ProfilesView
}
else
{
if (e.Key is Key.Enter or Key.Return)
switch (e.Key)
{
ViewModel?.SetDefaultServer();
}
else if (e.Key == Key.Delete)
{
ViewModel?.RemoveServerAsync();
}
else if (e.Key == Key.T)
{
ViewModel?.MoveServer(EMove.Top);
}
else if (e.Key == Key.U)
{
ViewModel?.MoveServer(EMove.Up);
}
else if (e.Key == Key.D)
{
ViewModel?.MoveServer(EMove.Down);
}
else if (e.Key == Key.B)
{
ViewModel?.MoveServer(EMove.Bottom);
}
else if (e.Key == Key.Escape)
{
ViewModel?.ServerSpeedtestStop();
case Key.Enter:
//case Key.Return:
ViewModel?.SetDefaultServer();
break;
case Key.Delete:
case Key.Back:
ViewModel?.RemoveServerAsync();
break;
case Key.T:
ViewModel?.MoveServer(EMove.Top);
break;
case Key.U:
ViewModel?.MoveServer(EMove.Up);
break;
case Key.D:
ViewModel?.MoveServer(EMove.Down);
break;
case Key.B:
ViewModel?.MoveServer(EMove.Bottom);
break;
case Key.Escape:
ViewModel?.ServerSpeedtestStop();
break;
}
}
}

View file

@ -264,7 +264,7 @@
x:Name="menuRuleRemove"
Height="{StaticResource MenuItemHeight}"
Header="{x:Static resx:ResUI.menuRuleRemove}"
InputGestureText="Delete" />
InputGestureText="Back" />
<MenuItem
x:Name="menuRuleSelectAll"
Height="{StaticResource MenuItemHeight}"

View file

@ -140,25 +140,28 @@ public partial class RoutingRuleSettingWindow
}
else
{
if (e.Key == Key.T)
switch (e.Key)
{
ViewModel?.MoveRule(EMove.Top);
}
else if (e.Key == Key.U)
{
ViewModel?.MoveRule(EMove.Up);
}
else if (e.Key == Key.D)
{
ViewModel?.MoveRule(EMove.Down);
}
else if (e.Key == Key.B)
{
ViewModel?.MoveRule(EMove.Bottom);
}
else if (e.Key == Key.Delete)
{
ViewModel?.RuleRemoveAsync();
case Key.T:
ViewModel?.MoveRule(EMove.Top);
break;
case Key.U:
ViewModel?.MoveRule(EMove.Up);
break;
case Key.D:
ViewModel?.MoveRule(EMove.Down);
break;
case Key.B:
ViewModel?.MoveRule(EMove.Bottom);
break;
case Key.Delete:
case Key.Back:
ViewModel?.RuleRemoveAsync();
break;
}
}
}

View file

@ -145,7 +145,7 @@
x:Name="menuRoutingAdvancedRemove"
Height="{StaticResource MenuItemHeight}"
Header="{x:Static resx:ResUI.menuRoutingAdvancedRemove}"
InputGestureText="Delete" />
InputGestureText="Back" />
<MenuItem
x:Name="menuRoutingAdvancedSelectAll"
Height="{StaticResource MenuItemHeight}"

View file

@ -78,18 +78,27 @@ public partial class RoutingSettingWindow
{
if (Keyboard.IsKeyDown(Key.LeftCtrl) || Keyboard.IsKeyDown(Key.RightCtrl))
{
if (e.Key == Key.A)
switch (e.Key)
{
lstRoutings.SelectAll();
case Key.A:
lstRoutings.SelectAll();
break;
}
}
else if (e.Key is Key.Enter or Key.Return)
else
{
ViewModel?.RoutingAdvancedSetDefault();
}
else if (e.Key == Key.Delete)
{
ViewModel?.RoutingAdvancedRemoveAsync();
switch (e.Key)
{
case Key.Enter:
//case Key.Return:
ViewModel?.RoutingAdvancedSetDefault();
break;
case Key.Delete:
case Key.Back:
ViewModel?.RoutingAdvancedRemoveAsync();
break;
}
}
}