mirror of
https://github.com/wabbajack-tools/wabbajack.git
synced 2024-08-30 18:42:17 +00:00
Don't block the UI so much during install
This commit is contained in:
parent
28c0224af5
commit
83cf5a3436
@ -7,6 +7,7 @@ using System.Reactive.Subjects;
|
||||
using System.Timers;
|
||||
using DynamicData;
|
||||
using DynamicData.Kernel;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using ReactiveUI;
|
||||
using Wabbajack.RateLimiter;
|
||||
|
||||
@ -14,7 +15,7 @@ namespace Wabbajack.Models;
|
||||
|
||||
public class ResourceMonitor : IDisposable
|
||||
{
|
||||
private readonly TimeSpan PollInterval = TimeSpan.FromMilliseconds(1000);
|
||||
private readonly TimeSpan PollInterval = TimeSpan.FromMilliseconds(250);
|
||||
|
||||
private readonly IResource[] _resources;
|
||||
private readonly Timer _timer;
|
||||
@ -27,13 +28,15 @@ public class ResourceMonitor : IDisposable
|
||||
private readonly SourceCache<CPUDisplayVM, ulong> _tasks = new(x => x.ID);
|
||||
public readonly ReadOnlyObservableCollection<CPUDisplayVM> _tasksFiltered;
|
||||
private readonly CompositeDisposable _compositeDisposable;
|
||||
private readonly ILogger<ResourceMonitor> _logger;
|
||||
public ReadOnlyObservableCollection<CPUDisplayVM> Tasks => _tasksFiltered;
|
||||
|
||||
|
||||
|
||||
|
||||
public ResourceMonitor(IEnumerable<IResource> resources)
|
||||
public ResourceMonitor(ILogger<ResourceMonitor> logger, IEnumerable<IResource> resources)
|
||||
{
|
||||
_logger = logger;
|
||||
_compositeDisposable = new CompositeDisposable();
|
||||
_resources = resources.ToArray();
|
||||
_prev = _resources.Select(x => (x.Name, (long)0)).ToArray();
|
||||
@ -42,6 +45,7 @@ public class ResourceMonitor : IDisposable
|
||||
.DisposeWith(_compositeDisposable);
|
||||
|
||||
_tasks.Connect()
|
||||
.Filter(t => t.IsWorking)
|
||||
.Bind(out _tasksFiltered)
|
||||
.Subscribe()
|
||||
.DisposeWith(_compositeDisposable);
|
||||
@ -61,6 +65,7 @@ public class ResourceMonitor : IDisposable
|
||||
var used = new HashSet<ulong>();
|
||||
foreach (var resource in _resources)
|
||||
{
|
||||
_logger.LogInformation("Resource {Name}: {Jobs}", resource.Name, resource.Jobs.Count());
|
||||
foreach (var job in resource.Jobs)
|
||||
{
|
||||
used.Add(job.ID);
|
||||
@ -71,6 +76,7 @@ public class ResourceMonitor : IDisposable
|
||||
var t = tsk.Value;
|
||||
t.Msg = job.Description;
|
||||
t.ProgressPercent = job.Size == 0 ? Percent.Zero : Percent.FactoryPutInRange(job.Current, (long)job.Size);
|
||||
t.IsWorking = job.Current > 0;
|
||||
}
|
||||
|
||||
// Create
|
||||
@ -81,7 +87,8 @@ public class ResourceMonitor : IDisposable
|
||||
ID = job.ID,
|
||||
StartTime = DateTime.Now,
|
||||
Msg = job.Description,
|
||||
ProgressPercent = job.Size == 0 ? Percent.Zero : Percent.FactoryPutInRange(job.Current, (long) job.Size)
|
||||
ProgressPercent = job.Size == 0 ? Percent.Zero : Percent.FactoryPutInRange(job.Current, (long) job.Size),
|
||||
IsWorking = job.Current > 0,
|
||||
};
|
||||
l.AddOrUpdate(vm);
|
||||
}
|
||||
|
@ -272,57 +272,61 @@ public class InstallerVM : BackNavigatingVM, IBackNavigatingVM, ICpuStatusVM
|
||||
|
||||
private async Task BeginInstall()
|
||||
{
|
||||
InstallState = InstallState.Installing;
|
||||
var postfix = (await ModListLocation.TargetPath.ToString().Hash()).ToHex();
|
||||
await _settingsManager.Save(InstallSettingsPrefix + postfix, new SavedInstallSettings
|
||||
await Task.Run(async () =>
|
||||
{
|
||||
ModListLocation = ModListLocation.TargetPath,
|
||||
InstallLocation = Installer.Location.TargetPath,
|
||||
DownloadLoadction = Installer.DownloadLocation.TargetPath,
|
||||
Metadata = ModlistMetadata
|
||||
});
|
||||
|
||||
try
|
||||
{
|
||||
var installer = StandardInstaller.Create(_serviceProvider, new InstallerConfiguration
|
||||
InstallState = InstallState.Installing;
|
||||
var postfix = (await ModListLocation.TargetPath.ToString().Hash()).ToHex();
|
||||
await _settingsManager.Save(InstallSettingsPrefix + postfix, new SavedInstallSettings
|
||||
{
|
||||
Game = ModList.GameType,
|
||||
Downloads = Installer.DownloadLocation.TargetPath,
|
||||
Install = Installer.Location.TargetPath,
|
||||
ModList = ModList,
|
||||
ModlistArchive = ModListLocation.TargetPath,
|
||||
SystemParameters = _parametersConstructor.Create(),
|
||||
GameFolder = _gameLocator.GameLocation(ModList.GameType)
|
||||
ModListLocation = ModListLocation.TargetPath,
|
||||
InstallLocation = Installer.Location.TargetPath,
|
||||
DownloadLoadction = Installer.DownloadLocation.TargetPath,
|
||||
Metadata = ModlistMetadata
|
||||
});
|
||||
|
||||
|
||||
installer.OnStatusUpdate = update =>
|
||||
try
|
||||
{
|
||||
StatusText = update.StatusText;
|
||||
StatusProgress = update.StepsProgress;
|
||||
var installer = StandardInstaller.Create(_serviceProvider, new InstallerConfiguration
|
||||
{
|
||||
Game = ModList.GameType,
|
||||
Downloads = Installer.DownloadLocation.TargetPath,
|
||||
Install = Installer.Location.TargetPath,
|
||||
ModList = ModList,
|
||||
ModlistArchive = ModListLocation.TargetPath,
|
||||
SystemParameters = _parametersConstructor.Create(),
|
||||
GameFolder = _gameLocator.GameLocation(ModList.GameType)
|
||||
});
|
||||
|
||||
TaskBarUpdate.Send(update.StatusText, TaskbarItemProgressState.Indeterminate, update.StepsProgress.Value);
|
||||
};
|
||||
if (!await installer.Begin(CancellationToken.None))
|
||||
|
||||
installer.OnStatusUpdate = update =>
|
||||
{
|
||||
StatusText = update.StatusText;
|
||||
StatusProgress = update.StepsProgress;
|
||||
|
||||
TaskBarUpdate.Send(update.StatusText, TaskbarItemProgressState.Indeterminate,
|
||||
update.StepsProgress.Value);
|
||||
};
|
||||
if (!await installer.Begin(CancellationToken.None))
|
||||
{
|
||||
TaskBarUpdate.Send($"Error during install of {ModList.Name}", TaskbarItemProgressState.Error);
|
||||
InstallState = InstallState.Failure;
|
||||
StatusText = $"Error during install of {ModList.Name}";
|
||||
StatusProgress = Percent.Zero;
|
||||
}
|
||||
else
|
||||
{
|
||||
TaskBarUpdate.Send($"Finished install of {ModList.Name}", TaskbarItemProgressState.Normal);
|
||||
InstallState = InstallState.Success;
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
TaskBarUpdate.Send($"Error during install of {ModList.Name}", TaskbarItemProgressState.Error);
|
||||
InstallState = InstallState.Failure;
|
||||
StatusText = $"Error during install of {ModList.Name}";
|
||||
StatusProgress = Percent.Zero;
|
||||
}
|
||||
else
|
||||
{
|
||||
TaskBarUpdate.Send($"Finished install of {ModList.Name}", TaskbarItemProgressState.Normal);
|
||||
InstallState = InstallState.Success;
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
TaskBarUpdate.Send($"Error during install of {ModList.Name}", TaskbarItemProgressState.Error);
|
||||
InstallState = InstallState.Failure;
|
||||
StatusText = $"Error during install of {ModList.Name}";
|
||||
StatusProgress = Percent.Zero;
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
|
@ -47,9 +47,12 @@ namespace Wabbajack
|
||||
MessageBus.Current.Listen<TaskBarUpdate>()
|
||||
.Subscribe(u =>
|
||||
{
|
||||
TaskbarItemInfo.Description = u.Description;
|
||||
TaskbarItemInfo.ProgressValue = u.ProgressValue;
|
||||
TaskbarItemInfo.ProgressState = u.State;
|
||||
Dispatcher.Invoke(() =>
|
||||
{
|
||||
TaskbarItemInfo.Description = u.Description;
|
||||
TaskbarItemInfo.ProgressValue = u.ProgressValue;
|
||||
TaskbarItemInfo.ProgressState = u.State;
|
||||
});
|
||||
});
|
||||
|
||||
MessageBus.Current.Listen<OpenBrowserTab>()
|
||||
|
@ -62,14 +62,18 @@ public abstract class AInstaller<T>
|
||||
private readonly Stopwatch _updateStopWatch = new();
|
||||
|
||||
public Action<StatusUpdate>? OnStatusUpdate;
|
||||
private readonly IResource<IInstaller> _limiter;
|
||||
|
||||
|
||||
public AInstaller(ILogger<T> logger, InstallerConfiguration config, IGameLocator gameLocator,
|
||||
FileExtractor.FileExtractor extractor,
|
||||
DTOSerializer jsonSerializer, Context vfs, FileHashCache fileHashCache,
|
||||
DownloadDispatcher downloadDispatcher,
|
||||
ParallelOptions parallelOptions, Client wjClient)
|
||||
ParallelOptions parallelOptions,
|
||||
IResource<IInstaller> limiter,
|
||||
Client wjClient)
|
||||
{
|
||||
_limiter = limiter;
|
||||
_manager = new TemporaryFileManager(config.Install.Combine("__temp__"));
|
||||
ExtractedModlistFolder = _manager.CreateFolder();
|
||||
_configuration = config;
|
||||
@ -210,9 +214,12 @@ public abstract class AInstaller<T>
|
||||
|
||||
if (grouped.Count == 0) return;
|
||||
|
||||
|
||||
await _vfs.Extract(grouped.Keys.ToHashSet(), async (vf, sf) =>
|
||||
{
|
||||
foreach (var directive in grouped[vf])
|
||||
var directives = grouped[vf];
|
||||
using var job = await _limiter.Begin($"Installing files from {vf.Name}", directives.Sum(f => f.VF.Size), token);
|
||||
foreach (var directive in directives)
|
||||
{
|
||||
var file = directive.Directive;
|
||||
UpdateProgress(file.Size);
|
||||
@ -260,6 +267,8 @@ public abstract class AInstaller<T>
|
||||
default:
|
||||
throw new Exception($"No handler for {directive}");
|
||||
}
|
||||
|
||||
await job.Report((int)directive.VF.Size, token);
|
||||
}
|
||||
}, token);
|
||||
}
|
||||
|
@ -26,6 +26,7 @@ using Wabbajack.Installer.Utilities;
|
||||
using Wabbajack.Networking.WabbajackClientApi;
|
||||
using Wabbajack.Paths;
|
||||
using Wabbajack.Paths.IO;
|
||||
using Wabbajack.RateLimiter;
|
||||
using Wabbajack.VFS;
|
||||
|
||||
namespace Wabbajack.Installer;
|
||||
@ -38,9 +39,9 @@ public class StandardInstaller : AInstaller<StandardInstaller>
|
||||
InstallerConfiguration config,
|
||||
IGameLocator gameLocator, FileExtractor.FileExtractor extractor,
|
||||
DTOSerializer jsonSerializer, Context vfs, FileHashCache fileHashCache,
|
||||
DownloadDispatcher downloadDispatcher, ParallelOptions parallelOptions, Client wjClient) :
|
||||
DownloadDispatcher downloadDispatcher, ParallelOptions parallelOptions, IResource<IInstaller> limiter, Client wjClient) :
|
||||
base(logger, config, gameLocator, extractor, jsonSerializer, vfs, fileHashCache, downloadDispatcher,
|
||||
parallelOptions, wjClient)
|
||||
parallelOptions, limiter, wjClient)
|
||||
{
|
||||
MaxSteps = 14;
|
||||
}
|
||||
@ -56,6 +57,7 @@ public class StandardInstaller : AInstaller<StandardInstaller>
|
||||
provider.GetRequiredService<FileHashCache>(),
|
||||
provider.GetRequiredService<DownloadDispatcher>(),
|
||||
provider.GetRequiredService<ParallelOptions>(),
|
||||
provider.GetRequiredService<IResource<IInstaller>>(),
|
||||
provider.GetRequiredService<Client>());
|
||||
}
|
||||
|
||||
|
@ -96,6 +96,9 @@ public static class ServiceExtensions
|
||||
|
||||
service.AddAllSingleton<IResource, IResource<ACompiler>>(s =>
|
||||
new Resource<ACompiler>("Compiler", GetSettings(s, "Compiler")));
|
||||
|
||||
service.AddAllSingleton<IResource, IResource<IInstaller>>(s =>
|
||||
new Resource<IInstaller>("Installer", GetSettings(s, "Installer")));
|
||||
|
||||
service.AddSingleton<LoggingRateLimiterReporter>();
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user