Skip to content

Commit ed6c46a

Browse files
Update msu type directory settings
1 parent 4d6d5ab commit ed6c46a

20 files changed

+316
-184
lines changed

MSURandomizer/Services/AppInitializationService.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ public void Initialize(string[] args)
3131
msuRandomizerInitializationService.Initialize(new MsuRandomizerInitializationRequest()
3232
{
3333
InitializeAppSettings = true,
34-
InitializeMsuTypes = false,
34+
InitializeMsuTypes = true,
3535
InitializeCache = false,
3636
InitializeUserOptions = true,
3737
LookupMsus = false,
@@ -78,7 +78,7 @@ public void FinishInitialization()
7878
InitializeAppSettings = false,
7979
InitializeMsuTypes = true,
8080
InitializeCache = true,
81-
InitializeUserOptions = true,
81+
InitializeUserOptions = false,
8282
LookupMsus = true
8383
});
8484
msuGameService.InstallLuaScripts();

MSURandomizer/Services/MsuListService.cs

Lines changed: 1 addition & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -72,11 +72,6 @@ public void FilterMSUs(MsuType msuType, MsuFilter msuFilter)
7272
{
7373
Model.MsuTypeName = msuType.DisplayName;
7474
Model.MsuType = msuType;
75-
var msuTypePath = Model.HardwareMode ? "" :
76-
userOptions.MsuUserOptions.MsuTypePaths.TryGetValue(msuType, out var path) ? path :
77-
userOptions.MsuUserOptions.DefaultMsuPath;
78-
var rootPath = Model.HardwareMode ? "" : GetMsuTypeBasePath(msuType);
79-
var useAbsolutePath = string.IsNullOrWhiteSpace(rootPath);
8075

8176
// Hardware MSUs are more limited in compatibility
8277
List<string>? compatibleMsuNames = null;
@@ -94,15 +89,10 @@ public void FilterMSUs(MsuType msuType, MsuFilter msuFilter)
9489
}
9590

9691
var filteredMsus = Model.MsuViewModels
97-
.Where(x => x.Msu.MatchesFilter(msuFilter, msuType, msuTypePath, compatibleMsuNames) &&
92+
.Where(x => x.Msu.MatchesFilter(msuFilter, msuType, compatibleMsuNames) &&
9893
(x.Msu.NumUniqueTracks > x.Msu.MsuType?.RequiredTrackNumbers.Count / 5 || x.Msu.NumUniqueTracks > 10))
9994
.OrderBy(x => x.MsuName)
10095
.ToList();
101-
foreach (var filteredMsu in filteredMsus)
102-
{
103-
filteredMsu.DisplayPath = useAbsolutePath ? filteredMsu.MsuPath : Path.GetRelativePath(rootPath!, filteredMsu.MsuPath);
104-
}
105-
10696
Model.FilteredMsus = filteredMsus;
10797
Model.SelectedMsus = Model.FilteredMsus
10898
.Where(x => Model.SelectedMsus.Select(vm => vm.MsuPath).Contains(x.MsuPath)).ToList();
@@ -189,19 +179,4 @@ public void PopulateMsuViewModels(List<Msu>? msus)
189179
OnDisplayUnknownMsuWindowRequest?.Invoke(this, EventArgs.Empty);
190180
}
191181
}
192-
193-
private string? GetMsuTypeBasePath(MsuType? msuType)
194-
{
195-
if (msuType == null)
196-
{
197-
return userOptions.MsuUserOptions.DefaultMsuPath;
198-
}
199-
200-
if (userOptions.MsuUserOptions.MsuTypeNamePaths.TryGetValue(msuType.DisplayName, out string? path))
201-
{
202-
return path;
203-
}
204-
205-
return userOptions.MsuUserOptions.DefaultMsuPath;
206-
}
207182
}
Lines changed: 37 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
using System;
22
using System.Collections.Generic;
3-
using System.IO;
3+
using System.Collections.ObjectModel;
44
using System.Linq;
55
using AutoMapper;
66
using AvaloniaControls.Controls;
@@ -16,23 +16,23 @@ public class SettingsWindowService(
1616
IMsuUserOptionsService userOptionsService,
1717
IMsuTypeService msuTypeService,
1818
IMsuLookupService msuLookupService,
19+
IMsuCacheService msuCacheService,
1920
IMapper mapper) : ControlService
2021
{
2122
private readonly SettingsWindowViewModel _model = new();
23+
private Dictionary<string, MsuType> _msuTypes = [];
24+
private List<string> _msuTypeList = [];
2225

2326
public SettingsWindowViewModel InitializeModel()
2427
{
2528
mapper.Map(userOptionsService.MsuUserOptions, _model);
2629
_model.DefaultDirectory = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments);
27-
foreach (var msuType in msuTypeService.MsuTypes.OrderBy(x => x.DisplayName))
28-
{
29-
_model.MsuTypeNamePathsList.Add(new MsuTypePath()
30-
{
31-
MsuType = msuType,
32-
Path = _model.MsuTypeNamePaths.GetValueOrDefault(msuType.DisplayName, ""),
33-
DefaultDirectory = _model.DefaultDirectory
34-
});
35-
}
30+
_msuTypes = msuTypeService.MsuTypes.OrderBy(x => x.DisplayName).ToDictionary(x => x.DisplayName, x => x);
31+
_msuTypeList = _msuTypes.Keys.ToList();
32+
_model.MsuDirectoryList = new ObservableCollection<MsuDirectory>(
33+
userOptionsService.MsuUserOptions.MsuDirectories.Select(x =>
34+
new MsuDirectory(x.Key, x.Value, _msuTypeList)));
35+
_model.DisplayNoMsuDirectoriesMessage = _model.MsuDirectoryList.Count == 0;
3636
return _model;
3737
}
3838

@@ -41,41 +41,50 @@ public void SaveModel()
4141
var options = userOptionsService.MsuUserOptions;
4242
var hasPathUpdated = HasPathUpdated(options);
4343
mapper.Map(_model, options);
44-
options.MsuTypePaths = _model.MsuTypeNamePathsList
45-
.Where(x => !string.IsNullOrWhiteSpace(x.Path) && Directory.Exists(x.Path) && x.MsuType != null)
46-
.ToDictionary(x => x.MsuType!, x => x.Path);
47-
options.MsuTypeNamePaths = _model.MsuTypeNamePathsList
48-
.Where(x => !string.IsNullOrWhiteSpace(x.Path) && Directory.Exists(x.Path) && x.MsuType != null)
49-
.ToDictionary(x => x.MsuType!.DisplayName, x => x.Path);
44+
options.MsuDirectories = _model.MsuDirectoryList.ToDictionary(x => x.Path, x => x.MsuTypeName);
5045
userOptionsService.Save();
5146
ScalableWindow.GlobalScaleFactor = options.UiScaling;
5247

5348
if (hasPathUpdated)
5449
{
5550
ITaskService.Run(() =>
5651
{
52+
msuCacheService.Clear(false);
5753
msuLookupService.LookupMsus();
5854
});
5955
}
6056
}
6157

62-
private bool HasPathUpdated(MsuUserOptions options)
58+
public bool AddDirectory(string directory)
6359
{
64-
if (_model.DefaultMsuPath != options.DefaultMsuPath)
60+
if (_model.MsuDirectoryList.Any(x => x.Path == directory))
6561
{
66-
return true;
62+
return false;
6763
}
68-
69-
foreach (var msuPath in _model.MsuTypeNamePathsList.Where(x => x.MsuType != null))
64+
_model.MsuDirectoryList.Add(new MsuDirectory(directory, _msuTypeList.FirstOrDefault() ?? "", _msuTypeList));
65+
_model.DisplayNoMsuDirectoriesMessage = false;
66+
return true;
67+
}
68+
69+
public void RemoveDirectory(string directory)
70+
{
71+
var directoryToRemove = _model.MsuDirectoryList.FirstOrDefault(x => x.Path == directory);
72+
if (directoryToRemove != null)
7073
{
71-
var newPath = msuPath.Path.Trim();
72-
var oldPath = options.MsuTypePaths.GetValueOrDefault(msuPath.MsuType!, "").Trim();
73-
if (newPath != oldPath)
74-
{
75-
return true;
76-
}
74+
_model.MsuDirectoryList.Remove(directoryToRemove);
75+
_model.DisplayNoMsuDirectoriesMessage = _model.MsuDirectoryList.Count == 0;
76+
}
77+
}
78+
79+
private bool HasPathUpdated(MsuUserOptions options)
80+
{
81+
if (_model.MsuDirectoryList.Count != options.MsuDirectories.Count)
82+
{
83+
return true;
7784
}
7885

79-
return false;
86+
var currentDirectories = options.MsuDirectories.Select(x => $"{x.Key}={x.Value}");
87+
var newDirectories = _model.MsuDirectoryList.Select(x => $"{x.Path}={x.MsuTypeName}");
88+
return !currentDirectories.SequenceEqual(newDirectories);
8089
}
8190
}

MSURandomizer/ViewModels/MsuViewModel.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,8 @@ public MsuViewModel(Msu msu)
2222
Msu = msu;
2323
MsuName = msu.DisplayName;
2424
MsuCreator = msu.DisplayCreator;
25-
MsuPath = DisplayPath = msu.Path;
25+
MsuPath = msu.Path;
26+
DisplayPath = msu.RelativePath;
2627
MsuTypeName = msu.MsuType?.DisplayName ?? msu.MsuTypeName;
2728
MsuTrackCount = $"{msu.ValidTracks.Count} Tracks";
2829
IsFavorite = msu.Settings.IsFavorite;

MSURandomizer/ViewModels/SettingsWindowViewModel.cs

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
using System;
22
using System.Collections.Generic;
3+
using System.Collections.ObjectModel;
34
using AvaloniaControls;
45
using AvaloniaControls.Models;
56
using MSURandomizerLibrary;
@@ -36,6 +37,10 @@ public class SettingsWindowViewModel : ViewModelBase
3637

3738
public bool LaunchArgumentsEnabled => !string.IsNullOrEmpty(LaunchApplication);
3839

40+
[Reactive] public bool DisplayNoMsuDirectoriesMessage { get; set; }
41+
42+
public ObservableCollection<MsuDirectory> MsuDirectoryList { get; set; } = [];
43+
3944
[Reactive] public string? LaunchArguments { get; set; }
4045

4146
[Reactive]
@@ -61,6 +66,21 @@ public class MsuTypePath : ViewModelBase
6166
public string MsuTypeName => MsuType?.DisplayName ?? "A Link to the Past";
6267
}
6368

69+
public class MsuDirectory : ViewModelBase
70+
{
71+
public MsuDirectory(string path, string msuTypeName = "", List<string>? msuTypes = null)
72+
{
73+
Path = path;
74+
MsuTypeName = msuTypeName;
75+
MsuTypes = msuTypes ?? [];
76+
}
77+
78+
[Reactive] public string Path { get; set; }
79+
[Reactive] public string MsuTypeName { get; set; }
80+
[Reactive] public List<string> MsuTypes { get; set; }
81+
public string AbbreviatedPath => Path.Length > 40 ? string.Concat("...", Path.AsSpan(Path.Length - 38)) : Path;
82+
}
83+
6484
[MapsTo(typeof(SnesConnectorSettings))]
6585
public class SnesConnectorSettingsViewModel : ViewModelBase
6686
{

MSURandomizer/Views/SettingsWindow.axaml

Lines changed: 26 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
xmlns:controls="clr-namespace:AvaloniaControls.Controls;assembly=AvaloniaControls"
66
xmlns:tools="clr-namespace:AvaloniaControls.Converters;assembly=AvaloniaControls"
77
xmlns:viewModels="clr-namespace:MSURandomizer.ViewModels"
8+
xmlns:avalonia="clr-namespace:Material.Icons.Avalonia;assembly=Material.Icons.Avalonia"
89
mc:Ignorable="d"
910
d:DesignWidth="800" d:DesignHeight="450"
1011
Width="800" Height="500"
@@ -23,6 +24,31 @@
2324
</controls:HeaderFooter>
2425
<ScrollViewer>
2526
<StackPanel Orientation="Vertical" Grid.IsSharedSizeScope="True" Margin="10">
27+
<controls:CardControl HeaderText="MSU Directories" Padding="6" Margin="0 0 0 6">
28+
<StackPanel Orientation="Vertical">
29+
<StackPanel Orientation="Horizontal" HorizontalAlignment="Center" IsVisible="{Binding DisplayNoMsuDirectoriesMessage}">
30+
<avalonia:MaterialIcon Kind="Error" Height="20" Width="20" Margin="0 0 5 0" Foreground="IndianRed"></avalonia:MaterialIcon>
31+
<TextBlock FontSize="16" Margin="0 3 0 5" VerticalAlignment="Bottom">
32+
At least one MSU directory must be added.
33+
</TextBlock>
34+
</StackPanel>
35+
<ItemsControl ItemsSource="{Binding MsuDirectoryList}" >
36+
<ItemsControl.ItemTemplate>
37+
<DataTemplate>
38+
<controls:LabeledControl Text="{Binding AbbreviatedPath}" Margin="3" ToolTip.Tip="{Binding Path}">
39+
<Grid ColumnDefinitions="*, Auto">
40+
<ComboBox Grid.Column="0" ItemsSource="{Binding MsuTypes}" SelectedItem="{Binding MsuTypeName}"></ComboBox>
41+
<Button Grid.Column="1" Margin="3 0 0 0" Tag="{Binding Path}" Click="RemoveDirectoryButton_OnClick">
42+
<avalonia:MaterialIcon Kind="Close" Width="15" Height="15" Background="Transparent"/>
43+
</Button>
44+
</Grid>
45+
</controls:LabeledControl>
46+
</DataTemplate>
47+
</ItemsControl.ItemTemplate>
48+
</ItemsControl>
49+
<Button Click="AddDirectoryButton_OnClick">Add Directory</Button>
50+
</StackPanel>
51+
</controls:CardControl>
2652
<controls:CardControl HeaderText="Basic Settings" Padding="6">
2753
<StackPanel Orientation="Vertical">
2854
<controls:LabeledControl Text="Check for Updates" Hint="Shows a popup when first launching when there is a new update on GitHub." DisplayHint="True" Margin="3">
@@ -34,14 +60,6 @@
3460
></ComboBox>
3561
</controls:LabeledControl>
3662

37-
<controls:LabeledControl Text="Default MSU Directory" Hint="The default directory to look for MSUs if a specific folder isn't set for an MSU type." DisplayHint="True" Margin="3">
38-
<controls:FileControl
39-
FilePath="{Binding DefaultMsuPath, Mode=TwoWay}"
40-
DefaultPath="{Binding DefaultDirectory}"
41-
FileInputType="Folder"
42-
></controls:FileControl>
43-
</controls:LabeledControl>
44-
4563
<controls:LabeledControl Text="Track Display Format" Hint="How currently played tracks will be displayed." DisplayHint="True" Margin="3">
4664
<StackPanel Orientation="Vertical">
4765
<controls:EnumComboBox
@@ -112,21 +130,6 @@
112130
</StackPanel>
113131
</controls:CardControl>
114132

115-
<controls:CardControl HeaderText="Individual Game Directories" Margin="0 6 0 0" Padding="6">
116-
<ItemsControl ItemsSource="{Binding MsuTypeNamePathsList}" >
117-
<ItemsControl.ItemTemplate>
118-
<DataTemplate>
119-
<controls:LabeledControl Text="{Binding MsuTypeName}" Margin="3">
120-
<controls:FileControl
121-
FileInputType="Folder"
122-
DefaultPath="{Binding DefaultDirectory}"
123-
FilePath="{Binding Path, Mode=TwoWay}"
124-
></controls:FileControl>
125-
</controls:LabeledControl>
126-
</DataTemplate>
127-
</ItemsControl.ItemTemplate>
128-
</ItemsControl>
129-
</controls:CardControl>
130133
</StackPanel>
131134
</ScrollViewer>
132135
</DockPanel>

MSURandomizer/Views/SettingsWindow.axaml.cs

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
1+
using System;
2+
using System.IO;
13
using Avalonia.Controls;
24
using Avalonia.Interactivity;
5+
using AvaloniaControls;
36
using AvaloniaControls.Controls;
47
using AvaloniaControls.Extensions;
58
using MSURandomizer.Services;
@@ -26,6 +29,10 @@ public SettingsWindow()
2629
new MsuTypePath(),
2730
new MsuTypePath(),
2831
new MsuTypePath(),
32+
],
33+
MsuDirectoryList =
34+
[
35+
new MsuDirectory("/test/path")
2936
]
3037
};
3138
return;
@@ -45,4 +52,33 @@ private void CancelButton_OnClick(object? sender, RoutedEventArgs e)
4552
{
4653
Close();
4754
}
55+
56+
private async void AddDirectoryButton_OnClick(object? sender, RoutedEventArgs e)
57+
{
58+
if (_service == null)
59+
{
60+
return;
61+
}
62+
63+
var storageItem = await CrossPlatformTools.OpenFileDialogAsync(this, FileInputControlType.Folder, null, null);
64+
var path = storageItem?.Path.LocalPath;
65+
if (string.IsNullOrEmpty(path) || !Directory.Exists(path))
66+
{
67+
return;
68+
}
69+
70+
if (!_service.AddDirectory(path))
71+
{
72+
_ = MessageWindow.ShowErrorDialog("That directory has already been selected");
73+
}
74+
}
75+
76+
private void RemoveDirectoryButton_OnClick(object? sender, RoutedEventArgs e)
77+
{
78+
if (sender is not Button { Tag: string directory } || _service == null)
79+
{
80+
return;
81+
}
82+
_service.RemoveDirectory(directory);
83+
}
4884
}

0 commit comments

Comments
 (0)