From e1238fa8e6dd2125237f8946131bda8c1a6bf3fb Mon Sep 17 00:00:00 2001 From: uom Date: Mon, 7 Feb 2022 01:25:51 +0700 Subject: [PATCH 01/20] iss 110 Feedback to the developer --- Navferty.ExcelAddIn.Web/Navferty.ExcelAddIn.Web.csproj | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Navferty.ExcelAddIn.Web/Navferty.ExcelAddIn.Web.csproj b/Navferty.ExcelAddIn.Web/Navferty.ExcelAddIn.Web.csproj index de58509..053409f 100644 --- a/Navferty.ExcelAddIn.Web/Navferty.ExcelAddIn.Web.csproj +++ b/Navferty.ExcelAddIn.Web/Navferty.ExcelAddIn.Web.csproj @@ -138,6 +138,9 @@ + + + From 697166ef20608039b3622e9ea248a507d37bdbf8 Mon Sep 17 00:00:00 2001 From: uom Date: Mon, 7 Feb 2022 02:20:48 +0700 Subject: [PATCH 02/20] FeedbackManager --- Navferty.Common/Feedback/FeedbackManager.cs | 103 ++++++ Navferty.Common/Navferty.Common.csproj | 1 + Navferty.Common/WinAPI/WinAPI.cs | 338 ++++++++++++++++++++ 3 files changed, 442 insertions(+) create mode 100644 Navferty.Common/Feedback/FeedbackManager.cs diff --git a/Navferty.Common/Feedback/FeedbackManager.cs b/Navferty.Common/Feedback/FeedbackManager.cs new file mode 100644 index 0000000..eeb1311 --- /dev/null +++ b/Navferty.Common/Feedback/FeedbackManager.cs @@ -0,0 +1,103 @@ +using System; +using System.Collections.Generic; +using System.Drawing; +using System.Drawing.Imaging; +using System.IO; +using System.Linq; +using System.Text; +using System.Windows.Forms; + +using Microsoft.Win32; + +#nullable enable + +namespace Navferty.Common.Feedback +{ + public static class FeedbackManager + { + private static FileInfo[] GetScreenshotsAsFiles(ImageFormat fmt, string fileExt = "jpg") + => System.Windows.Forms.Screen.AllScreens.ToList().Select(scr => + { + using (Bitmap bmCapt = new(scr.Bounds.Width, scr.Bounds.Height, PixelFormat.Format32bppArgb)) + { + var rcCapt = scr.Bounds; + using (Graphics g = Graphics.FromImage(bmCapt)) + g.CopyFromScreen(rcCapt.Left, rcCapt.Top, 0, 0, rcCapt.Size); + + var sBitmapFile = System.IO.Path.Combine( + System.IO.Path.GetTempPath(), (Guid.NewGuid().ToString() + '.'.ToString() + fileExt)); + bmCapt.Save(sBitmapFile, fmt); + return new System.IO.FileInfo(sBitmapFile); + } + }).ToArray(); + + private const string MAIL_SUBJECT = @"NavfertyExcelAddin Bug report from user!"; + private const int MAX_MESSAGE_BODY_LENGH = 500; + + private static bool SendFeedEMail( + string messageBody, + bool sendScreenshots = true + ) + { + //TODO: !!! Insert developer email instead of this !!! + string developerMail = (new Func(() => + { + using (var hKey = Registry.CurrentUser.OpenSubKey(@"Software\Microsoft\Office\16.0\Outlook\Profiles\Outlook\9375CFF0413111d3B88A00104B2A6676\00000005")) + return hKey.GetValue("Email").ToString(); + })).Invoke(); + + + List lScreenshotFiles = new(); + + if (string.IsNullOrWhiteSpace(messageBody)) + messageBody = string.Empty; + + + + if (messageBody.Length > MAX_MESSAGE_BODY_LENGH) + messageBody = new string(messageBody.Take(MAX_MESSAGE_BODY_LENGH).ToArray()); + + + StringBuilder sbTechInfo = new(); + sbTechInfo.AppendLine($"Message created {DateTime.Now}"); + sbTechInfo.AppendLine(Application.ProductVersion.ToString()); + sbTechInfo.AppendLine(Application.ExecutablePath); + sbTechInfo.AppendLine(); + sbTechInfo.AppendLine(messageBody); + + messageBody = sbTechInfo.ToString(); + + if (sendScreenshots) //Create screenshots to temp dir + lScreenshotFiles = GetScreenshotsAsFiles(ImageFormat.Jpeg).ToList(); + + try + { + //Send Screenshots + var bSend = WinAPI.MAPI.SendMail( + developerMail, + MAIL_SUBJECT, + messageBody, + WinAPI.MAPI.UIFlags.SendMailDirectNoUI, + lScreenshotFiles.Select(fi => fi.FullName).ToArray() + ); + + return bSend; + } + finally + { + //Cleanup Temp files + lScreenshotFiles.ForEach(fi => + { + try { fi.Delete(); } + catch { } + }); + } + } + + public static void ShowFeedbackUI() + { + SendFeedEMail("sd", true); + + } + } +} diff --git a/Navferty.Common/Navferty.Common.csproj b/Navferty.Common/Navferty.Common.csproj index b7c906c..5f99f1b 100644 --- a/Navferty.Common/Navferty.Common.csproj +++ b/Navferty.Common/Navferty.Common.csproj @@ -55,6 +55,7 @@ + diff --git a/Navferty.Common/WinAPI/WinAPI.cs b/Navferty.Common/WinAPI/WinAPI.cs index 8440e6f..7df7707 100644 --- a/Navferty.Common/WinAPI/WinAPI.cs +++ b/Navferty.Common/WinAPI/WinAPI.cs @@ -1,6 +1,9 @@ using System; +using System.Collections.Generic; using System.ComponentModel; using System.Drawing; +using System.IO; +using System.Linq; using System.Runtime.InteropServices; using System.Windows.Forms; @@ -70,5 +73,340 @@ protected override bool ReleaseHandle() public Graphics CreateGraphics() => Graphics.FromHdc(DangerousGetHandle()); } + + + /// + /// https://docs.microsoft.com/ru-ru/previous-versions/windows/desktop/windowsmapi/mapi32-dll-stub-registry-settings?redirectedfrom=MSDN + /// + internal static class MAPI + { + public const int MAX_ATTACHMENTS = 20; + + public enum MAPI_ERRORS : int + { + [Description("OK")] + OK = 0, + + [Description("User abort")] + UserAbort = 1, + + [Description("General MAPI failure")] + GeneralMAPIFailure = 2, + + [Description("MAPI login failure")] + MAPILoginFailure = 3, + + [Description("Disk full")] + DiskFull = 4, + + [Description("Insufficient memory")] + InsufficientMemory = 5, + + [Description("Access denied [6")] + AccessDenied = 6, + + [Description("Unknown")] + Unknown = 7, + + [Description("Too many sessions")] + TooManySessions = 8, + + [Description("Too many files were specified")] + TooManyFilesWereSpecified = 9, + + [Description("Too many recipients were specified")] + ToomanyRecipientsWereSpecified = 10, + + [Description("A specified attachment was not found")] + SpecifiedAttachmentWasNotFound = 11, + + [Description("Attachment open failure")] + AttachmentOpenFailure = 12, + + [Description("Attachment write failure")] + AttachmentWriteFailure = 13, + + [Description("Unknown recipient")] + UnknownRecipient = 14, + + [Description("Bad recipient type")] + BadRecipientType = 15, + + [Description("No messages")] + NoMessages = 16, + + [Description("Invalid message")] + InvalidMessage = 17, + + [Description("Text too large")] + TextTooLarge = 18, + + [Description("Invalid session")] + InvalidSession = 19, + + [Description("Type not supported")] + TypeNotSupported = 20, + + [Description("A recipient was specified ambiguously")] + RecipientWasSpecifiedAmbiguously = 21, + + [Description("Message in use")] + MessageInUse = 22, + + [Description("Network failure")] + NetworkFailure = 23, + + [Description("Invalid edit fields")] + InvalidEditFields = 24, + + [Description("Invalid recipients")] + InvalidRecipients = 25, + + [Description("Not supported")] + NotSupported = 26, + + //[EditorBrowsable(EditorBrowsableState.Never)] + Last + } + + public class MAPIException : System.Exception + { + public readonly MAPI_ERRORS ErrorCode = MAPI_ERRORS.OK; + internal MAPIException(MAPI_ERRORS err) : base(GetErrorMessageForCode(err)) + { + ErrorCode = err; + } + public override string Message => GetErrorMessageForCode(ErrorCode); + + public static string GetErrorMessageForCode(MAPI_ERRORS Err) + { + if (Err >= MAPI_ERRORS.Last) return $"MAPI Error {Err}"; + return Err.ToString(); + } + } + + public enum SendToFlags : int + { + MAPI_ORIG = 0, + MAPI_TO, + MAPI_CC, + MAPI_BCC + }; + + public enum UIFlags : uint + { + /// Display Send Mail UI dialog + PopupUI = 0, + + /// Send mail without displaying the mail UI dialog. + /// for safety reason, MSOutlook displays warning UI that allows user to allow or block sending this mail (mail message itself is not visible to user) + SendMailDirectNoUI + } + + #region API + + private enum MAPI_FLAGS : uint + { + MAPI_LOGON_UI = 1, // Показать интерфейс входа в систему + MAPI_NEW_SESSION = 2, // Не использовать общий сеанс + MAPI_DIALOG = 8, + //MAPI_ALLOW_OTHERS = 8; исходное шестнадцатеричное значение 0x00000008 ; Сделать это общим сеансом + MAPI_EXPLICIT_PROFILE = 16, //Не использовать профиль по умолчанию + MAPI_EXTENDED = 32, //Расширенный вход MAPI + MAPI_FORCE_DOWNLOAD = 4096, //Получить новую почту перед возвратом + MAPI_SERVICE_UI_ALWAYS = 8192, //Выполнить вход в систему во всех провайдерах + MAPI_NO_MAIL = 32768, //Не активировать транспорт + MAPI_PASSWORD_UI = 131072, //Отображать только пользовательский интерфейс пароля + MAPI_TIMEOUT_SHORT = 1048576, //Минимальное ожидание ресурсов входа в систему + MAPI_UNICODE = 0x80000000, + MAPI_USE_DEFAULT = 0x00000040 + } + + /// + /// If you're application is running with Elevated Privileges (i.e. as Administrator) and Outlook isn't, the send will fail. + /// You will have to tell the user to close all running instances of Outlook and try again. + /// + [DllImport("MAPI32.DLL", CharSet = CharSet.Ansi)] + private static extern MAPI_ERRORS MAPISendMail( + IntPtr lhSession, + IntPtr hWnd, + MapiMessage message, + MAPI_FLAGS flg, + int rsv); + + #endregion + + + public static bool SendMail( + IEnumerable recipients, + string strSubject, + string strBody, + UIFlags UIflags = UIFlags.PopupUI, + params string[] attachFiles + ) + { + using (MapiMessage msg = new() + { + subject = strSubject, + noteText = strBody + }) + { + (msg.hRecips, msg.recipCount) = RecipientsToBuffer(recipients); + (msg.hFiles, msg.fileCount) = AttachmentsToBuffer(attachFiles); + + MAPI_FLAGS how = (UIflags == UIFlags.PopupUI) ? (MAPI_FLAGS.MAPI_LOGON_UI | MAPI_FLAGS.MAPI_DIALOG) : (MAPI_FLAGS.MAPI_LOGON_UI); + how |= MAPI_FLAGS.MAPI_NEW_SESSION; + + var Err = MAPISendMail( + new IntPtr(0), + new IntPtr(0), + msg, + how, + 0); + + switch (Err) + { + case MAPI_ERRORS.OK: return true; + case MAPI_ERRORS.UserAbort: return false; + default: throw new MAPIException(Err); + } + } + } + + public static bool SendMail( + string sendTo, + string strSubject, + string strBody, + UIFlags uiFlags = UIFlags.PopupUI, + params string[] attachFiles) + => SendMail( + new MapiRecipDesc[] { CreateRecipient(sendTo, SendToFlags.MAPI_TO) }, + strSubject, strBody, uiFlags, attachFiles); + + + public static MapiRecipDesc CreateRecipient(string email, SendToFlags howTo = SendToFlags.MAPI_TO) + => new(email, howTo); + + private static (IntPtr hMem, int Count) RecipientsToBuffer(IEnumerable recipients) + { + if (!recipients.Any()) throw new ArgumentNullException(nameof(recipients)); + + var lRecipients = recipients.ToList(); + + int size = Marshal.SizeOf(typeof(MapiRecipDesc)); + IntPtr hMem = Marshal.AllocHGlobal(lRecipients.Count * size); + IntPtr hWrite = hMem; + lRecipients.ForEach(mapiDesc => + { + Marshal.StructureToPtr(mapiDesc, hWrite, false); + hWrite += size; + }); + return (hMem, lRecipients.Count); + } + + private static (IntPtr hMem, int fileCount) AttachmentsToBuffer(IEnumerable? attachments = null) + { + if (attachments == null || !attachments.Any()) return (IntPtr.Zero, 0); + if (attachments.Count() > MAX_ATTACHMENTS) throw new ArgumentOutOfRangeException($"{nameof(attachments)}.Count > {MAX_ATTACHMENTS}"); + + List lAttachments = attachments.ToList(); + + int size = Marshal.SizeOf(typeof(MapiFileDesc)); + IntPtr hMem = Marshal.AllocHGlobal(lAttachments.Count * size); + + MapiFileDesc mapiFileDesc = new(); + mapiFileDesc.position = -1; + + IntPtr ptr = hMem; + lAttachments.ForEach(path => + { + mapiFileDesc.name = Path.GetFileName(path); + mapiFileDesc.path = path; + Marshal.StructureToPtr(mapiFileDesc, ptr, false); + ptr += size; + }); + return (hMem, lAttachments.Count); + } + + + + [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)] + internal class MapiMessage : IDisposable + { + public int reserved; + public string subject; + public string noteText; + public string messageType; + public string dateReceived; + public string conversationID; + public int flags; + public IntPtr hOriginator; + public int recipCount; + public IntPtr hRecips; + public int fileCount; + public IntPtr hFiles; + + public void Dispose() + { + if (hRecips != IntPtr.Zero) + { + int size = Marshal.SizeOf(typeof(MapiRecipDesc)); + IntPtr ptr = hRecips; + for (int i = 0; i < recipCount; i++) + { + Marshal.DestroyStructure(ptr, typeof(MapiRecipDesc)); + ptr += size; + } + Marshal.FreeHGlobal(hRecips); + } + + if (hFiles != IntPtr.Zero) + { + int size = Marshal.SizeOf(typeof(MapiFileDesc)); + IntPtr ptr = hFiles; + for (int i = 0; i < fileCount; i++) + { + Marshal.DestroyStructure((IntPtr)ptr, + typeof(MapiFileDesc)); + ptr += size; + } + Marshal.FreeHGlobal(hFiles); + } + } + } + + [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)] + internal class MapiFileDesc + { + public int reserved; + public int flags; + public int position; + public string path; + public string name; + public IntPtr hType; + } + + [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)] + public class MapiRecipDesc + { + public int reserved = 0; + public SendToFlags recipClass = SendToFlags.MAPI_TO; + + /// MAPISendMail hanging with Outlook because the mail addresses had trailing spaces! + public string name = String.Empty; + public string address = String.Empty; + public int eIDSize = 0; + public IntPtr hEntryID = IntPtr.Zero; + + private MapiRecipDesc() { } + + public MapiRecipDesc(string email, SendToFlags howTo = SendToFlags.MAPI_TO) : this() + { + recipClass = howTo; + name = email.Trim(); + } + } + } } + } From 555d82ecfe8a29199fc0cbdfe6ec3693dbe87f8f Mon Sep 17 00:00:00 2001 From: uom Date: Mon, 7 Feb 2022 04:14:14 +0700 Subject: [PATCH 03/20] add system info dump --- Navferty.Common/Feedback/FeedbackManager.cs | 80 ++++++++---- .../Feedback/frmFeedbackUI.Designer.cs | 65 ++++++++++ Navferty.Common/Feedback/frmFeedbackUI.cs | 40 ++++++ Navferty.Common/Feedback/frmFeedbackUI.resx | 120 ++++++++++++++++++ Navferty.Common/Navferty.Common.csproj | 25 +++- Navferty.Common/packages.config | 4 + .../CurrencyExchangeRates/Manager.cs | 5 +- NavfertyExcelAddIn/app.config | 4 +- 8 files changed, 313 insertions(+), 30 deletions(-) create mode 100644 Navferty.Common/Feedback/frmFeedbackUI.Designer.cs create mode 100644 Navferty.Common/Feedback/frmFeedbackUI.cs create mode 100644 Navferty.Common/Feedback/frmFeedbackUI.resx create mode 100644 Navferty.Common/packages.config diff --git a/Navferty.Common/Feedback/FeedbackManager.cs b/Navferty.Common/Feedback/FeedbackManager.cs index eeb1311..81d57b5 100644 --- a/Navferty.Common/Feedback/FeedbackManager.cs +++ b/Navferty.Common/Feedback/FeedbackManager.cs @@ -2,13 +2,17 @@ using System.Collections.Generic; using System.Drawing; using System.Drawing.Imaging; +using System.Globalization; using System.IO; using System.Linq; +using System.Reflection; using System.Text; using System.Windows.Forms; using Microsoft.Win32; +using NLog; + #nullable enable namespace Navferty.Common.Feedback @@ -32,13 +36,17 @@ private static FileInfo[] GetScreenshotsAsFiles(ImageFormat fmt, string fileExt }).ToArray(); private const string MAIL_SUBJECT = @"NavfertyExcelAddin Bug report from user!"; - private const int MAX_MESSAGE_BODY_LENGH = 500; + private const int MAX_MESSAGE_BODY_LENGH = 1024 * 3; + + private static readonly Lazy logger = new(() => LogManager.GetCurrentClassLogger()); - private static bool SendFeedEMail( - string messageBody, + internal static bool SendFeedEMail( + string userText, bool sendScreenshots = true ) { + logger.Value.Debug("Start SendFeedEMail"); + //TODO: !!! Insert developer email instead of this !!! string developerMail = (new Func(() => { @@ -46,29 +54,20 @@ private static bool SendFeedEMail( return hKey.GetValue("Email").ToString(); })).Invoke(); + logger.Value.Debug($"developerMail: '{developerMail}'"); - List lScreenshotFiles = new(); - - if (string.IsNullOrWhiteSpace(messageBody)) - messageBody = string.Empty; - - + StringBuilder sbMessageBody = new(); + sbMessageBody.AppendLine(GetSystemInfo().Trim()); + sbMessageBody.AppendLine("*** User message:"); + sbMessageBody.AppendLine((string.IsNullOrWhiteSpace(userText) ? "[NONE]" : ('"' + userText + '"'))); - if (messageBody.Length > MAX_MESSAGE_BODY_LENGH) - messageBody = new string(messageBody.Take(MAX_MESSAGE_BODY_LENGH).ToArray()); + string messageBody = sbMessageBody.ToString(); + if (messageBody.Length > MAX_MESSAGE_BODY_LENGH) messageBody = new string(messageBody.Take(MAX_MESSAGE_BODY_LENGH).ToArray()); + logger.Value.Debug($"messageBody:\n'{messageBody}'"); - - StringBuilder sbTechInfo = new(); - sbTechInfo.AppendLine($"Message created {DateTime.Now}"); - sbTechInfo.AppendLine(Application.ProductVersion.ToString()); - sbTechInfo.AppendLine(Application.ExecutablePath); - sbTechInfo.AppendLine(); - sbTechInfo.AppendLine(messageBody); - - messageBody = sbTechInfo.ToString(); - - if (sendScreenshots) //Create screenshots to temp dir - lScreenshotFiles = GetScreenshotsAsFiles(ImageFormat.Jpeg).ToList(); + List lScreenshotFiles = new(); + if (sendScreenshots) lScreenshotFiles = GetScreenshotsAsFiles(ImageFormat.Jpeg).ToList();//Create screenshots to temp dir + logger.Value.Debug($"screensots: '{lScreenshotFiles.Count}'"); try { @@ -81,6 +80,7 @@ private static bool SendFeedEMail( lScreenshotFiles.Select(fi => fi.FullName).ToArray() ); + logger.Value.Debug($"Send result: {bSend}"); return bSend; } finally @@ -93,11 +93,41 @@ private static bool SendFeedEMail( }); } } + private static string GetSystemInfo() + { + var dtNow = DateTime.Now; + var asm = Assembly.GetExecutingAssembly(); + StringBuilder sbSysInfo = new(); + sbSysInfo.AppendLine("*** Product:"); + sbSysInfo.AppendLine($"Name: '{Application.ProductName}' v'{Application.ProductVersion}'"); + sbSysInfo.AppendLine($"Path: '{Application.ExecutablePath}'"); + sbSysInfo.AppendLine(); + sbSysInfo.AppendLine("*** Assembly:"); + sbSysInfo.AppendLine($"FullName: '{asm.FullName}'"); + sbSysInfo.AppendLine($"Location: '{asm.Location}'"); + sbSysInfo.AppendLine($"ImageRuntimeVersion: '{asm.ImageRuntimeVersion}'"); + sbSysInfo.AppendLine($"IsFullyTrusted: '{asm.IsFullyTrusted}'"); + sbSysInfo.AppendLine($"EntryPoint: '{asm.EntryPoint}'"); + sbSysInfo.AppendLine(); + sbSysInfo.AppendLine("*** TimeZone:"); + sbSysInfo.AppendLine(dtNow.Kind.ToString() + $": {dtNow}"); + sbSysInfo.AppendLine($"Utc: {dtNow.ToUniversalTime()}"); + sbSysInfo.AppendLine($"UtcOffset: {TimeZone.CurrentTimeZone.GetUtcOffset(dtNow)}"); + sbSysInfo.AppendLine(); + sbSysInfo.AppendLine("*** Culture:"); + sbSysInfo.AppendLine($"CultureInfo.CurrentCulture: {CultureInfo.CurrentCulture}"); + sbSysInfo.AppendLine($"CultureInfo.CurrentUICulture: {CultureInfo.CurrentUICulture}"); + sbSysInfo.AppendLine($"Application.CurrentCulture: {Application.CurrentCulture}"); + sbSysInfo.AppendLine($"InputLanguage: {Application.CurrentInputLanguage.Culture} (Layout: {Application.CurrentInputLanguage.LayoutName})"); + sbSysInfo.AppendLine(); + sbSysInfo.AppendLine($"VisualStyleState: {Application.VisualStyleState}"); + return sbSysInfo.ToString(); + } public static void ShowFeedbackUI() { - SendFeedEMail("sd", true); - + using var fui = new frmFeedbackUI(); + fui.ShowDialog(); } } } diff --git a/Navferty.Common/Feedback/frmFeedbackUI.Designer.cs b/Navferty.Common/Feedback/frmFeedbackUI.Designer.cs new file mode 100644 index 0000000..c49b307 --- /dev/null +++ b/Navferty.Common/Feedback/frmFeedbackUI.Designer.cs @@ -0,0 +1,65 @@ +namespace Navferty.Common.Feedback +{ + partial class frmFeedbackUI + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + this.button1 = new System.Windows.Forms.Button(); + this.SuspendLayout(); + // + // button1 + // + this.button1.Location = new System.Drawing.Point(206, 121); + this.button1.Name = "button1"; + this.button1.Size = new System.Drawing.Size(75, 23); + this.button1.TabIndex = 0; + this.button1.Text = "Send"; + this.button1.UseVisualStyleBackColor = true; + this.button1.Click += new System.EventHandler(this.button1_Click); + // + // frmFeedbackUI + // + this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.ClientSize = new System.Drawing.Size(339, 196); + this.Controls.Add(this.button1); + this.MaximizeBox = false; + this.MinimizeBox = false; + this.Name = "frmFeedbackUI"; + this.ShowIcon = false; + this.ShowInTaskbar = false; + this.StartPosition = System.Windows.Forms.FormStartPosition.CenterParent; + this.Text = "frmFeedbackUI"; + this.ResumeLayout(false); + + } + + #endregion + + private System.Windows.Forms.Button button1; + } +} \ No newline at end of file diff --git a/Navferty.Common/Feedback/frmFeedbackUI.cs b/Navferty.Common/Feedback/frmFeedbackUI.cs new file mode 100644 index 0000000..b1b4ff1 --- /dev/null +++ b/Navferty.Common/Feedback/frmFeedbackUI.cs @@ -0,0 +1,40 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Data; +using System.Drawing; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Windows.Forms; + +using Navferty.Common.Controls; + +using NLog; + +namespace Navferty.Common.Feedback +{ + internal partial class frmFeedbackUI : FormEx + { + private readonly ILogger logger = LogManager.GetCurrentClassLogger(); + + public frmFeedbackUI() + { + InitializeComponent(); + } + + private void button1_Click(object sender, EventArgs e) + { + try + { + if (FeedbackManager.SendFeedEMail("Test message", true)) + this.DialogResult = DialogResult.OK; + } + catch (Exception ex) + { + logger.Error(ex, "Failed to send feedback email!"); + MessageBox.Show(ex.Message, "Failed to send feedback email!", MessageBoxButtons.OK, MessageBoxIcon.Error); + } + } + } +} diff --git a/Navferty.Common/Feedback/frmFeedbackUI.resx b/Navferty.Common/Feedback/frmFeedbackUI.resx new file mode 100644 index 0000000..29dcb1b --- /dev/null +++ b/Navferty.Common/Feedback/frmFeedbackUI.resx @@ -0,0 +1,120 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/Navferty.Common/Navferty.Common.csproj b/Navferty.Common/Navferty.Common.csproj index 5f99f1b..226c926 100644 --- a/Navferty.Common/Navferty.Common.csproj +++ b/Navferty.Common/Navferty.Common.csproj @@ -56,19 +56,42 @@ + + Form + + + frmFeedbackUI.cs + + + + ..\packages\NLog.4.6.7\lib\net45\NLog.dll + + + + + + + + + + + + + + frmFeedbackUI.cs + - diff --git a/Navferty.Common/packages.config b/Navferty.Common/packages.config new file mode 100644 index 0000000..754300b --- /dev/null +++ b/Navferty.Common/packages.config @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/Navferty.ExcelAddIn.Web/CurrencyExchangeRates/Manager.cs b/Navferty.ExcelAddIn.Web/CurrencyExchangeRates/Manager.cs index c390acd..08dc622 100644 --- a/Navferty.ExcelAddIn.Web/CurrencyExchangeRates/Manager.cs +++ b/Navferty.ExcelAddIn.Web/CurrencyExchangeRates/Manager.cs @@ -9,9 +9,12 @@ namespace Navferty.ExcelAddIn.Web.CurrencyExchangeRates { public static class Manager { - public static ExchangeRateRecord? SelectExchageRate(IDialogService dialogService) { + + Navferty.Common.Feedback.FeedbackManager.ShowFeedbackUI(); + + using (var f = new frmExchangeRates(dialogService)) { if (f.ShowDialog() != DialogResult.OK) return null; diff --git a/NavfertyExcelAddIn/app.config b/NavfertyExcelAddIn/app.config index 7fbc27b..7295457 100644 --- a/NavfertyExcelAddIn/app.config +++ b/NavfertyExcelAddIn/app.config @@ -24,9 +24,7 @@ - + From 19e4e48aba46e2463edc19f1d7316d76b64d0834 Mon Sep 17 00:00:00 2001 From: uom Date: Mon, 7 Feb 2022 05:21:27 +0700 Subject: [PATCH 04/20] attach log file to message --- Navferty.Common/Feedback/FeedbackManager.cs | 25 +++++-- Navferty.Common/LogManagement.cs | 73 +++++++++++++++++++++ Navferty.Common/Navferty.Common.csproj | 1 + Navferty.Common/WinAPI/WinAPI.cs | 1 + 4 files changed, 93 insertions(+), 7 deletions(-) create mode 100644 Navferty.Common/LogManagement.cs diff --git a/Navferty.Common/Feedback/FeedbackManager.cs b/Navferty.Common/Feedback/FeedbackManager.cs index 81d57b5..28025c5 100644 --- a/Navferty.Common/Feedback/FeedbackManager.cs +++ b/Navferty.Common/Feedback/FeedbackManager.cs @@ -28,8 +28,7 @@ private static FileInfo[] GetScreenshotsAsFiles(ImageFormat fmt, string fileExt using (Graphics g = Graphics.FromImage(bmCapt)) g.CopyFromScreen(rcCapt.Left, rcCapt.Top, 0, 0, rcCapt.Size); - var sBitmapFile = System.IO.Path.Combine( - System.IO.Path.GetTempPath(), (Guid.NewGuid().ToString() + '.'.ToString() + fileExt)); + var sBitmapFile = Path.Combine(Path.GetTempPath(), (Guid.NewGuid().ToString() + '.'.ToString() + fileExt)); bmCapt.Save(sBitmapFile, fmt); return new System.IO.FileInfo(sBitmapFile); } @@ -45,7 +44,19 @@ internal static bool SendFeedEMail( bool sendScreenshots = true ) { + List lFilesToAttach = new(); + logger.Value.Debug("Start SendFeedEMail"); + var logFileName = LogManagement.GetTargetFilename(null); + var fiLogOld = new FileInfo(logFileName); + if (fiLogOld.Exists) + { + logger.Value.Debug($"Attaching Log File: '{fiLogOld.FullName}'"); + var sNewLogFile = Path.Combine(Path.GetTempPath(), (Guid.NewGuid().ToString() + "_" + fiLogOld.Name)); + var fiLogNew = new FileInfo(sNewLogFile); + fiLogOld.CopyTo(fiLogNew.FullName); + if (fiLogNew.Exists) lFilesToAttach.Add(fiLogNew); + } //TODO: !!! Insert developer email instead of this !!! string developerMail = (new Func(() => @@ -65,9 +76,9 @@ internal static bool SendFeedEMail( if (messageBody.Length > MAX_MESSAGE_BODY_LENGH) messageBody = new string(messageBody.Take(MAX_MESSAGE_BODY_LENGH).ToArray()); logger.Value.Debug($"messageBody:\n'{messageBody}'"); - List lScreenshotFiles = new(); - if (sendScreenshots) lScreenshotFiles = GetScreenshotsAsFiles(ImageFormat.Jpeg).ToList();//Create screenshots to temp dir - logger.Value.Debug($"screensots: '{lScreenshotFiles.Count}'"); + if (sendScreenshots) lFilesToAttach = GetScreenshotsAsFiles(ImageFormat.Jpeg).ToList();//Create screenshots to temp dir + logger.Value.Debug($"FilesToAttach: '{lFilesToAttach.Count}'"); + try { @@ -77,7 +88,7 @@ internal static bool SendFeedEMail( MAIL_SUBJECT, messageBody, WinAPI.MAPI.UIFlags.SendMailDirectNoUI, - lScreenshotFiles.Select(fi => fi.FullName).ToArray() + lFilesToAttach.Select(fi => fi.FullName).ToArray() ); logger.Value.Debug($"Send result: {bSend}"); @@ -86,7 +97,7 @@ internal static bool SendFeedEMail( finally { //Cleanup Temp files - lScreenshotFiles.ForEach(fi => + lFilesToAttach.ForEach(fi => { try { fi.Delete(); } catch { } diff --git a/Navferty.Common/LogManagement.cs b/Navferty.Common/LogManagement.cs new file mode 100644 index 0000000..45df900 --- /dev/null +++ b/Navferty.Common/LogManagement.cs @@ -0,0 +1,73 @@ + +using System.Linq; + +using NLog; +using NLog.Layouts; +using NLog.Targets; + +#nullable enable + +namespace Navferty.Common +{ + internal static class LogManagement + { + //private const string DefaultTargetName = "AllTargets"; + + public static string? GetTargetFilename(string? targetName) + { + FileTarget? target = null; + if (string.IsNullOrWhiteSpace(targetName)) + { + var fileTargets = GetFileTargets(); + target = fileTargets.FirstOrDefault(); + } + else + { + target = GetTarget(targetName!); + } + if (null == target) return null; + + var layout = target.FileName as SimpleLayout; + if (null == layout) return null; + + // layout.Text provides the filename "template" + // LogEventInfo is required; might make sense for a log line template but not really filename + //var filename = layout.Render(new LogEventInfo()).Replace(@"/", @""); + var filename = layout.Render(new LogEventInfo()).Replace(@"/", @"\").Replace(@"\\", @"\"); ; + return filename; + } + + private static T? GetTarget(string targetName) + where T : Target + { + if (null == LogManager.Configuration) return null; + var target = LogManager.Configuration.FindTargetByName(targetName) as T; + return target; + } + + private static T[]? GetTargets() + where T : Target + { + if (null == LogManager.Configuration) return null; + + var targets = LogManager.Configuration.AllTargets?.Where(trg => trg.GetType() == typeof(T)).ToArray(); + return (T[]?)targets; + } + private static FileTarget[]? GetFileTargets() + { + if (null == LogManager.Configuration) return null; + + var targets = LogManager.Configuration.AllTargets? + .Select(trg => + { + FileTarget? ft = null; + if (trg is FileTarget ft2) ft = ft2; + return ft; + }) + .Where(ft => ft != null) + .Select(ft => (FileTarget)ft!) + .ToArray(); + return targets; + } + } +} diff --git a/Navferty.Common/Navferty.Common.csproj b/Navferty.Common/Navferty.Common.csproj index 226c926..f71e110 100644 --- a/Navferty.Common/Navferty.Common.csproj +++ b/Navferty.Common/Navferty.Common.csproj @@ -50,6 +50,7 @@ Form + diff --git a/Navferty.Common/WinAPI/WinAPI.cs b/Navferty.Common/WinAPI/WinAPI.cs index 7df7707..7e966ec 100644 --- a/Navferty.Common/WinAPI/WinAPI.cs +++ b/Navferty.Common/WinAPI/WinAPI.cs @@ -268,6 +268,7 @@ params string[] attachFiles { case MAPI_ERRORS.OK: return true; case MAPI_ERRORS.UserAbort: return false; + case MAPI_ERRORS.NotSupported: return false;//If send with no UI, and user denied send, this occurs. default: throw new MAPIException(Err); } } From 0779fe0d13aceca0db09848ef67187f6884ac76d Mon Sep 17 00:00:00 2001 From: uom Date: Mon, 7 Feb 2022 14:58:20 +0700 Subject: [PATCH 05/20] Feedback UI --- Navferty.Common/Feedback/FeedbackManager.cs | 98 ++++++++---- .../Feedback/frmFeedbackUI.Designer.cs | 118 +++++++++++++-- Navferty.Common/Feedback/frmFeedbackUI.cs | 26 +++- .../Localization/UIStrings.Designer.cs | 126 ++++++++++++++++ Navferty.Common/Localization/UIStrings.resx | 141 ++++++++++++++++++ .../Localization/UIStrings.ru-RU.resx | 141 ++++++++++++++++++ Navferty.Common/Navferty.Common.csproj | 11 ++ Navferty.Common/WinAPI/WinAPI.cs | 8 +- .../CurrencyExchangeRates/Manager.cs | 4 - .../Navferty.ExcelAddIn.Web.csproj | 4 +- .../Feedback/FeedbackBuilder.cs | 22 +++ NavfertyExcelAddIn/Feedback/IFeedback.cs | 7 + NavfertyExcelAddIn/NavfertyExcelAddIn.csproj | 4 +- 13 files changed, 659 insertions(+), 51 deletions(-) create mode 100644 Navferty.Common/Localization/UIStrings.Designer.cs create mode 100644 Navferty.Common/Localization/UIStrings.resx create mode 100644 Navferty.Common/Localization/UIStrings.ru-RU.resx create mode 100644 NavfertyExcelAddIn/Feedback/FeedbackBuilder.cs create mode 100644 NavfertyExcelAddIn/Feedback/IFeedback.cs diff --git a/Navferty.Common/Feedback/FeedbackManager.cs b/Navferty.Common/Feedback/FeedbackManager.cs index 28025c5..7dbb05f 100644 --- a/Navferty.Common/Feedback/FeedbackManager.cs +++ b/Navferty.Common/Feedback/FeedbackManager.cs @@ -7,6 +7,7 @@ using System.Linq; using System.Reflection; using System.Text; +using System.Threading; using System.Windows.Forms; using Microsoft.Win32; @@ -19,6 +20,9 @@ namespace Navferty.Common.Feedback { public static class FeedbackManager { + private const string MAIL_SUBJECT = @"NavfertyExcelAddin Bug report from user!"; + internal const int MAX_USER_TEXT_LENGH = 1_000; + private static FileInfo[] GetScreenshotsAsFiles(ImageFormat fmt, string fileExt = "jpg") => System.Windows.Forms.Screen.AllScreens.ToList().Select(scr => { @@ -34,52 +38,95 @@ private static FileInfo[] GetScreenshotsAsFiles(ImageFormat fmt, string fileExt } }).ToArray(); - private const string MAIL_SUBJECT = @"NavfertyExcelAddin Bug report from user!"; - private const int MAX_MESSAGE_BODY_LENGH = 1024 * 3; - private static readonly Lazy logger = new(() => LogManager.GetCurrentClassLogger()); internal static bool SendFeedEMail( string userText, - bool sendScreenshots = true + bool sendScreenshots = true, + Form? parentWindow = null ) { + + var logger = LogManager.GetCurrentClassLogger(); + logger.Debug("Start SendFeedEMail Task..."); + List lFilesToAttach = new(); - logger.Value.Debug("Start SendFeedEMail"); - var logFileName = LogManagement.GetTargetFilename(null); - var fiLogOld = new FileInfo(logFileName); - if (fiLogOld.Exists) - { - logger.Value.Debug($"Attaching Log File: '{fiLogOld.FullName}'"); - var sNewLogFile = Path.Combine(Path.GetTempPath(), (Guid.NewGuid().ToString() + "_" + fiLogOld.Name)); - var fiLogNew = new FileInfo(sNewLogFile); - fiLogOld.CopyTo(fiLogNew.FullName); - if (fiLogNew.Exists) lFilesToAttach.Add(fiLogNew); - } + if (userText.Length > MAX_USER_TEXT_LENGH) userText = new string(userText.Take(MAX_USER_TEXT_LENGH).ToArray()); //TODO: !!! Insert developer email instead of this !!! string developerMail = (new Func(() => { using (var hKey = Registry.CurrentUser.OpenSubKey(@"Software\Microsoft\Office\16.0\Outlook\Profiles\Outlook\9375CFF0413111d3B88A00104B2A6676\00000005")) return hKey.GetValue("Email").ToString(); - })).Invoke(); + })).Invoke(); logger.Debug($"developerMail: '{developerMail}'"); - logger.Value.Debug($"developerMail: '{developerMail}'"); + string sysInfo = GetSystemInfo().Trim(); + logger.Debug($"System Info Dump:\n{sysInfo}\n\n********\nUser message: '{userText}'\n"); StringBuilder sbMessageBody = new(); - sbMessageBody.AppendLine(GetSystemInfo().Trim()); - sbMessageBody.AppendLine("*** User message:"); + sbMessageBody.Append("User message: "); sbMessageBody.AppendLine((string.IsNullOrWhiteSpace(userText) ? "[NONE]" : ('"' + userText + '"'))); - string messageBody = sbMessageBody.ToString(); - if (messageBody.Length > MAX_MESSAGE_BODY_LENGH) messageBody = new string(messageBody.Take(MAX_MESSAGE_BODY_LENGH).ToArray()); - logger.Value.Debug($"messageBody:\n'{messageBody}'"); - if (sendScreenshots) lFilesToAttach = GetScreenshotsAsFiles(ImageFormat.Jpeg).ToList();//Create screenshots to temp dir - logger.Value.Debug($"FilesToAttach: '{lFilesToAttach.Count}'"); + if (sendScreenshots) + { + if (parentWindow != null) + { + //Temporary hide feedback UI to make clear screenshots + parentWindow.Opacity = 0; + parentWindow.Refresh(); + Application.DoEvents(); + } + try + { + //Create screenshots to temp dir + var screenshotFiles = GetScreenshotsAsFiles(ImageFormat.Jpeg); + lFilesToAttach.AddRange(screenshotFiles); + string screenshotFileNames = string.Join(", ", screenshotFiles.Select(fi => fi.FullName)); + logger.Debug($"Screenshot Files ({lFilesToAttach.Count}): '{screenshotFileNames}'"); + } + finally + { + if (parentWindow != null) + { + //Restore feedback UI + parentWindow.Opacity = 1; + parentWindow.Refresh(); + Application.DoEvents(); + } + } + } + LogManager.Flush(); //Write NLog cache to disk + var logFileName = LogManagement.GetTargetFilename(null); + if (logFileName != null) + { + FileInfo fiLogFromNLogEngine = new(logFileName); + logger.Debug($"Log File Found: '{fiLogFromNLogEngine.FullName}', Exist: {fiLogFromNLogEngine.Exists}"); + if (fiLogFromNLogEngine.Exists) + { + FileInfo fiLogFileInTempDir = new(Path.Combine( + Path.GetTempPath(), + (Guid.NewGuid().ToString() + "_" + fiLogFromNLogEngine.Name))); + { + //Write NLog cache to disk + { + //logger.Factory.Flush(); + LogManager.Flush(); + Thread.Sleep(1000); //Waiting NLog flush task to finish + } + + //Copy NLog file to temp file + fiLogFromNLogEngine.CopyTo(fiLogFileInTempDir.FullName); + + //Attach temp NLog file to email + if (fiLogFileInTempDir.Exists) lFilesToAttach.Add(fiLogFileInTempDir); + } + } + } + logger.Debug($"Total Files To Attach: '{lFilesToAttach.Count}'"); try { //Send Screenshots @@ -88,10 +135,11 @@ internal static bool SendFeedEMail( MAIL_SUBJECT, messageBody, WinAPI.MAPI.UIFlags.SendMailDirectNoUI, + parentWindow, lFilesToAttach.Select(fi => fi.FullName).ToArray() ); - logger.Value.Debug($"Send result: {bSend}"); + logger.Debug($"Send result: {bSend}"); return bSend; } finally diff --git a/Navferty.Common/Feedback/frmFeedbackUI.Designer.cs b/Navferty.Common/Feedback/frmFeedbackUI.Designer.cs index c49b307..51ce1ad 100644 --- a/Navferty.Common/Feedback/frmFeedbackUI.Designer.cs +++ b/Navferty.Common/Feedback/frmFeedbackUI.Designer.cs @@ -28,38 +28,132 @@ protected override void Dispose(bool disposing) /// private void InitializeComponent() { - this.button1 = new System.Windows.Forms.Button(); + this.btnSend = new System.Windows.Forms.Button(); + this.lblMessage = new System.Windows.Forms.Label(); + this.chkIncludeScreenshots = new System.Windows.Forms.CheckBox(); + this.tableLayoutPanel1 = new System.Windows.Forms.TableLayoutPanel(); + this.txtUserMessage = new System.Windows.Forms.TextBox(); + this.lblSummary = new System.Windows.Forms.Label(); + this.llGotoGithub = new System.Windows.Forms.LinkLabel(); + this.tableLayoutPanel1.SuspendLayout(); this.SuspendLayout(); // - // button1 + // btnSend // - this.button1.Location = new System.Drawing.Point(206, 121); - this.button1.Name = "button1"; - this.button1.Size = new System.Drawing.Size(75, 23); - this.button1.TabIndex = 0; - this.button1.Text = "Send"; - this.button1.UseVisualStyleBackColor = true; - this.button1.Click += new System.EventHandler(this.button1_Click); + this.btnSend.Dock = System.Windows.Forms.DockStyle.Right; + this.btnSend.Location = new System.Drawing.Point(357, 225); + this.btnSend.Name = "btnSend"; + this.btnSend.Size = new System.Drawing.Size(113, 34); + this.btnSend.TabIndex = 0; + this.btnSend.Text = "Send"; + this.btnSend.UseVisualStyleBackColor = true; + this.btnSend.Click += new System.EventHandler(this.OnSend); + // + // lblMessage + // + this.lblMessage.AutoSize = true; + this.tableLayoutPanel1.SetColumnSpan(this.lblMessage, 2); + this.lblMessage.Dock = System.Windows.Forms.DockStyle.Top; + this.lblMessage.Location = new System.Drawing.Point(3, 0); + this.lblMessage.Name = "lblMessage"; + this.lblMessage.Size = new System.Drawing.Size(467, 13); + this.lblMessage.TabIndex = 1; + this.lblMessage.Text = "message"; + // + // chkIncludeScreenshots + // + this.chkIncludeScreenshots.AutoSize = true; + this.chkIncludeScreenshots.Location = new System.Drawing.Point(3, 189); + this.chkIncludeScreenshots.Name = "chkIncludeScreenshots"; + this.chkIncludeScreenshots.Size = new System.Drawing.Size(78, 17); + this.chkIncludeScreenshots.TabIndex = 2; + this.chkIncludeScreenshots.Text = "includeLog"; + this.chkIncludeScreenshots.UseVisualStyleBackColor = true; + // + // tableLayoutPanel1 + // + this.tableLayoutPanel1.ColumnCount = 2; + this.tableLayoutPanel1.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 100F)); + this.tableLayoutPanel1.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle()); + this.tableLayoutPanel1.Controls.Add(this.btnSend, 1, 4); + this.tableLayoutPanel1.Controls.Add(this.lblMessage, 0, 0); + this.tableLayoutPanel1.Controls.Add(this.txtUserMessage, 0, 1); + this.tableLayoutPanel1.Controls.Add(this.chkIncludeScreenshots, 0, 2); + this.tableLayoutPanel1.Controls.Add(this.lblSummary, 0, 3); + this.tableLayoutPanel1.Controls.Add(this.llGotoGithub, 0, 4); + this.tableLayoutPanel1.Dock = System.Windows.Forms.DockStyle.Fill; + this.tableLayoutPanel1.Location = new System.Drawing.Point(8, 8); + this.tableLayoutPanel1.Name = "tableLayoutPanel1"; + this.tableLayoutPanel1.RowCount = 5; + this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle()); + this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100F)); + this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle()); + this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle()); + this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 40F)); + this.tableLayoutPanel1.Size = new System.Drawing.Size(473, 262); + this.tableLayoutPanel1.TabIndex = 3; + // + // txtUserMessage + // + this.tableLayoutPanel1.SetColumnSpan(this.txtUserMessage, 2); + this.txtUserMessage.Dock = System.Windows.Forms.DockStyle.Fill; + this.txtUserMessage.HideSelection = false; + this.txtUserMessage.Location = new System.Drawing.Point(3, 16); + this.txtUserMessage.MaxLength = 1000; + this.txtUserMessage.Multiline = true; + this.txtUserMessage.Name = "txtUserMessage"; + this.txtUserMessage.ScrollBars = System.Windows.Forms.ScrollBars.Both; + this.txtUserMessage.Size = new System.Drawing.Size(467, 167); + this.txtUserMessage.TabIndex = 3; + // + // lblSummary + // + this.lblSummary.AutoSize = true; + this.lblSummary.Location = new System.Drawing.Point(3, 209); + this.lblSummary.Name = "lblSummary"; + this.lblSummary.Size = new System.Drawing.Size(48, 13); + this.lblSummary.TabIndex = 4; + this.lblSummary.Text = "summary"; + // + // llGotoGithub + // + this.llGotoGithub.AutoSize = true; + this.llGotoGithub.Dock = System.Windows.Forms.DockStyle.Bottom; + this.llGotoGithub.Location = new System.Drawing.Point(3, 249); + this.llGotoGithub.Name = "llGotoGithub"; + this.llGotoGithub.Size = new System.Drawing.Size(348, 13); + this.llGotoGithub.TabIndex = 5; + this.llGotoGithub.TabStop = true; + this.llGotoGithub.Text = "goto github"; // // frmFeedbackUI // this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; - this.ClientSize = new System.Drawing.Size(339, 196); - this.Controls.Add(this.button1); + this.ClientSize = new System.Drawing.Size(489, 278); + this.Controls.Add(this.tableLayoutPanel1); this.MaximizeBox = false; this.MinimizeBox = false; this.Name = "frmFeedbackUI"; + this.Padding = new System.Windows.Forms.Padding(8); this.ShowIcon = false; this.ShowInTaskbar = false; this.StartPosition = System.Windows.Forms.FormStartPosition.CenterParent; this.Text = "frmFeedbackUI"; + this.tableLayoutPanel1.ResumeLayout(false); + this.tableLayoutPanel1.PerformLayout(); this.ResumeLayout(false); } #endregion - private System.Windows.Forms.Button button1; + private System.Windows.Forms.Button btnSend; + private System.Windows.Forms.Label lblMessage; + private System.Windows.Forms.CheckBox chkIncludeScreenshots; + private System.Windows.Forms.TableLayoutPanel tableLayoutPanel1; + private System.Windows.Forms.TextBox txtUserMessage; + private System.Windows.Forms.Label lblSummary; + private System.Windows.Forms.LinkLabel llGotoGithub; } } \ No newline at end of file diff --git a/Navferty.Common/Feedback/frmFeedbackUI.cs b/Navferty.Common/Feedback/frmFeedbackUI.cs index b1b4ff1..dc64a3b 100644 --- a/Navferty.Common/Feedback/frmFeedbackUI.cs +++ b/Navferty.Common/Feedback/frmFeedbackUI.cs @@ -21,19 +21,37 @@ internal partial class frmFeedbackUI : FormEx public frmFeedbackUI() { InitializeComponent(); + + Text = Localization.UIStrings.Feedback_Title; + lblMessage.Text = String.Format(Localization.UIStrings.Feedback_Message, FeedbackManager.MAX_USER_TEXT_LENGH); + txtUserMessage.MaxLength = FeedbackManager.MAX_USER_TEXT_LENGH; + lblSummary.Text = Localization.UIStrings.Feedback_Summary; + + chkIncludeScreenshots.Text = Localization.UIStrings.Feedback_IncludeScreenshots; + chkIncludeScreenshots.Checked = true; + + llGotoGithub.Text = Localization.UIStrings.Feedback_GotoGithub; + btnSend.Text = Localization.UIStrings.Feedback_Send; } - private void button1_Click(object sender, EventArgs e) + private void OnSend(object sender, EventArgs e) { try { - if (FeedbackManager.SendFeedEMail("Test message", true)) - this.DialogResult = DialogResult.OK; + if (FeedbackManager.SendFeedEMail( + txtUserMessage.Text.Trim(), + chkIncludeScreenshots.Checked, + this)) + + DialogResult = DialogResult.OK; } catch (Exception ex) { logger.Error(ex, "Failed to send feedback email!"); - MessageBox.Show(ex.Message, "Failed to send feedback email!", MessageBoxButtons.OK, MessageBoxIcon.Error); + MessageBox.Show(ex.Message, + Localization.UIStrings.Feedback_ErrorTitle, + MessageBoxButtons.OK, + MessageBoxIcon.Error); } } } diff --git a/Navferty.Common/Localization/UIStrings.Designer.cs b/Navferty.Common/Localization/UIStrings.Designer.cs new file mode 100644 index 0000000..c1ae453 --- /dev/null +++ b/Navferty.Common/Localization/UIStrings.Designer.cs @@ -0,0 +1,126 @@ +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Runtime Version:4.0.30319.42000 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace Navferty.Common.Localization { + using System; + + + /// + /// A strongly-typed resource class, for looking up localized strings, etc. + /// + // This class was auto-generated by the StronglyTypedResourceBuilder + // 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.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + internal class UIStrings { + + private static global::System.Resources.ResourceManager resourceMan; + + private static global::System.Globalization.CultureInfo resourceCulture; + + [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + internal UIStrings() { + } + + /// + /// Returns the cached ResourceManager instance used by this class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Resources.ResourceManager ResourceManager { + get { + if (object.ReferenceEquals(resourceMan, null)) { + global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Navferty.Common.Localization.UIStrings", typeof(UIStrings).Assembly); + resourceMan = temp; + } + return resourceMan; + } + } + + /// + /// Overrides the current thread's CurrentUICulture property for all + /// resource lookups using this strongly typed resource class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Globalization.CultureInfo Culture { + get { + return resourceCulture; + } + set { + resourceCulture = value; + } + } + + /// + /// Looks up a localized string similar to Failed to send feedback email!. + /// + internal static string Feedback_ErrorTitle { + get { + return ResourceManager.GetString("Feedback_ErrorTitle", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Bug tracker and feature request. + /// + internal static string Feedback_GotoGithub { + get { + return ResourceManager.GetString("Feedback_GotoGithub", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Include screenshots. + /// + internal static string Feedback_IncludeScreenshots { + get { + return ResourceManager.GetString("Feedback_IncludeScreenshots", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Briefly describe the error that occurs (no more than {0} characters):. + /// + internal static string Feedback_Message { + get { + return ResourceManager.GetString("Feedback_Message", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Send. + /// + internal static string Feedback_Send { + get { + return ResourceManager.GetString("Feedback_Send", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to The error log will be included in the report.. + /// + internal static string Feedback_Summary { + get { + return ResourceManager.GetString("Feedback_Summary", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Feedback. + /// + internal static string Feedback_Title { + get { + return ResourceManager.GetString("Feedback_Title", resourceCulture); + } + } + } +} diff --git a/Navferty.Common/Localization/UIStrings.resx b/Navferty.Common/Localization/UIStrings.resx new file mode 100644 index 0000000..ee58a2d --- /dev/null +++ b/Navferty.Common/Localization/UIStrings.resx @@ -0,0 +1,141 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + Failed to send feedback email! + + + Bug tracker and feature request + + + Include screenshots + + + Briefly describe the error that occurs (no more than {0} characters): + + + Send + + + The error log will be included in the report. + + + Feedback + + \ No newline at end of file diff --git a/Navferty.Common/Localization/UIStrings.ru-RU.resx b/Navferty.Common/Localization/UIStrings.ru-RU.resx new file mode 100644 index 0000000..88e2883 --- /dev/null +++ b/Navferty.Common/Localization/UIStrings.ru-RU.resx @@ -0,0 +1,141 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + Не удалось отправить отчёт разработчику! + + + Трекер ошибок и запроса новых функций + + + Включить в отчёт скриншоты + + + Кратко опишите возникающую ошибку (не более {0} символов): + + + Отправить + + + В отчёт будет включён журнал ошибок. + + + Обратная связь + + \ No newline at end of file diff --git a/Navferty.Common/Navferty.Common.csproj b/Navferty.Common/Navferty.Common.csproj index f71e110..270f640 100644 --- a/Navferty.Common/Navferty.Common.csproj +++ b/Navferty.Common/Navferty.Common.csproj @@ -50,6 +50,11 @@ Form + + UIStrings.resx + True + True + @@ -92,6 +97,12 @@ frmFeedbackUI.cs + + ResXFileCodeGenerator + UIStrings.Designer.cs + Designer + + diff --git a/Navferty.Common/WinAPI/WinAPI.cs b/Navferty.Common/WinAPI/WinAPI.cs index 7e966ec..635a680 100644 --- a/Navferty.Common/WinAPI/WinAPI.cs +++ b/Navferty.Common/WinAPI/WinAPI.cs @@ -242,6 +242,7 @@ public static bool SendMail( string strSubject, string strBody, UIFlags UIflags = UIFlags.PopupUI, + IWin32Window? parentWindow = null, params string[] attachFiles ) { @@ -257,9 +258,11 @@ params string[] attachFiles MAPI_FLAGS how = (UIflags == UIFlags.PopupUI) ? (MAPI_FLAGS.MAPI_LOGON_UI | MAPI_FLAGS.MAPI_DIALOG) : (MAPI_FLAGS.MAPI_LOGON_UI); how |= MAPI_FLAGS.MAPI_NEW_SESSION; + IntPtr hWnd = (parentWindow == null) ? IntPtr.Zero : parentWindow.Handle; + var Err = MAPISendMail( new IntPtr(0), - new IntPtr(0), + hWnd, msg, how, 0); @@ -279,10 +282,11 @@ public static bool SendMail( string strSubject, string strBody, UIFlags uiFlags = UIFlags.PopupUI, + IWin32Window? parentWindow = null, params string[] attachFiles) => SendMail( new MapiRecipDesc[] { CreateRecipient(sendTo, SendToFlags.MAPI_TO) }, - strSubject, strBody, uiFlags, attachFiles); + strSubject, strBody, uiFlags, parentWindow, attachFiles); public static MapiRecipDesc CreateRecipient(string email, SendToFlags howTo = SendToFlags.MAPI_TO) diff --git a/Navferty.ExcelAddIn.Web/CurrencyExchangeRates/Manager.cs b/Navferty.ExcelAddIn.Web/CurrencyExchangeRates/Manager.cs index 08dc622..cb4fe05 100644 --- a/Navferty.ExcelAddIn.Web/CurrencyExchangeRates/Manager.cs +++ b/Navferty.ExcelAddIn.Web/CurrencyExchangeRates/Manager.cs @@ -11,10 +11,6 @@ public static class Manager { public static ExchangeRateRecord? SelectExchageRate(IDialogService dialogService) { - - Navferty.Common.Feedback.FeedbackManager.ShowFeedbackUI(); - - using (var f = new frmExchangeRates(dialogService)) { if (f.ShowDialog() != DialogResult.OK) return null; diff --git a/Navferty.ExcelAddIn.Web/Navferty.ExcelAddIn.Web.csproj b/Navferty.ExcelAddIn.Web/Navferty.ExcelAddIn.Web.csproj index 053409f..8e47a96 100644 --- a/Navferty.ExcelAddIn.Web/Navferty.ExcelAddIn.Web.csproj +++ b/Navferty.ExcelAddIn.Web/Navferty.ExcelAddIn.Web.csproj @@ -138,9 +138,7 @@ - - - + diff --git a/NavfertyExcelAddIn/Feedback/FeedbackBuilder.cs b/NavfertyExcelAddIn/Feedback/FeedbackBuilder.cs new file mode 100644 index 0000000..6852555 --- /dev/null +++ b/NavfertyExcelAddIn/Feedback/FeedbackBuilder.cs @@ -0,0 +1,22 @@ + +using Navferty.Common; + +#nullable enable + +namespace NavfertyExcelAddIn.Feedback +{ + public class FeedbackBuilder : IFeedback + { + internal readonly IDialogService dialogService; + private Microsoft.Office.Interop.Excel.Application App => Globals.ThisAddIn.Application; + + public FeedbackBuilder(IDialogService dialogService) + => this.dialogService = dialogService; + + + public void DisplayFeedbackUI() + { + Navferty.Common.Feedback.FeedbackManager.ShowFeedbackUI(); + } + } +} diff --git a/NavfertyExcelAddIn/Feedback/IFeedback.cs b/NavfertyExcelAddIn/Feedback/IFeedback.cs new file mode 100644 index 0000000..72052bc --- /dev/null +++ b/NavfertyExcelAddIn/Feedback/IFeedback.cs @@ -0,0 +1,7 @@ +namespace NavfertyExcelAddIn.Feedback +{ + public interface IFeedback + { + void DisplayFeedbackUI(); + } +} diff --git a/NavfertyExcelAddIn/NavfertyExcelAddIn.csproj b/NavfertyExcelAddIn/NavfertyExcelAddIn.csproj index be280f2..560852f 100644 --- a/NavfertyExcelAddIn/NavfertyExcelAddIn.csproj +++ b/NavfertyExcelAddIn/NavfertyExcelAddIn.csproj @@ -266,8 +266,10 @@ - + + + From 636f9e2d1c645d4ecbac6e40f20942d76c6a4ceb Mon Sep 17 00:00:00 2001 From: uom Date: Mon, 7 Feb 2022 15:18:24 +0700 Subject: [PATCH 06/20] Feedback added to ribbon --- Navferty.Common/Feedback/FeedbackManager.cs | 33 ++++++++++++----- .../Feedback/frmFeedbackUI.Designer.cs | 36 ++++++++++--------- Navferty.Common/Feedback/frmFeedbackUI.cs | 17 +++++++++ .../Localization/UIStrings.Designer.cs | 11 +++++- Navferty.Common/Localization/UIStrings.resx | 5 ++- .../Localization/UIStrings.ru-RU.resx | 5 ++- .../Localization/RibbonLabels.Designer.cs | 9 +++++ .../Localization/RibbonLabels.resx | 3 ++ .../Localization/RibbonLabels.ru-RU.resx | 3 ++ .../Localization/RibbonSupertips.Designer.cs | 9 +++++ .../Localization/RibbonSupertips.resx | 3 ++ .../Localization/RibbonSupertips.ru-RU.resx | 3 ++ NavfertyExcelAddIn/NavfertyRibbon.cs | 7 ++++ NavfertyExcelAddIn/NavfertyRibbon.xml | 9 ++++- NavfertyExcelAddIn/Registry.cs | 5 +++ 15 files changed, 129 insertions(+), 29 deletions(-) diff --git a/Navferty.Common/Feedback/FeedbackManager.cs b/Navferty.Common/Feedback/FeedbackManager.cs index 7dbb05f..e1ed806 100644 --- a/Navferty.Common/Feedback/FeedbackManager.cs +++ b/Navferty.Common/Feedback/FeedbackManager.cs @@ -20,6 +20,8 @@ namespace Navferty.Common.Feedback { public static class FeedbackManager { + private const string GITHUB_BUGTRACKER_URL = @"https://github.com/navferty/NavfertyExcelAddIn/issues"; + private const string DEVELOPER_MAIL = @"navferty@ymail.com"; private const string MAIL_SUBJECT = @"NavfertyExcelAddin Bug report from user!"; internal const int MAX_USER_TEXT_LENGH = 1_000; @@ -38,7 +40,20 @@ private static FileInfo[] GetScreenshotsAsFiles(ImageFormat fmt, string fileExt } }).ToArray(); - + /// This used for debug! + //If you want to send error reports to custom email, + //create new string value 'Navferty_ExcelAddIn_Feedback_Email' in root of 'HKEY_CURRENT_USER' and set you mail + /// + internal static string GetDeveloperMail() + { + try + { + string mail = Registry.CurrentUser.GetValue("Navferty_ExcelAddIn_Feedback_Email").ToString().Trim(); + if (string.IsNullOrWhiteSpace(mail)) mail = DEVELOPER_MAIL; + return mail; + } + catch { return DEVELOPER_MAIL; } + } internal static bool SendFeedEMail( string userText, @@ -50,17 +65,12 @@ internal static bool SendFeedEMail( var logger = LogManager.GetCurrentClassLogger(); logger.Debug("Start SendFeedEMail Task..."); - List lFilesToAttach = new(); + string developerMail = GetDeveloperMail(); + logger.Debug($"developerMail: '{developerMail}'"); + List lFilesToAttach = new(); if (userText.Length > MAX_USER_TEXT_LENGH) userText = new string(userText.Take(MAX_USER_TEXT_LENGH).ToArray()); - //TODO: !!! Insert developer email instead of this !!! - string developerMail = (new Func(() => - { - using (var hKey = Registry.CurrentUser.OpenSubKey(@"Software\Microsoft\Office\16.0\Outlook\Profiles\Outlook\9375CFF0413111d3B88A00104B2A6676\00000005")) - return hKey.GetValue("Email").ToString(); - })).Invoke(); logger.Debug($"developerMail: '{developerMail}'"); - string sysInfo = GetSystemInfo().Trim(); logger.Debug($"System Info Dump:\n{sysInfo}\n\n********\nUser message: '{userText}'\n"); @@ -188,5 +198,10 @@ public static void ShowFeedbackUI() using var fui = new frmFeedbackUI(); fui.ShowDialog(); } + + public static void JumpGithub() + { + System.Diagnostics.Process.Start(GITHUB_BUGTRACKER_URL); + } } } diff --git a/Navferty.Common/Feedback/frmFeedbackUI.Designer.cs b/Navferty.Common/Feedback/frmFeedbackUI.Designer.cs index 51ce1ad..a8d1100 100644 --- a/Navferty.Common/Feedback/frmFeedbackUI.Designer.cs +++ b/Navferty.Common/Feedback/frmFeedbackUI.Designer.cs @@ -41,10 +41,10 @@ private void InitializeComponent() // btnSend // this.btnSend.Dock = System.Windows.Forms.DockStyle.Right; - this.btnSend.Location = new System.Drawing.Point(357, 225); + this.btnSend.Location = new System.Drawing.Point(432, 235); this.btnSend.Name = "btnSend"; this.btnSend.Size = new System.Drawing.Size(113, 34); - this.btnSend.TabIndex = 0; + this.btnSend.TabIndex = 1; this.btnSend.Text = "Send"; this.btnSend.UseVisualStyleBackColor = true; this.btnSend.Click += new System.EventHandler(this.OnSend); @@ -56,18 +56,18 @@ private void InitializeComponent() this.lblMessage.Dock = System.Windows.Forms.DockStyle.Top; this.lblMessage.Location = new System.Drawing.Point(3, 0); this.lblMessage.Name = "lblMessage"; - this.lblMessage.Size = new System.Drawing.Size(467, 13); + this.lblMessage.Size = new System.Drawing.Size(542, 13); this.lblMessage.TabIndex = 1; this.lblMessage.Text = "message"; // // chkIncludeScreenshots // this.chkIncludeScreenshots.AutoSize = true; - this.chkIncludeScreenshots.Location = new System.Drawing.Point(3, 189); + this.chkIncludeScreenshots.Location = new System.Drawing.Point(3, 199); this.chkIncludeScreenshots.Name = "chkIncludeScreenshots"; - this.chkIncludeScreenshots.Size = new System.Drawing.Size(78, 17); + this.chkIncludeScreenshots.Size = new System.Drawing.Size(115, 17); this.chkIncludeScreenshots.TabIndex = 2; - this.chkIncludeScreenshots.Text = "includeLog"; + this.chkIncludeScreenshots.Text = "include screenshot"; this.chkIncludeScreenshots.UseVisualStyleBackColor = true; // // tableLayoutPanel1 @@ -90,8 +90,8 @@ private void InitializeComponent() this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle()); this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle()); this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 40F)); - this.tableLayoutPanel1.Size = new System.Drawing.Size(473, 262); - this.tableLayoutPanel1.TabIndex = 3; + this.tableLayoutPanel1.Size = new System.Drawing.Size(548, 272); + this.tableLayoutPanel1.TabIndex = 0; // // txtUserMessage // @@ -103,15 +103,17 @@ private void InitializeComponent() this.txtUserMessage.Multiline = true; this.txtUserMessage.Name = "txtUserMessage"; this.txtUserMessage.ScrollBars = System.Windows.Forms.ScrollBars.Both; - this.txtUserMessage.Size = new System.Drawing.Size(467, 167); - this.txtUserMessage.TabIndex = 3; + this.txtUserMessage.Size = new System.Drawing.Size(542, 177); + this.txtUserMessage.TabIndex = 0; // // lblSummary // this.lblSummary.AutoSize = true; - this.lblSummary.Location = new System.Drawing.Point(3, 209); + this.tableLayoutPanel1.SetColumnSpan(this.lblSummary, 2); + this.lblSummary.Dock = System.Windows.Forms.DockStyle.Top; + this.lblSummary.Location = new System.Drawing.Point(3, 219); this.lblSummary.Name = "lblSummary"; - this.lblSummary.Size = new System.Drawing.Size(48, 13); + this.lblSummary.Size = new System.Drawing.Size(542, 13); this.lblSummary.TabIndex = 4; this.lblSummary.Text = "summary"; // @@ -119,19 +121,21 @@ private void InitializeComponent() // this.llGotoGithub.AutoSize = true; this.llGotoGithub.Dock = System.Windows.Forms.DockStyle.Bottom; - this.llGotoGithub.Location = new System.Drawing.Point(3, 249); + this.llGotoGithub.Location = new System.Drawing.Point(3, 259); this.llGotoGithub.Name = "llGotoGithub"; - this.llGotoGithub.Size = new System.Drawing.Size(348, 13); - this.llGotoGithub.TabIndex = 5; + this.llGotoGithub.Size = new System.Drawing.Size(423, 13); + this.llGotoGithub.TabIndex = 2; this.llGotoGithub.TabStop = true; this.llGotoGithub.Text = "goto github"; + this.llGotoGithub.LinkClicked += new System.Windows.Forms.LinkLabelLinkClickedEventHandler(this.llGotoGithub_LinkClicked); // // frmFeedbackUI // this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; - this.ClientSize = new System.Drawing.Size(489, 278); + this.ClientSize = new System.Drawing.Size(564, 288); this.Controls.Add(this.tableLayoutPanel1); + this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedDialog; this.MaximizeBox = false; this.MinimizeBox = false; this.Name = "frmFeedbackUI"; diff --git a/Navferty.Common/Feedback/frmFeedbackUI.cs b/Navferty.Common/Feedback/frmFeedbackUI.cs index dc64a3b..299353c 100644 --- a/Navferty.Common/Feedback/frmFeedbackUI.cs +++ b/Navferty.Common/Feedback/frmFeedbackUI.cs @@ -54,5 +54,22 @@ private void OnSend(object sender, EventArgs e) MessageBoxIcon.Error); } } + + + private void llGotoGithub_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e) + { + try + { + FeedbackManager.JumpGithub(); + } + catch (Exception ex) + { + logger.Error(ex, "Failed to open Github bugtracker!"); + MessageBox.Show(ex.Message, + Localization.UIStrings.Feedback_Error, + MessageBoxButtons.OK, + MessageBoxIcon.Error); + } + } } } diff --git a/Navferty.Common/Localization/UIStrings.Designer.cs b/Navferty.Common/Localization/UIStrings.Designer.cs index c1ae453..b2c98e0 100644 --- a/Navferty.Common/Localization/UIStrings.Designer.cs +++ b/Navferty.Common/Localization/UIStrings.Designer.cs @@ -60,6 +60,15 @@ internal UIStrings() { } } + /// + /// Looks up a localized string similar to Error!. + /// + internal static string Feedback_Error { + get { + return ResourceManager.GetString("Feedback_Error", resourceCulture); + } + } + /// /// Looks up a localized string similar to Failed to send feedback email!. /// @@ -79,7 +88,7 @@ internal static string Feedback_GotoGithub { } /// - /// Looks up a localized string similar to Include screenshots. + /// Looks up a localized string similar to Include screenshot. /// internal static string Feedback_IncludeScreenshots { get { diff --git a/Navferty.Common/Localization/UIStrings.resx b/Navferty.Common/Localization/UIStrings.resx index ee58a2d..384592c 100644 --- a/Navferty.Common/Localization/UIStrings.resx +++ b/Navferty.Common/Localization/UIStrings.resx @@ -117,6 +117,9 @@ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + Error! + Failed to send feedback email! @@ -124,7 +127,7 @@ Bug tracker and feature request - Include screenshots + Include screenshot Briefly describe the error that occurs (no more than {0} characters): diff --git a/Navferty.Common/Localization/UIStrings.ru-RU.resx b/Navferty.Common/Localization/UIStrings.ru-RU.resx index 88e2883..e9f6165 100644 --- a/Navferty.Common/Localization/UIStrings.ru-RU.resx +++ b/Navferty.Common/Localization/UIStrings.ru-RU.resx @@ -117,6 +117,9 @@ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + Ошибка! + Не удалось отправить отчёт разработчику! @@ -124,7 +127,7 @@ Трекер ошибок и запроса новых функций - Включить в отчёт скриншоты + Приложить скриншот Кратко опишите возникающую ошибку (не более {0} символов): diff --git a/NavfertyExcelAddIn/Localization/RibbonLabels.Designer.cs b/NavfertyExcelAddIn/Localization/RibbonLabels.Designer.cs index c4502fd..df68ccd 100644 --- a/NavfertyExcelAddIn/Localization/RibbonLabels.Designer.cs +++ b/NavfertyExcelAddIn/Localization/RibbonLabels.Designer.cs @@ -123,6 +123,15 @@ internal static string CutNames { } } + /// + /// Looks up a localized string similar to Feedback. + /// + internal static string Feedback { + get { + return ResourceManager.GetString("Feedback", resourceCulture); + } + } + /// /// Looks up a localized string similar to Find Errors. /// diff --git a/NavfertyExcelAddIn/Localization/RibbonLabels.resx b/NavfertyExcelAddIn/Localization/RibbonLabels.resx index 205170b..3728320 100644 --- a/NavfertyExcelAddIn/Localization/RibbonLabels.resx +++ b/NavfertyExcelAddIn/Localization/RibbonLabels.resx @@ -237,4 +237,7 @@ Web tools + + Feedback + \ No newline at end of file diff --git a/NavfertyExcelAddIn/Localization/RibbonLabels.ru-RU.resx b/NavfertyExcelAddIn/Localization/RibbonLabels.ru-RU.resx index 341a4ab..70f0e80 100644 --- a/NavfertyExcelAddIn/Localization/RibbonLabels.ru-RU.resx +++ b/NavfertyExcelAddIn/Localization/RibbonLabels.ru-RU.resx @@ -237,4 +237,7 @@ Защита данных + + Обратная связь + \ No newline at end of file diff --git a/NavfertyExcelAddIn/Localization/RibbonSupertips.Designer.cs b/NavfertyExcelAddIn/Localization/RibbonSupertips.Designer.cs index 50bc47b..74f650f 100644 --- a/NavfertyExcelAddIn/Localization/RibbonSupertips.Designer.cs +++ b/NavfertyExcelAddIn/Localization/RibbonSupertips.Designer.cs @@ -96,6 +96,15 @@ internal static string CutNames { } } + /// + /// Looks up a localized string similar to Send a bug report or feature request to the developer. + /// + internal static string Feedback { + get { + return ResourceManager.GetString("Feedback", resourceCulture); + } + } + /// /// Looks up a localized string similar to Find all cells in the specified range that have any errors (#).. /// diff --git a/NavfertyExcelAddIn/Localization/RibbonSupertips.resx b/NavfertyExcelAddIn/Localization/RibbonSupertips.resx index dfbccb4..4f03519 100644 --- a/NavfertyExcelAddIn/Localization/RibbonSupertips.resx +++ b/NavfertyExcelAddIn/Localization/RibbonSupertips.resx @@ -196,4 +196,7 @@ Allows rewriting values in range -999 billion to 999 billion, with precision up Show or hide worksheet tabs + + Send a bug report or feature request to the developer + \ No newline at end of file diff --git a/NavfertyExcelAddIn/Localization/RibbonSupertips.ru-RU.resx b/NavfertyExcelAddIn/Localization/RibbonSupertips.ru-RU.resx index 2b455cc..0b13dc2 100644 --- a/NavfertyExcelAddIn/Localization/RibbonSupertips.ru-RU.resx +++ b/NavfertyExcelAddIn/Localization/RibbonSupertips.ru-RU.resx @@ -196,4 +196,7 @@ Отобразить или скрыть ярлычки листов + + Отправить отчёт об ошибке или пожелание новой функциональности разработчику + \ No newline at end of file diff --git a/NavfertyExcelAddIn/NavfertyRibbon.cs b/NavfertyExcelAddIn/NavfertyRibbon.cs index eb50693..f636738 100644 --- a/NavfertyExcelAddIn/NavfertyRibbon.cs +++ b/NavfertyExcelAddIn/NavfertyRibbon.cs @@ -423,6 +423,13 @@ public void CurrencyExchangeRatesSelect(IRibbonControl ribbonControl) } #endregion + #region Feedback + public void FeedbackStart(IRibbonControl ribbonControl) + { + GetService().DisplayFeedbackUI(); + } + #endregion + #endregion #region Utils diff --git a/NavfertyExcelAddIn/NavfertyRibbon.xml b/NavfertyExcelAddIn/NavfertyRibbon.xml index e0f0b67..2222bb2 100644 --- a/NavfertyExcelAddIn/NavfertyRibbon.xml +++ b/NavfertyExcelAddIn/NavfertyRibbon.xml @@ -121,8 +121,15 @@ +