mirror of
https://github.com/sp-tarkov/patcher.git
synced 2025-02-12 22:30:46 -05:00
Replace ViewNavigator with ReactiveUI RouterState, Fix PatchHelper rasing progress changed with no remaining source files, fix view load race conditions
This commit is contained in:
parent
6ef883958d
commit
25a3c270be
@ -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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,6 +1,9 @@
|
|||||||
using Avalonia;
|
using Avalonia;
|
||||||
using Avalonia.ReactiveUI;
|
using Avalonia.ReactiveUI;
|
||||||
|
using Splat;
|
||||||
using System;
|
using System;
|
||||||
|
using ReactiveUI;
|
||||||
|
using System.Reflection;
|
||||||
|
|
||||||
namespace PatchClient
|
namespace PatchClient
|
||||||
{
|
{
|
||||||
@ -15,9 +18,14 @@ namespace PatchClient
|
|||||||
|
|
||||||
// Avalonia configuration, don't remove; also used by visual designer.
|
// Avalonia configuration, don't remove; also used by visual designer.
|
||||||
public static AppBuilder BuildAvaloniaApp()
|
public static AppBuilder BuildAvaloniaApp()
|
||||||
=> AppBuilder.Configure<App>()
|
{
|
||||||
|
Locator.CurrentMutable.RegisterViewsForViewModels(Assembly.GetExecutingAssembly());
|
||||||
|
|
||||||
|
return AppBuilder.Configure<App>()
|
||||||
|
.UseReactiveUI()
|
||||||
.UsePlatformDetect()
|
.UsePlatformDetect()
|
||||||
.LogToTrace()
|
.LogToTrace()
|
||||||
.UseReactiveUI();
|
.UseReactiveUI();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,13 +1,15 @@
|
|||||||
using Avalonia;
|
using Avalonia;
|
||||||
using PatchClient.Models;
|
|
||||||
using ReactiveUI;
|
using ReactiveUI;
|
||||||
using Splat;
|
using System.Reactive.Disposables;
|
||||||
using System.Windows.Input;
|
using System.Windows.Input;
|
||||||
|
|
||||||
namespace PatchClient.ViewModels
|
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(() =>
|
public ICommand CloseCommand => ReactiveCommand.Create(() =>
|
||||||
{
|
{
|
||||||
if (Application.Current.ApplicationLifetime is Avalonia.Controls.ApplicationLifetimes.IClassicDesktopStyleApplicationLifetime desktopApp)
|
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()
|
public MainWindowViewModel()
|
||||||
{
|
{
|
||||||
navigator.SelectedViewModel = new PatcherViewModel();
|
this.WhenActivated((CompositeDisposable disposable) =>
|
||||||
|
{
|
||||||
Locator.CurrentMutable.RegisterConstant(navigator, typeof(ViewNavigator));
|
Router.Navigate.Execute(new PatcherViewModel(this));
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -4,14 +4,14 @@ namespace PatchClient.ViewModels
|
|||||||
{
|
{
|
||||||
public class MessageViewModel : ViewModelBase
|
public class MessageViewModel : ViewModelBase
|
||||||
{
|
{
|
||||||
private string _InfoText;
|
private string _InfoText = "";
|
||||||
public string InfoText
|
public string InfoText
|
||||||
{
|
{
|
||||||
get => _InfoText;
|
get => _InfoText;
|
||||||
set => this.RaiseAndSetIfChanged(ref _InfoText, value);
|
set => this.RaiseAndSetIfChanged(ref _InfoText, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
public MessageViewModel(string Message)
|
public MessageViewModel(IScreen Host, string Message) : base(Host)
|
||||||
{
|
{
|
||||||
InfoText = Message;
|
InfoText = Message;
|
||||||
}
|
}
|
||||||
|
@ -1,11 +1,12 @@
|
|||||||
using Avalonia;
|
using Avalonia;
|
||||||
|
using Avalonia.Threading;
|
||||||
using PatchClient.Models;
|
using PatchClient.Models;
|
||||||
using PatcherUtils;
|
using PatcherUtils;
|
||||||
using ReactiveUI;
|
using ReactiveUI;
|
||||||
using Splat;
|
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.ObjectModel;
|
using System.Collections.ObjectModel;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using System.Reactive.Disposables;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
namespace PatchClient.ViewModels
|
namespace PatchClient.ViewModels
|
||||||
@ -16,7 +17,7 @@ namespace PatchClient.ViewModels
|
|||||||
|
|
||||||
public ObservableCollection<LineItemProgress> LineItems { get; set; } = new ObservableCollection<LineItemProgress>();
|
public ObservableCollection<LineItemProgress> LineItems { get; set; } = new ObservableCollection<LineItemProgress>();
|
||||||
|
|
||||||
private string _ProgressMessage;
|
private string _ProgressMessage = "";
|
||||||
public string ProgressMessage
|
public string ProgressMessage
|
||||||
{
|
{
|
||||||
get => _ProgressMessage;
|
get => _ProgressMessage;
|
||||||
@ -30,35 +31,67 @@ namespace PatchClient.ViewModels
|
|||||||
set => this.RaiseAndSetIfChanged(ref _PatchPercent, value);
|
set => this.RaiseAndSetIfChanged(ref _PatchPercent, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
private string _PatchMessage;
|
private string _PatchMessage = "";
|
||||||
public string PatchMessage
|
public string PatchMessage
|
||||||
{
|
{
|
||||||
get => _PatchMessage;
|
get => _PatchMessage;
|
||||||
set => this.RaiseAndSetIfChanged(ref _PatchMessage, value);
|
set => this.RaiseAndSetIfChanged(ref _PatchMessage, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
private ViewNavigator navigator => Locator.Current.GetService<ViewNavigator>();
|
|
||||||
|
|
||||||
public PatcherViewModel()
|
public PatcherViewModel(IScreen Host) : base(Host)
|
||||||
{
|
{
|
||||||
RunPatcher();
|
this.WhenActivated((CompositeDisposable disposables) =>
|
||||||
|
{
|
||||||
|
//Test();
|
||||||
|
RunPatcher();
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// A dumb testing method to see if things look right. Obsolete is used more like a warning here.
|
||||||
|
/// </summary>
|
||||||
|
[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()
|
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);
|
PatchHelper patcher = new PatchHelper(Environment.CurrentDirectory, null, LazyOperations.PatchFolder);
|
||||||
|
|
||||||
patcher.ProgressChanged += patcher_ProgressChanged;
|
patcher.ProgressChanged += patcher_ProgressChanged;
|
||||||
|
|
||||||
string message = patcher.ApplyPatches();
|
string message = patcher.ApplyPatches();
|
||||||
|
|
||||||
navigator.SelectedViewModel = new MessageViewModel(message).WithDelay(400);
|
await NavigateToWithDelay(new MessageViewModel(HostScreen, message), 400);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,22 +1,72 @@
|
|||||||
using PatchClient.Models;
|
using Avalonia.Threading;
|
||||||
using ReactiveUI;
|
using ReactiveUI;
|
||||||
|
using System;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
namespace PatchClient.ViewModels
|
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; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Delay the return of the viewmodel
|
/// Delay the return of the viewmodel
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="Milliseconds">The amount of time in milliseconds to delay</param>
|
/// <param name="Milliseconds">The amount of time in milliseconds to delay</param>
|
||||||
/// <returns>The viewmodel after the delay time</returns>
|
/// <returns>The viewmodel after the delay time</returns>
|
||||||
/// <remarks>Useful to delay the navigation to another view via the <see cref="ViewNavigator"/>. For instance, to allow an animation to complete.</remarks>
|
/// <remarks>Useful to delay the navigation to another view. For instance, to allow an animation to complete.</remarks>
|
||||||
public ViewModelBase WithDelay(int Milliseconds)
|
private async Task<ViewModelBase> WithDelay(int Milliseconds)
|
||||||
{
|
{
|
||||||
System.Threading.Thread.Sleep(Milliseconds);
|
await Task.Delay(Milliseconds);
|
||||||
|
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Navigate to another viewmodel after a delay
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="ViewModel"></param>
|
||||||
|
/// <param name="Milliseconds"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public async Task NavigateToWithDelay(ViewModelBase ViewModel, int Milliseconds)
|
||||||
|
{
|
||||||
|
await Dispatcher.UIThread.InvokeAsync(async () =>
|
||||||
|
{
|
||||||
|
HostScreen.Router.Navigate.Execute(await ViewModel.WithDelay(Milliseconds));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Navigate to another viewmodel
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="ViewModel"></param>
|
||||||
|
public void NavigateTo(ViewModelBase ViewModel)
|
||||||
|
{
|
||||||
|
Dispatcher.UIThread.InvokeAsync(() =>
|
||||||
|
{
|
||||||
|
HostScreen.Router.Navigate.Execute(ViewModel);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Navigate to the previous viewmodel
|
||||||
|
/// </summary>
|
||||||
|
public void NavigateBack()
|
||||||
|
{
|
||||||
|
Dispatcher.UIThread.InvokeAsync(() =>
|
||||||
|
{
|
||||||
|
HostScreen.Router.NavigateBack.Execute();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public ViewModelBase(IScreen Host)
|
||||||
|
{
|
||||||
|
HostScreen = Host;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -4,6 +4,7 @@
|
|||||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||||
xmlns:cc="using:PatchClient.CustomControls"
|
xmlns:cc="using:PatchClient.CustomControls"
|
||||||
|
xmlns:rxui="using:Avalonia.ReactiveUI"
|
||||||
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
|
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
|
||||||
x:Class="PatchClient.Views.MainWindow"
|
x:Class="PatchClient.Views.MainWindow"
|
||||||
Icon="/Assets/avalonia-logo.ico"
|
Icon="/Assets/avalonia-logo.ico"
|
||||||
@ -29,9 +30,7 @@
|
|||||||
<cc:TitleBar Title="Patch Client"
|
<cc:TitleBar Title="Patch Client"
|
||||||
XButtonCommand="{Binding CloseCommand}"/>
|
XButtonCommand="{Binding CloseCommand}"/>
|
||||||
|
|
||||||
<DockPanel LastChildFill="True" Grid.Row="1">
|
<rxui:RoutedViewHost Router="{Binding Router}" Grid.Row="1"/>
|
||||||
<ContentControl Content="{Binding navigator.SelectedViewModel}"/>
|
|
||||||
</DockPanel>
|
|
||||||
|
|
||||||
</Grid>
|
</Grid>
|
||||||
</Window>
|
</Window>
|
||||||
|
@ -1,10 +1,12 @@
|
|||||||
using Avalonia;
|
using Avalonia;
|
||||||
using Avalonia.Controls;
|
|
||||||
using Avalonia.Markup.Xaml;
|
using Avalonia.Markup.Xaml;
|
||||||
|
using Avalonia.ReactiveUI;
|
||||||
|
using PatchClient.ViewModels;
|
||||||
|
using ReactiveUI;
|
||||||
|
|
||||||
namespace PatchClient.Views
|
namespace PatchClient.Views
|
||||||
{
|
{
|
||||||
public partial class MainWindow : Window
|
public partial class MainWindow : ReactiveWindow<MainWindowViewModel>
|
||||||
{
|
{
|
||||||
public MainWindow()
|
public MainWindow()
|
||||||
{
|
{
|
||||||
@ -16,6 +18,7 @@ namespace PatchClient.Views
|
|||||||
|
|
||||||
private void InitializeComponent()
|
private void InitializeComponent()
|
||||||
{
|
{
|
||||||
|
this.WhenActivated(disposables => { });
|
||||||
AvaloniaXamlLoader.Load(this);
|
AvaloniaXamlLoader.Load(this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,9 +1,11 @@
|
|||||||
using Avalonia.Controls;
|
|
||||||
using Avalonia.Markup.Xaml;
|
using Avalonia.Markup.Xaml;
|
||||||
|
using Avalonia.ReactiveUI;
|
||||||
|
using PatchClient.ViewModels;
|
||||||
|
using ReactiveUI;
|
||||||
|
|
||||||
namespace PatchClient.Views
|
namespace PatchClient.Views
|
||||||
{
|
{
|
||||||
public partial class MessageView : UserControl
|
public partial class MessageView : ReactiveUserControl<MessageViewModel>
|
||||||
{
|
{
|
||||||
public MessageView()
|
public MessageView()
|
||||||
{
|
{
|
||||||
@ -12,6 +14,7 @@ namespace PatchClient.Views
|
|||||||
|
|
||||||
private void InitializeComponent()
|
private void InitializeComponent()
|
||||||
{
|
{
|
||||||
|
this.WhenActivated(disposables => { });
|
||||||
AvaloniaXamlLoader.Load(this);
|
AvaloniaXamlLoader.Load(this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,9 +1,11 @@
|
|||||||
using Avalonia.Controls;
|
|
||||||
using Avalonia.Markup.Xaml;
|
using Avalonia.Markup.Xaml;
|
||||||
|
using Avalonia.ReactiveUI;
|
||||||
|
using PatchClient.ViewModels;
|
||||||
|
using ReactiveUI;
|
||||||
|
|
||||||
namespace PatchClient.Views
|
namespace PatchClient.Views
|
||||||
{
|
{
|
||||||
public partial class PatcherView : UserControl
|
public partial class PatcherView : ReactiveUserControl<PatcherViewModel>
|
||||||
{
|
{
|
||||||
public PatcherView()
|
public PatcherView()
|
||||||
{
|
{
|
||||||
@ -12,6 +14,7 @@ namespace PatchClient.Views
|
|||||||
|
|
||||||
private void InitializeComponent()
|
private void InitializeComponent()
|
||||||
{
|
{
|
||||||
|
this.WhenActivated(disposables => { });
|
||||||
AvaloniaXamlLoader.Load(this);
|
AvaloniaXamlLoader.Load(this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,9 @@
|
|||||||
using Avalonia;
|
using Avalonia;
|
||||||
using Avalonia.ReactiveUI;
|
using Avalonia.ReactiveUI;
|
||||||
|
using Splat;
|
||||||
using System;
|
using System;
|
||||||
|
using ReactiveUI;
|
||||||
|
using System.Reflection;
|
||||||
|
|
||||||
namespace PatchGenerator
|
namespace PatchGenerator
|
||||||
{
|
{
|
||||||
@ -15,9 +18,14 @@ namespace PatchGenerator
|
|||||||
|
|
||||||
// Avalonia configuration, don't remove; also used by visual designer.
|
// Avalonia configuration, don't remove; also used by visual designer.
|
||||||
public static AppBuilder BuildAvaloniaApp()
|
public static AppBuilder BuildAvaloniaApp()
|
||||||
=> AppBuilder.Configure<App>()
|
{
|
||||||
|
Locator.CurrentMutable.RegisterViewsForViewModels(Assembly.GetExecutingAssembly());
|
||||||
|
|
||||||
|
return AppBuilder.Configure<App>()
|
||||||
|
.UseReactiveUI()
|
||||||
.UsePlatformDetect()
|
.UsePlatformDetect()
|
||||||
.LogToTrace()
|
.LogToTrace()
|
||||||
.UseReactiveUI();
|
.UseReactiveUI();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,9 +1,7 @@
|
|||||||
{
|
{
|
||||||
"profiles": {
|
"profiles": {
|
||||||
"PatchGenerator": {
|
"PatchGenerator": {
|
||||||
"commandName": "Project",
|
"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\\"
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -1,14 +1,17 @@
|
|||||||
using Avalonia;
|
using Avalonia;
|
||||||
using PatchGenerator.Models;
|
using PatchGenerator.Models;
|
||||||
using ReactiveUI;
|
using ReactiveUI;
|
||||||
using Splat;
|
using System.Reactive;
|
||||||
using System.Windows.Input;
|
using System.Reactive.Disposables;
|
||||||
|
|
||||||
namespace PatchGenerator.ViewModels
|
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<Unit, Unit> CloseCommand => ReactiveCommand.Create(() =>
|
||||||
{
|
{
|
||||||
if (Application.Current.ApplicationLifetime is Avalonia.Controls.ApplicationLifetimes.IClassicDesktopStyleApplicationLifetime desktopApp)
|
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)
|
public MainWindowViewModel(GenStartupArgs genArgs = null)
|
||||||
{
|
{
|
||||||
Locator.CurrentMutable.RegisterConstant(navigator, typeof(ViewNavigator));
|
this.WhenActivated((CompositeDisposable disposables) =>
|
||||||
|
|
||||||
if (genArgs != null && genArgs.ReadyToRun)
|
|
||||||
{
|
{
|
||||||
PatchGenInfo genInfo = new PatchGenInfo();
|
|
||||||
|
|
||||||
genInfo.TargetFolderPath = genArgs.TargetFolderPath;
|
if (genArgs != null && genArgs.ReadyToRun)
|
||||||
genInfo.SourceFolderPath = genArgs.SourceFolderPath;
|
{
|
||||||
genInfo.PatchName = genArgs.OutputFolderName;
|
PatchGenInfo genInfo = new PatchGenInfo();
|
||||||
genInfo.AutoZip = genArgs.AutoZip;
|
|
||||||
|
|
||||||
navigator.SelectedViewModel = new PatchGenerationViewModel(genInfo);
|
genInfo.TargetFolderPath = genArgs.TargetFolderPath;
|
||||||
return;
|
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));
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
using PatchGenerator.Models;
|
using PatchGenerator.Models;
|
||||||
using Splat;
|
using ReactiveUI;
|
||||||
|
|
||||||
namespace PatchGenerator.ViewModels
|
namespace PatchGenerator.ViewModels
|
||||||
{
|
{
|
||||||
@ -7,9 +7,7 @@ namespace PatchGenerator.ViewModels
|
|||||||
{
|
{
|
||||||
public PatchGenInfo GenerationInfo { get; set; } = new PatchGenInfo();
|
public PatchGenInfo GenerationInfo { get; set; } = new PatchGenInfo();
|
||||||
|
|
||||||
private ViewNavigator navigator => Locator.Current.GetService<ViewNavigator>();
|
public OptionsViewModel(IScreen Host) : base(Host)
|
||||||
|
|
||||||
public OptionsViewModel()
|
|
||||||
{
|
{
|
||||||
GenerationInfo.SourceFolderPath = "Drop SOURCE folder here";
|
GenerationInfo.SourceFolderPath = "Drop SOURCE folder here";
|
||||||
GenerationInfo.TargetFolderPath = "Drop TARGET folder here";
|
GenerationInfo.TargetFolderPath = "Drop TARGET folder here";
|
||||||
@ -17,7 +15,7 @@ namespace PatchGenerator.ViewModels
|
|||||||
|
|
||||||
public void GeneratePatches()
|
public void GeneratePatches()
|
||||||
{
|
{
|
||||||
navigator.SelectedViewModel = new PatchGenerationViewModel(GenerationInfo);
|
NavigateTo(new PatchGenerationViewModel(HostScreen, GenerationInfo));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -8,6 +8,7 @@ using System.Collections.Generic;
|
|||||||
using System.Collections.ObjectModel;
|
using System.Collections.ObjectModel;
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
|
using System.Reactive.Disposables;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
@ -42,7 +43,7 @@ namespace PatchGenerator.ViewModels
|
|||||||
private Stopwatch patchGenStopwatch = new Stopwatch();
|
private Stopwatch patchGenStopwatch = new Stopwatch();
|
||||||
|
|
||||||
private readonly PatchGenInfo generationInfo;
|
private readonly PatchGenInfo generationInfo;
|
||||||
public PatchGenerationViewModel(PatchGenInfo GenerationInfo)
|
public PatchGenerationViewModel(IScreen Host, PatchGenInfo GenerationInfo) : base(Host)
|
||||||
{
|
{
|
||||||
generationInfo = GenerationInfo;
|
generationInfo = GenerationInfo;
|
||||||
|
|
||||||
@ -55,17 +56,16 @@ namespace PatchGenerator.ViewModels
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
GeneratePatches();
|
this.WhenActivated((CompositeDisposable dissposables) =>
|
||||||
|
{
|
||||||
|
GeneratePatches();
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public void GeneratePatches()
|
public void GeneratePatches()
|
||||||
{
|
{
|
||||||
Task.Run(() =>
|
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);
|
string patchOutputFolder = Path.Join(generationInfo.PatchName.FromCwd(), LazyOperations.PatchFolder);
|
||||||
|
|
||||||
PatchHelper patcher = new PatchHelper(generationInfo.SourceFolderPath, generationInfo.TargetFolderPath, patchOutputFolder);
|
PatchHelper patcher = new PatchHelper(generationInfo.SourceFolderPath, generationInfo.TargetFolderPath, patchOutputFolder);
|
||||||
|
@ -1,8 +1,72 @@
|
|||||||
|
using Avalonia.Threading;
|
||||||
using ReactiveUI;
|
using ReactiveUI;
|
||||||
|
using System;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
namespace PatchGenerator.ViewModels
|
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; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Delay the return of the viewmodel
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="Milliseconds">The amount of time in milliseconds to delay</param>
|
||||||
|
/// <returns>The viewmodel after the delay time</returns>
|
||||||
|
/// <remarks>Useful to delay the navigation to another view. For instance, to allow an animation to complete.</remarks>
|
||||||
|
private async Task<ViewModelBase> WithDelay(int Milliseconds)
|
||||||
|
{
|
||||||
|
await Task.Delay(Milliseconds);
|
||||||
|
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Navigate to another viewmodel after a delay
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="ViewModel"></param>
|
||||||
|
/// <param name="Milliseconds"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public async Task NavigateToWithDelay(ViewModelBase ViewModel, int Milliseconds)
|
||||||
|
{
|
||||||
|
await Dispatcher.UIThread.InvokeAsync(async () =>
|
||||||
|
{
|
||||||
|
HostScreen.Router.Navigate.Execute(await ViewModel.WithDelay(Milliseconds));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Navigate to another viewmodel
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="ViewModel"></param>
|
||||||
|
public void NavigateTo(ViewModelBase ViewModel)
|
||||||
|
{
|
||||||
|
Dispatcher.UIThread.InvokeAsync(() =>
|
||||||
|
{
|
||||||
|
HostScreen.Router.Navigate.Execute(ViewModel);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Navigate to the previous viewmodel
|
||||||
|
/// </summary>
|
||||||
|
public void NavigateBack()
|
||||||
|
{
|
||||||
|
Dispatcher.UIThread.InvokeAsync(() =>
|
||||||
|
{
|
||||||
|
HostScreen.Router.NavigateBack.Execute();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public ViewModelBase(IScreen Host)
|
||||||
|
{
|
||||||
|
HostScreen = Host;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -4,6 +4,7 @@
|
|||||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||||
xmlns:cc="using:PatchGenerator.CustomControls"
|
xmlns:cc="using:PatchGenerator.CustomControls"
|
||||||
|
xmlns:rxui="using:Avalonia.ReactiveUI"
|
||||||
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
|
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
|
||||||
x:Class="PatchGenerator.Views.MainWindow"
|
x:Class="PatchGenerator.Views.MainWindow"
|
||||||
Icon="/Assets/avalonia-logo.ico"
|
Icon="/Assets/avalonia-logo.ico"
|
||||||
@ -28,9 +29,7 @@
|
|||||||
<cc:TitleBar Title="Patch Generator"
|
<cc:TitleBar Title="Patch Generator"
|
||||||
XButtonCommand="{Binding CloseCommand}"/>
|
XButtonCommand="{Binding CloseCommand}"/>
|
||||||
|
|
||||||
<DockPanel LastChildFill="True" Grid.Row="1">
|
<rxui:RoutedViewHost Router="{Binding Router}" Grid.Row="1" />
|
||||||
<ContentControl Content="{Binding navigator.SelectedViewModel}"/>
|
|
||||||
</DockPanel>
|
|
||||||
|
|
||||||
</Grid>
|
</Grid>
|
||||||
|
|
||||||
|
@ -1,10 +1,12 @@
|
|||||||
using Avalonia;
|
using Avalonia;
|
||||||
using Avalonia.Controls;
|
|
||||||
using Avalonia.Markup.Xaml;
|
using Avalonia.Markup.Xaml;
|
||||||
|
using Avalonia.ReactiveUI;
|
||||||
|
using PatchGenerator.ViewModels;
|
||||||
|
using ReactiveUI;
|
||||||
|
|
||||||
namespace PatchGenerator.Views
|
namespace PatchGenerator.Views
|
||||||
{
|
{
|
||||||
public partial class MainWindow : Window
|
public partial class MainWindow : ReactiveWindow<MainWindowViewModel>
|
||||||
{
|
{
|
||||||
public MainWindow()
|
public MainWindow()
|
||||||
{
|
{
|
||||||
@ -16,6 +18,7 @@ namespace PatchGenerator.Views
|
|||||||
|
|
||||||
private void InitializeComponent()
|
private void InitializeComponent()
|
||||||
{
|
{
|
||||||
|
this.WhenActivated(disposables => { });
|
||||||
AvaloniaXamlLoader.Load(this);
|
AvaloniaXamlLoader.Load(this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,9 +1,11 @@
|
|||||||
using Avalonia.Controls;
|
|
||||||
using Avalonia.Markup.Xaml;
|
using Avalonia.Markup.Xaml;
|
||||||
|
using Avalonia.ReactiveUI;
|
||||||
|
using PatchGenerator.ViewModels;
|
||||||
|
using ReactiveUI;
|
||||||
|
|
||||||
namespace PatchGenerator.Views
|
namespace PatchGenerator.Views
|
||||||
{
|
{
|
||||||
public partial class OptionsView : UserControl
|
public partial class OptionsView : ReactiveUserControl<OptionsViewModel>
|
||||||
{
|
{
|
||||||
public OptionsView()
|
public OptionsView()
|
||||||
{
|
{
|
||||||
@ -12,6 +14,7 @@ namespace PatchGenerator.Views
|
|||||||
|
|
||||||
private void InitializeComponent()
|
private void InitializeComponent()
|
||||||
{
|
{
|
||||||
|
this.WhenActivated(disposables => { });
|
||||||
AvaloniaXamlLoader.Load(this);
|
AvaloniaXamlLoader.Load(this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,10 +1,13 @@
|
|||||||
using Avalonia.Controls;
|
using Avalonia.Controls;
|
||||||
using Avalonia.Markup.Xaml;
|
using Avalonia.Markup.Xaml;
|
||||||
|
using Avalonia.ReactiveUI;
|
||||||
using PatchGenerator.AttachedProperties;
|
using PatchGenerator.AttachedProperties;
|
||||||
|
using PatchGenerator.ViewModels;
|
||||||
|
using ReactiveUI;
|
||||||
|
|
||||||
namespace PatchGenerator.Views
|
namespace PatchGenerator.Views
|
||||||
{
|
{
|
||||||
public partial class PatchGenerationView : UserControl
|
public partial class PatchGenerationView : ReactiveUserControl<PatchGenerationViewModel>
|
||||||
{
|
{
|
||||||
public PatchGenerationView()
|
public PatchGenerationView()
|
||||||
{
|
{
|
||||||
@ -13,6 +16,7 @@ namespace PatchGenerator.Views
|
|||||||
|
|
||||||
private void InitializeComponent()
|
private void InitializeComponent()
|
||||||
{
|
{
|
||||||
|
this.WhenActivated(disposables => { });
|
||||||
AvaloniaXamlLoader.Load(this);
|
AvaloniaXamlLoader.Load(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -242,6 +242,9 @@ namespace PatcherUtils
|
|||||||
|
|
||||||
//Any remaining source files do not exist in the target folder and can be removed.
|
//Any remaining source files do not exist in the target folder and can be removed.
|
||||||
//reset progress info
|
//reset progress info
|
||||||
|
|
||||||
|
if (SourceFiles.Count == 0) return true;
|
||||||
|
|
||||||
RaiseProgressChanged(0, SourceFiles.Count, "Processing .del files...");
|
RaiseProgressChanged(0, SourceFiles.Count, "Processing .del files...");
|
||||||
filesProcessed = 0;
|
filesProcessed = 0;
|
||||||
fileCountTotal = SourceFiles.Count;
|
fileCountTotal = SourceFiles.Count;
|
||||||
|
BIN
Patcher/PatcherUtils/Resources/PatchClient.exe
(Stored with Git LFS)
BIN
Patcher/PatcherUtils/Resources/PatchClient.exe
(Stored with Git LFS)
Binary file not shown.
Loading…
x
Reference in New Issue
Block a user