diff --git a/CREDITS.md b/CREDITS.md index 2b8955f9..3d71f149 100644 --- a/CREDITS.md +++ b/CREDITS.md @@ -1,7 +1,9 @@ # Contributors ## Current mRemoteNG dev team +[Dimitrij Gorodeckij](https://github.com/Kvarkas) +## Past Contributors [David Sparer](http://github.com/sparerd) [Sean Kaim](http://github.com/kmscode) [Faryan Rezagholi](http://github.com/farosch) @@ -28,8 +30,6 @@ Tony Lambert [MitchellBot](http://github.com/MitchellBot) [Filippo Ferrazini](http://github.com/Filippo125) -## Past Contributors - Felix Deimel - mRemote original developer Riley McArdle - mRemoteNG original developer diff --git a/Directory.Packages.props b/Directory.Packages.props index bfb7eac3..3e71b499 100644 --- a/Directory.Packages.props +++ b/Directory.Packages.props @@ -6,7 +6,7 @@ - + @@ -23,8 +23,8 @@ - - + + @@ -58,18 +58,18 @@ - - + + - - - - + + + + - - - + + + @@ -77,7 +77,7 @@ - + @@ -87,16 +87,16 @@ - + - + - - + + - + diff --git a/mRemoteNG/App/Info/GeneralAppInfo.cs b/mRemoteNG/App/Info/GeneralAppInfo.cs index cf42a5c3..77c021fc 100644 --- a/mRemoteNG/App/Info/GeneralAppInfo.cs +++ b/mRemoteNG/App/Info/GeneralAppInfo.cs @@ -16,7 +16,7 @@ namespace mRemoteNG.App.Info public const string UrlHome = "https://mremoteng.org"; public const string UrlDonate = "https://mremoteng.org/contribute"; public const string UrlForum = "https://www.reddit.com/r/mRemoteNG"; - public const string UrlBugs = "https://bugs.mremoteng.org"; + public const string UrlBugs = "https://github.com/mRemoteNG/mRemoteNG/issues/new"; public const string UrlDocumentation = "https://mremoteng.readthedocs.io/en/latest/"; public static readonly string ApplicationVersion = Application.ProductVersion; public static readonly string ProductName = Application.ProductName; diff --git a/mRemoteNG/App/ProgramRoot.cs b/mRemoteNG/App/ProgramRoot.cs index 12a6b808..2fa9bf05 100644 --- a/mRemoteNG/App/ProgramRoot.cs +++ b/mRemoteNG/App/ProgramRoot.cs @@ -5,7 +5,7 @@ using mRemoteNG.Config.Settings; using mRemoteNG.DotNet.Update; using mRemoteNG.DotNet.Update; using mRemoteNG.UI.Forms; - +using mRemoteNG.Resources.Language; using System; using System.Diagnostics; using System.Drawing; @@ -53,12 +53,11 @@ namespace mRemoteNG.App { try { - var result = MessageBox.Show( - $".NET Desktop Runtime at least {DotNetRuntimeCheck.RequiredDotnetVersion}.0 is required.\n" + - "The application will now exit.\n\nPlease download and install latest desktop runtime:\n" + downloadUrl, - "Missing .NET " + DotNetRuntimeCheck.RequiredDotnetVersion + " Runtime", - MessageBoxButtons.OKCancel, - MessageBoxIcon.Information); + var result = ShowDownloadCancelDialog( + $".NET " + DotNetRuntimeCheck.RequiredDotnetVersion + ".0 " + Language.MsgRuntimeIsRequired + "\n\n" + + Language.MsgDownloadLatestRuntime + "\n" + downloadUrl + "\n\n" + + Language.MsgExit + "\n\n", + Language.MsgMissingRuntime + " .NET " + DotNetRuntimeCheck.RequiredDotnetVersion); if (result == DialogResult.OK && InternetConnection.IsPosible()) { @@ -82,12 +81,11 @@ namespace mRemoteNG.App var downloadUrl2 = "https://aka.ms/vs/17/release/vc_redist.x64.exe"; try { - var result = MessageBox.Show( - $"A Visual C++ (MSVC) runtime library is required.\n" + - "The application will now exit.\n\nPlease download and install latest desktop runtime:\n" + downloadUrl2, - "Missing Visual C++ Redistributable x86 Runtime", - MessageBoxButtons.OKCancel, - MessageBoxIcon.Information); + var result = ShowDownloadCancelDialog( + $"A Visual C++ (MSVC) " + Language.MsgRuntimeIsRequired + "\n\n" + + Language.MsgDownloadLatestRuntime + "\n" + downloadUrl2 + "\n\n" + + Language.MsgExit + "\n\n", + Language.MsgMissingRuntime + " Visual C++ Redistributable x64"); if (result == DialogResult.OK && InternetConnection.IsPosible()) { @@ -269,5 +267,101 @@ namespace mRemoteNG.App _wpfSplashThread = null; } } + + // Helper to show a dialog with "Download" and "Cancel" buttons. + // Returns DialogResult.OK if Download clicked, otherwise DialogResult.Cancel. + private static DialogResult ShowDownloadCancelDialog(string message, string caption) + { + using Form dialog = new Form() + { + Text = caption, + StartPosition = FormStartPosition.CenterScreen, + FormBorderStyle = FormBorderStyle.FixedDialog, + MinimizeBox = false, + MaximizeBox = false, + ShowInTaskbar = false, + ClientSize = new Size(560, 200), + Icon = SystemIcons.Information + }; + + // Try to find a URL in the message (very simple heuristic: first "http" until whitespace/newline) + int urlStart = message.IndexOf("http", StringComparison.OrdinalIgnoreCase); + string? url = null; + if (urlStart >= 0) + { + int urlEnd = message.IndexOfAny(new char[] { ' ', '\r', '\n', '\t' }, urlStart); + if (urlEnd == -1) urlEnd = message.Length; + url = message.Substring(urlStart, urlEnd - urlStart); + } + + LinkLabel lbl = new LinkLabel() + { + AutoSize = false, + Text = message, + Location = new Point(12, 12), + Size = new Size(dialog.ClientSize.Width - 24, dialog.ClientSize.Height - 60), + TextAlign = ContentAlignment.TopLeft, + LinkBehavior = LinkBehavior.SystemDefault + }; + lbl.MaximumSize = new Size(dialog.ClientSize.Width - 24, 0); + + if (!string.IsNullOrEmpty(url) && urlStart >= 0) + { + // Ensure link indices are within bounds of the LinkLabel text + int linkStartInLabel = urlStart; + int linkLength = url.Length; + if (linkStartInLabel + linkLength <= lbl.Text.Length) + { + lbl.Links.Add(linkStartInLabel, linkLength, url); + } + } + + lbl.LinkClicked += (s, e) => + { + string? linkUrl = e.Link.LinkData as string; + if (string.IsNullOrEmpty(linkUrl)) + return; + if (!InternetConnection.IsPosible()) + { + MessageBox.Show("No internet connection is available.", "Network", MessageBoxButtons.OK, MessageBoxIcon.Warning); + return; + } + + // Treat clicking the link the same as clicking the "Download" button: + // set DialogResult to OK so the caller receives DialogResult.OK and can proceed to open the download URL. + dialog.DialogResult = DialogResult.OK; + // Do not call Process.Start here to avoid duplicate launches; caller already opens the URL when it sees DialogResult.OK. + }; + + Button btnDownload = new Button() + { + Text = "Download", + DialogResult = DialogResult.OK, + Size = new Size(100, 28), + }; + Button btnCancel = new Button() + { + Text = "Cancel", + DialogResult = DialogResult.Cancel, + Size = new Size(100, 28), + }; + + // Position buttons + int padding = 12; + btnCancel.Location = new Point(dialog.ClientSize.Width - padding - btnCancel.Width, dialog.ClientSize.Height - padding - btnCancel.Height); + btnDownload.Location = new Point(btnCancel.Left - 8 - btnDownload.Width, btnCancel.Top); + + // Set dialog defaults + dialog.Controls.Add(lbl); + dialog.Controls.Add(btnDownload); + dialog.Controls.Add(btnCancel); + dialog.AcceptButton = btnDownload; + dialog.CancelButton = btnCancel; + + // Adjust label height to wrap text properly + lbl.Height = btnCancel.Top - lbl.Top - 8; + + return dialog.ShowDialog(); + } } } \ No newline at end of file diff --git a/mRemoteNG/Language/Language.Designer.cs b/mRemoteNG/Language/Language.Designer.cs index 1577891b..781f50bb 100644 --- a/mRemoteNG/Language/Language.Designer.cs +++ b/mRemoteNG/Language/Language.Designer.cs @@ -19,7 +19,7 @@ namespace mRemoteNG.Resources.Language { // class via a tool like ResGen or Visual Studio. // To add or remove a member, edit your .ResX file then rerun ResGen // with the /str option, or rebuild your VS project. - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "17.0.0.0")] + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "18.0.0.0")] [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] internal class Language { @@ -3206,6 +3206,42 @@ namespace mRemoteNG.Resources.Language { } } + /// + /// Looks up a localized string similar to Please download and install latest runtime:. + /// + internal static string MsgDownloadLatestRuntime { + get { + return ResourceManager.GetString("MsgDownloadLatestRuntime", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to The application will now exit.. + /// + internal static string MsgExit { + get { + return ResourceManager.GetString("MsgExit", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Missing Runtime:. + /// + internal static string MsgMissingRuntime { + get { + return ResourceManager.GetString("MsgMissingRuntime", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to runtime library is required. + /// + internal static string MsgRuntimeIsRequired { + get { + return ResourceManager.GetString("MsgRuntimeIsRequired", resourceCulture); + } + } + /// /// Looks up a localized string similar to Multi SSH:. /// diff --git a/mRemoteNG/Language/Language.de.resx b/mRemoteNG/Language/Language.de.resx index ea00c823..cd6224d8 100644 --- a/mRemoteNG/Language/Language.de.resx +++ b/mRemoteNG/Language/Language.de.resx @@ -2050,8 +2050,4 @@ Nightly umfasst Alphas, Betas und Release Candidates. WebView2-Erstellung fehlgeschlagen - - - - \ No newline at end of file diff --git a/mRemoteNG/Language/Language.el.resx b/mRemoteNG/Language/Language.el.resx index 5b779aaf..7bd9d12e 100644 --- a/mRemoteNG/Language/Language.el.resx +++ b/mRemoteNG/Language/Language.el.resx @@ -273,8 +273,4 @@ Πύλη - - - - \ No newline at end of file diff --git a/mRemoteNG/Language/Language.es.resx b/mRemoteNG/Language/Language.es.resx index bf0138a3..b04613a0 100644 --- a/mRemoteNG/Language/Language.es.resx +++ b/mRemoteNG/Language/Language.es.resx @@ -1541,8 +1541,4 @@ mRemoteNG ahora se cerrará y comenzará la instalación. Guardar conexiones al salir - - - - \ No newline at end of file diff --git a/mRemoteNG/Language/Language.fi-FI.resx b/mRemoteNG/Language/Language.fi-FI.resx index 6ee67b42..dd6242e5 100644 --- a/mRemoteNG/Language/Language.fi-FI.resx +++ b/mRemoteNG/Language/Language.fi-FI.resx @@ -138,8 +138,4 @@ 65536 Värit (16-bit) - - - - \ No newline at end of file diff --git a/mRemoteNG/Language/Language.fr.resx b/mRemoteNG/Language/Language.fr.resx index 742b1825..a1c1a529 100644 --- a/mRemoteNG/Language/Language.fr.resx +++ b/mRemoteNG/Language/Language.fr.resx @@ -2153,8 +2153,4 @@ Le canal nightly inclut les versions alpha, beta et release candidates. Création WebView2 échouée avec une exception - - - - \ No newline at end of file diff --git a/mRemoteNG/Language/Language.hu.resx b/mRemoteNG/Language/Language.hu.resx index c1d6adf9..e66fcf12 100644 --- a/mRemoteNG/Language/Language.hu.resx +++ b/mRemoteNG/Language/Language.hu.resx @@ -333,8 +333,4 @@ Átjáró - - - - \ No newline at end of file diff --git a/mRemoteNG/Language/Language.it.resx b/mRemoteNG/Language/Language.it.resx index a64f3cf8..75256c54 100644 --- a/mRemoteNG/Language/Language.it.resx +++ b/mRemoteNG/Language/Language.it.resx @@ -1556,7 +1556,4 @@ mRemoteNG verrà chiuso e l'installazione avrà inizio. Salva le connessioni all'uscita - - Vault o Openbao - \ No newline at end of file diff --git a/mRemoteNG/Language/Language.ja-JP.resx b/mRemoteNG/Language/Language.ja-JP.resx index a1b26d12..6121aa5b 100644 --- a/mRemoteNG/Language/Language.ja-JP.resx +++ b/mRemoteNG/Language/Language.ja-JP.resx @@ -1716,8 +1716,4 @@ mRemoteNGを終了してインストールを開始します 終了時に保存する - - - - \ No newline at end of file diff --git a/mRemoteNG/Language/Language.ko-KR.resx b/mRemoteNG/Language/Language.ko-KR.resx index fb50188e..aa28909d 100644 --- a/mRemoteNG/Language/Language.ko-KR.resx +++ b/mRemoteNG/Language/Language.ko-KR.resx @@ -1806,8 +1806,4 @@ mRemoteNG는 이제 종료되고 설치로 시작됩니다. 종료시 연결 저장 - - - - \ No newline at end of file diff --git a/mRemoteNG/Language/Language.lt.resx b/mRemoteNG/Language/Language.lt.resx index d383f211..eb884b7d 100644 --- a/mRemoteNG/Language/Language.lt.resx +++ b/mRemoteNG/Language/Language.lt.resx @@ -228,8 +228,4 @@ Nightly Channel includes Alphas, Betas & Release Candidates. Proxy - - - - \ No newline at end of file diff --git a/mRemoteNG/Language/Language.nb-NO.resx b/mRemoteNG/Language/Language.nb-NO.resx index b64a5045..cd5f88c5 100644 --- a/mRemoteNG/Language/Language.nb-NO.resx +++ b/mRemoteNG/Language/Language.nb-NO.resx @@ -2005,8 +2005,4 @@ Nightly-kanalen inkluderer alpha-, beta- og release candidate-versjoner. Lagre tilkoblinger ved avslutning - - - - \ No newline at end of file diff --git a/mRemoteNG/Language/Language.nl.resx b/mRemoteNG/Language/Language.nl.resx index a50f0853..740879e5 100644 --- a/mRemoteNG/Language/Language.nl.resx +++ b/mRemoteNG/Language/Language.nl.resx @@ -1588,8 +1588,4 @@ mRemoteNG zal nu worden gesloten en beginnen met de installatie. Sla verbindingen op bij afsluiten - - - - \ No newline at end of file diff --git a/mRemoteNG/Language/Language.pl.resx b/mRemoteNG/Language/Language.pl.resx index 80e952a1..5756cf8d 100644 --- a/mRemoteNG/Language/Language.pl.resx +++ b/mRemoteNG/Language/Language.pl.resx @@ -2359,8 +2359,4 @@ Kanał nocny obejmuje wersje alfa, beta i RC (gotowe do wydania). Brama - - - - \ No newline at end of file diff --git a/mRemoteNG/Language/Language.pt-BR.resx b/mRemoteNG/Language/Language.pt-BR.resx index c1e61fda..f14c096d 100644 --- a/mRemoteNG/Language/Language.pt-BR.resx +++ b/mRemoteNG/Language/Language.pt-BR.resx @@ -369,8 +369,4 @@ Gateway - - - - \ No newline at end of file diff --git a/mRemoteNG/Language/Language.pt.resx b/mRemoteNG/Language/Language.pt.resx index d64d73b9..36a8cb1f 100644 --- a/mRemoteNG/Language/Language.pt.resx +++ b/mRemoteNG/Language/Language.pt.resx @@ -1554,8 +1554,4 @@ Salvar as ligações à saída - - - - \ No newline at end of file diff --git a/mRemoteNG/Language/Language.resx b/mRemoteNG/Language/Language.resx index 75436593..50ed009f 100644 --- a/mRemoteNG/Language/Language.resx +++ b/mRemoteNG/Language/Language.resx @@ -2453,6 +2453,20 @@ Nightly Channel includes Alphas, Betas & Release Candidates. WarnMeOnlyWhenClosingMultipleConnections + + The application will now exit. + Message shown then application will normally close + + + Please download and install latest runtime: + Appears then missing a runtime + + + Missing Runtime: + + + runtime library is required + Vault or Openbao diff --git a/mRemoteNG/Language/Language.sv-SE.resx b/mRemoteNG/Language/Language.sv-SE.resx index f6f13893..50408a06 100644 --- a/mRemoteNG/Language/Language.sv-SE.resx +++ b/mRemoteNG/Language/Language.sv-SE.resx @@ -2172,8 +2172,4 @@ Nattliga kanalen inkluderar Alfa, Betor & Utgåvokandidater. Nätverksnod (gateway) - - - - \ No newline at end of file diff --git a/mRemoteNG/Language/Language.ta.resx b/mRemoteNG/Language/Language.ta.resx index 3c5d8981..6eb7bce8 100644 --- a/mRemoteNG/Language/Language.ta.resx +++ b/mRemoteNG/Language/Language.ta.resx @@ -2416,8 +2416,4 @@ முன்னறிவிப்பு - - - - \ No newline at end of file diff --git a/mRemoteNG/Language/Language.tr-TR.resx b/mRemoteNG/Language/Language.tr-TR.resx index 31f45dc2..7196be5d 100644 --- a/mRemoteNG/Language/Language.tr-TR.resx +++ b/mRemoteNG/Language/Language.tr-TR.resx @@ -1628,8 +1628,4 @@ MRemoteNG şimdi kapanacak ve kurulum başlayacak. Çıkışta bağlantıları kaydet - - - - \ No newline at end of file diff --git a/mRemoteNG/Language/Language.uk.resx b/mRemoteNG/Language/Language.uk.resx index d8082aa6..632fbb95 100644 --- a/mRemoteNG/Language/Language.uk.resx +++ b/mRemoteNG/Language/Language.uk.resx @@ -2002,8 +2002,4 @@ mRemoteNG зараз припинить роботу і почне процес Зберігати з'єднання при виході - - - - \ No newline at end of file diff --git a/mRemoteNG/Language/Language.zh-CN.resx b/mRemoteNG/Language/Language.zh-CN.resx index 13905d0d..5700271d 100644 --- a/mRemoteNG/Language/Language.zh-CN.resx +++ b/mRemoteNG/Language/Language.zh-CN.resx @@ -2080,8 +2080,4 @@ mRemoteNG 将退出并安装更新。 退出时保存连接配置文件 - - - - \ No newline at end of file diff --git a/mRemoteNG/Language/Language.zh-TW.resx b/mRemoteNG/Language/Language.zh-TW.resx index 5cb95f25..7502972b 100644 --- a/mRemoteNG/Language/Language.zh-TW.resx +++ b/mRemoteNG/Language/Language.zh-TW.resx @@ -1575,8 +1575,4 @@ mRemoteNG 將立即結束並開始安裝。 結束時儲存連線 - - - - \ No newline at end of file diff --git a/mRemoteNG/UI/Menu/msMain/HelpMenu.cs b/mRemoteNG/UI/Menu/msMain/HelpMenu.cs index b003a4af..dfd829a9 100644 --- a/mRemoteNG/UI/Menu/msMain/HelpMenu.cs +++ b/mRemoteNG/UI/Menu/msMain/HelpMenu.cs @@ -22,6 +22,7 @@ namespace mRemoteNG.UI.Menu private ToolStripSeparator _mMenInfoSep3; private ToolStripSeparator _mMenInfoSep4; private ToolStripMenuItem _mMenInfoForum; + private ToolStripMenuItem _mMenInfoBug; private ToolStripMenuItem _mMenToolsUpdate; public HelpMenu() @@ -36,6 +37,7 @@ namespace mRemoteNG.UI.Menu _mMenInfoWebsite = new ToolStripMenuItem(); _mMenInfoDonate = new ToolStripMenuItem(); _mMenInfoForum = new ToolStripMenuItem(); + _mMenInfoBug = new ToolStripMenuItem(); _mMenToolsUpdate = new ToolStripMenuItem(); _mMenInfoSep2 = new ToolStripSeparator(); _mMenInfoSep3 = new ToolStripSeparator(); @@ -51,6 +53,7 @@ namespace mRemoteNG.UI.Menu _mMenInfoSep1, _mMenInfoWebsite, _mMenInfoForum, + _mMenInfoBug, _mMenInfoSep2, _mMenToolsUpdate, _mMenInfoSep3, @@ -108,6 +111,13 @@ namespace mRemoteNG.UI.Menu _mMenInfoForum.Text = Language.SupportForum; _mMenInfoForum.Click += mMenInfoForum_Click; // + // mMenInfoBug + // + _mMenInfoBug.Name = "mMenInfoBug"; + _mMenInfoBug.Size = new System.Drawing.Size(190, 22); + _mMenInfoBug.Text = Language.ReportBug; + _mMenInfoBug.Click += mMenInfoBug_Click; + // // mMenInfoSep2 // _mMenInfoSep2.Name = "mMenInfoSep2"; @@ -139,6 +149,7 @@ namespace mRemoteNG.UI.Menu _mMenInfoWebsite.Text = Language.Website; _mMenInfoDonate.Text = Language.Donate; _mMenInfoForum.Text = Language.SupportForum; + _mMenInfoBug.Text = Language.ReportBug; _mMenInfoAbout.Text = Language.About; _mMenToolsUpdate.Text = Language.CheckForUpdates; } @@ -159,6 +170,8 @@ namespace mRemoteNG.UI.Menu private void mMenInfoForum_Click(object sender, EventArgs e) => Process.Start("explorer.exe", GeneralAppInfo.UrlForum); + private void mMenInfoBug_Click(object sender, EventArgs e) => Process.Start("explorer.exe", GeneralAppInfo.UrlBugs); + private void mMenInfoWebsite_Click(object sender, EventArgs e) => Process.Start("explorer.exe", GeneralAppInfo.UrlHome); private void mMenInfoDonate_Click(object sender, EventArgs e) => Process.Start("explorer.exe", GeneralAppInfo.UrlDonate);