diff --git a/v2rayN/ServiceLib/Resx/ResUI.Designer.cs b/v2rayN/ServiceLib/Resx/ResUI.Designer.cs index 80bac9c2..a7d57db9 100644 --- a/v2rayN/ServiceLib/Resx/ResUI.Designer.cs +++ b/v2rayN/ServiceLib/Resx/ResUI.Designer.cs @@ -843,6 +843,15 @@ namespace ServiceLib.Resx { } } + /// + /// 查找类似 Copy proxy command to clipboard 的本地化字符串。 + /// + public static string menuCopyProxyCmdToClipboard { + get { + return ResourceManager.GetString("menuCopyProxyCmdToClipboard", resourceCulture); + } + } + /// /// 查找类似 Clone selected server 的本地化字符串。 /// diff --git a/v2rayN/ServiceLib/Resx/ResUI.fa-Ir.resx b/v2rayN/ServiceLib/Resx/ResUI.fa-Ir.resx index 383c08d0..5a621898 100644 --- a/v2rayN/ServiceLib/Resx/ResUI.fa-Ir.resx +++ b/v2rayN/ServiceLib/Resx/ResUI.fa-Ir.resx @@ -1390,4 +1390,7 @@ تم - + + Copy proxy command to clipboard + + \ No newline at end of file diff --git a/v2rayN/ServiceLib/Resx/ResUI.hu.resx b/v2rayN/ServiceLib/Resx/ResUI.hu.resx index fae12ab6..f332718a 100644 --- a/v2rayN/ServiceLib/Resx/ResUI.hu.resx +++ b/v2rayN/ServiceLib/Resx/ResUI.hu.resx @@ -1390,4 +1390,7 @@ Theme + + Copy proxy command to clipboard + \ No newline at end of file diff --git a/v2rayN/ServiceLib/Resx/ResUI.resx b/v2rayN/ServiceLib/Resx/ResUI.resx index 3ddf3009..fb3ebdb9 100644 --- a/v2rayN/ServiceLib/Resx/ResUI.resx +++ b/v2rayN/ServiceLib/Resx/ResUI.resx @@ -1390,4 +1390,7 @@ Theme + + Copy proxy command to clipboard + \ No newline at end of file diff --git a/v2rayN/ServiceLib/Resx/ResUI.ru.resx b/v2rayN/ServiceLib/Resx/ResUI.ru.resx index 10b62876..53532b8a 100644 --- a/v2rayN/ServiceLib/Resx/ResUI.ru.resx +++ b/v2rayN/ServiceLib/Resx/ResUI.ru.resx @@ -1390,4 +1390,7 @@ Theme + + Copy proxy command to clipboard + \ No newline at end of file diff --git a/v2rayN/ServiceLib/Resx/ResUI.zh-Hans.resx b/v2rayN/ServiceLib/Resx/ResUI.zh-Hans.resx index 652adfcd..0aa7a08c 100644 --- a/v2rayN/ServiceLib/Resx/ResUI.zh-Hans.resx +++ b/v2rayN/ServiceLib/Resx/ResUI.zh-Hans.resx @@ -1387,4 +1387,7 @@ 主题 + + 复制终端代理命令至剪贴板 + \ No newline at end of file diff --git a/v2rayN/ServiceLib/Resx/ResUI.zh-Hant.resx b/v2rayN/ServiceLib/Resx/ResUI.zh-Hant.resx index 45ee71ee..c1818cce 100644 --- a/v2rayN/ServiceLib/Resx/ResUI.zh-Hant.resx +++ b/v2rayN/ServiceLib/Resx/ResUI.zh-Hant.resx @@ -1388,4 +1388,7 @@ 主題 + + 複製終端代理指令至剪貼簿 + \ No newline at end of file diff --git a/v2rayN/ServiceLib/ViewModels/StatusBarViewModel.cs b/v2rayN/ServiceLib/ViewModels/StatusBarViewModel.cs index 80e3f287..268ea7e7 100644 --- a/v2rayN/ServiceLib/ViewModels/StatusBarViewModel.cs +++ b/v2rayN/ServiceLib/ViewModels/StatusBarViewModel.cs @@ -32,6 +32,7 @@ namespace ServiceLib.ViewModels public ReactiveCommand AddServerViaScanCmd { get; } public ReactiveCommand SubUpdateCmd { get; } public ReactiveCommand SubUpdateViaProxyCmd { get; } + public ReactiveCommand CopyProxyCmdToClipboardCmd { get; } public ReactiveCommand NotifyLeftClickCmd { get; } #region System Proxy @@ -128,6 +129,11 @@ namespace ServiceLib.ViewModels y => y == true) .Subscribe(async c => await DoEnableTun(c)); + CopyProxyCmdToClipboardCmd = ReactiveCommand.CreateFromTask(async () => + { + await CopyProxyCmdToClipboard(); + }); + NotifyLeftClickCmd = ReactiveCommand.CreateFromTask(async () => { Locator.Current.GetService()?.ShowHideWindow(null); @@ -198,6 +204,23 @@ namespace ServiceLib.ViewModels await _updateView?.Invoke(EViewAction.DispatcherRefreshServersBiz, null); } + private async Task CopyProxyCmdToClipboard() + { + var cmd = Utils.IsWindows() ? "set" : "export"; + var address = $"{Global.Loopback}:{AppHandler.Instance.GetLocalPort(EInboundProtocol.socks)}"; + + var sb = new StringBuilder(); + sb.AppendLine($"{cmd} http_proxy=http://{address}"); + sb.AppendLine($"{cmd} https_proxy=http://{address}"); + sb.AppendLine($"{cmd} all_proxy=socks5://{address}"); + sb.AppendLine(""); + sb.AppendLine($"{cmd} HTTP_PROXY=http://{address}"); + sb.AppendLine($"{cmd} HTTPS_PROXY=http://{address}"); + sb.AppendLine($"{cmd} ALL_PROXY=socks5://{address}"); + + await _updateView?.Invoke(EViewAction.SetClipboardData, sb.ToString()); + } + private async Task AddServerViaClipboard() { var service = Locator.Current.GetService(); diff --git a/v2rayN/v2rayN.Desktop/App.axaml b/v2rayN/v2rayN.Desktop/App.axaml index 7428d63d..70da1f59 100644 --- a/v2rayN/v2rayN.Desktop/App.axaml +++ b/v2rayN/v2rayN.Desktop/App.axaml @@ -50,6 +50,8 @@ + + diff --git a/v2rayN/v2rayN.Desktop/Views/StatusBarView.axaml.cs b/v2rayN/v2rayN.Desktop/Views/StatusBarView.axaml.cs index f97e0e85..dfb467c6 100644 --- a/v2rayN/v2rayN.Desktop/Views/StatusBarView.axaml.cs +++ b/v2rayN/v2rayN.Desktop/Views/StatusBarView.axaml.cs @@ -69,6 +69,11 @@ namespace v2rayN.Desktop.Views }, DispatcherPriority.Default); break; + + case EViewAction.SetClipboardData: + if (obj is null) return false; + await AvaUtils.SetClipboardData(this, (string)obj); + break; } return await Task.FromResult(true); } diff --git a/v2rayN/v2rayN/Views/StatusBarView.xaml b/v2rayN/v2rayN/Views/StatusBarView.xaml index 35644516..7df3ee19 100644 --- a/v2rayN/v2rayN/Views/StatusBarView.xaml +++ b/v2rayN/v2rayN/Views/StatusBarView.xaml @@ -193,6 +193,11 @@ Height="{StaticResource MenuItemHeight}" Header="{x:Static resx:ResUI.menuSubUpdateViaProxy}" /> + + vm.SubUpdateCmd, v => v.menuSubUpdate2).DisposeWith(disposables); this.BindCommand(ViewModel, vm => vm.SubUpdateViaProxyCmd, v => v.menuSubUpdateViaProxy2).DisposeWith(disposables); + this.BindCommand(ViewModel, vm => vm.CopyProxyCmdToClipboardCmd, v => v.menuCopyProxyCmdToClipboard).DisposeWith(disposables); + this.OneWayBind(ViewModel, vm => vm.RunningServerToolTipText, v => v.tbNotify.ToolTipText).DisposeWith(disposables); this.OneWayBind(ViewModel, vm => vm.NotifyLeftClickCmd, v => v.tbNotify.LeftClickCommand).DisposeWith(disposables); @@ -96,6 +98,10 @@ namespace v2rayN.Views Application.Current.MainWindow.Icon = WindowsHandler.Instance.GetAppIcon(_config); }), DispatcherPriority.Normal); break; + case EViewAction.SetClipboardData: + if (obj is null) return false; + WindowsUtils.SetClipboardData((string)obj); + break; } return await Task.FromResult(true); }