From 25a3c270be151ee7b7e30aaf04e502cf0d946fcc Mon Sep 17 00:00:00 2001 From: "waffle.lord" Date: Tue, 28 Dec 2021 19:44:25 -0500 Subject: [PATCH] Replace ViewNavigator with ReactiveUI RouterState, Fix PatchHelper rasing progress changed with no remaining source files, fix view load race conditions --- Patcher/PatchClient/Models/ViewNavigator.cs | 14 ---- Patcher/PatchClient/Program.cs | 10 ++- .../ViewModels/MainWindowViewModel.cs | 16 +++-- .../ViewModels/MessageViewModel.cs | 4 +- .../ViewModels/PatcherViewModel.cs | 57 ++++++++++++---- .../PatchClient/ViewModels/ViewModelBase.cs | 60 +++++++++++++++-- Patcher/PatchClient/Views/MainWindow.axaml | 5 +- Patcher/PatchClient/Views/MainWindow.axaml.cs | 7 +- .../PatchClient/Views/MessageView.axaml.cs | 7 +- .../PatchClient/Views/PatcherView.axaml.cs | 7 +- Patcher/PatchGenerator/Program.cs | 10 ++- .../Properties/launchSettings.json | 4 +- .../ViewModels/MainWindowViewModel.cs | 38 ++++++----- .../ViewModels/OptionsViewModel.cs | 8 +-- .../ViewModels/PatchGenerationViewModel.cs | 12 ++-- .../ViewModels/ViewModelBase.cs | 66 ++++++++++++++++++- Patcher/PatchGenerator/Views/MainWindow.axaml | 5 +- .../PatchGenerator/Views/MainWindow.axaml.cs | 7 +- .../PatchGenerator/Views/OptionsView.axaml.cs | 7 +- .../Views/PatchGenerationView.axaml.cs | 6 +- Patcher/PatcherUtils/PatchHelper.cs | 3 + .../PatcherUtils/Resources/PatchClient.exe | 4 +- 22 files changed, 264 insertions(+), 93 deletions(-) delete mode 100644 Patcher/PatchClient/Models/ViewNavigator.cs diff --git a/Patcher/PatchClient/Models/ViewNavigator.cs b/Patcher/PatchClient/Models/ViewNavigator.cs deleted file mode 100644 index c407718..0000000 --- a/Patcher/PatchClient/Models/ViewNavigator.cs +++ /dev/null @@ -1,14 +0,0 @@ -using ReactiveUI; - -namespace PatchClient.Models -{ - public class ViewNavigator : ReactiveObject - { - private object _SelectedViewModel; - public object SelectedViewModel - { - get => _SelectedViewModel; - set => this.RaiseAndSetIfChanged(ref _SelectedViewModel, value); - } - } -} diff --git a/Patcher/PatchClient/Program.cs b/Patcher/PatchClient/Program.cs index bc1e0c4..a69c6d5 100644 --- a/Patcher/PatchClient/Program.cs +++ b/Patcher/PatchClient/Program.cs @@ -1,6 +1,9 @@ using Avalonia; using Avalonia.ReactiveUI; +using Splat; using System; +using ReactiveUI; +using System.Reflection; namespace PatchClient { @@ -15,9 +18,14 @@ namespace PatchClient // Avalonia configuration, don't remove; also used by visual designer. public static AppBuilder BuildAvaloniaApp() - => AppBuilder.Configure() + { + Locator.CurrentMutable.RegisterViewsForViewModels(Assembly.GetExecutingAssembly()); + + return AppBuilder.Configure() + .UseReactiveUI() .UsePlatformDetect() .LogToTrace() .UseReactiveUI(); + } } } diff --git a/Patcher/PatchClient/ViewModels/MainWindowViewModel.cs b/Patcher/PatchClient/ViewModels/MainWindowViewModel.cs index f56e6b7..439c5ac 100644 --- a/Patcher/PatchClient/ViewModels/MainWindowViewModel.cs +++ b/Patcher/PatchClient/ViewModels/MainWindowViewModel.cs @@ -1,13 +1,15 @@ using Avalonia; -using PatchClient.Models; using ReactiveUI; -using Splat; +using System.Reactive.Disposables; using System.Windows.Input; namespace PatchClient.ViewModels { - public class MainWindowViewModel : ViewModelBase + public class MainWindowViewModel : ReactiveObject, IActivatableViewModel, IScreen { + public ViewModelActivator Activator { get; } = new ViewModelActivator(); + public RoutingState Router { get; } = new RoutingState(); + public ICommand CloseCommand => ReactiveCommand.Create(() => { if (Application.Current.ApplicationLifetime is Avalonia.Controls.ApplicationLifetimes.IClassicDesktopStyleApplicationLifetime desktopApp) @@ -16,12 +18,12 @@ namespace PatchClient.ViewModels } }); - public ViewNavigator navigator { get; set; } = new ViewNavigator(); public MainWindowViewModel() { - navigator.SelectedViewModel = new PatcherViewModel(); - - Locator.CurrentMutable.RegisterConstant(navigator, typeof(ViewNavigator)); + this.WhenActivated((CompositeDisposable disposable) => + { + Router.Navigate.Execute(new PatcherViewModel(this)); + }); } } } diff --git a/Patcher/PatchClient/ViewModels/MessageViewModel.cs b/Patcher/PatchClient/ViewModels/MessageViewModel.cs index 4eecaf2..6b4a8b6 100644 --- a/Patcher/PatchClient/ViewModels/MessageViewModel.cs +++ b/Patcher/PatchClient/ViewModels/MessageViewModel.cs @@ -4,14 +4,14 @@ namespace PatchClient.ViewModels { public class MessageViewModel : ViewModelBase { - private string _InfoText; + private string _InfoText = ""; public string InfoText { get => _InfoText; set => this.RaiseAndSetIfChanged(ref _InfoText, value); } - public MessageViewModel(string Message) + public MessageViewModel(IScreen Host, string Message) : base(Host) { InfoText = Message; } diff --git a/Patcher/PatchClient/ViewModels/PatcherViewModel.cs b/Patcher/PatchClient/ViewModels/PatcherViewModel.cs index 6eaa5da..7e0a26b 100644 --- a/Patcher/PatchClient/ViewModels/PatcherViewModel.cs +++ b/Patcher/PatchClient/ViewModels/PatcherViewModel.cs @@ -1,11 +1,12 @@ using Avalonia; +using Avalonia.Threading; using PatchClient.Models; using PatcherUtils; using ReactiveUI; -using Splat; using System; using System.Collections.ObjectModel; using System.Linq; +using System.Reactive.Disposables; using System.Threading.Tasks; namespace PatchClient.ViewModels @@ -16,7 +17,7 @@ namespace PatchClient.ViewModels public ObservableCollection LineItems { get; set; } = new ObservableCollection(); - private string _ProgressMessage; + private string _ProgressMessage = ""; public string ProgressMessage { get => _ProgressMessage; @@ -30,35 +31,67 @@ namespace PatchClient.ViewModels set => this.RaiseAndSetIfChanged(ref _PatchPercent, value); } - private string _PatchMessage; + private string _PatchMessage = ""; public string PatchMessage { get => _PatchMessage; set => this.RaiseAndSetIfChanged(ref _PatchMessage, value); } - private ViewNavigator navigator => Locator.Current.GetService(); - public PatcherViewModel() + public PatcherViewModel(IScreen Host) : base(Host) { - RunPatcher(); + this.WhenActivated((CompositeDisposable disposables) => + { + //Test(); + RunPatcher(); + }); } + /// + /// A dumb testing method to see if things look right. Obsolete is used more like a warning here. + /// + [Obsolete] + private void Test() + { + Task.Run(async () => + { + LineItem x = new LineItem("test 1", 30); + LineItem xx = new LineItem("test 2", 100); + LineItem xxx = new LineItem("test 3", 70); + + LineItems.Add(new LineItemProgress(x)); + LineItems.Add(new LineItemProgress(xx)); + LineItems.Add(new LineItemProgress(xxx)); + + for (int i = 0; i <= 100; i++) + { + System.Threading.Thread.Sleep(20); + PatchPercent = i; + ProgressMessage = $"Patching @ {i}%"; + + foreach (var item in LineItems) + { + item.UpdateProgress(item.Total - i); + } + } + + await NavigateToWithDelay(new MessageViewModel(HostScreen, "Test Complete"), 400); + }); + } + + private void RunPatcher() { - Task.Run(() => + Task.Run(async() => { - //Slight delay to avoid some weird race condition in avalonia core, seems to be a bug, but also maybe I'm just stupid, idk -waffle - //Error without delay: An item with the same key has already been added. Key: [1, Avalonia.Controls.Generators.ItemContainerInfo] - System.Threading.Thread.Sleep(1000); - PatchHelper patcher = new PatchHelper(Environment.CurrentDirectory, null, LazyOperations.PatchFolder); patcher.ProgressChanged += patcher_ProgressChanged; string message = patcher.ApplyPatches(); - navigator.SelectedViewModel = new MessageViewModel(message).WithDelay(400); + await NavigateToWithDelay(new MessageViewModel(HostScreen, message), 400); }); } diff --git a/Patcher/PatchClient/ViewModels/ViewModelBase.cs b/Patcher/PatchClient/ViewModels/ViewModelBase.cs index ae56d9e..47a29d0 100644 --- a/Patcher/PatchClient/ViewModels/ViewModelBase.cs +++ b/Patcher/PatchClient/ViewModels/ViewModelBase.cs @@ -1,22 +1,72 @@ -using PatchClient.Models; +using Avalonia.Threading; using ReactiveUI; +using System; +using System.Threading.Tasks; namespace PatchClient.ViewModels { - public class ViewModelBase : ReactiveObject + public class ViewModelBase : ReactiveObject, IActivatableViewModel, IRoutableViewModel { + public ViewModelActivator Activator { get; } = new ViewModelActivator(); + + public string? UrlPathSegment => Guid.NewGuid().ToString().Substring(0, 7); + + public IScreen HostScreen { get; } + /// /// Delay the return of the viewmodel /// /// The amount of time in milliseconds to delay /// The viewmodel after the delay time - /// Useful to delay the navigation to another view via the . For instance, to allow an animation to complete. - public ViewModelBase WithDelay(int Milliseconds) + /// Useful to delay the navigation to another view. For instance, to allow an animation to complete. + private async Task WithDelay(int Milliseconds) { - System.Threading.Thread.Sleep(Milliseconds); + await Task.Delay(Milliseconds); return this; } + + /// + /// Navigate to another viewmodel after a delay + /// + /// + /// + /// + public async Task NavigateToWithDelay(ViewModelBase ViewModel, int Milliseconds) + { + await Dispatcher.UIThread.InvokeAsync(async () => + { + HostScreen.Router.Navigate.Execute(await ViewModel.WithDelay(Milliseconds)); + }); + } + + /// + /// Navigate to another viewmodel + /// + /// + public void NavigateTo(ViewModelBase ViewModel) + { + Dispatcher.UIThread.InvokeAsync(() => + { + HostScreen.Router.Navigate.Execute(ViewModel); + }); + } + + /// + /// Navigate to the previous viewmodel + /// + public void NavigateBack() + { + Dispatcher.UIThread.InvokeAsync(() => + { + HostScreen.Router.NavigateBack.Execute(); + }); + } + + public ViewModelBase(IScreen Host) + { + HostScreen = Host; + } } } diff --git a/Patcher/PatchClient/Views/MainWindow.axaml b/Patcher/PatchClient/Views/MainWindow.axaml index 2c3cde2..9b5aa70 100644 --- a/Patcher/PatchClient/Views/MainWindow.axaml +++ b/Patcher/PatchClient/Views/MainWindow.axaml @@ -4,6 +4,7 @@ xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:cc="using:PatchClient.CustomControls" + xmlns:rxui="using:Avalonia.ReactiveUI" mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450" x:Class="PatchClient.Views.MainWindow" Icon="/Assets/avalonia-logo.ico" @@ -29,9 +30,7 @@ - - - + diff --git a/Patcher/PatchClient/Views/MainWindow.axaml.cs b/Patcher/PatchClient/Views/MainWindow.axaml.cs index 78a19d3..1f88916 100644 --- a/Patcher/PatchClient/Views/MainWindow.axaml.cs +++ b/Patcher/PatchClient/Views/MainWindow.axaml.cs @@ -1,10 +1,12 @@ using Avalonia; -using Avalonia.Controls; using Avalonia.Markup.Xaml; +using Avalonia.ReactiveUI; +using PatchClient.ViewModels; +using ReactiveUI; namespace PatchClient.Views { - public partial class MainWindow : Window + public partial class MainWindow : ReactiveWindow { public MainWindow() { @@ -16,6 +18,7 @@ namespace PatchClient.Views private void InitializeComponent() { + this.WhenActivated(disposables => { }); AvaloniaXamlLoader.Load(this); } } diff --git a/Patcher/PatchClient/Views/MessageView.axaml.cs b/Patcher/PatchClient/Views/MessageView.axaml.cs index dab0189..462a9b9 100644 --- a/Patcher/PatchClient/Views/MessageView.axaml.cs +++ b/Patcher/PatchClient/Views/MessageView.axaml.cs @@ -1,9 +1,11 @@ -using Avalonia.Controls; using Avalonia.Markup.Xaml; +using Avalonia.ReactiveUI; +using PatchClient.ViewModels; +using ReactiveUI; namespace PatchClient.Views { - public partial class MessageView : UserControl + public partial class MessageView : ReactiveUserControl { public MessageView() { @@ -12,6 +14,7 @@ namespace PatchClient.Views private void InitializeComponent() { + this.WhenActivated(disposables => { }); AvaloniaXamlLoader.Load(this); } } diff --git a/Patcher/PatchClient/Views/PatcherView.axaml.cs b/Patcher/PatchClient/Views/PatcherView.axaml.cs index d8ad362..4ded343 100644 --- a/Patcher/PatchClient/Views/PatcherView.axaml.cs +++ b/Patcher/PatchClient/Views/PatcherView.axaml.cs @@ -1,9 +1,11 @@ -using Avalonia.Controls; using Avalonia.Markup.Xaml; +using Avalonia.ReactiveUI; +using PatchClient.ViewModels; +using ReactiveUI; namespace PatchClient.Views { - public partial class PatcherView : UserControl + public partial class PatcherView : ReactiveUserControl { public PatcherView() { @@ -12,6 +14,7 @@ namespace PatchClient.Views private void InitializeComponent() { + this.WhenActivated(disposables => { }); AvaloniaXamlLoader.Load(this); } } diff --git a/Patcher/PatchGenerator/Program.cs b/Patcher/PatchGenerator/Program.cs index dd81e50..43549a2 100644 --- a/Patcher/PatchGenerator/Program.cs +++ b/Patcher/PatchGenerator/Program.cs @@ -1,6 +1,9 @@ using Avalonia; using Avalonia.ReactiveUI; +using Splat; using System; +using ReactiveUI; +using System.Reflection; namespace PatchGenerator { @@ -15,9 +18,14 @@ namespace PatchGenerator // Avalonia configuration, don't remove; also used by visual designer. public static AppBuilder BuildAvaloniaApp() - => AppBuilder.Configure() + { + Locator.CurrentMutable.RegisterViewsForViewModels(Assembly.GetExecutingAssembly()); + + return AppBuilder.Configure() + .UseReactiveUI() .UsePlatformDetect() .LogToTrace() .UseReactiveUI(); + } } } diff --git a/Patcher/PatchGenerator/Properties/launchSettings.json b/Patcher/PatchGenerator/Properties/launchSettings.json index 112b9ec..aaa73fe 100644 --- a/Patcher/PatchGenerator/Properties/launchSettings.json +++ b/Patcher/PatchGenerator/Properties/launchSettings.json @@ -1,9 +1,7 @@ { "profiles": { "PatchGenerator": { - "commandName": "Project", - "commandLineArgs": "\"OutputFolderName::Patcher_12.3.4.5_to_6.7.8.9\" \"SourceFolderPath::C:\\Users\\JohnO\\Desktop\\12.12.10.16338\" \"TargetFolderPath::C:\\Users\\JohnO\\Desktop\\12.11.7.15680\" \"AutoZip::True\"", - "workingDirectory": "C:\\Users\\JohnO\\Desktop\\Patcher\\" + "commandName": "Project" } } } \ No newline at end of file diff --git a/Patcher/PatchGenerator/ViewModels/MainWindowViewModel.cs b/Patcher/PatchGenerator/ViewModels/MainWindowViewModel.cs index 6395726..79298c5 100644 --- a/Patcher/PatchGenerator/ViewModels/MainWindowViewModel.cs +++ b/Patcher/PatchGenerator/ViewModels/MainWindowViewModel.cs @@ -1,14 +1,17 @@ using Avalonia; using PatchGenerator.Models; using ReactiveUI; -using Splat; -using System.Windows.Input; +using System.Reactive; +using System.Reactive.Disposables; namespace PatchGenerator.ViewModels { - public class MainWindowViewModel : ViewModelBase + public class MainWindowViewModel : ReactiveObject, IActivatableViewModel, IScreen { - public ICommand CloseCommand => ReactiveCommand.Create(() => + public RoutingState Router { get; } = new RoutingState(); + public ViewModelActivator Activator { get; } = new ViewModelActivator(); + + public ReactiveCommand CloseCommand => ReactiveCommand.Create(() => { if (Application.Current.ApplicationLifetime is Avalonia.Controls.ApplicationLifetimes.IClassicDesktopStyleApplicationLifetime desktopApp) { @@ -16,25 +19,26 @@ namespace PatchGenerator.ViewModels } }); - public ViewNavigator navigator { get; set; } = new ViewNavigator(); public MainWindowViewModel(GenStartupArgs genArgs = null) { - Locator.CurrentMutable.RegisterConstant(navigator, typeof(ViewNavigator)); - - if (genArgs != null && genArgs.ReadyToRun) + this.WhenActivated((CompositeDisposable disposables) => { - PatchGenInfo genInfo = new PatchGenInfo(); - genInfo.TargetFolderPath = genArgs.TargetFolderPath; - genInfo.SourceFolderPath = genArgs.SourceFolderPath; - genInfo.PatchName = genArgs.OutputFolderName; - genInfo.AutoZip = genArgs.AutoZip; + if (genArgs != null && genArgs.ReadyToRun) + { + PatchGenInfo genInfo = new PatchGenInfo(); - navigator.SelectedViewModel = new PatchGenerationViewModel(genInfo); - return; - } + genInfo.TargetFolderPath = genArgs.TargetFolderPath; + genInfo.SourceFolderPath = genArgs.SourceFolderPath; + genInfo.PatchName = genArgs.OutputFolderName; + genInfo.AutoZip = genArgs.AutoZip; - navigator.SelectedViewModel = new OptionsViewModel(); + Router.Navigate.Execute(new PatchGenerationViewModel(this, genInfo)); + return; + } + + Router.Navigate.Execute(new OptionsViewModel(this)); + }); } } } diff --git a/Patcher/PatchGenerator/ViewModels/OptionsViewModel.cs b/Patcher/PatchGenerator/ViewModels/OptionsViewModel.cs index d5f1f84..9c28330 100644 --- a/Patcher/PatchGenerator/ViewModels/OptionsViewModel.cs +++ b/Patcher/PatchGenerator/ViewModels/OptionsViewModel.cs @@ -1,5 +1,5 @@ using PatchGenerator.Models; -using Splat; +using ReactiveUI; namespace PatchGenerator.ViewModels { @@ -7,9 +7,7 @@ namespace PatchGenerator.ViewModels { public PatchGenInfo GenerationInfo { get; set; } = new PatchGenInfo(); - private ViewNavigator navigator => Locator.Current.GetService(); - - public OptionsViewModel() + public OptionsViewModel(IScreen Host) : base(Host) { GenerationInfo.SourceFolderPath = "Drop SOURCE folder here"; GenerationInfo.TargetFolderPath = "Drop TARGET folder here"; @@ -17,7 +15,7 @@ namespace PatchGenerator.ViewModels public void GeneratePatches() { - navigator.SelectedViewModel = new PatchGenerationViewModel(GenerationInfo); + NavigateTo(new PatchGenerationViewModel(HostScreen, GenerationInfo)); } } } diff --git a/Patcher/PatchGenerator/ViewModels/PatchGenerationViewModel.cs b/Patcher/PatchGenerator/ViewModels/PatchGenerationViewModel.cs index 821f041..cae708b 100644 --- a/Patcher/PatchGenerator/ViewModels/PatchGenerationViewModel.cs +++ b/Patcher/PatchGenerator/ViewModels/PatchGenerationViewModel.cs @@ -8,6 +8,7 @@ using System.Collections.Generic; using System.Collections.ObjectModel; using System.Diagnostics; using System.IO; +using System.Reactive.Disposables; using System.Text; using System.Threading.Tasks; @@ -42,7 +43,7 @@ namespace PatchGenerator.ViewModels private Stopwatch patchGenStopwatch = new Stopwatch(); private readonly PatchGenInfo generationInfo; - public PatchGenerationViewModel(PatchGenInfo GenerationInfo) + public PatchGenerationViewModel(IScreen Host, PatchGenInfo GenerationInfo) : base(Host) { generationInfo = GenerationInfo; @@ -55,17 +56,16 @@ namespace PatchGenerator.ViewModels }); } - GeneratePatches(); + this.WhenActivated((CompositeDisposable dissposables) => + { + GeneratePatches(); + }); } public void GeneratePatches() { Task.Run(() => { - //Slight delay to avoid some weird race condition in avalonia core, seems to be a bug, but also maybe I'm just stupid, idk -waffle - //Error without delay: An item with the same key has already been added. Key: [1, Avalonia.Controls.Generators.ItemContainerInfo] - System.Threading.Thread.Sleep(1000); - string patchOutputFolder = Path.Join(generationInfo.PatchName.FromCwd(), LazyOperations.PatchFolder); PatchHelper patcher = new PatchHelper(generationInfo.SourceFolderPath, generationInfo.TargetFolderPath, patchOutputFolder); diff --git a/Patcher/PatchGenerator/ViewModels/ViewModelBase.cs b/Patcher/PatchGenerator/ViewModels/ViewModelBase.cs index 14a41bb..d11493e 100644 --- a/Patcher/PatchGenerator/ViewModels/ViewModelBase.cs +++ b/Patcher/PatchGenerator/ViewModels/ViewModelBase.cs @@ -1,8 +1,72 @@ +using Avalonia.Threading; using ReactiveUI; +using System; +using System.Threading.Tasks; namespace PatchGenerator.ViewModels { - public class ViewModelBase : ReactiveObject + public class ViewModelBase : ReactiveObject, IActivatableViewModel, IRoutableViewModel { + public ViewModelActivator Activator { get; } = new ViewModelActivator(); + + public string? UrlPathSegment => Guid.NewGuid().ToString().Substring(0, 7); + + public IScreen HostScreen { get; } + + /// + /// Delay the return of the viewmodel + /// + /// The amount of time in milliseconds to delay + /// The viewmodel after the delay time + /// Useful to delay the navigation to another view. For instance, to allow an animation to complete. + private async Task WithDelay(int Milliseconds) + { + await Task.Delay(Milliseconds); + + return this; + } + + /// + /// Navigate to another viewmodel after a delay + /// + /// + /// + /// + public async Task NavigateToWithDelay(ViewModelBase ViewModel, int Milliseconds) + { + await Dispatcher.UIThread.InvokeAsync(async () => + { + HostScreen.Router.Navigate.Execute(await ViewModel.WithDelay(Milliseconds)); + }); + } + + /// + /// Navigate to another viewmodel + /// + /// + public void NavigateTo(ViewModelBase ViewModel) + { + Dispatcher.UIThread.InvokeAsync(() => + { + HostScreen.Router.Navigate.Execute(ViewModel); + }); + } + + /// + /// Navigate to the previous viewmodel + /// + public void NavigateBack() + { + Dispatcher.UIThread.InvokeAsync(() => + { + HostScreen.Router.NavigateBack.Execute(); + }); + } + + public ViewModelBase(IScreen Host) + { + HostScreen = Host; + } } + } diff --git a/Patcher/PatchGenerator/Views/MainWindow.axaml b/Patcher/PatchGenerator/Views/MainWindow.axaml index 4e9c849..919a6f7 100644 --- a/Patcher/PatchGenerator/Views/MainWindow.axaml +++ b/Patcher/PatchGenerator/Views/MainWindow.axaml @@ -4,6 +4,7 @@ xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:cc="using:PatchGenerator.CustomControls" + xmlns:rxui="using:Avalonia.ReactiveUI" mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450" x:Class="PatchGenerator.Views.MainWindow" Icon="/Assets/avalonia-logo.ico" @@ -28,9 +29,7 @@ - - - + diff --git a/Patcher/PatchGenerator/Views/MainWindow.axaml.cs b/Patcher/PatchGenerator/Views/MainWindow.axaml.cs index ffc62a1..2af0cec 100644 --- a/Patcher/PatchGenerator/Views/MainWindow.axaml.cs +++ b/Patcher/PatchGenerator/Views/MainWindow.axaml.cs @@ -1,10 +1,12 @@ using Avalonia; -using Avalonia.Controls; using Avalonia.Markup.Xaml; +using Avalonia.ReactiveUI; +using PatchGenerator.ViewModels; +using ReactiveUI; namespace PatchGenerator.Views { - public partial class MainWindow : Window + public partial class MainWindow : ReactiveWindow { public MainWindow() { @@ -16,6 +18,7 @@ namespace PatchGenerator.Views private void InitializeComponent() { + this.WhenActivated(disposables => { }); AvaloniaXamlLoader.Load(this); } } diff --git a/Patcher/PatchGenerator/Views/OptionsView.axaml.cs b/Patcher/PatchGenerator/Views/OptionsView.axaml.cs index 484cfad..023ca58 100644 --- a/Patcher/PatchGenerator/Views/OptionsView.axaml.cs +++ b/Patcher/PatchGenerator/Views/OptionsView.axaml.cs @@ -1,9 +1,11 @@ -using Avalonia.Controls; using Avalonia.Markup.Xaml; +using Avalonia.ReactiveUI; +using PatchGenerator.ViewModels; +using ReactiveUI; namespace PatchGenerator.Views { - public partial class OptionsView : UserControl + public partial class OptionsView : ReactiveUserControl { public OptionsView() { @@ -12,6 +14,7 @@ namespace PatchGenerator.Views private void InitializeComponent() { + this.WhenActivated(disposables => { }); AvaloniaXamlLoader.Load(this); } } diff --git a/Patcher/PatchGenerator/Views/PatchGenerationView.axaml.cs b/Patcher/PatchGenerator/Views/PatchGenerationView.axaml.cs index 958aa2f..d19f48d 100644 --- a/Patcher/PatchGenerator/Views/PatchGenerationView.axaml.cs +++ b/Patcher/PatchGenerator/Views/PatchGenerationView.axaml.cs @@ -1,10 +1,13 @@ using Avalonia.Controls; using Avalonia.Markup.Xaml; +using Avalonia.ReactiveUI; using PatchGenerator.AttachedProperties; +using PatchGenerator.ViewModels; +using ReactiveUI; namespace PatchGenerator.Views { - public partial class PatchGenerationView : UserControl + public partial class PatchGenerationView : ReactiveUserControl { public PatchGenerationView() { @@ -13,6 +16,7 @@ namespace PatchGenerator.Views private void InitializeComponent() { + this.WhenActivated(disposables => { }); AvaloniaXamlLoader.Load(this); } diff --git a/Patcher/PatcherUtils/PatchHelper.cs b/Patcher/PatcherUtils/PatchHelper.cs index 8722185..f672ae7 100644 --- a/Patcher/PatcherUtils/PatchHelper.cs +++ b/Patcher/PatcherUtils/PatchHelper.cs @@ -242,6 +242,9 @@ namespace PatcherUtils //Any remaining source files do not exist in the target folder and can be removed. //reset progress info + + if (SourceFiles.Count == 0) return true; + RaiseProgressChanged(0, SourceFiles.Count, "Processing .del files..."); filesProcessed = 0; fileCountTotal = SourceFiles.Count; diff --git a/Patcher/PatcherUtils/Resources/PatchClient.exe b/Patcher/PatcherUtils/Resources/PatchClient.exe index 96c22f5..505ea6f 100644 --- a/Patcher/PatcherUtils/Resources/PatchClient.exe +++ b/Patcher/PatcherUtils/Resources/PatchClient.exe @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:2e5ce3000b392b9c341a0550f4223a522e84a7b64032298a6ec12a8da52dbebb -size 80031404 +oid sha256:6a9822ee15b05e7017463f41835a4e7d0f12e418d6d629176733cec434203f03 +size 440063838