Merge pull request #243 from SlimeNull/main

更改一点点离谱代码, 顺便按照 issue 中的意见, 添加了双击切换 proxy 的简单逻辑
This commit is contained in:
2dust
2023-02-22 20:17:55 +08:00
committed by GitHub
14 changed files with 64 additions and 83 deletions

View File

@@ -4,45 +4,26 @@ namespace ClashN.Base
{ {
static class StringEx static class StringEx
{ {
public static bool IsNullOrEmpty(this string value) public static bool BeginWithAny(this string? s, IEnumerable<char> chars)
{ {
return string.IsNullOrEmpty(value); if (string.IsNullOrEmpty(s))
} return false;
public static bool IsNullOrWhiteSpace(this string value)
{
return string.IsNullOrWhiteSpace(value);
}
public static bool BeginWithAny(this string s, IEnumerable<char> chars)
{
if (s.IsNullOrEmpty()) return false;
return chars.Contains(s[0]); return chars.Contains(s[0]);
} }
public static bool IsWhiteSpace(this string value)
{
foreach (char c in value)
{
if (char.IsWhiteSpace(c)) continue;
return false;
}
return true;
}
public static IEnumerable<string> NonWhiteSpaceLines(this TextReader reader) public static IEnumerable<string> NonWhiteSpaceLines(this TextReader reader)
{ {
string line; string? line;
while ((line = reader.ReadLine()) != null) while ((line = reader.ReadLine()) != null)
{ {
if (line.IsWhiteSpace()) continue; if (string.IsNullOrWhiteSpace(line))
continue;
yield return line; yield return line;
} }
} }
public static string TrimEx(this string value) public static string TrimEx(this string? value)
{ {
return value == null ? string.Empty : value.Trim(); return value == null ? string.Empty : value.Trim();
} }

View File

@@ -1,5 +1,6 @@
using ClashN.Mode; using ClashN.Mode;
using ClashN.Tool; using ClashN.Tool;
using System.Collections.Specialized;
using System.IO; using System.IO;
using System.Web; using System.Web;
@@ -93,9 +94,7 @@ namespace ClashN.Handler
config.ConstItem.defIEProxyExceptions = Global.IEProxyExceptions; config.ConstItem.defIEProxyExceptions = Global.IEProxyExceptions;
} }
if (config == null if (config.ProfileItems.Count <= 0)
|| config.ProfileItems.Count <= 0
)
{ {
Global.reloadCore = false; Global.reloadCore = false;
} }
@@ -114,7 +113,7 @@ namespace ClashN.Handler
} }
} }
LazyConfig.Instance.SetConfig(ref config); LazyConfig.Instance.SetConfig(config);
return 0; return 0;
} }
/// <summary> /// <summary>
@@ -262,7 +261,7 @@ namespace ClashN.Handler
} }
return -1; return -1;
} }
public static ProfileItem GetDefaultProfile(ref Config config) public static ProfileItem? GetDefaultProfile(ref Config config)
{ {
if (config.ProfileItems.Count <= 0) if (config.ProfileItems.Count <= 0)
{ {
@@ -571,13 +570,15 @@ namespace ClashN.Handler
Uri url = new Uri(clipboardData); Uri url = new Uri(clipboardData);
if (url.Host == "install-config") if (url.Host == "install-config")
{ {
var query = HttpUtility.ParseQueryString(url.Query); NameValueCollection query =
HttpUtility.ParseQueryString(url.Query);
if (!string.IsNullOrEmpty(query["url"] ?? "")) if (!string.IsNullOrEmpty(query["url"] ?? ""))
{ {
ProfileItem item = new ProfileItem() ProfileItem item = new ProfileItem()
{ {
groupId = groupId, groupId = groupId,
url = query["url"], url = query["url"] ?? string.Empty,
coreType = CoreKind.ClashMeta, coreType = CoreKind.ClashMeta,
address = string.Empty, address = string.Empty,
enabled = true, enabled = true,
@@ -613,15 +614,12 @@ namespace ClashN.Handler
else else
{ return -1; } { return -1; }
ProfileItem profileItem; ProfileItem? profileItem = null;
if (!string.IsNullOrEmpty(indexId)) if (!string.IsNullOrEmpty(indexId))
{
profileItem = config.GetProfileItem(indexId); profileItem = config.GetProfileItem(indexId);
}
else if (profileItem == null)
{
profileItem = new ProfileItem(); profileItem = new ProfileItem();
}
profileItem.groupId = groupId; profileItem.groupId = groupId;
if (AddProfileViaContent(ref config, profileItem, clipboardData) == 0) if (AddProfileViaContent(ref config, profileItem, clipboardData) == 0)

View File

@@ -70,7 +70,7 @@ namespace ClashN.Handler
/// DownloadString /// DownloadString
/// </summary> /// </summary>
/// <param name="url"></param> /// <param name="url"></param>
public async Task<(string, HttpResponseHeaders)> DownloadStringAsync(string url, bool blProxy, string userAgent) public async Task<(string, HttpResponseHeaders)?> DownloadStringAsync(string url, bool blProxy, string userAgent)
{ {
try try
{ {
@@ -108,10 +108,11 @@ namespace ClashN.Handler
Error?.Invoke(this, new ErrorEventArgs(ex.InnerException)); Error?.Invoke(this, new ErrorEventArgs(ex.InnerException));
} }
} }
return (null, null);
return null;
} }
public async Task<string> UrlRedirectAsync(string url, bool blProxy) public async Task<string?> UrlRedirectAsync(string url, bool blProxy)
{ {
Utils.SetSecurityProtocol(LazyConfig.Instance.Config.EnableSecurityProtocolTls13); Utils.SetSecurityProtocol(LazyConfig.Instance.Config.EnableSecurityProtocolTls13);
SocketsHttpHandler webRequestHandler = new SocketsHttpHandler SocketsHttpHandler webRequestHandler = new SocketsHttpHandler
@@ -124,7 +125,7 @@ namespace ClashN.Handler
HttpResponseMessage response = await client.GetAsync(url); HttpResponseMessage response = await client.GetAsync(url);
if (response.StatusCode.ToString() == "Redirect") if (response.StatusCode.ToString() == "Redirect")
{ {
return response.Headers.Location.ToString(); return response.Headers.Location?.ToString();
} }
else else
{ {

View File

@@ -15,7 +15,7 @@ namespace ClashN.Handler
{ {
get { return _instance.Value; } get { return _instance.Value; }
} }
public void SetConfig(ref Config config) public void SetConfig(Config config)
{ {
_config = config; _config = config;
} }

View File

@@ -218,10 +218,10 @@ namespace ClashN.Handler
{ {
_updateFunc(false, $"{hashCode}{args.GetException().Message}"); _updateFunc(false, $"{hashCode}{args.GetException().Message}");
}; };
var result = await downloadHandle.DownloadStringAsync(url, blProxy, userAgent); var result = (await downloadHandle.DownloadStringAsync(url, blProxy, userAgent)) ?? throw new Exception();
if (blProxy && string.IsNullOrEmpty(result.Item1)) if (blProxy && string.IsNullOrEmpty(result.Item1))
{ {
result = await downloadHandle.DownloadStringAsync(url, false, userAgent); result = (await downloadHandle.DownloadStringAsync(url, false, userAgent)) ?? throw new Exception();
} }
if (string.IsNullOrEmpty(result.Item1)) if (string.IsNullOrEmpty(result.Item1))

View File

@@ -74,12 +74,11 @@ namespace ClashN.Mode
return ProfileItems.FindIndex(it => it.indexId == id); return ProfileItems.FindIndex(it => it.indexId == id);
} }
public ProfileItem GetProfileItem(string id) public ProfileItem? GetProfileItem(string id)
{ {
if (string.IsNullOrEmpty(id)) if (string.IsNullOrEmpty(id))
{
return null; return null;
}
return ProfileItems.FirstOrDefault(it => it.indexId == id); return ProfileItems.FirstOrDefault(it => it.indexId == id);
} }
@@ -160,7 +159,7 @@ namespace ClashN.Mode
public bool colorModeDark { get; set; } public bool colorModeDark { get; set; }
public string? colorPrimaryName { get; set; } public string? colorPrimaryName { get; set; }
public string currentFontFamily { get; set; } public string currentFontFamily { get; set; } = string.Empty;
public int currentFontSize { get; set; } public int currentFontSize { get; set; }
public int proxiesSorting { get; set; } public int proxiesSorting { get; set; }
@@ -174,21 +173,9 @@ namespace ClashN.Mode
[Serializable] [Serializable]
public class ConstItem public class ConstItem
{ {
public string subConvertUrl public string subConvertUrl { get; set; } = string.Empty;
{ public string speedTestUrl { get; set; } = string.Empty;
get; set; public string speedPingTestUrl { get; set; } = string.Empty;
} public string defIEProxyExceptions { get; set; } = string.Empty;
public string speedTestUrl
{
get; set;
}
public string speedPingTestUrl
{
get; set;
}
public string defIEProxyExceptions
{
get; set;
}
} }
} }

View File

@@ -50,7 +50,7 @@ namespace ClashN.ViewModels
var canEditRemove = this.WhenAnyValue( var canEditRemove = this.WhenAnyValue(
x => x.SelectedSource, x => x.SelectedSource,
selectedSource => selectedSource != null && !selectedSource.id.IsNullOrEmpty()); selectedSource => selectedSource != null && !string.IsNullOrEmpty(selectedSource.id));
this.WhenAnyValue( this.WhenAnyValue(
x => x.SortingSelected, x => x.SortingSelected,
@@ -144,7 +144,7 @@ namespace ClashN.ViewModels
model.id = item.Id; model.id = item.Id;
model.network = item.metadata.Network; model.network = item.metadata.Network;
model.type = item.metadata.Type; model.type = item.metadata.Type;
model.host = $"{(item.metadata.Host.IsNullOrEmpty() ? item.metadata.DestinationIP : item.metadata.Host)}:{item.metadata.DestinationPort}"; model.host = $"{(string.IsNullOrEmpty(item.metadata.Host) ? item.metadata.DestinationIP : item.metadata.Host)}:{item.metadata.DestinationPort}";
var sp = (dtNow - item.start); var sp = (dtNow - item.start);
model.time = sp.TotalSeconds < 0 ? 1 : sp.TotalSeconds; model.time = sp.TotalSeconds < 0 ? 1 : sp.TotalSeconds;
model.upload = item.upload; model.upload = item.upload;

View File

@@ -460,7 +460,7 @@ namespace ClashN.ViewModels
{ {
ModifyTheme(_config.UiItem.colorModeDark); ModifyTheme(_config.UiItem.colorModeDark);
if (!_config.UiItem.colorPrimaryName.IsNullOrEmpty()) if (!string.IsNullOrEmpty(_config.UiItem.colorPrimaryName))
{ {
var swatch = new SwatchesProvider().Swatches.FirstOrDefault(t => t.Name == _config.UiItem.colorPrimaryName); var swatch = new SwatchesProvider().Swatches.FirstOrDefault(t => t.Name == _config.UiItem.colorPrimaryName);
if (swatch != null if (swatch != null

View File

@@ -34,7 +34,7 @@ namespace ClashN.ViewModels
_noticeHandler = Locator.Current.GetService<NoticeHandler>(); _noticeHandler = Locator.Current.GetService<NoticeHandler>();
_config = LazyConfig.Instance.Config; _config = LazyConfig.Instance.Config;
if (profileItem.indexId.IsNullOrEmpty()) if (string.IsNullOrEmpty(profileItem.indexId))
{ {
SelectedSource = profileItem; SelectedSource = profileItem;
} }

View File

@@ -59,7 +59,7 @@ namespace ClashN.ViewModels
var canEditRemove = this.WhenAnyValue( var canEditRemove = this.WhenAnyValue(
x => x.SelectedSource, x => x.SelectedSource,
selectedSource => selectedSource != null && !selectedSource.indexId.IsNullOrEmpty()); selectedSource => selectedSource != null && !string.IsNullOrEmpty(selectedSource.indexId));
//Profile //Profile
EditLocalFileCmd = ReactiveCommand.Create(() => EditLocalFileCmd = ReactiveCommand.Create(() =>

View File

@@ -65,7 +65,7 @@ namespace ClashN.ViewModels
//GetClashProxies(true); //GetClashProxies(true);
this.WhenAnyValue( this.WhenAnyValue(
x => x.SelectedGroup, x => x.SelectedGroup,
y => y != null && !y.name.IsNullOrEmpty()) y => y != null && !string.IsNullOrEmpty(y.name))
.Subscribe(c => RefreshProxyDetails(c)); .Subscribe(c => RefreshProxyDetails(c));
this.WhenAnyValue( this.WhenAnyValue(
@@ -268,7 +268,7 @@ namespace ClashN.ViewModels
continue; continue;
} }
var item = _proxyGroups.Where(t => t.name == kv.Key).FirstOrDefault(); var item = _proxyGroups.Where(t => t.name == kv.Key).FirstOrDefault();
if (item != null && !item.name.IsNullOrEmpty()) if (item != null && !string.IsNullOrEmpty(item.name))
{ {
continue; continue;
} }
@@ -379,11 +379,11 @@ namespace ClashN.ViewModels
public void SetActiveProxy() public void SetActiveProxy()
{ {
if (SelectedGroup == null || SelectedGroup.name.IsNullOrEmpty()) if (SelectedGroup == null || string.IsNullOrEmpty(SelectedGroup.name))
{ {
return; return;
} }
if (SelectedDetail == null || SelectedDetail.name.IsNullOrEmpty()) if (SelectedDetail == null || string.IsNullOrEmpty(SelectedDetail.name))
{ {
return; return;
} }

View File

@@ -141,7 +141,7 @@ namespace ClashN.ViewModels
//UI //UI
ColorModeDark = _config.UiItem.colorModeDark; ColorModeDark = _config.UiItem.colorModeDark;
_swatches.AddRange(new SwatchesProvider().Swatches); _swatches.AddRange(new SwatchesProvider().Swatches);
if (!_config.UiItem.colorPrimaryName.IsNullOrEmpty()) if (!string.IsNullOrEmpty(_config.UiItem.colorPrimaryName))
{ {
SelectedSwatch = _swatches.FirstOrDefault(t => t.Name == _config.UiItem.colorPrimaryName); SelectedSwatch = _swatches.FirstOrDefault(t => t.Name == _config.UiItem.colorPrimaryName);
} }
@@ -163,11 +163,11 @@ namespace ClashN.ViewModels
this.WhenAnyValue( this.WhenAnyValue(
x => x.SelectedSwatch, x => x.SelectedSwatch,
y => y != null && !y.Name.IsNullOrEmpty()) y => y != null && !string.IsNullOrEmpty(y.Name))
.Subscribe(c => .Subscribe(c =>
{ {
if (SelectedSwatch == null if (SelectedSwatch == null
|| SelectedSwatch.Name.IsNullOrEmpty() || string.IsNullOrEmpty(SelectedSwatch.Name)
|| SelectedSwatch.ExemplarHue == null || SelectedSwatch.ExemplarHue == null
|| SelectedSwatch.ExemplarHue?.Color == null) || SelectedSwatch.ExemplarHue?.Color == null)
{ {
@@ -183,7 +183,7 @@ namespace ClashN.ViewModels
this.WhenAnyValue( this.WhenAnyValue(
x => x.CurrentLanguage, x => x.CurrentLanguage,
y => y != null && !y.IsNullOrEmpty()) y => y != null && !string.IsNullOrEmpty(y))
.Subscribe(c => .Subscribe(c =>
{ {
if (!string.IsNullOrEmpty(CurrentLanguage)) if (!string.IsNullOrEmpty(CurrentLanguage))

View File

@@ -163,7 +163,7 @@
</ListView.ItemsPanel> </ListView.ItemsPanel>
<ListView.ItemTemplate> <ListView.ItemTemplate>
<DataTemplate> <DataTemplate>
<Border Width="160" Padding="0"> <Border Width="160" Padding="0" KeyDown="ProxyItem_KeyDown">
<DockPanel> <DockPanel>
<Border <Border
Width="5" Width="5"

View File

@@ -43,15 +43,29 @@ namespace ClashN.Views
private void ProxiesView_KeyDown(object sender, KeyEventArgs e) private void ProxiesView_KeyDown(object sender, KeyEventArgs e)
{ {
if (Keyboard.IsKeyDown(Key.F5)) switch (e.Key)
{ {
ViewModel?.ProxiesReload(); case Key.F5:
ViewModel?.ProxiesReload();
break;
case Key.Enter:
ViewModel?.SetActiveProxy();
break;
} }
else if (Keyboard.IsKeyDown(Key.Enter)) }
private object? lastProxyItemKeyDownSender;
private int lastProxyItemKeyDownTimestamp;
private void ProxyItem_KeyDown(object sender, KeyEventArgs e)
{
if (sender == lastProxyItemKeyDownSender && e.Timestamp - lastProxyItemKeyDownTimestamp < 500)
{ {
ViewModel?.SetActiveProxy(); ViewModel?.SetActiveProxy();
} }
lastProxyItemKeyDownSender = sender;
lastProxyItemKeyDownTimestamp = e.Timestamp;
} }
} }
} }