Compare commits

..

117 Commits
6.2 ... 6.13

Author SHA1 Message Date
2dust
aac2b4aaf0 up 6.13 2023-02-19 15:44:52 +08:00
2dust
fe070b306f Merge pull request #3309 from ilyfairy/master
改为可空类型, 简化代码
2023-02-19 15:33:25 +08:00
2dust
ecfadf8a23 Merge branch 'master' into master 2023-02-19 15:23:04 +08:00
2dust
653af71596 Add log switch in tun mode 2023-02-19 14:55:44 +08:00
小仙女
6a89be2e89 简化代码 2023-02-19 13:34:22 +08:00
小仙女
b84bad4e1a 改为可空类型 2023-02-19 12:18:08 +08:00
2dust
0f8d86f081 Refactoring sorting and delayed storage 2023-02-19 11:23:45 +08:00
2dust
d44f311ba1 Refactoring sorting and delayed storage 2023-02-19 10:43:42 +08:00
2dust
6f5428ca61 Merge pull request #3306 from Weltolk/master
语句更通顺
2023-02-19 09:59:47 +08:00
2dust
b0bee3ca1a Merge pull request #3305 from ilyfairy/master
优化, 改成使用语法糖
2023-02-19 09:59:30 +08:00
2dust
7908194d27 Merge pull request #3301 from meaqese/add-russian-language
full-russian-support
2023-02-18 20:07:57 +08:00
小仙女
b27c7fb2dd string.Join的第二个参数(List<string>)改成ToArray 2023-02-17 22:06:17 +08:00
小仙女
a23cb95a10 性能优化 2023-02-17 15:17:01 +08:00
小仙女
fc137f9b1c 语句更通顺 2023-02-17 15:09:26 +08:00
Weltolk
84780bf9ef Update ResUI.zh-Hans.resx 2023-02-17 14:39:59 +08:00
小仙女
1321037c52 优化, 改成使用语法糖 2023-02-17 14:36:28 +08:00
meaqese
de1da12d45 full-russian-support 2023-02-17 03:18:41 +03:00
2dust
6d4cbacd50 GenerateSatelliteAssembliesForCore 2023-02-15 20:48:56 +08:00
2dust
bf9f7ca990 Adjust the group style 2023-02-15 20:47:17 +08:00
2dust
ca334104d7 bug fixes 2023-02-15 20:37:51 +08:00
2dust
c3e00ba31b bug fixes 2023-02-15 20:37:27 +08:00
2dust
ea3a9cc70e ShowInTaskbar = false 2023-02-15 20:36:50 +08:00
2dust
7ad22e0a73 up 6.12 2023-02-12 20:54:41 +08:00
2dust
ca1abb58eb Add subscription update multiple update function 2023-02-12 20:42:10 +08:00
2dust
3e353944b2 Update App.xaml 2023-02-12 20:41:06 +08:00
2dust
007a250f55 up 6.11 2023-02-12 08:54:23 +08:00
2dust
e9bb6a9951 bug fixes 2023-02-12 08:53:28 +08:00
2dust
82f236e07b up 6.10 2023-02-11 20:03:54 +08:00
2dust
17bfe74ecf Add routing sort 2023-02-11 19:34:15 +08:00
2dust
b77827df90 Update v2rayN.csproj 2023-02-10 21:02:41 +08:00
2dust
a359a508ae fix Import old config 2023-02-10 21:02:29 +08:00
2dust
3a740118f0 Adjust task service settings 2023-02-10 18:58:20 +08:00
2dust
58d9bcbd14 tidy code github 2023-02-10 16:25:16 +08:00
2dust
24be7b2180 store msg filter 2023-02-10 16:01:47 +08:00
2dust
f4c9ca8dff Refactor routing basic settings 2023-02-10 14:51:00 +08:00
2dust
9b8181b72b Refactor gui settings 2023-02-10 14:36:37 +08:00
2dust
1ff1962425 Refactor basic settings 2023-02-10 14:16:59 +08:00
2dust
9b05736746 Add environment variables to geo files 2023-02-10 11:22:03 +08:00
2dust
dec722e693 Update UpdateHandle.cs 2023-02-10 11:05:11 +08:00
2dust
49fa0a4c67 DownloadStringAsyncOri 2023-02-10 11:04:57 +08:00
2dust
0cdc69e1e8 Update MsgView.xaml 2023-02-10 09:39:18 +08:00
2dust
0494cc4ce7 adjust group style 2023-02-09 16:43:50 +08:00
2dust
30d82947d6 fix 2023-02-09 15:17:52 +08:00
2dust
ec59249d79 Optimize file download 2023-02-09 14:54:54 +08:00
2dust
7eb869ab1d Optimize file download 2023-02-09 10:54:31 +08:00
2dust
d014724a2d Optimize speed test 2023-02-08 19:20:44 +08:00
2dust
dfb6cef364 Update OptionSettingWindow.xaml.cs 2023-02-08 15:07:23 +08:00
2dust
0ebf8c9349 Optimize Font size 2023-02-07 19:05:49 +08:00
2dust
9dfd89c90d up 6.9 2023-02-06 19:28:43 +08:00
2dust
f6972125cd Update tun_singbox 2023-02-06 19:19:36 +08:00
2dust
6e366bf55a Improved enhanced tun mode 2023-02-06 15:29:10 +08:00
2dust
5e2e45c673 Merge branch 'master' of https://github.com/2dust/v2rayN 2023-02-05 20:17:07 +08:00
2dust
f879235564 fix get Win32FamilyNames 2023-02-05 20:17:03 +08:00
2dust
b00aee2ae7 Merge pull request #3187 from saphirique/patch-1
Add russian language
2023-02-05 19:57:08 +08:00
saphirique
28c2159ec3 add russian language 2023-02-05 17:55:24 +08:00
2dust
33dcef2285 Optimize Update Subscription 2023-02-04 18:52:17 +08:00
2dust
b9acd0ec28 Font size custom 2023-02-04 15:43:49 +08:00
2dust
7989d5180b adjust style 2023-02-04 14:25:21 +08:00
2dust
238086942e change fonts folder 2023-02-04 12:50:38 +08:00
2dust
a704a30242 up 6.8 2023-02-03 20:03:21 +08:00
2dust
26dd0d0ea5 add more PresetFingerprints 2023-02-03 09:45:21 +08:00
2dust
e31a4bcaa9 share link to add fingerprint 2023-02-03 09:39:39 +08:00
2dust
1722dc570b Modified the tun mode configuration template 2023-02-03 08:59:28 +08:00
2dust
3575e69b43 Tun mode can be auto turned on at startup 2023-02-02 16:27:35 +08:00
2dust
373d89874c Add custom font settings 2023-02-02 13:51:58 +08:00
2dust
976087ce97 Merge pull request #3165 from DanielBlackBeard/master
add more Farsi Translation
2023-02-02 10:51:21 +08:00
2dust
69a45788ee Merge pull request #3154 from mojpangr26/dev
增加自定义UA
2023-02-02 10:51:03 +08:00
mojpangr26
92e4de12fb 修改可编辑cmb
增加提示
2023-02-02 09:41:23 +08:00
Persian Prince
ea7fdb9b3d add more Farsi Translation 2023-02-01 21:40:26 +03:30
mojpangr26
fe1c043b8e 自定义UA 2023-02-01 17:07:36 +08:00
2dust
146f597a0b Fix the problem after clicking to sort and drag 2023-02-01 15:23:17 +08:00
2dust
d2bef312ce Add default fingerprint settings 2023-02-01 11:24:45 +08:00
2dust
61f297215d Optimize remove server 2023-02-01 11:08:05 +08:00
2dust
639a9fd540 Add test completion prompt 2023-02-01 10:06:19 +08:00
2dust
3d0428c518 add info filter the preset value 2023-02-01 09:53:37 +08:00
2dust
f40f926ce1 up 6.7 2023-01-31 19:24:55 +08:00
2dust
d6db4f0e4c Add double-click server as active parameter 2023-01-31 16:08:26 +08:00
2dust
fcbc9471aa add edit server menu 2023-01-31 14:33:17 +08:00
2dust
b147e05794 bug fix 2023-01-31 14:13:25 +08:00
2dust
47e6eb546d Optimize speed test info 2023-01-31 14:05:31 +08:00
2dust
8ba05cb4ed Replace the font with Source Han Sans CN 2023-01-31 13:34:32 +08:00
2dust
84b91e9649 Fix activity node display 2023-01-31 13:25:52 +08:00
2dust
703e17478d fix speed test url 2023-01-31 12:55:19 +08:00
2dust
8584e15c32 Optimize Sort as delay 2023-01-30 15:30:48 +08:00
2dust
46be7aadab Add refresh switch to information window 2023-01-30 14:44:49 +08:00
2dust
a5871f6cba memory log window size 2023-01-30 14:06:18 +08:00
2dust
917dc1803c Optimize custom configuration 2023-01-30 13:16:48 +08:00
2dust
c0c0961b2b Increase list line spacing 2023-01-30 12:30:04 +08:00
2dust
0995ac6f9a fix rules setting key 2023-01-30 12:27:41 +08:00
2dust
b7f40e4cbf Increase the Margin of qrcode 2023-01-30 11:18:01 +08:00
2dust
754cbb9eaa fix allowInsecure bug 2023-01-30 09:53:04 +08:00
2dust
7052b56069 Optimize font 2023-01-30 09:36:27 +08:00
2dust
decdee825b Merge pull request #3107 from buiawpkgew1/patch-1
修改hysteria 官网
2023-01-28 16:08:44 +08:00
菾凴
5f66afc399 修改hysteria 官网
https://github.com/2dust/v2rayN/issues/3094
2023-01-20 21:44:54 +08:00
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
71 changed files with 4570 additions and 1582 deletions

View File

@@ -2,6 +2,7 @@
x:Class="v2rayN.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:conv="clr-namespace:v2rayN.Converters"
xmlns:local="clr-namespace:v2rayN"
xmlns:materialDesign="http://materialdesigninxaml.net/winfx/xaml/themes"
ShutdownMode="OnExplicitShutdown"
@@ -16,6 +17,10 @@
<ResourceDictionary Source="pack://application:,,,/MaterialDesignThemes.Wpf;component/Themes/MaterialDesignTheme.Defaults.xaml" />
</ResourceDictionary.MergedDictionaries>
<system:Double x:Key="MenuItemHeight">26</system:Double>
<system:Double x:Key="StdFontSize">12</system:Double>
<system:Double x:Key="StdFontSize1">13</system:Double>
<system:Double x:Key="StdFontSize2">14</system:Double>
<system:Double x:Key="StdFontSizeMsg">11</system:Double>
<Thickness
x:Key="ServerItemMargin"
Bottom="4"
@@ -32,19 +37,19 @@
x:Key="ModuleTitle"
BasedOn="{StaticResource MaterialDesignTextBlock}"
TargetType="{x:Type TextBlock}">
<Setter Property="FontSize" Value="16" />
<Setter Property="FontSize" Value="{DynamicResource StdFontSize2}" />
</Style>
<Style
x:Key="ToolbarTextBlock"
BasedOn="{StaticResource MaterialDesignTextBlock}"
TargetType="{x:Type TextBlock}">
<Setter Property="FontSize" Value="12" />
<Setter Property="FontSize" Value="{DynamicResource StdFontSize}" />
</Style>
<Style
x:Key="StatusbarItem"
BasedOn="{StaticResource MaterialDesignTextBlock}"
TargetType="{x:Type TextBlock}">
<Setter Property="FontSize" Value="12" />
<Setter Property="FontSize" Value="{DynamicResource StdFontSize}" />
<Setter Property="Padding" Value="0" />
</Style>
<Style TargetType="{x:Type TextElement}">
@@ -57,7 +62,7 @@
</Style>
<Style x:Key="lvItemSelected" TargetType="{x:Type ListViewItem}">
<Setter Property="Height" Value="20" />
<Setter Property="FontSize" Value="12" />
<Setter Property="FontSize" Value="{DynamicResource StdFontSize}" />
<Style.Triggers>
<Trigger Property="IsSelected" Value="true">
<Setter Property="Background" Value="{DynamicResource PrimaryHueLightBrush}" />
@@ -75,44 +80,69 @@
x:Key="ListItemCheckBox"
BasedOn="{StaticResource MaterialDesignUserForegroundCheckBox}"
TargetType="{x:Type CheckBox}">
<Setter Property="FontSize" Value="12" />
</Style>
<Style x:Key="ListItemChip" TargetType="{x:Type materialDesign:Chip}">
<Setter Property="FontSize" Value="11" />
<Setter Property="FontSize" Value="{DynamicResource StdFontSize}" />
</Style>
<Style
x:Key="DefButton"
BasedOn="{StaticResource MaterialDesignRaisedButton}"
TargetType="{x:Type ButtonBase}">
<Setter Property="FontSize" Value="14" />
<Setter Property="FontSize" Value="{DynamicResource StdFontSize1}" />
</Style>
<Style
x:Key="DefContextMenu"
BasedOn="{StaticResource MaterialDesignContextMenu}"
TargetType="{x:Type ContextMenu}">
<Setter Property="FontSize" Value="13" />
<Setter Property="FontSize" Value="{DynamicResource StdFontSize1}" />
<Setter Property="FontFamily" Value="{x:Static conv:MaterialDesignFonts.MyFont}" />
</Style>
<Style
x:Key="ToolbarMenu"
BasedOn="{StaticResource MaterialDesignMenu}"
TargetType="{x:Type Menu}">
<Setter Property="FontSize" Value="13" />
<Setter Property="FontSize" Value="{DynamicResource StdFontSize1}" />
<Setter Property="FontFamily" Value="{x:Static conv:MaterialDesignFonts.MyFont}" />
</Style>
<Style
x:Key="DefComboBox"
BasedOn="{StaticResource MaterialDesignComboBox}"
TargetType="{x:Type ComboBox}">
<Setter Property="FontSize" Value="12" />
<Setter Property="FontSize" Value="{DynamicResource StdFontSize}" />
<Setter Property="HorizontalAlignment" Value="Left" />
</Style>
<Style
x:Key="DefDataGrid"
BasedOn="{StaticResource MaterialDesignDataGrid}"
TargetType="{x:Type DataGrid}">
<Setter Property="FontSize" Value="12" />
<Setter Property="FontSize" Value="{DynamicResource StdFontSize}" />
</Style>
<Style
x:Key="DefTextBox"
BasedOn="{StaticResource MaterialDesignTextBox}"
TargetType="{x:Type TextBox}">
<Setter Property="FontSize" Value="{DynamicResource StdFontSize}" />
</Style>
<Style
x:Key="MyOutlinedTextBox"
BasedOn="{StaticResource MaterialDesignOutlinedTextBox}"
TargetType="{x:Type TextBox}">
<Setter Property="FontSize" Value="{DynamicResource StdFontSize}" />
</Style>
<Style
x:Key="MyGroupBox"
BasedOn="{StaticResource MaterialDesignGroupBox}"
TargetType="{x:Type GroupBox}">
<Setter Property="FontSize" Value="{DynamicResource StdFontSize}" />
</Style>
<Style
x:Key="MyChipListBoxItem"
BasedOn="{StaticResource MaterialDesignChoiceChipPrimaryOutlineListBoxItem}"
TargetType="{x:Type ListBoxItem}">
<Setter Property="Margin" Value="-2,0" />
</Style>
</ResourceDictionary>
</Application.Resources>

View File

@@ -0,0 +1,187 @@
using Downloader;
using System.IO;
using System.Net;
namespace v2rayN.Base
{
internal class DownloaderHelper
{
private static readonly Lazy<DownloaderHelper> _instance = new(() => new());
public static DownloaderHelper Instance => _instance.Value;
public async Task<string?> DownloadStringAsync(IWebProxy webProxy, string url, string? userAgent, int timeout)
{
if (string.IsNullOrEmpty(url))
{
return null;
}
var cancellationToken = new CancellationTokenSource();
cancellationToken.CancelAfter(timeout * 1000);
Uri uri = new(url);
//Authorization Header
var headers = new WebHeaderCollection();
if (!Utils.IsNullOrEmpty(uri.UserInfo))
{
headers.Add(HttpRequestHeader.Authorization, "Basic " + Utils.Base64Encode(uri.UserInfo));
}
var downloadOpt = new DownloadConfiguration()
{
Timeout = timeout * 1000,
MaxTryAgainOnFailover = 2,
RequestConfiguration =
{
Headers = headers,
UserAgent = userAgent,
Timeout = timeout * 1000,
Proxy = webProxy
}
};
using var downloader = new DownloadService(downloadOpt);
downloader.DownloadFileCompleted += (sender, value) =>
{
if (value.Error != null)
{
throw new Exception(string.Format("{0}", value.Error.Message));
}
};
using var stream = await downloader.DownloadFileTaskAsync(address: url, cancellationToken: cancellationToken.Token);
using StreamReader reader = new(stream);
downloadOpt = null;
return reader.ReadToEnd();
}
public async Task DownloadDataAsync4Speed(IWebProxy webProxy, string url, IProgress<string> progress, int timeout)
{
if (string.IsNullOrEmpty(url))
{
throw new ArgumentNullException(nameof(url));
}
var cancellationToken = new CancellationTokenSource();
cancellationToken.CancelAfter(timeout * 1000);
var downloadOpt = new DownloadConfiguration()
{
Timeout = timeout * 1000,
MaxTryAgainOnFailover = 2,
RequestConfiguration =
{
Timeout= timeout * 1000,
Proxy = webProxy
}
};
DateTime totalDatetime = DateTime.Now;
int totalSecond = 0;
var hasValue = false;
double maxSpeed = 0;
using var downloader = new DownloadService(downloadOpt);
//downloader.DownloadStarted += (sender, value) =>
//{
// if (progress != null)
// {
// progress.Report("Start download data...");
// }
//};
downloader.DownloadProgressChanged += (sender, value) =>
{
TimeSpan ts = (DateTime.Now - totalDatetime);
if (progress != null && ts.Seconds > totalSecond)
{
hasValue = true;
totalSecond = ts.Seconds;
if (value.BytesPerSecondSpeed > maxSpeed)
{
maxSpeed = value.BytesPerSecondSpeed;
var speed = (maxSpeed / 1000 / 1000).ToString("#0.0");
progress.Report(speed);
}
}
};
downloader.DownloadFileCompleted += (sender, value) =>
{
if (progress != null)
{
if (!hasValue && value.Error != null)
{
progress.Report(value.Error?.Message);
}
}
};
progress.Report("......");
await downloader.DownloadFileTaskAsync(address: url, cancellationToken: cancellationToken.Token);
downloadOpt = null;
}
public async Task DownloadFileAsync(IWebProxy webProxy, string url, string fileName, IProgress<double> progress, int timeout)
{
if (string.IsNullOrEmpty(url))
{
throw new ArgumentNullException(nameof(url));
}
if (string.IsNullOrEmpty(fileName))
{
throw new ArgumentNullException(nameof(fileName));
}
if (File.Exists(fileName))
{
File.Delete(fileName);
}
var cancellationToken = new CancellationTokenSource();
cancellationToken.CancelAfter(timeout * 1000);
var downloadOpt = new DownloadConfiguration()
{
Timeout = timeout * 1000,
MaxTryAgainOnFailover = 2,
RequestConfiguration =
{
Timeout= timeout * 1000,
Proxy = webProxy
}
};
var progressPercentage = 0;
var hasValue = false;
using var downloader = new DownloadService(downloadOpt);
downloader.DownloadStarted += (sender, value) =>
{
progress?.Report(0);
};
downloader.DownloadProgressChanged += (sender, value) =>
{
hasValue = true;
var percent = (int)value.ProgressPercentage;// Convert.ToInt32((totalRead * 1d) / (total * 1d) * 100);
if (progressPercentage != percent && percent % 10 == 0)
{
progressPercentage = percent;
progress.Report(percent);
}
};
downloader.DownloadFileCompleted += (sender, value) =>
{
if (progress != null)
{
if (hasValue && value.Error == null)
{
progress.Report(101);
}
}
};
await downloader.DownloadFileTaskAsync(url, fileName, cancellationToken: cancellationToken.Token);
downloadOpt = null;
}
}
}

View File

@@ -26,14 +26,14 @@ namespace v2rayN.Base
}
else
{
HttpClientHelper httpClientHelper = new HttpClientHelper();
HttpClientHelper httpClientHelper = new();
HttpClientHandler handler = new HttpClientHandler() { UseCookies = false };
HttpClientHandler handler = new() { UseCookies = false };
httpClientHelper.httpClient = new HttpClient(handler);
return httpClientHelper;
}
}
public async Task<string> GetAsync(string url)
public async Task<string?> GetAsync(string url)
{
if (string.IsNullOrEmpty(url))
{
@@ -43,7 +43,7 @@ namespace v2rayN.Base
return await response.Content.ReadAsStringAsync();
}
public async Task<string> GetAsync(HttpClient client, string url, CancellationToken token)
public async Task<string?> GetAsync(HttpClient client, string url, CancellationToken token)
{
if (string.IsNullOrEmpty(url))
{
@@ -54,7 +54,7 @@ namespace v2rayN.Base
{
throw new Exception(string.Format("{0}", response.StatusCode));
}
return await response.Content.ReadAsStringAsync();
return await response.Content.ReadAsStringAsync(token);
}
public async Task PutAsync(string url, Dictionary<string, string> headers)
@@ -71,11 +71,11 @@ namespace v2rayN.Base
{
if (string.IsNullOrEmpty(url))
{
throw new ArgumentNullException("url");
throw new ArgumentNullException(nameof(url));
}
if (string.IsNullOrEmpty(fileName))
{
throw new ArgumentNullException("fileName");
throw new ArgumentNullException(nameof(fileName));
}
if (File.Exists(fileName))
{
@@ -89,56 +89,51 @@ namespace v2rayN.Base
throw new Exception(string.Format("{0}", response.StatusCode));
}
var total = response.Content.Headers.ContentLength.HasValue ? response.Content.Headers.ContentLength.Value : -1L;
var total = response.Content.Headers.ContentLength ?? -1L;
var canReportProgress = total != -1 && progress != null;
using (var stream = await response.Content.ReadAsStreamAsync())
using var stream = await response.Content.ReadAsStreamAsync(token);
using var file = File.Create(fileName);
var totalRead = 0L;
var buffer = new byte[1024 * 1024];
var isMoreToRead = true;
var progressPercentage = 0;
do
{
using (var file = File.Create(fileName))
token.ThrowIfCancellationRequested();
var read = await stream.ReadAsync(buffer, token);
if (read == 0)
{
var totalRead = 0L;
var buffer = new byte[1024 * 1024];
var isMoreToRead = true;
var progressPercentage = 0;
isMoreToRead = false;
}
else
{
var data = new byte[read];
buffer.ToList().CopyTo(0, data, 0, read);
do
{
token.ThrowIfCancellationRequested();
// TODO: put here the code to write the file to disk
file.Write(data, 0, read);
var read = await stream.ReadAsync(buffer, 0, buffer.Length, token);
totalRead += read;
if (read == 0)
{
isMoreToRead = false;
}
else
{
var data = new byte[read];
buffer.ToList().CopyTo(0, data, 0, read);
// TODO: put here the code to write the file to disk
file.Write(data, 0, read);
totalRead += read;
if (canReportProgress)
{
var percent = Convert.ToInt32((totalRead * 1d) / (total * 1d) * 100);
if (progressPercentage != percent && percent % 10 == 0)
{
progressPercentage = percent;
progress.Report(percent);
}
}
}
} while (isMoreToRead);
file.Close();
if (canReportProgress)
{
progress.Report(101);
var percent = Convert.ToInt32((totalRead * 1d) / (total * 1d) * 100);
if (progressPercentage != percent && percent % 10 == 0)
{
progressPercentage = percent;
progress.Report(percent);
}
}
}
} while (isMoreToRead);
if (canReportProgress)
{
progress.Report(101);
}
}
@@ -146,7 +141,7 @@ namespace v2rayN.Base
{
if (string.IsNullOrEmpty(url))
{
throw new ArgumentNullException("url");
throw new ArgumentNullException(nameof(url));
}
var response = await client.GetAsync(url, HttpCompletionOption.ResponseHeadersRead, token);
@@ -159,57 +154,55 @@ namespace v2rayN.Base
//var total = response.Content.Headers.ContentLength.HasValue ? response.Content.Headers.ContentLength.Value : -1L;
//var canReportProgress = total != -1 && progress != null;
using (var stream = await response.Content.ReadAsStreamAsync())
using var stream = await response.Content.ReadAsStreamAsync(token);
var totalRead = 0L;
var buffer = new byte[1024 * 64];
var isMoreToRead = true;
string progressSpeed = string.Empty;
DateTime totalDatetime = DateTime.Now;
int totalSecond = 0;
do
{
var totalRead = 0L;
var buffer = new byte[1024 * 64];
var isMoreToRead = true;
string progressSpeed = string.Empty;
DateTime totalDatetime = DateTime.Now;
int totalSecond = 0;
do
if (token.IsCancellationRequested)
{
if (token.IsCancellationRequested)
if (totalRead > 0)
{
if (totalRead > 0)
{
return;
}
else
{
token.ThrowIfCancellationRequested();
}
}
var read = await stream.ReadAsync(buffer, 0, buffer.Length, token);
if (read == 0)
{
isMoreToRead = false;
return;
}
else
{
var data = new byte[read];
buffer.ToList().CopyTo(0, data, 0, read);
token.ThrowIfCancellationRequested();
}
}
// TODO:
totalRead += read;
var read = await stream.ReadAsync(buffer, token);
TimeSpan ts = (DateTime.Now - totalDatetime);
if (progress != null && ts.Seconds > totalSecond)
if (read == 0)
{
isMoreToRead = false;
}
else
{
var data = new byte[read];
buffer.ToList().CopyTo(0, data, 0, read);
// TODO:
totalRead += read;
TimeSpan ts = (DateTime.Now - totalDatetime);
if (progress != null && ts.Seconds > totalSecond)
{
totalSecond = ts.Seconds;
var speed = (totalRead * 1d / ts.TotalMilliseconds / 1000).ToString("#0.0");
if (progressSpeed != speed)
{
totalSecond = ts.Seconds;
var speed = (totalRead * 1d / ts.TotalMilliseconds / 1000).ToString("#0.0");
if (progressSpeed != speed)
{
progressSpeed = speed;
progress.Report(speed);
}
progressSpeed = speed;
progress.Report(speed);
}
}
} while (isMoreToRead);
}
}
} while (isMoreToRead);
}
}

View File

@@ -6,7 +6,7 @@ namespace v2rayN.Base
{
public sealed class SqliteHelper
{
private static readonly Lazy<SqliteHelper> _instance = new Lazy<SqliteHelper>(() => new());
private static readonly Lazy<SqliteHelper> _instance = new(() => new());
public static SqliteHelper Instance => _instance.Value;
private string _connstr;
public SQLiteConnection _db;

View File

@@ -34,7 +34,7 @@ namespace v2rayN.Base
public static IEnumerable<string> NonWhiteSpaceLines(this TextReader reader)
{
string line;
string? line;
while ((line = reader.ReadLine()) != null)
{
if (line.IsWhiteSpace()) continue;

View File

@@ -17,7 +17,7 @@ namespace v2rayN.Converters
return new SolidColorBrush(Colors.IndianRed);
}
public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
public object? ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
return null;
}

View File

@@ -0,0 +1,27 @@
using System.Windows.Media;
using v2rayN.Handler;
namespace v2rayN.Converters
{
public class MaterialDesignFonts
{
public static FontFamily MyFont { get; }
static MaterialDesignFonts()
{
try
{
var fontFamily = LazyConfig.Instance.GetConfig().uiItem.currentFontFamily;
if (!string.IsNullOrEmpty(fontFamily))
{
var fontPath = Utils.GetFontsPath();
MyFont = new FontFamily(new Uri(@$"file:///{fontPath}\"), $"./#{fontFamily}");
}
}
catch
{
}
MyFont ??= new FontFamily("Microsoft YaHei");
}
}
}

View File

@@ -3,6 +3,8 @@
class Global
{
#region const
public const string githubUrl = "https://github.com";
public const string githubApiUrl = "https://api.github.com/repos";
public const string v2rayWebsiteUrl = @"https://www.v2fly.org/";
public const string AboutUrl = @"https://github.com/2dust/v2rayN";
public const string UpdateUrl = AboutUrl + @"/releases";
@@ -12,12 +14,11 @@
public const string NUrl = @"https://github.com/2dust/v2rayN/releases";
public const string clashCoreUrl = "https://github.com/Dreamacro/clash/releases";
public const string clashMetaCoreUrl = "https://github.com/MetaCubeX/Clash.Meta/releases";
public const string hysteriaCoreUrl = "https://github.com/HyNetwork/hysteria/releases";
public const string hysteriaCoreUrl = "https://github.com/apernet/hysteria/releases";
public const string naiveproxyCoreUrl = "https://github.com/klzgrad/naiveproxy/releases";
public const string tuicCoreUrl = "https://github.com/EAimTY/tuic/releases";
public const string singboxCoreUrl = "https://github.com/SagerNet/sing-box/releases";
public const string geoUrl = "https://github.com/Loyalsoldier/v2ray-rules-dat/releases/latest/download/{0}.dat";
public const string SpeedTestUrl = @"http://cachefly.cachefly.net/10mb.test";
public const string SpeedPingTestUrl = @"https://www.google.com/generate_204";
public const string CustomRoutingListUrl = @"https://raw.githubusercontent.com/2dust/v2rayCustomRoutingList/master/";
@@ -77,34 +78,46 @@
public const string CommandClearMsg = "CommandClearMsg";
public const string DelayUnit = "";
public const string SpeedUnit = "";
public const int MinFontSize = 10;
public static readonly List<string> IEProxyProtocols = new List<string> {
public static readonly List<string> IEProxyProtocols = new() {
"{ip}:{http_port}",
"socks={ip}:{socks_port}",
"http={ip}:{http_port};https={ip}:{http_port};ftp={ip}:{http_port};socks={ip}:{socks_port}",
"http=http://{ip}:{http_port};https=http://{ip}:{http_port}",
""
};
public static readonly List<string> vmessSecuritys = new List<string> { "aes-128-gcm", "chacha20-poly1305", "auto", "none", "zero" };
public static readonly List<string> ssSecuritys = new List<string> { "aes-256-gcm", "aes-128-gcm", "chacha20-poly1305", "chacha20-ietf-poly1305", "none", "plain" };
public static readonly List<string> ssSecuritysInSagerNet = new List<string> { "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 List<string> { "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 List<string> { "", "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> networks = new List<string> { "tcp", "kcp", "ws", "h2", "quic", "grpc" };
public static readonly List<string> kcpHeaderTypes = new List<string> { "srtp", "utp", "wechat-video", "dtls", "wireguard" };
public static readonly List<string> coreTypes = new List<string> { "v2fly", "SagerNet", "Xray", "v2fly_v5" };
public static readonly List<string> domainStrategys = new List<string> { "AsIs", "IPIfNonMatch", "IPOnDemand" };
public static readonly List<string> domainMatchers = new List<string> { "linear", "mph", "" };
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> 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" };
public static readonly List<string> Protocols = new List<string> { "http", "tls", "bittorrent" };
public static readonly List<string> TunMtus = new List<string> { "9000", "1500" };
public static readonly List<string> TunStacks = new List<string> { "gvisor", "system" };
public static readonly List<string> vmessSecuritys = new() { "aes-128-gcm", "chacha20-poly1305", "auto", "none", "zero" };
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> 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" };
public static readonly List<string> domainStrategys = new() { "AsIs", "IPIfNonMatch", "IPOnDemand" };
public static readonly List<string> domainMatchers = new() { "linear", "mph", "" };
public static readonly List<string> fingerprints = new() { "chrome", "firefox", "safari", "ios", "android", "edge", "360", "qq", "random", "randomized", "" };
public static readonly List<string> userAgent = new() { "chrome", "firefox", "safari", "edge", "none" };
public static readonly Dictionary<string, string> userAgentTxt = new()
{
{"chrome","Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.131 Safari/537.36" },
{"firefox","Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:90.0) Gecko/20100101 Firefox/90.0" },
{"safari","Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/14.1.1 Safari/605.1.15" },
{"edge","Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36 Edg/91.0.864.70" },
{"none",""}
};
public static readonly List<string> allowInsecures = new() { "true", "false", "" };
public static readonly List<string> domainStrategy4Freedoms = new() { "AsIs", "UseIP", "UseIPv4", "UseIPv6", "" };
public static readonly List<string> Languages = new() { "zh-Hans", "en", "fa-Ir", "ru" };
public static readonly List<string> alpns = new() { "h2", "http/1.1", "h2,http/1.1", "" };
public static readonly List<string> LogLevel = new() { "debug", "info", "warning", "error", "none" };
public static readonly List<string> InboundTags = new() { "socks", "http", "socks2", "http2" };
public static readonly List<string> Protocols = new() { "http", "tls", "bittorrent" };
public static readonly List<string> TunMtus = new() { "9000", "1500" };
public static readonly List<string> TunStacks = new() { "gvisor", "system" };
public static readonly List<string> PresetMsgFilters = new() { "proxy", "direct", "block", "" };
public static readonly List<string> SpeedTestUrls = new() { @"http://cachefly.cachefly.net/100mb.test", @"http://cachefly.cachefly.net/10mb.test" };
#endregion

View File

@@ -13,7 +13,7 @@ namespace v2rayN.Handler
class ConfigHandler
{
private static string configRes = Global.ConfigFileName;
private static readonly object objLock = new object();
private static readonly object objLock = new();
#region ConfigHandler
@@ -43,18 +43,17 @@ namespace v2rayN.Handler
if (config == null)
{
config = new Config
{
};
}
if (config.coreBasicItem == null)
{
config.coreBasicItem = new()
{
logEnabled = false,
loglevel = "warning",
//Mux
muxEnabled = false,
enableStatistics = false,
statisticsFreshRate = 1,
enableRoutingAdvanced = true
};
}
@@ -62,7 +61,7 @@ namespace v2rayN.Handler
if (config.inbound == null)
{
config.inbound = new List<InItem>();
InItem inItem = new InItem
InItem inItem = new()
{
protocol = Global.InboundSocks,
localPort = 10808,
@@ -87,10 +86,17 @@ namespace v2rayN.Handler
config.inbound[0].protocol = Global.InboundSocks;
}
}
//路由规则
if (Utils.IsNullOrEmpty(config.domainStrategy))
if (config.routingBasicItem == null)
{
config.domainStrategy = Global.domainStrategys[0];//"IPIfNonMatch";
config.routingBasicItem = new()
{
enableRoutingAdvanced = true
};
}
//路由规则
if (Utils.IsNullOrEmpty(config.routingBasicItem.domainStrategy))
{
config.routingBasicItem.domainStrategy = Global.domainStrategys[0];//"IPIfNonMatch";
}
//if (Utils.IsNullOrEmpty(config.domainMatcher))
//{
@@ -130,6 +136,14 @@ namespace v2rayN.Handler
mtu = 9000,
};
}
if (config.guiItem == null)
{
config.guiItem = new()
{
enableStatistics = false,
statisticsFreshRate = 1,
};
}
if (config.uiItem == null)
{
config.uiItem = new UIItem()
@@ -150,14 +164,6 @@ namespace v2rayN.Handler
{
config.constItem = new ConstItem();
}
if (Utils.IsNullOrEmpty(config.constItem.speedTestUrl))
{
config.constItem.speedTestUrl = Global.SpeedTestUrl;
}
if (Utils.IsNullOrEmpty(config.constItem.speedPingTestUrl))
{
config.constItem.speedPingTestUrl = Global.SpeedPingTestUrl;
}
if (Utils.IsNullOrEmpty(config.constItem.defIEProxyExceptions))
{
config.constItem.defIEProxyExceptions = Global.IEProxyExceptions;
@@ -167,9 +173,26 @@ namespace v2rayN.Handler
// config.remoteDNS = "1.1.1.1";
//}
if (config.statisticsFreshRate > 100 || config.statisticsFreshRate < 1)
if (config.speedTestItem == null)
{
config.statisticsFreshRate = 1;
config.speedTestItem = new();
}
if (config.speedTestItem.speedTestTimeout < 10)
{
config.speedTestItem.speedTestTimeout = 10;
}
if (Utils.IsNullOrEmpty(config.speedTestItem.speedTestUrl))
{
config.speedTestItem.speedTestUrl = Global.SpeedTestUrls[0];
}
if (Utils.IsNullOrEmpty(config.speedTestItem.speedPingTestUrl))
{
config.speedTestItem.speedPingTestUrl = Global.SpeedPingTestUrl;
}
if (config.guiItem.statisticsFreshRate is > 100 or < 1)
{
config.guiItem.statisticsFreshRate = 1;
}
if (config == null)
@@ -182,7 +205,7 @@ namespace v2rayN.Handler
}
LazyConfig.Instance.SetConfig(ref config);
LazyConfig.Instance.SetConfig(config);
return 0;
}
/// <summary>
@@ -288,20 +311,45 @@ namespace v2rayN.Handler
}
config = Utils.FromJson<Config>(Utils.ToJson(configOld));
if (config.tunModeItem == null)
if (config.coreBasicItem == null)
{
config.tunModeItem = new TunModeItem
config.coreBasicItem = new()
{
enableTun = false,
showWindow = true,
mtu = 9000,
logEnabled = configOld.logEnabled,
loglevel = configOld.loglevel,
muxEnabled = configOld.muxEnabled,
};
}
if (config.routingBasicItem == null)
{
config.routingBasicItem = new()
{
enableRoutingAdvanced = configOld.enableRoutingAdvanced,
domainStrategy = configOld.domainStrategy
};
}
if (config.guiItem == null)
{
config.guiItem = new()
{
enableStatistics = configOld.enableStatistics,
statisticsFreshRate = configOld.statisticsFreshRate,
keepOlderDedupl = configOld.keepOlderDedupl,
ignoreGeoUpdateCore = configOld.ignoreGeoUpdateCore,
autoUpdateInterval = configOld.autoUpdateInterval,
checkPreReleaseUpdate = configOld.checkPreReleaseUpdate,
enableSecurityProtocolTls13 = configOld.enableSecurityProtocolTls13,
trayMenuServersLimit = configOld.trayMenuServersLimit,
};
}
GetDefaultServer(ref config);
GetDefaultRouting(ref config);
SaveConfig(ref config);
LazyConfig.Instance.SetConfig(ref config);
LoadConfig(ref config);
return 0;
}
@@ -390,14 +438,14 @@ namespace v2rayN.Handler
/// <param name="config"></param>
/// <param name="item"></param>
/// <returns></returns>
public static int SetDefaultServer(ref Config config, ProfileItem item)
public static int SetDefaultServerIndex(ref Config config, string? indexId)
{
if (item == null)
if (Utils.IsNullOrEmpty(indexId))
{
return -1;
}
config.indexId = item.indexId;
config.indexId = indexId;
Global.reloadCore = true;
ToJsonFile(config);
@@ -405,34 +453,34 @@ namespace v2rayN.Handler
return 0;
}
public static int SetDefaultServer(Config config, List<ProfileItem> lstProfile)
public static int SetDefaultServer(Config config, List<ProfileItemModel> lstProfile)
{
if (lstProfile.Exists(t => t.indexId == config.indexId))
{
return 0;
}
if (SqliteHelper.Instance.Table<ProfileItem>().Where(t => t.indexId == config.indexId).Count() > 0)
var allItems = LazyConfig.Instance.ProfileItemIndexs("");
if (allItems.Where(t => t == config.indexId).Any())
{
return 0;
}
if (lstProfile.Count > 0)
{
return SetDefaultServer(ref config, lstProfile[0]);
return SetDefaultServerIndex(ref config, lstProfile[0].indexId);
}
if (SqliteHelper.Instance.Table<ProfileItem>().Count() > 0)
if (allItems.Count > 0)
{
return SetDefaultServer(ref config, SqliteHelper.Instance.Table<ProfileItem>().FirstOrDefault());
return SetDefaultServerIndex(ref config, allItems.FirstOrDefault());
}
return -1;
}
public static ProfileItem GetDefaultServer(ref Config config)
public static ProfileItem? GetDefaultServer(ref Config config)
{
var item = LazyConfig.Instance.GetProfileItem(config.indexId);
if (item is null)
{
var item2 = SqliteHelper.Instance.Table<ProfileItem>().FirstOrDefault();
SetDefaultServer(ref config, item2);
SetDefaultServerIndex(ref config, item2?.indexId);
return item2;
}
@@ -457,9 +505,10 @@ namespace v2rayN.Handler
for (int i = 0; i < lstProfile.Count; i++)
{
lstProfile[i].sort = (i + 1) * 10;
ProfileExHandler.Instance.SetSort(lstProfile[i].indexId, (i + 1) * 10);
}
var sort = 0;
switch (eMove)
{
case EMove.Top:
@@ -468,7 +517,7 @@ namespace v2rayN.Handler
{
return 0;
}
lstProfile[index].sort = lstProfile[0].sort - 1;
sort = ProfileExHandler.Instance.GetSort(lstProfile[0].indexId) - 1;
break;
}
@@ -478,7 +527,7 @@ namespace v2rayN.Handler
{
return 0;
}
lstProfile[index].sort = lstProfile[index - 1].sort - 1;
sort = ProfileExHandler.Instance.GetSort(lstProfile[index - 1].indexId) - 1;
break;
}
@@ -489,7 +538,7 @@ namespace v2rayN.Handler
{
return 0;
}
lstProfile[index].sort = lstProfile[index + 1].sort + 1;
sort = ProfileExHandler.Instance.GetSort(lstProfile[index + 1].indexId) + 1;
break;
}
@@ -499,18 +548,16 @@ namespace v2rayN.Handler
{
return 0;
}
lstProfile[index].sort = lstProfile[lstProfile.Count - 1].sort + 1;
sort = ProfileExHandler.Instance.GetSort(lstProfile[^1].indexId) + 1;
break;
}
case EMove.Position:
lstProfile[index].sort = pos * 10 + 1;
sort = pos * 10 + 1;
break;
}
SqliteHelper.Instance.UpdateAll(lstProfile);
ProfileExHandler.Instance.SetSort(lstProfile[index].indexId, sort);
return 0;
}
@@ -638,7 +685,7 @@ namespace v2rayN.Handler
}
if (Utils.IsNullOrEmpty(profileItem.allowInsecure))
{
profileItem.allowInsecure = config.defAllowInsecure.ToString();
profileItem.allowInsecure = config.coreBasicItem.defAllowInsecure.ToString().ToLower();
}
AddServerCommon(ref config, profileItem);
@@ -650,11 +697,29 @@ namespace v2rayN.Handler
public static int SortServers(ref Config config, string subId, EServerColName name, bool asc)
{
var lstModel = LazyConfig.Instance.ProfileItems(subId, "");
var lstProfile = Utils.FromJson<List<ProfileItem>>(Utils.ToJson(lstModel));
if (lstProfile.Count <= 0)
if (lstModel.Count <= 0)
{
return -1;
}
var lstProfileExs = ProfileExHandler.Instance.ProfileExs;
var lstProfile = (from t in lstModel
join t3 in lstProfileExs on t.indexId equals t3.indexId into t3b
from t33 in t3b.DefaultIfEmpty()
select new ProfileItemModel
{
indexId = t.indexId,
configType = t.configType,
remarks = t.remarks,
address = t.address,
port = t.port,
security = t.security,
network = t.network,
streamSecurity = t.streamSecurity,
delay = t33 == null ? 0 : t33.delay,
speed = t33 == null ? 0 : t33.speed,
sort = t33 == null ? 0 : t33.sort
}).ToList();
var propertyName = string.Empty;
switch (name)
{
@@ -688,10 +753,30 @@ namespace v2rayN.Handler
}
for (int i = 0; i < lstProfile.Count; i++)
{
lstProfile[i].sort = (i + 1) * 10;
ProfileExHandler.Instance.SetSort(lstProfile[i].indexId, (i + 1) * 10);
}
if (name == EServerColName.delay)
{
var maxSort = lstProfile.Max(t => t.sort) + 10;
foreach (var item in lstProfile)
{
if (item.delay <= 0)
{
ProfileExHandler.Instance.SetSort(item.indexId, maxSort);
}
}
}
if (name == EServerColName.speed)
{
var maxSort = lstProfile.Max(t => t.sort) + 10;
foreach (var item in lstProfile)
{
if (item.speed <= 0)
{
ProfileExHandler.Instance.SetSort(item.indexId, maxSort);
}
}
}
SqliteHelper.Instance.UpdateAll(lstProfile);
return 0;
}
@@ -723,9 +808,9 @@ namespace v2rayN.Handler
public static int DedupServerList(ref Config config, ref List<ProfileItem> lstProfile)
{
List<ProfileItem> source = lstProfile;
bool keepOlder = config.keepOlderDedupl;
bool keepOlder = config.guiItem.keepOlderDedupl;
List<ProfileItem> list = new List<ProfileItem>();
List<ProfileItem> list = new();
if (!keepOlder) source.Reverse(); // Remove the early items first
foreach (ProfileItem item in source)
@@ -750,7 +835,7 @@ namespace v2rayN.Handler
profileItem.configVersion = 2;
if (Utils.IsNullOrEmpty(profileItem.allowInsecure))
{
profileItem.allowInsecure = config.defAllowInsecure.ToString();
profileItem.allowInsecure = config.coreBasicItem.defAllowInsecure.ToString().ToLower();
}
if (!Utils.IsNullOrEmpty(profileItem.network) && !Global.networks.Contains(profileItem.network))
{
@@ -760,15 +845,8 @@ namespace v2rayN.Handler
if (Utils.IsNullOrEmpty(profileItem.indexId))
{
profileItem.indexId = Utils.GetGUID(false);
if (profileItem.sort <= 0)
{
var maxSort = 0;
if (SqliteHelper.Instance.Table<ProfileItem>().Count() > 0)
{
maxSort = SqliteHelper.Instance.Table<ProfileItem>().Max(t => t == null ? 0 : t.sort);
}
profileItem.sort = maxSort + 1;
}
var maxSort = ProfileExHandler.Instance.GetMaxSort();
ProfileExHandler.Instance.SetSort(profileItem.indexId, maxSort + 1);
}
else if (profileItem.indexId == config.indexId)
{
@@ -859,11 +937,11 @@ 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);
}
//var maxSort = 0;
//if (SqliteHelper.Instance.Table<ProfileItem>().Count() > 0)
//{
// maxSort = SqliteHelper.Instance.Table<ProfileItem>().Max(t => t.sort);
//}
string[] arrData = clipboardData.Split(Environment.NewLine.ToCharArray());
foreach (string str in arrData)
{
@@ -901,7 +979,7 @@ namespace v2rayN.Handler
}
profileItem.subid = subid;
profileItem.isSub = isSub;
profileItem.sort = maxSort + countServers + 1;
//profileItem.sort = maxSort + countServers + 1;
if (profileItem.configType == EConfigType.VMess)
{
@@ -951,9 +1029,19 @@ namespace v2rayN.Handler
return -1;
}
ProfileItem profileItem = new ProfileItem();
//判断str是否包含s的任意一个字符串
static bool Containss(string str, params string[] s)
{
foreach (var item in s)
{
if (str.Contains(item, StringComparison.OrdinalIgnoreCase)) return true;
}
return false;
}
ProfileItem profileItem = new();
//Is v2ray configuration
V2rayConfig v2rayConfig = Utils.FromJson<V2rayConfig>(clipboardData);
V2rayConfig? v2rayConfig = Utils.FromJson<V2rayConfig>(clipboardData);
if (v2rayConfig != null
&& v2rayConfig.inbounds != null
&& v2rayConfig.inbounds.Count > 0
@@ -968,9 +1056,7 @@ namespace v2rayN.Handler
profileItem.remarks = "v2ray_custom";
}
//Is Clash configuration
else if (clipboardData.IndexOf("port") >= 0
&& clipboardData.IndexOf("socks-port") >= 0
&& clipboardData.IndexOf("proxies") >= 0)
else if (Containss(clipboardData, "port", "socks-port", "proxies"))
{
var fileName = Utils.GetTempPath($"{Utils.GetGUID(false)}.yaml");
File.WriteAllText(fileName, clipboardData);
@@ -980,12 +1066,7 @@ namespace v2rayN.Handler
profileItem.remarks = "clash_custom";
}
//Is hysteria configuration
else if (clipboardData.IndexOf("server") >= 0
&& clipboardData.IndexOf("up") >= 0
&& clipboardData.IndexOf("down") >= 0
&& clipboardData.IndexOf("listen") >= 0
&& clipboardData.IndexOf("<html>") < 0
&& clipboardData.IndexOf("<body>") < 0)
else if (Containss(clipboardData, "server", "up", "down", "listen", "<html>", "<body>"))
{
var fileName = Utils.GetTempPath($"{Utils.GetGUID(false)}.json");
File.WriteAllText(fileName, clipboardData);
@@ -995,10 +1076,7 @@ namespace v2rayN.Handler
profileItem.remarks = "hysteria_custom";
}
//Is naiveproxy configuration
else if (clipboardData.IndexOf("listen") >= 0
&& clipboardData.IndexOf("proxy") >= 0
&& clipboardData.IndexOf("<html>") < 0
&& clipboardData.IndexOf("<body>") < 0)
else if (Containss(clipboardData, "listen", "proxy", "<html>", "<body>"))
{
var fileName = Utils.GetTempPath($"{Utils.GetGUID(false)}.json");
File.WriteAllText(fileName, clipboardData);
@@ -1098,7 +1176,7 @@ namespace v2rayN.Handler
public static int AddBatchServers(ref Config config, string clipboardData, string subid, bool isSub)
{
List<ProfileItem> lstOriSub = null;
List<ProfileItem>? lstOriSub = null;
if (isSub && !Utils.IsNullOrEmpty(subid))
{
lstOriSub = LazyConfig.Instance.ProfileItems(subid);
@@ -1143,7 +1221,7 @@ namespace v2rayN.Handler
return 0;
}
SubItem subItem = new SubItem
SubItem subItem = new()
{
id = string.Empty,
remarks = "import_sub",
@@ -1194,11 +1272,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;
@@ -1415,7 +1493,7 @@ namespace v2rayN.Handler
{
if (SqliteHelper.Instance.Table<RoutingItem>().Where(t => t.id == routingItem.id).Count() > 0)
{
config.routingIndexId = routingItem.id;
config.routingBasicItem.routingIndexId = routingItem.id;
}
Global.reloadCore = true;
@@ -1426,7 +1504,7 @@ namespace v2rayN.Handler
}
public static RoutingItem GetDefaultRouting(ref Config config)
{
var item = LazyConfig.Instance.GetRoutingItem(config.routingIndexId);
var item = LazyConfig.Instance.GetRoutingItem(config.routingBasicItem.routingIndexId);
if (item is null)
{
var item2 = SqliteHelper.Instance.Table<RoutingItem>().FirstOrDefault(t => t.locked == false);
@@ -1439,13 +1517,16 @@ namespace v2rayN.Handler
public static int InitBuiltinRouting(ref Config config, bool blImportAdvancedRules = false)
{
if (blImportAdvancedRules || LazyConfig.Instance.RoutingItems().Count <= 0)
var items = LazyConfig.Instance.RoutingItems();
if (blImportAdvancedRules || items.Count <= 0)
{
var maxSort = items.Count;
//Bypass the mainland
var item2 = new RoutingItem()
{
remarks = "绕过大陆(Whitelist)",
url = string.Empty,
sort = maxSort + 1,
};
AddBatchRoutingRules(ref item2, Utils.GetEmbedText(Global.CustomRoutingFileName + "white"));
@@ -1454,6 +1535,7 @@ namespace v2rayN.Handler
{
remarks = "黑名单(Blacklist)",
url = string.Empty,
sort = maxSort + 2,
};
AddBatchRoutingRules(ref item3, Utils.GetEmbedText(Global.CustomRoutingFileName + "black"));
@@ -1462,6 +1544,7 @@ namespace v2rayN.Handler
{
remarks = "全局(Global)",
url = string.Empty,
sort = maxSort + 3,
};
AddBatchRoutingRules(ref item1, Utils.GetEmbedText(Global.CustomRoutingFileName + "global"));

View File

@@ -25,7 +25,7 @@ namespace v2rayN.Handler
/// <param name="msg"></param>
/// <param name="content"></param>
/// <returns></returns>
public static int GenerateClientConfig(ProfileItem node, string fileName, out string msg, out string content)
public static int GenerateClientConfig(ProfileItem node, string? fileName, out string msg, out string content)
{
content = string.Empty;
try
@@ -43,7 +43,7 @@ namespace v2rayN.Handler
}
else
{
V2rayConfig v2rayConfig = null;
V2rayConfig? v2rayConfig = null;
if (GenerateClientConfigContent(node, false, ref v2rayConfig, out msg) != 0)
{
return -1;
@@ -73,28 +73,29 @@ namespace v2rayN.Handler
{
if (blExport)
{
if (config.logEnabled)
if (config.coreBasicItem.logEnabled)
{
v2rayConfig.log.loglevel = config.loglevel;
v2rayConfig.log.loglevel = config.coreBasicItem.loglevel;
}
else
{
v2rayConfig.log.loglevel = config.loglevel;
v2rayConfig.log.loglevel = config.coreBasicItem.loglevel;
v2rayConfig.log.access = "";
v2rayConfig.log.error = "";
}
}
else
{
if (config.logEnabled)
if (config.coreBasicItem.logEnabled)
{
v2rayConfig.log.loglevel = config.loglevel;
v2rayConfig.log.access = Utils.GetLogPath(v2rayConfig.log.access);
v2rayConfig.log.error = Utils.GetLogPath(v2rayConfig.log.error);
var dtNow = DateTime.Now;
v2rayConfig.log.loglevel = config.coreBasicItem.loglevel;
v2rayConfig.log.access = Utils.GetLogPath($"Vaccess_{dtNow:yyyy-MM-dd}.txt");
v2rayConfig.log.error = Utils.GetLogPath($"Verror_{dtNow:yyyy-MM-dd}.txt");
}
else
{
v2rayConfig.log.loglevel = config.loglevel;
v2rayConfig.log.loglevel = config.coreBasicItem.loglevel;
v2rayConfig.log.access = "";
v2rayConfig.log.error = "";
}
@@ -113,11 +114,11 @@ namespace v2rayN.Handler
{
v2rayConfig.inbounds = new List<Inbounds>();
Inbounds inbound = GetInbound(config.inbound[0], Global.InboundSocks, 0, true);
Inbounds? inbound = GetInbound(config.inbound[0], Global.InboundSocks, 0, true);
v2rayConfig.inbounds.Add(inbound);
//http
Inbounds inbound2 = GetInbound(config.inbound[0], Global.InboundHttp, 1, false);
Inbounds? inbound2 = GetInbound(config.inbound[0], Global.InboundHttp, 1, false);
v2rayConfig.inbounds.Add(inbound2);
if (config.inbound[0].allowLANConn)
@@ -156,7 +157,7 @@ namespace v2rayN.Handler
return 0;
}
private static Inbounds GetInbound(InItem inItem, string tag, int offset, bool bSocks)
private static Inbounds? GetInbound(InItem inItem, string tag, int offset, bool bSocks)
{
string result = Utils.GetEmbedText(Global.v2raySampleInbound);
if (Utils.IsNullOrEmpty(result))
@@ -186,10 +187,10 @@ namespace v2rayN.Handler
if (v2rayConfig.routing != null
&& v2rayConfig.routing.rules != null)
{
v2rayConfig.routing.domainStrategy = config.domainStrategy;
v2rayConfig.routing.domainMatcher = Utils.IsNullOrEmpty(config.domainMatcher) ? null : config.domainMatcher;
v2rayConfig.routing.domainStrategy = config.routingBasicItem.domainStrategy;
v2rayConfig.routing.domainMatcher = Utils.IsNullOrEmpty(config.routingBasicItem.domainMatcher) ? null : config.routingBasicItem.domainMatcher;
if (config.enableRoutingAdvanced)
if (config.routingBasicItem.enableRoutingAdvanced)
{
var routing = ConfigHandler.GetDefaultRouting(ref config);
if (routing != null)
@@ -347,8 +348,8 @@ namespace v2rayN.Handler
}
//Mux
outbound.mux.enabled = config.muxEnabled;
outbound.mux.concurrency = config.muxEnabled ? 8 : -1;
outbound.mux.enabled = config.coreBasicItem.muxEnabled;
outbound.mux.concurrency = config.coreBasicItem.muxEnabled ? 8 : -1;
boundStreamSettings(node, "out", outbound.streamSettings);
@@ -404,7 +405,7 @@ namespace v2rayN.Handler
if (!Utils.IsNullOrEmpty(node.security)
&& !Utils.IsNullOrEmpty(node.id))
{
SocksUsersItem socksUsersItem = new SocksUsersItem
SocksUsersItem socksUsersItem = new()
{
user = node.security,
pass = node.id,
@@ -451,8 +452,8 @@ namespace v2rayN.Handler
usersItem.encryption = node.security;
//Mux
outbound.mux.enabled = config.muxEnabled;
outbound.mux.concurrency = config.muxEnabled ? 8 : -1;
outbound.mux.enabled = config.coreBasicItem.muxEnabled;
outbound.mux.concurrency = config.coreBasicItem.muxEnabled ? 8 : -1;
boundStreamSettings(node, "out", outbound.streamSettings);
@@ -546,17 +547,29 @@ namespace v2rayN.Handler
streamSettings.network = node.GetNetwork();
string host = node.requestHost.TrimEx();
string sni = node.sni;
string useragent = "";
if (!config.coreBasicItem.defUserAgent.IsNullOrEmpty())
{
try
{
useragent = Global.userAgentTxt[config.coreBasicItem.defUserAgent];
}
catch (KeyNotFoundException)
{
useragent = config.coreBasicItem.defUserAgent;
}
}
//if tls
if (node.streamSecurity == Global.StreamSecurity)
{
streamSettings.security = node.streamSecurity;
TlsSettings tlsSettings = new TlsSettings
TlsSettings tlsSettings = new()
{
allowInsecure = Utils.ToBool(node.allowInsecure),
allowInsecure = Utils.ToBool(node.allowInsecure.IsNullOrEmpty() ? config.coreBasicItem.defAllowInsecure.ToString().ToLower() : node.allowInsecure),
alpn = node.GetAlpn(),
fingerprint = node.fingerprint
fingerprint = node.fingerprint.IsNullOrEmpty() ? config.coreBasicItem.defFingerprint : node.fingerprint
};
if (!string.IsNullOrWhiteSpace(sni))
{
@@ -574,11 +587,11 @@ namespace v2rayN.Handler
{
streamSettings.security = node.streamSecurity;
TlsSettings xtlsSettings = new TlsSettings
TlsSettings xtlsSettings = new()
{
allowInsecure = Utils.ToBool(node.allowInsecure),
allowInsecure = Utils.ToBool(node.allowInsecure.IsNullOrEmpty() ? config.coreBasicItem.defAllowInsecure.ToString().ToLower() : node.allowInsecure),
alpn = node.GetAlpn(),
fingerprint = node.fingerprint
fingerprint = node.fingerprint.IsNullOrEmpty() ? config.coreBasicItem.defFingerprint : node.fingerprint
};
if (!string.IsNullOrWhiteSpace(sni))
{
@@ -595,7 +608,7 @@ namespace v2rayN.Handler
switch (node.GetNetwork())
{
case "kcp":
KcpSettings kcpSettings = new KcpSettings
KcpSettings kcpSettings = new()
{
mtu = config.kcpItem.mtu,
tti = config.kcpItem.tti
@@ -631,22 +644,21 @@ namespace v2rayN.Handler
break;
//ws
case "ws":
WsSettings wsSettings = new WsSettings
{
};
WsSettings wsSettings = new();
wsSettings.headers = new Headers();
string path = node.path;
if (!string.IsNullOrWhiteSpace(host))
{
wsSettings.headers = new Headers
{
Host = host
};
wsSettings.headers.Host = host;
}
if (!string.IsNullOrWhiteSpace(path))
{
wsSettings.path = path;
}
if (!string.IsNullOrWhiteSpace(useragent))
{
wsSettings.headers.UserAgent = useragent;
}
streamSettings.wsSettings = wsSettings;
//TlsSettings tlsSettings = new TlsSettings();
@@ -659,7 +671,7 @@ namespace v2rayN.Handler
break;
//h2
case "h2":
HttpSettings httpSettings = new HttpSettings();
HttpSettings httpSettings = new();
if (!string.IsNullOrWhiteSpace(host))
{
@@ -675,7 +687,7 @@ namespace v2rayN.Handler
break;
//quic
case "quic":
QuicSettings quicsettings = new QuicSettings
QuicSettings quicsettings = new()
{
security = host,
key = node.path,
@@ -698,7 +710,7 @@ namespace v2rayN.Handler
}
break;
case "grpc":
var grpcSettings = new GrpcSettings
GrpcSettings grpcSettings = new()
{
serviceName = node.path,
multiMode = (node.headerType == Global.GrpcmultiMode),
@@ -714,7 +726,7 @@ namespace v2rayN.Handler
//tcp
if (node.headerType.Equals(Global.TcpHeaderHttp))
{
TcpSettings tcpSettings = new TcpSettings
TcpSettings tcpSettings = new()
{
header = new Header
{
@@ -730,7 +742,7 @@ namespace v2rayN.Handler
string host2 = string.Join("\",\"", arrHost);
request = request.Replace("$requestHost$", $"\"{host2}\"");
//request = request.Replace("$requestHost$", string.Format("\"{0}\"", config.requestHost()));
request = request.Replace("$requestUserAgent$", $"\"{useragent}\"");
//Path
string pathHttp = @"/";
if (!Utils.IsNullOrEmpty(node.path))
@@ -783,7 +795,7 @@ namespace v2rayN.Handler
}
else
{
List<string> servers = new List<string>();
List<string> servers = new();
string[] arrDNS = config.remoteDNS.Split(',');
foreach (string str in arrDNS)
@@ -809,12 +821,12 @@ namespace v2rayN.Handler
private static int statistic(Config config, ref V2rayConfig v2rayConfig)
{
if (config.enableStatistics)
if (config.guiItem.enableStatistics)
{
string tag = Global.InboundAPITagName;
API apiObj = new API();
Policy policyObj = new Policy();
SystemPolicy policySystemSetting = new SystemPolicy();
API apiObj = new();
Policy policyObj = new();
SystemPolicy policySystemSetting = new();
string[] services = { "StatsService" };
@@ -831,8 +843,8 @@ namespace v2rayN.Handler
if (!v2rayConfig.inbounds.Exists(item => item.tag == tag))
{
Inbounds apiInbound = new Inbounds();
Inboundsettings apiInboundSettings = new Inboundsettings();
Inbounds apiInbound = new();
Inboundsettings apiInboundSettings = new();
apiInbound.tag = tag;
apiInbound.listen = Global.Loopback;
apiInbound.port = Global.statePort;
@@ -844,7 +856,7 @@ namespace v2rayN.Handler
if (!v2rayConfig.routing.rules.Exists(item => item.outboundTag == tag))
{
RulesItem apiRoutingRule = new RulesItem
RulesItem apiRoutingRule = new()
{
inboundTag = new List<string> { tag },
outboundTag = tag,
@@ -941,7 +953,7 @@ namespace v2rayN.Handler
return 0;
}
public static int GenerateClientConfigContent(ProfileItem node, bool blExport, ref V2rayConfig v2rayConfig, out string msg)
public static int GenerateClientConfigContent(ProfileItem node, bool blExport, ref V2rayConfig? v2rayConfig, out string msg)
{
try
{
@@ -1018,7 +1030,7 @@ namespace v2rayN.Handler
return -1;
}
V2rayConfig v2rayConfig = Utils.FromJson<V2rayConfig>(result);
V2rayConfig? v2rayConfig = Utils.FromJson<V2rayConfig>(result);
if (v2rayConfig == null)
{
msg = ResUI.FailedGenDefaultConfiguration;
@@ -1107,10 +1119,10 @@ namespace v2rayN.Handler
#region Import (export) client/server configuration
public static ProfileItem ImportFromClientConfig(string fileName, out string msg)
public static ProfileItem? ImportFromClientConfig(string fileName, out string msg)
{
msg = string.Empty;
ProfileItem profileItem = new ProfileItem();
ProfileItem profileItem = new();
try
{
@@ -1121,7 +1133,7 @@ namespace v2rayN.Handler
return null;
}
V2rayConfig v2rayConfig = Utils.FromJson<V2rayConfig>(result);
V2rayConfig? v2rayConfig = Utils.FromJson<V2rayConfig>(result);
if (v2rayConfig == null)
{
msg = ResUI.FailedConversionConfiguration;
@@ -1246,10 +1258,10 @@ namespace v2rayN.Handler
return profileItem;
}
public static ProfileItem ImportFromServerConfig(string fileName, out string msg)
public static ProfileItem? ImportFromServerConfig(string fileName, out string msg)
{
msg = string.Empty;
ProfileItem profileItem = new ProfileItem();
ProfileItem profileItem = new();
try
{
@@ -1260,7 +1272,7 @@ namespace v2rayN.Handler
return null;
}
V2rayConfig v2rayConfig = Utils.FromJson<V2rayConfig>(result);
V2rayConfig? v2rayConfig = Utils.FromJson<V2rayConfig>(result);
if (v2rayConfig == null)
{
msg = ResUI.FailedConversionConfiguration;
@@ -1385,7 +1397,7 @@ namespace v2rayN.Handler
public static int Export2ClientConfig(ProfileItem node, string fileName, out string msg)
{
V2rayConfig v2rayConfig = null;
V2rayConfig? v2rayConfig = null;
if (GenerateClientConfigContent(node, true, ref v2rayConfig, out msg) != 0)
{
return -1;
@@ -1424,14 +1436,14 @@ namespace v2rayN.Handler
return "";
}
V2rayConfig v2rayConfig = Utils.FromJson<V2rayConfig>(result);
V2rayConfig? v2rayConfig = Utils.FromJson<V2rayConfig>(result);
if (v2rayConfig == null)
{
msg = ResUI.FailedGenDefaultConfiguration;
return "";
}
List<IPEndPoint> lstIpEndPoints = new List<IPEndPoint>();
List<TcpConnectionInformation> lstTcpConns = new List<TcpConnectionInformation>();
List<IPEndPoint> lstIpEndPoints = new();
List<TcpConnectionInformation> lstTcpConns = new();
try
{
lstIpEndPoints.AddRange(IPGlobalProperties.GetIPGlobalProperties().GetActiveTcpListeners());
@@ -1461,7 +1473,7 @@ namespace v2rayN.Handler
{
continue;
}
if (it.configType == EConfigType.VMess || it.configType == EConfigType.VLESS)
if (it.configType is EConfigType.VMess or EConfigType.VLESS)
{
var item2 = LazyConfig.Instance.GetProfileItem(it.indexId);
if (item2 is null || Utils.IsNullOrEmpty(item2.id) || !Utils.IsGuidByParse(item2.id))
@@ -1497,7 +1509,7 @@ namespace v2rayN.Handler
it.allowTest = true;
//inbound
Inbounds inbound = new Inbounds
Inbounds inbound = new()
{
listen = Global.Loopback,
port = port,
@@ -1507,7 +1519,7 @@ namespace v2rayN.Handler
v2rayConfig.inbounds.Add(inbound);
//outbound
V2rayConfig v2rayConfigCopy = Utils.FromJson<V2rayConfig>(result);
V2rayConfig? v2rayConfigCopy = Utils.FromJson<V2rayConfig>(result);
var item = LazyConfig.Instance.GetProfileItem(it.indexId);
if (item is null)
{
@@ -1524,7 +1536,7 @@ namespace v2rayN.Handler
v2rayConfig.outbounds.Add(v2rayConfigCopy.outbounds[0]);
//rule
RulesItem rule = new RulesItem
RulesItem rule = new()
{
inboundTag = new List<string> { inbound.tag },
outboundTag = v2rayConfigCopy.outbounds[0].tag,

View File

@@ -12,14 +12,17 @@ namespace v2rayN.Handler
class CoreHandler
{
private static string _coreCConfigRes = Global.coreConfigFileName;
private CoreInfo _coreInfo;
private CoreInfo? _coreInfo;
private int _processId = 0;
private Process _process;
private Process? _process;
Action<bool, string> _updateFunc;
public CoreHandler(Action<bool, string> update)
{
_updateFunc = update;
Environment.SetEnvironmentVariable("v2ray.location.asset", Utils.GetBinPath(""), EnvironmentVariableTarget.Process);
Environment.SetEnvironmentVariable("xray.location.asset", Utils.GetBinPath(""), EnvironmentVariableTarget.Process);
}
public void LoadCore(Config config)
@@ -105,7 +108,7 @@ namespace v2rayN.Handler
Process[] existing = Process.GetProcessesByName(vName);
foreach (Process p in existing)
{
string path = p.MainModule.FileName;
string? path = p.MainModule?.FileName;
if (path == $"{Utils.GetBinPath(vName, _coreInfo.coreType)}.exe")
{
KillProcess(p);
@@ -170,7 +173,8 @@ namespace v2rayN.Handler
string fileName = CoreFindexe(_coreInfo);
if (fileName == "") return;
Process p = new Process
var displayLog = node.configType != EConfigType.Custom || node.displayLog;
Process p = new()
{
StartInfo = new ProcessStartInfo
{
@@ -178,18 +182,18 @@ namespace v2rayN.Handler
Arguments = _coreInfo.arguments,
WorkingDirectory = Utils.GetConfigPath(),
UseShellExecute = false,
RedirectStandardOutput = node.displayLog,
RedirectStandardError = node.displayLog,
RedirectStandardOutput = displayLog,
RedirectStandardError = displayLog,
CreateNoWindow = true,
StandardOutputEncoding = node.displayLog ? Encoding.UTF8 : null,
StandardErrorEncoding = node.displayLog ? Encoding.UTF8 : null,
StandardOutputEncoding = displayLog ? Encoding.UTF8 : null,
StandardErrorEncoding = displayLog ? Encoding.UTF8 : null,
}
};
if (node.displayLog)
if (displayLog)
{
p.OutputDataReceived += (sender, e) =>
{
if (!String.IsNullOrEmpty(e.Data))
if (!string.IsNullOrEmpty(e.Data))
{
string msg = e.Data + Environment.NewLine;
ShowMsg(false, msg);
@@ -197,7 +201,7 @@ namespace v2rayN.Handler
};
}
p.Start();
if (node.displayLog)
if (displayLog)
{
p.BeginOutputReadLine();
}
@@ -205,7 +209,7 @@ namespace v2rayN.Handler
if (p.WaitForExit(1000))
{
throw new Exception(node.displayLog ? p.StandardError.ReadToEnd() : "启动进程失败并退出 (Failed to start the process and exited)");
throw new Exception(displayLog ? p.StandardError.ReadToEnd() : "启动进程失败并退出 (Failed to start the process and exited)");
}
Global.processJob.AddProcess(p.Handle);
@@ -228,7 +232,7 @@ namespace v2rayN.Handler
string fileName = CoreFindexe(coreInfo);
if (fileName == "") return -1;
Process p = new Process
Process p = new()
{
StartInfo = new ProcessStartInfo
{

View File

@@ -16,7 +16,7 @@ namespace v2rayN.Handler
{
public event EventHandler<ResultEventArgs> UpdateCompleted;
public event ErrorEventHandler Error;
public event ErrorEventHandler? Error;
public class ResultEventArgs : EventArgs
@@ -33,20 +33,13 @@ namespace v2rayN.Handler
public async Task<int> DownloadDataAsync(string url, WebProxy webProxy, int downloadTimeout, Action<bool, string> update)
{
var hasValue = false;
try
{
Utils.SetSecurityProtocol(LazyConfig.Instance.GetConfig().enableSecurityProtocolTls13);
var client = new HttpClient(new SocketsHttpHandler()
{
Proxy = webProxy
});
Utils.SetSecurityProtocol(LazyConfig.Instance.GetConfig().guiItem.enableSecurityProtocolTls13);
var progress = new Progress<string>();
progress.ProgressChanged += (sender, value) =>
{
hasValue = true;
if (update != null)
{
string msg = $"{value}";
@@ -54,22 +47,17 @@ namespace v2rayN.Handler
}
};
var cancellationToken = new CancellationTokenSource();
cancellationToken.CancelAfter(downloadTimeout * 1000);
await HttpClientHelper.GetInstance().DownloadDataAsync4Speed(client,
await DownloaderHelper.Instance.DownloadDataAsync4Speed(webProxy,
url,
progress,
cancellationToken.Token);
downloadTimeout);
}
catch (Exception ex)
{
if (!hasValue)
update(false, ex.Message);
if (ex.InnerException != null)
{
update(false, ex.Message);
if (ex.InnerException != null)
{
update(false, ex.InnerException.Message);
}
update(false, ex.InnerException.Message);
}
}
return 0;
@@ -79,30 +67,25 @@ namespace v2rayN.Handler
{
try
{
Utils.SetSecurityProtocol(LazyConfig.Instance.GetConfig().enableSecurityProtocolTls13);
Utils.SetSecurityProtocol(LazyConfig.Instance.GetConfig().guiItem.enableSecurityProtocolTls13);
UpdateCompleted?.Invoke(this, new ResultEventArgs(false, ResUI.Downloading));
var client = new HttpClient(new SocketsHttpHandler()
{
Proxy = GetWebProxy(blProxy)
});
var progress = new Progress<double>();
progress.ProgressChanged += (sender, value) =>
{
if (UpdateCompleted != null)
{
string msg = $"...{value}%";
UpdateCompleted(this, new ResultEventArgs(value > 100 ? true : false, msg));
UpdateCompleted(this, new ResultEventArgs(value > 100, msg));
}
};
var cancellationToken = new CancellationTokenSource();
_ = HttpClientHelper.GetInstance().DownloadFileAsync(client,
url,
Utils.GetTempPath(Utils.GetDownloadFileName(url)),
progress,
cancellationToken.Token);
var webProxy = GetWebProxy(blProxy);
_ = DownloaderHelper.Instance.DownloadFileAsync(webProxy,
url,
Utils.GetTempPath(Utils.GetDownloadFileName(url)),
progress,
downloadTimeout);
}
catch (Exception ex)
{
@@ -116,20 +99,20 @@ namespace v2rayN.Handler
}
}
public async Task<string> UrlRedirectAsync(string url, bool blProxy)
public async Task<string?> UrlRedirectAsync(string url, bool blProxy)
{
Utils.SetSecurityProtocol(LazyConfig.Instance.GetConfig().enableSecurityProtocolTls13);
Utils.SetSecurityProtocol(LazyConfig.Instance.GetConfig().guiItem.enableSecurityProtocolTls13);
var webRequestHandler = new SocketsHttpHandler
{
AllowAutoRedirect = false,
Proxy = GetWebProxy(blProxy)
};
HttpClient client = new HttpClient(webRequestHandler);
HttpClient client = new(webRequestHandler);
HttpResponseMessage response = await client.GetAsync(url);
if (response.StatusCode.ToString() == "Redirect")
{
return response.Headers.Location.ToString();
return response.Headers.Location?.ToString();
}
else
{
@@ -138,15 +121,77 @@ namespace v2rayN.Handler
}
}
public async Task<string?> TryDownloadString(string url, bool blProxy, string userAgent)
{
try
{
var result1 = await DownloadStringAsync(url, blProxy, userAgent);
if (!Utils.IsNullOrEmpty(result1))
{
return result1;
}
}
catch (Exception ex)
{
Utils.SaveLog(ex.Message, ex);
Error?.Invoke(this, new ErrorEventArgs(ex));
if (ex.InnerException != null)
{
Error?.Invoke(this, new ErrorEventArgs(ex.InnerException));
}
}
try
{
var result2 = await DownloadStringViaDownloader(url, blProxy, userAgent);
if (!Utils.IsNullOrEmpty(result2))
{
return result2;
}
}
catch (Exception ex)
{
Utils.SaveLog(ex.Message, ex);
Error?.Invoke(this, new ErrorEventArgs(ex));
if (ex.InnerException != null)
{
Error?.Invoke(this, new ErrorEventArgs(ex.InnerException));
}
}
try
{
using var wc = new WebClient();
wc.Proxy = GetWebProxy(blProxy);
var result3 = await wc.DownloadStringTaskAsync(url);
if (!Utils.IsNullOrEmpty(result3))
{
return result3;
}
}
catch (Exception ex)
{
Utils.SaveLog(ex.Message, ex);
Error?.Invoke(this, new ErrorEventArgs(ex));
if (ex.InnerException != null)
{
Error?.Invoke(this, new ErrorEventArgs(ex.InnerException));
}
}
return null;
}
/// <summary>
/// DownloadString
/// </summary>
/// <param name="url"></param>
public async Task<string> DownloadStringAsync(string url, bool blProxy, string userAgent)
public async Task<string?> DownloadStringAsync(string url, bool blProxy, string userAgent)
{
try
{
Utils.SetSecurityProtocol(LazyConfig.Instance.GetConfig().enableSecurityProtocolTls13);
Utils.SetSecurityProtocol(LazyConfig.Instance.GetConfig().guiItem.enableSecurityProtocolTls13);
var client = new HttpClient(new SocketsHttpHandler()
{
Proxy = GetWebProxy(blProxy)
@@ -158,7 +203,7 @@ namespace v2rayN.Handler
}
client.DefaultRequestHeaders.UserAgent.TryParseAdd(userAgent);
Uri uri = new Uri(url);
Uri uri = new(url);
//Authorization Header
if (!Utils.IsNullOrEmpty(uri.UserInfo))
{
@@ -183,7 +228,39 @@ namespace v2rayN.Handler
return null;
}
public int RunAvailabilityCheck(WebProxy webProxy)
/// <summary>
/// DownloadString
/// </summary>
/// <param name="url"></param>
public async Task<string?> DownloadStringViaDownloader(string url, bool blProxy, string userAgent)
{
try
{
Utils.SetSecurityProtocol(LazyConfig.Instance.GetConfig().guiItem.enableSecurityProtocolTls13);
var webProxy = GetWebProxy(blProxy);
if (Utils.IsNullOrEmpty(userAgent))
{
userAgent = $"{Utils.GetVersion(false)}";
}
var result = await DownloaderHelper.Instance.DownloadStringAsync(webProxy, url, userAgent, 30);
return result;
}
catch (Exception ex)
{
Utils.SaveLog(ex.Message, ex);
Error?.Invoke(this, new ErrorEventArgs(ex));
if (ex.InnerException != null)
{
Error?.Invoke(this, new ErrorEventArgs(ex.InnerException));
}
}
return null;
}
public int RunAvailabilityCheck(WebProxy? webProxy)
{
try
{
@@ -195,7 +272,8 @@ namespace v2rayN.Handler
try
{
string status = GetRealPingTime(Global.SpeedPingTestUrl, webProxy, 10, out int responseTime);
var config = LazyConfig.Instance.GetConfig();
string status = GetRealPingTime(config.speedTestItem.speedPingTestUrl, webProxy, 10, out int responseTime);
bool noError = Utils.IsNullOrEmpty(status);
return noError ? responseTime : -1;
}
@@ -222,12 +300,11 @@ namespace v2rayN.Handler
myHttpWebRequest.Timeout = downloadTimeout * 1000;
myHttpWebRequest.Proxy = webProxy;
Stopwatch timer = new Stopwatch();
Stopwatch timer = new();
timer.Start();
HttpWebResponse myHttpWebResponse = (HttpWebResponse)myHttpWebRequest.GetResponse();
if (myHttpWebResponse.StatusCode != HttpStatusCode.OK
&& myHttpWebResponse.StatusCode != HttpStatusCode.NoContent)
if (myHttpWebResponse.StatusCode is not HttpStatusCode.OK and not HttpStatusCode.NoContent)
{
msg = myHttpWebResponse.StatusDescription;
}
@@ -244,7 +321,7 @@ namespace v2rayN.Handler
return msg;
}
private WebProxy GetWebProxy(bool blProxy)
private WebProxy? GetWebProxy(bool blProxy)
{
if (!blProxy)
{
@@ -261,11 +338,11 @@ namespace v2rayN.Handler
private bool SocketCheck(string ip, int port)
{
Socket sock = null;
Socket? sock = null;
try
{
IPAddress ipa = IPAddress.Parse(ip);
IPEndPoint point = new IPEndPoint(ipa, port);
IPEndPoint point = new(ipa, port);
sock = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
sock.Connect(point);
return true;

View File

@@ -5,7 +5,7 @@ namespace v2rayN.Handler
{
public sealed class LazyConfig
{
private static readonly Lazy<LazyConfig> _instance = new Lazy<LazyConfig>(() => new());
private static readonly Lazy<LazyConfig> _instance = new(() => new());
private Config _config;
private List<CoreInfo> coreInfos;
@@ -17,11 +17,12 @@ namespace v2rayN.Handler
SqliteHelper.Instance.CreateTable<ProfileItem>();
SqliteHelper.Instance.CreateTable<ServerStatItem>();
SqliteHelper.Instance.CreateTable<RoutingItem>();
SqliteHelper.Instance.CreateTable<ProfileExItem>();
}
#region Config
public void SetConfig(ref Config config)
public void SetConfig(Config config)
{
_config = config;
}
@@ -81,29 +82,43 @@ namespace v2rayN.Handler
return SqliteHelper.Instance.Table<ProfileItem>().Where(t => t.subid == subid).ToList();
}
}
public List<string> ProfileItemIndexs(string subid)
{
if (Utils.IsNullOrEmpty(subid))
{
return SqliteHelper.Instance.Table<ProfileItem>().Select(t => t.indexId).ToList();
}
else
{
return SqliteHelper.Instance.Table<ProfileItem>().Where(t => t.subid == subid).Select(t => t.indexId).ToList();
}
}
public List<ProfileItemModel> ProfileItems(string subid, string filter)
{
var sql = @$"select a.*
,b.remarks subRemarks
,case when a.indexId = '{_config.indexId}' then true else false end isActive
,b.remarks subRemarks
from ProfileItem a
left join SubItem b on a.subid = b.id
where 1=1 ";
if (!Utils.IsNullOrEmpty(subid))
{
sql += $" and a.subid = {subid}";
sql += $" and a.subid = '{subid}'";
}
if (!Utils.IsNullOrEmpty(filter))
{
if (filter.Contains("'"))
{
filter = filter.Replace("'", "");
}
sql += $" and a.remarks like '%{filter}%'";
}
sql += " order by a.sort";
return SqliteHelper.Instance.Query<ProfileItemModel>(sql).ToList();
}
public ProfileItem GetProfileItem(string indexId)
public ProfileItem? GetProfileItem(string indexId)
{
if (Utils.IsNullOrEmpty(indexId))
{
@@ -112,36 +127,9 @@ namespace v2rayN.Handler
return SqliteHelper.Instance.Table<ProfileItem>().FirstOrDefault(it => it.indexId == indexId);
}
public Task SetTestResult(string indexId, string delayVal, string speedVal)
{
string sql = string.Empty;
if (!Utils.IsNullOrEmpty(delayVal) && !Utils.IsNullOrEmpty(speedVal))
{
int.TryParse(delayVal, out int delay);
decimal.TryParse(speedVal, out decimal speed);
sql = $"update ProfileItem set delay={delay},speed={speed} where indexId = '{indexId}'";
}
else if (!Utils.IsNullOrEmpty(delayVal))
{
int.TryParse(delayVal, out int delay);
sql = $"update ProfileItem set delay={delay} where indexId = '{indexId}'";
}
else if (!Utils.IsNullOrEmpty(speedVal))
{
decimal.TryParse(speedVal, out decimal speed);
sql = $"update ProfileItem set speed={speed} where indexId = '{indexId}'";
}
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();
return SqliteHelper.Instance.Table<RoutingItem>().Where(it => it.locked == false).OrderBy(t => t.sort).ToList();
}
public RoutingItem GetRoutingItem(string id)
{
@@ -185,7 +173,7 @@ namespace v2rayN.Handler
return item.coreType;
}
public CoreInfo GetCoreInfo(ECoreType coreType)
public CoreInfo? GetCoreInfo(ECoreType coreType)
{
if (coreInfos == null)
{
@@ -194,7 +182,7 @@ namespace v2rayN.Handler
return coreInfos.Where(t => t.coreType == coreType).FirstOrDefault();
}
public List<CoreInfo> GetCoreInfos()
public List<CoreInfo>? GetCoreInfos()
{
if (coreInfos == null)
{
@@ -205,13 +193,13 @@ namespace v2rayN.Handler
private void InitCoreInfo()
{
coreInfos = new List<CoreInfo>();
coreInfos = new(16);
coreInfos.Add(new CoreInfo
{
coreType = ECoreType.v2rayN,
coreUrl = Global.NUrl,
coreReleaseApiUrl = Global.NUrl.Replace(@"https://github.com", @"https://api.github.com/repos"),
coreReleaseApiUrl = Global.NUrl.Replace(Global.githubUrl, Global.githubApiUrl),
coreDownloadUrl32 = Global.NUrl + "/download/{0}/v2rayN.zip",
coreDownloadUrl64 = Global.NUrl + "/download/{0}/v2rayN.zip",
});
@@ -222,7 +210,7 @@ namespace v2rayN.Handler
coreExes = new List<string> { "wv2ray", "v2ray" },
arguments = "",
coreUrl = Global.v2flyCoreUrl,
coreReleaseApiUrl = Global.v2flyCoreUrl.Replace(@"https://github.com", @"https://api.github.com/repos"),
coreReleaseApiUrl = Global.v2flyCoreUrl.Replace(Global.githubUrl, Global.githubApiUrl),
coreDownloadUrl32 = Global.v2flyCoreUrl + "/download/{0}/v2ray-windows-{1}.zip",
coreDownloadUrl64 = Global.v2flyCoreUrl + "/download/{0}/v2ray-windows-{1}.zip",
match = "V2Ray",
@@ -236,7 +224,7 @@ namespace v2rayN.Handler
coreExes = new List<string> { "SagerNet", "v2ray" },
arguments = "run",
coreUrl = Global.SagerNetCoreUrl,
coreReleaseApiUrl = Global.SagerNetCoreUrl.Replace(@"https://github.com", @"https://api.github.com/repos"),
coreReleaseApiUrl = Global.SagerNetCoreUrl.Replace(Global.githubUrl, Global.githubApiUrl),
coreDownloadUrl32 = Global.SagerNetCoreUrl + "/download/{0}/v2ray-windows-{1}.zip",
coreDownloadUrl64 = Global.SagerNetCoreUrl + "/download/{0}/v2ray-windows-{1}.zip",
match = "V2Ray",
@@ -250,7 +238,7 @@ namespace v2rayN.Handler
coreExes = new List<string> { "v2ray" },
arguments = "run",
coreUrl = Global.v2flyCoreUrl,
coreReleaseApiUrl = Global.v2flyCoreUrl.Replace(@"https://github.com", @"https://api.github.com/repos"),
coreReleaseApiUrl = Global.v2flyCoreUrl.Replace(Global.githubUrl, Global.githubApiUrl),
coreDownloadUrl32 = Global.v2flyCoreUrl + "/download/{0}/v2ray-windows-{1}.zip",
coreDownloadUrl64 = Global.v2flyCoreUrl + "/download/{0}/v2ray-windows-{1}.zip",
match = "V2Ray",
@@ -264,7 +252,7 @@ namespace v2rayN.Handler
coreExes = new List<string> { "xray", "wxray" },
arguments = "",
coreUrl = Global.xrayCoreUrl,
coreReleaseApiUrl = Global.xrayCoreUrl.Replace(@"https://github.com", @"https://api.github.com/repos"),
coreReleaseApiUrl = Global.xrayCoreUrl.Replace(Global.githubUrl, Global.githubApiUrl),
coreDownloadUrl32 = Global.xrayCoreUrl + "/download/{0}/Xray-windows-{1}.zip",
coreDownloadUrl64 = Global.xrayCoreUrl + "/download/{0}/Xray-windows-{1}.zip",
match = "Xray",
@@ -278,7 +266,7 @@ namespace v2rayN.Handler
coreExes = new List<string> { "clash-windows-amd64-v3", "clash-windows-amd64", "clash-windows-386", "clash" },
arguments = "-f config.json",
coreUrl = Global.clashCoreUrl,
coreReleaseApiUrl = Global.clashCoreUrl.Replace(@"https://github.com", @"https://api.github.com/repos"),
coreReleaseApiUrl = Global.clashCoreUrl.Replace(Global.githubUrl, Global.githubApiUrl),
coreDownloadUrl32 = Global.clashCoreUrl + "/download/{0}/clash-windows-386-{0}.zip",
coreDownloadUrl64 = Global.clashCoreUrl + "/download/{0}/clash-windows-amd64-{0}.zip",
match = "v",
@@ -292,7 +280,7 @@ namespace v2rayN.Handler
coreExes = new List<string> { "Clash.Meta-windows-amd64-compatible", "Clash.Meta-windows-amd64", "Clash.Meta-windows-386", "Clash.Meta", "clash" },
arguments = "-f config.json",
coreUrl = Global.clashMetaCoreUrl,
coreReleaseApiUrl = Global.clashMetaCoreUrl.Replace(@"https://github.com", @"https://api.github.com/repos"),
coreReleaseApiUrl = Global.clashMetaCoreUrl.Replace(Global.githubUrl, Global.githubApiUrl),
coreDownloadUrl32 = Global.clashMetaCoreUrl + "/download/{0}/Clash.Meta-windows-386-{0}.zip",
coreDownloadUrl64 = Global.clashMetaCoreUrl + "/download/{0}/Clash.Meta-windows-amd64-compatible-{0}.zip",
match = "v",
@@ -306,7 +294,7 @@ namespace v2rayN.Handler
coreExes = new List<string> { "hysteria-windows-amd64", "hysteria-windows-386", "hysteria" },
arguments = "",
coreUrl = Global.hysteriaCoreUrl,
coreReleaseApiUrl = Global.hysteriaCoreUrl.Replace(@"https://github.com", @"https://api.github.com/repos"),
coreReleaseApiUrl = Global.hysteriaCoreUrl.Replace(Global.githubUrl, Global.githubApiUrl),
coreDownloadUrl32 = Global.hysteriaCoreUrl + "/download/{0}/hysteria-windows-386.exe",
coreDownloadUrl64 = Global.hysteriaCoreUrl + "/download/{0}/hysteria-windows-amd64.exe",
redirectInfo = true,

View File

@@ -12,7 +12,7 @@ namespace v2rayN.Handler
{
public sealed class MainFormHandler
{
private static readonly Lazy<MainFormHandler> instance = new Lazy<MainFormHandler>(() => new MainFormHandler());
private static readonly Lazy<MainFormHandler> instance = new(() => new());
//Action<bool, string> _updateUI;
//private DownloadHandle downloadHandle2;
@@ -42,19 +42,14 @@ namespace v2rayN.Handler
{
return new Icon(fileName);
}
switch (index)
return index switch
{
case 0:
return Properties.Resources.NotifyIcon1;
case 1:
return Properties.Resources.NotifyIcon2;
case 2:
return Properties.Resources.NotifyIcon3;
case 3:
return Properties.Resources.NotifyIcon2;
}
return Properties.Resources.NotifyIcon1;
0 => Properties.Resources.NotifyIcon1,
1 => Properties.Resources.NotifyIcon2,
2 => Properties.Resources.NotifyIcon3,
3 => Properties.Resources.NotifyIcon2,
_ => Properties.Resources.NotifyIcon1, // default
};
}
catch (Exception ex)
{
@@ -82,11 +77,11 @@ namespace v2rayN.Handler
return BitmapFrame.Create(new Uri($"pack://application:,,,/Resources/NotifyIcon{index}.ico", UriKind.RelativeOrAbsolute));
}
private Icon GetNotifyIcon4Routing(Config config)
private Icon? GetNotifyIcon4Routing(Config config)
{
try
{
if (!config.enableRoutingAdvanced)
if (!config.routingBasicItem.enableRoutingAdvanced)
{
return null;
}
@@ -107,9 +102,9 @@ namespace v2rayN.Handler
int width = 128;
int height = 128;
Bitmap bitmap = new Bitmap(width, height);
Bitmap bitmap = new(width, height);
Graphics graphics = Graphics.FromImage(bitmap);
SolidBrush drawBrush = new SolidBrush(color);
SolidBrush drawBrush = new(color);
graphics.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.AntiAlias;
//graphics.FillRectangle(drawBrush, new Rectangle(0, 0, width, height));
@@ -143,7 +138,7 @@ namespace v2rayN.Handler
return;
}
SaveFileDialog fileDialog = new SaveFileDialog
SaveFileDialog fileDialog = new()
{
Filter = "Config|*.json",
FilterIndex = 2,
@@ -176,14 +171,13 @@ namespace v2rayN.Handler
{
return;
}
if (item.configType != EConfigType.VMess
&& item.configType != EConfigType.VLESS)
if (item.configType is not EConfigType.VMess and not EConfigType.VLESS)
{
UI.Show(ResUI.NonVmessService);
return;
}
SaveFileDialog fileDialog = new SaveFileDialog
SaveFileDialog fileDialog = new()
{
Filter = "Config|*.json",
FilterIndex = 2,
@@ -212,14 +206,14 @@ namespace v2rayN.Handler
public void BackupGuiNConfig(Config config, bool auto = false)
{
string fileName = $"guiNConfig_{DateTime.Now.ToString("yyyy_MM_dd_HH_mm_ss_fff")}.json";
string fileName = $"guiNConfig_{DateTime.Now:yyyy_MM_dd_HH_mm_ss_fff}.json";
if (auto)
{
fileName = Utils.GetBackupPath(fileName);
}
else
{
SaveFileDialog fileDialog = new SaveFileDialog
SaveFileDialog fileDialog = new()
{
FileName = fileName,
Filter = "guiNConfig|*.json",
@@ -254,7 +248,7 @@ namespace v2rayN.Handler
public bool RestoreGuiNConfig(ref Config config)
{
var fileContent = string.Empty;
using (OpenFileDialog fileDialog = new OpenFileDialog())
using (OpenFileDialog fileDialog = new())
{
fileDialog.InitialDirectory = Utils.GetBackupPath("");
fileDialog.Filter = "guiNConfig|*.json|All|*.*";
@@ -286,7 +280,7 @@ namespace v2rayN.Handler
BackupGuiNConfig(config, true);
config = resConfig;
LazyConfig.Instance.SetConfig(ref config);
LazyConfig.Instance.SetConfig(config);
return true;
}
@@ -309,9 +303,9 @@ namespace v2rayN.Handler
{
var dtNow = DateTime.Now;
if (config.autoUpdateSubInterval > 0)
if (config.guiItem.autoUpdateSubInterval > 0)
{
if ((dtNow - autoUpdateSubTime).Hours % config.autoUpdateSubInterval == 0)
if ((dtNow - autoUpdateSubTime).Hours % config.guiItem.autoUpdateSubInterval == 0)
{
updateHandle.UpdateSubscriptionProcess(config, "", true, (bool success, string msg) =>
{
@@ -324,9 +318,9 @@ namespace v2rayN.Handler
Thread.Sleep(60000);
}
if (config.autoUpdateInterval > 0)
if (config.guiItem.autoUpdateInterval > 0)
{
if ((dtNow - autoUpdateGeoTime).Hours % config.autoUpdateInterval == 0)
if ((dtNow - autoUpdateGeoTime).Hours % config.guiItem.autoUpdateInterval == 0)
{
updateHandle.UpdateGeoFile("geosite", config, (bool success, string msg) =>
{
@@ -381,12 +375,12 @@ namespace v2rayN.Handler
try
{
HotkeyManager.Current.AddOrReplace(((int)item.eGlobalHotkey).ToString(), gesture, handler);
var msg = string.Format(ResUI.RegisterGlobalHotkeySuccessfully, $"{item.eGlobalHotkey.ToString()}");
var msg = string.Format(ResUI.RegisterGlobalHotkeySuccessfully, $"{item.eGlobalHotkey}");
update(false, msg);
}
catch (Exception ex)
{
var msg = string.Format(ResUI.RegisterGlobalHotkeyFailed, $"{item.eGlobalHotkey.ToString()}", ex.Message);
var msg = string.Format(ResUI.RegisterGlobalHotkeyFailed, $"{item.eGlobalHotkey}", ex.Message);
update(false, msg);
Utils.SaveLog(msg);
}

View File

@@ -0,0 +1,114 @@
using v2rayN.Base;
using v2rayN.Mode;
namespace v2rayN.Handler
{
class ProfileExHandler
{
private static readonly Lazy<ProfileExHandler> _instance = new(() => new());
private List<ProfileExItem> _lstProfileEx;
public List<ProfileExItem> ProfileExs => _lstProfileEx;
public static ProfileExHandler Instance => _instance.Value;
public ProfileExHandler()
{
Init();
}
private void Init()
{
SqliteHelper.Instance.Execute($"delete from ProfileExItem where indexId not in ( select indexId from ProfileItem )");
_lstProfileEx = SqliteHelper.Instance.Table<ProfileExItem>().ToList();
}
private void AddProfileEx(string indexId, ref ProfileExItem profileEx)
{
profileEx = new()
{
indexId = indexId,
delay = 0,
speed = 0,
sort = 0
};
_lstProfileEx.Add(profileEx);
//SqliteHelper.Instance.Replace(profileEx);
}
public void ClearAll()
{
SqliteHelper.Instance.Execute($"delete from ProfileExItem ");
_lstProfileEx = new();
}
public void SaveTo()
{
try
{
foreach (var item in _lstProfileEx)
{
SqliteHelper.Instance.Replace(item);
}
//SqliteHelper.Instance.UpdateAll(_lstProfileEx);
}
catch (Exception ex)
{
Utils.SaveLog(ex.Message, ex);
}
}
public Task SetTestDelay(string indexId, string delayVal)
{
var profileEx = _lstProfileEx.FirstOrDefault(t => t.indexId == indexId);
if (profileEx == null)
{
AddProfileEx(indexId, ref profileEx);
}
int.TryParse(delayVal, out int delay);
profileEx.delay = delay;
return Task.CompletedTask;
}
public Task SetTestSpeed(string indexId, string speedVal)
{
var profileEx = _lstProfileEx.FirstOrDefault(t => t.indexId == indexId);
if (profileEx == null)
{
AddProfileEx(indexId, ref profileEx);
}
decimal.TryParse(speedVal, out decimal speed);
profileEx.speed = speed;
return Task.CompletedTask;
}
public void SetSort(string indexId, int sort)
{
var profileEx = _lstProfileEx.FirstOrDefault(t => t.indexId == indexId);
if (profileEx == null)
{
AddProfileEx(indexId, ref profileEx);
}
profileEx.sort = sort;
}
public int GetSort(string indexId)
{
var profileEx = _lstProfileEx.FirstOrDefault(t => t.indexId == indexId);
if (profileEx == null)
{
return 0;
}
return profileEx.sort;
}
public int GetMaxSort()
{
if (_lstProfileEx.Count <= 0)
{
return 0;
}
return _lstProfileEx.Max(t => t == null ? 0 : t.sort);
}
}
}

View File

@@ -10,16 +10,16 @@ namespace v2rayN.Handler
return SetProxy(null, null, 1);
}
public static bool SetProxy(string strProxy, string exceptions, int type)
public static bool SetProxy(string? strProxy, string? exceptions, int type)
{
InternetPerConnOptionList list = new InternetPerConnOptionList();
InternetPerConnOptionList list = new();
int optionCount = 1;
if (type == 1)
{
optionCount = 1;
}
else if (type == 2 || type == 4)
else if (type is 2 or 4)
{
optionCount = Utils.IsNullOrEmpty(exceptions) ? 2 : 3;
}
@@ -71,12 +71,12 @@ namespace v2rayN.Handler
{
if (Environment.Is64BitOperatingSystem)
{
IntPtr opt = new IntPtr(optionsPtr.ToInt64() + (i * optSize));
IntPtr opt = new(optionsPtr.ToInt64() + (i * optSize));
Marshal.StructureToPtr(options[i], opt, false);
}
else
{
IntPtr opt = new IntPtr(optionsPtr.ToInt32() + (i * optSize));
IntPtr opt = new(optionsPtr.ToInt32() + (i * optSize));
Marshal.StructureToPtr(options[i], opt, false);
}
}
@@ -84,7 +84,7 @@ namespace v2rayN.Handler
list.options = optionsPtr;
// and then make a pointer out of the whole list
IntPtr ipcoListPtr = Marshal.AllocCoTaskMem((int)list.dwSize);
IntPtr ipcoListPtr = Marshal.AllocCoTaskMem(list.dwSize);
Marshal.StructureToPtr(list, ipcoListPtr, false);
// and finally, call the API method!
@@ -189,24 +189,21 @@ namespace v2rayN.Handler
//判断是否使用代理
public static bool UsedProxy()
{
RegistryKey rk = Registry.CurrentUser.OpenSubKey(@"Software\Microsoft\Windows\CurrentVersion\Internet Settings", true);
if (rk.GetValue("ProxyEnable").ToString() == "1")
using RegistryKey? rk = Registry.CurrentUser.OpenSubKey(@"Software\Microsoft\Windows\CurrentVersion\Internet Settings", true);
if (rk?.GetValue("ProxyEnable")?.ToString() == "1")
{
rk.Close();
return true;
}
else
{
rk.Close();
return false;
}
}
//获得代理的IP和端口
public static string GetProxyProxyServer()
public static string? GetProxyProxyServer()
{
RegistryKey rk = Registry.CurrentUser.OpenSubKey(@"Software\Microsoft\Windows\CurrentVersion\Internet Settings", true);
using RegistryKey? rk = Registry.CurrentUser.OpenSubKey(@"Software\Microsoft\Windows\CurrentVersion\Internet Settings", true);
string ProxyServer = rk.GetValue("ProxyServer").ToString();
rk.Close();
return ProxyServer;
}

View File

@@ -9,13 +9,13 @@ namespace v2rayN.Handler
/// </summary>
public class QRCodeHelper
{
public static DrawingImage GetQRCode(string strContent)
public static DrawingImage? GetQRCode(string strContent)
{
try
{
QRCodeGenerator qrGenerator = new QRCodeGenerator();
QRCodeGenerator qrGenerator = new();
QRCodeData qrCodeData = qrGenerator.CreateQrCode(strContent, QRCodeGenerator.ECCLevel.H);
XamlQRCode qrCode = new XamlQRCode(qrCodeData);
XamlQRCode qrCode = new(qrCodeData);
DrawingImage qrCodeAsXaml = qrCode.GetGraphic(40);
return qrCodeAsXaml;
}

View File

@@ -17,32 +17,22 @@ namespace v2rayN.Handler
/// </summary>
/// <param name="item"></param>
/// <returns></returns>
public static string GetShareUrl(ProfileItem item)
public static string? GetShareUrl(ProfileItem item)
{
try
{
string url = string.Empty;
string? url = string.Empty;
switch (item.configType)
url = item.configType switch
{
case EConfigType.VMess:
url = ShareVmess(item);
break;
case EConfigType.Shadowsocks:
url = ShareShadowsocks(item);
break;
case EConfigType.Socks:
url = ShareSocks(item);
break;
case EConfigType.Trojan:
url = ShareTrojan(item);
break;
case EConfigType.VLESS:
url = ShareVLESS(item);
break;
default:
break;
}
EConfigType.VMess => ShareVmess(item),
EConfigType.Shadowsocks => ShareShadowsocks(item),
EConfigType.Socks => ShareSocks(item),
EConfigType.Trojan => ShareTrojan(item),
EConfigType.VLESS => ShareVLESS(item),
_ => null,
};
return url;
}
catch (Exception ex)
@@ -56,7 +46,7 @@ namespace v2rayN.Handler
{
string url = string.Empty;
VmessQRCode vmessQRCode = new VmessQRCode
VmessQRCode vmessQRCode = new()
{
v = item.configVersion.ToString(),
ps = item.remarks.TrimEx(), //备注也许很长 ;
@@ -71,7 +61,8 @@ namespace v2rayN.Handler
path = item.path,
tls = item.streamSecurity,
sni = item.sni,
alpn = item.alpn
alpn = item.alpn,
fp = item.fingerprint
};
url = Utils.ToJson(vmessQRCode);
@@ -176,7 +167,7 @@ namespace v2rayN.Handler
return Utils.IsIpv6(address) ? $"[{address}]" : address;
}
private static int GetStdTransport(ProfileItem item, string securityDef, ref Dictionary<string, string> dicQuery)
private static int GetStdTransport(ProfileItem item, string? securityDef, ref Dictionary<string, string> dicQuery)
{
if (!Utils.IsNullOrEmpty(item.flow))
{
@@ -202,6 +193,10 @@ namespace v2rayN.Handler
{
dicQuery.Add("alpn", Utils.UrlEncode(item.alpn));
}
if (!Utils.IsNullOrEmpty(item.fingerprint))
{
dicQuery.Add("fp", Utils.UrlEncode(item.fingerprint));
}
dicQuery.Add("type", !Utils.IsNullOrEmpty(item.network) ? item.network : "tcp");
@@ -255,7 +250,7 @@ namespace v2rayN.Handler
if (!Utils.IsNullOrEmpty(item.path))
{
dicQuery.Add("serviceName", Utils.UrlEncode(item.path));
if (item.headerType == Global.GrpcgunMode || item.headerType == Global.GrpcmultiMode)
if (item.headerType is Global.GrpcgunMode or Global.GrpcmultiMode)
{
dicQuery.Add("mode", Utils.UrlEncode(item.headerType));
}
@@ -273,13 +268,13 @@ namespace v2rayN.Handler
/// <summary>
/// 从剪贴板导入URL
/// </summary>
/// <param name="fileName"></param>
/// <param name="msg"></param>
/// <returns></returns>
public static ProfileItem ImportFromClipboardConfig(string clipboardData, out string msg)
public static ProfileItem? ImportFromClipboardConfig(string clipboardData, out string msg)
{
msg = string.Empty;
ProfileItem profileItem = new ProfileItem();
ProfileItem profileItem = new();
try
{
@@ -363,7 +358,7 @@ namespace v2rayN.Handler
return profileItem;
}
private static ProfileItem ResolveVmess(string result, out string msg)
private static ProfileItem? ResolveVmess(string result, out string msg)
{
msg = string.Empty;
var profileItem = new ProfileItem
@@ -371,11 +366,11 @@ namespace v2rayN.Handler
configType = EConfigType.VMess
};
result = result.Substring(Global.vmessProtocol.Length);
result = result[Global.vmessProtocol.Length..];
result = Utils.Base64Decode(result);
//转成Json
VmessQRCode vmessQRCode = Utils.FromJson<VmessQRCode>(result);
VmessQRCode? vmessQRCode = Utils.FromJson<VmessQRCode>(result);
if (vmessQRCode == null)
{
msg = ResUI.FailedConversionConfiguration;
@@ -408,21 +403,22 @@ namespace v2rayN.Handler
profileItem.streamSecurity = Utils.ToString(vmessQRCode.tls);
profileItem.sni = Utils.ToString(vmessQRCode.sni);
profileItem.alpn = Utils.ToString(vmessQRCode.alpn);
profileItem.fingerprint = Utils.ToString(vmessQRCode.fp);
return profileItem;
}
private static ProfileItem ResolveVmess4Kitsunebi(string result)
private static ProfileItem? ResolveVmess4Kitsunebi(string result)
{
ProfileItem profileItem = new ProfileItem
ProfileItem profileItem = new()
{
configType = EConfigType.VMess
};
result = result.Substring(Global.vmessProtocol.Length);
result = result[Global.vmessProtocol.Length..];
int indexSplit = result.IndexOf("?");
if (indexSplit > 0)
{
result = result.Substring(0, indexSplit);
result = result[..indexSplit];
}
result = Utils.Base64Decode(result);
@@ -433,7 +429,7 @@ namespace v2rayN.Handler
}
string[] arr21 = arr1[0].Split(':');
string[] arr22 = arr1[1].Split(':');
if (arr21.Length != 2 || arr21.Length != 2)
if (arr21.Length != 2 || arr22.Length != 2)
{
return null;
}
@@ -450,15 +446,15 @@ namespace v2rayN.Handler
return profileItem;
}
private static ProfileItem ResolveStdVmess(string result)
private static ProfileItem? ResolveStdVmess(string result)
{
ProfileItem i = new ProfileItem
ProfileItem i = new()
{
configType = EConfigType.VMess,
security = "auto"
};
Uri u = new Uri(result);
Uri u = new(result);
i.address = u.IdnHost;
i.port = u.Port;
@@ -531,7 +527,7 @@ namespace v2rayN.Handler
return i;
}
private static ProfileItem ResolveSip002(string result)
private static ProfileItem? ResolveSip002(string result)
{
Uri parsedUrl;
try
@@ -542,7 +538,7 @@ namespace v2rayN.Handler
{
return null;
}
ProfileItem server = new ProfileItem
ProfileItem server = new()
{
remarks = parsedUrl.GetComponents(UriComponents.Fragment, UriFormat.Unescaped),
address = parsedUrl.IdnHost,
@@ -550,7 +546,7 @@ namespace v2rayN.Handler
};
string rawUserInfo = parsedUrl.GetComponents(UriComponents.UserInfo, UriFormat.UriEscaped);
//2022-blake3
if (rawUserInfo.Contains(":"))
if (rawUserInfo.Contains(':'))
{
string[] userInfoParts = rawUserInfo.Split(new[] { ':' }, 2);
if (userInfoParts.Length != 2)
@@ -594,16 +590,16 @@ namespace v2rayN.Handler
return server;
}
private static readonly Regex UrlFinder = new Regex(@"ss://(?<base64>[A-Za-z0-9+-/=_]+)(?:#(?<tag>\S+))?", RegexOptions.IgnoreCase);
private static readonly Regex DetailsParser = new Regex(@"^((?<method>.+?):(?<password>.*)@(?<hostname>.+?):(?<port>\d+?))$", RegexOptions.IgnoreCase);
private static readonly Regex UrlFinder = new(@"ss://(?<base64>[A-Za-z0-9+-/=_]+)(?:#(?<tag>\S+))?", RegexOptions.IgnoreCase | RegexOptions.Compiled);
private static readonly Regex DetailsParser = new(@"^((?<method>.+?):(?<password>.*)@(?<hostname>.+?):(?<port>\d+?))$", RegexOptions.IgnoreCase | RegexOptions.Compiled);
private static ProfileItem ResolveSSLegacy(string result)
private static ProfileItem? ResolveSSLegacy(string result)
{
var match = UrlFinder.Match(result);
if (!match.Success)
return null;
ProfileItem server = new ProfileItem();
ProfileItem server = new();
var base64 = match.Groups["base64"].Value.TrimEnd('/');
var tag = match.Groups["tag"].Value;
if (!Utils.IsNullOrEmpty(tag))
@@ -629,16 +625,16 @@ namespace v2rayN.Handler
}
private static readonly Regex StdVmessUserInfo = new Regex(
@"^(?<network>[a-z]+)(\+(?<streamSecurity>[a-z]+))?:(?<id>[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12})$");
private static readonly Regex StdVmessUserInfo = new(
@"^(?<network>[a-z]+)(\+(?<streamSecurity>[a-z]+))?:(?<id>[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12})$", RegexOptions.Compiled);
private static ProfileItem ResolveSocks(string result)
private static ProfileItem? ResolveSocks(string result)
{
ProfileItem profileItem = new ProfileItem
ProfileItem profileItem = new()
{
configType = EConfigType.Socks
};
result = result.Substring(Global.socksProtocol.Length);
result = result[Global.socksProtocol.Length..];
//remark
int indexRemark = result.IndexOf("#");
if (indexRemark > 0)
@@ -648,7 +644,7 @@ namespace v2rayN.Handler
profileItem.remarks = Utils.UrlDecode(result.Substring(indexRemark + 1, result.Length - indexRemark - 1));
}
catch { }
result = result.Substring(0, indexRemark);
result = result[..indexRemark];
}
//part decode
int indexS = result.IndexOf("@");
@@ -672,15 +668,15 @@ namespace v2rayN.Handler
{
return null;
}
profileItem.address = arr1[1].Substring(0, indexPort);
profileItem.port = Utils.ToInt(arr1[1].Substring(indexPort + 1, arr1[1].Length - (indexPort + 1)));
profileItem.address = arr1[1][..indexPort];
profileItem.port = Utils.ToInt(arr1[1][(indexPort + 1)..]);
profileItem.security = arr21[0];
profileItem.id = arr21[1];
return profileItem;
}
private static ProfileItem ResolveSocksNew(string result)
private static ProfileItem? ResolveSocksNew(string result)
{
Uri parsedUrl;
try
@@ -691,7 +687,7 @@ namespace v2rayN.Handler
{
return null;
}
ProfileItem server = new ProfileItem
ProfileItem server = new()
{
remarks = parsedUrl.GetComponents(UriComponents.Fragment, UriFormat.Unescaped),
address = parsedUrl.IdnHost,
@@ -713,12 +709,12 @@ namespace v2rayN.Handler
private static ProfileItem ResolveTrojan(string result)
{
ProfileItem item = new ProfileItem
ProfileItem item = new()
{
configType = EConfigType.Trojan
};
Uri url = new Uri(result);
Uri url = new(result);
item.address = url.IdnHost;
item.port = url.Port;
@@ -732,13 +728,13 @@ namespace v2rayN.Handler
}
private static ProfileItem ResolveStdVLESS(string result)
{
ProfileItem item = new ProfileItem
ProfileItem item = new()
{
configType = EConfigType.VLESS,
security = "none"
};
Uri url = new Uri(result);
Uri url = new(result);
item.address = url.IdnHost;
item.port = url.Port;
@@ -759,6 +755,7 @@ namespace v2rayN.Handler
item.streamSecurity = query["security"] ?? "";
item.sni = query["sni"] ?? "";
item.alpn = Utils.UrlDecode(query["alpn"] ?? "");
item.fingerprint = Utils.UrlDecode(query["fp"] ?? "");
item.network = query["type"] ?? "tcp";
switch (item.network)
{

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,12 +24,20 @@ namespace v2rayN.Handler
{
_config = config;
_coreHandler = coreHandler;
//_selecteds = Utils.DeepCopy(selecteds);
_actionType = actionType;
_updateFunc = update;
_selecteds = new List<ServerTestItem>();
foreach (var it in selecteds)
{
if (it.configType == EConfigType.Custom)
{
continue;
}
if (it.port <= 0)
{
continue;
}
_selecteds.Add(new ServerTestItem()
{
indexId = it.indexId,
@@ -37,6 +46,25 @@ namespace v2rayN.Handler
configType = it.configType
});
}
//clear test result
foreach (var it in _selecteds)
{
switch (actionType)
{
case ESpeedActionType.Ping:
case ESpeedActionType.Tcping:
case ESpeedActionType.Realping:
UpdateFunc(it.indexId, ResUI.Speedtesting, "");
break;
case ESpeedActionType.Speedtest:
UpdateFunc(it.indexId, "", ResUI.Speedtesting);
break;
case ESpeedActionType.Mixedtest:
UpdateFunc(it.indexId, ResUI.Speedtesting, ResUI.Speedtesting);
break;
}
}
switch (actionType)
{
case ESpeedActionType.Ping:
@@ -84,29 +112,29 @@ namespace v2rayN.Handler
private void RunPing()
{
RunPingSub((ServerTestItem it) =>
RunPingSub(async (ServerTestItem it) =>
{
long time = Ping(it.address);
var output = FormatOut(time, Global.DelayUnit);
LazyConfig.Instance.SetTestResult(it.indexId, output, "");
await ProfileExHandler.Instance.SetTestDelay(it.indexId, output);
UpdateFunc(it.indexId, output);
});
}
private void RunTcping()
{
RunPingSub((ServerTestItem it) =>
RunPingSub(async (ServerTestItem it) =>
{
int time = GetTcpingTime(it.address, it.port);
var output = FormatOut(time, Global.DelayUnit);
LazyConfig.Instance.SetTestResult(it.indexId, output, "");
await ProfileExHandler.Instance.SetTestDelay(it.indexId, output);
UpdateFunc(it.indexId, output);
});
}
private async Task RunRealPing()
private Task RunRealPing()
{
int pid = -1;
try
@@ -117,12 +145,12 @@ namespace v2rayN.Handler
if (pid < 0)
{
UpdateFunc("", ResUI.FailedToRunCore);
return;
return Task.CompletedTask;
}
DownloadHandle downloadHandle = new DownloadHandle();
//Thread.Sleep(5000);
List<Task> tasks = new List<Task>();
List<Task> tasks = new();
foreach (var it in _selecteds)
{
if (!it.allowTest)
@@ -133,17 +161,18 @@ namespace v2rayN.Handler
{
continue;
}
tasks.Add(Task.Run(() =>
tasks.Add(Task.Run(async () =>
{
try
{
LazyConfig.Instance.SetTestResult(it.indexId, "-1", "");
WebProxy webProxy = new WebProxy(Global.Loopback, it.port);
WebProxy webProxy = new(Global.Loopback, it.port);
string output = GetRealPingTime(downloadHandle, webProxy);
LazyConfig.Instance.SetTestResult(it.indexId, output, "");
await ProfileExHandler.Instance.SetTestDelay(it.indexId, output);
UpdateFunc(it.indexId, output);
int.TryParse(output, out int delay);
it.delay = delay;
}
catch (Exception ex)
{
@@ -161,12 +190,19 @@ namespace v2rayN.Handler
finally
{
if (pid > 0) _coreHandler.CoreStopPid(pid);
ProfileExHandler.Instance.SaveTo();
}
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)
@@ -175,14 +211,13 @@ namespace v2rayN.Handler
return;
}
string url = _config.constItem.speedTestUrl;
DownloadHandle downloadHandle = new DownloadHandle();
string url = _config.speedTestItem.speedTestUrl;
var timeout = _config.speedTestItem.speedTestTimeout;
DownloadHandle downloadHandle = new();
var timeout = 10;
foreach (var it in _selecteds)
{
_ = LazyConfig.Instance.SetTestResult(it.indexId, "", "-1");
UpdateFunc(it.indexId, "", ResUI.Speedtesting);
if (!it.allowTest)
{
continue;
@@ -191,19 +226,24 @@ namespace v2rayN.Handler
{
continue;
}
testIndexId = it.indexId;
//if (it.delay < 0)
//{
// UpdateFunc(it.indexId, "", ResUI.SpeedtestingSkip);
// continue;
//}
await ProfileExHandler.Instance.SetTestSpeed(it.indexId, "-1");
var item = LazyConfig.Instance.GetProfileItem(it.indexId);
if (item is null) continue;
WebProxy webProxy = new WebProxy(Global.Loopback, it.port);
WebProxy webProxy = new(Global.Loopback, it.port);
await downloadHandle.DownloadDataAsync(url, webProxy, timeout, (bool success, string msg) =>
await downloadHandle.DownloadDataAsync(url, webProxy, timeout, async (bool success, string msg) =>
{
decimal.TryParse(msg, out decimal dec);
if (dec > 0)
{
_ = LazyConfig.Instance.SetTestResult(it.indexId, "", msg);
await ProfileExHandler.Instance.SetTestSpeed(it.indexId, msg);
}
UpdateFunc(it.indexId, "", msg);
});
@@ -213,17 +253,75 @@ namespace v2rayN.Handler
{
_coreHandler.CoreStopPid(pid);
}
UpdateFunc("", ResUI.SpeedtestingCompleted);
ProfileExHandler.Instance.SaveTo();
}
private async Task RunSpeedTestMulti()
{
int pid = -1;
pid = _coreHandler.LoadCoreConfigString(_config, _selecteds);
if (pid < 0)
{
UpdateFunc("", ResUI.FailedToRunCore);
return;
}
string url = _config.speedTestItem.speedTestUrl;
var timeout = _config.speedTestItem.speedTestTimeout;
DownloadHandle downloadHandle = new();
foreach (var it in _selecteds)
{
if (!it.allowTest)
{
continue;
}
if (it.configType == EConfigType.Custom)
{
continue;
}
await ProfileExHandler.Instance.SetTestSpeed(it.indexId, "-1");
var item = LazyConfig.Instance.GetProfileItem(it.indexId);
if (item is null) continue;
WebProxy webProxy = new(Global.Loopback, it.port);
_ = downloadHandle.DownloadDataAsync(url, webProxy, timeout, async (bool success, string msg) =>
{
decimal.TryParse(msg, out decimal dec);
if (dec > 0)
{
await ProfileExHandler.Instance.SetTestSpeed(it.indexId, msg);
}
UpdateFunc(it.indexId, "", msg);
});
Thread.Sleep(2000);
}
Thread.Sleep((timeout + 2) * 1000);
if (pid > 0)
{
_coreHandler.CoreStopPid(pid);
}
UpdateFunc("", ResUI.SpeedtestingCompleted);
ProfileExHandler.Instance.SaveTo();
}
private async Task RunMixedtestAsync()
{
await RunRealPing();
await RunSpeedTestAsync();
Thread.Sleep(1000);
await RunSpeedTestMulti();
}
public string GetRealPingTime(DownloadHandle downloadHandle, WebProxy webProxy)
{
string status = downloadHandle.GetRealPingTime(_config.constItem.speedPingTestUrl, webProxy, 10, out int responseTime);
string status = downloadHandle.GetRealPingTime(_config.speedTestItem.speedPingTestUrl, webProxy, 10, out int responseTime);
//string output = Utils.IsNullOrEmpty(status) ? FormatOut(responseTime, "ms") : status;
return FormatOut(Utils.IsNullOrEmpty(status) ? responseTime : -1, Global.DelayUnit);
}
@@ -240,11 +338,11 @@ namespace v2rayN.Handler
ipAddress = ipHostInfo.AddressList[0];
}
Stopwatch timer = new Stopwatch();
Stopwatch timer = new();
timer.Start();
IPEndPoint endPoint = new IPEndPoint(ipAddress, port);
Socket clientSocket = new Socket(endPoint.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
IPEndPoint endPoint = new(ipAddress, port);
using Socket clientSocket = new(endPoint.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
IAsyncResult result = clientSocket.BeginConnect(endPoint, null, null);
if (!result.AsyncWaitHandle.WaitOne(TimeSpan.FromSeconds(5)))
@@ -253,7 +351,6 @@ namespace v2rayN.Handler
timer.Stop();
responseTime = timer.Elapsed.Milliseconds;
clientSocket.Close();
}
catch (Exception ex)
{
@@ -275,7 +372,7 @@ namespace v2rayN.Handler
{
int timeout = 30;
int echoNum = 2;
Ping pingSender = new Ping();
using Ping pingSender = new();
for (int i = 0; i < echoNum; i++)
{
PingReply reply = pingSender.Send(host, timeout);

View File

@@ -13,7 +13,9 @@ namespace v2rayN.Handler
private Channel channel_;
private StatsService.StatsServiceClient client_;
private bool exitFlag_;
private ServerStatItem _serverStatItem;
private ServerStatItem? _serverStatItem;
private List<ServerStatItem> _lstServerStat;
public List<ServerStatItem> ServerStat => _lstServerStat;
Action<ServerSpeedItem> updateFunc_;
@@ -25,7 +27,7 @@ namespace v2rayN.Handler
public StatisticsHandler(Mode.Config config, Action<ServerSpeedItem> update)
{
config_ = config;
Enable = config.enableStatistics;
Enable = config.guiItem.enableStatistics;
updateFunc_ = update;
exitFlag_ = false;
@@ -68,7 +70,7 @@ namespace v2rayN.Handler
{
if (Enable && channel_.State == ChannelState.Ready)
{
QueryStatsResponse res = null;
QueryStatsResponse? res = null;
try
{
res = client_.QueryStats(new QueryStatsRequest() { Pattern = "", Reset = true });
@@ -83,11 +85,13 @@ 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;
@@ -97,14 +101,9 @@ namespace v2rayN.Handler
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;
var sleep = config_.guiItem.statisticsFreshRate < 1 ? 1 : config_.guiItem.statisticsFreshRate;
Thread.Sleep(1000 * sleep);
channel_.ConnectAsync();
}
@@ -118,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)
@@ -136,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
@@ -149,6 +163,7 @@ namespace v2rayN.Handler
dateNow = ticks
};
_ = SqliteHelper.Instance.Replacesync(_serverStatItem);
_lstServerStat.Add(_serverStatItem);
}
}
@@ -214,7 +229,7 @@ namespace v2rayN.Handler
try
{
// TCP stack please do me a favor
TcpListener l = new TcpListener(IPAddress.Loopback, 0);
TcpListener l = new(IPAddress.Loopback, 0);
l.Start();
int port = ((IPEndPoint)l.LocalEndpoint).Port;
l.Stop();

View File

@@ -20,7 +20,7 @@ namespace v2rayN.Handler
// <proxy-server><CR-LF>
// <bypass-list><CR-LF>
// <pac-url>
private static SysproxyConfig _userSettings = null;
private static SysproxyConfig? _userSettings = null;
enum RET_ERRORS : int
{
@@ -154,85 +154,82 @@ namespace v2rayN.Handler
// using event to avoid hanging when redirect standard output/error
// ref: https://stackoverflow.com/questions/139593/processstartinfo-hanging-on-waitforexit-why
// and http://blog.csdn.net/zhangweixing0/article/details/7356841
using (AutoResetEvent outputWaitHandle = new AutoResetEvent(false))
using (AutoResetEvent errorWaitHandle = new AutoResetEvent(false))
using AutoResetEvent outputWaitHandle = new(false);
using AutoResetEvent errorWaitHandle = new(false);
using Process process = new();
// Configure the process using the StartInfo properties.
process.StartInfo.FileName = Utils.GetTempPath("sysproxy.exe");
process.StartInfo.Arguments = arguments;
process.StartInfo.WorkingDirectory = Utils.GetTempPath();
process.StartInfo.WindowStyle = ProcessWindowStyle.Hidden;
process.StartInfo.UseShellExecute = false;
process.StartInfo.RedirectStandardError = true;
process.StartInfo.RedirectStandardOutput = true;
// Need to provide encoding info, or output/error strings we got will be wrong.
process.StartInfo.StandardOutputEncoding = Encoding.Unicode;
process.StartInfo.StandardErrorEncoding = Encoding.Unicode;
process.StartInfo.CreateNoWindow = true;
StringBuilder output = new(1024);
StringBuilder error = new(1024);
process.OutputDataReceived += (sender, e) =>
{
using (Process process = new Process())
if (e.Data == null)
{
// Configure the process using the StartInfo properties.
process.StartInfo.FileName = Utils.GetTempPath("sysproxy.exe");
process.StartInfo.Arguments = arguments;
process.StartInfo.WorkingDirectory = Utils.GetTempPath();
process.StartInfo.WindowStyle = ProcessWindowStyle.Hidden;
process.StartInfo.UseShellExecute = false;
process.StartInfo.RedirectStandardError = true;
process.StartInfo.RedirectStandardOutput = true;
// Need to provide encoding info, or output/error strings we got will be wrong.
process.StartInfo.StandardOutputEncoding = Encoding.Unicode;
process.StartInfo.StandardErrorEncoding = Encoding.Unicode;
process.StartInfo.CreateNoWindow = true;
StringBuilder output = new StringBuilder();
StringBuilder error = new StringBuilder();
process.OutputDataReceived += (sender, e) =>
{
if (e.Data == null)
{
outputWaitHandle.Set();
}
else
{
output.AppendLine(e.Data);
}
};
process.ErrorDataReceived += (sender, e) =>
{
if (e.Data == null)
{
errorWaitHandle.Set();
}
else
{
error.AppendLine(e.Data);
}
};
try
{
process.Start();
process.BeginErrorReadLine();
process.BeginOutputReadLine();
process.WaitForExit();
}
catch (System.ComponentModel.Win32Exception e)
{
// log the arguments
throw new Exception(process.StartInfo.Arguments);
}
string stderr = error.ToString();
string stdout = output.ToString();
int exitCode = process.ExitCode;
if (exitCode != (int)RET_ERRORS.RET_NO_ERROR)
{
throw new Exception(stderr);
}
//if (arguments == "query")
//{
// if (stdout.IsNullOrWhiteSpace() || stdout.IsNullOrEmpty())
// {
// throw new Exception("failed to query wininet settings");
// }
// _queryStr = stdout;
//}
outputWaitHandle.Set();
}
else
{
output.AppendLine(e.Data);
}
};
process.ErrorDataReceived += (sender, e) =>
{
if (e.Data == null)
{
errorWaitHandle.Set();
}
else
{
error.AppendLine(e.Data);
}
};
try
{
process.Start();
process.BeginErrorReadLine();
process.BeginOutputReadLine();
process.WaitForExit();
}
catch (System.ComponentModel.Win32Exception e)
{
// log the arguments
throw new Exception(process.StartInfo.Arguments);
}
string stderr = error.ToString();
string stdout = output.ToString();
int exitCode = process.ExitCode;
if (exitCode != (int)RET_ERRORS.RET_NO_ERROR)
{
throw new Exception(stderr);
}
//if (arguments == "query")
//{
// if (stdout.IsNullOrWhiteSpace() || stdout.IsNullOrEmpty())
// {
// throw new Exception("failed to query wininet settings");
// }
// _queryStr = stdout;
//}
}

View File

@@ -3,17 +3,18 @@ using System.IO;
using System.Reactive.Linq;
using v2rayN.Handler;
using v2rayN.Mode;
using v2rayN.Resx;
namespace v2rayN.Base
{
public sealed class TunHandler
{
private static readonly Lazy<TunHandler> _instance = new Lazy<TunHandler>(() => new());
private static readonly Lazy<TunHandler> _instance = new(() => new());
public static TunHandler Instance => _instance.Value;
private string _tunConfigName = "tunConfig.json";
private static Config _config;
private CoreInfo coreInfo;
private Process _process;
private Process? _process;
private static int _socksPort;
private static bool _needRestart = true;
private static bool _isRunning = false;
@@ -60,6 +61,7 @@ namespace v2rayN.Base
{
return;
}
CoreStartTest();
CoreStart();
}
}
@@ -72,7 +74,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;
@@ -91,13 +102,25 @@ namespace v2rayN.Base
configStr = configStr.Replace("$strict_route$", $"{_config.tunModeItem.strictRoute.ToString().ToLower()}");
configStr = configStr.Replace("$stack$", $"{_config.tunModeItem.stack}");
//logs
configStr = configStr.Replace("$log_disabled$", $"aaa{(!_config.tunModeItem.enabledLog).ToString().ToLower()}");
if (_config.tunModeItem.showWindow)
{
configStr = configStr.Replace("$log_output$", $"");
}
else
{
var dtNow = DateTime.Now;
var log_output = $"\"output\": \"{Utils.GetLogPath($"singbox_{dtNow:yyyy-MM-dd}.txt")}\", ";
configStr = configStr.Replace("$log_output$", $"{log_output.Replace(@"\", @"\\")}");
}
//port
configStr = configStr.Replace("$socksPort$", $"{_socksPort}");
//exe
List<string> lstDnsExe = new List<string>();
List<string> lstDirectExe = new List<string>();
List<string> lstDnsExe = new();
List<string> lstDirectExe = new();
var coreInfos = LazyConfig.Instance.GetCoreInfos();
foreach (var it in coreInfos)
{
@@ -109,13 +132,13 @@ namespace v2rayN.Base
{
if (!lstDnsExe.Contains(it2) && it.coreType != ECoreType.sing_box)
{
lstDnsExe.Add(it2);
//lstDnsExe.Add(it2);
lstDnsExe.Add($"{it2}.exe");
}
if (!lstDirectExe.Contains(it2))
{
lstDirectExe.Add(it2);
//lstDirectExe.Add(it2);
lstDirectExe.Add($"{it2}.exe");
}
}
@@ -126,27 +149,45 @@ namespace v2rayN.Base
string strDirect = string.Join("\",\"", lstDirectExe.ToArray());
configStr = configStr.Replace("$directProcessName$", $"\"{strDirect}\"");
if (_config.tunModeItem.bypassMode)
{
//direct ips
if (_config.tunModeItem.directIP != null && _config.tunModeItem.directIP.Count > 0)
{
var ips = new { outbound = "direct", ip_cidr = _config.tunModeItem.directIP };
configStr = configStr.Replace("$ruleDirectIPs$", "," + Utils.ToJson(ips));
}
//direct process
if (_config.tunModeItem.directProcess != null && _config.tunModeItem.directProcess.Count > 0)
{
var process = new { outbound = "direct", process_name = _config.tunModeItem.directProcess };
configStr = configStr.Replace("$ruleDirectProcess$", "," + Utils.ToJson(process));
}
}
else
{
//proxy ips
if (_config.tunModeItem.proxyIP != null && _config.tunModeItem.proxyIP.Count > 0)
{
var ips = new { outbound = "proxy", ip_cidr = _config.tunModeItem.proxyIP };
configStr = configStr.Replace("$ruleProxyIPs$", "," + Utils.ToJson(ips));
}
//proxy process
if (_config.tunModeItem.proxyProcess != null && _config.tunModeItem.proxyProcess.Count > 0)
{
var process = new { outbound = "proxy", process_name = _config.tunModeItem.proxyProcess };
configStr = configStr.Replace("$ruleProxyProcess$", "," + Utils.ToJson(process));
}
//ips
if (_config.tunModeItem.directIP != null && _config.tunModeItem.directIP.Count > 0)
{
var ips = new { outbound = "direct", ip_cidr = _config.tunModeItem.directIP };
configStr = configStr.Replace("$ruleDirectIPs$", "," + Utils.ToJson(ips));
}
else
{
configStr = configStr.Replace("$ruleDirectIPs$", "");
}
//process
if (_config.tunModeItem.directProcess != null && _config.tunModeItem.directProcess.Count > 0)
{
var process = new { outbound = "direct", process_name = _config.tunModeItem.directProcess };
configStr = configStr.Replace("$ruleDirectProcess$", "," + Utils.ToJson(process));
}
else
{
configStr = configStr.Replace("$ruleDirectProcess$", "");
var final = new { outbound = "direct", inbound = "tun-in" };
configStr = configStr.Replace("$ruleFinally$", "," + Utils.ToJson(final));
}
configStr = configStr.Replace("$ruleDirectIPs$", "");
configStr = configStr.Replace("$ruleDirectProcess$", "");
configStr = configStr.Replace("$ruleProxyIPs$", "");
configStr = configStr.Replace("$ruleProxyProcess$", "");
configStr = configStr.Replace("$ruleFinally$", "");
File.WriteAllText(Utils.GetConfigPath(_tunConfigName), configStr);
@@ -163,6 +204,7 @@ namespace v2rayN.Base
KillProcess(_process);
_process.Dispose();
_process = null;
_needRestart = true;
}
}
catch (Exception ex)
@@ -186,7 +228,8 @@ namespace v2rayN.Base
}
if (Utils.IsNullOrEmpty(fileName))
{
string msg = string.Format(ResUI.NotFoundCore, Utils.GetBinPath("", coreInfo.coreType), string.Join(", ", coreInfo.coreExes.ToArray()), coreInfo.coreUrl);
Utils.SaveLog(msg);
}
return fileName;
}
@@ -196,12 +239,12 @@ namespace v2rayN.Base
try
{
string fileName = CoreFindexe();
if (fileName == "")
if (Utils.IsNullOrEmpty(fileName))
{
return;
}
var showWindow = _config.tunModeItem.showWindow;
Process p = new Process
Process p = new()
{
StartInfo = new ProcessStartInfo
{
@@ -210,7 +253,7 @@ namespace v2rayN.Base
WorkingDirectory = Utils.GetConfigPath(),
UseShellExecute = showWindow,
CreateNoWindow = !showWindow,
RedirectStandardError = !showWindow,
//RedirectStandardError = !showWindow,
Verb = "runas",
}
};
@@ -219,14 +262,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());
}
//if (showWindow)
//{
throw new Exception("start tun mode fail");
//}
//else
//{
// throw new Exception(p.StandardError.ReadToEnd());
//}
}
Global.processJob.AddProcess(p.Handle);
@@ -254,5 +297,47 @@ namespace v2rayN.Base
Utils.SaveLog(ex.Message, ex);
}
}
private int CoreStartTest()
{
Utils.SaveLog("Tun mode configuration file test start");
try
{
string fileName = CoreFindexe();
if (fileName == "")
{
return -1;
}
Process p = new Process
{
StartInfo = new ProcessStartInfo
{
FileName = fileName,
Arguments = $"run -c \"{Utils.GetConfigPath(_tunConfigName)}\"",
WorkingDirectory = Utils.GetConfigPath(),
UseShellExecute = false,
CreateNoWindow = true,
RedirectStandardError = true,
Verb = "runas",
}
};
p.Start();
if (p.WaitForExit(2000))
{
throw new Exception(p.StandardError.ReadToEnd());
}
KillProcess(p);
return 0;
}
catch (Exception ex)
{
Utils.SaveLog(ex.Message, ex);
return -1;
}
finally
{
Utils.SaveLog("Tun mode configuration file test end");
}
}
}
}

View File

@@ -35,51 +35,46 @@ namespace v2rayN.Handler
_updateFunc = update;
var url = string.Empty;
DownloadHandle downloadHandle = null;
if (downloadHandle == null)
DownloadHandle downloadHandle = new();
downloadHandle.UpdateCompleted += (sender2, args) =>
{
downloadHandle = new DownloadHandle();
downloadHandle.UpdateCompleted += (sender2, args) =>
if (args.Success)
{
if (args.Success)
{
_updateFunc(false, ResUI.MsgDownloadV2rayCoreSuccessfully);
_updateFunc(false, ResUI.MsgDownloadV2rayCoreSuccessfully);
try
try
{
string fileName = Utils.GetTempPath(Utils.GetDownloadFileName(url));
fileName = Utils.UrlEncode(fileName);
Process process = new()
{
string fileName = Utils.GetTempPath(Utils.GetDownloadFileName(url));
fileName = Utils.UrlEncode(fileName);
Process process = new Process
StartInfo = new ProcessStartInfo
{
StartInfo = new ProcessStartInfo
{
FileName = "v2rayUpgrade.exe",
Arguments = $"\"{fileName}\"",
WorkingDirectory = Utils.StartupPath()
}
};
process.Start();
if (process.Id > 0)
{
_updateFunc(true, "");
FileName = "v2rayUpgrade.exe",
Arguments = $"\"{fileName}\"",
WorkingDirectory = Utils.StartupPath()
}
}
catch (Exception ex)
};
process.Start();
if (process.Id > 0)
{
_updateFunc(false, ex.Message);
_updateFunc(true, "");
}
}
else
catch (Exception ex)
{
_updateFunc(false, args.Msg);
_updateFunc(false, ex.Message);
}
};
downloadHandle.Error += (sender2, args) =>
}
else
{
_updateFunc(false, args.GetException().Message);
};
}
_updateFunc(false, args.Msg);
}
};
downloadHandle.Error += (sender2, args) =>
{
_updateFunc(false, args.GetException().Message);
};
AbsoluteCompleted += (sender2, args) =>
{
if (args.Success)
@@ -106,36 +101,32 @@ namespace v2rayN.Handler
_updateFunc = update;
var url = string.Empty;
DownloadHandle downloadHandle = null;
if (downloadHandle == null)
DownloadHandle downloadHandle = new();
downloadHandle.UpdateCompleted += (sender2, args) =>
{
downloadHandle = new DownloadHandle();
downloadHandle.UpdateCompleted += (sender2, args) =>
if (args.Success)
{
if (args.Success)
{
_updateFunc(false, ResUI.MsgDownloadV2rayCoreSuccessfully);
_updateFunc(false, ResUI.MsgUnpacking);
_updateFunc(false, ResUI.MsgDownloadV2rayCoreSuccessfully);
_updateFunc(false, ResUI.MsgUnpacking);
try
{
_updateFunc(true, url);
}
catch (Exception ex)
{
_updateFunc(false, ex.Message);
}
}
else
try
{
_updateFunc(false, args.Msg);
_updateFunc(true, url);
}
};
downloadHandle.Error += (sender2, args) =>
catch (Exception ex)
{
_updateFunc(false, ex.Message);
}
}
else
{
_updateFunc(true, args.GetException().Message);
};
}
_updateFunc(false, args.Msg);
}
};
downloadHandle.Error += (sender2, args) =>
{
_updateFunc(true, args.GetException().Message);
};
AbsoluteCompleted += (sender2, args) =>
{
@@ -213,10 +204,10 @@ namespace v2rayN.Handler
url = Utils.GetPunycode(url);
_updateFunc(false, $"{hashCode}{ResUI.MsgStartGettingSubscriptions}");
var result = await downloadHandle.DownloadStringAsync(url, blProxy, userAgent);
var result = await downloadHandle.TryDownloadString(url, blProxy, userAgent);
if (blProxy && Utils.IsNullOrEmpty(result))
{
result = await downloadHandle.DownloadStringAsync(url, false, userAgent);
result = await downloadHandle.TryDownloadString(url, false, userAgent);
}
if (Utils.IsNullOrEmpty(result))
@@ -226,12 +217,17 @@ namespace v2rayN.Handler
else
{
_updateFunc(false, $"{hashCode}{ResUI.MsgGetSubscriptionSuccessfully}");
if (result.Length < 99)
if (result!.Length < 99)
{
_updateFunc(false, $"{hashCode}{result}");
}
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}"
@@ -257,45 +253,44 @@ namespace v2rayN.Handler
_updateFunc = update;
var url = string.Format(Global.geoUrl, geoName);
DownloadHandle downloadHandle = null;
if (downloadHandle == null)
DownloadHandle downloadHandle = new();
downloadHandle.UpdateCompleted += (sender2, args) =>
{
downloadHandle = new DownloadHandle();
downloadHandle.UpdateCompleted += (sender2, args) =>
if (args.Success)
{
if (args.Success)
{
_updateFunc(false, string.Format(ResUI.MsgDownloadGeoFileSuccessfully, geoName));
_updateFunc(false, string.Format(ResUI.MsgDownloadGeoFileSuccessfully, geoName));
try
try
{
string fileName = Utils.GetTempPath(Utils.GetDownloadFileName(url));
if (File.Exists(fileName))
{
string fileName = Utils.GetTempPath(Utils.GetDownloadFileName(url));
if (File.Exists(fileName))
{
Global.coreTypes.ForEach(it =>
{
string targetPath = Utils.GetBinPath($"{geoName}.dat", (ECoreType)Enum.Parse(typeof(ECoreType), it));
File.Copy(fileName, targetPath, true);
});
//_updateFunc(true, "");
}
}
catch (Exception ex)
{
_updateFunc(false, ex.Message);
//Global.coreTypes.ForEach(it =>
//{
// string targetPath = Utils.GetBinPath($"{geoName}.dat", (ECoreType)Enum.Parse(typeof(ECoreType), it));
// File.Copy(fileName, targetPath, true);
//});
string targetPath = Utils.GetBinPath($"{geoName}.dat");
File.Copy(fileName, targetPath, true);
File.Delete(fileName);
//_updateFunc(true, "");
}
}
else
catch (Exception ex)
{
_updateFunc(false, args.Msg);
_updateFunc(false, ex.Message);
}
};
downloadHandle.Error += (sender2, args) =>
}
else
{
_updateFunc(false, args.GetException().Message);
};
}
_updateFunc(false, args.Msg);
}
};
downloadHandle.Error += (sender2, args) =>
{
_updateFunc(false, args.GetException().Message);
};
askToDownload(downloadHandle, url, false);
}
@@ -365,7 +360,7 @@ namespace v2rayN.Handler
return "";
}
Process p = new Process();
using Process p = new();
p.StartInfo.FileName = filePath;
p.StartInfo.Arguments = coreInfo.versionArg;
p.StartInfo.WorkingDirectory = Utils.StartupPath();

View File

@@ -8,148 +8,31 @@
{
#region property
/// <summary>
/// 允许日志
/// </summary>
public bool logEnabled
{
get; set;
}
/// <summary>
/// 日志等级
/// </summary>
public string loglevel
{
get; set;
}
public string indexId
{
get; set;
}
/// <summary>
/// 允许Mux多路复用
/// </summary>
public bool muxEnabled
{
get; set;
}
/// <summary>
///
/// </summary>
public ESysProxyType sysProxyType
{
get; set;
}
public bool autoRun { get; set; }
/// <summary>
/// 启用实时网速和流量统计
/// </summary>
public bool enableStatistics
{
get; set;
}
/// <summary>
/// 去重时优先保留较旧(顶部)节点
/// </summary>
public bool keepOlderDedupl
{
get; set;
}
/// <summary>
/// 视图刷新率
/// </summary>
public int statisticsFreshRate
{
get; set;
}
/// <summary>
/// 自定义远程DNS
/// </summary>
public string remoteDNS
{
get; set;
}
public string indexId { get; set; }
public string remoteDNS { get; set; }
/// <summary>
/// Outbound Freedom domainStrategy
/// </summary>
public string domainStrategy4Freedom
{
get; set;
}
public string domainStrategy4Freedom { get; set; }
/// <summary>
/// 是否允许不安全连接
/// </summary>
public bool defAllowInsecure
{
get; set;
}
/// <summary>
/// 域名解析策略
/// </summary>
public string domainStrategy
{
get; set;
}
public string domainMatcher
{
get; set;
}
public string routingIndexId { get; set; }
public bool enableRoutingAdvanced
{
get; set;
}
public bool ignoreGeoUpdateCore
{
get; set;
}
/// <summary>
/// systemProxyExceptions
/// </summary>
public string systemProxyExceptions
{
get; set;
}
public ESysProxyType sysProxyType { get; set; }
public string systemProxyExceptions { get; set; }
public string systemProxyAdvancedProtocol { get; set; }
public int autoUpdateInterval { get; set; } = 10;
public int autoUpdateSubInterval { get; set; } = 10;
public bool checkPreReleaseUpdate { get; set; } = false;
public bool enableSecurityProtocolTls13
{
get; set;
}
public int trayMenuServersLimit { get; set; } = 20;
public bool autoHideStartup { get; set; }
#endregion
#region other entities
public CoreBasicItem coreBasicItem { get; set; }
public TunModeItem tunModeItem { get; set; }
public KcpItem kcpItem { get; set; }
public GrpcItem grpcItem { get; set; }
public RoutingBasicItem routingBasicItem { get; set; }
public GUIItem guiItem { get; set; }
public UIItem uiItem { get; set; }
public ConstItem constItem { get; set; }
public SpeedTestItem speedTestItem { get; set; }
public List<InItem> inbound { get; set; }
public List<KeyEventItem> globalHotkeys { get; set; }
public List<CoreTypeItem> coreTypeItem { get; set; }

View File

@@ -2,6 +2,37 @@
namespace v2rayN.Mode
{
[Serializable]
public class CoreBasicItem
{
/// <summary>
/// 允许日志
/// </summary>
public bool logEnabled { get; set; }
/// <summary>
/// 日志等级
/// </summary>
public string loglevel { get; set; }
/// <summary>
/// 允许Mux多路复用
/// </summary>
public bool muxEnabled { get; set; }
/// <summary>
/// 是否允许不安全连接
/// </summary>
public bool defAllowInsecure { get; set; }
public string defFingerprint { get; set; }
/// <summary>
/// 默认用户代理
/// </summary>
public string defUserAgent { get; set; }
}
[Serializable]
public class InItem
{
@@ -51,23 +82,53 @@ namespace v2rayN.Mode
public int initial_windows_size { get; set; }
}
[Serializable]
public class GUIItem
{
public bool autoRun { get; set; }
public bool enableStatistics { get; set; }
public int statisticsFreshRate { get; set; }
public bool keepOlderDedupl { get; set; }
public bool ignoreGeoUpdateCore { get; set; } = true;
public int autoUpdateInterval { get; set; } = 10;
public int autoUpdateSubInterval { get; set; } = 10;
public bool checkPreReleaseUpdate { get; set; } = false;
public bool enableSecurityProtocolTls13 { get; set; }
public int trayMenuServersLimit { get; set; } = 20;
}
[Serializable]
public class UIItem
{
public bool enableAutoAdjustMainLvColWidth { get; set; }
public double mainWidth { get; set; }
public double mainHeight { get; set; }
public double mainGirdHeight1 { get; set; }
public double mainGirdHeight2 { get; set; }
public bool colorModeDark { get; set; }
public string? colorPrimaryName { get; set; }
public string currentLanguage { get; set; }
public string currentFontFamily { get; set; }
public int currentFontSize { get; set; }
public bool enableDragDropSort { get; set; }
public bool doubleClick2Activate { get; set; }
public bool autoHideStartup { get; set; } = true;
public string mainMsgFilter { get; set; }
public Dictionary<string, int> mainLvColWidth { get; set; }
}
[Serializable]
public class ConstItem
{
public string speedTestUrl { get; set; }
public string speedPingTestUrl { get; set; }
public string defIEProxyExceptions { get; set; }
}
@@ -99,11 +160,37 @@ namespace v2rayN.Mode
{
public bool enableTun { get; set; }
public bool showWindow { get; set; }
public bool enabledLog { get; set; }
public bool strictRoute { get; set; }
public string stack { get; set; }
public int mtu { get; set; }
public string customTemplate { get; set; }
public bool bypassMode { get; set; } = true;
public List<string> directIP { get; set; }
public List<string> directProcess { get; set; }
public List<string> proxyIP { get; set; }
public List<string> proxyProcess { get; set; }
}
[Serializable]
public class SpeedTestItem
{
public int speedTestTimeout { get; set; }
public string speedTestUrl { get; set; }
public string speedPingTestUrl { get; set; }
}
[Serializable]
public class RoutingBasicItem
{
/// <summary>
/// 域名解析策略
/// </summary>
public string domainStrategy { get; set; }
public string domainMatcher { get; set; }
public string routingIndexId { get; set; }
public bool enableRoutingAdvanced { get; set; }
}
}

View File

@@ -0,0 +1,14 @@
using SQLite;
namespace v2rayN.Mode
{
[Serializable]
public class ProfileExItem
{
[PrimaryKey]
public string indexId { get; set; }
public int delay { get; set; }
public decimal speed { get; set; }
public int sort { get; set; }
}
}

View File

@@ -11,7 +11,6 @@ namespace v2rayN.Mode
indexId = string.Empty;
configType = EConfigType.VMess;
configVersion = 2;
sort = 0;
address = string.Empty;
port = 0;
id = string.Empty;
@@ -107,11 +106,6 @@ namespace v2rayN.Mode
get; set;
}
public int sort
{
get; set;
}
/// <summary>
/// 远程服务器地址
/// </summary>
@@ -202,9 +196,6 @@ namespace v2rayN.Mode
get; set;
}
public int delay { get; set; }
public decimal speed { get; set; }
/// <summary>
/// SubItem id
/// </summary>

View File

@@ -5,6 +5,9 @@
{
public bool isActive { get; set; }
public string subRemarks { get; set; }
public int delay { get; set; }
public decimal speed { get; set; }
public int sort { get; set; }
public string delayVal { get; set; }
public string speedVal { get; set; }
public string todayUp { get; set; }

View File

@@ -15,6 +15,7 @@ namespace v2rayN.Mode
public bool locked { get; set; }
public string customIcon { get; set; }
public string domainStrategy { get; set; }
public int sort { 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

@@ -1,4 +1,6 @@
namespace v2rayN.Mode
using Newtonsoft.Json;
namespace v2rayN.Mode
{
/// <summary>
/// v2ray配置文件实体类
@@ -505,6 +507,12 @@
///
/// </summary>
public string Host { get; set; }
/// <summary>
/// 用户代理
/// </summary>
[JsonProperty("User-Agent")]
public string UserAgent { get; set; }
}
public class HttpSettings

View File

@@ -63,5 +63,10 @@
/// TLS alpn
/// </summary>
public string alpn { get; set; } = string.Empty;
/// <summary>
/// TLS fingerprint
/// </summary>
public string fp { get; set; } = string.Empty;
}
}

View File

@@ -70,7 +70,7 @@ namespace v2rayN.Resx {
}
/// <summary>
/// 查找类似 All servers 的本地化字符串。
/// 查找类似 All 的本地化字符串。
/// </summary>
public static string AllGroupServers {
get {
@@ -681,6 +681,15 @@ namespace v2rayN.Resx {
}
}
/// <summary>
/// 查找类似 Edit Server (Ctrl+D) 的本地化字符串。
/// </summary>
public static string menuEditServer {
get {
return ResourceManager.GetString("menuEditServer", resourceCulture);
}
}
/// <summary>
/// 查找类似 Exit 的本地化字符串。
/// </summary>
@@ -781,7 +790,7 @@ namespace v2rayN.Resx {
}
/// <summary>
/// 查找类似 One-click test Latency and speed (Ctrl+E) 的本地化字符串。
/// 查找类似 One-click multi test Latency and speed (Ctrl+E) 的本地化字符串。
/// </summary>
public static string menuMixedTestServer {
get {
@@ -1114,7 +1123,7 @@ namespace v2rayN.Resx {
}
/// <summary>
/// 查找类似 Share Server (Ctrl+D) 的本地化字符串。
/// 查找类似 Share Server (Ctrl+F) 的本地化字符串。
/// </summary>
public static string menuShareServer {
get {
@@ -1752,6 +1761,24 @@ namespace v2rayN.Resx {
}
}
/// <summary>
/// 查找类似 Test completed 的本地化字符串。
/// </summary>
public static string SpeedtestingCompleted {
get {
return ResourceManager.GetString("SpeedtestingCompleted", resourceCulture);
}
}
/// <summary>
/// 查找类似 Skip test 的本地化字符串。
/// </summary>
public static string SpeedtestingSkip {
get {
return ResourceManager.GetString("SpeedtestingSkip", resourceCulture);
}
}
/// <summary>
/// 查找类似 PAC failed to start. Please run this program as Administrator. 的本地化字符串。
/// </summary>
@@ -1861,6 +1888,15 @@ namespace v2rayN.Resx {
}
}
/// <summary>
/// 查找类似 AutoRefresh 的本地化字符串。
/// </summary>
public static string TbAutoRefresh {
get {
return ResourceManager.GetString("TbAutoRefresh", resourceCulture);
}
}
/// <summary>
/// 查找类似 Domain and ip are auto sorted when saving 的本地化字符串。
/// </summary>
@@ -2356,6 +2392,24 @@ namespace v2rayN.Resx {
}
}
/// <summary>
/// 查找类似 FontFamily(Require restart) 的本地化字符串。
/// </summary>
public static string TbSettingsCurrentFontFamily {
get {
return ResourceManager.GetString("TbSettingsCurrentFontFamily", resourceCulture);
}
}
/// <summary>
/// 查找类似 Copy the font TTF file to the directory guiFonts, restart the settings 的本地化字符串。
/// </summary>
public static string TbSettingsCurrentFontFamilyTip {
get {
return ResourceManager.GetString("TbSettingsCurrentFontFamilyTip", resourceCulture);
}
}
/// <summary>
/// 查找类似 AllowInsecure 的本地化字符串。
/// </summary>
@@ -2365,6 +2419,33 @@ namespace v2rayN.Resx {
}
}
/// <summary>
/// 查找类似 Default TLS fingerprint 的本地化字符串。
/// </summary>
public static string TbSettingsDefFingerprint {
get {
return ResourceManager.GetString("TbSettingsDefFingerprint", resourceCulture);
}
}
/// <summary>
/// 查找类似 User-Agent 的本地化字符串。
/// </summary>
public static string TbSettingsDefUserAgent {
get {
return ResourceManager.GetString("TbSettingsDefUserAgent", resourceCulture);
}
}
/// <summary>
/// 查找类似 This parameter is valid only for tcp/http and ws 的本地化字符串。
/// </summary>
public static string TbSettingsDefUserAgentTips {
get {
return ResourceManager.GetString("TbSettingsDefUserAgentTips", resourceCulture);
}
}
/// <summary>
/// 查找类似 Outbound Freedom domainStrategy 的本地化字符串。
/// </summary>
@@ -2374,6 +2455,15 @@ namespace v2rayN.Resx {
}
}
/// <summary>
/// 查找类似 Double-click server make active 的本地化字符串。
/// </summary>
public static string TbSettingsDoubleClick2Activate {
get {
return ResourceManager.GetString("TbSettingsDoubleClick2Activate", resourceCulture);
}
}
/// <summary>
/// 查找类似 Automatically adjust column width after updating subscription 的本地化字符串。
/// </summary>
@@ -2392,6 +2482,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>
@@ -2410,6 +2509,15 @@ namespace v2rayN.Resx {
}
}
/// <summary>
/// 查找类似 FontSize 的本地化字符串。
/// </summary>
public static string TbSettingsFontSize {
get {
return ResourceManager.GetString("TbSettingsFontSize", resourceCulture);
}
}
/// <summary>
/// 查找类似 Http Port 的本地化字符串。
/// </summary>
@@ -2447,7 +2555,7 @@ namespace v2rayN.Resx {
}
/// <summary>
/// 查找类似 Language 的本地化字符串。
/// 查找类似 Language(Restart) 的本地化字符串。
/// </summary>
public static string TbSettingsLanguage {
get {
@@ -2456,7 +2564,7 @@ namespace v2rayN.Resx {
}
/// <summary>
/// 查找类似 Record local logs 的本地化字符串。
/// 查找类似 Enable Log 的本地化字符串。
/// </summary>
public static string TbSettingsLogEnabled {
get {
@@ -2572,6 +2680,33 @@ namespace v2rayN.Resx {
}
}
/// <summary>
/// 查找类似 http port=socks port+1 的本地化字符串。
/// </summary>
public static string TbSettingsSocksPortTip {
get {
return ResourceManager.GetString("TbSettingsSocksPortTip", resourceCulture);
}
}
/// <summary>
/// 查找类似 SpeedTest Single Timeout Value 的本地化字符串。
/// </summary>
public static string TbSettingsSpeedTestTimeout {
get {
return ResourceManager.GetString("TbSettingsSpeedTestTimeout", resourceCulture);
}
}
/// <summary>
/// 查找类似 SpeedTest Url 的本地化字符串。
/// </summary>
public static string TbSettingsSpeedTestUrl {
get {
return ResourceManager.GetString("TbSettingsSpeedTestUrl", resourceCulture);
}
}
/// <summary>
/// 查找类似 Start on boot 的本地化字符串。
/// </summary>
@@ -2581,6 +2716,15 @@ namespace v2rayN.Resx {
}
}
/// <summary>
/// 查找类似 Set this with admin privileges, get admin privileges after startup 的本地化字符串。
/// </summary>
public static string TbSettingsStartBootTip {
get {
return ResourceManager.GetString("TbSettingsStartBootTip", resourceCulture);
}
}
/// <summary>
/// 查找类似 Enable Statistics (Require restart) 的本地化字符串。
/// </summary>
@@ -2644,6 +2788,33 @@ namespace v2rayN.Resx {
}
}
/// <summary>
/// 查找类似 Bypass Mode 的本地化字符串。
/// </summary>
public static string TbSettingsTunModeBypassMode {
get {
return ResourceManager.GetString("TbSettingsTunModeBypassMode", resourceCulture);
}
}
/// <summary>
/// 查找类似 Enable: If no route matches, the final proxy 的本地化字符串。
/// </summary>
public static string TbSettingsTunModeBypassModeTip {
get {
return ResourceManager.GetString("TbSettingsTunModeBypassModeTip", resourceCulture);
}
}
/// <summary>
/// 查找类似 Custom Template 的本地化字符串。
/// </summary>
public static string TbSettingsTunModeCustomTemplate {
get {
return ResourceManager.GetString("TbSettingsTunModeCustomTemplate", resourceCulture);
}
}
/// <summary>
/// 查找类似 Direct IP CIDR, separated by commas (,) 的本地化字符串。
/// </summary>
@@ -2662,6 +2833,24 @@ namespace v2rayN.Resx {
}
}
/// <summary>
/// 查找类似 Proxy IP CIDR, separated by commas (,) 的本地化字符串。
/// </summary>
public static string TbSettingsTunModeProxyIP {
get {
return ResourceManager.GetString("TbSettingsTunModeProxyIP", resourceCulture);
}
}
/// <summary>
/// 查找类似 Proxy Process name, separated by commas (,) 的本地化字符串。
/// </summary>
public static string TbSettingsTunModeProxyProcess {
get {
return ResourceManager.GetString("TbSettingsTunModeProxyProcess", resourceCulture);
}
}
/// <summary>
/// 查找类似 Show console 的本地化字符串。
/// </summary>
@@ -2879,7 +3068,7 @@ namespace v2rayN.Resx {
}
/// <summary>
/// 查找类似 *QUIC securty 的本地化字符串。
/// 查找类似 *QUIC security 的本地化字符串。
/// </summary>
public static string TransportRequestHostTip4 {
get {

View File

@@ -130,7 +130,7 @@
<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>
<value>توجه داشته باشید که پیکربندی سفارشی کاملاً به پیکربندی خود شما بستگی دارد و با همه تنظیمات کار نمی کند. اگر می خواهید از پروکسی سیستم استفاده کنید، لطفاً پورت درحال شنود را به صورت دستی تغییر دهید.</value>
</data>
<data name="Downloading" xml:space="preserve">
<value>درحال دانلود...</value>
@@ -187,10 +187,10 @@
<value>پیکربندی اولیه</value>
</data>
<data name="IsLatestCore" xml:space="preserve">
<value>{0} already up to date.</value>
<value>{0} در حال حاضر به روز است.</value>
</data>
<data name="IsLatestN" xml:space="preserve">
<value>{0} already up to date.</value>
<value>{0} در حال حاضر به روز است.</value>
</data>
<data name="LvAddress" xml:space="preserve">
<value>آدرس</value>
@@ -262,28 +262,28 @@
<value>شروع به دریافت اشتراک شد</value>
</data>
<data name="MsgStartUpdating" xml:space="preserve">
<value>Start updating {0}...</value>
<value>شروع بروزرسانی {0}...</value>
</data>
<data name="MsgStartUpdatingPAC" xml:space="preserve">
<value>Start updating PAC...</value>
<value>شروع بروزرسانی PAC...</value>
</data>
<data name="MsgSubscriptionDecodingFailed" xml:space="preserve">
<value>محتوای اشتراک نامعتبر است</value>
</data>
<data name="MsgUnpacking" xml:space="preserve">
<value>is unpacking...</value>
<value>در حال باز کردن بسته می باشد ...</value>
</data>
<data name="MsgUpdateSubscriptionEnd" xml:space="preserve">
<value>Update subscription end</value>
<value>بروزرسانی اشتراک به پایان رسید</value>
</data>
<data name="MsgUpdateSubscriptionStart" xml:space="preserve">
<value>Update subscription starts</value>
<value>بروزرسانی اشتراک شروع شد</value>
</data>
<data name="MsgUpdateV2rayCoreSuccessfully" xml:space="preserve">
<value>Update Core successfully</value>
<value>هسته با موفقیت بروزرسانی شد</value>
</data>
<data name="MsgUpdateV2rayCoreSuccessfullyMore" xml:space="preserve">
<value>Update Core successfully! Restarting service...</value>
<value>هسته با موفقیت بروزرسانی شد! راه اندازی مجدد سرویس...</value>
</data>
<data name="NeedHttpGlobalProxy" xml:space="preserve">
<value> This feature relies on the Http global proxy, please set it correctly first.</value>
@@ -301,7 +301,7 @@
<value>Scan completed, no valid QR code found</value>
</data>
<data name="OperationFailed" xml:space="preserve">
<value> operation failed, please check and retry</value>
<value> عملیات انجام نشد، لطفا بررسی کنید و دوباره امتحان کنید</value>
</data>
<data name="PleaseFillRemarks" xml:space="preserve">
<value>Please Fill Remarks</value>
@@ -343,20 +343,20 @@
<value>Start service ({0})...</value>
</data>
<data name="SuccessfulConfiguration" xml:space="preserve">
<value>Configuration successful
<value>پیکربندی با موفقیت انجام شد
{0}</value>
</data>
<data name="SuccessfullyImportedCustomServer" xml:space="preserve">
<value>سرور پیکربندی سفارشی با موفقیت وارد شد.</value>
</data>
<data name="SuccessfullyImportedServerViaClipboard" xml:space="preserve">
<value>{0} servers have been imported from clipboard.</value>
<value>{0} سرورها از کلیپ بورد وارد شده اند.</value>
</data>
<data name="SuccessfullyImportedServerViaScan" xml:space="preserve">
<value>Scan import URL successfully</value>
<value>اسکن URL وارد کردن با موفقیت</value>
</data>
<data name="TestMeOutput" xml:space="preserve">
<value>The ping of current service: {0} ms</value>
<value>پینگ سرویس فعلی: {0} ms</value>
</data>
<data name="OperationSuccess" xml:space="preserve">
<value>موفقیت عملیات</value>
@@ -368,7 +368,7 @@
<value>آیا مطمئن هستید که قوانین را حذف می کنید؟</value>
</data>
<data name="RoutingRuleDetailRequiredTips" xml:space="preserve">
<value>{0},One of the required.</value>
<value>{0},یکی از مورد نیاز.</value>
</data>
<data name="LvRemarks" xml:space="preserve">
<value>Remarks</value>
@@ -386,7 +386,7 @@
<value>Do you want to append rules? Choose yes to append, choose otherwise to replace</value>
</data>
<data name="MsgDownloadGeoFileSuccessfully" xml:space="preserve">
<value>Download GeoFile: {0} successfully</value>
<value>دانلود GeoFile: {0} با موفقیت</value>
</data>
<data name="MsgInformationTitle" xml:space="preserve">
<value>اطلاعات</value>
@@ -536,7 +536,7 @@
<value>پروکسی سیستم تغییر نکند</value>
</data>
<data name="menuSystemProxyPac" xml:space="preserve">
<value>Pac Mode</value>
<value>حالت Pac</value>
</data>
<data name="menuSystemProxySet" xml:space="preserve">
<value>تنظیم پراکسی سیستم</value>
@@ -791,10 +791,10 @@
<value>Outbound Freedom domainStrategy</value>
</data>
<data name="TbSettingsEnableAutoAdjustMainLvColWidth" xml:space="preserve">
<value>Automatically adjust column width after updating subscription</value>
<value>پس از به‌روزرسانی اشتراک، عرض ستون را به صورت خودکار تنظیم شود</value>
</data>
<data name="TbSettingsEnableCheckPreReleaseUpdate" xml:space="preserve">
<value>به روز رسانی های پیش از انتشار را بررسی کنید</value>
<value>به روز رسانی های پیش از انتشار را بررسی شود</value>
</data>
<data name="TbSettingsException" xml:space="preserve">
<value>استثنا</value>
@@ -827,13 +827,13 @@
<value>تنظیمات v2rayN</value>
</data>
<data name="TbSettingsPacListenPort" xml:space="preserve">
<value>Pac listen port</value>
<value>Pac پورت درحال شنود</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>
<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>
@@ -845,16 +845,16 @@
<value>Turn on Sniffing</value>
</data>
<data name="TbSettingsSocksPort" xml:space="preserve">
<value>Socks Port</value>
<value>ساکس Port</value>
</data>
<data name="TbSettingsStartBoot" xml:space="preserve">
<value>Start on boot</value>
<value>درهنگام راه ائدازی شروع شود</value>
</data>
<data name="TbSettingsStatistics" xml:space="preserve">
<value>Enable Statistics (Require restart)</value>
<value>فعال کردن آمار (نیاز به راه اندازی مجدد)</value>
</data>
<data name="TbSettingsStatisticsFreshRate" xml:space="preserve">
<value>Statistics freshrate (second)</value>
<value>نرخ تازه سازی آمار (ثانیه)</value>
</data>
<data name="TbSettingsSubConvert" xml:space="preserve">
<value>Subscription conversion Url</value>
@@ -884,7 +884,7 @@
<value>تنظیم کلید میانبر جهانی</value>
</data>
<data name="TbGlobalHotkeySettingTip" xml:space="preserve">
<value>Set directly by pressing the keyboard, Take effect after restart</value>
<value>مستقیماً با فشار دادن صفحه کلید تنظیم کنید، بعد از راه اندازی مجدد اعمال شود</value>
</data>
<data name="TbNotChangeSystemProxy" xml:space="preserve">
<value>پروکسی سیستم را تغییر ندهید</value>
@@ -899,7 +899,7 @@
<value>حالت Pac</value>
</data>
<data name="menuShareServer" xml:space="preserve">
<value>اشتراک گذاری سرور(Ctrl+D)</value>
<value>اشتراک گذاری سرور(Ctrl+F)</value>
</data>
<data name="menuRouting" xml:space="preserve">
<value>مسیریابی</value>
@@ -929,7 +929,7 @@
<value>{0} Website</value>
</data>
<data name="menuRoutingAdvanced" xml:space="preserve">
<value>Advanced Function</value>
<value>عملکرد پیشرفته</value>
</data>
<data name="menuRoutingAdvancedAdd" xml:space="preserve">
<value>اضافه کردن</value>
@@ -1001,7 +1001,7 @@
<value>تنظیم جزئیات قانون مسیریابی</value>
</data>
<data name="TbAutoSort" xml:space="preserve">
<value>Domain and ip are auto sorted when saving</value>
<value>دامنه و آی پی در هنگام ذخیره به طور خودکار مرتب می شوند</value>
</data>
<data name="TbRuleobjectDoc" xml:space="preserve">
<value>Ruleobject Doc</value>
@@ -1060,4 +1060,10 @@
<data name="TbSettingsTunModeShowWindow" xml:space="preserve">
<value>نمایش کنسول</value>
</data>
<data name="TbSettingsDefUserAgent" xml:space="preserve">
<value>User-Agent</value>
</data>
<data name="TbSettingsDefUserAgentTips" xml:space="preserve">
<value>This parameter is valid only for tcp/http and ws</value>
</data>
</root>

View File

@@ -419,7 +419,7 @@
<value>*h2 host Separated by commas (,)</value>
</data>
<data name="TransportRequestHostTip4" xml:space="preserve">
<value>*QUIC securty</value>
<value>*QUIC security</value>
</data>
<data name="TransportHeaderTypeTip1" xml:space="preserve">
<value>*tcp camouflage type</value>
@@ -449,7 +449,7 @@
<value>Ungrouped</value>
</data>
<data name="AllGroupServers" xml:space="preserve">
<value>All servers</value>
<value>All</value>
</data>
<data name="FillServerAddressCustom" xml:space="preserve">
<value>Please browse to import server configuration</value>
@@ -548,7 +548,7 @@
<value>Dark Mode</value>
</data>
<data name="TbSettingsLanguage" xml:space="preserve">
<value>Language</value>
<value>Language(Restart)</value>
</data>
<data name="menuAddServerViaClipboard" xml:space="preserve">
<value>Import bulk URL from clipboard (Ctrl+V)</value>
@@ -815,7 +815,7 @@
<value>Keep older when deduplication</value>
</data>
<data name="TbSettingsLogEnabled" xml:space="preserve">
<value>Record local logs</value>
<value>Enable Log</value>
</data>
<data name="TbSettingsLogLevel" xml:space="preserve">
<value>Log Level</value>
@@ -899,7 +899,7 @@
<value>Pac Mode</value>
</data>
<data name="menuShareServer" xml:space="preserve">
<value>Share Server (Ctrl+D)</value>
<value>Share Server (Ctrl+F)</value>
</data>
<data name="menuRouting" xml:space="preserve">
<value>Routing</value>
@@ -1022,7 +1022,7 @@
<value>RouteOnly</value>
</data>
<data name="menuMixedTestServer" xml:space="preserve">
<value>One-click test Latency and speed (Ctrl+E)</value>
<value>One-click multi test Latency and speed (Ctrl+E)</value>
</data>
<data name="LvTestDelay" xml:space="preserve">
<value>Delay(ms)</value>
@@ -1063,4 +1063,67 @@
<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>
<data name="TbAutoRefresh" xml:space="preserve">
<value>AutoRefresh</value>
</data>
<data name="SpeedtestingSkip" xml:space="preserve">
<value>Skip test</value>
</data>
<data name="menuEditServer" xml:space="preserve">
<value>Edit Server (Ctrl+D)</value>
</data>
<data name="TbSettingsDoubleClick2Activate" xml:space="preserve">
<value>Double-click server make active</value>
</data>
<data name="SpeedtestingCompleted" xml:space="preserve">
<value>Test completed</value>
</data>
<data name="TbSettingsDefFingerprint" xml:space="preserve">
<value>Default TLS fingerprint</value>
</data>
<data name="TbSettingsDefUserAgent" xml:space="preserve">
<value>User-Agent</value>
</data>
<data name="TbSettingsDefUserAgentTips" xml:space="preserve">
<value>This parameter is valid only for tcp/http and ws</value>
</data>
<data name="TbSettingsCurrentFontFamily" xml:space="preserve">
<value>FontFamily(Require restart)</value>
</data>
<data name="TbSettingsCurrentFontFamilyTip" xml:space="preserve">
<value>Copy the font TTF file to the directory guiFonts, restart the settings</value>
</data>
<data name="TbSettingsSocksPortTip" xml:space="preserve">
<value>http port=socks port+1</value>
</data>
<data name="TbSettingsStartBootTip" xml:space="preserve">
<value>Set this with admin privileges, get admin privileges after startup</value>
</data>
<data name="TbSettingsFontSize" xml:space="preserve">
<value>FontSize</value>
</data>
<data name="TbSettingsTunModeProxyIP" xml:space="preserve">
<value>Proxy IP CIDR, separated by commas (,)</value>
</data>
<data name="TbSettingsTunModeProxyProcess" xml:space="preserve">
<value>Proxy Process name, separated by commas (,)</value>
</data>
<data name="TbSettingsTunModeBypassMode" xml:space="preserve">
<value>Bypass Mode</value>
</data>
<data name="TbSettingsTunModeBypassModeTip" xml:space="preserve">
<value>Enable: If no route matches, the final proxy</value>
</data>
<data name="TbSettingsSpeedTestTimeout" xml:space="preserve">
<value>SpeedTest Single Timeout Value</value>
</data>
<data name="TbSettingsSpeedTestUrl" xml:space="preserve">
<value>SpeedTest Url</value>
</data>
</root>

File diff suppressed because it is too large Load Diff

View File

@@ -130,7 +130,7 @@
<value>配置格式不正确</value>
</data>
<data name="CustomServerTips" xml:space="preserve">
<value>注意,自定义配置完全依赖您自己的配置,不能使用所有设置功能。如需使用系统代理请手修改监听端口。</value>
<value>注意,自定义配置完全依赖您自己的配置,不能使用所有设置功能。如需使用系统代理请手修改监听端口。</value>
</data>
<data name="Downloading" xml:space="preserve">
<value>下载开始...</value>
@@ -148,7 +148,7 @@
<value>生成默认配置文件失败</value>
</data>
<data name="FailedGetDefaultConfiguration" xml:space="preserve">
<value>取默认配置失败</value>
<value>取默认配置失败</value>
</data>
<data name="FailedImportedCustomServer" xml:space="preserve">
<value>导入自定义配置服务器失败</value>
@@ -449,7 +449,7 @@
<value>未分组服务器</value>
</data>
<data name="AllGroupServers" xml:space="preserve">
<value>所有服务器</value>
<value>所有</value>
</data>
<data name="FillServerAddressCustom" xml:space="preserve">
<value>请浏览导入服务器配置</value>
@@ -548,7 +548,7 @@
<value>暗黑模式</value>
</data>
<data name="TbSettingsLanguage" xml:space="preserve">
<value>语言</value>
<value>语言(重启)</value>
</data>
<data name="menuAddServerViaClipboard" xml:space="preserve">
<value>从剪贴板导入批量URL (Ctrl+V)</value>
@@ -815,7 +815,7 @@
<value>去重时保留序号较小的项</value>
</data>
<data name="TbSettingsLogEnabled" xml:space="preserve">
<value>记录本地日志(默认关闭)</value>
<value>启用日志(默认关闭)</value>
</data>
<data name="TbSettingsLogLevel" xml:space="preserve">
<value>日志等级</value>
@@ -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>
@@ -899,13 +899,13 @@
<value>Pac模式</value>
</data>
<data name="menuShareServer" xml:space="preserve">
<value>分享服务器 (Ctrl+D)</value>
<value>分享服务器 (Ctrl+F)</value>
</data>
<data name="menuRouting" xml:space="preserve">
<value>路由</value>
</data>
<data name="NotRunAsAdmin" xml:space="preserve">
<value>以管理员身份运行</value>
<value>以管理员身份运行</value>
</data>
<data name="RunAsAdmin" xml:space="preserve">
<value>以管理员身份运行</value>
@@ -1022,7 +1022,7 @@
<value>RouteOnly</value>
</data>
<data name="menuMixedTestServer" xml:space="preserve">
<value>一键测试延迟和速度 (Ctrl+E)</value>
<value>一键多线程测试延迟和速度 (Ctrl+E)</value>
</data>
<data name="LvTestDelay" xml:space="preserve">
<value>延迟(ms)</value>
@@ -1063,4 +1063,67 @@
<data name="menuMoveToGroup" xml:space="preserve">
<value>移至订阅分组</value>
</data>
</root>
<data name="TbSettingsTunModeCustomTemplate" xml:space="preserve">
<value>自定义配置模板</value>
</data>
<data name="TbSettingsEnableDragDropSort" xml:space="preserve">
<value>启用服务器拖放排序(需重启)</value>
</data>
<data name="TbAutoRefresh" xml:space="preserve">
<value>自动刷新</value>
</data>
<data name="SpeedtestingSkip" xml:space="preserve">
<value>跳过测试</value>
</data>
<data name="menuEditServer" xml:space="preserve">
<value>编辑服务器 (Ctrl+D)</value>
</data>
<data name="TbSettingsDoubleClick2Activate" xml:space="preserve">
<value>主界面双击设为活动服务器</value>
</data>
<data name="SpeedtestingCompleted" xml:space="preserve">
<value>测试完成</value>
</data>
<data name="TbSettingsDefFingerprint" xml:space="preserve">
<value>默认TLS指纹(fingerprint)</value>
</data>
<data name="TbSettingsDefUserAgent" xml:space="preserve">
<value>用户代理(User-Agent)</value>
</data>
<data name="TbSettingsDefUserAgentTips" xml:space="preserve">
<value>仅对tcp/http、ws协议生效</value>
</data>
<data name="TbSettingsCurrentFontFamily" xml:space="preserve">
<value>当前字体(需重启)</value>
</data>
<data name="TbSettingsCurrentFontFamilyTip" xml:space="preserve">
<value>拷贝字体TTF文件到目录guiFonts重启设置</value>
</data>
<data name="TbSettingsSocksPortTip" xml:space="preserve">
<value>http端口=socks端口+1</value>
</data>
<data name="TbSettingsStartBootTip" xml:space="preserve">
<value>以管理员权限设置此项,在启动后获得管理员权限</value>
</data>
<data name="TbSettingsFontSize" xml:space="preserve">
<value>字体大小</value>
</data>
<data name="TbSettingsTunModeProxyIP" xml:space="preserve">
<value>代理的IP CIDR用逗号(,)分隔</value>
</data>
<data name="TbSettingsTunModeProxyProcess" xml:space="preserve">
<value>代理的进程名,用逗号(,)分隔</value>
</data>
<data name="TbSettingsTunModeBypassMode" xml:space="preserve">
<value>绕行模式</value>
</data>
<data name="TbSettingsTunModeBypassModeTip" xml:space="preserve">
<value>启用:路由无匹配则最终代理</value>
</data>
<data name="TbSettingsSpeedTestTimeout" xml:space="preserve">
<value>测速单个超时值</value>
</data>
<data name="TbSettingsSpeedTestUrl" xml:space="preserve">
<value>测速文件地址</value>
</data>
</root>

View File

@@ -1 +1 @@
{"version":"1.1","method":"GET","path":[$requestPath$],"headers":{"Host":[$requestHost$],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/55.0.2883.75 Safari/537.36","Mozilla/5.0 (iPhone; CPU iPhone OS 10_0_2 like Mac OS X) AppleWebKit/601.1 (KHTML, like Gecko) CriOS/53.0.2785.109 Mobile/14A456 Safari/601.1.46"],"Accept-Encoding":["gzip, deflate"],"Connection":["keep-alive"],"Pragma":"no-cache"}}
{"version":"1.1","method":"GET","path":[$requestPath$],"headers":{"Host":[$requestHost$],"User-Agent":[$requestUserAgent$],"Accept-Encoding":["gzip, deflate"],"Connection":["keep-alive"],"Pragma":"no-cache"}}

View File

@@ -1,10 +1,12 @@
{
"log": {
"disabled": $log_disabled$,
"level": "debug",
$log_output$
"timestamp": true
},
"dns": {
"servers": [
{
"tag": "google",
"address": "tls://8.8.8.8"
},
"servers": [
{
"tag": "local",
"address": "223.5.5.5",
@@ -27,6 +29,7 @@
"inbounds": [
{
"type": "tun",
"tag": "tun-in",
"interface_name": "singbox_tun",
"inet4_address": "172.19.0.1/30",
@@ -106,6 +109,9 @@
}
$ruleDirectIPs$
$ruleDirectProcess$
$ruleProxyIPs$
$ruleProxyProcess$
$ruleFinally$
]
}
}

View File

@@ -10,8 +10,7 @@ namespace v2rayN.Tool
{
try
{
using (FileStream fs = new FileStream(fileName, FileMode.Create, FileAccess.Write))
fs.Write(content, 0, content.Length);
File.WriteAllBytes(fileName, content);
return true;
}
catch (Exception ex)
@@ -25,20 +24,9 @@ namespace v2rayN.Tool
{
try
{
// Because the uncompressed size of the file is unknown,
// we are using an arbitrary buffer size.
byte[] buffer = new byte[4096];
int n;
using (FileStream fs = File.Create(fileName))
using (GZipStream input = new GZipStream(new MemoryStream(content),
CompressionMode.Decompress, false))
{
while ((n = input.Read(buffer, 0, buffer.Length)) > 0)
{
fs.Write(buffer, 0, n);
}
}
using FileStream fs = File.Create(fileName);
using GZipStream input = new(new MemoryStream(content), CompressionMode.Decompress, false);
input.CopyTo(fs);
}
catch (Exception ex)
{
@@ -55,42 +43,38 @@ namespace v2rayN.Tool
{
try
{
using (FileStream fs = new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
using (StreamReader sr = new StreamReader(fs, encoding))
{
return sr.ReadToEnd();
}
using FileStream fs = new(path, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
using StreamReader sr = new(fs, encoding);
return sr.ReadToEnd();
}
catch (Exception ex)
{
Utils.SaveLog(ex.Message, ex);
throw ex;
throw;
}
}
public static bool ZipExtractToFile(string fileName, string toPath, string ignoredName)
{
try
{
using (ZipArchive archive = ZipFile.OpenRead(fileName))
using ZipArchive archive = ZipFile.OpenRead(fileName);
foreach (ZipArchiveEntry entry in archive.Entries)
{
foreach (ZipArchiveEntry entry in archive.Entries)
if (entry.Length == 0)
{
if (entry.Length == 0)
continue;
}
try
{
if (!Utils.IsNullOrEmpty(ignoredName) && entry.Name.Contains(ignoredName))
{
continue;
}
try
{
if (!Utils.IsNullOrEmpty(ignoredName) && entry.Name.Contains(ignoredName))
{
continue;
}
entry.ExtractToFile(Path.Combine(toPath, entry.Name), true);
}
catch (IOException ex)
{
Utils.SaveLog(ex.Message, ex);
}
entry.ExtractToFile(Path.Combine(toPath, entry.Name), true);
}
catch (IOException ex)
{
Utils.SaveLog(ex.Message, ex);
}
}
}

View File

@@ -16,12 +16,12 @@ namespace v2rayN
{
handle = CreateJobObject(IntPtr.Zero, null);
IntPtr extendedInfoPtr = IntPtr.Zero;
JOBOBJECT_BASIC_LIMIT_INFORMATION info = new JOBOBJECT_BASIC_LIMIT_INFORMATION
JOBOBJECT_BASIC_LIMIT_INFORMATION info = new()
{
LimitFlags = 0x2000
};
JOBOBJECT_EXTENDED_LIMIT_INFORMATION extendedInfo = new JOBOBJECT_EXTENDED_LIMIT_INFORMATION
JOBOBJECT_EXTENDED_LIMIT_INFORMATION extendedInfo = new()
{
BasicLimitInformation = info
};
@@ -100,7 +100,7 @@ namespace v2rayN
#region Interop
[DllImport("kernel32.dll", CharSet = CharSet.Unicode)]
private static extern IntPtr CreateJobObject(IntPtr a, string lpName);
private static extern IntPtr CreateJobObject(IntPtr a, string? lpName);
[DllImport("kernel32.dll", SetLastError = true)]
private static extern bool SetInformationJobObject(IntPtr hJob, JobObjectInfoType infoType, IntPtr lpJobObjectInfo, UInt32 cbJobObjectInfoLength);

View File

@@ -9,8 +9,8 @@ namespace v2rayN.Tool
{
public static void Setup()
{
LoggingConfiguration config = new LoggingConfiguration();
FileTarget fileTarget = new FileTarget();
LoggingConfiguration config = new();
FileTarget fileTarget = new();
config.AddTarget("file", fileTarget);
fileTarget.Layout = "${longdate}-${level:uppercase=true} ${message}";
fileTarget.FileName = Utils.GetLogPath("${shortdate}.txt");

View File

@@ -1,4 +1,5 @@
using Microsoft.Win32;
using Microsoft.Win32.TaskScheduler;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using NLog;
@@ -47,11 +48,10 @@ namespace v2rayN
try
{
Assembly assembly = Assembly.GetExecutingAssembly();
using (Stream stream = assembly.GetManifestResourceStream(res))
using (StreamReader reader = new StreamReader(stream))
{
result = reader.ReadToEnd();
}
using Stream? stream = assembly.GetManifestResourceStream(res);
ArgumentNullException.ThrowIfNull(stream);
using StreamReader reader = new(stream);
result = reader.ReadToEnd();
}
catch (Exception ex)
{
@@ -71,10 +71,12 @@ namespace v2rayN
try
{
using (StreamReader reader = new StreamReader(res))
if (!File.Exists(res))
{
result = reader.ReadToEnd();
return result;
}
using StreamReader reader = new(res);
result = reader.ReadToEnd();
}
catch (Exception ex)
{
@@ -89,7 +91,7 @@ namespace v2rayN
/// <typeparam name="T"></typeparam>
/// <param name="strJson"></param>
/// <returns></returns>
public static T FromJson<T>(string strJson)
public static T? FromJson<T>(string strJson)
{
try
{
@@ -97,8 +99,7 @@ namespace v2rayN
{
return default;
}
T obj = JsonConvert.DeserializeObject<T>(strJson);
return obj;
return JsonConvert.DeserializeObject<T>(strJson);
}
catch
{
@@ -111,7 +112,7 @@ namespace v2rayN
/// </summary>
/// <param name="obj"></param>
/// <returns></returns>
public static string ToJson(Object obj, bool indented = true)
public static string ToJson(object? obj, bool indented = true)
{
string result = string.Empty;
try
@@ -140,25 +141,23 @@ namespace v2rayN
/// <param name="obj"></param>
/// <param name="filePath"></param>
/// <returns></returns>
public static int ToJsonFile(Object obj, string filePath, bool nullValue = true)
public static int ToJsonFile(object? obj, string filePath, bool nullValue = true)
{
int result;
try
{
using (StreamWriter file = File.CreateText(filePath))
using StreamWriter file = File.CreateText(filePath);
JsonSerializer serializer;
if (nullValue)
{
JsonSerializer serializer;
if (nullValue)
{
serializer = new JsonSerializer() { Formatting = Formatting.Indented };
}
else
{
serializer = new JsonSerializer() { Formatting = Formatting.Indented, NullValueHandling = NullValueHandling.Ignore };
}
serializer.Serialize(file, obj);
serializer = new JsonSerializer() { Formatting = Formatting.Indented };
}
else
{
serializer = new JsonSerializer() { Formatting = Formatting.Indented, NullValueHandling = NullValueHandling.Ignore };
}
serializer.Serialize(file, obj);
result = 0;
}
catch (Exception ex)
@@ -169,7 +168,7 @@ namespace v2rayN
return result;
}
public static JObject ParseJson(string strJson)
public static JObject? ParseJson(string strJson)
{
try
{
@@ -201,7 +200,7 @@ namespace v2rayN
}
if (wrap)
{
return string.Join("," + Environment.NewLine, lst.ToArray());
return string.Join("," + Environment.NewLine, lst);
}
else
{
@@ -224,7 +223,7 @@ namespace v2rayN
try
{
str = str.Replace(Environment.NewLine, "");
return new List<string>(str.Split(new string[] { "," }, StringSplitOptions.RemoveEmptyEntries));
return new List<string>(str.Split(',', StringSplitOptions.RemoveEmptyEntries));
}
catch (Exception ex)
{
@@ -243,8 +242,9 @@ namespace v2rayN
try
{
str = str.Replace(Environment.NewLine, "");
List<string> list = new List<string>(str.Split(new string[] { "," }, StringSplitOptions.RemoveEmptyEntries));
return list.OrderBy(x => x).ToList();
List<string> list = new(str.Split(',', StringSplitOptions.RemoveEmptyEntries));
list.Sort();
return list;
}
catch (Exception ex)
{
@@ -336,7 +336,7 @@ namespace v2rayN
{
try
{
return (obj == null ? string.Empty : obj.ToString());
return obj?.ToString() ?? string.Empty;
}
catch (Exception ex)
{
@@ -413,10 +413,9 @@ namespace v2rayN
public static string GetMD5(string str)
{
var md5 = MD5.Create();
byte[] byteOld = Encoding.UTF8.GetBytes(str);
byte[] byteNew = md5.ComputeHash(byteOld);
StringBuilder sb = new StringBuilder();
byte[] byteNew = MD5.HashData(byteOld);
StringBuilder sb = new(32);
foreach (byte b in byteNew)
{
sb.Append(b.ToString("x2"));
@@ -439,7 +438,7 @@ namespace v2rayN
}
try
{
Uri uri = new Uri(url);
Uri uri = new(url);
if (uri.Host == uri.IdnHost)
{
return url;
@@ -567,18 +566,14 @@ namespace v2rayN
public static bool IsIpv6(string ip)
{
IPAddress address;
if (IPAddress.TryParse(ip, out address))
if (IPAddress.TryParse(ip, out IPAddress? address))
{
switch (address.AddressFamily)
return address.AddressFamily switch
{
case AddressFamily.InterNetwork:
return false;
case AddressFamily.InterNetworkV6:
return true;
default:
return false;
}
AddressFamily.InterNetwork => false,
AddressFamily.InterNetworkV6 => true,
_ => false,
};
}
return false;
}
@@ -601,11 +596,22 @@ 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)
@@ -670,13 +676,13 @@ namespace v2rayN
return Application.StartupPath;
}
public static string RegReadValue(string path, string name, string def)
public static string? RegReadValue(string path, string name, string def)
{
RegistryKey regKey = null;
RegistryKey? regKey = null;
try
{
regKey = Registry.CurrentUser.OpenSubKey(path, false);
string value = regKey?.GetValue(name) as string;
string? value = regKey?.GetValue(name) as string;
if (IsNullOrEmpty(value))
{
return def;
@@ -699,7 +705,7 @@ namespace v2rayN
public static void RegWriteValue(string path, string name, object value)
{
RegistryKey regKey = null;
RegistryKey? regKey = null;
try
{
regKey = Registry.CurrentUser.CreateSubKey(path);
@@ -731,14 +737,55 @@ namespace v2rayN
public static bool CheckForDotNetVersion(int release = 528040)
{
const string subkey = @"SOFTWARE\Microsoft\NET Framework Setup\NDP\v4\Full\";
using (RegistryKey ndpKey = RegistryKey.OpenBaseKey(RegistryHive.LocalMachine, RegistryView.Registry32).OpenSubKey(subkey))
using RegistryKey? ndpKey = RegistryKey.OpenBaseKey(RegistryHive.LocalMachine, RegistryView.Registry32).OpenSubKey(subkey);
if (ndpKey != null && ndpKey.GetValue("Release") != null)
{
if (ndpKey != null && ndpKey.GetValue("Release") != null)
{
return (int)ndpKey.GetValue("Release") >= release ? true : false;
}
return false;
return (int)ndpKey.GetValue("Release") >= release ? true : false;
}
return false;
}
/// <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.Settings.StopIfGoingOnBatteries = false;
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.Principal.RunLevel = TaskRunLevel.Highest;
task.Actions.Add(new ExecAction(deamonFileName));
taskService.RootFolder.RegisterTaskDefinition(TaskName, task);
}
#endregion
@@ -847,16 +894,13 @@ namespace v2rayN
public static T DeepCopy<T>(T obj)
{
object retval;
using (MemoryStream ms = new MemoryStream())
{
BinaryFormatter bf = new BinaryFormatter();
//序列化成流
bf.Serialize(ms, obj);
ms.Seek(0, SeekOrigin.Begin);
//反序列化成对象
retval = bf.Deserialize(ms);
ms.Close();
}
MemoryStream ms = new MemoryStream();
BinaryFormatter bf = new BinaryFormatter();
//序列化成流
bf.Serialize(ms, obj);
ms.Seek(0, SeekOrigin.Begin);
//反序列化成对象
retval = bf.Deserialize(ms);
return (T)retval;
}
@@ -864,7 +908,7 @@ namespace v2rayN
/// 获取剪贴板数
/// </summary>
/// <returns></returns>
public static string GetClipboardData()
public static string? GetClipboardData()
{
string strData = string.Empty;
try
@@ -951,7 +995,7 @@ namespace v2rayN
return fileName;
}
public static IPAddress GetDefaultGateway()
public static IPAddress? GetDefaultGateway()
{
return NetworkInterface
.GetAllNetworkInterfaces()
@@ -1014,14 +1058,11 @@ namespace v2rayN
public static string UnGzip(byte[] buf)
{
MemoryStream sb = new MemoryStream();
using (GZipStream input = new GZipStream(new MemoryStream(buf),
CompressionMode.Decompress,
false))
{
input.CopyTo(sb);
}
return Encoding.UTF8.GetString(sb.ToArray());
using MemoryStream sb = new();
using GZipStream input = new(new MemoryStream(buf), CompressionMode.Decompress, false);
input.CopyTo(sb);
sb.Position = 0;
return new StreamReader(sb, Encoding.UTF8).ReadToEnd();
}
public static string GetBackupPath(string filename)
@@ -1064,7 +1105,14 @@ namespace v2rayN
Directory.CreateDirectory(_tempPath);
}
}
return Path.Combine(_tempPath, filename);
if (string.IsNullOrEmpty(filename))
{
return _tempPath;
}
else
{
return Path.Combine(_tempPath, filename);
}
}
public static string GetLogPath(string filename = "")
{
@@ -1082,6 +1130,22 @@ namespace v2rayN
return Path.Combine(_tempPath, filename);
}
}
public static string GetFontsPath(string filename = "")
{
string _tempPath = Path.Combine(StartupPath(), "guiFonts");
if (!Directory.Exists(_tempPath))
{
Directory.CreateDirectory(_tempPath);
}
if (string.IsNullOrEmpty(filename))
{
return _tempPath;
}
else
{
return Path.Combine(_tempPath, filename);
}
}
#endregion
@@ -1114,42 +1178,40 @@ namespace v2rayN
{
foreach (Screen screen in Screen.AllScreens)
{
using (Bitmap fullImage = new Bitmap(screen.Bounds.Width,
screen.Bounds.Height))
using Bitmap fullImage = new Bitmap(screen.Bounds.Width,
screen.Bounds.Height);
using (Graphics g = Graphics.FromImage(fullImage))
{
using (Graphics g = Graphics.FromImage(fullImage))
g.CopyFromScreen(screen.Bounds.X,
screen.Bounds.Y,
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 Rectangle(marginLeft, marginTop, fullImage.Width - marginLeft * 2, fullImage.Height - marginTop * 2);
Bitmap target = new Bitmap(screen.Bounds.Width, screen.Bounds.Height);
double imageScale = (double)screen.Bounds.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 BitmapLuminanceSource(target);
BinaryBitmap bitmap = new BinaryBitmap(new HybridBinarizer(source));
QRCodeReader reader = new QRCodeReader();
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 Rectangle(marginLeft, marginTop, fullImage.Width - marginLeft * 2, fullImage.Height - marginTop * 2);
Bitmap target = new Bitmap(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 BitmapLuminanceSource(target);
BinaryBitmap bitmap = new BinaryBitmap(new HybridBinarizer(source));
QRCodeReader reader = new QRCodeReader();
Result result = reader.decode(bitmap);
if (result != null)
{
string ret = result.Text;
return ret;
}
string ret = result.Text;
return ret;
}
}
}

View File

@@ -26,6 +26,7 @@ namespace v2rayN.ViewModels
public ReactiveCommand<Unit, Unit> BrowseServerCmd { get; }
public ReactiveCommand<Unit, Unit> EditServerCmd { get; }
public ReactiveCommand<Unit, Unit> SaveServerCmd { get; }
public bool IsModified { get; set; }
public AddServer2ViewModel(ProfileItem profileItem, Window view)
{
@@ -86,6 +87,7 @@ namespace v2rayN.ViewModels
item.remarks = SelectedSource.remarks;
item.address = SelectedSource.address;
item.coreType = SelectedSource.coreType;
item.displayLog = SelectedSource.displayLog;
item.preSocksPort = SelectedSource.preSocksPort;
}
@@ -104,7 +106,7 @@ namespace v2rayN.ViewModels
{
UI.Show(ResUI.CustomServerTips);
OpenFileDialog fileDialog = new OpenFileDialog
OpenFileDialog fileDialog = new()
{
Multiselect = false,
Filter = "Config|*.json|YAML|*.yaml;*.yml|All|*.*"
@@ -119,15 +121,16 @@ namespace v2rayN.ViewModels
return;
}
var item = LazyConfig.Instance.GetProfileItem(SelectedSource.indexId);
if (item is null)
{
item = SelectedSource;
}
item ??= SelectedSource;
item.address = fileName;
if (ConfigHandler.AddCustomServer(ref _config, item, false) == 0)
{
_noticeHandler?.Enqueue(ResUI.SuccessfullyImportedCustomServer);
_view.DialogResult = true;
if (!Utils.IsNullOrEmpty(item.indexId))
{
SelectedSource = Utils.DeepCopy(item);
}
IsModified = true;
}
else
{

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;
@@ -36,7 +37,7 @@ namespace v2rayN.ViewModels
private string _serverFilter = string.Empty;
private static Config _config;
private NoticeHandler? _noticeHandler;
private readonly PaletteHelper _paletteHelper = new PaletteHelper();
private readonly PaletteHelper _paletteHelper = new();
private Dictionary<int, bool> _dicHeaderSort = new();
private Action<string> _updateView;
@@ -83,6 +84,7 @@ namespace v2rayN.ViewModels
public ReactiveCommand<Unit, Unit> AddServerViaClipboardCmd { get; }
public ReactiveCommand<Unit, Unit> AddServerViaScanCmd { get; }
//servers delete
public ReactiveCommand<Unit, Unit> EditServerCmd { get; }
public ReactiveCommand<Unit, Unit> RemoveServerCmd { get; }
public ReactiveCommand<Unit, Unit> RemoveDuplicateServerCmd { get; }
public ReactiveCommand<Unit, Unit> CopyServerCmd { get; }
@@ -111,8 +113,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
@@ -187,6 +189,8 @@ namespace v2rayN.ViewModels
public IObservableCollection<Swatch> Swatches => _swatches;
[Reactive]
public Swatch SelectedSwatch { get; set; }
[Reactive]
public int CurrentFontSize { get; set; }
[Reactive]
public string CurrentLanguage { get; set; }
@@ -210,6 +214,10 @@ namespace v2rayN.ViewModels
SelectedMoveToGroup = new();
SelectedRouting = new();
SelectedServer = new();
if (_config.tunModeItem.enableTun && Utils.IsAdministrator())
{
EnableTun = true;
}
//RefreshServers();
InitSubscriptionView();
@@ -226,7 +234,7 @@ namespace v2rayN.ViewModels
this.WhenAnyValue(
x => x.SelectedMoveToGroup,
y => y != null && !y.remarks.IsNullOrEmpty())
.Subscribe(c => MoveToGroup(c));
.Subscribe(c => MoveToGroup(c));
this.WhenAnyValue(
x => x.SelectedRouting,
@@ -246,7 +254,7 @@ namespace v2rayN.ViewModels
SystemProxySelected = (int)_config.sysProxyType;
this.WhenAnyValue(
x => x.SystemProxySelected,
y => y != null && y >= 0)
y => y >= 0)
.Subscribe(c => DoSystemProxySelected(c));
this.WhenAnyValue(
@@ -292,6 +300,10 @@ namespace v2rayN.ViewModels
return ScanScreenTaskAsync();
});
//servers delete
EditServerCmd = ReactiveCommand.Create(() =>
{
EditServer(false, EConfigType.Custom);
}, canEditRemove);
RemoveServerCmd = ReactiveCommand.Create(() =>
{
RemoveServer();
@@ -387,13 +399,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(() =>
{
@@ -494,7 +506,7 @@ namespace v2rayN.ViewModels
//MainFormHandler.Instance.BackupGuiNConfig(_config, true);
_coreHandler = new CoreHandler(UpdateHandler);
if (_config.enableStatistics)
if (_config.guiItem.enableStatistics)
{
_statistics = new StatisticsHandler(_config, UpdateStatisticsHandler);
}
@@ -520,12 +532,17 @@ namespace v2rayN.ViewModels
{
_noticeHandler?.SendMessage(msg);
}
private async void UpdateTaskHandler(bool success, string msg)
private void UpdateTaskHandler(bool success, string msg)
{
_noticeHandler?.SendMessage(msg);
if (success)
{
RefreshServers();
Reload();
if (_config.uiItem.enableAutoAdjustMainLvColWidth)
{
_updateView("AdjustMainLvColWidth");
}
}
}
private void UpdateStatisticsHandler(ServerSpeedItem update)
@@ -554,7 +571,16 @@ namespace v2rayN.ViewModels
item.totalDown = Utils.HumanFy(update.totalDown);
item.totalUp = Utils.HumanFy(update.totalUp);
_profileItems.Replace(item, Utils.DeepCopy(item));
if (SelectedProfile?.indexId == item.indexId)
{
var temp = Utils.DeepCopy(item);
_profileItems.Replace(item, temp);
SelectedProfile = temp;
}
else
{
_profileItems.Replace(item, Utils.DeepCopy(item));
}
}
}
}
@@ -576,7 +602,8 @@ namespace v2rayN.ViewModels
{
if (Utils.IsNullOrEmpty(indexId))
{
_noticeHandler?.SendMessage(delay);
_noticeHandler?.SendMessage(delay, true);
_noticeHandler?.Enqueue(delay);
return;
}
var item = _profileItems.Where(it => it.indexId == indexId).FirstOrDefault();
@@ -637,6 +664,9 @@ namespace v2rayN.ViewModels
SysProxyHandle.UpdateSysProxy(_config, true);
}
ProfileExHandler.Instance.SaveTo();
_statistics?.SaveTo();
_statistics?.Close();
_coreHandler.CoreStop();
@@ -680,17 +710,19 @@ namespace v2rayN.ViewModels
private void RefreshServers()
{
List<ProfileItemModel> lstModel = LazyConfig.Instance.ProfileItems(_subId, _serverFilter);
_lstProfile = Utils.FromJson<List<ProfileItem>>(Utils.ToJson(lstModel));
ConfigHandler.SetDefaultServer(_config, lstModel);
List<ServerStatItem> lstServerStat = new();
if (_statistics != null && _statistics.Enable)
{
lstServerStat = LazyConfig.Instance.ServerStatItems();
lstServerStat = _statistics.ServerStat;
}
var lstProfileExs = ProfileExHandler.Instance.ProfileExs;
lstModel = (from t in lstModel
join t2 in lstServerStat
on t.indexId equals t2.indexId into t2b
join t2 in lstServerStat on t.indexId equals t2.indexId into t2b
from t22 in t2b.DefaultIfEmpty()
join t3 in lstProfileExs on t.indexId equals t3.indexId into t3b
from t33 in t3b.DefaultIfEmpty()
select new ProfileItemModel
{
indexId = t.indexId,
@@ -702,17 +734,16 @@ namespace v2rayN.ViewModels
network = t.network,
streamSecurity = t.streamSecurity,
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,
isActive = t.indexId == _config.indexId,
sort = t33 == null ? 0 : t33.sort,
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),
todayUp = t22 == null ? "" : Utils.HumanFy(t22.todayUp),
totalDown = t22 == null ? "" : Utils.HumanFy(t22.totalDown),
totalUp = t22 == null ? "" : Utils.HumanFy(t22.totalUp)
}).ToList();
ConfigHandler.SetDefaultServer(_config, _lstProfile);
}).OrderBy(t => t.sort).ToList();
_lstProfile = Utils.FromJson<List<ProfileItem>>(Utils.ToJson(lstModel));
Application.Current.Dispatcher.Invoke((Action)(() =>
{
@@ -720,7 +751,15 @@ namespace v2rayN.ViewModels
_profileItems.AddRange(lstModel);
if (lstModel.Count > 0)
{
SelectedProfile = lstModel[0];
var selected = lstModel.FirstOrDefault(t => t.indexId == _config.indexId);
if (selected != null)
{
SelectedProfile = selected;
}
else
{
SelectedProfile = lstModel[0];
}
}
RefreshServersMenu();
@@ -737,7 +776,7 @@ namespace v2rayN.ViewModels
private void RefreshServersMenu()
{
_servers.Clear();
if (_lstProfile.Count > _config.trayMenuServersLimit)
if (_lstProfile.Count > _config.guiItem.trayMenuServersLimit)
{
return;
}
@@ -765,7 +804,14 @@ namespace v2rayN.ViewModels
{
_subItems.Add(item);
}
SelectedSub = _subItems[0];
if (_subId != null && _subItems.FirstOrDefault(t => t.id == _subId) != null)
{
SelectedSub = _subItems.FirstOrDefault(t => t.id == _subId);
}
else
{
SelectedSub = _subItems[0];
}
}
#endregion
@@ -774,7 +820,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;
}
@@ -839,6 +885,7 @@ namespace v2rayN.ViewModels
int ret = ConfigHandler.AddBatchServers(ref _config, clipboardData, _subId, false);
if (ret > 0)
{
InitSubscriptionView();
RefreshServers();
_noticeHandler?.Enqueue(string.Format(ResUI.SuccessfullyImportedServerViaClipboard, ret));
}
@@ -863,6 +910,7 @@ namespace v2rayN.ViewModels
int ret = ConfigHandler.AddBatchServers(ref _config, result, _subId, false);
if (ret > 0)
{
InitSubscriptionView();
RefreshServers();
_noticeHandler?.Enqueue(ResUI.SuccessfullyImportedServerViaScan);
}
@@ -879,12 +927,16 @@ namespace v2rayN.ViewModels
{
return;
}
var exists = lstSelecteds.Exists(t => t.indexId == _config.indexId);
ConfigHandler.RemoveServer(_config, lstSelecteds);
_noticeHandler?.Enqueue(ResUI.OperationSuccess);
RefreshServers();
Reload();
if (exists)
{
Reload();
}
}
private void RemoveDuplicateServer()
@@ -910,7 +962,7 @@ namespace v2rayN.ViewModels
public void SetDefaultServer()
{
if (Utils.IsNullOrEmpty(SelectedProfile.indexId))
if (Utils.IsNullOrEmpty(SelectedProfile?.indexId))
{
return;
}
@@ -933,7 +985,7 @@ namespace v2rayN.ViewModels
return;
}
if (ConfigHandler.SetDefaultServer(ref _config, item) == 0)
if (ConfigHandler.SetDefaultServerIndex(ref _config, indexId) == 0)
{
RefreshServers();
Reload();
@@ -1009,7 +1061,7 @@ namespace v2rayN.ViewModels
}
(new UpdateHandle()).RunAvailabilityCheck((bool success, string msg) =>
{
_noticeHandler?.SendMessage(msg);
_noticeHandler?.SendMessage(msg, true);
Application.Current.Dispatcher.Invoke((Action)(() =>
{
if (!Global.ShowInTaskbar)
@@ -1062,6 +1114,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)
{
@@ -1074,7 +1137,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()
@@ -1106,7 +1169,7 @@ namespace v2rayN.ViewModels
return;
}
StringBuilder sb = new StringBuilder();
StringBuilder sb = new();
foreach (var it in lstSelecteds)
{
string url = ShareHandler.GetShareUrl(it);
@@ -1120,7 +1183,7 @@ namespace v2rayN.ViewModels
if (sb.Length > 0)
{
Utils.SetClipboardData(sb.ToString());
_noticeHandler?.Enqueue(ResUI.BatchExportURLSuccessfully);
_noticeHandler?.SendMessage(ResUI.BatchExportURLSuccessfully);
}
}
@@ -1131,10 +1194,10 @@ namespace v2rayN.ViewModels
return;
}
StringBuilder sb = new StringBuilder();
StringBuilder sb = new();
foreach (var it in lstSelecteds)
{
string url = ShareHandler.GetShareUrl(it);
string? url = ShareHandler.GetShareUrl(it);
if (Utils.IsNullOrEmpty(url))
{
continue;
@@ -1145,7 +1208,7 @@ namespace v2rayN.ViewModels
if (sb.Length > 0)
{
Utils.SetClipboardData(Utils.Base64Encode(sb.ToString()));
_noticeHandler?.Enqueue(ResUI.BatchExportSubscriptionSuccessfully);
_noticeHandler?.SendMessage(ResUI.BatchExportSubscriptionSuccessfully);
}
}
@@ -1174,20 +1237,7 @@ namespace v2rayN.ViewModels
private void UpdateSubscriptionProcess(string subId, bool blProxy)
{
void _updateUI(bool success, string msg)
{
_noticeHandler?.SendMessage(msg);
if (success)
{
RefreshServers();
if (_config.uiItem.enableAutoAdjustMainLvColWidth)
{
_updateView("AdjustMainLvColWidth");
}
}
};
(new UpdateHandle()).UpdateSubscriptionProcess(_config, subId, blProxy, _updateUI);
(new UpdateHandle()).UpdateSubscriptionProcess(_config, subId, blProxy, UpdateTaskHandler);
}
#endregion
@@ -1218,7 +1268,7 @@ namespace v2rayN.ViewModels
private void ImportOldGuiConfig()
{
OpenFileDialog fileDialog = new OpenFileDialog
OpenFileDialog fileDialog = new()
{
Multiselect = false,
Filter = "guiNConfig|*.json|All|*.*"
@@ -1262,7 +1312,7 @@ namespace v2rayN.ViewModels
MyAppExit(false);
}
};
(new UpdateHandle()).CheckUpdateGuiN(_config, _updateUI, _config.checkPreReleaseUpdate);
(new UpdateHandle()).CheckUpdateGuiN(_config, _updateUI, _config.guiItem.checkPreReleaseUpdate);
}
private void CheckUpdateCore(ECoreType type)
@@ -1277,16 +1327,21 @@ namespace v2rayN.ViewModels
string fileName = Utils.GetTempPath(Utils.GetDownloadFileName(msg));
string toPath = Utils.GetBinPath("", type);
FileManager.ZipExtractToFile(fileName, toPath, _config.ignoreGeoUpdateCore ? "geo" : "");
FileManager.ZipExtractToFile(fileName, toPath, _config.guiItem.ignoreGeoUpdateCore ? "geo" : "");
_noticeHandler?.SendMessage(ResUI.MsgUpdateV2rayCoreSuccessfullyMore);
Reload();
_noticeHandler?.SendMessage(ResUI.MsgUpdateV2rayCoreSuccessfully);
if (File.Exists(fileName))
{
File.Delete(fileName);
}
}
};
(new UpdateHandle()).CheckUpdateCore(type, _config, _updateUI, _config.checkPreReleaseUpdate);
(new UpdateHandle()).CheckUpdateCore(type, _config, _updateUI, _config.guiItem.checkPreReleaseUpdate);
}
private void CheckUpdateGeo()
@@ -1390,7 +1445,7 @@ namespace v2rayN.ViewModels
private void RefreshRoutingsMenu()
{
_routingItems.Clear();
if (!_config.enableRoutingAdvanced)
if (!_config.routingBasicItem.enableRoutingAdvanced)
{
BlRouting = false;
return;
@@ -1401,7 +1456,7 @@ namespace v2rayN.ViewModels
foreach (var item in routings)
{
_routingItems.Add(item);
if (item.id.Equals(_config.routingIndexId))
if (item.id.Equals(_config.routingBasicItem.routingIndexId))
{
SelectedRouting = item;
}
@@ -1425,7 +1480,7 @@ namespace v2rayN.ViewModels
{
return;
}
if (_config.routingIndexId == item.id)
if (_config.routingBasicItem.routingIndexId == item.id)
{
return;
}
@@ -1477,7 +1532,7 @@ namespace v2rayN.ViewModels
public void ShowHideWindow(bool? blShow)
{
var bl = blShow.HasValue ? blShow.Value : !Global.ShowInTaskbar;
var bl = blShow ?? !Global.ShowInTaskbar;
if (bl)
{
//Application.Current.MainWindow.ShowInTaskbar = true;
@@ -1526,6 +1581,7 @@ namespace v2rayN.ViewModels
{
SelectedSwatch = _swatches.FirstOrDefault(t => t.Name == _config.uiItem.colorPrimaryName);
}
CurrentFontSize = _config.uiItem.currentFontSize;
CurrentLanguage = _config.uiItem.currentLanguage;
this.WhenAnyValue(
@@ -1561,6 +1617,24 @@ namespace v2rayN.ViewModels
}
});
this.WhenAnyValue(
x => x.CurrentFontSize,
y => y > 0)
.Subscribe(c =>
{
if (CurrentFontSize >= Global.MinFontSize)
{
_config.uiItem.currentFontSize = CurrentFontSize;
double size = (long)CurrentFontSize;
Application.Current.Resources["StdFontSize"] = size;
Application.Current.Resources["StdFontSize1"] = size + 1;
Application.Current.Resources["StdFontSize2"] = size + 2;
Application.Current.Resources["StdFontSizeMsg"] = size - 1;
ConfigHandler.SaveConfig(ref _config);
}
});
this.WhenAnyValue(
x => x.CurrentLanguage,
y => y != null && !y.IsNullOrEmpty())
@@ -1577,7 +1651,7 @@ namespace v2rayN.ViewModels
public void InboundDisplayStaus()
{
StringBuilder sb = new StringBuilder();
StringBuilder sb = new();
sb.Append($"[{Global.InboundSocks}:{LazyConfig.Instance.GetLocalPort(Global.InboundSocks)}]");
sb.Append(" | ");
//if (_config.sysProxyType == ESysProxyType.ForcedChange)
@@ -1588,21 +1662,21 @@ namespace v2rayN.ViewModels
//{
sb.Append($"[{Global.InboundHttp}:{LazyConfig.Instance.GetLocalPort(Global.InboundHttp)}]");
//}
InboundDisplay = $"{ResUI.LabLocal}:{sb.ToString()}";
InboundDisplay = $"{ResUI.LabLocal}:{sb}";
if (_config.inbound[0].allowLANConn)
{
if (_config.inbound[0].newPort4LAN)
{
StringBuilder sb2 = new StringBuilder();
StringBuilder sb2 = new();
sb2.Append($"[{Global.InboundSocks}:{LazyConfig.Instance.GetLocalPort(Global.InboundSocks2)}]");
sb2.Append(" | ");
sb2.Append($"[{Global.InboundHttp}:{LazyConfig.Instance.GetLocalPort(Global.InboundHttp2)}]");
InboundLanDisplay = $"{ResUI.LabLAN}:{sb2.ToString()}";
InboundLanDisplay = $"{ResUI.LabLAN}:{sb2}";
}
else
{
InboundLanDisplay = $"{ResUI.LabLAN}:{sb.ToString()}";
InboundLanDisplay = $"{ResUI.LabLAN}:{sb}";
}
}
else
@@ -1633,16 +1707,16 @@ namespace v2rayN.ViewModels
private void AutoHideStartup()
{
if (_config.autoHideStartup)
if (_config.uiItem.autoHideStartup)
{
Observable.Range(1, 1)
.Delay(TimeSpan.FromSeconds(1))
.Subscribe(x =>
{
Application.Current.Dispatcher.Invoke((Action)(() =>
Application.Current.Dispatcher.Invoke(() =>
{
ShowHideWindow(false);
}));
});
});
}
}

View File

@@ -28,6 +28,8 @@ namespace v2rayN.ViewModels
[Reactive] public bool logEnabled { get; set; }
[Reactive] public string loglevel { get; set; }
[Reactive] public bool defAllowInsecure { get; set; }
[Reactive] public string defFingerprint { get; set; }
[Reactive] public string defUserAgent { get; set; }
#endregion
#region Core DNS
@@ -55,9 +57,15 @@ 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 bool DoubleClick2Activate { get; set; }
[Reactive] public int autoUpdateInterval { get; set; }
[Reactive] public int autoUpdateSubInterval { get; set; }
[Reactive] public int trayMenuServersLimit { get; set; }
[Reactive] public string currentFontFamily { get; set; }
[Reactive] public int SpeedTestTimeout { get; set; }
[Reactive] public string SpeedTestUrl { get; set; }
#endregion
#region System proxy
@@ -67,11 +75,17 @@ namespace v2rayN.ViewModels
#region Tun mode
[Reactive] public bool TunShowWindow { get; set; }
[Reactive] public bool TunEnabledLog { get; set; }
[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 bool TunBypassMode { get; set; }
[Reactive] public bool TunBypassMode2 { get; set; }
[Reactive] public string TunDirectIP { get; set; }
[Reactive] public string TunDirectProcess { get; set; }
[Reactive] public string TunProxyIP { get; set; }
[Reactive] public string TunProxyProcess { get; set; }
#endregion
#region CoreType
@@ -103,10 +117,12 @@ namespace v2rayN.ViewModels
newPort4LAN = inbound.newPort4LAN;
user = inbound.user;
pass = inbound.pass;
muxEnabled = _config.muxEnabled;
logEnabled = _config.logEnabled;
loglevel = _config.loglevel;
defAllowInsecure = _config.defAllowInsecure;
muxEnabled = _config.coreBasicItem.muxEnabled;
logEnabled = _config.coreBasicItem.logEnabled;
loglevel = _config.coreBasicItem.loglevel;
defAllowInsecure = _config.coreBasicItem.defAllowInsecure;
defFingerprint = _config.coreBasicItem.defFingerprint;
defUserAgent = _config.coreBasicItem.defUserAgent;
#endregion
#region Core DNS
@@ -125,18 +141,24 @@ namespace v2rayN.ViewModels
#endregion
#region UI
AutoRun = _config.autoRun;
EnableStatistics = _config.enableStatistics;
StatisticsFreshRate = _config.statisticsFreshRate;
KeepOlderDedupl = _config.keepOlderDedupl;
IgnoreGeoUpdateCore = _config.ignoreGeoUpdateCore;
AutoRun = _config.guiItem.autoRun;
EnableStatistics = _config.guiItem.enableStatistics;
StatisticsFreshRate = _config.guiItem.statisticsFreshRate;
KeepOlderDedupl = _config.guiItem.keepOlderDedupl;
IgnoreGeoUpdateCore = _config.guiItem.ignoreGeoUpdateCore;
EnableAutoAdjustMainLvColWidth = _config.uiItem.enableAutoAdjustMainLvColWidth;
EnableSecurityProtocolTls13 = _config.enableSecurityProtocolTls13;
AutoHideStartup = _config.autoHideStartup;
EnableCheckPreReleaseUpdate = _config.checkPreReleaseUpdate;
autoUpdateInterval = _config.autoUpdateInterval;
autoUpdateSubInterval = _config.autoUpdateSubInterval;
trayMenuServersLimit = _config.trayMenuServersLimit;
EnableSecurityProtocolTls13 = _config.guiItem.enableSecurityProtocolTls13;
AutoHideStartup = _config.uiItem.autoHideStartup;
EnableCheckPreReleaseUpdate = _config.guiItem.checkPreReleaseUpdate;
EnableDragDropSort = _config.uiItem.enableDragDropSort;
DoubleClick2Activate = _config.uiItem.doubleClick2Activate;
autoUpdateInterval = _config.guiItem.autoUpdateInterval;
autoUpdateSubInterval = _config.guiItem.autoUpdateSubInterval;
trayMenuServersLimit = _config.guiItem.trayMenuServersLimit;
currentFontFamily = _config.uiItem.currentFontFamily;
SpeedTestTimeout = _config.speedTestItem.speedTestTimeout;
SpeedTestUrl = _config.speedTestItem.speedTestUrl;
#endregion
#region System proxy
@@ -147,11 +169,19 @@ namespace v2rayN.ViewModels
#region Tun mode
TunShowWindow = _config.tunModeItem.showWindow;
TunEnabledLog = _config.tunModeItem.enabledLog;
TunStrictRoute = _config.tunModeItem.strictRoute;
TunStack = _config.tunModeItem.stack;
TunMtu = _config.tunModeItem.mtu;
TunCustomTemplate = _config.tunModeItem.customTemplate;
TunBypassMode = _config.tunModeItem.bypassMode;
TunDirectIP = Utils.List2String(_config.tunModeItem.directIP, true);
TunDirectProcess = Utils.List2String(_config.tunModeItem.directProcess, true);
TunProxyIP = Utils.List2String(_config.tunModeItem.proxyIP, true);
TunProxyProcess = Utils.List2String(_config.tunModeItem.proxyProcess, true);
this.WhenAnyValue(
x => x.TunBypassMode)
.Subscribe(c => TunBypassMode2 = !TunBypassMode);
#endregion
@@ -259,10 +289,12 @@ namespace v2rayN.ViewModels
{
_config.inbound.RemoveAt(1);
}
_config.logEnabled = logEnabled;
_config.loglevel = loglevel;
_config.muxEnabled = muxEnabled;
_config.defAllowInsecure = defAllowInsecure;
_config.coreBasicItem.logEnabled = logEnabled;
_config.coreBasicItem.loglevel = loglevel;
_config.coreBasicItem.muxEnabled = muxEnabled;
_config.coreBasicItem.defAllowInsecure = defAllowInsecure;
_config.coreBasicItem.defFingerprint = defFingerprint;
_config.coreBasicItem.defUserAgent = defUserAgent;
//DNS
@@ -282,22 +314,27 @@ namespace v2rayN.ViewModels
//UI
Utils.SetAutoRun(AutoRun);
_config.autoRun = AutoRun;
_config.enableStatistics = EnableStatistics;
_config.statisticsFreshRate = StatisticsFreshRate;
if (_config.statisticsFreshRate > 100 || _config.statisticsFreshRate < 1)
_config.guiItem.autoRun = AutoRun;
_config.guiItem.enableStatistics = EnableStatistics;
_config.guiItem.statisticsFreshRate = StatisticsFreshRate;
if (_config.guiItem.statisticsFreshRate > 100 || _config.guiItem.statisticsFreshRate < 1)
{
_config.statisticsFreshRate = 1;
_config.guiItem.statisticsFreshRate = 1;
}
_config.keepOlderDedupl = KeepOlderDedupl;
_config.ignoreGeoUpdateCore = IgnoreGeoUpdateCore;
_config.guiItem.keepOlderDedupl = KeepOlderDedupl;
_config.guiItem.ignoreGeoUpdateCore = IgnoreGeoUpdateCore;
_config.uiItem.enableAutoAdjustMainLvColWidth = EnableAutoAdjustMainLvColWidth;
_config.enableSecurityProtocolTls13 = EnableSecurityProtocolTls13;
_config.autoHideStartup = AutoHideStartup;
_config.autoUpdateInterval = autoUpdateInterval;
_config.autoUpdateSubInterval = autoUpdateSubInterval;
_config.checkPreReleaseUpdate = EnableCheckPreReleaseUpdate;
_config.trayMenuServersLimit = trayMenuServersLimit;
_config.guiItem.enableSecurityProtocolTls13 = EnableSecurityProtocolTls13;
_config.uiItem.autoHideStartup = AutoHideStartup;
_config.guiItem.autoUpdateInterval = autoUpdateInterval;
_config.guiItem.autoUpdateSubInterval = autoUpdateSubInterval;
_config.guiItem.checkPreReleaseUpdate = EnableCheckPreReleaseUpdate;
_config.uiItem.enableDragDropSort = EnableDragDropSort;
_config.uiItem.doubleClick2Activate = DoubleClick2Activate;
_config.guiItem.trayMenuServersLimit = trayMenuServersLimit;
_config.uiItem.currentFontFamily = currentFontFamily;
_config.speedTestItem.speedTestTimeout = SpeedTestTimeout;
_config.speedTestItem.speedTestUrl = SpeedTestUrl;
//systemProxy
_config.systemProxyExceptions = systemProxyExceptions;
@@ -305,11 +342,16 @@ namespace v2rayN.ViewModels
//tun mode
_config.tunModeItem.showWindow = TunShowWindow;
_config.tunModeItem.enabledLog = TunEnabledLog;
_config.tunModeItem.strictRoute = TunStrictRoute;
_config.tunModeItem.stack = TunStack;
_config.tunModeItem.mtu = TunMtu;
_config.tunModeItem.customTemplate = TunCustomTemplate;
_config.tunModeItem.bypassMode = TunBypassMode;
_config.tunModeItem.directIP = Utils.String2List(TunDirectIP);
_config.tunModeItem.directProcess = Utils.String2List(TunDirectProcess);
_config.tunModeItem.proxyIP = Utils.String2List(TunProxyIP);
_config.tunModeItem.proxyProcess = Utils.String2List(TunProxyProcess);
//coreType
SaveCoreType();

View File

@@ -71,9 +71,9 @@ namespace v2rayN.ViewModels
ConfigHandler.InitBuiltinRouting(ref _config);
enableRoutingAdvanced = _config.enableRoutingAdvanced;
domainStrategy = _config.domainStrategy;
domainMatcher = _config.domainMatcher;
enableRoutingAdvanced = _config.routingBasicItem.enableRoutingAdvanced;
domainStrategy = _config.routingBasicItem.domainStrategy;
domainMatcher = _config.routingBasicItem.domainMatcher;
RefreshRoutingItems();
@@ -163,7 +163,7 @@ namespace v2rayN.ViewModels
foreach (var item in routings)
{
bool def = false;
if (item.id.Equals(_config.routingIndexId))
if (item.id.Equals(_config.routingBasicItem.routingIndexId))
{
def = true;
}
@@ -176,15 +176,16 @@ namespace v2rayN.ViewModels
remarks = item.remarks,
url = item.url,
customIcon = item.customIcon,
sort = item.sort,
};
_routingItems.Add(it);
}
}
private void SaveRouting()
{
_config.domainStrategy = domainStrategy;
_config.enableRoutingAdvanced = enableRoutingAdvanced;
_config.domainMatcher = domainMatcher;
_config.routingBasicItem.domainStrategy = domainStrategy;
_config.routingBasicItem.enableRoutingAdvanced = enableRoutingAdvanced;
_config.routingBasicItem.domainMatcher = domainMatcher;
EndBindingLockedData();

View File

@@ -3,6 +3,7 @@
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:Views="clr-namespace:v2rayN.Views"
xmlns:conv="clr-namespace:v2rayN.Converters"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:v2rayN"
xmlns:materialDesign="http://materialdesigninxaml.net/winfx/xaml/themes"
@@ -15,7 +16,10 @@
Height="500"
x:TypeArguments="vms:AddServer2ViewModel"
Background="{DynamicResource MaterialDesignPaper}"
FontFamily="{x:Static conv:MaterialDesignFonts.MyFont}"
ResizeMode="NoResize"
ShowInTaskbar="False"
TextElement.FontFamily="{x:Static conv:MaterialDesignFonts.MyFont}"
TextElement.Foreground="{DynamicResource MaterialDesignBody}"
TextOptions.TextFormattingMode="Display"
TextOptions.TextRenderingMode="Auto"
@@ -70,7 +74,7 @@
Margin="4"
VerticalAlignment="Top"
AcceptsReturn="True"
Style="{StaticResource MaterialDesignOutlinedTextBox}" />
Style="{StaticResource MyOutlinedTextBox}" />
<TextBlock
Grid.Row="2"
@@ -88,7 +92,7 @@
VerticalAlignment="Top"
AcceptsReturn="True"
IsReadOnly="True"
Style="{StaticResource MaterialDesignOutlinedTextBox}" />
Style="{StaticResource MyOutlinedTextBox}" />
<StackPanel
Grid.Row="2"
Grid.Column="2"
@@ -122,6 +126,7 @@
Width="200"
Margin="4"
HorizontalAlignment="Left"
FontSize="{DynamicResource StdFontSize}"
MaxDropDownHeight="1000"
Style="{StaticResource MaterialDesignOutlinedComboBox}" />
@@ -154,7 +159,7 @@
Margin="4"
HorizontalAlignment="Left"
AcceptsReturn="True"
Style="{StaticResource MaterialDesignOutlinedTextBox}" />
Style="{StaticResource MyOutlinedTextBox}" />
<StackPanel
Grid.Row="6"
Grid.Column="1"

View File

@@ -11,6 +11,7 @@ namespace v2rayN.Views
public AddServer2Window(ProfileItem profileItem)
{
InitializeComponent();
this.Owner = Application.Current.MainWindow;
this.Loaded += Window_Loaded;
ViewModel = new AddServer2ViewModel(profileItem, this);
@@ -44,7 +45,14 @@ namespace v2rayN.Views
}
private void btnCancel_Click(object sender, System.Windows.RoutedEventArgs e)
{
this.Close();
if (ViewModel?.IsModified == true)
{
this.DialogResult = true;
}
else
{
this.Close();
}
}
}

View File

@@ -2,6 +2,7 @@
x:Class="v2rayN.Views.AddServerWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:conv="clr-namespace:v2rayN.Converters"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:materialDesign="http://materialdesigninxaml.net/winfx/xaml/themes"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
@@ -13,7 +14,10 @@
Height="800"
x:TypeArguments="vms:AddServerViewModel"
Background="{DynamicResource MaterialDesignPaper}"
FontFamily="{x:Static conv:MaterialDesignFonts.MyFont}"
ResizeMode="NoResize"
ShowInTaskbar="False"
TextElement.FontFamily="{x:Static conv:MaterialDesignFonts.MyFont}"
TextElement.Foreground="{DynamicResource MaterialDesignBody}"
TextOptions.TextFormattingMode="Display"
TextOptions.TextRenderingMode="Auto"
@@ -80,7 +84,8 @@
Grid.Row="1"
Grid.Column="1"
Width="400"
Margin="{StaticResource ServerItemMargin}" />
Margin="{StaticResource ServerItemMargin}"
Style="{StaticResource DefTextBox}" />
<TextBlock
Grid.Row="2"
@@ -94,7 +99,8 @@
Grid.Row="2"
Grid.Column="1"
Width="400"
Margin="{StaticResource ServerItemMargin}" />
Margin="{StaticResource ServerItemMargin}"
Style="{StaticResource DefTextBox}" />
<TextBlock
Grid.Row="3"
@@ -109,7 +115,8 @@
Grid.Column="1"
Width="100"
Margin="{StaticResource ServerItemMargin}"
HorizontalAlignment="Left" />
HorizontalAlignment="Left"
Style="{StaticResource DefTextBox}" />
</Grid>
<Separator
@@ -145,7 +152,8 @@
Grid.Row="1"
Grid.Column="1"
Width="400"
Margin="{StaticResource ServerItemMargin}" />
Margin="{StaticResource ServerItemMargin}"
Style="{StaticResource DefTextBox}" />
<Button
x:Name="btnGUID"
Grid.Row="1"
@@ -168,7 +176,8 @@
Grid.Column="1"
Width="100"
Margin="{StaticResource ServerItemMargin}"
HorizontalAlignment="Left" />
HorizontalAlignment="Left"
Style="{StaticResource DefTextBox}" />
<TextBlock
Grid.Row="3"
@@ -213,7 +222,8 @@
Grid.Row="1"
Grid.Column="1"
Width="400"
Margin="{StaticResource ServerItemMargin}" />
Margin="{StaticResource ServerItemMargin}"
Style="{StaticResource DefTextBox}" />
<TextBlock
Grid.Row="2"
@@ -258,7 +268,8 @@
Grid.Row="1"
Grid.Column="1"
Width="400"
Margin="{StaticResource ServerItemMargin}" />
Margin="{StaticResource ServerItemMargin}"
Style="{StaticResource DefTextBox}" />
<TextBlock
Grid.Row="2"
@@ -272,7 +283,8 @@
Grid.Row="2"
Grid.Column="1"
Width="400"
Margin="{StaticResource ServerItemMargin}" />
Margin="{StaticResource ServerItemMargin}"
Style="{StaticResource DefTextBox}" />
</Grid>
<Grid
@@ -303,7 +315,8 @@
Grid.Row="1"
Grid.Column="1"
Width="400"
Margin="{StaticResource ServerItemMargin}" />
Margin="{StaticResource ServerItemMargin}"
Style="{StaticResource DefTextBox}" />
<Button
x:Name="btnGUID5"
Grid.Row="1"
@@ -341,7 +354,8 @@
Grid.Column="1"
Width="200"
Margin="{StaticResource ServerItemMargin}"
HorizontalAlignment="Left" />
HorizontalAlignment="Left"
Style="{StaticResource DefTextBox}" />
</Grid>
<Grid
x:Name="gridTrojan"
@@ -370,7 +384,8 @@
Grid.Row="1"
Grid.Column="1"
Width="400"
Margin="{StaticResource ServerItemMargin}" />
Margin="{StaticResource ServerItemMargin}"
Style="{StaticResource DefTextBox}" />
<TextBlock
Grid.Row="2"
@@ -475,7 +490,8 @@
Grid.Row="3"
Grid.Column="1"
Width="400"
Margin="{StaticResource ServerItemMargin}" />
Margin="{StaticResource ServerItemMargin}"
Style="{StaticResource DefTextBox}" />
<TextBlock
x:Name="tipRequestHost"
Grid.Row="3"
@@ -497,7 +513,8 @@
Grid.Row="4"
Grid.Column="1"
Width="400"
Margin="{StaticResource ServerItemMargin}" />
Margin="{StaticResource ServerItemMargin}"
Style="{StaticResource DefTextBox}" />
<TextBlock
x:Name="tipPath"
Grid.Row="4"
@@ -569,7 +586,8 @@
Grid.Column="1"
Width="400"
Margin="{StaticResource ServerItemMargin}"
HorizontalAlignment="Left" />
HorizontalAlignment="Left"
Style="{StaticResource DefTextBox}" />
<TextBlock
Grid.Row="2"
@@ -599,6 +617,7 @@
Grid.Column="1"
Width="200"
Margin="{StaticResource ServerItemMargin}"
IsEditable="True"
Style="{StaticResource DefComboBox}" />
<TextBlock

View File

@@ -16,6 +16,7 @@ namespace v2rayN.Views
public AddServerWindow(ProfileItem profileItem)
{
InitializeComponent();
this.Owner = Application.Current.MainWindow;
this.Loaded += Window_Loaded;
cmbNetwork.SelectionChanged += CmbNetwork_SelectionChanged;
cmbStreamSecurity.SelectionChanged += CmbStreamSecurity_SelectionChanged;

View File

@@ -3,6 +3,7 @@
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:Views="clr-namespace:v2rayN.Views"
xmlns:conv="clr-namespace:v2rayN.Converters"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:materialDesign="http://materialdesigninxaml.net/winfx/xaml/themes"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
@@ -14,8 +15,11 @@
Height="500"
x:TypeArguments="vms:SubEditViewModel"
Background="{DynamicResource MaterialDesignPaper}"
FontFamily="{x:Static conv:MaterialDesignFonts.MyFont}"
KeyDown="GlobalHotkeySettingWindow_KeyDown"
ResizeMode="NoResize"
ShowInTaskbar="False"
TextElement.FontFamily="{x:Static conv:MaterialDesignFonts.MyFont}"
TextElement.Foreground="{DynamicResource MaterialDesignBody}"
TextOptions.TextFormattingMode="Display"
TextOptions.TextRenderingMode="Auto"
@@ -68,7 +72,7 @@
VerticalAlignment="Top"
AcceptsReturn="True"
IsReadOnly="True"
Style="{StaticResource MaterialDesignOutlinedTextBox}" />
Style="{StaticResource MyOutlinedTextBox}" />
<TextBlock
Grid.Row="2"
@@ -85,7 +89,7 @@
VerticalAlignment="Top"
AcceptsReturn="True"
IsReadOnly="True"
Style="{StaticResource MaterialDesignOutlinedTextBox}" />
Style="{StaticResource MyOutlinedTextBox}" />
<TextBlock
Grid.Row="3"
@@ -102,7 +106,7 @@
VerticalAlignment="Top"
AcceptsReturn="True"
IsReadOnly="True"
Style="{StaticResource MaterialDesignOutlinedTextBox}" />
Style="{StaticResource MyOutlinedTextBox}" />
<TextBlock
Grid.Row="4"
Grid.Column="0"
@@ -118,7 +122,7 @@
VerticalAlignment="Top"
AcceptsReturn="True"
IsReadOnly="True"
Style="{StaticResource MaterialDesignOutlinedTextBox}" />
Style="{StaticResource MyOutlinedTextBox}" />
<TextBlock
Grid.Row="5"
Grid.Column="0"
@@ -134,7 +138,7 @@
VerticalAlignment="Top"
AcceptsReturn="True"
IsReadOnly="True"
Style="{StaticResource MaterialDesignOutlinedTextBox}" />
Style="{StaticResource MyOutlinedTextBox}" />
</Grid>
<TextBlock

View File

@@ -16,6 +16,7 @@ namespace v2rayN.Views
public GlobalHotkeySettingWindow()
{
InitializeComponent();
this.Owner = Application.Current.MainWindow;
_config = LazyConfig.Instance.GetConfig();
if (_config.globalHotkeys == null)

View File

@@ -3,7 +3,7 @@
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:base="clr-namespace:v2rayN.Base"
xmlns:converters="clr-namespace:v2rayN.Converters"
xmlns:conv="clr-namespace:v2rayN.Converters"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:v2rayN.Views"
xmlns:materialDesign="http://materialdesigninxaml.net/winfx/xaml/themes"
@@ -19,7 +19,9 @@
MinHeight="600"
x:TypeArguments="vms:MainWindowViewModel"
Background="{DynamicResource MaterialDesignPaper}"
FontFamily="{x:Static conv:MaterialDesignFonts.MyFont}"
ShowInTaskbar="True"
TextElement.FontFamily="{x:Static conv:MaterialDesignFonts.MyFont}"
TextElement.Foreground="{DynamicResource MaterialDesignBody}"
TextOptions.TextFormattingMode="Display"
TextOptions.TextRenderingMode="Auto"
@@ -31,7 +33,7 @@
<ResourceDictionary Source="pack://application:,,,/MaterialDesignThemes.Wpf;component/Themes/MaterialDesignTheme.Popupbox.xaml" />
</ResourceDictionary.MergedDictionaries>
<BooleanToVisibilityConverter x:Key="BoolToVisConverter" />
<converters:DelayColorConverter x:Key="DelayColorConverter" />
<conv:DelayColorConverter x:Key="DelayColorConverter" />
</ResourceDictionary>
</Window.Resources>
@@ -47,7 +49,7 @@
VerticalAlignment="Center"
ClipToBounds="True"
Style="{StaticResource MaterialDesignToolBar}">
<Menu Margin="0,8" Style="{StaticResource ToolbarMenu}">
<Menu Margin="0,1" Style="{StaticResource ToolbarMenu}">
<MenuItem Padding="8,0">
<MenuItem.Header>
<StackPanel Orientation="Horizontal">
@@ -93,7 +95,7 @@
</MenuItem>
</Menu>
<Separator />
<Menu Margin="0,8" Style="{StaticResource ToolbarMenu}">
<Menu Margin="0,1" Style="{StaticResource ToolbarMenu}">
<MenuItem Padding="8,0">
<MenuItem.Header>
<StackPanel Orientation="Horizontal">
@@ -125,7 +127,7 @@
</MenuItem>
</Menu>
<Separator />
<Menu Margin="0,8" Style="{StaticResource ToolbarMenu}">
<Menu Margin="0,1" Style="{StaticResource ToolbarMenu}">
<MenuItem Padding="8,0">
<MenuItem.Header>
<StackPanel Orientation="Horizontal">
@@ -163,7 +165,7 @@
</MenuItem>
</Menu>
<Separator />
<Menu Margin="0,8" Style="{StaticResource ToolbarMenu}">
<Menu Margin="0,1" Style="{StaticResource ToolbarMenu}">
<MenuItem x:Name="menuReload" Padding="8,0">
<MenuItem.Header>
<StackPanel Orientation="Horizontal">
@@ -174,7 +176,7 @@
</MenuItem>
</Menu>
<Separator />
<Menu Margin="0,8" Style="{StaticResource ToolbarMenu}">
<Menu Margin="0,1" Style="{StaticResource ToolbarMenu}">
<MenuItem Padding="8,0">
<MenuItem.Header>
<StackPanel Orientation="Horizontal">
@@ -215,7 +217,7 @@
</MenuItem>
</Menu>
<Separator />
<Menu Margin="0,8" Style="{StaticResource ToolbarMenu}">
<Menu Margin="0,1" Style="{StaticResource ToolbarMenu}">
<MenuItem x:Name="menuHelp" Padding="8,0">
<MenuItem.Header>
<StackPanel Orientation="Horizontal">
@@ -226,7 +228,7 @@
</MenuItem>
</Menu>
<Separator />
<Menu Margin="0,8" Style="{StaticResource ToolbarMenu}">
<Menu Margin="0,1" Style="{StaticResource ToolbarMenu}">
<MenuItem
x:Name="menuPromotion"
Padding="8,0"
@@ -240,7 +242,7 @@
</MenuItem>
</Menu>
<Separator />
<Menu Margin="0,8" Style="{StaticResource ToolbarMenu}">
<Menu Margin="0,1" Style="{StaticResource ToolbarMenu}">
<MenuItem
x:Name="menuClose"
Padding="8,0"
@@ -259,71 +261,106 @@
HorizontalAlignment="Right"
Style="{StaticResource MaterialDesignToolForegroundPopupBox}">
<StackPanel Margin="8">
<StackPanel Orientation="Horizontal">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<TextBlock
Grid.Row="0"
Grid.Column="0"
VerticalAlignment="Center"
Style="{StaticResource ToolbarTextBlock}"
Text="{x:Static resx:ResUI.TbSettingsColorMode}" />
<ToggleButton x:Name="togDarkMode" Margin="8" />
</StackPanel>
<StackPanel Orientation="Horizontal">
<ToggleButton
x:Name="togDarkMode"
Grid.Row="0"
Grid.Column="1"
Margin="8" />
<TextBlock
Grid.Row="1"
Grid.Column="0"
VerticalAlignment="Center"
Style="{StaticResource ToolbarTextBlock}"
Text="{x:Static resx:ResUI.TbSettingsColor}" />
<ComboBox
x:Name="cmbSwatches"
Grid.Row="1"
Grid.Column="1"
Width="100"
Margin="8"
DisplayMemberPath="Name"
Style="{StaticResource DefComboBox}" />
</StackPanel>
<StackPanel Orientation="Horizontal">
<TextBlock
Grid.Row="2"
Grid.Column="0"
VerticalAlignment="Center"
Style="{StaticResource ToolbarTextBlock}"
Text="{x:Static resx:ResUI.TbSettingsFontSize}" />
<ComboBox
x:Name="cmbCurrentFontSize"
Grid.Row="2"
Grid.Column="1"
Width="100"
Margin="8"
Style="{StaticResource DefComboBox}" />
<TextBlock
Grid.Row="3"
Grid.Column="0"
VerticalAlignment="Center"
Style="{StaticResource ToolbarTextBlock}"
Text="{x:Static resx:ResUI.TbSettingsLanguage}" />
<ComboBox
x:Name="cmbCurrentLanguage"
Grid.Row="3"
Grid.Column="1"
Width="100"
Margin="8"
materialDesign:HintAssist.Hint="Language"
Style="{StaticResource DefComboBox}" />
</StackPanel>
</Grid>
</StackPanel>
</materialDesign:PopupBox>
</ToolBar>
</ToolBarTray>
<ToolBarTray DockPanel.Dock="Top">
<ToolBar
HorizontalAlignment="Center"
VerticalAlignment="Center"
ClipToBounds="True"
Style="{StaticResource MaterialDesignToolBar}">
<ListBox x:Name="lstGroup" Style="{StaticResource MaterialDesignChoiceChipPrimaryOutlineListBox}">
<ListBox.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding remarks}" />
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
<Button
x:Name="btnAddSub"
Width="30"
Height="30"
Margin="8,0"
Style="{StaticResource MaterialDesignFloatingActionMiniLightButton}">
<materialDesign:PackIcon Kind="Plus" />
</Button>
<Separator />
<TextBox
x:Name="txtServerFilter"
Width="200"
Margin="8,0"
materialDesign:HintAssist.Hint="{x:Static resx:ResUI.MsgServerTitle}"
materialDesign:TextFieldAssist.HasClearButton="True" />
</ToolBar>
</ToolBarTray>
<WrapPanel Margin="2" DockPanel.Dock="Top">
<ListBox
x:Name="lstGroup"
FontSize="{DynamicResource StdFontSize}"
ItemContainerStyle="{StaticResource MyChipListBoxItem}"
Style="{StaticResource MaterialDesignChoiceChipPrimaryOutlineListBox}">
<ListBox.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding remarks}" />
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
<Button
x:Name="btnAddSub"
Width="30"
Height="30"
Margin="4,0"
Style="{StaticResource MaterialDesignFloatingActionMiniLightButton}">
<materialDesign:PackIcon Kind="Plus" />
</Button>
<TextBox
x:Name="txtServerFilter"
Width="200"
Margin="4,0"
materialDesign:HintAssist.Hint="{x:Static resx:ResUI.MsgServerTitle}"
materialDesign:TextFieldAssist.HasClearButton="True"
Style="{StaticResource DefTextBox}" />
</WrapPanel>
<materialDesign:ColorZone
Height="50"
@@ -350,11 +387,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"
@@ -371,6 +409,7 @@
Width="120"
Margin="8,0"
materialDesign:HintAssist.Hint="{x:Static resx:ResUI.menuSystemproxy}"
FontSize="{DynamicResource StdFontSize}"
Style="{StaticResource MaterialDesignFloatingHintComboBox}">
<ComboBoxItem Content="{x:Static resx:ResUI.menuSystemProxyClear}" />
<ComboBoxItem Content="{x:Static resx:ResUI.menuSystemProxySet}" />
@@ -384,6 +423,7 @@
Margin="8,0"
materialDesign:HintAssist.Hint="{x:Static resx:ResUI.menuRouting}"
DisplayMemberPath="remarks"
FontSize="{DynamicResource StdFontSize}"
Style="{StaticResource MaterialDesignFloatingHintComboBox}" />
</StackPanel>
@@ -401,7 +441,7 @@
</DockPanel>
</materialDesign:ColorZone>
<Grid>
<Grid x:Name="gridMain">
<Grid.RowDefinitions>
<RowDefinition Height="1*" />
<RowDefinition Height="10" />
@@ -410,7 +450,7 @@
<DataGrid
x:Name="lstProfiles"
Grid.Row="0"
materialDesign:DataGridAssist.CellPadding="1,0"
materialDesign:DataGridAssist.CellPadding="2,2"
AutoGenerateColumns="False"
BorderThickness="1"
CanUserAddRows="False"
@@ -430,6 +470,10 @@
</DataGrid.InputBindings>
<DataGrid.ContextMenu>
<ContextMenu Style="{StaticResource DefContextMenu}">
<MenuItem
x:Name="menuEditServer"
Height="{StaticResource MenuItemHeight}"
Header="{x:Static resx:ResUI.menuEditServer}" />
<MenuItem
x:Name="menuSetDefaultServer"
Height="{StaticResource MenuItemHeight}"
@@ -451,6 +495,31 @@
Height="{StaticResource MenuItemHeight}"
Header="{x:Static resx:ResUI.menuShareServer}" />
<Separator />
<MenuItem
x:Name="menuMixedTestServer"
Height="{StaticResource MenuItemHeight}"
Header="{x:Static resx:ResUI.menuMixedTestServer}" />
<MenuItem
x:Name="menuPingServer"
Height="{StaticResource MenuItemHeight}"
Header="{x:Static resx:ResUI.menuPingServer}" />
<MenuItem
x:Name="menuTcpingServer"
Height="{StaticResource MenuItemHeight}"
Header="{x:Static resx:ResUI.menuTcpingServer}" />
<MenuItem
x:Name="menuRealPingServer"
Height="{StaticResource MenuItemHeight}"
Header="{x:Static resx:ResUI.menuRealPingServer}" />
<MenuItem
x:Name="menuSpeedServer"
Height="{StaticResource MenuItemHeight}"
Header="{x:Static resx:ResUI.menuSpeedServer}" />
<MenuItem
x:Name="menuSortServerResult"
Height="{StaticResource MenuItemHeight}"
Header="{x:Static resx:ResUI.menuSortServerResult}" />
<Separator />
<MenuItem
x:Name="menuMoveToGroup"
Height="{StaticResource MenuItemHeight}"
@@ -463,6 +532,7 @@
Width="200"
materialDesign:HintAssist.Hint="{x:Static resx:ResUI.menuSubscription}"
DisplayMemberPath="remarks"
FontSize="{DynamicResource StdFontSize}"
Style="{StaticResource MaterialDesignFilledComboBox}" />
</DockPanel>
</MenuItem.Header>
@@ -490,31 +560,6 @@
Click="menuSelectAll_Click"
Header="{x:Static resx:ResUI.menuSelectAll}" />
<Separator />
<MenuItem
x:Name="menuMixedTestServer"
Height="{StaticResource MenuItemHeight}"
Header="{x:Static resx:ResUI.menuMixedTestServer}" />
<MenuItem
x:Name="menuPingServer"
Height="{StaticResource MenuItemHeight}"
Header="{x:Static resx:ResUI.menuPingServer}" />
<MenuItem
x:Name="menuTcpingServer"
Height="{StaticResource MenuItemHeight}"
Header="{x:Static resx:ResUI.menuTcpingServer}" />
<MenuItem
x:Name="menuRealPingServer"
Height="{StaticResource MenuItemHeight}"
Header="{x:Static resx:ResUI.menuRealPingServer}" />
<MenuItem
x:Name="menuSpeedServer"
Height="{StaticResource MenuItemHeight}"
Header="{x:Static resx:ResUI.menuSpeedServer}" />
<MenuItem
x:Name="menuSortServerResult"
Height="{StaticResource MenuItemHeight}"
Header="{x:Static resx:ResUI.menuSortServerResult}" />
<Separator />
<MenuItem
x:Name="menuExport2ClientConfig"
Height="{StaticResource MenuItemHeight}"
@@ -696,6 +741,7 @@
MaxWidth="300"
materialDesign:HintAssist.Hint="{x:Static resx:ResUI.menuRouting}"
DisplayMemberPath="remarks"
FontSize="{DynamicResource StdFontSize}"
Style="{StaticResource MaterialDesignFilledComboBox}" />
</DockPanel>
</MenuItem.Header>
@@ -708,6 +754,7 @@
MaxWidth="300"
materialDesign:HintAssist.Hint="{x:Static resx:ResUI.menuServers}"
DisplayMemberPath="Text"
FontSize="{DynamicResource StdFontSize}"
Style="{StaticResource MaterialDesignFilledComboBox}" />
</DockPanel>
</MenuItem.Header>

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,10 +33,23 @@ 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));
for (int i = Global.MinFontSize; i <= Global.MinFontSize + 8; i++)
{
cmbCurrentFontSize.Items.Add(i.ToString());
}
Global.Languages.ForEach(it =>
{
cmbCurrentLanguage.Items.Add(it);
@@ -59,6 +76,7 @@ namespace v2rayN.Views
this.BindCommand(ViewModel, vm => vm.AddServerViaScanCmd, v => v.menuAddServerViaScan).DisposeWith(disposables);
//servers delete
this.BindCommand(ViewModel, vm => vm.EditServerCmd, v => v.menuEditServer).DisposeWith(disposables);
this.BindCommand(ViewModel, vm => vm.RemoveServerCmd, v => v.menuRemoveServer).DisposeWith(disposables);
this.BindCommand(ViewModel, vm => vm.RemoveDuplicateServerCmd, v => v.menuRemoveDuplicateServer).DisposeWith(disposables);
this.BindCommand(ViewModel, vm => vm.CopyServerCmd, v => v.menuCopyServer).DisposeWith(disposables);
@@ -91,8 +109,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
@@ -160,6 +178,7 @@ namespace v2rayN.Views
this.Bind(ViewModel, vm => vm.ColorModeDark, v => v.togDarkMode.IsChecked).DisposeWith(disposables);
this.OneWayBind(ViewModel, vm => vm.Swatches, v => v.cmbSwatches.ItemsSource).DisposeWith(disposables);
this.Bind(ViewModel, vm => vm.SelectedSwatch, v => v.cmbSwatches.SelectedItem).DisposeWith(disposables);
this.Bind(ViewModel, vm => vm.CurrentFontSize, v => v.cmbCurrentFontSize.Text).DisposeWith(disposables);
this.Bind(ViewModel, vm => vm.CurrentLanguage, v => v.cmbCurrentLanguage.Text).DisposeWith(disposables);
});
@@ -169,8 +188,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
@@ -229,17 +247,32 @@ namespace v2rayN.Views
private void LstProfiles_MouseDoubleClick(object sender, MouseButtonEventArgs e)
{
ViewModel?.EditServer(false, EConfigType.Custom);
if (_config.uiItem.doubleClick2Activate)
{
ViewModel?.SetDefaultServer();
}
else
{
ViewModel?.EditServer(false, EConfigType.Custom);
}
}
private void LstProfiles_ColumnHeader_Click(object sender, RoutedEventArgs e)
{
var colHeader = sender as DataGridColumnHeader;
if (colHeader == null || colHeader.TabIndex < 0)
if (colHeader == null || colHeader.TabIndex < 0 || colHeader.Column == null)
{
return;
}
if (colHeader.TabIndex == 0)
//find index
var index = lstProfiles.Columns.IndexOf(colHeader.Column);
if (index < 0)
{
index = colHeader.TabIndex;
}
if (index == 0)
{
foreach (var it in lstProfiles.Columns)
{
@@ -249,7 +282,7 @@ namespace v2rayN.Views
return;
}
ViewModel?.SortServer(colHeader.TabIndex);
ViewModel?.SortServer(index);
}
private void menuSelectAll_Click(object sender, RoutedEventArgs e)
@@ -312,6 +345,10 @@ namespace v2rayN.Views
ViewModel?.Export2ShareUrl();
}
else if (e.Key == Key.D)
{
ViewModel?.EditServer(false, EConfigType.Custom);
}
else if (e.Key == Key.F)
{
ViewModel?.ShareServer();
}
@@ -372,24 +409,32 @@ 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;
}
if (_config.uiItem.mainGirdHeight1 > 0 && _config.uiItem.mainGirdHeight2 > 0)
{
gridMain.RowDefinitions[0].Height = new GridLength(_config.uiItem.mainGirdHeight1, GridUnitType.Star);
gridMain.RowDefinitions[2].Height = new GridLength(_config.uiItem.mainGirdHeight2, GridUnitType.Star);
}
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));
lstProfiles.Columns[k].Width = width;
}
if (!_config.enableStatistics)
if (!_config.guiItem.enableStatistics)
{
colTodayUp.Visibility = Visibility.Hidden;
colTodayDown.Visibility = Visibility.Hidden;
@@ -406,6 +451,8 @@ namespace v2rayN.Views
{
ConfigHandler.AddformMainLvColWidth(ref _config, ((EServerColName)k).ToString(), Convert.ToInt32(lstProfiles.Columns[k].ActualWidth));
}
_config.uiItem.mainGirdHeight1 = Math.Ceiling(gridMain.RowDefinitions[0].ActualHeight + 0.1);
_config.uiItem.mainGirdHeight2 = Math.Ceiling(gridMain.RowDefinitions[2].ActualHeight + 0.1);
}
private void AddHelpMenuItem()
@@ -433,6 +480,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

@@ -20,20 +20,35 @@
Margin="8,0"
VerticalAlignment="Center"
Foreground="{DynamicResource PrimaryHueLightBrush}"
Style="{StaticResource ToolbarTextBlock}"
Text="{x:Static resx:ResUI.MsgInformationTitle}" />
<TextBox
x:Name="txtMsgFilter"
<ComboBox
x:Name="cmbMsgFilter"
Width="200"
Margin="8,0"
materialDesign:HintAssist.Hint="{x:Static resx:ResUI.MsgFilterTitle}"
materialDesign:TextFieldAssist.HasClearButton="True" />
materialDesign:TextFieldAssist.HasClearButton="True"
IsEditable="True"
Style="{StaticResource DefComboBox}"
TextBoxBase.TextChanged="cmbMsgFilter_TextChanged" />
<TextBlock
Margin="8,0"
VerticalAlignment="Center"
Style="{StaticResource ToolbarTextBlock}"
Text="{x:Static resx:ResUI.TbAutoRefresh}" />
<ToggleButton
x:Name="togAutoRefresh"
Margin="8,0"
HorizontalAlignment="Left"
IsChecked="True" />
</StackPanel>
<TextBox
Name="txtMsg"
BorderThickness="0"
FontSize="11"
FontSize="{DynamicResource StdFontSizeMsg}"
HorizontalScrollBarVisibility="Auto"
IsReadOnly="True"
TextAlignment="Left"
TextWrapping="Wrap"
VerticalScrollBarVisibility="Visible">
<TextBox.ContextMenu>

View File

@@ -3,15 +3,27 @@ using System.Reactive.Linq;
using System.Text.RegularExpressions;
using System.Windows.Threading;
using v2rayN.Base;
using v2rayN.Handler;
using v2rayN.Mode;
namespace v2rayN.Views
{
public partial class MsgView
{
private static Config _config;
public MsgView()
{
InitializeComponent();
_config = LazyConfig.Instance.GetConfig();
MessageBus.Current.Listen<string>("MsgView").Subscribe(x => DelegateAppendText(x));
Global.PresetMsgFilters.ForEach(it =>
{
cmbMsgFilter.Items.Add(it);
});
if (!_config.uiItem.mainMsgFilter.IsNullOrEmpty())
{
cmbMsgFilter.Text = _config.uiItem.mainMsgFilter;
}
}
void DelegateAppendText(string msg)
@@ -26,7 +38,11 @@ namespace v2rayN.Views
ClearMsg();
return;
}
var MsgFilter = txtMsgFilter.Text.TrimEx();
if (!togAutoRefresh.IsChecked.Value)
{
return;
}
var MsgFilter = cmbMsgFilter.Text.TrimEx();
if (!Utils.IsNullOrEmpty(MsgFilter))
{
if (!Regex.IsMatch(msg, MsgFilter))
@@ -79,6 +95,10 @@ namespace v2rayN.Views
{
ClearMsg();
}
private void cmbMsgFilter_TextChanged(object sender, System.Windows.Controls.TextChangedEventArgs e)
{
_config.uiItem.mainMsgFilter = cmbMsgFilter.Text.TrimEx();
}
}
}

View File

@@ -2,6 +2,7 @@
x:Class="v2rayN.Views.OptionSettingWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:conv="clr-namespace:v2rayN.Converters"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:materialDesign="http://materialdesigninxaml.net/winfx/xaml/themes"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
@@ -13,7 +14,10 @@
Height="700"
x:TypeArguments="vms:OptionSettingViewModel"
Background="{DynamicResource MaterialDesignPaper}"
FontFamily="{x:Static conv:MaterialDesignFonts.MyFont}"
ResizeMode="NoResize"
ShowInTaskbar="False"
TextElement.FontFamily="{x:Static conv:MaterialDesignFonts.MyFont}"
TextElement.Foreground="{DynamicResource MaterialDesignBody}"
TextOptions.TextFormattingMode="Display"
TextOptions.TextRenderingMode="Auto"
@@ -45,194 +49,250 @@
<TabControl>
<TabItem Header="{x:Static resx:ResUI.TbSettingsCore}">
<Grid Margin="{StaticResource SettingItemMargin}">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<ScrollViewer VerticalScrollBarVisibility="Visible">
<Grid Margin="{StaticResource SettingItemMargin}">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<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" />
</Grid.ColumnDefinitions>
<TextBlock
Grid.Row="0"
Grid.Column="0"
Margin="{StaticResource SettingItemMargin}"
VerticalAlignment="Center"
Style="{StaticResource ToolbarTextBlock}"
Text="{x:Static resx:ResUI.TbSettingsSocksPort}" />
<TextBox
x:Name="txtlocalPort"
Grid.Row="0"
Grid.Column="1"
Width="200"
Margin="{StaticResource SettingItemMargin}" />
<TextBlock
Grid.Row="0"
Grid.Column="0"
Margin="{StaticResource SettingItemMargin}"
VerticalAlignment="Center"
Style="{StaticResource ToolbarTextBlock}"
Text="{x:Static resx:ResUI.TbSettingsSocksPort}" />
<TextBox
x:Name="txtlocalPort"
Grid.Row="0"
Grid.Column="1"
Width="200"
Margin="{StaticResource SettingItemMargin}"
Style="{StaticResource DefTextBox}" />
<TextBlock
Grid.Row="0"
Grid.Column="2"
Margin="{StaticResource ServerItemMargin}"
VerticalAlignment="Center"
Style="{StaticResource ToolbarTextBlock}"
Text="{x:Static resx:ResUI.TbSettingsSocksPortTip}" />
<TextBlock
Grid.Row="1"
Grid.Column="0"
Margin="{StaticResource SettingItemMargin}"
VerticalAlignment="Center"
Style="{StaticResource ToolbarTextBlock}"
Text="{x:Static resx:ResUI.TbSettingsUdpEnabled}" />
<ToggleButton
x:Name="togudpEnabled"
Grid.Row="1"
Grid.Column="1"
Margin="{StaticResource SettingItemMargin}"
HorizontalAlignment="Left" />
<TextBlock
Grid.Row="1"
Grid.Column="0"
Margin="{StaticResource SettingItemMargin}"
VerticalAlignment="Center"
Style="{StaticResource ToolbarTextBlock}"
Text="{x:Static resx:ResUI.TbSettingsUdpEnabled}" />
<ToggleButton
x:Name="togudpEnabled"
Grid.Row="1"
Grid.Column="1"
Margin="{StaticResource SettingItemMargin}"
HorizontalAlignment="Left" />
<TextBlock
Grid.Row="2"
Grid.Column="0"
Margin="{StaticResource SettingItemMargin}"
VerticalAlignment="Center"
Style="{StaticResource ToolbarTextBlock}"
Text="{x:Static resx:ResUI.TbSettingsSniffingEnabled}" />
<ToggleButton
x:Name="togsniffingEnabled"
Grid.Row="2"
Grid.Column="1"
Margin="{StaticResource SettingItemMargin}"
HorizontalAlignment="Left" />
<TextBlock
Grid.Row="2"
Grid.Column="0"
Margin="{StaticResource SettingItemMargin}"
VerticalAlignment="Center"
Style="{StaticResource ToolbarTextBlock}"
Text="{x:Static resx:ResUI.TbSettingsSniffingEnabled}" />
<ToggleButton
x:Name="togsniffingEnabled"
Grid.Row="2"
Grid.Column="1"
Margin="{StaticResource SettingItemMargin}"
HorizontalAlignment="Left" />
<TextBlock
Grid.Row="3"
Grid.Column="0"
Margin="{StaticResource SettingItemMargin}"
VerticalAlignment="Center"
Style="{StaticResource ToolbarTextBlock}"
Text="{x:Static resx:ResUI.TbSettingsRouteOnly}" />
<ToggleButton
x:Name="togrouteOnly"
Grid.Row="3"
Grid.Column="1"
Margin="{StaticResource SettingItemMargin}"
HorizontalAlignment="Left" />
<TextBlock
Grid.Row="3"
Grid.Column="0"
Margin="{StaticResource SettingItemMargin}"
VerticalAlignment="Center"
Style="{StaticResource ToolbarTextBlock}"
Text="{x:Static resx:ResUI.TbSettingsRouteOnly}" />
<ToggleButton
x:Name="togrouteOnly"
Grid.Row="3"
Grid.Column="1"
Margin="{StaticResource SettingItemMargin}"
HorizontalAlignment="Left" />
<TextBlock
Grid.Row="4"
Grid.Column="0"
Margin="{StaticResource SettingItemMargin}"
VerticalAlignment="Center"
Style="{StaticResource ToolbarTextBlock}"
Text="{x:Static resx:ResUI.TbSettingsAllowLAN}" />
<ToggleButton
x:Name="togAllowLANConn"
Grid.Row="4"
Grid.Column="1"
Margin="{StaticResource SettingItemMargin}"
HorizontalAlignment="Left" />
<TextBlock
Grid.Row="4"
Grid.Column="0"
Margin="{StaticResource SettingItemMargin}"
VerticalAlignment="Center"
Style="{StaticResource ToolbarTextBlock}"
Text="{x:Static resx:ResUI.TbSettingsAllowLAN}" />
<ToggleButton
x:Name="togAllowLANConn"
Grid.Row="4"
Grid.Column="1"
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.TbSettingsNewPort4LAN}" />
<ToggleButton
x:Name="togNewPort4LAN"
Grid.Row="5"
Grid.Column="1"
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.TbSettingsNewPort4LAN}" />
<ToggleButton
x:Name="togNewPort4LAN"
Grid.Row="5"
Grid.Column="1"
Margin="{StaticResource SettingItemMargin}"
HorizontalAlignment="Left" />
<TextBlock
Grid.Row="6"
Grid.Column="0"
Margin="{StaticResource SettingItemMargin}"
VerticalAlignment="Center"
Style="{StaticResource ToolbarTextBlock}"
Text="{x:Static resx:ResUI.TbSettingsUser}" />
<TextBox
x:Name="txtuser"
Grid.Row="6"
Grid.Column="1"
Width="200"
Margin="{StaticResource SettingItemMargin}" />
<TextBlock
Grid.Row="6"
Grid.Column="0"
Margin="{StaticResource SettingItemMargin}"
VerticalAlignment="Center"
Style="{StaticResource ToolbarTextBlock}"
Text="{x:Static resx:ResUI.TbSettingsUser}" />
<TextBox
x:Name="txtuser"
Grid.Row="6"
Grid.Column="1"
Width="200"
Margin="{StaticResource SettingItemMargin}"
Style="{StaticResource DefTextBox}" />
<TextBlock
Grid.Row="7"
Grid.Column="0"
Margin="{StaticResource SettingItemMargin}"
VerticalAlignment="Center"
Style="{StaticResource ToolbarTextBlock}"
Text="{x:Static resx:ResUI.TbSettingsPass}" />
<TextBox
x:Name="txtpass"
Grid.Row="7"
Grid.Column="1"
Width="200"
Margin="{StaticResource SettingItemMargin}" />
<TextBlock
Grid.Row="7"
Grid.Column="0"
Margin="{StaticResource SettingItemMargin}"
VerticalAlignment="Center"
Style="{StaticResource ToolbarTextBlock}"
Text="{x:Static resx:ResUI.TbSettingsPass}" />
<TextBox
x:Name="txtpass"
Grid.Row="7"
Grid.Column="1"
Width="200"
Margin="{StaticResource SettingItemMargin}"
Style="{StaticResource DefTextBox}" />
<TextBlock
Grid.Row="8"
Grid.Column="0"
Margin="{StaticResource SettingItemMargin}"
VerticalAlignment="Center"
Style="{StaticResource ToolbarTextBlock}"
Text="{x:Static resx:ResUI.TbSettingsMuxEnabled}" />
<ToggleButton
x:Name="togmuxEnabled"
Grid.Row="8"
Grid.Column="1"
Margin="{StaticResource SettingItemMargin}"
HorizontalAlignment="Left" />
<TextBlock
Grid.Row="8"
Grid.Column="0"
Margin="{StaticResource SettingItemMargin}"
VerticalAlignment="Center"
Style="{StaticResource ToolbarTextBlock}"
Text="{x:Static resx:ResUI.TbSettingsMuxEnabled}" />
<ToggleButton
x:Name="togmuxEnabled"
Grid.Row="8"
Grid.Column="1"
Margin="{StaticResource SettingItemMargin}"
HorizontalAlignment="Left" />
<TextBlock
Grid.Row="9"
Grid.Column="0"
Margin="{StaticResource SettingItemMargin}"
VerticalAlignment="Center"
Style="{StaticResource ToolbarTextBlock}"
Text="{x:Static resx:ResUI.TbSettingsLogEnabled}" />
<ToggleButton
x:Name="toglogEnabled"
Grid.Row="9"
Grid.Column="1"
Margin="{StaticResource SettingItemMargin}"
HorizontalAlignment="Left" />
<TextBlock
Grid.Row="9"
Grid.Column="0"
Margin="{StaticResource SettingItemMargin}"
VerticalAlignment="Center"
Style="{StaticResource ToolbarTextBlock}"
Text="{x:Static resx:ResUI.TbSettingsLogEnabled}" />
<ToggleButton
x:Name="toglogEnabled"
Grid.Row="9"
Grid.Column="1"
Margin="{StaticResource SettingItemMargin}"
HorizontalAlignment="Left" />
<TextBlock
Grid.Row="10"
Grid.Column="0"
Margin="{StaticResource SettingItemMargin}"
VerticalAlignment="Center"
Style="{StaticResource ToolbarTextBlock}"
Text="{x:Static resx:ResUI.TbSettingsLogLevel}" />
<ComboBox
x:Name="cmbloglevel"
Grid.Row="10"
Grid.Column="1"
Margin="{StaticResource SettingItemMargin}"
materialDesign:HintAssist.Hint="Level" />
<TextBlock
Grid.Row="10"
Grid.Column="0"
Margin="{StaticResource SettingItemMargin}"
VerticalAlignment="Center"
Style="{StaticResource ToolbarTextBlock}"
Text="{x:Static resx:ResUI.TbSettingsLogLevel}" />
<ComboBox
x:Name="cmbloglevel"
Grid.Row="10"
Grid.Column="1"
Width="200"
Margin="{StaticResource SettingItemMargin}"
materialDesign:HintAssist.Hint="Level"
Style="{StaticResource DefComboBox}" />
<TextBlock
Grid.Row="11"
Grid.Column="0"
Margin="{StaticResource SettingItemMargin}"
VerticalAlignment="Center"
Style="{StaticResource ToolbarTextBlock}"
Text="{x:Static resx:ResUI.TbSettingsDefAllowInsecure}" />
<ToggleButton
x:Name="togdefAllowInsecure"
Grid.Row="11"
Grid.Column="1"
Margin="{StaticResource SettingItemMargin}"
HorizontalAlignment="Left" />
</Grid>
<TextBlock
Grid.Row="11"
Grid.Column="0"
Margin="{StaticResource SettingItemMargin}"
VerticalAlignment="Center"
Style="{StaticResource ToolbarTextBlock}"
Text="{x:Static resx:ResUI.TbSettingsDefAllowInsecure}" />
<ToggleButton
x:Name="togdefAllowInsecure"
Grid.Row="11"
Grid.Column="1"
Margin="{StaticResource SettingItemMargin}"
HorizontalAlignment="Left" />
<TextBlock
Grid.Row="12"
Grid.Column="0"
Margin="{StaticResource SettingItemMargin}"
VerticalAlignment="Center"
Style="{StaticResource ToolbarTextBlock}"
Text="{x:Static resx:ResUI.TbSettingsDefFingerprint}" />
<ComboBox
x:Name="cmbdefFingerprint"
Grid.Row="12"
Grid.Column="1"
Width="200"
Margin="{StaticResource SettingItemMargin}"
IsEditable="True"
Style="{StaticResource DefComboBox}" />
<TextBlock
Grid.Row="13"
Grid.Column="0"
Margin="{StaticResource SettingItemMargin}"
VerticalAlignment="Center"
Style="{StaticResource ToolbarTextBlock}"
Text="{x:Static resx:ResUI.TbSettingsDefUserAgent}" />
<ComboBox
x:Name="cmbdefUserAgent"
Grid.Row="13"
Grid.Column="1"
Width="200"
Margin="{StaticResource SettingItemMargin}"
IsEditable="True"
Style="{StaticResource DefComboBox}" />
<TextBlock
Grid.Row="13"
Grid.Column="3"
Margin="{StaticResource SettingItemMargin}"
Style="{StaticResource ToolbarTextBlock}"
Text="{x:Static resx:ResUI.TbSettingsDefUserAgentTips}" />
</Grid>
</ScrollViewer>
</TabItem>
<TabItem Header="{x:Static resx:ResUI.TbSettingsCoreDns}">
@@ -246,7 +306,8 @@
<ComboBox
x:Name="cmbdomainStrategy4Freedom"
Width="200"
Margin="{StaticResource SettingItemMargin}" />
Margin="{StaticResource SettingItemMargin}"
Style="{StaticResource DefComboBox}" />
</StackPanel>
<StackPanel DockPanel.Dock="Top" Orientation="Horizontal">
@@ -270,6 +331,7 @@
VerticalAlignment="Stretch"
AcceptsReturn="True"
BorderThickness="1"
Style="{StaticResource DefTextBox}"
TextWrapping="Wrap"
VerticalScrollBarVisibility="Auto" />
</DockPanel>
@@ -303,7 +365,7 @@
VerticalAlignment="Center"
Style="{StaticResource ToolbarTextBlock}"
Text="mtu" />
<TextBox
<TextBox Style="{StaticResource DefTextBox}"
x:Name="txtKcpmtu"
Grid.Row="1"
Grid.Column="1"
@@ -317,7 +379,7 @@
VerticalAlignment="Center"
Style="{StaticResource ToolbarTextBlock}"
Text="tti" />
<TextBox
<TextBox Style="{StaticResource DefTextBox}"
x:Name="txtKcptti"
Grid.Row="2"
Grid.Column="1"
@@ -331,7 +393,7 @@
VerticalAlignment="Center"
Style="{StaticResource ToolbarTextBlock}"
Text="uplinkCapacity" />
<TextBox
<TextBox Style="{StaticResource DefTextBox}"
x:Name="txtKcpuplinkCapacity"
Grid.Row="3"
Grid.Column="1"
@@ -345,7 +407,7 @@
VerticalAlignment="Center"
Style="{StaticResource ToolbarTextBlock}"
Text="downlinkCapacity" />
<TextBox
<TextBox Style="{StaticResource DefTextBox}"
x:Name="txtKcpdownlinkCapacity"
Grid.Row="4"
Grid.Column="1"
@@ -359,7 +421,7 @@
VerticalAlignment="Center"
Style="{StaticResource ToolbarTextBlock}"
Text="readBufferSize" />
<TextBox
<TextBox Style="{StaticResource DefTextBox}"
x:Name="txtKcpreadBufferSize"
Grid.Row="5"
Grid.Column="1"
@@ -373,7 +435,7 @@
VerticalAlignment="Center"
Style="{StaticResource ToolbarTextBlock}"
Text="writeBufferSize" />
<TextBox
<TextBox Style="{StaticResource DefTextBox}"
x:Name="txtKcpwriteBufferSize"
Grid.Row="6"
Grid.Column="1"
@@ -415,10 +477,15 @@
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<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" />
</Grid.ColumnDefinitions>
<TextBlock
@@ -434,6 +501,13 @@
Grid.Column="1"
Margin="{StaticResource SettingItemMargin}"
HorizontalAlignment="Left" />
<TextBlock
Grid.Row="1"
Grid.Column="2"
Margin="{StaticResource ServerItemMargin}"
VerticalAlignment="Center"
Style="{StaticResource ToolbarTextBlock}"
Text="{x:Static resx:ResUI.TbSettingsStartBootTip}" />
<TextBlock
Grid.Row="2"
@@ -461,7 +535,8 @@
Grid.Row="3"
Grid.Column="1"
Width="200"
Margin="{StaticResource SettingItemMargin}" />
Margin="{StaticResource SettingItemMargin}"
Style="{StaticResource DefComboBox}" />
<TextBlock
Grid.Row="4"
@@ -553,13 +628,13 @@
Margin="{StaticResource SettingItemMargin}"
VerticalAlignment="Center"
Style="{StaticResource ToolbarTextBlock}"
Text="{x:Static resx:ResUI.TbSettingsAutoUpdateInterval}" />
<TextBox
x:Name="txtautoUpdateInterval"
Text="{x:Static resx:ResUI.TbSettingsEnableDragDropSort}" />
<ToggleButton
x:Name="togEnableDragDropSort"
Grid.Row="10"
Grid.Column="1"
Width="200"
Margin="{StaticResource SettingItemMargin}" />
Margin="{StaticResource SettingItemMargin}"
HorizontalAlignment="Left" />
<TextBlock
Grid.Row="11"
@@ -567,16 +642,48 @@
Margin="{StaticResource SettingItemMargin}"
VerticalAlignment="Center"
Style="{StaticResource ToolbarTextBlock}"
Text="{x:Static resx:ResUI.TbSettingsDoubleClick2Activate}" />
<ToggleButton
x:Name="togDoubleClick2Activate"
Grid.Row="11"
Grid.Column="1"
Margin="{StaticResource SettingItemMargin}"
HorizontalAlignment="Left" />
<TextBlock
Grid.Row="12"
Grid.Column="0"
Margin="{StaticResource SettingItemMargin}"
VerticalAlignment="Center"
Style="{StaticResource ToolbarTextBlock}"
Text="{x:Static resx:ResUI.TbSettingsAutoUpdateInterval}" />
<TextBox
x:Name="txtautoUpdateInterval"
Grid.Row="12"
Grid.Column="1"
Width="200"
Margin="{StaticResource SettingItemMargin}"
HorizontalAlignment="Left"
Style="{StaticResource DefTextBox}" />
<TextBlock
Grid.Row="13"
Grid.Column="0"
Margin="{StaticResource SettingItemMargin}"
VerticalAlignment="Center"
Style="{StaticResource ToolbarTextBlock}"
Text="{x:Static resx:ResUI.TbSettingsAutoUpdate}" />
<TextBox
x:Name="txtautoUpdateSubInterval"
Grid.Row="11"
Grid.Row="13"
Grid.Column="1"
Width="200"
Margin="{StaticResource SettingItemMargin}" />
Margin="{StaticResource SettingItemMargin}"
HorizontalAlignment="Left"
Style="{StaticResource DefTextBox}" />
<TextBlock
Grid.Row="12"
Grid.Row="14"
Grid.Column="0"
Margin="{StaticResource SettingItemMargin}"
VerticalAlignment="Center"
@@ -584,10 +691,65 @@
Text="{x:Static resx:ResUI.TbSettingsTrayMenuServersLimit}" />
<TextBox
x:Name="txttrayMenuServersLimit"
Grid.Row="12"
Grid.Row="14"
Grid.Column="1"
Width="200"
Margin="{StaticResource SettingItemMargin}" />
Margin="{StaticResource SettingItemMargin}"
HorizontalAlignment="Left"
Style="{StaticResource DefTextBox}" />
<TextBlock
Grid.Row="15"
Grid.Column="0"
Margin="{StaticResource SettingItemMargin}"
VerticalAlignment="Center"
Style="{StaticResource ToolbarTextBlock}"
Text="{x:Static resx:ResUI.TbSettingsCurrentFontFamily}" />
<ComboBox
x:Name="cmbcurrentFontFamily"
Grid.Row="15"
Grid.Column="1"
Width="200"
Margin="{StaticResource SettingItemMargin}"
MaxDropDownHeight="1000"
Style="{StaticResource DefComboBox}" />
<TextBlock
Grid.Row="15"
Grid.Column="2"
Margin="{StaticResource ServerItemMargin}"
VerticalAlignment="Center"
Style="{StaticResource ToolbarTextBlock}"
Text="{x:Static resx:ResUI.TbSettingsCurrentFontFamilyTip}" />
<TextBlock
Grid.Row="16"
Grid.Column="0"
Margin="{StaticResource SettingItemMargin}"
VerticalAlignment="Center"
Style="{StaticResource ToolbarTextBlock}"
Text="{x:Static resx:ResUI.TbSettingsSpeedTestTimeout}" />
<ComboBox
x:Name="cmbSpeedTestTimeout"
Grid.Row="16"
Grid.Column="1"
Width="200"
Margin="{StaticResource SettingItemMargin}"
Style="{StaticResource DefComboBox}" />
<TextBlock
Grid.Row="17"
Grid.Column="0"
Margin="{StaticResource SettingItemMargin}"
VerticalAlignment="Center"
Style="{StaticResource ToolbarTextBlock}"
Text="{x:Static resx:ResUI.TbSettingsSpeedTestUrl}" />
<ComboBox
x:Name="cmbSpeedTestUrl"
Grid.Row="17"
Grid.Column="1"
Width="300"
Margin="{StaticResource SettingItemMargin}"
Style="{StaticResource DefComboBox}" />
</Grid>
</ScrollViewer>
</TabItem>
@@ -604,8 +766,10 @@
<ComboBox
x:Name="cmbsystemProxyAdvancedProtocol"
Grid.Row="4"
MinWidth="200"
Margin="{StaticResource SettingItemMargin}"
materialDesign:HintAssist.Hint="Protocol" />
materialDesign:HintAssist.Hint="Protocol"
Style="{StaticResource DefComboBox}" />
</StackPanel>
@@ -622,6 +786,7 @@
VerticalAlignment="Stretch"
AcceptsReturn="True"
BorderThickness="1"
Style="{StaticResource DefTextBox}"
TextWrapping="Wrap"
VerticalScrollBarVisibility="Auto" />
</DockPanel>
@@ -642,14 +807,16 @@
<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" />
</Grid.ColumnDefinitions>
<TextBlock
Grid.Row="1"
Grid.Row="0"
Grid.Column="0"
Margin="{StaticResource SettingItemMargin}"
VerticalAlignment="Center"
@@ -657,6 +824,20 @@
Text="{x:Static resx:ResUI.TbSettingsTunModeShowWindow}" />
<ToggleButton
x:Name="togShowWindow"
Grid.Row="0"
Grid.Column="1"
Margin="{StaticResource SettingItemMargin}"
HorizontalAlignment="Left" />
<TextBlock
Grid.Row="1"
Grid.Column="0"
Margin="{StaticResource SettingItemMargin}"
VerticalAlignment="Center"
Style="{StaticResource ToolbarTextBlock}"
Text="{x:Static resx:ResUI.TbSettingsLogEnabled}" />
<ToggleButton
x:Name="togEnabledLog"
Grid.Row="1"
Grid.Column="1"
Margin="{StaticResource SettingItemMargin}"
@@ -688,7 +869,9 @@
Grid.Row="3"
Grid.Column="1"
Width="200"
Margin="{StaticResource SettingItemMargin}" />
Margin="{StaticResource SettingItemMargin}"
HorizontalAlignment="Left"
Style="{StaticResource DefComboBox}" />
<TextBlock
Grid.Row="4"
@@ -702,10 +885,65 @@
Grid.Row="4"
Grid.Column="1"
Width="200"
Margin="{StaticResource SettingItemMargin}" />
Margin="{StaticResource SettingItemMargin}"
HorizontalAlignment="Left"
Style="{StaticResource DefComboBox}" />
<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="400"
Margin="{StaticResource SettingItemMargin}"
VerticalAlignment="Top"
AcceptsReturn="True"
Style="{StaticResource DefTextBox}"
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}" />
<TextBlock
Grid.Row="6"
Grid.Column="0"
Margin="{StaticResource SettingItemMargin}"
VerticalAlignment="Center"
Style="{StaticResource ToolbarTextBlock}"
Text="{x:Static resx:ResUI.TbSettingsTunModeBypassMode}" />
<ToggleButton
x:Name="togBypassMode"
Grid.Row="6"
Grid.Column="1"
Margin="{StaticResource SettingItemMargin}"
HorizontalAlignment="Left" />
<TextBlock
Grid.Row="6"
Grid.Column="2"
Margin="{StaticResource ServerItemMargin}"
VerticalAlignment="Center"
Style="{StaticResource ToolbarTextBlock}"
Text="{x:Static resx:ResUI.TbSettingsTunModeBypassModeTip}" />
</Grid>
<Grid Margin="{StaticResource SettingItemMargin}">
<Grid
x:Name="gridTunModeDirect"
Width="600"
Margin="{StaticResource SettingItemMargin}"
HorizontalAlignment="Left">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="1*" />
<ColumnDefinition Width="10" />
@@ -714,10 +952,11 @@
<GroupBox
Grid.Column="0"
Header="{x:Static resx:ResUI.TbSettingsTunModeDirectIP}"
Style="{StaticResource MaterialDesignGroupBox}">
Style="{StaticResource MyGroupBox}">
<TextBox
Name="txtDirectIP"
AcceptsReturn="True"
Style="{StaticResource DefTextBox}"
TextWrapping="Wrap"
VerticalScrollBarVisibility="Auto" />
</GroupBox>
@@ -725,14 +964,51 @@
<GroupBox
Grid.Column="2"
Header="{x:Static resx:ResUI.TbSettingsTunModeDirectProcess}"
Style="{StaticResource MaterialDesignGroupBox}">
Style="{StaticResource MyGroupBox}">
<TextBox
Name="txtDirectProcess"
AcceptsReturn="True"
Style="{StaticResource DefTextBox}"
TextWrapping="Wrap"
VerticalScrollBarVisibility="Auto" />
</GroupBox>
</Grid>
<Grid
x:Name="gridTunModeProxy"
Width="600"
Margin="{StaticResource SettingItemMargin}"
HorizontalAlignment="Left">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="1*" />
<ColumnDefinition Width="10" />
<ColumnDefinition Width="1*" />
</Grid.ColumnDefinitions>
<GroupBox
Grid.Column="0"
Header="{x:Static resx:ResUI.TbSettingsTunModeProxyIP}"
Style="{StaticResource MyGroupBox}">
<TextBox
Name="txtProxyIP"
AcceptsReturn="True"
Style="{StaticResource DefTextBox}"
TextWrapping="Wrap"
VerticalScrollBarVisibility="Auto" />
</GroupBox>
<GridSplitter Grid.Column="1" HorizontalAlignment="Stretch" />
<GroupBox
Grid.Column="2"
Header="{x:Static resx:ResUI.TbSettingsTunModeProxyProcess}"
Style="{StaticResource MyGroupBox}">
<TextBox
Name="txtProxyProcess"
AcceptsReturn="True"
Style="{StaticResource DefTextBox}"
TextWrapping="Wrap"
VerticalScrollBarVisibility="Auto" />
</GroupBox>
</Grid>
</DockPanel>
</TabItem>
@@ -763,7 +1039,8 @@
Grid.Row="1"
Grid.Column="1"
Width="200"
Margin="{StaticResource SettingItemMargin}" />
Margin="{StaticResource SettingItemMargin}"
Style="{StaticResource DefComboBox}" />
<TextBlock
Grid.Row="2"
@@ -777,7 +1054,8 @@
Grid.Row="2"
Grid.Column="1"
Width="200"
Margin="{StaticResource SettingItemMargin}" />
Margin="{StaticResource SettingItemMargin}"
Style="{StaticResource DefComboBox}" />
<TextBlock
Grid.Row="3"
@@ -791,7 +1069,8 @@
Grid.Row="3"
Grid.Column="1"
Width="200"
Margin="{StaticResource SettingItemMargin}" />
Margin="{StaticResource SettingItemMargin}"
Style="{StaticResource DefComboBox}" />
<TextBlock
Grid.Row="4"
@@ -805,7 +1084,8 @@
Grid.Row="4"
Grid.Column="1"
Width="200"
Margin="{StaticResource SettingItemMargin}" />
Margin="{StaticResource SettingItemMargin}"
Style="{StaticResource DefComboBox}" />
<TextBlock
Grid.Row="5"
@@ -819,7 +1099,8 @@
Grid.Row="5"
Grid.Column="1"
Width="200"
Margin="{StaticResource SettingItemMargin}" />
Margin="{StaticResource SettingItemMargin}"
Style="{StaticResource DefComboBox}" />
<TextBlock
Grid.Row="6"
@@ -833,7 +1114,8 @@
Grid.Row="6"
Grid.Column="1"
Width="200"
Margin="{StaticResource SettingItemMargin}" />
Margin="{StaticResource SettingItemMargin}"
Style="{StaticResource DefComboBox}" />
</Grid>
</TabItem>
</TabControl>

View File

@@ -1,15 +1,24 @@
using ReactiveUI;
using System.Globalization;
using System.IO;
using System.Reactive.Disposables;
using System.Windows;
using System.Windows.Media;
using v2rayN.Handler;
using v2rayN.Mode;
using v2rayN.ViewModels;
namespace v2rayN.Views
{
public partial class OptionSettingWindow
{
private static Config _config;
public OptionSettingWindow()
{
InitializeComponent();
this.Owner = Application.Current.MainWindow;
_config = LazyConfig.Instance.GetConfig();
ViewModel = new OptionSettingViewModel(this);
@@ -21,6 +30,14 @@ namespace v2rayN.Views
{
cmbloglevel.Items.Add(it);
});
Global.fingerprints.ForEach(it =>
{
cmbdefFingerprint.Items.Add(it);
});
Global.userAgent.ForEach(it =>
{
cmbdefUserAgent.Items.Add(it);
});
Global.domainStrategy4Freedoms.ForEach(it =>
{
cmbdomainStrategy4Freedom.Items.Add(it);
@@ -47,6 +64,57 @@ namespace v2rayN.Views
cmbCoreType6.Items.Add(it);
});
for (int i = 2; i <= 6; i++)
{
cmbSpeedTestTimeout.Items.Add(i * 5);
}
Global.SpeedTestUrls.ForEach(it =>
{
cmbSpeedTestUrl.Items.Add(it);
});
//fill fonts
try
{
var dir = new DirectoryInfo(Utils.GetFontsPath());
var files = dir.GetFiles("*.ttf");
var culture = _config.uiItem.currentLanguage.Equals(Global.Languages[0]) ? "zh-cn" : "en-us";
var culture2 = "en-us";
foreach (var it in files)
{
var families = Fonts.GetFontFamilies(Utils.GetFontsPath(it.Name));
foreach (FontFamily family in families)
{
var typefaces = family.GetTypefaces();
foreach (Typeface typeface in typefaces)
{
typeface.TryGetGlyphTypeface(out GlyphTypeface glyph);
//var fontFace = glyph.Win32FaceNames[new CultureInfo("en-us")];
//if (!fontFace.Equals("Regular") && !fontFace.Equals("Normal"))
//{
// continue;
//}
var fontFamily = glyph.Win32FamilyNames[new CultureInfo(culture)];
if (Utils.IsNullOrEmpty(fontFamily))
{
fontFamily = glyph.Win32FamilyNames[new CultureInfo(culture2)];
if (Utils.IsNullOrEmpty(fontFamily))
{
continue;
}
}
cmbcurrentFontFamily.Items.Add(fontFamily);
break;
}
}
}
}
catch (Exception ex)
{
Utils.SaveLog("fill fonts error", ex);
}
cmbcurrentFontFamily.Items.Add(string.Empty);
this.WhenActivated(disposables =>
{
this.Bind(ViewModel, vm => vm.localPort, v => v.txtlocalPort.Text).DisposeWith(disposables);
@@ -63,6 +131,8 @@ namespace v2rayN.Views
this.Bind(ViewModel, vm => vm.logEnabled, v => v.toglogEnabled.IsChecked).DisposeWith(disposables);
this.Bind(ViewModel, vm => vm.loglevel, v => v.cmbloglevel.Text).DisposeWith(disposables);
this.Bind(ViewModel, vm => vm.defAllowInsecure, v => v.togdefAllowInsecure.IsChecked).DisposeWith(disposables);
this.Bind(ViewModel, vm => vm.defFingerprint, v => v.cmbdefFingerprint.Text).DisposeWith(disposables);
this.Bind(ViewModel, vm => vm.defUserAgent, v => v.cmbdefUserAgent.Text).DisposeWith(disposables);
this.Bind(ViewModel, vm => vm.domainStrategy4Freedom, v => v.cmbdomainStrategy4Freedom.Text).DisposeWith(disposables);
@@ -87,9 +157,14 @@ 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.DoubleClick2Activate, v => v.togDoubleClick2Activate.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);
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.systemProxyAdvancedProtocol, v => v.cmbsystemProxyAdvancedProtocol.Text).DisposeWith(disposables);
@@ -97,11 +172,18 @@ namespace v2rayN.Views
this.Bind(ViewModel, vm => vm.TunShowWindow, v => v.togShowWindow.IsChecked).DisposeWith(disposables);
this.Bind(ViewModel, vm => vm.TunEnabledLog, v => v.togEnabledLog.IsChecked).DisposeWith(disposables);
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.TunBypassMode, v => v.togBypassMode.IsChecked).DisposeWith(disposables);
this.OneWayBind(ViewModel, vm => vm.TunBypassMode, v => v.gridTunModeDirect.Visibility, vmToViewConverterOverride: new BooleanToVisibilityTypeConverter()).DisposeWith(disposables);
this.OneWayBind(ViewModel, vm => vm.TunBypassMode2, v => v.gridTunModeProxy.Visibility, vmToViewConverterOverride: new BooleanToVisibilityTypeConverter()).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);
this.Bind(ViewModel, vm => vm.TunProxyIP, v => v.txtProxyIP.Text).DisposeWith(disposables);
this.Bind(ViewModel, vm => vm.TunProxyProcess, v => v.txtProxyProcess.Text).DisposeWith(disposables);
this.Bind(ViewModel, vm => vm.CoreType1, v => v.cmbCoreType1.Text).DisposeWith(disposables);
@@ -124,6 +206,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

@@ -9,7 +9,7 @@
d:DesignHeight="300"
d:DesignWidth="300"
mc:Ignorable="d">
<Grid Margin="16">
<Grid Margin="30">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />

View File

@@ -2,6 +2,7 @@
x:Class="v2rayN.Views.RoutingRuleDetailsWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:conv="clr-namespace:v2rayN.Converters"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:materialDesign="http://materialdesigninxaml.net/winfx/xaml/themes"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
@@ -13,7 +14,10 @@
Height="700"
x:TypeArguments="vms:RoutingRuleDetailsViewModel"
Background="{DynamicResource MaterialDesignPaper}"
FontFamily="{x:Static conv:MaterialDesignFonts.MyFont}"
ResizeMode="NoResize"
ShowInTaskbar="False"
TextElement.FontFamily="{x:Static conv:MaterialDesignFonts.MyFont}"
TextElement.Foreground="{DynamicResource MaterialDesignBody}"
TextOptions.TextFormattingMode="Display"
TextOptions.TextRenderingMode="Auto"
@@ -62,7 +66,8 @@
Grid.Column="1"
Width="200"
Margin="4"
HorizontalAlignment="Left" />
HorizontalAlignment="Left"
Style="{StaticResource DefTextBox}" />
<TextBlock
Grid.Row="2"
@@ -77,6 +82,7 @@
Grid.Column="1"
Margin="4"
HorizontalAlignment="Left"
FontSize="{DynamicResource StdFontSize}"
Style="{StaticResource MaterialDesignFilterChipPrimaryListBox}" />
<TextBlock
@@ -91,6 +97,7 @@
Grid.Row="3"
Grid.Column="1"
Margin="4"
FontSize="{DynamicResource StdFontSize}"
Style="{StaticResource MaterialDesignFilterChipPrimaryListBox}" />
<TextBlock
@@ -140,7 +147,7 @@
HorizontalAlignment="Left"
VerticalAlignment="Center">
<CheckBox x:Name="chkAutoSort">
<TextBlock Text="{x:Static resx:ResUI.TbAutoSort}" />
<TextBlock Style="{StaticResource ToolbarTextBlock}" Text="{x:Static resx:ResUI.TbAutoSort}" />
</CheckBox>
</StackPanel>
<Button
@@ -169,10 +176,11 @@
<GroupBox
Grid.Column="0"
Header="Domain"
Style="{StaticResource MaterialDesignGroupBox}">
Style="{StaticResource MyGroupBox}">
<TextBox
Name="txtDomain"
AcceptsReturn="True"
Style="{StaticResource DefTextBox}"
TextWrapping="Wrap"
VerticalScrollBarVisibility="Auto" />
</GroupBox>
@@ -180,10 +188,11 @@
<GroupBox
Grid.Column="2"
Header="IP"
Style="{StaticResource MaterialDesignGroupBox}">
Style="{StaticResource MyGroupBox}">
<TextBox
Name="txtIP"
AcceptsReturn="True"
Style="{StaticResource DefTextBox}"
TextWrapping="Wrap"
VerticalScrollBarVisibility="Auto" />
</GroupBox>

View File

@@ -12,6 +12,7 @@ namespace v2rayN.Views
public RoutingRuleDetailsWindow(RulesItem rulesItem)
{
InitializeComponent();
this.Owner = Application.Current.MainWindow;
this.Loaded += Window_Loaded;
clbProtocol.SelectionChanged += ClbProtocol_SelectionChanged;
clbInboundTag.SelectionChanged += ClbInboundTag_SelectionChanged;

View File

@@ -2,6 +2,7 @@
x:Class="v2rayN.Views.RoutingRuleSettingWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:conv="clr-namespace:v2rayN.Converters"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:materialDesign="http://materialdesigninxaml.net/winfx/xaml/themes"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
@@ -13,7 +14,10 @@
Height="700"
x:TypeArguments="vms:RoutingRuleSettingViewModel"
Background="{DynamicResource MaterialDesignPaper}"
FontFamily="{x:Static conv:MaterialDesignFonts.MyFont}"
ResizeMode="NoResize"
ShowInTaskbar="False"
TextElement.FontFamily="{x:Static conv:MaterialDesignFonts.MyFont}"
TextElement.Foreground="{DynamicResource MaterialDesignBody}"
TextOptions.TextFormattingMode="Display"
TextOptions.TextRenderingMode="Auto"
@@ -89,6 +93,7 @@
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
@@ -111,6 +116,7 @@
HorizontalAlignment="Left"
VerticalAlignment="Top"
AcceptsReturn="True"
Style="{StaticResource DefTextBox}"
TextWrapping="Wrap" />
<TextBlock
@@ -143,6 +149,7 @@
Margin="4"
VerticalAlignment="Top"
AcceptsReturn="True"
Style="{StaticResource DefTextBox}"
TextWrapping="Wrap" />
<TextBlock
@@ -160,6 +167,7 @@
Margin="4"
VerticalAlignment="Top"
AcceptsReturn="True"
Style="{StaticResource DefTextBox}"
TextWrapping="Wrap" />
<Button
x:Name="btnBrowse"
@@ -171,6 +179,23 @@
Content="{x:Static resx:ResUI.TbBrowse}"
Style="{StaticResource DefButton}" />
<TextBlock
Grid.Row="4"
Grid.Column="0"
Margin="4"
VerticalAlignment="Center"
Style="{StaticResource ToolbarTextBlock}"
Text="{x:Static resx:ResUI.LvSort}" />
<TextBox
x:Name="txtSort"
Grid.Row="4"
Grid.Column="1"
Width="200"
Margin="4"
HorizontalAlignment="Left"
AcceptsReturn="True"
Style="{StaticResource DefTextBox}" />
</Grid>
<TabControl x:Name="tabAdvanced">

View File

@@ -12,6 +12,7 @@ namespace v2rayN.Views
public RoutingRuleSettingWindow(RoutingItem routingItem)
{
InitializeComponent();
this.Owner = Application.Current.MainWindow;
this.Loaded += Window_Loaded;
this.PreviewKeyDown += RoutingRuleSettingWindow_PreviewKeyDown;
lstRules.SelectionChanged += lstRules_SelectionChanged;
@@ -33,6 +34,7 @@ namespace v2rayN.Views
this.Bind(ViewModel, vm => vm.SelectedRouting.domainStrategy, v => v.cmbdomainStrategy.Text).DisposeWith(disposables);
this.Bind(ViewModel, vm => vm.SelectedRouting.url, v => v.txtUrl.Text).DisposeWith(disposables);
this.Bind(ViewModel, vm => vm.SelectedRouting.customIcon, v => v.txtCustomIcon.Text).DisposeWith(disposables);
this.Bind(ViewModel, vm => vm.SelectedRouting.sort, v => v.txtSort.Text).DisposeWith(disposables);
this.BindCommand(ViewModel, vm => vm.RuleAddCmd, v => v.menuRuleAdd).DisposeWith(disposables);
this.BindCommand(ViewModel, vm => vm.ImportRulesFromFileCmd, v => v.menuImportRulesFromFile).DisposeWith(disposables);
@@ -75,15 +77,15 @@ namespace v2rayN.Views
{
ViewModel?.MoveRule(EMove.Top);
}
else if (e.Key == Key.B)
else if (e.Key == Key.U)
{
ViewModel?.MoveRule(EMove.Up);
}
else if (e.Key == Key.U)
else if (e.Key == Key.D)
{
ViewModel?.MoveRule(EMove.Down);
}
else if (e.Key == Key.D)
else if (e.Key == Key.B)
{
ViewModel?.MoveRule(EMove.Bottom);
}

View File

@@ -2,6 +2,7 @@
x:Class="v2rayN.Views.RoutingSettingWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:conv="clr-namespace:v2rayN.Converters"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:materialDesign="http://materialdesigninxaml.net/winfx/xaml/themes"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
@@ -13,7 +14,10 @@
Height="700"
x:TypeArguments="vms:RoutingSettingViewModel"
Background="{DynamicResource MaterialDesignPaper}"
FontFamily="{x:Static conv:MaterialDesignFonts.MyFont}"
ResizeMode="NoResize"
ShowInTaskbar="False"
TextElement.FontFamily="{x:Static conv:MaterialDesignFonts.MyFont}"
TextElement.Foreground="{DynamicResource MaterialDesignBody}"
TextOptions.TextFormattingMode="Display"
TextOptions.TextRenderingMode="Auto"
@@ -194,15 +198,19 @@
Binding="{Binding remarks}"
Header="{x:Static resx:ResUI.LvAlias}" />
<DataGridTextColumn
Width="70"
Width="60"
Binding="{Binding ruleNum}"
Header="{x:Static resx:ResUI.LvCount}" />
<DataGridTextColumn
Width="280"
Width="60"
Binding="{Binding sort}"
Header="{x:Static resx:ResUI.LvSort}" />
<DataGridTextColumn
Width="260"
Binding="{Binding url}"
Header="{x:Static resx:ResUI.LvUrl}" />
<DataGridTextColumn
Width="280"
Width="260"
Binding="{Binding customIcon}"
Header="{x:Static resx:ResUI.LvCustomIcon}" />
</DataGrid.Columns>
@@ -221,10 +229,11 @@
<GroupBox
Grid.Column="0"
Header="Domain"
Style="{StaticResource MaterialDesignGroupBox}">
Style="{StaticResource MyGroupBox}">
<TextBox
Name="txtProxyDomain"
AcceptsReturn="True"
Style="{StaticResource DefTextBox}"
TextWrapping="Wrap"
VerticalScrollBarVisibility="Auto" />
</GroupBox>
@@ -232,10 +241,11 @@
<GroupBox
Grid.Column="2"
Header="IP"
Style="{StaticResource MaterialDesignGroupBox}">
Style="{StaticResource MyGroupBox}">
<TextBox
Name="txtProxyIP"
AcceptsReturn="True"
Style="{StaticResource DefTextBox}"
TextWrapping="Wrap"
VerticalScrollBarVisibility="Auto" />
</GroupBox>
@@ -252,10 +262,11 @@
<GroupBox
Grid.Column="0"
Header="Domain"
Style="{StaticResource MaterialDesignGroupBox}">
Style="{StaticResource MyGroupBox}">
<TextBox
Name="txtDirectDomain"
AcceptsReturn="True"
Style="{StaticResource DefTextBox}"
TextWrapping="Wrap"
VerticalScrollBarVisibility="Auto" />
</GroupBox>
@@ -263,10 +274,11 @@
<GroupBox
Grid.Column="2"
Header="IP"
Style="{StaticResource MaterialDesignGroupBox}">
Style="{StaticResource MyGroupBox}">
<TextBox
Name="txtDirectIP"
AcceptsReturn="True"
Style="{StaticResource DefTextBox}"
TextWrapping="Wrap"
VerticalScrollBarVisibility="Auto" />
</GroupBox>
@@ -283,10 +295,11 @@
<GroupBox
Grid.Column="0"
Header="Domain"
Style="{StaticResource MaterialDesignGroupBox}">
Style="{StaticResource MyGroupBox}">
<TextBox
Name="txtBlockDomain"
AcceptsReturn="True"
Style="{StaticResource DefTextBox}"
TextWrapping="Wrap"
VerticalScrollBarVisibility="Auto" />
</GroupBox>
@@ -294,10 +307,11 @@
<GroupBox
Grid.Column="2"
Header="IP"
Style="{StaticResource MaterialDesignGroupBox}">
Style="{StaticResource MyGroupBox}">
<TextBox
Name="txtBlockIP"
AcceptsReturn="True"
Style="{StaticResource DefTextBox}"
TextWrapping="Wrap"
VerticalScrollBarVisibility="Auto" />
</GroupBox>

View File

@@ -1,5 +1,6 @@
using ReactiveUI;
using System.Reactive.Disposables;
using System.Windows;
using System.Windows.Input;
using v2rayN.Mode;
using v2rayN.ViewModels;
@@ -11,6 +12,7 @@ namespace v2rayN.Views
public RoutingSettingWindow()
{
InitializeComponent();
this.Owner = Application.Current.MainWindow;
this.Closing += RoutingSettingWindow_Closing;
this.PreviewKeyDown += RoutingSettingWindow_PreviewKeyDown;
lstRoutings.SelectionChanged += lstRoutings_SelectionChanged;

View File

@@ -2,6 +2,7 @@
x:Class="v2rayN.Views.SubEditWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:conv="clr-namespace:v2rayN.Converters"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:materialDesign="http://materialdesigninxaml.net/winfx/xaml/themes"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
@@ -13,7 +14,10 @@
Height="550"
x:TypeArguments="vms:SubEditViewModel"
Background="{DynamicResource MaterialDesignPaper}"
FontFamily="{x:Static conv:MaterialDesignFonts.MyFont}"
ResizeMode="NoResize"
ShowInTaskbar="False"
TextElement.FontFamily="{x:Static conv:MaterialDesignFonts.MyFont}"
TextElement.Foreground="{DynamicResource MaterialDesignBody}"
TextOptions.TextFormattingMode="Display"
TextOptions.TextRenderingMode="Auto"
@@ -66,7 +70,7 @@
Margin="4"
VerticalAlignment="Top"
AcceptsReturn="True"
Style="{StaticResource MaterialDesignOutlinedTextBox}"
Style="{StaticResource MyOutlinedTextBox}"
TextWrapping="Wrap" />
<TextBlock
@@ -85,7 +89,7 @@
VerticalAlignment="Top"
materialDesign:HintAssist.Hint="{x:Static resx:ResUI.SubUrlTips}"
AcceptsReturn="True"
Style="{StaticResource MaterialDesignOutlinedTextBox}"
Style="{StaticResource MyOutlinedTextBox}"
TextWrapping="Wrap" />
<TextBlock
@@ -117,7 +121,7 @@
VerticalAlignment="Top"
materialDesign:HintAssist.Hint="{x:Static resx:ResUI.SubUrlTips}"
AcceptsReturn="True"
Style="{StaticResource MaterialDesignOutlinedTextBox}"
Style="{StaticResource MyOutlinedTextBox}"
TextWrapping="Wrap" />
<TextBlock
@@ -136,7 +140,7 @@
VerticalAlignment="Top"
materialDesign:HintAssist.Hint="{x:Static resx:ResUI.SubUrlTips}"
AcceptsReturn="True"
Style="{StaticResource MaterialDesignOutlinedTextBox}" />
Style="{StaticResource MyOutlinedTextBox}" />
<TextBlock
Grid.Row="6"
@@ -153,7 +157,7 @@
Margin="4"
VerticalAlignment="Top"
AcceptsReturn="True"
Style="{StaticResource MaterialDesignOutlinedTextBox}" />
Style="{StaticResource MyOutlinedTextBox}" />
</Grid>
<Grid

View File

@@ -11,6 +11,7 @@ namespace v2rayN.Views
public SubEditWindow(SubItem subItem)
{
InitializeComponent();
this.Owner = Application.Current.MainWindow;
this.Loaded += Window_Loaded;
ViewModel = new SubEditViewModel(subItem, this);

View File

@@ -2,6 +2,7 @@
x:Class="v2rayN.Views.SubSettingWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:conv="clr-namespace:v2rayN.Converters"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:materialDesign="http://materialdesigninxaml.net/winfx/xaml/themes"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
@@ -13,7 +14,10 @@
Height="600"
x:TypeArguments="vms:SubSettingViewModel"
Background="{DynamicResource MaterialDesignPaper}"
FontFamily="{x:Static conv:MaterialDesignFonts.MyFont}"
ResizeMode="NoResize"
ShowInTaskbar="False"
TextElement.FontFamily="{x:Static conv:MaterialDesignFonts.MyFont}"
TextElement.Foreground="{DynamicResource MaterialDesignBody}"
TextOptions.TextFormattingMode="Display"
TextOptions.TextRenderingMode="Auto"

View File

@@ -1,6 +1,7 @@
using ReactiveUI;
using System.ComponentModel;
using System.Reactive.Disposables;
using System.Windows;
using System.Windows.Input;
using v2rayN.ViewModels;
@@ -11,6 +12,7 @@ namespace v2rayN.Views
public SubSettingWindow()
{
InitializeComponent();
this.Owner = Application.Current.MainWindow;
ViewModel = new SubSettingViewModel(this);
this.Closing += SubSettingWindow_Closing;
@@ -40,7 +42,7 @@ namespace v2rayN.Views
private void LstSubscription_MouseDoubleClick(object sender, MouseButtonEventArgs e)
{
ViewModel?.EditSub(false);
}
}
private void menuClose_Click(object sender, System.Windows.RoutedEventArgs e)
{

View File

@@ -1,6 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<GenerateSatelliteAssembliesForCore>true</GenerateSatelliteAssembliesForCore>
<OutputType>WinExe</OutputType>
<TargetFramework>net6.0-windows</TargetFramework>
<Nullable>enable</Nullable>
@@ -9,11 +10,12 @@
<ImplicitUsings>enable</ImplicitUsings>
<ApplicationIcon>v2rayN.ico</ApplicationIcon>
<Copyright>Copyright © 2017-2023 (GPLv3)</Copyright>
<FileVersion>6.2</FileVersion>
<FileVersion>6.13</FileVersion>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="MaterialDesignThemes" Version="4.6.1" />
<PackageReference Include="Downloader" Version="3.0.3" />
<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" />
@@ -25,7 +27,7 @@
<PackageReference Include="ReactiveUI.Fody" Version="18.4.1" />
<PackageReference Include="ReactiveUI.Validation" Version="3.0.22" />
<PackageReference Include="ReactiveUI.WPF" Version="18.4.1" />
<PackageReference Include="Splat.NLog" Version="14.6.1" />
<PackageReference Include="Splat.NLog" Version="14.6.8" />
<PackageReference Include="System.Reactive" Version="5.0.0" />
</ItemGroup>
@@ -99,6 +101,9 @@
<EmbeddedResource Update="Resx\ResUI.fa-Ir.resx">
<Generator>PublicResXFileCodeGenerator</Generator>
</EmbeddedResource>
<EmbeddedResource Update="Resx\ResUI.ru.resx">
<Generator>PublicResXFileCodeGenerator</Generator>
</EmbeddedResource>
</ItemGroup>
</Project>