diff --git a/v2rayN/ServiceLib/Handler/Builder/CoreConfigContextBuilder.cs b/v2rayN/ServiceLib/Handler/Builder/CoreConfigContextBuilder.cs index 9a3aea84..1cbfbf14 100644 --- a/v2rayN/ServiceLib/Handler/Builder/CoreConfigContextBuilder.cs +++ b/v2rayN/ServiceLib/Handler/Builder/CoreConfigContextBuilder.cs @@ -269,6 +269,7 @@ public class CoreConfigContextBuilder IndexId = $"inner-{Utils.GetGuid(false)}", ConfigType = EConfigType.ProxyChain, CoreType = AppManager.Instance.GetCoreType(node, node.ConfigType), + Remarks = node.Remarks, }; List childItems = [prevNode?.IndexId, node.IndexId, nextNode?.IndexId]; var chainExtraItem = chainNode.GetProtocolExtra() with diff --git a/v2rayN/ServiceLib/Handler/ConfigHandler.cs b/v2rayN/ServiceLib/Handler/ConfigHandler.cs index e6978c69..3e16fc3e 100644 --- a/v2rayN/ServiceLib/Handler/ConfigHandler.cs +++ b/v2rayN/ServiceLib/Handler/ConfigHandler.cs @@ -154,6 +154,7 @@ public static class ConfigHandler DownMbps = 100 }; config.ClashUIItem ??= new(); + config.ClashUIItem.ConnectionsColumnItem ??= new(); config.SystemProxyItem ??= new(); config.WebDavItem ??= new(); config.CheckUpdateItem ??= new(); diff --git a/v2rayN/ServiceLib/Models/ConfigItems.cs b/v2rayN/ServiceLib/Models/ConfigItems.cs index 7dc8c266..56e5fe47 100644 --- a/v2rayN/ServiceLib/Models/ConfigItems.cs +++ b/v2rayN/ServiceLib/Models/ConfigItems.cs @@ -208,6 +208,7 @@ public class ClashUIItem public int ProxiesAutoDelayTestInterval { get; set; } = 10; public bool ConnectionsAutoRefresh { get; set; } public int ConnectionsRefreshInterval { get; set; } = 2; + public List ConnectionsColumnItem { get; set; } } [Serializable] diff --git a/v2rayN/v2rayN.Desktop/Views/ClashConnectionsView.axaml b/v2rayN/v2rayN.Desktop/Views/ClashConnectionsView.axaml index 21bad138..6a9b7088 100644 --- a/v2rayN/v2rayN.Desktop/Views/ClashConnectionsView.axaml +++ b/v2rayN/v2rayN.Desktop/Views/ClashConnectionsView.axaml @@ -74,23 +74,28 @@ + Header="{x:Static resx:ResUI.TbSortingHost}" + Tag="Host" /> + Header="{x:Static resx:ResUI.TbSortingChain}" + Tag="Chain" /> + Header="{x:Static resx:ResUI.TbSortingNetwork}" + Tag="Network" /> + Header="{x:Static resx:ResUI.TbSortingType}" + Tag="Type" /> + Header="{x:Static resx:ResUI.TbSortingTime}" + Tag="Elapsed" /> diff --git a/v2rayN/v2rayN.Desktop/Views/ClashConnectionsView.axaml.cs b/v2rayN/v2rayN.Desktop/Views/ClashConnectionsView.axaml.cs index 1c39df72..23722ad0 100644 --- a/v2rayN/v2rayN.Desktop/Views/ClashConnectionsView.axaml.cs +++ b/v2rayN/v2rayN.Desktop/Views/ClashConnectionsView.axaml.cs @@ -2,9 +2,15 @@ namespace v2rayN.Desktop.Views; public partial class ClashConnectionsView : ReactiveUserControl { + private static Config _config; + private static readonly string _tag = "ClashConnectionsView"; + public ClashConnectionsView() { InitializeComponent(); + + _config = AppManager.Instance.Config; + ViewModel = new ClashConnectionsViewModel(UpdateViewHandler); btnAutofitColumnWidth.Click += BtnAutofitColumnWidth_Click; @@ -19,7 +25,15 @@ public partial class ClashConnectionsView : ReactiveUserControl vm.HostFilter, v => v.txtHostFilter.Text).DisposeWith(disposables); this.BindCommand(ViewModel, vm => vm.ConnectionCloseAllCmd, v => v.btnConnectionCloseAll).DisposeWith(disposables); this.Bind(ViewModel, vm => vm.AutoRefresh, v => v.togAutoRefresh.IsChecked).DisposeWith(disposables); + + AppEvents.AppExitRequested + .AsObservable() + .ObserveOn(RxApp.MainThreadScheduler) + .Subscribe(_ => StorageUI()) + .DisposeWith(disposables); }); + + RestoreUI(); } private async Task UpdateViewHandler(EViewAction action, object? obj) @@ -51,4 +65,74 @@ public partial class ClashConnectionsView : ReactiveUserControl t.Index).ToList(); + if (lvColumnItem == null) + { + return; + } + + var displayIndex = 0; + foreach (var item in lvColumnItem) + { + foreach (var item2 in lstConnections.Columns) + { + if (item2.Tag == null) + { + continue; + } + if (item2.Tag.Equals(item.Name)) + { + if (item.Width < 0) + { + item2.IsVisible = false; + } + else + { + item2.Width = new DataGridLength(item.Width, DataGridLengthUnitType.Pixel); + item2.DisplayIndex = displayIndex++; + } + } + } + } + } + catch (Exception ex) + { + Logging.SaveLog(_tag, ex); + } + } + + private void StorageUI() + { + try + { + List lvColumnItem = new(); + foreach (var item2 in lstConnections.Columns) + { + if (item2.Tag == null) + { + continue; + } + lvColumnItem.Add(new() + { + Name = (string)item2.Tag, + Width = (int)(item2.IsVisible == true ? item2.ActualWidth : -1), + Index = item2.DisplayIndex + }); + } + _config.ClashUIItem.ConnectionsColumnItem = lvColumnItem; + } + catch (Exception ex) + { + Logging.SaveLog(_tag, ex); + } + } + + #endregion UI } diff --git a/v2rayN/v2rayN.Desktop/Views/ProfilesView.axaml.cs b/v2rayN/v2rayN.Desktop/Views/ProfilesView.axaml.cs index 4ca8e793..40336be5 100644 --- a/v2rayN/v2rayN.Desktop/Views/ProfilesView.axaml.cs +++ b/v2rayN/v2rayN.Desktop/Views/ProfilesView.axaml.cs @@ -7,6 +7,7 @@ public partial class ProfilesView : ReactiveUserControl { private static Config _config; private Window? _window; + private static readonly string _tag = "ProfilesView"; public ProfilesView() { @@ -381,7 +382,7 @@ public partial class ProfilesView : ReactiveUserControl } catch (Exception ex) { - Logging.SaveLog("ProfilesView", ex); + Logging.SaveLog(_tag, ex); } } @@ -399,53 +400,67 @@ public partial class ProfilesView : ReactiveUserControl private void RestoreUI() { - var lvColumnItem = _config.UiItem.MainColumnItem.OrderBy(t => t.Index).ToList(); - var displayIndex = 0; - foreach (var item in lvColumnItem) + try { + var lvColumnItem = _config.UiItem.MainColumnItem.OrderBy(t => t.Index).ToList(); + var displayIndex = 0; + foreach (var item in lvColumnItem) + { + foreach (var item2 in lstProfiles.Columns) + { + if (item2.Tag == null) + { + continue; + } + if (item2.Tag.Equals(item.Name)) + { + if (item.Width < 0) + { + item2.IsVisible = false; + } + else + { + item2.Width = new DataGridLength(item.Width, DataGridLengthUnitType.Pixel); + item2.DisplayIndex = displayIndex++; + } + if (item.Name.ToLower().StartsWith("to")) + { + item2.IsVisible = _config.GuiItem.EnableStatistics; + } + } + } + } + } + catch (Exception ex) + { + Logging.SaveLog(_tag, ex); + } + } + + private void StorageUI() + { + try + { + List lvColumnItem = new(); foreach (var item2 in lstProfiles.Columns) { if (item2.Tag == null) { continue; } - if (item2.Tag.Equals(item.Name)) + lvColumnItem.Add(new() { - if (item.Width < 0) - { - item2.IsVisible = false; - } - else - { - item2.Width = new DataGridLength(item.Width, DataGridLengthUnitType.Pixel); - item2.DisplayIndex = displayIndex++; - } - if (item.Name.ToLower().StartsWith("to")) - { - item2.IsVisible = _config.GuiItem.EnableStatistics; - } - } + Name = (string)item2.Tag, + Width = (int)(item2.IsVisible == true ? item2.ActualWidth : -1), + Index = item2.DisplayIndex + }); } + _config.UiItem.MainColumnItem = lvColumnItem; } - } - - private void StorageUI() - { - List lvColumnItem = new(); - foreach (var item2 in lstProfiles.Columns) + catch (Exception ex) { - if (item2.Tag == null) - { - continue; - } - lvColumnItem.Add(new() - { - Name = (string)item2.Tag, - Width = (int)(item2.IsVisible == true ? item2.ActualWidth : -1), - Index = item2.DisplayIndex - }); + Logging.SaveLog(_tag, ex); } - _config.UiItem.MainColumnItem = lvColumnItem; } #endregion UI diff --git a/v2rayN/v2rayN/Views/ClashConnectionsView.xaml b/v2rayN/v2rayN/Views/ClashConnectionsView.xaml index 0e6ba6a7..067926ff 100644 --- a/v2rayN/v2rayN/Views/ClashConnectionsView.xaml +++ b/v2rayN/v2rayN/Views/ClashConnectionsView.xaml @@ -2,6 +2,7 @@ x:Class="v2rayN.Views.ClashConnectionsView" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" + xmlns:base="clr-namespace:v2rayN.Base" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:materialDesign="http://materialdesigninxaml.net/winfx/xaml/themes" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" @@ -78,25 +79,30 @@ - - - - - diff --git a/v2rayN/v2rayN/Views/ClashConnectionsView.xaml.cs b/v2rayN/v2rayN/Views/ClashConnectionsView.xaml.cs index 0a6245a9..47482b8e 100644 --- a/v2rayN/v2rayN/Views/ClashConnectionsView.xaml.cs +++ b/v2rayN/v2rayN/Views/ClashConnectionsView.xaml.cs @@ -1,4 +1,5 @@ using System.Windows.Controls; +using v2rayN.Base; namespace v2rayN.Views; @@ -7,9 +8,14 @@ namespace v2rayN.Views; /// public partial class ClashConnectionsView { + private static Config _config; + private static readonly string _tag = "ClashConnectionsView"; + public ClashConnectionsView() { InitializeComponent(); + _config = AppManager.Instance.Config; + ViewModel = new ClashConnectionsViewModel(UpdateViewHandler); btnAutofitColumnWidth.Click += BtnAutofitColumnWidth_Click; @@ -24,7 +30,15 @@ public partial class ClashConnectionsView this.Bind(ViewModel, vm => vm.HostFilter, v => v.txtHostFilter.Text).DisposeWith(disposables); this.BindCommand(ViewModel, vm => vm.ConnectionCloseAllCmd, v => v.btnConnectionCloseAll).DisposeWith(disposables); this.Bind(ViewModel, vm => vm.AutoRefresh, v => v.togAutoRefresh.IsChecked).DisposeWith(disposables); + + AppEvents.AppExitRequested + .AsObservable() + .ObserveOn(RxApp.MainThreadScheduler) + .Subscribe(_ => StorageUI()) + .DisposeWith(disposables); }); + + RestoreUI(); } private async Task UpdateViewHandler(EViewAction action, object? obj) @@ -48,7 +62,7 @@ public partial class ClashConnectionsView } catch (Exception ex) { - Logging.SaveLog("ClashConnectionsView", ex); + Logging.SaveLog(_tag, ex); } } @@ -56,4 +70,71 @@ public partial class ClashConnectionsView { ViewModel?.ClashConnectionClose(false); } + + #region UI + + private void RestoreUI() + { + try + { + var lvColumnItem = _config.ClashUIItem?.ConnectionsColumnItem?.OrderBy(t => t.Index).ToList(); + if (lvColumnItem == null) + { + return; + } + + var displayIndex = 0; + foreach (var item in lvColumnItem) + { + foreach (var col in lstConnections.Columns.Cast()) + { + if (col.ExName == item.Name) + { + if (item.Width > 0) + { + col.Width = item.Width; + } + + col.DisplayIndex = displayIndex++; + break; + } + } + } + } + catch (Exception ex) + { + Logging.SaveLog(_tag, ex); + } + } + + private void StorageUI() + { + try + { + List lvColumnItem = new(); + foreach (var col in lstConnections.Columns.Cast()) + { + var name = col.ExName; + if (string.IsNullOrWhiteSpace(name)) + { + continue; + } + + lvColumnItem.Add(new() + { + Name = name, + Width = (int)col.ActualWidth, + Index = col.DisplayIndex + }); + } + + _config.ClashUIItem.ConnectionsColumnItem = lvColumnItem; + } + catch (Exception ex) + { + Logging.SaveLog(_tag, ex); + } + } + + #endregion UI } diff --git a/v2rayN/v2rayN/Views/ProfilesView.xaml.cs b/v2rayN/v2rayN/Views/ProfilesView.xaml.cs index 46def3e2..1440e6ec 100644 --- a/v2rayN/v2rayN/Views/ProfilesView.xaml.cs +++ b/v2rayN/v2rayN/Views/ProfilesView.xaml.cs @@ -10,6 +10,7 @@ namespace v2rayN.Views; public partial class ProfilesView { private static Config _config; + private static readonly string _tag = "ProfilesView"; public ProfilesView() { @@ -339,7 +340,7 @@ public partial class ProfilesView } catch (Exception ex) { - Logging.SaveLog("ProfilesView", ex); + Logging.SaveLog(_tag, ex); } } @@ -357,46 +358,59 @@ public partial class ProfilesView private void RestoreUI() { - var lvColumnItem = _config.UiItem.MainColumnItem.OrderBy(t => t.Index).ToList(); - var displayIndex = 0; - foreach (var item in lvColumnItem) + try { - foreach (MyDGTextColumn item2 in lstProfiles.Columns) + var lvColumnItem = _config.UiItem.MainColumnItem.OrderBy(t => t.Index).ToList(); + var displayIndex = 0; + foreach (var item in lvColumnItem) { - if (item2.ExName == item.Name) + foreach (var item2 in lstProfiles.Columns.Cast()) { - if (item.Width < 0) + if (item2.ExName == item.Name) { - item2.Visibility = Visibility.Hidden; - } - else - { - item2.Width = item.Width; - item2.DisplayIndex = displayIndex++; - } - if (item.Name.ToLower().StartsWith("to")) - { - item2.Visibility = _config.GuiItem.EnableStatistics ? Visibility.Visible : Visibility.Hidden; + if (item.Width < 0) + { + item2.Visibility = Visibility.Hidden; + } + else + { + item2.Width = item.Width; + item2.DisplayIndex = displayIndex++; + } + if (item.Name.ToLower().StartsWith("to")) + { + item2.Visibility = _config.GuiItem.EnableStatistics ? Visibility.Visible : Visibility.Hidden; + } } } } } + catch (Exception ex) + { + Logging.SaveLog(_tag, ex); + } } private void StorageUI() { - List lvColumnItem = new(); - foreach (var t in lstProfiles.Columns) + try { - var item2 = (MyDGTextColumn)t; - lvColumnItem.Add(new() + List lvColumnItem = new(); + foreach (var item2 in lstProfiles.Columns.Cast()) { - Name = item2.ExName, - Width = (int)(item2.Visibility == Visibility.Visible ? item2.ActualWidth : -1), - Index = item2.DisplayIndex - }); + lvColumnItem.Add(new() + { + Name = item2.ExName, + Width = (int)(item2.Visibility == Visibility.Visible ? item2.ActualWidth : -1), + Index = item2.DisplayIndex + }); + } + _config.UiItem.MainColumnItem = lvColumnItem; + } + catch (Exception ex) + { + Logging.SaveLog(_tag, ex); } - _config.UiItem.MainColumnItem = lvColumnItem; } #endregion UI @@ -405,7 +419,7 @@ public partial class ProfilesView private Point startPoint = new(); private int startIndex = -1; - private string formatData = "ProfileItemModel"; + private readonly string formatData = "ProfileItemModel"; /// /// Helper to search up the VisualTree