2f61e5dc00
- Updated HookBrowserViewModel, MainViewModel, SettingsViewModel, and SyncViewModel to inherit from BaseViewModel. - Introduced BaseViewModel with methods for running actions on the UI thread. - Enhanced SyncViewModel to handle property changes on the UI thread. - Refactored ExtractorService to return ExtractorResult instead of IReadOnlyList<HookDefinition>. - Added ExtractorResult class to encapsulate extraction results, including success status and error messages. - Implemented UIProgress class for reporting progress on the UI thread. - Updated hook_groups.json with additional classes and methods for various categories. - Improved error handling and logging in ExtractorService and SyncViewModel.
234 lines
6.6 KiB
C#
234 lines
6.6 KiB
C#
using Avalonia.Threading;
|
|
using CommunityToolkit.Mvvm.ComponentModel;
|
|
using CommunityToolkit.Mvvm.Input;
|
|
using gregExtractor.Models;
|
|
using gregExtractor.Services;
|
|
using gregExtractor.Utils;
|
|
|
|
namespace gregExtractor.GUI.ViewModels;
|
|
|
|
public sealed class CreateViewModel : BaseViewModel
|
|
{
|
|
private readonly TemplateService _templateService = new();
|
|
|
|
private int _step = 1;
|
|
private string _modName = "MyDataCenterMod";
|
|
private string _author = "TeamGreg";
|
|
private string _version = "1.0.0";
|
|
private string _description = "Generated by gregExtractor";
|
|
private string _outputPath = Directory.GetCurrentDirectory();
|
|
private TemplateType _selectedTemplateType = TemplateType.HarmonyPatch;
|
|
private string? _selectedCategory;
|
|
private bool _isLoading;
|
|
|
|
public CreateViewModel()
|
|
{
|
|
HookClassifier classifier = HookClassifier.LoadFromFile(null, new UIProgress<string>(AddLog));
|
|
foreach (string group in classifier.Groups.Keys.OrderBy(x => x, StringComparer.OrdinalIgnoreCase))
|
|
Categories.Add(group);
|
|
|
|
if (!Categories.Contains("Misc", StringComparer.OrdinalIgnoreCase))
|
|
Categories.Add("Misc");
|
|
|
|
TemplateTypes = Enum.GetValues<TemplateType>();
|
|
|
|
NextStepCommand = new RelayCommand(NextStep, () => !IsLoading);
|
|
PreviousStepCommand = new RelayCommand(PreviousStep, () => !IsLoading);
|
|
BrowseOutputPathCommand = new AsyncRelayCommand(BrowseOutputPathAsync);
|
|
GenerateCommand = new AsyncRelayCommand(GenerateAsync, () => !IsLoading && !string.IsNullOrWhiteSpace(ModName));
|
|
OpenOutputCommand = new RelayCommand(OpenOutput, () => Directory.Exists(OutputPath));
|
|
}
|
|
|
|
public Func<string?, Task<string?>>? BrowseFolderHandler { get; set; }
|
|
|
|
public int Step
|
|
{
|
|
get => _step;
|
|
set => SetProperty(ref _step, Math.Clamp(value, 1, 3));
|
|
}
|
|
|
|
public bool IsLoading
|
|
{
|
|
get => _isLoading;
|
|
set
|
|
{
|
|
if (Dispatcher.UIThread.CheckAccess())
|
|
{
|
|
if (!SetProperty(ref _isLoading, value))
|
|
return;
|
|
}
|
|
else
|
|
{
|
|
Dispatcher.UIThread.Post(() => SetProperty(ref _isLoading, value));
|
|
return;
|
|
}
|
|
|
|
NextStepCommand.NotifyCanExecuteChanged();
|
|
PreviousStepCommand.NotifyCanExecuteChanged();
|
|
GenerateCommand.NotifyCanExecuteChanged();
|
|
}
|
|
}
|
|
|
|
public string ModName
|
|
{
|
|
get => _modName;
|
|
set
|
|
{
|
|
if (!SetProperty(ref _modName, value))
|
|
return;
|
|
|
|
GenerateCommand.NotifyCanExecuteChanged();
|
|
}
|
|
}
|
|
|
|
public string Author
|
|
{
|
|
get => _author;
|
|
set => SetProperty(ref _author, value);
|
|
}
|
|
|
|
public string Version
|
|
{
|
|
get => _version;
|
|
set => SetProperty(ref _version, value);
|
|
}
|
|
|
|
public string Description
|
|
{
|
|
get => _description;
|
|
set => SetProperty(ref _description, value);
|
|
}
|
|
|
|
public string OutputPath
|
|
{
|
|
get => _outputPath;
|
|
set
|
|
{
|
|
if (!SetProperty(ref _outputPath, value?.Trim() ?? string.Empty))
|
|
return;
|
|
|
|
OpenOutputCommand.NotifyCanExecuteChanged();
|
|
}
|
|
}
|
|
|
|
public TemplateType SelectedTemplateType
|
|
{
|
|
get => _selectedTemplateType;
|
|
set => SetProperty(ref _selectedTemplateType, value);
|
|
}
|
|
|
|
public string? SelectedCategory
|
|
{
|
|
get => _selectedCategory;
|
|
set => SetProperty(ref _selectedCategory, value);
|
|
}
|
|
|
|
public IReadOnlyList<TemplateType> TemplateTypes { get; }
|
|
|
|
public ObservableCollection<string> Categories { get; } = new();
|
|
|
|
public ObservableCollection<string> PreviewTree { get; } = new();
|
|
|
|
public ObservableCollection<string> LogLines { get; } = new();
|
|
|
|
public IRelayCommand NextStepCommand { get; }
|
|
|
|
public IRelayCommand PreviousStepCommand { get; }
|
|
|
|
public IAsyncRelayCommand BrowseOutputPathCommand { get; }
|
|
|
|
public IAsyncRelayCommand GenerateCommand { get; }
|
|
|
|
public IRelayCommand OpenOutputCommand { get; }
|
|
|
|
private void NextStep()
|
|
{
|
|
Step = Math.Min(3, Step + 1);
|
|
if (Step == 3)
|
|
RefreshPreview();
|
|
}
|
|
|
|
private void PreviousStep()
|
|
{
|
|
Step = Math.Max(1, Step - 1);
|
|
}
|
|
|
|
private async Task BrowseOutputPathAsync()
|
|
{
|
|
if (BrowseFolderHandler is null)
|
|
return;
|
|
|
|
string? selected = await BrowseFolderHandler("CreateOutput").ConfigureAwait(false);
|
|
if (!string.IsNullOrWhiteSpace(selected))
|
|
OutputPath = selected;
|
|
}
|
|
|
|
private async Task GenerateAsync()
|
|
{
|
|
IsLoading = true;
|
|
try
|
|
{
|
|
string hooksPath = Path.Combine(Directory.GetCurrentDirectory(), "game_hooks.json");
|
|
var result = await Task.Run(() => _templateService.GenerateModAsync(
|
|
ModName,
|
|
SelectedCategory,
|
|
SelectedTemplateType,
|
|
OutputPath,
|
|
hooksPath,
|
|
new UIProgress<string>(AddLog),
|
|
CancellationToken.None)).ConfigureAwait(false);
|
|
|
|
await Dispatcher.UIThread.InvokeAsync(() =>
|
|
{
|
|
PreviewTree.Clear();
|
|
PreviewTree.Add(Path.GetFileName(result.ModDirectory) + "/");
|
|
foreach (string file in result.GeneratedFiles.OrderBy(x => x, StringComparer.OrdinalIgnoreCase))
|
|
PreviewTree.Add(" " + Path.GetRelativePath(result.ModDirectory, file).Replace('\\', '/'));
|
|
});
|
|
|
|
AddLog($"Mod erstellt: {result.ModDirectory}");
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
AddLog($"Mod-Erstellung fehlgeschlagen: {ex.Message}");
|
|
}
|
|
finally
|
|
{
|
|
IsLoading = false;
|
|
}
|
|
}
|
|
|
|
private void OpenOutput()
|
|
{
|
|
if (!Directory.Exists(OutputPath))
|
|
return;
|
|
|
|
Process.Start(new ProcessStartInfo
|
|
{
|
|
FileName = OutputPath,
|
|
UseShellExecute = true,
|
|
});
|
|
}
|
|
|
|
private void RefreshPreview()
|
|
{
|
|
RunOnUIThread(() =>
|
|
{
|
|
PreviewTree.Clear();
|
|
PreviewTree.Add(ModName + "/");
|
|
PreviewTree.Add(" " + ModName + ".csproj");
|
|
PreviewTree.Add(" MainPlugin.cs");
|
|
PreviewTree.Add(" mod.json");
|
|
PreviewTree.Add(" Patches/");
|
|
});
|
|
}
|
|
|
|
private void AddLog(string message)
|
|
{
|
|
string line = $"[{DateTime.Now:HH:mm:ss}] {message}";
|
|
if (LogLines.Count > 1000)
|
|
LogLines.RemoveAt(0);
|
|
|
|
LogLines.Add(line);
|
|
}
|
|
} |