qstbak/Questionable/Questionable.Windows.QuestComponents/QuestValidationComponent.cs
2025-10-09 07:53:51 +10:00

255 lines
6.6 KiB
C#

using System;
using System.Collections.Generic;
using System.Globalization;
using System.Numerics;
using Dalamud.Bindings.ImGui;
using Dalamud.Interface;
using Dalamud.Interface.Colors;
using Dalamud.Interface.Utility.Raii;
using Dalamud.Plugin;
using Questionable.Data;
using Questionable.Validation;
namespace Questionable.Windows.QuestComponents;
internal sealed class QuestValidationComponent
{
private readonly QuestValidator _questValidator;
private readonly QuestData _questData;
private readonly IDalamudPluginInterface _pluginInterface;
private readonly ValidationDetailsRenderer _detailsRenderer;
public bool ShouldDraw => _questValidator.Issues.Count > 0;
public QuestValidationComponent(QuestValidator questValidator, QuestData questData, IDalamudPluginInterface pluginInterface)
{
_questValidator = questValidator;
_questData = questData;
_pluginInterface = pluginInterface;
_detailsRenderer = new ValidationDetailsRenderer(questData, pluginInterface);
}
public void Draw()
{
DrawSummaryHeader();
ImGui.Separator();
DrawValidationTable();
_detailsRenderer.DrawDetailWindows();
}
private void DrawSummaryHeader()
{
int issueCount = _questValidator.IssueCount;
int errorCount = _questValidator.ErrorCount;
int num = issueCount - errorCount;
ImU8String text = new ImU8String(33, 1);
text.AppendLiteral("Validation Results: ");
text.AppendFormatted(issueCount);
text.AppendLiteral(" total issues");
ImGui.Text(text);
if (errorCount > 0)
{
ImGui.SameLine();
ImGui.Text("(");
ImGui.SameLine();
using (ImRaii.PushColor(ImGuiCol.Text, ImGuiColors.DalamudRed))
{
text = new ImU8String(7, 1);
text.AppendFormatted(errorCount);
text.AppendLiteral(" errors");
ImGui.Text(text);
}
}
if (num > 0)
{
if (errorCount > 0)
{
ImGui.SameLine();
using (ImRaii.PushColor(ImGuiCol.Text, ImGuiColors.DalamudOrange))
{
text = new ImU8String(12, 1);
text.AppendLiteral(", ");
text.AppendFormatted(num);
text.AppendLiteral(" warnings)");
ImGui.Text(text);
return;
}
}
ImGui.SameLine();
ImGui.Text("(");
ImGui.SameLine();
using (ImRaii.PushColor(ImGuiCol.Text, ImGuiColors.DalamudOrange))
{
text = new ImU8String(10, 1);
text.AppendFormatted(num);
text.AppendLiteral(" warnings)");
ImGui.Text(text);
return;
}
}
if (errorCount > 0)
{
ImGui.SameLine();
ImGui.Text(")");
}
}
private void DrawValidationTable()
{
using ImRaii.IEndObject endObject = ImRaii.Table("ValidationIssues", 6, ImGuiTableFlags.Borders | ImGuiTableFlags.Sortable | ImGuiTableFlags.RowBg | ImGuiTableFlags.ScrollY);
if (!(!endObject))
{
ImGui.TableSetupColumn("ID", ImGuiTableColumnFlags.WidthFixed, 60f);
ImGui.TableSetupColumn("Name", ImGuiTableColumnFlags.WidthFixed, 250f);
ImGui.TableSetupColumn("Seq", ImGuiTableColumnFlags.WidthFixed, 40f);
ImGui.TableSetupColumn("Step", ImGuiTableColumnFlags.WidthFixed, 40f);
ImGui.TableSetupColumn("Issue", ImGuiTableColumnFlags.WidthStretch);
ImGui.TableSetupColumn("Actions", ImGuiTableColumnFlags.WidthFixed, 60f);
ImGui.TableHeadersRow();
IReadOnlyList<ValidationIssue> issues = _questValidator.Issues;
for (int i = 0; i < issues.Count; i++)
{
DrawValidationRow(issues[i], i);
}
}
}
private void DrawValidationRow(ValidationIssue issue, int index)
{
ImGui.TableNextRow();
if (ImGui.TableNextColumn())
{
ImGui.TextUnformatted(issue.ElementId?.ToString() ?? string.Empty);
}
if (ImGui.TableNextColumn())
{
ImGui.TextUnformatted((issue.ElementId != null) ? _questData.GetQuestInfo(issue.ElementId).Name : issue.AlliedSociety.ToString());
}
if (ImGui.TableNextColumn())
{
if (issue.Sequence.HasValue)
{
ImGui.TextUnformatted(issue.Sequence.Value.ToString(CultureInfo.InvariantCulture));
}
else
{
using (ImRaii.PushColor(ImGuiCol.Text, ImGuiColors.DalamudGrey2))
{
ImGui.TextUnformatted("\ufffd");
}
}
}
if (ImGui.TableNextColumn())
{
if (issue.Step.HasValue)
{
ImGui.TextUnformatted(issue.Step.Value.ToString(CultureInfo.InvariantCulture));
}
else
{
using (ImRaii.PushColor(ImGuiCol.Text, ImGuiColors.DalamudGrey2))
{
ImGui.TextUnformatted("\ufffd");
}
}
}
if (ImGui.TableNextColumn())
{
DrawIssueCell(issue, index);
}
if (ImGui.TableNextColumn())
{
DrawActionsCell(issue, index);
}
}
private void DrawIssueCell(ValidationIssue issue, int index)
{
Vector4 color = ((issue.Severity == EIssueSeverity.Error) ? ImGuiColors.DalamudRed : ImGuiColors.DalamudOrange);
FontAwesomeIcon icon = ((issue.Severity == EIssueSeverity.Error) ? FontAwesomeIcon.ExclamationTriangle : FontAwesomeIcon.InfoCircle);
using (_pluginInterface.UiBuilder.IconFontFixedWidthHandle.Push())
{
using (ImRaii.PushColor(ImGuiCol.Text, color))
{
ImGui.TextUnformatted(icon.ToIconString());
}
}
ImGui.SameLine();
string issueSummary = GetIssueSummary(issue);
using (ImRaii.PushColor(ImGuiCol.Text, color))
{
ImGui.TextWrapped(issueSummary);
}
}
private void DrawActionsCell(ValidationIssue issue, int index)
{
if (HasDetailedDescription(issue) && ImGui.SmallButton($"Details##{index}"))
{
_detailsRenderer.OpenDetails(issue, index);
}
}
private static string GetIssueSummary(ValidationIssue issue)
{
string text = ValidationDetailsRenderer.CleanJsonText(issue.Description ?? string.Empty);
if (issue.Type == EIssueType.QuestDisabled && issue.ElementId == null)
{
string[] array = text.Split(':', 2);
if (array.Length == 0)
{
return text;
}
return array[0];
}
if (issue.Type == EIssueType.InvalidJsonSchema)
{
string[] array2 = text.Split('\n', 2, StringSplitOptions.RemoveEmptyEntries);
if (array2.Length == 0)
{
return text;
}
return array2[0];
}
if (issue.Type == EIssueType.InvalidJsonSyntax)
{
string[] array3 = text.Split('\n', 2, StringSplitOptions.RemoveEmptyEntries);
if (array3.Length == 0)
{
return text;
}
return array3[0];
}
string[] array4 = text.Split('\n', StringSplitOptions.RemoveEmptyEntries);
if (array4.Length <= 2)
{
return text;
}
return array4[0] + ((array4.Length > 1) ? "..." : "");
}
private static bool HasDetailedDescription(ValidationIssue issue)
{
string text = issue.Description ?? string.Empty;
if (issue.Type == EIssueType.QuestDisabled && issue.ElementId == null)
{
return true;
}
if (issue.Type == EIssueType.InvalidJsonSchema)
{
return true;
}
if (issue.Type == EIssueType.InvalidJsonSyntax)
{
return true;
}
if (!text.Contains('\n', StringComparison.Ordinal))
{
return text.Length > 100;
}
return true;
}
}