mirror of
https://github.com/2dust/v2rayN.git
synced 2026-10-31 01:24:59 +03:00
Lock sing-box max version (#10091)
* Refactor Semantic Version * Lock max version * Allow sing-box update to pre-release
This commit is contained in:
@@ -229,6 +229,7 @@ public sealed class CoreInfoManager
|
|||||||
DownloadUrlLinuxLoong64 = urlSingbox + "/download/{0}/sing-box-{1}-linux-loong64.tar.gz",
|
DownloadUrlLinuxLoong64 = urlSingbox + "/download/{0}/sing-box-{1}-linux-loong64.tar.gz",
|
||||||
DownloadUrlOSX64 = urlSingbox + "/download/{0}/sing-box-{1}-darwin-amd64.tar.gz",
|
DownloadUrlOSX64 = urlSingbox + "/download/{0}/sing-box-{1}-darwin-amd64.tar.gz",
|
||||||
DownloadUrlOSXArm64 = urlSingbox + "/download/{0}/sing-box-{1}-darwin-arm64.tar.gz",
|
DownloadUrlOSXArm64 = urlSingbox + "/download/{0}/sing-box-{1}-darwin-arm64.tar.gz",
|
||||||
|
LockedMaxVersion = new SemanticVersion(1, 14, int.MaxValue),
|
||||||
Match = "sing-box",
|
Match = "sing-box",
|
||||||
VersionArg = "version",
|
VersionArg = "version",
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -16,6 +16,7 @@ public class CoreInfo
|
|||||||
public string? DownloadUrlLinuxLoong64 { get; set; }
|
public string? DownloadUrlLinuxLoong64 { get; set; }
|
||||||
public string? DownloadUrlOSX64 { get; set; }
|
public string? DownloadUrlOSX64 { get; set; }
|
||||||
public string? DownloadUrlOSXArm64 { get; set; }
|
public string? DownloadUrlOSXArm64 { get; set; }
|
||||||
|
public SemanticVersion? LockedMaxVersion { get; set; }
|
||||||
public string? Match { get; set; }
|
public string? Match { get; set; }
|
||||||
public string? VersionArg { get; set; }
|
public string? VersionArg { get; set; }
|
||||||
public bool AbsolutePath { get; set; }
|
public bool AbsolutePath { get; set; }
|
||||||
|
|||||||
@@ -1,18 +1,20 @@
|
|||||||
namespace ServiceLib.Models.Dto;
|
namespace ServiceLib.Models.Dto;
|
||||||
|
|
||||||
public class SemanticVersion
|
public class SemanticVersion : IEquatable<SemanticVersion>, IComparable
|
||||||
{
|
{
|
||||||
|
private readonly string? build;
|
||||||
private readonly int major;
|
private readonly int major;
|
||||||
private readonly int minor;
|
private readonly int minor;
|
||||||
private readonly int patch;
|
private readonly int patch;
|
||||||
private readonly string version;
|
private readonly string? prerelease;
|
||||||
|
private readonly string raw;
|
||||||
|
|
||||||
public SemanticVersion(int major, int minor, int patch)
|
public SemanticVersion(int major, int minor, int patch)
|
||||||
{
|
{
|
||||||
this.major = major;
|
this.major = major;
|
||||||
this.minor = minor;
|
this.minor = minor;
|
||||||
this.patch = patch;
|
this.patch = patch;
|
||||||
version = $"{major}.{minor}.{patch}";
|
raw = $"{major}.{minor}.{patch}";
|
||||||
}
|
}
|
||||||
|
|
||||||
public SemanticVersion(string? version)
|
public SemanticVersion(string? version)
|
||||||
@@ -24,26 +26,41 @@ public class SemanticVersion
|
|||||||
major = 0;
|
major = 0;
|
||||||
minor = 0;
|
minor = 0;
|
||||||
patch = 0;
|
patch = 0;
|
||||||
|
raw = $"{major}.{minor}.{patch}";
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
this.version = version.RemovePrefix('v');
|
raw = version;
|
||||||
|
|
||||||
var parts = this.version.Split('.');
|
var span = version.StartsWith("v", StringComparison.OrdinalIgnoreCase)
|
||||||
if (parts.Length == 2)
|
? version.AsSpan(1)
|
||||||
|
: version.AsSpan();
|
||||||
|
var plusIdx = span.IndexOf('+');
|
||||||
|
var metadataSpan = plusIdx >= 0 ? span[(plusIdx + 1)..] : [];
|
||||||
|
var leftOfPlus = plusIdx >= 0 ? span[..plusIdx] : span;
|
||||||
|
var dashIdx = leftOfPlus.IndexOf('-');
|
||||||
|
var versionSpan = dashIdx >= 0 ? leftOfPlus[..dashIdx] : leftOfPlus;
|
||||||
|
var preReleaseSpan = dashIdx >= 0 ? leftOfPlus[(dashIdx + 1)..] : [];
|
||||||
|
|
||||||
|
build = metadataSpan.Length > 0 ? metadataSpan.ToString() : null;
|
||||||
|
prerelease = preReleaseSpan.Length > 0 ? preReleaseSpan.ToString() : null;
|
||||||
|
|
||||||
|
var parts = versionSpan.ToString().Split('.');
|
||||||
|
switch (parts.Length)
|
||||||
{
|
{
|
||||||
major = int.Parse(parts.First());
|
case 2:
|
||||||
minor = int.Parse(parts.Last());
|
major = int.Parse(parts.First());
|
||||||
patch = 0;
|
minor = int.Parse(parts.Last());
|
||||||
}
|
patch = 0;
|
||||||
else if (parts.Length is 3 or 4)
|
break;
|
||||||
{
|
|
||||||
major = int.Parse(parts[0]);
|
case 3 or 4:
|
||||||
minor = int.Parse(parts[1]);
|
major = int.Parse(parts[0]);
|
||||||
patch = int.Parse(parts[2]);
|
minor = int.Parse(parts[1]);
|
||||||
}
|
patch = int.Parse(parts[2]);
|
||||||
else
|
break;
|
||||||
{
|
|
||||||
throw new ArgumentException("Invalid version string");
|
default:
|
||||||
|
throw new ArgumentException("Invalid version string");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch
|
catch
|
||||||
@@ -51,135 +68,186 @@ public class SemanticVersion
|
|||||||
major = 0;
|
major = 0;
|
||||||
minor = 0;
|
minor = 0;
|
||||||
patch = 0;
|
patch = 0;
|
||||||
|
raw = $"{major}.{minor}.{patch}";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool Equals(SemanticVersion? other)
|
||||||
|
{
|
||||||
|
if (other is null)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (ReferenceEquals(this, other))
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return major == other.major && minor == other.minor && patch == other.patch && prerelease == other.prerelease;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static bool TryParse(string? version, out SemanticVersion? result)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
result = new SemanticVersion(version);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
result = null;
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public override bool Equals(object? obj)
|
public override bool Equals(object? obj)
|
||||||
{
|
{
|
||||||
if (obj is SemanticVersion other)
|
return obj is SemanticVersion other && Equals(other);
|
||||||
{
|
|
||||||
return major == other.major && minor == other.minor && patch == other.patch;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public override int GetHashCode()
|
public override int GetHashCode()
|
||||||
{
|
{
|
||||||
return major.GetHashCode() ^ minor.GetHashCode() ^ patch.GetHashCode();
|
return HashCode.Combine(major, minor, patch, prerelease);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Use ToVersionString(string? prefix) instead if possible.
|
|
||||||
/// </summary>
|
|
||||||
/// <returns>major.minor.patch</returns>
|
|
||||||
public override string ToString()
|
public override string ToString()
|
||||||
{
|
{
|
||||||
return version;
|
return raw;
|
||||||
}
|
}
|
||||||
|
|
||||||
public string ToVersionString(string? prefix = null)
|
public string ToStandardVersionString(string? prefix = null)
|
||||||
{
|
{
|
||||||
if (prefix == null)
|
var sb = new StringBuilder();
|
||||||
|
if (!string.IsNullOrEmpty(prefix))
|
||||||
{
|
{
|
||||||
return version;
|
sb.Append(prefix);
|
||||||
}
|
}
|
||||||
else
|
sb.Append($"{major}.{minor}.{patch}");
|
||||||
|
if (!string.IsNullOrEmpty(prerelease))
|
||||||
{
|
{
|
||||||
return $"{prefix}{version}";
|
sb.Append($"-{prerelease}");
|
||||||
}
|
}
|
||||||
|
if (!string.IsNullOrEmpty(build))
|
||||||
|
{
|
||||||
|
sb.Append($"+{build}");
|
||||||
|
}
|
||||||
|
return sb.ToString();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static bool operator ==(SemanticVersion v1, SemanticVersion v2)
|
public static bool operator <(SemanticVersion left, SemanticVersion right)
|
||||||
{ return v1.Equals(v2); }
|
{
|
||||||
|
return left.CompareTo(right) < 0;
|
||||||
|
}
|
||||||
|
|
||||||
public static bool operator !=(SemanticVersion v1, SemanticVersion v2)
|
public static bool operator >(SemanticVersion left, SemanticVersion right)
|
||||||
{ return !v1.Equals(v2); }
|
{
|
||||||
|
return left.CompareTo(right) > 0;
|
||||||
|
}
|
||||||
|
|
||||||
public static bool operator >=(SemanticVersion v1, SemanticVersion v2)
|
public static bool operator <=(SemanticVersion left, SemanticVersion right)
|
||||||
{ return v1.GreaterEquals(v2); }
|
{
|
||||||
|
return left.CompareTo(right) <= 0;
|
||||||
|
}
|
||||||
|
|
||||||
public static bool operator <=(SemanticVersion v1, SemanticVersion v2)
|
public static bool operator >=(SemanticVersion left, SemanticVersion right)
|
||||||
{ return v1.LessEquals(v2); }
|
{
|
||||||
|
return left.CompareTo(right) >= 0;
|
||||||
|
}
|
||||||
|
|
||||||
#region Private
|
#region Private
|
||||||
|
|
||||||
private bool GreaterEquals(SemanticVersion other)
|
public int CompareTo(SemanticVersion other)
|
||||||
{
|
{
|
||||||
if (major < other.major)
|
if (major != other.major)
|
||||||
{
|
{
|
||||||
return false;
|
return major.CompareTo(other.major);
|
||||||
}
|
}
|
||||||
else if (major > other.major)
|
if (minor != other.minor)
|
||||||
{
|
{
|
||||||
return true;
|
return minor.CompareTo(other.minor);
|
||||||
}
|
}
|
||||||
else
|
if (patch != other.patch)
|
||||||
{
|
{
|
||||||
if (minor < other.minor)
|
return patch.CompareTo(other.patch);
|
||||||
|
}
|
||||||
|
return ComparePreRelease(prerelease, other.prerelease);
|
||||||
|
}
|
||||||
|
|
||||||
|
public int CompareTo(object? obj)
|
||||||
|
{
|
||||||
|
if (obj is null)
|
||||||
|
{
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
if (obj is SemanticVersion other)
|
||||||
|
{
|
||||||
|
return CompareTo(other);
|
||||||
|
}
|
||||||
|
throw new ArgumentException("Object is not a SemanticVersion");
|
||||||
|
}
|
||||||
|
|
||||||
|
private static int ComparePreRelease(string? left, string? right)
|
||||||
|
{
|
||||||
|
if (string.IsNullOrEmpty(left) && string.IsNullOrEmpty(right))
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if (string.IsNullOrEmpty(left))
|
||||||
|
{
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
if (string.IsNullOrEmpty(right))
|
||||||
|
{
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
var leftSpan = left.AsSpan();
|
||||||
|
var rightSpan = right.AsSpan();
|
||||||
|
using var leftEnum = leftSpan.Split('.').GetEnumerator();
|
||||||
|
using var rightEnum = rightSpan.Split('.').GetEnumerator();
|
||||||
|
|
||||||
|
while (true)
|
||||||
|
{
|
||||||
|
var hasLeft = leftEnum.MoveNext();
|
||||||
|
var hasRight = rightEnum.MoveNext();
|
||||||
|
|
||||||
|
if (!hasLeft && !hasRight)
|
||||||
{
|
{
|
||||||
return false;
|
return 0;
|
||||||
}
|
}
|
||||||
else if (minor > other.minor)
|
if (!hasLeft)
|
||||||
{
|
{
|
||||||
return true;
|
return -1;
|
||||||
}
|
}
|
||||||
else
|
if (!hasRight)
|
||||||
{
|
{
|
||||||
if (patch < other.patch)
|
return 1;
|
||||||
{
|
}
|
||||||
return false;
|
|
||||||
}
|
var leftSegment = leftSpan[leftEnum.Current];
|
||||||
else if (patch > other.patch)
|
var rightSegment = rightSpan[rightEnum.Current];
|
||||||
{
|
|
||||||
return true;
|
var segCmp = CompareSegment(leftSegment, rightSegment);
|
||||||
}
|
if (segCmp != 0)
|
||||||
else
|
{
|
||||||
{
|
return segCmp;
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private bool LessEquals(SemanticVersion other)
|
private static int CompareSegment(ReadOnlySpan<char> left, ReadOnlySpan<char> right)
|
||||||
{
|
{
|
||||||
if (major < other.major)
|
var leftIsNum = ulong.TryParse(left, out var leftNum);
|
||||||
|
var rightIsNum = ulong.TryParse(right, out var rightNum);
|
||||||
|
|
||||||
|
return (leftIsNum, rightIsNum) switch
|
||||||
{
|
{
|
||||||
return true;
|
(true, true) => leftNum.CompareTo(rightNum),
|
||||||
}
|
|
||||||
else if (major > other.major)
|
(false, true) => 1,
|
||||||
{
|
(true, false) => -1,
|
||||||
return false;
|
|
||||||
}
|
(false, false) => left.SequenceCompareTo(right),
|
||||||
else
|
};
|
||||||
{
|
|
||||||
if (minor < other.minor)
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
else if (minor > other.minor)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (patch < other.patch)
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
else if (patch > other.patch)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion Private
|
#endregion Private
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
namespace ServiceLib.Services;
|
namespace ServiceLib.Services;
|
||||||
|
|
||||||
public class UpdateService(Config config, Func<bool, string, Task> updateFunc)
|
public partial class UpdateService(Config config, Func<bool, string, Task> updateFunc)
|
||||||
{
|
{
|
||||||
private readonly Config? _config = config;
|
private readonly Config? _config = config;
|
||||||
private readonly Func<bool, string, Task>? _updateFunc = updateFunc;
|
private readonly Func<bool, string, Task>? _updateFunc = updateFunc;
|
||||||
@@ -174,7 +174,7 @@ public class UpdateService(Config config, Func<bool, string, Task> updateFunc)
|
|||||||
{
|
{
|
||||||
var coreInfo = CoreInfoManager.Instance.GetCoreInfo(type);
|
var coreInfo = CoreInfoManager.Instance.GetCoreInfo(type);
|
||||||
var tagName = string.Empty;
|
var tagName = string.Empty;
|
||||||
if (preRelease)
|
if (preRelease || coreInfo?.LockedMaxVersion != null)
|
||||||
{
|
{
|
||||||
var url = coreInfo?.ReleaseApiUrl;
|
var url = coreInfo?.ReleaseApiUrl;
|
||||||
var result = await downloadHandle.TryDownloadString(url, true, Global.AppName);
|
var result = await downloadHandle.TryDownloadString(url, true, Global.AppName);
|
||||||
@@ -187,6 +187,24 @@ public class UpdateService(Config config, Func<bool, string, Task> updateFunc)
|
|||||||
var gitHubRelease = preRelease ? gitHubReleases?.First() : gitHubReleases?.First(r => r.Prerelease == false);
|
var gitHubRelease = preRelease ? gitHubReleases?.First() : gitHubReleases?.First(r => r.Prerelease == false);
|
||||||
tagName = gitHubRelease?.TagName;
|
tagName = gitHubRelease?.TagName;
|
||||||
//var body = gitHubRelease?.Body;
|
//var body = gitHubRelease?.Body;
|
||||||
|
|
||||||
|
if (coreInfo?.LockedMaxVersion != null)
|
||||||
|
{
|
||||||
|
var lockedMaxVersion = coreInfo.LockedMaxVersion;
|
||||||
|
var remoteVersion = new SemanticVersion(tagName);
|
||||||
|
if (remoteVersion > lockedMaxVersion)
|
||||||
|
{
|
||||||
|
var fallbackRelease = gitHubReleases?
|
||||||
|
.Where(r => preRelease || !r.Prerelease)
|
||||||
|
.Select(r => new { Release = r, IsValid = SemanticVersion.TryParse(r.TagName, out var v), Version = v })
|
||||||
|
.Where(x => x.IsValid && x.Version <= coreInfo.LockedMaxVersion)
|
||||||
|
.MaxBy(x => x.Version)?
|
||||||
|
.Release;
|
||||||
|
|
||||||
|
gitHubRelease = fallbackRelease;
|
||||||
|
tagName = gitHubRelease?.TagName;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -202,6 +220,9 @@ public class UpdateService(Config config, Func<bool, string, Task> updateFunc)
|
|||||||
return new UpdateResult(true, new SemanticVersion(tagName));
|
return new UpdateResult(true, new SemanticVersion(tagName));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[GeneratedRegex(@"v?(?<version>\d+\.\d+\.\d+(?:-[0-9a-zA-Z.-]+)?(?:\+[0-9a-zA-Z.-]+)?)", RegexOptions.IgnoreCase)]
|
||||||
|
private static partial Regex SemVerRegex();
|
||||||
|
|
||||||
private async Task<SemanticVersion> GetCoreVersion(ECoreType type)
|
private async Task<SemanticVersion> GetCoreVersion(ECoreType type)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
@@ -227,23 +248,7 @@ public class UpdateService(Config config, Func<bool, string, Task> updateFunc)
|
|||||||
|
|
||||||
var result = await Utils.GetCliWrapOutput(filePath, coreInfo.VersionArg);
|
var result = await Utils.GetCliWrapOutput(filePath, coreInfo.VersionArg);
|
||||||
var echo = result ?? "";
|
var echo = result ?? "";
|
||||||
var version = string.Empty;
|
var version = SemVerRegex().Match(echo).Groups["version"].Value;
|
||||||
switch (type)
|
|
||||||
{
|
|
||||||
case ECoreType.v2fly:
|
|
||||||
case ECoreType.Xray:
|
|
||||||
case ECoreType.v2fly_v5:
|
|
||||||
version = Regex.Match(echo, $"{coreInfo.Match} ([0-9.]+) \\(").Groups[1].Value;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case ECoreType.mihomo:
|
|
||||||
version = Regex.Match(echo, $"v[0-9.]+").Groups[0].Value;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case ECoreType.sing_box:
|
|
||||||
version = Regex.Match(echo, $"([0-9.]+)").Groups[1].Value;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
return new SemanticVersion(version);
|
return new SemanticVersion(version);
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
@@ -269,30 +274,25 @@ public class UpdateService(Config config, Func<bool, string, Task> updateFunc)
|
|||||||
case ECoreType.v2fly:
|
case ECoreType.v2fly:
|
||||||
case ECoreType.Xray:
|
case ECoreType.Xray:
|
||||||
case ECoreType.v2fly_v5:
|
case ECoreType.v2fly_v5:
|
||||||
{
|
|
||||||
curVersion = await GetCoreVersion(type);
|
|
||||||
message = string.Format(ResUI.IsLatestCore, type, curVersion.ToVersionString("v"));
|
|
||||||
url = string.Format(coreUrl, version.ToVersionString("v"));
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case ECoreType.mihomo:
|
case ECoreType.mihomo:
|
||||||
{
|
{
|
||||||
curVersion = await GetCoreVersion(type);
|
curVersion = await GetCoreVersion(type);
|
||||||
message = string.Format(ResUI.IsLatestCore, type, curVersion);
|
message = string.Format(ResUI.IsLatestCore, type, curVersion.ToStandardVersionString("v"));
|
||||||
url = string.Format(coreUrl, version.ToVersionString("v"));
|
url = string.Format(coreUrl, version);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case ECoreType.sing_box:
|
case ECoreType.sing_box:
|
||||||
{
|
{
|
||||||
curVersion = await GetCoreVersion(type);
|
curVersion = await GetCoreVersion(type);
|
||||||
message = string.Format(ResUI.IsLatestCore, type, curVersion.ToVersionString("v"));
|
message = string.Format(ResUI.IsLatestCore, type, curVersion.ToStandardVersionString("v"));
|
||||||
url = string.Format(coreUrl, version.ToVersionString("v"), version);
|
url = string.Format(coreUrl, version, version.ToString().RemovePrefix("v"));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case ECoreType.v2rayN:
|
case ECoreType.v2rayN:
|
||||||
{
|
{
|
||||||
curVersion = new SemanticVersion(Utils.GetVersionInfo());
|
curVersion = new SemanticVersion(Utils.GetVersionInfo());
|
||||||
message = string.Format(ResUI.IsLatestN, type, curVersion);
|
message = string.Format(ResUI.IsLatestN, type, curVersion.ToStandardVersionString("v"));
|
||||||
url = string.Format(coreUrl, version);
|
url = string.Format(coreUrl, version);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -300,7 +300,7 @@ public class UpdateService(Config config, Func<bool, string, Task> updateFunc)
|
|||||||
throw new ArgumentException("Type");
|
throw new ArgumentException("Type");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (curVersion >= version && version != new SemanticVersion(0, 0, 0))
|
if (curVersion >= version && !version.Equals(new SemanticVersion(0, 0, 0)))
|
||||||
{
|
{
|
||||||
return new UpdateResult(false, message);
|
return new UpdateResult(false, message);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -193,7 +193,7 @@ public partial class CheckUpdateViewModel : MyReactiveObject
|
|||||||
}
|
}
|
||||||
await CheckUpdateN(EnableCheckPreReleaseUpdate);
|
await CheckUpdateN(EnableCheckPreReleaseUpdate);
|
||||||
}
|
}
|
||||||
else if (item.CoreType == ECoreType.Xray)
|
else if (item.CoreType is ECoreType.Xray or ECoreType.sing_box)
|
||||||
{
|
{
|
||||||
await CheckUpdateCore(item, EnableCheckPreReleaseUpdate);
|
await CheckUpdateCore(item, EnableCheckPreReleaseUpdate);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user