Merge remote-tracking branch 'origin/master' into apiX-rollup

This commit is contained in:
github-actions[bot] 2024-06-15 22:45:08 +00:00
commit 263610c9e7
28 changed files with 1526 additions and 311 deletions

View file

@ -208,6 +208,19 @@ internal class PluginInstallerWindow : Window, IDisposable
EnabledDisabled,
ProfileOrNot,
}
[Flags]
private enum PluginHeaderFlags
{
None = 0,
IsThirdParty = 1 << 0,
HasTrouble = 1 << 1,
UpdateAvailable = 1 << 2,
IsNew = 1 << 3,
IsInstallableOutdated = 1 << 4,
IsOrphan = 1 << 5,
IsTesting = 1 << 6,
}
private bool AnyOperationInProgress => this.installStatus == OperationStatus.InProgress ||
this.updateStatus == OperationStatus.InProgress ||
@ -712,8 +725,12 @@ internal class PluginInstallerWindow : Window, IDisposable
{
this.updateStatus = OperationStatus.InProgress;
this.loadingIndicatorKind = LoadingIndicatorKind.UpdatingAll;
var toUpdate = this.pluginListUpdatable
.Where(x => x.InstalledPlugin.IsLoaded)
.ToList();
Task.Run(() => pluginManager.UpdatePluginsAsync(true, false))
Task.Run(() => pluginManager.UpdatePluginsAsync(toUpdate, false))
.ContinueWith(task =>
{
this.updateStatus = OperationStatus.Complete;
@ -1807,22 +1824,62 @@ internal class PluginInstallerWindow : Window, IDisposable
return ready;
}
private bool DrawPluginCollapsingHeader(string label, LocalPlugin? plugin, IPluginManifest manifest, bool isThirdParty, bool trouble, bool updateAvailable, bool isNew, bool installableOutdated, bool isOrphan, Action drawContextMenuAction, int index)
private bool DrawPluginCollapsingHeader(string label, LocalPlugin? plugin, IPluginManifest manifest, PluginHeaderFlags flags, Action drawContextMenuAction, int index)
{
ImGui.Separator();
var isOpen = this.openPluginCollapsibles.Contains(index);
var sectionSize = ImGuiHelpers.GlobalScale * 66;
var tapeCursor = ImGui.GetCursorPos();
ImGui.Separator();
var startCursor = ImGui.GetCursorPos();
if (flags.HasFlag(PluginHeaderFlags.IsTesting))
{
void DrawCautionTape(Vector2 position, Vector2 size, float stripeWidth, float skewAmount)
{
var wdl = ImGui.GetWindowDrawList();
var windowPos = ImGui.GetWindowPos();
var scroll = new Vector2(ImGui.GetScrollX(), ImGui.GetScrollY());
var adjustedPosition = windowPos + position - scroll;
var yellow = ImGui.ColorConvertFloat4ToU32(new Vector4(1.0f, 0.9f, 0.0f, 0.10f));
var numStripes = (int)(size.X / stripeWidth) + (int)(size.Y / skewAmount) + 1; // +1 to cover partial stripe
for (var i = 0; i < numStripes; i++)
{
var x0 = adjustedPosition.X + i * stripeWidth;
var x1 = x0 + stripeWidth;
var y0 = adjustedPosition.Y;
var y1 = y0 + size.Y;
var p0 = new Vector2(x0, y0);
var p1 = new Vector2(x1, y0);
var p2 = new Vector2(x1 - skewAmount, y1);
var p3 = new Vector2(x0 - skewAmount, y1);
if (i % 2 != 0)
continue;
wdl.AddQuadFilled(p0, p1, p2, p3, yellow);
}
}
DrawCautionTape(tapeCursor + new Vector2(0, 1), new Vector2(ImGui.GetWindowWidth(), sectionSize + ImGui.GetStyle().ItemSpacing.Y), ImGuiHelpers.GlobalScale * 40, 20);
}
ImGui.PushStyleColor(ImGuiCol.Button, isOpen ? new Vector4(0.5f, 0.5f, 0.5f, 0.1f) : Vector4.Zero);
ImGui.PushStyleColor(ImGuiCol.ButtonHovered, new Vector4(0.5f, 0.5f, 0.5f, 0.2f));
ImGui.PushStyleColor(ImGuiCol.ButtonActive, new Vector4(0.5f, 0.5f, 0.5f, 0.35f));
ImGui.PushStyleVar(ImGuiStyleVar.FrameRounding, 0);
ImGui.SetCursorPos(tapeCursor);
if (ImGui.Button($"###plugin{index}CollapsibleBtn", new Vector2(ImGui.GetContentRegionAvail().X, sectionSize)))
if (ImGui.Button($"###plugin{index}CollapsibleBtn", new Vector2(ImGui.GetContentRegionAvail().X, sectionSize + ImGui.GetStyle().ItemSpacing.Y)))
{
if (isOpen)
{
@ -1854,7 +1911,7 @@ internal class PluginInstallerWindow : Window, IDisposable
if (ImGui.IsRectVisible(rectOffset + cursorBeforeImage, rectOffset + cursorBeforeImage + iconSize))
{
var iconTex = this.imageCache.DefaultIcon;
var hasIcon = this.imageCache.TryGetIcon(plugin, manifest, isThirdParty, out var cachedIconTex, out var loadedSince);
var hasIcon = this.imageCache.TryGetIcon(plugin, manifest, flags.HasFlag(PluginHeaderFlags.IsThirdParty), out var cachedIconTex, out var loadedSince);
if (hasIcon && cachedIconTex != null)
{
iconTex = cachedIconTex;
@ -1868,7 +1925,7 @@ internal class PluginInstallerWindow : Window, IDisposable
float EaseOutCubic(float t) => 1 - MathF.Pow(1 - t, 3);
var secondsSinceLoad = (float)DateTime.Now.Subtract(loadedSince.Value).TotalSeconds;
var fadeTo = pluginDisabled || installableOutdated ? 0.4f : 1f;
var fadeTo = pluginDisabled || flags.HasFlag(PluginHeaderFlags.IsInstallableOutdated) ? 0.4f : 1f;
float Interp(float to) => Math.Clamp(EaseOutCubic(Math.Min(secondsSinceLoad, fadeTime) / fadeTime) * to, 0, 1);
iconAlpha = Interp(fadeTo);
@ -1886,11 +1943,11 @@ internal class PluginInstallerWindow : Window, IDisposable
var isLoaded = plugin is { IsLoaded: true };
ImGui.PushStyleVar(ImGuiStyleVar.Alpha, overlayAlpha);
if (updateAvailable)
if (flags.HasFlag(PluginHeaderFlags.UpdateAvailable))
ImGui.Image(this.imageCache.UpdateIcon.ImGuiHandle, iconSize);
else if ((trouble && !pluginDisabled) || isOrphan)
else if ((flags.HasFlag(PluginHeaderFlags.HasTrouble) && !pluginDisabled) || flags.HasFlag(PluginHeaderFlags.IsOrphan))
ImGui.Image(this.imageCache.TroubleIcon.ImGuiHandle, iconSize);
else if (installableOutdated)
else if (flags.HasFlag(PluginHeaderFlags.IsInstallableOutdated))
ImGui.Image(this.imageCache.OutdatedInstallableIcon.ImGuiHandle, iconSize);
else if (pluginDisabled)
ImGui.Image(this.imageCache.DisabledIcon.ImGuiHandle, iconSize);
@ -1934,7 +1991,7 @@ internal class PluginInstallerWindow : Window, IDisposable
this.DrawFontawesomeIconOutlined(FontAwesomeIcon.Wrench, devIconOutlineColor, devIconColor);
this.VerifiedCheckmarkFadeTooltip(label, "This is a dev plugin. You added it.");
}
else if (!isThirdParty)
else if (!flags.HasFlag(PluginHeaderFlags.IsThirdParty))
{
this.DrawFontawesomeIconOutlined(FontAwesomeIcon.CheckCircle, verifiedOutlineColor, verifiedIconColor);
this.VerifiedCheckmarkFadeTooltip(label, Locs.VerifiedCheckmark_VerifiedTooltip);
@ -1954,7 +2011,7 @@ internal class PluginInstallerWindow : Window, IDisposable
ImGui.SameLine();
ImGui.TextColored(ImGuiColors.DalamudGrey3, downloadCountText);
if (isNew)
if (flags.HasFlag(PluginHeaderFlags.IsNew))
{
ImGui.SameLine();
ImGui.TextColored(ImGuiColors.TankBlue, Locs.PluginTitleMod_New);
@ -1964,12 +2021,12 @@ internal class PluginInstallerWindow : Window, IDisposable
ImGui.SetCursorPos(cursor);
// Outdated warning
if (plugin is { IsOutdated: true, IsBanned: false } || installableOutdated)
if (plugin is { IsOutdated: true, IsBanned: false } || flags.HasFlag(PluginHeaderFlags.IsInstallableOutdated))
{
ImGui.PushStyleColor(ImGuiCol.Text, ImGuiColors.DalamudRed);
var bodyText = Locs.PluginBody_Outdated + " ";
if (updateAvailable)
if (flags.HasFlag(PluginHeaderFlags.UpdateAvailable))
bodyText += Locs.PluginBody_Outdated_CanNowUpdate;
else
bodyText += Locs.PluginBody_Outdated_WaitForUpdate;
@ -1987,7 +2044,7 @@ internal class PluginInstallerWindow : Window, IDisposable
: Locs.PluginBody_BannedReason(plugin.BanReason);
bodyText += " ";
if (updateAvailable)
if (flags.HasFlag(PluginHeaderFlags.UpdateAvailable))
bodyText += Locs.PluginBody_Outdated_CanNowUpdate;
else
bodyText += Locs.PluginBody_Outdated_WaitForUpdate;
@ -2031,7 +2088,7 @@ internal class PluginInstallerWindow : Window, IDisposable
ImGui.SetCursorPosX(cursor.X);
// Description
if (plugin is null or { IsOutdated: false, IsBanned: false } && !trouble)
if (plugin is null or { IsOutdated: false, IsBanned: false } && !flags.HasFlag(PluginHeaderFlags.HasTrouble))
{
if (!string.IsNullOrWhiteSpace(manifest.Punchline))
{
@ -2152,11 +2209,22 @@ internal class PluginInstallerWindow : Window, IDisposable
{
label += Locs.PluginTitleMod_TestingAvailable;
}
var isThirdParty = manifest.SourceRepo.IsThirdParty;
ImGui.PushID($"available{index}{manifest.InternalName}");
var isThirdParty = manifest.SourceRepo.IsThirdParty;
if (this.DrawPluginCollapsingHeader(label, null, manifest, isThirdParty, false, false, !wasSeen, isOutdated, false, () => this.DrawAvailablePluginContextMenu(manifest), index))
var flags = PluginHeaderFlags.None;
if (isThirdParty)
flags |= PluginHeaderFlags.IsThirdParty;
if (!wasSeen)
flags |= PluginHeaderFlags.IsNew;
if (isOutdated)
flags |= PluginHeaderFlags.IsInstallableOutdated;
if (useTesting || manifest.IsTestingExclusive)
flags |= PluginHeaderFlags.IsTesting;
if (this.DrawPluginCollapsingHeader(label, null, manifest, flags, () => this.DrawAvailablePluginContextMenu(manifest), index))
{
if (!wasSeen)
configuration.SeenPluginInternalName.Add(manifest.InternalName);
@ -2420,7 +2488,19 @@ internal class PluginInstallerWindow : Window, IDisposable
var hasChangelog = !applicableChangelog.IsNullOrWhitespace();
var didDrawChangelogInsideCollapsible = false;
if (this.DrawPluginCollapsingHeader(label, plugin, plugin.Manifest, plugin.IsThirdParty, trouble, availablePluginUpdate != default, false, false, plugin.IsOrphaned, () => this.DrawInstalledPluginContextMenu(plugin, testingOptIn), index))
var flags = PluginHeaderFlags.None;
if (plugin.IsThirdParty)
flags |= PluginHeaderFlags.IsThirdParty;
if (trouble)
flags |= PluginHeaderFlags.HasTrouble;
if (availablePluginUpdate != default)
flags |= PluginHeaderFlags.UpdateAvailable;
if (plugin.IsOrphaned)
flags |= PluginHeaderFlags.IsOrphan;
if (plugin.IsTesting)
flags |= PluginHeaderFlags.IsTesting;
if (this.DrawPluginCollapsingHeader(label, plugin, plugin.Manifest, flags, () => this.DrawInstalledPluginContextMenu(plugin, testingOptIn), index))
{
if (!this.WasPluginSeen(plugin.Manifest.InternalName))
configuration.SeenPluginInternalName.Add(plugin.Manifest.InternalName);

View file

@ -12,7 +12,6 @@ using Dalamud.Interface.Utility;
using Dalamud.Interface.Utility.Raii;
using Dalamud.Plugin.Internal;
using Dalamud.Plugin.Internal.Profiles;
using Dalamud.Plugin.Internal.Types;
using Dalamud.Utility;
using ImGuiNET;
using Serilog;
@ -300,39 +299,16 @@ internal class ProfileManagerWidget
return;
}
const string addPluginToProfilePopup = "###addPluginToProfile";
var addPluginToProfilePopupId = ImGui.GetID(addPluginToProfilePopup);
using (var popup = ImRaii.Popup(addPluginToProfilePopup))
{
if (popup.Success)
var addPluginToProfilePopupId = DalamudComponents.DrawPluginPicker(
"###addPluginToProfilePicker",
ref this.pickerSearch,
plugin =>
{
var width = ImGuiHelpers.GlobalScale * 300;
using var disabled = ImRaii.Disabled(profman.IsBusy);
ImGui.SetNextItemWidth(width);
ImGui.InputTextWithHint("###pluginPickerSearch", Locs.SearchHint, ref this.pickerSearch, 255);
if (ImGui.BeginListBox("###pluginPicker", new Vector2(width, width - 80)))
{
// TODO: Plugin searching should be abstracted... installer and this should use the same search
foreach (var plugin in pm.InstalledPlugins.Where(x => x.Manifest.SupportsProfiles &&
(this.pickerSearch.IsNullOrWhitespace() || x.Manifest.Name.ToLowerInvariant().Contains(this.pickerSearch.ToLowerInvariant()))))
{
using var disabled2 =
ImRaii.Disabled(profile.Plugins.Any(y => y.InternalName == plugin.Manifest.InternalName));
if (ImGui.Selectable($"{plugin.Manifest.Name}{(plugin is LocalDevPlugin ? "(dev plugin)" : string.Empty)}###selector{plugin.Manifest.InternalName}"))
{
Task.Run(() => profile.AddOrUpdateAsync(plugin.EffectiveWorkingPluginId, plugin.Manifest.InternalName, true, false))
.ContinueWith(this.installer.DisplayErrorContinuation, Locs.ErrorCouldNotChangeState);
}
}
ImGui.EndListBox();
}
}
}
Task.Run(() => profile.AddOrUpdateAsync(plugin.EffectiveWorkingPluginId, plugin.Manifest.InternalName, true, false))
.ContinueWith(this.installer.DisplayErrorContinuation, Locs.ErrorCouldNotChangeState);
},
plugin => !plugin.Manifest.SupportsProfiles ||
profile.Plugins.Any(x => x.WorkingPluginId == plugin.EffectiveWorkingPluginId));
var didAny = false;
@ -603,8 +579,6 @@ internal class ProfileManagerWidget
public static string BackToOverview => Loc.Localize("ProfileManagerBackToOverview", "Back to overview");
public static string SearchHint => Loc.Localize("ProfileManagerSearchHint", "Search...");
public static string AddProfileHint => Loc.Localize("ProfileManagerAddProfileHint", "No collections! Add one!");
public static string CloneProfileHint => Loc.Localize("ProfileManagerCloneProfile", "Clone this collection");