Skip to content

Commit 67e3a9c

Browse files
committed
Added faster startup and install confirmation
1 parent 334f324 commit 67e3a9c

11 files changed

Lines changed: 101 additions & 39 deletions

Directory.Build.props

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
<Project>
22
<PropertyGroup>
33
<Nullable>enable</Nullable>
4-
<AvaloniaVersion>11.1.4</AvaloniaVersion>
4+
<AvaloniaVersion>11.2.1</AvaloniaVersion>
55
</PropertyGroup>
66
</Project>

MelonLoader.Installer/MLManager.cs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,6 @@ internal static class MLManager
1313
private static MLVersion? localBuild;
1414

1515
public static List<MLVersion> Versions { get; private set; } = [];
16-
public static bool Initialized { get; private set; }
1716

1817
static MLManager()
1918
{

MelonLoader.Installer/MelonLoader.Installer.csproj

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
<Project Sdk="Microsoft.NET.Sdk">
22
<PropertyGroup>
33
<OutputType>WinExe</OutputType>
4-
<TargetFramework>net8.0-windows</TargetFramework>
4+
<TargetFramework>net9.0-windows</TargetFramework>
55
<RuntimeIdentifier>win-x64</RuntimeIdentifier>
66
<Nullable>enable</Nullable>
77
<ImplicitUsings>enable</ImplicitUsings>
@@ -33,12 +33,12 @@
3333
<!--Condition
3434
below is needed to remove Avalonia.Diagnostics package from build output in Release
3535
configuration.-->
36-
<PackageReference Condition="'$(Configuration)' == 'Debug'" Include="Avalonia.Diagnostics" Version="11.2.0" />
37-
<PackageReference Include="Avalonia" Version="11.2.0" />
38-
<PackageReference Include="Avalonia.Themes.Fluent" Version="11.2.0" />
39-
<PackageReference Include="Avalonia.Fonts.Inter" Version="11.2.0" />
36+
<PackageReference Condition="'$(Configuration)' == 'Debug'" Include="Avalonia.Diagnostics" Version="$(AvaloniaVersion)" />
37+
<PackageReference Include="Avalonia" Version="$(AvaloniaVersion)" />
38+
<PackageReference Include="Avalonia.Themes.Fluent" Version="$(AvaloniaVersion)" />
39+
<PackageReference Include="Avalonia.Fonts.Inter" Version="$(AvaloniaVersion)" />
4040
<PackageReference Include="CommunityToolkit.Mvvm" Version="8.3.2" />
41-
<PackageReference Include="Avalonia.Desktop" Version="11.2.0" />
41+
<PackageReference Include="Avalonia.Desktop" Version="$(AvaloniaVersion)" />
4242

4343
<PackageReference Include="Gameloop.Vdf" Version="0.6.2" />
4444
<PackageReference Include="Microsoft.CSharp" Version="4.7.0" />

MelonLoader.Installer/Program.cs

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -43,9 +43,6 @@ private static void Main(string[] args)
4343
if (!CheckProcessLock())
4444
return;
4545

46-
if (!Updater.UpdateIfPossible())
47-
MLManager.Init();
48-
4946
BuildAvaloniaApp().StartWithClassicDesktopLifetime(args);
5047

5148
Exiting?.Invoke();
@@ -95,11 +92,13 @@ private static bool CheckProcessLock()
9592

9693
internal static void GrabAttention()
9794
=> GrabAttention(Process.GetCurrentProcess());
95+
9896
private static void GrabAttention(Process process)
9997
{
100-
nint processHandle = process.MainWindowHandle;
98+
var processHandle = process.MainWindowHandle;
10199
if (WindowsUtils.IsIconic(processHandle))
102100
WindowsUtils.ShowWindow(processHandle, 9);
101+
103102
WindowsUtils.SetForegroundWindow(processHandle);
104103
WindowsUtils.BringWindowToTop(processHandle);
105104
}

MelonLoader.Installer/ViewModels/DetailsViewModel.cs

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@
33
public class DetailsViewModel(GameModel game) : ViewModelBase
44
{
55
private bool _installing;
6+
private bool _confirmation;
7+
private bool _offline;
68

79
public GameModel Game => game;
810

@@ -13,6 +15,33 @@ public bool Installing
1315
{
1416
_installing = value;
1517
OnPropertyChanged(nameof(Installing));
18+
OnPropertyChanged(nameof(CanInstall));
19+
OnPropertyChanged(nameof(EnableSettings));
1620
}
1721
}
22+
23+
public bool Confirmation
24+
{
25+
get => _confirmation;
26+
set
27+
{
28+
_confirmation = value;
29+
OnPropertyChanged(nameof(Confirmation));
30+
OnPropertyChanged(nameof(CanInstall));
31+
}
32+
}
33+
34+
public bool Offline
35+
{
36+
get => _offline;
37+
set
38+
{
39+
_offline = value;
40+
OnPropertyChanged(nameof(Confirmation));
41+
OnPropertyChanged(nameof(EnableSettings));
42+
}
43+
}
44+
45+
public bool CanInstall => !Installing && !Confirmation;
46+
public bool EnableSettings => !Offline && !Installing;
1847
}

MelonLoader.Installer/ViewModels/MainViewModel.cs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,18 @@ namespace MelonLoader.Installer.ViewModels;
44

55
public partial class MainViewModel : ViewModelBase
66
{
7+
private static bool _ready;
8+
9+
public bool Ready
10+
{
11+
get => _ready;
12+
set
13+
{
14+
_ready = value;
15+
OnPropertyChanged(nameof(Ready));
16+
}
17+
}
18+
719
public ObservableCollection<GameModel> Games => GameManager.Games;
820

921
public string Version => 'v' + Program.Version.ToString(3);

MelonLoader.Installer/Views/DetailsView.axaml

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -26,14 +26,14 @@
2626
<TextBlock Grid.Row="7" HorizontalAlignment="Center" FontSize="18" Foreground="#7FFF"
2727
Text="{Binding Game.MLStatusText}" />
2828
<TextBlock Grid.Row="9" HorizontalAlignment="Center" Foreground="#BFFF">Select a version</TextBlock>
29-
<ComboBox SelectionChanged="VersionSelectHandler"
29+
<ComboBox SelectionChanged="VersionSelectHandler" IsEnabled="{Binding EnableSettings}"
3030
Name="VersionCombobox" Grid.Row="10" Margin="5" HorizontalAlignment="Center"
3131
SelectedIndex="0" MaxDropDownHeight="150" />
32-
<TextBlock Grid.Row="11" Tapped="SelectZipHandler" HorizontalAlignment="Center"
32+
<TextBlock Grid.Row="11" Tapped="SelectZipHandler" HorizontalAlignment="Center" IsEnabled="{Binding EnableSettings}"
3333
Foreground="Gray" TextDecorations="Underline" FontSize="13" Cursor="Hand">Or select a
3434
zipped version</TextBlock>
3535
<StackPanel Grid.Row="12">
36-
<CheckBox Name="NightlyCheck"
36+
<CheckBox Name="NightlyCheck" IsEnabled="{Binding EnableSettings}"
3737
ToolTip.Tip="Enables bleeding-edge builds. ONLY ENABLE IF YOU KNOW WHAT YOU'RE DOING!"
3838
Click="NightlyToggleHandler" HorizontalAlignment="Center">Enable Nightly builds</CheckBox>
3939
<CheckBox IsEnabled="{Binding !Installing}" Name="KeepFilesCheck"
@@ -42,8 +42,8 @@
4242
IsVisible="{Binding Game.MLInstalled}" IsChecked="True">Keep mods and settings</CheckBox>
4343
</StackPanel>
4444
<Grid Grid.Row="13" Margin="10" Width="300" HorizontalAlignment="Center">
45-
<Grid IsVisible="{Binding !Installing}" ColumnDefinitions="*, auto">
46-
<Button Click="InstallHandler" Name="InstallButton" Grid.Column="0"
45+
<Grid IsVisible="{Binding CanInstall}" ColumnDefinitions="*, auto">
46+
<Button Click="InstallHandler" IsEnabled="{Binding !Offline}" Name="InstallButton" Grid.Column="0"
4747
HorizontalAlignment="Stretch" Background="#383" Height="40"
4848
HorizontalContentAlignment="Center" VerticalContentAlignment="Center"
4949
FontSize="18">Install</Button>
@@ -52,7 +52,7 @@
5252
Background="#833" Height="40" HorizontalContentAlignment="Center"
5353
VerticalContentAlignment="Center" FontSize="18">Uninstall</Button>
5454
</Grid>
55-
<Grid IsVisible="{Binding Installing}">
55+
<Grid IsVisible="{Binding !CanInstall}">
5656
<ProgressBar Name="Progress" Height="40" Background="#4383" Foreground="#383" />
5757
<TextBlock Name="InstallStatus" HorizontalAlignment="Center"
5858
VerticalAlignment="Center" Opacity="0.7" FontSize="14" />

MelonLoader.Installer/Views/DetailsView.axaml.cs

Lines changed: 10 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -48,9 +48,7 @@ protected override void OnDataContextChanged(EventArgs e)
4848

4949
if (!MLManager.Init())
5050
{
51-
InstallButton.IsEnabled = false;
52-
NightlyCheck.IsEnabled = false;
53-
VersionCombobox.IsEnabled = false;
51+
Model.Offline = true;
5452
ErrorBox.Open("Failed to fetch MelonLoader releases. Ensure you're online.");
5553
}
5654
}
@@ -91,6 +89,8 @@ public void UpdateVersionInfo()
9189
if (Model == null || VersionCombobox.SelectedItem == null)
9290
return;
9391

92+
Model.Confirmation = false;
93+
9494
MelonIcon.Opacity = Model.Game.MLInstalled ? 1 : 0.3;
9595

9696
if (Model.Game.MLVersion == null)
@@ -99,7 +99,7 @@ public void UpdateVersionInfo()
9999
return;
100100
}
101101

102-
var comp = ((MLVersion)VersionCombobox.SelectedItem).Version.ComparePrecedenceTo(Model.Game.MLVersion);
102+
var comp = ((MLVersion)VersionCombobox.SelectedItem).Version.CompareSortOrderTo(Model.Game.MLVersion);
103103

104104
InstallButton.Content = comp switch
105105
{
@@ -118,8 +118,6 @@ private void InstallHandler(object sender, RoutedEventArgs args)
118118
}
119119

120120
Model.Installing = true;
121-
NightlyCheck.IsEnabled = false;
122-
VersionCombobox.IsEnabled = false;
123121

124122
_ = MLManager.InstallAsync(Path.GetDirectoryName(Model.Game.Path)!, Model.Game.MLInstalled && !KeepFilesCheck.IsChecked!.Value,
125123
(MLVersion)VersionCombobox.SelectedItem!, Model.Game.Is32Bit,
@@ -141,16 +139,18 @@ private void OnInstallFinished(string? errorMessage)
141139
if (Model == null)
142140
return;
143141

144-
Model.Installing = false;
145-
NightlyCheck.IsEnabled = true;
146-
VersionCombobox.IsEnabled = true;
147-
148142
Model.Game.ValidateGame();
149143

144+
Model.Installing = false;
145+
150146
if (errorMessage != null)
151147
{
152148
ErrorBox.Open(errorMessage);
149+
return;
153150
}
151+
152+
InstallStatus.Text = "Done!";
153+
Model.Confirmation = true;
154154
}
155155

156156
private void OpenDirHandler(object sender, RoutedEventArgs args)
@@ -205,8 +205,6 @@ private async void SelectZipHandler(object sender, TappedEventArgs args)
205205
var path = files[0].Path.LocalPath;
206206

207207
Model.Installing = true;
208-
NightlyCheck.IsEnabled = false;
209-
VersionCombobox.IsEnabled = false;
210208

211209
_ = Task.Run(() => MLManager.SetLocalZip(path,
212210
(progress, newStatus) => Dispatcher.UIThread.Post(() => OnInstallProgress(progress, newStatus)),

MelonLoader.Installer/Views/MainView.axaml

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -28,23 +28,26 @@ If you can't find your game on the list, add it manually.</TextBlock>
2828
<Border Grid.Row="2" Background="#3223" CornerRadius="8" Margin="0 10" ClipToBounds="True">
2929
<Grid>
3030
<ScrollViewer>
31-
<ItemsControl ItemsSource="{Binding Games}" Margin="10">
31+
<ItemsControl IsVisible="{Binding Ready}" ItemsSource="{Binding Games}" Margin="10">
3232
<ItemsControl.ItemTemplate>
3333
<DataTemplate>
3434
<views:GameControl DataContext="{Binding}" />
3535
</DataTemplate>
3636
</ItemsControl.ItemTemplate>
3737
</ItemsControl>
3838
</ScrollViewer>
39-
<TextBlock Name="NoGamesText" Foreground="#3FFF" HorizontalAlignment="Center"
39+
<TextBlock Name="NoGamesText" IsVisible="False" Foreground="#3FFF" HorizontalAlignment="Center"
4040
VerticalAlignment="Center" TextAlignment="Center" xml:space="preserve">
4141
No Unity games have been found on your device.
4242
Please add one manually using the button below.
4343
</TextBlock>
44+
<TextBlock Name="LoadingText" IsVisible="{Binding !Ready}" Foreground="#9FFF" FontSize="20" HorizontalAlignment="Center"
45+
VerticalAlignment="Center" TextAlignment="Center">
46+
Loading...
47+
</TextBlock>
4448
</Grid>
4549
</Border>
46-
<Button Grid.Row="3" HorizontalAlignment="Right" Click="AddGameManuallyHandler">Add Game
47-
Manually</Button>
50+
<Button Grid.Row="3" IsEnabled="{Binding Ready}" HorizontalAlignment="Right" Click="AddGameManuallyHandler">Add Game Manually</Button>
4851
<StackPanel Height="38" Grid.Row="3" Spacing="1" Orientation="Horizontal">
4952
<Button Click="MelonWikiLink" ToolTip.Tip="MelonWiki"
5053
ToolTip.Placement="RightEdgeAlignedBottom" Padding="3" CornerRadius="1000"

MelonLoader.Installer/Views/MainView.axaml.cs

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,41 @@
11
using Avalonia.Controls;
22
using Avalonia.Interactivity;
3+
using Avalonia.Threading;
4+
using MelonLoader.Installer.ViewModels;
35
using System.Collections.Specialized;
46

57
namespace MelonLoader.Installer.Views;
68

79
public partial class MainView : UserControl
810
{
11+
public MainViewModel? Model => (MainViewModel?)DataContext;
12+
913
public MainView()
1014
{
1115
InitializeComponent();
16+
}
17+
18+
protected override void OnDataContextChanged(EventArgs e)
19+
{
20+
base.OnDataContextChanged(e);
21+
22+
if (Model == null)
23+
return;
24+
25+
Task.Run(InitServicesAsync);
26+
}
27+
28+
private void InitServicesAsync()
29+
{
30+
MLManager.Init();
31+
GameManager.Init();
32+
33+
Dispatcher.UIThread.Post(Init);
34+
}
35+
36+
private void Init()
37+
{
38+
Model!.Ready = true;
1239

1340
OnGameListUpdate(null, null);
1441
GameManager.Games.CollectionChanged += OnGameListUpdate;

0 commit comments

Comments
 (0)