diff --git a/MetaforceInstaller.Core/Defaults.cs b/MetaforceInstaller.Core/Defaults.cs
deleted file mode 100644
index ec22aad..0000000
--- a/MetaforceInstaller.Core/Defaults.cs
+++ /dev/null
@@ -1,7 +0,0 @@
-namespace MetaforceInstaller.Core;
-
-public static class Defaults
-{
- public static readonly string StoragePath =
- Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData) + Path.DirectorySeparatorChar + "MetaforceInstaller";
-}
\ No newline at end of file
diff --git a/MetaforceInstaller.Core/Intefaces/IStorageService.cs b/MetaforceInstaller.Core/Intefaces/IStorageService.cs
deleted file mode 100644
index 5967309..0000000
--- a/MetaforceInstaller.Core/Intefaces/IStorageService.cs
+++ /dev/null
@@ -1,9 +0,0 @@
-using MetaforceInstaller.Core.Models;
-
-namespace MetaforceInstaller.Core.Intefaces;
-
-public interface IStorageService
-{
- AppData Load();
- void Save(AppData data);
-}
\ No newline at end of file
diff --git a/MetaforceInstaller.Core/MetaforceInstaller.Core.csproj b/MetaforceInstaller.Core/MetaforceInstaller.Core.csproj
index 0b0eeda..0a85bfc 100644
--- a/MetaforceInstaller.Core/MetaforceInstaller.Core.csproj
+++ b/MetaforceInstaller.Core/MetaforceInstaller.Core.csproj
@@ -7,26 +7,20 @@
-
-
- PreserveNewest
- AdbWinApi.dll
-
-
- PreserveNewest
- AdbWinUsbApi.dll
-
+
+
+
-
-
-
-
-
+
+
+
+
+
-
-
+
+
diff --git a/MetaforceInstaller.Core/Models/AppData.cs b/MetaforceInstaller.Core/Models/AppData.cs
deleted file mode 100644
index 5c37871..0000000
--- a/MetaforceInstaller.Core/Models/AppData.cs
+++ /dev/null
@@ -1,6 +0,0 @@
-namespace MetaforceInstaller.Core.Models;
-
-public class AppData
-{
- public List Installations { get; set; } = new();
-}
\ No newline at end of file
diff --git a/MetaforceInstaller.Core/Models/InstallationData.cs b/MetaforceInstaller.Core/Models/InstallationData.cs
deleted file mode 100644
index 6f53baa..0000000
--- a/MetaforceInstaller.Core/Models/InstallationData.cs
+++ /dev/null
@@ -1,9 +0,0 @@
-namespace MetaforceInstaller.Core.Models;
-
-public class InstallationData
-{
- public Guid Id { get; set; } = Guid.NewGuid();
- public required string Title { get; set; }
- public required InstallationParts Parts { get; set; }
- public DateTime InstalledAt { get; set; } = DateTime.Now;
-}
\ No newline at end of file
diff --git a/MetaforceInstaller.Core/Models/InstallationParts.cs b/MetaforceInstaller.Core/Models/InstallationParts.cs
deleted file mode 100644
index 62acb62..0000000
--- a/MetaforceInstaller.Core/Models/InstallationParts.cs
+++ /dev/null
@@ -1,12 +0,0 @@
-namespace MetaforceInstaller.Core.Models;
-
-public class InstallationParts
-{
- public string? OculusClientPath { get; init; }
- public string? PicoClientPath { get; init; }
- public string? AndroidAdminPath { get; init; }
- public string? AndroidContentPath { get; init; }
- public string? WindowsContentPath { get; init; }
- public string? WindowsAdminPath { get; init; }
- public string? WindowsServerPath { get; init; }
-}
\ No newline at end of file
diff --git a/MetaforceInstaller.Core/Services/AdbService.cs b/MetaforceInstaller.Core/Services/AdbService.cs
index 07ca0ed..ddf790f 100644
--- a/MetaforceInstaller.Core/Services/AdbService.cs
+++ b/MetaforceInstaller.Core/Services/AdbService.cs
@@ -15,15 +15,9 @@ public class AdbService : IAdbService
private readonly ILogger _logger;
private readonly AdbClient _adbClient;
private DeviceData _deviceData;
- private DeviceMonitor? _deviceMonitor;
public event EventHandler? ProgressChanged;
public event EventHandler? StatusChanged;
- public EventHandler? DeviceConnected;
- public EventHandler? DeviceDisconnected;
- public EventHandler? DeviceChanged;
-
- public bool IsDeviceConnected => _deviceData != null && _deviceData.State == DeviceState.Online;
public AdbService(ILogger? logger = null)
{
@@ -33,46 +27,6 @@ public class AdbService : IAdbService
var serverStatus = server.StartServer(adbPath, restartServerIfNewer: false);
_adbClient = new AdbClient();
RefreshDeviceData();
- StartDeviceMonitoring();
- }
-
- private void StartDeviceMonitoring()
- {
- try
- {
- _deviceMonitor = new DeviceMonitor(new AdbSocket(_adbClient.EndPoint));
- _deviceMonitor.DeviceConnected += OnDeviceConnected;
- _deviceMonitor.DeviceDisconnected += OnDeviceDisconnected;
- _deviceMonitor.DeviceChanged += OnDeviceChanged;
- _deviceMonitor.Start();
-
- _logger.LogInformation("Device monitoring started");
- }
- catch (Exception ex)
- {
- _logger.LogError($"Failed to start device monitoring: {ex.Message}");
- }
- }
-
- private void OnDeviceConnected(object? sender, DeviceDataEventArgs e)
- {
- _logger.LogInformation($"Device conn: {e.Device.Serial}");
- RefreshDeviceData();
- DeviceConnected?.Invoke(this, e);
- }
-
- private void OnDeviceDisconnected(object? sender, DeviceDataEventArgs e)
- {
- _logger.LogInformation($"Device disconnected: {e.Device.Serial}");
- RefreshDeviceData();
- DeviceDisconnected?.Invoke(this, e);
- }
-
- private void OnDeviceChanged(object? sender, DeviceDataEventArgs e)
- {
- _logger.LogInformation($"Device changed: {e.Device.Serial}");
- RefreshDeviceData();
- DeviceChanged?.Invoke(this, e);
}
public void RefreshDeviceData()
@@ -209,7 +163,7 @@ public class AdbService : IAdbService
() => { _adbClient.ExecuteRemoteCommand($"mkdir -p \"{remoteDir}\"", _deviceData, reciever); },
cancellationToken);
}
-
+
_logger.LogInformation($"Ensured remote directory: {remoteDir}");
await Task.Run(() =>
@@ -249,15 +203,4 @@ public class AdbService : IAdbService
{
return new DeviceInfo(_deviceData.Serial, _deviceData.State.ToString(), _deviceData.Model, _deviceData.Name);
}
-
- public void Dispose()
- {
- if (_deviceMonitor != null)
- {
- _deviceMonitor.DeviceConnected -= OnDeviceConnected;
- _deviceMonitor.DeviceDisconnected -= OnDeviceDisconnected;
- _deviceMonitor.DeviceChanged -= OnDeviceChanged;
- _deviceMonitor.Dispose();
- }
- }
}
\ No newline at end of file
diff --git a/MetaforceInstaller.Core/Services/StorageService.cs b/MetaforceInstaller.Core/Services/StorageService.cs
deleted file mode 100644
index 4ab4ffa..0000000
--- a/MetaforceInstaller.Core/Services/StorageService.cs
+++ /dev/null
@@ -1,35 +0,0 @@
-using System.Text.Json;
-using MetaforceInstaller.Core.Intefaces;
-using MetaforceInstaller.Core.Models;
-
-namespace MetaforceInstaller.Core.Services;
-
-public class StorageService : IStorageService
-{
- private readonly string _storagePath;
-
- public StorageService()
- {
- var appDirectory = Defaults.StoragePath;
- Directory.CreateDirectory(appDirectory);
- _storagePath = Path.Combine(appDirectory, "installations.json");
- }
-
- public AppData Load()
- {
- if (!File.Exists(_storagePath))
- return new AppData();
-
- var json = File.ReadAllText(_storagePath);
- return JsonSerializer.Deserialize(json) ?? new AppData();
- }
-
- public void Save(AppData data)
- {
- var json = JsonSerializer.Serialize(data, new JsonSerializerOptions
- {
- WriteIndented = true
- });
- File.WriteAllText(_storagePath, json);
- }
-}
\ No newline at end of file
diff --git a/MetaforceInstaller.Core/Services/ZipScrapper.cs b/MetaforceInstaller.Core/Services/ZipScrapper.cs
deleted file mode 100644
index b5c4122..0000000
--- a/MetaforceInstaller.Core/Services/ZipScrapper.cs
+++ /dev/null
@@ -1,160 +0,0 @@
-using System.IO.Compression;
-using MetaforceInstaller.Core.Models;
-
-namespace MetaforceInstaller.Core.Services;
-
-public class ZipScrapper
-{
- public static InstallationParts PeekFiles(ZipArchive archive)
- {
- return new InstallationParts
- {
- AndroidContentPath = FindAndroidContent(archive),
- OculusClientPath = FindOculusClient(archive),
- PicoClientPath = FindPicoClient(archive),
- AndroidAdminPath = FindAndroidAdmin(archive),
- WindowsAdminPath = FindPcAdmin(archive),
- WindowsContentPath = FindWindowsContent(archive),
- WindowsServerPath = FindServer(archive),
- };
- }
-
- ///
- /// Extracts ZIP archive to a unique folder based on installation GUID
- ///
- /// ZIP archive to extract
- /// Base storage path
- /// Unique GUID for this installation
- /// Progress reporter
- /// Full path to the extracted folder
- public static string ExtractZip(
- ZipArchive archive,
- string baseOutputPath,
- Guid installationGuid,
- IProgress? progress = null)
- {
- // Create unique folder for this installation
- var installationFolder = Path.Combine(baseOutputPath, installationGuid.ToString());
- Directory.CreateDirectory(installationFolder);
-
- var entries = archive.Entries.Where(e => !string.IsNullOrEmpty(e.Name)).ToList();
- var totalEntries = entries.Count;
- var processedEntries = 0;
-
- foreach (var entry in entries)
- {
- var destinationPath = Path.Combine(installationFolder, entry.FullName);
- var destinationDir = Path.GetDirectoryName(destinationPath);
-
- if (!string.IsNullOrEmpty(destinationDir))
- {
- Directory.CreateDirectory(destinationDir);
- }
-
- entry.ExtractToFile(destinationPath, overwrite: true);
-
- processedEntries++;
- progress?.Report((double)processedEntries / totalEntries * 100);
- }
-
- return installationFolder;
- }
-
- ///
- /// Updates InstallationParts paths to reflect the actual extracted location
- ///
- public static InstallationParts UpdatePathsAfterExtraction(
- InstallationParts parts,
- string extractedFolderPath)
- {
- return new InstallationParts
- {
- AndroidContentPath = UpdatePath(parts.AndroidContentPath, extractedFolderPath),
- OculusClientPath = UpdatePath(parts.OculusClientPath, extractedFolderPath),
- PicoClientPath = UpdatePath(parts.PicoClientPath, extractedFolderPath),
- AndroidAdminPath = UpdatePath(parts.AndroidAdminPath, extractedFolderPath),
- WindowsAdminPath = UpdatePath(parts.WindowsAdminPath, extractedFolderPath),
- WindowsContentPath = UpdatePath(parts.WindowsContentPath, extractedFolderPath),
- WindowsServerPath = UpdatePath(parts.WindowsServerPath, extractedFolderPath),
- };
- }
-
- private static string? UpdatePath(string? relativePath, string basePath)
- {
- if (string.IsNullOrEmpty(relativePath))
- return null;
-
- return Path.Combine(basePath, relativePath);
- }
-
- private static string? FindPicoClient(ZipArchive archive)
- {
- return FindEntry(archive,
- name: "MetaforcePico",
- extension: ".apk");
- }
-
- private static string? FindOculusClient(ZipArchive archive)
- {
- return FindEntry(archive,
- name: "MetaforceOculus",
- extension: ".apk");
- }
-
- private static string? FindAndroidAdmin(ZipArchive archive)
- {
- return FindEntry(archive,
- name: "MetaforceAdmin",
- extension: ".apk");
- }
-
- private static string? FindAndroidContent(ZipArchive archive)
- {
- return FindEntry(archive,
- name: "Content_Android",
- extension: ".zip");
- }
-
- private static string? FindWindowsContent(ZipArchive archive)
- {
- return FindEntry(archive,
- name: "Content_StandaloneWindows",
- extension: ".zip");
- }
-
- private static string? FindPcAdmin(ZipArchive archive)
- {
- return FindExecutable(archive, "MetaforceAdminPC");
- }
-
- private static string? FindServer(ZipArchive archive)
- {
- return FindExecutable(archive, "MetaforceServer");
- }
-
- ///
- /// Finds an entry in archive by name and extension
- ///
- private static string? FindEntry(ZipArchive archive, string name, string extension)
- {
- var entry = archive.Entries.FirstOrDefault(e =>
- e.Name.Contains(name, StringComparison.OrdinalIgnoreCase) &&
- e.Name.EndsWith(extension, StringComparison.OrdinalIgnoreCase));
-
- return entry?.FullName;
- }
-
- ///
- /// Finds an executable in archive, excluding crash handlers
- ///
- private static string? FindExecutable(ZipArchive archive, string containsName)
- {
- var entry = archive.Entries.FirstOrDefault(e =>
- e.FullName.Contains(containsName, StringComparison.OrdinalIgnoreCase) &&
- e.Name.EndsWith(".exe", StringComparison.OrdinalIgnoreCase) &&
- !e.Name.Contains("UnityCrashHandler", StringComparison.OrdinalIgnoreCase) &&
- !e.Name.Contains("crashpad_handler", StringComparison.OrdinalIgnoreCase));
-
- return entry?.FullName;
- }
-}
\ No newline at end of file
diff --git a/MetaforceInstaller.UI/App.axaml.cs b/MetaforceInstaller.UI/App.axaml.cs
index 38eec17..16212ac 100644
--- a/MetaforceInstaller.UI/App.axaml.cs
+++ b/MetaforceInstaller.UI/App.axaml.cs
@@ -1,7 +1,6 @@
using Avalonia;
using Avalonia.Controls.ApplicationLifetimes;
using Avalonia.Markup.Xaml;
-using MetaforceInstaller.UI.Windows;
namespace MetaforceInstaller.UI;
@@ -14,7 +13,6 @@ public partial class App : Application
public override void OnFrameworkInitializationCompleted()
{
- Lang.Resources.Culture = System.Globalization.CultureInfo.CurrentCulture;
if (ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktop)
{
desktop.MainWindow = new MainWindow();
diff --git a/MetaforceInstaller.UI/Lang/Resources.Designer.cs b/MetaforceInstaller.UI/Lang/Resources.Designer.cs
deleted file mode 100644
index a61e233..0000000
--- a/MetaforceInstaller.UI/Lang/Resources.Designer.cs
+++ /dev/null
@@ -1,251 +0,0 @@
-//------------------------------------------------------------------------------
-//
-// This code was generated by a tool.
-//
-// Changes to this file may cause incorrect behavior and will be lost if
-// the code is regenerated.
-//
-//------------------------------------------------------------------------------
-
-namespace MetaforceInstaller.UI.Lang {
- using System;
-
-
- ///
- /// A strongly-typed resource class, for looking up localized strings, etc.
- ///
- // This class was auto-generated by the StronglyTypedResourceBuilder
- // class via a tool like ResGen or Visual Studio.
- // To add or remove a member, edit your .ResX file then rerun ResGen
- // with the /str option, or rebuild your VS project.
- [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")]
- [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
- [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
- public class Resources {
-
- private static global::System.Resources.ResourceManager resourceMan;
-
- private static global::System.Globalization.CultureInfo resourceCulture;
-
- [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
- internal Resources() {
- }
-
- ///
- /// Returns the cached ResourceManager instance used by this class.
- ///
- [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
- public static global::System.Resources.ResourceManager ResourceManager {
- get {
- if (object.ReferenceEquals(resourceMan, null)) {
- global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("MetaforceInstaller.UI.Lang.Resources", typeof(Resources).Assembly);
- resourceMan = temp;
- }
- return resourceMan;
- }
- }
-
- ///
- /// Overrides the current thread's CurrentUICulture property for all
- /// resource lookups using this strongly typed resource class.
- ///
- [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
- public static global::System.Globalization.CultureInfo Culture {
- get {
- return resourceCulture;
- }
- set {
- resourceCulture = value;
- }
- }
-
- ///
- /// Looks up a localized string similar to Add new installation.
- ///
- public static string AddInstallation {
- get {
- return ResourceManager.GetString("AddInstallation", resourceCulture);
- }
- }
-
- ///
- /// Looks up a localized string similar to Cancel.
- ///
- public static string CancelButton {
- get {
- return ResourceManager.GetString("CancelButton", resourceCulture);
- }
- }
-
- ///
- /// Looks up a localized string similar to Choose .zip.
- ///
- public static string ChooseZip {
- get {
- return ResourceManager.GetString("ChooseZip", resourceCulture);
- }
- }
-
- ///
- /// Looks up a localized string similar to Connected to.
- ///
- public static string ConnectedTo {
- get {
- return ResourceManager.GetString("ConnectedTo", resourceCulture);
- }
- }
-
- ///
- /// Looks up a localized string similar to Delete.
- ///
- public static string Delete {
- get {
- return ResourceManager.GetString("Delete", resourceCulture);
- }
- }
-
- ///
- /// Looks up a localized string similar to Install admin.
- ///
- public static string InstallAdminCheckbox {
- get {
- return ResourceManager.GetString("InstallAdminCheckbox", resourceCulture);
- }
- }
-
- ///
- /// Looks up a localized string similar to Install Android admin.
- ///
- public static string InstallAndroidAdmin {
- get {
- return ResourceManager.GetString("InstallAndroidAdmin", resourceCulture);
- }
- }
-
- ///
- /// Looks up a localized string similar to Install.
- ///
- public static string InstallButton {
- get {
- return ResourceManager.GetString("InstallButton", resourceCulture);
- }
- }
-
- ///
- /// Looks up a localized string similar to Install server.
- ///
- public static string InstallServerCheckbox {
- get {
- return ResourceManager.GetString("InstallServerCheckbox", resourceCulture);
- }
- }
-
- ///
- /// Looks up a localized string similar to Install VR client.
- ///
- public static string InstallVRClient {
- get {
- return ResourceManager.GetString("InstallVRClient", resourceCulture);
- }
- }
-
- ///
- /// Looks up a localized string similar to Launch PC admin.
- ///
- public static string LaunchPCAdmin {
- get {
- return ResourceManager.GetString("LaunchPCAdmin", resourceCulture);
- }
- }
-
- ///
- /// Looks up a localized string similar to Launch server.
- ///
- public static string LaunchServer {
- get {
- return ResourceManager.GetString("LaunchServer", resourceCulture);
- }
- }
-
- ///
- /// Looks up a localized string similar to Name of new installation.
- ///
- public static string NameOfNewInstallation {
- get {
- return ResourceManager.GetString("NameOfNewInstallation", resourceCulture);
- }
- }
-
- ///
- /// Looks up a localized string similar to Couldn't find Android content.
- ///
- public static string NoAndroidContentError {
- get {
- return ResourceManager.GetString("NoAndroidContentError", resourceCulture);
- }
- }
-
- ///
- /// Looks up a localized string similar to Couldn't find directory with PC admin.
- ///
- public static string NoPCAdminError {
- get {
- return ResourceManager.GetString("NoPCAdminError", resourceCulture);
- }
- }
-
- ///
- /// Looks up a localized string similar to Couldn't find directory with server.
- ///
- public static string NoServerError {
- get {
- return ResourceManager.GetString("NoServerError", resourceCulture);
- }
- }
-
- ///
- /// Looks up a localized string similar to Not connected.
- ///
- public static string NotConnected {
- get {
- return ResourceManager.GetString("NotConnected", resourceCulture);
- }
- }
-
- ///
- /// Looks up a localized string similar to Couldn't find any VR clients.
- ///
- public static string NoVRClientsError {
- get {
- return ResourceManager.GetString("NoVRClientsError", resourceCulture);
- }
- }
-
- ///
- /// Looks up a localized string similar to Couldn't find Windows content.
- ///
- public static string NoWindowsContentError {
- get {
- return ResourceManager.GetString("NoWindowsContentError", resourceCulture);
- }
- }
-
- ///
- /// Looks up a localized string similar to Save Android admin.
- ///
- public static string SaveAndroidAdminCheckbox {
- get {
- return ResourceManager.GetString("SaveAndroidAdminCheckbox", resourceCulture);
- }
- }
-
- ///
- /// Looks up a localized string similar to Save VR client.
- ///
- public static string SaveVRClientCheckbox {
- get {
- return ResourceManager.GetString("SaveVRClientCheckbox", resourceCulture);
- }
- }
- }
-}
diff --git a/MetaforceInstaller.UI/Lang/Resources.resx b/MetaforceInstaller.UI/Lang/Resources.resx
deleted file mode 100644
index c641fa3..0000000
--- a/MetaforceInstaller.UI/Lang/Resources.resx
+++ /dev/null
@@ -1,84 +0,0 @@
-
-
-
-
-
-
-
-
-
- text/microsoft-resx
-
-
- 1.3
-
-
- System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
-
-
- System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
-
-
- Launch server
-
-
- Launch PC admin
-
-
- Install VR client
-
-
- Install Android admin
-
-
- Delete
-
-
- Add new installation
-
-
- Not connected
-
-
- Connected to
-
-
- Name of new installation
-
-
- Choose .zip
-
-
- Install server
-
-
- Install admin
-
-
- Save Android admin
-
-
- Save VR client
-
-
- Install
-
-
- Cancel
-
-
- Couldn't find directory with server
-
-
- Couldn't find directory with PC admin
-
-
- Couldn't find Windows content
-
-
- Couldn't find Android content
-
-
- Couldn't find any VR clients
-
-
\ No newline at end of file
diff --git a/MetaforceInstaller.UI/Lang/Resources.ru.resx b/MetaforceInstaller.UI/Lang/Resources.ru.resx
deleted file mode 100644
index 891e8d9..0000000
--- a/MetaforceInstaller.UI/Lang/Resources.ru.resx
+++ /dev/null
@@ -1,77 +0,0 @@
-
-
- text/microsoft-resx
-
-
- 1.3
-
-
- System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
-
-
- System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
-
-
- Запустить сервер
-
-
- Запустить админку
-
-
- Удалить
-
-
- Установить андроид-админку
-
-
- Установить на шлем
-
-
- Добавить версию
-
-
- Подключено:
-
-
- Не подключено
-
-
- Выбрать .zip
-
-
- Отмена
-
-
- Установить админку
-
-
- Установить
-
-
- Установить сервер
-
-
- Название версии
-
-
- Сохранить андроид-админку
-
-
- Сохранить VR-клиенты
-
-
- Не удалось обнаружить Андроид контент
-
-
- Не удалось обнаружить ПК-админку
-
-
- Не удалось обнаружить сервер
-
-
- Не удалось обнаружить VR-клиенты
-
-
- Не удалось обнаружить Windows контент
-
-
\ No newline at end of file
diff --git a/MetaforceInstaller.UI/MainWindow.axaml b/MetaforceInstaller.UI/MainWindow.axaml
new file mode 100644
index 0000000..61a426d
--- /dev/null
+++ b/MetaforceInstaller.UI/MainWindow.axaml
@@ -0,0 +1,70 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/MetaforceInstaller.UI/MainWindow.axaml.cs b/MetaforceInstaller.UI/MainWindow.axaml.cs
new file mode 100644
index 0000000..d6a49e1
--- /dev/null
+++ b/MetaforceInstaller.UI/MainWindow.axaml.cs
@@ -0,0 +1,230 @@
+using System;
+using System.IO;
+using System.Threading.Tasks;
+using Avalonia.Controls;
+using Avalonia.Interactivity;
+using Avalonia.Platform.Storage;
+using Avalonia.Threading;
+using Avalonia.VisualTree;
+using MetaforceInstaller.Core.Models;
+using MetaforceInstaller.Core.Services;
+
+namespace MetaforceInstaller.UI;
+
+public partial class MainWindow : Window
+{
+ private string? _apkPath;
+ private string? _zipPath;
+ private AdbService _adbService;
+
+ private const int PROGRESS_LOG_STEP = 10;
+ private const int PROGRESS_UPDATE_STEP = 1;
+
+ private int _lastLoggedProgress = -1;
+ private int _lastUpdatedProgress = -1;
+
+ public MainWindow()
+ {
+ InitializeComponent();
+
+ LogMessage("MetaforceInstaller by slavagm");
+
+ _adbService = new AdbService();
+ _adbService.ProgressChanged += OnAdbProgressChanged;
+ _adbService.StatusChanged += OnAdbStatusChanged;
+
+ CheckAndEnableInstallButton();
+
+ ChooseApkButton.Click += OnChooseApkClicked;
+ ChooseContentButton.Click += OnChooseContentClicked;
+ InstallButton.Click += OnInstallClicked;
+ }
+
+ private void OnAdbProgressChanged(object? sender, ProgressInfo e)
+ {
+ Dispatcher.UIThread.InvokeAsync(() =>
+ {
+ if (e.PercentageComplete != _lastUpdatedProgress &&
+ e.PercentageComplete % PROGRESS_UPDATE_STEP == 0)
+ {
+ InstallProgressBar.Value = e.PercentageComplete;
+ _lastUpdatedProgress = e.PercentageComplete;
+ }
+
+ if (e.PercentageComplete != _lastLoggedProgress &&
+ e.PercentageComplete % PROGRESS_LOG_STEP == 0 || e.PercentageComplete == 100)
+ {
+ LogMessage(
+ e.TotalBytes > 0
+ ? $"Прогресс: {e.PercentageComplete}% ({FormatBytes(e.BytesTransferred)} / {FormatBytes(e.TotalBytes)})"
+ : $"Прогресс: {e.PercentageComplete}%");
+
+ _lastLoggedProgress = e.PercentageComplete;
+ }
+ });
+ }
+
+ private void OnProgressReport(ProgressInfo progressInfo)
+ {
+ Dispatcher.UIThread.InvokeAsync(() =>
+ {
+ if (progressInfo.PercentageComplete != _lastUpdatedProgress &&
+ progressInfo.PercentageComplete % PROGRESS_UPDATE_STEP == 0)
+ {
+ InstallProgressBar.Value = progressInfo.PercentageComplete;
+ _lastUpdatedProgress = progressInfo.PercentageComplete;
+ }
+
+
+ if (progressInfo.PercentageComplete != _lastLoggedProgress &&
+ (progressInfo.PercentageComplete % PROGRESS_LOG_STEP == 0 || progressInfo.PercentageComplete == 100))
+ {
+ LogMessage(
+ progressInfo.TotalBytes > 0
+ ? $"Прогресс: {progressInfo.PercentageComplete}% ({FormatBytes(progressInfo.BytesTransferred)} / {FormatBytes(progressInfo.TotalBytes)})"
+ : $"Прогресс: {progressInfo.PercentageComplete}%");
+
+ _lastLoggedProgress = progressInfo.PercentageComplete;
+ }
+ });
+ }
+
+ private void OnAdbStatusChanged(object? sender, string e)
+ {
+ Dispatcher.UIThread.InvokeAsync(() =>
+ {
+ InstallProgressBar.Value = 0;
+ _lastLoggedProgress = -1;
+ _lastUpdatedProgress = -1;
+ LogMessage(e);
+ });
+ }
+
+ private string FormatBytes(long bytes)
+ {
+ string[] suffixes = ["B", "KB", "MB", "GB", "TB"];
+ var counter = 0;
+ double number = bytes;
+
+ while (Math.Round(number / 1024) >= 1)
+ {
+ number /= 1024;
+ counter++;
+ }
+
+ return $"{number:N1} {suffixes[counter]}";
+ }
+
+
+ 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;
+ }
+
+ _adbService.RefreshDeviceData();
+
+ InstallButton.IsEnabled = false;
+ InstallProgressBar.Value = 0;
+
+ try
+ {
+ LogMessage("Начинаем установку...");
+
+ var deviceInfo = _adbService.GetDeviceInfo();
+ LogMessage($"Найдено устройство: {deviceInfo.SerialNumber}");
+ LogMessage($"Состояние: {deviceInfo.State}");
+ LogMessage($"Модель: {deviceInfo.Model} - {deviceInfo.Name}");
+
+ var progress = new Progress(OnProgressReport);
+
+ await _adbService.InstallApkAsync(_apkPath, progress);
+
+ var apkInfo = ApkScrapper.GetApkInfo(_apkPath);
+ LogMessage($"Ставим {apkInfo.PackageName} версии {apkInfo.VersionName}");
+ var zipName = Path.GetFileName(_zipPath);
+ var outputPath =
+ @$"/storage/emulated/0/Android/data/{apkInfo.PackageName}/files/{zipName}";
+ LogMessage($"Начинаем копирование контента в {outputPath}");
+
+ await _adbService.CopyFileAsync(_zipPath, outputPath, progress);
+
+ 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();
+ }
+}
\ No newline at end of file
diff --git a/MetaforceInstaller.UI/MetaforceInstaller.UI.csproj b/MetaforceInstaller.UI/MetaforceInstaller.UI.csproj
index 3a83cb5..26ffaf3 100644
--- a/MetaforceInstaller.UI/MetaforceInstaller.UI.csproj
+++ b/MetaforceInstaller.UI/MetaforceInstaller.UI.csproj
@@ -8,7 +8,7 @@
true
app.manifest
true
- 2.0.0-b1
+ 1.2.1
@@ -34,19 +34,4 @@
-
-
- PublicResXFileCodeGenerator
- Resources.Designer.cs
-
-
-
-
-
- True
- True
- Resources.resx
-
-
-
diff --git a/MetaforceInstaller.UI/ViewModels/MainWindowViewModel.cs b/MetaforceInstaller.UI/ViewModels/MainWindowViewModel.cs
deleted file mode 100644
index 22c0005..0000000
--- a/MetaforceInstaller.UI/ViewModels/MainWindowViewModel.cs
+++ /dev/null
@@ -1,65 +0,0 @@
-using System.Collections.Generic;
-using System.Collections.ObjectModel;
-using System.ComponentModel;
-using System.Runtime.CompilerServices;
-using Avalonia.Media;
-using MetaforceInstaller.Core.Models;
-
-namespace MetaforceInstaller.UI.ViewModels;
-
-public class MainWindowViewModel : INotifyPropertyChanged
-{
- public event PropertyChangedEventHandler? PropertyChanged;
-
- public ObservableCollection Installations { get; set; } = new();
-
- private bool _isDeviceConnected;
-
- public bool IsDeviceConnected
- {
- get => _isDeviceConnected;
- set
- {
- if (_isDeviceConnected != value)
- {
- _isDeviceConnected = value;
- OnPropertyChanged();
- OnPropertyChanged(nameof(StatusColor));
- OnPropertyChanged(nameof(StatusText));
- }
- }
- }
-
- private string _deviceSerial = string.Empty;
-
- public string DeviceSerial
- {
- get => _deviceSerial;
- set
- {
- if (_deviceSerial != value)
- {
- _deviceSerial = value;
- OnPropertyChanged();
- OnPropertyChanged(nameof(StatusText));
- }
- }
- }
-
- public IBrush StatusColor => IsDeviceConnected ? Brushes.Green : Brushes.Red;
- public string StatusText => IsDeviceConnected ? $"{Lang.Resources.ConnectedTo} {_deviceSerial}" : Lang.Resources.NotConnected;
-
- public void LoadInstallations(IEnumerable data)
- {
- Installations.Clear();
- foreach (var installation in data)
- {
- Installations.Add(installation);
- }
- }
-
- protected virtual void OnPropertyChanged([CallerMemberName] string? propertyName = null)
- {
- PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
- }
-}
\ No newline at end of file
diff --git a/MetaforceInstaller.UI/Windows/MainWindow.axaml b/MetaforceInstaller.UI/Windows/MainWindow.axaml
deleted file mode 100644
index e7d4655..0000000
--- a/MetaforceInstaller.UI/Windows/MainWindow.axaml
+++ /dev/null
@@ -1,89 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/MetaforceInstaller.UI/Windows/MainWindow.axaml.cs b/MetaforceInstaller.UI/Windows/MainWindow.axaml.cs
deleted file mode 100644
index 8ab161b..0000000
--- a/MetaforceInstaller.UI/Windows/MainWindow.axaml.cs
+++ /dev/null
@@ -1,150 +0,0 @@
-using System;
-using System.Diagnostics;
-using System.Reflection;
-using AdvancedSharpAdbClient.Models;
-using Avalonia.Controls;
-using Avalonia.Interactivity;
-using Avalonia.Threading;
-using MetaforceInstaller.Core.Intefaces;
-using MetaforceInstaller.Core.Models;
-using MetaforceInstaller.Core.Services;
-using MetaforceInstaller.UI.ViewModels;
-
-namespace MetaforceInstaller.UI.Windows;
-
-public partial class MainWindow : Window
-{
- private MainWindowViewModel _viewModel;
- private IStorageService _storageService;
- private AdbService _adbService;
-
- public MainWindow()
- {
- InitializeComponent();
-
- _viewModel = new MainWindowViewModel();
- _storageService = new StorageService();
- _adbService = new AdbService();
-
- DataContext = _viewModel;
-
- VersionLabel.Content = Assembly.GetExecutingAssembly()
- .GetCustomAttribute()?.Version;
-
- NewInstallationButton.Click += OnNewInstalltionClick;
-
- _adbService.DeviceConnected += OnAdbDeviceConnected;
- _adbService.DeviceDisconnected += OnAdbDeviceDisconnected;
- _adbService.DeviceChanged += OnAdbDeviceChanged;
-
- LoadInstallations();
- UpdateDeviceStatus();
- }
-
- private void UpdateDeviceStatus()
- {
- var isConnected = _adbService.IsDeviceConnected;
- _viewModel.IsDeviceConnected = isConnected;
-
- if (isConnected)
- {
- try
- {
- var deviceInfo = _adbService.GetDeviceInfo();
- _viewModel.DeviceSerial = deviceInfo.SerialNumber;
- }
- catch
- {
- _viewModel.DeviceSerial = "Unknown";
- }
- }
- else
- {
- _viewModel.DeviceSerial = string.Empty;
- }
- }
-
- private void OnAdbDeviceConnected(object? sender, DeviceDataEventArgs e)
- {
- Dispatcher.UIThread.Post(() =>
- {
- UpdateDeviceStatus();
- });
- }
-
- private void OnAdbDeviceDisconnected(object? sender, DeviceDataEventArgs e)
- {
- Dispatcher.UIThread.Post(() =>
- {
- UpdateDeviceStatus();
- });
- }
-
- private void OnAdbDeviceChanged(object? sender, DeviceDataEventArgs e)
- {
- Dispatcher.UIThread.Post(() =>
- {
- UpdateDeviceStatus();
- });
- }
-
- private void LoadInstallations()
- {
- var appData = _storageService.Load();
- _viewModel.LoadInstallations(appData.Installations);
- }
-
- public async void OnNewInstalltionClick(object? sender, RoutedEventArgs e)
- {
- var newInstallationDialog = new NewInstallationDialog(_storageService);
- await newInstallationDialog.ShowDialog(this);
- LoadInstallations();
- }
-
- public async void OnDeleteInstallationClick(object? sender, RoutedEventArgs e)
- {
- if (sender is Button button && button.DataContext is InstallationData installationData)
- {
- var name = installationData.Title;
- Console.WriteLine($"Delete {name}");
- }
- }
-
- public async void OnLaunchServerClick(object? sender, RoutedEventArgs e)
- {
- if (sender is Button button && button.DataContext is InstallationData installationData)
- {
- var exePath = installationData.Parts.WindowsServerPath;
- var processInfo = new ProcessStartInfo
- {
- FileName = exePath,
- UseShellExecute = false,
- };
- Process.Start(processInfo);
- }
- }
-
- public async void OnLaunchAdminClick(object? sender, RoutedEventArgs e)
- {
- if (sender is Button button && button.DataContext is InstallationData installationData)
- {
- var exePath = installationData.Parts.WindowsAdminPath;
- var processInfo = new ProcessStartInfo
- {
- FileName = exePath,
- UseShellExecute = false,
- };
- Process.Start(processInfo);
- }
- }
-
- protected override void OnClosed(EventArgs e)
- {
- _adbService.DeviceConnected -= OnAdbDeviceConnected;
- _adbService.DeviceDisconnected -= OnAdbDeviceDisconnected;
- _adbService.DeviceChanged -= OnAdbDeviceChanged;
- _adbService.Dispose();
-
- base.OnClosed(e);
- }
-}
\ No newline at end of file
diff --git a/MetaforceInstaller.UI/Windows/NewInstallationDialog.axaml b/MetaforceInstaller.UI/Windows/NewInstallationDialog.axaml
deleted file mode 100644
index d9a410a..0000000
--- a/MetaforceInstaller.UI/Windows/NewInstallationDialog.axaml
+++ /dev/null
@@ -1,28 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/MetaforceInstaller.UI/Windows/NewInstallationDialog.axaml.cs b/MetaforceInstaller.UI/Windows/NewInstallationDialog.axaml.cs
deleted file mode 100644
index da8b7a1..0000000
--- a/MetaforceInstaller.UI/Windows/NewInstallationDialog.axaml.cs
+++ /dev/null
@@ -1,164 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.IO;
-using System.IO.Compression;
-using System.Linq;
-using System.Threading.Tasks;
-using Avalonia.Controls;
-using Avalonia.Interactivity;
-using Avalonia.Platform.Storage;
-using MetaforceInstaller.Core;
-using MetaforceInstaller.Core.Intefaces;
-using MetaforceInstaller.Core.Models;
-using MetaforceInstaller.Core.Services;
-
-namespace MetaforceInstaller.UI.Windows;
-
-public partial class NewInstallationDialog : Window
-{
- private string? _zipPath;
- private InstallationParts? _installationParts;
- private readonly IStorageService _storageService;
-
- public NewInstallationDialog(IStorageService storageService)
- {
- InitializeComponent();
-
- _storageService = storageService;
-
- RefreshCheckboxes();
- CancelButton.Click += OnCancelClick;
- ChooseZip.Click += OnChooseZipClick;
- InstallButton.IsEnabled = false;
- InstallButton.Click += OnInstallClick;
- }
-
- private void RefreshCheckboxes()
- {
- var serverCheckbox = ServerCheckBox;
- var pcAdminCheckbox = PcAdminCheckBox;
- var androidAdminCheckbox = AndroidAdminCheckbox;
- var vrClientCheckbox = VrClientCheckbox;
- serverCheckbox.Content = Lang.Resources.InstallServerCheckbox;
- serverCheckbox.IsEnabled = true;
- pcAdminCheckbox.Content = Lang.Resources.InstallAdminCheckbox;
- pcAdminCheckbox.IsEnabled = true;
- androidAdminCheckbox.Content = Lang.Resources.SaveAndroidAdminCheckbox;
- androidAdminCheckbox.IsEnabled = true;
- vrClientCheckbox.Content = Lang.Resources.SaveVRClientCheckbox;
- vrClientCheckbox.IsEnabled = true;
- }
-
- private async void OnChooseZipClick(object? sender, RoutedEventArgs e)
- {
- var topLevel = GetTopLevel(this);
- var files = await topLevel!.StorageProvider.OpenFilePickerAsync(new FilePickerOpenOptions
- {
- Title = "Выберите архив с контентом",
- AllowMultiple = false,
- FileTypeFilter =
- [
- new FilePickerFileType("ZIP Files")
- {
- Patterns = ["*.zip"]
- }
- ]
- });
-
- if (files.Count >= 1)
- {
- _zipPath = files[0].Path.LocalPath;
- using var archive = ZipFile.OpenRead(_zipPath);
- _installationParts = ZipScrapper.PeekFiles(archive);
- UpdateCheckboxes();
- archive.Dispose();
- }
- }
-
- private async void OnInstallClick(object? sender, RoutedEventArgs e)
- {
- using var archive = ZipFile.OpenRead(_zipPath);
- var title = TitleTextBox.Text ?? Path.GetFileNameWithoutExtension(_zipPath);
- var installationGuid = Guid.NewGuid();
-
- var progress = new Progress(value => { ProgressBar.Value = value; });
-
- string extractedPath = null;
- await Task.Run(() =>
- {
- extractedPath = ZipScrapper.ExtractZip(
- archive,
- Defaults.StoragePath,
- installationGuid,
- progress);
- });
-
- InstallButton.IsEnabled = false;
-
- var appData = _storageService.Load();
-
- var updatedParts = ZipScrapper.UpdatePathsAfterExtraction(_installationParts, extractedPath);
-
- var installationData = new InstallationData
- {
- Id = installationGuid,
- Title = title,
- Parts = updatedParts
- };
-
- appData.Installations.Add(installationData);
- _storageService.Save(appData);
- Close();
- }
-
- private void UpdateCheckboxes()
- {
- RefreshCheckboxes();
- var serverCheckbox = ServerCheckBox;
- var pcAdminCheckbox = PcAdminCheckBox;
- var androidAdminCheckbox = AndroidAdminCheckbox;
- var vrClientCheckbox = VrClientCheckbox;
-
-
- if (string.IsNullOrEmpty(_installationParts.WindowsServerPath))
- {
- serverCheckbox.IsEnabled = false;
- serverCheckbox.Content += $"\n{Lang.Resources.NoServerError}";
- }
-
- if (string.IsNullOrEmpty(_installationParts.WindowsAdminPath))
- {
- pcAdminCheckbox.IsEnabled = false;
- pcAdminCheckbox.Content += $"\n{Lang.Resources.NoPCAdminError}";
- }
-
- if (string.IsNullOrEmpty(_installationParts.WindowsContentPath))
- {
- pcAdminCheckbox.IsEnabled = false;
- pcAdminCheckbox.Content += $"\n{Lang.Resources.NoWindowsContentError}";
- }
-
- if (string.IsNullOrEmpty(_installationParts.AndroidContentPath))
- {
- vrClientCheckbox.IsEnabled = false;
- vrClientCheckbox.Content += $"\n{Lang.Resources.NoAndroidContentError}";
- androidAdminCheckbox.IsEnabled = false;
- androidAdminCheckbox.Content += $"\n{Lang.Resources.NoAndroidContentError}";
- }
-
- if (string.IsNullOrEmpty(_installationParts.PicoClientPath) &&
- string.IsNullOrEmpty(_installationParts.OculusClientPath))
- {
- vrClientCheckbox.IsEnabled = false;
- vrClientCheckbox.Content += $"\n{Lang.Resources.NoVRClientsError}";
- }
-
- InstallButton.IsEnabled = new List
- { serverCheckbox, pcAdminCheckbox, androidAdminCheckbox, vrClientCheckbox }.Any(x => x?.IsEnabled == true);
- }
-
- private void OnCancelClick(object? sender, RoutedEventArgs e)
- {
- Close();
- }
-}
\ No newline at end of file