Compare commits

..

4 commits

Author SHA1 Message Date
DHR60
6c1ace9b35
Merge 466cf53d35 into 9c58fec8d4 2025-10-05 14:47:35 +00:00
DHR60
466cf53d35 PreCheck 2025-10-05 22:46:00 +08:00
2dust
9c58fec8d4 Bug fix
Some checks failed
release Linux / build (Release) (push) Has been cancelled
release macOS / build (Release) (push) Has been cancelled
release Windows desktop (Avalonia UI) / build (Release) (push) Has been cancelled
release Windows / build (Release) (push) Has been cancelled
2025-10-05 19:55:52 +08:00
DHR60
11343a30fd
Multi profile (#7929)
* Multi Profile

* VM and wpf

* avalonia

* Fix right click not working

* Exclude specific profile types from selection

* Rename

* Add Policy Group support

* Add generate policy group

* Adjust UI

* Add Proxy Chain support

* Fix

* Add fallback support

* Add PolicyGroup include other Group support

* Add group in traffic splitting support

* Avoid duplicate tags

* Refactor

* Adjust chained proxy, actual outbound is at the top

Based on actual network flow instead of data packets

* Add helper function

* Refactor

* Add chain selection control to group outbounds

* Avoid self-reference

* Fix

* Improves Tun2Socks address handling

* Avoids circular dependency in profile groups

Adds cycle detection to prevent infinite loops when evaluating profile groups.

This ensures that profile group configurations don't result in stack overflow errors when groups reference each other, directly or indirectly.

* Fix

* Fix

* Update ProfileGroupItem.cs

* Refactor

* Remove unnecessary checks

---------

Co-authored-by: 2dust <31833384+2dust@users.noreply.github.com>
2025-10-05 16:27:34 +08:00

View file

@ -186,27 +186,37 @@ public class ProfileGroupItemManager
visited.Add(indexId); visited.Add(indexId);
stack.Add(indexId); stack.Add(indexId);
Instance.TryGet(indexId, out var groupItem); try
if (groupItem == null || groupItem.ChildItems.IsNullOrEmpty())
{ {
Instance.TryGet(indexId, out var groupItem);
if (groupItem == null || groupItem.ChildItems.IsNullOrEmpty())
{
return false;
}
var childIds = Utils.String2List(groupItem.ChildItems)
.Where(p => !string.IsNullOrEmpty(p))
.ToList();
if (childIds == null)
{
return false;
}
foreach (var child in childIds)
{
if (HasCycle(child, visited, stack))
{
return true;
}
}
return false; return false;
} }
finally
var childIds = Utils.String2List(groupItem.ChildItems)
.Where(p => !string.IsNullOrEmpty(p))
.ToList();
foreach (var child in childIds)
{ {
if (HasCycle(child, visited, stack)) stack.Remove(indexId);
{
return true;
}
} }
stack.Remove(indexId);
return false;
} }
public static async Task<(List<ProfileItem> Items, ProfileGroupItem? Group)> GetChildProfileItems(string? indexId) public static async Task<(List<ProfileItem> Items, ProfileGroupItem? Group)> GetChildProfileItems(string? indexId)