mirror of
https://github.com/Artemis-RGB/Artemis
synced 2025-12-13 05:48:35 +00:00
Core - Fixed crash on startup if workshop folder is missing
Updating - Properly delay auto-update check until the UI shows,
This commit is contained in:
parent
cf10193bd2
commit
0b6bf5685e
@ -105,7 +105,7 @@ public class AutoRunProvider : IAutoRunProvider
|
|||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public async Task EnableAutoRun(bool recreate, int autoRunDelay)
|
public async Task EnableAutoRun(bool recreate, int autoRunDelay)
|
||||||
{
|
{
|
||||||
if (Constants.CurrentVersion == "development")
|
if (Constants.CurrentVersion == "local")
|
||||||
return;
|
return;
|
||||||
|
|
||||||
await CleanupOldAutorun();
|
await CleanupOldAutorun();
|
||||||
|
|||||||
@ -110,7 +110,7 @@ public class WindowsUpdateNotificationProvider : IUpdateNotificationProvider
|
|||||||
// If the main window is not open the user isn't busy, restart straight away
|
// If the main window is not open the user isn't busy, restart straight away
|
||||||
if (!_mainWindowService.IsMainWindowOpen)
|
if (!_mainWindowService.IsMainWindowOpen)
|
||||||
{
|
{
|
||||||
_updateService.RestartForUpdate(true);
|
_updateService.RestartForUpdate("WindowsNotification", true);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -165,6 +165,6 @@ public class WindowsUpdateNotificationProvider : IUpdateNotificationProvider
|
|||||||
else if (action == "cancel")
|
else if (action == "cancel")
|
||||||
_cancellationTokenSource?.Cancel();
|
_cancellationTokenSource?.Cancel();
|
||||||
else if (action == "restart-for-update")
|
else if (action == "restart-for-update")
|
||||||
_updateService.RestartForUpdate(false);
|
_updateService.RestartForUpdate("WindowsNotification", false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -62,7 +62,6 @@ public class RootViewModel : RoutableHostScreen<RoutableScreen>, IMainWindowProv
|
|||||||
router.SetRoot(this);
|
router.SetRoot(this);
|
||||||
mainWindowService.ConfigureMainWindowProvider(this);
|
mainWindowService.ConfigureMainWindowProvider(this);
|
||||||
|
|
||||||
DisplayAccordingToSettings();
|
|
||||||
OpenScreen = ReactiveCommand.Create<string?>(ExecuteOpenScreen);
|
OpenScreen = ReactiveCommand.Create<string?>(ExecuteOpenScreen);
|
||||||
OpenDebugger = ReactiveCommand.CreateFromTask(ExecuteOpenDebugger);
|
OpenDebugger = ReactiveCommand.CreateFromTask(ExecuteOpenDebugger);
|
||||||
Exit = ReactiveCommand.CreateFromTask(ExecuteExit);
|
Exit = ReactiveCommand.CreateFromTask(ExecuteExit);
|
||||||
@ -74,10 +73,17 @@ public class RootViewModel : RoutableHostScreen<RoutableScreen>, IMainWindowProv
|
|||||||
.Select(vm => vm ?? _defaultTitleBarViewModel)
|
.Select(vm => vm ?? _defaultTitleBarViewModel)
|
||||||
.ToProperty(this, vm => vm.TitleBarViewModel);
|
.ToProperty(this, vm => vm.TitleBarViewModel);
|
||||||
|
|
||||||
|
if (ShouldShowUI())
|
||||||
|
{
|
||||||
|
ShowSplashScreen();
|
||||||
|
_coreService.Initialized += (_, _) => Dispatcher.UIThread.InvokeAsync(OpenMainWindow);
|
||||||
|
}
|
||||||
|
|
||||||
Task.Run(() =>
|
Task.Run(() =>
|
||||||
{
|
{
|
||||||
// Before doing heavy lifting, initialize the update service which may prompt a restart
|
// Before doing heavy lifting, initialize the update service which may prompt a restart
|
||||||
if (_updateService.Initialize())
|
// Only initialize with an update check if we're not going to show the UI
|
||||||
|
if (_updateService.Initialize(!ShouldShowUI()))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// Workshop service goes first so it has a chance to clean up old workshop entries and introduce new ones
|
// Workshop service goes first so it has a chance to clean up old workshop entries and introduce new ones
|
||||||
@ -118,17 +124,13 @@ public class RootViewModel : RoutableHostScreen<RoutableScreen>, IMainWindowProv
|
|||||||
OnMainWindowClosed();
|
OnMainWindowClosed();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void DisplayAccordingToSettings()
|
private bool ShouldShowUI()
|
||||||
{
|
{
|
||||||
bool autoRunning = Constants.StartupArguments.Contains("--autorun");
|
bool autoRunning = Constants.StartupArguments.Contains("--autorun");
|
||||||
bool minimized = Constants.StartupArguments.Contains("--minimized");
|
bool minimized = Constants.StartupArguments.Contains("--minimized");
|
||||||
bool showOnAutoRun = _settingsService.GetSetting("UI.ShowOnStartup", true).Value;
|
bool showOnAutoRun = _settingsService.GetSetting("UI.ShowOnStartup", true).Value;
|
||||||
|
|
||||||
if ((autoRunning && !showOnAutoRun) || minimized)
|
return (autoRunning && showOnAutoRun) || !minimized;
|
||||||
return;
|
|
||||||
|
|
||||||
ShowSplashScreen();
|
|
||||||
_coreService.Initialized += (_, _) => Dispatcher.UIThread.InvokeAsync(OpenMainWindow);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void ShowSplashScreen()
|
private void ShowSplashScreen()
|
||||||
|
|||||||
@ -87,7 +87,7 @@ public partial class ReleaseDetailsViewModel : RoutableScreen<ReleaseDetailsView
|
|||||||
|
|
||||||
private void ExecuteRestart()
|
private void ExecuteRestart()
|
||||||
{
|
{
|
||||||
_updateService.RestartForUpdate(false);
|
_updateService.RestartForUpdate("ReleaseDetails", false);
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task ExecuteInstall(CancellationToken cancellationToken)
|
private async Task ExecuteInstall(CancellationToken cancellationToken)
|
||||||
|
|||||||
@ -17,7 +17,7 @@
|
|||||||
<TextBlock Grid.Row="1" Grid.Column="0" Text="{CompiledBinding Release.CreatedAt, Converter={StaticResource DateTimeConverter}}" VerticalAlignment="Center" Classes="subtitle" FontSize="13" />
|
<TextBlock Grid.Row="1" Grid.Column="0" Text="{CompiledBinding Release.CreatedAt, Converter={StaticResource DateTimeConverter}}" VerticalAlignment="Center" Classes="subtitle" FontSize="13" />
|
||||||
<avalonia:MaterialIcon Classes="status-icon" Grid.Row="0" Grid.Column="1" Grid.RowSpan="2" Kind="CheckCircle" ToolTip.Tip="Current version"
|
<avalonia:MaterialIcon Classes="status-icon" Grid.Row="0" Grid.Column="1" Grid.RowSpan="2" Kind="CheckCircle" ToolTip.Tip="Current version"
|
||||||
IsVisible="{CompiledBinding IsCurrentVersion}" />
|
IsVisible="{CompiledBinding IsCurrentVersion}" />
|
||||||
<avalonia:MaterialIcon Classes="status-icon" Grid.Row="0" Grid.Column="1" Grid.RowSpan="2" Kind="History" ToolTip.Tip="Previous version"
|
<avalonia:MaterialIcon Classes="status-icon" Grid.Row="0" Grid.Column="1" Grid.RowSpan="2" Kind="History" ToolTip.Tip="Last previously installed version"
|
||||||
IsVisible="{CompiledBinding IsPreviousVersion}" />
|
IsVisible="{CompiledBinding IsPreviousVersion}" />
|
||||||
</Grid>
|
</Grid>
|
||||||
<StackPanel Margin="4" IsVisible="{CompiledBinding !ShowStatusIndicator}">
|
<StackPanel Margin="4" IsVisible="{CompiledBinding !ShowStatusIndicator}">
|
||||||
|
|||||||
@ -22,8 +22,13 @@ public class SerilogAvaloniaSink : ILogSink
|
|||||||
{
|
{
|
||||||
SerilogLogLevel logLevel = GetSerilogLogLevel(level, area);
|
SerilogLogLevel logLevel = GetSerilogLogLevel(level, area);
|
||||||
|
|
||||||
|
#if DEBUG
|
||||||
// Except with binding errors, ignore anything that is information or lower
|
// Except with binding errors, ignore anything that is information or lower
|
||||||
return (area == "Binding" || logLevel > SerilogLogLevel.Information) && _logger.IsEnabled(logLevel);
|
return (area == "Binding" || logLevel > SerilogLogLevel.Information) && _logger.IsEnabled(logLevel);
|
||||||
|
#else
|
||||||
|
// Ignore binding errors in release builds, shoo
|
||||||
|
return area != "Binding" && logLevel > SerilogLogLevel.Information && _logger.IsEnabled(logLevel);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
|
|||||||
@ -42,12 +42,14 @@ public interface IUpdateService : IArtemisUIService
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Restarts the application to install a pending update.
|
/// Restarts the application to install a pending update.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
/// <param name="source">The source from which the restart is requested.</param>
|
||||||
/// <param name="silent">A boolean indicating whether to perform a silent install of the update.</param>
|
/// <param name="silent">A boolean indicating whether to perform a silent install of the update.</param>
|
||||||
void RestartForUpdate(bool silent);
|
void RestartForUpdate(string source, bool silent);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Initializes the update service.
|
/// Initializes the update service.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
/// <param name="performAutoUpdate"></param>
|
||||||
/// <returns>A boolean indicating whether a restart will occur to install a pending update.</returns>
|
/// <returns>A boolean indicating whether a restart will occur to install a pending update.</returns>
|
||||||
bool Initialize();
|
bool Initialize(bool performAutoUpdate);
|
||||||
}
|
}
|
||||||
@ -104,19 +104,19 @@ public class UpdateService : IUpdateService
|
|||||||
{
|
{
|
||||||
ReleaseInstaller installer = _getReleaseInstaller(release.Id);
|
ReleaseInstaller installer = _getReleaseInstaller(release.Id);
|
||||||
await installer.InstallAsync(CancellationToken.None);
|
await installer.InstallAsync(CancellationToken.None);
|
||||||
RestartForUpdate(true);
|
RestartForUpdate("AutoInstallUpdate", true);
|
||||||
}
|
}
|
||||||
|
|
||||||
private async void HandleAutoUpdateEvent(object? sender, EventArgs e)
|
private async void HandleAutoUpdateEvent(object? sender, EventArgs e)
|
||||||
{
|
{
|
||||||
if (Constants.CurrentVersion == "local")
|
if (Constants.CurrentVersion == "local")
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// The event can trigger from multiple sources with a timer acting as a fallback, only actual perform an action once per max 59 minutes
|
// The event can trigger from multiple sources with a timer acting as a fallback, only actually perform an action once per max 59 minutes
|
||||||
if (DateTime.UtcNow - _lastAutoUpdateCheck < TimeSpan.FromMinutes(59))
|
if (DateTime.UtcNow - _lastAutoUpdateCheck < TimeSpan.FromMinutes(59))
|
||||||
return;
|
return;
|
||||||
_lastAutoUpdateCheck = DateTime.UtcNow;
|
_lastAutoUpdateCheck = DateTime.UtcNow;
|
||||||
|
|
||||||
if (!_autoCheck.Value || _suspendAutoCheck)
|
if (!_autoCheck.Value || _suspendAutoCheck)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
@ -157,7 +157,7 @@ public class UpdateService : IUpdateService
|
|||||||
public async Task<bool> CheckForUpdate()
|
public async Task<bool> CheckForUpdate()
|
||||||
{
|
{
|
||||||
_logger.Information("Performing auto-update check");
|
_logger.Information("Performing auto-update check");
|
||||||
|
|
||||||
IOperationResult<IGetNextReleaseResult> result = await _updatingClient.GetNextRelease.ExecuteAsync(Constants.CurrentVersion, Channel, _updatePlatform);
|
IOperationResult<IGetNextReleaseResult> result = await _updatingClient.GetNextRelease.ExecuteAsync(Constants.CurrentVersion, Channel, _updatePlatform);
|
||||||
result.EnsureNoErrors();
|
result.EnsureNoErrors();
|
||||||
|
|
||||||
@ -171,7 +171,7 @@ public class UpdateService : IUpdateService
|
|||||||
// Unless auto install is enabled, only offer it once per session
|
// Unless auto install is enabled, only offer it once per session
|
||||||
if (!_autoInstall.Value)
|
if (!_autoInstall.Value)
|
||||||
_suspendAutoCheck = true;
|
_suspendAutoCheck = true;
|
||||||
|
|
||||||
// If the window is open show the changelog, don't auto-update while the user is busy
|
// If the window is open show the changelog, don't auto-update while the user is busy
|
||||||
if (_mainWindowService.IsMainWindowOpen || !_autoInstall.Value)
|
if (_mainWindowService.IsMainWindowOpen || !_autoInstall.Value)
|
||||||
{
|
{
|
||||||
@ -194,8 +194,10 @@ public class UpdateService : IUpdateService
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public void RestartForUpdate(bool silent)
|
public void RestartForUpdate(string source, bool silent)
|
||||||
{
|
{
|
||||||
|
_logger.Information("Restarting for update required by {Source}, silent: {Silent}", source, silent);
|
||||||
|
|
||||||
if (!Directory.Exists(Path.Combine(Constants.UpdatingFolder, "pending")))
|
if (!Directory.Exists(Path.Combine(Constants.UpdatingFolder, "pending")))
|
||||||
throw new ArtemisUIException("Cannot install update, none is pending.");
|
throw new ArtemisUIException("Cannot install update, none is pending.");
|
||||||
|
|
||||||
@ -204,11 +206,11 @@ public class UpdateService : IUpdateService
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public bool Initialize()
|
public bool Initialize(bool performAutoUpdate)
|
||||||
{
|
{
|
||||||
if (Constants.CurrentVersion == "local")
|
if (Constants.CurrentVersion == "local")
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
string? channelArgument = Constants.StartupArguments.FirstOrDefault(a => a.StartsWith("--channel="));
|
string? channelArgument = Constants.StartupArguments.FirstOrDefault(a => a.StartsWith("--channel="));
|
||||||
if (channelArgument != null)
|
if (channelArgument != null)
|
||||||
Channel = channelArgument.Split("=")[1];
|
Channel = channelArgument.Split("=")[1];
|
||||||
@ -235,7 +237,7 @@ public class UpdateService : IUpdateService
|
|||||||
_logger.Information("Installing pending update");
|
_logger.Information("Installing pending update");
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
RestartForUpdate(true);
|
RestartForUpdate("PendingFolder", true);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
@ -246,9 +248,10 @@ public class UpdateService : IUpdateService
|
|||||||
}
|
}
|
||||||
|
|
||||||
ProcessReleaseStatus();
|
ProcessReleaseStatus();
|
||||||
|
|
||||||
// Trigger the auto update event so that it doesn't take an hour for the first check to happen
|
// Trigger the auto update event so that it doesn't take an hour for the first check to happen
|
||||||
HandleAutoUpdateEvent(this, EventArgs.Empty);
|
if (performAutoUpdate)
|
||||||
|
HandleAutoUpdateEvent(this, EventArgs.Empty);
|
||||||
|
|
||||||
_logger.Information("Update service initialized for {Channel} channel", Channel);
|
_logger.Information("Update service initialized for {Channel} channel", Channel);
|
||||||
return false;
|
return false;
|
||||||
|
|||||||
@ -179,12 +179,26 @@ public class WorkshopService : IWorkshopService
|
|||||||
{
|
{
|
||||||
if (_initialized)
|
if (_initialized)
|
||||||
throw new ArtemisWorkshopException("Workshop service is already initialized");
|
throw new ArtemisWorkshopException("Workshop service is already initialized");
|
||||||
|
|
||||||
RemoveOrphanedFiles();
|
try
|
||||||
_pluginManagementService.AdditionalPluginDirectories.AddRange(GetInstalledEntries().Where(e => e.EntryType == EntryType.Plugin).Select(e => e.GetReleaseDirectory()));
|
{
|
||||||
_initialized = true;
|
if (!Directory.Exists(Constants.WorkshopFolder))
|
||||||
|
Directory.CreateDirectory(Constants.WorkshopFolder);
|
||||||
|
|
||||||
|
RemoveOrphanedFiles();
|
||||||
|
|
||||||
|
_pluginManagementService.AdditionalPluginDirectories.AddRange(GetInstalledEntries()
|
||||||
|
.Where(e => e.EntryType == EntryType.Plugin)
|
||||||
|
.Select(e => e.GetReleaseDirectory()));
|
||||||
|
|
||||||
|
_initialized = true;
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
_logger.Error(e, "Failed to initialize workshop service");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void RemoveOrphanedFiles()
|
private void RemoveOrphanedFiles()
|
||||||
{
|
{
|
||||||
List<InstalledEntry> entries = GetInstalledEntries();
|
List<InstalledEntry> entries = GetInstalledEntries();
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user