Compare commits
85 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
2e64f23ef9 | ||
|
|
801d1fd320 | ||
|
|
cfffb5756e | ||
|
|
b30daf8e56 | ||
|
|
84eba671f0 | ||
|
|
f28b93daa0 | ||
|
|
dc16136c59 | ||
|
|
e47caf8c4f | ||
|
|
8ad80bb75d | ||
|
|
22475e459d | ||
|
|
73ad33dfc9 | ||
|
|
f1782c78f4 | ||
|
|
b544dde2c6 | ||
|
|
1a7dca8e58 | ||
|
|
23c7d7fb46 | ||
|
|
65fda407dc | ||
|
|
12ebad436a | ||
|
|
c7297dba7e | ||
|
|
e61368a26e | ||
|
|
b98da3a5dc | ||
|
|
12f3400894 | ||
|
|
4b5508fc3c | ||
|
|
5f40e6e0b7 | ||
|
|
080d660cfa | ||
|
|
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 | ||
|
|
69050bfe41 | ||
|
|
eebc16bcdd | ||
|
|
d4921535f2 | ||
|
|
b1eeb648a7 | ||
|
|
ba702ba041 | ||
|
|
c40d88d0b6 | ||
|
|
285f91e9e8 | ||
|
|
947a7aa7df | ||
|
|
0b37e36036 | ||
|
|
92320f5086 | ||
|
|
ae17e0c264 | ||
|
|
ec756ee943 | ||
|
|
b0ff814753 | ||
|
|
1f7eb2d48a | ||
|
|
eeab8e4a90 | ||
|
|
77fbddf488 | ||
|
|
bf396f8802 | ||
|
|
13cb8b84bf | ||
|
|
3ab992f5fb | ||
|
|
a386ecfc9c | ||
|
|
a71399c42c | ||
|
|
5a5d7e0981 |
1
.gitignore
vendored
1
.gitignore
vendored
@@ -16,3 +16,4 @@
|
||||
/v2rayN/v2rayUpgrade/bin/Release
|
||||
/v2rayN/v2rayUpgrade/obj/
|
||||
*.user
|
||||
/.vs/v2rayN
|
||||
|
||||
@@ -30,8 +30,9 @@ namespace v2rayN
|
||||
{
|
||||
Global.ExePathKey = Utils.GetMD5(Utils.GetExePath());
|
||||
|
||||
var rebootas = (e.Args ?? new string[] { }).Any(t => t == Global.RebootAs);
|
||||
ProgramStarted = new EventWaitHandle(false, EventResetMode.AutoReset, Global.ExePathKey, out bool bCreatedNew);
|
||||
if (!bCreatedNew)
|
||||
if (!rebootas && !bCreatedNew)
|
||||
{
|
||||
ProgramStarted.Set();
|
||||
Current.Shutdown();
|
||||
@@ -42,10 +43,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);
|
||||
|
||||
|
||||
@@ -9,8 +9,9 @@ namespace v2rayN.Base
|
||||
private static readonly Lazy<SqliteHelper> _instance = new(() => new());
|
||||
public static SqliteHelper Instance => _instance.Value;
|
||||
private string _connstr;
|
||||
public SQLiteConnection _db;
|
||||
public SQLiteAsyncConnection _dbAsync;
|
||||
private SQLiteConnection _db;
|
||||
private SQLiteAsyncConnection _dbAsync;
|
||||
private static readonly object objLock = new();
|
||||
|
||||
public SqliteHelper()
|
||||
{
|
||||
@@ -24,17 +25,27 @@ 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);
|
||||
}
|
||||
public int Replace(object model)
|
||||
{
|
||||
return _db.InsertOrReplace(model);
|
||||
lock (objLock)
|
||||
{
|
||||
return _db.InsertOrReplace(model);
|
||||
}
|
||||
}
|
||||
public async Task<int> Replacesync(object model)
|
||||
{
|
||||
@@ -43,7 +54,10 @@ namespace v2rayN.Base
|
||||
|
||||
public int Update(object model)
|
||||
{
|
||||
return _db.Update(model);
|
||||
lock (objLock)
|
||||
{
|
||||
return _db.Update(model);
|
||||
}
|
||||
}
|
||||
public async Task<int> UpdateAsync(object model)
|
||||
{
|
||||
@@ -51,12 +65,18 @@ namespace v2rayN.Base
|
||||
}
|
||||
public int UpdateAll(IEnumerable models)
|
||||
{
|
||||
return _db.UpdateAll(models);
|
||||
lock (objLock)
|
||||
{
|
||||
return _db.UpdateAll(models);
|
||||
}
|
||||
}
|
||||
|
||||
public int Delete(object model)
|
||||
{
|
||||
return _db.Delete(model);
|
||||
lock (objLock)
|
||||
{
|
||||
return _db.Delete(model);
|
||||
}
|
||||
}
|
||||
public async Task<int> DeleteAsync(object 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";
|
||||
@@ -80,6 +80,7 @@
|
||||
public const string DelayUnit = "";
|
||||
public const string SpeedUnit = "";
|
||||
public const int MinFontSize = 10;
|
||||
public const string RebootAs = "rebootas";
|
||||
|
||||
public static readonly List<string> IEProxyProtocols = new() {
|
||||
"{ip}:{http_port}",
|
||||
@@ -92,7 +93,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" };
|
||||
@@ -124,7 +125,6 @@
|
||||
|
||||
#region global variable
|
||||
|
||||
public static bool reloadCore { get; set; }
|
||||
public static int statePort { get; set; }
|
||||
public static Job processJob { get; set; }
|
||||
public static bool ShowInTaskbar { get; set; }
|
||||
|
||||
@@ -195,16 +195,6 @@ namespace v2rayN.Handler
|
||||
config.guiItem.statisticsFreshRate = 1;
|
||||
}
|
||||
|
||||
if (config == null)
|
||||
{
|
||||
Global.reloadCore = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
Global.reloadCore = true;
|
||||
|
||||
}
|
||||
|
||||
LazyConfig.Instance.SetConfig(config);
|
||||
return 0;
|
||||
}
|
||||
@@ -215,7 +205,6 @@ namespace v2rayN.Handler
|
||||
/// <returns></returns>
|
||||
public static int SaveConfig(ref Config config, bool reload = true)
|
||||
{
|
||||
Global.reloadCore = reload;
|
||||
|
||||
ToJsonFile(config);
|
||||
|
||||
@@ -363,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;
|
||||
|
||||
@@ -381,7 +370,7 @@ namespace v2rayN.Handler
|
||||
return -1;
|
||||
}
|
||||
|
||||
AddServerCommon(ref config, profileItem);
|
||||
AddServerCommon(ref config, profileItem, toFile);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -394,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;
|
||||
}
|
||||
|
||||
@@ -410,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";
|
||||
@@ -425,7 +424,7 @@ namespace v2rayN.Handler
|
||||
}
|
||||
else
|
||||
{
|
||||
AddServerCommon(ref config, profileItem);
|
||||
AddServerCommon(ref config, profileItem, true);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -446,7 +445,6 @@ namespace v2rayN.Handler
|
||||
}
|
||||
|
||||
config.indexId = indexId;
|
||||
Global.reloadCore = true;
|
||||
|
||||
ToJsonFile(config);
|
||||
|
||||
@@ -459,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;
|
||||
}
|
||||
@@ -468,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)
|
||||
{
|
||||
@@ -600,7 +593,7 @@ namespace v2rayN.Handler
|
||||
}
|
||||
|
||||
|
||||
AddServerCommon(ref config, profileItem);
|
||||
AddServerCommon(ref config, profileItem, true);
|
||||
|
||||
|
||||
return 0;
|
||||
@@ -632,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;
|
||||
|
||||
@@ -645,7 +638,7 @@ namespace v2rayN.Handler
|
||||
return -1;
|
||||
}
|
||||
|
||||
AddServerCommon(ref config, profileItem);
|
||||
AddServerCommon(ref config, profileItem, toFile);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -656,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;
|
||||
}
|
||||
@@ -673,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;
|
||||
|
||||
@@ -683,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;
|
||||
}
|
||||
@@ -793,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;
|
||||
|
||||
@@ -806,43 +795,56 @@ namespace v2rayN.Handler
|
||||
profileItem.path = profileItem.path.TrimEx();
|
||||
profileItem.streamSecurity = profileItem.streamSecurity.TrimEx();
|
||||
|
||||
AddServerCommon(ref config, profileItem);
|
||||
if (!Global.flows.Contains(profileItem.flow))
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
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;
|
||||
@@ -854,19 +856,12 @@ namespace v2rayN.Handler
|
||||
var maxSort = ProfileExHandler.Instance.GetMaxSort();
|
||||
ProfileExHandler.Instance.SetSort(profileItem.indexId, maxSort + 1);
|
||||
}
|
||||
else if (profileItem.indexId == config.indexId)
|
||||
{
|
||||
Global.reloadCore = true;
|
||||
}
|
||||
|
||||
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)
|
||||
@@ -943,16 +938,14 @@ 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);
|
||||
//}
|
||||
//Check for duplicate indexId
|
||||
List<string>? lstDbIndexId = null;
|
||||
List<ProfileItem> lstAdd = new();
|
||||
string[] arrData = clipboardData.Split(Environment.NewLine.ToCharArray());
|
||||
foreach (string str in arrData)
|
||||
{
|
||||
//maybe sub
|
||||
if (Utils.IsNullOrEmpty(subid) && (str.StartsWith(Global.httpsProtocol) || str.StartsWith(Global.httpProtocol)))
|
||||
if (!isSub && (str.StartsWith(Global.httpsProtocol) || str.StartsWith(Global.httpProtocol)))
|
||||
{
|
||||
if (AddSubItem(ref config, str) == 0)
|
||||
{
|
||||
@@ -969,10 +962,23 @@ 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 = existItem;
|
||||
//Check for duplicate indexId
|
||||
if (lstDbIndexId is null)
|
||||
{
|
||||
lstDbIndexId = LazyConfig.Instance.ProfileItemIndexs("");
|
||||
}
|
||||
if (lstAdd.Any(t => t.indexId == existItem.indexId)
|
||||
|| lstDbIndexId.Any(t => t == existItem.indexId))
|
||||
{
|
||||
profileItem.indexId = string.Empty;
|
||||
}
|
||||
else
|
||||
{
|
||||
profileItem.indexId = existItem.indexId;
|
||||
}
|
||||
}
|
||||
//filter
|
||||
if (!Utils.IsNullOrEmpty(subFilter))
|
||||
@@ -985,43 +991,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);
|
||||
@@ -1185,7 +1187,15 @@ namespace v2rayN.Handler
|
||||
lstOriSub = LazyConfig.Instance.ProfileItems(subid);
|
||||
}
|
||||
|
||||
int counter = AddBatchServers(ref config, clipboardData, subid, isSub, lstOriSub);
|
||||
var counter = 0;
|
||||
if (Utils.IsBase64String(clipboardData))
|
||||
{
|
||||
counter = AddBatchServers(ref config, Utils.Base64Decode(clipboardData), subid, isSub, lstOriSub);
|
||||
}
|
||||
if (counter < 1)
|
||||
{
|
||||
counter = AddBatchServers(ref config, clipboardData, subid, isSub, lstOriSub);
|
||||
}
|
||||
if (counter < 1)
|
||||
{
|
||||
counter = AddBatchServers(ref config, Utils.Base64Decode(clipboardData), subid, isSub, lstOriSub);
|
||||
@@ -1273,6 +1283,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}'");
|
||||
@@ -1281,6 +1292,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;
|
||||
}
|
||||
@@ -1300,17 +1315,11 @@ namespace v2rayN.Handler
|
||||
|
||||
public static int MoveToGroup(Config config, List<ProfileItem> lstProfile, string subid)
|
||||
{
|
||||
foreach (var it in lstProfile)
|
||||
foreach (var item in lstProfile)
|
||||
{
|
||||
var item = LazyConfig.Instance.GetProfileItem(it.indexId);
|
||||
if (item is null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
item.subid = subid;
|
||||
SqliteHelper.Instance.Update(item);
|
||||
}
|
||||
SqliteHelper.Instance.UpdateAll(lstProfile);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -1461,8 +1470,6 @@ namespace v2rayN.Handler
|
||||
config.routingBasicItem.routingIndexId = routingItem.id;
|
||||
}
|
||||
|
||||
Global.reloadCore = true;
|
||||
|
||||
ToJsonFile(config);
|
||||
|
||||
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);
|
||||
|
||||
@@ -1505,6 +1465,11 @@ namespace v2rayN.Handler
|
||||
{
|
||||
continue;
|
||||
}
|
||||
if (item.configType == EConfigType.VLESS
|
||||
&& !Global.flows.Contains(item.flow))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
outbound(item, ref v2rayConfigCopy);
|
||||
v2rayConfigCopy.outbounds[0].tag = Global.agentTag + inbound.port.ToString();
|
||||
|
||||
@@ -27,46 +27,43 @@ namespace v2rayN.Handler
|
||||
|
||||
public void LoadCore(Config config)
|
||||
{
|
||||
if (Global.reloadCore)
|
||||
var node = ConfigHandler.GetDefaultServer(ref config);
|
||||
if (node == null)
|
||||
{
|
||||
var node = ConfigHandler.GetDefaultServer(ref config);
|
||||
if (node == null)
|
||||
{
|
||||
ShowMsg(false, ResUI.CheckServerSettings);
|
||||
return;
|
||||
}
|
||||
ShowMsg(false, ResUI.CheckServerSettings);
|
||||
return;
|
||||
}
|
||||
|
||||
if (SetCore(config, node) != 0)
|
||||
{
|
||||
ShowMsg(false, ResUI.CheckServerSettings);
|
||||
return;
|
||||
}
|
||||
string fileName = Utils.GetConfigPath(_coreCConfigRes);
|
||||
if (CoreConfigHandler.GenerateClientConfig(node, fileName, out string msg, out string content) != 0)
|
||||
{
|
||||
ShowMsg(false, msg);
|
||||
}
|
||||
else
|
||||
{
|
||||
ShowMsg(false, msg);
|
||||
ShowMsg(true, $"{node.GetSummary()}");
|
||||
CoreStop();
|
||||
CoreStart(node);
|
||||
}
|
||||
if (SetCore(config, node) != 0)
|
||||
{
|
||||
ShowMsg(false, ResUI.CheckServerSettings);
|
||||
return;
|
||||
}
|
||||
string fileName = Utils.GetConfigPath(_coreCConfigRes);
|
||||
if (CoreConfigHandler.GenerateClientConfig(node, fileName, out string msg, out string content) != 0)
|
||||
{
|
||||
ShowMsg(false, msg);
|
||||
}
|
||||
else
|
||||
{
|
||||
ShowMsg(false, msg);
|
||||
ShowMsg(true, $"{node.GetSummary()}");
|
||||
CoreStop();
|
||||
CoreStart(node);
|
||||
}
|
||||
|
||||
//start a socks service
|
||||
if (_process != null && !_process.HasExited && node.configType == EConfigType.Custom && node.preSocksPort > 0)
|
||||
//start a socks service
|
||||
if (_process != null && !_process.HasExited && node.configType == EConfigType.Custom && node.preSocksPort > 0)
|
||||
{
|
||||
var itemSocks = new ProfileItem()
|
||||
{
|
||||
var itemSocks = new ProfileItem()
|
||||
{
|
||||
configType = EConfigType.Socks,
|
||||
address = Global.Loopback,
|
||||
port = node.preSocksPort
|
||||
};
|
||||
if (CoreConfigHandler.GenerateClientConfig(itemSocks, null, out string msg2, out string configStr) == 0)
|
||||
{
|
||||
_processId = CoreStartViaString(configStr);
|
||||
}
|
||||
configType = EConfigType.Socks,
|
||||
address = Global.Loopback,
|
||||
port = node.preSocksPort
|
||||
};
|
||||
if (CoreConfigHandler.GenerateClientConfig(itemSocks, null, out string msg2, out string configStr) == 0)
|
||||
{
|
||||
_processId = CoreStartViaString(configStr);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -159,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;
|
||||
@@ -216,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);
|
||||
|
||||
@@ -188,9 +188,11 @@ namespace v2rayN.Handler
|
||||
try
|
||||
{
|
||||
Utils.SetSecurityProtocol(LazyConfig.Instance.GetConfig().guiItem.enableSecurityProtocolTls13);
|
||||
var webProxy = GetWebProxy(blProxy);
|
||||
var client = new HttpClient(new SocketsHttpHandler()
|
||||
{
|
||||
Proxy = GetWebProxy(blProxy)
|
||||
Proxy = webProxy,
|
||||
UseProxy = webProxy != null
|
||||
});
|
||||
|
||||
if (Utils.IsNullOrEmpty(userAgent))
|
||||
|
||||
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 Microsoft.Win32;
|
||||
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;
|
||||
@@ -144,7 +142,7 @@ namespace v2rayN.Handler
|
||||
FilterIndex = 2,
|
||||
RestoreDirectory = true
|
||||
};
|
||||
if (fileDialog.ShowDialog() != DialogResult.OK)
|
||||
if (fileDialog.ShowDialog() != true)
|
||||
{
|
||||
return;
|
||||
}
|
||||
@@ -183,7 +181,7 @@ namespace v2rayN.Handler
|
||||
FilterIndex = 2,
|
||||
RestoreDirectory = true
|
||||
};
|
||||
if (fileDialog.ShowDialog() != DialogResult.OK)
|
||||
if (fileDialog.ShowDialog() != true)
|
||||
{
|
||||
return;
|
||||
}
|
||||
@@ -220,7 +218,7 @@ namespace v2rayN.Handler
|
||||
FilterIndex = 2,
|
||||
RestoreDirectory = true
|
||||
};
|
||||
if (fileDialog.ShowDialog() != DialogResult.OK)
|
||||
if (fileDialog.ShowDialog() != true)
|
||||
{
|
||||
return;
|
||||
}
|
||||
@@ -248,22 +246,22 @@ namespace v2rayN.Handler
|
||||
public bool RestoreGuiNConfig(ref Config config)
|
||||
{
|
||||
var fileContent = string.Empty;
|
||||
using (OpenFileDialog fileDialog = new())
|
||||
{
|
||||
fileDialog.InitialDirectory = Utils.GetBackupPath("");
|
||||
fileDialog.Filter = "guiNConfig|*.json|All|*.*";
|
||||
fileDialog.FilterIndex = 2;
|
||||
fileDialog.RestoreDirectory = true;
|
||||
OpenFileDialog fileDialog = new();
|
||||
|
||||
if (fileDialog.ShowDialog() == DialogResult.OK)
|
||||
{
|
||||
fileContent = Utils.LoadResource(fileDialog.FileName);
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
fileDialog.InitialDirectory = Utils.GetBackupPath("");
|
||||
fileDialog.Filter = "guiNConfig|*.json|All|*.*";
|
||||
fileDialog.FilterIndex = 2;
|
||||
fileDialog.RestoreDirectory = true;
|
||||
|
||||
if (fileDialog.ShowDialog() == true)
|
||||
{
|
||||
fileContent = Utils.LoadResource(fileDialog.FileName);
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (Utils.IsNullOrEmpty(fileContent))
|
||||
{
|
||||
UI.ShowWarning(ResUI.OperationFailed);
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -24,7 +24,7 @@ namespace v2rayN.Handler
|
||||
|
||||
_lstProfileEx = new(SqliteHelper.Instance.Table<ProfileExItem>());
|
||||
|
||||
Task.Run(async () =>
|
||||
Task.Run(() =>
|
||||
{
|
||||
while (true)
|
||||
{
|
||||
@@ -35,7 +35,7 @@ namespace v2rayN.Handler
|
||||
var item = _lstProfileEx.FirstOrDefault(t => t.indexId == id);
|
||||
if (item is not null)
|
||||
{
|
||||
await SqliteHelper.Instance.Replacesync(item);
|
||||
SqliteHelper.Instance.Replace(item);
|
||||
}
|
||||
}
|
||||
Thread.Sleep(1000 * 60);
|
||||
|
||||
@@ -49,7 +49,7 @@ namespace v2rayN.Handler
|
||||
VmessQRCode vmessQRCode = new()
|
||||
{
|
||||
v = item.configVersion.ToString(),
|
||||
ps = item.remarks.TrimEx(), //备注也许很长 ;
|
||||
ps = item.remarks.TrimEx(),
|
||||
add = item.address,
|
||||
port = item.port.ToString(),
|
||||
id = item.id,
|
||||
@@ -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;
|
||||
|
||||
@@ -162,7 +162,7 @@ namespace v2rayN.Handler
|
||||
todayDown = 0,
|
||||
dateNow = ticks
|
||||
};
|
||||
_ = SqliteHelper.Instance.Replacesync(_serverStatItem);
|
||||
SqliteHelper.Instance.Replace(_serverStatItem);
|
||||
_lstServerStat.Add(_serverStatItem);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
using Splat;
|
||||
using DynamicData;
|
||||
using Splat;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
using System.Text.RegularExpressions;
|
||||
using System.Windows.Forms;
|
||||
using System.Windows;
|
||||
using v2rayN.Base;
|
||||
using v2rayN.Mode;
|
||||
using v2rayN.Resx;
|
||||
@@ -163,36 +164,22 @@ namespace v2rayN.Handler
|
||||
|
||||
Task.Run(async () =>
|
||||
{
|
||||
//Turn off system proxy
|
||||
bool bSysProxyType = false;
|
||||
if (!blProxy && config.sysProxyType == ESysProxyType.ForcedChange)
|
||||
{
|
||||
bSysProxyType = true;
|
||||
config.sysProxyType = ESysProxyType.ForcedClear;
|
||||
SysProxyHandle.UpdateSysProxy(config, false);
|
||||
Thread.Sleep(3000);
|
||||
}
|
||||
|
||||
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) =>
|
||||
@@ -200,16 +187,55 @@ namespace v2rayN.Handler
|
||||
_updateFunc(false, $"{hashCode}{args.GetException().Message}");
|
||||
};
|
||||
|
||||
//idn to idc
|
||||
url = Utils.GetPunycode(url);
|
||||
|
||||
_updateFunc(false, $"{hashCode}{ResUI.MsgStartGettingSubscriptions}");
|
||||
|
||||
//one url
|
||||
url = Utils.GetPunycode(url);
|
||||
var result = await downloadHandle.TryDownloadString(url, blProxy, userAgent);
|
||||
if (blProxy && Utils.IsNullOrEmpty(result))
|
||||
{
|
||||
result = await downloadHandle.TryDownloadString(url, false, userAgent);
|
||||
}
|
||||
|
||||
//more url
|
||||
if (!Utils.IsNullOrEmpty(item.moreUrl.TrimEx()))
|
||||
{
|
||||
if (!Utils.IsNullOrEmpty(result) && Utils.IsBase64String(result))
|
||||
{
|
||||
result = Utils.Base64Decode(result);
|
||||
}
|
||||
|
||||
var lstUrl = new List<string>
|
||||
{
|
||||
item.moreUrl.TrimEx().Split(",")
|
||||
};
|
||||
foreach (var it in lstUrl)
|
||||
{
|
||||
var url2 = Utils.GetPunycode(it);
|
||||
if (Utils.IsNullOrEmpty(url2))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
var result2 = await downloadHandle.TryDownloadString(url2, blProxy, userAgent);
|
||||
if (blProxy && Utils.IsNullOrEmpty(result2))
|
||||
{
|
||||
result2 = await downloadHandle.TryDownloadString(url2, false, userAgent);
|
||||
}
|
||||
if (!Utils.IsNullOrEmpty(result2))
|
||||
{
|
||||
if (Utils.IsBase64String(result2))
|
||||
{
|
||||
result += Utils.Base64Decode(result2);
|
||||
}
|
||||
else
|
||||
{
|
||||
result += result2;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (Utils.IsNullOrEmpty(result))
|
||||
{
|
||||
_updateFunc(false, $"{hashCode}{ResUI.MsgSubscriptionDecodingFailed}");
|
||||
@@ -235,18 +261,12 @@ namespace v2rayN.Handler
|
||||
}
|
||||
_updateFunc(false, "-------------------------------------------------------");
|
||||
}
|
||||
//restore system proxy
|
||||
if (bSysProxyType)
|
||||
{
|
||||
config.sysProxyType = ESysProxyType.ForcedChange;
|
||||
SysProxyHandle.UpdateSysProxy(config, false);
|
||||
}
|
||||
|
||||
_updateFunc(true, $"{ResUI.MsgUpdateSubscriptionEnd}");
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
public void UpdateGeoFile(string geoName, Config config, Action<bool, string> update)
|
||||
{
|
||||
_config = config;
|
||||
@@ -483,7 +503,7 @@ namespace v2rayN.Handler
|
||||
bool blDownload = false;
|
||||
if (blAsk)
|
||||
{
|
||||
if (UI.ShowYesNo(string.Format(ResUI.DownloadYesNo, url)) == DialogResult.Yes)
|
||||
if (UI.ShowYesNo(string.Format(ResUI.DownloadYesNo, url)) == MessageBoxResult.Yes)
|
||||
{
|
||||
blDownload = true;
|
||||
}
|
||||
|
||||
@@ -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; }
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -301,7 +301,7 @@
|
||||
get; set;
|
||||
}
|
||||
/// <summary>
|
||||
/// 备注或别名
|
||||
///
|
||||
/// </summary>
|
||||
public string remarks
|
||||
{
|
||||
|
||||
9
v2rayN/v2rayN/Mode/EViewAction.cs
Normal file
9
v2rayN/v2rayN/Mode/EViewAction.cs
Normal file
@@ -0,0 +1,9 @@
|
||||
namespace v2rayN.Mode
|
||||
{
|
||||
public enum EViewAction
|
||||
{
|
||||
AdjustMainLvColWidth,
|
||||
ProfilesFocus
|
||||
|
||||
}
|
||||
}
|
||||
@@ -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; }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,45 +6,20 @@ namespace v2rayN.Mode
|
||||
public class SubItem
|
||||
{
|
||||
[PrimaryKey]
|
||||
public string id
|
||||
{
|
||||
get; set;
|
||||
}
|
||||
public string id { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 备注
|
||||
/// </summary>
|
||||
public string remarks
|
||||
{
|
||||
get; set;
|
||||
}
|
||||
public string remarks { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// url
|
||||
/// </summary>
|
||||
public string url
|
||||
{
|
||||
get; set;
|
||||
}
|
||||
public string url { get; set; }
|
||||
|
||||
public string moreUrl { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// enable
|
||||
/// </summary>
|
||||
public bool enabled { get; set; } = true;
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public string userAgent
|
||||
{
|
||||
get; set;
|
||||
} = string.Empty;
|
||||
public string userAgent { get; set; } = string.Empty;
|
||||
|
||||
public int sort { get; set; }
|
||||
|
||||
public int sort
|
||||
{
|
||||
get; set;
|
||||
}
|
||||
public string filter { 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; }
|
||||
|
||||
}
|
||||
|
||||
|
||||
209
v2rayN/v2rayN/Resx/ResUI.Designer.cs
generated
209
v2rayN/v2rayN/Resx/ResUI.Designer.cs
generated
@@ -366,15 +366,6 @@ namespace v2rayN.Resx {
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查找类似 Alias 的本地化字符串。
|
||||
/// </summary>
|
||||
public static string LvAlias {
|
||||
get {
|
||||
return ResourceManager.GetString("LvAlias", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查找类似 Count 的本地化字符串。
|
||||
/// </summary>
|
||||
@@ -420,6 +411,15 @@ namespace v2rayN.Resx {
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查找类似 More urls, separated by commas 的本地化字符串。
|
||||
/// </summary>
|
||||
public static string LvMoreUrl {
|
||||
get {
|
||||
return ResourceManager.GetString("LvMoreUrl", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查找类似 Port 的本地化字符串。
|
||||
/// </summary>
|
||||
@@ -474,15 +474,6 @@ namespace v2rayN.Resx {
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查找类似 Test Results 的本地化字符串。
|
||||
/// </summary>
|
||||
public static string LvTestResults {
|
||||
get {
|
||||
return ResourceManager.GetString("LvTestResults", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查找类似 Speed(M/s) 的本地化字符串。
|
||||
/// </summary>
|
||||
@@ -564,15 +555,6 @@ namespace v2rayN.Resx {
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查找类似 Medium 的本地化字符串。
|
||||
/// </summary>
|
||||
public static string MediumFresh {
|
||||
get {
|
||||
return ResourceManager.GetString("MediumFresh", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查找类似 Add a custom configuration server 的本地化字符串。
|
||||
/// </summary>
|
||||
@@ -933,6 +915,15 @@ namespace v2rayN.Resx {
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查找类似 Reboot as administrator 的本地化字符串。
|
||||
/// </summary>
|
||||
public static string menuRebootAsAdmin {
|
||||
get {
|
||||
return ResourceManager.GetString("menuRebootAsAdmin", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查找类似 Reload 的本地化字符串。
|
||||
/// </summary>
|
||||
@@ -1384,7 +1375,7 @@ namespace v2rayN.Resx {
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查找类似 Please fill in the address (Url) 的本地化字符串。
|
||||
/// 查找类似 Please fill in the Url 的本地化字符串。
|
||||
/// </summary>
|
||||
public static string MsgNeedUrl {
|
||||
get {
|
||||
@@ -1401,24 +1392,6 @@ namespace v2rayN.Resx {
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查找类似 PAC update failed 的本地化字符串。
|
||||
/// </summary>
|
||||
public static string MsgPACUpdateFailed {
|
||||
get {
|
||||
return ResourceManager.GetString("MsgPACUpdateFailed", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查找类似 PAC update succeeded 的本地化字符串。
|
||||
/// </summary>
|
||||
public static string MsgPACUpdateSuccessfully {
|
||||
get {
|
||||
return ResourceManager.GetString("MsgPACUpdateSuccessfully", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查找类似 Resolve {0} successfully 的本地化字符串。
|
||||
/// </summary>
|
||||
@@ -1438,11 +1411,11 @@ namespace v2rayN.Resx {
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查找类似 Simplify PAC Success 的本地化字符串。
|
||||
/// 查找类似 Updates are not enabled, skip this subscription 的本地化字符串。
|
||||
/// </summary>
|
||||
public static string MsgSimplifyPAC {
|
||||
public static string MsgSkipSubscriptionUpdate {
|
||||
get {
|
||||
return ResourceManager.GetString("MsgSimplifyPAC", resourceCulture);
|
||||
return ResourceManager.GetString("MsgSkipSubscriptionUpdate", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1464,15 +1437,6 @@ namespace v2rayN.Resx {
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查找类似 Start updating PAC... 的本地化字符串。
|
||||
/// </summary>
|
||||
public static string MsgStartUpdatingPAC {
|
||||
get {
|
||||
return ResourceManager.GetString("MsgStartUpdatingPAC", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查找类似 Invalid subscription content 的本地化字符串。
|
||||
/// </summary>
|
||||
@@ -1527,24 +1491,6 @@ namespace v2rayN.Resx {
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查找类似 This feature relies on the Http global proxy, please set it correctly first. 的本地化字符串。
|
||||
/// </summary>
|
||||
public static string NeedHttpGlobalProxy {
|
||||
get {
|
||||
return ResourceManager.GetString("NeedHttpGlobalProxy", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查找类似 Normal use of this version requires .NET Framework 4.8 的本地化字符串。
|
||||
/// </summary>
|
||||
public static string NetFrameworkRequirementsTip {
|
||||
get {
|
||||
return ResourceManager.GetString("NetFrameworkRequirementsTip", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查找类似 Non-VMess or ss protocol 的本地化字符串。
|
||||
/// </summary>
|
||||
@@ -1653,15 +1599,6 @@ namespace v2rayN.Resx {
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查找类似 Fast 的本地化字符串。
|
||||
/// </summary>
|
||||
public static string QuickFresh {
|
||||
get {
|
||||
return ResourceManager.GetString("QuickFresh", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查找类似 Global hotkey {0} registered failed, reason {1} 的本地化字符串。
|
||||
/// </summary>
|
||||
@@ -1744,20 +1681,11 @@ namespace v2rayN.Resx {
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查找类似 Slow 的本地化字符串。
|
||||
/// 查找类似 {0}:{1}/s↑ | {2}/s↓ 的本地化字符串。
|
||||
/// </summary>
|
||||
public static string SlowFresh {
|
||||
public static string SpeedDisplayText {
|
||||
get {
|
||||
return ResourceManager.GetString("SlowFresh", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查找类似 Note: This feature relies on the Http global proxy. Please manually adjust the Http global proxy and active node after testing. 的本地化字符串。
|
||||
/// </summary>
|
||||
public static string SpeedServerTips {
|
||||
get {
|
||||
return ResourceManager.GetString("SpeedServerTips", resourceCulture);
|
||||
return ResourceManager.GetString("SpeedDisplayText", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1789,11 +1717,11 @@ namespace v2rayN.Resx {
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查找类似 PAC failed to start. Please run this program as Administrator. 的本地化字符串。
|
||||
/// 查找类似 Waiting for testing 的本地化字符串。
|
||||
/// </summary>
|
||||
public static string StartPacFailed {
|
||||
public static string SpeedtestingWait {
|
||||
get {
|
||||
return ResourceManager.GetString("StartPacFailed", resourceCulture);
|
||||
return ResourceManager.GetString("SpeedtestingWait", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2167,6 +2095,15 @@ namespace v2rayN.Resx {
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查找类似 PublicKey 的本地化字符串。
|
||||
/// </summary>
|
||||
public static string TbPublicKey {
|
||||
get {
|
||||
return ResourceManager.GetString("TbPublicKey", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查找类似 Alias (remarks) 的本地化字符串。
|
||||
/// </summary>
|
||||
@@ -2320,15 +2257,6 @@ namespace v2rayN.Resx {
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查找类似 Automatic latency test interval (minutes) 的本地化字符串。
|
||||
/// </summary>
|
||||
public static string TbSettingsAutoTest {
|
||||
get {
|
||||
return ResourceManager.GetString("TbSettingsAutoTest", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查找类似 Automatic update interval of subscriptions (hours) 的本地化字符串。
|
||||
/// </summary>
|
||||
@@ -2500,6 +2428,15 @@ namespace v2rayN.Resx {
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查找类似 Enable hardware acceleration(Require restart) 的本地化字符串。
|
||||
/// </summary>
|
||||
public static string TbSettingsEnableHWA {
|
||||
get {
|
||||
return ResourceManager.GetString("TbSettingsEnableHWA", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查找类似 Exception 的本地化字符串。
|
||||
/// </summary>
|
||||
@@ -2545,15 +2482,6 @@ namespace v2rayN.Resx {
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查找类似 Enable IPv6 的本地化字符串。
|
||||
/// </summary>
|
||||
public static string TbSettingsIpv6 {
|
||||
get {
|
||||
return ResourceManager.GetString("TbSettingsIpv6", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查找类似 Keep older when deduplication 的本地化字符串。
|
||||
/// </summary>
|
||||
@@ -2617,15 +2545,6 @@ namespace v2rayN.Resx {
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查找类似 Pac listen port 的本地化字符串。
|
||||
/// </summary>
|
||||
public static string TbSettingsPacListenPort {
|
||||
get {
|
||||
return ResourceManager.GetString("TbSettingsPacListenPort", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查找类似 Auth pass 的本地化字符串。
|
||||
/// </summary>
|
||||
@@ -2653,15 +2572,6 @@ namespace v2rayN.Resx {
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查找类似 After modifying the following parameters, click Save to take effect 的本地化字符串。
|
||||
/// </summary>
|
||||
public static string TbSettingsSaveTip {
|
||||
get {
|
||||
return ResourceManager.GetString("TbSettingsSaveTip", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查找类似 Set Win10 UWP Loopback 的本地化字符串。
|
||||
/// </summary>
|
||||
@@ -2896,6 +2806,15 @@ namespace v2rayN.Resx {
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查找类似 ShortId 的本地化字符串。
|
||||
/// </summary>
|
||||
public static string TbShortId {
|
||||
get {
|
||||
return ResourceManager.GetString("TbShortId", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查找类似 SNI 的本地化字符串。
|
||||
/// </summary>
|
||||
@@ -2905,6 +2824,15 @@ namespace v2rayN.Resx {
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查找类似 SpiderX 的本地化字符串。
|
||||
/// </summary>
|
||||
public static string TbSpiderX {
|
||||
get {
|
||||
return ResourceManager.GetString("TbSpiderX", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查找类似 TLS 的本地化字符串。
|
||||
/// </summary>
|
||||
@@ -2950,6 +2878,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>
|
||||
|
||||
@@ -195,9 +195,6 @@
|
||||
<data name="LvAddress" xml:space="preserve">
|
||||
<value>آدرس</value>
|
||||
</data>
|
||||
<data name="LvAlias" xml:space="preserve">
|
||||
<value>Alias</value>
|
||||
</data>
|
||||
<data name="LvEncryptionMethod" xml:space="preserve">
|
||||
<value>امنیت</value>
|
||||
</data>
|
||||
@@ -210,9 +207,6 @@
|
||||
<data name="LvSubscription" xml:space="preserve">
|
||||
<value>گروه فرعی</value>
|
||||
</data>
|
||||
<data name="LvTestResults" xml:space="preserve">
|
||||
<value>نتایج تست</value>
|
||||
</data>
|
||||
<data name="LvTodayDownloadDataAmount" xml:space="preserve">
|
||||
<value> ترافیک دانلود امروز</value>
|
||||
</data>
|
||||
@@ -228,9 +222,6 @@
|
||||
<data name="LvTransportProtocol" xml:space="preserve">
|
||||
<value>جابجایی</value>
|
||||
</data>
|
||||
<data name="MediumFresh" xml:space="preserve">
|
||||
<value>متوسط</value>
|
||||
</data>
|
||||
<data name="MsgClearSubscription" xml:space="preserve">
|
||||
<value>محتوای اشتراک اصلی را پاک کنید</value>
|
||||
</data>
|
||||
@@ -246,27 +237,15 @@
|
||||
<data name="MsgNoValidSubscription" xml:space="preserve">
|
||||
<value>هیچ اشتراک معتبری تنظیم نشده است</value>
|
||||
</data>
|
||||
<data name="MsgPACUpdateFailed" xml:space="preserve">
|
||||
<value>به روز رسانی PAC ناموفق بود</value>
|
||||
</data>
|
||||
<data name="MsgPACUpdateSuccessfully" xml:space="preserve">
|
||||
<value>به روز رسانی PAC با موفقیت انجام شد</value>
|
||||
</data>
|
||||
<data name="MsgParsingSuccessfully" xml:space="preserve">
|
||||
<value>Resolve {0} successfully</value>
|
||||
</data>
|
||||
<data name="MsgSimplifyPAC" xml:space="preserve">
|
||||
<value>Simplify PAC Success</value>
|
||||
</data>
|
||||
<data name="MsgStartGettingSubscriptions" xml:space="preserve">
|
||||
<value>شروع به دریافت اشتراک شد</value>
|
||||
</data>
|
||||
<data name="MsgStartUpdating" xml:space="preserve">
|
||||
<value>شروع بروزرسانی {0}...</value>
|
||||
</data>
|
||||
<data name="MsgStartUpdatingPAC" xml:space="preserve">
|
||||
<value>شروع بروزرسانی PAC...</value>
|
||||
</data>
|
||||
<data name="MsgSubscriptionDecodingFailed" xml:space="preserve">
|
||||
<value>محتوای اشتراک نامعتبر است</value>
|
||||
</data>
|
||||
@@ -285,9 +264,6 @@
|
||||
<data name="MsgUpdateV2rayCoreSuccessfullyMore" xml:space="preserve">
|
||||
<value>هسته با موفقیت بروزرسانی شد! راه اندازی مجدد سرویس...</value>
|
||||
</data>
|
||||
<data name="NeedHttpGlobalProxy" xml:space="preserve">
|
||||
<value> This feature relies on the Http global proxy, please set it correctly first.</value>
|
||||
</data>
|
||||
<data name="NonvmessOrssProtocol" xml:space="preserve">
|
||||
<value>Non-VMess or ss protocol</value>
|
||||
</data>
|
||||
@@ -315,9 +291,6 @@
|
||||
<data name="PleaseSelectServer" xml:space="preserve">
|
||||
<value>لطفا ابتدا سرور را انتخاب کنید</value>
|
||||
</data>
|
||||
<data name="QuickFresh" xml:space="preserve">
|
||||
<value>سریع</value>
|
||||
</data>
|
||||
<data name="RemoveDuplicateServerResult" xml:space="preserve">
|
||||
<value>Servers deduplication completed. Old: {0}, New: {1}.</value>
|
||||
</data>
|
||||
@@ -330,15 +303,6 @@
|
||||
<data name="SaveServerConfigurationIn" xml:space="preserve">
|
||||
<value>The server configuration file is saved at: {0}</value>
|
||||
</data>
|
||||
<data name="SlowFresh" xml:space="preserve">
|
||||
<value>آهسته. تدریجی</value>
|
||||
</data>
|
||||
<data name="SpeedServerTips" xml:space="preserve">
|
||||
<value>توجه: این ویژگی به پروکسی جهانی Http متکی است. لطفاً پس از آزمایش، پراکسی جهانی Http و گره فعال را به صورت دستی تنظیم کنید.</value>
|
||||
</data>
|
||||
<data name="StartPacFailed" xml:space="preserve">
|
||||
<value>PAC شروع نشد. لطفا این برنامه را به عنوان Administrator اجرا کنید.</value>
|
||||
</data>
|
||||
<data name="StartService" xml:space="preserve">
|
||||
<value>Start service ({0})...</value>
|
||||
</data>
|
||||
@@ -472,9 +436,6 @@
|
||||
<data name="MsgServerTitle" xml:space="preserve">
|
||||
<value>فیلتر سرورها</value>
|
||||
</data>
|
||||
<data name="NetFrameworkRequirementsTip" xml:space="preserve">
|
||||
<value>استفاده معمولی از این نسخه به .NET Framework 4.8 نیاز دارد</value>
|
||||
</data>
|
||||
<data name="menuCheckUpdate" xml:space="preserve">
|
||||
<value>بررسی بروزرسانی</value>
|
||||
</data>
|
||||
@@ -763,9 +724,6 @@
|
||||
<data name="TbSettingsAutoHideStartup" xml:space="preserve">
|
||||
<value>Auto hide startup</value>
|
||||
</data>
|
||||
<data name="TbSettingsAutoTest" xml:space="preserve">
|
||||
<value>فاصله تست تأخیر خودکار (دقیقه)</value>
|
||||
</data>
|
||||
<data name="TbSettingsAutoUpdate" xml:space="preserve">
|
||||
<value>فاصله به روز رسانی خودکار اشتراک ها (ساعت)</value>
|
||||
</data>
|
||||
@@ -808,9 +766,6 @@
|
||||
<data name="TbSettingsIgnoreGeoUpdateCore" xml:space="preserve">
|
||||
<value>هنگام بهروزرسانی هسته، فایلهای Geo را نادیده بگیرید</value>
|
||||
</data>
|
||||
<data name="TbSettingsIpv6" xml:space="preserve">
|
||||
<value>IPv6 را فعال کنید</value>
|
||||
</data>
|
||||
<data name="TbSettingsKeepOlderDedupl" xml:space="preserve">
|
||||
<value>Keep older when deduplication</value>
|
||||
</data>
|
||||
@@ -826,18 +781,12 @@
|
||||
<data name="TbSettingsN" xml:space="preserve">
|
||||
<value>تنظیمات v2rayN</value>
|
||||
</data>
|
||||
<data name="TbSettingsPacListenPort" xml:space="preserve">
|
||||
<value>Pac پورت درحال شنود</value>
|
||||
</data>
|
||||
<data name="TbSettingsPass" xml:space="preserve">
|
||||
<value>Auth pass</value>
|
||||
</data>
|
||||
<data name="TbSettingsRemoteDNS" xml:space="preserve">
|
||||
<value>سفارشی DNS (multiple, separated by commas (,))</value>
|
||||
</data>
|
||||
<data name="TbSettingsSaveTip" xml:space="preserve">
|
||||
<value>After modifying the following parameters, click Save to take effect</value>
|
||||
</data>
|
||||
<data name="TbSettingsSetUWP" xml:space="preserve">
|
||||
<value>Set Win10 UWP Loopback</value>
|
||||
</data>
|
||||
@@ -1066,4 +1015,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>
|
||||
@@ -195,9 +195,6 @@
|
||||
<data name="LvAddress" xml:space="preserve">
|
||||
<value>Address</value>
|
||||
</data>
|
||||
<data name="LvAlias" xml:space="preserve">
|
||||
<value>Alias</value>
|
||||
</data>
|
||||
<data name="LvEncryptionMethod" xml:space="preserve">
|
||||
<value>Security</value>
|
||||
</data>
|
||||
@@ -210,9 +207,6 @@
|
||||
<data name="LvSubscription" xml:space="preserve">
|
||||
<value>Subs group</value>
|
||||
</data>
|
||||
<data name="LvTestResults" xml:space="preserve">
|
||||
<value>Test Results</value>
|
||||
</data>
|
||||
<data name="LvTodayDownloadDataAmount" xml:space="preserve">
|
||||
<value>Download traffic today</value>
|
||||
</data>
|
||||
@@ -228,9 +222,6 @@
|
||||
<data name="LvTransportProtocol" xml:space="preserve">
|
||||
<value>Transport</value>
|
||||
</data>
|
||||
<data name="MediumFresh" xml:space="preserve">
|
||||
<value>Medium</value>
|
||||
</data>
|
||||
<data name="MsgClearSubscription" xml:space="preserve">
|
||||
<value>Clear original subscription content</value>
|
||||
</data>
|
||||
@@ -246,27 +237,15 @@
|
||||
<data name="MsgNoValidSubscription" xml:space="preserve">
|
||||
<value>No valid subscriptions set</value>
|
||||
</data>
|
||||
<data name="MsgPACUpdateFailed" xml:space="preserve">
|
||||
<value>PAC update failed</value>
|
||||
</data>
|
||||
<data name="MsgPACUpdateSuccessfully" xml:space="preserve">
|
||||
<value>PAC update succeeded</value>
|
||||
</data>
|
||||
<data name="MsgParsingSuccessfully" xml:space="preserve">
|
||||
<value>Resolve {0} successfully</value>
|
||||
</data>
|
||||
<data name="MsgSimplifyPAC" xml:space="preserve">
|
||||
<value>Simplify PAC Success</value>
|
||||
</data>
|
||||
<data name="MsgStartGettingSubscriptions" xml:space="preserve">
|
||||
<value>Start getting subscriptions</value>
|
||||
</data>
|
||||
<data name="MsgStartUpdating" xml:space="preserve">
|
||||
<value>Start updating {0}...</value>
|
||||
</data>
|
||||
<data name="MsgStartUpdatingPAC" xml:space="preserve">
|
||||
<value>Start updating PAC...</value>
|
||||
</data>
|
||||
<data name="MsgSubscriptionDecodingFailed" xml:space="preserve">
|
||||
<value>Invalid subscription content</value>
|
||||
</data>
|
||||
@@ -285,9 +264,6 @@
|
||||
<data name="MsgUpdateV2rayCoreSuccessfullyMore" xml:space="preserve">
|
||||
<value>Update Core successfully! Restarting service...</value>
|
||||
</data>
|
||||
<data name="NeedHttpGlobalProxy" xml:space="preserve">
|
||||
<value> This feature relies on the Http global proxy, please set it correctly first.</value>
|
||||
</data>
|
||||
<data name="NonvmessOrssProtocol" xml:space="preserve">
|
||||
<value>Non-VMess or ss protocol</value>
|
||||
</data>
|
||||
@@ -315,9 +291,6 @@
|
||||
<data name="PleaseSelectServer" xml:space="preserve">
|
||||
<value>Please select the server first</value>
|
||||
</data>
|
||||
<data name="QuickFresh" xml:space="preserve">
|
||||
<value>Fast</value>
|
||||
</data>
|
||||
<data name="RemoveDuplicateServerResult" xml:space="preserve">
|
||||
<value>Servers deduplication completed. Old: {0}, New: {1}.</value>
|
||||
</data>
|
||||
@@ -330,15 +303,6 @@
|
||||
<data name="SaveServerConfigurationIn" xml:space="preserve">
|
||||
<value>The server configuration file is saved at: {0}</value>
|
||||
</data>
|
||||
<data name="SlowFresh" xml:space="preserve">
|
||||
<value>Slow</value>
|
||||
</data>
|
||||
<data name="SpeedServerTips" xml:space="preserve">
|
||||
<value>Note: This feature relies on the Http global proxy. Please manually adjust the Http global proxy and active node after testing.</value>
|
||||
</data>
|
||||
<data name="StartPacFailed" xml:space="preserve">
|
||||
<value>PAC failed to start. Please run this program as Administrator.</value>
|
||||
</data>
|
||||
<data name="StartService" xml:space="preserve">
|
||||
<value>Start service ({0})...</value>
|
||||
</data>
|
||||
@@ -380,7 +344,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>
|
||||
@@ -472,9 +436,6 @@
|
||||
<data name="MsgServerTitle" xml:space="preserve">
|
||||
<value>Servers Filter</value>
|
||||
</data>
|
||||
<data name="NetFrameworkRequirementsTip" xml:space="preserve">
|
||||
<value>Normal use of this version requires .NET Framework 4.8</value>
|
||||
</data>
|
||||
<data name="menuCheckUpdate" xml:space="preserve">
|
||||
<value>Check Update</value>
|
||||
</data>
|
||||
@@ -763,9 +724,6 @@
|
||||
<data name="TbSettingsAutoHideStartup" xml:space="preserve">
|
||||
<value>Auto hide startup</value>
|
||||
</data>
|
||||
<data name="TbSettingsAutoTest" xml:space="preserve">
|
||||
<value>Automatic latency test interval (minutes)</value>
|
||||
</data>
|
||||
<data name="TbSettingsAutoUpdate" xml:space="preserve">
|
||||
<value>Automatic update interval of subscriptions (hours)</value>
|
||||
</data>
|
||||
@@ -808,9 +766,6 @@
|
||||
<data name="TbSettingsIgnoreGeoUpdateCore" xml:space="preserve">
|
||||
<value>Ignore Geo files when updating core</value>
|
||||
</data>
|
||||
<data name="TbSettingsIpv6" xml:space="preserve">
|
||||
<value>Enable IPv6</value>
|
||||
</data>
|
||||
<data name="TbSettingsKeepOlderDedupl" xml:space="preserve">
|
||||
<value>Keep older when deduplication</value>
|
||||
</data>
|
||||
@@ -826,18 +781,12 @@
|
||||
<data name="TbSettingsN" xml:space="preserve">
|
||||
<value>v2rayN settings</value>
|
||||
</data>
|
||||
<data name="TbSettingsPacListenPort" xml:space="preserve">
|
||||
<value>Pac listen port</value>
|
||||
</data>
|
||||
<data name="TbSettingsPass" xml:space="preserve">
|
||||
<value>Auth pass</value>
|
||||
</data>
|
||||
<data name="TbSettingsRemoteDNS" xml:space="preserve">
|
||||
<value>Custom DNS (multiple, separated by commas (,))</value>
|
||||
</data>
|
||||
<data name="TbSettingsSaveTip" xml:space="preserve">
|
||||
<value>After modifying the following parameters, click Save to take effect</value>
|
||||
</data>
|
||||
<data name="TbSettingsSetUWP" xml:space="preserve">
|
||||
<value>Set Win10 UWP Loopback</value>
|
||||
</data>
|
||||
@@ -1132,4 +1081,34 @@
|
||||
<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>
|
||||
<data name="menuRebootAsAdmin" xml:space="preserve">
|
||||
<value>Reboot as administrator</value>
|
||||
</data>
|
||||
<data name="LvMoreUrl" xml:space="preserve">
|
||||
<value>More urls, separated by commas</value>
|
||||
</data>
|
||||
<data name="SpeedDisplayText" xml:space="preserve">
|
||||
<value>{0}:{1}/s↑ | {2}/s↓</value>
|
||||
</data>
|
||||
</root>
|
||||
@@ -195,9 +195,6 @@
|
||||
<data name="LvAddress" xml:space="preserve">
|
||||
<value>Адрес</value>
|
||||
</data>
|
||||
<data name="LvAlias" xml:space="preserve">
|
||||
<value>Псевдоним</value>
|
||||
</data>
|
||||
<data name="LvEncryptionMethod" xml:space="preserve">
|
||||
<value>Безопасность</value>
|
||||
</data>
|
||||
@@ -210,9 +207,6 @@
|
||||
<data name="LvSubscription" xml:space="preserve">
|
||||
<value>Группа подписки</value>
|
||||
</data>
|
||||
<data name="LvTestResults" xml:space="preserve">
|
||||
<value>Результаты тестирования</value>
|
||||
</data>
|
||||
<data name="LvTodayDownloadDataAmount" xml:space="preserve">
|
||||
<value>Загружено трафика сегодня</value>
|
||||
</data>
|
||||
@@ -228,9 +222,6 @@
|
||||
<data name="LvTransportProtocol" xml:space="preserve">
|
||||
<value>Протокол</value>
|
||||
</data>
|
||||
<data name="MediumFresh" xml:space="preserve">
|
||||
<value>Medium</value>
|
||||
</data>
|
||||
<data name="MsgClearSubscription" xml:space="preserve">
|
||||
<value>Очистить контент оригинальной подписки</value>
|
||||
</data>
|
||||
@@ -246,27 +237,15 @@
|
||||
<data name="MsgNoValidSubscription" xml:space="preserve">
|
||||
<value>Нет установлены подписки</value>
|
||||
</data>
|
||||
<data name="MsgPACUpdateFailed" xml:space="preserve">
|
||||
<value>Ошибка обновления PAC</value>
|
||||
</data>
|
||||
<data name="MsgPACUpdateSuccessfully" xml:space="preserve">
|
||||
<value>PAC успешно обновлен</value>
|
||||
</data>
|
||||
<data name="MsgParsingSuccessfully" xml:space="preserve">
|
||||
<value>Парсинг {0} прошел успешно</value>
|
||||
</data>
|
||||
<data name="MsgSimplifyPAC" xml:space="preserve">
|
||||
<value>Упрощение PAC прошло успешно</value>
|
||||
</data>
|
||||
<data name="MsgStartGettingSubscriptions" xml:space="preserve">
|
||||
<value>Начинаю получать подписки</value>
|
||||
</data>
|
||||
<data name="MsgStartUpdating" xml:space="preserve">
|
||||
<value>Начинаю обновление {0}...</value>
|
||||
</data>
|
||||
<data name="MsgStartUpdatingPAC" xml:space="preserve">
|
||||
<value>Начинаю обновление PAC...</value>
|
||||
</data>
|
||||
<data name="MsgSubscriptionDecodingFailed" xml:space="preserve">
|
||||
<value>Некорректное содержимое подписки</value>
|
||||
</data>
|
||||
@@ -285,9 +264,6 @@
|
||||
<data name="MsgUpdateV2rayCoreSuccessfullyMore" xml:space="preserve">
|
||||
<value>Успешное обновление ядра! Перезапуск службы...</value>
|
||||
</data>
|
||||
<data name="NeedHttpGlobalProxy" xml:space="preserve">
|
||||
<value>Эта функция зависит от глобального прокси-сервера HTTP, пожалуйста, сначала установите его правильно.</value>
|
||||
</data>
|
||||
<data name="NonvmessOrssProtocol" xml:space="preserve">
|
||||
<value>Не является протоколом Vmess или SS</value>
|
||||
</data>
|
||||
@@ -315,9 +291,6 @@
|
||||
<data name="PleaseSelectServer" xml:space="preserve">
|
||||
<value>Сначала выберите сервер</value>
|
||||
</data>
|
||||
<data name="QuickFresh" xml:space="preserve">
|
||||
<value>Быстрый</value>
|
||||
</data>
|
||||
<data name="RemoveDuplicateServerResult" xml:space="preserve">
|
||||
<value>Удаление дублей завершено. Старая: {0}, Новая: {1}.</value>
|
||||
</data>
|
||||
@@ -330,15 +303,6 @@
|
||||
<data name="SaveServerConfigurationIn" xml:space="preserve">
|
||||
<value>Файл конфигурации сервера сохранен по адресу: {0}</value>
|
||||
</data>
|
||||
<data name="SlowFresh" xml:space="preserve">
|
||||
<value>Медленный</value>
|
||||
</data>
|
||||
<data name="SpeedServerTips" xml:space="preserve">
|
||||
<value>Примечание. Эта функция зависит от глобального прокси-сервера HTTP. После тестирования вручную настройте глобальный прокси-сервер HTTP и активный узел.</value>
|
||||
</data>
|
||||
<data name="StartPacFailed" xml:space="preserve">
|
||||
<value>PAC не удалось запустить. Пожалуйста, запустите эту программу от имени администратора.</value>
|
||||
</data>
|
||||
<data name="StartService" xml:space="preserve">
|
||||
<value>Запуск сервиса ({0})...</value>
|
||||
</data>
|
||||
@@ -472,9 +436,6 @@
|
||||
<data name="MsgServerTitle" xml:space="preserve">
|
||||
<value>Фильтр серверов</value>
|
||||
</data>
|
||||
<data name="NetFrameworkRequirementsTip" xml:space="preserve">
|
||||
<value>Для корректной работы требуется .NET Framework 4.8</value>
|
||||
</data>
|
||||
<data name="menuCheckUpdate" xml:space="preserve">
|
||||
<value>Проверить обновления</value>
|
||||
</data>
|
||||
@@ -763,9 +724,6 @@
|
||||
<data name="TbSettingsAutoHideStartup" xml:space="preserve">
|
||||
<value>Auto hide startup</value>
|
||||
</data>
|
||||
<data name="TbSettingsAutoTest" xml:space="preserve">
|
||||
<value>Интервал автоматической проверки задержки в минутах</value>
|
||||
</data>
|
||||
<data name="TbSettingsAutoUpdate" xml:space="preserve">
|
||||
<value>Интервал автоматического обновления подписок в часах</value>
|
||||
</data>
|
||||
@@ -808,9 +766,6 @@
|
||||
<data name="TbSettingsIgnoreGeoUpdateCore" xml:space="preserve">
|
||||
<value>Игнорировать файлы Geo при обновлении ядра</value>
|
||||
</data>
|
||||
<data name="TbSettingsIpv6" xml:space="preserve">
|
||||
<value>Включить IPv6</value>
|
||||
</data>
|
||||
<data name="TbSettingsKeepOlderDedupl" xml:space="preserve">
|
||||
<value>Сохранить старые при удалении дублей</value>
|
||||
</data>
|
||||
@@ -826,18 +781,12 @@
|
||||
<data name="TbSettingsN" xml:space="preserve">
|
||||
<value>Настройки v2rayN</value>
|
||||
</data>
|
||||
<data name="TbSettingsPacListenPort" xml:space="preserve">
|
||||
<value>Порт PAC</value>
|
||||
</data>
|
||||
<data name="TbSettingsPass" xml:space="preserve">
|
||||
<value>Пароль аутентификации</value>
|
||||
</data>
|
||||
<data name="TbSettingsRemoteDNS" xml:space="preserve">
|
||||
<value>Пользовательский DNS (если несколько делите с запятыми (,))</value>
|
||||
</data>
|
||||
<data name="TbSettingsSaveTip" xml:space="preserve">
|
||||
<value>После изменения следующих параметров нажмите «Сохранить», чтобы изменения вступили в силу</value>
|
||||
</data>
|
||||
<data name="TbSettingsSetUWP" xml:space="preserve">
|
||||
<value>Set Win10 UWP Loopback</value>
|
||||
</data>
|
||||
@@ -1108,4 +1057,7 @@
|
||||
<data name="TbSettingsFontSize" xml:space="preserve">
|
||||
<value>Размер шрифта</value>
|
||||
</data>
|
||||
<data name="TbSettingsEnableHWA" xml:space="preserve">
|
||||
<value>Включить аппаратное ускорение (требуется перезагрузка)</value>
|
||||
</data>
|
||||
</root>
|
||||
@@ -195,9 +195,6 @@
|
||||
<data name="LvAddress" xml:space="preserve">
|
||||
<value>地址</value>
|
||||
</data>
|
||||
<data name="LvAlias" xml:space="preserve">
|
||||
<value>别名</value>
|
||||
</data>
|
||||
<data name="LvEncryptionMethod" xml:space="preserve">
|
||||
<value>加密方式</value>
|
||||
</data>
|
||||
@@ -210,9 +207,6 @@
|
||||
<data name="LvSubscription" xml:space="preserve">
|
||||
<value>订阅分组</value>
|
||||
</data>
|
||||
<data name="LvTestResults" xml:space="preserve">
|
||||
<value>测试结果</value>
|
||||
</data>
|
||||
<data name="LvTodayDownloadDataAmount" xml:space="preserve">
|
||||
<value>今日下载</value>
|
||||
</data>
|
||||
@@ -228,9 +222,6 @@
|
||||
<data name="LvTransportProtocol" xml:space="preserve">
|
||||
<value>传输协议</value>
|
||||
</data>
|
||||
<data name="MediumFresh" xml:space="preserve">
|
||||
<value>中等</value>
|
||||
</data>
|
||||
<data name="MsgClearSubscription" xml:space="preserve">
|
||||
<value>清除原订阅内容</value>
|
||||
</data>
|
||||
@@ -246,27 +237,15 @@
|
||||
<data name="MsgNoValidSubscription" xml:space="preserve">
|
||||
<value>未设置有效的订阅</value>
|
||||
</data>
|
||||
<data name="MsgPACUpdateFailed" xml:space="preserve">
|
||||
<value>PAC更新失败</value>
|
||||
</data>
|
||||
<data name="MsgPACUpdateSuccessfully" xml:space="preserve">
|
||||
<value>PAC更新成功</value>
|
||||
</data>
|
||||
<data name="MsgParsingSuccessfully" xml:space="preserve">
|
||||
<value>解析{0}成功</value>
|
||||
</data>
|
||||
<data name="MsgSimplifyPAC" xml:space="preserve">
|
||||
<value>简化PAC成功</value>
|
||||
</data>
|
||||
<data name="MsgStartGettingSubscriptions" xml:space="preserve">
|
||||
<value>开始获取订阅内容</value>
|
||||
</data>
|
||||
<data name="MsgStartUpdating" xml:space="preserve">
|
||||
<value>开始更新 {0}...</value>
|
||||
</data>
|
||||
<data name="MsgStartUpdatingPAC" xml:space="preserve">
|
||||
<value>开始更新 PAC...</value>
|
||||
</data>
|
||||
<data name="MsgSubscriptionDecodingFailed" xml:space="preserve">
|
||||
<value>无效的订阅内容</value>
|
||||
</data>
|
||||
@@ -285,9 +264,6 @@
|
||||
<data name="MsgUpdateV2rayCoreSuccessfullyMore" xml:space="preserve">
|
||||
<value>更新Core成功!正在重启服务...</value>
|
||||
</data>
|
||||
<data name="NeedHttpGlobalProxy" xml:space="preserve">
|
||||
<value>此功能依赖Http全局代理,请先设置正确。</value>
|
||||
</data>
|
||||
<data name="NonvmessOrssProtocol" xml:space="preserve">
|
||||
<value>非VMess或ss协议</value>
|
||||
</data>
|
||||
@@ -304,7 +280,7 @@
|
||||
<value>操作失败,请检查重试</value>
|
||||
</data>
|
||||
<data name="PleaseFillRemarks" xml:space="preserve">
|
||||
<value>请填写备注</value>
|
||||
<value>请填写别名</value>
|
||||
</data>
|
||||
<data name="PleaseSelectEncryption" xml:space="preserve">
|
||||
<value>请选择加密方式</value>
|
||||
@@ -315,9 +291,6 @@
|
||||
<data name="PleaseSelectServer" xml:space="preserve">
|
||||
<value>请先选择服务器</value>
|
||||
</data>
|
||||
<data name="QuickFresh" xml:space="preserve">
|
||||
<value>快</value>
|
||||
</data>
|
||||
<data name="RemoveDuplicateServerResult" xml:space="preserve">
|
||||
<value>服务器去重完成。原数量: {0},现数量: {1}</value>
|
||||
</data>
|
||||
@@ -330,15 +303,6 @@
|
||||
<data name="SaveServerConfigurationIn" xml:space="preserve">
|
||||
<value>服务端配置文件保存在:{0}</value>
|
||||
</data>
|
||||
<data name="SlowFresh" xml:space="preserve">
|
||||
<value>慢</value>
|
||||
</data>
|
||||
<data name="SpeedServerTips" xml:space="preserve">
|
||||
<value>注意:此功能依赖Http全局代理!测试完成后,请手工调整Http全局代理和活动节点。</value>
|
||||
</data>
|
||||
<data name="StartPacFailed" xml:space="preserve">
|
||||
<value>PAC服务启动失败,请用管理员启动</value>
|
||||
</data>
|
||||
<data name="StartService" xml:space="preserve">
|
||||
<value>启动服务({0})...</value>
|
||||
</data>
|
||||
@@ -380,7 +344,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>
|
||||
@@ -410,13 +374,13 @@
|
||||
<value>*grpc serviceName</value>
|
||||
</data>
|
||||
<data name="TransportRequestHostTip1" xml:space="preserve">
|
||||
<value>*http host中间逗号(,)隔开</value>
|
||||
<value>*http host中间逗号(,)分隔</value>
|
||||
</data>
|
||||
<data name="TransportRequestHostTip2" xml:space="preserve">
|
||||
<value>*ws host</value>
|
||||
</data>
|
||||
<data name="TransportRequestHostTip3" xml:space="preserve">
|
||||
<value>*h2 host中间逗号(,)隔开</value>
|
||||
<value>*h2 host中间逗号(,)分隔</value>
|
||||
</data>
|
||||
<data name="TransportRequestHostTip4" xml:space="preserve">
|
||||
<value>*QUIC 加密方式</value>
|
||||
@@ -472,9 +436,6 @@
|
||||
<data name="MsgServerTitle" xml:space="preserve">
|
||||
<value>服务器过滤器</value>
|
||||
</data>
|
||||
<data name="NetFrameworkRequirementsTip" xml:space="preserve">
|
||||
<value>正常使用此版本需要.NET Framework 4.8,请更新后重启</value>
|
||||
</data>
|
||||
<data name="menuCheckUpdate" xml:space="preserve">
|
||||
<value>检查更新</value>
|
||||
</data>
|
||||
@@ -710,7 +671,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>
|
||||
@@ -763,9 +724,6 @@
|
||||
<data name="TbSettingsAutoHideStartup" xml:space="preserve">
|
||||
<value>启动后隐藏窗口</value>
|
||||
</data>
|
||||
<data name="TbSettingsAutoTest" xml:space="preserve">
|
||||
<value>自动延迟测试的间隔 (单位分钟)</value>
|
||||
</data>
|
||||
<data name="TbSettingsAutoUpdate" xml:space="preserve">
|
||||
<value>自动更新订阅的间隔(单位小时)</value>
|
||||
</data>
|
||||
@@ -808,9 +766,6 @@
|
||||
<data name="TbSettingsIgnoreGeoUpdateCore" xml:space="preserve">
|
||||
<value>更新Core时忽略Geo文件</value>
|
||||
</data>
|
||||
<data name="TbSettingsIpv6" xml:space="preserve">
|
||||
<value>启用IPv6</value>
|
||||
</data>
|
||||
<data name="TbSettingsKeepOlderDedupl" xml:space="preserve">
|
||||
<value>去重时保留序号较小的项</value>
|
||||
</data>
|
||||
@@ -826,17 +781,11 @@
|
||||
<data name="TbSettingsN" xml:space="preserve">
|
||||
<value>v2rayN 设置</value>
|
||||
</data>
|
||||
<data name="TbSettingsPacListenPort" xml:space="preserve">
|
||||
<value>Pac监听端口号</value>
|
||||
</data>
|
||||
<data name="TbSettingsPass" xml:space="preserve">
|
||||
<value>认证密码</value>
|
||||
</data>
|
||||
<data name="TbSettingsRemoteDNS" xml:space="preserve">
|
||||
<value>自定义DNS(可多个,用逗号(,)隔开)</value>
|
||||
</data>
|
||||
<data name="TbSettingsSaveTip" xml:space="preserve">
|
||||
<value>修改以下参数后,点击保存才生效</value>
|
||||
<value>自定义DNS(可多个,用逗号(,)分隔)</value>
|
||||
</data>
|
||||
<data name="TbSettingsSetUWP" xml:space="preserve">
|
||||
<value>解除Win10 UWP应用回环代理限制</value>
|
||||
@@ -1132,4 +1081,31 @@
|
||||
<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>
|
||||
<data name="menuRebootAsAdmin" xml:space="preserve">
|
||||
<value>以管理员身份重启</value>
|
||||
</data>
|
||||
<data name="LvMoreUrl" xml:space="preserve">
|
||||
<value>更多地址(url),用逗号(,)分隔</value>
|
||||
</data>
|
||||
</root>
|
||||
@@ -14,7 +14,14 @@
|
||||
{
|
||||
"outboundTag": "proxy",
|
||||
"ip": [
|
||||
"geoip:telegram"
|
||||
"geoip:cloudflare",
|
||||
"geoip:cloudfront",
|
||||
"geoip:facebook",
|
||||
"geoip:fastly",
|
||||
"geoip:google",
|
||||
"geoip:netflix",
|
||||
"geoip:telegram",
|
||||
"geoip:twitter"
|
||||
],
|
||||
"domain": [
|
||||
"geosite:gfw",
|
||||
|
||||
@@ -1,5 +1,10 @@
|
||||
{
|
||||
"servers": [
|
||||
{
|
||||
"tag": "out_dns",
|
||||
"address": "8.8.8.8",
|
||||
"detour": "proxy"
|
||||
},
|
||||
{
|
||||
"tag": "local",
|
||||
"address": "223.5.5.5",
|
||||
@@ -11,6 +16,11 @@
|
||||
}
|
||||
],
|
||||
"rules": [
|
||||
{
|
||||
"geosite": "cn",
|
||||
"server": "local",
|
||||
"disable_cache": true
|
||||
},
|
||||
{
|
||||
"geosite": "category-ads-all",
|
||||
"server": "block",
|
||||
@@ -18,4 +28,4 @@
|
||||
}
|
||||
],
|
||||
"strategy": "ipv4_only"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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()
|
||||
{
|
||||
|
||||
@@ -1,45 +1,22 @@
|
||||
using System.Windows.Forms;
|
||||
using System.Windows;
|
||||
|
||||
namespace v2rayN
|
||||
{
|
||||
class UI
|
||||
{
|
||||
private readonly static string caption = "v2rayN";
|
||||
|
||||
public static void Show(string msg)
|
||||
{
|
||||
MessageBox.Show(msg, "v2rayN", MessageBoxButtons.OK, MessageBoxIcon.Information);
|
||||
MessageBox.Show(msg, caption, MessageBoxButton.OK, MessageBoxImage.Information, MessageBoxResult.OK);
|
||||
}
|
||||
public static void ShowWarning(string msg)
|
||||
{
|
||||
MessageBox.Show(msg, "v2rayN", MessageBoxButtons.OK, MessageBoxIcon.Warning);
|
||||
MessageBox.Show(msg, caption, MessageBoxButton.OK, MessageBoxImage.Warning, MessageBoxResult.OK);
|
||||
}
|
||||
public static void ShowError(string msg)
|
||||
public static MessageBoxResult ShowYesNo(string msg)
|
||||
{
|
||||
MessageBox.Show(msg, "v2rayN", MessageBoxButtons.OK, MessageBoxIcon.Error);
|
||||
return MessageBox.Show(msg, caption, MessageBoxButton.YesNo, MessageBoxImage.Question);
|
||||
}
|
||||
|
||||
public static DialogResult ShowYesNo(string msg)
|
||||
{
|
||||
return MessageBox.Show(msg, "v2rayN", MessageBoxButtons.YesNo, MessageBoxIcon.Question);
|
||||
}
|
||||
|
||||
//public static string GetResourseString(string key)
|
||||
//{
|
||||
// CultureInfo cultureInfo = null;
|
||||
// try
|
||||
// {
|
||||
// string languageCode = this.LanguageCode;
|
||||
// cultureInfo = new CultureInfo(languageCode);
|
||||
// return Common.ResourceManager.GetString(key, cultureInfo);
|
||||
// }
|
||||
// catch (Exception)
|
||||
// {
|
||||
// //默认读取英文的多语言
|
||||
// cultureInfo = new CultureInfo(MKey.kDefaultLanguageCode);
|
||||
// return Common.ResourceManager.GetString(key, cultureInfo);
|
||||
// }
|
||||
//}
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -18,7 +18,7 @@ using System.Security.Principal;
|
||||
using System.Text;
|
||||
using System.Text.RegularExpressions;
|
||||
using System.Web;
|
||||
using System.Windows.Forms;
|
||||
using System.Windows;
|
||||
using System.Windows.Interop;
|
||||
using System.Windows.Media;
|
||||
using System.Windows.Media.Imaging;
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -427,6 +429,11 @@ namespace v2rayN
|
||||
BitmapSizeOptions.FromEmptyOptions());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// idn to idc
|
||||
/// </summary>
|
||||
/// <param name="url"></param>
|
||||
/// <returns></returns>
|
||||
public static string GetPunycode(string url)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(url))
|
||||
@@ -451,6 +458,12 @@ namespace v2rayN
|
||||
}
|
||||
}
|
||||
|
||||
public static bool IsBase64String(string plainText)
|
||||
{
|
||||
var buffer = new Span<byte>(new byte[plainText.Length]);
|
||||
return Convert.TryFromBase64String(plainText, buffer, out int _);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
@@ -665,12 +678,12 @@ namespace v2rayN
|
||||
/// <returns></returns>
|
||||
public static string GetExePath()
|
||||
{
|
||||
return Application.ExecutablePath;
|
||||
return Environment.ProcessPath;
|
||||
}
|
||||
|
||||
public static string StartupPath()
|
||||
{
|
||||
return Application.StartupPath;
|
||||
return AppDomain.CurrentDomain.BaseDirectory;
|
||||
}
|
||||
|
||||
public static string? RegReadValue(string path, string name, string def)
|
||||
@@ -778,7 +791,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 +920,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 +1163,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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1169,47 +1188,44 @@ namespace v2rayN
|
||||
|
||||
#region scan screen
|
||||
|
||||
public static string ScanScreen()
|
||||
public static string ScanScreen(float dpiX, float dpiY)
|
||||
{
|
||||
try
|
||||
{
|
||||
foreach (Screen screen in Screen.AllScreens)
|
||||
var left = (int)(SystemParameters.WorkArea.Left);
|
||||
var top = (int)(SystemParameters.WorkArea.Top);
|
||||
var width = (int)(SystemParameters.WorkArea.Width / dpiX);
|
||||
var height = (int)(SystemParameters.WorkArea.Height / dpiY);
|
||||
|
||||
using Bitmap fullImage = new Bitmap(width, height);
|
||||
using (Graphics g = Graphics.FromImage(fullImage))
|
||||
{
|
||||
using Bitmap fullImage = new Bitmap(screen.Bounds.Width,
|
||||
screen.Bounds.Height);
|
||||
using (Graphics g = Graphics.FromImage(fullImage))
|
||||
g.CopyFromScreen(left, top, 0, 0, fullImage.Size, CopyPixelOperation.SourceCopy);
|
||||
}
|
||||
int maxTry = 10;
|
||||
for (int i = 0; i < maxTry; i++)
|
||||
{
|
||||
int marginLeft = (int)((double)fullImage.Width * i / 2.5 / maxTry);
|
||||
int marginTop = (int)((double)fullImage.Height * i / 2.5 / maxTry);
|
||||
Rectangle cropRect = new(marginLeft, marginTop, fullImage.Width - marginLeft * 2, fullImage.Height - marginTop * 2);
|
||||
Bitmap target = new(width, height);
|
||||
|
||||
double imageScale = (double)width / (double)cropRect.Width;
|
||||
using (Graphics g = Graphics.FromImage(target))
|
||||
{
|
||||
g.CopyFromScreen(screen.Bounds.X,
|
||||
screen.Bounds.Y,
|
||||
0, 0,
|
||||
fullImage.Size,
|
||||
CopyPixelOperation.SourceCopy);
|
||||
g.DrawImage(fullImage, new Rectangle(0, 0, target.Width, target.Height),
|
||||
cropRect,
|
||||
GraphicsUnit.Pixel);
|
||||
}
|
||||
int maxTry = 10;
|
||||
for (int i = 0; i < maxTry; i++)
|
||||
|
||||
BitmapLuminanceSource source = new(target);
|
||||
BinaryBitmap bitmap = new(new HybridBinarizer(source));
|
||||
QRCodeReader reader = new();
|
||||
Result result = reader.decode(bitmap);
|
||||
if (result != null)
|
||||
{
|
||||
int marginLeft = (int)((double)fullImage.Width * i / 2.5 / maxTry);
|
||||
int marginTop = (int)((double)fullImage.Height * i / 2.5 / maxTry);
|
||||
Rectangle cropRect = new(marginLeft, marginTop, fullImage.Width - marginLeft * 2, fullImage.Height - marginTop * 2);
|
||||
Bitmap target = new(screen.Bounds.Width, screen.Bounds.Height);
|
||||
|
||||
double imageScale = (double)screen.Bounds.Width / (double)cropRect.Width;
|
||||
using (Graphics g = Graphics.FromImage(target))
|
||||
{
|
||||
g.DrawImage(fullImage, new Rectangle(0, 0, target.Width, target.Height),
|
||||
cropRect,
|
||||
GraphicsUnit.Pixel);
|
||||
}
|
||||
|
||||
BitmapLuminanceSource source = new(target);
|
||||
BinaryBitmap bitmap = new(new HybridBinarizer(source));
|
||||
QRCodeReader reader = new();
|
||||
Result result = reader.decode(bitmap);
|
||||
if (result != null)
|
||||
{
|
||||
string ret = result.Text;
|
||||
return ret;
|
||||
}
|
||||
string ret = result.Text;
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1220,6 +1236,14 @@ namespace v2rayN
|
||||
return string.Empty;
|
||||
}
|
||||
|
||||
public static Tuple<float, float> GetDpiXY(Window window)
|
||||
{
|
||||
IntPtr hWnd = new WindowInteropHelper(window).EnsureHandle();
|
||||
Graphics g = Graphics.FromHwnd(hWnd);
|
||||
|
||||
return new(96 / g.DpiX, 96 / g.DpiY);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
using Microsoft.Win32;
|
||||
using ReactiveUI;
|
||||
using ReactiveUI.Fody.Helpers;
|
||||
using ReactiveUI.Validation.Helpers;
|
||||
@@ -5,7 +6,6 @@ using Splat;
|
||||
using System.IO;
|
||||
using System.Reactive;
|
||||
using System.Windows;
|
||||
using System.Windows.Forms;
|
||||
using v2rayN.Base;
|
||||
using v2rayN.Handler;
|
||||
using v2rayN.Mode;
|
||||
@@ -111,7 +111,7 @@ namespace v2rayN.ViewModels
|
||||
Multiselect = false,
|
||||
Filter = "Config|*.json|YAML|*.yaml;*.yml|All|*.*"
|
||||
};
|
||||
if (fileDialog.ShowDialog() != DialogResult.OK)
|
||||
if (fileDialog.ShowDialog() != true)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -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,17 +3,17 @@ using DynamicData.Binding;
|
||||
using MaterialDesignColors;
|
||||
using MaterialDesignColors.ColorManipulation;
|
||||
using MaterialDesignThemes.Wpf;
|
||||
using NHotkey;
|
||||
using Microsoft.Win32;
|
||||
using ReactiveUI;
|
||||
using ReactiveUI.Fody.Helpers;
|
||||
using Splat;
|
||||
using System.Diagnostics;
|
||||
using System.Drawing;
|
||||
using System.IO;
|
||||
using System.Reactive;
|
||||
using System.Reactive.Linq;
|
||||
using System.Text;
|
||||
using System.Windows;
|
||||
using System.Windows.Forms;
|
||||
using System.Windows.Media;
|
||||
using v2rayN.Base;
|
||||
using v2rayN.Handler;
|
||||
@@ -21,7 +21,6 @@ using v2rayN.Mode;
|
||||
using v2rayN.Resx;
|
||||
using v2rayN.Tool;
|
||||
using v2rayN.Views;
|
||||
using Application = System.Windows.Application;
|
||||
|
||||
|
||||
namespace v2rayN.ViewModels
|
||||
@@ -39,7 +38,7 @@ namespace v2rayN.ViewModels
|
||||
private NoticeHandler? _noticeHandler;
|
||||
private readonly PaletteHelper _paletteHelper = new();
|
||||
private Dictionary<string, bool> _dicHeaderSort = new();
|
||||
private Action<string> _updateView;
|
||||
private Action<EViewAction> _updateView;
|
||||
|
||||
#endregion
|
||||
|
||||
@@ -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
|
||||
@@ -121,6 +122,7 @@ namespace v2rayN.ViewModels
|
||||
public ReactiveCommand<Unit, Unit> OptionSettingCmd { get; }
|
||||
public ReactiveCommand<Unit, Unit> RoutingSettingCmd { get; }
|
||||
public ReactiveCommand<Unit, Unit> GlobalHotkeySettingCmd { get; }
|
||||
public ReactiveCommand<Unit, Unit> RebootAsAdminCmd { get; }
|
||||
public ReactiveCommand<Unit, Unit> ClearServerStatisticsCmd { get; }
|
||||
public ReactiveCommand<Unit, Unit> ImportOldGuiConfigCmd { get; }
|
||||
|
||||
@@ -175,6 +177,8 @@ namespace v2rayN.ViewModels
|
||||
[Reactive]
|
||||
public string RunningServerDisplay { get; set; }
|
||||
[Reactive]
|
||||
public string RunningServerToolTipText { get; set; }
|
||||
[Reactive]
|
||||
public string RunningInfoDisplay { get; set; }
|
||||
[Reactive]
|
||||
public string SpeedProxyDisplay { get; set; }
|
||||
@@ -198,7 +202,7 @@ namespace v2rayN.ViewModels
|
||||
|
||||
#region Init
|
||||
|
||||
public MainWindowViewModel(ISnackbarMessageQueue snackbarMessageQueue, Action<string> updateView)
|
||||
public MainWindowViewModel(ISnackbarMessageQueue snackbarMessageQueue, Action<EViewAction> updateView)
|
||||
{
|
||||
_updateView = updateView;
|
||||
ThreadPool.RegisterWaitForSingleObject(App.ProgramStarted, OnProgramStarted, null, -1, false);
|
||||
@@ -429,6 +433,10 @@ namespace v2rayN.ViewModels
|
||||
_noticeHandler?.Enqueue(ResUI.OperationSuccess);
|
||||
}
|
||||
});
|
||||
RebootAsAdminCmd = ReactiveCommand.Create(() =>
|
||||
{
|
||||
RebootAsAdmin();
|
||||
});
|
||||
ClearServerStatisticsCmd = ReactiveCommand.Create(() =>
|
||||
{
|
||||
_statistics?.ClearAllServerStatistics();
|
||||
@@ -538,11 +546,15 @@ namespace v2rayN.ViewModels
|
||||
_noticeHandler?.SendMessage(msg);
|
||||
if (success)
|
||||
{
|
||||
var indexIdOld = _config.indexId;
|
||||
RefreshServers();
|
||||
Reload();
|
||||
if (indexIdOld != _config.indexId)
|
||||
{
|
||||
Reload();
|
||||
}
|
||||
if (_config.uiItem.enableAutoAdjustMainLvColWidth)
|
||||
{
|
||||
_updateView("AdjustMainLvColWidth");
|
||||
_updateView(EViewAction.AdjustMainLvColWidth);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -556,8 +568,9 @@ namespace v2rayN.ViewModels
|
||||
{
|
||||
return;
|
||||
}
|
||||
SpeedProxyDisplay = string.Format("{0}:{1}/s<><73> | {2}/s<><73>", Global.agentTag, Utils.HumanFy(update.proxyUp), Utils.HumanFy(update.proxyDown));
|
||||
SpeedDirectDisplay = string.Format("{0}:{1}/s<><73> | {2}/s<><73>", Global.directTag, Utils.HumanFy(update.directUp), Utils.HumanFy(update.directDown));
|
||||
|
||||
SpeedProxyDisplay = string.Format(ResUI.SpeedDisplayText, Global.agentTag, Utils.HumanFy(update.proxyUp), Utils.HumanFy(update.proxyDown));
|
||||
SpeedDirectDisplay = string.Format(ResUI.SpeedDisplayText, Global.directTag, Utils.HumanFy(update.directUp), Utils.HumanFy(update.directDown));
|
||||
|
||||
if (update.proxyUp + update.proxyDown > 0)
|
||||
{
|
||||
@@ -624,27 +637,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)
|
||||
{
|
||||
@@ -696,7 +708,7 @@ namespace v2rayN.ViewModels
|
||||
|
||||
RefreshServers();
|
||||
|
||||
_updateView("ProfilesFocus");
|
||||
_updateView(EViewAction.ProfilesFocus);
|
||||
}
|
||||
|
||||
private void ServerFilterChanged(bool c)
|
||||
@@ -712,6 +724,7 @@ namespace v2rayN.ViewModels
|
||||
private void RefreshServers()
|
||||
{
|
||||
List<ProfileItemModel> lstModel = LazyConfig.Instance.ProfileItems(_subId, _serverFilter);
|
||||
|
||||
ConfigHandler.SetDefaultServer(_config, lstModel);
|
||||
|
||||
List<ServerStatItem> lstServerStat = new();
|
||||
@@ -735,9 +748,11 @@ 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,
|
||||
delay = t33 == null ? 0 : t33.delay,
|
||||
delayVal = t33?.delay != 0 ? $"{t33?.delay} {Global.DelayUnit}" : string.Empty,
|
||||
speedVal = t33?.speed != 0 ? $"{t33?.speed} {Global.SpeedUnit}" : string.Empty,
|
||||
todayDown = t22 == null ? "" : Utils.HumanFy(t22.todayDown),
|
||||
@@ -770,7 +785,14 @@ namespace v2rayN.ViewModels
|
||||
var running = ConfigHandler.GetDefaultServer(ref _config);
|
||||
if (running != null)
|
||||
{
|
||||
RunningServerDisplay = string.Format("{0}:{1}", ResUI.menuServers, running.GetSummary());
|
||||
var runningSummary = running.GetSummary();
|
||||
RunningServerDisplay = $"{ResUI.menuServers}:{runningSummary}";
|
||||
RunningServerToolTipText = runningSummary;
|
||||
}
|
||||
else
|
||||
{
|
||||
RunningServerDisplay =
|
||||
RunningServerToolTipText = ResUI.CheckServerSettings;
|
||||
}
|
||||
}));
|
||||
}
|
||||
@@ -780,9 +802,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];
|
||||
@@ -819,21 +843,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;
|
||||
}
|
||||
|
||||
@@ -896,9 +930,10 @@ namespace v2rayN.ViewModels
|
||||
{
|
||||
ShowHideWindow(false);
|
||||
|
||||
var dpiXY = Utils.GetDpiXY(Application.Current.MainWindow);
|
||||
string result = await Task.Run(() =>
|
||||
{
|
||||
return Utils.ScanScreen();
|
||||
return Utils.ScanScreen(dpiXY.Item1, dpiXY.Item2);
|
||||
});
|
||||
|
||||
ShowHideWindow(true);
|
||||
@@ -920,12 +955,12 @@ namespace v2rayN.ViewModels
|
||||
}
|
||||
public void RemoveServer()
|
||||
{
|
||||
if (GetProfileItems(out List<ProfileItem> lstSelecteds) < 0)
|
||||
if (GetProfileItems(out List<ProfileItem> lstSelecteds, false) < 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (UI.ShowYesNo(ResUI.RemoveServer) == DialogResult.No)
|
||||
if (UI.ShowYesNo(ResUI.RemoveServer) == MessageBoxResult.No)
|
||||
{
|
||||
return;
|
||||
}
|
||||
@@ -943,15 +978,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;
|
||||
}
|
||||
@@ -1041,10 +1075,7 @@ namespace v2rayN.ViewModels
|
||||
return;
|
||||
}
|
||||
|
||||
if (!_dicHeaderSort.ContainsKey(colName))
|
||||
{
|
||||
_dicHeaderSort.Add(colName, true);
|
||||
}
|
||||
_dicHeaderSort.TryAdd(colName, true);
|
||||
_dicHeaderSort.TryGetValue(colName, out bool asc);
|
||||
if (ConfigHandler.SortServers(ref _config, _subId, colName, asc) != 0)
|
||||
{
|
||||
@@ -1083,7 +1114,7 @@ namespace v2rayN.ViewModels
|
||||
return;
|
||||
}
|
||||
|
||||
if (GetProfileItems(out List<ProfileItem> lstSelecteds) < 0)
|
||||
if (GetProfileItems(out List<ProfileItem> lstSelecteds, true) < 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
@@ -1134,7 +1165,7 @@ namespace v2rayN.ViewModels
|
||||
{
|
||||
SelectedProfiles = _profileItems;
|
||||
}
|
||||
if (GetProfileItems(out List<ProfileItem> lstSelecteds) < 0)
|
||||
if (GetProfileItems(out List<ProfileItem> lstSelecteds, false) < 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
@@ -1166,7 +1197,7 @@ namespace v2rayN.ViewModels
|
||||
|
||||
public void Export2ShareUrl()
|
||||
{
|
||||
if (GetProfileItems(out List<ProfileItem> lstSelecteds) < 0)
|
||||
if (GetProfileItems(out List<ProfileItem> lstSelecteds, true) < 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
@@ -1191,7 +1222,7 @@ namespace v2rayN.ViewModels
|
||||
|
||||
private void Export2SubContent()
|
||||
{
|
||||
if (GetProfileItems(out List<ProfileItem> lstSelecteds) < 0)
|
||||
if (GetProfileItems(out List<ProfileItem> lstSelecteds, true) < 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
@@ -1268,6 +1299,24 @@ namespace v2rayN.ViewModels
|
||||
}
|
||||
}
|
||||
|
||||
private void RebootAsAdmin()
|
||||
{
|
||||
ProcessStartInfo startInfo = new()
|
||||
{
|
||||
UseShellExecute = true,
|
||||
Arguments = Global.RebootAs,
|
||||
WorkingDirectory = Utils.StartupPath(),
|
||||
FileName = Utils.GetExePath(),
|
||||
Verb = "runas",
|
||||
};
|
||||
try
|
||||
{
|
||||
Process.Start(startInfo);
|
||||
MyAppExit(false);
|
||||
}
|
||||
catch { }
|
||||
}
|
||||
|
||||
private void ImportOldGuiConfig()
|
||||
{
|
||||
OpenFileDialog fileDialog = new()
|
||||
@@ -1275,7 +1324,7 @@ namespace v2rayN.ViewModels
|
||||
Multiselect = false,
|
||||
Filter = "guiNConfig|*.json|All|*.*"
|
||||
};
|
||||
if (fileDialog.ShowDialog() != DialogResult.OK)
|
||||
if (fileDialog.ShowDialog() != true)
|
||||
{
|
||||
return;
|
||||
}
|
||||
@@ -1362,7 +1411,6 @@ namespace v2rayN.ViewModels
|
||||
|
||||
public void Reload()
|
||||
{
|
||||
Global.reloadCore = true;
|
||||
_ = LoadV2ray();
|
||||
}
|
||||
|
||||
@@ -1382,7 +1430,6 @@ namespace v2rayN.ViewModels
|
||||
{
|
||||
_coreHandler.LoadCore(_config);
|
||||
|
||||
Global.reloadCore = false;
|
||||
//ConfigHandler.SaveConfig(ref _config, false);
|
||||
|
||||
ChangeSystemProxyStatus(_config.sysProxyType, false);
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
using DynamicData.Binding;
|
||||
using Microsoft.Win32;
|
||||
using ReactiveUI;
|
||||
using ReactiveUI.Fody.Helpers;
|
||||
using Splat;
|
||||
using System.Reactive;
|
||||
using System.Windows;
|
||||
using System.Windows.Forms;
|
||||
using v2rayN.Base;
|
||||
using v2rayN.Handler;
|
||||
using v2rayN.Mode;
|
||||
@@ -173,7 +173,7 @@ namespace v2rayN.ViewModels
|
||||
UI.Show(ResUI.PleaseSelectRules);
|
||||
return;
|
||||
}
|
||||
if (UI.ShowYesNo(ResUI.RemoveRules) == DialogResult.No)
|
||||
if (UI.ShowYesNo(ResUI.RemoveRules) == MessageBoxResult.No)
|
||||
{
|
||||
return;
|
||||
}
|
||||
@@ -268,7 +268,7 @@ namespace v2rayN.ViewModels
|
||||
Multiselect = false,
|
||||
Filter = "Rules|*.json|All|*.*"
|
||||
};
|
||||
if (fileDialog.ShowDialog() != DialogResult.OK)
|
||||
if (fileDialog.ShowDialog() != true)
|
||||
{
|
||||
return;
|
||||
}
|
||||
@@ -299,7 +299,7 @@ namespace v2rayN.ViewModels
|
||||
UI.Show(ResUI.OperationSuccess);
|
||||
}
|
||||
}
|
||||
private void ImportRulesFromUrl()
|
||||
private async Task ImportRulesFromUrl()
|
||||
{
|
||||
var url = SelectedRouting.url;
|
||||
if (Utils.IsNullOrEmpty(url))
|
||||
@@ -308,24 +308,21 @@ namespace v2rayN.ViewModels
|
||||
return;
|
||||
}
|
||||
|
||||
Task.Run(async () =>
|
||||
DownloadHandle downloadHandle = new DownloadHandle();
|
||||
string result = await downloadHandle.TryDownloadString(url, true, "");
|
||||
if (AddBatchRoutingRules(SelectedRouting, result) == 0)
|
||||
{
|
||||
DownloadHandle downloadHandle = new DownloadHandle();
|
||||
string result = await downloadHandle.DownloadStringAsync(url, false, "");
|
||||
if (AddBatchRoutingRules(SelectedRouting, result) == 0)
|
||||
Application.Current.Dispatcher.Invoke((Action)(() =>
|
||||
{
|
||||
Application.Current.Dispatcher.Invoke((Action)(() =>
|
||||
{
|
||||
RefreshRulesItems();
|
||||
}));
|
||||
UI.Show(ResUI.OperationSuccess);
|
||||
}
|
||||
});
|
||||
RefreshRulesItems();
|
||||
}));
|
||||
UI.Show(ResUI.OperationSuccess);
|
||||
}
|
||||
}
|
||||
private int AddBatchRoutingRules(RoutingItem routingItem, string clipboardData)
|
||||
{
|
||||
bool blReplace = false;
|
||||
if (UI.ShowYesNo(ResUI.AddBatchRoutingRulesYesNo) == DialogResult.No)
|
||||
if (UI.ShowYesNo(ResUI.AddBatchRoutingRulesYesNo) == MessageBoxResult.No)
|
||||
{
|
||||
blReplace = true;
|
||||
}
|
||||
|
||||
@@ -4,7 +4,6 @@ using ReactiveUI.Fody.Helpers;
|
||||
using Splat;
|
||||
using System.Reactive;
|
||||
using System.Windows;
|
||||
using System.Windows.Forms;
|
||||
using v2rayN.Base;
|
||||
using v2rayN.Handler;
|
||||
using v2rayN.Mode;
|
||||
@@ -244,7 +243,7 @@ namespace v2rayN.ViewModels
|
||||
UI.Show(ResUI.PleaseSelectRules);
|
||||
return;
|
||||
}
|
||||
if (UI.ShowYesNo(ResUI.RemoveRules) == DialogResult.No)
|
||||
if (UI.ShowYesNo(ResUI.RemoveRules) == MessageBoxResult.No)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -62,6 +62,7 @@ namespace v2rayN.ViewModels
|
||||
{
|
||||
item.remarks = SelectedSource.remarks;
|
||||
item.url = SelectedSource.url;
|
||||
item.moreUrl = SelectedSource.moreUrl;
|
||||
item.enabled = SelectedSource.enabled;
|
||||
item.userAgent = SelectedSource.userAgent;
|
||||
item.sort = SelectedSource.sort;
|
||||
|
||||
@@ -6,7 +6,6 @@ using ReactiveUI.Fody.Helpers;
|
||||
using Splat;
|
||||
using System.Reactive;
|
||||
using System.Windows;
|
||||
using System.Windows.Forms;
|
||||
using v2rayN.Base;
|
||||
using v2rayN.Handler;
|
||||
using v2rayN.Mode;
|
||||
@@ -24,6 +23,7 @@ namespace v2rayN.ViewModels
|
||||
public IObservableCollection<SubItem> SubItems => _subItems;
|
||||
[Reactive]
|
||||
public SubItem SelectedSource { get; set; }
|
||||
public IList<SubItem> SelectedSources { get; set; }
|
||||
|
||||
public ReactiveCommand<Unit, Unit> SubAddCmd { get; }
|
||||
public ReactiveCommand<Unit, Unit> SubDeleteCmd { get; }
|
||||
@@ -96,12 +96,15 @@ namespace v2rayN.ViewModels
|
||||
|
||||
private void DeleteSub()
|
||||
{
|
||||
if (UI.ShowYesNo(ResUI.RemoveServer) == DialogResult.No)
|
||||
if (UI.ShowYesNo(ResUI.RemoveServer) == MessageBoxResult.No)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
ConfigHandler.DeleteSubItem(ref _config, SelectedSource?.id);
|
||||
foreach (var it in SelectedSources)
|
||||
{
|
||||
ConfigHandler.DeleteSubItem(ref _config, it?.id);
|
||||
}
|
||||
RefreshSubItems();
|
||||
_noticeHandler?.Enqueue(ResUI.OperationSuccess);
|
||||
IsModified = true;
|
||||
|
||||
@@ -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,67 +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)
|
||||
{
|
||||
var txt = ((TextBox)sender);
|
||||
var index = Utils.ToInt(txt.Name.Substring(txt.Name.Length - 1, 1));
|
||||
|
||||
if (e.Key == Key.System)
|
||||
return;
|
||||
var formsKey = (Forms.Keys)KeyInterop.VirtualKeyFromKey(e.Key);
|
||||
|
||||
lstKey[index].KeyCode = formsKey;
|
||||
lstKey[index].Alt = Keyboard.IsKeyDown(Key.LeftAlt) || Keyboard.IsKeyDown(Key.RightAlt);
|
||||
lstKey[index].Control = Keyboard.IsKeyDown(Key.LeftCtrl) || Keyboard.IsKeyDown(Key.RightCtrl);
|
||||
lstKey[index].Shift = Keyboard.IsKeyDown(Key.LeftShift) || Keyboard.IsKeyDown(Key.RightShift);
|
||||
|
||||
BindingData(index);
|
||||
e.Handled = true;
|
||||
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
|
||||
@@ -125,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)
|
||||
|
||||
@@ -10,13 +10,13 @@
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:reactiveui="http://reactiveui.net"
|
||||
xmlns:resx="clr-namespace:v2rayN.Resx"
|
||||
xmlns:tb="http://www.hardcodet.net/taskbar"
|
||||
xmlns:tb="clr-namespace:H.NotifyIcon;assembly=H.NotifyIcon.Wpf"
|
||||
xmlns:vms="clr-namespace:v2rayN.ViewModels"
|
||||
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}"
|
||||
@@ -53,7 +53,10 @@
|
||||
<MenuItem Padding="8,0">
|
||||
<MenuItem.Header>
|
||||
<StackPanel Orientation="Horizontal">
|
||||
<materialDesign:PackIcon Margin="0,0,8,0" Kind="Server" />
|
||||
<materialDesign:PackIcon
|
||||
Margin="0,0,8,0"
|
||||
VerticalAlignment="Center"
|
||||
Kind="Server" />
|
||||
<TextBlock Text="{x:Static resx:ResUI.menuServers}" />
|
||||
</StackPanel>
|
||||
</MenuItem.Header>
|
||||
@@ -99,7 +102,10 @@
|
||||
<MenuItem Padding="8,0">
|
||||
<MenuItem.Header>
|
||||
<StackPanel Orientation="Horizontal">
|
||||
<materialDesign:PackIcon Margin="0,0,8,0" Kind="BookClockOutline" />
|
||||
<materialDesign:PackIcon
|
||||
Margin="0,0,8,0"
|
||||
VerticalAlignment="Center"
|
||||
Kind="BookClockOutline" />
|
||||
<TextBlock Text="{x:Static resx:ResUI.menuSubscription}" />
|
||||
</StackPanel>
|
||||
</MenuItem.Header>
|
||||
@@ -131,7 +137,10 @@
|
||||
<MenuItem Padding="8,0">
|
||||
<MenuItem.Header>
|
||||
<StackPanel Orientation="Horizontal">
|
||||
<materialDesign:PackIcon Margin="0,0,8,0" Kind="SettingsOutline" />
|
||||
<materialDesign:PackIcon
|
||||
Margin="0,0,8,0"
|
||||
VerticalAlignment="Center"
|
||||
Kind="SettingsOutline" />
|
||||
<TextBlock Text="{x:Static resx:ResUI.menuSetting}" />
|
||||
</StackPanel>
|
||||
</MenuItem.Header>
|
||||
@@ -148,6 +157,10 @@
|
||||
Height="{StaticResource MenuItemHeight}"
|
||||
Header="{x:Static resx:ResUI.menuGlobalHotkeySetting}" />
|
||||
<Separator Margin="-40,5" />
|
||||
<MenuItem
|
||||
x:Name="menuRebootAsAdmin"
|
||||
Height="{StaticResource MenuItemHeight}"
|
||||
Header="{x:Static resx:ResUI.menuRebootAsAdmin}" />
|
||||
<MenuItem
|
||||
x:Name="menuSettingsSetUWP"
|
||||
Height="{StaticResource MenuItemHeight}"
|
||||
@@ -169,7 +182,10 @@
|
||||
<MenuItem x:Name="menuReload" Padding="8,0">
|
||||
<MenuItem.Header>
|
||||
<StackPanel Orientation="Horizontal">
|
||||
<materialDesign:PackIcon Margin="0,0,8,0" Kind="Reload" />
|
||||
<materialDesign:PackIcon
|
||||
Margin="0,0,8,0"
|
||||
VerticalAlignment="Center"
|
||||
Kind="Reload" />
|
||||
<TextBlock Text="{x:Static resx:ResUI.menuReload}" />
|
||||
</StackPanel>
|
||||
</MenuItem.Header>
|
||||
@@ -180,7 +196,10 @@
|
||||
<MenuItem Padding="8,0">
|
||||
<MenuItem.Header>
|
||||
<StackPanel Orientation="Horizontal">
|
||||
<materialDesign:PackIcon Margin="0,0,8,0" Kind="Update" />
|
||||
<materialDesign:PackIcon
|
||||
Margin="0,0,8,0"
|
||||
VerticalAlignment="Center"
|
||||
Kind="Update" />
|
||||
<TextBlock Text="{x:Static resx:ResUI.menuCheckUpdate}" />
|
||||
</StackPanel>
|
||||
</MenuItem.Header>
|
||||
@@ -221,7 +240,10 @@
|
||||
<MenuItem x:Name="menuHelp" Padding="8,0">
|
||||
<MenuItem.Header>
|
||||
<StackPanel Orientation="Horizontal">
|
||||
<materialDesign:PackIcon Margin="0,0,8,0" Kind="HelpCircleOutline" />
|
||||
<materialDesign:PackIcon
|
||||
Margin="0,0,8,0"
|
||||
VerticalAlignment="Center"
|
||||
Kind="HelpCircleOutline" />
|
||||
<TextBlock Text="{x:Static resx:ResUI.menuHelp}" />
|
||||
</StackPanel>
|
||||
</MenuItem.Header>
|
||||
@@ -235,7 +257,10 @@
|
||||
Click="menuPromotion_Click">
|
||||
<MenuItem.Header>
|
||||
<StackPanel Orientation="Horizontal">
|
||||
<materialDesign:PackIcon Margin="0,0,8,0" Kind="VolumeHigh" />
|
||||
<materialDesign:PackIcon
|
||||
Margin="0,0,8,0"
|
||||
VerticalAlignment="Center"
|
||||
Kind="VolumeHigh" />
|
||||
<TextBlock Text="{x:Static resx:ResUI.menuPromotion}" />
|
||||
</StackPanel>
|
||||
</MenuItem.Header>
|
||||
@@ -249,7 +274,10 @@
|
||||
Click="menuClose_Click">
|
||||
<MenuItem.Header>
|
||||
<StackPanel Orientation="Horizontal">
|
||||
<materialDesign:PackIcon Margin="0,0,8,0" Kind="Minimize" />
|
||||
<materialDesign:PackIcon
|
||||
Margin="0,0,8,0"
|
||||
VerticalAlignment="Center"
|
||||
Kind="Minimize" />
|
||||
<TextBlock Text="{x:Static resx:ResUI.menuClose}" />
|
||||
</StackPanel>
|
||||
</MenuItem.Header>
|
||||
@@ -259,6 +287,7 @@
|
||||
<materialDesign:PopupBox
|
||||
Padding="8,0"
|
||||
HorizontalAlignment="Right"
|
||||
StaysOpen="True"
|
||||
Style="{StaticResource MaterialDesignToolForegroundPopupBox}">
|
||||
<StackPanel Margin="8">
|
||||
<Grid>
|
||||
@@ -351,7 +380,15 @@
|
||||
Height="30"
|
||||
Margin="4,0"
|
||||
Style="{StaticResource MaterialDesignFloatingActionMiniLightButton}">
|
||||
<materialDesign:PackIcon Kind="Plus" />
|
||||
<materialDesign:PackIcon VerticalAlignment="Center" Kind="Plus" />
|
||||
</Button>
|
||||
<Button
|
||||
x:Name="btnAutofitColumnWidth"
|
||||
Width="30"
|
||||
Height="30"
|
||||
Margin="4,0"
|
||||
Style="{StaticResource MaterialDesignFloatingActionMiniLightButton}">
|
||||
<materialDesign:PackIcon VerticalAlignment="Center" Kind="ArrowSplitVertical" />
|
||||
</Button>
|
||||
<TextBox
|
||||
x:Name="txtServerFilter"
|
||||
@@ -459,7 +496,6 @@
|
||||
CanUserSortColumns="False"
|
||||
EnableRowVirtualization="True"
|
||||
Focusable="True"
|
||||
FrozenColumnCount="1"
|
||||
GridLinesVisibility="All"
|
||||
HeadersVisibility="All"
|
||||
IsReadOnly="True"
|
||||
@@ -590,19 +626,19 @@
|
||||
<Style BasedOn="{StaticResource MaterialDesignDataGridColumnHeader}" TargetType="DataGridColumnHeader">
|
||||
<EventSetter Event="Click" Handler="LstProfiles_ColumnHeader_Click" />
|
||||
</Style>
|
||||
|
||||
<Style BasedOn="{StaticResource MaterialDesignDataGridCell}" TargetType="DataGridCell">
|
||||
<Style.Triggers>
|
||||
<DataTrigger Binding="{Binding isActive}" Value="True">
|
||||
<Setter Property="Background" Value="{DynamicResource PrimaryHueLightBrush}" />
|
||||
<Setter Property="Foreground" Value="Black" />
|
||||
<Setter Property="BorderBrush" Value="{DynamicResource PrimaryHueLightBrush}" />
|
||||
</DataTrigger>
|
||||
</Style.Triggers>
|
||||
</Style>
|
||||
|
||||
</DataGrid.Resources>
|
||||
<DataGrid.Columns>
|
||||
<DataGridTemplateColumn Width="50">
|
||||
<DataGridTemplateColumn.CellTemplate>
|
||||
<DataTemplate>
|
||||
<Border
|
||||
Width="auto"
|
||||
Height="auto"
|
||||
Background="{DynamicResource PrimaryHueLightBrush}"
|
||||
Visibility="{Binding Path=isActive, Converter={StaticResource BoolToVisConverter}}" />
|
||||
</DataTemplate>
|
||||
</DataGridTemplateColumn.CellTemplate>
|
||||
</DataGridTemplateColumn>
|
||||
|
||||
<base:MyDGTextColumn
|
||||
Width="80"
|
||||
@@ -613,7 +649,7 @@
|
||||
Width="150"
|
||||
Binding="{Binding remarks}"
|
||||
ExName="remarks"
|
||||
Header="{x:Static resx:ResUI.LvAlias}" />
|
||||
Header="{x:Static resx:ResUI.LvRemarks}" />
|
||||
<base:MyDGTextColumn
|
||||
Width="120"
|
||||
Binding="{Binding address}"
|
||||
@@ -712,6 +748,7 @@
|
||||
<materialDesign:PackIcon
|
||||
x:Name="menuSystemProxyClear2"
|
||||
Margin="0,0,8,0"
|
||||
VerticalAlignment="Center"
|
||||
Kind="Check" />
|
||||
<TextBlock Text="{x:Static resx:ResUI.menuSystemProxyClear}" />
|
||||
</StackPanel>
|
||||
@@ -723,6 +760,7 @@
|
||||
<materialDesign:PackIcon
|
||||
x:Name="menuSystemProxySet2"
|
||||
Margin="0,0,8,0"
|
||||
VerticalAlignment="Center"
|
||||
Kind="Check" />
|
||||
<TextBlock Text="{x:Static resx:ResUI.menuSystemProxySet}" />
|
||||
</StackPanel>
|
||||
@@ -734,6 +772,7 @@
|
||||
<materialDesign:PackIcon
|
||||
x:Name="menuSystemProxyNothing2"
|
||||
Margin="0,0,8,0"
|
||||
VerticalAlignment="Center"
|
||||
Kind="Check" />
|
||||
<TextBlock Text="{x:Static resx:ResUI.menuSystemProxyNothing}" />
|
||||
</StackPanel>
|
||||
@@ -745,6 +784,7 @@
|
||||
<materialDesign:PackIcon
|
||||
x:Name="menuSystemProxyPac2"
|
||||
Margin="0,0,8,0"
|
||||
VerticalAlignment="Center"
|
||||
Kind="Check" />
|
||||
<TextBlock Text="{x:Static resx:ResUI.menuSystemProxyPac}" />
|
||||
</StackPanel>
|
||||
@@ -802,6 +842,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>
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
using ReactiveUI;
|
||||
using Splat;
|
||||
using System.ComponentModel;
|
||||
using System.Drawing;
|
||||
using System.Reactive.Disposables;
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
@@ -15,7 +14,6 @@ using v2rayN.Mode;
|
||||
using v2rayN.Resx;
|
||||
using v2rayN.ViewModels;
|
||||
using Point = System.Windows.Point;
|
||||
using SystemInformation = System.Windows.Forms.SystemInformation;
|
||||
|
||||
namespace v2rayN.Views
|
||||
{
|
||||
@@ -31,9 +29,11 @@ namespace v2rayN.Views
|
||||
App.Current.SessionEnding += Current_SessionEnding;
|
||||
this.Closing += MainWindow_Closing;
|
||||
this.PreviewKeyDown += MainWindow_PreviewKeyDown;
|
||||
btnAutofitColumnWidth.Click += BtnAutofitColumnWidth_Click;
|
||||
lstProfiles.PreviewKeyDown += LstProfiles_PreviewKeyDown;
|
||||
lstProfiles.SelectionChanged += lstProfiles_SelectionChanged;
|
||||
lstProfiles.LoadingRow += LstProfiles_LoadingRow;
|
||||
lstProfiles.RowHeaderWidth = 30;
|
||||
if (_config.uiItem.enableDragDropSort)
|
||||
{
|
||||
lstProfiles.AllowDrop = true;
|
||||
@@ -118,6 +118,7 @@ namespace v2rayN.Views
|
||||
this.BindCommand(ViewModel, vm => vm.OptionSettingCmd, v => v.menuOptionSetting).DisposeWith(disposables);
|
||||
this.BindCommand(ViewModel, vm => vm.RoutingSettingCmd, v => v.menuRoutingSetting).DisposeWith(disposables);
|
||||
this.BindCommand(ViewModel, vm => vm.GlobalHotkeySettingCmd, v => v.menuGlobalHotkeySetting).DisposeWith(disposables);
|
||||
this.BindCommand(ViewModel, vm => vm.RebootAsAdminCmd, v => v.menuRebootAsAdmin).DisposeWith(disposables);
|
||||
this.BindCommand(ViewModel, vm => vm.ClearServerStatisticsCmd, v => v.menuClearServerStatistics).DisposeWith(disposables);
|
||||
this.BindCommand(ViewModel, vm => vm.ImportOldGuiConfigCmd, v => v.menuImportOldGuiConfig).DisposeWith(disposables);
|
||||
|
||||
@@ -150,6 +151,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);
|
||||
@@ -158,6 +160,7 @@ namespace v2rayN.Views
|
||||
this.BindCommand(ViewModel, vm => vm.SubUpdateViaProxyCmd, v => v.menuSubUpdateViaProxy2).DisposeWith(disposables);
|
||||
|
||||
this.OneWayBind(ViewModel, vm => vm.NotifyIcon, v => v.tbNotify.Icon).DisposeWith(disposables);
|
||||
this.OneWayBind(ViewModel, vm => vm.RunningServerToolTipText, v => v.tbNotify.ToolTipText).DisposeWith(disposables);
|
||||
this.OneWayBind(ViewModel, vm => vm.NotifyLeftClickCmd, v => v.tbNotify.LeftClickCommand).DisposeWith(disposables);
|
||||
this.OneWayBind(ViewModel, vm => vm.AppIcon, v => v.Icon).DisposeWith(disposables);
|
||||
|
||||
@@ -190,23 +193,30 @@ 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
|
||||
|
||||
private void UpdateViewHandler(string action)
|
||||
private void UpdateViewHandler(EViewAction action)
|
||||
{
|
||||
if (action == "AdjustMainLvColWidth")
|
||||
if (action == EViewAction.AdjustMainLvColWidth)
|
||||
{
|
||||
Application.Current.Dispatcher.Invoke(() =>
|
||||
{
|
||||
foreach (var it in lstProfiles.Columns)
|
||||
{
|
||||
it.Width = new DataGridLength(1, DataGridLengthUnitType.Auto);
|
||||
}
|
||||
AutofitColumnWidth();
|
||||
});
|
||||
}
|
||||
else if (action == "ProfilesFocus")
|
||||
else if (action == EViewAction.ProfilesFocus)
|
||||
{
|
||||
lstProfiles.Focus();
|
||||
}
|
||||
@@ -266,16 +276,6 @@ namespace v2rayN.Views
|
||||
return;
|
||||
}
|
||||
|
||||
if (colHeader.Column.GetType().Name != typeof(MyDGTextColumn).Name)
|
||||
{
|
||||
foreach (var it in lstProfiles.Columns)
|
||||
{
|
||||
//it.MinWidth = it.ActualWidth;
|
||||
it.Width = new DataGridLength(1, DataGridLengthUnitType.Auto);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
var colName = ((MyDGTextColumn)colHeader.Column).ExName;
|
||||
ViewModel?.SortServer(colName);
|
||||
}
|
||||
@@ -396,6 +396,18 @@ namespace v2rayN.Views
|
||||
{
|
||||
Utils.ProcessStart(Utils.GetBinPath("EnableLoopback.exe"));
|
||||
}
|
||||
|
||||
private void BtnAutofitColumnWidth_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
AutofitColumnWidth();
|
||||
}
|
||||
private void AutofitColumnWidth()
|
||||
{
|
||||
foreach (var it in lstProfiles.Columns)
|
||||
{
|
||||
it.Width = new DataGridLength(1, DataGridLengthUnitType.Auto);
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region UI
|
||||
@@ -408,16 +420,10 @@ namespace v2rayN.Views
|
||||
Height = _config.uiItem.mainHeight;
|
||||
}
|
||||
|
||||
IntPtr hWnd = new WindowInteropHelper(this).EnsureHandle();
|
||||
Graphics g = Graphics.FromHwnd(hWnd);
|
||||
if (Width > SystemInformation.WorkingArea.Width * 96 / g.DpiX)
|
||||
{
|
||||
Width = SystemInformation.WorkingArea.Width * 96 / g.DpiX;
|
||||
}
|
||||
if (Height > SystemInformation.WorkingArea.Height * 96 / g.DpiY)
|
||||
{
|
||||
Height = SystemInformation.WorkingArea.Height * 96 / g.DpiY;
|
||||
}
|
||||
var maxWidth = SystemParameters.WorkArea.Width;
|
||||
var maxHeight = SystemParameters.WorkArea.Height;
|
||||
if (Width > maxWidth) Width = maxWidth;
|
||||
if (Height > maxHeight) Height = maxHeight;
|
||||
if (_config.uiItem.mainGirdHeight1 > 0 && _config.uiItem.mainGirdHeight2 > 0)
|
||||
{
|
||||
gridMain.RowDefinitions[0].Height = new GridLength(_config.uiItem.mainGirdHeight1, GridUnitType.Star);
|
||||
@@ -433,8 +439,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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -459,7 +472,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">
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
xmlns:resx="clr-namespace:v2rayN.Resx"
|
||||
xmlns:vms="clr-namespace:v2rayN.ViewModels"
|
||||
Title="{x:Static resx:ResUI.menuSetting}"
|
||||
Width="900"
|
||||
Width="1000"
|
||||
Height="700"
|
||||
x:TypeArguments="vms:OptionSettingViewModel"
|
||||
Background="{DynamicResource MaterialDesignPaper}"
|
||||
@@ -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" />
|
||||
@@ -47,7 +47,7 @@
|
||||
Style="{StaticResource DefButton}" />
|
||||
</Grid>
|
||||
|
||||
<TabControl>
|
||||
<TabControl HorizontalContentAlignment="Left">
|
||||
<TabItem Header="{x:Static resx:ResUI.TbSettingsCore}">
|
||||
<ScrollViewer VerticalScrollBarVisibility="Visible">
|
||||
<Grid Margin="{StaticResource SettingItemMargin}">
|
||||
@@ -481,11 +481,12 @@
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="Auto" />
|
||||
</Grid.RowDefinitions>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="Auto" />
|
||||
<ColumnDefinition Width="Auto" />
|
||||
<ColumnDefinition Width="Auto" />
|
||||
<ColumnDefinition Width="*" />
|
||||
</Grid.ColumnDefinitions>
|
||||
|
||||
<TextBlock
|
||||
@@ -507,7 +508,8 @@
|
||||
Margin="{StaticResource ServerItemMargin}"
|
||||
VerticalAlignment="Center"
|
||||
Style="{StaticResource ToolbarTextBlock}"
|
||||
Text="{x:Static resx:ResUI.TbSettingsStartBootTip}" />
|
||||
Text="{x:Static resx:ResUI.TbSettingsStartBootTip}"
|
||||
TextWrapping="Wrap" />
|
||||
|
||||
<TextBlock
|
||||
Grid.Row="2"
|
||||
@@ -719,7 +721,8 @@
|
||||
Margin="{StaticResource ServerItemMargin}"
|
||||
VerticalAlignment="Center"
|
||||
Style="{StaticResource ToolbarTextBlock}"
|
||||
Text="{x:Static resx:ResUI.TbSettingsCurrentFontFamilyTip}" />
|
||||
Text="{x:Static resx:ResUI.TbSettingsCurrentFontFamilyTip}"
|
||||
TextWrapping="Wrap" />
|
||||
|
||||
<TextBlock
|
||||
Grid.Row="16"
|
||||
@@ -750,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>
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using ReactiveUI;
|
||||
using Microsoft.Win32;
|
||||
using ReactiveUI;
|
||||
using System.Globalization;
|
||||
using System.IO;
|
||||
using System.Reactive.Disposables;
|
||||
@@ -164,6 +165,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);
|
||||
@@ -209,7 +211,7 @@ namespace v2rayN.Views
|
||||
}
|
||||
private void btnBrowse_Click(object sender, System.Windows.RoutedEventArgs e)
|
||||
{
|
||||
var openFileDialog1 = new System.Windows.Forms.OpenFileDialog();
|
||||
var openFileDialog1 = new OpenFileDialog();
|
||||
openFileDialog1.Filter = "tunConfig|*.json|All|*.*";
|
||||
openFileDialog1.ShowDialog();
|
||||
|
||||
|
||||
@@ -134,7 +134,7 @@
|
||||
</Grid>
|
||||
|
||||
<Grid
|
||||
Margin="16"
|
||||
Margin="8"
|
||||
HorizontalAlignment="Center"
|
||||
DockPanel.Dock="Bottom">
|
||||
<Grid.ColumnDefinitions>
|
||||
|
||||
@@ -32,28 +32,40 @@
|
||||
Style="{StaticResource MaterialDesignToolBar}">
|
||||
<Button x:Name="menuRuleAdd">
|
||||
<StackPanel Orientation="Horizontal">
|
||||
<materialDesign:PackIcon Margin="0,0,8,0" Kind="Plus" />
|
||||
<materialDesign:PackIcon
|
||||
Margin="0,0,8,0"
|
||||
VerticalAlignment="Center"
|
||||
Kind="Plus" />
|
||||
<TextBlock Style="{StaticResource ToolbarTextBlock}" Text="{x:Static resx:ResUI.menuRuleAdd}" />
|
||||
</StackPanel>
|
||||
</Button>
|
||||
<Separator />
|
||||
<Button x:Name="menuImportRulesFromFile">
|
||||
<StackPanel Orientation="Horizontal">
|
||||
<materialDesign:PackIcon Margin="0,0,8,0" Kind="Import" />
|
||||
<materialDesign:PackIcon
|
||||
Margin="0,0,8,0"
|
||||
VerticalAlignment="Center"
|
||||
Kind="Import" />
|
||||
<TextBlock Style="{StaticResource ToolbarTextBlock}" Text="{x:Static resx:ResUI.menuImportRulesFromFile}" />
|
||||
</StackPanel>
|
||||
</Button>
|
||||
<Separator />
|
||||
<Button x:Name="menuImportRulesFromClipboard">
|
||||
<StackPanel Orientation="Horizontal">
|
||||
<materialDesign:PackIcon Margin="0,0,8,0" Kind="Import" />
|
||||
<materialDesign:PackIcon
|
||||
Margin="0,0,8,0"
|
||||
VerticalAlignment="Center"
|
||||
Kind="Import" />
|
||||
<TextBlock Style="{StaticResource ToolbarTextBlock}" Text="{x:Static resx:ResUI.menuImportRulesFromClipboard}" />
|
||||
</StackPanel>
|
||||
</Button>
|
||||
<Separator />
|
||||
<Button x:Name="menuImportRulesFromUrl">
|
||||
<StackPanel Orientation="Horizontal">
|
||||
<materialDesign:PackIcon Margin="0,0,8,0" Kind="Import" />
|
||||
<materialDesign:PackIcon
|
||||
Margin="0,0,8,0"
|
||||
VerticalAlignment="Center"
|
||||
Kind="Import" />
|
||||
<TextBlock Style="{StaticResource ToolbarTextBlock}" Text="{x:Static resx:ResUI.menuImportRulesFromUrl}" />
|
||||
</StackPanel>
|
||||
</Button>
|
||||
@@ -61,7 +73,7 @@
|
||||
</ToolBarTray>
|
||||
|
||||
<Grid
|
||||
Margin="16"
|
||||
Margin="8"
|
||||
HorizontalAlignment="Center"
|
||||
DockPanel.Dock="Bottom">
|
||||
<Grid.ColumnDefinitions>
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using ReactiveUI;
|
||||
using Microsoft.Win32;
|
||||
using ReactiveUI;
|
||||
using System.Reactive.Disposables;
|
||||
using System.Windows;
|
||||
using System.Windows.Input;
|
||||
@@ -108,7 +109,7 @@ namespace v2rayN.Views
|
||||
|
||||
private void btnBrowse_Click(object sender, System.Windows.RoutedEventArgs e)
|
||||
{
|
||||
var openFileDialog1 = new System.Windows.Forms.OpenFileDialog();
|
||||
var openFileDialog1 = new OpenFileDialog();
|
||||
openFileDialog1.Filter = "PNG|*.png";
|
||||
openFileDialog1.ShowDialog();
|
||||
|
||||
|
||||
@@ -39,7 +39,10 @@
|
||||
<MenuItem x:Name="menuRoutingBasic" Padding="8,0">
|
||||
<MenuItem.Header>
|
||||
<StackPanel Orientation="Horizontal">
|
||||
<materialDesign:PackIcon Margin="0,0,8,0" Kind="Server" />
|
||||
<materialDesign:PackIcon
|
||||
Margin="0,0,8,0"
|
||||
VerticalAlignment="Center"
|
||||
Kind="Server" />
|
||||
<TextBlock Text="{x:Static resx:ResUI.menuRoutingBasic}" />
|
||||
</StackPanel>
|
||||
</MenuItem.Header>
|
||||
@@ -54,7 +57,10 @@
|
||||
<MenuItem x:Name="menuRoutingAdvanced" Padding="8,0">
|
||||
<MenuItem.Header>
|
||||
<StackPanel Orientation="Horizontal">
|
||||
<materialDesign:PackIcon Margin="0,0,8,0" Kind="Routes" />
|
||||
<materialDesign:PackIcon
|
||||
Margin="0,0,8,0"
|
||||
VerticalAlignment="Center"
|
||||
Kind="Routes" />
|
||||
<TextBlock Text="{x:Static resx:ResUI.menuRoutingAdvanced}" />
|
||||
</StackPanel>
|
||||
</MenuItem.Header>
|
||||
@@ -108,7 +114,7 @@
|
||||
</ToolBarTray>
|
||||
|
||||
<Grid
|
||||
Margin="16"
|
||||
Margin="8"
|
||||
HorizontalAlignment="Center"
|
||||
DockPanel.Dock="Bottom">
|
||||
<Grid.ColumnDefinitions>
|
||||
@@ -196,7 +202,7 @@
|
||||
<DataGridTextColumn
|
||||
Width="200"
|
||||
Binding="{Binding remarks}"
|
||||
Header="{x:Static resx:ResUI.LvAlias}" />
|
||||
Header="{x:Static resx:ResUI.LvRemarks}" />
|
||||
<DataGridTextColumn
|
||||
Width="60"
|
||||
Binding="{Binding ruleNum}"
|
||||
|
||||
@@ -23,6 +23,14 @@
|
||||
TextOptions.TextRenderingMode="Auto"
|
||||
WindowStartupLocation="CenterScreen"
|
||||
mc:Ignorable="d">
|
||||
<Window.Resources>
|
||||
<ResourceDictionary>
|
||||
<ResourceDictionary.MergedDictionaries>
|
||||
<ResourceDictionary Source="pack://application:,,,/MaterialDesignThemes.Wpf;component/Themes/MaterialDesignTheme.Popupbox.xaml" />
|
||||
</ResourceDictionary.MergedDictionaries>
|
||||
</ResourceDictionary>
|
||||
</Window.Resources>
|
||||
|
||||
<ScrollViewer
|
||||
materialDesign:ScrollViewerAssist.IsAutoHideEnabled="True"
|
||||
HorizontalScrollBarVisibility="Auto"
|
||||
@@ -45,6 +53,7 @@
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="Auto" />
|
||||
<ColumnDefinition Width="Auto" />
|
||||
<ColumnDefinition Width="Auto" />
|
||||
</Grid.ColumnDefinitions>
|
||||
|
||||
<TextBlock
|
||||
@@ -92,6 +101,31 @@
|
||||
Style="{StaticResource MyOutlinedTextBox}"
|
||||
TextWrapping="Wrap" />
|
||||
|
||||
<materialDesign:PopupBox
|
||||
Grid.Row="2"
|
||||
Grid.Column="2"
|
||||
HorizontalAlignment="Right"
|
||||
StaysOpen="True"
|
||||
Style="{StaticResource MaterialDesignToolForegroundPopupBox}">
|
||||
<StackPanel>
|
||||
<TextBlock
|
||||
Margin="4"
|
||||
VerticalAlignment="Center"
|
||||
Style="{StaticResource ToolbarTextBlock}"
|
||||
Text="{x:Static resx:ResUI.LvMoreUrl}" />
|
||||
<TextBox
|
||||
x:Name="txtMoreUrl"
|
||||
Width="400"
|
||||
Margin="4"
|
||||
VerticalAlignment="Top"
|
||||
materialDesign:HintAssist.Hint="{x:Static resx:ResUI.SubUrlTips}"
|
||||
AcceptsReturn="True"
|
||||
MinLines="4"
|
||||
Style="{StaticResource MyOutlinedTextBox}"
|
||||
TextWrapping="Wrap" />
|
||||
</StackPanel>
|
||||
</materialDesign:PopupBox>
|
||||
|
||||
<TextBlock
|
||||
Grid.Row="3"
|
||||
Grid.Column="0"
|
||||
@@ -162,7 +196,7 @@
|
||||
</Grid>
|
||||
<Grid
|
||||
Grid.Row="1"
|
||||
Margin="16"
|
||||
Margin="8"
|
||||
HorizontalAlignment="Center">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="200" />
|
||||
|
||||
@@ -20,6 +20,7 @@ namespace v2rayN.Views
|
||||
{
|
||||
this.Bind(ViewModel, vm => vm.SelectedSource.remarks, v => v.txtRemarks.Text).DisposeWith(disposables);
|
||||
this.Bind(ViewModel, vm => vm.SelectedSource.url, v => v.txtUrl.Text).DisposeWith(disposables);
|
||||
this.Bind(ViewModel, vm => vm.SelectedSource.moreUrl, v => v.txtMoreUrl.Text).DisposeWith(disposables);
|
||||
this.Bind(ViewModel, vm => vm.SelectedSource.enabled, v => v.togEnable.IsChecked).DisposeWith(disposables);
|
||||
this.Bind(ViewModel, vm => vm.SelectedSource.userAgent, v => v.txtUserAgent.Text).DisposeWith(disposables);
|
||||
this.Bind(ViewModel, vm => vm.SelectedSource.sort, v => v.txtSort.Text).DisposeWith(disposables);
|
||||
|
||||
@@ -33,28 +33,40 @@
|
||||
Style="{StaticResource MaterialDesignToolBar}">
|
||||
<Button x:Name="menuSubAdd">
|
||||
<StackPanel Orientation="Horizontal">
|
||||
<materialDesign:PackIcon Margin="0,0,8,0" Kind="Plus" />
|
||||
<materialDesign:PackIcon
|
||||
Margin="0,0,8,0"
|
||||
VerticalAlignment="Center"
|
||||
Kind="Plus" />
|
||||
<TextBlock Style="{StaticResource ToolbarTextBlock}" Text="{x:Static resx:ResUI.menuSubAdd}" />
|
||||
</StackPanel>
|
||||
</Button>
|
||||
<Separator />
|
||||
<Button x:Name="menuSubDelete">
|
||||
<StackPanel Orientation="Horizontal">
|
||||
<materialDesign:PackIcon Margin="0,0,8,0" Kind="Delete" />
|
||||
<materialDesign:PackIcon
|
||||
Margin="0,0,8,0"
|
||||
VerticalAlignment="Center"
|
||||
Kind="Delete" />
|
||||
<TextBlock Style="{StaticResource ToolbarTextBlock}" Text="{x:Static resx:ResUI.menuSubDelete}" />
|
||||
</StackPanel>
|
||||
</Button>
|
||||
<Separator />
|
||||
<Button x:Name="menuSubEdit">
|
||||
<StackPanel Orientation="Horizontal">
|
||||
<materialDesign:PackIcon Margin="0,0,8,0" Kind="Edit" />
|
||||
<materialDesign:PackIcon
|
||||
Margin="0,0,8,0"
|
||||
VerticalAlignment="Center"
|
||||
Kind="Edit" />
|
||||
<TextBlock Style="{StaticResource ToolbarTextBlock}" Text="{x:Static resx:ResUI.menuSubEdit}" />
|
||||
</StackPanel>
|
||||
</Button>
|
||||
<Separator />
|
||||
<Button x:Name="menuSubShare">
|
||||
<StackPanel Orientation="Horizontal">
|
||||
<materialDesign:PackIcon Margin="0,0,8,0" Kind="QrcodePlus" />
|
||||
<materialDesign:PackIcon
|
||||
Margin="0,0,8,0"
|
||||
VerticalAlignment="Center"
|
||||
Kind="QrcodePlus" />
|
||||
<TextBlock Style="{StaticResource ToolbarTextBlock}" Text="{x:Static resx:ResUI.menuSubShare}" />
|
||||
</StackPanel>
|
||||
</Button>
|
||||
@@ -63,7 +75,10 @@
|
||||
Click="menuClose_Click"
|
||||
IsCancel="True">
|
||||
<StackPanel Orientation="Horizontal">
|
||||
<materialDesign:PackIcon Margin="0,0,8,0" Kind="Close" />
|
||||
<materialDesign:PackIcon
|
||||
Margin="0,0,8,0"
|
||||
VerticalAlignment="Center"
|
||||
Kind="Close" />
|
||||
<TextBlock Style="{StaticResource ToolbarTextBlock}" Text="{x:Static resx:ResUI.menuClose}" />
|
||||
</StackPanel>
|
||||
</Button>
|
||||
@@ -93,7 +108,7 @@
|
||||
Binding="{Binding url}"
|
||||
Header="{x:Static resx:ResUI.LvUrl}" />
|
||||
<DataGridTextColumn
|
||||
Width="80"
|
||||
Width="100"
|
||||
Binding="{Binding enabled}"
|
||||
Header="{x:Static resx:ResUI.LvEnabled}" />
|
||||
<DataGridTextColumn
|
||||
|
||||
@@ -3,6 +3,7 @@ using System.ComponentModel;
|
||||
using System.Reactive.Disposables;
|
||||
using System.Windows;
|
||||
using System.Windows.Input;
|
||||
using v2rayN.Mode;
|
||||
using v2rayN.ViewModels;
|
||||
|
||||
namespace v2rayN.Views
|
||||
@@ -17,6 +18,7 @@ namespace v2rayN.Views
|
||||
ViewModel = new SubSettingViewModel(this);
|
||||
this.Closing += SubSettingWindow_Closing;
|
||||
lstSubscription.MouseDoubleClick += LstSubscription_MouseDoubleClick;
|
||||
lstSubscription.SelectionChanged += LstSubscription_SelectionChanged;
|
||||
|
||||
this.WhenActivated(disposables =>
|
||||
{
|
||||
@@ -43,6 +45,10 @@ namespace v2rayN.Views
|
||||
{
|
||||
ViewModel?.EditSub(false);
|
||||
}
|
||||
private void LstSubscription_SelectionChanged(object sender, System.Windows.Controls.SelectionChangedEventArgs e)
|
||||
{
|
||||
ViewModel.SelectedSources = lstSubscription.SelectedItems.Cast<SubItem>().ToList();
|
||||
}
|
||||
|
||||
private void menuClose_Click(object sender, System.Windows.RoutedEventArgs e)
|
||||
{
|
||||
|
||||
@@ -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.14</FileVersion>
|
||||
<FileVersion>6.21</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="H.NotifyIcon.Wpf" Version="2.0.108" />
|
||||
<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