diff --git a/Dalamud/Interface/DalamudWindowOpenKinds.cs b/Dalamud/Interface/DalamudWindowOpenKinds.cs
index 1f82cca49..588ff858b 100644
--- a/Dalamud/Interface/DalamudWindowOpenKinds.cs
+++ b/Dalamud/Interface/DalamudWindowOpenKinds.cs
@@ -14,6 +14,11 @@ public enum PluginInstallerOpenKind
/// Open to the "Installed Plugins" page.
///
InstalledPlugins,
+
+ ///
+ /// Open to the "Can be updated" page.
+ ///
+ UpdateablePlugins,
///
/// Open to the "Changelogs" page.
diff --git a/Dalamud/Interface/Internal/PluginCategoryManager.cs b/Dalamud/Interface/Internal/PluginCategoryManager.cs
index 3f94b2d2e..a02dfffb9 100644
--- a/Dalamud/Interface/Internal/PluginCategoryManager.cs
+++ b/Dalamud/Interface/Internal/PluginCategoryManager.cs
@@ -28,6 +28,7 @@ internal class PluginCategoryManager
new(12, "special.dalamud", () => Locs.Category_Dalamud),
new(13, "special.plugins", () => Locs.Category_Plugins),
new(14, "special.profiles", () => Locs.Category_PluginProfiles),
+ new(15, "special.updateable", () => Locs.Category_UpdateablePlugins),
new(FirstTagBasedCategoryId + 0, "other", () => Locs.Category_Other),
new(FirstTagBasedCategoryId + 1, "jobs", () => Locs.Category_Jobs),
new(FirstTagBasedCategoryId + 2, "ui", () => Locs.Category_UI),
@@ -43,7 +44,7 @@ internal class PluginCategoryManager
private GroupInfo[] groupList =
{
new(GroupKind.DevTools, () => Locs.Group_DevTools, 10, 11),
- new(GroupKind.Installed, () => Locs.Group_Installed, 0, 1, 14),
+ new(GroupKind.Installed, () => Locs.Group_Installed, 0, 1, 15, 14),
new(GroupKind.Available, () => Locs.Group_Available, 0),
new(GroupKind.Changelog, () => Locs.Group_Changelog, 0, 12, 13),
@@ -432,6 +433,8 @@ internal class PluginCategoryManager
public static string Category_PluginProfiles => Loc.Localize("InstallerCategoryPluginProfiles", "Plugin Collections");
+ public static string Category_UpdateablePlugins => Loc.Localize("InstallerCategoryCanBeUpdated", "Can be updated");
+
public static string Category_Other => Loc.Localize("InstallerCategoryOther", "Other");
public static string Category_Jobs => Loc.Localize("InstallerCategoryJobs", "Jobs");
diff --git a/Dalamud/Interface/Internal/Windows/PluginInstaller/PluginInstallerWindow.cs b/Dalamud/Interface/Internal/Windows/PluginInstaller/PluginInstallerWindow.cs
index 05a352a53..046557e87 100644
--- a/Dalamud/Interface/Internal/Windows/PluginInstaller/PluginInstallerWindow.cs
+++ b/Dalamud/Interface/Internal/Windows/PluginInstaller/PluginInstallerWindow.cs
@@ -221,6 +221,14 @@ internal class PluginInstallerWindow : Window, IDisposable
IsTesting = 1 << 6,
}
+ private enum InstalledPluginListFilter
+ {
+ None,
+ Testing,
+ Updateable,
+ Dev,
+ }
+
private bool AnyOperationInProgress => this.installStatus == OperationStatus.InProgress ||
this.updateStatus == OperationStatus.InProgress ||
this.enableDisableStatus == OperationStatus.InProgress;
@@ -430,6 +438,12 @@ internal class PluginInstallerWindow : Window, IDisposable
// All category
this.categoryManager.CurrentCategoryIdx = 0;
break;
+ case PluginInstallerOpenKind.UpdateablePlugins:
+ // Installed group
+ this.categoryManager.CurrentGroupIdx = 1;
+ // Updateable category
+ this.categoryManager.CurrentCategoryIdx = 15;
+ break;
case PluginInstallerOpenKind.Changelogs:
// Changelog group
this.categoryManager.CurrentGroupIdx = 3;
@@ -1215,7 +1229,8 @@ internal class PluginInstallerWindow : Window, IDisposable
if (proxy.LocalPlugin != null)
{
- this.DrawInstalledPlugin(proxy.LocalPlugin, i++, proxy.RemoteManifest, true);
+ var update = this.pluginListUpdatable.FirstOrDefault(up => up.InstalledPlugin == proxy.LocalPlugin);
+ this.DrawInstalledPlugin(proxy.LocalPlugin, i++, proxy.RemoteManifest, update);
}
else if (proxy.RemoteManifest != null)
{
@@ -1225,8 +1240,8 @@ internal class PluginInstallerWindow : Window, IDisposable
ImGui.PopID();
}
}
-
- private void DrawInstalledPluginList(bool filterTesting)
+
+ private void DrawInstalledPluginList(InstalledPluginListFilter filter)
{
var pluginList = this.pluginListInstalled;
var manager = Service.Get();
@@ -1247,47 +1262,57 @@ internal class PluginInstallerWindow : Window, IDisposable
return;
}
+ var drewAny = false;
var i = 0;
foreach (var plugin in filteredList)
{
- if (filterTesting && !manager.HasTestingOptIn(plugin.Manifest))
+ if (filter == InstalledPluginListFilter.Testing && !manager.HasTestingOptIn(plugin.Manifest))
continue;
+
+ // Find applicable update and manifest, if we have them
+ AvailablePluginUpdate? update = null;
+ RemotePluginManifest? remoteManifest = null;
- // Find the applicable remote manifest
- var remoteManifest = this.pluginListAvailable
- .FirstOrDefault(rm => rm.InternalName == plugin.Manifest.InternalName &&
- rm.RepoUrl == plugin.Manifest.RepoUrl);
+ if (filter != InstalledPluginListFilter.Dev)
+ {
+ update = this.pluginListUpdatable.FirstOrDefault(up => up.InstalledPlugin == plugin);
+ if (filter == InstalledPluginListFilter.Updateable && update == null)
+ continue;
- this.DrawInstalledPlugin(plugin, i++, remoteManifest);
+ // Find the applicable remote manifest
+ remoteManifest = this.pluginListAvailable
+ .FirstOrDefault(rm => rm.InternalName == plugin.Manifest.InternalName &&
+ rm.RepoUrl == plugin.Manifest.RepoUrl);
+ }
+ else if (!plugin.IsDev)
+ {
+ continue;
+ }
+
+ this.DrawInstalledPlugin(plugin, i++, remoteManifest, update);
+ drewAny = true;
}
- }
-
- private void DrawInstalledDevPluginList()
- {
- var pluginList = this.pluginListInstalled
- .Where(plugin => plugin.IsDev)
- .ToList();
-
- if (pluginList.Count == 0)
+
+ if (!drewAny)
{
- ImGui.TextColored(ImGuiColors.DalamudGrey, Locs.TabBody_SearchNoInstalled);
- return;
- }
+ var text = filter switch
+ {
+ InstalledPluginListFilter.None => Locs.TabBody_NoPluginsInstalled,
+ InstalledPluginListFilter.Testing => Locs.TabBody_NoPluginsTesting,
+ InstalledPluginListFilter.Updateable => Locs.TabBody_NoPluginsUpdateable,
+ InstalledPluginListFilter.Dev => Locs.TabBody_NoPluginsDev,
+ _ => throw new ArgumentException(null, nameof(filter)),
+ };
+
+ ImGuiHelpers.ScaledDummy(60);
- var filteredList = pluginList
- .Where(plugin => !this.IsManifestFiltered(plugin.Manifest))
- .ToList();
-
- if (filteredList.Count == 0)
- {
- ImGui.TextColored(ImGuiColors.DalamudGrey2, Locs.TabBody_SearchNoMatching);
- return;
- }
-
- var i = 0;
- foreach (var plugin in filteredList)
- {
- this.DrawInstalledPlugin(plugin, i++, null);
+ using (ImRaii.PushColor(ImGuiCol.Text, ImGuiColors.DalamudGrey))
+ {
+ foreach (var line in text.Split('\n'))
+ {
+ ImGuiHelpers.CenteredText(line);
+ }
+ }
}
}
@@ -1462,7 +1487,7 @@ internal class PluginInstallerWindow : Window, IDisposable
switch (this.categoryManager.CurrentCategoryIdx)
{
case 0:
- this.DrawInstalledDevPluginList();
+ this.DrawInstalledPluginList(InstalledPluginListFilter.Dev);
break;
case 1:
@@ -1470,7 +1495,7 @@ internal class PluginInstallerWindow : Window, IDisposable
break;
default:
- // umm, there's nothing else, keep handled set and just skip drawing...
+ ImGui.TextUnformatted("You found a mysterious category. Please keep it to yourself.");
break;
}
@@ -1479,16 +1504,24 @@ internal class PluginInstallerWindow : Window, IDisposable
switch (this.categoryManager.CurrentCategoryIdx)
{
case 0:
- this.DrawInstalledPluginList(false);
+ this.DrawInstalledPluginList(InstalledPluginListFilter.None);
break;
case 1:
- this.DrawInstalledPluginList(true);
+ this.DrawInstalledPluginList(InstalledPluginListFilter.Testing);
+ break;
+
+ case 2:
+ this.DrawInstalledPluginList(InstalledPluginListFilter.Updateable);
break;
- case 2:
+ case 3:
this.profileManagerWidget.Draw();
break;
+
+ default:
+ ImGui.TextUnformatted("You found a secret category. Please feel a sense of pride and accomplishment.");
+ break;
}
break;
@@ -2325,7 +2358,7 @@ internal class PluginInstallerWindow : Window, IDisposable
}
}
- private void DrawInstalledPlugin(LocalPlugin plugin, int index, RemotePluginManifest? remoteManifest, bool showInstalled = false)
+ private void DrawInstalledPlugin(LocalPlugin plugin, int index, RemotePluginManifest? remoteManifest, AvailablePluginUpdate? availablePluginUpdate, bool showInstalled = false)
{
var configuration = Service.Get();
var commandManager = Service.Get();
@@ -2384,8 +2417,6 @@ internal class PluginInstallerWindow : Window, IDisposable
trouble = true;
}
- var availablePluginUpdate = this.pluginListUpdatable.FirstOrDefault(up => up.InstalledPlugin == plugin);
-
// Dev plugins can never update
if (plugin.IsDev)
availablePluginUpdate = null;
@@ -3684,7 +3715,16 @@ internal class PluginInstallerWindow : Window, IDisposable
public static string TabBody_DownloadFailed => Loc.Localize("InstallerDownloadFailed", "Download failed.");
public static string TabBody_SafeMode => Loc.Localize("InstallerSafeMode", "Dalamud is running in Plugin Safe Mode, restart to activate plugins.");
-
+
+ public static string TabBody_NoPluginsTesting => Loc.Localize("InstallerNoPluginsTesting", "You aren't testing any plugins at the moment!\nYou can opt in to testing versions in the plugin context menu.");
+
+ public static string TabBody_NoPluginsInstalled =>
+ string.Format(Loc.Localize("InstallerNoPluginsInstalled", "You don't have any plugins installed yet!\nYou can install them from the \"{0}\" tab."), PluginCategoryManager.Locs.Category_All);
+
+ public static string TabBody_NoPluginsUpdateable => Loc.Localize("InstallerNoPluginsUpdate", "No plugins have updates available at the moment.");
+
+ public static string TabBody_NoPluginsDev => Loc.Localize("InstallerNoPluginsDev", "You don't have any dev plugins. Add them some the settings.");
+
#endregion
#region Search text
diff --git a/Dalamud/Plugin/Internal/AutoUpdate/AutoUpdateManager.cs b/Dalamud/Plugin/Internal/AutoUpdate/AutoUpdateManager.cs
index 229566b3e..cbcbe637e 100644
--- a/Dalamud/Plugin/Internal/AutoUpdate/AutoUpdateManager.cs
+++ b/Dalamud/Plugin/Internal/AutoUpdate/AutoUpdateManager.cs
@@ -128,6 +128,17 @@ internal class AutoUpdateManager : IServiceType
_ => throw new ArgumentOutOfRangeException(nameof(behavior), behavior, null),
};
}
+
+ private static void DrawOpenInstallerNotificationButton(bool primary, IActiveNotification notification)
+ {
+ if (primary ?
+ DalamudComponents.PrimaryButton(Locs.NotificationButtonOpenPluginInstaller) :
+ DalamudComponents.SecondaryButton(Locs.NotificationButtonOpenPluginInstaller))
+ {
+ Service.Get().OpenPluginInstallerTo(PluginInstallerOpenKind.UpdateablePlugins);
+ notification.DismissNow();
+ }
+ }
private void OnUpdate(IFramework framework)
{
@@ -293,11 +304,7 @@ internal class AutoUpdateManager : IServiceType
notification.DrawActions += _ =>
{
ImGuiHelpers.ScaledDummy(2);
- if (DalamudComponents.PrimaryButton(Locs.NotificationButtonOpenPluginInstaller))
- {
- Service.Get().OpenPluginInstaller();
- notification.DismissNow();
- }
+ DrawOpenInstallerNotificationButton(true, notification);
};
// Update the notification to show the final state
@@ -356,11 +363,7 @@ internal class AutoUpdateManager : IServiceType
}
ImGui.SameLine();
- if (DalamudComponents.SecondaryButton(Locs.NotificationButtonOpenPluginInstaller))
- {
- Service.Get().OpenPluginInstaller();
- notification.DismissNow();
- }
+ DrawOpenInstallerNotificationButton(false, notification);
};
}