mirror of
https://github.com/goatcorp/Dalamud.git
synced 2025-12-30 12:23:39 +01:00
Merge remote-tracking branch 'origin/master' into apiX-rollup
This commit is contained in:
commit
263610c9e7
28 changed files with 1526 additions and 311 deletions
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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");
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue