diff --git a/v2rayN/ServiceLib/Manager/GroupProfileManager.cs b/v2rayN/ServiceLib/Manager/GroupProfileManager.cs index 4296059d..53ef0429 100644 --- a/v2rayN/ServiceLib/Manager/GroupProfileManager.cs +++ b/v2rayN/ServiceLib/Manager/GroupProfileManager.cs @@ -75,7 +75,7 @@ public class GroupProfileManager return (await GetChildProfileItemsByProtocolExtra(protocolExtra), protocolExtra); } - private static async Task> GetChildProfileItemsByProtocolExtra(ProtocolExtraItem? protocolExtra) + public static async Task> GetChildProfileItemsByProtocolExtra(ProtocolExtraItem? protocolExtra) { if (protocolExtra == null) { diff --git a/v2rayN/ServiceLib/Resx/ResUI.Designer.cs b/v2rayN/ServiceLib/Resx/ResUI.Designer.cs index 46de8983..6f223693 100644 --- a/v2rayN/ServiceLib/Resx/ResUI.Designer.cs +++ b/v2rayN/ServiceLib/Resx/ResUI.Designer.cs @@ -1680,6 +1680,15 @@ namespace ServiceLib.Resx { } } + /// + /// 查找类似 Configuration item preview 的本地化字符串。 + /// + public static string menuServerListPreview { + get { + return ResourceManager.GetString("menuServerListPreview", resourceCulture); + } + } + /// /// 查找类似 Configuration 的本地化字符串。 /// diff --git a/v2rayN/ServiceLib/Resx/ResUI.fa-Ir.resx b/v2rayN/ServiceLib/Resx/ResUI.fa-Ir.resx index fdcffe9b..dbce6ac4 100644 --- a/v2rayN/ServiceLib/Resx/ResUI.fa-Ir.resx +++ b/v2rayN/ServiceLib/Resx/ResUI.fa-Ir.resx @@ -1668,4 +1668,7 @@ The "Get Certificate" action may fail if a self-signed certificate is used or if Port hopping interval + + Configuration item preview + \ No newline at end of file diff --git a/v2rayN/ServiceLib/Resx/ResUI.fr.resx b/v2rayN/ServiceLib/Resx/ResUI.fr.resx index 5db657ca..005a51d5 100644 --- a/v2rayN/ServiceLib/Resx/ResUI.fr.resx +++ b/v2rayN/ServiceLib/Resx/ResUI.fr.resx @@ -1665,4 +1665,7 @@ The "Get Certificate" action may fail if a self-signed certificate is used or if Port hopping interval + + Configuration item preview + \ No newline at end of file diff --git a/v2rayN/ServiceLib/Resx/ResUI.hu.resx b/v2rayN/ServiceLib/Resx/ResUI.hu.resx index 9e5c9c4d..3d169590 100644 --- a/v2rayN/ServiceLib/Resx/ResUI.hu.resx +++ b/v2rayN/ServiceLib/Resx/ResUI.hu.resx @@ -1668,4 +1668,7 @@ The "Get Certificate" action may fail if a self-signed certificate is used or if Port hopping interval + + Configuration item preview + \ No newline at end of file diff --git a/v2rayN/ServiceLib/Resx/ResUI.resx b/v2rayN/ServiceLib/Resx/ResUI.resx index dfd744a3..041a103b 100644 --- a/v2rayN/ServiceLib/Resx/ResUI.resx +++ b/v2rayN/ServiceLib/Resx/ResUI.resx @@ -1668,4 +1668,7 @@ The "Get Certificate" action may fail if a self-signed certificate is used or if Port hopping interval + + Configuration item preview + \ No newline at end of file diff --git a/v2rayN/ServiceLib/Resx/ResUI.ru.resx b/v2rayN/ServiceLib/Resx/ResUI.ru.resx index 67cffea7..66ebef79 100644 --- a/v2rayN/ServiceLib/Resx/ResUI.ru.resx +++ b/v2rayN/ServiceLib/Resx/ResUI.ru.resx @@ -1668,4 +1668,7 @@ The "Get Certificate" action may fail if a self-signed certificate is used or if Port hopping interval + + Configuration item preview + \ No newline at end of file diff --git a/v2rayN/ServiceLib/Resx/ResUI.zh-Hans.resx b/v2rayN/ServiceLib/Resx/ResUI.zh-Hans.resx index f17495fd..c8936668 100644 --- a/v2rayN/ServiceLib/Resx/ResUI.zh-Hans.resx +++ b/v2rayN/ServiceLib/Resx/ResUI.zh-Hans.resx @@ -1665,4 +1665,7 @@ 端口跳跃间隔 + + 子配置项预览 + \ No newline at end of file diff --git a/v2rayN/ServiceLib/Resx/ResUI.zh-Hant.resx b/v2rayN/ServiceLib/Resx/ResUI.zh-Hant.resx index 160340d1..2ee4dc4f 100644 --- a/v2rayN/ServiceLib/Resx/ResUI.zh-Hant.resx +++ b/v2rayN/ServiceLib/Resx/ResUI.zh-Hant.resx @@ -1665,4 +1665,7 @@ Port hopping interval + + Configuration item preview + \ No newline at end of file diff --git a/v2rayN/ServiceLib/ViewModels/AddGroupServerViewModel.cs b/v2rayN/ServiceLib/ViewModels/AddGroupServerViewModel.cs index c19d218b..6e4d021c 100644 --- a/v2rayN/ServiceLib/ViewModels/AddGroupServerViewModel.cs +++ b/v2rayN/ServiceLib/ViewModels/AddGroupServerViewModel.cs @@ -27,6 +27,8 @@ public class AddGroupServerViewModel : MyReactiveObject public IObservableCollection ChildItemsObs { get; } = new ObservableCollectionExtended(); + public IObservableCollection AllProfilePreviewItemsObs { get; } = new ObservableCollectionExtended(); + //public ReactiveCommand AddCmd { get; } public ReactiveCommand RemoveCmd { get; } @@ -182,6 +184,32 @@ public class AddGroupServerViewModel : MyReactiveObject await Task.CompletedTask; } + private ProtocolExtraItem GetUpdatedProtocolExtra() + { + return SelectedSource.GetProtocolExtra() with + { + ChildItems = + Utils.List2String(ChildItemsObs.Where(s => !s.IndexId.IsNullOrEmpty()).Select(s => s.IndexId).ToList()), + MultipleLoad = PolicyGroupType switch + { + var s when s == ResUI.TbLeastPing => EMultipleLoad.LeastPing, + var s when s == ResUI.TbFallback => EMultipleLoad.Fallback, + var s when s == ResUI.TbRandom => EMultipleLoad.Random, + var s when s == ResUI.TbRoundRobin => EMultipleLoad.RoundRobin, + var s when s == ResUI.TbLeastLoad => EMultipleLoad.LeastLoad, + _ => EMultipleLoad.LeastPing, + }, + SubChildItems = SelectedSubItem?.Id, + Filter = Filter, + }; + } + + public async Task UpdatePreviewList() + { + AllProfilePreviewItemsObs.Clear(); + AllProfilePreviewItemsObs.AddRange(await GroupProfileManager.GetChildProfileItemsByProtocolExtra(GetUpdatedProtocolExtra())); + } + private async Task SaveServerAsync() { var remarks = SelectedSource.Remarks; @@ -202,24 +230,11 @@ public class AddGroupServerViewModel : MyReactiveObject return; } - SelectedSource.SetProtocolExtra(SelectedSource.GetProtocolExtra() with - { - ChildItems = - Utils.List2String(ChildItemsObs.Where(s => !s.IndexId.IsNullOrEmpty()).Select(s => s.IndexId).ToList()), - MultipleLoad = PolicyGroupType switch - { - var s when s == ResUI.TbLeastPing => EMultipleLoad.LeastPing, - var s when s == ResUI.TbFallback => EMultipleLoad.Fallback, - var s when s == ResUI.TbRandom => EMultipleLoad.Random, - var s when s == ResUI.TbRoundRobin => EMultipleLoad.RoundRobin, - var s when s == ResUI.TbLeastLoad => EMultipleLoad.LeastLoad, - _ => EMultipleLoad.LeastPing, - }, - SubChildItems = SelectedSubItem?.Id, - Filter = Filter, - }); + var protocolExtra = GetUpdatedProtocolExtra(); - var hasCycle = await GroupProfileManager.HasCycle(SelectedSource.IndexId, SelectedSource.GetProtocolExtra()); + SelectedSource.SetProtocolExtra(protocolExtra); + + var hasCycle = await GroupProfileManager.HasCycle(SelectedSource.IndexId, protocolExtra); if (hasCycle) { NoticeManager.Instance.Enqueue(string.Format(ResUI.GroupSelfReference, remarks)); diff --git a/v2rayN/v2rayN.Desktop/Views/AddGroupServerWindow.axaml b/v2rayN/v2rayN.Desktop/Views/AddGroupServerWindow.axaml index bb95588d..c036bb03 100644 --- a/v2rayN/v2rayN.Desktop/Views/AddGroupServerWindow.axaml +++ b/v2rayN/v2rayN.Desktop/Views/AddGroupServerWindow.axaml @@ -88,7 +88,10 @@ - + + + + + + + + + + + + + diff --git a/v2rayN/v2rayN.Desktop/Views/AddGroupServerWindow.axaml.cs b/v2rayN/v2rayN.Desktop/Views/AddGroupServerWindow.axaml.cs index 26827350..142f9d6b 100644 --- a/v2rayN/v2rayN.Desktop/Views/AddGroupServerWindow.axaml.cs +++ b/v2rayN/v2rayN.Desktop/Views/AddGroupServerWindow.axaml.cs @@ -16,6 +16,7 @@ public partial class AddGroupServerWindow : WindowBase Loaded += Window_Loaded; btnCancel.Click += (s, e) => Close(); lstChild.SelectionChanged += LstChild_SelectionChanged; + tabControl.SelectionChanged += TabControl_SelectionChanged; ViewModel = new AddGroupServerViewModel(profileItem, UpdateViewHandler); @@ -38,6 +39,10 @@ public partial class AddGroupServerWindow : WindowBase case EConfigType.ProxyChain: Title = ResUI.TbConfigTypeProxyChain; gridPolicyGroup.IsVisible = false; + if (tabControl.Items.Count > 0) + { + tabControl.Items.RemoveAt(0); + } break; } @@ -50,7 +55,6 @@ public partial class AddGroupServerWindow : WindowBase this.Bind(ViewModel, vm => vm.SelectedSubItem, v => v.cmbSubChildItems.SelectedItem).DisposeWith(disposables); this.Bind(ViewModel, vm => vm.Filter, v => v.txtFilter.Text).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); @@ -167,4 +171,29 @@ public partial class AddGroupServerWindow : WindowBase ViewModel.SelectedChildren = lstChild.SelectedItems.Cast().ToList(); } } + + private async void TabControl_SelectionChanged(object? sender, SelectionChangedEventArgs e) + { + try + { + if (e.Source is not TabControl tc) + { + return; + } + if (!(tc.SelectedIndex == tc.Items.Count - 1 && tc.Items.Count > 0)) + { + return; + } + if (ViewModel == null) + { + return; + } + + await ViewModel.UpdatePreviewList(); + } + catch + { + // ignored + } + } } diff --git a/v2rayN/v2rayN/Views/AddGroupServerWindow.xaml b/v2rayN/v2rayN/Views/AddGroupServerWindow.xaml index 841b3d84..baaa0114 100644 --- a/v2rayN/v2rayN/Views/AddGroupServerWindow.xaml +++ b/v2rayN/v2rayN/Views/AddGroupServerWindow.xaml @@ -135,6 +135,7 @@ @@ -272,6 +273,47 @@ + + + + + + + + + + + + diff --git a/v2rayN/v2rayN/Views/AddGroupServerWindow.xaml.cs b/v2rayN/v2rayN/Views/AddGroupServerWindow.xaml.cs index 14f5a7bf..4b1642d2 100644 --- a/v2rayN/v2rayN/Views/AddGroupServerWindow.xaml.cs +++ b/v2rayN/v2rayN/Views/AddGroupServerWindow.xaml.cs @@ -11,6 +11,7 @@ public partial class AddGroupServerWindow PreviewKeyDown += AddGroupServerWindow_PreviewKeyDown; lstChild.SelectionChanged += LstChild_SelectionChanged; menuSelectAllChild.Click += MenuSelectAllChild_Click; + tabControl.SelectionChanged += TabControl_SelectionChanged; ViewModel = new AddGroupServerViewModel(profileItem, UpdateViewHandler); @@ -33,6 +34,10 @@ public partial class AddGroupServerWindow case EConfigType.ProxyChain: Title = ResUI.TbConfigTypeProxyChain; gridPolicyGroup.Visibility = Visibility.Collapsed; + if (tabControl.Items.Count > 0) + { + tabControl.Items.RemoveAt(0); + } break; } @@ -48,6 +53,8 @@ public partial class AddGroupServerWindow 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.OneWayBind(ViewModel, vm => vm.AllProfilePreviewItemsObs, v => v.lstPreviewChild.ItemsSource).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); @@ -148,4 +155,29 @@ public partial class AddGroupServerWindow { lstChild.SelectAll(); } + + private async void TabControl_SelectionChanged(object? sender, System.Windows.Controls.SelectionChangedEventArgs e) + { + try + { + if (e.Source is not System.Windows.Controls.TabControl tc) + { + return; + } + if (!(tc.SelectedIndex == tc.Items.Count - 1 && tc.Items.Count > 0)) + { + return; + } + if (ViewModel == null) + { + return; + } + + await ViewModel.UpdatePreviewList(); + } + catch + { + // ignored + } + } }