using System; using System.Collections.Generic; 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.Model.Questing; 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(); UiThemeUtils.SectionSpacing(); 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)) { ImU8String text2 = new ImU8String(7, 1); text2.AppendFormatted(errorCount); text2.AppendLiteral(" errors"); ImGui.Text(text2); } } if (num > 0) { if (errorCount > 0) { ImGui.SameLine(); using (ImRaii.PushColor(ImGuiCol.Text, ImGuiColors.DalamudOrange)) { ImU8String text3 = new ImU8String(12, 1); text3.AppendLiteral(", "); text3.AppendFormatted(num); text3.AppendLiteral(" warnings)"); ImGui.Text(text3); return; } } ImGui.SameLine(); ImGui.Text("("); ImGui.SameLine(); using (ImRaii.PushColor(ImGuiCol.Text, ImGuiColors.DalamudOrange)) { ImU8String text4 = new ImU8String(10, 1); text4.AppendFormatted(num); text4.AppendLiteral(" warnings)"); ImGui.Text(text4); return; } } if (errorCount > 0) { ImGui.SameLine(); ImGui.Text(")"); } } private void DrawValidationTable() { using ImRaii.TableDisposable tableDisposable = UiThemeUtils.BeginThemedTable("ValidationIssues", 5, ImGuiTableFlags.ScrollX | ImGuiTableFlags.ScrollY); if (!(!tableDisposable)) { ImGui.TableSetupColumn("Type", ImGuiTableColumnFlags.WidthFixed, 50f); ImGui.TableSetupColumn("ID", ImGuiTableColumnFlags.WidthFixed, 60f); ImGui.TableSetupColumn("Name", ImGuiTableColumnFlags.WidthFixed, 250f); ImGui.TableSetupColumn("Location", ImGuiTableColumnFlags.WidthFixed, 100f); ImGui.TableSetupColumn("Issue", ImGuiTableColumnFlags.WidthStretch); ImGui.TableHeadersRow(); IReadOnlyList 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.PathType switch { EPathType.Quest => "Quest", EPathType.Fate => "Fate", EPathType.Gathering => "Gather", EPathType.SeasonalDuty => "Duty", _ => issue.PathType.ToString(), }); } if (ImGui.TableNextColumn()) { ImGui.TextUnformatted(issue.Id ?? string.Empty); } if (ImGui.TableNextColumn()) { string text = string.Empty; if (issue.PathType == EPathType.Quest && issue.Id != null) { if (ElementId.TryFromString(issue.Id, out ElementId elementId) && elementId != null) { try { text = _questData.GetQuestInfo(elementId).Name; } catch { text = issue.Id; } } else { text = issue.Id; } } else if (issue.Id != null) { text = issue.Id; } UiThemeUtils.RowLabel(text, 0f); } if (ImGui.TableNextColumn()) { if (!string.IsNullOrEmpty(issue.Location)) { ImGui.TextUnformatted(issue.Location); } else { using (ImRaii.PushColor(ImGuiCol.Text, ImGuiColors.DalamudGrey2)) { ImGui.TextUnformatted("-"); } } } if (ImGui.TableNextColumn()) { DrawIssueCell(issue, index); } } private void DrawIssueCell(ValidationIssue issue, int index) { Vector4 color = issue.Severity switch { EIssueSeverity.Error => ImGuiColors.DalamudRed, EIssueSeverity.Warning => ImGuiColors.DalamudYellow, _ => ImGuiColors.DalamudOrange, }; FontAwesomeIcon icon = issue.Severity switch { EIssueSeverity.Error => FontAwesomeIcon.ExclamationTriangle, EIssueSeverity.Warning => FontAwesomeIcon.ExclamationCircle, _ => 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 static string GetIssueSummary(ValidationIssue issue) { string text = issue.Description ?? string.Empty; if (issue.Type == EIssueType.QuestDisabled && issue.Id == null) { string[] array = text.Split(':', 2); if (array.Length == 0) { return text; } return array[0]; } string[] array2 = text.Split('\n', 2, StringSplitOptions.RemoveEmptyEntries); if (array2.Length == 0) { return text; } if (array2.Length <= 1) { return array2[0]; } return array2[0] + "..."; } private static bool HasDetailedDescription(ValidationIssue issue) { if (issue.Type == EIssueType.QuestDisabled && issue.Id == null) { return true; } string text = issue.Description ?? string.Empty; if (!text.Contains('\n', StringComparison.Ordinal)) { return text.Length > 100; } return true; } }