using System; using System.Globalization; using System.Linq; using System.Numerics; using Dalamud.Bindings.ImGui; using Dalamud.Interface; using Dalamud.Interface.Utility.Raii; using Questionable.Model.Changelog; namespace Questionable.Windows.ChangelogComponents; internal sealed class ChangelogEntryComponent { private readonly Configuration _configuration; private readonly int _windowOpenCount; private readonly float _animationTime; public ChangelogEntryComponent(Configuration configuration, int windowOpenCount, float animationTime) { _configuration = configuration; _windowOpenCount = windowOpenCount; _animationTime = animationTime; } public void Draw(ChangelogEntry changelog, bool isLatest, bool hasSetInitialState) { bool isNew = changelog.IsNewVersion(_configuration.LastViewedChangelogVersion); ImGui.GetWindowDrawList(); string text = changelog.ReleaseDate.ToString("MMMM dd, yyyy", CultureInfo.InvariantCulture); if (!hasSetInitialState) { ImGui.SetNextItemOpen(isLatest, ImGuiCond.Always); } string text2 = "v" + changelog.Version; float fontSize = ImGui.GetFontSize(); float num = fontSize; Vector2 versionSize; using (ImRaii.PushFont(UiBuilder.MonoFont)) { versionSize = ImGui.CalcTextSize(text2); } Vector2 dateSize = ImGui.CalcTextSize(text); float scaledIconFontSize = fontSize * 0.85f; float x = ImGui.GetContentRegionAvail().X; bool flag; using (ImRaii.PushColor(ImGuiCol.Header, new Vector4(0.2f, 0.18f, 0.25f, 0.6f))) { using (ImRaii.PushColor(ImGuiCol.HeaderHovered, new Vector4(0.3f, 0.25f, 0.35f, 0.8f))) { using (ImRaii.PushColor(ImGuiCol.HeaderActive, new Vector4(0.25f, 0.22f, 0.3f, 1f))) { Vector2 cursorPos = ImGui.GetCursorPos(); Vector2 cursorScreenPos = ImGui.GetCursorScreenPos(); ImU8String label = new ImU8String(19, 2); label.AppendLiteral("###header_"); label.AppendFormatted(changelog.Version); label.AppendLiteral("_changes_"); label.AppendFormatted(_windowOpenCount); flag = ImGui.CollapsingHeader(label); Vector2 cursorPos2 = ImGui.GetCursorPos(); float verticalOffset = (cursorPos2.Y - cursorPos.Y - num) * 0.5f - 1f; DrawVersionText(text2, versionSize, cursorPos, verticalOffset); DrawNewBadge(isNew, cursorScreenPos, x); DrawDateWithIcon(text, dateSize, scaledIconFontSize, cursorScreenPos, cursorPos, x, verticalOffset, fontSize); ImGui.SetCursorPos(cursorPos2); } } } if (flag) { DrawChangelogContent(changelog); } } private static void DrawVersionText(string versionText, Vector2 versionSize, Vector2 headerStartPos, float verticalOffset) { float x = headerStartPos.X + ImGui.GetStyle().FramePadding.X * 2f + 20f; using (ImRaii.PushFont(UiBuilder.MonoFont)) { ImGui.SetCursorPos(new Vector2(x, headerStartPos.Y + verticalOffset)); ImGui.TextColored(new Vector4(0.95f, 0.95f, 0.95f, 1f), versionText); } } private void DrawNewBadge(bool isNew, Vector2 headerStartScreenPos, float availableWidth) { if (isNew) { float num = 2.5f; float w = (MathF.Sin(_animationTime * num) + 1f) * 0.5f * 0.15f; float frameHeight = ImGui.GetFrameHeight(); float frameRounding = ImGui.GetStyle().FrameRounding; ImGui.GetWindowDrawList().AddRectFilled(headerStartScreenPos, headerStartScreenPos + new Vector2(availableWidth, frameHeight), ImGui.ColorConvertFloat4ToU32(new Vector4(0.5f, 1f, 0.6f, w)), frameRounding); } } private static void DrawDateWithIcon(string dateText, Vector2 dateSize, float scaledIconFontSize, Vector2 headerStartScreenPos, Vector2 headerStartPos, float availableWidth, float verticalOffset, float defaultFontSize) { string text = FontAwesomeIcon.Calendar.ToIconString(); Vector2 vector; using (ImRaii.PushFont(UiBuilder.IconFont)) { vector = ImGui.CalcTextSize(text); } float num = vector.X * (scaledIconFontSize / defaultFontSize); float num2 = num + 4f + dateSize.X; float num3 = availableWidth - num2 - 12f; Vector2 pos = headerStartScreenPos + new Vector2(num3, verticalOffset); ImGui.GetWindowDrawList().AddText(UiBuilder.IconFont, scaledIconFontSize, pos, ImGui.ColorConvertFloat4ToU32(new Vector4(0.65f, 0.6f, 0.8f, 1f)), text); ImGui.SetCursorPos(new Vector2(num3 + num + 4f, headerStartPos.Y + verticalOffset)); ImGui.TextColored(new Vector4(0.95f, 0.95f, 1f, 1f), dateText); } private static void DrawChangelogContent(ChangelogEntry changelog) { Vector2 cursorPos = ImGui.GetCursorPos(); Vector2 vector = new Vector2(16f, 8f); float x = ImGui.GetContentRegionAvail().X; IOrderedEnumerable> orderedEnumerable = from changeEntry in changelog.Changes group changeEntry by changeEntry.Category into g orderby g.Key select g; ImDrawListPtr windowDrawList = ImGui.GetWindowDrawList(); windowDrawList.ChannelsSplit(2); windowDrawList.ChannelsSetCurrent(1); float baseX = cursorPos.X + vector.X; ImGui.SetCursorPos(cursorPos + new Vector2(vector.X, vector.Y)); bool flag = true; foreach (IGrouping item in orderedEnumerable) { if (!flag) { ImGui.Spacing(); } ChangelogCategoryComponent.DrawCategoryGroup(item.Key, item.ToList(), baseX); flag = false; } Vector2 cursorPos2 = ImGui.GetCursorPos(); windowDrawList.ChannelsSetCurrent(0); ImGui.SetCursorPos(cursorPos); Vector2 cursorScreenPos = ImGui.GetCursorScreenPos(); ImGui.SetCursorPos(cursorPos2 + new Vector2(0f, vector.Y)); Vector2 cursorScreenPos2 = ImGui.GetCursorScreenPos(); windowDrawList.AddRectFilled(cursorScreenPos, new Vector2(cursorScreenPos.X + x, cursorScreenPos2.Y), ImGui.ColorConvertFloat4ToU32(new Vector4(0.1f, 0.08f, 0.14f, 0.5f)), 4f); windowDrawList.AddRect(cursorScreenPos, new Vector2(cursorScreenPos.X + x, cursorScreenPos2.Y), ImGui.ColorConvertFloat4ToU32(new Vector4(0.55f, 0.45f, 0.75f, 0.15f)), 4f, ImDrawFlags.None, 1f); windowDrawList.ChannelsMerge(); ImGui.SetCursorPos(new Vector2(cursorPos.X, cursorPos2.Y + vector.Y + 2f)); } }