Compare commits

..

35 Commits
6.1 ... 6.6

Author SHA1 Message Date
2dust
5ceb638edf up 6.6 2023-01-09 20:04:24 +08:00
2dust
688b9ef5ee fix display 2023-01-09 20:03:39 +08:00
2dust
4909a557d5 Revert "Change the way to call the core in the speed test"
This reverts commit dd85ccd3f8.
2023-01-09 19:39:45 +08:00
2dust
75f63afadc bug fix 2023-01-08 09:24:09 +08:00
2dust
e90a624c9a up 6.5 2023-01-07 20:58:45 +08:00
2dust
dd85ccd3f8 Change the way to call the core in the speed test 2023-01-07 20:55:44 +08:00
2dust
fc54e19ce2 Add subscription failure log 2023-01-07 20:15:20 +08:00
2dust
118a920e57 Added drag and drop sorting option 2023-01-07 19:56:56 +08:00
2dust
975a335538 adjust timeout 2023-01-06 19:31:11 +08:00
2dust
c6ec4f38b0 Optimize speed test 2023-01-06 19:23:36 +08:00
2dust
5a5d686be1 up 6.4 2023-01-05 19:08:05 +08:00
2dust
8fc430d124 add tun mode custom config template 2023-01-05 19:05:16 +08:00
2dust
721eb40a8a bug fix 2023-01-05 19:03:29 +08:00
2dust
f18103751f Drag and Drop 2023-01-05 14:31:53 +08:00
2dust
9d30bb669e up 6.3 2023-01-04 17:18:29 +08:00
2dust
ab6f5c21c8 Auto Start via TaskService 2023-01-04 17:17:43 +08:00
2dust
4fc2ed32d2 bug fix 2023-01-04 15:47:08 +08:00
2dust
00ab4f2a7d delete temp file 2023-01-04 11:02:43 +08:00
2dust
cb5d8b405b fix bug 2023-01-04 11:02:26 +08:00
2dust
7b28aa8500 Optimize traffic statistics 2023-01-04 10:21:26 +08:00
2dust
97a369df0a Merge pull request #2962 from FrzMtrsprt/Fix_Window_Size
Fix window size on first launch
2023-01-04 09:07:23 +08:00
2dust
73a817c1cb remove tun Redirect Standard Error 2023-01-04 09:02:00 +08:00
FrzMtrsprt
c16053f0e5 Fix window size on first launch 2023-01-03 21:35:04 +08:00
2dust
3dfd108fc4 up 6.2 2023-01-03 16:32:49 +08:00
2dust
576696b25e add move to group 2023-01-03 16:32:33 +08:00
2dust
781fab5aab bug fix 2023-01-03 15:43:57 +08:00
2dust
0f099a19cd Improve traffic refresh 2023-01-03 15:11:34 +08:00
2dust
43b96ea4e5 bug fix 2023-01-03 10:52:44 +08:00
2dust
8cbf6bfffa Improve tun mode 2023-01-03 10:09:44 +08:00
2dust
52debcdcb3 Improved check for update v2rayN 2023-01-03 09:36:23 +08:00
2dust
9d38d89c25 Improve tun mode log 2023-01-02 20:22:00 +08:00
2dust
837f0ca393 Merge branch 'master' of https://github.com/2dust/v2rayN 2023-01-02 19:59:50 +08:00
2dust
42fd5b6eb2 fix bugs 2023-01-02 19:59:48 +08:00
2dust
7bdf76a665 Merge pull request #2928 from DanielBlackBeard/master
Update ResUI.fa-Ir.resx
2023-01-02 19:00:45 +08:00
Persian Prince
784ef278ea Update ResUI.fa-Ir.resx 2023-01-02 09:25:19 +03:30
26 changed files with 694 additions and 255 deletions

View File

@@ -98,7 +98,7 @@
public static readonly List<string> fingerprints = new List<string> { "chrome", "firefox", "safari", "randomized", "" };
public static readonly List<string> allowInsecures = new List<string> { "true", "false", "" };
public static readonly List<string> domainStrategy4Freedoms = new List<string> { "AsIs", "UseIP", "UseIPv4", "UseIPv6", "" };
public static readonly List<string> Languages = new List<string> { "zh-Hans", "en" ,"fa-Ir" };
public static readonly List<string> Languages = new List<string> { "zh-Hans", "en", "fa-Ir" };
public static readonly List<string> alpns = new List<string> { "h2", "http/1.1", "h2,http/1.1", "" };
public static readonly List<string> LogLevel = new List<string> { "debug", "info", "warning", "error", "none" };
public static readonly List<string> InboundTags = new List<string> { "socks", "http", "socks2", "http2" };

View File

@@ -1194,11 +1194,11 @@ namespace v2rayN.Handler
}
if (isSub)
{
SqliteHelper.Instance.Execute($"delete from ProfileItem where isSub = 1 and subid = {subid}");
SqliteHelper.Instance.Execute($"delete from ProfileItem where isSub = 1 and subid = '{subid}'");
}
else
{
SqliteHelper.Instance.Execute($"delete from ProfileItem where subid = {subid}");
SqliteHelper.Instance.Execute($"delete from ProfileItem where subid = '{subid}'");
}
return 0;
@@ -1217,6 +1217,22 @@ namespace v2rayN.Handler
return 0;
}
public static int MoveToGroup(Config config, List<ProfileItem> lstProfile, string subid)
{
foreach (var it in lstProfile)
{
var item = LazyConfig.Instance.GetProfileItem(it.indexId);
if (item is null)
{
continue;
}
item.subid = subid;
SqliteHelper.Instance.Update(item);
}
return 0;
}
#endregion
#region UI

View File

@@ -1463,8 +1463,8 @@ namespace v2rayN.Handler
}
if (it.configType == EConfigType.VMess || it.configType == EConfigType.VLESS)
{
var item2 = LazyConfig.Instance.GetProfileItem(config.indexId);
if (item2 is null || !Utils.IsGuidByParse(item2.id))
var item2 = LazyConfig.Instance.GetProfileItem(it.indexId);
if (item2 is null || Utils.IsNullOrEmpty(item2.id) || !Utils.IsGuidByParse(item2.id))
{
continue;
}

View File

@@ -92,7 +92,7 @@ namespace v2rayN.Handler
where 1=1 ";
if (!Utils.IsNullOrEmpty(subid))
{
sql += $" and a.subid = {subid}";
sql += $" and a.subid = '{subid}'";
}
if (!Utils.IsNullOrEmpty(filter))
{
@@ -134,11 +134,6 @@ namespace v2rayN.Handler
return SqliteHelper.Instance.ExecuteAsync(sql);
}
public List<ServerStatItem> ServerStatItems()
{
return SqliteHelper.Instance.Table<ServerStatItem>().ToList();
}
public List<RoutingItem> RoutingItems()
{
return SqliteHelper.Instance.Table<RoutingItem>().Where(it => it.locked == false).ToList();

View File

@@ -12,6 +12,7 @@ namespace v2rayN.Handler
private Config _config;
private CoreHandler _coreHandler;
private List<ServerTestItem> _selecteds;
private ESpeedActionType _actionType;
Action<string, string, string> _updateFunc;
public SpeedtestHandler(Config config)
@@ -23,7 +24,7 @@ namespace v2rayN.Handler
{
_config = config;
_coreHandler = coreHandler;
//_selecteds = Utils.DeepCopy(selecteds);
_actionType = actionType;
_updateFunc = update;
_selecteds = new List<ServerTestItem>();
@@ -106,7 +107,7 @@ namespace v2rayN.Handler
});
}
private async Task RunRealPing()
private Task RunRealPing()
{
int pid = -1;
try
@@ -117,7 +118,7 @@ namespace v2rayN.Handler
if (pid < 0)
{
UpdateFunc("", ResUI.FailedToRunCore);
return;
return Task.CompletedTask;
}
DownloadHandle downloadHandle = new DownloadHandle();
@@ -144,6 +145,8 @@ namespace v2rayN.Handler
LazyConfig.Instance.SetTestResult(it.indexId, output, "");
UpdateFunc(it.indexId, output);
int.TryParse(output, out int delay);
it.delay = delay;
}
catch (Exception ex)
{
@@ -162,11 +165,17 @@ namespace v2rayN.Handler
{
if (pid > 0) _coreHandler.CoreStopPid(pid);
}
return Task.CompletedTask;
}
private async Task RunSpeedTestAsync()
{
string testIndexId = string.Empty;
int pid = -1;
if (_actionType == ESpeedActionType.Mixedtest)
{
_selecteds = _selecteds.OrderBy(t => t.delay).ToList();
}
pid = _coreHandler.LoadCoreConfigString(_config, _selecteds);
if (pid < 0)
@@ -178,11 +187,9 @@ namespace v2rayN.Handler
string url = _config.constItem.speedTestUrl;
DownloadHandle downloadHandle = new DownloadHandle();
var timeout = 10;
var timeout = 8;
foreach (var it in _selecteds)
{
_ = LazyConfig.Instance.SetTestResult(it.indexId, "", "-1");
UpdateFunc(it.indexId, "", ResUI.Speedtesting);
if (!it.allowTest)
{
continue;
@@ -191,7 +198,12 @@ namespace v2rayN.Handler
{
continue;
}
testIndexId = it.indexId;
if (it.delay < 0)
{
continue;
}
_ = LazyConfig.Instance.SetTestResult(it.indexId, "", "-1");
UpdateFunc(it.indexId, "", ResUI.Speedtesting);
var item = LazyConfig.Instance.GetProfileItem(it.indexId);
if (item is null) continue;
@@ -218,6 +230,8 @@ namespace v2rayN.Handler
{
await RunRealPing();
Thread.Sleep(1000);
await RunSpeedTestAsync();
}

View File

@@ -14,6 +14,8 @@ namespace v2rayN.Handler
private StatsService.StatsServiceClient client_;
private bool exitFlag_;
private ServerStatItem _serverStatItem;
private List<ServerStatItem> _lstServerStat;
public List<ServerStatItem> ServerStat => _lstServerStat;
Action<ServerSpeedItem> updateFunc_;
@@ -83,21 +85,22 @@ namespace v2rayN.Handler
GetServerStatItem(config_.indexId);
ParseOutput(res.Stat, out ServerSpeedItem server);
_serverStatItem.todayUp += server.proxyUp;
_serverStatItem.todayDown += server.proxyDown;
_serverStatItem.totalUp += server.proxyUp;
_serverStatItem.totalDown += server.proxyDown;
if (server.proxyUp != 0 || server.proxyDown != 0)
{
_serverStatItem.todayUp += server.proxyUp;
_serverStatItem.todayDown += server.proxyDown;
_serverStatItem.totalUp += server.proxyUp;
_serverStatItem.totalDown += server.proxyDown;
}
if (Global.ShowInTaskbar)
{
server.indexId = config_.indexId;
server.todayUp = _serverStatItem.todayUp;
server.todayDown = _serverStatItem.todayDown;
server.totalUp = _serverStatItem.totalUp;
server.totalDown = _serverStatItem.totalDown;
updateFunc_(server);
}
if (server.proxyUp != 0 || server.proxyDown != 0)
{
_ = SqliteHelper.Instance.UpdateAsync(_serverStatItem);
}
}
}
var sleep = config_.statisticsFreshRate < 1 ? 1 : config_.statisticsFreshRate;
@@ -114,12 +117,27 @@ namespace v2rayN.Handler
{
SqliteHelper.Instance.Execute($"delete from ServerStatItem ");
_serverStatItem = null;
_lstServerStat = new();
}
public void SaveTo()
{
try
{
SqliteHelper.Instance.UpdateAll(_lstServerStat);
}
catch (Exception ex)
{
Utils.SaveLog(ex.Message, ex);
}
}
private void Init()
{
long ticks = DateTime.Now.Date.Ticks;
SqliteHelper.Instance.Execute($"update ServerStatItem set todayUp = 0,todayDown=0,dateNow={ticks} where dateNow<>{ticks}");
_lstServerStat = SqliteHelper.Instance.Table<ServerStatItem>().ToList();
}
private void GetServerStatItem(string indexId)
@@ -132,7 +150,7 @@ namespace v2rayN.Handler
if (_serverStatItem == null)
{
_serverStatItem = SqliteHelper.Instance.Table<ServerStatItem>().FirstOrDefault(t => t.indexId == indexId);
_serverStatItem = _lstServerStat.FirstOrDefault(t => t.indexId == indexId);
if (_serverStatItem == null)
{
_serverStatItem = new ServerStatItem
@@ -145,6 +163,7 @@ namespace v2rayN.Handler
dateNow = ticks
};
_ = SqliteHelper.Instance.Replacesync(_serverStatItem);
_lstServerStat.Add(_serverStatItem);
}
}

View File

@@ -72,7 +72,16 @@ namespace v2rayN.Base
private bool Init()
{
coreInfo = LazyConfig.Instance.GetCoreInfo(ECoreType.sing_box);
//Template
string configStr = Utils.GetEmbedText(Global.TunSingboxFileName);
if (!Utils.IsNullOrEmpty(_config.tunModeItem.customTemplate) && File.Exists(_config.tunModeItem.customTemplate))
{
var customTemplate = File.ReadAllText(_config.tunModeItem.customTemplate);
if (!Utils.IsNullOrEmpty(customTemplate))
{
configStr = customTemplate;
}
}
if (Utils.IsNullOrEmpty(configStr))
{
return false;
@@ -200,15 +209,17 @@ namespace v2rayN.Base
{
return;
}
var showWindow = _config.tunModeItem.showWindow;
Process p = new Process
{
StartInfo = new ProcessStartInfo
{
FileName = fileName,
Arguments = $"run -c {Utils.GetConfigPath(_tunConfigName)}",
Arguments = $"run -c \"{Utils.GetConfigPath(_tunConfigName)}\"",
WorkingDirectory = Utils.GetConfigPath(),
UseShellExecute = _config.tunModeItem.showWindow,
CreateNoWindow = !_config.tunModeItem.showWindow,
UseShellExecute = showWindow,
CreateNoWindow = !showWindow,
//RedirectStandardError = !showWindow,
Verb = "runas",
}
};
@@ -217,7 +228,14 @@ namespace v2rayN.Base
_isRunning = true;
if (p.WaitForExit(1000))
{
//if (showWindow)
//{
throw new Exception("start tun mode fail");
//}
//else
//{
// throw new Exception(p.StandardError.ReadToEnd());
//}
}
Global.processJob.AddProcess(p.Handle);

View File

@@ -55,7 +55,7 @@ namespace v2rayN.Handler
StartInfo = new ProcessStartInfo
{
FileName = "v2rayUpgrade.exe",
Arguments = "\"" + fileName + "\"",
Arguments = $"\"{fileName}\"",
WorkingDirectory = Utils.StartupPath()
}
};
@@ -232,6 +232,11 @@ namespace v2rayN.Handler
}
int ret = ConfigHandler.AddBatchServers(ref config, result, id, true);
if (ret <= 0)
{
Utils.SaveLog("FailedImportSubscription");
Utils.SaveLog(result);
}
_updateFunc(false,
ret > 0
? $"{hashCode}{ResUI.MsgUpdateSubscriptionEnd}"
@@ -278,6 +283,8 @@ namespace v2rayN.Handler
string targetPath = Utils.GetBinPath($"{geoName}.dat", (ECoreType)Enum.Parse(typeof(ECoreType), it));
File.Copy(fileName, targetPath, true);
});
File.Delete(fileName);
//_updateFunc(true, "");
}
}
@@ -457,6 +464,17 @@ namespace v2rayN.Handler
throw new ArgumentException("Type");
}
if (type == ECoreType.v2rayN)
{
decimal.TryParse(curVersion, out decimal decCur);
decimal.TryParse(version, out decimal dec);
if (decCur >= dec)
{
AbsoluteCompleted?.Invoke(this, new ResultEventArgs(false, message));
return;
}
}
if (curVersion == version)
{
AbsoluteCompleted?.Invoke(this, new ResultEventArgs(false, message));

View File

@@ -60,6 +60,7 @@ namespace v2rayN.Mode
public bool colorModeDark { get; set; }
public string? colorPrimaryName { get; set; }
public string currentLanguage { get; set; }
public bool enableDragDropSort { get; set; }
public Dictionary<string, int> mainLvColWidth { get; set; }
}
@@ -102,6 +103,7 @@ namespace v2rayN.Mode
public bool strictRoute { get; set; }
public string stack { get; set; }
public int mtu { get; set; }
public string customTemplate { get; set; }
public List<string> directIP { get; set; }
public List<string> directProcess { get; set; }

View File

@@ -1,12 +1,8 @@
namespace v2rayN.Mode
{
[Serializable]
class ServerSpeedItem
class ServerSpeedItem : ServerStatItem
{
public string indexId
{
get; set;
}
public long proxyUp
{
get; set;

View File

@@ -3,25 +3,11 @@
[Serializable]
class ServerTestItem
{
public string indexId
{
get; set;
}
public string address
{
get; set;
}
public int port
{
get; set;
}
public EConfigType configType
{
get; set;
}
public bool allowTest
{
get; set;
}
public string indexId { get; set; }
public string address { get; set; }
public int port { get; set; }
public EConfigType configType { get; set; }
public bool allowTest { get; set; }
public int delay { get; set; }
}
}

View File

@@ -807,6 +807,15 @@ namespace v2rayN.Resx {
}
}
/// <summary>
/// 查找类似 Move to group 的本地化字符串。
/// </summary>
public static string menuMoveToGroup {
get {
return ResourceManager.GetString("menuMoveToGroup", resourceCulture);
}
}
/// <summary>
/// 查找类似 Move to top (T) 的本地化字符串。
/// </summary>
@@ -2383,6 +2392,15 @@ namespace v2rayN.Resx {
}
}
/// <summary>
/// 查找类似 Enable Server Drag Drop Sort(Require restart) 的本地化字符串。
/// </summary>
public static string TbSettingsEnableDragDropSort {
get {
return ResourceManager.GetString("TbSettingsEnableDragDropSort", resourceCulture);
}
}
/// <summary>
/// 查找类似 Exception 的本地化字符串。
/// </summary>
@@ -2635,6 +2653,15 @@ namespace v2rayN.Resx {
}
}
/// <summary>
/// 查找类似 Custom Template 的本地化字符串。
/// </summary>
public static string TbSettingsTunModeCustomTemplate {
get {
return ResourceManager.GetString("TbSettingsTunModeCustomTemplate", resourceCulture);
}
}
/// <summary>
/// 查找类似 Direct IP CIDR, separated by commas (,) 的本地化字符串。
/// </summary>

View File

@@ -118,22 +118,22 @@
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<data name="BatchExportSubscriptionSuccessfully" xml:space="preserve">
<value>Batch export subscription to clipboard successfully</value>
<value>صادرات دسته ای محتوای اشتراک به کلیپ بورد با موفقیت انجام شد</value>
</data>
<data name="BatchExportURLSuccessfully" xml:space="preserve">
<value>Batch export share URL to clipboard successfully</value>
</data>
<data name="CheckServerSettings" xml:space="preserve">
<value>Please check the server settings first</value>
<value>لطفا ابتدا تنظیمات سرور را بررسی کنید</value>
</data>
<data name="ConfigurationFormatIncorrect" xml:space="preserve">
<value>Invalid configuration format</value>
<value>فرمت پیکربندی نادرست است</value>
</data>
<data name="CustomServerTips" xml:space="preserve">
<value>Note that custom configuration relies entirely on your own configuration and does not work with all settings. If you want to use the system proxy, please modify the listening port manually.</value>
</data>
<data name="Downloading" xml:space="preserve">
<value>Downloading...</value>
<value>درحال دانلود...</value>
</data>
<data name="downloadSpeed" xml:space="preserve">
<value>دانلود</value>
@@ -142,49 +142,49 @@
<value>Whether to download? {0}</value>
</data>
<data name="FailedConversionConfiguration" xml:space="preserve">
<value>Failed to convert configuration file</value>
<value>تبدیل فایل پیکربندی انجام نشد</value>
</data>
<data name="FailedGenDefaultConfiguration" xml:space="preserve">
<value>Failed to generate default configuration file</value>
<value>فایل پیکربندی پیش فرض ایجاد نشد</value>
</data>
<data name="FailedGetDefaultConfiguration" xml:space="preserve">
<value> Failed to get the default configuration</value>
<value>پیکربندی پیش فرض دریافت نشد</value>
</data>
<data name="FailedImportedCustomServer" xml:space="preserve">
<value>Failed to import custom configuration server</value>
<value>سرور پیکربندی سفارشی وارد نشد</value>
</data>
<data name="FailedReadConfiguration" xml:space="preserve">
<value>Failed to read configuration file</value>
<value>فایل پیکربندی خوانده نشد</value>
</data>
<data name="FillCorrectServerPort" xml:space="preserve">
<value>Please fill in the correct format server port</value>
<value>لطفا فرمت صحیح پورت سرور را پر کنید</value>
</data>
<data name="FillKcpParameters" xml:space="preserve">
<value>Please fill in the KCP parameters correctly</value>
<value>لطفاً پارامترهای KCP را به درستی پر کنید</value>
</data>
<data name="FillLocalListeningPort" xml:space="preserve">
<value>Please fill in the local listening port</value>
<value>لطفاً پورت گوش دادن محلی را پر کنید</value>
</data>
<data name="FillPassword" xml:space="preserve">
<value>Please fill in the password</value>
<value>لطفا رمز عبور را وارد کنید</value>
</data>
<data name="FillServerAddress" xml:space="preserve">
<value>Please fill in the server address</value>
<value>لطفا آدرس سرور را وارد کنید</value>
</data>
<data name="FillUUID" xml:space="preserve">
<value>Please fill in the user ID</value>
<value>لطفا شناسه کاربری را وارد کنید</value>
</data>
<data name="IncorrectClientConfiguration" xml:space="preserve">
<value> is not the correct client configuration file, please check</value>
<value>فایل پیکربندی مشتری صحیح نیست، لطفا بررسی کنید</value>
</data>
<data name="Incorrectconfiguration" xml:space="preserve">
<value> is not the correct configuration, please check</value>
<value>پیکربندی درستی نیست، لطفا بررسی کنید</value>
</data>
<data name="IncorrectServerConfiguration" xml:space="preserve">
<value> is not the correct server configuration file, please check</value>
<value>فایل پیکربندی سرور صحیح نیست، لطفا بررسی کنید</value>
</data>
<data name="InitialConfiguration" xml:space="preserve">
<value>Initial Configuration</value>
<value>پیکربندی اولیه</value>
</data>
<data name="IsLatestCore" xml:space="preserve">
<value>{0} already up to date.</value>
@@ -205,52 +205,52 @@
<value>پورت</value>
</data>
<data name="LvServiceType" xml:space="preserve">
<value>Type</value>
<value>نوع</value>
</data>
<data name="LvSubscription" xml:space="preserve">
<value>Subs group</value>
<value>گروه فرعی</value>
</data>
<data name="LvTestResults" xml:space="preserve">
<value>Test Results</value>
<value>نتایج تست</value>
</data>
<data name="LvTodayDownloadDataAmount" xml:space="preserve">
<value>Download traffic today</value>
<value> ترافیک دانلود امروز</value>
</data>
<data name="LvTodayUploadDataAmount" xml:space="preserve">
<value>Upload traffic today</value>
<value> ترافیک اپلود امروز</value>
</data>
<data name="LvTotalDownloadDataAmount" xml:space="preserve">
<value>Total download traffic</value>
<value>کل ترافیک دانلود</value>
</data>
<data name="LvTotalUploadDataAmount" xml:space="preserve">
<value>Total upload traffic</value>
<value>کل ترافیک آپلود</value>
</data>
<data name="LvTransportProtocol" xml:space="preserve">
<value>Transport</value>
<value>جابجایی</value>
</data>
<data name="MediumFresh" xml:space="preserve">
<value>Medium</value>
<value>متوسط</value>
</data>
<data name="MsgClearSubscription" xml:space="preserve">
<value>Clear original subscription content</value>
<value>محتوای اشتراک اصلی را پاک کنید</value>
</data>
<data name="MsgDownloadV2rayCoreSuccessfully" xml:space="preserve">
<value>Download Core successfully</value>
<value>دانلود Core با موفقیت</value>
</data>
<data name="MsgFailedImportSubscription" xml:space="preserve">
<value>Failed to import subscription content</value>
<value>محتوای اشتراک وارد نشد</value>
</data>
<data name="MsgGetSubscriptionSuccessfully" xml:space="preserve">
<value>Get subscription content successfully</value>
<value>محتوای اشتراک با موفقیت دریافت شد</value>
</data>
<data name="MsgNoValidSubscription" xml:space="preserve">
<value>No valid subscriptions set</value>
<value>هیچ اشتراک معتبری تنظیم نشده است</value>
</data>
<data name="MsgPACUpdateFailed" xml:space="preserve">
<value>PAC update failed</value>
<value>به روز رسانی PAC ناموفق بود</value>
</data>
<data name="MsgPACUpdateSuccessfully" xml:space="preserve">
<value>PAC update succeeded</value>
<value>به روز رسانی PAC با موفقیت انجام شد</value>
</data>
<data name="MsgParsingSuccessfully" xml:space="preserve">
<value>Resolve {0} successfully</value>
@@ -259,7 +259,7 @@
<value>Simplify PAC Success</value>
</data>
<data name="MsgStartGettingSubscriptions" xml:space="preserve">
<value>Start getting subscriptions</value>
<value>شروع به دریافت اشتراک شد</value>
</data>
<data name="MsgStartUpdating" xml:space="preserve">
<value>Start updating {0}...</value>
@@ -268,7 +268,7 @@
<value>Start updating PAC...</value>
</data>
<data name="MsgSubscriptionDecodingFailed" xml:space="preserve">
<value>Invalid subscription content</value>
<value>محتوای اشتراک نامعتبر است</value>
</data>
<data name="MsgUnpacking" xml:space="preserve">
<value>is unpacking...</value>
@@ -307,22 +307,22 @@
<value>Please Fill Remarks</value>
</data>
<data name="PleaseSelectEncryption" xml:space="preserve">
<value>Please select the encryption method</value>
<value>لطفاً روش رمزگذاری را انتخاب کنید</value>
</data>
<data name="PleaseSelectProtocol" xml:space="preserve">
<value>Please select a protocol</value>
<value>لطفا یک پروتکل انتخاب کنید</value>
</data>
<data name="PleaseSelectServer" xml:space="preserve">
<value>Please select the server first</value>
<value>لطفا ابتدا سرور را انتخاب کنید</value>
</data>
<data name="QuickFresh" xml:space="preserve">
<value>Fast</value>
<value>سریع</value>
</data>
<data name="RemoveDuplicateServerResult" xml:space="preserve">
<value>Servers deduplication completed. Old: {0}, New: {1}.</value>
</data>
<data name="RemoveServer" xml:space="preserve">
<value>Are you sure to remove the server?</value>
<value>آیا مطمئن هستید که سرور را حذف می کنید؟</value>
</data>
<data name="SaveClientConfigurationIn" xml:space="preserve">
<value>The client configuration file is saved at: {0}</value>
@@ -331,13 +331,13 @@
<value>The server configuration file is saved at: {0}</value>
</data>
<data name="SlowFresh" xml:space="preserve">
<value>Slow</value>
<value>آهسته. تدریجی</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>
<value>توجه: این ویژگی به پروکسی جهانی Http متکی است. لطفاً پس از آزمایش، پراکسی جهانی Http و گره فعال را به صورت دستی تنظیم کنید.</value>
</data>
<data name="StartPacFailed" xml:space="preserve">
<value>PAC failed to start. Please run this program as Administrator.</value>
<value>PAC شروع نشد. لطفا این برنامه را به عنوان Administrator اجرا کنید.</value>
</data>
<data name="StartService" xml:space="preserve">
<value>Start service ({0})...</value>
@@ -347,7 +347,7 @@
{0}</value>
</data>
<data name="SuccessfullyImportedCustomServer" xml:space="preserve">
<value>Custom configuration server imported successfully.</value>
<value>سرور پیکربندی سفارشی با موفقیت وارد شد.</value>
</data>
<data name="SuccessfullyImportedServerViaClipboard" xml:space="preserve">
<value>{0} servers have been imported from clipboard.</value>
@@ -359,13 +359,13 @@
<value>The ping of current service: {0} ms</value>
</data>
<data name="OperationSuccess" xml:space="preserve">
<value>Operation success</value>
<value>موفقیت عملیات</value>
</data>
<data name="PleaseSelectRules" xml:space="preserve">
<value>Please select rules</value>
<value>لطفا قوانین را انتخاب کنید</value>
</data>
<data name="RemoveRules" xml:space="preserve">
<value>Are you sure to remove the rules?</value>
<value>آیا مطمئن هستید که قوانین را حذف می کنید؟</value>
</data>
<data name="RoutingRuleDetailRequiredTips" xml:space="preserve">
<value>{0},One of the required.</value>
@@ -389,13 +389,13 @@
<value>Download GeoFile: {0} successfully</value>
</data>
<data name="MsgInformationTitle" xml:space="preserve">
<value>Information</value>
<value>اطلاعات</value>
</data>
<data name="LvCustomIcon" xml:space="preserve">
<value>Custom Icon</value>
<value>نماد سفارشی</value>
</data>
<data name="FillCorrectDNSText" xml:space="preserve">
<value>Please fill in the correct custom DNS</value>
<value>لطفاً DNS سفارشی صحیح را پر کنید</value>
</data>
<data name="TransportPathTip1" xml:space="preserve">
<value>*ws path</value>
@@ -446,34 +446,34 @@
<value>Global hotkey {0} registered successfully</value>
</data>
<data name="UngroupedServers" xml:space="preserve">
<value>Ungrouped</value>
<value>گروه بندی نشده</value>
</data>
<data name="AllGroupServers" xml:space="preserve">
<value>All servers</value>
<value>همه سرورها</value>
</data>
<data name="FillServerAddressCustom" xml:space="preserve">
<value>Please browse to import server configuration</value>
</data>
<data name="SystemProxy" xml:space="preserve">
<value>System proxy</value>
<value>پروکسی سیستم</value>
</data>
<data name="Speedtesting" xml:space="preserve">
<value>Testing...</value>
<value>درحال تست کردن...</value>
</data>
<data name="TooManyServersTip" xml:space="preserve">
<value>Too many servers, please open the main interface</value>
<value>تعداد سرورها خیلی زیاد است، لطفا رابط اصلی را باز کنید</value>
</data>
<data name="LabLAN" xml:space="preserve">
<value>LAN</value>
</data>
<data name="LabLocal" xml:space="preserve">
<value>Local</value>
<value>محلی</value>
</data>
<data name="MsgServerTitle" xml:space="preserve">
<value>Servers Filter</value>
<value>فیلتر سرورها</value>
</data>
<data name="NetFrameworkRequirementsTip" xml:space="preserve">
<value>Normal use of this version requires .NET Framework 4.8</value>
<value>استفاده معمولی از این نسخه به .NET Framework 4.8 نیاز دارد</value>
</data>
<data name="menuCheckUpdate" xml:space="preserve">
<value>بررسی بروزرسانی</value>
@@ -491,10 +491,10 @@
<value>کمک</value>
</data>
<data name="menuOptionSetting" xml:space="preserve">
<value>تنظیمات گزینه</value>
<value>تنظیمات پارامتر</value>
</data>
<data name="menuPromotion" xml:space="preserve">
<value>Promotion</value>
<value>ترفیع</value>
</data>
<data name="menuReload" xml:space="preserve">
<value>بارگذاری مجدد</value>
@@ -524,7 +524,7 @@
<value>اشتراک را بدون پروکسی به روز شود</value>
</data>
<data name="menuSubUpdateViaProxy" xml:space="preserve">
<value>Update subscription with proxy</value>
<value>اشتراک را با پروکسی به روز شود</value>
</data>
<data name="menuSystemproxy" xml:space="preserve">
<value>پروکسی سیستم</value>
@@ -551,91 +551,91 @@
<value>زبان</value>
</data>
<data name="menuAddServerViaClipboard" xml:space="preserve">
<value>Import bulk URL from clipboard (Ctrl+V)</value>
<value>وارد کردن URL انبوه از کلیپ بورد (Ctrl+V)</value>
</data>
<data name="menuAddServerViaScan" xml:space="preserve">
<value>Scan QR code on the screen (Ctrl+S)</value>
<value>اسکن کد QR روی صفحه (Ctrl+S)</value>
</data>
<data name="menuCopyServer" xml:space="preserve">
<value>Clone selected server</value>
<value>سرور انتخاب شده را شبیه سازی کنید</value>
</data>
<data name="menuRemoveDuplicateServer" xml:space="preserve">
<value>Remove duplicate servers</value>
<value>سرورهای تکراری را حذف کنید</value>
</data>
<data name="menuRemoveServer" xml:space="preserve">
<value>Remove selected servers (Delete)</value>
<value>حذف سرورهای انتخابی (Delete)</value>
</data>
<data name="menuSetDefaultServer" xml:space="preserve">
<value>Set as active server (Enter)</value>
<value>به عنوان سرور فعال تنظیم کنید (Enter)</value>
</data>
<data name="menuClearServerStatistics" xml:space="preserve">
<value>Clear all service statistics</value>
<value>تمام آمار خدمات را پاک کنید</value>
</data>
<data name="menuPingServer" xml:space="preserve">
<value>Test servers ping (Ctrl+P)</value>
<value>تست پینگ سرورها (Ctrl+P)</value>
</data>
<data name="menuRealPingServer" xml:space="preserve">
<value>Test servers real delay (Ctrl+R)</value>
<value>آزمایش سرورها با تاخیر واقعی (Ctrl+R)</value>
</data>
<data name="menuSortServerResult" xml:space="preserve">
<value>Sort by test result</value>
<value>مرتب سازی بر اساس نتیجه تست</value>
</data>
<data name="menuSpeedServer" xml:space="preserve">
<value>Test servers download speed (Ctrl+T)</value>
<value>تست سرعت دانلود سرورها (Ctrl+T)</value>
</data>
<data name="menuTcpingServer" xml:space="preserve">
<value>Test servers with tcping (Ctrl+O)</value>
<value>تست سرورها با tcping (Ctrl+O)</value>
</data>
<data name="menuTestMe" xml:space="preserve">
<value>Test current service status</value>
<value>وضعیت سرویس فعلی را تست کنید</value>
</data>
<data name="menuExport2ClientConfig" xml:space="preserve">
<value>سرور انتخابی را برای پیکربندی کلاینت صادر کنید</value>
</data>
<data name="menuExport2ServerConfig" xml:space="preserve">
<value>Export selected server for server configuration</value>
<value>سرور انتخاب شده را برای پیکربندی سرور صادر کنید</value>
</data>
<data name="menuExport2ShareUrl" xml:space="preserve">
<value>Export share URLs to clipboard (Ctrl+C)</value>
<value>URL های اشتراک گذاری را به کلیپ بورد صادر کنید (Ctrl+C)</value>
</data>
<data name="menuExport2SubContent" xml:space="preserve">
<value>Export subscription (base64) share to clipboard</value>
<value>اشتراک (base64) را به کلیپ بورد صادر کنید</value>
</data>
<data name="menuAddCustomServer" xml:space="preserve">
<value>یک سرور پیکربندی سفارشی اضافه شود</value>
</data>
<data name="menuAddShadowsocksServer" xml:space="preserve">
<value>Add [Shadowsocks] server</value>
<value>سرور [شادوساکس] را اضافه کنید</value>
</data>
<data name="menuAddSocksServer" xml:space="preserve">
<value>Add [Socks] server</value>
<value>سرور [ساکس] را اضافه کنید</value>
</data>
<data name="menuAddTrojanServer" xml:space="preserve">
<value>Add [Trojan] server</value>
<value>سرور [تروجان] را اضافه کنید</value>
</data>
<data name="menuAddVlessServer" xml:space="preserve">
<value>Add [VLESS] server</value>
<value>سرور [VLESS] را اضافه کنید</value>
</data>
<data name="menuAddVmessServer" xml:space="preserve">
<value>Add [VMess] server</value>
<value>سرور [VMess] را اضافه کنید</value>
</data>
<data name="menuSelectAll" xml:space="preserve">
<value>Select All (Ctrl+A)</value>
<value>انتخاب همه (Ctrl+A)</value>
</data>
<data name="menuMsgViewClear" xml:space="preserve">
<value>Clear All</value>
<value>همه را پاک کن</value>
</data>
<data name="menuMsgViewCopy" xml:space="preserve">
<value>Copy (Ctrl+C)</value>
<value>کپی (Ctrl+C)</value>
</data>
<data name="menuMsgViewCopyAll" xml:space="preserve">
<value>Copy All</value>
<value>کپی همه</value>
</data>
<data name="menuMsgViewFilter" xml:space="preserve">
<value>Set message filters</value>
<value>فیلترهای پیام را تنظیم کنید</value>
</data>
<data name="menuMsgViewSelectAll" xml:space="preserve">
<value>Select All (Ctrl+A)</value>
<value>انتخاب همه (Ctrl+A)</value>
</data>
<data name="menuSubAdd" xml:space="preserve">
<value>اضافه کردن</value>
@@ -665,7 +665,7 @@
<value>تایید</value>
</data>
<data name="GbTransport" xml:space="preserve">
<value>Transport</value>
<value>انتقال</value>
</data>
<data name="TbAddress" xml:space="preserve">
<value>آدرس</value>
@@ -689,7 +689,7 @@
<value>UUID(id)</value>
</data>
<data name="TbNetwork" xml:space="preserve">
<value>Transport protocol(network)</value>
<value>پروتکل جابجایی (شبکه)</value>
</data>
<data name="TbPath" xml:space="preserve">
<value>مسیر</value>
@@ -716,10 +716,10 @@
<value>*Default value tcp</value>
</data>
<data name="TbCoreType" xml:space="preserve">
<value>Core Type</value>
<value>نوع هسته</value>
</data>
<data name="TbFlow5" xml:space="preserve">
<value>Flow</value>
<value>جریان</value>
</data>
<data name="TbGUID" xml:space="preserve">
<value>Generate</value>
@@ -728,19 +728,19 @@
<value>رمزعبور</value>
</data>
<data name="TbId4" xml:space="preserve">
<value>Password(Optional)</value>
<value>رمز عبور (اختیاری)</value>
</data>
<data name="TbId5" xml:space="preserve">
<value>UUID(id)</value>
</data>
<data name="TbSecurity3" xml:space="preserve">
<value>Encryption</value>
<value>رمزگذاری</value>
</data>
<data name="TbSecurity4" xml:space="preserve">
<value>User(Optional)</value>
<value>کاربر (اختیاری)</value>
</data>
<data name="TbSecurity5" xml:space="preserve">
<value>Encryption</value>
<value>رمزگذاری</value>
</data>
<data name="TbPreSocksPort" xml:space="preserve">
<value>txtPreSocksPort</value>
@@ -755,37 +755,37 @@
<value>ویرایش</value>
</data>
<data name="TbSettingsAdvancedProtocol" xml:space="preserve">
<value>Advanced proxy settings, protocol selection (optional)</value>
<value>تنظیمات پیشرفته پروکسی، انتخاب پروتکل (اختیاری)</value>
</data>
<data name="TbSettingsAllowLAN" xml:space="preserve">
<value>Allow connections from the LAN</value>
<value>اتصالات از LAN را مجاز کنید</value>
</data>
<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>
<value>فاصله تست تأخیر خودکار (دقیقه)</value>
</data>
<data name="TbSettingsAutoUpdate" xml:space="preserve">
<value>Automatic update interval of subscriptions (hours)</value>
<value>فاصله به روز رسانی خودکار اشتراک ها (ساعت)</value>
</data>
<data name="TbSettingsAutoUpdateInterval" xml:space="preserve">
<value>Automatic update interval of and Geo (hours)</value>
<value>فاصله به روز رسانی خودکار و Geo (ساعت)</value>
</data>
<data name="TbSettingsCore" xml:space="preserve">
<value>Core: basic settings</value>
<value>هسته: تنظیمات اولیه</value>
</data>
<data name="TbSettingsCoreDns" xml:space="preserve">
<value>Core: DNS settings</value>
<value>هسته: تنظیمات DNS</value>
</data>
<data name="TbSettingsCoreKcp" xml:space="preserve">
<value>Core: KCP settings</value>
<value>هسته: تنظیمات KCP</value>
</data>
<data name="TbSettingsCoreType" xml:space="preserve">
<value>CoreType settings</value>
<value>تنظیمات CoreType</value>
</data>
<data name="TbSettingsDefAllowInsecure" xml:space="preserve">
<value>AllowInsecure</value>
<value>اجازه ناامن</value>
</data>
<data name="TbSettingsDomainStrategy4Freedom" xml:space="preserve">
<value>Outbound Freedom domainStrategy</value>
@@ -794,7 +794,7 @@
<value>Automatically adjust column width after updating subscription</value>
</data>
<data name="TbSettingsEnableCheckPreReleaseUpdate" xml:space="preserve">
<value>Check for pre-release updates</value>
<value>به روز رسانی های پیش از انتشار را بررسی کنید</value>
</data>
<data name="TbSettingsException" xml:space="preserve">
<value>استثنا</value>
@@ -803,28 +803,28 @@
<value>Exception. Do not use proxy server for addresses beginning with,Use semicolon (;)</value>
</data>
<data name="TbSettingsHttpPort" xml:space="preserve">
<value>Http Port</value>
<value>پورت Http</value>
</data>
<data name="TbSettingsIgnoreGeoUpdateCore" xml:space="preserve">
<value>Ignore Geo files when updating core</value>
<value>هنگام به‌روزرسانی هسته، فایل‌های Geo را نادیده بگیرید</value>
</data>
<data name="TbSettingsIpv6" xml:space="preserve">
<value>Enable IPv6</value>
<value>IPv6 را فعال کنید</value>
</data>
<data name="TbSettingsKeepOlderDedupl" xml:space="preserve">
<value>Keep older when deduplication</value>
</data>
<data name="TbSettingsLogEnabled" xml:space="preserve">
<value>Record local logs</value>
<value>ثبت گزارش های محلی</value>
</data>
<data name="TbSettingsLogLevel" xml:space="preserve">
<value>Log Level</value>
<value>سطح ثبت رویداد</value>
</data>
<data name="TbSettingsMuxEnabled" xml:space="preserve">
<value>Turn on Mux Multiplexing</value>
</data>
<data name="TbSettingsN" xml:space="preserve">
<value>v2rayN settings</value>
<value>تنظیمات v2rayN</value>
</data>
<data name="TbSettingsPacListenPort" xml:space="preserve">
<value>Pac listen port</value>
@@ -860,7 +860,7 @@
<value>Subscription conversion Url</value>
</data>
<data name="TbSettingsSystemproxy" xml:space="preserve">
<value>System proxy settings</value>
<value>تنظیمات پراکسی سیستم</value>
</data>
<data name="TbSettingsTLS13" xml:space="preserve">
<value>Enable Security Protocol TLS v1.3 (subscription/update)</value>
@@ -875,19 +875,19 @@
<value>Auth user</value>
</data>
<data name="TbClearSystemProxy" xml:space="preserve">
<value>Clear system proxy</value>
<value>پاک کردن پروکسی سیستم</value>
</data>
<data name="TbDisplayGUI" xml:space="preserve">
<value>Display GUI</value>
<value>نمایش رابط کاربری گرافیکی</value>
</data>
<data name="TbGlobalHotkeySetting" xml:space="preserve">
<value>GlobalHotkey Setting</value>
<value>تنظیم کلید میانبر جهانی</value>
</data>
<data name="TbGlobalHotkeySettingTip" xml:space="preserve">
<value>Set directly by pressing the keyboard, Take effect after restart</value>
</data>
<data name="TbNotChangeSystemProxy" xml:space="preserve">
<value>Do not change system proxy</value>
<value>پروکسی سیستم را تغییر ندهید</value>
</data>
<data name="TbReset" xml:space="preserve">
<value>بازنشانی</value>
@@ -896,10 +896,10 @@
<value>تنظیم پراکسی سیستم</value>
</data>
<data name="TbSystemProxyPac" xml:space="preserve">
<value>Pac Mode</value>
<value>حالت Pac</value>
</data>
<data name="menuShareServer" xml:space="preserve">
<value>Share Server (Ctrl+D)</value>
<value>اشتراک گذاری سرور(Ctrl+D)</value>
</data>
<data name="menuRouting" xml:space="preserve">
<value>مسیریابی</value>
@@ -911,10 +911,10 @@
<value>اجرا به عنوان ادمین</value>
</data>
<data name="menuMoveBottom" xml:space="preserve">
<value>Move to bottom (B)</value>
<value>به پایین حرکت شود(B)</value>
</data>
<data name="menuMoveDown" xml:space="preserve">
<value>Down (D)</value>
<value>پایین (D)</value>
</data>
<data name="menuMoveTop" xml:space="preserve">
<value>Move to top (T)</value>
@@ -935,25 +935,25 @@
<value>اضافه کردن</value>
</data>
<data name="menuRoutingAdvancedImportRules" xml:space="preserve">
<value>Import Advanced Rules</value>
<value>وارد کردن قوانین پیشرفته</value>
</data>
<data name="menuRoutingAdvancedRemove" xml:space="preserve">
<value>Remove selected</value>
<value>حذف انتخاب شده</value>
</data>
<data name="menuRoutingAdvancedSetDefault" xml:space="preserve">
<value>Set as active rule</value>
</data>
<data name="menuRoutingBasic" xml:space="preserve">
<value>Basic Function</value>
<value>عملکرد پایه</value>
</data>
<data name="menuRoutingBasicImportRules" xml:space="preserve">
<value>Import Basic Rules</value>
<value>واردات قوانین اساسی</value>
</data>
<data name="TbdomainMatcher" xml:space="preserve">
<value>Domain Matcher</value>
<value>تطبیق دامنه</value>
</data>
<data name="TbdomainStrategy" xml:space="preserve">
<value>Domain strategy</value>
<value>استراتژی دامنه</value>
</data>
<data name="TbenableRoutingAdvanced" xml:space="preserve">
<value>فعال کردن عملکرد پیشرفته</value>
@@ -968,37 +968,37 @@
<value>1.Proxy Domain or IP</value>
</data>
<data name="TbRoutingTabRuleList" xml:space="preserve">
<value>Pre-defined Rule Set List</value>
<value>لیست مجموعه قوانین از پیش تعریف شده</value>
</data>
<data name="TbRoutingTips" xml:space="preserve">
<value>*Set the rules, separated by commas (,); The comma in the regular is replaced by &lt;COMMA&gt;</value>
</data>
<data name="menuImportRulesFromClipboard" xml:space="preserve">
<value>Import Rules From Clipboard</value>
<value>وارد کردن قوانین از کلیپ بورد</value>
</data>
<data name="menuImportRulesFromFile" xml:space="preserve">
<value>Import Rules From File</value>
<value>وارد کردن قوانین از فایل</value>
</data>
<data name="menuImportRulesFromUrl" xml:space="preserve">
<value>Import Rules From Sub Url</value>
<value>وارد کردن قوانین از Sub Url</value>
</data>
<data name="menuRoutingRuleSetting" xml:space="preserve">
<value>تنظیم قانون</value>
</data>
<data name="menuRuleAdd" xml:space="preserve">
<value>Rule Add</value>
<value>اضافه کردن قانون</value>
</data>
<data name="menuRuleExportSelected" xml:space="preserve">
<value>Export Selected Rules</value>
<value>صادر کردن قوانین انتخاب شده</value>
</data>
<data name="menuRuleList" xml:space="preserve">
<value>Rule List</value>
<value>فهرست قوانین</value>
</data>
<data name="menuRuleRemove" xml:space="preserve">
<value>Remove Rules</value>
<value>حذف قوانین</value>
</data>
<data name="menuRoutingRuleDetailsSetting" xml:space="preserve">
<value>RoutingRuleDetailsSetting</value>
<value>تنظیم جزئیات قانون مسیریابی</value>
</data>
<data name="TbAutoSort" xml:space="preserve">
<value>Domain and ip are auto sorted when saving</value>
@@ -1007,19 +1007,19 @@
<value>Ruleobject Doc</value>
</data>
<data name="TbDnsObjectDoc" xml:space="preserve">
<value>Support DnsObject</value>
<value>پشتیبانی از DnsObject</value>
</data>
<data name="SubUrlTips" xml:space="preserve">
<value>Group please leave blank here</value>
<value>گروه لطفا اینجا را خالی بگذارید</value>
</data>
<data name="TipChangeRouting" xml:space="preserve">
<value>Routing setting is changed</value>
<value>تنظیمات مسیریابی تغییر کرده است</value>
</data>
<data name="TipChangeSystemProxy" xml:space="preserve">
<value>System proxy setting is changed</value>
<value>تنظیمات پراکسی سیستم تغییر کرده است</value>
</data>
<data name="TbSettingsRouteOnly" xml:space="preserve">
<value>RouteOnly</value>
<value>فقط مسیر</value>
</data>
<data name="menuMixedTestServer" xml:space="preserve">
<value>One-click test Latency and speed (Ctrl+E)</value>
@@ -1031,25 +1031,25 @@
<value>Speed(M/s)</value>
</data>
<data name="FailedToRunCore" xml:space="preserve">
<value>Failed to run Core, please see the log</value>
<value>Core اجرا نشد، لطفاً گزارش را ببینید</value>
</data>
<data name="LvFilter" xml:space="preserve">
<value>Remarks regular filter</value>
</data>
<data name="TbDisplayLog" xml:space="preserve">
<value>Display Log</value>
<value>نمایش گزارش</value>
</data>
<data name="menuImportOldGuiConfig" xml:space="preserve">
<value>Import old config guiNConfig</value>
<value>پیکربندی قدیمی guiNConfig را وارد شود</value>
</data>
<data name="TbEnableTunAs" xml:space="preserve">
<value>Enable Tun</value>
<value>Tun را فعال شود</value>
</data>
<data name="TbSettingsNewPort4LAN" xml:space="preserve">
<value>New Port for LAN</value>
<value>پورت جدید برای LAN</value>
</data>
<data name="TbSettingsTunMode" xml:space="preserve">
<value>TunMode settings</value>
<value>تنظیمات TunMode</value>
</data>
<data name="TbSettingsTunModeDirectIP" xml:space="preserve">
<value>Direct IP CIDR, separated by commas (,)</value>

View File

@@ -1060,4 +1060,13 @@
<data name="TbSettingsTunModeShowWindow" xml:space="preserve">
<value>Show console</value>
</data>
<data name="menuMoveToGroup" xml:space="preserve">
<value>Move to group</value>
</data>
<data name="TbSettingsTunModeCustomTemplate" xml:space="preserve">
<value>Custom Template</value>
</data>
<data name="TbSettingsEnableDragDropSort" xml:space="preserve">
<value>Enable Server Drag Drop Sort(Require restart)</value>
</data>
</root>

View File

@@ -851,7 +851,7 @@
<value>开机启动(可能会不成功)</value>
</data>
<data name="TbSettingsStatistics" xml:space="preserve">
<value>启用统计(实时网速显示,需重启)</value>
<value>启用统计(实时网速显示,需重启)</value>
</data>
<data name="TbSettingsStatisticsFreshRate" xml:space="preserve">
<value>统计刷新频率(单位秒)</value>
@@ -1060,4 +1060,13 @@
<data name="TbSettingsTunModeShowWindow" xml:space="preserve">
<value>显示控制台</value>
</data>
<data name="menuMoveToGroup" xml:space="preserve">
<value>移至订阅分组</value>
</data>
<data name="TbSettingsTunModeCustomTemplate" xml:space="preserve">
<value>自定义配置模板</value>
</data>
<data name="TbSettingsEnableDragDropSort" xml:space="preserve">
<value>启用服务器拖放排序(需重启)</value>
</data>
</root>

View File

@@ -1,4 +1,5 @@
using Microsoft.Win32;
using Microsoft.Win32.TaskScheduler;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using NLog;
@@ -601,17 +602,28 @@ namespace v2rayN
//delete first
RegWriteValue(Global.AutoRunRegPath, autoRunName, "");
if (IsAdministrator())
{
AutoStart(autoRunName, "", "");
}
if (run)
{
string exePath = $"\"{GetExePath()}\"";
RegWriteValue(Global.AutoRunRegPath, autoRunName, exePath);
if (IsAdministrator())
{
AutoStart(autoRunName, exePath, "");
}
else
{
RegWriteValue(Global.AutoRunRegPath, autoRunName, exePath);
}
}
}
catch (Exception ex)
{
SaveLog(ex.Message, ex);
}
}
}
/// <summary>
@@ -741,6 +753,47 @@ namespace v2rayN
}
}
/// <summary>
/// Auto Start via TaskService
/// </summary>
/// <param name="taskName"></param>
/// <param name="fileName"></param>
/// <param name="description"></param>
/// <exception cref="ArgumentNullException"></exception>
public static void AutoStart(string taskName, string fileName, string description)
{
if (string.IsNullOrEmpty(taskName))
{
return;
}
string TaskName = taskName;
var logonUser = WindowsIdentity.GetCurrent().Name;
string taskDescription = description;
string deamonFileName = fileName;
using (var taskService = new TaskService())
{
var tasks = taskService.RootFolder.GetTasks(new Regex(TaskName));
foreach (var t in tasks)
{
taskService.RootFolder.DeleteTask(t.Name);
}
if (string.IsNullOrEmpty(fileName))
{
return;
}
var task = taskService.NewTask();
task.RegistrationInfo.Description = taskDescription;
task.Settings.DisallowStartIfOnBatteries = false;
task.Triggers.Add(new LogonTrigger { UserId = logonUser, Delay = TimeSpan.FromMinutes(1) });
task.Principal.RunLevel = TaskRunLevel.Highest;
task.Actions.Add(new ExecAction(deamonFileName));
taskService.RootFolder.RegisterTaskDefinition(TaskName, task);
}
}
#endregion
#region

View File

@@ -86,6 +86,7 @@ namespace v2rayN.ViewModels
item.remarks = SelectedSource.remarks;
item.address = SelectedSource.address;
item.coreType = SelectedSource.coreType;
item.displayLog = SelectedSource.displayLog;
item.preSocksPort = SelectedSource.preSocksPort;
}

View File

@@ -8,6 +8,7 @@ using ReactiveUI;
using ReactiveUI.Fody.Helpers;
using Splat;
using System.Drawing;
using System.IO;
using System.Reactive;
using System.Reactive.Linq;
using System.Text;
@@ -62,6 +63,8 @@ namespace v2rayN.ViewModels
[Reactive]
public SubItem SelectedSub { get; set; }
[Reactive]
public SubItem SelectedMoveToGroup { get; set; }
[Reactive]
public RoutingItem SelectedRouting { get; set; }
[Reactive]
public ComboItem SelectedServer { get; set; }
@@ -86,7 +89,7 @@ namespace v2rayN.ViewModels
public ReactiveCommand<Unit, Unit> CopyServerCmd { get; }
public ReactiveCommand<Unit, Unit> SetDefaultServerCmd { get; }
public ReactiveCommand<Unit, Unit> ShareServerCmd { get; }
//servers move
//servers move
public ReactiveCommand<Unit, Unit> MoveTopCmd { get; }
public ReactiveCommand<Unit, Unit> MoveUpCmd { get; }
public ReactiveCommand<Unit, Unit> MoveDownCmd { get; }
@@ -109,8 +112,8 @@ namespace v2rayN.ViewModels
public ReactiveCommand<Unit, Unit> SubSettingCmd { get; }
public ReactiveCommand<Unit, Unit> AddSubCmd { get; }
public ReactiveCommand<Unit, Unit> SubUpdateCmd { get; }
public ReactiveCommand<Unit, Unit> SubGroupUpdateCmd { get; }
public ReactiveCommand<Unit, Unit> SubUpdateViaProxyCmd { get; }
public ReactiveCommand<Unit, Unit> SubGroupUpdateCmd { get; }
public ReactiveCommand<Unit, Unit> SubGroupUpdateViaProxyCmd { get; }
//Setting
@@ -205,6 +208,7 @@ namespace v2rayN.ViewModels
SelectedProfile = new();
SelectedSub = new();
SelectedMoveToGroup = new();
SelectedRouting = new();
SelectedServer = new();
@@ -220,6 +224,10 @@ namespace v2rayN.ViewModels
x => x.SelectedSub,
y => y != null && !y.remarks.IsNullOrEmpty() && _subId != y.id)
.Subscribe(c => SubSelectedChanged(c));
this.WhenAnyValue(
x => x.SelectedMoveToGroup,
y => y != null && !y.remarks.IsNullOrEmpty())
.Subscribe(c => MoveToGroup(c));
this.WhenAnyValue(
x => x.SelectedRouting,
@@ -305,7 +313,7 @@ namespace v2rayN.ViewModels
{
ShareServer();
}, canEditRemove);
//servers move
//servers move
MoveTopCmd = ReactiveCommand.Create(() =>
{
MoveServer(EMove.Top);
@@ -380,13 +388,13 @@ namespace v2rayN.ViewModels
{
UpdateSubscriptionProcess("", false);
});
SubGroupUpdateCmd = ReactiveCommand.Create(() =>
{
UpdateSubscriptionProcess(_subId, true);
});
SubUpdateViaProxyCmd = ReactiveCommand.Create(() =>
{
UpdateSubscriptionProcess("", false);
UpdateSubscriptionProcess("", true);
});
SubGroupUpdateCmd = ReactiveCommand.Create(() =>
{
UpdateSubscriptionProcess(_subId, false);
});
SubGroupUpdateViaProxyCmd = ReactiveCommand.Create(() =>
{
@@ -533,6 +541,24 @@ namespace v2rayN.ViewModels
}
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));
if (update.proxyUp + update.proxyDown > 0)
{
var second = DateTime.Now.Second;
if (second % 3 == 0)
{
var item = _profileItems.Where(it => it.indexId == update.indexId).FirstOrDefault();
if (item != null)
{
item.todayDown = Utils.HumanFy(update.todayDown);
item.todayUp = Utils.HumanFy(update.todayUp);
item.totalDown = Utils.HumanFy(update.totalDown);
item.totalUp = Utils.HumanFy(update.totalUp);
_profileItems.Replace(item, Utils.DeepCopy(item));
}
}
}
}));
}
catch (Exception ex)
@@ -612,6 +638,7 @@ namespace v2rayN.ViewModels
SysProxyHandle.UpdateSysProxy(_config, true);
}
_statistics?.SaveTo();
_statistics?.Close();
_coreHandler.CoreStop();
@@ -638,6 +665,8 @@ namespace v2rayN.ViewModels
_subId = SelectedSub?.id;
RefreshServers();
_updateView("ProfilesFocus");
}
private void ServerFilterChanged(bool c)
@@ -658,7 +687,7 @@ namespace v2rayN.ViewModels
List<ServerStatItem> lstServerStat = new();
if (_statistics != null && _statistics.Enable)
{
lstServerStat = LazyConfig.Instance.ServerStatItems();
lstServerStat = _statistics.ServerStat;
}
lstModel = (from t in lstModel
join t2 in lstServerStat
@@ -677,8 +706,8 @@ namespace v2rayN.ViewModels
subRemarks = t.subRemarks,
isActive = t.isActive,
delay = t.delay,
delayVal = t.delay > 0 ? $"{t.delay} {Global.DelayUnit}" : string.Empty,
speedVal = t.speed > 0 ? $"{t.speed} {Global.SpeedUnit}" : string.Empty,
delayVal = t.delay != 0 ? $"{t.delay} {Global.DelayUnit}" : string.Empty,
speedVal = t.speed != 0 ? $"{t.speed} {Global.SpeedUnit}" : string.Empty,
todayDown = t22 == null ? "" : Utils.HumanFy(t22.todayDown),
todayUp = t22 == null ? "" : Utils.HumanFy(t22.todayUp),
totalDown = t22 == null ? "" : Utils.HumanFy(t22.totalDown),
@@ -747,7 +776,7 @@ namespace v2rayN.ViewModels
private int GetProfileItems(out List<ProfileItem> lstSelecteds)
{
lstSelecteds = new List<ProfileItem>();
if (SelectedProfiles == null && SelectedProfiles.Count() <= 0)
if (SelectedProfiles == null || SelectedProfiles.Count() <= 0)
{
return -1;
}
@@ -995,6 +1024,26 @@ namespace v2rayN.ViewModels
}
//move server
private void MoveToGroup(bool c)
{
if (!c)
{
return;
}
if (GetProfileItems(out List<ProfileItem> lstSelecteds) < 0)
{
return;
}
ConfigHandler.MoveToGroup(_config, lstSelecteds, SelectedMoveToGroup.id);
_noticeHandler?.Enqueue(ResUI.OperationSuccess);
RefreshServers();
SelectedMoveToGroup = new();
//Reload();
}
public void MoveServer(EMove eMove)
{
var item = _lstProfile.FirstOrDefault(t => t.indexId == SelectedProfile.indexId);
@@ -1015,6 +1064,17 @@ namespace v2rayN.ViewModels
}
}
public void MoveServerTo(int startIndex, ProfileItemModel targetItem)
{
var targetIndex = _profileItems.IndexOf(targetItem);
if (startIndex >= 0 && targetIndex >= 0 && startIndex != targetIndex)
{
if (ConfigHandler.MoveServer(ref _config, ref _lstProfile, startIndex, EMove.Position, targetIndex) == 0)
{
RefreshServers();
}
}
}
public void ServerSpeedtest(ESpeedActionType actionType)
{
@@ -1027,7 +1087,7 @@ namespace v2rayN.ViewModels
return;
}
//ClearTestResult();
SpeedtestHandler statistics = new SpeedtestHandler(_config, _coreHandler, lstSelecteds, actionType, UpdateSpeedtestHandler);
new SpeedtestHandler(_config, _coreHandler, lstSelecteds, actionType, UpdateSpeedtestHandler);
}
private void Export2ClientConfig()
@@ -1237,6 +1297,11 @@ namespace v2rayN.ViewModels
Reload();
_noticeHandler?.SendMessage(ResUI.MsgUpdateV2rayCoreSuccessfully);
if (File.Exists(fileName))
{
File.Delete(fileName);
}
}
};
(new UpdateHandle()).CheckUpdateCore(type, _config, _updateUI, _config.checkPreReleaseUpdate);

View File

@@ -55,6 +55,7 @@ namespace v2rayN.ViewModels
[Reactive] public bool EnableSecurityProtocolTls13 { get; set; }
[Reactive] public bool AutoHideStartup { get; set; }
[Reactive] public bool EnableCheckPreReleaseUpdate { get; set; }
[Reactive] public bool EnableDragDropSort { get; set; }
[Reactive] public int autoUpdateInterval { get; set; }
[Reactive] public int autoUpdateSubInterval { get; set; }
[Reactive] public int trayMenuServersLimit { get; set; }
@@ -70,6 +71,7 @@ namespace v2rayN.ViewModels
[Reactive] public bool TunStrictRoute { get; set; }
[Reactive] public string TunStack { get; set; }
[Reactive] public int TunMtu { get; set; }
[Reactive] public string TunCustomTemplate { get; set; }
[Reactive] public string TunDirectIP { get; set; }
[Reactive] public string TunDirectProcess { get; set; }
#endregion
@@ -134,6 +136,7 @@ namespace v2rayN.ViewModels
EnableSecurityProtocolTls13 = _config.enableSecurityProtocolTls13;
AutoHideStartup = _config.autoHideStartup;
EnableCheckPreReleaseUpdate = _config.checkPreReleaseUpdate;
EnableDragDropSort = _config.uiItem.enableDragDropSort;
autoUpdateInterval = _config.autoUpdateInterval;
autoUpdateSubInterval = _config.autoUpdateSubInterval;
trayMenuServersLimit = _config.trayMenuServersLimit;
@@ -150,6 +153,7 @@ namespace v2rayN.ViewModels
TunStrictRoute = _config.tunModeItem.strictRoute;
TunStack = _config.tunModeItem.stack;
TunMtu = _config.tunModeItem.mtu;
TunCustomTemplate = _config.tunModeItem.customTemplate;
TunDirectIP = Utils.List2String(_config.tunModeItem.directIP, true);
TunDirectProcess = Utils.List2String(_config.tunModeItem.directProcess, true);
@@ -297,6 +301,7 @@ namespace v2rayN.ViewModels
_config.autoUpdateInterval = autoUpdateInterval;
_config.autoUpdateSubInterval = autoUpdateSubInterval;
_config.checkPreReleaseUpdate = EnableCheckPreReleaseUpdate;
_config.uiItem.enableDragDropSort = EnableDragDropSort;
_config.trayMenuServersLimit = trayMenuServersLimit;
//systemProxy
@@ -308,6 +313,7 @@ namespace v2rayN.ViewModels
_config.tunModeItem.strictRoute = TunStrictRoute;
_config.tunModeItem.stack = TunStack;
_config.tunModeItem.mtu = TunMtu;
_config.tunModeItem.customTemplate = TunCustomTemplate;
_config.tunModeItem.directIP = Utils.String2List(TunDirectIP);
_config.tunModeItem.directProcess = Utils.String2List(TunDirectProcess);

View File

@@ -350,11 +350,12 @@
</StackPanel>
<StackPanel
x:Name="spEnableTun"
Width="auto"
Margin="8,0"
VerticalAlignment="Center"
DockPanel.Dock="Left">
<TextBlock x:Name="txtEnableTun" Text="{x:Static resx:ResUI.TbEnableTunAs}" />
<TextBlock Text="{x:Static resx:ResUI.TbEnableTunAs}" />
<ToggleButton
x:Name="togEnableTun"
Margin="4"
@@ -451,6 +452,23 @@
Height="{StaticResource MenuItemHeight}"
Header="{x:Static resx:ResUI.menuShareServer}" />
<Separator />
<MenuItem
x:Name="menuMoveToGroup"
Height="{StaticResource MenuItemHeight}"
Header="{x:Static resx:ResUI.menuMoveToGroup}">
<MenuItem Height="Auto">
<MenuItem.Header>
<DockPanel>
<ComboBox
x:Name="cmbMoveToGroup"
Width="200"
materialDesign:HintAssist.Hint="{x:Static resx:ResUI.menuSubscription}"
DisplayMemberPath="remarks"
Style="{StaticResource MaterialDesignFilledComboBox}" />
</DockPanel>
</MenuItem.Header>
</MenuItem>
</MenuItem>
<MenuItem
x:Name="menuMoveTop"
Height="{StaticResource MenuItemHeight}"

View File

@@ -1,15 +1,19 @@
using ReactiveUI;
using Splat;
using System.ComponentModel;
using System.Drawing;
using System.Reactive.Disposables;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Controls.Primitives;
using System.Windows.Input;
using System.Windows.Interop;
using System.Windows.Media;
using v2rayN.Handler;
using v2rayN.Mode;
using v2rayN.Resx;
using v2rayN.ViewModels;
using Point = System.Windows.Point;
using SystemInformation = System.Windows.Forms.SystemInformation;
namespace v2rayN.Views
@@ -29,6 +33,14 @@ namespace v2rayN.Views
lstProfiles.PreviewKeyDown += LstProfiles_PreviewKeyDown;
lstProfiles.SelectionChanged += lstProfiles_SelectionChanged;
lstProfiles.LoadingRow += LstProfiles_LoadingRow;
if (_config.uiItem.enableDragDropSort)
{
lstProfiles.AllowDrop = true;
lstProfiles.PreviewMouseLeftButtonDown += LstProfiles_PreviewMouseLeftButtonDown;
lstProfiles.MouseMove += LstProfiles_MouseMove;
lstProfiles.DragEnter += LstProfiles_DragEnter;
lstProfiles.Drop += LstProfiles_Drop;
}
ViewModel = new MainWindowViewModel(MainSnackbar.MessageQueue!, UpdateViewHandler);
Locator.CurrentMutable.RegisterLazySingleton(() => ViewModel, typeof(MainWindowViewModel));
@@ -66,6 +78,9 @@ namespace v2rayN.Views
this.BindCommand(ViewModel, vm => vm.ShareServerCmd, v => v.menuShareServer).DisposeWith(disposables);
//servers move
this.OneWayBind(ViewModel, vm => vm.SubItems, v => v.cmbMoveToGroup.ItemsSource).DisposeWith(disposables);
this.Bind(ViewModel, vm => vm.SelectedMoveToGroup, v => v.cmbMoveToGroup.SelectedItem).DisposeWith(disposables);
this.BindCommand(ViewModel, vm => vm.MoveTopCmd, v => v.menuMoveTop).DisposeWith(disposables);
this.BindCommand(ViewModel, vm => vm.MoveUpCmd, v => v.menuMoveUp).DisposeWith(disposables);
this.BindCommand(ViewModel, vm => vm.MoveDownCmd, v => v.menuMoveDown).DisposeWith(disposables);
@@ -88,8 +103,8 @@ namespace v2rayN.Views
//sub
this.BindCommand(ViewModel, vm => vm.SubSettingCmd, v => v.menuSubSetting).DisposeWith(disposables);
this.BindCommand(ViewModel, vm => vm.SubUpdateCmd, v => v.menuSubUpdate).DisposeWith(disposables);
this.BindCommand(ViewModel, vm => vm.SubGroupUpdateCmd, v => v.menuSubGroupUpdate).DisposeWith(disposables);
this.BindCommand(ViewModel, vm => vm.SubUpdateViaProxyCmd, v => v.menuSubUpdateViaProxy).DisposeWith(disposables);
this.BindCommand(ViewModel, vm => vm.SubGroupUpdateCmd, v => v.menuSubGroupUpdate).DisposeWith(disposables);
this.BindCommand(ViewModel, vm => vm.SubGroupUpdateViaProxyCmd, v => v.menuSubGroupUpdateViaProxy).DisposeWith(disposables);
//setting
@@ -166,8 +181,7 @@ namespace v2rayN.Views
var IsAdministrator = Utils.IsAdministrator();
this.Title = $"{Utils.GetVersion()} - {(IsAdministrator ? ResUI.RunAsAdmin : ResUI.NotRunAsAdmin)}";
togEnableTun.Visibility = IsAdministrator ? Visibility.Visible : Visibility.Hidden;
txtEnableTun.Visibility = IsAdministrator ? Visibility.Visible : Visibility.Hidden;
spEnableTun.Visibility = IsAdministrator ? Visibility.Visible : Visibility.Collapsed;
}
#region Event
@@ -184,6 +198,10 @@ namespace v2rayN.Views
}
}));
}
else if (action == "ProfilesFocus")
{
lstProfiles.Focus();
}
}
private void MainWindow_Closing(object? sender, CancelEventArgs e)
@@ -212,10 +230,10 @@ namespace v2rayN.Views
}
private void LstProfiles_LoadingRow(object? sender, DataGridRowEventArgs e)
{
if (e.Row.GetIndex() == 0)
{
lstProfiles.Focus();
}
//if (e.Row.GetIndex() == 0)
//{
// lstProfiles.Focus();
//}
e.Row.Header = e.Row.GetIndex() + 1;
}
@@ -323,15 +341,15 @@ namespace v2rayN.Views
{
ViewModel?.MoveServer(EMove.Top);
}
else if (e.Key == Key.B)
else if (e.Key == Key.U)
{
ViewModel?.MoveServer(EMove.Up);
}
else if (e.Key == Key.U)
else if (e.Key == Key.D)
{
ViewModel?.MoveServer(EMove.Down);
}
else if (e.Key == Key.D)
else if (e.Key == Key.B)
{
ViewModel?.MoveServer(EMove.Bottom);
}
@@ -365,18 +383,21 @@ namespace v2rayN.Views
{
if (_config.uiItem.mainWidth > 0 && _config.uiItem.mainHeight > 0)
{
if (_config.uiItem.mainWidth > SystemInformation.WorkingArea.Width)
{
_config.uiItem.mainWidth = SystemInformation.WorkingArea.Width * 2 / 3;
}
if (_config.uiItem.mainHeight > SystemInformation.WorkingArea.Height)
{
_config.uiItem.mainHeight = SystemInformation.WorkingArea.Height * 2 / 3;
}
this.Width = _config.uiItem.mainWidth;
this.Height = _config.uiItem.mainHeight;
Width = _config.uiItem.mainWidth;
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;
}
for (int k = 0; k < lstProfiles.Columns.Count; k++)
{
var width = ConfigHandler.GetformMainLvColWidth(ref _config, ((EServerColName)k).ToString(), Convert.ToInt32(lstProfiles.Columns[k].Width.Value));
@@ -426,6 +447,100 @@ namespace v2rayN.Views
#endregion
#region Drag and Drop
private Point startPoint = new Point();
private int startIndex = -1;
private string formatData = "ProfileItemModel";
/// <summary>
/// Helper to search up the VisualTree
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="current"></param>
/// <returns></returns>
private static T? FindAnchestor<T>(DependencyObject current) where T : DependencyObject
{
do
{
if (current is T)
{
return (T)current;
}
current = VisualTreeHelper.GetParent(current);
}
while (current != null);
return null;
}
private void LstProfiles_PreviewMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
// Get current mouse position
startPoint = e.GetPosition(null);
}
private void LstProfiles_MouseMove(object sender, MouseEventArgs e)
{
// Get the current mouse position
Point mousePos = e.GetPosition(null);
Vector diff = startPoint - mousePos;
if (e.LeftButton == MouseButtonState.Pressed &&
(Math.Abs(diff.X) > SystemParameters.MinimumHorizontalDragDistance ||
Math.Abs(diff.Y) > SystemParameters.MinimumVerticalDragDistance))
{
// Get the dragged Item
var listView = sender as DataGrid;
if (listView == null) return;
var listViewItem = FindAnchestor<DataGridRow>((DependencyObject)e.OriginalSource);
if (listViewItem == null) return; // Abort
// Find the data behind the ListViewItem
ProfileItemModel item = (ProfileItemModel)listView.ItemContainerGenerator.ItemFromContainer(listViewItem);
if (item == null) return; // Abort
// Initialize the drag & drop operation
startIndex = lstProfiles.SelectedIndex;
DataObject dragData = new DataObject(formatData, item);
DragDrop.DoDragDrop(listViewItem, dragData, DragDropEffects.Copy | DragDropEffects.Move);
}
}
private void LstProfiles_DragEnter(object sender, DragEventArgs e)
{
if (!e.Data.GetDataPresent(formatData) || sender != e.Source)
{
e.Effects = DragDropEffects.None;
}
}
private void LstProfiles_Drop(object sender, DragEventArgs e)
{
if (e.Data.GetDataPresent(formatData) && sender == e.Source)
{
// Get the drop Item destination
var listView = sender as DataGrid;
if (listView == null) return;
var listViewItem = FindAnchestor<DataGridRow>((DependencyObject)e.OriginalSource);
if (listViewItem == null)
{
// Abort
e.Effects = DragDropEffects.None;
return;
}
// Find the data behind the Item
ProfileItemModel item = (ProfileItemModel)listView.ItemContainerGenerator.ItemFromContainer(listViewItem);
if (item == null) return;
// Move item into observable collection
// (this will be automatically reflected to lstView.ItemsSource)
e.Effects = DragDropEffects.Move;
ViewModel?.MoveServerTo(startIndex, item);
startIndex = -1;
}
}
#endregion
}
}

View File

@@ -415,6 +415,7 @@
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
@@ -553,16 +554,30 @@
Margin="{StaticResource SettingItemMargin}"
VerticalAlignment="Center"
Style="{StaticResource ToolbarTextBlock}"
Text="{x:Static resx:ResUI.TbSettingsEnableDragDropSort}" />
<ToggleButton
x:Name="togEnableDragDropSort"
Grid.Row="10"
Grid.Column="1"
Margin="{StaticResource SettingItemMargin}"
HorizontalAlignment="Left" />
<TextBlock
Grid.Row="11"
Grid.Column="0"
Margin="{StaticResource SettingItemMargin}"
VerticalAlignment="Center"
Style="{StaticResource ToolbarTextBlock}"
Text="{x:Static resx:ResUI.TbSettingsAutoUpdateInterval}" />
<TextBox
x:Name="txtautoUpdateInterval"
Grid.Row="10"
Grid.Row="11"
Grid.Column="1"
Width="200"
Margin="{StaticResource SettingItemMargin}" />
<TextBlock
Grid.Row="11"
Grid.Row="12"
Grid.Column="0"
Margin="{StaticResource SettingItemMargin}"
VerticalAlignment="Center"
@@ -570,13 +585,13 @@
Text="{x:Static resx:ResUI.TbSettingsAutoUpdate}" />
<TextBox
x:Name="txtautoUpdateSubInterval"
Grid.Row="11"
Grid.Row="12"
Grid.Column="1"
Width="200"
Margin="{StaticResource SettingItemMargin}" />
<TextBlock
Grid.Row="12"
Grid.Row="13"
Grid.Column="0"
Margin="{StaticResource SettingItemMargin}"
VerticalAlignment="Center"
@@ -584,7 +599,7 @@
Text="{x:Static resx:ResUI.TbSettingsTrayMenuServersLimit}" />
<TextBox
x:Name="txttrayMenuServersLimit"
Grid.Row="12"
Grid.Row="13"
Grid.Column="1"
Width="200"
Margin="{StaticResource SettingItemMargin}" />
@@ -646,6 +661,7 @@
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<TextBlock
@@ -688,7 +704,8 @@
Grid.Row="3"
Grid.Column="1"
Width="200"
Margin="{StaticResource SettingItemMargin}" />
Margin="{StaticResource SettingItemMargin}"
HorizontalAlignment="Left" />
<TextBlock
Grid.Row="4"
@@ -702,7 +719,34 @@
Grid.Row="4"
Grid.Column="1"
Width="200"
Margin="{StaticResource SettingItemMargin}" />
Margin="{StaticResource SettingItemMargin}"
HorizontalAlignment="Left" />
<TextBlock
Grid.Row="5"
Grid.Column="0"
Margin="{StaticResource SettingItemMargin}"
VerticalAlignment="Center"
Style="{StaticResource ToolbarTextBlock}"
Text="{x:Static resx:ResUI.TbSettingsTunModeCustomTemplate}" />
<TextBox
x:Name="txtCustomTemplate"
Grid.Row="5"
Grid.Column="1"
Width="600"
Margin="{StaticResource SettingItemMargin}"
VerticalAlignment="Top"
AcceptsReturn="True"
TextWrapping="Wrap" />
<Button
x:Name="btnBrowse"
Grid.Row="5"
Grid.Column="2"
Width="100"
Margin="2,0,8,0"
Click="btnBrowse_Click"
Content="{x:Static resx:ResUI.TbBrowse}"
Style="{StaticResource DefButton}" />
</Grid>
<Grid Margin="{StaticResource SettingItemMargin}">

View File

@@ -87,6 +87,7 @@ namespace v2rayN.Views
this.Bind(ViewModel, vm => vm.EnableSecurityProtocolTls13, v => v.togEnableSecurityProtocolTls13.IsChecked).DisposeWith(disposables);
this.Bind(ViewModel, vm => vm.AutoHideStartup, v => v.togAutoHideStartup.IsChecked).DisposeWith(disposables);
this.Bind(ViewModel, vm => vm.EnableCheckPreReleaseUpdate, v => v.togEnableCheckPreReleaseUpdate.IsChecked).DisposeWith(disposables);
this.Bind(ViewModel, vm => vm.EnableDragDropSort, v => v.togEnableDragDropSort.IsChecked).DisposeWith(disposables);
this.Bind(ViewModel, vm => vm.autoUpdateInterval, v => v.txtautoUpdateInterval.Text).DisposeWith(disposables);
this.Bind(ViewModel, vm => vm.autoUpdateSubInterval, v => v.txtautoUpdateSubInterval.Text).DisposeWith(disposables);
this.Bind(ViewModel, vm => vm.trayMenuServersLimit, v => v.txttrayMenuServersLimit.Text).DisposeWith(disposables);
@@ -100,6 +101,7 @@ namespace v2rayN.Views
this.Bind(ViewModel, vm => vm.TunStrictRoute, v => v.togStrictRoute.IsChecked).DisposeWith(disposables);
this.Bind(ViewModel, vm => vm.TunStack, v => v.cmbStack.Text).DisposeWith(disposables);
this.Bind(ViewModel, vm => vm.TunMtu, v => v.cmbMtu.Text).DisposeWith(disposables);
this.Bind(ViewModel, vm => vm.TunCustomTemplate, v => v.txtCustomTemplate.Text).DisposeWith(disposables);
this.Bind(ViewModel, vm => vm.TunDirectIP, v => v.txtDirectIP.Text).DisposeWith(disposables);
this.Bind(ViewModel, vm => vm.TunDirectProcess, v => v.txtDirectProcess.Text).DisposeWith(disposables);
@@ -124,6 +126,13 @@ namespace v2rayN.Views
{
this.Close();
}
private void btnBrowse_Click(object sender, System.Windows.RoutedEventArgs e)
{
var openFileDialog1 = new System.Windows.Forms.OpenFileDialog();
openFileDialog1.Filter = "tunConfig|*.json|All|*.*";
openFileDialog1.ShowDialog();
txtCustomTemplate.Text = openFileDialog1.FileName;
}
}
}

View File

@@ -11,6 +11,7 @@ namespace v2rayN.Views
public RoutingSettingWindow()
{
InitializeComponent();
this.Closing += RoutingSettingWindow_Closing;
this.PreviewKeyDown += RoutingSettingWindow_PreviewKeyDown;
lstRoutings.SelectionChanged += lstRoutings_SelectionChanged;
lstRoutings.MouseDoubleClick += LstRoutings_MouseDoubleClick;
@@ -61,6 +62,14 @@ namespace v2rayN.Views
});
}
private void RoutingSettingWindow_Closing(object? sender, System.ComponentModel.CancelEventArgs e)
{
if (ViewModel?.IsModified == true)
{
this.DialogResult = true;
}
}
private void RoutingSettingWindow_PreviewKeyDown(object sender, KeyEventArgs e)
{
if (Keyboard.IsKeyDown(Key.LeftCtrl) || Keyboard.IsKeyDown(Key.RightCtrl))

View File

@@ -1,4 +1,5 @@
using ReactiveUI;
using System.ComponentModel;
using System.Reactive.Disposables;
using System.Windows.Input;
using v2rayN.ViewModels;
@@ -12,6 +13,7 @@ namespace v2rayN.Views
InitializeComponent();
ViewModel = new SubSettingViewModel(this);
this.Closing += SubSettingWindow_Closing;
lstSubscription.MouseDoubleClick += LstSubscription_MouseDoubleClick;
this.WhenActivated(disposables =>
@@ -27,6 +29,14 @@ namespace v2rayN.Views
});
}
private void SubSettingWindow_Closing(object? sender, CancelEventArgs e)
{
if (ViewModel?.IsModified == true)
{
this.DialogResult = true;
}
}
private void LstSubscription_MouseDoubleClick(object sender, MouseButtonEventArgs e)
{
ViewModel?.EditSub(false);

View File

@@ -9,7 +9,7 @@
<ImplicitUsings>enable</ImplicitUsings>
<ApplicationIcon>v2rayN.ico</ApplicationIcon>
<Copyright>Copyright © 2017-2023 (GPLv3)</Copyright>
<FileVersion>6.1</FileVersion>
<FileVersion>6.6</FileVersion>
</PropertyGroup>
<ItemGroup>