Compare commits

..

19 commits

Author SHA1 Message Date
DHR60
d99daac318 PreCheck 2025-09-12 17:29:36 +08:00
DHR60
8c1d48f2d0 Avoid duplicate tags 2025-09-12 17:29:36 +08:00
DHR60
54fcbafe2a Add group in traffic splitting support 2025-09-12 17:29:36 +08:00
DHR60
05e598e5fa Add PolicyGroup include other Group support 2025-09-12 17:29:36 +08:00
DHR60
f11707011d Add fallback support 2025-09-12 17:29:36 +08:00
DHR60
2482e599cc Fix 2025-09-12 17:29:24 +08:00
DHR60
1ff017ee4d Add Proxy Chain support 2025-09-12 16:37:10 +08:00
DHR60
db3c1a1f15 Adjust UI 2025-09-12 16:37:10 +08:00
DHR60
ed6ddefcd9 Add generate policy group 2025-09-12 16:37:10 +08:00
DHR60
2f3fcb2584 Add Policy Group support 2025-09-12 16:37:10 +08:00
DHR60
25845f79a2 Rename 2025-09-12 16:37:10 +08:00
DHR60
b31f02511a Exclude specific profile types from selection 2025-09-12 16:37:10 +08:00
DHR60
8e44e202ca Fix right click not working 2025-09-12 16:37:10 +08:00
DHR60
b8d40c1d05 avalonia 2025-09-12 16:37:10 +08:00
DHR60
68027332fe VM and wpf 2025-09-12 16:37:10 +08:00
DHR60
3a89be9ddd Multi Profile 2025-09-12 16:37:10 +08:00
DHR60
c20d5b3208 Add global fakeip and fakeip filter 2025-09-12 16:37:10 +08:00
DHR60
54e83391d0
Pre-resolve to apply hosts (#7937) 2025-09-12 16:28:31 +08:00
JieXu
3e0578f775
Update CheckUpdateViewModel.cs (#7932)
* Update CheckUpdateViewModel.cs

* Update Utils.cs

* Update Utils.cs

* Update Utils.cs

* Update CheckUpdateViewModel.cs

* Update CheckUpdateViewModel.cs

* Update Utils.cs
2025-09-12 16:24:59 +08:00
7 changed files with 132 additions and 27 deletions

View file

@ -331,6 +331,32 @@ public class Utils
.ToList(); .ToList();
} }
public static Dictionary<string, List<string>> ParseHostsToDictionary(string hostsContent)
{
var userHostsMap = hostsContent
.Split(new[] { '\r', '\n' }, StringSplitOptions.RemoveEmptyEntries)
.Select(line => line.Trim())
// skip full-line comments
.Where(line => !string.IsNullOrWhiteSpace(line) && !line.StartsWith("#"))
// strip inline comments (truncate at '#')
.Select(line =>
{
var index = line.IndexOf('#');
return index >= 0 ? line.Substring(0, index).Trim() : line;
})
// ensure line still contains valid parts
.Where(line => !string.IsNullOrWhiteSpace(line) && line.Contains(' '))
.Select(line => line.Split(new[] { ' ', '\t' }, StringSplitOptions.RemoveEmptyEntries))
.Where(parts => parts.Length >= 2)
.GroupBy(parts => parts[0])
.ToDictionary(
group => group.Key,
group => group.SelectMany(parts => parts.Skip(1)).ToList()
);
return userHostsMap;
}
#endregion #endregion
#region #region
@ -857,6 +883,55 @@ public class Utils
return false; return false;
} }
public static bool IsPackagedInstall()
{
try
{
if (IsWindows() || IsOSX())
{
return false;
}
if (!string.IsNullOrEmpty(Environment.GetEnvironmentVariable("APPIMAGE")))
{
return true;
}
var exePath = GetExePath();
var baseDir = string.IsNullOrEmpty(exePath) ? StartupPath() : Path.GetDirectoryName(exePath) ?? "";
var p = baseDir.Replace('\\', '/');
if (string.IsNullOrEmpty(p))
{
return false;
}
if (p.Contains("/.mount_", StringComparison.Ordinal))
{
return true;
}
if (p.StartsWith("/opt/v2rayN", StringComparison.OrdinalIgnoreCase))
{
return true;
}
if (p.StartsWith("/usr/lib/v2rayN", StringComparison.OrdinalIgnoreCase))
{
return true;
}
if (p.StartsWith("/usr/share/v2rayN", StringComparison.OrdinalIgnoreCase))
{
return true;
}
}
catch
{
}
return false;
}
private static async Task<string?> GetLinuxUserId() private static async Task<string?> GetLinuxUserId()
{ {
var arg = new List<string>() { "-c", "id -u" }; var arg = new List<string>() { "-c", "id -u" };

View file

@ -103,17 +103,7 @@ public partial class CoreConfigSingboxService
if (!simpleDNSItem.Hosts.IsNullOrEmpty()) if (!simpleDNSItem.Hosts.IsNullOrEmpty())
{ {
var userHostsMap = simpleDNSItem.Hosts var userHostsMap = Utils.ParseHostsToDictionary(simpleDNSItem.Hosts);
.Split(new[] { '\r', '\n' }, StringSplitOptions.RemoveEmptyEntries)
.Select(line => line.Trim())
.Where(line => !string.IsNullOrWhiteSpace(line) && line.Contains(' '))
.Select(line => line.Split(new[] { ' ', '\t' }, StringSplitOptions.RemoveEmptyEntries))
.Where(parts => parts.Length >= 2)
.GroupBy(parts => parts[0])
.ToDictionary(
group => group.Key,
group => group.SelectMany(parts => parts.Skip(1)).ToList()
);
foreach (var kvp in userHostsMap) foreach (var kvp in userHostsMap)
{ {

View file

@ -71,6 +71,31 @@ public partial class CoreConfigSingboxService
}); });
} }
var hostsDomains = new List<string>();
var systemHostsMap = Utils.GetSystemHosts();
foreach (var kvp in systemHostsMap)
{
hostsDomains.Add(kvp.Key);
}
var dnsItem = await AppManager.Instance.GetDNSItem(ECoreType.sing_box);
if (dnsItem == null || dnsItem.Enabled == false)
{
var simpleDNSItem = _config.SimpleDNSItem;
if (!simpleDNSItem.Hosts.IsNullOrEmpty())
{
var userHostsMap = Utils.ParseHostsToDictionary(simpleDNSItem.Hosts);
foreach (var kvp in userHostsMap)
{
hostsDomains.Add(kvp.Key);
}
}
}
singboxConfig.route.rules.Add(new()
{
action = "resolve",
domain = hostsDomains,
});
singboxConfig.route.rules.Add(new() singboxConfig.route.rules.Add(new()
{ {
outbound = Global.DirectTag, outbound = Global.DirectTag,

View file

@ -261,17 +261,7 @@ public partial class CoreConfigV2rayService
if (!simpleDNSItem.Hosts.IsNullOrEmpty()) if (!simpleDNSItem.Hosts.IsNullOrEmpty())
{ {
var userHostsMap = simpleDNSItem.Hosts var userHostsMap = Utils.ParseHostsToDictionary(simpleDNSItem.Hosts);
.Split(new[] { '\r', '\n' }, StringSplitOptions.RemoveEmptyEntries)
.Select(line => line.Trim())
.Where(line => !string.IsNullOrWhiteSpace(line) && line.Contains(' '))
.Select(line => line.Split(new[] { ' ', '\t' }, StringSplitOptions.RemoveEmptyEntries))
.Where(parts => parts.Length >= 2)
.GroupBy(parts => parts[0])
.ToDictionary(
group => group.Key,
group => group.SelectMany(parts => parts.Skip(1)).ToList()
);
foreach (var kvp in userHostsMap) foreach (var kvp in userHostsMap)
{ {

View file

@ -39,26 +39,30 @@ public class AddGroupServerViewModel : MyReactiveObject
_config = AppManager.Instance.Config; _config = AppManager.Instance.Config;
_updateView = updateView; _updateView = updateView;
var canEditRemove = this.WhenAnyValue(
x => x.SelectedChild,
SelectedChild => SelectedChild != null && !SelectedChild.Remarks.IsNullOrEmpty());
RemoveCmd = ReactiveCommand.CreateFromTask(async () => RemoveCmd = ReactiveCommand.CreateFromTask(async () =>
{ {
await ChildRemoveAsync(); await ChildRemoveAsync();
}); }, canEditRemove);
MoveTopCmd = ReactiveCommand.CreateFromTask(async () => MoveTopCmd = ReactiveCommand.CreateFromTask(async () =>
{ {
await MoveServer(EMove.Top); await MoveServer(EMove.Top);
}); }, canEditRemove);
MoveUpCmd = ReactiveCommand.CreateFromTask(async () => MoveUpCmd = ReactiveCommand.CreateFromTask(async () =>
{ {
await MoveServer(EMove.Up); await MoveServer(EMove.Up);
}); }, canEditRemove);
MoveDownCmd = ReactiveCommand.CreateFromTask(async () => MoveDownCmd = ReactiveCommand.CreateFromTask(async () =>
{ {
await MoveServer(EMove.Down); await MoveServer(EMove.Down);
}); }, canEditRemove);
MoveBottomCmd = ReactiveCommand.CreateFromTask(async () => MoveBottomCmd = ReactiveCommand.CreateFromTask(async () =>
{ {
await MoveServer(EMove.Bottom); await MoveServer(EMove.Bottom);
}); }, canEditRemove);
SaveCmd = ReactiveCommand.CreateFromTask(async () => SaveCmd = ReactiveCommand.CreateFromTask(async () =>
{ {
await SaveServerAsync(); await SaveServerAsync();

View file

@ -63,6 +63,16 @@ public class CheckUpdateViewModel : MyReactiveObject
private CheckUpdateModel GetCheckUpdateModel(string coreType) private CheckUpdateModel GetCheckUpdateModel(string coreType)
{ {
if (coreType == _v2rayN && Utils.IsPackagedInstall())
{
return new()
{
IsSelected = false,
CoreType = coreType,
Remarks = ResUI.menuCheckUpdate + " (Not Support)",
};
}
return new() return new()
{ {
IsSelected = _config.CheckUpdateItem.SelectedCoreTypes?.Contains(coreType) ?? true, IsSelected = _config.CheckUpdateItem.SelectedCoreTypes?.Contains(coreType) ?? true,
@ -104,6 +114,11 @@ public class CheckUpdateViewModel : MyReactiveObject
} }
else if (item.CoreType == _v2rayN) else if (item.CoreType == _v2rayN)
{ {
if (Utils.IsPackagedInstall())
{
await UpdateView(_v2rayN, "Not Support");
continue;
}
await CheckUpdateN(EnableCheckPreReleaseUpdate); await CheckUpdateN(EnableCheckPreReleaseUpdate);
} }
else if (item.CoreType == ECoreType.Xray.ToString()) else if (item.CoreType == ECoreType.Xray.ToString())

View file

@ -16,6 +16,7 @@ public partial class AddGroupServerWindow
this.Loaded += Window_Loaded; this.Loaded += Window_Loaded;
this.PreviewKeyDown += AddGroupServerWindow_PreviewKeyDown; this.PreviewKeyDown += AddGroupServerWindow_PreviewKeyDown;
lstChild.SelectionChanged += LstChild_SelectionChanged; lstChild.SelectionChanged += LstChild_SelectionChanged;
menuSelectAllChild.Click += MenuSelectAllChild_Click;
ViewModel = new AddGroupServerViewModel(profileItem, UpdateViewHandler); ViewModel = new AddGroupServerViewModel(profileItem, UpdateViewHandler);
@ -138,4 +139,9 @@ public partial class AddGroupServerWindow
ViewModel.SelectedChildren = lstChild.SelectedItems.Cast<ProfileItem>().ToList(); ViewModel.SelectedChildren = lstChild.SelectedItems.Cast<ProfileItem>().ToList();
} }
} }
private void MenuSelectAllChild_Click(object sender, RoutedEventArgs e)
{
lstChild.SelectAll();
}
} }