mirror of https://github.com/2dust/v2rayN
Use tun mode without running with sudo in linux
parent
f921ff7d77
commit
9d638968a9
|
@ -68,6 +68,7 @@ namespace ServiceLib.Handler
|
||||||
{
|
{
|
||||||
ShowMsg(true, $"{node.GetSummary()}");
|
ShowMsg(true, $"{node.GetSummary()}");
|
||||||
await CoreStop();
|
await CoreStop();
|
||||||
|
await Task.Delay(100);
|
||||||
await CoreStart(node);
|
await CoreStart(node);
|
||||||
|
|
||||||
//In tun mode, do a delay check and restart the core
|
//In tun mode, do a delay check and restart the core
|
||||||
|
@ -169,21 +170,12 @@ namespace ServiceLib.Handler
|
||||||
ShowMsg(false, $"{Environment.OSVersion} - {(Environment.Is64BitOperatingSystem ? 64 : 32)}");
|
ShowMsg(false, $"{Environment.OSVersion} - {(Environment.Is64BitOperatingSystem ? 64 : 32)}");
|
||||||
ShowMsg(false, string.Format(ResUI.StartService, DateTime.Now.ToString("yyyy/MM/dd HH:mm:ss")));
|
ShowMsg(false, string.Format(ResUI.StartService, DateTime.Now.ToString("yyyy/MM/dd HH:mm:ss")));
|
||||||
|
|
||||||
//ECoreType coreType;
|
|
||||||
//if (node.configType != EConfigType.Custom && _config.tunModeItem.enableTun)
|
|
||||||
//{
|
|
||||||
// coreType = ECoreType.sing_box;
|
|
||||||
//}
|
|
||||||
//else
|
|
||||||
//{
|
|
||||||
// coreType = LazyConfig.Instance.GetCoreType(node, node.configType);
|
|
||||||
//}
|
|
||||||
var coreType = AppHandler.Instance.GetCoreType(node, node.ConfigType);
|
var coreType = AppHandler.Instance.GetCoreType(node, node.ConfigType);
|
||||||
_config.RunningCoreType = coreType;
|
_config.RunningCoreType = coreType;
|
||||||
var coreInfo = CoreInfoHandler.Instance.GetCoreInfo(coreType);
|
var coreInfo = CoreInfoHandler.Instance.GetCoreInfo(coreType);
|
||||||
|
|
||||||
var displayLog = node.ConfigType != EConfigType.Custom || node.DisplayLog;
|
var displayLog = node.ConfigType != EConfigType.Custom || node.DisplayLog;
|
||||||
var proc = await RunProcess(coreInfo, Global.CoreConfigFileName, displayLog);
|
var proc = await RunProcess(coreInfo, Global.CoreConfigFileName, displayLog, true);
|
||||||
if (proc is null)
|
if (proc is null)
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
|
@ -225,7 +217,7 @@ namespace ServiceLib.Handler
|
||||||
if (result.Success)
|
if (result.Success)
|
||||||
{
|
{
|
||||||
var coreInfo2 = CoreInfoHandler.Instance.GetCoreInfo(preCoreType);
|
var coreInfo2 = CoreInfoHandler.Instance.GetCoreInfo(preCoreType);
|
||||||
var proc2 = await RunProcess(coreInfo2, Global.CorePreConfigFileName, true);
|
var proc2 = await RunProcess(coreInfo2, Global.CorePreConfigFileName, true, true);
|
||||||
if (proc2 is not null)
|
if (proc2 is not null)
|
||||||
{
|
{
|
||||||
_processPre = proc2;
|
_processPre = proc2;
|
||||||
|
@ -243,7 +235,7 @@ namespace ServiceLib.Handler
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var coreInfo = CoreInfoHandler.Instance.GetCoreInfo(coreType);
|
var coreInfo = CoreInfoHandler.Instance.GetCoreInfo(coreType);
|
||||||
var proc = await RunProcess(coreInfo, Global.CoreSpeedtestConfigFileName, true);
|
var proc = await RunProcess(coreInfo, Global.CoreSpeedtestConfigFileName, true, false);
|
||||||
if (proc is null)
|
if (proc is null)
|
||||||
{
|
{
|
||||||
return -1;
|
return -1;
|
||||||
|
@ -264,17 +256,28 @@ namespace ServiceLib.Handler
|
||||||
_updateFunc?.Invoke(notify, msg);
|
_updateFunc?.Invoke(notify, msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private bool IsNeedSudo(ECoreType eCoreType)
|
||||||
|
{
|
||||||
|
return _config.TunModeItem.EnableTun
|
||||||
|
&& eCoreType == ECoreType.sing_box
|
||||||
|
&& Utils.IsLinux()
|
||||||
|
&& _config.TunModeItem.LinuxSudoPassword.IsNotEmpty()
|
||||||
|
;
|
||||||
|
}
|
||||||
|
|
||||||
#endregion Private
|
#endregion Private
|
||||||
|
|
||||||
#region Process
|
#region Process
|
||||||
|
|
||||||
private async Task<Process?> RunProcess(CoreInfo coreInfo, string configPath, bool displayLog)
|
private async Task<Process?> RunProcess(CoreInfo coreInfo, string configPath, bool displayLog, bool mayNeedSudo)
|
||||||
{
|
{
|
||||||
var fileName = CoreFindExe(coreInfo);
|
var fileName = CoreFindExe(coreInfo);
|
||||||
if (Utils.IsNullOrEmpty(fileName))
|
if (Utils.IsNullOrEmpty(fileName))
|
||||||
{
|
{
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var isNeedSudo = mayNeedSudo && IsNeedSudo(coreInfo.CoreType);
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
Process proc = new()
|
Process proc = new()
|
||||||
|
@ -292,6 +295,15 @@ namespace ServiceLib.Handler
|
||||||
StandardErrorEncoding = displayLog ? Encoding.UTF8 : null,
|
StandardErrorEncoding = displayLog ? Encoding.UTF8 : null,
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
if (isNeedSudo)
|
||||||
|
{
|
||||||
|
proc.StartInfo.FileName = $"/bin/sudo";
|
||||||
|
proc.StartInfo.Arguments = $"-S {fileName} {string.Format(coreInfo.Arguments, configPath)}";
|
||||||
|
proc.StartInfo.StandardInputEncoding = Encoding.UTF8;
|
||||||
|
proc.StartInfo.RedirectStandardInput = true;
|
||||||
|
}
|
||||||
|
|
||||||
var startUpErrorMessage = new StringBuilder();
|
var startUpErrorMessage = new StringBuilder();
|
||||||
var startUpSuccessful = false;
|
var startUpSuccessful = false;
|
||||||
if (displayLog)
|
if (displayLog)
|
||||||
|
@ -313,6 +325,15 @@ namespace ServiceLib.Handler
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
proc.Start();
|
proc.Start();
|
||||||
|
|
||||||
|
if (isNeedSudo)
|
||||||
|
{
|
||||||
|
await Task.Delay(10);
|
||||||
|
await proc.StandardInput.WriteLineAsync(_config.TunModeItem.LinuxSudoPassword);
|
||||||
|
await Task.Delay(10);
|
||||||
|
await proc.StandardInput.WriteLineAsync(_config.TunModeItem.LinuxSudoPassword);
|
||||||
|
}
|
||||||
|
|
||||||
if (displayLog)
|
if (displayLog)
|
||||||
{
|
{
|
||||||
proc.BeginOutputReadLine();
|
proc.BeginOutputReadLine();
|
||||||
|
|
|
@ -161,6 +161,7 @@
|
||||||
public int Mtu { get; set; }
|
public int Mtu { get; set; }
|
||||||
public bool EnableExInbound { get; set; }
|
public bool EnableExInbound { get; set; }
|
||||||
public bool EnableIPv6Address { get; set; }
|
public bool EnableIPv6Address { get; set; }
|
||||||
|
public string? LinuxSudoPassword { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
[Serializable]
|
[Serializable]
|
||||||
|
|
|
@ -3148,6 +3148,42 @@ namespace ServiceLib.Resx {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 查找类似 Linux system sudo password 的本地化字符串。
|
||||||
|
/// </summary>
|
||||||
|
public static string TbSettingsLinuxSudoPassword {
|
||||||
|
get {
|
||||||
|
return ResourceManager.GetString("TbSettingsLinuxSudoPassword", resourceCulture);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 查找类似 Please set the sudo password in Tun mode settings first 的本地化字符串。
|
||||||
|
/// </summary>
|
||||||
|
public static string TbSettingsLinuxSudoPasswordIsEmpty {
|
||||||
|
get {
|
||||||
|
return ResourceManager.GetString("TbSettingsLinuxSudoPasswordIsEmpty", resourceCulture);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 查找类似 Please do not run this app with sudo 的本地化字符串。
|
||||||
|
/// </summary>
|
||||||
|
public static string TbSettingsLinuxSudoPasswordNotSudoRunApp {
|
||||||
|
get {
|
||||||
|
return ResourceManager.GetString("TbSettingsLinuxSudoPasswordNotSudoRunApp", resourceCulture);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 查找类似 The password will only be stored in the local file. 的本地化字符串。
|
||||||
|
/// </summary>
|
||||||
|
public static string TbSettingsLinuxSudoPasswordTip {
|
||||||
|
get {
|
||||||
|
return ResourceManager.GetString("TbSettingsLinuxSudoPasswordTip", resourceCulture);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 查找类似 Enable Log 的本地化字符串。
|
/// 查找类似 Enable Log 的本地化字符串。
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|
|
@ -1369,4 +1369,16 @@
|
||||||
<data name="TbRuleMatchingTips" xml:space="preserve">
|
<data name="TbRuleMatchingTips" xml:space="preserve">
|
||||||
<value>(Domain or IP or ProcName) and Port and Protocol and InboundTag => OutboundTag</value>
|
<value>(Domain or IP or ProcName) and Port and Protocol and InboundTag => OutboundTag</value>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="TbSettingsLinuxSudoPassword" xml:space="preserve">
|
||||||
|
<value>Linux system sudo password</value>
|
||||||
|
</data>
|
||||||
|
<data name="TbSettingsLinuxSudoPasswordTip" xml:space="preserve">
|
||||||
|
<value>The password will only be stored in the local file.</value>
|
||||||
|
</data>
|
||||||
|
<data name="TbSettingsLinuxSudoPasswordIsEmpty" xml:space="preserve">
|
||||||
|
<value>Please set the sudo password in Tun mode settings first</value>
|
||||||
|
</data>
|
||||||
|
<data name="TbSettingsLinuxSudoPasswordNotSudoRunApp" xml:space="preserve">
|
||||||
|
<value>Please do not run this app with sudo</value>
|
||||||
|
</data>
|
||||||
</root>
|
</root>
|
|
@ -1369,4 +1369,16 @@
|
||||||
<data name="LvMemo" xml:space="preserve">
|
<data name="LvMemo" xml:space="preserve">
|
||||||
<value>Remarks Memo</value>
|
<value>Remarks Memo</value>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="TbSettingsLinuxSudoPassword" xml:space="preserve">
|
||||||
|
<value>Linux system sudo password</value>
|
||||||
|
</data>
|
||||||
|
<data name="TbSettingsLinuxSudoPasswordTip" xml:space="preserve">
|
||||||
|
<value>The password will only be stored in the local file.</value>
|
||||||
|
</data>
|
||||||
|
<data name="TbSettingsLinuxSudoPasswordIsEmpty" xml:space="preserve">
|
||||||
|
<value>Please set the sudo password in Tun mode settings first</value>
|
||||||
|
</data>
|
||||||
|
<data name="TbSettingsLinuxSudoPasswordNotSudoRunApp" xml:space="preserve">
|
||||||
|
<value>Please do not run this app with sudo</value>
|
||||||
|
</data>
|
||||||
</root>
|
</root>
|
|
@ -1369,4 +1369,16 @@
|
||||||
<data name="menuRemoteBackupAndRestore" xml:space="preserve">
|
<data name="menuRemoteBackupAndRestore" xml:space="preserve">
|
||||||
<value>Remote (WebDAV)</value>
|
<value>Remote (WebDAV)</value>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="TbSettingsLinuxSudoPassword" xml:space="preserve">
|
||||||
|
<value>Linux system sudo password</value>
|
||||||
|
</data>
|
||||||
|
<data name="TbSettingsLinuxSudoPasswordTip" xml:space="preserve">
|
||||||
|
<value>The password will only be stored in the local file.</value>
|
||||||
|
</data>
|
||||||
|
<data name="TbSettingsLinuxSudoPasswordIsEmpty" xml:space="preserve">
|
||||||
|
<value>Please set the sudo password in Tun mode settings first</value>
|
||||||
|
</data>
|
||||||
|
<data name="TbSettingsLinuxSudoPasswordNotSudoRunApp" xml:space="preserve">
|
||||||
|
<value>Please do not run this app with sudo</value>
|
||||||
|
</data>
|
||||||
</root>
|
</root>
|
|
@ -1366,4 +1366,16 @@
|
||||||
<data name="LvMemo" xml:space="preserve">
|
<data name="LvMemo" xml:space="preserve">
|
||||||
<value>备注备忘</value>
|
<value>备注备忘</value>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="TbSettingsLinuxSudoPassword" xml:space="preserve">
|
||||||
|
<value>Linux系统的sudo密码</value>
|
||||||
|
</data>
|
||||||
|
<data name="TbSettingsLinuxSudoPasswordTip" xml:space="preserve">
|
||||||
|
<value>密码只会存储在本地文件中,没有密码无法开启Tun</value>
|
||||||
|
</data>
|
||||||
|
<data name="TbSettingsLinuxSudoPasswordIsEmpty" xml:space="preserve">
|
||||||
|
<value>请先在Tun模式设置中设置sudo密码</value>
|
||||||
|
</data>
|
||||||
|
<data name="TbSettingsLinuxSudoPasswordNotSudoRunApp" xml:space="preserve">
|
||||||
|
<value>请不要用sudo运行本app</value>
|
||||||
|
</data>
|
||||||
</root>
|
</root>
|
|
@ -1366,4 +1366,16 @@
|
||||||
<data name="TbPath7" xml:space="preserve">
|
<data name="TbPath7" xml:space="preserve">
|
||||||
<value>混淆密碼(obfs password)</value>
|
<value>混淆密碼(obfs password)</value>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="TbSettingsLinuxSudoPassword" xml:space="preserve">
|
||||||
|
<value>Linux系統的sudo密碼</value>
|
||||||
|
</data>
|
||||||
|
<data name="TbSettingsLinuxSudoPasswordTip" xml:space="preserve">
|
||||||
|
<value>密碼只會儲存在本機檔案中,沒有密碼無法開啟Tun</value>
|
||||||
|
</data>
|
||||||
|
<data name="TbSettingsLinuxSudoPasswordIsEmpty" xml:space="preserve">
|
||||||
|
<value>請先在Tun模式設定中設定sudo密碼</value>
|
||||||
|
</data>
|
||||||
|
<data name="TbSettingsLinuxSudoPasswordNotSudoRunApp" xml:space="preserve">
|
||||||
|
<value>請不要用sudo來運行本app</value>
|
||||||
|
</data>
|
||||||
</root>
|
</root>
|
|
@ -14,7 +14,7 @@
|
||||||
<PackageReference Include="sqlite-net-pcl" Version="1.9.172" />
|
<PackageReference Include="sqlite-net-pcl" Version="1.9.172" />
|
||||||
<PackageReference Include="Splat.NLog" Version="15.2.22" />
|
<PackageReference Include="Splat.NLog" Version="15.2.22" />
|
||||||
<PackageReference Include="WebDav.Client" Version="2.8.0" />
|
<PackageReference Include="WebDav.Client" Version="2.8.0" />
|
||||||
<PackageReference Include="YamlDotNet" Version="16.1.3" />
|
<PackageReference Include="YamlDotNet" Version="16.2.0" />
|
||||||
<PackageReference Include="QRCoder" Version="1.6.0" />
|
<PackageReference Include="QRCoder" Version="1.6.0" />
|
||||||
<PackageReference Include="CliWrap" Version="3.6.7" />
|
<PackageReference Include="CliWrap" Version="3.6.7" />
|
||||||
<PackageReference Include="SkiaSharp.QrCode" Version="0.7.0" />
|
<PackageReference Include="SkiaSharp.QrCode" Version="0.7.0" />
|
||||||
|
|
|
@ -85,6 +85,7 @@ namespace ServiceLib.ViewModels
|
||||||
[Reactive] public int TunMtu { get; set; }
|
[Reactive] public int TunMtu { get; set; }
|
||||||
[Reactive] public bool TunEnableExInbound { get; set; }
|
[Reactive] public bool TunEnableExInbound { get; set; }
|
||||||
[Reactive] public bool TunEnableIPv6Address { get; set; }
|
[Reactive] public bool TunEnableIPv6Address { get; set; }
|
||||||
|
[Reactive] public string TunLinuxSudoPassword { get; set; }
|
||||||
|
|
||||||
#endregion Tun mode
|
#endregion Tun mode
|
||||||
|
|
||||||
|
@ -197,6 +198,7 @@ namespace ServiceLib.ViewModels
|
||||||
TunMtu = _config.TunModeItem.Mtu;
|
TunMtu = _config.TunModeItem.Mtu;
|
||||||
TunEnableExInbound = _config.TunModeItem.EnableExInbound;
|
TunEnableExInbound = _config.TunModeItem.EnableExInbound;
|
||||||
TunEnableIPv6Address = _config.TunModeItem.EnableIPv6Address;
|
TunEnableIPv6Address = _config.TunModeItem.EnableIPv6Address;
|
||||||
|
TunLinuxSudoPassword = _config.TunModeItem.LinuxSudoPassword;
|
||||||
|
|
||||||
#endregion Tun mode
|
#endregion Tun mode
|
||||||
|
|
||||||
|
@ -340,6 +342,7 @@ namespace ServiceLib.ViewModels
|
||||||
_config.TunModeItem.Mtu = TunMtu;
|
_config.TunModeItem.Mtu = TunMtu;
|
||||||
_config.TunModeItem.EnableExInbound = TunEnableExInbound;
|
_config.TunModeItem.EnableExInbound = TunEnableExInbound;
|
||||||
_config.TunModeItem.EnableIPv6Address = TunEnableIPv6Address;
|
_config.TunModeItem.EnableIPv6Address = TunEnableIPv6Address;
|
||||||
|
_config.TunModeItem.LinuxSudoPassword = TunLinuxSudoPassword;
|
||||||
|
|
||||||
//coreType
|
//coreType
|
||||||
await SaveCoreType();
|
await SaveCoreType();
|
||||||
|
|
|
@ -108,7 +108,7 @@ namespace ServiceLib.ViewModels
|
||||||
SelectedServer = new();
|
SelectedServer = new();
|
||||||
RunningServerToolTipText = "-";
|
RunningServerToolTipText = "-";
|
||||||
|
|
||||||
if (_config.TunModeItem.EnableTun && AppHandler.Instance.IsAdministrator)
|
if (_config.TunModeItem.EnableTun && AllowEnableTun())
|
||||||
{
|
{
|
||||||
EnableTun = true;
|
EnableTun = true;
|
||||||
}
|
}
|
||||||
|
@ -414,10 +414,17 @@ namespace ServiceLib.ViewModels
|
||||||
{
|
{
|
||||||
_config.TunModeItem.EnableTun = EnableTun;
|
_config.TunModeItem.EnableTun = EnableTun;
|
||||||
// When running as a non-administrator, reboot to administrator mode
|
// When running as a non-administrator, reboot to administrator mode
|
||||||
if (EnableTun && !AppHandler.Instance.IsAdministrator)
|
if (EnableTun && AllowEnableTun() == false)
|
||||||
{
|
{
|
||||||
_config.TunModeItem.EnableTun = false;
|
_config.TunModeItem.EnableTun = false;
|
||||||
Locator.Current.GetService<MainWindowViewModel>()?.RebootAsAdmin();
|
if (Utils.IsWindows())
|
||||||
|
{
|
||||||
|
Locator.Current.GetService<MainWindowViewModel>()?.RebootAsAdmin();
|
||||||
|
}
|
||||||
|
else if (Utils.IsLinux())
|
||||||
|
{
|
||||||
|
NoticeHandler.Instance.SendMessageAndEnqueue(ResUI.TbSettingsLinuxSudoPasswordIsEmpty);
|
||||||
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
await ConfigHandler.SaveConfig(_config);
|
await ConfigHandler.SaveConfig(_config);
|
||||||
|
@ -425,6 +432,19 @@ namespace ServiceLib.ViewModels
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private bool AllowEnableTun()
|
||||||
|
{
|
||||||
|
if (Utils.IsWindows())
|
||||||
|
{
|
||||||
|
return AppHandler.Instance.IsAdministrator;
|
||||||
|
}
|
||||||
|
else if (Utils.IsLinux())
|
||||||
|
{
|
||||||
|
return _config.TunModeItem.LinuxSudoPassword.IsNotEmpty();
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
#endregion System proxy and Routings
|
#endregion System proxy and Routings
|
||||||
|
|
||||||
#region UI
|
#region UI
|
||||||
|
|
|
@ -117,6 +117,11 @@ namespace v2rayN.Desktop.Views
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
if (AppHandler.Instance.IsAdministrator)
|
||||||
|
{
|
||||||
|
this.Title = $"{Utils.GetVersion()} - {ResUI.TbSettingsLinuxSudoPasswordNotSudoRunApp}";
|
||||||
|
NoticeHandler.Instance.SendMessageAndEnqueue(ResUI.TbSettingsLinuxSudoPasswordNotSudoRunApp);
|
||||||
|
}
|
||||||
menuRebootAsAdmin.IsVisible = false;
|
menuRebootAsAdmin.IsVisible = false;
|
||||||
menuSettingsSetUWP.IsVisible = false;
|
menuSettingsSetUWP.IsVisible = false;
|
||||||
menuGlobalHotkeySetting.IsVisible = false;
|
menuGlobalHotkeySetting.IsVisible = false;
|
||||||
|
@ -282,6 +287,7 @@ namespace v2rayN.Desktop.Views
|
||||||
e.Cancel = true;
|
e.Cancel = true;
|
||||||
ShowHideWindow(false);
|
ShowHideWindow(false);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case WindowCloseReason.ApplicationShutdown or WindowCloseReason.OSShutdown:
|
case WindowCloseReason.ApplicationShutdown or WindowCloseReason.OSShutdown:
|
||||||
await ViewModel?.MyAppExitAsync(true);
|
await ViewModel?.MyAppExitAsync(true);
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -721,6 +721,7 @@
|
||||||
<RowDefinition Height="Auto" />
|
<RowDefinition Height="Auto" />
|
||||||
<RowDefinition Height="Auto" />
|
<RowDefinition Height="Auto" />
|
||||||
<RowDefinition Height="Auto" />
|
<RowDefinition Height="Auto" />
|
||||||
|
<RowDefinition Height="Auto" />
|
||||||
</Grid.RowDefinitions>
|
</Grid.RowDefinitions>
|
||||||
<Grid.ColumnDefinitions>
|
<Grid.ColumnDefinitions>
|
||||||
<ColumnDefinition Width="Auto" />
|
<ColumnDefinition Width="Auto" />
|
||||||
|
@ -794,6 +795,28 @@
|
||||||
Grid.Column="1"
|
Grid.Column="1"
|
||||||
HorizontalAlignment="Left"
|
HorizontalAlignment="Left"
|
||||||
Classes="Margin8" />
|
Classes="Margin8" />
|
||||||
|
|
||||||
|
<TextBlock
|
||||||
|
Grid.Row="7"
|
||||||
|
Grid.Column="0"
|
||||||
|
VerticalAlignment="Center"
|
||||||
|
Classes="Margin8"
|
||||||
|
Text="{x:Static resx:ResUI.TbSettingsLinuxSudoPassword}" />
|
||||||
|
<TextBox
|
||||||
|
x:Name="txtLinuxSudoPassword"
|
||||||
|
Grid.Row="7"
|
||||||
|
Grid.Column="1"
|
||||||
|
Width="200"
|
||||||
|
HorizontalAlignment="Left"
|
||||||
|
Classes="Margin8"
|
||||||
|
PasswordChar="*" />
|
||||||
|
<TextBlock
|
||||||
|
Grid.Row="7"
|
||||||
|
Grid.Column="2"
|
||||||
|
VerticalAlignment="Center"
|
||||||
|
Classes="Margin8"
|
||||||
|
Text="{x:Static resx:ResUI.TbSettingsLinuxSudoPasswordTip}"
|
||||||
|
TextWrapping="Wrap" />
|
||||||
</Grid>
|
</Grid>
|
||||||
</DockPanel>
|
</DockPanel>
|
||||||
</TabItem>
|
</TabItem>
|
||||||
|
|
|
@ -152,6 +152,7 @@ namespace v2rayN.Desktop.Views
|
||||||
this.Bind(ViewModel, vm => vm.TunMtu, v => v.cmbMtu.SelectedValue).DisposeWith(disposables);
|
this.Bind(ViewModel, vm => vm.TunMtu, v => v.cmbMtu.SelectedValue).DisposeWith(disposables);
|
||||||
this.Bind(ViewModel, vm => vm.TunEnableExInbound, v => v.togEnableExInbound.IsChecked).DisposeWith(disposables);
|
this.Bind(ViewModel, vm => vm.TunEnableExInbound, v => v.togEnableExInbound.IsChecked).DisposeWith(disposables);
|
||||||
this.Bind(ViewModel, vm => vm.TunEnableIPv6Address, v => v.togEnableIPv6Address.IsChecked).DisposeWith(disposables);
|
this.Bind(ViewModel, vm => vm.TunEnableIPv6Address, v => v.togEnableIPv6Address.IsChecked).DisposeWith(disposables);
|
||||||
|
this.Bind(ViewModel, vm => vm.TunLinuxSudoPassword, v => v.txtLinuxSudoPassword.Text).DisposeWith(disposables);
|
||||||
|
|
||||||
this.Bind(ViewModel, vm => vm.CoreType1, v => v.cmbCoreType1.SelectedValue).DisposeWith(disposables);
|
this.Bind(ViewModel, vm => vm.CoreType1, v => v.cmbCoreType1.SelectedValue).DisposeWith(disposables);
|
||||||
this.Bind(ViewModel, vm => vm.CoreType2, v => v.cmbCoreType2.SelectedValue).DisposeWith(disposables);
|
this.Bind(ViewModel, vm => vm.CoreType2, v => v.cmbCoreType2.SelectedValue).DisposeWith(disposables);
|
||||||
|
|
|
@ -41,7 +41,7 @@ namespace v2rayN.Desktop.Views
|
||||||
this.Bind(ViewModel, vm => vm.SelectedRouting, v => v.cmbRoutings2.SelectedItem).DisposeWith(disposables);
|
this.Bind(ViewModel, vm => vm.SelectedRouting, v => v.cmbRoutings2.SelectedItem).DisposeWith(disposables);
|
||||||
});
|
});
|
||||||
|
|
||||||
spEnableTun.IsVisible = (Utils.IsWindows() || AppHandler.Instance.IsAdministrator);
|
//spEnableTun.IsVisible = (Utils.IsWindows() || AppHandler.Instance.IsAdministrator);
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task<bool> UpdateViewHandler(EViewAction action, object? obj)
|
private async Task<bool> UpdateViewHandler(EViewAction action, object? obj)
|
||||||
|
|
Loading…
Reference in New Issue