From 4b19c9f30ba66a34712699bc66b91cd751f59b98 Mon Sep 17 00:00:00 2001
From: Denis-RZ <77514212+Denis-RZ@users.noreply.github.com>
Date: Sat, 7 Jun 2025 11:59:32 +0800
Subject: [PATCH] Expand Avalonia UI functionality
---
README.md | 11 +-
UniversalCodePatcher.Avalonia/App.axaml | 10 +
UniversalCodePatcher.Avalonia/App.axaml.cs | 23 ++
.../MainWindow.axaml | 80 +++++
.../MainWindow.axaml.cs | 332 ++++++++++++++++++
UniversalCodePatcher.Avalonia/Program.cs | 21 ++
.../UniversalCodePatcher.Avalonia.csproj | 26 ++
UniversalCodePatcher.Avalonia/app.manifest | 18 +
UniversalCodePatcher.sln | 42 ++-
docs/avalonia_reference.md | 32 ++
10 files changed, 574 insertions(+), 21 deletions(-)
create mode 100644 UniversalCodePatcher.Avalonia/App.axaml
create mode 100644 UniversalCodePatcher.Avalonia/App.axaml.cs
create mode 100644 UniversalCodePatcher.Avalonia/MainWindow.axaml
create mode 100644 UniversalCodePatcher.Avalonia/MainWindow.axaml.cs
create mode 100644 UniversalCodePatcher.Avalonia/Program.cs
create mode 100644 UniversalCodePatcher.Avalonia/UniversalCodePatcher.Avalonia.csproj
create mode 100644 UniversalCodePatcher.Avalonia/app.manifest
create mode 100644 docs/avalonia_reference.md
diff --git a/README.md b/README.md
index 72089ca..b2abcda 100644
--- a/README.md
+++ b/README.md
@@ -8,7 +8,8 @@ Intelligent multi-language code patcher with modular architecture.
- **Semantic Code Analysis**: Advanced AST-based parsing (not regex!)
- **Multiple Languages**: JavaScript, TypeScript, C# support
- **Diff Engine**: Create and apply unified diffs without Git dependency
-- **Visual Interface**: Professional WinForms GUI
+- **Visual Interface**: Professional WinForms GUI
+- **Cross Platform UI**: Reference Avalonia version for Linux
- **Backup System**: Automatic backups before patching
## Modules
@@ -29,8 +30,12 @@ Intelligent multi-language code patcher with modular architecture.
## Building
1. Open UniversalCodePatcher.sln in Visual Studio
-2. Build solution (Ctrl+Shift+B)
-3. Run (F5)
+2. Build solution (Ctrl+Shift+B)
+3. Run (F5)
+4. Alternatively run the Avalonia UI with:
+ ```bash
+ dotnet run --project UniversalCodePatcher.Avalonia
+ ```
## Usage
diff --git a/UniversalCodePatcher.Avalonia/App.axaml b/UniversalCodePatcher.Avalonia/App.axaml
new file mode 100644
index 0000000..2189954
--- /dev/null
+++ b/UniversalCodePatcher.Avalonia/App.axaml
@@ -0,0 +1,10 @@
+
+
+
+
+
+
+
diff --git a/UniversalCodePatcher.Avalonia/App.axaml.cs b/UniversalCodePatcher.Avalonia/App.axaml.cs
new file mode 100644
index 0000000..9a898fa
--- /dev/null
+++ b/UniversalCodePatcher.Avalonia/App.axaml.cs
@@ -0,0 +1,23 @@
+using Avalonia;
+using Avalonia.Controls.ApplicationLifetimes;
+using Avalonia.Markup.Xaml;
+
+namespace UniversalCodePatcher.Avalonia;
+
+public partial class App : Application
+{
+ public override void Initialize()
+ {
+ AvaloniaXamlLoader.Load(this);
+ }
+
+ public override void OnFrameworkInitializationCompleted()
+ {
+ if (ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktop)
+ {
+ desktop.MainWindow = new MainWindow();
+ }
+
+ base.OnFrameworkInitializationCompleted();
+ }
+}
diff --git a/UniversalCodePatcher.Avalonia/MainWindow.axaml b/UniversalCodePatcher.Avalonia/MainWindow.axaml
new file mode 100644
index 0000000..8b76f77
--- /dev/null
+++ b/UniversalCodePatcher.Avalonia/MainWindow.axaml
@@ -0,0 +1,80 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/UniversalCodePatcher.Avalonia/MainWindow.axaml.cs b/UniversalCodePatcher.Avalonia/MainWindow.axaml.cs
new file mode 100644
index 0000000..b930beb
--- /dev/null
+++ b/UniversalCodePatcher.Avalonia/MainWindow.axaml.cs
@@ -0,0 +1,332 @@
+using Avalonia.Controls;
+using Avalonia.Controls.ApplicationLifetimes;
+using Avalonia.Interactivity;
+using Avalonia.Platform.Storage;
+using Avalonia;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.IO;
+using System.Linq;
+using System.Text.Json;
+using System;
+using Avalonia.VisualTree;
+using Avalonia.Layout;
+
+namespace UniversalCodePatcher.Avalonia;
+
+public partial class MainWindow : Window
+{
+ private string? _projectPath;
+ private bool _showHiddenFiles;
+ private bool _isDirty;
+ private readonly List _recentProjects = new();
+ private const int MaxRecent = 5;
+
+ private string RecentFile => Path.Combine(
+ Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData),
+ "UniversalCodePatcher", "recent.txt");
+
+ public MainWindow()
+ {
+ InitializeComponent();
+ LoadRecentProjects();
+ SourceBox.PropertyChanged += (_, e) =>
+ {
+ if (e.Property == TextBox.TextProperty)
+ _isDirty = true;
+ };
+ }
+
+ private async void OnNewProject(object? sender, RoutedEventArgs e)
+ {
+ var picker = TopLevel.GetTopLevel(this)?.StorageProvider;
+ if (picker == null)
+ return;
+ var folder = await picker.OpenFolderPickerAsync(new FolderPickerOpenOptions());
+ var path = folder.Count > 0 ? folder[0].Path.LocalPath : null;
+ if (path != null)
+ {
+ _projectPath = path;
+ LoadProject(path);
+ AddRecentProject(path);
+ _isDirty = false;
+ }
+ }
+
+ private void OnOpenProject(object? sender, RoutedEventArgs e)
+ {
+ OnNewProject(sender, e);
+ }
+
+ private void AddRecentProject(string path)
+ {
+ Directory.CreateDirectory(Path.GetDirectoryName(RecentFile)!);
+ _recentProjects.Remove(path);
+ _recentProjects.Insert(0, path);
+ if (_recentProjects.Count > MaxRecent)
+ _recentProjects.RemoveAt(_recentProjects.Count - 1);
+ File.WriteAllLines(RecentFile, _recentProjects);
+ PopulateRecentMenu();
+ }
+
+ private void LoadRecentProjects()
+ {
+ if (File.Exists(RecentFile))
+ _recentProjects.AddRange(File.ReadAllLines(RecentFile));
+ PopulateRecentMenu();
+ }
+
+ private void PopulateRecentMenu()
+ {
+ if (this.FindControl