Merge pull request #243 from SlimeNull/main
更改一点点离谱代码, 顺便按照 issue 中的意见, 添加了双击切换 proxy 的简单逻辑
This commit is contained in:
@@ -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();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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)
|
||||||
|
|||||||
@@ -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
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -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;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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))
|
||||||
|
|||||||
@@ -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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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(() =>
|
||||||
|
|||||||
@@ -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;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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))
|
||||||
|
|||||||
@@ -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"
|
||||||
|
|||||||
@@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user