Wow that was about as easy as pulling Trex teeth. Not sure why the RxApp scheduler isn't the same as the WPF scheduler

This commit is contained in:
Timothy Baldridge 2021-12-29 21:43:31 -07:00
parent cc8c40f803
commit 2215acf0e9
6 changed files with 96 additions and 56 deletions

View File

@ -4,7 +4,8 @@
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:Wabbajack"
ShutdownMode="OnExplicitShutdown"
Startup="OnStartup">
Startup="OnStartup"
Exit="OnExit">
<Application.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>

View File

@ -1,8 +1,14 @@
using System;
using System.Reactive.Concurrency;
using System.Reactive.Disposables;
using System.Windows;
using System.Windows.Threading;
using CefSharp.DevTools.Debugger;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using ReactiveUI;
using Splat;
using Wabbajack.Common;
using Wabbajack;
using Wabbajack.Services.OSIntegrated;
@ -16,18 +22,27 @@ namespace Wabbajack
public partial class App
{
private readonly IServiceProvider _serviceProvider;
private readonly IHost _host;
public App()
{
var services = new ServiceCollection();
_host = Host.CreateDefaultBuilder(Array.Empty<string>())
.ConfigureLogging(c =>
{
c.ClearProviders();
})
.ConfigureServices((host, services) =>
{
ConfigureServices(services);
})
.Build();
var host = Host.CreateDefaultBuilder(Array.Empty<string>())
//.ConfigureLogging(c => { c.ClearProviders(); })
.ConfigureServices((host, services) => { ConfigureServices(services); }).Build();
_serviceProvider = host.Services;
_serviceProvider = _host.Services;
}
private IServiceCollection ConfigureServices(IServiceCollection services)
{
RxApp.MainThreadScheduler = new DispatcherScheduler(Dispatcher.CurrentDispatcher);
services.AddOSIntegrated();
services.AddTransient<MainWindow>();
services.AddTransient<MainWindowVM>();
@ -40,13 +55,25 @@ namespace Wabbajack
services.AddTransient<ModeSelectionVM>();
services.AddTransient<ModListGalleryVM>();
return services;
}
private void OnStartup(object sender, StartupEventArgs e)
{
var mainWindow = _serviceProvider.GetRequiredService<MainWindow>();
mainWindow!.Show();
RxApp.MainThreadScheduler.Schedule(0, (_, _) =>
{
var mainWindow = _serviceProvider.GetRequiredService<MainWindow>();
mainWindow!.Show();
return Disposable.Empty;
});
}
private void OnExit(object sender, ExitEventArgs e)
{
using (_host)
{
_host.StopAsync();
}
base.OnExit(e);
}
}
}

View File

@ -6,6 +6,7 @@ using System.Reactive.Disposables;
using System.Reactive.Linq;
using System.Reactive.Subjects;
using System.Threading.Tasks;
using System.Windows.Threading;
using DynamicData;
using DynamicData.Kernel;
using ReactiveUI;

View File

@ -63,6 +63,9 @@ namespace Wabbajack
[Reactive]
public bool IsBroken { get; private set; }
[Reactive]
public ModListStatus Status { get; set; }
[Reactive]
public bool IsDownloading { get; private set; }
@ -99,6 +102,8 @@ namespace Wabbajack
_wjClient = wjClient;
Location = LauncherUpdater.CommonFolder.Value.Combine("downloaded_mod_lists", Metadata.Links.MachineURL).WithExtension(Ext.Wabbajack);
ModListTagList = new List<ModListTag>();
UpdateStatus().FireAndForget();
Metadata.Tags.ForEach(tag =>
{
@ -224,6 +229,9 @@ namespace Wabbajack
private async Task Download()
{
Status = ModListStatus.Downloading;
using var ll = LoadingLock.WithLoading();
var (progress, task) = _maintainer.DownloadModlist(Metadata);
var dispose = progress
.BindToStrict(this, vm => vm.ProgressPercent);
@ -231,7 +239,25 @@ namespace Wabbajack
await task;
await _wjClient.SendMetric("downloading", Metadata.Title);
await UpdateStatus();
dispose.Dispose();
}
private async Task UpdateStatus()
{
if (await _maintainer.HaveModList(Metadata))
Status = ModListStatus.Downloaded;
else if (LoadingLock.IsLoading)
Status = ModListStatus.Downloading;
else
Status = ModListStatus.NotDownloaded;
}
public enum ModListStatus
{
NotDownloaded,
Downloading,
Downloaded
}
}
}

View File

@ -356,51 +356,13 @@
Height="40"
Margin="5,0"
VerticalAlignment="Center">
<Button.Style>
<Style BasedOn="{StaticResource IconBareButtonStyle}" TargetType="Button">
<Setter Property="Content">
<Setter.Value>
<iconPacks:Material
Width="20"
Height="20"
Kind="Download" />
</Setter.Value>
</Setter>
<Setter Property="ToolTip" Value="Download modlist" />
<Style.Triggers>
<MultiDataTrigger>
<MultiDataTrigger.Conditions>
<Condition Binding="{Binding Exists}" Value="True" />
<Condition Binding="{Binding IsEnabled, RelativeSource={RelativeSource Self}}" Value="True" />
</MultiDataTrigger.Conditions>
<MultiDataTrigger.Setters>
<Setter Property="Content">
<Setter.Value>
<iconPacks:Material
Width="20"
Height="20"
Kind="Play" />
</Setter.Value>
</Setter>
<Setter Property="ToolTip" Value="Install modlist" />
<Setter Property="Padding" Value="3,0,0,0" />
</MultiDataTrigger.Setters>
</MultiDataTrigger>
<DataTrigger Binding="{Binding Error.Succeeded}" Value="False">
<Setter Property="Content">
<Setter.Value>
<iconPacks:Material
Width="20"
Height="20"
Kind="AlertCircle" />
</Setter.Value>
</Setter>
<Setter Property="ToolTip" Value="Error downloading modlist. Check logs and/or restart Wabbajack to try again." />
<Setter Property="Foreground" Value="{StaticResource ErrorBrush}" />
</DataTrigger>
</Style.Triggers>
</Style>
</Button.Style>
<StackPanel x:Name="IconContainer">
<iconPacks:Material
x:Name="ErrorIcon"
Width="20"
Height="20"
Kind="Exclamation" />
</StackPanel>
</Button>
</Grid>

View File

@ -1,6 +1,9 @@
using System.Reactive.Disposables;
using System;
using System.Reactive.Disposables;
using System.Reactive.Linq;
using System.Windows;
using System.Windows.Media.Media3D;
using MahApps.Metro.IconPacks;
using ReactiveUI;
namespace Wabbajack
@ -65,6 +68,26 @@ namespace Wabbajack
.BindTo(this, x => x.DownloadProgressBar.Value)
.DisposeWith(disposables);
ViewModel.WhenAnyValue(x => x.Status)
.ObserveOnGuiThread()
.Subscribe(x =>
{
IconContainer.Children.Clear();
IconContainer.Children.Add(new PackIconMaterial
{
Width = 20,
Height = 20,
Kind = x switch
{
ModListMetadataVM.ModListStatus.Downloaded => PackIconMaterialKind.Play,
ModListMetadataVM.ModListStatus.Downloading => PackIconMaterialKind.Network,
ModListMetadataVM.ModListStatus.NotDownloaded => PackIconMaterialKind.Download,
_ => throw new ArgumentOutOfRangeException(nameof(x), x, null)
}
});
})
.DisposeWith(disposables);
/*
this.MarkAsNeeded<ModListTileView, ModListMetadataVM, bool>(this.ViewModel, x => x.IsBroken);
this.MarkAsNeeded<ModListTileView, ModListMetadataVM, bool>(this.ViewModel, x => x.Exists);