mirror of
https://github.com/goatcorp/Dalamud.git
synced 2025-12-12 18:27:23 +01:00
- Add chat notification back to AutoUpdate (#2146)
- ImRaii UI elements in AutoUpdate tab - Fix scoping in IconButton
This commit is contained in:
parent
f7ef68d65e
commit
2e6cb6ef00
5 changed files with 166 additions and 114 deletions
|
|
@ -249,7 +249,7 @@ internal sealed class DalamudConfiguration : IInternalDisposableService
|
|||
/// Gets or sets a value indicating whether or not docking should be globally enabled in ImGui.
|
||||
/// </summary>
|
||||
public bool IsDocking { get; set; }
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating whether or not plugin user interfaces should trigger sound effects.
|
||||
/// This setting is effected by the in-game "System Sounds" option and volume.
|
||||
|
|
@ -484,10 +484,15 @@ internal sealed class DalamudConfiguration : IInternalDisposableService
|
|||
public AutoUpdateBehavior? AutoUpdateBehavior { get; set; } = null;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating whether or not users should be notified regularly about pending updates.
|
||||
/// Gets or sets a value indicating whether users should be notified regularly about pending updates.
|
||||
/// </summary>
|
||||
public bool CheckPeriodicallyForUpdates { get; set; } = true;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating whether users should be notified about updates in chat.
|
||||
/// </summary>
|
||||
public bool SendUpdateNotificationToChat { get; set; } = false;
|
||||
|
||||
/// <summary>
|
||||
/// Load a configuration from the provided path.
|
||||
/// </summary>
|
||||
|
|
@ -504,7 +509,7 @@ internal sealed class DalamudConfiguration : IInternalDisposableService
|
|||
{
|
||||
deserialized =
|
||||
JsonConvert.DeserializeObject<DalamudConfiguration>(text, SerializerSettings);
|
||||
|
||||
|
||||
// If this reads as null, the file was empty, that's no good
|
||||
if (deserialized == null)
|
||||
throw new Exception("Read config was null.");
|
||||
|
|
@ -530,7 +535,7 @@ internal sealed class DalamudConfiguration : IInternalDisposableService
|
|||
{
|
||||
Log.Error(e, "Failed to set defaults for DalamudConfiguration");
|
||||
}
|
||||
|
||||
|
||||
return deserialized;
|
||||
}
|
||||
|
||||
|
|
@ -549,7 +554,7 @@ internal sealed class DalamudConfiguration : IInternalDisposableService
|
|||
{
|
||||
this.Save();
|
||||
}
|
||||
|
||||
|
||||
/// <inheritdoc/>
|
||||
void IInternalDisposableService.DisposeService()
|
||||
{
|
||||
|
|
@ -595,14 +600,14 @@ internal sealed class DalamudConfiguration : IInternalDisposableService
|
|||
this.ReduceMotions = winAnimEnabled == 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Migrate old auto-update setting to new auto-update behavior
|
||||
this.AutoUpdateBehavior ??= this.AutoUpdatePlugins
|
||||
? Plugin.Internal.AutoUpdate.AutoUpdateBehavior.UpdateAll
|
||||
: Plugin.Internal.AutoUpdate.AutoUpdateBehavior.OnlyNotify;
|
||||
#pragma warning restore CS0618
|
||||
}
|
||||
|
||||
|
||||
private void Save()
|
||||
{
|
||||
ThreadSafety.AssertMainThread();
|
||||
|
|
|
|||
|
|
@ -272,15 +272,14 @@ public static partial class ImGuiComponents
|
|||
/// <returns>Width.</returns>
|
||||
public static float GetIconButtonWithTextWidth(FontAwesomeIcon icon, string text)
|
||||
{
|
||||
Vector2 iconSize;
|
||||
using (ImRaii.PushFont(UiBuilder.IconFont))
|
||||
{
|
||||
var iconSize = ImGui.CalcTextSize(icon.ToIconString());
|
||||
|
||||
var textSize = ImGui.CalcTextSize(text);
|
||||
|
||||
var iconPadding = 3 * ImGuiHelpers.GlobalScale;
|
||||
|
||||
return iconSize.X + textSize.X + (ImGui.GetStyle().FramePadding.X * 2) + iconPadding;
|
||||
iconSize = ImGui.CalcTextSize(icon.ToIconString());
|
||||
}
|
||||
|
||||
var textSize = ImGui.CalcTextSize(text);
|
||||
var iconPadding = 3 * ImGuiHelpers.GlobalScale;
|
||||
return iconSize.X + textSize.X + (ImGui.GetStyle().FramePadding.X * 2) + iconPadding;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -32,19 +32,21 @@ internal static partial class DalamudComponents
|
|||
var pm = Service<PluginManager>.GetNullable();
|
||||
if (pm == null)
|
||||
return 0;
|
||||
|
||||
|
||||
var addPluginToProfilePopupId = ImGui.GetID(id);
|
||||
using var popup = ImRaii.Popup(id);
|
||||
|
||||
if (popup.Success)
|
||||
{
|
||||
var width = ImGuiHelpers.GlobalScale * 300;
|
||||
|
||||
|
||||
ImGui.SetNextItemWidth(width);
|
||||
ImGui.InputTextWithHint("###pluginPickerSearch", Locs.SearchHint, ref pickerSearch, 255);
|
||||
|
||||
var currentSearchString = pickerSearch;
|
||||
if (ImGui.BeginListBox("###pluginPicker", new Vector2(width, width - 80)))
|
||||
|
||||
using var listBox = ImRaii.ListBox("###pluginPicker", new Vector2(width, width - 80));
|
||||
if (listBox.Success)
|
||||
{
|
||||
// TODO: Plugin searching should be abstracted... installer and this should use the same search
|
||||
var plugins = pm.InstalledPlugins.Where(
|
||||
|
|
@ -53,19 +55,15 @@ internal static partial class DalamudComponents
|
|||
currentSearchString,
|
||||
StringComparison.InvariantCultureIgnoreCase)))
|
||||
.Where(pluginFiltered ?? (_ => true));
|
||||
|
||||
|
||||
foreach (var plugin in plugins)
|
||||
{
|
||||
using var disabled2 =
|
||||
ImRaii.Disabled(pluginDisabled(plugin));
|
||||
|
||||
using var disabled2 = ImRaii.Disabled(pluginDisabled(plugin));
|
||||
if (ImGui.Selectable($"{plugin.Manifest.Name}{(plugin is LocalDevPlugin ? "(dev plugin)" : string.Empty)}###selector{plugin.Manifest.InternalName}"))
|
||||
{
|
||||
onClicked(plugin);
|
||||
}
|
||||
}
|
||||
|
||||
ImGui.EndListBox();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -23,10 +23,11 @@ public class SettingsTabAutoUpdates : SettingsTab
|
|||
{
|
||||
private AutoUpdateBehavior behavior;
|
||||
private bool checkPeriodically;
|
||||
private bool chatNotification;
|
||||
private string pickerSearch = string.Empty;
|
||||
private List<AutoUpdatePreference> autoUpdatePreferences = [];
|
||||
|
||||
public override SettingsEntry[] Entries { get; } = Array.Empty<SettingsEntry>();
|
||||
|
||||
public override SettingsEntry[] Entries { get; } = [];
|
||||
|
||||
public override string Title => Loc.Localize("DalamudSettingsAutoUpdates", "Auto-Updates");
|
||||
|
||||
|
|
@ -36,15 +37,15 @@ public class SettingsTabAutoUpdates : SettingsTab
|
|||
"Dalamud can update your plugins automatically, making sure that you always " +
|
||||
"have the newest features and bug fixes. You can choose when and how auto-updates are run here."));
|
||||
ImGuiHelpers.ScaledDummy(2);
|
||||
|
||||
|
||||
ImGuiHelpers.SafeTextColoredWrapped(ImGuiColors.DalamudGrey, Loc.Localize("DalamudSettingsAutoUpdateDisclaimer1",
|
||||
"You can always update your plugins manually by clicking the update button in the plugin list. " +
|
||||
"You can also opt into updates for specific plugins by right-clicking them and selecting \"Always auto-update\"."));
|
||||
ImGuiHelpers.SafeTextColoredWrapped(ImGuiColors.DalamudGrey, Loc.Localize("DalamudSettingsAutoUpdateDisclaimer2",
|
||||
"Dalamud will only notify you about updates while you are idle."));
|
||||
|
||||
|
||||
ImGuiHelpers.ScaledDummy(8);
|
||||
|
||||
|
||||
ImGuiHelpers.SafeTextColoredWrapped(ImGuiColors.DalamudWhite, Loc.Localize("DalamudSettingsAutoUpdateBehavior",
|
||||
"When the game starts..."));
|
||||
var behaviorInt = (int)this.behavior;
|
||||
|
|
@ -62,20 +63,21 @@ public class SettingsTabAutoUpdates : SettingsTab
|
|||
"These updates are not reviewed by the Dalamud team and may contain malicious code.");
|
||||
ImGuiHelpers.SafeTextColoredWrapped(ImGuiColors.DalamudOrange, warning);
|
||||
}
|
||||
|
||||
|
||||
ImGuiHelpers.ScaledDummy(8);
|
||||
|
||||
|
||||
ImGui.Checkbox(Loc.Localize("DalamudSettingsAutoUpdateChatMessage", "Show notification about updates available in chat"), ref this.chatNotification);
|
||||
ImGui.Checkbox(Loc.Localize("DalamudSettingsAutoUpdatePeriodically", "Periodically check for new updates while playing"), ref this.checkPeriodically);
|
||||
ImGuiHelpers.SafeTextColoredWrapped(ImGuiColors.DalamudGrey, Loc.Localize("DalamudSettingsAutoUpdatePeriodicallyHint",
|
||||
"Plugins won't update automatically after startup, you will only receive a notification while you are not actively playing."));
|
||||
|
||||
|
||||
ImGuiHelpers.ScaledDummy(5);
|
||||
ImGui.Separator();
|
||||
ImGuiHelpers.ScaledDummy(5);
|
||||
|
||||
|
||||
ImGuiHelpers.SafeTextColoredWrapped(ImGuiColors.DalamudWhite, Loc.Localize("DalamudSettingsAutoUpdateOptedIn",
|
||||
"Per-plugin overrides"));
|
||||
|
||||
|
||||
ImGuiHelpers.SafeTextColoredWrapped(ImGuiColors.DalamudWhite, Loc.Localize("DalamudSettingsAutoUpdateOverrideHint",
|
||||
"Here, you can choose to receive or not to receive updates for specific plugins. " +
|
||||
"This will override the settings above for the selected plugins."));
|
||||
|
|
@ -83,25 +85,25 @@ public class SettingsTabAutoUpdates : SettingsTab
|
|||
if (this.autoUpdatePreferences.Count == 0)
|
||||
{
|
||||
ImGuiHelpers.ScaledDummy(20);
|
||||
|
||||
|
||||
using (ImRaii.PushColor(ImGuiCol.Text, ImGuiColors.DalamudGrey))
|
||||
{
|
||||
ImGuiHelpers.CenteredText(Loc.Localize("DalamudSettingsAutoUpdateOptedInHint2",
|
||||
"You don't have auto-update rules for any plugins."));
|
||||
}
|
||||
|
||||
|
||||
ImGuiHelpers.ScaledDummy(2);
|
||||
}
|
||||
else
|
||||
{
|
||||
ImGuiHelpers.ScaledDummy(5);
|
||||
|
||||
|
||||
var pic = Service<PluginImageCache>.Get();
|
||||
|
||||
var windowSize = ImGui.GetWindowSize();
|
||||
var pluginLineHeight = 32 * ImGuiHelpers.GlobalScale;
|
||||
Guid? wantRemovePluginGuid = null;
|
||||
|
||||
|
||||
foreach (var preference in this.autoUpdatePreferences)
|
||||
{
|
||||
var pmPlugin = Service<PluginManager>.Get().InstalledPlugins
|
||||
|
|
@ -120,11 +122,12 @@ public class SettingsTabAutoUpdates : SettingsTab
|
|||
if (pmPlugin.IsDev)
|
||||
{
|
||||
ImGui.SetCursorPos(cursorBeforeIcon);
|
||||
ImGui.PushStyleVar(ImGuiStyleVar.Alpha, 0.7f);
|
||||
ImGui.Image(pic.DevPluginIcon.ImGuiHandle, new Vector2(pluginLineHeight));
|
||||
ImGui.PopStyleVar();
|
||||
using (ImRaii.PushStyle(ImGuiStyleVar.Alpha, 0.7f))
|
||||
{
|
||||
ImGui.Image(pic.DevPluginIcon.ImGuiHandle, new Vector2(pluginLineHeight));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
ImGui.SameLine();
|
||||
|
||||
var text = $"{pmPlugin.Name}{(pmPlugin.IsDev ? " (dev plugin" : string.Empty)}";
|
||||
|
|
@ -147,7 +150,7 @@ public class SettingsTabAutoUpdates : SettingsTab
|
|||
|
||||
ImGui.SetCursorPosY(ImGui.GetCursorPosY() + (pluginLineHeight / 2) - (textHeight.Y / 2));
|
||||
ImGui.TextUnformatted(text);
|
||||
|
||||
|
||||
ImGui.SetCursorPos(before);
|
||||
}
|
||||
|
||||
|
|
@ -166,19 +169,18 @@ public class SettingsTabAutoUpdates : SettingsTab
|
|||
}
|
||||
|
||||
ImGui.SetNextItemWidth(ImGuiHelpers.GlobalScale * 250);
|
||||
if (ImGui.BeginCombo(
|
||||
$"###autoUpdateBehavior{preference.WorkingPluginId}",
|
||||
OptKindToString(preference.Kind)))
|
||||
using (var combo = ImRaii.Combo($"###autoUpdateBehavior{preference.WorkingPluginId}", OptKindToString(preference.Kind)))
|
||||
{
|
||||
foreach (var kind in Enum.GetValues<AutoUpdatePreference.OptKind>())
|
||||
if (combo.Success)
|
||||
{
|
||||
if (ImGui.Selectable(OptKindToString(kind)))
|
||||
foreach (var kind in Enum.GetValues<AutoUpdatePreference.OptKind>())
|
||||
{
|
||||
preference.Kind = kind;
|
||||
if (ImGui.Selectable(OptKindToString(kind)))
|
||||
{
|
||||
preference.Kind = kind;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ImGui.EndCombo();
|
||||
}
|
||||
|
||||
ImGui.SameLine();
|
||||
|
|
@ -193,7 +195,7 @@ public class SettingsTabAutoUpdates : SettingsTab
|
|||
if (ImGui.IsItemHovered())
|
||||
ImGui.SetTooltip(Loc.Localize("DalamudSettingsAutoUpdateOptInRemove", "Remove this override"));
|
||||
}
|
||||
|
||||
|
||||
if (wantRemovePluginGuid != null)
|
||||
{
|
||||
this.autoUpdatePreferences.RemoveAll(x => x.WorkingPluginId == wantRemovePluginGuid);
|
||||
|
|
@ -205,19 +207,19 @@ public class SettingsTabAutoUpdates : SettingsTab
|
|||
var id = plugin.EffectiveWorkingPluginId;
|
||||
if (id == Guid.Empty)
|
||||
throw new InvalidOperationException("Plugin ID is empty.");
|
||||
|
||||
|
||||
this.autoUpdatePreferences.Add(new AutoUpdatePreference(id));
|
||||
}
|
||||
|
||||
|
||||
bool IsPluginDisabled(LocalPlugin plugin)
|
||||
=> this.autoUpdatePreferences.Any(x => x.WorkingPluginId == plugin.EffectiveWorkingPluginId);
|
||||
|
||||
|
||||
bool IsPluginFiltered(LocalPlugin plugin)
|
||||
=> !plugin.IsDev;
|
||||
|
||||
|
||||
var pickerId = DalamudComponents.DrawPluginPicker(
|
||||
"###autoUpdatePicker", ref this.pickerSearch, OnPluginPicked, IsPluginDisabled, IsPluginFiltered);
|
||||
|
||||
|
||||
const FontAwesomeIcon addButtonIcon = FontAwesomeIcon.Plus;
|
||||
var addButtonText = Loc.Localize("DalamudSettingsAutoUpdateOptInAdd", "Add new override");
|
||||
ImGuiHelpers.CenterCursorFor(ImGuiComponents.GetIconButtonWithTextWidth(addButtonIcon, addButtonText));
|
||||
|
|
@ -235,20 +237,22 @@ public class SettingsTabAutoUpdates : SettingsTab
|
|||
var configuration = Service<DalamudConfiguration>.Get();
|
||||
|
||||
this.behavior = configuration.AutoUpdateBehavior ?? AutoUpdateBehavior.None;
|
||||
this.chatNotification = configuration.SendUpdateNotificationToChat;
|
||||
this.checkPeriodically = configuration.CheckPeriodicallyForUpdates;
|
||||
this.autoUpdatePreferences = configuration.PluginAutoUpdatePreferences;
|
||||
|
||||
|
||||
base.Load();
|
||||
}
|
||||
|
||||
public override void Save()
|
||||
{
|
||||
var configuration = Service<DalamudConfiguration>.Get();
|
||||
|
||||
|
||||
configuration.AutoUpdateBehavior = this.behavior;
|
||||
configuration.SendUpdateNotificationToChat = this.chatNotification;
|
||||
configuration.CheckPeriodicallyForUpdates = this.checkPeriodically;
|
||||
configuration.PluginAutoUpdatePreferences = this.autoUpdatePreferences;
|
||||
|
||||
|
||||
base.Save();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -9,6 +9,10 @@ using Dalamud.Console;
|
|||
using Dalamud.Game;
|
||||
using Dalamud.Game.ClientState;
|
||||
using Dalamud.Game.ClientState.Conditions;
|
||||
using Dalamud.Game.Gui;
|
||||
using Dalamud.Game.Text;
|
||||
using Dalamud.Game.Text.SeStringHandling;
|
||||
using Dalamud.Game.Text.SeStringHandling.Payloads;
|
||||
using Dalamud.Interface;
|
||||
using Dalamud.Interface.ImGuiNotification;
|
||||
using Dalamud.Interface.ImGuiNotification.EventArgs;
|
||||
|
|
@ -31,17 +35,17 @@ namespace Dalamud.Plugin.Internal.AutoUpdate;
|
|||
internal class AutoUpdateManager : IServiceType
|
||||
{
|
||||
private static readonly ModuleLog Log = new("AUTOUPDATE");
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Time we should wait after login to update.
|
||||
/// </summary>
|
||||
private static readonly TimeSpan UpdateTimeAfterLogin = TimeSpan.FromSeconds(20);
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Time we should wait between scheduled update checks.
|
||||
/// </summary>
|
||||
private static readonly TimeSpan TimeBetweenUpdateChecks = TimeSpan.FromHours(2);
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Time we should wait between scheduled update checks if the user has dismissed the notification,
|
||||
/// instead of updating. We don't want to spam the user with notifications.
|
||||
|
|
@ -56,28 +60,30 @@ internal class AutoUpdateManager : IServiceType
|
|||
|
||||
[ServiceManager.ServiceDependency]
|
||||
private readonly PluginManager pluginManager = Service<PluginManager>.Get();
|
||||
|
||||
|
||||
[ServiceManager.ServiceDependency]
|
||||
private readonly DalamudConfiguration config = Service<DalamudConfiguration>.Get();
|
||||
|
||||
|
||||
[ServiceManager.ServiceDependency]
|
||||
private readonly NotificationManager notificationManager = Service<NotificationManager>.Get();
|
||||
|
||||
|
||||
[ServiceManager.ServiceDependency]
|
||||
private readonly DalamudInterface dalamudInterface = Service<DalamudInterface>.Get();
|
||||
|
||||
|
||||
private readonly IConsoleVariable<bool> isDryRun;
|
||||
|
||||
|
||||
private DateTime? loginTime;
|
||||
private DateTime? nextUpdateCheckTime;
|
||||
private DateTime? unblockedSince;
|
||||
|
||||
|
||||
private bool hasStartedInitialUpdateThisSession;
|
||||
|
||||
private IActiveNotification? updateNotification;
|
||||
|
||||
|
||||
private Task? autoUpdateTask;
|
||||
|
||||
|
||||
private readonly Task<DalamudLinkPayload> openInstallerWindowLink;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="AutoUpdateManager"/> class.
|
||||
/// </summary>
|
||||
|
|
@ -92,7 +98,18 @@ internal class AutoUpdateManager : IServiceType
|
|||
t.Result.Logout += (int type, int code) => this.OnLogout();
|
||||
});
|
||||
Service<Framework>.GetAsync().ContinueWith(t => { t.Result.Update += this.OnUpdate; });
|
||||
|
||||
|
||||
this.openInstallerWindowLink =
|
||||
Service<ChatGui>.GetAsync().ContinueWith(
|
||||
chatGuiTask => chatGuiTask.Result.AddChatLinkHandler(
|
||||
"Dalamud",
|
||||
1001,
|
||||
(_, _) =>
|
||||
{
|
||||
Service<DalamudInterface>.GetNullable()?.OpenPluginInstallerTo(PluginInstallerOpenKind.InstalledPlugins);
|
||||
}));
|
||||
|
||||
|
||||
this.isDryRun = console.AddVariable("dalamud.autoupdate.dry_run", "Simulate updates instead", false);
|
||||
console.AddCommand("dalamud.autoupdate.trigger_login", "Trigger a login event", () =>
|
||||
{
|
||||
|
|
@ -106,36 +123,36 @@ internal class AutoUpdateManager : IServiceType
|
|||
return true;
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
private enum UpdateListingRestriction
|
||||
{
|
||||
Unrestricted,
|
||||
AllowNone,
|
||||
AllowMainRepo,
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Gets a value indicating whether or not auto-updates have already completed this session.
|
||||
/// </summary>
|
||||
public bool IsAutoUpdateComplete { get; private set; }
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Gets the time of the next scheduled update check.
|
||||
/// </summary>
|
||||
public DateTime? NextUpdateCheckTime => this.nextUpdateCheckTime;
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Gets the time the auto-update was unblocked.
|
||||
/// </summary>
|
||||
public DateTime? UnblockedSince => this.unblockedSince;
|
||||
|
||||
|
||||
private static UpdateListingRestriction DecideUpdateListingRestriction(AutoUpdateBehavior behavior)
|
||||
{
|
||||
return behavior switch
|
||||
{
|
||||
// We don't generally allow any updates in this mode, but specific opt-ins.
|
||||
AutoUpdateBehavior.None => UpdateListingRestriction.AllowNone,
|
||||
|
||||
|
||||
// If we're only notifying, I guess it's fine to list all plugins.
|
||||
AutoUpdateBehavior.OnlyNotify => UpdateListingRestriction.Unrestricted,
|
||||
|
||||
|
|
@ -144,7 +161,7 @@ internal class AutoUpdateManager : IServiceType
|
|||
_ => throw new ArgumentOutOfRangeException(nameof(behavior), behavior, null),
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
private static void DrawOpenInstallerNotificationButton(bool primary, PluginInstallerOpenKind kind, IActiveNotification notification)
|
||||
{
|
||||
if (primary ?
|
||||
|
|
@ -179,7 +196,7 @@ internal class AutoUpdateManager : IServiceType
|
|||
this.updateNotification = null;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// If we're blocked, we don't do anything.
|
||||
if (!isUnblocked)
|
||||
return;
|
||||
|
|
@ -199,16 +216,16 @@ internal class AutoUpdateManager : IServiceType
|
|||
if (!this.hasStartedInitialUpdateThisSession && DateTime.Now > this.loginTime.Value.Add(UpdateTimeAfterLogin))
|
||||
{
|
||||
this.hasStartedInitialUpdateThisSession = true;
|
||||
|
||||
|
||||
var currentlyUpdatablePlugins = this.GetAvailablePluginUpdates(DecideUpdateListingRestriction(behavior));
|
||||
if (currentlyUpdatablePlugins.Count == 0)
|
||||
{
|
||||
this.IsAutoUpdateComplete = true;
|
||||
this.nextUpdateCheckTime = DateTime.Now + TimeBetweenUpdateChecks;
|
||||
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
// TODO: This is not 100% what we want... Plugins that are opted-in should be updated regardless of the behavior,
|
||||
// and we should show a notification for the others afterwards.
|
||||
if (behavior == AutoUpdateBehavior.OnlyNotify)
|
||||
|
|
@ -241,6 +258,7 @@ internal class AutoUpdateManager : IServiceType
|
|||
Log.Error(t.Exception!, "Failed to reload plugin masters for auto-update");
|
||||
}
|
||||
|
||||
Log.Verbose($"Available Updates: {string.Join(", ", this.pluginManager.UpdatablePlugins.Select(s => s.UpdateManifest.InternalName))}");
|
||||
var updatable = this.GetAvailablePluginUpdates(
|
||||
DecideUpdateListingRestriction(behavior));
|
||||
|
||||
|
|
@ -252,7 +270,7 @@ internal class AutoUpdateManager : IServiceType
|
|||
{
|
||||
this.nextUpdateCheckTime = DateTime.Now + TimeBetweenUpdateChecks;
|
||||
Log.Verbose(
|
||||
"Auto update found nothing to do, next update at {Time}",
|
||||
"Auto update found nothing to do, next update at {Time}",
|
||||
this.nextUpdateCheckTime);
|
||||
}
|
||||
});
|
||||
|
|
@ -263,13 +281,13 @@ internal class AutoUpdateManager : IServiceType
|
|||
{
|
||||
if (this.updateNotification != null)
|
||||
throw new InvalidOperationException("Already showing a notification");
|
||||
|
||||
|
||||
this.updateNotification = this.notificationManager.AddNotification(notification);
|
||||
|
||||
this.updateNotification.Dismiss += _ =>
|
||||
{
|
||||
this.updateNotification = null;
|
||||
|
||||
|
||||
// Schedule the next update opportunistically for when this closes.
|
||||
this.nextUpdateCheckTime = DateTime.Now + TimeBetweenUpdateChecks;
|
||||
};
|
||||
|
|
@ -291,7 +309,7 @@ internal class AutoUpdateManager : IServiceType
|
|||
{
|
||||
Log.Warning("Auto-update task was canceled");
|
||||
}
|
||||
|
||||
|
||||
this.autoUpdateTask = null;
|
||||
this.IsAutoUpdateComplete = true;
|
||||
});
|
||||
|
|
@ -321,20 +339,20 @@ internal class AutoUpdateManager : IServiceType
|
|||
notification.Content = Locs.NotificationContentUpdating(updateProgress.CurrentPluginManifest.Name);
|
||||
notification.Progress = (float)updateProgress.PluginsProcessed / updateProgress.TotalPlugins;
|
||||
};
|
||||
|
||||
|
||||
var pluginStates = (await this.pluginManager.UpdatePluginsAsync(updatablePlugins, this.isDryRun.Value, true, progress)).ToList();
|
||||
this.pluginManager.PrintUpdatedPlugins(pluginStates, Loc.Localize("DalamudPluginAutoUpdate", "The following plugins were auto-updated:"));
|
||||
|
||||
notification.Progress = 1;
|
||||
notification.UserDismissable = true;
|
||||
notification.HardExpiry = DateTime.Now.AddSeconds(30);
|
||||
|
||||
|
||||
notification.DrawActions += _ =>
|
||||
{
|
||||
ImGuiHelpers.ScaledDummy(2);
|
||||
DrawOpenInstallerNotificationButton(true, PluginInstallerOpenKind.InstalledPlugins, notification);
|
||||
};
|
||||
|
||||
|
||||
// Update the notification to show the final state
|
||||
if (pluginStates.All(x => x.Status == PluginUpdateStatus.StatusKind.Success))
|
||||
{
|
||||
|
|
@ -342,7 +360,7 @@ internal class AutoUpdateManager : IServiceType
|
|||
|
||||
// Janky way to make sure the notification does not change before it's minimized...
|
||||
await Task.Delay(500);
|
||||
|
||||
|
||||
notification.Title = Locs.NotificationTitleUpdatesSuccessful;
|
||||
notification.MinimizedText = Locs.NotificationContentUpdatesSuccessfulMinimized;
|
||||
notification.Type = NotificationType.Success;
|
||||
|
|
@ -354,11 +372,11 @@ internal class AutoUpdateManager : IServiceType
|
|||
notification.MinimizedText = Locs.NotificationContentUpdatesFailedMinimized;
|
||||
notification.Type = NotificationType.Error;
|
||||
notification.Content = Locs.NotificationContentUpdatesFailed;
|
||||
|
||||
|
||||
var failedPlugins = pluginStates
|
||||
.Where(x => x.Status != PluginUpdateStatus.StatusKind.Success)
|
||||
.Select(x => x.Name).ToList();
|
||||
|
||||
|
||||
notification.Content += "\n" + Locs.NotificationContentFailedPlugins(failedPlugins);
|
||||
}
|
||||
}
|
||||
|
|
@ -367,7 +385,7 @@ internal class AutoUpdateManager : IServiceType
|
|||
{
|
||||
if (updatablePlugins.Count == 0)
|
||||
return;
|
||||
|
||||
|
||||
var notification = this.GetBaseNotification(new Notification
|
||||
{
|
||||
Title = Locs.NotificationTitleUpdatesAvailable,
|
||||
|
|
@ -400,16 +418,44 @@ internal class AutoUpdateManager : IServiceType
|
|||
notification.Dismiss += args =>
|
||||
{
|
||||
if (args.Reason != NotificationDismissReason.Manual) return;
|
||||
|
||||
|
||||
this.nextUpdateCheckTime = DateTime.Now + TimeBetweenUpdateChecksIfDismissed;
|
||||
Log.Verbose("User dismissed update notification, next check at {Time}", this.nextUpdateCheckTime);
|
||||
};
|
||||
|
||||
// Send out a chat message only if the user requested so
|
||||
if (!this.config.SendUpdateNotificationToChat)
|
||||
return;
|
||||
|
||||
var chatGui = Service<ChatGui>.GetNullable();
|
||||
if (chatGui == null)
|
||||
{
|
||||
Log.Verbose("Unable to get chat gui, discard notification for chat.");
|
||||
return;
|
||||
}
|
||||
|
||||
chatGui.Print(new XivChatEntry
|
||||
{
|
||||
Message = new SeString(new List<Payload>
|
||||
{
|
||||
new TextPayload(Locs.NotificationContentUpdatesAvailableMinimized(updatablePlugins.Count)),
|
||||
new TextPayload(" ["),
|
||||
new UIForegroundPayload(500),
|
||||
this.openInstallerWindowLink.Result,
|
||||
new TextPayload(Loc.Localize("DalamudInstallerHelp", "Open the plugin installer")),
|
||||
RawPayload.LinkTerminator,
|
||||
new UIForegroundPayload(0),
|
||||
new TextPayload("]"),
|
||||
}),
|
||||
|
||||
Type = XivChatType.Urgent,
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
private List<AvailablePluginUpdate> GetAvailablePluginUpdates(UpdateListingRestriction restriction)
|
||||
{
|
||||
var optIns = this.config.PluginAutoUpdatePreferences.ToArray();
|
||||
|
||||
|
||||
// Get all of our updatable plugins and do some initial filtering that must apply to all plugins.
|
||||
var updateablePlugins = this.pluginManager.UpdatablePlugins
|
||||
.Where(
|
||||
|
|
@ -423,14 +469,14 @@ internal class AutoUpdateManager : IServiceType
|
|||
bool FilterPlugin(AvailablePluginUpdate availablePluginUpdate)
|
||||
{
|
||||
var optIn = optIns.FirstOrDefault(x => x.WorkingPluginId == availablePluginUpdate.InstalledPlugin.EffectiveWorkingPluginId);
|
||||
|
||||
|
||||
// If this is an opt-out, we don't update.
|
||||
if (optIn is { Kind: AutoUpdatePreference.OptKind.NeverUpdate })
|
||||
return false;
|
||||
|
||||
if (restriction == UpdateListingRestriction.AllowNone && optIn is not { Kind: AutoUpdatePreference.OptKind.AlwaysUpdate })
|
||||
return false;
|
||||
|
||||
|
||||
if (restriction == UpdateListingRestriction.AllowMainRepo && availablePluginUpdate.InstalledPlugin.IsThirdParty)
|
||||
return false;
|
||||
|
||||
|
|
@ -442,7 +488,7 @@ internal class AutoUpdateManager : IServiceType
|
|||
{
|
||||
this.loginTime = DateTime.Now;
|
||||
}
|
||||
|
||||
|
||||
private void OnLogout()
|
||||
{
|
||||
this.loginTime = null;
|
||||
|
|
@ -452,7 +498,7 @@ internal class AutoUpdateManager : IServiceType
|
|||
{
|
||||
var condition = Service<Condition>.Get();
|
||||
return this.IsPluginManagerReady() &&
|
||||
!this.dalamudInterface.IsPluginInstallerOpen &&
|
||||
!this.dalamudInterface.IsPluginInstallerOpen &&
|
||||
condition.OnlyAny(ConditionFlag.NormalConditions,
|
||||
ConditionFlag.Jumping,
|
||||
ConditionFlag.Mounted,
|
||||
|
|
@ -469,21 +515,21 @@ internal class AutoUpdateManager : IServiceType
|
|||
public static string NotificationButtonOpenPluginInstaller => Loc.Localize("AutoUpdateOpenPluginInstaller", "Open installer");
|
||||
|
||||
public static string NotificationButtonUpdate => Loc.Localize("AutoUpdateUpdate", "Update");
|
||||
|
||||
|
||||
public static string NotificationTitleUpdatesAvailable => Loc.Localize("AutoUpdateUpdatesAvailable", "Updates available!");
|
||||
|
||||
|
||||
public static string NotificationTitleUpdatesSuccessful => Loc.Localize("AutoUpdateUpdatesSuccessful", "Updates successful!");
|
||||
|
||||
|
||||
public static string NotificationTitleUpdatingPlugins => Loc.Localize("AutoUpdateUpdatingPlugins", "Updating plugins...");
|
||||
|
||||
|
||||
public static string NotificationTitleUpdatesFailed => Loc.Localize("AutoUpdateUpdatesFailed", "Updates failed!");
|
||||
|
||||
|
||||
public static string NotificationContentUpdatesSuccessful => Loc.Localize("AutoUpdateUpdatesSuccessfulContent", "All plugins have been updated successfully.");
|
||||
|
||||
|
||||
public static string NotificationContentUpdatesSuccessfulMinimized => Loc.Localize("AutoUpdateUpdatesSuccessfulContentMinimized", "Plugins updated successfully.");
|
||||
|
||||
|
||||
public static string NotificationContentUpdatesFailed => Loc.Localize("AutoUpdateUpdatesFailedContent", "Some plugins failed to update. Please check the plugin installer for more information.");
|
||||
|
||||
|
||||
public static string NotificationContentUpdatesFailedMinimized => Loc.Localize("AutoUpdateUpdatesFailedContentMinimized", "Plugins failed to update.");
|
||||
|
||||
public static string NotificationContentUpdatesAvailable(ICollection<AvailablePluginUpdate> updatablePlugins)
|
||||
|
|
@ -497,20 +543,20 @@ internal class AutoUpdateManager : IServiceType
|
|||
"There are {0} plugins that can be updated:"),
|
||||
updatablePlugins.Count))
|
||||
+ "\n\n" + string.Join(", ", updatablePlugins.Select(x => x.InstalledPlugin.Manifest.Name));
|
||||
|
||||
|
||||
public static string NotificationContentUpdatesAvailableMinimized(int numUpdates)
|
||||
=> numUpdates == 1 ?
|
||||
Loc.Localize("AutoUpdateUpdatesAvailableContentMinimizedSingular", "1 plugin update available") :
|
||||
Loc.Localize("AutoUpdateUpdatesAvailableContentMinimizedSingular", "1 plugin update available") :
|
||||
string.Format(Loc.Localize("AutoUpdateUpdatesAvailableContentMinimizedPlural", "{0} plugin updates available"), numUpdates);
|
||||
|
||||
|
||||
public static string NotificationContentPreparingToUpdate(int numPlugins)
|
||||
=> numPlugins == 1 ?
|
||||
Loc.Localize("AutoUpdatePreparingToUpdateSingular", "Preparing to update 1 plugin...") :
|
||||
Loc.Localize("AutoUpdatePreparingToUpdateSingular", "Preparing to update 1 plugin...") :
|
||||
string.Format(Loc.Localize("AutoUpdatePreparingToUpdatePlural", "Preparing to update {0} plugins..."), numPlugins);
|
||||
|
||||
|
||||
public static string NotificationContentUpdating(string name)
|
||||
=> string.Format(Loc.Localize("AutoUpdateUpdating", "Updating {0}..."), name);
|
||||
|
||||
|
||||
public static string NotificationContentFailedPlugins(IEnumerable<string> failedPlugins)
|
||||
=> string.Format(Loc.Localize("AutoUpdateFailedPlugins", "Failed plugin(s): {0}"), string.Join(", ", failedPlugins));
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue