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.
170 lines
5.0 KiB
C#
170 lines
5.0 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 HookBrowserRow
|
|
{
|
|
public required string Group { get; init; }
|
|
public required string Namespace { get; init; }
|
|
public required string ClassName { get; init; }
|
|
public required string MethodName { get; init; }
|
|
public required string ReturnType { get; init; }
|
|
public required bool IsVoid { get; init; }
|
|
public required string Parameters { get; init; }
|
|
}
|
|
|
|
public sealed class HookBrowserViewModel : BaseViewModel
|
|
{
|
|
private readonly ExtractorService _extractorService = new();
|
|
private HookClassifier _classifier;
|
|
|
|
private string _searchText = string.Empty;
|
|
private string _selectedGroup = "Alle";
|
|
private bool _isLoading;
|
|
|
|
public HookBrowserViewModel()
|
|
{
|
|
_classifier = HookClassifier.LoadFromFile(null, new UIProgress<string>(_ => { }));
|
|
|
|
Groups.Add("Alle");
|
|
RefreshCommand = new AsyncRelayCommand(RefreshAsync, () => !IsLoading);
|
|
}
|
|
|
|
public string SearchText
|
|
{
|
|
get => _searchText;
|
|
set
|
|
{
|
|
if (!SetProperty(ref _searchText, value))
|
|
return;
|
|
|
|
RunOnUIThread(ApplyFilter);
|
|
}
|
|
}
|
|
|
|
public string SelectedGroup
|
|
{
|
|
get => _selectedGroup;
|
|
set
|
|
{
|
|
if (!SetProperty(ref _selectedGroup, value))
|
|
return;
|
|
|
|
RunOnUIThread(ApplyFilter);
|
|
}
|
|
}
|
|
|
|
public bool IsLoading
|
|
{
|
|
get => _isLoading;
|
|
set
|
|
{
|
|
if (!SetProperty(ref _isLoading, value))
|
|
return;
|
|
|
|
RefreshCommand.NotifyCanExecuteChanged();
|
|
}
|
|
}
|
|
|
|
public ObservableCollection<string> Groups { get; } = new();
|
|
|
|
public ObservableCollection<HookBrowserRow> Rows { get; } = new();
|
|
|
|
public ObservableCollection<HookBrowserRow> FilteredRows { get; } = new();
|
|
|
|
public IAsyncRelayCommand RefreshCommand { get; }
|
|
|
|
public async Task RefreshAsync()
|
|
{
|
|
_classifier = HookClassifier.LoadFromFile(null, new UIProgress<string>(_ => { }));
|
|
|
|
string? il2CppPath = SteamLocator.FindIl2CppAssembliesPath();
|
|
if (string.IsNullOrWhiteSpace(il2CppPath))
|
|
{
|
|
RunOnUIThread(() =>
|
|
{
|
|
Rows.Clear();
|
|
FilteredRows.Clear();
|
|
});
|
|
return;
|
|
}
|
|
|
|
IsLoading = true;
|
|
try
|
|
{
|
|
var result = await _extractorService.ExtractAsync(
|
|
il2CppPath,
|
|
_classifier,
|
|
new UIProgress<string>(_ => { }),
|
|
CancellationToken.None).ConfigureAwait(false);
|
|
|
|
if (!result.IsSuccess)
|
|
{
|
|
RunOnUIThread(() =>
|
|
{
|
|
Rows.Clear();
|
|
FilteredRows.Clear();
|
|
});
|
|
return;
|
|
}
|
|
|
|
var hooks = result.Hooks;
|
|
|
|
await RunOnUIThreadAsync(() =>
|
|
{
|
|
Rows.Clear();
|
|
foreach (HookDefinition hook in hooks)
|
|
{
|
|
Rows.Add(new HookBrowserRow
|
|
{
|
|
Group = hook.Group,
|
|
Namespace = hook.Namespace,
|
|
ClassName = hook.ClassName,
|
|
MethodName = hook.MethodName,
|
|
ReturnType = hook.ReturnType,
|
|
IsVoid = hook.IsVoid,
|
|
Parameters = string.Join(", ", hook.Parameters.Select(p => $"{p.Type} {p.Name}")),
|
|
});
|
|
}
|
|
|
|
HashSet<string> groups = hooks.Select(h => h.Group).ToHashSet(StringComparer.OrdinalIgnoreCase);
|
|
Groups.Clear();
|
|
Groups.Add("Alle");
|
|
foreach (string group in groups.OrderBy(x => x, StringComparer.OrdinalIgnoreCase))
|
|
Groups.Add(group);
|
|
|
|
ApplyFilter();
|
|
});
|
|
}
|
|
finally
|
|
{
|
|
IsLoading = false;
|
|
}
|
|
}
|
|
|
|
private void ApplyFilter()
|
|
{
|
|
IEnumerable<HookBrowserRow> query = Rows;
|
|
|
|
if (!SelectedGroup.Equals("Alle", StringComparison.OrdinalIgnoreCase))
|
|
query = query.Where(x => x.Group.Equals(SelectedGroup, StringComparison.OrdinalIgnoreCase));
|
|
|
|
if (!string.IsNullOrWhiteSpace(SearchText))
|
|
{
|
|
query = query.Where(x =>
|
|
x.MethodName.Contains(SearchText, StringComparison.OrdinalIgnoreCase)
|
|
|| x.ClassName.Contains(SearchText, StringComparison.OrdinalIgnoreCase)
|
|
|| x.Namespace.Contains(SearchText, StringComparison.OrdinalIgnoreCase)
|
|
|| x.Group.Contains(SearchText, StringComparison.OrdinalIgnoreCase));
|
|
}
|
|
|
|
FilteredRows.Clear();
|
|
foreach (HookBrowserRow row in query)
|
|
FilteredRows.Add(row);
|
|
}
|
|
} |