Merge pull request #1709 from wabbajack-tools/style-play-buttons

Style play buttons
This commit is contained in:
Timothy Baldridge 2021-11-08 06:55:17 -07:00 committed by GitHub
commit 09667841e9
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
16 changed files with 212 additions and 58 deletions

View File

@ -62,6 +62,22 @@
<Setter Property="CornerRadius" Value="4"></Setter> <Setter Property="CornerRadius" Value="4"></Setter>
</Style> </Style>
<Style Selector=".InstalledList Border">
<Setter Property="BorderThickness" Value="2"></Setter>
<Setter Property="BorderBrush" Value="DarkGray"></Setter>
<Setter Property="CornerRadius" Value="4"></Setter>
</Style>
<Style Selector=".InstalledList TextBlock">
<Setter Property="FontWeight" Value="Bold"></Setter>
<Setter Property="FontSize" Value="18"></Setter>
<Setter Property="Margin" Value="4"/>
</Style>
<Style Selector="Button.InstalledList">
<Setter Property="Margin" Value="4"></Setter>
</Style>
</Styles> </Styles>

View File

@ -5,11 +5,15 @@
xmlns:i="clr-namespace:Material.Icons.Avalonia;assembly=Material.Icons.Avalonia" xmlns:i="clr-namespace:Material.Icons.Avalonia;assembly=Material.Icons.Avalonia"
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450" mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
x:Class="Wabbajack.App.Controls.InstalledListView"> x:Class="Wabbajack.App.Controls.InstalledListView">
<Grid RowDefinitions="Auto, Auto" ColumnDefinitions="*, Auto"> <Button Name="ListButton" Classes="InstalledList" HorizontalAlignment="Stretch">
<TextBlock Grid.Row="0" Grid.Column="0" x:Name="Title" /> <Border Classes="InstalledList">
<TextBlock Grid.Row="1" Grid.Column="0" x:Name="InstallationPath" /> <Grid RowDefinitions="Auto, Auto Auto, Auto" ColumnDefinitions="Auto, *">
<Button Grid.Row="0" Grid.Column="1" Grid.RowSpan="2" x:Name="PlayButton"> <Image x:Name="ListImage" Grid.RowSpan="4" Grid.Row="0" Grid.Column="0" Width="270" Height="150"></Image>
<i:MaterialIcon Kind="PlayArrow" /> <TextBlock Grid.Row="0" Grid.Column="1" x:Name="Title" />
</Button> <TextBlock Grid.Row="1" Grid.Column="1" x:Name="Version" />
<TextBlock Grid.Row="2" Grid.Column="1" x:Name="Author"></TextBlock>
<TextBlock Grid.Row="3" Grid.Column="1" x:Name="InstallationPath" />
</Grid> </Grid>
</Border>
</Button>
</UserControl> </UserControl>

View File

@ -12,14 +12,23 @@ public partial class InstalledListView : ReactiveUserControl<InstalledListViewMo
this.WhenActivated(disposables => this.WhenActivated(disposables =>
{ {
this.OneWayBind(ViewModel, vm => vm.Image, view => view.ListImage.Source)
.DisposeWith(disposables);
this.OneWayBind(ViewModel, vm => vm.Name, view => view.Title.Text) this.OneWayBind(ViewModel, vm => vm.Name, view => view.Title.Text)
.DisposeWith(disposables); .DisposeWith(disposables);
this.OneWayBind(ViewModel, vm => vm.InstallPath, view => view.Title.Text, this.OneWayBind(ViewModel, vm => vm.Author, view => view.Author.Text)
.DisposeWith(disposables);
this.OneWayBind(ViewModel, vm => vm.Version, view => view.Version.Text)
.DisposeWith(disposables);
this.OneWayBind(ViewModel, vm => vm.InstallPath, view => view.InstallationPath.Text,
p => p.ToString()) p => p.ToString())
.DisposeWith(disposables); .DisposeWith(disposables);
this.BindCommand(ViewModel, vm => vm.Play, view => view.PlayButton) this.BindCommand(ViewModel, vm => vm.Play, view => view.ListButton)
.DisposeWith(disposables); .DisposeWith(disposables);
}); });
} }

View File

@ -1,8 +1,14 @@
using System.Reactive; using System.Reactive;
using System.Threading.Tasks;
using Avalonia.Media.Imaging;
using Avalonia.Threading;
using ReactiveUI; using ReactiveUI;
using ReactiveUI.Fody.Helpers;
using Wabbajack.App.Messages; using Wabbajack.App.Messages;
using Wabbajack.App.Models;
using Wabbajack.App.Screens; using Wabbajack.App.Screens;
using Wabbajack.App.ViewModels; using Wabbajack.App.ViewModels;
using Wabbajack.Common;
using Wabbajack.DTOs.SavedSettings; using Wabbajack.DTOs.SavedSettings;
using Wabbajack.Paths; using Wabbajack.Paths;
@ -12,7 +18,7 @@ public class InstalledListViewModel : ViewModelBase
{ {
private readonly InstallationConfigurationSetting _setting; private readonly InstallationConfigurationSetting _setting;
public InstalledListViewModel(InstallationConfigurationSetting setting) public InstalledListViewModel(InstallationConfigurationSetting setting, ImageCache imageCache)
{ {
Activator = new ViewModelActivator(); Activator = new ViewModelActivator();
_setting = setting; _setting = setting;
@ -22,10 +28,28 @@ public class InstalledListViewModel : ViewModelBase
MessageBus.Current.SendMessage(new ConfigureLauncher(InstallPath)); MessageBus.Current.SendMessage(new ConfigureLauncher(InstallPath));
MessageBus.Current.SendMessage(new NavigateTo(typeof(LauncherViewModel))); MessageBus.Current.SendMessage(new NavigateTo(typeof(LauncherViewModel)));
}); });
LoadImage(imageCache).FireAndForget();
}
public async Task LoadImage(ImageCache cache)
{
var img = await cache.From(_setting.Install.Combine("modlist-image.png"), 270, 150);
Dispatcher.UIThread.Post(() =>
{
Image = img;
});
} }
public AbsolutePath InstallPath => _setting.Install; public AbsolutePath InstallPath => _setting.Install;
public string Name => _setting.Metadata?.Title ?? ""; public string Name => _setting.Metadata?.Title ?? "";
public string Version => _setting.Metadata?.Version?.ToString() ?? "";
public string Author => _setting.Metadata?.Author ?? "";
public ReactiveCommand<Unit, Unit> Play { get; } public ReactiveCommand<Unit, Unit> Play { get; }
[Reactive]
public IBitmap Image { get; set; }
} }

View File

@ -9,21 +9,16 @@
<Grid RowDefinitions="Auto, *, Auto" Classes="LogView"> <Grid RowDefinitions="Auto, *, Auto" Classes="LogView">
<TextBlock Grid.Row="0" Classes="Title">Current Log Contents</TextBlock> <TextBlock Grid.Row="0" Classes="Title">Current Log Contents</TextBlock>
<Border Grid.Row="1"> <Border Grid.Row="1">
<ScrollViewer ScrollChanged="ScrollViewer_OnScrollChanged" x:Name="ScrollViewer" <ItemsRepeater x:Name="Messages">
HorizontalScrollBarVisibility="Visible" VerticalScrollBarVisibility="Visible"> <ItemsRepeater.Layout>
<ItemsControl x:Name="Messages"> <StackLayout></StackLayout>
<ItemsControl.ItemsPanel> </ItemsRepeater.Layout>
<ItemsPanelTemplate> <ItemsRepeater.ItemTemplate>
<StackPanel />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate> <DataTemplate>
<controls:LogViewItem /> <controls:LogViewItem />
</DataTemplate> </DataTemplate>
</ItemsControl.ItemTemplate> </ItemsRepeater.ItemTemplate>
</ItemsControl> </ItemsRepeater>
</ScrollViewer>
</Border> </Border>
<StackPanel Grid.Row="2" Orientation="Horizontal" HorizontalAlignment="Right"> <StackPanel Grid.Row="2" Orientation="Horizontal" HorizontalAlignment="Right">
<Button x:Name="CopyLog"> <Button x:Name="CopyLog">

View File

@ -1,3 +1,4 @@
using System.Linq;
using Avalonia.Controls; using Avalonia.Controls;
using Avalonia.Controls.Mixins; using Avalonia.Controls.Mixins;
using Avalonia.ReactiveUI; using Avalonia.ReactiveUI;
@ -14,15 +15,11 @@ public partial class LogView : ReactiveUserControl<LogViewModel>
InitializeComponent(); InitializeComponent();
this.WhenActivated(disposables => this.WhenActivated(disposables =>
{ {
this.OneWayBind(ViewModel, vm => vm.Messages, view => view.Messages.Items) this.OneWayBind(ViewModel, vm => vm.Messages, view => view.Messages.Items,
items => items.Reverse().ToArray())
.DisposeWith(disposables); .DisposeWith(disposables);
this.BindCommand(ViewModel, vm => vm.CopyLogFile, view => view.CopyLog) this.BindCommand(ViewModel, vm => vm.CopyLogFile, view => view.CopyLog)
.DisposeWith(disposables); .DisposeWith(disposables);
}); });
} }
private void ScrollViewer_OnScrollChanged(object? sender, ScrollChangedEventArgs e)
{
ScrollViewer.ScrollToEnd();
}
} }

View File

@ -6,6 +6,8 @@ using System.Reactive.Subjects;
using System.Threading.Tasks; using System.Threading.Tasks;
using Microsoft.CodeAnalysis.CSharp.Syntax; using Microsoft.CodeAnalysis.CSharp.Syntax;
using ReactiveUI; using ReactiveUI;
using Wabbajack.App.Controls;
using Wabbajack.Paths;
namespace Wabbajack.App.Extensions; namespace Wabbajack.App.Extensions;
@ -40,4 +42,22 @@ public static class IObservableExtensions
return Disposable.Create(() => d.Dispose()); return Disposable.Create(() => d.Dispose());
} }
public static IDisposable BindFileSelectionBox<TViewModel>(this FileSelectionBox box, TViewModel viewModel,
Expression<Func<TViewModel, AbsolutePath>> vmProperty)
where TViewModel: class?
{
var disposables = new CompositeDisposable();
box.WhenAnyValue(view => view.SelectedPath)
.BindTo(viewModel, vmProperty)
.DisposeWith(disposables);
viewModel.WhenAnyValue(vmProperty)
.Where(p => p != default)
.Subscribe(box.Load)
.DisposeWith(disposables);
return disposables;
}
} }

View File

@ -9,8 +9,10 @@ using Avalonia.Media;
using Avalonia.Media.Imaging; using Avalonia.Media.Imaging;
using SkiaSharp; using SkiaSharp;
using Wabbajack.Hashing.xxHash64; using Wabbajack.Hashing.xxHash64;
using Wabbajack.Paths;
using Wabbajack.Paths.IO; using Wabbajack.Paths.IO;
using Wabbajack.RateLimiter; using Wabbajack.RateLimiter;
using Wabbajack.VFS;
namespace Wabbajack.App.Models; namespace Wabbajack.App.Models;
@ -19,13 +21,15 @@ public class ImageCache
private readonly Configuration _configuration; private readonly Configuration _configuration;
private readonly HttpClient _client; private readonly HttpClient _client;
private readonly IResource<HttpClient> _limiter; private readonly IResource<HttpClient> _limiter;
private readonly FileHashCache _hashCache;
public ImageCache(Configuration configuration, HttpClient client, IResource<HttpClient> limiter) public ImageCache(Configuration configuration, HttpClient client, IResource<HttpClient> limiter, FileHashCache hashCache)
{ {
_configuration = configuration; _configuration = configuration;
_configuration.ImageCacheLocation.CreateDirectory(); _configuration.ImageCacheLocation.CreateDirectory();
_client = client; _client = client;
_limiter = limiter; _limiter = limiter;
_hashCache = hashCache;
} }
public async Task<IBitmap> From(Uri uri, int width, int height) public async Task<IBitmap> From(Uri uri, int width, int height)
@ -46,4 +50,18 @@ public class ImageCache
return new Bitmap(new MemoryStream(data)); return new Bitmap(new MemoryStream(data));
} }
public async Task<IBitmap> From(AbsolutePath image, int width, int height)
{
var hash = await _hashCache.FileHashCachedAsync(image, CancellationToken.None);
var file = _configuration.ImageCacheLocation.Combine(hash + $"_{width}_{height}");
if (!file.FileExists())
{
var resized = SKBitmap.Decode(image.ToString()).Resize(new SKSizeI(width, height), SKFilterQuality.High);
await file.WriteAllBytesAsync(resized.Encode(SKEncodedImageFormat.Webp, 90).ToArray());
}
var data = await file.ReadAllBytesAsync();
return new Bitmap(new MemoryStream(data));
}
} }

View File

@ -62,7 +62,7 @@ public class CompilationViewModel : ViewModelBase
{ {
try try
{ {
await _compiler.Begin(CancellationToken.None); var result = await Task.Run(async () => await _compiler.Begin(CancellationToken.None));
} }
catch (Exception ex) catch (Exception ex)
{ {

View File

@ -6,9 +6,9 @@
xmlns:i="clr-namespace:Material.Icons.Avalonia;assembly=Material.Icons.Avalonia" xmlns:i="clr-namespace:Material.Icons.Avalonia;assembly=Material.Icons.Avalonia"
xmlns:controls="clr-namespace:Wabbajack.App.Controls" xmlns:controls="clr-namespace:Wabbajack.App.Controls"
x:Class="Wabbajack.App.Screens.CompilerConfigurationView"> x:Class="Wabbajack.App.Screens.CompilerConfigurationView">
<Grid RowDefinitions="40, *, 40"> <Grid RowDefinitions="40, *, 40" Margin="8">
<TextBlock Grid.Row="0" x:Name="StatusText" FontSize="20" FontWeight="Bold">Compiler Configuration</TextBlock> <TextBlock Grid.Row="0" x:Name="StatusText" FontSize="20" FontWeight="Bold">Compiler Configuration</TextBlock>
<Grid Grid.Row="1" ColumnDefinitions="Auto, *" RowDefinitions="Auto, Auto, Auto, Auto, Auto, Auto, Auto" <Grid Grid.Row="1" ColumnDefinitions="Auto, *" RowDefinitions="Auto, Auto, Auto, Auto, Auto, Auto, Auto, Auto"
Margin="4"> Margin="4">
<Label Grid.Column="0" Grid.Row="0" HorizontalAlignment="Right">Title:</Label> <Label Grid.Column="0" Grid.Row="0" HorizontalAlignment="Right">Title:</Label>
<TextBox Grid.Column="1" Grid.Row="0" x:Name="Title" /> <TextBox Grid.Column="1" Grid.Row="0" x:Name="Title" />
@ -30,8 +30,27 @@
<Label Grid.Column="0" Grid.Row="5" HorizontalAlignment="Right">Output Folder:</Label> <Label Grid.Column="0" Grid.Row="5" HorizontalAlignment="Right">Output Folder:</Label>
<controls:FileSelectionBox Grid.Column="1" Grid.Row="5" x:Name="OutputFolder" SelectFolder="True" /> <controls:FileSelectionBox Grid.Column="1" Grid.Row="5" x:Name="OutputFolder" SelectFolder="True" />
<Label Grid.Column="0" Grid.Row="6" HorizontalAlignment="Right" VerticalAlignment="Top">Always Enabled:</Label> <Label Grid.Column="0" Grid.Row="6" HorizontalAlignment="Right" VerticalAlignment="Top">Other Profiles:</Label>
<StackPanel Grid.Column="1" Grid.Row="6" Orientation="Vertical"> <StackPanel Grid.Column="1" Grid.Row="6" Orientation="Vertical">
<Button x:Name="AddOtherProfile">
<i:MaterialIcon Kind="AddCircle" />
</Button>
<ItemsControl x:Name="OtherProfilesList">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel Orientation="Vertical" />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<controls:RemovableListItem />
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</StackPanel>
<Label Grid.Column="0" Grid.Row="7" HorizontalAlignment="Right" VerticalAlignment="Top">Always Enabled:</Label>
<StackPanel Grid.Column="1" Grid.Row="7" Orientation="Vertical">
<Button x:Name="AddAlwaysEnabled"> <Button x:Name="AddAlwaysEnabled">
<i:MaterialIcon Kind="AddCircle" /> <i:MaterialIcon Kind="AddCircle" />
</Button> </Button>
@ -50,6 +69,8 @@
</StackPanel> </StackPanel>
</Grid> </Grid>
<Grid ColumnDefinitions="*, Auto, Auto" Grid.Row="2"> <Grid ColumnDefinitions="*, Auto, Auto" Grid.Row="2">
<Button Grid.Column="1" x:Name="InferSettings" Click="InferSettings_OnClick"> <Button Grid.Column="1" x:Name="InferSettings" Click="InferSettings_OnClick">

View File

@ -7,6 +7,7 @@ using Avalonia.Interactivity;
using Avalonia.Threading; using Avalonia.Threading;
using ReactiveUI; using ReactiveUI;
using Wabbajack.App.Controls; using Wabbajack.App.Controls;
using Wabbajack.App.Extensions;
using Wabbajack.App.Views; using Wabbajack.App.Views;
using Wabbajack.Common; using Wabbajack.Common;
using Wabbajack.Paths; using Wabbajack.Paths;
@ -19,25 +20,23 @@ public partial class CompilerConfigurationView : ScreenBase<CompilerConfiguratio
{ {
InitializeComponent(); InitializeComponent();
AddAlwaysEnabled.Command = ReactiveCommand.Create(() => AddAlwaysEnabled_Command().FireAndForget()); AddAlwaysEnabled.Command = ReactiveCommand.Create(() => AddAlwaysEnabled_Command().FireAndForget());
AddOtherProfile.Command = ReactiveCommand.Create(() => AddOtherProfile_Command().FireAndForget());
this.WhenActivated(disposables => this.WhenActivated(disposables =>
{ {
this.Bind(ViewModel, vm => vm.SettingsFile, view => view.SettingsFile.SelectedPath)
.DisposeWith(disposables);
this.Bind(ViewModel, vm => vm.Title, view => view.Title.Text) this.Bind(ViewModel, vm => vm.Title, view => view.Title.Text)
.DisposeWith(disposables); .DisposeWith(disposables);
this.Bind(ViewModel, vm => vm.SettingsFile, view => view.SettingsFile.SelectedPath) SettingsFile.BindFileSelectionBox(ViewModel, vm => vm.SettingsFile)
.DisposeWith(disposables); .DisposeWith(disposables);
this.Bind(ViewModel, vm => vm.Source, view => view.Source.SelectedPath) Source.BindFileSelectionBox(ViewModel, vm => vm.Source)
.DisposeWith(disposables); .DisposeWith(disposables);
this.Bind(ViewModel, vm => vm.Downloads, view => view.DownloadsFolder.SelectedPath) DownloadsFolder.BindFileSelectionBox(ViewModel, vm => vm.Downloads)
.DisposeWith(disposables); .DisposeWith(disposables);
this.Bind(ViewModel, vm => vm.OutputFolder, view => view.OutputFolder.SelectedPath) OutputFolder.BindFileSelectionBox(ViewModel, vm => vm.OutputFolder)
.DisposeWith(disposables); .DisposeWith(disposables);
this.OneWayBind(ViewModel, vm => vm.AllGames, view => view.BaseGame.Items) this.OneWayBind(ViewModel, vm => vm.AllGames, view => view.BaseGame.Items)
@ -56,9 +55,28 @@ public partial class CompilerConfigurationView : ScreenBase<CompilerConfiguratio
DeleteCommand = ReactiveCommand.Create(() => { ViewModel?.RemoveAlwaysExcluded(itm); }) DeleteCommand = ReactiveCommand.Create(() => { ViewModel?.RemoveAlwaysExcluded(itm); })
})) }))
.DisposeWith(disposables); .DisposeWith(disposables);
this.OneWayBind(ViewModel, vm => vm.OtherProfiles, view => view.OtherProfilesList.Items,
d => d!.Select(itm => new RemovableItemViewModel
{
Text = itm.ToString(),
DeleteCommand = ReactiveCommand.Create(() => { ViewModel?.RemoveOtherProfile(itm); })
}))
.DisposeWith(disposables);
}); });
} }
private async Task AddOtherProfile_Command()
{
var dialog = new OpenFolderDialog
{
Title = "Select a profile folder"
};
var result = await dialog.ShowAsync(App.MainWindow);
if (!string.IsNullOrWhiteSpace(result))
ViewModel!.AddOtherProfile(result.ToAbsolutePath());
}
private async Task AddAlwaysEnabled_Command() private async Task AddAlwaysEnabled_Command()
{ {
var dialog = new OpenFolderDialog var dialog = new OpenFolderDialog

View File

@ -71,6 +71,9 @@ public class CompilerConfigurationViewModel : ViewModelBase
[Reactive] public IEnumerable<RelativePath> AlwaysEnabled { get; set; } = Array.Empty<RelativePath>(); [Reactive] public IEnumerable<RelativePath> AlwaysEnabled { get; set; } = Array.Empty<RelativePath>();
[Reactive]
public string[] OtherProfiles { get; set; } = Array.Empty<string>();
public AbsolutePath SettingsOutputLocation => Source.Combine(Title) public AbsolutePath SettingsOutputLocation => Source.Combine(Title)
.WithExtension(IsMO2Compilation ? Ext.MO2CompilerSettings : Ext.CompilerSettings); .WithExtension(IsMO2Compilation ? Ext.MO2CompilerSettings : Ext.CompilerSettings);
@ -102,16 +105,31 @@ public class CompilerConfigurationViewModel : ViewModelBase
{ {
return new MO2CompilerSettings return new MO2CompilerSettings
{ {
ModListName = Title,
Downloads = Downloads, Downloads = Downloads,
Source = Source, Source = Source,
Game = BaseGame.Game, Game = BaseGame.Game,
Profile = SelectedProfile, Profile = SelectedProfile,
UseGamePaths = true, UseGamePaths = true,
OutputFile = OutputFolder.Combine(SelectedProfile).WithExtension(Ext.Wabbajack), OutputFile = OutputFolder.Combine(SelectedProfile).WithExtension(Ext.Wabbajack),
AlwaysEnabled = AlwaysEnabled.ToArray() AlwaysEnabled = AlwaysEnabled.ToArray(),
OtherProfiles = OtherProfiles.ToArray()
}; };
} }
public bool AddOtherProfile(AbsolutePath path)
{
if (!path.InFolder(Source.Combine(Consts.MO2Profiles))) return false;
var relative = path.RelativeTo(Source.Combine(Consts.MO2Profiles)).ToString();
OtherProfiles = OtherProfiles.Append(relative).Distinct().ToArray();
return true;
}
public void RemoveOtherProfile(string profile)
{
OtherProfiles = OtherProfiles.Where(p => p != profile).ToArray();
}
public bool AddAlwaysExcluded(AbsolutePath path) public bool AddAlwaysExcluded(AbsolutePath path)
{ {
if (!path.InFolder(Source)) return false; if (!path.InFolder(Source)) return false;
@ -149,6 +167,8 @@ public class CompilerConfigurationViewModel : ViewModelBase
IsMO2Compilation = true; IsMO2Compilation = true;
AlwaysEnabled = Array.Empty<RelativePath>();
// Find Always Enabled mods // Find Always Enabled mods
foreach (var modFolder in mo2Folder.Combine("mods").EnumerateDirectories()) foreach (var modFolder in mo2Folder.Combine("mods").EnumerateDirectories())
{ {
@ -162,6 +182,12 @@ public class CompilerConfigurationViewModel : ViewModelBase
AlwaysEnabled = AlwaysEnabled.Append(modFolder.RelativeTo(mo2Folder)).ToArray(); AlwaysEnabled = AlwaysEnabled.Append(modFolder.RelativeTo(mo2Folder)).ToArray();
} }
var otherProfilesFile = settingsFile.Parent.Combine("otherprofiles.txt");
if (otherProfilesFile.FileExists())
{
OtherProfiles = await otherProfilesFile.ReadAllLinesAsync().ToArray();
}
if (mo2Folder.Depth > 1) if (mo2Folder.Depth > 1)
OutputFolder = mo2Folder.Parent; OutputFolder = mo2Folder.Parent;
@ -171,6 +197,8 @@ public class CompilerConfigurationViewModel : ViewModelBase
} }
} }
private async Task SaveSettingsFile() private async Task SaveSettingsFile()
{ {
await using var st = SettingsOutputLocation.Open(FileMode.Create, FileAccess.Write, FileShare.None); await using var st = SettingsOutputLocation.Open(FileMode.Create, FileAccess.Write, FileShare.None);
@ -187,6 +215,7 @@ public class CompilerConfigurationViewModel : ViewModelBase
{ {
var mo2 = await LoadSettingsFile<MO2CompilerSettings>(path); var mo2 = await LoadSettingsFile<MO2CompilerSettings>(path);
AlwaysEnabled = mo2.AlwaysEnabled; AlwaysEnabled = mo2.AlwaysEnabled;
OtherProfiles = mo2.OtherProfiles;
SelectedProfile = mo2.Profile; SelectedProfile = mo2.Profile;
s = mo2; s = mo2;
} }
@ -195,6 +224,7 @@ public class CompilerConfigurationViewModel : ViewModelBase
throw new NotImplementedException(); throw new NotImplementedException();
} }
Title = s.ModListName;
Source = s.Source; Source = s.Source;
Downloads = s.Downloads; Downloads = s.Downloads;
OutputFolder = s.OutputFile.Depth > 1 ? s.OutputFile.Parent : s.OutputFile; OutputFolder = s.OutputFile.Depth > 1 ? s.OutputFile.Parent : s.OutputFile;

View File

@ -6,17 +6,15 @@
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450" mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
x:Class="Wabbajack.App.Screens.PlaySelectView"> x:Class="Wabbajack.App.Screens.PlaySelectView">
<Grid RowDefinitions="*"> <Grid RowDefinitions="*">
<ItemsControl x:Name="Lists"> <ItemsRepeater x:Name="Lists">
<ItemsControl.ItemsPanel> <ItemsRepeater.Layout>
<ItemsPanelTemplate> <StackLayout></StackLayout>
<StackPanel /> </ItemsRepeater.Layout>
</ItemsPanelTemplate> <ItemsRepeater.ItemTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate> <DataTemplate>
<controls:InstalledListView /> <controls:InstalledListView />
</DataTemplate> </DataTemplate>
</ItemsControl.ItemTemplate> </ItemsRepeater.ItemTemplate>
</ItemsControl> </ItemsRepeater>
</Grid> </Grid>
</UserControl> </UserControl>

View File

@ -14,9 +14,11 @@ namespace Wabbajack.App.Screens;
public class PlaySelectViewModel : ViewModelBase, IActivatableViewModel public class PlaySelectViewModel : ViewModelBase, IActivatableViewModel
{ {
private readonly InstallationStateManager _manager; private readonly InstallationStateManager _manager;
private readonly ImageCache _imageCache;
public PlaySelectViewModel(InstallationStateManager manager) public PlaySelectViewModel(InstallationStateManager manager, ImageCache imageCache)
{ {
_imageCache = imageCache;
_manager = manager; _manager = manager;
Activator = new ViewModelActivator(); Activator = new ViewModelActivator();
@ -32,6 +34,6 @@ public class PlaySelectViewModel : ViewModelBase, IActivatableViewModel
public async Task LoadAndSetItems() public async Task LoadAndSetItems()
{ {
var items = await _manager.GetAll(); var items = await _manager.GetAll();
Items = items.Settings.Select(a => new InstalledListViewModel(a)).ToArray(); Items = items.Settings.Select(a => new InstalledListViewModel(a, _imageCache)).ToArray();
} }
} }

View File

@ -7,4 +7,5 @@ public class MO2CompilerSettings : CompilerSettings
{ {
public string Profile { get; set; } = ""; public string Profile { get; set; } = "";
public RelativePath[] AlwaysEnabled { get; set; } = Array.Empty<RelativePath>(); public RelativePath[] AlwaysEnabled { get; set; } = Array.Empty<RelativePath>();
public string[] OtherProfiles { get; set; }
} }

View File

@ -20,4 +20,5 @@ public class InstallationConfigurationSetting
public ModlistMetadata? Metadata { get; set; } public ModlistMetadata? Metadata { get; set; }
public AbsolutePath Image { get; set; } public AbsolutePath Image { get; set; }
} }