Files
2dust_v2rayN/v2rayN/v2rayN/Views/ProfilesView.xaml.cs
T

410 lines
16 KiB
C#

using ReactiveUI;
using Splat;
using System.Reactive.Disposables;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Controls.Primitives;
using System.Windows.Input;
using System.Windows.Media;
using v2rayN.Base;
using v2rayN.Enums;
using v2rayN.Handler;
using v2rayN.Models;
using v2rayN.Resx;
using v2rayN.ViewModels;
using Point = System.Windows.Point;
namespace v2rayN.Views
{
public partial class ProfilesView
{
private static Config _config;
public ProfilesView()
{
InitializeComponent();
lstGroup.MaxHeight = Math.Floor(SystemParameters.WorkArea.Height * 0.20 / 40) * 40;
_config = LazyConfig.Instance.GetConfig();
Application.Current.Exit += Current_Exit;
btnAutofitColumnWidth.Click += BtnAutofitColumnWidth_Click;
txtServerFilter.PreviewKeyDown += TxtServerFilter_PreviewKeyDown;
lstProfiles.PreviewKeyDown += LstProfiles_PreviewKeyDown;
lstProfiles.SelectionChanged += lstProfiles_SelectionChanged;
lstProfiles.LoadingRow += LstProfiles_LoadingRow;
if (_config.uiItem.enableDragDropSort)
{
lstProfiles.AllowDrop = true;
lstProfiles.PreviewMouseLeftButtonDown += LstProfiles_PreviewMouseLeftButtonDown;
lstProfiles.MouseMove += LstProfiles_MouseMove;
lstProfiles.DragEnter += LstProfiles_DragEnter;
lstProfiles.Drop += LstProfiles_Drop;
}
ViewModel = new ProfilesViewModel(UpdateViewHandler);
Locator.CurrentMutable.RegisterLazySingleton(() => ViewModel, typeof(ProfilesViewModel));
this.WhenActivated(disposables =>
{
this.OneWayBind(ViewModel, vm => vm.ProfileItems, v => v.lstProfiles.ItemsSource).DisposeWith(disposables);
this.Bind(ViewModel, vm => vm.SelectedProfile, v => v.lstProfiles.SelectedItem).DisposeWith(disposables);
this.OneWayBind(ViewModel, vm => vm.SubItems, v => v.lstGroup.ItemsSource).DisposeWith(disposables);
this.Bind(ViewModel, vm => vm.SelectedSub, v => v.lstGroup.SelectedItem).DisposeWith(disposables);
this.Bind(ViewModel, vm => vm.ServerFilter, v => v.txtServerFilter.Text).DisposeWith(disposables);
this.BindCommand(ViewModel, vm => vm.AddSubCmd, v => v.btnAddSub).DisposeWith(disposables);
this.BindCommand(ViewModel, vm => vm.EditSubCmd, v => v.btnEditSub).DisposeWith(disposables);
//servers delete
this.BindCommand(ViewModel, vm => vm.EditServerCmd, v => v.menuEditServer).DisposeWith(disposables);
this.BindCommand(ViewModel, vm => vm.RemoveServerCmd, v => v.menuRemoveServer).DisposeWith(disposables);
this.BindCommand(ViewModel, vm => vm.RemoveDuplicateServerCmd, v => v.menuRemoveDuplicateServer).DisposeWith(disposables);
this.BindCommand(ViewModel, vm => vm.CopyServerCmd, v => v.menuCopyServer).DisposeWith(disposables);
this.BindCommand(ViewModel, vm => vm.SetDefaultServerCmd, v => v.menuSetDefaultServer).DisposeWith(disposables);
this.BindCommand(ViewModel, vm => vm.ShareServerCmd, v => v.menuShareServer).DisposeWith(disposables);
this.BindCommand(ViewModel, vm => vm.SetDefaultMultipleServerCmd, v => v.menuSetDefaultMultipleServer).DisposeWith(disposables);
this.BindCommand(ViewModel, vm => vm.SetDefaultLoadBalanceServerCmd, v => v.menuSetDefaultLoadBalanceServer).DisposeWith(disposables);
//servers move
this.OneWayBind(ViewModel, vm => vm.SubItems, v => v.cmbMoveToGroup.ItemsSource).DisposeWith(disposables);
this.Bind(ViewModel, vm => vm.SelectedMoveToGroup, v => v.cmbMoveToGroup.SelectedItem).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);
//servers ping
this.BindCommand(ViewModel, vm => vm.MixedTestServerCmd, v => v.menuMixedTestServer).DisposeWith(disposables);
this.BindCommand(ViewModel, vm => vm.TcpingServerCmd, v => v.menuTcpingServer).DisposeWith(disposables);
this.BindCommand(ViewModel, vm => vm.RealPingServerCmd, v => v.menuRealPingServer).DisposeWith(disposables);
this.BindCommand(ViewModel, vm => vm.SpeedServerCmd, v => v.menuSpeedServer).DisposeWith(disposables);
this.BindCommand(ViewModel, vm => vm.SortServerResultCmd, v => v.menuSortServerResult).DisposeWith(disposables);
//servers export
this.BindCommand(ViewModel, vm => vm.Export2ClientConfigCmd, v => v.menuExport2ClientConfig).DisposeWith(disposables);
this.BindCommand(ViewModel, vm => vm.Export2ShareUrlCmd, v => v.menuExport2ShareUrl).DisposeWith(disposables);
});
RestoreUI();
}
#region Event
private void Current_Exit(object sender, ExitEventArgs e)
{
StorageUI();
}
private bool UpdateViewHandler(EViewAction action)
{
if (action == EViewAction.AdjustMainLvColWidth)
{
Application.Current.Dispatcher.Invoke(() =>
{
AutofitColumnWidth();
});
}
else if (action == EViewAction.ProfilesFocus)
{
lstProfiles.Focus();
}
else if (action == EViewAction.ShowYesNo)
{
if (UI.ShowYesNo(ResUI.RemoveServer) == MessageBoxResult.No)
{
return false;
}
}
return true;
}
private void lstProfiles_SelectionChanged(object sender, System.Windows.Controls.SelectionChangedEventArgs e)
{
ViewModel.SelectedProfiles = lstProfiles.SelectedItems.Cast<ProfileItemModel>().ToList();
}
private void LstProfiles_LoadingRow(object? sender, DataGridRowEventArgs e)
{
e.Row.Header = $" {e.Row.GetIndex() + 1}";
}
private void LstProfiles_MouseDoubleClick(object sender, MouseButtonEventArgs e)
{
if (_config.uiItem.doubleClick2Activate)
{
ViewModel?.SetDefaultServer();
}
else
{
ViewModel?.EditServer(false, EConfigType.Custom);
}
}
private void LstProfiles_ColumnHeader_Click(object sender, RoutedEventArgs e)
{
var colHeader = sender as DataGridColumnHeader;
if (colHeader == null || colHeader.TabIndex < 0 || colHeader.Column == null)
{
return;
}
var colName = ((MyDGTextColumn)colHeader.Column).ExName;
ViewModel?.SortServer(colName);
}
private void menuSelectAll_Click(object sender, RoutedEventArgs e)
{
lstProfiles.SelectAll();
}
private void LstProfiles_PreviewKeyDown(object sender, KeyEventArgs e)
{
if (Keyboard.IsKeyDown(Key.LeftCtrl) || Keyboard.IsKeyDown(Key.RightCtrl))
{
switch (e.Key)
{
case Key.A:
menuSelectAll_Click(null, null);
break;
case Key.C:
ViewModel?.Export2ShareUrl();
break;
case Key.D:
ViewModel?.EditServer(false, EConfigType.Custom);
break;
case Key.F:
ViewModel?.ShareServer();
break;
case Key.O:
ViewModel?.ServerSpeedtest(ESpeedActionType.Tcping);
break;
case Key.R:
ViewModel?.ServerSpeedtest(ESpeedActionType.Realping);
break;
case Key.T:
ViewModel?.ServerSpeedtest(ESpeedActionType.Speedtest);
break;
case Key.E:
ViewModel?.ServerSpeedtest(ESpeedActionType.Mixedtest);
break;
}
}
else
{
if (e.Key is Key.Enter or Key.Return)
{
ViewModel?.SetDefaultServer();
}
else if (e.Key == Key.Delete)
{
ViewModel?.RemoveServer();
}
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)
{
MessageBus.Current.SendMessage("true", Global.CommandStopSpeedTest);
}
}
}
private void BtnAutofitColumnWidth_Click(object sender, RoutedEventArgs e)
{
AutofitColumnWidth();
}
private void AutofitColumnWidth()
{
foreach (var it in lstProfiles.Columns)
{
it.Width = new DataGridLength(1, DataGridLengthUnitType.Auto);
}
}
private void TxtServerFilter_PreviewKeyDown(object sender, KeyEventArgs e)
{
if (e.Key is Key.Enter or Key.Return)
{
ViewModel?.RefreshServers();
}
}
#endregion Event
#region UI
private void RestoreUI()
{
var lvColumnItem = _config.uiItem.mainColumnItem.OrderBy(t => t.Index).ToList();
var displayIndex = 0;
foreach (var item in lvColumnItem)
{
foreach (MyDGTextColumn item2 in lstProfiles.Columns)
{
if (item2.ExName == item.Name)
{
if (item.Width < 0)
{
item2.Visibility = Visibility.Hidden;
}
else
{
item2.Width = item.Width;
item2.DisplayIndex = displayIndex++;
}
}
}
}
if (!_config.guiItem.enableStatistics)
{
colTodayUp.Visibility =
colTodayDown.Visibility =
colTotalUp.Visibility =
colTotalDown.Visibility = Visibility.Hidden;
}
else
{
colTodayUp.Visibility =
colTodayDown.Visibility =
colTotalUp.Visibility =
colTotalDown.Visibility = Visibility.Visible;
}
}
private void StorageUI()
{
List<ColumnItem> lvColumnItem = new();
for (int k = 0; k < lstProfiles.Columns.Count; k++)
{
var item2 = (MyDGTextColumn)lstProfiles.Columns[k];
lvColumnItem.Add(new()
{
Name = item2.ExName,
Width = item2.Visibility == Visibility.Visible ? Utils.ToInt(item2.ActualWidth) : -1,
Index = item2.DisplayIndex
});
}
_config.uiItem.mainColumnItem = lvColumnItem;
ConfigHandler.SaveConfig(_config);
}
#endregion UI
#region Drag and Drop
private Point startPoint = new();
private int startIndex = -1;
private string formatData = "ProfileItemModel";
/// <summary>
/// Helper to search up the VisualTree
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="current"></param>
/// <returns></returns>
private static T? FindAncestor<T>(DependencyObject current) where T : DependencyObject
{
do
{
if (current is T)
{
return (T)current;
}
current = VisualTreeHelper.GetParent(current);
}
while (current != null);
return null;
}
private void LstProfiles_PreviewMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
// Get current mouse position
startPoint = e.GetPosition(null);
}
private void LstProfiles_MouseMove(object sender, MouseEventArgs e)
{
// Get the current mouse position
Point mousePos = e.GetPosition(null);
Vector diff = startPoint - mousePos;
if (e.LeftButton == MouseButtonState.Pressed &&
(Math.Abs(diff.X) > SystemParameters.MinimumHorizontalDragDistance ||
Math.Abs(diff.Y) > SystemParameters.MinimumVerticalDragDistance))
{
// Get the dragged Item
if (sender is not DataGrid listView) return;
var listViewItem = FindAncestor<DataGridRow>((DependencyObject)e.OriginalSource);
if (listViewItem == null) return; // Abort
// Find the data behind the ListViewItem
ProfileItemModel item = (ProfileItemModel)listView.ItemContainerGenerator.ItemFromContainer(listViewItem);
if (item == null) return; // Abort
// Initialize the drag & drop operation
startIndex = lstProfiles.SelectedIndex;
DataObject dragData = new(formatData, item);
DragDrop.DoDragDrop(listViewItem, dragData, DragDropEffects.Copy | DragDropEffects.Move);
}
}
private void LstProfiles_DragEnter(object sender, DragEventArgs e)
{
if (!e.Data.GetDataPresent(formatData) || sender != e.Source)
{
e.Effects = DragDropEffects.None;
}
}
private void LstProfiles_Drop(object sender, DragEventArgs e)
{
if (e.Data.GetDataPresent(formatData) && sender == e.Source)
{
// Get the drop Item destination
if (sender is not DataGrid listView) return;
var listViewItem = FindAncestor<DataGridRow>((DependencyObject)e.OriginalSource);
if (listViewItem == null)
{
// Abort
e.Effects = DragDropEffects.None;
return;
}
// Find the data behind the Item
ProfileItemModel item = (ProfileItemModel)listView.ItemContainerGenerator.ItemFromContainer(listViewItem);
if (item == null) return;
// Move item into observable collection
// (this will be automatically reflected to lstView.ItemsSource)
e.Effects = DragDropEffects.Move;
ViewModel?.MoveServerTo(startIndex, item);
startIndex = -1;
}
}
#endregion Drag and Drop
}
}