mirror of
https://github.com/2dust/v2rayN.git
synced 2025-11-18 21:52:52 +00:00
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
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:
parent
84f812c8ee
commit
2ebd2b28a8
15 changed files with 168 additions and 129 deletions
|
|
@ -152,7 +152,10 @@
|
||||||
<DataGrid.ContextMenu>
|
<DataGrid.ContextMenu>
|
||||||
<ContextMenu>
|
<ContextMenu>
|
||||||
<MenuItem x:Name="menuAddChildServer" Header="{x:Static resx:ResUI.menuAddChildServer}" />
|
<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
|
<MenuItem
|
||||||
x:Name="menuSelectAllChild"
|
x:Name="menuSelectAllChild"
|
||||||
Header="{x:Static resx:ResUI.menuSelectAll}"
|
Header="{x:Static resx:ResUI.menuSelectAll}"
|
||||||
|
|
|
||||||
|
|
@ -132,6 +132,7 @@ public partial class AddGroupServerWindow : WindowBase<AddGroupServerViewModel>
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case Key.Delete:
|
case Key.Delete:
|
||||||
|
case Key.Back:
|
||||||
ViewModel?.ChildRemoveAsync();
|
ViewModel?.ChildRemoveAsync();
|
||||||
e.Handled = true;
|
e.Handled = true;
|
||||||
break;
|
break;
|
||||||
|
|
|
||||||
|
|
@ -115,7 +115,7 @@
|
||||||
<MenuItem
|
<MenuItem
|
||||||
x:Name="menuRemoveServer"
|
x:Name="menuRemoveServer"
|
||||||
Header="{x:Static resx:ResUI.menuRemoveServer}"
|
Header="{x:Static resx:ResUI.menuRemoveServer}"
|
||||||
InputGesture="Delete" />
|
InputGesture="Back" />
|
||||||
<MenuItem x:Name="menuRemoveDuplicateServer" Header="{x:Static resx:ResUI.menuRemoveDuplicateServer}" />
|
<MenuItem x:Name="menuRemoveDuplicateServer" Header="{x:Static resx:ResUI.menuRemoveDuplicateServer}" />
|
||||||
<MenuItem x:Name="menuRemoveInvalidServerResult" Header="{x:Static resx:ResUI.menuRemoveInvalidServerResult}" />
|
<MenuItem x:Name="menuRemoveInvalidServerResult" Header="{x:Static resx:ResUI.menuRemoveInvalidServerResult}" />
|
||||||
<Separator />
|
<Separator />
|
||||||
|
|
|
||||||
|
|
@ -313,33 +313,37 @@ public partial class ProfilesView : ReactiveUserControl<ProfilesViewModel>
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (e.Key is Key.Enter or Key.Return)
|
switch (e.Key)
|
||||||
{
|
{
|
||||||
|
case Key.Enter:
|
||||||
|
//case Key.Return:
|
||||||
ViewModel?.SetDefaultServer();
|
ViewModel?.SetDefaultServer();
|
||||||
}
|
break;
|
||||||
else if (e.Key == Key.Delete)
|
|
||||||
{
|
case Key.Delete:
|
||||||
|
case Key.Back:
|
||||||
ViewModel?.RemoveServerAsync();
|
ViewModel?.RemoveServerAsync();
|
||||||
}
|
break;
|
||||||
else if (e.Key == Key.T)
|
|
||||||
{
|
case Key.T:
|
||||||
ViewModel?.MoveServer(EMove.Top);
|
ViewModel?.MoveServer(EMove.Top);
|
||||||
}
|
break;
|
||||||
else if (e.Key == Key.U)
|
|
||||||
{
|
case Key.U:
|
||||||
ViewModel?.MoveServer(EMove.Up);
|
ViewModel?.MoveServer(EMove.Up);
|
||||||
}
|
break;
|
||||||
else if (e.Key == Key.D)
|
|
||||||
{
|
case Key.D:
|
||||||
ViewModel?.MoveServer(EMove.Down);
|
ViewModel?.MoveServer(EMove.Down);
|
||||||
}
|
break;
|
||||||
else if (e.Key == Key.B)
|
|
||||||
{
|
case Key.B:
|
||||||
ViewModel?.MoveServer(EMove.Bottom);
|
ViewModel?.MoveServer(EMove.Bottom);
|
||||||
}
|
break;
|
||||||
else if (e.Key == Key.Escape)
|
|
||||||
{
|
case Key.Escape:
|
||||||
ViewModel?.ServerSpeedtestStop();
|
ViewModel?.ServerSpeedtestStop();
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -187,7 +187,7 @@
|
||||||
<MenuItem
|
<MenuItem
|
||||||
x:Name="menuRuleRemove"
|
x:Name="menuRuleRemove"
|
||||||
Header="{x:Static resx:ResUI.menuRuleRemove}"
|
Header="{x:Static resx:ResUI.menuRuleRemove}"
|
||||||
InputGesture="Delete" />
|
InputGesture="Back" />
|
||||||
<MenuItem
|
<MenuItem
|
||||||
x:Name="menuRuleSelectAll"
|
x:Name="menuRuleSelectAll"
|
||||||
Header="{x:Static resx:ResUI.menuSelectAll}"
|
Header="{x:Static resx:ResUI.menuSelectAll}"
|
||||||
|
|
|
||||||
|
|
@ -140,25 +140,28 @@ public partial class RoutingRuleSettingWindow : WindowBase<RoutingRuleSettingVie
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (e.Key == Key.T)
|
switch (e.Key)
|
||||||
{
|
{
|
||||||
|
case Key.T:
|
||||||
ViewModel?.MoveRule(EMove.Top);
|
ViewModel?.MoveRule(EMove.Top);
|
||||||
}
|
break;
|
||||||
else if (e.Key == Key.U)
|
|
||||||
{
|
case Key.U:
|
||||||
ViewModel?.MoveRule(EMove.Up);
|
ViewModel?.MoveRule(EMove.Up);
|
||||||
}
|
break;
|
||||||
else if (e.Key == Key.D)
|
|
||||||
{
|
case Key.D:
|
||||||
ViewModel?.MoveRule(EMove.Down);
|
ViewModel?.MoveRule(EMove.Down);
|
||||||
}
|
break;
|
||||||
else if (e.Key == Key.B)
|
|
||||||
{
|
case Key.B:
|
||||||
ViewModel?.MoveRule(EMove.Bottom);
|
ViewModel?.MoveRule(EMove.Bottom);
|
||||||
}
|
break;
|
||||||
else if (e.Key == Key.Delete)
|
|
||||||
{
|
case Key.Delete:
|
||||||
|
case Key.Back:
|
||||||
ViewModel?.RuleRemoveAsync();
|
ViewModel?.RuleRemoveAsync();
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -102,7 +102,7 @@
|
||||||
<MenuItem
|
<MenuItem
|
||||||
x:Name="menuRoutingAdvancedRemove"
|
x:Name="menuRoutingAdvancedRemove"
|
||||||
Header="{x:Static resx:ResUI.menuRoutingAdvancedRemove}"
|
Header="{x:Static resx:ResUI.menuRoutingAdvancedRemove}"
|
||||||
InputGesture="Delete" />
|
InputGesture="Back" />
|
||||||
<MenuItem
|
<MenuItem
|
||||||
x:Name="menuRoutingAdvancedSelectAll"
|
x:Name="menuRoutingAdvancedSelectAll"
|
||||||
Header="{x:Static resx:ResUI.menuSelectAll}"
|
Header="{x:Static resx:ResUI.menuSelectAll}"
|
||||||
|
|
|
||||||
|
|
@ -73,18 +73,27 @@ public partial class RoutingSettingWindow : WindowBase<RoutingSettingViewModel>
|
||||||
{
|
{
|
||||||
if (e.KeyModifiers is KeyModifiers.Control or KeyModifiers.Meta)
|
if (e.KeyModifiers is KeyModifiers.Control or KeyModifiers.Meta)
|
||||||
{
|
{
|
||||||
if (e.Key == Key.A)
|
switch (e.Key)
|
||||||
{
|
{
|
||||||
|
case Key.A:
|
||||||
lstRoutings.SelectAll();
|
lstRoutings.SelectAll();
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (e.Key is Key.Enter or Key.Return)
|
else
|
||||||
{
|
{
|
||||||
|
switch (e.Key)
|
||||||
|
{
|
||||||
|
case Key.Enter:
|
||||||
|
//case Key.Return:
|
||||||
ViewModel?.RoutingAdvancedSetDefault();
|
ViewModel?.RoutingAdvancedSetDefault();
|
||||||
}
|
break;
|
||||||
else if (e.Key == Key.Delete)
|
|
||||||
{
|
case Key.Delete:
|
||||||
|
case Key.Back:
|
||||||
ViewModel?.RoutingAdvancedRemoveAsync();
|
ViewModel?.RoutingAdvancedRemoveAsync();
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -91,25 +91,28 @@ public partial class AddGroupServerWindow
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (e.Key == Key.T)
|
switch (e.Key)
|
||||||
{
|
{
|
||||||
|
case Key.T:
|
||||||
ViewModel?.MoveServer(EMove.Top);
|
ViewModel?.MoveServer(EMove.Top);
|
||||||
}
|
break;
|
||||||
else if (e.Key == Key.U)
|
|
||||||
{
|
case Key.U:
|
||||||
ViewModel?.MoveServer(EMove.Up);
|
ViewModel?.MoveServer(EMove.Up);
|
||||||
}
|
break;
|
||||||
else if (e.Key == Key.D)
|
|
||||||
{
|
case Key.D:
|
||||||
ViewModel?.MoveServer(EMove.Down);
|
ViewModel?.MoveServer(EMove.Down);
|
||||||
}
|
break;
|
||||||
else if (e.Key == Key.B)
|
|
||||||
{
|
case Key.B:
|
||||||
ViewModel?.MoveServer(EMove.Bottom);
|
ViewModel?.MoveServer(EMove.Bottom);
|
||||||
}
|
break;
|
||||||
else if (e.Key == Key.Delete)
|
|
||||||
{
|
case Key.Delete:
|
||||||
|
case Key.Back:
|
||||||
ViewModel?.ChildRemoveAsync();
|
ViewModel?.ChildRemoveAsync();
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -138,7 +138,7 @@
|
||||||
x:Name="menuRemoveServer"
|
x:Name="menuRemoveServer"
|
||||||
Height="{StaticResource MenuItemHeight}"
|
Height="{StaticResource MenuItemHeight}"
|
||||||
Header="{x:Static resx:ResUI.menuRemoveServer}"
|
Header="{x:Static resx:ResUI.menuRemoveServer}"
|
||||||
InputGestureText="Delete" />
|
InputGestureText="Back" />
|
||||||
<MenuItem
|
<MenuItem
|
||||||
x:Name="menuRemoveDuplicateServer"
|
x:Name="menuRemoveDuplicateServer"
|
||||||
Height="{StaticResource MenuItemHeight}"
|
Height="{StaticResource MenuItemHeight}"
|
||||||
|
|
|
||||||
|
|
@ -292,33 +292,37 @@ public partial class ProfilesView
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (e.Key is Key.Enter or Key.Return)
|
switch (e.Key)
|
||||||
{
|
{
|
||||||
|
case Key.Enter:
|
||||||
|
//case Key.Return:
|
||||||
ViewModel?.SetDefaultServer();
|
ViewModel?.SetDefaultServer();
|
||||||
}
|
break;
|
||||||
else if (e.Key == Key.Delete)
|
|
||||||
{
|
case Key.Delete:
|
||||||
|
case Key.Back:
|
||||||
ViewModel?.RemoveServerAsync();
|
ViewModel?.RemoveServerAsync();
|
||||||
}
|
break;
|
||||||
else if (e.Key == Key.T)
|
|
||||||
{
|
case Key.T:
|
||||||
ViewModel?.MoveServer(EMove.Top);
|
ViewModel?.MoveServer(EMove.Top);
|
||||||
}
|
break;
|
||||||
else if (e.Key == Key.U)
|
|
||||||
{
|
case Key.U:
|
||||||
ViewModel?.MoveServer(EMove.Up);
|
ViewModel?.MoveServer(EMove.Up);
|
||||||
}
|
break;
|
||||||
else if (e.Key == Key.D)
|
|
||||||
{
|
case Key.D:
|
||||||
ViewModel?.MoveServer(EMove.Down);
|
ViewModel?.MoveServer(EMove.Down);
|
||||||
}
|
break;
|
||||||
else if (e.Key == Key.B)
|
|
||||||
{
|
case Key.B:
|
||||||
ViewModel?.MoveServer(EMove.Bottom);
|
ViewModel?.MoveServer(EMove.Bottom);
|
||||||
}
|
break;
|
||||||
else if (e.Key == Key.Escape)
|
|
||||||
{
|
case Key.Escape:
|
||||||
ViewModel?.ServerSpeedtestStop();
|
ViewModel?.ServerSpeedtestStop();
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -264,7 +264,7 @@
|
||||||
x:Name="menuRuleRemove"
|
x:Name="menuRuleRemove"
|
||||||
Height="{StaticResource MenuItemHeight}"
|
Height="{StaticResource MenuItemHeight}"
|
||||||
Header="{x:Static resx:ResUI.menuRuleRemove}"
|
Header="{x:Static resx:ResUI.menuRuleRemove}"
|
||||||
InputGestureText="Delete" />
|
InputGestureText="Back" />
|
||||||
<MenuItem
|
<MenuItem
|
||||||
x:Name="menuRuleSelectAll"
|
x:Name="menuRuleSelectAll"
|
||||||
Height="{StaticResource MenuItemHeight}"
|
Height="{StaticResource MenuItemHeight}"
|
||||||
|
|
|
||||||
|
|
@ -140,25 +140,28 @@ public partial class RoutingRuleSettingWindow
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (e.Key == Key.T)
|
switch (e.Key)
|
||||||
{
|
{
|
||||||
|
case Key.T:
|
||||||
ViewModel?.MoveRule(EMove.Top);
|
ViewModel?.MoveRule(EMove.Top);
|
||||||
}
|
break;
|
||||||
else if (e.Key == Key.U)
|
|
||||||
{
|
case Key.U:
|
||||||
ViewModel?.MoveRule(EMove.Up);
|
ViewModel?.MoveRule(EMove.Up);
|
||||||
}
|
break;
|
||||||
else if (e.Key == Key.D)
|
|
||||||
{
|
case Key.D:
|
||||||
ViewModel?.MoveRule(EMove.Down);
|
ViewModel?.MoveRule(EMove.Down);
|
||||||
}
|
break;
|
||||||
else if (e.Key == Key.B)
|
|
||||||
{
|
case Key.B:
|
||||||
ViewModel?.MoveRule(EMove.Bottom);
|
ViewModel?.MoveRule(EMove.Bottom);
|
||||||
}
|
break;
|
||||||
else if (e.Key == Key.Delete)
|
|
||||||
{
|
case Key.Delete:
|
||||||
|
case Key.Back:
|
||||||
ViewModel?.RuleRemoveAsync();
|
ViewModel?.RuleRemoveAsync();
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -145,7 +145,7 @@
|
||||||
x:Name="menuRoutingAdvancedRemove"
|
x:Name="menuRoutingAdvancedRemove"
|
||||||
Height="{StaticResource MenuItemHeight}"
|
Height="{StaticResource MenuItemHeight}"
|
||||||
Header="{x:Static resx:ResUI.menuRoutingAdvancedRemove}"
|
Header="{x:Static resx:ResUI.menuRoutingAdvancedRemove}"
|
||||||
InputGestureText="Delete" />
|
InputGestureText="Back" />
|
||||||
<MenuItem
|
<MenuItem
|
||||||
x:Name="menuRoutingAdvancedSelectAll"
|
x:Name="menuRoutingAdvancedSelectAll"
|
||||||
Height="{StaticResource MenuItemHeight}"
|
Height="{StaticResource MenuItemHeight}"
|
||||||
|
|
|
||||||
|
|
@ -78,18 +78,27 @@ public partial class RoutingSettingWindow
|
||||||
{
|
{
|
||||||
if (Keyboard.IsKeyDown(Key.LeftCtrl) || Keyboard.IsKeyDown(Key.RightCtrl))
|
if (Keyboard.IsKeyDown(Key.LeftCtrl) || Keyboard.IsKeyDown(Key.RightCtrl))
|
||||||
{
|
{
|
||||||
if (e.Key == Key.A)
|
switch (e.Key)
|
||||||
{
|
{
|
||||||
|
case Key.A:
|
||||||
lstRoutings.SelectAll();
|
lstRoutings.SelectAll();
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (e.Key is Key.Enter or Key.Return)
|
else
|
||||||
{
|
{
|
||||||
|
switch (e.Key)
|
||||||
|
{
|
||||||
|
case Key.Enter:
|
||||||
|
//case Key.Return:
|
||||||
ViewModel?.RoutingAdvancedSetDefault();
|
ViewModel?.RoutingAdvancedSetDefault();
|
||||||
}
|
break;
|
||||||
else if (e.Key == Key.Delete)
|
|
||||||
{
|
case Key.Delete:
|
||||||
|
case Key.Back:
|
||||||
ViewModel?.RoutingAdvancedRemoveAsync();
|
ViewModel?.RoutingAdvancedRemoveAsync();
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue