mirror of https://github.com/2dust/v2rayN
Add Config Type Filter
parent
f11b46ed37
commit
c9ec34b836
|
@ -20,6 +20,9 @@ public class ProfilesSelectViewModel : MyReactiveObject
|
||||||
private string _serverFilter = string.Empty;
|
private string _serverFilter = string.Empty;
|
||||||
private Dictionary<string, bool> _dicHeaderSort = new();
|
private Dictionary<string, bool> _dicHeaderSort = new();
|
||||||
private string _subIndexId = string.Empty;
|
private string _subIndexId = string.Empty;
|
||||||
|
// ConfigType filter state: default include-mode with all types selected
|
||||||
|
private List<EConfigType> _filterConfigTypes = new();
|
||||||
|
private bool _filterExclude = false;
|
||||||
|
|
||||||
#endregion private prop
|
#endregion private prop
|
||||||
|
|
||||||
|
@ -40,6 +43,20 @@ public class ProfilesSelectViewModel : MyReactiveObject
|
||||||
[Reactive]
|
[Reactive]
|
||||||
public string ServerFilter { get; set; }
|
public string ServerFilter { get; set; }
|
||||||
|
|
||||||
|
// Include/Exclude filter for ConfigType
|
||||||
|
public List<EConfigType> FilterConfigTypes
|
||||||
|
{
|
||||||
|
get => _filterConfigTypes;
|
||||||
|
set => this.RaiseAndSetIfChanged(ref _filterConfigTypes, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Reactive]
|
||||||
|
public bool FilterExclude
|
||||||
|
{
|
||||||
|
get => _filterExclude;
|
||||||
|
set => this.RaiseAndSetIfChanged(ref _filterExclude, value);
|
||||||
|
}
|
||||||
|
|
||||||
#endregion ObservableCollection
|
#endregion ObservableCollection
|
||||||
|
|
||||||
#region Init
|
#region Init
|
||||||
|
@ -61,6 +78,15 @@ public class ProfilesSelectViewModel : MyReactiveObject
|
||||||
y => y != null && _serverFilter != y)
|
y => y != null && _serverFilter != y)
|
||||||
.Subscribe(async c => await ServerFilterChanged(c));
|
.Subscribe(async c => await ServerFilterChanged(c));
|
||||||
|
|
||||||
|
// React to ConfigType filter changes
|
||||||
|
this.WhenAnyValue(x => x.FilterExclude)
|
||||||
|
.Skip(1)
|
||||||
|
.Subscribe(async _ => await RefreshServersBiz());
|
||||||
|
|
||||||
|
this.WhenAnyValue(x => x.FilterConfigTypes)
|
||||||
|
.Skip(1)
|
||||||
|
.Subscribe(async _ => await RefreshServersBiz());
|
||||||
|
|
||||||
#endregion WhenAnyValue && ReactiveCommand
|
#endregion WhenAnyValue && ReactiveCommand
|
||||||
|
|
||||||
#region AppEvents
|
#region AppEvents
|
||||||
|
@ -85,6 +111,17 @@ public class ProfilesSelectViewModel : MyReactiveObject
|
||||||
SelectedProfile = new();
|
SelectedProfile = new();
|
||||||
SelectedSub = new();
|
SelectedSub = new();
|
||||||
|
|
||||||
|
// Default: include mode with all ConfigTypes selected
|
||||||
|
try
|
||||||
|
{
|
||||||
|
FilterExclude = false;
|
||||||
|
FilterConfigTypes = Enum.GetValues(typeof(EConfigType)).Cast<EConfigType>().ToList();
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
FilterConfigTypes = new();
|
||||||
|
}
|
||||||
|
|
||||||
await RefreshSubscriptions();
|
await RefreshSubscriptions();
|
||||||
await RefreshServers();
|
await RefreshServers();
|
||||||
}
|
}
|
||||||
|
@ -258,6 +295,19 @@ public class ProfilesSelectViewModel : MyReactiveObject
|
||||||
TotalUp = t22 == null ? "" : Utils.HumanFy(t22.TotalUp)
|
TotalUp = t22 == null ? "" : Utils.HumanFy(t22.TotalUp)
|
||||||
}).OrderBy(t => t.Sort).ToList();
|
}).OrderBy(t => t.Sort).ToList();
|
||||||
|
|
||||||
|
// Apply ConfigType filter (include or exclude)
|
||||||
|
if (FilterConfigTypes != null && FilterConfigTypes.Count > 0)
|
||||||
|
{
|
||||||
|
if (FilterExclude)
|
||||||
|
{
|
||||||
|
lstModel = lstModel.Where(t => !FilterConfigTypes.Contains(t.ConfigType)).ToList();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
lstModel = lstModel.Where(t => FilterConfigTypes.Contains(t.ConfigType)).ToList();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return lstModel;
|
return lstModel;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -360,4 +410,15 @@ public class ProfilesSelectViewModel : MyReactiveObject
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion Servers && Groups
|
#endregion Servers && Groups
|
||||||
|
|
||||||
|
#region Public API
|
||||||
|
|
||||||
|
// External setter for ConfigType filter
|
||||||
|
public void SetConfigTypeFilter(IEnumerable<EConfigType> types, bool exclude = false)
|
||||||
|
{
|
||||||
|
FilterConfigTypes = types?.Distinct().ToList() ?? new List<EConfigType>();
|
||||||
|
FilterExclude = exclude;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion Public API
|
||||||
}
|
}
|
||||||
|
|
|
@ -72,6 +72,10 @@ public partial class ProfilesSelectWindow : ReactiveWindow<ProfilesSelectViewMod
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Expose ConfigType filter controls to callers
|
||||||
|
public void SetConfigTypeFilter(IEnumerable<EConfigType> types, bool exclude = false)
|
||||||
|
=> ViewModel?.SetConfigTypeFilter(types, exclude);
|
||||||
|
|
||||||
private async Task<bool> UpdateViewHandler(EViewAction action, object? obj)
|
private async Task<bool> UpdateViewHandler(EViewAction action, object? obj)
|
||||||
{
|
{
|
||||||
switch (action)
|
switch (action)
|
||||||
|
|
|
@ -98,6 +98,7 @@ public partial class RoutingRuleDetailsWindow : WindowBase<RoutingRuleDetailsVie
|
||||||
private async void BtnSelectProfile_Click(object? sender, RoutedEventArgs e)
|
private async void BtnSelectProfile_Click(object? sender, RoutedEventArgs e)
|
||||||
{
|
{
|
||||||
var selectWindow = new ProfilesSelectWindow();
|
var selectWindow = new ProfilesSelectWindow();
|
||||||
|
selectWindow.SetConfigTypeFilter(new[] { EConfigType.Custom }, exclude: true);
|
||||||
var result = await selectWindow.ShowDialog<bool?>(this);
|
var result = await selectWindow.ShowDialog<bool?>(this);
|
||||||
if (result == true)
|
if (result == true)
|
||||||
{
|
{
|
||||||
|
|
|
@ -64,6 +64,7 @@ public partial class SubEditWindow : WindowBase<SubEditViewModel>
|
||||||
private async void BtnSelectPrevProfile_Click(object? sender, RoutedEventArgs e)
|
private async void BtnSelectPrevProfile_Click(object? sender, RoutedEventArgs e)
|
||||||
{
|
{
|
||||||
var selectWindow = new ProfilesSelectWindow();
|
var selectWindow = new ProfilesSelectWindow();
|
||||||
|
selectWindow.SetConfigTypeFilter(new[] { EConfigType.Custom }, exclude: true);
|
||||||
var result = await selectWindow.ShowDialog<bool?>(this);
|
var result = await selectWindow.ShowDialog<bool?>(this);
|
||||||
if (result == true)
|
if (result == true)
|
||||||
{
|
{
|
||||||
|
@ -78,6 +79,7 @@ public partial class SubEditWindow : WindowBase<SubEditViewModel>
|
||||||
private async void BtnSelectNextProfile_Click(object? sender, RoutedEventArgs e)
|
private async void BtnSelectNextProfile_Click(object? sender, RoutedEventArgs e)
|
||||||
{
|
{
|
||||||
var selectWindow = new ProfilesSelectWindow();
|
var selectWindow = new ProfilesSelectWindow();
|
||||||
|
selectWindow.SetConfigTypeFilter(new[] { EConfigType.Custom }, exclude: true);
|
||||||
var result = await selectWindow.ShowDialog<bool?>(this);
|
var result = await selectWindow.ShowDialog<bool?>(this);
|
||||||
if (result == true)
|
if (result == true)
|
||||||
{
|
{
|
||||||
|
|
|
@ -66,6 +66,10 @@ public partial class ProfilesSelectWindow
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Expose ConfigType filter controls to callers
|
||||||
|
public void SetConfigTypeFilter(IEnumerable<EConfigType> types, bool exclude = false)
|
||||||
|
=> ViewModel?.SetConfigTypeFilter(types, exclude);
|
||||||
|
|
||||||
#region Event
|
#region Event
|
||||||
|
|
||||||
private async Task<bool> UpdateViewHandler(EViewAction action, object? obj)
|
private async Task<bool> UpdateViewHandler(EViewAction action, object? obj)
|
||||||
|
|
|
@ -93,6 +93,7 @@ public partial class RoutingRuleDetailsWindow
|
||||||
private async void BtnSelectProfile_Click(object sender, RoutedEventArgs e)
|
private async void BtnSelectProfile_Click(object sender, RoutedEventArgs e)
|
||||||
{
|
{
|
||||||
var selectWindow = new ProfilesSelectWindow();
|
var selectWindow = new ProfilesSelectWindow();
|
||||||
|
selectWindow.SetConfigTypeFilter(new[] { EConfigType.Custom }, exclude: true);
|
||||||
if (selectWindow.ShowDialog() == true)
|
if (selectWindow.ShowDialog() == true)
|
||||||
{
|
{
|
||||||
var profile = await selectWindow.ProfileItem;
|
var profile = await selectWindow.ProfileItem;
|
||||||
|
|
|
@ -58,6 +58,7 @@ public partial class SubEditWindow
|
||||||
private async void BtnSelectPrevProfile_Click(object sender, RoutedEventArgs e)
|
private async void BtnSelectPrevProfile_Click(object sender, RoutedEventArgs e)
|
||||||
{
|
{
|
||||||
var selectWindow = new ProfilesSelectWindow();
|
var selectWindow = new ProfilesSelectWindow();
|
||||||
|
selectWindow.SetConfigTypeFilter(new[] { EConfigType.Custom }, exclude: true);
|
||||||
if (selectWindow.ShowDialog() == true)
|
if (selectWindow.ShowDialog() == true)
|
||||||
{
|
{
|
||||||
var profile = await selectWindow.ProfileItem;
|
var profile = await selectWindow.ProfileItem;
|
||||||
|
@ -71,6 +72,7 @@ public partial class SubEditWindow
|
||||||
private async void BtnSelectNextProfile_Click(object sender, RoutedEventArgs e)
|
private async void BtnSelectNextProfile_Click(object sender, RoutedEventArgs e)
|
||||||
{
|
{
|
||||||
var selectWindow = new ProfilesSelectWindow();
|
var selectWindow = new ProfilesSelectWindow();
|
||||||
|
selectWindow.SetConfigTypeFilter(new[] { EConfigType.Custom }, exclude: true);
|
||||||
if (selectWindow.ShowDialog() == true)
|
if (selectWindow.ShowDialog() == true)
|
||||||
{
|
{
|
||||||
var profile = await selectWindow.ProfileItem;
|
var profile = await selectWindow.ProfileItem;
|
||||||
|
|
Loading…
Reference in New Issue