diff --git a/MetaforceInstaller.UI/App.axaml b/MetaforceInstaller.UI/App.axaml
new file mode 100644
index 0000000..d947dd9
--- /dev/null
+++ b/MetaforceInstaller.UI/App.axaml
@@ -0,0 +1,10 @@
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/MetaforceInstaller.UI/App.axaml.cs b/MetaforceInstaller.UI/App.axaml.cs
new file mode 100644
index 0000000..16212ac
--- /dev/null
+++ b/MetaforceInstaller.UI/App.axaml.cs
@@ -0,0 +1,23 @@
+using Avalonia;
+using Avalonia.Controls.ApplicationLifetimes;
+using Avalonia.Markup.Xaml;
+
+namespace MetaforceInstaller.UI;
+
+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();
+ }
+}
\ No newline at end of file
diff --git a/MetaforceInstaller.UI/MainWindow.axaml b/MetaforceInstaller.UI/MainWindow.axaml
new file mode 100644
index 0000000..c1e1044
--- /dev/null
+++ b/MetaforceInstaller.UI/MainWindow.axaml
@@ -0,0 +1,49 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/MetaforceInstaller.UI/MainWindow.axaml.cs b/MetaforceInstaller.UI/MainWindow.axaml.cs
new file mode 100644
index 0000000..108c1f9
--- /dev/null
+++ b/MetaforceInstaller.UI/MainWindow.axaml.cs
@@ -0,0 +1,131 @@
+using System;
+using System.IO;
+using System.Threading.Tasks;
+using Avalonia.Controls;
+using Avalonia.Interactivity;
+using Avalonia.Platform.Storage;
+using Avalonia.VisualTree;
+
+namespace MetaforceInstaller.UI;
+
+public partial class MainWindow : Window
+{
+ private string? _apkPath;
+ private string? _zipPath;
+
+ public MainWindow()
+ {
+ InitializeComponent();
+ CheckAndEnableInstallButton();
+
+ ChooseApkButton.Click += OnChooseApkClicked;
+ ChooseContentButton.Click += OnChooseContentClicked;
+ InstallButton.Click += OnInstallClicked;
+ }
+
+ private async void CheckAndEnableInstallButton()
+ {
+ InstallButton.IsEnabled = !string.IsNullOrEmpty(_apkPath) && !string.IsNullOrEmpty(_zipPath);
+ }
+
+ private async void OnChooseApkClicked(object? sender, RoutedEventArgs e)
+ {
+ var topLevel = GetTopLevel(this);
+ var files = await topLevel!.StorageProvider.OpenFilePickerAsync(new FilePickerOpenOptions
+ {
+ Title = "Выберите APK файл",
+ AllowMultiple = false,
+ FileTypeFilter = new[]
+ {
+ new FilePickerFileType("APK Files")
+ {
+ Patterns = new[] { "*.apk" }
+ }
+ }
+ });
+
+ if (files.Count >= 1)
+ {
+ _apkPath = files[0].Path.LocalPath;
+ LogMessage($"APK выбран: {Path.GetFileName(_apkPath)}");
+ }
+
+ CheckAndEnableInstallButton();
+ }
+
+ private async void OnChooseContentClicked(object? sender, RoutedEventArgs e)
+ {
+ var topLevel = GetTopLevel(this);
+ var files = await topLevel!.StorageProvider.OpenFilePickerAsync(new FilePickerOpenOptions
+ {
+ Title = "Выберите архив с контентом",
+ AllowMultiple = false,
+ FileTypeFilter = new[]
+ {
+ new FilePickerFileType("ZIP Files")
+ {
+ Patterns = new[] { "*.zip" }
+ }
+ }
+ });
+
+ if (files.Count >= 1)
+ {
+ _zipPath = files[0].Path.LocalPath;
+ LogMessage($"Контент выбран: {Path.GetFileName(_zipPath)}");
+ }
+
+ CheckAndEnableInstallButton();
+ }
+
+ private async void OnInstallClicked(object? sender, RoutedEventArgs e)
+ {
+ if (string.IsNullOrEmpty(_apkPath) || string.IsNullOrEmpty(_zipPath))
+ {
+ LogMessage("Ошибка: Выберите APK файл и папку с контентом");
+ return;
+ }
+
+ InstallButton.IsEnabled = false;
+ InstallProgressBar.Value = 0;
+
+ try
+ {
+ LogMessage("Начинаем установку...");
+
+ // Здесь будет ваша логика установки
+ await SimulateInstallation();
+
+ LogMessage("Установка завершена успешно!");
+ }
+ catch (Exception ex)
+ {
+ LogMessage($"Ошибка установки: {ex.Message}");
+ }
+ finally
+ {
+ InstallButton.IsEnabled = true;
+ InstallProgressBar.Value = 0;
+ }
+ }
+
+ private void LogMessage(string message)
+ {
+ var timestamp = DateTime.Now.ToString("HH:mm:ss");
+ LogsTextBox.Text += $"[{timestamp}] {message}\n";
+
+ // Прокручиваем к концу
+ var scrollViewer = LogsTextBox.FindAncestorOfType();
+ scrollViewer?.ScrollToEnd();
+ }
+
+ private async Task SimulateInstallation()
+ {
+ for (int i = 0; i <= 100; i += 10)
+ {
+ InstallProgressBar.Value = i;
+ LogMessage($"Прогресс: {i}%");
+ await Task.Delay(500); // Симуляция работы
+ }
+ }
+}
\ No newline at end of file
diff --git a/MetaforceInstaller.UI/MetaforceInstaller.UI.csproj b/MetaforceInstaller.UI/MetaforceInstaller.UI.csproj
new file mode 100644
index 0000000..ba515c6
--- /dev/null
+++ b/MetaforceInstaller.UI/MetaforceInstaller.UI.csproj
@@ -0,0 +1,22 @@
+
+
+ WinExe
+ net8.0
+ enable
+ true
+ app.manifest
+ true
+
+
+
+
+
+
+
+
+
+ None
+ All
+
+
+
diff --git a/MetaforceInstaller.UI/Program.cs b/MetaforceInstaller.UI/Program.cs
new file mode 100644
index 0000000..c77ddc1
--- /dev/null
+++ b/MetaforceInstaller.UI/Program.cs
@@ -0,0 +1,21 @@
+using Avalonia;
+using System;
+
+namespace MetaforceInstaller.UI;
+
+class Program
+{
+ // Initialization code. Don't use any Avalonia, third-party APIs or any
+ // SynchronizationContext-reliant code before AppMain is called: things aren't initialized
+ // yet and stuff might break.
+ [STAThread]
+ public static void Main(string[] args) => BuildAvaloniaApp()
+ .StartWithClassicDesktopLifetime(args);
+
+ // Avalonia configuration, don't remove; also used by visual designer.
+ public static AppBuilder BuildAvaloniaApp()
+ => AppBuilder.Configure()
+ .UsePlatformDetect()
+ .WithInterFont()
+ .LogToTrace();
+}
\ No newline at end of file
diff --git a/MetaforceInstaller.UI/app.manifest b/MetaforceInstaller.UI/app.manifest
new file mode 100644
index 0000000..0543ed4
--- /dev/null
+++ b/MetaforceInstaller.UI/app.manifest
@@ -0,0 +1,18 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/MetaforceInstaller.sln b/MetaforceInstaller.sln
index a2406c6..b2da3d6 100644
--- a/MetaforceInstaller.sln
+++ b/MetaforceInstaller.sln
@@ -4,6 +4,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MetaforceInstaller.Cli", "M
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MetaforceInstaller.Core", "MetaforceInstaller.Core\MetaforceInstaller.Core.csproj", "{83961B6E-21E7-4B7A-B4FA-6128A44BCE1F}"
EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MetaforceInstaller.UI", "MetaforceInstaller.UI\MetaforceInstaller.UI.csproj", "{546DDE53-4607-4852-B951-434061C46FB2}"
+EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@@ -18,5 +20,9 @@ Global
{83961B6E-21E7-4B7A-B4FA-6128A44BCE1F}.Debug|Any CPU.Build.0 = Debug|Any CPU
{83961B6E-21E7-4B7A-B4FA-6128A44BCE1F}.Release|Any CPU.ActiveCfg = Release|Any CPU
{83961B6E-21E7-4B7A-B4FA-6128A44BCE1F}.Release|Any CPU.Build.0 = Release|Any CPU
+ {546DDE53-4607-4852-B951-434061C46FB2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {546DDE53-4607-4852-B951-434061C46FB2}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {546DDE53-4607-4852-B951-434061C46FB2}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {546DDE53-4607-4852-B951-434061C46FB2}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
EndGlobal