eorzea-votes/client/EorzeaVotes/Ui/PluginUi.cs

235 lines
8.1 KiB
C#

using System.Numerics;
using Dalamud.Interface.Utility;
using EorzeaVotes.Config;
using EorzeaVotes.Model;
using EorzeaVotes.Ui.Tabs;
using EorzeaVotes.Utilities;
using ImGuiNET;
using Lumina.Excel.GeneratedSheets;
namespace EorzeaVotes.Ui;
internal class PluginUi : IDisposable {
private Plugin Plugin { get; }
#if DEBUG
internal bool Visible = true;
#else
internal bool Visible;
#endif
private string _dateScratch = string.Empty;
private readonly List<IDrawable> _drawables = [];
private TabId? _forceOpen;
private QuestionsTab QuestionsTab { get; }
private SettingsTab SettingsTab { get; }
internal PluginUi(Plugin plugin) {
this.Plugin = plugin;
this.QuestionsTab = new QuestionsTab(this.Plugin);
this.SettingsTab = new SettingsTab(this.Plugin);
this.UpdateDateScratch();
this.Plugin.Interface.UiBuilder.Draw += this.Draw;
this.Plugin.Interface.UiBuilder.OpenConfigUi += this.OpenConfigUi;
this.Plugin.Interface.UiBuilder.OpenMainUi += this.OpenMainUi;
}
public void Dispose() {
this.Plugin.Interface.UiBuilder.OpenMainUi -= this.OpenMainUi;
this.Plugin.Interface.UiBuilder.OpenConfigUi -= this.OpenConfigUi;
this.Plugin.Interface.UiBuilder.Draw -= this.Draw;
}
private void OpenConfigUi() {
this.Visible = true;
this._forceOpen = TabId.Settings;
}
private void OpenMainUi() {
this.Visible = true;
this._forceOpen = TabId.Questions;
}
private void UpdateDateScratch() {
this._dateScratch = this.Plugin.Config.BirthDate?.ToString("O") ?? string.Empty;
}
internal bool IsMoreDetailsOpen(Guid id) {
return this._drawables.Any(d => d is MoreDetailsWindow mdw && mdw.Question.Id == id);
}
internal void OpenMoreDetails(FullQuestion question) {
if (this.IsMoreDetailsOpen(question.Id)) {
return;
}
this._drawables.Add(new MoreDetailsWindow(this.Plugin, question));
}
private void DrawDrawables() {
this._drawables.RemoveAll(drawable => {
try {
return drawable.Draw() == DrawStatus.Finished;
} catch (Exception ex) {
Service.Log.Error(ex, "Error in IDrawable, closing");
return true;
}
});
}
private void Draw() {
this.DrawDrawables();
if (!this.Visible) {
return;
}
ImGui.SetNextWindowSize(new Vector2(512, 768), ImGuiCond.FirstUseEver);
using var end = new OnDispose(ImGui.End);
if (!ImGui.Begin(Plugin.Name, ref this.Visible)) {
return;
}
ImGui.PushTextWrapPos();
using var pop = new OnDispose(ImGui.PopTextWrapPos);
if (this.Plugin.Config.OnBoarded) {
this.DrawMain();
} else {
this.DrawOnboarding();
}
}
internal bool DrawOptionalQuestions() {
var anyChanged = false;
anyChanged |= ImGuiHelper.EnumDropDownVertical(
"I most identify as",
"Unspecified",
ref this.Plugin.Config.Gender,
helpTooltip: "This does not encompass the entire spectrum of experiencing gender. Please feel free to skip this question if you do not identify with any of the choices. It is hard and potentially privacy-invasive to accept all possible answers here for use in statistical breakdowns.",
nameFunction: GenderExt.Name
);
var dateInput = ImGuiHelper.InputDateVertical(
"I was born on (yyyy-mm-dd)",
ref this._dateScratch,
ref this.Plugin.Config.BirthDate
);
if (dateInput) {
anyChanged = true;
this.UpdateDateScratch();
}
if (this.Plugin.Config.BirthDate != null) {
ImGui.TextUnformatted(this.Plugin.Config.BirthDate.Value.ToString("D"));
}
anyChanged |= ImGuiHelper.ComboCheckboxVertical(
"I would like to send the race, clan, and gender of the character I'm playing when I vote",
ref this.Plugin.Config.RaceClanGender
);
anyChanged |= ImGuiHelper.ComboCheckboxVertical(
"I would like to send the home world of the character I'm playing when I vote",
ref this.Plugin.Config.HomeWorld
);
if (
ImGuiHelper.VerticalInput(
"I started playing FFXIV in (year - enter 0 to omit)",
id => ImGui.InputInt(id, ref this.Plugin.Config.YearStartedPlaying)
)
) {
if (this.Plugin.Config.YearStartedPlaying != 0) {
this.Plugin.Config.YearStartedPlaying = Math.Clamp(this.Plugin.Config.YearStartedPlaying, 2010, DateTime.UtcNow.Year);
}
anyChanged = true;
}
var jobs = this.Plugin.DataManager.GetExcelSheet<ClassJob>()!;
var jobPreview = this.Plugin.Config.MainJob == null
? "Unspecified"
: Util.TitleCase(jobs.GetRow(this.Plugin.Config.MainJob.Value)?.Name.RawString ?? "unknown");
if (
ImGuiHelper.VerticalInput(
"The job I most consider to be my \"main\" is",
id => ImGui.BeginCombo(id, jobPreview))
) {
using var endCombo = new OnDispose(ImGui.EndCombo);
if (ImGui.Selectable("Unspecified", this.Plugin.Config.MainJob == null)) {
anyChanged = true;
this.Plugin.Config.MainJob = null;
}
foreach (var job in jobs) {
if (job.RowId == 0 || string.IsNullOrWhiteSpace(job.Name.RawString)) {
continue;
}
if (ImGui.Selectable(Util.TitleCase(job.Name.RawString), job.RowId == this.Plugin.Config.MainJob)) {
anyChanged = true;
this.Plugin.Config.MainJob = job.RowId;
}
}
}
anyChanged |= ImGuiHelper.EnumDropDownVertical(
"My Myers-Briggs Type Indicator is",
"Unspecified",
ref this.Plugin.Config.MyersBriggs,
helpTooltip: "The MBTI is pseudoscience, but this is a fun question.",
nameFunction: mbti => mbti == null
? "Unspecified"
: (Enum.GetName(mbti.Value) ?? "???").ToUpperInvariant()
);
return anyChanged;
}
private void DrawOnboarding() {
ImGuiHelpers.CenteredText($"Welcome to {Plugin.Name}!");
ImGui.TextUnformatted("This plugin allows you to vote on lighthearted opinion polls and then see the results. There will be one question per day with new questions available at midnight UTC.");
ImGui.Spacing();
ImGui.TextUnformatted("After voting (or after the question is closed), you can see the results. There are also statistical breakdowns of the votes based on volunteered information.");
ImGui.Spacing();
ImGui.TextUnformatted("Since this is the first time you have opened this plugin, you will be shown some optional questions below. You may choose to answer none, some, or all of the questions. Your responses will be sent with your votes to enable further statistical breakdowns. You can always change your responses later. The country associated with your IP address is always sent, so do not vote if you are uncomfortable with that.");
ImGui.Spacing();
ImGuiHelpers.CenteredText("Optional questions");
var anyChanged = this.DrawOptionalQuestions();
ImGui.Spacing();
if (ImGui.Button("Done", new Vector2(ImGui.GetContentRegionAvail().X, 0))) {
this.Plugin.Config.OnBoarded = true;
anyChanged = true;
}
if (anyChanged) {
this.Plugin.SaveConfig();
}
}
private void DrawMain() {
if (!ImGui.BeginTabBar("ev-tabs")) {
return;
}
using var endTabBar = new OnDispose(ImGui.EndTabBar);
var forceOpen = this._forceOpen;
this._forceOpen = null;
this.QuestionsTab.Draw(forceOpen == TabId.Questions);
this.SettingsTab.Draw(forceOpen == TabId.Settings);
SuggestTab.Draw(forceOpen == TabId.Suggestions);
}
}