mirror of
https://github.com/wabbajack-tools/wabbajack.git
synced 2024-08-30 18:42:17 +00:00
Merge pull request #1676 from wabbajack-tools/resources-in-settings-page
Resources in settings page
This commit is contained in:
commit
56cd1d5f14
15
Wabbajack.App/Controls/InstalledListView.axaml
Normal file
15
Wabbajack.App/Controls/InstalledListView.axaml
Normal file
@ -0,0 +1,15 @@
|
||||
<UserControl xmlns="https://github.com/avaloniaui"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:i="clr-namespace:Material.Icons.Avalonia;assembly=Material.Icons.Avalonia"
|
||||
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
|
||||
x:Class="Wabbajack.App.Controls.InstalledListView">
|
||||
<Grid RowDefinitions="Auto, Auto" ColumnDefinitions="*, Auto">
|
||||
<TextBlock Grid.Row="0" Grid.Column="0" x:Name="Title"></TextBlock>
|
||||
<TextBlock Grid.Row="1" Grid.Column="0" x:Name="InstallationPath"></TextBlock>
|
||||
<Button Grid.Row="0" Grid.Column="1" Grid.RowSpan="2" x:Name="PlayButton">
|
||||
<i:MaterialIcon Kind="PlayArrow"></i:MaterialIcon>
|
||||
</Button>
|
||||
</Grid>
|
||||
</UserControl>
|
28
Wabbajack.App/Controls/InstalledListView.axaml.cs
Normal file
28
Wabbajack.App/Controls/InstalledListView.axaml.cs
Normal file
@ -0,0 +1,28 @@
|
||||
using Avalonia.Controls.Mixins;
|
||||
using Avalonia.ReactiveUI;
|
||||
using ReactiveUI;
|
||||
using Wabbajack.App.Utilities;
|
||||
|
||||
namespace Wabbajack.App.Controls;
|
||||
|
||||
public partial class InstalledListView : ReactiveUserControl<InstalledListViewModel>, IActivatableView
|
||||
{
|
||||
public InstalledListView()
|
||||
{
|
||||
InitializeComponent();
|
||||
|
||||
this.WhenActivated(disposables =>
|
||||
{
|
||||
this.OneWayBind(ViewModel, vm => vm.Name, view => view.Title.Text)
|
||||
.DisposeWith(disposables);
|
||||
|
||||
this.OneWayBind(ViewModel, vm => vm.InstallPath, view => view.Title.Text,
|
||||
p => p.ToString())
|
||||
.DisposeWith(disposables);
|
||||
|
||||
this.BindCommand(ViewModel, vm => vm.Play, view => view.PlayButton)
|
||||
.DisposeWith(disposables);
|
||||
});
|
||||
}
|
||||
|
||||
}
|
32
Wabbajack.App/Controls/InstalledListViewModel.cs
Normal file
32
Wabbajack.App/Controls/InstalledListViewModel.cs
Normal file
@ -0,0 +1,32 @@
|
||||
using System.Reactive;
|
||||
using ReactiveUI;
|
||||
using ReactiveUI.Fody.Helpers;
|
||||
using Wabbajack.App.Messages;
|
||||
using Wabbajack.App.Screens;
|
||||
using Wabbajack.App.ViewModels;
|
||||
using Wabbajack.DTOs.SavedSettings;
|
||||
using Wabbajack.Paths;
|
||||
|
||||
namespace Wabbajack.App.Controls;
|
||||
|
||||
public class InstalledListViewModel : ViewModelBase
|
||||
{
|
||||
private readonly InstallationConfigurationSetting _setting;
|
||||
public AbsolutePath InstallPath => _setting.Install;
|
||||
|
||||
public string Name => _setting.Metadata?.Title ?? "";
|
||||
public ReactiveCommand<Unit, Unit> Play { get; }
|
||||
|
||||
public InstalledListViewModel(InstallationConfigurationSetting setting)
|
||||
{
|
||||
Activator = new ViewModelActivator();
|
||||
_setting = setting;
|
||||
|
||||
Play = ReactiveCommand.Create(() =>
|
||||
{
|
||||
MessageBus.Instance.Send(new ConfigureLauncher(InstallPath));
|
||||
MessageBus.Instance.Send(new NavigateTo(typeof(LauncherViewModel)));
|
||||
});
|
||||
}
|
||||
|
||||
}
|
16
Wabbajack.App/Controls/ResourceView.axaml
Normal file
16
Wabbajack.App/Controls/ResourceView.axaml
Normal file
@ -0,0 +1,16 @@
|
||||
<UserControl xmlns="https://github.com/avaloniaui"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
|
||||
x:Class="Wabbajack.App.Controls.ResourceView">
|
||||
<StackPanel Orientation="Horizontal">
|
||||
<TextBlock x:Name="ResourceName" Width="100" HorizontalAlignment="Left" VerticalAlignment="Center"></TextBlock>
|
||||
<Label Width="100" HorizontalContentAlignment="Right" VerticalAlignment="Center">Tasks:</Label>
|
||||
<TextBox x:Name="MaxTasks" Width="20" HorizontalAlignment="Left" VerticalAlignment="Center"></TextBox>
|
||||
<Label Width="100" HorizontalContentAlignment="Right" VerticalAlignment="Center">Throughput:</Label>
|
||||
<TextBox x:Name="MaxThroughput" Width="20" HorizontalAlignment="Left" VerticalAlignment="Center"></TextBox>
|
||||
<Label Width="100" HorizontalContentAlignment="Right" VerticalAlignment="Center">Status:</Label>
|
||||
<TextBlock x:Name="CurrentThrougput" Width="50" HorizontalAlignment="Left" VerticalAlignment="Center"></TextBlock>
|
||||
</StackPanel>
|
||||
</UserControl>
|
32
Wabbajack.App/Controls/ResourceView.axaml.cs
Normal file
32
Wabbajack.App/Controls/ResourceView.axaml.cs
Normal file
@ -0,0 +1,32 @@
|
||||
|
||||
|
||||
using System.Reactive.Disposables;
|
||||
using Avalonia.ReactiveUI;
|
||||
using FluentFTP.Helpers;
|
||||
using ReactiveUI;
|
||||
|
||||
namespace Wabbajack.App.Controls;
|
||||
|
||||
public partial class ResourceView : ReactiveUserControl<ResourceViewModel>, IActivatableView
|
||||
{
|
||||
public ResourceView()
|
||||
{
|
||||
InitializeComponent();
|
||||
this.WhenActivated(disposables =>
|
||||
{
|
||||
this.OneWayBind(ViewModel, vm => vm.Name, view => view.ResourceName.Text)
|
||||
.DisposeWith(disposables);
|
||||
|
||||
this.Bind(ViewModel, vm => vm.MaxTasks, view => view.MaxTasks.Text)
|
||||
.DisposeWith(disposables);
|
||||
this.Bind(ViewModel, vm => vm.MaxThroughput, view => view.MaxThroughput.Text)
|
||||
.DisposeWith(disposables);
|
||||
|
||||
this.OneWayBind(ViewModel, vm => vm.CurrentThroughput, view => view.CurrentThrougput.Text,
|
||||
val => val.FileSizeToString())
|
||||
.DisposeWith(disposables);
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
}
|
76
Wabbajack.App/Controls/ResourceViewModel.cs
Normal file
76
Wabbajack.App/Controls/ResourceViewModel.cs
Normal file
@ -0,0 +1,76 @@
|
||||
using System;
|
||||
using System.Reactive.Disposables;
|
||||
using System.Reactive.Linq;
|
||||
using System.Timers;using ReactiveUI;
|
||||
using ReactiveUI.Fody.Helpers;
|
||||
using Wabbajack.App.ViewModels;
|
||||
using Wabbajack.RateLimiter;
|
||||
|
||||
namespace Wabbajack.App.Controls;
|
||||
|
||||
public class ResourceViewModel : ViewModelBase, IActivatableViewModel, IDisposable
|
||||
{
|
||||
private readonly IResource _resource;
|
||||
private readonly Timer _timer;
|
||||
|
||||
[Reactive]
|
||||
public int MaxTasks { get; set; }
|
||||
|
||||
[Reactive]
|
||||
public long MaxThroughput { get; set; }
|
||||
|
||||
[Reactive]
|
||||
public long CurrentThroughput { get; set; }
|
||||
|
||||
[Reactive]
|
||||
public string Name { get; set; }
|
||||
|
||||
public ResourceViewModel(IResource resource)
|
||||
{
|
||||
Activator = new ViewModelActivator();
|
||||
_resource = resource;
|
||||
_timer = new Timer(1.0);
|
||||
|
||||
Name = resource.Name;
|
||||
|
||||
this.WhenActivated(disposables =>
|
||||
{
|
||||
_timer.Elapsed += TimerElapsed;
|
||||
_timer.Start();
|
||||
|
||||
Disposable.Create(() =>
|
||||
{
|
||||
_timer.Stop();
|
||||
_timer.Elapsed -= TimerElapsed;
|
||||
}).DisposeWith(disposables);
|
||||
|
||||
this.WhenAnyValue(vm => vm.MaxThroughput)
|
||||
.Skip(1)
|
||||
.Subscribe(v =>
|
||||
{
|
||||
_resource.MaxThroughput = MaxThroughput;
|
||||
}).DisposeWith(disposables);
|
||||
|
||||
this.WhenAnyValue(vm => vm.MaxTasks)
|
||||
.Skip(1)
|
||||
.Subscribe(v =>
|
||||
{
|
||||
_resource.MaxTasks = MaxTasks;
|
||||
}).DisposeWith(disposables);
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
private void TimerElapsed(object? sender, ElapsedEventArgs e)
|
||||
{
|
||||
MaxTasks = _resource.MaxTasks;
|
||||
MaxThroughput = _resource.MaxThroughput;
|
||||
CurrentThroughput = _resource.StatusReport.Transferred;
|
||||
}
|
||||
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
_timer.Dispose();
|
||||
}
|
||||
}
|
22
Wabbajack.App/Screens/PlaySelectView.axaml
Normal file
22
Wabbajack.App/Screens/PlaySelectView.axaml
Normal file
@ -0,0 +1,22 @@
|
||||
<UserControl xmlns="https://github.com/avaloniaui"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:controls="clr-namespace:Wabbajack.App.Controls"
|
||||
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
|
||||
x:Class="Wabbajack.App.Screens.PlaySelectView">
|
||||
<Grid RowDefinitions="*">
|
||||
<ItemsControl x:Name="Lists">
|
||||
<ItemsControl.ItemsPanel>
|
||||
<ItemsPanelTemplate>
|
||||
<StackPanel></StackPanel>
|
||||
</ItemsPanelTemplate>
|
||||
</ItemsControl.ItemsPanel>
|
||||
<ItemsControl.ItemTemplate>
|
||||
<DataTemplate>
|
||||
<controls:InstalledListView></controls:InstalledListView>
|
||||
</DataTemplate>
|
||||
</ItemsControl.ItemTemplate>
|
||||
</ItemsControl>
|
||||
</Grid>
|
||||
</UserControl>
|
19
Wabbajack.App/Screens/PlaySelectView.axaml.cs
Normal file
19
Wabbajack.App/Screens/PlaySelectView.axaml.cs
Normal file
@ -0,0 +1,19 @@
|
||||
using Avalonia.Controls.Mixins;
|
||||
using ReactiveUI;
|
||||
using Wabbajack.App.Views;
|
||||
|
||||
namespace Wabbajack.App.Screens;
|
||||
|
||||
public partial class PlaySelectView : ScreenBase<PlaySelectViewModel>
|
||||
{
|
||||
public PlaySelectView()
|
||||
{
|
||||
InitializeComponent();
|
||||
this.WhenActivated(disposables =>
|
||||
{
|
||||
this.OneWayBind(ViewModel, vm => vm.Items, view => view.Lists.Items)
|
||||
.DisposeWith(disposables);
|
||||
});
|
||||
}
|
||||
|
||||
}
|
40
Wabbajack.App/Screens/PlaySelectViewModel.cs
Normal file
40
Wabbajack.App/Screens/PlaySelectViewModel.cs
Normal file
@ -0,0 +1,40 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Reactive.Disposables;
|
||||
using System.Threading.Tasks;
|
||||
using ReactiveUI;
|
||||
using ReactiveUI.Fody.Helpers;
|
||||
using Wabbajack.App.Controls;
|
||||
using Wabbajack.App.Models;
|
||||
using Wabbajack.App.ViewModels;
|
||||
using Wabbajack.Common;
|
||||
using Wabbajack.DTOs.SavedSettings;
|
||||
|
||||
namespace Wabbajack.App.Screens;
|
||||
|
||||
public class PlaySelectViewModel : ViewModelBase, IActivatableViewModel
|
||||
{
|
||||
private readonly InstallationStateManager _manager;
|
||||
|
||||
[Reactive]
|
||||
public IEnumerable<InstalledListViewModel> Items { get; set; }
|
||||
|
||||
public PlaySelectViewModel(InstallationStateManager manager)
|
||||
{
|
||||
_manager = manager;
|
||||
Activator = new ViewModelActivator();
|
||||
|
||||
this.WhenActivated(disposables =>
|
||||
{
|
||||
LoadAndSetItems().FireAndForget();
|
||||
Disposable.Empty.DisposeWith(disposables);
|
||||
});
|
||||
}
|
||||
|
||||
public async Task LoadAndSetItems()
|
||||
{
|
||||
var items = await _manager.GetAll();
|
||||
Items = items.Settings.Select(a => new InstalledListViewModel(a)).ToArray();
|
||||
}
|
||||
|
||||
}
|
@ -2,6 +2,7 @@
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:controls="clr-namespace:Wabbajack.App.Controls"
|
||||
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
|
||||
x:Class="Wabbajack.App.Screens.SettingsView">
|
||||
<WrapPanel Margin="40">
|
||||
@ -26,5 +27,25 @@
|
||||
|
||||
</Grid>
|
||||
</Border>
|
||||
|
||||
<Border x:Name="ResourcesBorder" Margin="5" BorderThickness="1">
|
||||
<Grid RowDefinitions="Auto, Auto">
|
||||
<TextBlock FontSize="20" Grid.ColumnSpan="4">Resource Limits</TextBlock>
|
||||
|
||||
<ItemsControl Grid.Row="1" x:Name="ResourceList">
|
||||
<ItemsControl.ItemsPanel>
|
||||
<ItemsPanelTemplate>
|
||||
<StackPanel Orientation="Vertical"></StackPanel>
|
||||
</ItemsPanelTemplate>
|
||||
</ItemsControl.ItemsPanel>
|
||||
<ItemsControl.ItemTemplate>
|
||||
<DataTemplate>
|
||||
<controls:ResourceView></controls:ResourceView>
|
||||
</DataTemplate>
|
||||
</ItemsControl.ItemTemplate>
|
||||
</ItemsControl>
|
||||
|
||||
</Grid>
|
||||
</Border>
|
||||
</WrapPanel>
|
||||
</UserControl>
|
||||
|
@ -16,6 +16,8 @@ namespace Wabbajack.App.Screens
|
||||
.DisposeWith(disposables);
|
||||
this.BindCommand(ViewModel, vm => vm.NexusLogout, view => view.NexusLogOut)
|
||||
.DisposeWith(disposables);
|
||||
this.OneWayBind(ViewModel, vm => vm.Resources, view => view.ResourceList.Items)
|
||||
.DisposeWith(disposables);
|
||||
|
||||
});
|
||||
}
|
||||
|
@ -1,14 +1,18 @@
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Reactive;
|
||||
using System.Reactive.Disposables;
|
||||
using System.Reactive.Linq;
|
||||
using System.Reactive.Subjects;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using ReactiveUI;
|
||||
using Wabbajack.App.Controls;
|
||||
using Wabbajack.App.Messages;
|
||||
using Wabbajack.App.ViewModels;
|
||||
using Wabbajack.Paths;
|
||||
using Wabbajack.Paths.IO;
|
||||
using Wabbajack.RateLimiter;
|
||||
using Wabbajack.Services.OSIntegrated.TokenProviders;
|
||||
|
||||
namespace Wabbajack.App.Screens
|
||||
@ -23,10 +27,12 @@ namespace Wabbajack.App.Screens
|
||||
public FileSystemWatcher Watcher { get; set; }
|
||||
|
||||
private readonly Subject<AbsolutePath> _fileSystemEvents = new();
|
||||
|
||||
public SettingsViewModel(ILogger<SettingsViewModel> logger, Configuration configuration, NexusApiTokenProvider nexusProvider)
|
||||
public readonly IEnumerable<ResourceViewModel> Resources;
|
||||
|
||||
public SettingsViewModel(ILogger<SettingsViewModel> logger, Configuration configuration, NexusApiTokenProvider nexusProvider, IEnumerable<IResource> resources)
|
||||
{
|
||||
_logger = logger;
|
||||
Resources = resources.Select(r => new ResourceViewModel(r)).ToArray();
|
||||
Activator = new ViewModelActivator();
|
||||
|
||||
this.WhenActivated(disposables =>
|
||||
|
@ -36,11 +36,11 @@ namespace Wabbajack.App
|
||||
services.AddSingleton<MessageBus>();
|
||||
services.AddSingleton<MainWindow>();
|
||||
services.AddSingleton<BrowseViewModel>();
|
||||
|
||||
services.AddTransient<BrowseItemViewModel>();
|
||||
|
||||
services.AddTransient<LogViewModel>();
|
||||
|
||||
services.AddTransient<InstalledListViewModel>();
|
||||
|
||||
services.AddDTOConverters();
|
||||
services.AddDTOSerializer();
|
||||
services.AddSingleton<ModeSelectionViewModel>();
|
||||
@ -55,11 +55,13 @@ namespace Wabbajack.App
|
||||
services.AddSingleton<IScreenView, SettingsView>();
|
||||
services.AddSingleton<IScreenView, BrowseView>();
|
||||
services.AddSingleton<IScreenView, LauncherView>();
|
||||
services.AddSingleton<IScreenView, PlaySelectView>();
|
||||
|
||||
services.AddSingleton<InstallationStateManager>();
|
||||
services.AddSingleton<HttpClient>();
|
||||
|
||||
services.AddSingleton<LogScreenViewModel>();
|
||||
services.AddSingleton<PlaySelectViewModel>();
|
||||
services.AddAllSingleton<IReceiverMarker, ErrorPageViewModel>();
|
||||
services.AddAllSingleton<IReceiverMarker, StandardInstallationViewModel>();
|
||||
services.AddAllSingleton<IReceiverMarker, InstallConfigurationViewModel>();
|
||||
|
@ -18,7 +18,7 @@
|
||||
<controls:LargeIconButton Grid.Column="0" Text="Browse" Icon="CloudDownload" x:Name="BrowseButton"></controls:LargeIconButton>
|
||||
<controls:LargeIconButton Grid.Column="1" Text="Install" Icon="HarddiskPlus" x:Name="InstallButton"></controls:LargeIconButton>
|
||||
<controls:LargeIconButton Grid.Column="2" Text="Compile" Icon="DatabaseImport" x:Name="CompileButton"></controls:LargeIconButton>
|
||||
<controls:LargeIconButton Grid.Column="3" Text="Play" Icon="TelevisionPlay"></controls:LargeIconButton>
|
||||
<controls:LargeIconButton Grid.Column="3" Text="Play" Icon="TelevisionPlay" x:Name="LaunchButton"></controls:LargeIconButton>
|
||||
</Grid>
|
||||
</Grid>
|
||||
</UserControl>
|
||||
|
@ -29,6 +29,11 @@ namespace Wabbajack.App.Views
|
||||
{
|
||||
MessageBus.Instance.Send(new NavigateTo(typeof(CompilerConfigurationViewModel)));
|
||||
}).DisposeWith(disposables);
|
||||
|
||||
LaunchButton.Button.Command = ReactiveCommand.Create(() =>
|
||||
{
|
||||
MessageBus.Instance.Send(new NavigateTo(typeof(PlaySelectViewModel)));
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -7,7 +7,8 @@ namespace Wabbajack.RateLimiter
|
||||
{
|
||||
StatusReport StatusReport { get; }
|
||||
string Name { get; }
|
||||
|
||||
int MaxTasks { get; set; }
|
||||
long MaxThroughput { get; set; }
|
||||
}
|
||||
public interface IResource<T> : IResource
|
||||
{
|
||||
|
@ -16,8 +16,8 @@ namespace Wabbajack.RateLimiter
|
||||
private readonly ConcurrentDictionary<ulong, Job<T>> _tasks;
|
||||
private ulong _nextId = 0;
|
||||
private long _totalUsed = 0;
|
||||
private readonly int _maxTasks;
|
||||
private readonly long _maxThroughput;
|
||||
public int MaxTasks { get; set; }
|
||||
public long MaxThroughput { get; set; }
|
||||
private readonly string _humanName;
|
||||
public string Name => _humanName;
|
||||
|
||||
@ -26,10 +26,10 @@ namespace Wabbajack.RateLimiter
|
||||
public Resource(string? humanName = null, int? maxTasks = 0, long maxThroughput = long.MaxValue)
|
||||
{
|
||||
_humanName = humanName ?? "<unknown>";
|
||||
_maxTasks = maxTasks ?? Environment.ProcessorCount;
|
||||
_maxThroughput = maxThroughput;
|
||||
MaxTasks = maxTasks ?? Environment.ProcessorCount;
|
||||
MaxThroughput = maxThroughput;
|
||||
|
||||
_semaphore = new SemaphoreSlim(_maxTasks);
|
||||
_semaphore = new SemaphoreSlim(MaxTasks);
|
||||
_channel = Channel.CreateBounded<PendingReport>(10);
|
||||
_tasks = new ();
|
||||
|
||||
@ -44,14 +44,14 @@ namespace Wabbajack.RateLimiter
|
||||
await foreach (var item in _channel.Reader.ReadAllAsync(token))
|
||||
{
|
||||
Interlocked.Add(ref _totalUsed, item.Size);
|
||||
if (_maxThroughput == long.MaxValue)
|
||||
if (MaxThroughput == long.MaxValue)
|
||||
{
|
||||
item.Result.TrySetResult();
|
||||
sw.Restart();
|
||||
continue;
|
||||
}
|
||||
|
||||
var span = TimeSpan.FromSeconds((double)item.Size / _maxThroughput);
|
||||
var span = TimeSpan.FromSeconds((double)item.Size / MaxThroughput);
|
||||
|
||||
|
||||
await Task.Delay(span, token);
|
||||
|
Loading…
Reference in New Issue
Block a user