mirror of
https://github.com/2dust/v2rayN.git
synced 2025-10-13 11:59:13 +00:00
avalonia
This commit is contained in:
parent
dd2bfd9511
commit
d074d9a72a
5 changed files with 312 additions and 0 deletions
149
v2rayN/v2rayN.Desktop/Views/AddGroupServerWindow.axaml
Normal file
149
v2rayN/v2rayN.Desktop/Views/AddGroupServerWindow.axaml
Normal file
|
@ -0,0 +1,149 @@
|
|||
<Window
|
||||
x:Class="v2rayN.Desktop.Views.AddGroupServerWindow"
|
||||
xmlns="https://github.com/avaloniaui"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:resx="clr-namespace:ServiceLib.Resx;assembly=ServiceLib"
|
||||
xmlns:vms="clr-namespace:ServiceLib.ViewModels;assembly=ServiceLib"
|
||||
Title="{x:Static resx:ResUI.menuServers}"
|
||||
Width="900"
|
||||
Height="700"
|
||||
x:DataType="vms:AddGroupServerViewModel"
|
||||
ShowInTaskbar="False"
|
||||
WindowStartupLocation="CenterScreen"
|
||||
mc:Ignorable="d">
|
||||
|
||||
<DockPanel Margin="{StaticResource Margin8}">
|
||||
<StackPanel
|
||||
Margin="{StaticResource Margin4}"
|
||||
HorizontalAlignment="Center"
|
||||
DockPanel.Dock="Bottom"
|
||||
Orientation="Horizontal">
|
||||
<Button
|
||||
x:Name="btnSave"
|
||||
Width="100"
|
||||
Content="{x:Static resx:ResUI.TbConfirm}"
|
||||
IsDefault="True" />
|
||||
<Button
|
||||
x:Name="btnCancel"
|
||||
Width="100"
|
||||
Margin="{StaticResource MarginLr8}"
|
||||
Content="{x:Static resx:ResUI.TbCancel}"
|
||||
IsCancel="True" />
|
||||
</StackPanel>
|
||||
|
||||
<ScrollViewer HorizontalScrollBarVisibility="Auto" VerticalScrollBarVisibility="Auto">
|
||||
<Grid RowDefinitions="Auto,*,Auto,Auto,Auto,Auto,Auto,Auto,Auto">
|
||||
|
||||
<Grid
|
||||
Grid.Row="0"
|
||||
ColumnDefinitions="180,Auto,Auto"
|
||||
RowDefinitions="Auto,Auto,Auto,Auto,Auto">
|
||||
<TextBlock
|
||||
Grid.Row="0"
|
||||
Grid.Column="0"
|
||||
Margin="{StaticResource Margin4}"
|
||||
Text="{x:Static resx:ResUI.menuServers}" />
|
||||
|
||||
<TextBlock
|
||||
Grid.Row="1"
|
||||
Grid.Column="0"
|
||||
Margin="{StaticResource Margin4}"
|
||||
VerticalAlignment="Center"
|
||||
Text="{x:Static resx:ResUI.TbRemarks}" />
|
||||
<TextBox
|
||||
x:Name="txtRemarks"
|
||||
Grid.Row="1"
|
||||
Grid.Column="1"
|
||||
Width="400"
|
||||
Margin="{StaticResource Margin4}" />
|
||||
|
||||
<TextBlock
|
||||
Grid.Row="2"
|
||||
Grid.Column="0"
|
||||
Margin="{StaticResource Margin4}"
|
||||
VerticalAlignment="Center"
|
||||
Text="{x:Static resx:ResUI.TbCoreType}" />
|
||||
<ComboBox
|
||||
x:Name="cmbCoreType"
|
||||
Grid.Row="2"
|
||||
Grid.Column="1"
|
||||
Width="200"
|
||||
Margin="{StaticResource Margin4}" />
|
||||
|
||||
<Grid
|
||||
x:Name="gridPolicyGroup"
|
||||
Grid.Row="3"
|
||||
Grid.Column="0"
|
||||
Grid.ColumnSpan="3"
|
||||
ColumnDefinitions="180,Auto,Auto">
|
||||
<TextBlock
|
||||
Grid.Column="0"
|
||||
Margin="{StaticResource Margin4}"
|
||||
VerticalAlignment="Center"
|
||||
Text="{x:Static resx:ResUI.TbPolicyGroupType}" />
|
||||
<ComboBox
|
||||
x:Name="cmbPolicyGroupType"
|
||||
Grid.Column="1"
|
||||
Width="200"
|
||||
Margin="{StaticResource Margin4}" />
|
||||
</Grid>
|
||||
</Grid>
|
||||
|
||||
<DataGrid
|
||||
x:Name="lstChild"
|
||||
Grid.Row="1"
|
||||
AutoGenerateColumns="False"
|
||||
BorderThickness="1"
|
||||
CanUserReorderColumns="False"
|
||||
CanUserResizeColumns="True"
|
||||
CanUserSortColumns="False"
|
||||
GridLinesVisibility="All"
|
||||
HeadersVisibility="Column"
|
||||
IsReadOnly="True"
|
||||
ItemsSource="{Binding ChildItemsObs}"
|
||||
SelectionMode="Extended">
|
||||
<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="menuSelectAllChild" Header="{x:Static resx:ResUI.menuSelectAll}" />
|
||||
<Separator />
|
||||
<MenuItem x:Name="menuMoveTop" Header="{x:Static resx:ResUI.menuMoveTop}" />
|
||||
<MenuItem x:Name="menuMoveUp" Header="{x:Static resx:ResUI.menuMoveUp}" />
|
||||
<MenuItem x:Name="menuMoveDown" Header="{x:Static resx:ResUI.menuMoveDown}" />
|
||||
<MenuItem x:Name="menuMoveBottom" Header="{x:Static resx:ResUI.menuMoveBottom}" />
|
||||
</ContextMenu>
|
||||
</DataGrid.ContextMenu>
|
||||
<DataGrid.Columns>
|
||||
<DataGridTextColumn
|
||||
Width="150"
|
||||
Binding="{Binding ConfigType}"
|
||||
Header="{x:Static resx:ResUI.LvServiceType}" />
|
||||
<DataGridTextColumn
|
||||
Width="150"
|
||||
Binding="{Binding Remarks}"
|
||||
Header="{x:Static resx:ResUI.LvRemarks}" />
|
||||
<DataGridTextColumn
|
||||
Width="120"
|
||||
Binding="{Binding Address}"
|
||||
Header="{x:Static resx:ResUI.LvAddress}" />
|
||||
<DataGridTextColumn
|
||||
Width="100"
|
||||
Binding="{Binding Port}"
|
||||
Header="{x:Static resx:ResUI.LvPort}" />
|
||||
<DataGridTextColumn
|
||||
Width="100"
|
||||
Binding="{Binding Network}"
|
||||
Header="{x:Static resx:ResUI.LvTransportProtocol}" />
|
||||
<DataGridTextColumn
|
||||
Width="100"
|
||||
Binding="{Binding StreamSecurity}"
|
||||
Header="{x:Static resx:ResUI.LvTLS}" />
|
||||
</DataGrid.Columns>
|
||||
</DataGrid>
|
||||
</Grid>
|
||||
</ScrollViewer>
|
||||
</DockPanel>
|
||||
</Window>
|
149
v2rayN/v2rayN.Desktop/Views/AddGroupServerWindow.axaml.cs
Normal file
149
v2rayN/v2rayN.Desktop/Views/AddGroupServerWindow.axaml.cs
Normal file
|
@ -0,0 +1,149 @@
|
|||
using System.Reactive.Disposables;
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Input;
|
||||
using Avalonia.Interactivity;
|
||||
using ReactiveUI;
|
||||
using v2rayN.Desktop.Base;
|
||||
|
||||
namespace v2rayN.Desktop.Views;
|
||||
|
||||
public partial class AddGroupServerWindow : WindowBase<AddGroupServerViewModel>
|
||||
{
|
||||
public AddGroupServerWindow()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
|
||||
public AddGroupServerWindow(ProfileItem profileItem)
|
||||
{
|
||||
InitializeComponent();
|
||||
|
||||
this.Loaded += Window_Loaded;
|
||||
btnCancel.Click += (s, e) => this.Close();
|
||||
|
||||
ViewModel = new AddGroupServerViewModel(profileItem, UpdateViewHandler);
|
||||
|
||||
cmbCoreType.ItemsSource = Global.CoreTypes;
|
||||
cmbPolicyGroupType.ItemsSource = new List<string>
|
||||
{
|
||||
ResUI.TbLeastPing,
|
||||
ResUI.TbRandom,
|
||||
ResUI.TbRoundRobin,
|
||||
ResUI.TbLeastLoad,
|
||||
};
|
||||
|
||||
switch (profileItem.ConfigType)
|
||||
{
|
||||
case EConfigType.PolicyGroup:
|
||||
this.Title = ResUI.TbConfigTypePolicyGroup;
|
||||
break;
|
||||
case EConfigType.ProxyChain:
|
||||
this.Title = ResUI.TbConfigTypeProxyChain;
|
||||
gridPolicyGroup.IsVisible = false;
|
||||
break;
|
||||
}
|
||||
|
||||
this.WhenActivated(disposables =>
|
||||
{
|
||||
this.Bind(ViewModel, vm => vm.SelectedSource.Remarks, v => v.txtRemarks.Text).DisposeWith(disposables);
|
||||
this.Bind(ViewModel, vm => vm.CoreType, v => v.cmbCoreType.SelectedValue).DisposeWith(disposables);
|
||||
this.Bind(ViewModel, vm => vm.PolicyGroupType, v => v.cmbPolicyGroupType.SelectedValue).DisposeWith(disposables);
|
||||
|
||||
this.OneWayBind(ViewModel, vm => vm.ChildItemsObs, v => v.lstChild.ItemsSource).DisposeWith(disposables);
|
||||
this.Bind(ViewModel, vm => vm.SelectedChild, v => v.lstChild.SelectedItem).DisposeWith(disposables);
|
||||
|
||||
this.BindCommand(ViewModel, vm => vm.RemoveCmd, v => v.menuRemoveChildServer).DisposeWith(disposables);
|
||||
this.BindCommand(ViewModel, vm => vm.MoveTopCmd, v => v.menuMoveTop).DisposeWith(disposables);
|
||||
this.BindCommand(ViewModel, vm => vm.MoveUpCmd, v => v.menuMoveUp).DisposeWith(disposables);
|
||||
this.BindCommand(ViewModel, vm => vm.MoveDownCmd, v => v.menuMoveDown).DisposeWith(disposables);
|
||||
this.BindCommand(ViewModel, vm => vm.MoveBottomCmd, v => v.menuMoveBottom).DisposeWith(disposables);
|
||||
|
||||
this.BindCommand(ViewModel, vm => vm.SaveCmd, v => v.btnSave).DisposeWith(disposables);
|
||||
});
|
||||
|
||||
// Context menu actions that require custom logic (Add, SelectAll)
|
||||
menuAddChildServer.Click += MenuAddChild_Click;
|
||||
menuSelectAllChild.Click += (s, e) => lstChild.SelectAll();
|
||||
|
||||
// Keyboard shortcuts when focus is within grid
|
||||
this.AddHandler(KeyDownEvent, AddGroupServerWindow_KeyDown, RoutingStrategies.Tunnel);
|
||||
lstChild.LoadingRow += LstChild_LoadingRow;
|
||||
}
|
||||
|
||||
private void LstChild_LoadingRow(object? sender, DataGridRowEventArgs e)
|
||||
{
|
||||
e.Row.Header = $" {e.Row.Index + 1}";
|
||||
}
|
||||
|
||||
private async Task<bool> UpdateViewHandler(EViewAction action, object? obj)
|
||||
{
|
||||
switch (action)
|
||||
{
|
||||
case EViewAction.CloseWindow:
|
||||
this.Close(true);
|
||||
break;
|
||||
}
|
||||
return await Task.FromResult(true);
|
||||
}
|
||||
|
||||
private void Window_Loaded(object? sender, RoutedEventArgs e)
|
||||
{
|
||||
txtRemarks.Focus();
|
||||
}
|
||||
|
||||
private void AddGroupServerWindow_KeyDown(object? sender, KeyEventArgs e)
|
||||
{
|
||||
if (!lstChild.IsKeyboardFocusWithin)
|
||||
return;
|
||||
|
||||
if ((e.KeyModifiers & (KeyModifiers.Control | KeyModifiers.Meta)) != 0)
|
||||
{
|
||||
if (e.Key == Key.A)
|
||||
{
|
||||
lstChild.SelectAll();
|
||||
e.Handled = true;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
switch (e.Key)
|
||||
{
|
||||
case Key.T:
|
||||
ViewModel?.MoveServer(EMove.Top);
|
||||
e.Handled = true;
|
||||
break;
|
||||
case Key.U:
|
||||
ViewModel?.MoveServer(EMove.Up);
|
||||
e.Handled = true;
|
||||
break;
|
||||
case Key.D:
|
||||
ViewModel?.MoveServer(EMove.Down);
|
||||
e.Handled = true;
|
||||
break;
|
||||
case Key.B:
|
||||
ViewModel?.MoveServer(EMove.Bottom);
|
||||
e.Handled = true;
|
||||
break;
|
||||
case Key.Delete:
|
||||
ViewModel?.ChildRemoveAsync();
|
||||
e.Handled = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private async void MenuAddChild_Click(object? sender, RoutedEventArgs e)
|
||||
{
|
||||
var selectWindow = new ProfilesSelectWindow();
|
||||
selectWindow.SetConfigTypeFilter(new[] { EConfigType.Custom }, exclude: true);
|
||||
var result = await selectWindow.ShowDialog<bool?>(this);
|
||||
if (result == true)
|
||||
{
|
||||
var profile = await selectWindow.ProfileItem;
|
||||
if (profile != null && ViewModel != null)
|
||||
{
|
||||
ViewModel.ChildItemsObs.Add(profile);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -35,6 +35,8 @@
|
|||
<MenuItem x:Name="menuAddServerViaScan" Header="{x:Static resx:ResUI.menuAddServerViaScan}" />
|
||||
<MenuItem x:Name="menuAddServerViaImage" Header="{x:Static resx:ResUI.menuAddServerViaImage}" />
|
||||
<MenuItem x:Name="menuAddCustomServer" Header="{x:Static resx:ResUI.menuAddCustomServer}" />
|
||||
<MenuItem x:Name="menuAddPolicyGroupServer" Header="{x:Static resx:ResUI.menuAddPolicyGroupServer}" />
|
||||
<MenuItem x:Name="menuAddProxyChainServer" Header="{x:Static resx:ResUI.menuAddProxyChainServer}" />
|
||||
<Separator />
|
||||
<MenuItem x:Name="menuAddVmessServer" Header="{x:Static resx:ResUI.menuAddVmessServer}" />
|
||||
<MenuItem x:Name="menuAddVlessServer" Header="{x:Static resx:ResUI.menuAddVlessServer}" />
|
||||
|
|
|
@ -83,6 +83,8 @@ public partial class MainWindow : WindowBase<MainWindowViewModel>
|
|||
this.BindCommand(ViewModel, vm => vm.AddWireguardServerCmd, v => v.menuAddWireguardServer).DisposeWith(disposables);
|
||||
this.BindCommand(ViewModel, vm => vm.AddAnytlsServerCmd, v => v.menuAddAnytlsServer).DisposeWith(disposables);
|
||||
this.BindCommand(ViewModel, vm => vm.AddCustomServerCmd, v => v.menuAddCustomServer).DisposeWith(disposables);
|
||||
this.BindCommand(ViewModel, vm => vm.AddPolicyGroupServerCmd, v => v.menuAddPolicyGroupServer).DisposeWith(disposables);
|
||||
this.BindCommand(ViewModel, vm => vm.AddProxyChainServerCmd, v => v.menuAddProxyChainServer).DisposeWith(disposables);
|
||||
this.BindCommand(ViewModel, vm => vm.AddServerViaClipboardCmd, v => v.menuAddServerViaClipboard).DisposeWith(disposables);
|
||||
this.BindCommand(ViewModel, vm => vm.AddServerViaScanCmd, v => v.menuAddServerViaScan).DisposeWith(disposables);
|
||||
this.BindCommand(ViewModel, vm => vm.AddServerViaImageCmd, v => v.menuAddServerViaImage).DisposeWith(disposables);
|
||||
|
@ -207,6 +209,11 @@ public partial class MainWindow : WindowBase<MainWindowViewModel>
|
|||
return false;
|
||||
return await new AddServer2Window((ProfileItem)obj).ShowDialog<bool>(this);
|
||||
|
||||
case EViewAction.AddGroupServerWindow:
|
||||
if (obj is null)
|
||||
return false;
|
||||
return await new AddGroupServerWindow((ProfileItem)obj).ShowDialog<bool>(this);
|
||||
|
||||
case EViewAction.DNSSettingWindow:
|
||||
return await new DNSSettingWindow().ShowDialog<bool>(this);
|
||||
|
||||
|
|
|
@ -167,6 +167,11 @@ public partial class ProfilesView : ReactiveUserControl<ProfilesViewModel>
|
|||
return false;
|
||||
return await new AddServer2Window((ProfileItem)obj).ShowDialog<bool>(_window);
|
||||
|
||||
case EViewAction.AddGroupServerWindow:
|
||||
if (obj is null)
|
||||
return false;
|
||||
return await new AddGroupServerWindow((ProfileItem)obj).ShowDialog<bool>(_window);
|
||||
|
||||
case EViewAction.ShareServer:
|
||||
if (obj is null)
|
||||
return false;
|
||||
|
|
Loading…
Reference in a new issue