mirror of
https://github.com/rmcrackan/Libation.git
synced 2026-09-17 16:58:35 -04:00
Merge pull request #2000 from rmcrackan/cursor/opt-out-update-checker-efc8
Let users turn off the startup update check
This commit is contained in:
16 files changed
+259
-27
No files matched your search
@@ -332,7 +332,8 @@ public static class LibationScaffolding
|
||||
config.ImportEpisodes,
|
||||
config.ImportPlusTitles,
|
||||
config.DownloadEpisodes,
|
||||
config.BetaOptIn,
|
||||
// Off means no startup upgrade prompt, which is otherwise indistinguishable from a broken check
|
||||
config.CheckForUpgradesAtStartup,
|
||||
config.UseCoverAsFolderIcon,
|
||||
config.LibationFiles,
|
||||
AudibleFileStorage.BooksDirectory,
|
||||
|
||||
@@ -69,21 +69,30 @@
|
||||
</StackPanel>
|
||||
|
||||
</controls:GroupBox>
|
||||
<CheckBox
|
||||
<StackPanel
|
||||
Grid.Row="1"
|
||||
Margin="10,5"
|
||||
IsEnabled="{Binding !UseWebViewSettingDisabled}"
|
||||
IsChecked="{Binding UseWebView, Mode=TwoWay}">
|
||||
<StackPanel>
|
||||
<TextBlock Text="{Binding UseWebViewText}" />
|
||||
<TextBlock
|
||||
IsVisible="{Binding UseWebViewSettingDisabled}"
|
||||
FontStyle="Italic"
|
||||
Opacity="0.8"
|
||||
Margin="0,2,0,0"
|
||||
Text="{Binding UseWebViewSnapMessage}" />
|
||||
</StackPanel>
|
||||
</CheckBox>
|
||||
Spacing="5">
|
||||
<CheckBox
|
||||
IsEnabled="{Binding !UseWebViewSettingDisabled}"
|
||||
IsChecked="{Binding UseWebView, Mode=TwoWay}">
|
||||
<StackPanel>
|
||||
<TextBlock Text="{Binding UseWebViewText}" />
|
||||
<TextBlock
|
||||
IsVisible="{Binding UseWebViewSettingDisabled}"
|
||||
FontStyle="Italic"
|
||||
Opacity="0.8"
|
||||
Margin="0,2,0,0"
|
||||
Text="{Binding UseWebViewSnapMessage}" />
|
||||
</StackPanel>
|
||||
</CheckBox>
|
||||
|
||||
<CheckBox
|
||||
IsChecked="{Binding CheckForUpgradesAtStartup, Mode=TwoWay}"
|
||||
ToolTip.Tip="{Binding CheckForUpgradesAtStartupTip}">
|
||||
<TextBlock Text="{Binding CheckForUpgradesAtStartupText}" />
|
||||
</CheckBox>
|
||||
</StackPanel>
|
||||
|
||||
<controls:GroupBox
|
||||
Grid.Row="2"
|
||||
|
||||
@@ -14,6 +14,7 @@ public partial class UpgradeNotificationDialog : DialogWindow
|
||||
public string? ReleaseNotes { get; }
|
||||
public string? OkText { get; }
|
||||
private string? PackageUrl { get; }
|
||||
private bool CanUpgrade { get; } = true;
|
||||
public UpgradeNotificationDialog()
|
||||
{
|
||||
if (Design.IsDesignMode)
|
||||
@@ -33,6 +34,7 @@ public partial class UpgradeNotificationDialog : DialogWindow
|
||||
public UpgradeNotificationDialog(UpgradeProperties upgradeProperties, bool canUpgrade, string? upgradeUnavailableReason = null) : this()
|
||||
{
|
||||
Title = $"Libation version {upgradeProperties.LatestRelease.ToVersionString()} is now available.";
|
||||
CanUpgrade = canUpgrade;
|
||||
PackageUrl = upgradeProperties.ZipUrl;
|
||||
DownloadLinkText = upgradeProperties.ZipName;
|
||||
ReleaseNotes = upgradeProperties.Notes;
|
||||
@@ -41,7 +43,11 @@ public partial class UpgradeNotificationDialog : DialogWindow
|
||||
DataContext = this;
|
||||
}
|
||||
|
||||
public void OK_Click(object sender, Avalonia.Interactivity.RoutedEventArgs e) => Close(DialogResult.OK);
|
||||
// When Libation cannot install the upgrade itself, this button reads "OK" and the dialog is a
|
||||
// notice with a download link. Reporting OK there would be read as "yes, install it", starting a
|
||||
// download and an install that was never on offer, so acknowledging a notice closes and no more.
|
||||
public void OK_Click(object sender, Avalonia.Interactivity.RoutedEventArgs e)
|
||||
=> Close(CanUpgrade ? DialogResult.OK : DialogResult.Cancel);
|
||||
public void DontRemind_Click(object sender, Avalonia.Interactivity.RoutedEventArgs e) => Close(DialogResult.Ignore);
|
||||
public void Download_Tapped(object sender, Avalonia.Input.TappedEventArgs e)
|
||||
=> Go.To.Url(PackageUrl);
|
||||
|
||||
@@ -35,6 +35,7 @@ public class ImportantSettingsVM : ViewModelBase
|
||||
CreationTime = DateTimeSources.SingleOrDefault(v => v.Value == config.CreationTime) ?? DateTimeSources[0];
|
||||
LastWriteTime = DateTimeSources.SingleOrDefault(v => v.Value == config.LastWriteTime) ?? DateTimeSources[0];
|
||||
UseWebView = config.UseWebView;
|
||||
CheckForUpgradesAtStartup = config.CheckForUpgradesAtStartup;
|
||||
LoggingLevel = config.LogLevel;
|
||||
GridScaleFactor = scaleFactorToLinearRange(config.GridScaleFactor);
|
||||
GridFontScaleFactor = scaleFactorToLinearRange(config.GridFontScaleFactor);
|
||||
@@ -77,6 +78,7 @@ public class ImportantSettingsVM : ViewModelBase
|
||||
config.CreationTime = CreationTime.Value;
|
||||
config.LastWriteTime = LastWriteTime.Value;
|
||||
config.UseWebView = UseWebView;
|
||||
config.CheckForUpgradesAtStartup = CheckForUpgradesAtStartup;
|
||||
config.LogLevel = LoggingLevel;
|
||||
config.TokenStorageMethod = SelectedTokenStorageMethod;
|
||||
initialTokenStorageMethod = SelectedTokenStorageMethod;
|
||||
@@ -145,10 +147,11 @@ public class ImportantSettingsVM : ViewModelBase
|
||||
/// <summary>When true, the Use WebView setting is disabled (e.g. when running in Linux Snap to avoid portal/sandbox crashes).</summary>
|
||||
public bool UseWebViewSettingDisabled => Configuration.IsRunningUnderSnap;
|
||||
public string UseWebViewSnapMessage { get; } = Configuration.IsRunningUnderSnap ? "Disabled when running in Linux Snap (avoids login crash). Use external browser instead." : "";
|
||||
public string CheckForUpgradesAtStartupText { get; } = Configuration.GetDescription(nameof(Configuration.CheckForUpgradesAtStartup));
|
||||
public string CheckForUpgradesAtStartupTip { get; } = Configuration.GetHelpText(nameof(Configuration.CheckForUpgradesAtStartup));
|
||||
public Serilog.Events.LogEventLevel[] LoggingLevels { get; } = Enum.GetValues<Serilog.Events.LogEventLevel>();
|
||||
public string GridScaleFactorText { get; } = Configuration.GetDescription(nameof(Configuration.GridScaleFactor));
|
||||
public string GridFontScaleFactorText { get; } = Configuration.GetDescription(nameof(Configuration.GridFontScaleFactor));
|
||||
public string BetaOptInText { get; } = Configuration.GetDescription(nameof(Configuration.BetaOptIn));
|
||||
public EnumDisplay<Configuration.Theme>[] Themes { get; }
|
||||
= Enum.GetValues<Configuration.Theme>()
|
||||
.Select(v => new EnumDisplay<Configuration.Theme>(v))
|
||||
@@ -171,6 +174,7 @@ public class ImportantSettingsVM : ViewModelBase
|
||||
public EnumDisplay<Configuration.DateTimeSource> CreationTime { get; set; }
|
||||
public EnumDisplay<Configuration.DateTimeSource> LastWriteTime { get; set; }
|
||||
public bool UseWebView { get; set; }
|
||||
public bool CheckForUpgradesAtStartup { get; set; }
|
||||
public Serilog.Events.LogEventLevel LoggingLevel { get; set; }
|
||||
|
||||
public bool EncryptTokens
|
||||
|
||||
@@ -278,7 +278,7 @@ public partial class MainWindow : ReactiveWindow<MainVM>
|
||||
upgrader.UpgradeFailed += async (_, message) => await Dispatcher.UIThread.InvokeAsync(() => { setProgressVisible(false); MessageBox.Show(this, message, "Upgrade Failed", MessageBoxButtons.OK, MessageBoxIcon.Error); });
|
||||
|
||||
#if !DEBUG
|
||||
Opened += async (_, _) => await upgrader.CheckForUpgradeAsync(upgradeAvailable);
|
||||
Opened += async (_, _) => await upgrader.CheckForUpgradeAtStartupAsync(upgradeAvailable);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
@@ -168,6 +168,17 @@ public partial class Configuration
|
||||
When enabled, books from the Audible Plus catalog (titles you stream or borrow under your membership, not purchased) are imported into Libation.
|
||||
|
||||
Downloading or liberating many Plus titles in a short time can cause Audible to temporarily deny content licenses ("license denied") for a day or two. That limit is enforced by Audible, not Libation — waiting and retrying usually fixes it. If problems persist after several days, report on Libation's GitHub with logs.
|
||||
""" },
|
||||
{nameof(CheckForUpgradesAtStartup), """
|
||||
When enabled, Libation asks GitHub whether a newer
|
||||
release exists each time it starts, and offers it to
|
||||
you if there is one.
|
||||
|
||||
Turn this off if something else keeps Libation up to
|
||||
date, such as a package manager or an AppImage
|
||||
updater. You can still check whenever you like:
|
||||
Settings > About has a "Check for Upgrade" button
|
||||
that works either way.
|
||||
""" }
|
||||
}.AsReadOnly();
|
||||
|
||||
|
||||
@@ -117,8 +117,8 @@ public partial class Configuration
|
||||
[Description("Book display font size")]
|
||||
public float GridFontScaleFactor { get => float.Min(2, float.Max(0.5f, GetNonString(defaultValue: 1f))); set => SetNonString(value); }
|
||||
|
||||
[Description("Use the beta version of Libation\r\nNew and experimental features, but probably buggy.\r\n(requires restart to take effect)")]
|
||||
public bool BetaOptIn { get => GetNonString(defaultValue: false); set => SetNonString(value); }
|
||||
[Description("Check for new Libation versions at startup")]
|
||||
public bool CheckForUpgradesAtStartup { get => GetNonString(defaultValue: true); set => SetNonString(value); }
|
||||
|
||||
[Description("Location for book storage. Includes destination of newly liberated books")]
|
||||
public LongPath? Books
|
||||
|
||||
@@ -226,6 +226,32 @@ public abstract class UpgraderBase
|
||||
? new(false, ApplicationControlUpgradeMessage, ApplicationControlUpgradeSummary)
|
||||
: new(platformCanUpgrade, null, null);
|
||||
|
||||
/// <summary>
|
||||
/// Whether the flow may go on to download and install. The dialog's answer is not enough on its
|
||||
/// own: when Libation cannot install the upgrade itself, the prompt is a notice with a download
|
||||
/// link, so a UI that reports acceptance anyway must not be able to start an install that was
|
||||
/// never on offer - or, under Application Control, one that leaves Libation unable to start.
|
||||
/// </summary>
|
||||
internal static bool MayInstallUpgrade(bool userAccepted, bool capUpgrade)
|
||||
=> userAccepted && capUpgrade;
|
||||
|
||||
/// <summary>
|
||||
/// The check both GUIs run when their main window opens, skipped when the user has turned off
|
||||
/// <see cref="Configuration.CheckForUpgradesAtStartup"/>. Only this automatic check is optional:
|
||||
/// the About window's "Check for Upgrade" button asks for a check outright and calls
|
||||
/// <see cref="CheckForUpgradeAsync(Func{UpgradeEventArgs, Task})"/> regardless of the setting.
|
||||
/// </summary>
|
||||
public async Task CheckForUpgradeAtStartupAsync(Func<UpgradeEventArgs, Task> upgradeAvailableHandler)
|
||||
{
|
||||
if (!Configuration.Instance.CheckForUpgradesAtStartup)
|
||||
{
|
||||
Serilog.Log.Logger.Information("Skipping the startup upgrade check: {Setting} is off.", nameof(Configuration.CheckForUpgradesAtStartup));
|
||||
return;
|
||||
}
|
||||
|
||||
await CheckForUpgradeAsync(upgradeAvailableHandler);
|
||||
}
|
||||
|
||||
/// <summary>Check for upgrade and invoke <paramref name="upgradeAvailableHandler"/> if an update is available. Returns the check outcome so the UI can show "up to date", "update available", or "unable to determine".</summary>
|
||||
public async Task<VersionCheckResult> CheckForUpgradeAsync(Func<UpgradeEventArgs, Task> upgradeAvailableHandler)
|
||||
{
|
||||
@@ -266,13 +292,14 @@ public abstract class UpgraderBase
|
||||
if (upgradeEventArgs.Ignore)
|
||||
config.SetString(upgradeProperties.LatestRelease.ToString(), ignoreUpgrade);
|
||||
|
||||
if (!upgradeEventArgs.InstallUpgrade) return result;
|
||||
|
||||
// A second stop, because a UI that ignores CapUpgrade must not be able to start an
|
||||
// upgrade that ends with Libation unable to start.
|
||||
if (applicationControlBlocksUpgrade)
|
||||
if (!MayInstallUpgrade(upgradeEventArgs.InstallUpgrade, capability.CapUpgrade))
|
||||
{
|
||||
Serilog.Log.Logger.Information("Skipped the in-app upgrade to {LatestRelease}: Windows Application Control is enforcing.", upgradeProperties.LatestRelease);
|
||||
if (upgradeEventArgs.InstallUpgrade)
|
||||
Serilog.Log.Logger.Information(
|
||||
"Skipped the in-app upgrade to {LatestRelease}: {Reason}.",
|
||||
upgradeProperties.LatestRelease,
|
||||
applicationControlBlocksUpgrade ? "Windows Application Control is enforcing" : "this install cannot upgrade itself");
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
@@ -69,6 +69,7 @@
|
||||
absFolderLbl = new System.Windows.Forms.Label();
|
||||
absFolderCb = new System.Windows.Forms.ComboBox();
|
||||
tab1ImportantSettings = new System.Windows.Forms.TabPage();
|
||||
checkForUpgradesCbox = new System.Windows.Forms.CheckBox();
|
||||
themeLbl = new System.Windows.Forms.Label();
|
||||
themeCb = new System.Windows.Forms.ComboBox();
|
||||
label22 = new System.Windows.Forms.Label();
|
||||
@@ -405,6 +406,16 @@
|
||||
loggingLevelCb.Size = new System.Drawing.Size(129, 23);
|
||||
loggingLevelCb.TabIndex = 4;
|
||||
//
|
||||
// checkForUpgradesCbox
|
||||
//
|
||||
checkForUpgradesCbox.AutoSize = true;
|
||||
checkForUpgradesCbox.Location = new System.Drawing.Point(6, 569);
|
||||
checkForUpgradesCbox.Name = "checkForUpgradesCbox";
|
||||
checkForUpgradesCbox.Size = new System.Drawing.Size(300, 19);
|
||||
checkForUpgradesCbox.TabIndex = 13;
|
||||
checkForUpgradesCbox.Text = "[Check for upgrades at startup]";
|
||||
checkForUpgradesCbox.UseVisualStyleBackColor = true;
|
||||
//
|
||||
// tabControl
|
||||
//
|
||||
tabControl.Anchor = System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left | System.Windows.Forms.AnchorStyles.Right;
|
||||
@@ -423,6 +434,7 @@
|
||||
//
|
||||
tab1ImportantSettings.AutoScroll = true;
|
||||
tab1ImportantSettings.BackColor = System.Drawing.SystemColors.Window;
|
||||
tab1ImportantSettings.Controls.Add(checkForUpgradesCbox);
|
||||
tab1ImportantSettings.Controls.Add(themeLbl);
|
||||
tab1ImportantSettings.Controls.Add(themeCb);
|
||||
tab1ImportantSettings.Controls.Add(label22);
|
||||
@@ -1926,6 +1938,7 @@
|
||||
private System.Windows.Forms.CheckBox createCueSheetCbox;
|
||||
private System.Windows.Forms.CheckBox autoScanCb;
|
||||
private System.Windows.Forms.CheckBox useWebViewCb;
|
||||
private System.Windows.Forms.CheckBox checkForUpgradesCbox;
|
||||
private System.Windows.Forms.CheckBox downloadCoverArtCbox;
|
||||
private System.Windows.Forms.CheckBox autoDownloadEpisodesCb;
|
||||
private System.Windows.Forms.CheckBox saveEpisodesToSeriesFolderCbox;
|
||||
|
||||
@@ -42,6 +42,8 @@ public partial class SettingsDialog
|
||||
lastWriteTimeLbl.Text = desc(nameof(config.LastWriteTime));
|
||||
gridScaleFactorLbl.Text = desc(nameof(config.GridScaleFactor));
|
||||
gridFontScaleFactorLbl.Text = desc(nameof(config.GridFontScaleFactor));
|
||||
checkForUpgradesCbox.Text = desc(nameof(config.CheckForUpgradesAtStartup));
|
||||
toolTip.SetToolTip(checkForUpgradesCbox, Configuration.GetHelpText(nameof(config.CheckForUpgradesAtStartup)));
|
||||
|
||||
var dateTimeSources = Enum.GetValues<Configuration.DateTimeSource>().Select(v => new EnumDisplay<Configuration.DateTimeSource>(v)).ToArray();
|
||||
creationTimeCb.Items.AddRange(dateTimeSources);
|
||||
@@ -70,6 +72,7 @@ public partial class SettingsDialog
|
||||
|
||||
saveEpisodesToSeriesFolderCbox.Checked = config.SavePodcastsToParentFolder;
|
||||
overwriteExistingCbox.Checked = config.OverwriteExisting;
|
||||
checkForUpgradesCbox.Checked = config.CheckForUpgradesAtStartup;
|
||||
gridScaleFactorTbar.Value = scaleFactorToLinearRange(config.GridScaleFactor);
|
||||
gridFontScaleFactorTbar.Value = scaleFactorToLinearRange(config.GridFontScaleFactor);
|
||||
|
||||
@@ -195,6 +198,7 @@ public partial class SettingsDialog
|
||||
|
||||
config.SavePodcastsToParentFolder = saveEpisodesToSeriesFolderCbox.Checked;
|
||||
config.OverwriteExisting = overwriteExistingCbox.Checked;
|
||||
config.CheckForUpgradesAtStartup = checkForUpgradesCbox.Checked;
|
||||
|
||||
config.CreationTime = (creationTimeCb.SelectedItem as EnumDisplay<Configuration.DateTimeSource>)?.Value ?? Configuration.DateTimeSource.File;
|
||||
config.LastWriteTime = (lastWriteTimeCb.SelectedItem as EnumDisplay<Configuration.DateTimeSource>)?.Value ?? Configuration.DateTimeSource.File;
|
||||
|
||||
@@ -27,7 +27,7 @@ public partial class Form1
|
||||
upgrader.UpgradeFailed += (_, message) => Invoke(() => { setProgressVisible(false); MessageBox.Show(this, message, "Upgrade Failed", MessageBoxButtons.OK, MessageBoxIcon.Error); });
|
||||
|
||||
#if !DEBUG
|
||||
Shown += async (_, _) => await upgrader.CheckForUpgradeAsync(upgradeAvailable);
|
||||
Shown += async (_, _) => await upgrader.CheckForUpgradeAtStartupAsync(upgradeAvailable);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,52 @@
|
||||
using AssertionHelper;
|
||||
using LibationFileManager;
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
|
||||
namespace UpgradeCheckSettingTests;
|
||||
|
||||
[TestClass]
|
||||
[DoNotParallelize]
|
||||
public class UpgradeCheckSettingTests
|
||||
{
|
||||
[TestCleanup]
|
||||
public void Cleanup()
|
||||
{
|
||||
Configuration.RestoreSingletonInstance();
|
||||
}
|
||||
|
||||
// The update check is opt-out, so every install that predates the setting has to keep checking
|
||||
// without anything having written the key.
|
||||
[TestMethod]
|
||||
public void Default_when_missing_is_enabled()
|
||||
{
|
||||
var config = Configuration.CreateMockInstance();
|
||||
|
||||
config.Exists(nameof(Configuration.CheckForUpgradesAtStartup)).Should().BeFalse();
|
||||
Assert.IsTrue(config.CheckForUpgradesAtStartup);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void Round_trips_off_and_on()
|
||||
{
|
||||
var config = Configuration.CreateMockInstance();
|
||||
|
||||
config.CheckForUpgradesAtStartup = false;
|
||||
Assert.IsFalse(config.CheckForUpgradesAtStartup);
|
||||
Assert.IsFalse(config.CreateEphemeralCopy().CheckForUpgradesAtStartup);
|
||||
|
||||
config.CheckForUpgradesAtStartup = true;
|
||||
Assert.IsTrue(config.CheckForUpgradesAtStartup);
|
||||
Assert.IsTrue(config.CreateEphemeralCopy().CheckForUpgradesAtStartup);
|
||||
}
|
||||
|
||||
// get-setting and the -o override both reflect over Configuration properties carrying
|
||||
// [Description], so a missing attribute would silently drop the setting from the CLI.
|
||||
[TestMethod]
|
||||
public void Has_a_description_so_the_cli_can_see_it()
|
||||
{
|
||||
var description = Configuration.GetDescription(nameof(Configuration.CheckForUpgradesAtStartup));
|
||||
|
||||
Assert.AreNotEqual($"[{nameof(Configuration.CheckForUpgradesAtStartup)}]", description);
|
||||
StringAssert.Contains(description, "startup");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,81 @@
|
||||
using LibationFileManager;
|
||||
|
||||
namespace LibationUiBase.Tests;
|
||||
|
||||
/// <summary>
|
||||
/// Covers the one thing the CheckForUpgradesAtStartup setting has to do: keep the startup check off
|
||||
/// the network when it is off, and leave it alone when it is on.
|
||||
/// <para>
|
||||
/// <see cref="MockUpgrader"/> is the seam. With <see cref="MockUpgrader.CheckForUpgradeSucceeds"/>
|
||||
/// false, the check reports its own distinctive failure and the flow returns before reaching
|
||||
/// <c>InteropFactory</c>, whose <c>CanUpgrade</c> throws off-platform. That failure message is
|
||||
/// therefore proof that the check ran, and its absence proof that it did not.
|
||||
/// </para>
|
||||
/// </summary>
|
||||
[TestClass]
|
||||
[DoNotParallelize]
|
||||
public class StartupUpgradeCheckTests
|
||||
{
|
||||
private const string CheckRanMessage = "Mock Check For Upgrade Failed";
|
||||
|
||||
[TestCleanup]
|
||||
public void Cleanup()
|
||||
{
|
||||
Configuration.RestoreSingletonInstance();
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public async Task Startup_checks_when_the_setting_is_on()
|
||||
{
|
||||
var config = Configuration.CreateMockInstance();
|
||||
config.CheckForUpgradesAtStartup = true;
|
||||
|
||||
var (upgrader, failures) = BuildUpgraderThatFailsItsCheck();
|
||||
await upgrader.CheckForUpgradeAtStartupAsync(ShouldNotBeCalled);
|
||||
|
||||
Assert.AreEqual(1, failures.Count);
|
||||
StringAssert.Contains(failures[0], CheckRanMessage);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public async Task Startup_does_not_check_when_the_setting_is_off()
|
||||
{
|
||||
var config = Configuration.CreateMockInstance();
|
||||
config.CheckForUpgradesAtStartup = false;
|
||||
|
||||
var (upgrader, failures) = BuildUpgraderThatFailsItsCheck();
|
||||
await upgrader.CheckForUpgradeAtStartupAsync(ShouldNotBeCalled);
|
||||
|
||||
Assert.AreEqual(0, failures.Count);
|
||||
}
|
||||
|
||||
// Turning the automatic check off must not disable the About window's "Check for Upgrade"
|
||||
// button, which calls CheckForUpgradeAsync directly.
|
||||
[TestMethod]
|
||||
public async Task A_requested_check_still_runs_when_the_setting_is_off()
|
||||
{
|
||||
var config = Configuration.CreateMockInstance();
|
||||
config.CheckForUpgradesAtStartup = false;
|
||||
|
||||
var (upgrader, failures) = BuildUpgraderThatFailsItsCheck();
|
||||
var result = await upgrader.CheckForUpgradeAsync(ShouldNotBeCalled);
|
||||
|
||||
Assert.AreEqual(AppScaffolding.VersionCheckOutcome.UnableToDetermine, result.Outcome);
|
||||
Assert.AreEqual(1, failures.Count);
|
||||
StringAssert.Contains(failures[0], CheckRanMessage);
|
||||
}
|
||||
|
||||
private static (MockUpgrader Upgrader, List<string> Failures) BuildUpgraderThatFailsItsCheck()
|
||||
{
|
||||
var upgrader = new MockUpgrader { CheckForUpgradeSucceeds = false };
|
||||
List<string> failures = [];
|
||||
upgrader.UpgradeFailed += (_, message) => failures.Add(message);
|
||||
return (upgrader, failures);
|
||||
}
|
||||
|
||||
private static Task ShouldNotBeCalled(UpgradeEventArgs e)
|
||||
{
|
||||
Assert.Fail("The upgrade-available handler ran, but the check was supposed to fail before an update could be offered.");
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
}
|
||||
@@ -51,4 +51,24 @@ public class UpgradeCapabilityTests
|
||||
Assert.IsNull(capability.Reason);
|
||||
Assert.IsNull(capability.Summary);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void An_accepted_upgrade_installs_when_the_platform_can()
|
||||
=> Assert.IsTrue(UpgraderBase.MayInstallUpgrade(userAccepted: true, capUpgrade: true));
|
||||
|
||||
// Chardonnay's prompt relabels its button to "OK" when Libation cannot install the upgrade
|
||||
// itself, but still reported acceptance, so acknowledging a download-link notice began a
|
||||
// download and an install that was never on offer and could only fail.
|
||||
[TestMethod]
|
||||
public void Acceptance_is_not_enough_when_libation_cannot_install_the_upgrade()
|
||||
=> Assert.IsFalse(UpgraderBase.MayInstallUpgrade(userAccepted: true, capUpgrade: false));
|
||||
|
||||
// InstallUpgrade defaults to true, so a UI that never answers must not be taken as a yes on a
|
||||
// platform that cannot install.
|
||||
[TestMethod]
|
||||
public void Declining_never_installs()
|
||||
{
|
||||
Assert.IsFalse(UpgraderBase.MayInstallUpgrade(userAccepted: false, capUpgrade: true));
|
||||
Assert.IsFalse(UpgraderBase.MayInstallUpgrade(userAccepted: false, capUpgrade: false));
|
||||
}
|
||||
}
|
||||
@@ -12,6 +12,8 @@ To make upgrades and reinstalls easier, Libation separates all of its responsibi
|
||||
|
||||
## Settings
|
||||
|
||||
- Check for new Libation versions at startup. Enabled by default: each time Libation starts it asks GitHub whether a newer release exists, and offers it to you if there is one. Turn it off if something else keeps Libation up to date, such as a package manager or an AppImage updater. Turning it off only stops the automatic check - Settings > About still has a "Check for Upgrade" button that works either way.
|
||||
|
||||
- Allow Libation to fix up audiobook metadata. After decrypting a title, Libation attempts to fix details like chapters and cover art. Some power users and/or control freaks prefer to manage this themselves. By unchecking this setting, Libation will only decrypt the book and will leave metadata as-is, warts and all.
|
||||
|
||||
In addition to the options that are enabled if you allow Libation to "fix up" the audiobook, it does the following:
|
||||
|
||||
@@ -62,7 +62,9 @@ sudo dnf5 install ./libation.rpm
|
||||
am -i libation
|
||||
```
|
||||
Thanks to Package Forge dev [Samuel](https://github.com/Samueru-sama) for [AppImage](https://github.com/pkgforge-dev/Libation-AppImage) maintenence.
|
||||
|
||||
|
||||
When your package manager updates Libation for you, the startup update check has nothing useful to tell you. Turn off "Check for new Libation versions at startup" on the Important settings tab to stop it. Settings > About still has a "Check for Upgrade" button whenever you want to look.
|
||||
|
||||
### Arch Linux
|
||||
|
||||
```bash
|
||||
|
||||
Reference in new issue
Block a user