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); }; }