Compare commits
41 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
790209efbc | ||
|
|
f1679e444c | ||
|
|
9dc6ba182a | ||
|
|
785a30e623 | ||
|
|
f09efdad66 | ||
|
|
4e73b3ae28 | ||
|
|
6213f86f81 | ||
|
|
0a6955cd59 | ||
|
|
6ee8f03ec0 | ||
|
|
b1a82d95c2 | ||
|
|
30bc9ded29 | ||
|
|
5a32892e94 | ||
|
|
e33de896b6 | ||
|
|
3ba92444a5 | ||
|
|
4f120e8eb4 | ||
|
|
08aebf5736 | ||
|
|
5a4966ba8d | ||
|
|
9ba963fc45 | ||
|
|
ccc10dbae4 | ||
|
|
d858342269 | ||
|
|
63f251d1fd | ||
|
|
83efe66f3e | ||
|
|
3f5729044f | ||
|
|
045af7e8df | ||
|
|
6f181053b2 | ||
|
|
4ff1dc2982 | ||
|
|
a883ba8808 | ||
|
|
961bd6140c | ||
|
|
5f364b48c9 | ||
|
|
5a04911c7c | ||
|
|
8ff248aa62 | ||
|
|
046ac95dc3 | ||
|
|
6fb17a4b74 | ||
|
|
f84397393d | ||
|
|
800c93e2aa | ||
|
|
df6179a1a8 | ||
|
|
3e3a079ba1 | ||
|
|
0bf4a43663 | ||
|
|
5e9f4ad926 | ||
|
|
ba702ba041 | ||
|
|
c40d88d0b6 |
1
.gitignore
vendored
1
.gitignore
vendored
@@ -16,3 +16,4 @@
|
||||
/v2rayN/v2rayUpgrade/bin/Release
|
||||
/v2rayN/v2rayUpgrade/obj/
|
||||
*.user
|
||||
/.vs/v2rayN
|
||||
|
||||
@@ -42,10 +42,11 @@ namespace v2rayN
|
||||
Global.processJob = new Job();
|
||||
|
||||
Logging.Setup();
|
||||
Init();
|
||||
Logging.LoggingEnabled(_config.guiItem.enableLog);
|
||||
Utils.SaveLog($"v2rayN start up | {Utils.GetVersion()} | {Utils.GetExePath()}");
|
||||
Logging.ClearLogs();
|
||||
|
||||
Init();
|
||||
|
||||
Thread.CurrentThread.CurrentUICulture = new(_config.uiItem.currentLanguage);
|
||||
|
||||
|
||||
@@ -115,7 +115,7 @@ namespace v2rayN.Base
|
||||
}
|
||||
}
|
||||
};
|
||||
progress.Report("......");
|
||||
//progress.Report("......");
|
||||
|
||||
using var stream = await downloader.DownloadFileTaskAsync(address: url, cancellationToken: cancellationToken.Token);
|
||||
|
||||
|
||||
@@ -25,11 +25,18 @@ namespace v2rayN.Base
|
||||
return _db.CreateTable<T>();
|
||||
}
|
||||
|
||||
public int Add(object model)
|
||||
public int Insert(object model)
|
||||
{
|
||||
return _db.Insert(model);
|
||||
}
|
||||
public async Task<int> AddAsync(object model)
|
||||
public int InsertAll(IEnumerable models)
|
||||
{
|
||||
lock (objLock)
|
||||
{
|
||||
return _db.InsertAll(models);
|
||||
}
|
||||
}
|
||||
public async Task<int> InsertAsync(object model)
|
||||
{
|
||||
return await _dbAsync.InsertAsync(model);
|
||||
}
|
||||
|
||||
@@ -43,7 +43,7 @@
|
||||
public const string directTag = "direct";
|
||||
public const string blockTag = "block";
|
||||
public const string StreamSecurity = "tls";
|
||||
public const string StreamSecurityX = "xtls";
|
||||
public const string StreamSecurityReality = "reality";
|
||||
public const string InboundSocks = "socks";
|
||||
public const string InboundHttp = "http";
|
||||
public const string InboundSocks2 = "socks2";
|
||||
@@ -92,7 +92,7 @@
|
||||
public static readonly List<string> ssSecuritys = new() { "aes-256-gcm", "aes-128-gcm", "chacha20-poly1305", "chacha20-ietf-poly1305", "none", "plain" };
|
||||
public static readonly List<string> ssSecuritysInSagerNet = new() { "none", "2022-blake3-aes-128-gcm", "2022-blake3-aes-256-gcm", "2022-blake3-chacha20-poly1305", "aes-128-gcm", "aes-192-gcm", "aes-256-gcm", "chacha20-ietf-poly1305", "xchacha20-ietf-poly1305", "rc4", "rc4-md5", "aes-128-ctr", "aes-192-ctr", "aes-256-ctr", "aes-128-cfb", "aes-192-cfb", "aes-256-cfb", "aes-128-cfb8", "aes-192-cfb8", "aes-256-cfb8", "aes-128-ofb", "aes-192-ofb", "aes-256-ofb", "bf-cfb", "cast5-cfb", "des-cfb", "idea-cfb", "rc2-cfb", "seed-cfb", "camellia-128-cfb", "camellia-192-cfb", "camellia-256-cfb", "camellia-128-cfb8", "camellia-192-cfb8", "camellia-256-cfb8", "salsa20", "chacha20", "chacha20-ietf", "xchacha20" };
|
||||
public static readonly List<string> ssSecuritysInXray = new() { "aes-256-gcm", "aes-128-gcm", "chacha20-poly1305", "chacha20-ietf-poly1305", "xchacha20-poly1305", "xchacha20-ietf-poly1305", "none", "plain", "2022-blake3-aes-128-gcm", "2022-blake3-aes-256-gcm", "2022-blake3-chacha20-poly1305" };
|
||||
public static readonly List<string> xtlsFlows = new() { "", "xtls-rprx-origin", "xtls-rprx-origin-udp443", "xtls-rprx-direct", "xtls-rprx-direct-udp443", "xtls-rprx-vision", "xtls-rprx-vision-udp443" };
|
||||
public static readonly List<string> flows = new() { "", "xtls-rprx-vision", "xtls-rprx-vision-udp443" };
|
||||
public static readonly List<string> networks = new() { "tcp", "kcp", "ws", "h2", "quic", "grpc" };
|
||||
public static readonly List<string> kcpHeaderTypes = new() { "srtp", "utp", "wechat-video", "dtls", "wireguard" };
|
||||
public static readonly List<string> coreTypes = new() { "v2fly", "SagerNet", "Xray", "v2fly_v5" };
|
||||
|
||||
@@ -352,7 +352,7 @@ namespace v2rayN.Handler
|
||||
/// <param name="config"></param>
|
||||
/// <param name="profileItem"></param>
|
||||
/// <returns></returns>
|
||||
public static int AddServer(ref Config config, ProfileItem profileItem)
|
||||
public static int AddServer(ref Config config, ProfileItem profileItem, bool toFile = true)
|
||||
{
|
||||
profileItem.configType = EConfigType.VMess;
|
||||
|
||||
@@ -370,7 +370,7 @@ namespace v2rayN.Handler
|
||||
return -1;
|
||||
}
|
||||
|
||||
AddServerCommon(ref config, profileItem);
|
||||
AddServerCommon(ref config, profileItem, toFile);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -383,11 +383,15 @@ namespace v2rayN.Handler
|
||||
/// <returns></returns>
|
||||
public static int RemoveServer(Config config, List<ProfileItem> indexs)
|
||||
{
|
||||
var subid = "TempRemoveSubId";
|
||||
foreach (var item in indexs)
|
||||
{
|
||||
RemoveProfileItem(config, item.indexId);
|
||||
item.subid = subid;
|
||||
}
|
||||
|
||||
SqliteHelper.Instance.UpdateAll(indexs);
|
||||
RemoveServerViaSubid(ref config, subid, false);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -399,8 +403,14 @@ namespace v2rayN.Handler
|
||||
/// <returns></returns>
|
||||
public static int CopyServer(ref Config config, List<ProfileItem> indexs)
|
||||
{
|
||||
foreach (var item in indexs)
|
||||
foreach (var it in indexs)
|
||||
{
|
||||
var item = LazyConfig.Instance.GetProfileItem(it.indexId);
|
||||
if (item is null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
ProfileItem profileItem = Utils.DeepCopy(item);
|
||||
profileItem.indexId = string.Empty;
|
||||
profileItem.remarks = $"{item.remarks}-clone";
|
||||
@@ -414,7 +424,7 @@ namespace v2rayN.Handler
|
||||
}
|
||||
else
|
||||
{
|
||||
AddServerCommon(ref config, profileItem);
|
||||
AddServerCommon(ref config, profileItem, true);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -447,8 +457,7 @@ namespace v2rayN.Handler
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
var allItems = LazyConfig.Instance.ProfileItemIndexs("");
|
||||
if (allItems.Where(t => t == config.indexId).Any())
|
||||
if (SqliteHelper.Instance.Table<ProfileItem>().Where(t => t.indexId == config.indexId).Any())
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
@@ -456,11 +465,7 @@ namespace v2rayN.Handler
|
||||
{
|
||||
return SetDefaultServerIndex(ref config, lstProfile[0].indexId);
|
||||
}
|
||||
if (allItems.Count > 0)
|
||||
{
|
||||
return SetDefaultServerIndex(ref config, allItems.FirstOrDefault());
|
||||
}
|
||||
return -1;
|
||||
return SetDefaultServerIndex(ref config, SqliteHelper.Instance.Table<ProfileItem>().Select(t => t.indexId).FirstOrDefault());
|
||||
}
|
||||
public static ProfileItem? GetDefaultServer(ref Config config)
|
||||
{
|
||||
@@ -588,7 +593,7 @@ namespace v2rayN.Handler
|
||||
}
|
||||
|
||||
|
||||
AddServerCommon(ref config, profileItem);
|
||||
AddServerCommon(ref config, profileItem, true);
|
||||
|
||||
|
||||
return 0;
|
||||
@@ -620,7 +625,7 @@ namespace v2rayN.Handler
|
||||
/// <param name="config"></param>
|
||||
/// <param name="profileItem"></param>
|
||||
/// <returns></returns>
|
||||
public static int AddShadowsocksServer(ref Config config, ProfileItem profileItem)
|
||||
public static int AddShadowsocksServer(ref Config config, ProfileItem profileItem, bool toFile = true)
|
||||
{
|
||||
profileItem.configType = EConfigType.Shadowsocks;
|
||||
|
||||
@@ -633,7 +638,7 @@ namespace v2rayN.Handler
|
||||
return -1;
|
||||
}
|
||||
|
||||
AddServerCommon(ref config, profileItem);
|
||||
AddServerCommon(ref config, profileItem, toFile);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -644,13 +649,13 @@ namespace v2rayN.Handler
|
||||
/// <param name="config"></param>
|
||||
/// <param name="profileItem"></param>
|
||||
/// <returns></returns>
|
||||
public static int AddSocksServer(ref Config config, ProfileItem profileItem)
|
||||
public static int AddSocksServer(ref Config config, ProfileItem profileItem, bool toFile = true)
|
||||
{
|
||||
profileItem.configType = EConfigType.Socks;
|
||||
|
||||
profileItem.address = profileItem.address.TrimEx();
|
||||
|
||||
AddServerCommon(ref config, profileItem);
|
||||
AddServerCommon(ref config, profileItem, toFile);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -661,7 +666,7 @@ namespace v2rayN.Handler
|
||||
/// <param name="config"></param>
|
||||
/// <param name="profileItem"></param>
|
||||
/// <returns></returns>
|
||||
public static int AddTrojanServer(ref Config config, ProfileItem profileItem)
|
||||
public static int AddTrojanServer(ref Config config, ProfileItem profileItem, bool toFile = true)
|
||||
{
|
||||
profileItem.configType = EConfigType.Trojan;
|
||||
|
||||
@@ -671,12 +676,8 @@ namespace v2rayN.Handler
|
||||
{
|
||||
profileItem.streamSecurity = Global.StreamSecurity;
|
||||
}
|
||||
if (Utils.IsNullOrEmpty(profileItem.allowInsecure))
|
||||
{
|
||||
profileItem.allowInsecure = config.coreBasicItem.defAllowInsecure.ToString().ToLower();
|
||||
}
|
||||
|
||||
AddServerCommon(ref config, profileItem);
|
||||
AddServerCommon(ref config, profileItem, toFile);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -781,7 +782,7 @@ namespace v2rayN.Handler
|
||||
/// <param name="config"></param>
|
||||
/// <param name="profileItem"></param>
|
||||
/// <returns></returns>
|
||||
public static int AddVlessServer(ref Config config, ProfileItem profileItem)
|
||||
public static int AddVlessServer(ref Config config, ProfileItem profileItem, bool toFile = true)
|
||||
{
|
||||
profileItem.configType = EConfigType.VLESS;
|
||||
|
||||
@@ -794,43 +795,51 @@ namespace v2rayN.Handler
|
||||
profileItem.path = profileItem.path.TrimEx();
|
||||
profileItem.streamSecurity = profileItem.streamSecurity.TrimEx();
|
||||
|
||||
AddServerCommon(ref config, profileItem);
|
||||
AddServerCommon(ref config, profileItem, toFile);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
public static int DedupServerList(ref Config config, ref List<ProfileItem> lstProfile)
|
||||
public static Tuple<int, int> DedupServerList(Config config, string subId)
|
||||
{
|
||||
List<ProfileItem> source = lstProfile;
|
||||
bool keepOlder = config.guiItem.keepOlderDedupl;
|
||||
var lstProfile = LazyConfig.Instance.ProfileItems(subId);
|
||||
|
||||
List<ProfileItem> list = new();
|
||||
if (!keepOlder) source.Reverse(); // Remove the early items first
|
||||
List<ProfileItem> lstKeep = new();
|
||||
List<ProfileItem> lstRemove = new();
|
||||
if (config.guiItem.keepOlderDedupl) lstProfile.Reverse();
|
||||
|
||||
foreach (ProfileItem item in source)
|
||||
foreach (ProfileItem item in lstProfile)
|
||||
{
|
||||
if (!list.Exists(i => CompareProfileItem(i, item, false)))
|
||||
if (!lstKeep.Exists(i => CompareProfileItem(i, item, false)))
|
||||
{
|
||||
list.Add(item);
|
||||
lstKeep.Add(item);
|
||||
}
|
||||
else
|
||||
{
|
||||
RemoveProfileItem(config, item.indexId);
|
||||
lstRemove.Add(item);
|
||||
}
|
||||
}
|
||||
//if (!keepOlder) list.Reverse();
|
||||
//config.vmess = list;
|
||||
RemoveServer(config, lstRemove);
|
||||
|
||||
return list.Count;
|
||||
return new Tuple<int, int>(lstProfile.Count, lstKeep.Count);
|
||||
}
|
||||
|
||||
public static int AddServerCommon(ref Config config, ProfileItem profileItem)
|
||||
public static int AddServerCommon(ref Config config, ProfileItem profileItem, bool toFile = true)
|
||||
{
|
||||
profileItem.configVersion = 2;
|
||||
if (Utils.IsNullOrEmpty(profileItem.allowInsecure))
|
||||
|
||||
if (!Utils.IsNullOrEmpty(profileItem.streamSecurity))
|
||||
{
|
||||
profileItem.allowInsecure = config.coreBasicItem.defAllowInsecure.ToString().ToLower();
|
||||
if (Utils.IsNullOrEmpty(profileItem.allowInsecure))
|
||||
{
|
||||
profileItem.allowInsecure = config.coreBasicItem.defAllowInsecure.ToString().ToLower();
|
||||
}
|
||||
if (Utils.IsNullOrEmpty(profileItem.fingerprint))
|
||||
{
|
||||
profileItem.fingerprint = config.coreBasicItem.defFingerprint;
|
||||
}
|
||||
}
|
||||
|
||||
if (!Utils.IsNullOrEmpty(profileItem.network) && !Global.networks.Contains(profileItem.network))
|
||||
{
|
||||
profileItem.network = Global.DefaultNetwork;
|
||||
@@ -842,18 +851,12 @@ namespace v2rayN.Handler
|
||||
var maxSort = ProfileExHandler.Instance.GetMaxSort();
|
||||
ProfileExHandler.Instance.SetSort(profileItem.indexId, maxSort + 1);
|
||||
}
|
||||
else if (profileItem.indexId == config.indexId)
|
||||
{
|
||||
}
|
||||
|
||||
if (SqliteHelper.Instance.Replace(profileItem) > 0)
|
||||
if (toFile)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
return -1;
|
||||
SqliteHelper.Instance.Replace(profileItem);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
private static bool CompareProfileItem(ProfileItem o, ProfileItem n, bool remarks)
|
||||
@@ -930,11 +933,7 @@ namespace v2rayN.Handler
|
||||
}
|
||||
|
||||
int countServers = 0;
|
||||
//var maxSort = 0;
|
||||
//if (SqliteHelper.Instance.Table<ProfileItem>().Count() > 0)
|
||||
//{
|
||||
// maxSort = SqliteHelper.Instance.Table<ProfileItem>().Max(t => t.sort);
|
||||
//}
|
||||
List<ProfileItem> lstAdd = new();
|
||||
string[] arrData = clipboardData.Split(Environment.NewLine.ToCharArray());
|
||||
foreach (string str in arrData)
|
||||
{
|
||||
@@ -956,7 +955,7 @@ namespace v2rayN.Handler
|
||||
//exist sub items
|
||||
if (isSub && !Utils.IsNullOrEmpty(subid))
|
||||
{
|
||||
var existItem = lstOriSub?.FirstOrDefault(t => CompareProfileItem(t, profileItem, true));
|
||||
var existItem = lstOriSub?.FirstOrDefault(t => t.isSub == isSub && CompareProfileItem(t, profileItem, true));
|
||||
if (existItem != null)
|
||||
{
|
||||
profileItem.indexId = existItem.indexId;
|
||||
@@ -972,43 +971,39 @@ namespace v2rayN.Handler
|
||||
}
|
||||
profileItem.subid = subid;
|
||||
profileItem.isSub = isSub;
|
||||
//profileItem.sort = maxSort + countServers + 1;
|
||||
var addStatus = -1;
|
||||
|
||||
if (profileItem.configType == EConfigType.VMess)
|
||||
{
|
||||
if (AddServer(ref config, profileItem) == 0)
|
||||
{
|
||||
countServers++;
|
||||
}
|
||||
addStatus = AddServer(ref config, profileItem, false);
|
||||
}
|
||||
else if (profileItem.configType == EConfigType.Shadowsocks)
|
||||
{
|
||||
if (AddShadowsocksServer(ref config, profileItem) == 0)
|
||||
{
|
||||
countServers++;
|
||||
}
|
||||
addStatus = AddShadowsocksServer(ref config, profileItem, false);
|
||||
}
|
||||
else if (profileItem.configType == EConfigType.Socks)
|
||||
{
|
||||
if (AddSocksServer(ref config, profileItem) == 0)
|
||||
{
|
||||
countServers++;
|
||||
}
|
||||
addStatus = AddSocksServer(ref config, profileItem, false);
|
||||
}
|
||||
else if (profileItem.configType == EConfigType.Trojan)
|
||||
{
|
||||
if (AddTrojanServer(ref config, profileItem) == 0)
|
||||
{
|
||||
countServers++;
|
||||
}
|
||||
addStatus = AddTrojanServer(ref config, profileItem, false);
|
||||
}
|
||||
else if (profileItem.configType == EConfigType.VLESS)
|
||||
{
|
||||
if (AddVlessServer(ref config, profileItem) == 0)
|
||||
{
|
||||
countServers++;
|
||||
}
|
||||
addStatus = AddVlessServer(ref config, profileItem, false);
|
||||
}
|
||||
|
||||
if (addStatus == 0)
|
||||
{
|
||||
countServers++;
|
||||
lstAdd.Add(profileItem);
|
||||
}
|
||||
}
|
||||
|
||||
if (lstAdd.Count > 0)
|
||||
{
|
||||
SqliteHelper.Instance.InsertAll(lstAdd);
|
||||
}
|
||||
|
||||
ToJsonFile(config);
|
||||
@@ -1260,6 +1255,7 @@ namespace v2rayN.Handler
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
var customProfile = SqliteHelper.Instance.Table<ProfileItem>().Where(t => t.subid == subid && t.configType == EConfigType.Custom).ToList();
|
||||
if (isSub)
|
||||
{
|
||||
SqliteHelper.Instance.Execute($"delete from ProfileItem where isSub = 1 and subid = '{subid}'");
|
||||
@@ -1268,6 +1264,10 @@ namespace v2rayN.Handler
|
||||
{
|
||||
SqliteHelper.Instance.Execute($"delete from ProfileItem where subid = '{subid}'");
|
||||
}
|
||||
foreach (var item in customProfile)
|
||||
{
|
||||
File.Delete(Utils.GetConfigPath(item.address));
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -456,17 +456,9 @@ namespace v2rayN.Handler
|
||||
|
||||
boundStreamSettings(node, "out", outbound.streamSettings);
|
||||
|
||||
//if xtls
|
||||
if (node.streamSecurity == Global.StreamSecurityX)
|
||||
if (node.streamSecurity == Global.StreamSecurityReality)
|
||||
{
|
||||
if (Utils.IsNullOrEmpty(node.flow))
|
||||
{
|
||||
usersItem.flow = Global.xtlsFlows[1];
|
||||
}
|
||||
else
|
||||
{
|
||||
usersItem.flow = node.flow.Replace("splice", "direct");
|
||||
}
|
||||
usersItem.flow = node.flow;
|
||||
|
||||
outbound.mux.enabled = false;
|
||||
outbound.mux.concurrency = -1;
|
||||
@@ -505,22 +497,6 @@ namespace v2rayN.Handler
|
||||
serversItem.ota = false;
|
||||
serversItem.level = 1;
|
||||
|
||||
//if xtls
|
||||
if (node.streamSecurity == Global.StreamSecurityX)
|
||||
{
|
||||
if (Utils.IsNullOrEmpty(node.flow))
|
||||
{
|
||||
serversItem.flow = Global.xtlsFlows[1];
|
||||
}
|
||||
else
|
||||
{
|
||||
serversItem.flow = node.flow.Replace("splice", "direct");
|
||||
}
|
||||
|
||||
outbound.mux.enabled = false;
|
||||
outbound.mux.concurrency = -1;
|
||||
}
|
||||
|
||||
outbound.mux.enabled = false;
|
||||
outbound.mux.concurrency = -1;
|
||||
|
||||
@@ -581,26 +557,21 @@ namespace v2rayN.Handler
|
||||
streamSettings.tlsSettings = tlsSettings;
|
||||
}
|
||||
|
||||
//if xtls
|
||||
if (node.streamSecurity == Global.StreamSecurityX)
|
||||
//if Reality
|
||||
if (node.streamSecurity == Global.StreamSecurityReality)
|
||||
{
|
||||
streamSettings.security = node.streamSecurity;
|
||||
|
||||
TlsSettings xtlsSettings = new()
|
||||
TlsSettings realitySettings = new()
|
||||
{
|
||||
allowInsecure = Utils.ToBool(node.allowInsecure.IsNullOrEmpty() ? config.coreBasicItem.defAllowInsecure.ToString().ToLower() : node.allowInsecure),
|
||||
alpn = node.GetAlpn(),
|
||||
fingerprint = node.fingerprint.IsNullOrEmpty() ? config.coreBasicItem.defFingerprint : node.fingerprint
|
||||
fingerprint = node.fingerprint.IsNullOrEmpty() ? config.coreBasicItem.defFingerprint : node.fingerprint,
|
||||
serverName = sni,
|
||||
publicKey = node.publicKey,
|
||||
shortId = node.shortId,
|
||||
spiderX = node.spiderX,
|
||||
};
|
||||
if (!string.IsNullOrWhiteSpace(sni))
|
||||
{
|
||||
xtlsSettings.serverName = sni;
|
||||
}
|
||||
else if (!string.IsNullOrWhiteSpace(host))
|
||||
{
|
||||
xtlsSettings.serverName = Utils.String2List(host)[0];
|
||||
}
|
||||
streamSettings.xtlsSettings = xtlsSettings;
|
||||
|
||||
streamSettings.realitySettings = realitySettings;
|
||||
}
|
||||
|
||||
//streamSettings
|
||||
@@ -660,13 +631,6 @@ namespace v2rayN.Handler
|
||||
}
|
||||
streamSettings.wsSettings = wsSettings;
|
||||
|
||||
//TlsSettings tlsSettings = new TlsSettings();
|
||||
//tlsSettings.allowInsecure = config.allowInsecure();
|
||||
//if (!string.IsNullOrWhiteSpace(host))
|
||||
//{
|
||||
// tlsSettings.serverName = host;
|
||||
//}
|
||||
//streamSettings.tlsSettings = tlsSettings;
|
||||
break;
|
||||
//h2
|
||||
case "h2":
|
||||
@@ -680,9 +644,6 @@ namespace v2rayN.Handler
|
||||
|
||||
streamSettings.httpSettings = httpSettings;
|
||||
|
||||
//TlsSettings tlsSettings2 = new TlsSettings();
|
||||
//tlsSettings2.allowInsecure = config.allowInsecure();
|
||||
//streamSettings.tlsSettings = tlsSettings2;
|
||||
break;
|
||||
//quic
|
||||
case "quic":
|
||||
@@ -718,7 +679,6 @@ namespace v2rayN.Handler
|
||||
permit_without_stream = config.grpcItem.permit_without_stream,
|
||||
initial_windows_size = config.grpcItem.initial_windows_size,
|
||||
};
|
||||
|
||||
streamSettings.grpcSettings = grpcSettings;
|
||||
break;
|
||||
default:
|
||||
@@ -1430,7 +1390,7 @@ namespace v2rayN.Handler
|
||||
Utils.SaveLog(ex.Message, ex);
|
||||
}
|
||||
|
||||
log(configCopy, ref v2rayConfig, false);
|
||||
log(configCopy, ref v2rayConfig, true);
|
||||
//routing(config, ref v2rayConfig);
|
||||
//dns(configCopy, ref v2rayConfig);
|
||||
|
||||
|
||||
@@ -156,6 +156,7 @@ namespace v2rayN.Handler
|
||||
if (Utils.IsNullOrEmpty(fileName))
|
||||
{
|
||||
string msg = string.Format(ResUI.NotFoundCore, Utils.GetBinPath("", coreInfo.coreType), string.Join(", ", coreInfo.coreExes.ToArray()), coreInfo.coreUrl);
|
||||
Utils.SaveLog(msg);
|
||||
ShowMsg(false, msg);
|
||||
}
|
||||
return fileName;
|
||||
@@ -213,6 +214,7 @@ namespace v2rayN.Handler
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Utils.SaveLog(Utils.ToJson(node));
|
||||
Utils.SaveLog(ex.Message, ex);
|
||||
string msg = ex.Message;
|
||||
ShowMsg(true, msg);
|
||||
|
||||
172
v2rayN/v2rayN/Handler/HotkeyHandler.cs
Normal file
172
v2rayN/v2rayN/Handler/HotkeyHandler.cs
Normal file
@@ -0,0 +1,172 @@
|
||||
using System.ComponentModel;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text;
|
||||
using System.Windows;
|
||||
using System.Windows.Input;
|
||||
using System.Windows.Interop;
|
||||
using v2rayN.Mode;
|
||||
using v2rayN.Resx;
|
||||
|
||||
namespace v2rayN.Handler
|
||||
{
|
||||
public sealed class HotkeyHandler
|
||||
{
|
||||
private static readonly Lazy<HotkeyHandler> _instance = new(() => new());
|
||||
public static HotkeyHandler Instance = _instance.Value;
|
||||
|
||||
private const int WmHotkey = 0x0312;
|
||||
private Config _config
|
||||
{
|
||||
get => LazyConfig.Instance.GetConfig();
|
||||
}
|
||||
private Dictionary<int, List<EGlobalHotkey>> _hotkeyTriggerDic;
|
||||
|
||||
public bool IsPause { get; set; } = false;
|
||||
public event Action<bool, string>? UpdateViewEvent;
|
||||
public event Action<EGlobalHotkey>? HotkeyTriggerEvent;
|
||||
public HotkeyHandler()
|
||||
{
|
||||
_hotkeyTriggerDic = new();
|
||||
ComponentDispatcher.ThreadPreprocessMessage += OnThreadPreProcessMessage;
|
||||
Init();
|
||||
}
|
||||
|
||||
private void Init()
|
||||
{
|
||||
_hotkeyTriggerDic.Clear();
|
||||
if (_config.globalHotkeys == null) return;
|
||||
foreach (var item in _config.globalHotkeys)
|
||||
{
|
||||
if (item.KeyCode != null && item.KeyCode != Key.None)
|
||||
{
|
||||
int key = KeyInterop.VirtualKeyFromKey((Key)item.KeyCode);
|
||||
KeyModifiers modifiers = KeyModifiers.None;
|
||||
if (item.Control) modifiers |= KeyModifiers.Ctrl;
|
||||
if (item.Shift) modifiers |= KeyModifiers.Shift;
|
||||
if (item.Alt) modifiers |= KeyModifiers.Alt;
|
||||
key = (key << 16) | (int)modifiers;
|
||||
if (!_hotkeyTriggerDic.ContainsKey(key))
|
||||
{
|
||||
_hotkeyTriggerDic.Add(key, new() { item.eGlobalHotkey });
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!_hotkeyTriggerDic[key].Contains(item.eGlobalHotkey))
|
||||
_hotkeyTriggerDic[key].Add(item.eGlobalHotkey);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
public void Load()
|
||||
{
|
||||
foreach (var _hotkeyCode in _hotkeyTriggerDic.Keys)
|
||||
{
|
||||
var hotkeyInfo = GetHotkeyInfo(_hotkeyCode);
|
||||
bool isSuccess = false;
|
||||
string msg;
|
||||
|
||||
Application.Current.Dispatcher.Invoke(() =>
|
||||
{
|
||||
isSuccess = RegisterHotKey(IntPtr.Zero, _hotkeyCode, hotkeyInfo.fsModifiers, hotkeyInfo.vKey);
|
||||
});
|
||||
foreach (var name in hotkeyInfo.Names)
|
||||
{
|
||||
if (isSuccess)
|
||||
{
|
||||
msg = string.Format(ResUI.RegisterGlobalHotkeySuccessfully, $"{name}({hotkeyInfo.hotkeyStr})");
|
||||
}
|
||||
else
|
||||
{
|
||||
var errInfo = new Win32Exception(Marshal.GetLastWin32Error()).Message;
|
||||
msg = string.Format(ResUI.RegisterGlobalHotkeyFailed, $"{name}({hotkeyInfo.hotkeyStr})", errInfo);
|
||||
}
|
||||
UpdateViewEvent?.Invoke(false, msg);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
public void ReLoad()
|
||||
{
|
||||
foreach (var hotkey in _hotkeyTriggerDic.Keys)
|
||||
{
|
||||
Application.Current.Dispatcher.Invoke(() =>
|
||||
{
|
||||
UnregisterHotKey(IntPtr.Zero, hotkey);
|
||||
});
|
||||
}
|
||||
Init();
|
||||
Load();
|
||||
}
|
||||
private (int fsModifiers, int vKey, string hotkeyStr, List<string> Names) GetHotkeyInfo(int hotkeycode)
|
||||
{
|
||||
var _fsModifiers = hotkeycode & 0xffff;
|
||||
var _vkey = (hotkeycode >> 16) & 0xffff;
|
||||
var _hotkeyStr = new StringBuilder();
|
||||
var _names = new List<string>();
|
||||
|
||||
var mdif = (KeyModifiers)_fsModifiers;
|
||||
var key = KeyInterop.KeyFromVirtualKey(_vkey);
|
||||
if ((mdif | KeyModifiers.Ctrl) == KeyModifiers.Ctrl) _hotkeyStr.Append($"{KeyModifiers.Ctrl}+");
|
||||
if ((mdif | KeyModifiers.Alt) == KeyModifiers.Alt) _hotkeyStr.Append($"{KeyModifiers.Alt}+");
|
||||
if ((mdif | KeyModifiers.Shift) == KeyModifiers.Shift) _hotkeyStr.Append($"{KeyModifiers.Shift}+");
|
||||
_hotkeyStr.Append(key.ToString());
|
||||
|
||||
foreach (var name in _hotkeyTriggerDic[hotkeycode])
|
||||
{
|
||||
_names.Add(name.ToString());
|
||||
}
|
||||
|
||||
|
||||
return (_fsModifiers, _vkey, _hotkeyStr.ToString(), _names);
|
||||
}
|
||||
private void OnThreadPreProcessMessage(ref MSG msg, ref bool handled)
|
||||
{
|
||||
if (msg.message != WmHotkey || !_hotkeyTriggerDic.ContainsKey((int)msg.lParam))
|
||||
{
|
||||
return;
|
||||
}
|
||||
handled = true;
|
||||
var _hotKeyCode = (int)msg.lParam;
|
||||
if (IsPause)
|
||||
{
|
||||
Application.Current.Dispatcher.Invoke(() =>
|
||||
{
|
||||
UIElement? element = Keyboard.FocusedElement as UIElement;
|
||||
if (element != null)
|
||||
{
|
||||
var _keyEventArgs = new KeyEventArgs(Keyboard.PrimaryDevice,
|
||||
PresentationSource.FromVisual(element), 0,
|
||||
KeyInterop.KeyFromVirtualKey(GetHotkeyInfo(_hotKeyCode).vKey))
|
||||
{
|
||||
RoutedEvent = UIElement.KeyDownEvent
|
||||
};
|
||||
element.RaiseEvent(_keyEventArgs);
|
||||
}
|
||||
});
|
||||
}
|
||||
else
|
||||
{
|
||||
foreach (var keyEvent in _hotkeyTriggerDic[(int)msg.lParam])
|
||||
{
|
||||
HotkeyTriggerEvent?.Invoke(keyEvent);
|
||||
}
|
||||
}
|
||||
}
|
||||
[DllImport("user32.dll", SetLastError = true)]
|
||||
private static extern bool RegisterHotKey(IntPtr hWnd, int id, int fsModifiers, int vlc);
|
||||
|
||||
[DllImport("user32.dll", SetLastError = true)]
|
||||
private static extern bool UnregisterHotKey(IntPtr hWnd, int id);
|
||||
[Flags]
|
||||
private enum KeyModifiers
|
||||
{
|
||||
None = 0x0000,
|
||||
Alt = 0x0001,
|
||||
Ctrl = 0x0002,
|
||||
Shift = 0x0004,
|
||||
Win = 0x0008,
|
||||
NoRepeat = 0x4000
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -112,7 +112,7 @@ namespace v2rayN.Handler
|
||||
{
|
||||
filter = filter.Replace("'", "");
|
||||
}
|
||||
sql += $" and a.remarks like '%{filter}%'";
|
||||
sql += String.Format(" and (a.remarks like '%{0}%' or a.address like '%{0}%') ", filter);
|
||||
}
|
||||
|
||||
return SqliteHelper.Instance.Query<ProfileItemModel>(sql).ToList();
|
||||
|
||||
@@ -1,9 +1,7 @@
|
||||
using NHotkey;
|
||||
using NHotkey.Wpf;
|
||||
|
||||
using System.Drawing;
|
||||
using System.IO;
|
||||
using System.Windows.Forms;
|
||||
using System.Windows.Input;
|
||||
using System.Windows.Media.Imaging;
|
||||
using v2rayN.Mode;
|
||||
using v2rayN.Resx;
|
||||
@@ -343,48 +341,11 @@ namespace v2rayN.Handler
|
||||
}
|
||||
}
|
||||
|
||||
public void RegisterGlobalHotkey(Config config, EventHandler<HotkeyEventArgs> handler, Action<bool, string> update)
|
||||
public void RegisterGlobalHotkey(Config config, Action<EGlobalHotkey> handler, Action<bool, string> update)
|
||||
{
|
||||
if (config.globalHotkeys == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
foreach (var item in config.globalHotkeys)
|
||||
{
|
||||
if (item.KeyCode == null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
var modifiers = ModifierKeys.None;
|
||||
if (item.Control)
|
||||
{
|
||||
modifiers |= ModifierKeys.Control;
|
||||
}
|
||||
if (item.Alt)
|
||||
{
|
||||
modifiers |= ModifierKeys.Alt;
|
||||
}
|
||||
if (item.Shift)
|
||||
{
|
||||
modifiers |= ModifierKeys.Shift;
|
||||
}
|
||||
|
||||
var gesture = new KeyGesture(KeyInterop.KeyFromVirtualKey((int)item.KeyCode), modifiers);
|
||||
try
|
||||
{
|
||||
HotkeyManager.Current.AddOrReplace(((int)item.eGlobalHotkey).ToString(), gesture, handler);
|
||||
var msg = string.Format(ResUI.RegisterGlobalHotkeySuccessfully, $"{item.eGlobalHotkey}");
|
||||
update(false, msg);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
var msg = string.Format(ResUI.RegisterGlobalHotkeyFailed, $"{item.eGlobalHotkey}", ex.Message);
|
||||
update(false, msg);
|
||||
Utils.SaveLog(msg);
|
||||
}
|
||||
}
|
||||
HotkeyHandler.Instance.UpdateViewEvent += update;
|
||||
HotkeyHandler.Instance.HotkeyTriggerEvent += handler;
|
||||
HotkeyHandler.Instance.Load();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -197,6 +197,18 @@ namespace v2rayN.Handler
|
||||
{
|
||||
dicQuery.Add("fp", Utils.UrlEncode(item.fingerprint));
|
||||
}
|
||||
if (!Utils.IsNullOrEmpty(item.publicKey))
|
||||
{
|
||||
dicQuery.Add("pbk", Utils.UrlEncode(item.publicKey));
|
||||
}
|
||||
if (!Utils.IsNullOrEmpty(item.shortId))
|
||||
{
|
||||
dicQuery.Add("sid", Utils.UrlEncode(item.shortId));
|
||||
}
|
||||
if (!Utils.IsNullOrEmpty(item.spiderX))
|
||||
{
|
||||
dicQuery.Add("spx", Utils.UrlEncode(item.spiderX));
|
||||
}
|
||||
|
||||
dicQuery.Add("type", !Utils.IsNullOrEmpty(item.network) ? item.network : "tcp");
|
||||
|
||||
@@ -756,6 +768,10 @@ namespace v2rayN.Handler
|
||||
item.sni = query["sni"] ?? "";
|
||||
item.alpn = Utils.UrlDecode(query["alpn"] ?? "");
|
||||
item.fingerprint = Utils.UrlDecode(query["fp"] ?? "");
|
||||
item.publicKey = Utils.UrlDecode(query["pbk"] ?? "");
|
||||
item.shortId = Utils.UrlDecode(query["sid"] ?? "");
|
||||
item.spiderX = Utils.UrlDecode(query["spx"] ?? "");
|
||||
|
||||
item.network = query["type"] ?? "tcp";
|
||||
switch (item.network)
|
||||
{
|
||||
|
||||
@@ -58,11 +58,11 @@ namespace v2rayN.Handler
|
||||
ProfileExHandler.Instance.SetTestDelay(it.indexId, "0");
|
||||
break;
|
||||
case ESpeedActionType.Speedtest:
|
||||
UpdateFunc(it.indexId, "", ResUI.Speedtesting);
|
||||
UpdateFunc(it.indexId, "", ResUI.SpeedtestingWait);
|
||||
ProfileExHandler.Instance.SetTestSpeed(it.indexId, "0");
|
||||
break;
|
||||
case ESpeedActionType.Mixedtest:
|
||||
UpdateFunc(it.indexId, ResUI.Speedtesting, ResUI.Speedtesting);
|
||||
UpdateFunc(it.indexId, ResUI.Speedtesting, ResUI.SpeedtestingWait);
|
||||
ProfileExHandler.Instance.SetTestDelay(it.indexId, "0");
|
||||
ProfileExHandler.Instance.SetTestSpeed(it.indexId, "0");
|
||||
break;
|
||||
@@ -236,6 +236,7 @@ namespace v2rayN.Handler
|
||||
// continue;
|
||||
//}
|
||||
ProfileExHandler.Instance.SetTestSpeed(it.indexId, "-1");
|
||||
UpdateFunc(it.indexId, "", ResUI.Speedtesting);
|
||||
|
||||
var item = LazyConfig.Instance.GetProfileItem(it.indexId);
|
||||
if (item is null) continue;
|
||||
@@ -287,6 +288,7 @@ namespace v2rayN.Handler
|
||||
continue;
|
||||
}
|
||||
ProfileExHandler.Instance.SetTestSpeed(it.indexId, "-1");
|
||||
UpdateFunc(it.indexId, "", ResUI.Speedtesting);
|
||||
|
||||
var item = LazyConfig.Instance.GetProfileItem(it.indexId);
|
||||
if (item is null) continue;
|
||||
|
||||
@@ -175,24 +175,20 @@ namespace v2rayN.Handler
|
||||
|
||||
foreach (var item in subItem)
|
||||
{
|
||||
if (item.enabled == false)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
if (!Utils.IsNullOrEmpty(subId) && item.id != subId)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
string id = item.id.TrimEx();
|
||||
string url = item.url.TrimEx();
|
||||
string userAgent = item.userAgent.TrimEx();
|
||||
string hashCode = $"{item.remarks}->";
|
||||
if (Utils.IsNullOrEmpty(id) || Utils.IsNullOrEmpty(url))
|
||||
if (Utils.IsNullOrEmpty(id) || Utils.IsNullOrEmpty(url) || (!Utils.IsNullOrEmpty(subId) && item.id != subId))
|
||||
{
|
||||
//_updateFunc(false, $"{hashCode}{ResUI.MsgNoValidSubscription}");
|
||||
continue;
|
||||
}
|
||||
if (item.enabled == false)
|
||||
{
|
||||
_updateFunc(false, $"{hashCode}{ResUI.MsgSkipSubscriptionUpdate}");
|
||||
continue;
|
||||
}
|
||||
|
||||
var downloadHandle = new DownloadHandle();
|
||||
downloadHandle.Error += (sender2, args) =>
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
using System.Windows.Forms;
|
||||
|
||||
using System.Windows.Input;
|
||||
namespace v2rayN.Mode
|
||||
{
|
||||
[Serializable]
|
||||
@@ -104,6 +103,10 @@ namespace v2rayN.Mode
|
||||
public bool enableSecurityProtocolTls13 { get; set; }
|
||||
|
||||
public int trayMenuServersLimit { get; set; } = 20;
|
||||
|
||||
public bool enableHWA { get; set; } = false;
|
||||
|
||||
public bool enableLog { get; set; } = true;
|
||||
}
|
||||
|
||||
[Serializable]
|
||||
@@ -144,7 +147,7 @@ namespace v2rayN.Mode
|
||||
|
||||
public bool Shift { get; set; }
|
||||
|
||||
public Keys? KeyCode { get; set; }
|
||||
public Key? KeyCode { get; set; }
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -85,158 +85,100 @@ namespace v2rayN.Mode
|
||||
#endregion
|
||||
|
||||
[PrimaryKey]
|
||||
public string indexId
|
||||
{
|
||||
get; set;
|
||||
}
|
||||
public string indexId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// config type(1=normal,2=custom)
|
||||
/// </summary>
|
||||
public EConfigType configType
|
||||
{
|
||||
get; set;
|
||||
}
|
||||
|
||||
public EConfigType configType { get; set; }
|
||||
/// <summary>
|
||||
/// 版本(现在=2)
|
||||
/// </summary>
|
||||
public int configVersion
|
||||
{
|
||||
get; set;
|
||||
}
|
||||
public int configVersion { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 远程服务器地址
|
||||
/// </summary>
|
||||
public string address
|
||||
{
|
||||
get; set;
|
||||
}
|
||||
public string address { get; set; }
|
||||
/// <summary>
|
||||
/// 远程服务器端口
|
||||
/// </summary>
|
||||
public int port
|
||||
{
|
||||
get; set;
|
||||
}
|
||||
public int port { get; set; }
|
||||
/// <summary>
|
||||
/// 远程服务器ID
|
||||
/// </summary>
|
||||
public string id
|
||||
{
|
||||
get; set;
|
||||
}
|
||||
public string id { get; set; }
|
||||
/// <summary>
|
||||
/// 远程服务器额外ID
|
||||
/// </summary>
|
||||
public int alterId
|
||||
{
|
||||
get; set;
|
||||
}
|
||||
public int alterId { get; set; }
|
||||
/// <summary>
|
||||
/// 本地安全策略
|
||||
/// </summary>
|
||||
public string security
|
||||
{
|
||||
get; set;
|
||||
}
|
||||
public string security { get; set; }
|
||||
/// <summary>
|
||||
/// tcp,kcp,ws,h2,quic
|
||||
/// </summary>
|
||||
public string network
|
||||
{
|
||||
get; set;
|
||||
}
|
||||
public string network { get; set; }
|
||||
/// <summary>
|
||||
/// 备注或别名
|
||||
/// </summary>
|
||||
public string remarks
|
||||
{
|
||||
get; set;
|
||||
}
|
||||
public string remarks { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 伪装类型
|
||||
/// </summary>
|
||||
public string headerType
|
||||
{
|
||||
get; set;
|
||||
}
|
||||
public string headerType { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 伪装的域名
|
||||
/// </summary>
|
||||
public string requestHost
|
||||
{
|
||||
get; set;
|
||||
}
|
||||
public string requestHost { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// ws h2 path
|
||||
/// </summary>
|
||||
public string path
|
||||
{
|
||||
get; set;
|
||||
}
|
||||
public string path { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 传输层安全
|
||||
/// </summary>
|
||||
public string streamSecurity
|
||||
{
|
||||
get; set;
|
||||
}
|
||||
public string streamSecurity { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 是否允许不安全连接(用于客户端)
|
||||
/// </summary>
|
||||
public string allowInsecure
|
||||
{
|
||||
get; set;
|
||||
}
|
||||
public string allowInsecure { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// SubItem id
|
||||
/// </summary>
|
||||
public string subid
|
||||
{
|
||||
get; set;
|
||||
}
|
||||
public string subid { get; set; }
|
||||
public bool isSub { get; set; } = true;
|
||||
|
||||
/// <summary>
|
||||
/// VLESS flow
|
||||
/// </summary>
|
||||
public string flow
|
||||
{
|
||||
get; set;
|
||||
}
|
||||
public string flow { get; set; }
|
||||
/// <summary>
|
||||
/// tls sni
|
||||
/// </summary>
|
||||
public string sni
|
||||
{
|
||||
get; set;
|
||||
}
|
||||
public string sni { get; set; }
|
||||
/// <summary>
|
||||
/// tls alpn
|
||||
/// </summary>
|
||||
public string alpn { get; set; } = string.Empty;
|
||||
|
||||
|
||||
public ECoreType? coreType
|
||||
{
|
||||
get; set;
|
||||
}
|
||||
public ECoreType? coreType { get; set; }
|
||||
|
||||
public int preSocksPort
|
||||
{
|
||||
get; set;
|
||||
}
|
||||
public int preSocksPort { get; set; }
|
||||
|
||||
public string fingerprint { get; set; }
|
||||
|
||||
public bool displayLog { get; set; } = true;
|
||||
public string publicKey { get; set; }
|
||||
public string shortId { get; set; }
|
||||
public string spiderX { get; set; }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -389,9 +389,9 @@ namespace v2rayN.Mode
|
||||
public QuicSettings quicSettings { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// VLESS xtls
|
||||
/// VLESS only
|
||||
/// </summary>
|
||||
public TlsSettings xtlsSettings { get; set; }
|
||||
public TlsSettings realitySettings { get; set; }
|
||||
/// <summary>
|
||||
/// grpc
|
||||
/// </summary>
|
||||
@@ -404,24 +404,23 @@ namespace v2rayN.Mode
|
||||
/// <summary>
|
||||
/// 是否允许不安全连接(用于客户端)
|
||||
/// </summary>
|
||||
public bool allowInsecure { get; set; }
|
||||
public bool? allowInsecure { get; set; }
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public string serverName { get; set; }
|
||||
public string? serverName { get; set; }
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public List<string> alpn
|
||||
{
|
||||
get; set;
|
||||
}
|
||||
public List<string>? alpn { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// "chrome" | "firefox" | "safari" | "randomized"
|
||||
/// </summary>
|
||||
public string fingerprint { get; set; }
|
||||
public string? fingerprint { get; set; }
|
||||
|
||||
public bool? show { get; set; } = false;
|
||||
public string? publicKey { get; set; }
|
||||
public string? shortId { get; set; }
|
||||
public string? spiderX { get; set; }
|
||||
|
||||
}
|
||||
|
||||
|
||||
65
v2rayN/v2rayN/Resx/ResUI.Designer.cs
generated
65
v2rayN/v2rayN/Resx/ResUI.Designer.cs
generated
@@ -1384,7 +1384,7 @@ namespace v2rayN.Resx {
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查找类似 Please fill in the address (Url) 的本地化字符串。
|
||||
/// 查找类似 Please fill in the Url 的本地化字符串。
|
||||
/// </summary>
|
||||
public static string MsgNeedUrl {
|
||||
get {
|
||||
@@ -1446,6 +1446,15 @@ namespace v2rayN.Resx {
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查找类似 Updates are not enabled, skip this subscription 的本地化字符串。
|
||||
/// </summary>
|
||||
public static string MsgSkipSubscriptionUpdate {
|
||||
get {
|
||||
return ResourceManager.GetString("MsgSkipSubscriptionUpdate", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查找类似 Start getting subscriptions 的本地化字符串。
|
||||
/// </summary>
|
||||
@@ -1788,6 +1797,15 @@ namespace v2rayN.Resx {
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查找类似 Waiting for testing 的本地化字符串。
|
||||
/// </summary>
|
||||
public static string SpeedtestingWait {
|
||||
get {
|
||||
return ResourceManager.GetString("SpeedtestingWait", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查找类似 PAC failed to start. Please run this program as Administrator. 的本地化字符串。
|
||||
/// </summary>
|
||||
@@ -2167,6 +2185,15 @@ namespace v2rayN.Resx {
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查找类似 PublicKey 的本地化字符串。
|
||||
/// </summary>
|
||||
public static string TbPublicKey {
|
||||
get {
|
||||
return ResourceManager.GetString("TbPublicKey", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查找类似 Alias (remarks) 的本地化字符串。
|
||||
/// </summary>
|
||||
@@ -2500,6 +2527,15 @@ namespace v2rayN.Resx {
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查找类似 Enable hardware acceleration(Require restart) 的本地化字符串。
|
||||
/// </summary>
|
||||
public static string TbSettingsEnableHWA {
|
||||
get {
|
||||
return ResourceManager.GetString("TbSettingsEnableHWA", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查找类似 Exception 的本地化字符串。
|
||||
/// </summary>
|
||||
@@ -2896,6 +2932,15 @@ namespace v2rayN.Resx {
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查找类似 ShortId 的本地化字符串。
|
||||
/// </summary>
|
||||
public static string TbShortId {
|
||||
get {
|
||||
return ResourceManager.GetString("TbShortId", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查找类似 SNI 的本地化字符串。
|
||||
/// </summary>
|
||||
@@ -2905,6 +2950,15 @@ namespace v2rayN.Resx {
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查找类似 SpiderX 的本地化字符串。
|
||||
/// </summary>
|
||||
public static string TbSpiderX {
|
||||
get {
|
||||
return ResourceManager.GetString("TbSpiderX", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查找类似 TLS 的本地化字符串。
|
||||
/// </summary>
|
||||
@@ -2950,6 +3004,15 @@ namespace v2rayN.Resx {
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查找类似 Please turn off when there is an abnormal disconnection 的本地化字符串。
|
||||
/// </summary>
|
||||
public static string TipDisplayLog {
|
||||
get {
|
||||
return ResourceManager.GetString("TipDisplayLog", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查找类似 *Default value tcp 的本地化字符串。
|
||||
/// </summary>
|
||||
|
||||
@@ -1066,4 +1066,7 @@
|
||||
<data name="TbSettingsDefUserAgentTips" xml:space="preserve">
|
||||
<value>This parameter is valid only for tcp/http and ws</value>
|
||||
</data>
|
||||
<data name="TbSettingsEnableHWA" xml:space="preserve">
|
||||
<value>فعالسازی شتابدهنده سختافزاری (نیاز به راهاندازی مجدد)</value>
|
||||
</data>
|
||||
</root>
|
||||
@@ -380,7 +380,7 @@
|
||||
<value>Count</value>
|
||||
</data>
|
||||
<data name="MsgNeedUrl" xml:space="preserve">
|
||||
<value>Please fill in the address (Url)</value>
|
||||
<value>Please fill in the Url</value>
|
||||
</data>
|
||||
<data name="AddBatchRoutingRulesYesNo" xml:space="preserve">
|
||||
<value>Do you want to append rules? Choose yes to append, choose otherwise to replace</value>
|
||||
@@ -1132,4 +1132,25 @@
|
||||
<data name="menuMoveTo" xml:space="preserve">
|
||||
<value>Move up and down</value>
|
||||
</data>
|
||||
<data name="TbPublicKey" xml:space="preserve">
|
||||
<value>PublicKey</value>
|
||||
</data>
|
||||
<data name="TbShortId" xml:space="preserve">
|
||||
<value>ShortId</value>
|
||||
</data>
|
||||
<data name="TbSpiderX" xml:space="preserve">
|
||||
<value>SpiderX</value>
|
||||
</data>
|
||||
<data name="TbSettingsEnableHWA" xml:space="preserve">
|
||||
<value>Enable hardware acceleration(Require restart)</value>
|
||||
</data>
|
||||
<data name="SpeedtestingWait" xml:space="preserve">
|
||||
<value>Waiting for testing</value>
|
||||
</data>
|
||||
<data name="TipDisplayLog" xml:space="preserve">
|
||||
<value>Please turn off when there is an abnormal disconnection</value>
|
||||
</data>
|
||||
<data name="MsgSkipSubscriptionUpdate" xml:space="preserve">
|
||||
<value>Updates are not enabled, skip this subscription</value>
|
||||
</data>
|
||||
</root>
|
||||
@@ -1108,4 +1108,7 @@
|
||||
<data name="TbSettingsFontSize" xml:space="preserve">
|
||||
<value>Размер шрифта</value>
|
||||
</data>
|
||||
<data name="TbSettingsEnableHWA" xml:space="preserve">
|
||||
<value>Включить аппаратное ускорение (требуется перезагрузка)</value>
|
||||
</data>
|
||||
</root>
|
||||
@@ -304,7 +304,7 @@
|
||||
<value>操作失败,请检查重试</value>
|
||||
</data>
|
||||
<data name="PleaseFillRemarks" xml:space="preserve">
|
||||
<value>请填写备注</value>
|
||||
<value>请填写别名</value>
|
||||
</data>
|
||||
<data name="PleaseSelectEncryption" xml:space="preserve">
|
||||
<value>请选择加密方式</value>
|
||||
@@ -380,7 +380,7 @@
|
||||
<value>数量</value>
|
||||
</data>
|
||||
<data name="MsgNeedUrl" xml:space="preserve">
|
||||
<value>请填写地址(Url)</value>
|
||||
<value>请填写Url</value>
|
||||
</data>
|
||||
<data name="AddBatchRoutingRulesYesNo" xml:space="preserve">
|
||||
<value>是否追加规则?选择是则追加,选择否则替换</value>
|
||||
@@ -710,7 +710,7 @@
|
||||
<value>SNI</value>
|
||||
</data>
|
||||
<data name="TbStreamSecurity" xml:space="preserve">
|
||||
<value>TLS</value>
|
||||
<value>传输层安全(TLS)</value>
|
||||
</data>
|
||||
<data name="TipNetwork" xml:space="preserve">
|
||||
<value>*默认tcp,选错会无法连接</value>
|
||||
@@ -1132,4 +1132,25 @@
|
||||
<data name="menuMoveTo" xml:space="preserve">
|
||||
<value>移至上下</value>
|
||||
</data>
|
||||
<data name="TbPublicKey" xml:space="preserve">
|
||||
<value>PublicKey</value>
|
||||
</data>
|
||||
<data name="TbShortId" xml:space="preserve">
|
||||
<value>ShortId</value>
|
||||
</data>
|
||||
<data name="TbSpiderX" xml:space="preserve">
|
||||
<value>SpiderX</value>
|
||||
</data>
|
||||
<data name="TbSettingsEnableHWA" xml:space="preserve">
|
||||
<value>启用硬件加速(需重启)</value>
|
||||
</data>
|
||||
<data name="SpeedtestingWait" xml:space="preserve">
|
||||
<value>等待测试中...</value>
|
||||
</data>
|
||||
<data name="TipDisplayLog" xml:space="preserve">
|
||||
<value>当有异常断流时请关闭</value>
|
||||
</data>
|
||||
<data name="MsgSkipSubscriptionUpdate" xml:space="preserve">
|
||||
<value>未启用更新,跳过此订阅</value>
|
||||
</data>
|
||||
</root>
|
||||
@@ -17,6 +17,13 @@ namespace v2rayN.Tool
|
||||
config.LoggingRules.Add(new LoggingRule("*", LogLevel.Debug, fileTarget));
|
||||
LogManager.Configuration = config;
|
||||
}
|
||||
public static void LoggingEnabled(bool enable)
|
||||
{
|
||||
if (!enable)
|
||||
{
|
||||
LogManager.SuspendLogging();
|
||||
}
|
||||
}
|
||||
|
||||
public static void ClearLogs()
|
||||
{
|
||||
|
||||
@@ -282,6 +282,8 @@ namespace v2rayN
|
||||
.Replace(Environment.NewLine, "")
|
||||
.Replace("\n", "")
|
||||
.Replace("\r", "")
|
||||
.Replace('_', '/')
|
||||
.Replace('-', '+')
|
||||
.Replace(" ", "");
|
||||
|
||||
if (plainText.Length % 4 > 0)
|
||||
@@ -312,7 +314,7 @@ namespace v2rayN
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
SaveLog(ex.Message, ex);
|
||||
//SaveLog(ex.Message, ex);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
@@ -324,7 +326,7 @@ namespace v2rayN
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
SaveLog(ex.Message, ex);
|
||||
//SaveLog(ex.Message, ex);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -337,7 +339,7 @@ namespace v2rayN
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
SaveLog(ex.Message, ex);
|
||||
//SaveLog(ex.Message, ex);
|
||||
return string.Empty;
|
||||
}
|
||||
}
|
||||
@@ -778,7 +780,7 @@ namespace v2rayN
|
||||
task.Settings.RunOnlyIfIdle = false;
|
||||
task.Settings.IdleSettings.StopOnIdleEnd = false;
|
||||
task.Settings.ExecutionTimeLimit = TimeSpan.Zero;
|
||||
task.Triggers.Add(new LogonTrigger { UserId = logonUser, Delay = TimeSpan.FromMinutes(1) });
|
||||
task.Triggers.Add(new LogonTrigger { UserId = logonUser, Delay = TimeSpan.FromSeconds(10) });
|
||||
task.Principal.RunLevel = TaskRunLevel.Highest;
|
||||
task.Actions.Add(new ExecAction(deamonFileName));
|
||||
|
||||
@@ -907,13 +909,13 @@ namespace v2rayN
|
||||
/// <returns></returns>
|
||||
public static string? GetClipboardData()
|
||||
{
|
||||
string strData = string.Empty;
|
||||
string? strData = string.Empty;
|
||||
try
|
||||
{
|
||||
IDataObject data = Clipboard.GetDataObject();
|
||||
if (data.GetDataPresent(DataFormats.UnicodeText))
|
||||
{
|
||||
strData = data.GetData(DataFormats.UnicodeText).ToString();
|
||||
strData = data.GetData(DataFormats.UnicodeText)?.ToString();
|
||||
}
|
||||
return strData;
|
||||
}
|
||||
@@ -1150,17 +1152,23 @@ namespace v2rayN
|
||||
|
||||
public static void SaveLog(string strContent)
|
||||
{
|
||||
var logger = LogManager.GetLogger("Log1");
|
||||
logger.Info(strContent);
|
||||
if (LogManager.IsLoggingEnabled())
|
||||
{
|
||||
var logger = LogManager.GetLogger("Log1");
|
||||
logger.Info(strContent);
|
||||
}
|
||||
}
|
||||
public static void SaveLog(string strTitle, Exception ex)
|
||||
{
|
||||
var logger = LogManager.GetLogger("Log2");
|
||||
logger.Debug($"{strTitle},{ex.Message}");
|
||||
logger.Debug(ex.StackTrace);
|
||||
if (ex?.InnerException != null)
|
||||
if (LogManager.IsLoggingEnabled())
|
||||
{
|
||||
logger.Error(ex.InnerException);
|
||||
var logger = LogManager.GetLogger("Log2");
|
||||
logger.Debug($"{strTitle},{ex.Message}");
|
||||
logger.Debug(ex.StackTrace);
|
||||
if (ex?.InnerException != null)
|
||||
{
|
||||
logger.Error(ex.InnerException);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -118,6 +118,10 @@ namespace v2rayN.ViewModels
|
||||
item.allowInsecure = SelectedSource.allowInsecure;
|
||||
item.fingerprint = SelectedSource.fingerprint;
|
||||
item.alpn = SelectedSource.alpn;
|
||||
|
||||
item.publicKey = SelectedSource.publicKey;
|
||||
item.shortId = SelectedSource.shortId;
|
||||
item.spiderX = SelectedSource.spiderX;
|
||||
}
|
||||
|
||||
int ret = -1;
|
||||
|
||||
@@ -3,7 +3,6 @@ using DynamicData.Binding;
|
||||
using MaterialDesignColors;
|
||||
using MaterialDesignColors.ColorManipulation;
|
||||
using MaterialDesignThemes.Wpf;
|
||||
using NHotkey;
|
||||
using ReactiveUI;
|
||||
using ReactiveUI.Fody.Helpers;
|
||||
using Splat;
|
||||
@@ -70,6 +69,8 @@ namespace v2rayN.ViewModels
|
||||
public ComboItem SelectedServer { get; set; }
|
||||
[Reactive]
|
||||
public string ServerFilter { get; set; }
|
||||
[Reactive]
|
||||
public bool BlServers { get; set; }
|
||||
#endregion
|
||||
|
||||
#region Menu
|
||||
@@ -630,27 +631,26 @@ namespace v2rayN.ViewModels
|
||||
}
|
||||
}
|
||||
|
||||
private void OnHotkeyHandler(object sender, HotkeyEventArgs e)
|
||||
private void OnHotkeyHandler(EGlobalHotkey e)
|
||||
{
|
||||
switch (Utils.ToInt(e.Name))
|
||||
switch (e)
|
||||
{
|
||||
case (int)EGlobalHotkey.ShowForm:
|
||||
case EGlobalHotkey.ShowForm:
|
||||
ShowHideWindow(null);
|
||||
break;
|
||||
case (int)EGlobalHotkey.SystemProxyClear:
|
||||
case EGlobalHotkey.SystemProxyClear:
|
||||
SetListenerType(ESysProxyType.ForcedClear);
|
||||
break;
|
||||
case (int)EGlobalHotkey.SystemProxySet:
|
||||
case EGlobalHotkey.SystemProxySet:
|
||||
SetListenerType(ESysProxyType.ForcedChange);
|
||||
break;
|
||||
case (int)EGlobalHotkey.SystemProxyUnchanged:
|
||||
case EGlobalHotkey.SystemProxyUnchanged:
|
||||
SetListenerType(ESysProxyType.Unchanged);
|
||||
break;
|
||||
case (int)EGlobalHotkey.SystemProxyPac:
|
||||
case EGlobalHotkey.SystemProxyPac:
|
||||
SetListenerType(ESysProxyType.Pac);
|
||||
break;
|
||||
}
|
||||
e.Handled = true;
|
||||
}
|
||||
public void MyAppExit(bool blWindowsShutDown)
|
||||
{
|
||||
@@ -718,6 +718,7 @@ namespace v2rayN.ViewModels
|
||||
private void RefreshServers()
|
||||
{
|
||||
List<ProfileItemModel> lstModel = LazyConfig.Instance.ProfileItems(_subId, _serverFilter);
|
||||
|
||||
ConfigHandler.SetDefaultServer(_config, lstModel);
|
||||
|
||||
List<ServerStatItem> lstServerStat = new();
|
||||
@@ -741,6 +742,7 @@ namespace v2rayN.ViewModels
|
||||
security = t.security,
|
||||
network = t.network,
|
||||
streamSecurity = t.streamSecurity,
|
||||
subid = t.subid,
|
||||
subRemarks = t.subRemarks,
|
||||
isActive = t.indexId == _config.indexId,
|
||||
sort = t33 == null ? 0 : t33.sort,
|
||||
@@ -781,6 +783,11 @@ namespace v2rayN.ViewModels
|
||||
RunningServerDisplay = $"{ResUI.menuServers}:{runningSummary}";
|
||||
RunningServerToolTipText = runningSummary;
|
||||
}
|
||||
else
|
||||
{
|
||||
RunningServerDisplay =
|
||||
RunningServerToolTipText = ResUI.CheckServerSettings;
|
||||
}
|
||||
}));
|
||||
}
|
||||
|
||||
@@ -789,9 +796,11 @@ namespace v2rayN.ViewModels
|
||||
_servers.Clear();
|
||||
if (_lstProfile.Count > _config.guiItem.trayMenuServersLimit)
|
||||
{
|
||||
BlServers = false;
|
||||
return;
|
||||
}
|
||||
|
||||
BlServers = true;
|
||||
for (int k = 0; k < _lstProfile.Count; k++)
|
||||
{
|
||||
ProfileItem it = _lstProfile[k];
|
||||
@@ -828,21 +837,31 @@ namespace v2rayN.ViewModels
|
||||
#endregion
|
||||
|
||||
#region Add Servers
|
||||
private int GetProfileItems(out List<ProfileItem> lstSelecteds)
|
||||
private int GetProfileItems(out List<ProfileItem> lstSelecteds, bool latest)
|
||||
{
|
||||
lstSelecteds = new List<ProfileItem>();
|
||||
if (SelectedProfiles == null || SelectedProfiles.Count <= 0)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
foreach (var profile in SelectedProfiles)
|
||||
|
||||
var orderProfiles = SelectedProfiles?.OrderBy(t => t.sort);
|
||||
if (latest)
|
||||
{
|
||||
var item = LazyConfig.Instance.GetProfileItem(profile.indexId);
|
||||
if (item is not null)
|
||||
foreach (var profile in orderProfiles)
|
||||
{
|
||||
lstSelecteds.Add(item);
|
||||
var item = LazyConfig.Instance.GetProfileItem(profile.indexId);
|
||||
if (item is not null)
|
||||
{
|
||||
lstSelecteds.Add(item);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
lstSelecteds = Utils.FromJson<List<ProfileItem>>(Utils.ToJson(orderProfiles));
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -929,7 +948,7 @@ namespace v2rayN.ViewModels
|
||||
}
|
||||
public void RemoveServer()
|
||||
{
|
||||
if (GetProfileItems(out List<ProfileItem> lstSelecteds) < 0)
|
||||
if (GetProfileItems(out List<ProfileItem> lstSelecteds, false) < 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
@@ -952,15 +971,14 @@ namespace v2rayN.ViewModels
|
||||
|
||||
private void RemoveDuplicateServer()
|
||||
{
|
||||
int oldCount = _lstProfile.Count;
|
||||
int newCount = ConfigHandler.DedupServerList(ref _config, ref _lstProfile);
|
||||
var tuple = ConfigHandler.DedupServerList(_config, _subId);
|
||||
RefreshServers();
|
||||
Reload();
|
||||
_noticeHandler?.Enqueue(string.Format(ResUI.RemoveDuplicateServerResult, oldCount, newCount));
|
||||
_noticeHandler?.Enqueue(string.Format(ResUI.RemoveDuplicateServerResult, tuple.Item1, tuple.Item2));
|
||||
}
|
||||
private void CopyServer()
|
||||
{
|
||||
if (GetProfileItems(out List<ProfileItem> lstSelecteds) < 0)
|
||||
if (GetProfileItems(out List<ProfileItem> lstSelecteds, false) < 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
@@ -1092,7 +1110,7 @@ namespace v2rayN.ViewModels
|
||||
return;
|
||||
}
|
||||
|
||||
if (GetProfileItems(out List<ProfileItem> lstSelecteds) < 0)
|
||||
if (GetProfileItems(out List<ProfileItem> lstSelecteds, false) < 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
@@ -1143,7 +1161,7 @@ namespace v2rayN.ViewModels
|
||||
{
|
||||
SelectedProfiles = _profileItems;
|
||||
}
|
||||
if (GetProfileItems(out List<ProfileItem> lstSelecteds) < 0)
|
||||
if (GetProfileItems(out List<ProfileItem> lstSelecteds, false) < 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
@@ -1175,7 +1193,7 @@ namespace v2rayN.ViewModels
|
||||
|
||||
public void Export2ShareUrl()
|
||||
{
|
||||
if (GetProfileItems(out List<ProfileItem> lstSelecteds) < 0)
|
||||
if (GetProfileItems(out List<ProfileItem> lstSelecteds, true) < 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
@@ -1200,7 +1218,7 @@ namespace v2rayN.ViewModels
|
||||
|
||||
private void Export2SubContent()
|
||||
{
|
||||
if (GetProfileItems(out List<ProfileItem> lstSelecteds) < 0)
|
||||
if (GetProfileItems(out List<ProfileItem> lstSelecteds, true) < 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -65,6 +65,7 @@ namespace v2rayN.ViewModels
|
||||
[Reactive] public string currentFontFamily { get; set; }
|
||||
[Reactive] public int SpeedTestTimeout { get; set; }
|
||||
[Reactive] public string SpeedTestUrl { get; set; }
|
||||
[Reactive] public bool EnableHWA { get; set; }
|
||||
|
||||
#endregion
|
||||
|
||||
@@ -160,6 +161,7 @@ namespace v2rayN.ViewModels
|
||||
currentFontFamily = _config.uiItem.currentFontFamily;
|
||||
SpeedTestTimeout = _config.speedTestItem.speedTestTimeout;
|
||||
SpeedTestUrl = _config.speedTestItem.speedTestUrl;
|
||||
EnableHWA = _config.guiItem.enableHWA;
|
||||
|
||||
#endregion
|
||||
|
||||
@@ -339,6 +341,7 @@ namespace v2rayN.ViewModels
|
||||
_config.uiItem.currentFontFamily = currentFontFamily;
|
||||
_config.speedTestItem.speedTestTimeout = SpeedTestTimeout;
|
||||
_config.speedTestItem.speedTestUrl = SpeedTestUrl;
|
||||
_config.guiItem.enableHWA = EnableHWA;
|
||||
|
||||
//systemProxy
|
||||
_config.systemProxyExceptions = systemProxyExceptions;
|
||||
|
||||
@@ -137,12 +137,19 @@
|
||||
VerticalAlignment="Center"
|
||||
Style="{StaticResource ToolbarTextBlock}"
|
||||
Text="{x:Static resx:ResUI.TbDisplayLog}" />
|
||||
<ToggleButton
|
||||
x:Name="togDisplayLog"
|
||||
<StackPanel
|
||||
Grid.Row="4"
|
||||
Grid.Column="1"
|
||||
Margin="4"
|
||||
HorizontalAlignment="Left" />
|
||||
Orientation="Horizontal">
|
||||
<ToggleButton x:Name="togDisplayLog" HorizontalAlignment="Left" />
|
||||
<TextBlock
|
||||
Margin="8,0"
|
||||
VerticalAlignment="Center"
|
||||
Style="{StaticResource ToolbarTextBlock}"
|
||||
Text="{x:Static resx:ResUI.TipDisplayLog}" />
|
||||
</StackPanel>
|
||||
|
||||
|
||||
<TextBlock
|
||||
Grid.Row="5"
|
||||
@@ -176,7 +183,7 @@
|
||||
|
||||
<Grid
|
||||
Grid.Row="1"
|
||||
Margin="16"
|
||||
Margin="8"
|
||||
HorizontalAlignment="Center">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="200" />
|
||||
|
||||
@@ -10,8 +10,8 @@
|
||||
xmlns:resx="clr-namespace:v2rayN.Resx"
|
||||
xmlns:vms="clr-namespace:v2rayN.ViewModels"
|
||||
Title="{x:Static resx:ResUI.menuServers}"
|
||||
Width="800"
|
||||
Height="800"
|
||||
Width="820"
|
||||
Height="820"
|
||||
x:TypeArguments="vms:AddServerViewModel"
|
||||
Background="{DynamicResource MaterialDesignPaper}"
|
||||
FontFamily="{x:Static conv:MaterialDesignFonts.MyFont}"
|
||||
@@ -559,8 +559,10 @@
|
||||
Margin="{StaticResource ServerItemMargin}"
|
||||
Style="{StaticResource DefComboBox}" />
|
||||
</Grid>
|
||||
|
||||
<Grid x:Name="gridTlsMore" Grid.Row="7">
|
||||
<Grid
|
||||
x:Name="gridTlsMore"
|
||||
Grid.Row="7"
|
||||
Visibility="Hidden">
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="Auto" />
|
||||
@@ -595,25 +597,10 @@
|
||||
Margin="{StaticResource ServerItemMargin}"
|
||||
VerticalAlignment="Center"
|
||||
Style="{StaticResource ToolbarTextBlock}"
|
||||
Text="{x:Static resx:ResUI.TbAllowInsecure}" />
|
||||
<ComboBox
|
||||
x:Name="cmbAllowInsecure"
|
||||
Grid.Row="2"
|
||||
Grid.Column="1"
|
||||
Width="100"
|
||||
Margin="{StaticResource ServerItemMargin}"
|
||||
Style="{StaticResource DefComboBox}" />
|
||||
|
||||
<TextBlock
|
||||
Grid.Row="3"
|
||||
Grid.Column="0"
|
||||
Margin="{StaticResource ServerItemMargin}"
|
||||
VerticalAlignment="Center"
|
||||
Style="{StaticResource ToolbarTextBlock}"
|
||||
Text="{x:Static resx:ResUI.TbFingerprint}" />
|
||||
<ComboBox
|
||||
x:Name="cmbFingerprint"
|
||||
Grid.Row="3"
|
||||
Grid.Row="2"
|
||||
Grid.Column="1"
|
||||
Width="200"
|
||||
Margin="{StaticResource ServerItemMargin}"
|
||||
@@ -621,7 +608,7 @@
|
||||
Style="{StaticResource DefComboBox}" />
|
||||
|
||||
<TextBlock
|
||||
Grid.Row="4"
|
||||
Grid.Row="3"
|
||||
Grid.Column="0"
|
||||
Margin="{StaticResource ServerItemMargin}"
|
||||
VerticalAlignment="Center"
|
||||
@@ -629,13 +616,125 @@
|
||||
Text="{x:Static resx:ResUI.TbAlpn}" />
|
||||
<ComboBox
|
||||
x:Name="cmbAlpn"
|
||||
Grid.Row="4"
|
||||
Grid.Row="3"
|
||||
Grid.Column="1"
|
||||
Width="200"
|
||||
Margin="{StaticResource ServerItemMargin}"
|
||||
Style="{StaticResource DefComboBox}" />
|
||||
</Grid>
|
||||
|
||||
<TextBlock
|
||||
Grid.Row="4"
|
||||
Grid.Column="0"
|
||||
Margin="{StaticResource ServerItemMargin}"
|
||||
VerticalAlignment="Center"
|
||||
Style="{StaticResource ToolbarTextBlock}"
|
||||
Text="{x:Static resx:ResUI.TbAllowInsecure}" />
|
||||
<ComboBox
|
||||
x:Name="cmbAllowInsecure"
|
||||
Grid.Row="4"
|
||||
Grid.Column="1"
|
||||
Width="100"
|
||||
Margin="{StaticResource ServerItemMargin}"
|
||||
Style="{StaticResource DefComboBox}" />
|
||||
</Grid>
|
||||
<Grid
|
||||
x:Name="gridRealityMore"
|
||||
Grid.Row="7"
|
||||
Visibility="Hidden">
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="Auto" />
|
||||
</Grid.RowDefinitions>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="180" />
|
||||
<ColumnDefinition Width="Auto" />
|
||||
</Grid.ColumnDefinitions>
|
||||
|
||||
<TextBlock
|
||||
Grid.Row="0"
|
||||
Grid.Column="0"
|
||||
Margin="{StaticResource ServerItemMargin}"
|
||||
VerticalAlignment="Center"
|
||||
Style="{StaticResource ToolbarTextBlock}"
|
||||
Text="{x:Static resx:ResUI.TbSNI}" />
|
||||
<TextBox
|
||||
x:Name="txtSNI2"
|
||||
Grid.Row="0"
|
||||
Grid.Column="1"
|
||||
Width="400"
|
||||
Margin="{StaticResource ServerItemMargin}"
|
||||
HorizontalAlignment="Left"
|
||||
Style="{StaticResource DefTextBox}" />
|
||||
|
||||
<TextBlock
|
||||
Grid.Row="1"
|
||||
Grid.Column="0"
|
||||
Margin="{StaticResource ServerItemMargin}"
|
||||
VerticalAlignment="Center"
|
||||
Style="{StaticResource ToolbarTextBlock}"
|
||||
Text="{x:Static resx:ResUI.TbFingerprint}" />
|
||||
<ComboBox
|
||||
x:Name="cmbFingerprint2"
|
||||
Grid.Row="1"
|
||||
Grid.Column="1"
|
||||
Width="200"
|
||||
Margin="{StaticResource ServerItemMargin}"
|
||||
IsEditable="True"
|
||||
Style="{StaticResource DefComboBox}" />
|
||||
|
||||
<TextBlock
|
||||
Grid.Row="2"
|
||||
Grid.Column="0"
|
||||
Margin="{StaticResource ServerItemMargin}"
|
||||
VerticalAlignment="Center"
|
||||
Style="{StaticResource ToolbarTextBlock}"
|
||||
Text="{x:Static resx:ResUI.TbPublicKey}" />
|
||||
<TextBox
|
||||
x:Name="txtPublicKey"
|
||||
Grid.Row="2"
|
||||
Grid.Column="1"
|
||||
Width="400"
|
||||
Margin="{StaticResource ServerItemMargin}"
|
||||
HorizontalAlignment="Left"
|
||||
Style="{StaticResource DefTextBox}" />
|
||||
|
||||
<TextBlock
|
||||
Grid.Row="3"
|
||||
Grid.Column="0"
|
||||
Margin="{StaticResource ServerItemMargin}"
|
||||
VerticalAlignment="Center"
|
||||
Style="{StaticResource ToolbarTextBlock}"
|
||||
Text="{x:Static resx:ResUI.TbShortId}" />
|
||||
<TextBox
|
||||
x:Name="txtShortId"
|
||||
Grid.Row="3"
|
||||
Grid.Column="1"
|
||||
Width="200"
|
||||
Margin="{StaticResource ServerItemMargin}"
|
||||
HorizontalAlignment="Left"
|
||||
Style="{StaticResource DefTextBox}" />
|
||||
|
||||
<TextBlock
|
||||
Grid.Row="4"
|
||||
Grid.Column="0"
|
||||
Margin="{StaticResource ServerItemMargin}"
|
||||
VerticalAlignment="Center"
|
||||
Style="{StaticResource ToolbarTextBlock}"
|
||||
Text="{x:Static resx:ResUI.TbSpiderX}" />
|
||||
<TextBox
|
||||
x:Name="txtSpiderX"
|
||||
Grid.Row="4"
|
||||
Grid.Column="1"
|
||||
Width="400"
|
||||
Margin="{StaticResource ServerItemMargin}"
|
||||
HorizontalAlignment="Left"
|
||||
Style="{StaticResource DefTextBox}" />
|
||||
|
||||
|
||||
</Grid>
|
||||
<Separator
|
||||
Grid.Row="8"
|
||||
Margin="0,2"
|
||||
@@ -643,7 +742,7 @@
|
||||
|
||||
<Grid
|
||||
Grid.Row="9"
|
||||
Margin="16"
|
||||
Margin="8"
|
||||
HorizontalAlignment="Center">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="200" />
|
||||
|
||||
@@ -39,6 +39,7 @@ namespace v2rayN.Views
|
||||
Global.fingerprints.ForEach(it =>
|
||||
{
|
||||
cmbFingerprint.Items.Add(it);
|
||||
cmbFingerprint2.Items.Add(it);
|
||||
});
|
||||
Global.allowInsecures.ForEach(it =>
|
||||
{
|
||||
@@ -74,8 +75,8 @@ namespace v2rayN.Views
|
||||
break;
|
||||
case EConfigType.VLESS:
|
||||
gridVLESS.Visibility = Visibility.Visible;
|
||||
cmbStreamSecurity.Items.Add(Global.StreamSecurityX);
|
||||
Global.xtlsFlows.ForEach(it =>
|
||||
cmbStreamSecurity.Items.Add(Global.StreamSecurityReality);
|
||||
Global.flows.ForEach(it =>
|
||||
{
|
||||
cmbFlow5.Items.Add(it);
|
||||
});
|
||||
@@ -86,8 +87,7 @@ namespace v2rayN.Views
|
||||
break;
|
||||
case EConfigType.Trojan:
|
||||
gridTrojan.Visibility = Visibility.Visible;
|
||||
cmbStreamSecurity.Items.Add(Global.StreamSecurityX);
|
||||
Global.xtlsFlows.ForEach(it =>
|
||||
Global.flows.ForEach(it =>
|
||||
{
|
||||
cmbFlow6.Items.Add(it);
|
||||
});
|
||||
@@ -138,6 +138,13 @@ namespace v2rayN.Views
|
||||
this.Bind(ViewModel, vm => vm.SelectedSource.allowInsecure, v => v.cmbAllowInsecure.Text).DisposeWith(disposables);
|
||||
this.Bind(ViewModel, vm => vm.SelectedSource.fingerprint, v => v.cmbFingerprint.Text).DisposeWith(disposables);
|
||||
this.Bind(ViewModel, vm => vm.SelectedSource.alpn, v => v.cmbAlpn.Text).DisposeWith(disposables);
|
||||
//reality
|
||||
this.Bind(ViewModel, vm => vm.SelectedSource.sni, v => v.txtSNI2.Text).DisposeWith(disposables);
|
||||
this.Bind(ViewModel, vm => vm.SelectedSource.fingerprint, v => v.cmbFingerprint2.Text).DisposeWith(disposables);
|
||||
this.Bind(ViewModel, vm => vm.SelectedSource.publicKey, v => v.txtPublicKey.Text).DisposeWith(disposables);
|
||||
this.Bind(ViewModel, vm => vm.SelectedSource.shortId, v => v.txtShortId.Text).DisposeWith(disposables);
|
||||
this.Bind(ViewModel, vm => vm.SelectedSource.spiderX, v => v.txtSpiderX.Text).DisposeWith(disposables);
|
||||
|
||||
|
||||
this.BindCommand(ViewModel, vm => vm.SaveCmd, v => v.btnSave).DisposeWith(disposables);
|
||||
|
||||
@@ -159,13 +166,20 @@ namespace v2rayN.Views
|
||||
private void CmbStreamSecurity_SelectionChanged(object sender, SelectionChangedEventArgs e)
|
||||
{
|
||||
var security = cmbStreamSecurity.SelectedItem.ToString();
|
||||
if (Utils.IsNullOrEmpty(security))
|
||||
if (security == Global.StreamSecurityReality)
|
||||
{
|
||||
gridRealityMore.Visibility = Visibility.Visible;
|
||||
gridTlsMore.Visibility = Visibility.Hidden;
|
||||
}
|
||||
else if (security == Global.StreamSecurity)
|
||||
{
|
||||
gridRealityMore.Visibility = Visibility.Hidden;
|
||||
gridTlsMore.Visibility = Visibility.Visible;
|
||||
}
|
||||
else
|
||||
{
|
||||
gridTlsMore.Visibility = Visibility.Visible;
|
||||
gridRealityMore.Visibility = Visibility.Hidden;
|
||||
gridTlsMore.Visibility = Visibility.Hidden;
|
||||
}
|
||||
}
|
||||
private void btnGUID_Click(object sender, RoutedEventArgs e)
|
||||
|
||||
@@ -150,7 +150,7 @@
|
||||
|
||||
<Grid
|
||||
Grid.Row="2"
|
||||
Margin="16"
|
||||
Margin="8"
|
||||
HorizontalAlignment="Center">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="150" />
|
||||
|
||||
@@ -1,47 +1,24 @@
|
||||
using System.Windows;
|
||||
using System.Text;
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Input;
|
||||
using v2rayN.Handler;
|
||||
using v2rayN.Mode;
|
||||
using v2rayN.Resx;
|
||||
using Forms = System.Windows.Forms;
|
||||
|
||||
namespace v2rayN.Views
|
||||
{
|
||||
public partial class GlobalHotkeySettingWindow
|
||||
{
|
||||
private static Config _config;
|
||||
List<KeyEventItem> lstKey;
|
||||
private static Config _config = default!;
|
||||
private Dictionary<object, KeyEventItem> _TextBoxKeyEventItem = default!;
|
||||
|
||||
public GlobalHotkeySettingWindow()
|
||||
{
|
||||
InitializeComponent();
|
||||
this.Owner = Application.Current.MainWindow;
|
||||
_config = LazyConfig.Instance.GetConfig();
|
||||
|
||||
if (_config.globalHotkeys == null)
|
||||
{
|
||||
_config.globalHotkeys = new List<KeyEventItem>();
|
||||
}
|
||||
|
||||
foreach (EGlobalHotkey it in Enum.GetValues(typeof(EGlobalHotkey)))
|
||||
{
|
||||
if (_config.globalHotkeys.FindIndex(t => t.eGlobalHotkey == it) >= 0)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
_config.globalHotkeys.Add(new KeyEventItem()
|
||||
{
|
||||
eGlobalHotkey = it,
|
||||
Alt = false,
|
||||
Control = false,
|
||||
Shift = false,
|
||||
KeyCode = null
|
||||
});
|
||||
}
|
||||
|
||||
lstKey = Utils.DeepCopy(_config.globalHotkeys);
|
||||
_config.globalHotkeys ??= new List<KeyEventItem>();
|
||||
|
||||
txtGlobalHotkey0.KeyDown += TxtGlobalHotkey_KeyDown;
|
||||
txtGlobalHotkey1.KeyDown += TxtGlobalHotkey_KeyDown;
|
||||
@@ -49,69 +26,84 @@ namespace v2rayN.Views
|
||||
txtGlobalHotkey3.KeyDown += TxtGlobalHotkey_KeyDown;
|
||||
txtGlobalHotkey4.KeyDown += TxtGlobalHotkey_KeyDown;
|
||||
|
||||
BindingData(-1);
|
||||
|
||||
HotkeyHandler.Instance.IsPause = true;
|
||||
this.Closing += (s, e) => HotkeyHandler.Instance.IsPause = false;
|
||||
Utils.SetDarkBorder(this, _config.uiItem.colorModeDark);
|
||||
InitData();
|
||||
}
|
||||
|
||||
private void InitData()
|
||||
{
|
||||
_TextBoxKeyEventItem = new()
|
||||
{
|
||||
{ txtGlobalHotkey0,GetKeyEventItemByEGlobalHotkey(_config.globalHotkeys,EGlobalHotkey.ShowForm) },
|
||||
{ txtGlobalHotkey1,GetKeyEventItemByEGlobalHotkey(_config.globalHotkeys,EGlobalHotkey.SystemProxyClear) },
|
||||
{ txtGlobalHotkey2,GetKeyEventItemByEGlobalHotkey(_config.globalHotkeys,EGlobalHotkey.SystemProxySet) },
|
||||
{ txtGlobalHotkey3,GetKeyEventItemByEGlobalHotkey(_config.globalHotkeys,EGlobalHotkey.SystemProxyUnchanged)},
|
||||
{ txtGlobalHotkey4,GetKeyEventItemByEGlobalHotkey(_config.globalHotkeys,EGlobalHotkey.SystemProxyPac)}
|
||||
};
|
||||
BindingData();
|
||||
}
|
||||
|
||||
|
||||
private void TxtGlobalHotkey_KeyDown(object sender, KeyEventArgs e)
|
||||
{
|
||||
e.Handled = true;
|
||||
var _ModifierKeys = new Key[] { Key.LeftCtrl, Key.RightCtrl, Key.LeftShift, Key.RightShift, Key.LeftAlt, Key.RightAlt };
|
||||
if (!_ModifierKeys.Contains(e.Key) && !_ModifierKeys.Contains(e.SystemKey))
|
||||
{
|
||||
var txt = ((TextBox)sender);
|
||||
var index = Utils.ToInt(txt.Name.Substring(txt.Name.Length - 1, 1));
|
||||
var formsKey = (Forms.Keys)KeyInterop.VirtualKeyFromKey(e.Key == Key.System ? e.SystemKey : e.Key);
|
||||
|
||||
lstKey[index].KeyCode = formsKey;
|
||||
lstKey[index].Alt = (Keyboard.Modifiers & ModifierKeys.Alt) == ModifierKeys.Alt;
|
||||
lstKey[index].Control = (Keyboard.Modifiers & ModifierKeys.Control) == ModifierKeys.Control;
|
||||
lstKey[index].Shift = (Keyboard.Modifiers & ModifierKeys.Shift) == ModifierKeys.Shift;
|
||||
|
||||
BindingData(index);
|
||||
}
|
||||
var _ModifierKeys = new Key[] { Key.LeftCtrl, Key.RightCtrl, Key.LeftShift,
|
||||
Key.RightShift, Key.LeftAlt, Key.RightAlt, Key.LWin, Key.RWin};
|
||||
_TextBoxKeyEventItem[sender].KeyCode = e.Key == Key.System ? (_ModifierKeys.Contains(e.SystemKey) ? Key.None : e.SystemKey) : (_ModifierKeys.Contains(e.Key) ? Key.None : e.Key);
|
||||
_TextBoxKeyEventItem[sender].Alt = (Keyboard.Modifiers & ModifierKeys.Alt) == ModifierKeys.Alt;
|
||||
_TextBoxKeyEventItem[sender].Control = (Keyboard.Modifiers & ModifierKeys.Control) == ModifierKeys.Control;
|
||||
_TextBoxKeyEventItem[sender].Shift = (Keyboard.Modifiers & ModifierKeys.Shift) == ModifierKeys.Shift;
|
||||
(sender as TextBox)!.Text = KeyEventItemToString(_TextBoxKeyEventItem[sender]);
|
||||
}
|
||||
|
||||
private void BindingData(int index)
|
||||
private KeyEventItem GetKeyEventItemByEGlobalHotkey(List<KeyEventItem> KELsit, EGlobalHotkey eg)
|
||||
{
|
||||
for (int k = 0; k < lstKey.Count; k++)
|
||||
return Utils.DeepCopy(KELsit.Find((it) => it.eGlobalHotkey == eg) ?? new()
|
||||
{
|
||||
if (index >= 0 && index != k)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
var item = lstKey[k];
|
||||
var keys = string.Empty;
|
||||
eGlobalHotkey = eg,
|
||||
Control = false,
|
||||
Alt = false,
|
||||
Shift = false,
|
||||
KeyCode = null
|
||||
});
|
||||
|
||||
if (item.Control)
|
||||
{
|
||||
keys += $"{Forms.Keys.Control} + ";
|
||||
}
|
||||
if (item.Alt)
|
||||
{
|
||||
keys += $"{Forms.Keys.Alt} + ";
|
||||
}
|
||||
if (item.Shift)
|
||||
{
|
||||
keys += $"{Forms.Keys.Shift} + ";
|
||||
}
|
||||
if (item.KeyCode != null)
|
||||
{
|
||||
keys += $"{item.KeyCode}";
|
||||
}
|
||||
}
|
||||
private string KeyEventItemToString(KeyEventItem item)
|
||||
{
|
||||
var res = new StringBuilder();
|
||||
|
||||
SetText($"txtGlobalHotkey{k}", keys);
|
||||
if (item.Control) res.Append($"{ModifierKeys.Control}+");
|
||||
if (item.Shift) res.Append($"{ModifierKeys.Shift}+");
|
||||
if (item.Alt) res.Append($"{ModifierKeys.Alt}+");
|
||||
if (item.KeyCode != null && item.KeyCode != Key.None)
|
||||
res.Append($"{item.KeyCode}");
|
||||
|
||||
return res.ToString();
|
||||
}
|
||||
private void BindingData()
|
||||
{
|
||||
foreach (var item in _TextBoxKeyEventItem)
|
||||
{
|
||||
if (item.Value.KeyCode != null && item.Value.KeyCode != Key.None)
|
||||
{
|
||||
(item.Key as TextBox)!.Text = KeyEventItemToString(item.Value);
|
||||
}
|
||||
else
|
||||
{
|
||||
(item.Key as TextBox)!.Text = string.Empty;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void btnSave_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
_config.globalHotkeys = lstKey;
|
||||
_config.globalHotkeys = _TextBoxKeyEventItem.Values.ToList();
|
||||
|
||||
if (ConfigHandler.SaveConfig(ref _config, false) == 0)
|
||||
{
|
||||
HotkeyHandler.Instance.ReLoad();
|
||||
this.DialogResult = true;
|
||||
}
|
||||
else
|
||||
@@ -127,37 +119,14 @@ namespace v2rayN.Views
|
||||
|
||||
private void btnReset_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
lstKey.Clear();
|
||||
foreach (EGlobalHotkey it in Enum.GetValues(typeof(EGlobalHotkey)))
|
||||
foreach (var k in _TextBoxKeyEventItem.Keys)
|
||||
{
|
||||
if (lstKey.FindIndex(t => t.eGlobalHotkey == it) >= 0)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
lstKey.Add(new KeyEventItem()
|
||||
{
|
||||
eGlobalHotkey = it,
|
||||
Alt = false,
|
||||
Control = false,
|
||||
Shift = false,
|
||||
KeyCode = null
|
||||
});
|
||||
}
|
||||
BindingData(-1);
|
||||
}
|
||||
private void SetText(string name, string txt)
|
||||
{
|
||||
foreach (UIElement element in gridText.Children)
|
||||
{
|
||||
if (element is TextBox box)
|
||||
{
|
||||
if (box.Name == name)
|
||||
{
|
||||
box.Text = txt;
|
||||
}
|
||||
}
|
||||
_TextBoxKeyEventItem[k].Alt = false;
|
||||
_TextBoxKeyEventItem[k].Control = false;
|
||||
_TextBoxKeyEventItem[k].Shift = false;
|
||||
_TextBoxKeyEventItem[k].KeyCode = Key.None;
|
||||
}
|
||||
BindingData();
|
||||
}
|
||||
|
||||
private void GlobalHotkeySettingWindow_KeyDown(object sender, KeyEventArgs e)
|
||||
|
||||
@@ -15,8 +15,8 @@
|
||||
Title="v2rayN"
|
||||
Width="900"
|
||||
Height="700"
|
||||
MinWidth="800"
|
||||
MinHeight="600"
|
||||
MinWidth="900"
|
||||
MinHeight="700"
|
||||
x:TypeArguments="vms:MainWindowViewModel"
|
||||
Background="{DynamicResource MaterialDesignPaper}"
|
||||
FontFamily="{x:Static conv:MaterialDesignFonts.MyFont}"
|
||||
@@ -617,7 +617,7 @@
|
||||
</Style>
|
||||
</DataGrid.Resources>
|
||||
<DataGrid.Columns>
|
||||
<DataGridTemplateColumn Width="50">
|
||||
<DataGridTemplateColumn Width="40">
|
||||
<DataGridTemplateColumn.CellTemplate>
|
||||
<DataTemplate>
|
||||
<Border
|
||||
@@ -831,6 +831,22 @@
|
||||
Header="{x:Static resx:ResUI.menuExit}" />
|
||||
</ContextMenu>
|
||||
</tb:TaskbarIcon.ContextMenu>
|
||||
<tb:TaskbarIcon.TrayToolTip>
|
||||
<Border
|
||||
Width="Auto"
|
||||
Height="Auto"
|
||||
Background="{DynamicResource MaterialDesignLightBackground}"
|
||||
BorderBrush="{DynamicResource MaterialDesignDarkBackground}"
|
||||
BorderThickness="0"
|
||||
CornerRadius="4">
|
||||
<TextBlock
|
||||
Margin="8"
|
||||
HorizontalAlignment="Center"
|
||||
VerticalAlignment="Center"
|
||||
Foreground="{DynamicResource MaterialDesignDarkBackground}"
|
||||
Text="{Binding Mode=OneWay, Path=ToolTipText}" />
|
||||
</Border>
|
||||
</tb:TaskbarIcon.TrayToolTip>
|
||||
</tb:TaskbarIcon>
|
||||
<materialDesign:Snackbar x:Name="MainSnackbar" MessageQueue="{materialDesign:MessageQueue}" />
|
||||
</Grid>
|
||||
|
||||
@@ -150,6 +150,7 @@ namespace v2rayN.Views
|
||||
|
||||
this.OneWayBind(ViewModel, vm => vm.Servers, v => v.cmbServers.ItemsSource).DisposeWith(disposables);
|
||||
this.Bind(ViewModel, vm => vm.SelectedServer, v => v.cmbServers.SelectedItem).DisposeWith(disposables);
|
||||
this.OneWayBind(ViewModel, vm => vm.BlServers, v => v.cmbServers.Visibility).DisposeWith(disposables);
|
||||
|
||||
//tray menu
|
||||
this.BindCommand(ViewModel, vm => vm.AddServerViaClipboardCmd, v => v.menuAddServerViaClipboard2).DisposeWith(disposables);
|
||||
@@ -191,11 +192,16 @@ namespace v2rayN.Views
|
||||
this.Title = $"{Utils.GetVersion()} - {(IsAdministrator ? ResUI.RunAsAdmin : ResUI.NotRunAsAdmin)}";
|
||||
|
||||
spEnableTun.Visibility = IsAdministrator ? Visibility.Visible : Visibility.Collapsed;
|
||||
|
||||
|
||||
if (_config.uiItem.autoHideStartup)
|
||||
{
|
||||
WindowState = WindowState.Minimized;
|
||||
}
|
||||
|
||||
if (!_config.guiItem.enableHWA)
|
||||
{
|
||||
RenderOptions.ProcessRenderMode = RenderMode.SoftwareOnly;
|
||||
}
|
||||
}
|
||||
|
||||
#region Event
|
||||
@@ -439,8 +445,15 @@ namespace v2rayN.Views
|
||||
var item2 = (MyDGTextColumn)lstProfiles.Columns[k];
|
||||
if (item2.ExName == item.Name)
|
||||
{
|
||||
item2.Width = item.Width;
|
||||
item2.DisplayIndex = i + 1;
|
||||
if (item.Width <= 0)
|
||||
{
|
||||
item2.Visibility = Visibility.Hidden;
|
||||
}
|
||||
else
|
||||
{
|
||||
item2.Width = item.Width;
|
||||
item2.DisplayIndex = i + 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -465,7 +478,7 @@ namespace v2rayN.Views
|
||||
lvColumnItem.Add(new()
|
||||
{
|
||||
Name = item2.ExName,
|
||||
Width = Convert.ToInt32(item2.ActualWidth),
|
||||
Width = item2.Visibility == Visibility.Visible ? Convert.ToInt32(item2.ActualWidth) : 0,
|
||||
Index = item2.DisplayIndex
|
||||
});
|
||||
}
|
||||
|
||||
@@ -48,6 +48,7 @@
|
||||
FontSize="{DynamicResource StdFontSizeMsg}"
|
||||
HorizontalScrollBarVisibility="Auto"
|
||||
IsReadOnly="True"
|
||||
IsReadOnlyCaretVisible="True"
|
||||
TextAlignment="Left"
|
||||
TextWrapping="Wrap"
|
||||
VerticalScrollBarVisibility="Visible">
|
||||
|
||||
@@ -23,7 +23,7 @@
|
||||
TextOptions.TextRenderingMode="Auto"
|
||||
WindowStartupLocation="CenterScreen"
|
||||
mc:Ignorable="d">
|
||||
<DockPanel Margin="16">
|
||||
<DockPanel Margin="8">
|
||||
<Grid HorizontalAlignment="Center" DockPanel.Dock="Bottom">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="200" />
|
||||
@@ -481,6 +481,7 @@
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="Auto" />
|
||||
</Grid.RowDefinitions>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="Auto" />
|
||||
@@ -752,6 +753,20 @@
|
||||
Width="300"
|
||||
Margin="{StaticResource SettingItemMargin}"
|
||||
Style="{StaticResource DefComboBox}" />
|
||||
|
||||
<TextBlock
|
||||
Grid.Row="18"
|
||||
Grid.Column="0"
|
||||
Margin="{StaticResource SettingItemMargin}"
|
||||
VerticalAlignment="Center"
|
||||
Style="{StaticResource ToolbarTextBlock}"
|
||||
Text="{x:Static resx:ResUI.TbSettingsEnableHWA}" />
|
||||
<ToggleButton
|
||||
x:Name="togEnableHWA"
|
||||
Grid.Row="18"
|
||||
Grid.Column="1"
|
||||
Margin="{StaticResource SettingItemMargin}"
|
||||
HorizontalAlignment="Left" />
|
||||
</Grid>
|
||||
</ScrollViewer>
|
||||
</TabItem>
|
||||
|
||||
@@ -164,6 +164,7 @@ namespace v2rayN.Views
|
||||
this.Bind(ViewModel, vm => vm.currentFontFamily, v => v.cmbcurrentFontFamily.Text).DisposeWith(disposables);
|
||||
this.Bind(ViewModel, vm => vm.SpeedTestTimeout, v => v.cmbSpeedTestTimeout.Text).DisposeWith(disposables);
|
||||
this.Bind(ViewModel, vm => vm.SpeedTestUrl, v => v.cmbSpeedTestUrl.Text).DisposeWith(disposables);
|
||||
this.Bind(ViewModel, vm => vm.EnableHWA, v => v.togEnableHWA.IsChecked).DisposeWith(disposables);
|
||||
|
||||
|
||||
this.Bind(ViewModel, vm => vm.systemProxyAdvancedProtocol, v => v.cmbsystemProxyAdvancedProtocol.Text).DisposeWith(disposables);
|
||||
|
||||
@@ -134,7 +134,7 @@
|
||||
</Grid>
|
||||
|
||||
<Grid
|
||||
Margin="16"
|
||||
Margin="8"
|
||||
HorizontalAlignment="Center"
|
||||
DockPanel.Dock="Bottom">
|
||||
<Grid.ColumnDefinitions>
|
||||
|
||||
@@ -73,7 +73,7 @@
|
||||
</ToolBarTray>
|
||||
|
||||
<Grid
|
||||
Margin="16"
|
||||
Margin="8"
|
||||
HorizontalAlignment="Center"
|
||||
DockPanel.Dock="Bottom">
|
||||
<Grid.ColumnDefinitions>
|
||||
|
||||
@@ -114,7 +114,7 @@
|
||||
</ToolBarTray>
|
||||
|
||||
<Grid
|
||||
Margin="16"
|
||||
Margin="8"
|
||||
HorizontalAlignment="Center"
|
||||
DockPanel.Dock="Bottom">
|
||||
<Grid.ColumnDefinitions>
|
||||
|
||||
@@ -162,7 +162,7 @@
|
||||
</Grid>
|
||||
<Grid
|
||||
Grid.Row="1"
|
||||
Margin="16"
|
||||
Margin="8"
|
||||
HorizontalAlignment="Center">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="200" />
|
||||
|
||||
@@ -6,4 +6,18 @@
|
||||
<dpiAwareness xmlns="http://schemas.microsoft.com/SMI/2016/WindowsSettings">PerMonitorV2</dpiAwareness>
|
||||
</asmv3:windowsSettings>
|
||||
</asmv3:application>
|
||||
|
||||
<!-- Enable themes for Windows common controls and dialogs (Windows XP and later) -->
|
||||
<dependency>
|
||||
<dependentAssembly>
|
||||
<assemblyIdentity
|
||||
type="win32"
|
||||
name="Microsoft.Windows.Common-Controls"
|
||||
version="6.0.0.0"
|
||||
processorArchitecture="*"
|
||||
publicKeyToken="6595b64144ccf1df"
|
||||
language="*"
|
||||
/>
|
||||
</dependentAssembly>
|
||||
</dependency>
|
||||
</assembly>
|
||||
@@ -10,20 +10,18 @@
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<ApplicationIcon>v2rayN.ico</ApplicationIcon>
|
||||
<Copyright>Copyright © 2017-2023 (GPLv3)</Copyright>
|
||||
<FileVersion>6.15</FileVersion>
|
||||
<FileVersion>6.20</FileVersion>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Downloader" Version="3.0.3" />
|
||||
<PackageReference Include="Downloader" Version="3.0.4" />
|
||||
<PackageReference Include="MaterialDesignThemes" Version="4.7.1" />
|
||||
<PackageReference Include="Hardcodet.NotifyIcon.Wpf" Version="1.1.0" />
|
||||
<PackageReference Include="Newtonsoft.Json" Version="13.0.2" />
|
||||
<PackageReference Include="NHotkey" Version="2.1.0" />
|
||||
<PackageReference Include="NHotkey.Wpf" Version="2.1.0" />
|
||||
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
|
||||
<PackageReference Include="QRCoder.Xaml" Version="1.4.3" />
|
||||
<PackageReference Include="sqlite-net-pcl" Version="1.8.116" />
|
||||
<PackageReference Include="TaskScheduler" Version="2.10.1" />
|
||||
<PackageReference Include="ZXing.Net.Bindings.Windows.Compatibility" Version="0.16.10" />
|
||||
<PackageReference Include="ZXing.Net.Bindings.Windows.Compatibility" Version="0.16.12" />
|
||||
<PackageReference Include="ReactiveUI.Fody" Version="18.4.1" />
|
||||
<PackageReference Include="ReactiveUI.Validation" Version="3.0.22" />
|
||||
<PackageReference Include="ReactiveUI.WPF" Version="18.4.1" />
|
||||
|
||||
Reference in New Issue
Block a user