diff --git a/Dalamud/Dalamud.cs b/Dalamud/Dalamud.cs
index 2ebfe8667..3305c9949 100644
--- a/Dalamud/Dalamud.cs
+++ b/Dalamud/Dalamud.cs
@@ -22,6 +22,7 @@ using Dalamud.IoC.Internal;
using Dalamud.Logging.Internal;
using Dalamud.Plugin.Internal;
using Dalamud.Plugin.Ipc.Internal;
+using Dalamud.Support;
using HarmonyLib;
using Serilog;
using Serilog.Core;
diff --git a/Dalamud/EntryPoint.cs b/Dalamud/EntryPoint.cs
index bb8fc38ea..fe7c2e792 100644
--- a/Dalamud/EntryPoint.cs
+++ b/Dalamud/EntryPoint.cs
@@ -8,6 +8,7 @@ using System.Threading.Tasks;
using Dalamud.Configuration.Internal;
using Dalamud.Logging.Internal;
+using Dalamud.Support;
using Newtonsoft.Json;
using PInvoke;
using Serilog;
diff --git a/Dalamud/Interface/Colors/ImGuiColors.cs b/Dalamud/Interface/Colors/ImGuiColors.cs
index 0e6ac69f5..341460efe 100644
--- a/Dalamud/Interface/Colors/ImGuiColors.cs
+++ b/Dalamud/Interface/Colors/ImGuiColors.cs
@@ -10,51 +10,51 @@ namespace Dalamud.Interface.Colors
///
/// Gets red used in dalamud.
///
- public static Vector4 DalamudRed { get; } = new Vector4(1f, 0f, 0f, 1f);
+ public static Vector4 DalamudRed { get; internal set; } = new Vector4(1f, 0f, 0f, 1f);
///
/// Gets grey used in dalamud.
///
- public static Vector4 DalamudGrey { get; } = new Vector4(0.7f, 0.7f, 0.7f, 1f);
+ public static Vector4 DalamudGrey { get; internal set; } = new Vector4(0.7f, 0.7f, 0.7f, 1f);
///
/// Gets grey used in dalamud.
///
- public static Vector4 DalamudGrey2 { get; } = new Vector4(0.7f, 0.7f, 0.7f, 1f);
+ public static Vector4 DalamudGrey2 { get; internal set; } = new Vector4(0.7f, 0.7f, 0.7f, 1f);
///
/// Gets grey used in dalamud.
///
- public static Vector4 DalamudGrey3 { get; } = new Vector4(0.5f, 0.5f, 0.5f, 1f);
+ public static Vector4 DalamudGrey3 { get; internal set; } = new Vector4(0.5f, 0.5f, 0.5f, 1f);
///
/// Gets white used in dalamud.
///
- public static Vector4 DalamudWhite { get; } = new Vector4(1f, 1f, 1f, 1f);
+ public static Vector4 DalamudWhite { get; internal set; } = new Vector4(1f, 1f, 1f, 1f);
///
/// Gets white used in dalamud.
///
- public static Vector4 DalamudWhite2 { get; } = new Vector4(0.878f, 0.878f, 0.878f, 1f);
+ public static Vector4 DalamudWhite2 { get; internal set; } = new Vector4(0.878f, 0.878f, 0.878f, 1f);
///
/// Gets orange used in dalamud.
///
- public static Vector4 DalamudOrange { get; } = new Vector4(1f, 0.709f, 0f, 1f);
+ public static Vector4 DalamudOrange { get; internal set; } = new Vector4(1f, 0.709f, 0f, 1f);
///
/// Gets tank blue (UIColor37).
///
- public static Vector4 TankBlue { get; } = new Vector4(0f, 0.6f, 1f, 1f);
+ public static Vector4 TankBlue { get; internal set; } = new Vector4(0f, 0.6f, 1f, 1f);
///
/// Gets healer green (UIColor504).
///
- public static Vector4 HealerGreen { get; } = new Vector4(0f, 0.8f, 0.1333333f, 1f);
+ public static Vector4 HealerGreen { get; internal set; } = new Vector4(0f, 0.8f, 0.1333333f, 1f);
///
/// Gets dps red (UIColor545).
///
- public static Vector4 DPSRed { get; } = new Vector4(0.7058824f, 0f, 0f, 1f);
+ public static Vector4 DPSRed { get; internal set; } = new Vector4(0.7058824f, 0f, 0f, 1f);
}
}
diff --git a/Dalamud/Interface/Internal/Windows/PluginInstallerWindow.cs b/Dalamud/Interface/Internal/Windows/PluginInstallerWindow.cs
index f663cd168..7b001a4bd 100644
--- a/Dalamud/Interface/Internal/Windows/PluginInstallerWindow.cs
+++ b/Dalamud/Interface/Internal/Windows/PluginInstallerWindow.cs
@@ -22,6 +22,7 @@ using Dalamud.Plugin;
using Dalamud.Plugin.Internal;
using Dalamud.Plugin.Internal.Exceptions;
using Dalamud.Plugin.Internal.Types;
+using Dalamud.Support;
using Dalamud.Utility;
using ImGuiNET;
using ImGuiScene;
@@ -67,6 +68,12 @@ namespace Dalamud.Interface.Internal.Windows
private bool errorModalOnNextFrame = false;
private string errorModalMessage = string.Empty;
+ private bool feedbackModalDrawing = true;
+ private bool feedbackModalOnNextFrame = false;
+ private string feedbackModalBody = string.Empty;
+ private string feedbackModalContact = string.Empty;
+ private PluginManifest? feedbackPlugin = null;
+
private int updatePluginCount = 0;
private List? updatedPlugins;
@@ -186,6 +193,7 @@ namespace Dalamud.Interface.Internal.Windows
this.DrawPluginTabBar();
this.DrawFooter();
this.DrawErrorModal();
+ this.DrawFeedbackModal();
}
///
@@ -448,6 +456,65 @@ namespace Dalamud.Interface.Internal.Windows
{
ImGui.OpenPopup(modalTitle);
this.errorModalOnNextFrame = false;
+ this.errorModalDrawing = true;
+ }
+ }
+
+ private void DrawFeedbackModal()
+ {
+ var modalTitle = Locs.FeedbackModal_Title;
+
+ if (ImGui.BeginPopupModal(modalTitle, ref this.feedbackModalDrawing, ImGuiWindowFlags.AlwaysAutoResize | ImGuiWindowFlags.NoScrollbar))
+ {
+ ImGui.Text(Locs.FeedbackModal_Text);
+ ImGui.Spacing();
+
+ ImGui.InputTextMultiline("Feedback Content", ref this.feedbackModalBody, 1000, new Vector2(400, 200));
+
+ ImGui.Spacing();
+
+ ImGui.InputText("Contact Information", ref this.feedbackModalContact, 100);
+
+ ImGui.Spacing();
+
+ ImGui.TextColored(ImGuiColors.DalamudGrey, Locs.FeedbackModal_Hint);
+
+ var buttonWidth = 120f;
+ ImGui.SetCursorPosX((ImGui.GetWindowWidth() - buttonWidth) / 2);
+
+ if (ImGui.Button(Locs.ErrorModalButton_Ok, new Vector2(buttonWidth, 40)))
+ {
+ if (this.feedbackPlugin != null)
+ {
+ Task.Run(async () => await BugBait.SendFeedback(this.feedbackPlugin, this.feedbackModalBody, this.feedbackModalContact))
+ .ContinueWith(
+ t =>
+ {
+ var notif = Service.Get();
+ if (t.IsCanceled || t.IsFaulted)
+ notif.AddNotification(Locs.FeedbackModal_NotificationError, Locs.FeedbackModal_Title, NotificationType.Error);
+ else
+ notif.AddNotification(Locs.FeedbackModal_NotificationSuccess, Locs.FeedbackModal_Title, NotificationType.Success);
+ });
+ }
+ else
+ {
+ Log.Error("FeedbackPlugin was null.");
+ }
+
+ ImGui.CloseCurrentPopup();
+ }
+
+ ImGui.EndPopup();
+ }
+
+ if (this.feedbackModalOnNextFrame)
+ {
+ ImGui.OpenPopup(modalTitle);
+ this.feedbackModalOnNextFrame = false;
+ this.feedbackModalDrawing = true;
+ this.feedbackModalBody = string.Empty;
+ this.feedbackModalContact = string.Empty;
}
}
@@ -1037,6 +1104,11 @@ namespace Dalamud.Interface.Internal.Windows
this.DrawVisitRepoUrlButton(manifest.RepoUrl);
+ if (!manifest.SourceRepo.IsThirdParty)
+ {
+ this.DrawSendFeedbackButton(manifest);
+ }
+
ImGuiHelpers.ScaledDummy(5);
if (this.DrawPluginImages(null, manifest, isThirdParty, index))
@@ -1261,6 +1333,11 @@ namespace Dalamud.Interface.Internal.Windows
this.DrawDeletePluginButton(plugin);
this.DrawVisitRepoUrlButton(plugin.Manifest.RepoUrl);
+ if (!isThirdParty)
+ {
+ this.DrawSendFeedbackButton(plugin.Manifest);
+ }
+
if (availablePluginUpdate != default)
this.DrawUpdateSinglePluginButton(availablePluginUpdate);
@@ -1465,6 +1542,21 @@ namespace Dalamud.Interface.Internal.Windows
}
}
+ private void DrawSendFeedbackButton(PluginManifest manifest)
+ {
+ ImGui.SameLine();
+ if (ImGuiComponents.IconButton(FontAwesomeIcon.Comment))
+ {
+ this.feedbackPlugin = manifest;
+ this.feedbackModalOnNextFrame = true;
+ }
+
+ if (ImGui.IsItemHovered())
+ {
+ ImGui.SetTooltip(Locs.FeedbackModal_Title);
+ }
+ }
+
private void DrawDevPluginButtons(LocalPlugin localPlugin)
{
var configuration = Service.Get();
@@ -2165,6 +2257,20 @@ namespace Dalamud.Interface.Internal.Windows
#endregion
+ #region Feedback Modal
+
+ public static string FeedbackModal_Title => Loc.Localize("InstallerFeedback", "Send Feedback");
+
+ public static string FeedbackModal_Text => Loc.Localize("InstallerFeedbackInfo", "You can send feedback to the developer of this plugin here.\nYou can include your Discord tag or email address if you wish to give them the opportunity to answer.");
+
+ public static string FeedbackModal_Hint => Loc.Localize("InstallerFeedbackHint", "All plugin developers will be able to see your feedback.\nPlease never include any personal or revealing information.\nThe collected feedback is not stored and immediately relayed to Discord.");
+
+ public static string FeedbackModal_NotificationSuccess => Loc.Localize("InstallerFeedbackNotificationSuccess", "Your feedback was sent successfully!");
+
+ public static string FeedbackModal_NotificationError => Loc.Localize("InstallerFeedbackNotificationSuccess", "Your feedback could not be sent.");
+
+ #endregion
+
#region Plugin Update chatbox
public static string PluginUpdateHeader_Chatbox => Loc.Localize("DalamudPluginUpdates", "Updates:");
diff --git a/Dalamud/Support/BugBait.cs b/Dalamud/Support/BugBait.cs
new file mode 100644
index 000000000..149c76617
--- /dev/null
+++ b/Dalamud/Support/BugBait.cs
@@ -0,0 +1,61 @@
+using System.Net.Http;
+using System.Text;
+using System.Threading.Tasks;
+
+using Dalamud.Plugin.Internal.Types;
+using Dalamud.Utility;
+using Newtonsoft.Json;
+
+namespace Dalamud.Support
+{
+ ///
+ /// Class responsible for sending feedback.
+ ///
+ internal static class BugBait
+ {
+ private const string BugBaitUrl = "https://dalamud-bugbait.goatsoft.workers.dev/feedback";
+
+ ///
+ /// Send feedback to Discord.
+ ///
+ /// The plugin to send feedback about.
+ /// The content of the feedback.
+ /// The reporter name.
+ /// A representing the asynchronous operation.
+ public static async Task SendFeedback(PluginManifest plugin, string content, string reporter)
+ {
+ if (content.IsNullOrWhitespace())
+ return;
+
+ using var client = new HttpClient();
+
+ var model = new FeedbackModel
+ {
+ Content = content,
+ Reporter = reporter,
+ Name = plugin.InternalName,
+ Version = plugin.AssemblyVersion.ToString(),
+ };
+
+ var postContent = new StringContent(JsonConvert.SerializeObject(model), Encoding.UTF8, "application/json");
+ var response = await client.PostAsync(BugBaitUrl, postContent);
+
+ response.EnsureSuccessStatusCode();
+ }
+
+ private class FeedbackModel
+ {
+ [JsonProperty("content")]
+ public string? Content { get; set; }
+
+ [JsonProperty("name")]
+ public string? Name { get; set; }
+
+ [JsonProperty("version")]
+ public string? Version { get; set; }
+
+ [JsonProperty("reporter")]
+ public string? Reporter { get; set; }
+ }
+ }
+}
diff --git a/Dalamud/Troubleshooting.cs b/Dalamud/Support/Troubleshooting.cs
similarity index 99%
rename from Dalamud/Troubleshooting.cs
rename to Dalamud/Support/Troubleshooting.cs
index 97b88c591..3417a9696 100644
--- a/Dalamud/Troubleshooting.cs
+++ b/Dalamud/Support/Troubleshooting.cs
@@ -12,7 +12,7 @@ using Dalamud.Utility;
using Newtonsoft.Json;
using Serilog;
-namespace Dalamud
+namespace Dalamud.Support
{
///
/// Class responsible for printing troubleshooting information to the log.