改了一堆屎山代码

This commit is contained in:
SlimeNull
2023-02-17 20:21:29 +08:00
parent 4409a891df
commit 95d90d6fd4
41 changed files with 648 additions and 710 deletions

View File

@@ -1,4 +1,4 @@
# clashN # ClashN
A clash client for Windows, supports [Clash core](https://github.com/Dreamacro/clash) and [Clash.Meta core](https://github.com/MetaCubeX/Clash.Meta) A clash client for Windows, supports [Clash core](https://github.com/Dreamacro/clash) and [Clash.Meta core](https://github.com/MetaCubeX/Clash.Meta)
[![GitHub commit activity](https://img.shields.io/github/commit-activity/m/2dust/clashn)](https://github.com/2dust/clashn/commits/master) [![GitHub commit activity](https://img.shields.io/github/commit-activity/m/2dust/clashn)](https://github.com/2dust/clashn/commits/master)
@@ -6,14 +6,30 @@ A clash client for Windows, supports [Clash core](https://github.com/Dreamacro/c
### How to use ### How to use
- Please download clashN.zip from [releases](https://github.com/2dust/clashN/releases) 1. Download `clashN.zip` from [releases](https://github.com/2dust/clashN/releases)
- Unzip to folder 2. Unzip to any folder you want
- Run clashN.exe 3. Run ClashN.exe
### Tips
- You can also add `v2ray` subscription to `ClashN`, just enable `Subcription conversion` when you add a profile.
### Requirements ### Requirements
- Microsoft [.NET 6.0 Desktop Runtime](https://dotnet.microsoft.com/zh-cn/download/dotnet/6.0/runtime) (or download this file directly: [windowsdesktop-runtime-6.0.9-win-x64.exe](https://download.visualstudio.microsoft.com/download/pr/fe8415d4-8a35-4af9-80a5-51306a96282d/05f9b2a1b4884238e69468e49b3a5453/windowsdesktop-runtime-6.0.9-win-x64.exe)) - Microsoft [.NET 6.0 Desktop Runtime](https://dotnet.microsoft.com/zh-cn/download/dotnet/6.0/runtime) (or download this file directly: [windowsdesktop-runtime-6.0.9-win-x64.exe](https://download.visualstudio.microsoft.com/download/pr/fe8415d4-8a35-4af9-80a5-51306a96282d/05f9b2a1b4884238e69468e49b3a5453/windowsdesktop-runtime-6.0.9-win-x64.exe))
- Clash core [https://github.com/Dreamacro/clash/releases](https://github.com/Dreamacro/clash/releases) - Clash core [https://github.com/Dreamacro/clash/releases](https://github.com/Dreamacro/clash/releases)
- Clash.Meta core [https://github.com/MetaCubeX/Clash.Meta/releases](https://github.com/MetaCubeX/Clash.Meta/releases) - Clash.Meta core [https://github.com/MetaCubeX/Clash.Meta/releases](https://github.com/MetaCubeX/Clash.Meta/releases)
### Telegram Channel ### Telegram Channel
[github_2dust](https://t.me/github_2dust) [github_2dust](https://t.me/github_2dust)
### Contribute
To build this project, you should clone both '[ClashN](https://github.com/2dust/clashN)' and '[v2rayN]([2dust/v2rayN: A V2Ray client for Windows, support Xray core and v2fly core (github.com)](https://github.com/2dust/v2rayN))' to the same folder

View File

@@ -11,8 +11,21 @@ namespace ClashN
/// </summary> /// </summary>
public partial class App : Application public partial class App : Application
{ {
public static EventWaitHandle ProgramStarted; public static EventWaitHandle? ProgramStarted;
private static Config _config; private Config? _config;
static App()
{
ProgramStarted = new EventWaitHandle(false, EventResetMode.AutoReset, "ProgramStartedEvent", out bool bCreatedNew);
if (!bCreatedNew)
{
ProgramStarted.Set();
App.Current.Shutdown();
Environment.Exit(-1);
return;
}
}
public App() public App()
{ {
// Locator.CurrentMutable.RegisterViewsForViewModels(Assembly.GetCallingAssembly()); // Locator.CurrentMutable.RegisterViewsForViewModels(Assembly.GetCallingAssembly());
@@ -34,14 +47,6 @@ namespace ClashN
Utils.SetClipboardData(arg); Utils.SetClipboardData(arg);
} }
ProgramStarted = new EventWaitHandle(false, EventResetMode.AutoReset, "ProgramStartedEvent", out bool bCreatedNew);
if (!bCreatedNew)
{
ProgramStarted.Set();
App.Current.Shutdown();
Environment.Exit(-1);
return;
}
Global.processJob = new Job(); Global.processJob = new Job();
Logging.Setup(); Logging.Setup();
@@ -58,7 +63,7 @@ namespace ClashN
private void Init() private void Init()
{ {
if (ConfigHandler.LoadConfig(ref _config) != 0) if (ConfigProc.LoadConfig(ref _config) != 0)
{ {
UI.ShowWarning($"Loading GUI configuration file is abnormal,please restart the application{Environment.NewLine}加载GUI配置文件异常,请重启应用"); UI.ShowWarning($"Loading GUI configuration file is abnormal,please restart the application{Environment.NewLine}加载GUI配置文件异常,请重启应用");
Application.Current.Shutdown(); Application.Current.Shutdown();
@@ -80,7 +85,7 @@ namespace ClashN
} }
} }
private void TaskScheduler_UnobservedTaskException(object sender, UnobservedTaskExceptionEventArgs e) private void TaskScheduler_UnobservedTaskException(object? sender, UnobservedTaskExceptionEventArgs e)
{ {
Utils.SaveLog("TaskScheduler_UnobservedTaskException", e.Exception); Utils.SaveLog("TaskScheduler_UnobservedTaskException", e.Exception);
} }

View File

@@ -14,7 +14,13 @@ namespace ClashN.Base
/// <summary> /// <summary>
/// </summary> /// </summary>
private HttpClientHelper() { } private HttpClientHelper()
{
httpClient = new HttpClient(new HttpClientHandler()
{
UseCookies = false
});
}
/// <summary> /// <summary>
/// </summary> /// </summary>
@@ -34,26 +40,26 @@ namespace ClashN.Base
return httpClientHelper; return httpClientHelper;
} }
} }
public async Task<string> GetAsync(string url)
public async Task<string?> TryGetAsync(string url)
{ {
if (Utils.IsNullOrEmpty(url)) if (string.IsNullOrEmpty(url))
{
return null; return null;
}
try try
{ {
HttpResponseMessage response = await httpClient.GetAsync(url); HttpResponseMessage response = await httpClient.GetAsync(url);
return await response.Content.ReadAsStringAsync(); return await response.Content.ReadAsStringAsync();
} }
catch catch
{ {
return null;
} }
return null;
} }
public async Task<(string, HttpResponseHeaders)> GetAsync(HttpClient client, string url, CancellationToken token) public async Task<(string, HttpResponseHeaders)> GetAsync(HttpClient client, string url, CancellationToken token)
{ {
if (Utils.IsNullOrEmpty(url)) if (string.IsNullOrEmpty(url))
{ {
return (null, null); return (null, null);
} }
@@ -97,77 +103,63 @@ namespace ClashN.Base
public async Task DownloadFileAsync(HttpClient client, string url, string fileName, IProgress<double> progress, CancellationToken token) public async Task DownloadFileAsync(HttpClient client, string url, string fileName, IProgress<double> progress, CancellationToken token)
{ {
if (Utils.IsNullOrEmpty(url)) if (string.IsNullOrEmpty(url))
{ throw new ArgumentNullException(nameof(url));
throw new ArgumentNullException("url"); if (string.IsNullOrEmpty(fileName))
} throw new ArgumentNullException(nameof(fileName));
if (Utils.IsNullOrEmpty(fileName))
{
throw new ArgumentNullException("fileName");
}
if (File.Exists(fileName))
{
File.Delete(fileName);
}
var response = await client.GetAsync(url, HttpCompletionOption.ResponseHeadersRead, token); HttpResponseMessage response =
await client.GetAsync(url, HttpCompletionOption.ResponseHeadersRead, token);
if (!response.IsSuccessStatusCode) if (!response.IsSuccessStatusCode)
{
throw new Exception(string.Format("The request returned with HTTP status code {0}", response.StatusCode)); throw new Exception(string.Format("The request returned with HTTP status code {0}", response.StatusCode));
}
var total = response.Content.Headers.ContentLength.HasValue ? response.Content.Headers.ContentLength.Value : -1L; var total = response.Content.Headers.ContentLength.HasValue ? response.Content.Headers.ContentLength.Value : -1L;
var canReportProgress = total != -1 && progress != null; var canReportProgress = total != -1 && progress != null;
using (var stream = await response.Content.ReadAsStreamAsync()) using var stream = await response.Content.ReadAsStreamAsync();
using var file = File.Create(fileName);
var totalRead = 0L;
var buffer = new byte[1024 * 1024];
var isMoreToRead = true;
progressPercentage = -1;
do
{ {
using (var file = File.Create(fileName)) token.ThrowIfCancellationRequested();
var read = await stream.ReadAsync(buffer, 0, buffer.Length, token);
if (read == 0)
{ {
var totalRead = 0L; isMoreToRead = false;
var buffer = new byte[1024 * 1024]; }
var isMoreToRead = true; else
progressPercentage = -1; {
var data = new byte[read];
buffer.ToList().CopyTo(0, data, 0, read);
do // TODO: put here the code to write the file to disk
{ file.Write(data, 0, read);
token.ThrowIfCancellationRequested();
var read = await stream.ReadAsync(buffer, 0, buffer.Length, token); totalRead += read;
if (read == 0)
{
isMoreToRead = false;
}
else
{
var data = new byte[read];
buffer.ToList().CopyTo(0, data, 0, read);
// TODO: put here the code to write the file to disk
file.Write(data, 0, read);
totalRead += read;
if (canReportProgress)
{
var percent = Convert.ToInt32((totalRead * 1d) / (total * 1d) * 100);
if (progressPercentage != percent && percent % 10 == 0)
{
progressPercentage = percent;
progress.Report(percent);
}
}
}
} while (isMoreToRead);
file.Close();
if (canReportProgress) if (canReportProgress)
{ {
progress.Report(101); var percent = Convert.ToInt32((totalRead * 1d) / (total * 1d) * 100);
if (progressPercentage != percent && percent % 10 == 0)
{
progressPercentage = percent;
progress?.Report(percent);
}
} }
} }
} } while (isMoreToRead);
if (canReportProgress)
progress?.Report(101);
} }
} }
} }

View File

@@ -11,7 +11,7 @@ namespace ClashN.Converters
{ {
try try
{ {
var fontFamily = LazyConfig.Instance.GetConfig().uiItem.currentFontFamily; var fontFamily = LazyConfig.Instance.Config.UiItem.currentFontFamily;
if (!string.IsNullOrEmpty(fontFamily)) if (!string.IsNullOrEmpty(fontFamily))
{ {
var fontPath = Utils.GetFontsPath(); var fontPath = Utils.GetFontsPath();

View File

@@ -8,7 +8,7 @@ namespace ClashN.Handler
/// <summary> /// <summary>
/// 本软件配置文件处理类 /// 本软件配置文件处理类
/// </summary> /// </summary>
class ConfigHandler class ConfigProc
{ {
private static string configRes = Global.ConfigFileName; private static string configRes = Global.ConfigFileName;
private static readonly object objLock = new object(); private static readonly object objLock = new object();
@@ -20,11 +20,11 @@ namespace ClashN.Handler
/// </summary> /// </summary>
/// <param name="config"></param> /// <param name="config"></param>
/// <returns></returns> /// <returns></returns>
public static int LoadConfig(ref Config config) public static int LoadConfig(ref Config? config)
{ {
//载入配置文件 //载入配置文件
string result = Utils.LoadResource(Utils.GetConfigPath(configRes)); string result = Utils.LoadResource(Utils.GetConfigPath(configRes));
if (!Utils.IsNullOrEmpty(result)) if (!string.IsNullOrEmpty(result))
{ {
//转成Json //转成Json
config = Utils.FromJson<Config>(result); config = Utils.FromJson<Config>(result);
@@ -42,71 +42,59 @@ namespace ClashN.Handler
{ {
config = new Config config = new Config
{ {
logLevel = "warning", LogLevel = "warning",
profileItems = new List<ProfileItem>(), EnableStatistics = true,
enableStatistics = true,
}; };
} }
//本地监听 //本地监听
if (config.mixedPort == 0) if (config.MixedPort == 0)
{ config.MixedPort = 7888;
config.mixedPort = 7888;
} if (config.HttpPort == 0)
if (config.httpPort == 0) config.HttpPort = 7890;
{
config.httpPort = 7890; if (config.SocksPort == 0)
} config.SocksPort = 7891;
if (config.socksPort == 0)
{ if (config.ApiPort == 0)
config.socksPort = 7891; config.ApiPort = 9090;
}
if (config.APIPort == 0)
{
config.APIPort = 9090;
}
if (config.PacPort == 0) if (config.PacPort == 0)
{ {
config.PacPort = 7990; config.PacPort = 7990;
} }
if (config.profileItems == null) if (config.UiItem == null)
{ {
config.profileItems = new List<ProfileItem>(); config.UiItem = new UIItem()
}
if (config.uiItem == null)
{
config.uiItem = new UIItem()
{ {
}; };
} }
if (config.constItem == null) if (config.ConstItem == null)
{ {
config.constItem = new ConstItem(); config.ConstItem = new ConstItem();
} }
//if (Utils.IsNullOrEmpty(config.constItem.subConvertUrl)) //if (string.IsNullOrEmpty(config.constItem.subConvertUrl))
//{ //{
// config.constItem.subConvertUrl = Global.SubConvertUrl; // config.constItem.subConvertUrl = Global.SubConvertUrl;
//} //}
if (Utils.IsNullOrEmpty(config.constItem.speedTestUrl)) if (string.IsNullOrEmpty(config.ConstItem.speedTestUrl))
{ {
config.constItem.speedTestUrl = Global.SpeedTestUrl; config.ConstItem.speedTestUrl = Global.SpeedTestUrl;
} }
if (Utils.IsNullOrEmpty(config.constItem.speedPingTestUrl)) if (string.IsNullOrEmpty(config.ConstItem.speedPingTestUrl))
{ {
config.constItem.speedPingTestUrl = Global.SpeedPingTestUrl; config.ConstItem.speedPingTestUrl = Global.SpeedPingTestUrl;
} }
if (Utils.IsNullOrEmpty(config.constItem.defIEProxyExceptions)) if (string.IsNullOrEmpty(config.ConstItem.defIEProxyExceptions))
{ {
config.constItem.defIEProxyExceptions = Global.IEProxyExceptions; config.ConstItem.defIEProxyExceptions = Global.IEProxyExceptions;
} }
if (config == null if (config == null
|| config.profileItems.Count <= 0 || config.ProfileItems.Count <= 0
) )
{ {
Global.reloadCore = false; Global.reloadCore = false;
@@ -115,11 +103,11 @@ namespace ClashN.Handler
{ {
Global.reloadCore = true; Global.reloadCore = true;
for (int i = 0; i < config.profileItems.Count; i++) for (int i = 0; i < config.ProfileItems.Count; i++)
{ {
ProfileItem profileItem = config.profileItems[i]; ProfileItem profileItem = config.ProfileItems[i];
if (Utils.IsNullOrEmpty(profileItem.indexId)) if (string.IsNullOrEmpty(profileItem.indexId))
{ {
profileItem.indexId = Utils.GetGUID(false); profileItem.indexId = Utils.GetGUID(false);
} }
@@ -134,7 +122,7 @@ namespace ClashN.Handler
/// </summary> /// </summary>
/// <param name="config"></param> /// <param name="config"></param>
/// <returns></returns> /// <returns></returns>
public static int SaveConfig(ref Config config, bool reload = true) public static int SaveConfig(Config config, bool reload = true)
{ {
Global.reloadCore = reload; Global.reloadCore = reload;
@@ -215,7 +203,7 @@ namespace ClashN.Handler
profileItem.indexId = string.Empty; profileItem.indexId = string.Empty;
profileItem.remarks = string.Format("{0}-clone", item.remarks); profileItem.remarks = string.Format("{0}-clone", item.remarks);
if (Utils.IsNullOrEmpty(profileItem.address) || !File.Exists(Utils.GetConfigPath(profileItem.address))) if (string.IsNullOrEmpty(profileItem.address) || !File.Exists(Utils.GetConfigPath(profileItem.address)))
{ {
profileItem.address = string.Empty; profileItem.address = string.Empty;
AddProfileCommon(ref config, profileItem); AddProfileCommon(ref config, profileItem);
@@ -246,7 +234,7 @@ namespace ClashN.Handler
return -1; return -1;
} }
config.indexId = item.indexId; config.IndexId = item.indexId;
Global.reloadCore = true; Global.reloadCore = true;
ToJsonFile(config); ToJsonFile(config);
@@ -256,11 +244,11 @@ namespace ClashN.Handler
public static int SetDefaultProfile(Config config, List<ProfileItem> lstProfile) public static int SetDefaultProfile(Config config, List<ProfileItem> lstProfile)
{ {
if (lstProfile.Exists(t => t.indexId == config.indexId)) if (lstProfile.Exists(t => t.indexId == config.IndexId))
{ {
return 0; return 0;
} }
if (config.profileItems.Exists(t => t.indexId == config.indexId)) if (config.ProfileItems.Exists(t => t.indexId == config.IndexId))
{ {
return 0; return 0;
} }
@@ -268,26 +256,26 @@ namespace ClashN.Handler
{ {
return SetDefaultProfile(ref config, lstProfile[0]); return SetDefaultProfile(ref config, lstProfile[0]);
} }
if (config.profileItems.Count > 0) if (config.ProfileItems.Count > 0)
{ {
return SetDefaultProfile(ref config, config.profileItems[0]); return SetDefaultProfile(ref config, config.ProfileItems[0]);
} }
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)
{ {
return null; return null;
} }
var index = config.FindIndexId(config.indexId); var index = config.FindIndexId(config.IndexId);
if (index < 0) if (index < 0)
{ {
SetDefaultProfile(ref config, config.profileItems[0]); SetDefaultProfile(ref config, config.ProfileItems[0]);
return config.profileItems[0]; return config.ProfileItems[0];
} }
return config.profileItems[index]; return config.ProfileItems[index];
} }
/// <summary> /// <summary>
@@ -297,9 +285,9 @@ namespace ClashN.Handler
/// <param name="index"></param> /// <param name="index"></param>
/// <param name="eMove"></param> /// <param name="eMove"></param>
/// <returns></returns> /// <returns></returns>
public static int MoveProfile(ref Config config, int index, EMove eMove, int pos = -1) public static int MoveProfile(ref Config config, int index, MovementTarget eMove, int pos = -1)
{ {
List<ProfileItem> lstProfile = config.profileItems.OrderBy(it => it.sort).ToList(); List<ProfileItem> lstProfile = config.ProfileItems.OrderBy(it => it.sort).ToList();
int count = lstProfile.Count; int count = lstProfile.Count;
if (index < 0 || index > lstProfile.Count - 1) if (index < 0 || index > lstProfile.Count - 1)
{ {
@@ -313,48 +301,48 @@ namespace ClashN.Handler
switch (eMove) switch (eMove)
{ {
case EMove.Top: case MovementTarget.Top:
{
if (index == 0)
{ {
if (index == 0) return 0;
{
return 0;
}
lstProfile[index].sort = lstProfile[0].sort - 1;
break;
} }
case EMove.Up: lstProfile[index].sort = lstProfile[0].sort - 1;
break;
}
case MovementTarget.Up:
{
if (index == 0)
{ {
if (index == 0) return 0;
{
return 0;
}
lstProfile[index].sort = lstProfile[index - 1].sort - 1;
break;
} }
lstProfile[index].sort = lstProfile[index - 1].sort - 1;
case EMove.Down: break;
}
case MovementTarget.Down:
{
if (index == count - 1)
{ {
if (index == count - 1) return 0;
{
return 0;
}
lstProfile[index].sort = lstProfile[index + 1].sort + 1;
break;
} }
case EMove.Bottom: lstProfile[index].sort = lstProfile[index + 1].sort + 1;
break;
}
case MovementTarget.Bottom:
{
if (index == count - 1)
{ {
if (index == count - 1) return 0;
{
return 0;
}
lstProfile[index].sort = lstProfile[lstProfile.Count - 1].sort + 1;
break;
} }
case EMove.Position: lstProfile[index].sort = lstProfile[lstProfile.Count - 1].sort + 1;
break;
}
case MovementTarget.Position:
lstProfile[index].sort = pos * 10 + 1; lstProfile[index].sort = pos * 10 + 1;
break; break;
} }
@@ -366,19 +354,19 @@ namespace ClashN.Handler
public static int AddProfileViaContent(ref Config config, ProfileItem profileItem, string content) public static int AddProfileViaContent(ref Config config, ProfileItem profileItem, string content)
{ {
if (Utils.IsNullOrEmpty(content)) if (string.IsNullOrEmpty(content))
{ {
return -1; return -1;
} }
string newFileName = profileItem.address; string newFileName = profileItem.address;
if (Utils.IsNullOrEmpty(newFileName)) if (string.IsNullOrEmpty(newFileName))
{ {
var ext = ".yaml"; var ext = ".yaml";
newFileName = string.Format("{0}{1}", Utils.GetGUID(), ext); newFileName = string.Format("{0}{1}", Utils.GetGUID(), ext);
profileItem.address = newFileName; profileItem.address = newFileName;
} }
if (Utils.IsNullOrEmpty(profileItem.remarks)) if (string.IsNullOrEmpty(profileItem.remarks))
{ {
profileItem.remarks = "clash_local_file"; profileItem.remarks = "clash_local_file";
} }
@@ -392,7 +380,7 @@ namespace ClashN.Handler
return -1; return -1;
} }
if (Utils.IsNullOrEmpty(profileItem.remarks)) if (string.IsNullOrEmpty(profileItem.remarks))
{ {
profileItem.remarks = string.Format("import custom@{0}", DateTime.Now.ToShortDateString()); profileItem.remarks = string.Format("import custom@{0}", DateTime.Now.ToShortDateString());
} }
@@ -416,7 +404,7 @@ namespace ClashN.Handler
try try
{ {
File.Copy(fileName, Path.Combine(Utils.GetConfigPath(), newFileName)); File.Copy(fileName, Path.Combine(Utils.GetConfigPath(), newFileName));
if (!Utils.IsNullOrEmpty(profileItem.address)) if (!string.IsNullOrEmpty(profileItem.address))
{ {
File.Delete(Path.Combine(Utils.GetConfigPath(), profileItem.address)); File.Delete(Path.Combine(Utils.GetConfigPath(), profileItem.address));
} }
@@ -427,7 +415,7 @@ namespace ClashN.Handler
} }
profileItem.address = newFileName; profileItem.address = newFileName;
if (Utils.IsNullOrEmpty(profileItem.remarks)) if (string.IsNullOrEmpty(profileItem.remarks))
{ {
profileItem.remarks = string.Format("import custom@{0}", DateTime.Now.ToShortDateString()); profileItem.remarks = string.Format("import custom@{0}", DateTime.Now.ToShortDateString());
} }
@@ -441,7 +429,7 @@ namespace ClashN.Handler
public static int EditProfile(ref Config config, ProfileItem profileItem) public static int EditProfile(ref Config config, ProfileItem profileItem)
{ {
if (!Utils.IsNullOrEmpty(profileItem.indexId) && config.indexId == profileItem.indexId) if (!string.IsNullOrEmpty(profileItem.indexId) && config.IndexId == profileItem.indexId)
{ {
Global.reloadCore = true; Global.reloadCore = true;
} }
@@ -449,7 +437,7 @@ namespace ClashN.Handler
AddProfileCommon(ref config, profileItem); AddProfileCommon(ref config, profileItem);
//TODO auto update via url //TODO auto update via url
//if (!Utils.IsNullOrEmpty(profileItem.url)) //if (!string.IsNullOrEmpty(profileItem.url))
//{ //{
// var httpClient = new HttpClient(); // var httpClient = new HttpClient();
// string result = httpClient.GetStringAsync(profileItem.url).Result; // string result = httpClient.GetStringAsync(profileItem.url).Result;
@@ -502,20 +490,20 @@ namespace ClashN.Handler
public static int AddProfileCommon(ref Config config, ProfileItem profileItem) public static int AddProfileCommon(ref Config config, ProfileItem profileItem)
{ {
if (Utils.IsNullOrEmpty(profileItem.indexId)) if (string.IsNullOrEmpty(profileItem.indexId))
{ {
profileItem.indexId = Utils.GetGUID(false); profileItem.indexId = Utils.GetGUID(false);
} }
if (profileItem.coreType is null) if (profileItem.coreType is null)
{ {
profileItem.coreType = ECoreType.clash_meta; profileItem.coreType = CoreKind.ClashMeta;
} }
if (!config.profileItems.Exists(it => it.indexId == profileItem.indexId)) if (!config.ProfileItems.Exists(it => it.indexId == profileItem.indexId))
{ {
var maxSort = config.profileItems.Any() ? config.profileItems.Max(t => t.sort) : 0; var maxSort = config.ProfileItems.Any() ? config.ProfileItems.Max(t => t.sort) : 0;
profileItem.sort = maxSort++; profileItem.sort = maxSort++;
config.profileItems.Add(profileItem); config.ProfileItems.Add(profileItem);
} }
return 0; return 0;
@@ -525,16 +513,16 @@ namespace ClashN.Handler
{ {
try try
{ {
if (File.Exists(Utils.GetConfigPath(config.profileItems[index].address))) if (File.Exists(Utils.GetConfigPath(config.ProfileItems[index].address)))
{ {
File.Delete(Utils.GetConfigPath(config.profileItems[index].address)); File.Delete(Utils.GetConfigPath(config.ProfileItems[index].address));
} }
} }
catch (Exception ex) catch (Exception ex)
{ {
Utils.SaveLog("RemoveProfileItem", ex); Utils.SaveLog("RemoveProfileItem", ex);
} }
config.profileItems.RemoveAt(index); config.ProfileItems.RemoveAt(index);
return 0; return 0;
} }
@@ -545,7 +533,7 @@ namespace ClashN.Handler
{ {
return string.Empty; return string.Empty;
} }
if (Utils.IsNullOrEmpty(item.address)) if (string.IsNullOrEmpty(item.address))
{ {
return string.Empty; return string.Empty;
} }
@@ -556,19 +544,19 @@ namespace ClashN.Handler
public static int AddBatchProfiles(ref Config config, string clipboardData, string indexId, string groupId) public static int AddBatchProfiles(ref Config config, string clipboardData, string indexId, string groupId)
{ {
if (Utils.IsNullOrEmpty(clipboardData)) if (string.IsNullOrEmpty(clipboardData))
{ {
return -1; return -1;
} }
//maybe url //maybe url
if (Utils.IsNullOrEmpty(indexId) && (clipboardData.StartsWith(Global.httpsProtocol) || clipboardData.StartsWith(Global.httpProtocol))) if (string.IsNullOrEmpty(indexId) && (clipboardData.StartsWith(Global.httpsProtocol) || clipboardData.StartsWith(Global.httpProtocol)))
{ {
ProfileItem item = new ProfileItem() ProfileItem item = new ProfileItem()
{ {
groupId = groupId, groupId = groupId,
url = clipboardData, url = clipboardData,
coreType = ECoreType.clash_meta, coreType = CoreKind.ClashMeta,
address = string.Empty, address = string.Empty,
enabled = true, enabled = true,
remarks = "clash_subscription" remarks = "clash_subscription"
@@ -578,19 +566,19 @@ namespace ClashN.Handler
} }
//maybe clashProtocol //maybe clashProtocol
if (Utils.IsNullOrEmpty(indexId) && (clipboardData.StartsWith(Global.clashProtocol))) if (string.IsNullOrEmpty(indexId) && (clipboardData.StartsWith(Global.clashProtocol)))
{ {
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); var query = HttpUtility.ParseQueryString(url.Query);
if (!Utils.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"],
coreType = ECoreType.clash_meta, coreType = CoreKind.ClashMeta,
address = string.Empty, address = string.Empty,
enabled = true, enabled = true,
remarks = "clash_subscription" remarks = "clash_subscription"
@@ -608,7 +596,7 @@ namespace ClashN.Handler
{ {
groupId = groupId, groupId = groupId,
url = "", url = "",
coreType = ECoreType.clash_meta, coreType = CoreKind.ClashMeta,
address = string.Empty, address = string.Empty,
enabled = false, enabled = false,
remarks = "clash_local_file" remarks = "clash_local_file"
@@ -622,10 +610,11 @@ namespace ClashN.Handler
&& clipboardData.IndexOf("proxies") >= 0 && clipboardData.IndexOf("proxies") >= 0
&& clipboardData.IndexOf("rules") >= 0) && clipboardData.IndexOf("rules") >= 0)
{ } { }
else { return -1; } else
{ return -1; }
ProfileItem profileItem; ProfileItem profileItem;
if (!Utils.IsNullOrEmpty(indexId)) if (!string.IsNullOrEmpty(indexId))
{ {
profileItem = config.GetProfileItem(indexId); profileItem = config.GetProfileItem(indexId);
} }
@@ -648,7 +637,7 @@ namespace ClashN.Handler
public static void ClearAllServerStatistics(ref Config config) public static void ClearAllServerStatistics(ref Config config)
{ {
foreach (var item in config.profileItems) foreach (var item in config.ProfileItems)
{ {
item.uploadRemote = 0; item.uploadRemote = 0;
item.downloadRemote = 0; item.downloadRemote = 0;

View File

@@ -42,7 +42,7 @@ namespace ClashN.Handler
} }
string addressFileName = node.address; string addressFileName = node.address;
if (Utils.IsNullOrEmpty(addressFileName)) if (string.IsNullOrEmpty(addressFileName))
{ {
msg = ResUI.FailedGetDefaultConfiguration; msg = ResUI.FailedGetDefaultConfiguration;
return -1; return -1;
@@ -60,7 +60,7 @@ namespace ClashN.Handler
string tagYamlStr1 = "!<str>"; string tagYamlStr1 = "!<str>";
string tagYamlStr2 = "__strn__"; string tagYamlStr2 = "__strn__";
string tagYamlStr3 = "!!str"; string tagYamlStr3 = "!!str";
var config = LazyConfig.Instance.GetConfig(); var config = LazyConfig.Instance.Config;
var txtFile = File.ReadAllText(addressFileName); var txtFile = File.ReadAllText(addressFileName);
txtFile = txtFile.Replace(tagYamlStr1, tagYamlStr2); txtFile = txtFile.Replace(tagYamlStr1, tagYamlStr2);
@@ -71,50 +71,51 @@ namespace ClashN.Handler
return -1; return -1;
} }
//mixed-port //mixed-port
ModifyContent(fileContent, "mixed-port", config.mixedPort); fileContent["mixed-port"] = config.MixedPort;
//port //port
ModifyContent(fileContent, "port", config.httpPort); fileContent["port"] = config.HttpPort;
//socks-port //socks-port
ModifyContent(fileContent, "socks-port", config.socksPort); fileContent["socks-port"] = config.SocksPort;
//log-level //log-level
ModifyContent(fileContent, "log-level", config.logLevel); fileContent["log-level"] = config.LogLevel;
//external-controller //external-controller
ModifyContent(fileContent, "external-controller", $"{Global.Loopback}:{config.APIPort}"); fileContent["external-controller"] = $"{Global.Loopback}:{config.ApiPort}";
//allow-lan //allow-lan
if (config.allowLANConn) if (config.AllowLANConn)
{ {
ModifyContent(fileContent, "allow-lan", "true"); fileContent["allow-lan"] = "true";
ModifyContent(fileContent, "bind-address", "*"); fileContent["bind-address"] = "*";
} }
else else
{ {
ModifyContent(fileContent, "allow-lan", "false"); fileContent["allow-lan"] = "false";
} }
//ipv6 //ipv6
ModifyContent(fileContent, "ipv6", config.enableIpv6); fileContent["ipv6"] = config.EnableIpv6;
//mode //mode
if (!fileContent.ContainsKey("mode")) if (!fileContent.ContainsKey("mode"))
{ {
ModifyContent(fileContent, "mode", ERuleMode.Rule.ToString().ToLower()); fileContent["mode"] = ERuleMode.Rule.ToString().ToLower();
} }
else else
{ {
if (config.ruleMode != ERuleMode.Unchanged) if (config.ruleMode != ERuleMode.Unchanged)
{ {
ModifyContent(fileContent, "mode", config.ruleMode.ToString().ToLower()); fileContent["model"] = config.ruleMode.ToString().ToLower();
} }
} }
//enable tun mode //enable tun mode
if (config.enableTun) if (config.EnableTun)
{ {
string tun = Utils.GetEmbedText(Global.SampleTun); string tun = Utils.GetEmbedText(Global.SampleTun);
if (!Utils.IsNullOrEmpty(tun)) if (!string.IsNullOrEmpty(tun))
{ {
var tunContent = Utils.FromYaml<Dictionary<string, object>>(tun); var tunContent = Utils.FromYaml<Dictionary<string, object>>(tun);
ModifyContent(fileContent, "tun", tunContent["tun"]); if (tunContent != null)
fileContent["tun"] = tunContent["tun"];
} }
} }
@@ -152,7 +153,7 @@ namespace ClashN.Handler
private static void MixinContent(Dictionary<string, object> fileContent, Config config, ProfileItem node) private static void MixinContent(Dictionary<string, object> fileContent, Config config, ProfileItem node)
{ {
if (!config.enableMixinContent) if (!config.EnableMixinContent)
{ {
return; return;
} }
@@ -173,7 +174,7 @@ namespace ClashN.Handler
} }
foreach (var item in mixinContent) foreach (var item in mixinContent)
{ {
if (!config.enableTun && item.Key == "tun") if (!config.EnableTun && item.Key == "tun")
{ {
continue; continue;
} }
@@ -186,23 +187,12 @@ namespace ClashN.Handler
} }
else else
{ {
ModifyContent(fileContent, item.Key, item.Value); fileContent[item.Key] = item.Value;
} }
} }
return; return;
} }
private static void ModifyContent(Dictionary<string, object> fileContent, string key, object value)
{
if (fileContent.ContainsKey(key))
{
fileContent[key] = value;
}
else
{
fileContent.Add(key, value);
}
}
private static void ModifyContentMerge(Dictionary<string, object> fileContent, string key, object value) private static void ModifyContentMerge(Dictionary<string, object> fileContent, string key, object value)
{ {
bool blPrepend = false; bool blPrepend = false;

View File

@@ -28,7 +28,7 @@ namespace ClashN.Handler
{ {
if (Global.reloadCore) if (Global.reloadCore)
{ {
var item = ConfigHandler.GetDefaultProfile(ref config); var item = ConfigProc.GetDefaultProfile(ref config);
if (item == null) if (item == null)
{ {
CoreStop(); CoreStop();
@@ -36,12 +36,12 @@ namespace ClashN.Handler
return; return;
} }
if (config.enableTun && !Utils.IsAdministrator()) if (config.EnableTun && !Utils.IsAdministrator())
{ {
ShowMsg(true, ResUI.EnableTunModeFailed); ShowMsg(true, ResUI.EnableTunModeFailed);
return; return;
} }
if (config.enableTun && item.coreType == ECoreType.clash) if (config.EnableTun && item.coreType == CoreKind.Clash)
{ {
ShowMsg(true, ResUI.TunModeCoreTip); ShowMsg(true, ResUI.TunModeCoreTip);
return; return;
@@ -171,7 +171,7 @@ namespace ClashN.Handler
break; break;
} }
} }
if (Utils.IsNullOrEmpty(fileName)) if (string.IsNullOrEmpty(fileName))
{ {
string msg = string.Format(ResUI.NotFoundCore, coreInfo.coreUrl); string msg = string.Format(ResUI.NotFoundCore, coreInfo.coreUrl);
ShowMsg(false, msg); ShowMsg(false, msg);

View File

@@ -13,9 +13,8 @@ namespace ClashN.Handler
/// </summary> /// </summary>
class DownloadHandle class DownloadHandle
{ {
public event EventHandler<ResultEventArgs> UpdateCompleted; public event EventHandler<ResultEventArgs>? UpdateCompleted;
public event ErrorEventHandler? Error;
public event ErrorEventHandler Error;
public class ResultEventArgs : EventArgs public class ResultEventArgs : EventArgs
@@ -34,7 +33,7 @@ namespace ClashN.Handler
{ {
try try
{ {
Utils.SetSecurityProtocol(LazyConfig.Instance.GetConfig().enableSecurityProtocolTls13); Utils.SetSecurityProtocol(LazyConfig.Instance.Config.EnableSecurityProtocolTls13);
UpdateCompleted?.Invoke(this, new ResultEventArgs(false, ResUI.Downloading)); UpdateCompleted?.Invoke(this, new ResultEventArgs(false, ResUI.Downloading));
var client = new HttpClient(new SocketsHttpHandler() var client = new HttpClient(new SocketsHttpHandler()
@@ -75,13 +74,13 @@ namespace ClashN.Handler
{ {
try try
{ {
Utils.SetSecurityProtocol(LazyConfig.Instance.GetConfig().enableSecurityProtocolTls13); Utils.SetSecurityProtocol(LazyConfig.Instance.Config.EnableSecurityProtocolTls13);
var client = new HttpClient(new SocketsHttpHandler() var client = new HttpClient(new SocketsHttpHandler()
{ {
Proxy = GetWebProxy(blProxy) Proxy = GetWebProxy(blProxy)
}); });
if (Utils.IsNullOrEmpty(userAgent)) if (string.IsNullOrEmpty(userAgent))
{ {
userAgent = $"{Utils.GetVersion(false)}"; userAgent = $"{Utils.GetVersion(false)}";
} }
@@ -89,7 +88,7 @@ namespace ClashN.Handler
Uri uri = new Uri(url); Uri uri = new Uri(url);
//Authorization Header //Authorization Header
if (!Utils.IsNullOrEmpty(uri.UserInfo)) if (!string.IsNullOrEmpty(uri.UserInfo))
{ {
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Basic", Utils.Base64Encode(uri.UserInfo)); client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Basic", Utils.Base64Encode(uri.UserInfo));
} }
@@ -114,7 +113,7 @@ namespace ClashN.Handler
public async Task<string> UrlRedirectAsync(string url, bool blProxy) public async Task<string> UrlRedirectAsync(string url, bool blProxy)
{ {
Utils.SetSecurityProtocol(LazyConfig.Instance.GetConfig().enableSecurityProtocolTls13); Utils.SetSecurityProtocol(LazyConfig.Instance.Config.EnableSecurityProtocolTls13);
SocketsHttpHandler webRequestHandler = new SocketsHttpHandler SocketsHttpHandler webRequestHandler = new SocketsHttpHandler
{ {
AllowAutoRedirect = false, AllowAutoRedirect = false,
@@ -140,7 +139,7 @@ namespace ClashN.Handler
{ {
return null; return null;
} }
var socksPort = LazyConfig.Instance.GetConfig().socksPort; var socksPort = LazyConfig.Instance.Config.SocksPort;
if (!SocketCheck(Global.Loopback, socksPort)) if (!SocketCheck(Global.Loopback, socksPort))
{ {
return null; return null;

View File

@@ -19,10 +19,7 @@ namespace ClashN.Handler
{ {
_config = config; _config = config;
} }
public Config GetConfig() public Config Config => _config;
{
return _config;
}
public void SetProxies(Dictionary<String, ProxiesItem> proxies) public void SetProxies(Dictionary<String, ProxiesItem> proxies)
{ {
@@ -35,17 +32,17 @@ namespace ClashN.Handler
public Dictionary<string, object> ProfileContent { get; set; } public Dictionary<string, object> ProfileContent { get; set; }
public ECoreType GetCoreType(ProfileItem profileItem) public CoreKind GetCoreType(ProfileItem profileItem)
{ {
if (profileItem != null && profileItem.coreType != null) if (profileItem != null && profileItem.coreType != null)
{ {
return (ECoreType)profileItem.coreType; return (CoreKind)profileItem.coreType;
} }
return ECoreType.clash; return CoreKind.Clash;
} }
public CoreInfo GetCoreInfo(ECoreType coreType) public CoreInfo GetCoreInfo(CoreKind coreType)
{ {
if (coreInfos == null) if (coreInfos == null)
{ {
@@ -60,7 +57,7 @@ namespace ClashN.Handler
coreInfos.Add(new CoreInfo coreInfos.Add(new CoreInfo
{ {
coreType = ECoreType.clashN, coreType = CoreKind.ClashN,
coreUrl = Global.NUrl, coreUrl = Global.NUrl,
coreLatestUrl = Global.NUrl + "/latest", coreLatestUrl = Global.NUrl + "/latest",
coreDownloadUrl32 = Global.NUrl + "/download/{0}/clashN-32.zip", coreDownloadUrl32 = Global.NUrl + "/download/{0}/clashN-32.zip",
@@ -69,7 +66,7 @@ namespace ClashN.Handler
coreInfos.Add(new CoreInfo coreInfos.Add(new CoreInfo
{ {
coreType = ECoreType.clash, coreType = CoreKind.Clash,
coreExes = new List<string> { "clash-windows-amd64-v3", "clash-windows-amd64", "clash-windows-386", "clash" }, coreExes = new List<string> { "clash-windows-amd64-v3", "clash-windows-amd64", "clash-windows-386", "clash" },
arguments = "-f config.yaml", arguments = "-f config.yaml",
coreUrl = Global.clashCoreUrl, coreUrl = Global.clashCoreUrl,
@@ -81,7 +78,7 @@ namespace ClashN.Handler
coreInfos.Add(new CoreInfo coreInfos.Add(new CoreInfo
{ {
coreType = ECoreType.clash_meta, coreType = CoreKind.ClashMeta,
coreExes = new List<string> { $"Clash.Meta-windows-amd64{(Avx2.X64.IsSupported ? "" : "-compatible")}", "Clash.Meta-windows-amd64-compatible", "Clash.Meta-windows-amd64", "Clash.Meta-windows-386", "Clash.Meta", "clash" }, coreExes = new List<string> { $"Clash.Meta-windows-amd64{(Avx2.X64.IsSupported ? "" : "-compatible")}", "Clash.Meta-windows-amd64-compatible", "Clash.Meta-windows-amd64", "Clash.Meta-windows-386", "Clash.Meta", "clash" },
arguments = "-f config.yaml", arguments = "-f config.yaml",
coreUrl = Global.clashMetaCoreUrl, coreUrl = Global.clashMetaCoreUrl,
@@ -93,7 +90,7 @@ namespace ClashN.Handler
coreInfos.Add(new CoreInfo coreInfos.Add(new CoreInfo
{ {
coreType = ECoreType.clash_premium, coreType = CoreKind.ClashPremium,
coreExes = new List<string> { "clash-windows-amd64-v3", "clash-windows-amd64", "clash-windows-386", "clash" }, coreExes = new List<string> { "clash-windows-amd64-v3", "clash-windows-amd64", "clash-windows-386", "clash" },
arguments = "-f config.yaml", arguments = "-f config.yaml",
coreUrl = Global.clashCoreUrl, coreUrl = Global.clashCoreUrl,

View File

@@ -23,7 +23,7 @@ namespace ClashN.Handler
{ {
try try
{ {
int index = (int)config.sysProxyType; int index = (int)config.SysProxyType;
//Load from local file //Load from local file
var fileName = Utils.GetPath($"NotifyIcon{index + 1}.ico"); var fileName = Utils.GetPath($"NotifyIcon{index + 1}.ico");
@@ -76,7 +76,7 @@ namespace ClashN.Handler
} }
fileName = fileDialog.FileName; fileName = fileDialog.FileName;
} }
if (Utils.IsNullOrEmpty(fileName)) if (string.IsNullOrEmpty(fileName))
{ {
return; return;
} }
@@ -112,9 +112,9 @@ namespace ClashN.Handler
{ {
var dtNow = DateTime.Now; var dtNow = DateTime.Now;
if (config.autoUpdateSubInterval > 0) if (config.AutoUpdateSubInterval > 0)
{ {
if ((dtNow - autoUpdateSubTime).Hours % config.autoUpdateSubInterval == 0) if ((dtNow - autoUpdateSubTime).Hours % config.AutoUpdateSubInterval == 0)
{ {
updateHandle.UpdateSubscriptionProcess(config, true, null, (bool success, string msg) => updateHandle.UpdateSubscriptionProcess(config, true, null, (bool success, string msg) =>
{ {
@@ -183,13 +183,13 @@ namespace ClashN.Handler
var gesture = new KeyGesture(KeyInterop.KeyFromVirtualKey((int)item.KeyCode), modifiers); var gesture = new KeyGesture(KeyInterop.KeyFromVirtualKey((int)item.KeyCode), modifiers);
try try
{ {
HotkeyManager.Current.AddOrReplace(((int)item.eGlobalHotkey).ToString(), gesture, handler); HotkeyManager.Current.AddOrReplace(((int)item.GlobalHotkey).ToString(), gesture, handler);
var msg = string.Format(ResUI.RegisterGlobalHotkeySuccessfully, $"{item.eGlobalHotkey.ToString()} = {Utils.ToJson(item)}"); var msg = string.Format(ResUI.RegisterGlobalHotkeySuccessfully, $"{item.GlobalHotkey.ToString()} = {Utils.ToJson(item)}");
update(false, msg); update(false, msg);
} }
catch (Exception ex) catch (Exception ex)
{ {
var msg = string.Format(ResUI.RegisterGlobalHotkeyFailed, $"{item.eGlobalHotkey.ToString()} = {Utils.ToJson(item)}", ex.Message); var msg = string.Format(ResUI.RegisterGlobalHotkeyFailed, $"{item.GlobalHotkey.ToString()} = {Utils.ToJson(item)}", ex.Message);
update(false, msg); update(false, msg);
Utils.SaveLog(msg); Utils.SaveLog(msg);
} }
@@ -205,12 +205,12 @@ namespace ClashN.Handler
{ {
for (var i = 0; i < 5; i++) for (var i = 0; i < 5; i++)
{ {
var url = $"{Global.httpProtocol}{Global.Loopback}:{config.APIPort}/proxies"; var url = $"{Global.httpProtocol}{Global.Loopback}:{config.ApiPort}/proxies";
var result = await HttpClientHelper.GetInstance().GetAsync(url); var result = await HttpClientHelper.GetInstance().TryGetAsync(url);
var clashProxies = Utils.FromJson<ClashProxies>(result); var clashProxies = Utils.FromJson<ClashProxies>(result);
var url2 = $"{Global.httpProtocol}{Global.Loopback}:{config.APIPort}/providers/proxies"; var url2 = $"{Global.httpProtocol}{Global.Loopback}:{config.ApiPort}/providers/proxies";
var result2 = await HttpClientHelper.GetInstance().GetAsync(url2); var result2 = await HttpClientHelper.GetInstance().TryGetAsync(url2);
var clashProviders = Utils.FromJson<ClashProviders>(result2); var clashProviders = Utils.FromJson<ClashProviders>(result2);
if (clashProxies != null || clashProviders != null) if (clashProxies != null || clashProviders != null)
@@ -261,8 +261,8 @@ namespace ClashN.Handler
{ {
return; return;
} }
var urlBase = $"{Global.httpProtocol}{Global.Loopback}:{LazyConfig.Instance.GetConfig().APIPort}/proxies"; var urlBase = $"{Global.httpProtocol}{Global.Loopback}:{LazyConfig.Instance.Config.ApiPort}/proxies";
urlBase += @"/{0}/delay?timeout=10000&url=" + LazyConfig.Instance.GetConfig().constItem.speedPingTestUrl; urlBase += @"/{0}/delay?timeout=10000&url=" + LazyConfig.Instance.Config.ConstItem.speedPingTestUrl;
List<Task> tasks = new List<Task>(); List<Task> tasks = new List<Task>();
foreach (var it in lstProxy) foreach (var it in lstProxy)
@@ -275,7 +275,7 @@ namespace ClashN.Handler
var url = string.Format(urlBase, name); var url = string.Format(urlBase, name);
tasks.Add(Task.Run(async () => tasks.Add(Task.Run(async () =>
{ {
var result = await HttpClientHelper.GetInstance().GetAsync(url); var result = await HttpClientHelper.GetInstance().TryGetAsync(url);
update(it, result); update(it, result);
})); }));
} }
@@ -320,7 +320,7 @@ namespace ClashN.Handler
{ {
try try
{ {
var url = $"{Global.httpProtocol}{Global.Loopback}:{LazyConfig.Instance.GetConfig().APIPort}/proxies/{name}"; var url = $"{Global.httpProtocol}{Global.Loopback}:{LazyConfig.Instance.Config.ApiPort}/proxies/{name}";
Dictionary<string, string> headers = new Dictionary<string, string>(); Dictionary<string, string> headers = new Dictionary<string, string>();
headers.Add("name", nameNode); headers.Add("name", nameNode);
await HttpClientHelper.GetInstance().PutAsync(url, headers); await HttpClientHelper.GetInstance().PutAsync(url, headers);
@@ -341,7 +341,7 @@ namespace ClashN.Handler
return; return;
} }
var urlBase = $"{Global.httpProtocol}{Global.Loopback}:{LazyConfig.Instance.GetConfig().APIPort}/configs"; var urlBase = $"{Global.httpProtocol}{Global.Loopback}:{LazyConfig.Instance.Config.ApiPort}/configs";
await HttpClientHelper.GetInstance().PatchAsync(urlBase, headers); await HttpClientHelper.GetInstance().PatchAsync(urlBase, headers);
}); });
@@ -352,7 +352,7 @@ namespace ClashN.Handler
ClashConnectionClose(""); ClashConnectionClose("");
try try
{ {
var url = $"{Global.httpProtocol}{Global.Loopback}:{LazyConfig.Instance.GetConfig().APIPort}/configs?force=true"; var url = $"{Global.httpProtocol}{Global.Loopback}:{LazyConfig.Instance.Config.ApiPort}/configs?force=true";
Dictionary<string, string> headers = new Dictionary<string, string>(); Dictionary<string, string> headers = new Dictionary<string, string>();
headers.Add("path", filePath); headers.Add("path", filePath);
await HttpClientHelper.GetInstance().PutAsync(url, headers); await HttpClientHelper.GetInstance().PutAsync(url, headers);
@@ -371,8 +371,8 @@ namespace ClashN.Handler
{ {
try try
{ {
var url = $"{Global.httpProtocol}{Global.Loopback}:{config.APIPort}/connections"; var url = $"{Global.httpProtocol}{Global.Loopback}:{config.ApiPort}/connections";
var result = await HttpClientHelper.GetInstance().GetAsync(url); var result = await HttpClientHelper.GetInstance().TryGetAsync(url);
var clashConnections = Utils.FromJson<ClashConnections>(result); var clashConnections = Utils.FromJson<ClashConnections>(result);
update(clashConnections); update(clashConnections);
@@ -387,7 +387,7 @@ namespace ClashN.Handler
{ {
try try
{ {
var url = $"{Global.httpProtocol}{Global.Loopback}:{LazyConfig.Instance.GetConfig().APIPort}/connections/{id}"; var url = $"{Global.httpProtocol}{Global.Loopback}:{LazyConfig.Instance.Config.ApiPort}/connections/{id}";
await HttpClientHelper.GetInstance().DeleteAsync(url); await HttpClientHelper.GetInstance().DeleteAsync(url);
} }
catch (Exception ex) catch (Exception ex)

View File

@@ -21,7 +21,7 @@ namespace ClashN.Handler
} }
else if (type == 2 || type == 4) else if (type == 2 || type == 4)
{ {
optionCount = Utils.IsNullOrEmpty(exceptions) ? 2 : 3; optionCount = string.IsNullOrEmpty(exceptions) ? 2 : 3;
} }
int m_Int = (int)PerConnFlags.PROXY_TYPE_DIRECT; int m_Int = (int)PerConnFlags.PROXY_TYPE_DIRECT;
@@ -37,7 +37,7 @@ namespace ClashN.Handler
m_Option = PerConnOption.INTERNET_PER_CONN_AUTOCONFIG_URL; m_Option = PerConnOption.INTERNET_PER_CONN_AUTOCONFIG_URL;
} }
//int optionCount = Utils.IsNullOrEmpty(strProxy) ? 1 : (Utils.IsNullOrEmpty(exceptions) ? 2 : 3); //int optionCount = string.IsNullOrEmpty(strProxy) ? 1 : (string.IsNullOrEmpty(exceptions) ? 2 : 3);
InternetConnectionOption[] options = new InternetConnectionOption[optionCount]; InternetConnectionOption[] options = new InternetConnectionOption[optionCount];
// USE a proxy server ... // USE a proxy server ...
options[0].m_Option = PerConnOption.INTERNET_PER_CONN_FLAGS; options[0].m_Option = PerConnOption.INTERNET_PER_CONN_FLAGS;

View File

@@ -29,8 +29,8 @@ namespace ClashN.Handler
{ {
_selecteds.Add(new ServerTestItem() _selecteds.Add(new ServerTestItem()
{ {
indexId = it.indexId, IndexId = it.indexId,
address = it.address Address = it.address
}); });
} }
@@ -74,9 +74,9 @@ namespace ClashN.Handler
{ {
RunPingSub((ServerTestItem it) => RunPingSub((ServerTestItem it) =>
{ {
long time = Utils.Ping(it.address); long time = Utils.Ping(it.Address);
_updateFunc(it.indexId, FormatOut(time, "ms")); _updateFunc(it.IndexId, FormatOut(time, "ms"));
}); });
} }
@@ -84,9 +84,9 @@ namespace ClashN.Handler
{ {
RunPingSub((ServerTestItem it) => RunPingSub((ServerTestItem it) =>
{ {
int time = GetTcpingTime(it.address, it.port); int time = GetTcpingTime(it.Address, it.Port);
_updateFunc(it.indexId, FormatOut(time, "ms")); _updateFunc(it.IndexId, FormatOut(time, "ms"));
}); });
} }
@@ -95,7 +95,7 @@ namespace ClashN.Handler
{ {
try try
{ {
int httpPort = _config.httpPort; int httpPort = _config.HttpPort;
Task<int> t = Task.Run(() => Task<int> t = Task.Run(() =>
{ {
@@ -103,8 +103,8 @@ namespace ClashN.Handler
{ {
WebProxy webProxy = new WebProxy(Global.Loopback, httpPort); WebProxy webProxy = new WebProxy(Global.Loopback, httpPort);
int responseTime = -1; int responseTime = -1;
string status = GetRealPingTime(LazyConfig.Instance.GetConfig().constItem.speedPingTestUrl, webProxy, out responseTime); string status = GetRealPingTime(LazyConfig.Instance.Config.ConstItem.speedPingTestUrl, webProxy, out responseTime);
bool noError = Utils.IsNullOrEmpty(status); bool noError = string.IsNullOrEmpty(status);
return noError ? responseTime : -1; return noError ? responseTime : -1;
} }
catch (Exception ex) catch (Exception ex)

View File

@@ -30,7 +30,7 @@ namespace ClashN.Handler
public StatisticsHandler(Config config, Action<ulong, ulong> update) public StatisticsHandler(Config config, Action<ulong, ulong> update)
{ {
config_ = config; config_ = config;
Enable = config.enableStatistics; Enable = config.EnableStatistics;
updateFunc_ = update; updateFunc_ = update;
exitFlag_ = false; exitFlag_ = false;
@@ -46,7 +46,7 @@ namespace ClashN.Handler
try try
{ {
url = $"ws://{Global.Loopback}:{config_.APIPort}/traffic"; url = $"ws://{Global.Loopback}:{config_.ApiPort}/traffic";
if (webSocket == null) if (webSocket == null)
{ {
@@ -104,9 +104,9 @@ namespace ClashN.Handler
while (!res.CloseStatus.HasValue) while (!res.CloseStatus.HasValue)
{ {
var result = Encoding.UTF8.GetString(buffer, 0, res.Count); var result = Encoding.UTF8.GetString(buffer, 0, res.Count);
if (!Utils.IsNullOrEmpty(result)) if (!string.IsNullOrEmpty(result))
{ {
var serverStatItem = config_.GetProfileItem(config_.indexId); var serverStatItem = config_.GetProfileItem(config_.IndexId);
ParseOutput(result, out ulong up, out ulong down); ParseOutput(result, out ulong up, out ulong down);
if (up + down > 0) if (up + down > 0)
{ {
@@ -134,7 +134,7 @@ namespace ClashN.Handler
// try // try
// { // {
// string result = Utils.LoadResource(Utils.GetConfigPath(Global.StatisticLogOverall)); // string result = Utils.LoadResource(Utils.GetConfigPath(Global.StatisticLogOverall));
// if (!Utils.IsNullOrEmpty(result)) // if (!string.IsNullOrEmpty(result))
// { // {
// serverStatistics_ = Utils.FromJson<ServerStatistics>(result); // serverStatistics_ = Utils.FromJson<ServerStatistics>(result);
// } // }
@@ -239,7 +239,7 @@ namespace ClashN.Handler
down = trafficItem.down; down = trafficItem.down;
} }
} }
catch (Exception ex) catch (Exception)
{ {
//Utils.SaveLog(ex.Message, ex); //Utils.SaveLog(ex.Message, ex);
} }

View File

@@ -36,54 +36,54 @@ namespace ClashN.Handler
public static bool UpdateSysProxy(Config config, bool forceDisable) public static bool UpdateSysProxy(Config config, bool forceDisable)
{ {
var type = config.sysProxyType; var type = config.SysProxyType;
if (forceDisable && (type == ESysProxyType.ForcedChange || type == ESysProxyType.Pac)) if (forceDisable && (type == SysProxyType.ForcedChange || type == SysProxyType.Pac))
{ {
type = ESysProxyType.ForcedClear; type = SysProxyType.ForcedClear;
} }
try try
{ {
int port = config.httpPort; int port = config.HttpPort;
int socksPort = config.socksPort; int socksPort = config.SocksPort;
if (port <= 0) if (port <= 0)
{ {
return false; return false;
} }
if (type == ESysProxyType.ForcedChange) if (type == SysProxyType.ForcedChange)
{ {
var strExceptions = $"{config.constItem.defIEProxyExceptions};{config.systemProxyExceptions}"; var strExceptions = $"{config.ConstItem.defIEProxyExceptions};{config.SystemProxyExceptions}";
var strProxy = string.Empty; var strProxy = string.Empty;
if (Utils.IsNullOrEmpty(config.systemProxyAdvancedProtocol)) if (string.IsNullOrEmpty(config.SystemProxyAdvancedProtocol))
{ {
strProxy = $"{Global.Loopback}:{port}"; strProxy = $"{Global.Loopback}:{port}";
} }
else else
{ {
strProxy = config.systemProxyAdvancedProtocol strProxy = config.SystemProxyAdvancedProtocol
.Replace("{ip}", Global.Loopback) .Replace("{ip}", Global.Loopback)
.Replace("{http_port}", port.ToString()) .Replace("{http_port}", port.ToString())
.Replace("{socks_port}", socksPort.ToString()); .Replace("{socks_port}", socksPort.ToString());
} }
SetIEProxy(true, strProxy, strExceptions); SetIEProxy(true, strProxy, strExceptions);
} }
else if (type == ESysProxyType.ForcedClear) else if (type == SysProxyType.ForcedClear)
{ {
ResetIEProxy(); ResetIEProxy();
} }
else if (type == ESysProxyType.Unchanged) else if (type == SysProxyType.Unchanged)
{ {
} }
else if (type == ESysProxyType.Pac) else if (type == SysProxyType.Pac)
{ {
PacHandler.Start(Utils.GetConfigPath(), port, config.PacPort); PacHandler.Start(Utils.GetConfigPath(), port, config.PacPort);
var strProxy = $"{Global.httpProtocol}{Global.Loopback}:{config.PacPort}/pac?t={DateTime.Now.Ticks}"; var strProxy = $"{Global.httpProtocol}{Global.Loopback}:{config.PacPort}/pac?t={DateTime.Now.Ticks}";
SetIEProxy(false, strProxy, ""); SetIEProxy(false, strProxy, "");
} }
if (type != ESysProxyType.Pac) if (type != SysProxyType.Pac)
{ {
PacHandler.Stop(); PacHandler.Stop();
} }
@@ -196,9 +196,8 @@ namespace ClashN.Handler
} }
catch (System.ComponentModel.Win32Exception e) catch (System.ComponentModel.Win32Exception e)
{ {
// log the arguments // log the arguments
throw new Exception(process.StartInfo.Arguments); throw new Exception(process.StartInfo.Arguments, e);
} }
string stderr = error.ToString(); string stderr = error.ToString();
string stdout = output.ToString(); string stdout = output.ToString();

View File

@@ -88,7 +88,7 @@ namespace ClashN.Handler
_updateFunc(false, string.Format(ResUI.MsgParsingSuccessfully, "clashN")); _updateFunc(false, string.Format(ResUI.MsgParsingSuccessfully, "clashN"));
url = args.Msg; url = args.Msg;
askToDownload(downloadHandle, url, true); AskToDownload(downloadHandle, url, true);
} }
else else
{ {
@@ -97,11 +97,11 @@ namespace ClashN.Handler
} }
}; };
_updateFunc(false, string.Format(ResUI.MsgStartUpdating, "clashN")); _updateFunc(false, string.Format(ResUI.MsgStartUpdating, "clashN"));
CheckUpdateAsync(ECoreType.clashN); CheckUpdateAsync(CoreKind.ClashN);
} }
public void CheckUpdateCore(ECoreType type, Config config, Action<bool, string> update) public void CheckUpdateCore(CoreKind type, Config config, Action<bool, string> update)
{ {
_config = config; _config = config;
_updateFunc = update; _updateFunc = update;
@@ -144,7 +144,7 @@ namespace ClashN.Handler
{ {
_updateFunc(false, string.Format(ResUI.MsgParsingSuccessfully, "Core")); _updateFunc(false, string.Format(ResUI.MsgParsingSuccessfully, "Core"));
url = args.Msg; url = args.Msg;
askToDownload(downloadHandle, url, true); AskToDownload(downloadHandle, url, true);
} }
else else
{ {
@@ -164,7 +164,7 @@ namespace ClashN.Handler
_updateFunc(false, ResUI.MsgUpdateSubscriptionStart); _updateFunc(false, ResUI.MsgUpdateSubscriptionStart);
if (config.profileItems == null || config.profileItems.Count <= 0) if (config.ProfileItems == null || config.ProfileItems.Count <= 0)
{ {
_updateFunc(false, ResUI.MsgNoValidSubscription); _updateFunc(false, ResUI.MsgNoValidSubscription);
return; return;
@@ -174,17 +174,17 @@ namespace ClashN.Handler
{ {
//Turn off system proxy //Turn off system proxy
bool bSysProxyType = false; bool bSysProxyType = false;
if (!blProxy && config.sysProxyType == ESysProxyType.ForcedChange) if (!blProxy && config.SysProxyType == SysProxyType.ForcedChange)
{ {
bSysProxyType = true; bSysProxyType = true;
config.sysProxyType = ESysProxyType.ForcedClear; config.SysProxyType = SysProxyType.ForcedClear;
SysProxyHandle.UpdateSysProxy(config, false); SysProxyHandle.UpdateSysProxy(config, false);
Thread.Sleep(3000); Thread.Sleep(3000);
} }
if (profileItems == null) if (profileItems == null)
{ {
profileItems = config.profileItems; profileItems = config.ProfileItems;
} }
foreach (var item in profileItems) foreach (var item in profileItems)
{ {
@@ -193,7 +193,7 @@ namespace ClashN.Handler
string userAgent = item.userAgent.TrimEx(); string userAgent = item.userAgent.TrimEx();
string groupId = item.groupId.TrimEx(); string groupId = item.groupId.TrimEx();
string hashCode = $"{item.remarks}->"; string hashCode = $"{item.remarks}->";
if (item.enabled == false || Utils.IsNullOrEmpty(indexId) || Utils.IsNullOrEmpty(url)) if (item.enabled == false || string.IsNullOrEmpty(indexId) || string.IsNullOrEmpty(url))
{ {
_updateFunc(false, $"{hashCode}{ResUI.MsgSkipSubscriptionUpdate}"); _updateFunc(false, $"{hashCode}{ResUI.MsgSkipSubscriptionUpdate}");
continue; continue;
@@ -203,11 +203,11 @@ namespace ClashN.Handler
if (item.enableConvert) if (item.enableConvert)
{ {
if (Utils.IsNullOrEmpty(config.constItem.subConvertUrl)) if (string.IsNullOrEmpty(config.ConstItem.subConvertUrl))
{ {
config.constItem.subConvertUrl = Global.SubConvertUrls[0]; config.ConstItem.subConvertUrl = Global.SubConvertUrls[0];
} }
url = String.Format(config.constItem.subConvertUrl, Utils.UrlEncode(url)); url = String.Format(config.ConstItem.subConvertUrl, Utils.UrlEncode(url));
if (!url.Contains("config=")) if (!url.Contains("config="))
{ {
url += String.Format("&config={0}", Global.SubConvertConfig[0]); url += String.Format("&config={0}", Global.SubConvertConfig[0]);
@@ -219,12 +219,12 @@ 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);
if (blProxy && Utils.IsNullOrEmpty(result.Item1)) if (blProxy && string.IsNullOrEmpty(result.Item1))
{ {
result = await downloadHandle.DownloadStringAsync(url, false, userAgent); result = await downloadHandle.DownloadStringAsync(url, false, userAgent);
} }
if (Utils.IsNullOrEmpty(result.Item1)) if (string.IsNullOrEmpty(result.Item1))
{ {
_updateFunc(false, $"{hashCode}{ResUI.MsgSubscriptionDecodingFailed}"); _updateFunc(false, $"{hashCode}{ResUI.MsgSubscriptionDecodingFailed}");
} }
@@ -236,7 +236,7 @@ namespace ClashN.Handler
_updateFunc(false, $"{hashCode}{result}"); _updateFunc(false, $"{hashCode}{result}");
} }
int ret = ConfigHandler.AddBatchProfiles(ref config, result.Item1, indexId, groupId); int ret = ConfigProc.AddBatchProfiles(ref config, result.Item1, indexId, groupId);
if (ret == 0) if (ret == 0)
{ {
item.updateTime = ((DateTimeOffset)DateTime.Now).ToUnixTimeSeconds(); item.updateTime = ((DateTimeOffset)DateTime.Now).ToUnixTimeSeconds();
@@ -282,7 +282,7 @@ namespace ClashN.Handler
//restore system proxy //restore system proxy
if (bSysProxyType) if (bSysProxyType)
{ {
config.sysProxyType = ESysProxyType.ForcedChange; config.SysProxyType = SysProxyType.ForcedChange;
SysProxyHandle.UpdateSysProxy(config, false); SysProxyHandle.UpdateSysProxy(config, false);
} }
_updateFunc(true, $"{ResUI.MsgUpdateSubscriptionEnd}"); _updateFunc(true, $"{ResUI.MsgUpdateSubscriptionEnd}");
@@ -340,12 +340,12 @@ namespace ClashN.Handler
}; };
} }
askToDownload(downloadHandle, url, false); AskToDownload(downloadHandle, url, false);
} }
#region private #region private
private async void CheckUpdateAsync(ECoreType type) private async void CheckUpdateAsync(CoreKind type)
{ {
try try
{ {
@@ -353,7 +353,7 @@ namespace ClashN.Handler
string url = coreInfo.coreLatestUrl; string url = coreInfo.coreLatestUrl;
var result = await (new DownloadHandle()).UrlRedirectAsync(url, true); var result = await (new DownloadHandle()).UrlRedirectAsync(url, true);
if (!Utils.IsNullOrEmpty(result)) if (!string.IsNullOrEmpty(result))
{ {
responseHandler(type, result); responseHandler(type, result);
} }
@@ -377,7 +377,7 @@ namespace ClashN.Handler
/// <summary> /// <summary>
/// 获取Core版本 /// 获取Core版本
/// </summary> /// </summary>
private string getCoreVersion(ECoreType type) private string getCoreVersion(CoreKind type)
{ {
try try
{ {
@@ -393,7 +393,7 @@ namespace ClashN.Handler
break; break;
} }
} }
if (Utils.IsNullOrEmpty(filePath)) if (string.IsNullOrEmpty(filePath))
{ {
string msg = string.Format(ResUI.NotFoundCore, @""); string msg = string.Format(ResUI.NotFoundCore, @"");
return ""; return "";
@@ -420,7 +420,7 @@ namespace ClashN.Handler
return ""; return "";
} }
} }
private void responseHandler(ECoreType type, string redirectUrl) private void responseHandler(CoreKind type, string redirectUrl)
{ {
try try
{ {
@@ -430,7 +430,7 @@ namespace ClashN.Handler
string curVersion; string curVersion;
string message; string message;
string url; string url;
if (type == ECoreType.clash) if (type == CoreKind.Clash)
{ {
curVersion = getCoreVersion(type); curVersion = getCoreVersion(type);
message = string.Format(ResUI.IsLatestCore, curVersion); message = string.Format(ResUI.IsLatestCore, curVersion);
@@ -443,7 +443,7 @@ namespace ClashN.Handler
url = string.Format(coreInfo.coreDownloadUrl32, version); url = string.Format(coreInfo.coreDownloadUrl32, version);
} }
} }
else if (type == ECoreType.clash_meta) else if (type == CoreKind.ClashMeta)
{ {
curVersion = getCoreVersion(type); curVersion = getCoreVersion(type);
message = string.Format(ResUI.IsLatestCore, curVersion); message = string.Format(ResUI.IsLatestCore, curVersion);
@@ -456,7 +456,7 @@ namespace ClashN.Handler
url = string.Format(coreInfo.coreDownloadUrl32, version); url = string.Format(coreInfo.coreDownloadUrl32, version);
} }
} }
else if (type == ECoreType.clashN) else if (type == CoreKind.ClashN)
{ {
curVersion = FileVersionInfo.GetVersionInfo(Utils.GetExePath()).FileVersion.ToString(); curVersion = FileVersionInfo.GetVersionInfo(Utils.GetExePath()).FileVersion.ToString();
message = string.Format(ResUI.IsLatestN, curVersion); message = string.Format(ResUI.IsLatestN, curVersion);
@@ -482,7 +482,7 @@ namespace ClashN.Handler
} }
} }
private void askToDownload(DownloadHandle downloadHandle, string url, bool blAsk) private void AskToDownload(DownloadHandle downloadHandle, string url, bool blAsk)
{ {
bool blDownload = false; bool blDownload = false;
if (blAsk) if (blAsk)

View File

@@ -2,36 +2,36 @@
{ {
public class ClashConnections public class ClashConnections
{ {
public ulong downloadTotal { get; set; } public ulong DownloadTotal { get; set; }
public ulong uploadTotal { get; set; } public ulong UploadTotal { get; set; }
public List<ConnectionItem> connections { get; set; } public List<ConnectionItem> Connections { get; } = new List<ConnectionItem>();
} }
public class ConnectionItem public class ConnectionItem
{ {
public string id { get; set; } public string Id { get; set; } = string.Empty;
public MetadataItem metadata { get; set; } public MetadataItem metadata { get; set; }
public ulong upload { get; set; } public ulong upload { get; set; }
public ulong download { get; set; } public ulong download { get; set; }
public DateTime start { get; set; } public DateTime start { get; set; }
public List<string> chains { get; set; } public List<string> Chains { get; } = new List<string>();
public string rule { get; set; } public string rule { get; set; }
public string rulePayload { get; set; } public string rulePayload { get; set; }
} }
public class MetadataItem public class MetadataItem
{ {
public string network { get; set; } public string Network { get; set; }
public string type { get; set; } public string Type { get; set; }
public string sourceIP { get; set; } public string SourceIP { get; set; }
public string destinationIP { get; set; } public string DestinationIP { get; set; }
public string sourcePort { get; set; } public string SourcePort { get; set; }
public string destinationPort { get; set; } public string DestinationPort { get; set; }
public string host { get; set; } public string Host { get; set; }
public string dnsMode { get; set; } public string DnsMode { get; set; }
public object uid { get; set; } public object Uid { get; set; }
public string process { get; set; } public string Process { get; set; }
public string processPath { get; set; } public string ProcessPath { get; set; }
public string remoteDestination { get; set; } public string RemoteDestination { get; set; }
} }
} }

View File

@@ -2,13 +2,7 @@
{ {
class ComboItem class ComboItem
{ {
public int ID public int ID { get; set; }
{ public string Text { get; set; }
get; set;
}
public string Text
{
get; set;
}
} }
} }

View File

@@ -1,5 +1,4 @@
using System.Drawing; using System.Drawing;
using System.Windows.Forms;
namespace ClashN.Mode namespace ClashN.Mode
{ {
@@ -10,69 +9,57 @@ namespace ClashN.Mode
public class Config public class Config
{ {
#region property #region property
public int mixedPort { get; set; } public int MixedPort { get; set; } = 7888;
public int httpPort { get; set; } public int HttpPort { get; set; } = 7890;
public int socksPort { get; set; } public int SocksPort { get; set; } = 7891;
public int APIPort { get; set; } public int ApiPort { get; set; } = 9090;
public string logLevel { get; set; } public string LogLevel { get; set; }
public bool enableIpv6 { get; set; } public bool EnableIpv6 { get; set; }
public string indexId { get; set; } public string IndexId { get; set; }
public ESysProxyType sysProxyType { get; set; } public SysProxyType SysProxyType { get; set; }
public ERuleMode ruleMode { get; set; } public ERuleMode ruleMode { get; set; }
public bool allowLANConn { get; set; } public bool AllowLANConn { get; set; }
public bool autoRun { get; set; } public bool AutoRun { get; set; }
public bool enableStatistics { get; set; } public bool EnableStatistics { get; set; }
public string systemProxyExceptions { get; set; } public string SystemProxyExceptions { get; set; }
public string systemProxyAdvancedProtocol { get; set; } public string SystemProxyAdvancedProtocol { get; set; }
public int autoUpdateSubInterval { get; set; } = 10; public int AutoUpdateSubInterval { get; set; } = 10;
public int autoDelayTestInterval { get; set; } = 10; public int AutoDelayTestInterval { get; set; } = 10;
public bool enableSecurityProtocolTls13 { get; set; } public bool EnableSecurityProtocolTls13 { get; set; }
public bool enableMixinContent { get; set; } public bool EnableMixinContent { get; set; }
public int PacPort { get; set; } public int PacPort { get; set; }
public bool autoHideStartup { get; set; } public bool AutoHideStartup { get; set; }
public bool enableTun { get; set; } public bool EnableTun { get; set; }
#endregion #endregion
#region other entities #region other entities
public List<ProfileItem> profileItems public List<ProfileItem> ProfileItems { get; } = new List<ProfileItem>();
{
get; set;
}
public UIItem uiItem public UIItem? UiItem { get; set; }
{
get; set;
}
public ConstItem constItem public ConstItem? ConstItem { get; set; }
{
get; set;
}
public List<KeyEventItem> globalHotkeys public List<KeyShortcut> globalHotkeys { get; } = new List<KeyShortcut>();
{
get; set;
}
#endregion #endregion
@@ -80,25 +67,25 @@ namespace ClashN.Mode
public int FindIndexId(string id) public int FindIndexId(string id)
{ {
if (Utils.IsNullOrEmpty(id)) if (string.IsNullOrEmpty(id))
{ {
return -1; return -1;
} }
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 (Utils.IsNullOrEmpty(id)) if (string.IsNullOrEmpty(id))
{ {
return null; return null;
} }
return profileItems.FirstOrDefault(it => it.indexId == id); return ProfileItems.FirstOrDefault(it => it.indexId == id);
} }
public bool IsActiveNode(ProfileItem item) public bool IsActiveNode(ProfileItem item)
{ {
if (!Utils.IsNullOrEmpty(item.indexId) && item.indexId == indexId) if (!string.IsNullOrEmpty(item.indexId) && item.indexId == IndexId)
{ {
return true; return true;
} }
@@ -135,44 +122,20 @@ namespace ClashN.Mode
#endregion #endregion
public string indexId public string indexId { get; set; }
{
get; set;
}
public int sort public int sort { get; set; }
{
get; set;
}
public string address public string address { get; set; }
{
get; set;
}
public string remarks public string remarks { get; set; }
{
get; set;
}
public string testResult public string testResult { get; set; }
{
get; set;
}
public string groupId public string groupId { get; set; } = string.Empty;
{ public CoreKind? coreType { get; set; }
get; set;
} = string.Empty;
public ECoreType? coreType
{
get; set;
}
public string url public string url { get; set; }
{
get; set;
}
public bool enabled { get; set; } = true; public bool enabled { get; set; } = true;
@@ -228,18 +191,4 @@ namespace ClashN.Mode
get; set; get; set;
} }
} }
[Serializable]
public class KeyEventItem
{
public EGlobalHotkey eGlobalHotkey { get; set; }
public bool Alt { get; set; }
public bool Control { get; set; }
public bool Shift { get; set; }
public Keys? KeyCode { get; set; }
}
} }

View File

@@ -3,7 +3,7 @@
[Serializable] [Serializable]
public class CoreInfo public class CoreInfo
{ {
public ECoreType coreType { get; set; } public CoreKind coreType { get; set; }
public List<string> coreExes { get; set; } public List<string> coreExes { get; set; }

View File

@@ -0,0 +1,11 @@

namespace ClashN.Mode
{
public enum CoreKind
{
Clash = 1,
ClashMeta = 2,
ClashPremium = 3,
ClashN = 99
}
}

View File

@@ -1,11 +0,0 @@

namespace ClashN.Mode
{
public enum ECoreType
{
clash = 1,
clash_meta = 2,
clash_premium = 3,
clashN = 99
}
}

View File

@@ -1,7 +1,7 @@
 
namespace ClashN.Mode namespace ClashN.Mode
{ {
public enum EGlobalHotkey public enum GlobalHotkeyAction
{ {
ShowForm = 0, ShowForm = 0,
SystemProxyClear = 1, SystemProxyClear = 1,

View File

@@ -0,0 +1,18 @@
using System.Windows.Forms;
namespace ClashN.Mode
{
[Serializable]
public struct KeyShortcut
{
public GlobalHotkeyAction GlobalHotkey { get; set; }
public bool Alt { get; set; }
public bool Control { get; set; }
public bool Shift { get; set; }
public Keys? KeyCode { get; set; }
}
}

View File

@@ -1,7 +1,7 @@
 
namespace ClashN.Mode namespace ClashN.Mode
{ {
public enum EMove public enum MovementTarget
{ {
Top = 1, Top = 1,
Up = 2, Up = 2,

View File

@@ -4,15 +4,9 @@ namespace ClashN.Mode
{ {
public class ProfileItemModel : ProfileItem public class ProfileItemModel : ProfileItem
{ {
public bool isActive { get; set; } public bool IsActive { get; set; }
public bool HasUrl public bool HasUrl => string.IsNullOrEmpty(url);
{ public bool HasAddress => string.IsNullOrEmpty(address);
get { return !url.IsNullOrEmpty(); }
}
public bool HasAddress
{
get { return !address.IsNullOrEmpty(); }
}
public string StrUpdateTime public string StrUpdateTime
{ {
get get
@@ -25,14 +19,8 @@ namespace ClashN.Mode
return dateTime.AddSeconds(updateTime).ToLocalTime().ToString("MM-dd HH:mm"); return dateTime.AddSeconds(updateTime).ToLocalTime().ToString("MM-dd HH:mm");
} }
} }
public string TrafficUsed public string TrafficUsed => Utils.HumanFy(uploadRemote + downloadRemote);
{ public string TrafficTotal => totalRemote <= 0 ? "∞" : Utils.HumanFy(totalRemote);
get { return Utils.HumanFy(uploadRemote + downloadRemote); }
}
public string TrafficTotal
{
get { return totalRemote <= 0 ? "∞" : Utils.HumanFy(totalRemote); }
}
public string StrExpireTime public string StrExpireTime
{ {
get get

View File

@@ -3,21 +3,9 @@
[Serializable] [Serializable]
class ServerTestItem class ServerTestItem
{ {
public string indexId public string IndexId { get; set; }
{ public string Address { get; set; }
get; set; public int Port { get; set; }
} public bool AllowTest { get; set; }
public string address
{
get; set;
}
public int port
{
get; set;
}
public bool allowTest
{
get; set;
}
} }
} }

View File

@@ -1,7 +1,7 @@
 
namespace ClashN.Mode namespace ClashN.Mode
{ {
public enum ESysProxyType public enum SysProxyType
{ {
ForcedClear = 0, ForcedClear = 0,
ForcedChange = 1, ForcedChange = 1,

View File

@@ -81,7 +81,7 @@ namespace ClashN.Tool
} }
try try
{ {
if (!Utils.IsNullOrEmpty(ignoredName) && entry.Name.Contains(ignoredName)) if (!string.IsNullOrEmpty(ignoredName) && entry.Name.Contains(ignoredName))
{ {
continue; continue;
} }

View File

@@ -7,14 +7,16 @@ namespace ClashN.Tool
{ {
public static IOrderedQueryable<T> OrderBy<T>(this IQueryable<T> query, string propertyName) public static IOrderedQueryable<T> OrderBy<T>(this IQueryable<T> query, string propertyName)
{ {
return _OrderBy<T>(query, propertyName, false); return OrderBy<T>(query, propertyName, false);
}
public static IOrderedQueryable<T> OrderByDescending<T>(this IQueryable<T> query, string propertyName)
{
return _OrderBy<T>(query, propertyName, true);
} }
static IOrderedQueryable<T> _OrderBy<T>(IQueryable<T> query, string propertyName, bool isDesc) public static IOrderedQueryable<T> OrderByDescending<T>(this IQueryable<T> query, string propertyName)
{
return OrderBy<T>(query, propertyName, true);
}
static IOrderedQueryable<T> OrderBy<T>(IQueryable<T> query, string propertyName, bool isDesc)
{ {
string methodname = (isDesc) ? "OrderByDescendingInternal" : "OrderByInternal"; string methodname = (isDesc) ? "OrderByDescendingInternal" : "OrderByInternal";
@@ -25,17 +27,21 @@ namespace ClashN.Tool
return (IOrderedQueryable<T>)method.Invoke(null, new object[] { query, memberProp }); return (IOrderedQueryable<T>)method.Invoke(null, new object[] { query, memberProp });
} }
public static IOrderedQueryable<T> OrderByInternal<T, TProp>(IQueryable<T> query, PropertyInfo memberProperty) public static IOrderedQueryable<T> OrderByInternal<T, TProp>(IQueryable<T> query, PropertyInfo memberProperty)
{//public
return query.OrderBy(_GetLamba<T, TProp>(memberProperty));
}
public static IOrderedQueryable<T> OrderByDescendingInternal<T, TProp>(IQueryable<T> query, PropertyInfo memberProperty)
{//public
return query.OrderByDescending(_GetLamba<T, TProp>(memberProperty));
}
static Expression<Func<T, TProp>> _GetLamba<T, TProp>(PropertyInfo memberProperty)
{ {
if (memberProperty.PropertyType != typeof(TProp)) throw new Exception(); return query.OrderBy(GetLambda<T, TProp>(memberProperty));
}
public static IOrderedQueryable<T> OrderByDescendingInternal<T, TProp>(IQueryable<T> query, PropertyInfo memberProperty)
{
return query.OrderByDescending(GetLambda<T, TProp>(memberProperty));
}
static Expression<Func<T, TProp>> GetLambda<T, TProp>(PropertyInfo memberProperty)
{
if (memberProperty.PropertyType != typeof(TProp))
throw new Exception();
var thisArg = Expression.Parameter(typeof(T)); var thisArg = Expression.Parameter(typeof(T));
var lamba = Expression.Lambda<Func<T, TProp>>(Expression.Property(thisArg, memberProperty), thisArg); var lamba = Expression.Lambda<Func<T, TProp>>(Expression.Property(thisArg, memberProperty), thisArg);

View File

@@ -21,6 +21,7 @@ using System.Text.RegularExpressions;
using System.Web; using System.Web;
using System.Windows.Forms; using System.Windows.Forms;
using YamlDotNet.Serialization; using YamlDotNet.Serialization;
using YamlDotNet.Serialization.NamingConventions;
using ZXing; using ZXing;
using ZXing.Common; using ZXing.Common;
using ZXing.QrCode; using ZXing.QrCode;
@@ -407,7 +408,7 @@ namespace ClashN
/// </summary> /// </summary>
/// <param name="text"></param> /// <param name="text"></param>
/// <returns></returns> /// <returns></returns>
public static bool IsNullOrEmpty(string text) public static bool IsNullOrEmpty(string? text)
{ {
if (string.IsNullOrEmpty(text)) if (string.IsNullOrEmpty(text))
{ {
@@ -846,13 +847,13 @@ namespace ClashN
string location = GetExePath(); string location = GetExePath();
if (blFull) if (blFull)
{ {
return string.Format("clashN - V{0} - {1}", return string.Format("ClashN - V{0} - {1}",
FileVersionInfo.GetVersionInfo(location).FileVersion?.ToString(), FileVersionInfo.GetVersionInfo(location).FileVersion?.ToString(),
File.GetLastWriteTime(location).ToString("yyyy/MM/dd")); File.GetLastWriteTime(location).ToString("yyyy/MM/dd"));
} }
else else
{ {
return string.Format("clashN/{0}", return string.Format("ClashN/{0}",
FileVersionInfo.GetVersionInfo(location).FileVersion?.ToString()); FileVersionInfo.GetVersionInfo(location).FileVersion?.ToString());
} }
} }
@@ -889,9 +890,9 @@ namespace ClashN
/// 获取剪贴板数 /// 获取剪贴板数
/// </summary> /// </summary>
/// <returns></returns> /// <returns></returns>
public static string GetClipboardData() public static string? GetClipboardData()
{ {
string strData = string.Empty; string? strData = null;
try try
{ {
@@ -900,7 +901,8 @@ namespace ClashN
{ {
strData = data.GetData(DataFormats.UnicodeText).ToString(); strData = data.GetData(DataFormats.UnicodeText).ToString();
} }
if (Utils.IsNullOrEmpty(strData))
if (string.IsNullOrEmpty(strData))
{ {
var file = Clipboard.GetFileDropList(); var file = Clipboard.GetFileDropList();
if (file.Count > 0) if (file.Count > 0)
@@ -915,6 +917,7 @@ namespace ClashN
{ {
SaveLog(ex.Message, ex); SaveLog(ex.Message, ex);
} }
return strData; return strData;
} }
@@ -1099,7 +1102,7 @@ namespace ClashN
} }
} }
public static string GetBinPath(string filename, ECoreType? coreType = null) public static string GetBinPath(string filename, CoreKind? coreType = null)
{ {
string _tempPath = Path.Combine(StartupPath(), "bin"); string _tempPath = Path.Combine(StartupPath(), "bin");
if (!Directory.Exists(_tempPath)) if (!Directory.Exists(_tempPath))
@@ -1223,7 +1226,7 @@ namespace ClashN
public static T FromYaml<T>(string str) public static T FromYaml<T>(string str)
{ {
var deserializer = new DeserializerBuilder() var deserializer = new DeserializerBuilder()
//.WithNamingConvention(UnderscoredNamingConvention.Instance) .WithNamingConvention(PascalCaseNamingConvention.Instance)
.Build(); .Build();
try try
{ {
@@ -1245,7 +1248,7 @@ namespace ClashN
public static string ToYaml(Object obj) public static string ToYaml(Object obj)
{ {
var serializer = new SerializerBuilder() var serializer = new SerializerBuilder()
//.WithNamingConvention(CamelCaseNamingConvention.Instance) .WithNamingConvention(HyphenatedNamingConvention.Instance)
.Build(); .Build();
string result = string.Empty; string result = string.Empty;

View File

@@ -15,6 +15,14 @@ namespace ClashN.ViewModels
public class ConnectionsViewModel : ReactiveObject public class ConnectionsViewModel : ReactiveObject
{ {
private static Config _config; private static Config _config;
static ConnectionsViewModel()
{
_config = LazyConfig.Instance.Config;
}
private NoticeHandler? _noticeHandler; private NoticeHandler? _noticeHandler;
private IObservableCollection<ConnectionModel> _connectionItems = new ObservableCollectionExtended<ConnectionModel>(); private IObservableCollection<ConnectionModel> _connectionItems = new ObservableCollectionExtended<ConnectionModel>();
@@ -35,11 +43,10 @@ namespace ClashN.ViewModels
public ConnectionsViewModel() public ConnectionsViewModel()
{ {
_noticeHandler = Locator.Current.GetService<NoticeHandler>(); _noticeHandler = Locator.Current.GetService<NoticeHandler>();
_config = LazyConfig.Instance.GetConfig();
AutoRefreshInterval = 10; AutoRefreshInterval = 10;
SortingSelected = _config.uiItem.connectionsSorting; SortingSelected = _config.UiItem.connectionsSorting;
AutoRefresh = _config.uiItem.connectionsAutoRefresh; AutoRefresh = _config.UiItem.connectionsAutoRefresh;
var canEditRemove = this.WhenAnyValue( var canEditRemove = this.WhenAnyValue(
x => x.SelectedSource, x => x.SelectedSource,
@@ -47,13 +54,13 @@ namespace ClashN.ViewModels
this.WhenAnyValue( this.WhenAnyValue(
x => x.SortingSelected, x => x.SortingSelected,
y => y != null && y >= 0) y => y >= 0)
.Subscribe(c => DoSortingSelected(c)); .Subscribe(c => DoSortingSelected(c));
this.WhenAnyValue( this.WhenAnyValue(
x => x.AutoRefresh, x => x.AutoRefresh,
y => y == true) y => y == true)
.Subscribe(c => { _config.uiItem.connectionsAutoRefresh = AutoRefresh; }); .Subscribe(c => { _config.UiItem.connectionsAutoRefresh = AutoRefresh; });
ConnectionCloseCmd = ReactiveCommand.Create(() => ConnectionCloseCmd = ReactiveCommand.Create(() =>
{ {
@@ -74,9 +81,9 @@ namespace ClashN.ViewModels
{ {
return; return;
} }
if (SortingSelected != _config.uiItem.connectionsSorting) if (SortingSelected != _config.UiItem.connectionsSorting)
{ {
_config.uiItem.connectionsSorting = SortingSelected; _config.UiItem.connectionsSorting = SortingSelected;
} }
GetClashConnections(); GetClashConnections();
@@ -119,7 +126,7 @@ namespace ClashN.ViewModels
Application.Current.Dispatcher.Invoke((Action)(() => Application.Current.Dispatcher.Invoke((Action)(() =>
{ {
RefreshConnections(it?.connections!); RefreshConnections(it?.Connections!);
})); }));
}); });
} }
@@ -134,10 +141,10 @@ namespace ClashN.ViewModels
{ {
ConnectionModel model = new(); ConnectionModel model = new();
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 = $"{(item.metadata.Host.IsNullOrEmpty() ? 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;
@@ -145,7 +152,7 @@ namespace ClashN.ViewModels
model.uploadTraffic = $"{Utils.HumanFy(item.upload)}"; model.uploadTraffic = $"{Utils.HumanFy(item.upload)}";
model.downloadTraffic = $"{Utils.HumanFy(item.download)}"; model.downloadTraffic = $"{Utils.HumanFy(item.download)}";
model.elapsed = sp.ToString(@"hh\:mm\:ss"); model.elapsed = sp.ToString(@"hh\:mm\:ss");
model.chain = item.chains.Count > 0 ? item.chains[0] : String.Empty; model.chain = item.Chains.Count > 0 ? item.Chains[0] : String.Empty;
lstModel.Add(model); lstModel.Add(model);
} }

View File

@@ -19,7 +19,7 @@ namespace ClashN.ViewModels
public HelpViewModel() public HelpViewModel()
{ {
_config = LazyConfig.Instance.GetConfig(); _config = LazyConfig.Instance.Config;
_noticeHandler = Locator.Current.GetService<NoticeHandler>(); _noticeHandler = Locator.Current.GetService<NoticeHandler>();
CheckUpdateCmd = ReactiveCommand.Create(() => CheckUpdateCmd = ReactiveCommand.Create(() =>
@@ -28,11 +28,11 @@ namespace ClashN.ViewModels
}); });
CheckUpdateClashCoreCmd = ReactiveCommand.Create(() => CheckUpdateClashCoreCmd = ReactiveCommand.Create(() =>
{ {
CheckUpdateCore(ECoreType.clash); CheckUpdateCore(CoreKind.Clash);
}); });
CheckUpdateClashMetaCoreCmd = ReactiveCommand.Create(() => CheckUpdateClashMetaCoreCmd = ReactiveCommand.Create(() =>
{ {
CheckUpdateCore(ECoreType.clash_meta); CheckUpdateCore(CoreKind.ClashMeta);
}); });
} }
@@ -48,7 +48,7 @@ namespace ClashN.ViewModels
}; };
(new UpdateHandle()).CheckUpdateGuiN(_config, _updateUI); (new UpdateHandle()).CheckUpdateGuiN(_config, _updateUI);
} }
private void CheckUpdateCore(ECoreType type) private void CheckUpdateCore(CoreKind type)
{ {
void _updateUI(bool success, string msg) void _updateUI(bool success, string msg)
{ {

View File

@@ -92,7 +92,7 @@ namespace ClashN.ViewModels
public MainWindowViewModel(ISnackbarMessageQueue snackbarMessageQueue) public MainWindowViewModel(ISnackbarMessageQueue snackbarMessageQueue)
{ {
_config = LazyConfig.Instance.GetConfig(); _config = LazyConfig.Instance.Config;
Locator.CurrentMutable.RegisterLazySingleton(() => new NoticeHandler(snackbarMessageQueue), typeof(NoticeHandler)); Locator.CurrentMutable.RegisterLazySingleton(() => new NoticeHandler(snackbarMessageQueue), typeof(NoticeHandler));
_noticeHandler = Locator.Current.GetService<NoticeHandler>(); _noticeHandler = Locator.Current.GetService<NoticeHandler>();
@@ -112,7 +112,7 @@ namespace ClashN.ViewModels
GetPromotionView = new(); GetPromotionView = new();
RestoreUI(); RestoreUI();
if (_config.autoHideStartup) if (_config.AutoHideStartup)
{ {
Observable.Range(1, 1) Observable.Range(1, 1)
.Delay(TimeSpan.FromSeconds(1)) .Delay(TimeSpan.FromSeconds(1))
@@ -129,19 +129,19 @@ namespace ClashN.ViewModels
//System proxy //System proxy
SystemProxyClearCmd = ReactiveCommand.Create(() => SystemProxyClearCmd = ReactiveCommand.Create(() =>
{ {
SetListenerType(ESysProxyType.ForcedClear); SetListenerType(SysProxyType.ForcedClear);
});//, this.WhenAnyValue(x => x.BlSystemProxyClear, y => !y)); });//, this.WhenAnyValue(x => x.BlSystemProxyClear, y => !y));
SystemProxySetCmd = ReactiveCommand.Create(() => SystemProxySetCmd = ReactiveCommand.Create(() =>
{ {
SetListenerType(ESysProxyType.ForcedChange); SetListenerType(SysProxyType.ForcedChange);
});//, this.WhenAnyValue(x => x.BlSystemProxySet, y => !y)); });//, this.WhenAnyValue(x => x.BlSystemProxySet, y => !y));
SystemProxyNothingCmd = ReactiveCommand.Create(() => SystemProxyNothingCmd = ReactiveCommand.Create(() =>
{ {
SetListenerType(ESysProxyType.Unchanged); SetListenerType(SysProxyType.Unchanged);
});//, this.WhenAnyValue(x => x.BlSystemProxyNothing, y => !y)); });//, this.WhenAnyValue(x => x.BlSystemProxyNothing, y => !y));
SystemProxyPacCmd = ReactiveCommand.Create(() => SystemProxyPacCmd = ReactiveCommand.Create(() =>
{ {
SetListenerType(ESysProxyType.Pac); SetListenerType(SysProxyType.Pac);
});//, this.WhenAnyValue(x => x.BlSystemProxyNothing, y => !y)); });//, this.WhenAnyValue(x => x.BlSystemProxyNothing, y => !y));
//Rule mode //Rule mode
@@ -195,18 +195,17 @@ namespace ClashN.ViewModels
{ {
Application.Current.Dispatcher.Invoke((Action)(() => Application.Current.Dispatcher.Invoke((Action)(() =>
{ {
string clipboardData = Utils.GetClipboardData(); string? clipboardData = Utils.GetClipboardData();
if (state != null) if (state != null && clipboardData != null)
{ {
if (Utils.IsNullOrEmpty(clipboardData) || !clipboardData.StartsWith(Global.clashProtocol)) if (string.IsNullOrEmpty(clipboardData) || !clipboardData.StartsWith(Global.clashProtocol))
{ {
return; return;
} }
} }
if (!blFirst) if (!blFirst)
{
ShowHideWindow(true); ShowHideWindow(true);
}
Locator.Current.GetService<ProfilesViewModel>()?.AddProfilesViaClipboard(true); Locator.Current.GetService<ProfilesViewModel>()?.AddProfilesViaClipboard(true);
})); }));
@@ -229,7 +228,7 @@ namespace ClashN.ViewModels
} }
StorageUI(); StorageUI();
ConfigHandler.SaveConfig(ref _config); ConfigProc.SaveConfig(_config);
//statistics?.SaveToFile(); //statistics?.SaveToFile();
statistics?.Close(); statistics?.Close();
} }
@@ -245,20 +244,20 @@ namespace ClashN.ViewModels
{ {
switch (Utils.ToInt(e.Name)) switch (Utils.ToInt(e.Name))
{ {
case (int)EGlobalHotkey.ShowForm: case (int)GlobalHotkeyAction.ShowForm:
ShowHideWindow(null); ShowHideWindow(null);
break; break;
case (int)EGlobalHotkey.SystemProxyClear: case (int)GlobalHotkeyAction.SystemProxyClear:
SetListenerType(ESysProxyType.ForcedClear); SetListenerType(SysProxyType.ForcedClear);
break; break;
case (int)EGlobalHotkey.SystemProxySet: case (int)GlobalHotkeyAction.SystemProxySet:
SetListenerType(ESysProxyType.ForcedChange); SetListenerType(SysProxyType.ForcedChange);
break; break;
case (int)EGlobalHotkey.SystemProxyUnchanged: case (int)GlobalHotkeyAction.SystemProxyUnchanged:
SetListenerType(ESysProxyType.Unchanged); SetListenerType(SysProxyType.Unchanged);
break; break;
case (int)EGlobalHotkey.SystemProxyPac: case (int)GlobalHotkeyAction.SystemProxyPac:
SetListenerType(ESysProxyType.Pac); SetListenerType(SysProxyType.Pac);
break; break;
} }
e.Handled = true; e.Handled = true;
@@ -273,7 +272,7 @@ namespace ClashN.ViewModels
coreHandler = new CoreHandler(UpdateHandler); coreHandler = new CoreHandler(UpdateHandler);
if (_config.enableStatistics) if (_config.EnableStatistics)
{ {
statistics = new StatisticsHandler(_config, UpdateStatisticsHandler); statistics = new StatisticsHandler(_config, UpdateStatisticsHandler);
} }
@@ -346,10 +345,10 @@ namespace ClashN.ViewModels
}); });
Global.reloadCore = false; Global.reloadCore = false;
ConfigHandler.SaveConfig(ref _config, false); ConfigProc.SaveConfig(_config, false);
//statistics?.SaveToFile(); //statistics?.SaveToFile();
ChangePACButtonStatus(_config.sysProxyType); ChangePACButtonStatus(_config.SysProxyType);
SetRuleMode(_config.ruleMode); SetRuleMode(_config.ruleMode);
Locator.Current.GetService<ProxiesViewModel>()?.ProxiesReload(); Locator.Current.GetService<ProxiesViewModel>()?.ProxiesReload();
@@ -359,10 +358,10 @@ namespace ClashN.ViewModels
public void CloseCore() public void CloseCore()
{ {
ConfigHandler.SaveConfig(ref _config, false); ConfigProc.SaveConfig(_config, false);
//statistics?.SaveToFile(); //statistics?.SaveToFile();
ChangePACButtonStatus(ESysProxyType.ForcedClear); ChangePACButtonStatus(SysProxyType.ForcedClear);
coreHandler.CoreStop(); coreHandler.CoreStop();
} }
@@ -370,30 +369,30 @@ namespace ClashN.ViewModels
#region System proxy and Rule mode #region System proxy and Rule mode
public void SetListenerType(ESysProxyType type) public void SetListenerType(SysProxyType type)
{ {
if (_config.sysProxyType == type) if (_config.SysProxyType == type)
{ {
return; return;
} }
_config.sysProxyType = type; _config.SysProxyType = type;
ChangePACButtonStatus(type); ChangePACButtonStatus(type);
Locator.Current.GetService<ProxiesViewModel>()?.ReloadSystemProxySelected(); Locator.Current.GetService<ProxiesViewModel>()?.ReloadSystemProxySelected();
} }
private void ChangePACButtonStatus(ESysProxyType type) private void ChangePACButtonStatus(SysProxyType type)
{ {
SysProxyHandle.UpdateSysProxy(_config, false); SysProxyHandle.UpdateSysProxy(_config, false);
BlSystemProxyClear = (type == ESysProxyType.ForcedClear); BlSystemProxyClear = (type == SysProxyType.ForcedClear);
BlSystemProxySet = (type == ESysProxyType.ForcedChange); BlSystemProxySet = (type == SysProxyType.ForcedChange);
BlSystemProxyNothing = (type == ESysProxyType.Unchanged); BlSystemProxyNothing = (type == SysProxyType.Unchanged);
BlSystemProxyPac = (type == ESysProxyType.Pac); BlSystemProxyPac = (type == SysProxyType.Pac);
_noticeHandler?.SendMessage($"Change system proxy", true); _noticeHandler?.SendMessage($"Change system proxy", true);
ConfigHandler.SaveConfig(ref _config, false); ConfigProc.SaveConfig(_config, false);
//mainMsgControl.DisplayToolStatus(config); //mainMsgControl.DisplayToolStatus(config);
@@ -422,7 +421,7 @@ namespace ClashN.ViewModels
_noticeHandler?.SendMessage($"Set rule mode {_config.ruleMode.ToString()}->{mode.ToString()}", true); _noticeHandler?.SendMessage($"Set rule mode {_config.ruleMode.ToString()}->{mode.ToString()}", true);
_config.ruleMode = mode; _config.ruleMode = mode;
ConfigHandler.SaveConfig(ref _config, false); ConfigProc.SaveConfig(_config, false);
if (mode != ERuleMode.Unchanged) if (mode != ERuleMode.Unchanged)
{ {
@@ -459,11 +458,11 @@ namespace ClashN.ViewModels
private void RestoreUI() private void RestoreUI()
{ {
ModifyTheme(_config.uiItem.colorModeDark); ModifyTheme(_config.UiItem.colorModeDark);
if (!_config.uiItem.colorPrimaryName.IsNullOrEmpty()) if (!_config.UiItem.colorPrimaryName.IsNullOrEmpty())
{ {
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
&& swatch.ExemplarHue != null && swatch.ExemplarHue != null
&& swatch.ExemplarHue?.Color != null) && swatch.ExemplarHue?.Color != null)
@@ -477,10 +476,10 @@ namespace ClashN.ViewModels
// this.Location = config.uiItem.mainLocation; // this.Location = config.uiItem.mainLocation;
//} //}
if (_config.uiItem.mainWidth > 0 && _config.uiItem.mainHeight > 0) if (_config.UiItem.mainWidth > 0 && _config.UiItem.mainHeight > 0)
{ {
Application.Current.MainWindow.Width = _config.uiItem.mainWidth; Application.Current.MainWindow.Width = _config.UiItem.mainWidth;
Application.Current.MainWindow.Height = _config.uiItem.mainHeight; Application.Current.MainWindow.Height = _config.UiItem.mainHeight;
} }
IntPtr hWnd = new WindowInteropHelper(Application.Current.MainWindow).EnsureHandle(); IntPtr hWnd = new WindowInteropHelper(Application.Current.MainWindow).EnsureHandle();
@@ -496,8 +495,8 @@ namespace ClashN.ViewModels
} }
private void StorageUI() private void StorageUI()
{ {
_config.uiItem.mainWidth = Application.Current.MainWindow.Width; _config.UiItem.mainWidth = Application.Current.MainWindow.Width;
_config.uiItem.mainHeight = Application.Current.MainWindow.Height; _config.UiItem.mainHeight = Application.Current.MainWindow.Height;
} }
public void ModifyTheme(bool isDarkTheme) public void ModifyTheme(bool isDarkTheme)

View File

@@ -32,7 +32,7 @@ namespace ClashN.ViewModels
public ProfileEditViewModel(ProfileItem profileItem, PorfileEditWindow view) public ProfileEditViewModel(ProfileItem profileItem, PorfileEditWindow view)
{ {
_noticeHandler = Locator.Current.GetService<NoticeHandler>(); _noticeHandler = Locator.Current.GetService<NoticeHandler>();
_config = LazyConfig.Instance.GetConfig(); _config = LazyConfig.Instance.Config;
if (profileItem.indexId.IsNullOrEmpty()) if (profileItem.indexId.IsNullOrEmpty())
{ {
@@ -44,7 +44,7 @@ namespace ClashN.ViewModels
} }
_view = view; _view = view;
CoreType = (SelectedSource.coreType ?? ECoreType.clash).ToString(); CoreType = (SelectedSource.coreType ?? CoreKind.Clash).ToString();
BrowseProfileCmd = ReactiveCommand.Create(() => BrowseProfileCmd = ReactiveCommand.Create(() =>
{ {
@@ -61,25 +61,25 @@ namespace ClashN.ViewModels
SaveProfile(); SaveProfile();
}); });
Utils.SetDarkBorder(view, _config.uiItem.colorModeDark); Utils.SetDarkBorder(view, _config.UiItem.colorModeDark);
} }
private void SaveProfile() private void SaveProfile()
{ {
string remarks = SelectedSource.remarks; string remarks = SelectedSource.remarks;
if (Utils.IsNullOrEmpty(remarks)) if (string.IsNullOrEmpty(remarks))
{ {
_noticeHandler?.Enqueue(ResUI.PleaseFillRemarks); _noticeHandler?.Enqueue(ResUI.PleaseFillRemarks);
return; return;
} }
if (Utils.IsNullOrEmpty(CoreType)) if (string.IsNullOrEmpty(CoreType))
{ {
SelectedSource.coreType = null; SelectedSource.coreType = null;
} }
else else
{ {
SelectedSource.coreType = (ECoreType)Enum.Parse(typeof(ECoreType), CoreType); SelectedSource.coreType = (CoreKind)Enum.Parse(typeof(CoreKind), CoreType);
} }
var item = _config.GetProfileItem(SelectedSource.indexId); var item = _config.GetProfileItem(SelectedSource.indexId);
@@ -98,7 +98,7 @@ namespace ClashN.ViewModels
item.enableConvert = SelectedSource.enableConvert; item.enableConvert = SelectedSource.enableConvert;
} }
if (ConfigHandler.EditProfile(ref _config, item) == 0) if (ConfigProc.EditProfile(ref _config, item) == 0)
{ {
Locator.Current.GetService<ProfilesViewModel>()?.RefreshProfiles(); Locator.Current.GetService<ProfilesViewModel>()?.RefreshProfiles();
_noticeHandler?.Enqueue(ResUI.OperationSuccess); _noticeHandler?.Enqueue(ResUI.OperationSuccess);
@@ -128,7 +128,7 @@ namespace ClashN.ViewModels
return; return;
} }
string fileName = fileDialog.FileName; string fileName = fileDialog.FileName;
if (Utils.IsNullOrEmpty(fileName)) if (string.IsNullOrEmpty(fileName))
{ {
return; return;
} }
@@ -137,7 +137,7 @@ namespace ClashN.ViewModels
{ {
item = SelectedSource; item = SelectedSource;
} }
if (ConfigHandler.AddProfileViaPath(ref _config, item, fileName) == 0) if (ConfigProc.AddProfileViaPath(ref _config, item, fileName) == 0)
{ {
_noticeHandler?.Enqueue(ResUI.SuccessfullyImportedCustomProfile); _noticeHandler?.Enqueue(ResUI.SuccessfullyImportedCustomProfile);
Locator.Current.GetService<ProfilesViewModel>()?.RefreshProfiles(); Locator.Current.GetService<ProfilesViewModel>()?.RefreshProfiles();
@@ -152,7 +152,7 @@ namespace ClashN.ViewModels
private void EditProfile() private void EditProfile()
{ {
var address = SelectedSource.address; var address = SelectedSource.address;
if (Utils.IsNullOrEmpty(address)) if (string.IsNullOrEmpty(address))
{ {
_noticeHandler?.Enqueue(ResUI.FillProfileAddressCustom); _noticeHandler?.Enqueue(ResUI.FillProfileAddressCustom);
return; return;

View File

@@ -51,7 +51,7 @@ namespace ClashN.ViewModels
public ProfilesViewModel() public ProfilesViewModel()
{ {
_noticeHandler = Locator.Current.GetService<NoticeHandler>(); _noticeHandler = Locator.Current.GetService<NoticeHandler>();
_config = LazyConfig.Instance.GetConfig(); _config = LazyConfig.Instance.Config;
SelectedSource = new(); SelectedSource = new();
@@ -128,7 +128,7 @@ namespace ClashN.ViewModels
ClearStatisticCmd = ReactiveCommand.Create(() => ClearStatisticCmd = ReactiveCommand.Create(() =>
{ {
ConfigHandler.ClearAllServerStatistics(ref _config); ConfigProc.ClearAllServerStatistics(ref _config);
RefreshProfiles(); RefreshProfiles();
}); });
ProfileReloadCmd = ReactiveCommand.Create(() => ProfileReloadCmd = ReactiveCommand.Create(() =>
@@ -144,7 +144,7 @@ namespace ClashN.ViewModels
private void EditLocalFile() private void EditLocalFile()
{ {
var address = SelectedSource.address; var address = SelectedSource.address;
if (Utils.IsNullOrEmpty(address)) if (string.IsNullOrEmpty(address))
{ {
_noticeHandler?.Enqueue(ResUI.FillProfileAddressCustom); _noticeHandler?.Enqueue(ResUI.FillProfileAddressCustom);
return; return;
@@ -168,7 +168,7 @@ namespace ClashN.ViewModels
{ {
item = new() item = new()
{ {
coreType = ECoreType.clash_meta coreType = CoreKind.ClashMeta
}; };
} }
else else
@@ -202,13 +202,13 @@ namespace ClashN.ViewModels
Locator.Current.GetService<MainWindowViewModel>()?.ShowHideWindow(true); Locator.Current.GetService<MainWindowViewModel>()?.ShowHideWindow(true);
if (Utils.IsNullOrEmpty(result)) if (string.IsNullOrEmpty(result))
{ {
_noticeHandler?.Enqueue(ResUI.NoValidQRcodeFound); _noticeHandler?.Enqueue(ResUI.NoValidQRcodeFound);
} }
else else
{ {
int ret = ConfigHandler.AddBatchProfiles(ref _config, result, "", ""); int ret = ConfigProc.AddBatchProfiles(ref _config, result, "", "");
if (ret == 0) if (ret == 0)
{ {
RefreshProfiles(); RefreshProfiles();
@@ -218,12 +218,12 @@ namespace ClashN.ViewModels
} }
public void AddProfilesViaClipboard(bool bClear) public void AddProfilesViaClipboard(bool bClear)
{ {
string clipboardData = Utils.GetClipboardData(); string? clipboardData = Utils.GetClipboardData();
if (Utils.IsNullOrEmpty(clipboardData)) if (string.IsNullOrEmpty(clipboardData))
{ {
return; return;
} }
int ret = ConfigHandler.AddBatchProfiles(ref _config, clipboardData, "", ""); int ret = ConfigProc.AddBatchProfiles(ref _config, clipboardData, "", "");
if (ret == 0) if (ret == 0)
{ {
if (bClear) if (bClear)
@@ -242,8 +242,8 @@ namespace ClashN.ViewModels
{ {
return; return;
} }
var content = ConfigHandler.GetProfileContent(item); var content = ConfigProc.GetProfileContent(item);
if (Utils.IsNullOrEmpty(content)) if (string.IsNullOrEmpty(content))
{ {
content = item.url; content = item.url;
} }
@@ -286,7 +286,7 @@ namespace ClashN.ViewModels
return; return;
} }
ConfigHandler.RemoveProfile(_config, new List<ProfileItem>() { item }); ConfigProc.RemoveProfile(_config, new List<ProfileItem>() { item });
_noticeHandler?.Enqueue(ResUI.OperationSuccess); _noticeHandler?.Enqueue(ResUI.OperationSuccess);
@@ -301,7 +301,7 @@ namespace ClashN.ViewModels
{ {
return; return;
} }
if (ConfigHandler.CopyProfile(ref _config, new List<ProfileItem>() { item }) == 0) if (ConfigProc.CopyProfile(ref _config, new List<ProfileItem>() { item }) == 0)
{ {
_noticeHandler?.Enqueue(ResUI.OperationSuccess); _noticeHandler?.Enqueue(ResUI.OperationSuccess);
RefreshProfiles(); RefreshProfiles();
@@ -309,7 +309,7 @@ namespace ClashN.ViewModels
} }
public void SetDefaultProfile() public void SetDefaultProfile()
{ {
if (Utils.IsNullOrEmpty(SelectedSource?.indexId)) if (string.IsNullOrEmpty(SelectedSource?.indexId))
{ {
return; return;
} }
@@ -320,7 +320,7 @@ namespace ClashN.ViewModels
return; return;
} }
if (ConfigHandler.SetDefaultProfile(ref _config, item) == 0) if (ConfigProc.SetDefaultProfile(ref _config, item) == 0)
{ {
_noticeHandler?.Enqueue(ResUI.OperationSuccess); _noticeHandler?.Enqueue(ResUI.OperationSuccess);
RefreshProfiles(); RefreshProfiles();
@@ -331,13 +331,13 @@ namespace ClashN.ViewModels
public void RefreshProfiles() public void RefreshProfiles()
{ {
ConfigHandler.SetDefaultProfile(_config, _config.profileItems); ConfigProc.SetDefaultProfile(_config, _config.ProfileItems);
var lstModel = new List<ProfileItemModel>(); var lstModel = new List<ProfileItemModel>();
foreach (var item in _config.profileItems.OrderBy(it => it.sort)) foreach (var item in _config.ProfileItems.OrderBy(it => it.sort))
{ {
var model = Utils.FromJson<ProfileItemModel>(Utils.ToJson(item)); var model = Utils.FromJson<ProfileItemModel>(Utils.ToJson(item));
model.isActive = _config.IsActiveNode(item); model.IsActive = _config.IsActiveNode(item);
lstModel.Add(model); lstModel.Add(model);
} }
@@ -354,7 +354,7 @@ namespace ClashN.ViewModels
var targetIndex = _profileItems.IndexOf(targetItem); var targetIndex = _profileItems.IndexOf(targetItem);
if (startIndex >= 0 && targetIndex >= 0 && startIndex != targetIndex) if (startIndex >= 0 && targetIndex >= 0 && startIndex != targetIndex)
{ {
if (ConfigHandler.MoveProfile(ref _config, startIndex, EMove.Position, targetIndex) == 0) if (ConfigProc.MoveProfile(ref _config, startIndex, MovementTarget.Position, targetIndex) == 0)
{ {
RefreshProfiles(); RefreshProfiles();
} }
@@ -368,7 +368,7 @@ namespace ClashN.ViewModels
{ {
return; return;
} }
if (Utils.IsNullOrEmpty(item.url)) if (string.IsNullOrEmpty(item.url))
{ {
return; return;
} }

View File

@@ -54,13 +54,13 @@ namespace ClashN.ViewModels
public ProxiesViewModel() public ProxiesViewModel()
{ {
_noticeHandler = Locator.Current.GetService<NoticeHandler>(); _noticeHandler = Locator.Current.GetService<NoticeHandler>();
_config = LazyConfig.Instance.GetConfig(); _config = LazyConfig.Instance.Config;
SelectedGroup = new(); SelectedGroup = new();
SelectedDetail = new(); SelectedDetail = new();
AutoRefresh = _config.uiItem.proxiesAutoRefresh; AutoRefresh = _config.UiItem.proxiesAutoRefresh;
EnableTun = _config.enableTun; EnableTun = _config.EnableTun;
SortingSelected = _config.uiItem.proxiesSorting; SortingSelected = _config.UiItem.proxiesSorting;
//GetClashProxies(true); //GetClashProxies(true);
this.WhenAnyValue( this.WhenAnyValue(
@@ -70,17 +70,17 @@ namespace ClashN.ViewModels
this.WhenAnyValue( this.WhenAnyValue(
x => x.SystemProxySelected, x => x.SystemProxySelected,
y => y != null && y >= 0) y => y >= 0)
.Subscribe(c => DoSystemProxySelected(c)); .Subscribe(c => DoSystemProxySelected(c));
this.WhenAnyValue( this.WhenAnyValue(
x => x.RuleModeSelected, x => x.RuleModeSelected,
y => y != null && y >= 0) y => y >= 0)
.Subscribe(c => DoRulemodeSelected(c)); .Subscribe(c => DoRulemodeSelected(c));
this.WhenAnyValue( this.WhenAnyValue(
x => x.SortingSelected, x => x.SortingSelected,
y => y != null && y >= 0) y => y >= 0)
.Subscribe(c => DoSortingSelected(c)); .Subscribe(c => DoSortingSelected(c));
this.WhenAnyValue( this.WhenAnyValue(
@@ -91,7 +91,7 @@ namespace ClashN.ViewModels
this.WhenAnyValue( this.WhenAnyValue(
x => x.AutoRefresh, x => x.AutoRefresh,
y => y == true) y => y == true)
.Subscribe(c => { _config.uiItem.proxiesAutoRefresh = AutoRefresh; }); .Subscribe(c => { _config.UiItem.proxiesAutoRefresh = AutoRefresh; });
ProxiesReloadCmd = ReactiveCommand.Create(() => ProxiesReloadCmd = ReactiveCommand.Create(() =>
{ {
@@ -123,11 +123,11 @@ namespace ClashN.ViewModels
{ {
return; return;
} }
if (_config.sysProxyType == (ESysProxyType)SystemProxySelected) if (_config.SysProxyType == (SysProxyType)SystemProxySelected)
{ {
return; return;
} }
Locator.Current.GetService<MainWindowViewModel>()?.SetListenerType((ESysProxyType)SystemProxySelected); Locator.Current.GetService<MainWindowViewModel>()?.SetListenerType((SysProxyType)SystemProxySelected);
} }
void DoRulemodeSelected(bool c) void DoRulemodeSelected(bool c)
{ {
@@ -148,9 +148,9 @@ namespace ClashN.ViewModels
{ {
return; return;
} }
if (SortingSelected != _config.uiItem.proxiesSorting) if (SortingSelected != _config.UiItem.proxiesSorting)
{ {
_config.uiItem.proxiesSorting = SortingSelected; _config.UiItem.proxiesSorting = SortingSelected;
} }
RefreshProxyDetails(c); RefreshProxyDetails(c);
@@ -186,7 +186,7 @@ namespace ClashN.ViewModels
} }
public void ReloadSystemProxySelected() public void ReloadSystemProxySelected()
{ {
SystemProxySelected = (int)_config.sysProxyType; SystemProxySelected = (int)_config.SysProxyType;
} }
public void ReloadRulemodeSelected() public void ReloadRulemodeSelected()
{ {
@@ -195,9 +195,9 @@ namespace ClashN.ViewModels
void DoEnableTun(bool c) void DoEnableTun(bool c)
{ {
if (_config.enableTun != EnableTun) if (_config.EnableTun != EnableTun)
{ {
_config.enableTun = EnableTun; _config.EnableTun = EnableTun;
TunModeSwitch(); TunModeSwitch();
} }
} }
@@ -242,7 +242,7 @@ namespace ClashN.ViewModels
{ {
foreach (var it in proxyGroups) foreach (var it in proxyGroups)
{ {
if (Utils.IsNullOrEmpty(it.name) || !proxies.ContainsKey(it.name)) if (string.IsNullOrEmpty(it.name) || !proxies.ContainsKey(it.name))
{ {
continue; continue;
} }
@@ -298,7 +298,7 @@ namespace ClashN.ViewModels
return; return;
} }
var name = SelectedGroup?.name; var name = SelectedGroup?.name;
if (Utils.IsNullOrEmpty(name)) if (string.IsNullOrEmpty(name))
{ {
return; return;
} }
@@ -388,12 +388,12 @@ namespace ClashN.ViewModels
return; return;
} }
var name = SelectedGroup.name; var name = SelectedGroup.name;
if (Utils.IsNullOrEmpty(name)) if (string.IsNullOrEmpty(name))
{ {
return; return;
} }
var nameNode = SelectedDetail.name; var nameNode = SelectedDetail.name;
if (Utils.IsNullOrEmpty(nameNode)) if (string.IsNullOrEmpty(nameNode))
{ {
return; return;
} }
@@ -437,7 +437,7 @@ namespace ClashN.ViewModels
GetClashProxies(true); GetClashProxies(true);
return; return;
} }
if (Utils.IsNullOrEmpty(result)) if (string.IsNullOrEmpty(result))
{ {
return; return;
} }
@@ -485,9 +485,9 @@ namespace ClashN.ViewModels
} }
var dtNow = DateTime.Now; var dtNow = DateTime.Now;
if (_config.autoDelayTestInterval > 0) if (_config.AutoDelayTestInterval > 0)
{ {
if ((dtNow - autoDelayTestTime).Minutes % _config.autoDelayTestInterval == 0) if ((dtNow - autoDelayTestTime).Minutes % _config.AutoDelayTestInterval == 0)
{ {
ProxiesDelayTest(); ProxiesDelayTest();
autoDelayTestTime = dtNow; autoDelayTestTime = dtNow;

View File

@@ -93,31 +93,31 @@ namespace ClashN.ViewModels
public SettingsViewModel() public SettingsViewModel()
{ {
_config = LazyConfig.Instance.GetConfig(); _config = LazyConfig.Instance.Config;
//Core //Core
MixedPort = _config.mixedPort; MixedPort = _config.MixedPort;
SocksPort = _config.socksPort; SocksPort = _config.SocksPort;
HttpPort = _config.httpPort; HttpPort = _config.HttpPort;
APIPort = _config.APIPort; APIPort = _config.ApiPort;
AllowLANConn = _config.allowLANConn; AllowLANConn = _config.AllowLANConn;
EnableIpv6 = _config.enableIpv6; EnableIpv6 = _config.EnableIpv6;
LogLevel = _config.logLevel; LogLevel = _config.LogLevel;
EnableMixinContent = _config.enableMixinContent; EnableMixinContent = _config.EnableMixinContent;
EditMixinContentCmd = ReactiveCommand.Create(() => EditMixinContentCmd = ReactiveCommand.Create(() =>
{ {
EditMixinContent(); EditMixinContent();
}, this.IsValid()); }, this.IsValid());
//clashN //clashN
AutoRun = _config.autoRun; AutoRun = _config.AutoRun;
EnableStatistics = _config.enableStatistics; EnableStatistics = _config.EnableStatistics;
EnableSecurityProtocolTls13 = _config.enableSecurityProtocolTls13; EnableSecurityProtocolTls13 = _config.EnableSecurityProtocolTls13;
autoUpdateSubInterval = _config.autoUpdateSubInterval; autoUpdateSubInterval = _config.AutoUpdateSubInterval;
autoDelayTestInterval = _config.autoDelayTestInterval; autoDelayTestInterval = _config.AutoDelayTestInterval;
SubConvertUrl = _config.constItem.subConvertUrl; SubConvertUrl = _config.ConstItem.subConvertUrl;
currentFontFamily = _config.uiItem.currentFontFamily; currentFontFamily = _config.UiItem.currentFontFamily;
AutoHideStartup = _config.autoHideStartup; AutoHideStartup = _config.AutoHideStartup;
SetLoopbackCmd = ReactiveCommand.Create(() => SetLoopbackCmd = ReactiveCommand.Create(() =>
{ {
@@ -134,30 +134,30 @@ namespace ClashN.ViewModels
}, this.IsValid()); }, this.IsValid());
//System proxy //System proxy
systemProxyExceptions = _config.systemProxyExceptions; systemProxyExceptions = _config.SystemProxyExceptions;
systemProxyAdvancedProtocol = _config.systemProxyAdvancedProtocol; systemProxyAdvancedProtocol = _config.SystemProxyAdvancedProtocol;
PacPort = _config.PacPort; PacPort = _config.PacPort;
//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 (!_config.UiItem.colorPrimaryName.IsNullOrEmpty())
{ {
SelectedSwatch = _swatches.FirstOrDefault(t => t.Name == _config.uiItem.colorPrimaryName); SelectedSwatch = _swatches.FirstOrDefault(t => t.Name == _config.UiItem.colorPrimaryName);
} }
CurrentLanguage = Utils.RegReadValue(Global.MyRegPath, Global.MyRegKeyLanguage, Global.Languages[0]); CurrentLanguage = Utils.RegReadValue(Global.MyRegPath, Global.MyRegKeyLanguage, Global.Languages[0]);
CurrentFontSize = _config.uiItem.currentFontSize; CurrentFontSize = _config.UiItem.currentFontSize;
this.WhenAnyValue( this.WhenAnyValue(
x => x.ColorModeDark, x => x.ColorModeDark,
y => y == true) y => y == true)
.Subscribe(c => .Subscribe(c =>
{ {
if (_config.uiItem.colorModeDark != ColorModeDark) if (_config.UiItem.colorModeDark != ColorModeDark)
{ {
_config.uiItem.colorModeDark = ColorModeDark; _config.UiItem.colorModeDark = ColorModeDark;
Locator.Current.GetService<MainWindowViewModel>()?.ModifyTheme(ColorModeDark); Locator.Current.GetService<MainWindowViewModel>()?.ModifyTheme(ColorModeDark);
ConfigHandler.SaveConfig(ref _config); ConfigProc.SaveConfig(_config);
} }
}); });
@@ -173,11 +173,11 @@ namespace ClashN.ViewModels
{ {
return; return;
} }
if (_config.uiItem.colorPrimaryName != SelectedSwatch?.Name) if (_config.UiItem.colorPrimaryName != SelectedSwatch?.Name)
{ {
_config.uiItem.colorPrimaryName = SelectedSwatch?.Name; _config.UiItem.colorPrimaryName = SelectedSwatch?.Name;
Locator.Current.GetService<MainWindowViewModel>()?.ChangePrimaryColor(SelectedSwatch.ExemplarHue.Color); Locator.Current.GetService<MainWindowViewModel>()?.ChangePrimaryColor(SelectedSwatch.ExemplarHue.Color);
ConfigHandler.SaveConfig(ref _config); ConfigProc.SaveConfig(_config);
} }
}); });
@@ -186,7 +186,7 @@ namespace ClashN.ViewModels
y => y != null && !y.IsNullOrEmpty()) y => y != null && !y.IsNullOrEmpty())
.Subscribe(c => .Subscribe(c =>
{ {
if (!Utils.IsNullOrEmpty(CurrentLanguage)) if (!string.IsNullOrEmpty(CurrentLanguage))
{ {
Utils.RegWriteValue(Global.MyRegPath, Global.MyRegKeyLanguage, CurrentLanguage); Utils.RegWriteValue(Global.MyRegPath, Global.MyRegKeyLanguage, CurrentLanguage);
Thread.CurrentThread.CurrentUICulture = new System.Globalization.CultureInfo(CurrentLanguage); Thread.CurrentThread.CurrentUICulture = new System.Globalization.CultureInfo(CurrentLanguage);
@@ -198,11 +198,11 @@ namespace ClashN.ViewModels
y => y > 0) y => y > 0)
.Subscribe(c => .Subscribe(c =>
{ {
if (_config.uiItem.colorModeDark != ColorModeDark) if (_config.UiItem.colorModeDark != ColorModeDark)
{ {
_config.uiItem.colorModeDark = ColorModeDark; _config.UiItem.colorModeDark = ColorModeDark;
Locator.Current.GetService<MainWindowViewModel>()?.ModifyTheme(ColorModeDark); Locator.Current.GetService<MainWindowViewModel>()?.ModifyTheme(ColorModeDark);
ConfigHandler.SaveConfig(ref _config); ConfigProc.SaveConfig(_config);
} }
}); });
@@ -213,14 +213,14 @@ namespace ClashN.ViewModels
{ {
if (CurrentFontSize >= Global.MinFontSize) if (CurrentFontSize >= Global.MinFontSize)
{ {
_config.uiItem.currentFontSize = CurrentFontSize; _config.UiItem.currentFontSize = CurrentFontSize;
double size = (long)CurrentFontSize; double size = (long)CurrentFontSize;
Application.Current.Resources["StdFontSize1"] = size; Application.Current.Resources["StdFontSize1"] = size;
Application.Current.Resources["StdFontSize2"] = size + 1; Application.Current.Resources["StdFontSize2"] = size + 1;
Application.Current.Resources["StdFontSize3"] = size + 2; Application.Current.Resources["StdFontSize3"] = size + 2;
Application.Current.Resources["StdFontSize4"] = size + 3; Application.Current.Resources["StdFontSize4"] = size + 3;
ConfigHandler.SaveConfig(ref _config); ConfigProc.SaveConfig(_config);
} }
}); });
@@ -235,32 +235,32 @@ namespace ClashN.ViewModels
void SaveConfig() void SaveConfig()
{ {
//Core //Core
_config.mixedPort = MixedPort; _config.MixedPort = MixedPort;
_config.socksPort = SocksPort; _config.SocksPort = SocksPort;
_config.httpPort = HttpPort; _config.HttpPort = HttpPort;
_config.APIPort = APIPort; _config.ApiPort = APIPort;
_config.allowLANConn = AllowLANConn; _config.AllowLANConn = AllowLANConn;
_config.enableIpv6 = EnableIpv6; _config.EnableIpv6 = EnableIpv6;
_config.logLevel = LogLevel; _config.LogLevel = LogLevel;
_config.enableMixinContent = EnableMixinContent; _config.EnableMixinContent = EnableMixinContent;
//clashN //clashN
Utils.SetAutoRun(AutoRun); Utils.SetAutoRun(AutoRun);
_config.autoRun = AutoRun; _config.AutoRun = AutoRun;
_config.enableStatistics = EnableStatistics; _config.EnableStatistics = EnableStatistics;
_config.enableSecurityProtocolTls13 = EnableSecurityProtocolTls13; _config.EnableSecurityProtocolTls13 = EnableSecurityProtocolTls13;
_config.autoUpdateSubInterval = autoUpdateSubInterval; _config.AutoUpdateSubInterval = autoUpdateSubInterval;
_config.autoDelayTestInterval = autoDelayTestInterval; _config.AutoDelayTestInterval = autoDelayTestInterval;
_config.constItem.subConvertUrl = SubConvertUrl; _config.ConstItem.subConvertUrl = SubConvertUrl;
_config.uiItem.currentFontFamily = currentFontFamily; _config.UiItem.currentFontFamily = currentFontFamily;
_config.autoHideStartup = AutoHideStartup; _config.AutoHideStartup = AutoHideStartup;
//System proxy //System proxy
_config.systemProxyExceptions = systemProxyExceptions; _config.SystemProxyExceptions = systemProxyExceptions;
_config.systemProxyAdvancedProtocol = systemProxyAdvancedProtocol; _config.SystemProxyAdvancedProtocol = systemProxyAdvancedProtocol;
_config.PacPort = PacPort; _config.PacPort = PacPort;
if (ConfigHandler.SaveConfig(ref _config) == 0) if (ConfigProc.SaveConfig(_config) == 0)
{ {
Locator.Current.GetService<NoticeHandler>()?.Enqueue(ResUI.OperationSuccess); Locator.Current.GetService<NoticeHandler>()?.Enqueue(ResUI.OperationSuccess);
Locator.Current.GetService<MainWindowViewModel>()?.LoadCore(); Locator.Current.GetService<MainWindowViewModel>()?.LoadCore();
@@ -278,7 +278,7 @@ namespace ClashN.ViewModels
if (!File.Exists(address)) if (!File.Exists(address))
{ {
string contents = Utils.GetEmbedText(Global.SampleMixin); string contents = Utils.GetEmbedText(Global.SampleMixin);
if (!Utils.IsNullOrEmpty(contents)) if (!string.IsNullOrEmpty(contents))
{ {
File.WriteAllText(address, contents); File.WriteAllText(address, contents);
} }

View File

@@ -14,28 +14,23 @@ namespace ClashN.Views
public partial class GlobalHotkeySettingWindow public partial class GlobalHotkeySettingWindow
{ {
private static Config _config; private static Config _config;
List<KeyEventItem> lstKey; List<KeyShortcut> lstKey;
public GlobalHotkeySettingWindow() public GlobalHotkeySettingWindow()
{ {
InitializeComponent(); InitializeComponent();
_config = LazyConfig.Instance.GetConfig(); _config = LazyConfig.Instance.Config;
if (_config.globalHotkeys == null) foreach (GlobalHotkeyAction it in Enum.GetValues(typeof(GlobalHotkeyAction)))
{ {
_config.globalHotkeys = new List<KeyEventItem>(); if (_config.globalHotkeys.FindIndex(t => t.GlobalHotkey == it) >= 0)
}
foreach (EGlobalHotkey it in Enum.GetValues(typeof(EGlobalHotkey)))
{
if (_config.globalHotkeys.FindIndex(t => t.eGlobalHotkey == it) >= 0)
{ {
continue; continue;
} }
_config.globalHotkeys.Add(new KeyEventItem() _config.globalHotkeys.Add(new KeyShortcut()
{ {
eGlobalHotkey = it, GlobalHotkey = it,
Alt = false, Alt = false,
Control = false, Control = false,
Shift = false, Shift = false,
@@ -53,7 +48,7 @@ namespace ClashN.Views
BindingData(-1); BindingData(-1);
Utils.SetDarkBorder(this, _config.uiItem.colorModeDark); Utils.SetDarkBorder(this, _config.UiItem.colorModeDark);
} }
@@ -66,10 +61,13 @@ namespace ClashN.Views
return; return;
var formsKey = (Forms.Keys)KeyInterop.VirtualKeyFromKey(e.Key); var formsKey = (Forms.Keys)KeyInterop.VirtualKeyFromKey(e.Key);
lstKey[index].KeyCode = formsKey; lstKey[index] = new KeyShortcut()
lstKey[index].Alt = Keyboard.IsKeyDown(Key.LeftAlt) || Keyboard.IsKeyDown(Key.RightAlt); {
lstKey[index].Control = Keyboard.IsKeyDown(Key.LeftCtrl) || Keyboard.IsKeyDown(Key.RightCtrl); KeyCode = formsKey,
lstKey[index].Shift = Keyboard.IsKeyDown(Key.LeftShift) || Keyboard.IsKeyDown(Key.RightShift); Alt = Keyboard.IsKeyDown(Key.LeftAlt) || Keyboard.IsKeyDown(Key.RightAlt),
Control = Keyboard.IsKeyDown(Key.LeftCtrl) || Keyboard.IsKeyDown(Key.RightCtrl),
Shift = Keyboard.IsKeyDown(Key.LeftShift) || Keyboard.IsKeyDown(Key.RightShift),
};
BindingData(index); BindingData(index);
} }
@@ -108,9 +106,10 @@ namespace ClashN.Views
private void btnSave_Click(object sender, RoutedEventArgs e) private void btnSave_Click(object sender, RoutedEventArgs e)
{ {
_config.globalHotkeys = lstKey; _config.globalHotkeys.Clear();
_config.globalHotkeys.AddRange(lstKey);
if (ConfigHandler.SaveConfig(ref _config, false) == 0) if (ConfigProc.SaveConfig(_config, false) == 0)
{ {
this.Close(); this.Close();
} }
@@ -128,16 +127,16 @@ namespace ClashN.Views
private void btnReset_Click(object sender, RoutedEventArgs e) private void btnReset_Click(object sender, RoutedEventArgs e)
{ {
lstKey.Clear(); lstKey.Clear();
foreach (EGlobalHotkey it in Enum.GetValues(typeof(EGlobalHotkey))) foreach (GlobalHotkeyAction it in Enum.GetValues(typeof(GlobalHotkeyAction)))
{ {
if (lstKey.FindIndex(t => t.eGlobalHotkey == it) >= 0) if (lstKey.FindIndex(t => t.GlobalHotkey == it) >= 0)
{ {
continue; continue;
} }
lstKey.Add(new KeyEventItem() lstKey.Add(new KeyShortcut()
{ {
eGlobalHotkey = it, GlobalHotkey = it,
Alt = false, Alt = false,
Control = false, Control = false,
Shift = false, Shift = false,

View File

@@ -41,7 +41,7 @@ namespace ClashN.Views
return; return;
} }
string? msgFilter = ViewModel?.MsgFilter; string? msgFilter = ViewModel?.MsgFilter;
if (!Utils.IsNullOrEmpty(msgFilter)) if (!string.IsNullOrEmpty(msgFilter))
{ {
if (!Regex.IsMatch(msg, msgFilter)) if (!Regex.IsMatch(msg, msgFilter))
{ {

View File

@@ -22,7 +22,7 @@ namespace ClashN.Views
public void AppendText(string msg) public void AppendText(string msg)
{ {
//if (!Utils.IsNullOrEmpty(MsgFilter)) //if (!string.IsNullOrEmpty(MsgFilter))
//{ //{
// if (!Regex.IsMatch(text, MsgFilter)) // if (!Regex.IsMatch(text, MsgFilter))
// { // {

View File

@@ -19,7 +19,7 @@ namespace ClashN.Views
public SettingsView() public SettingsView()
{ {
InitializeComponent(); InitializeComponent();
_config = LazyConfig.Instance.GetConfig(); _config = LazyConfig.Instance.Config;
ViewModel = new SettingsViewModel(); ViewModel = new SettingsViewModel();
Global.SubConvertUrls.ForEach(it => Global.SubConvertUrls.ForEach(it =>
@@ -66,10 +66,10 @@ namespace ClashN.Views
// continue; // continue;
//} //}
var fontFamily = glyph.Win32FamilyNames[new CultureInfo(culture)]; var fontFamily = glyph.Win32FamilyNames[new CultureInfo(culture)];
if (Utils.IsNullOrEmpty(fontFamily)) if (string.IsNullOrEmpty(fontFamily))
{ {
fontFamily = glyph.Win32FamilyNames[new CultureInfo(culture2)]; fontFamily = glyph.Win32FamilyNames[new CultureInfo(culture2)];
if (Utils.IsNullOrEmpty(fontFamily)) if (string.IsNullOrEmpty(fontFamily))
{ {
continue; continue;
} }