diff --git a/MetaforceInstaller.Cli/MetaforceInstaller.Cli.csproj b/MetaforceInstaller.Cli/MetaforceInstaller.Cli.csproj deleted file mode 100644 index a267acc..0000000 --- a/MetaforceInstaller.Cli/MetaforceInstaller.Cli.csproj +++ /dev/null @@ -1,24 +0,0 @@ - - - - Exe - net8.0 - enable - true - true - enable - - - - - - - - - - - - - - - diff --git a/MetaforceInstaller.Cli/Program.cs b/MetaforceInstaller.Cli/Program.cs deleted file mode 100644 index bf8bf51..0000000 --- a/MetaforceInstaller.Cli/Program.cs +++ /dev/null @@ -1,133 +0,0 @@ -using MetaforceInstaller.Cli.Utils; -using MetaforceInstaller.Core.Services; - -namespace MetaforceInstaller.Cli; - -static class Program -{ - static async Task Main(string[] args) - { - try - { - var installationRequest = ArgumentParser.ParseArguments(args); - - if (installationRequest is null || - string.IsNullOrEmpty(installationRequest.ApkPath) || - string.IsNullOrEmpty(installationRequest.ZipPath)) - { - ShowUsage(); - return; - } - - var adbService = new AdbService(); - - var apkInfo = ApkScrapper.GetApkInfo(installationRequest.ApkPath); - var zipName = Path.GetFileName(installationRequest.ZipPath); - var outputPath = - @$"/storage/emulated/0/Android/data/{apkInfo.PackageName}/files/{zipName}"; - - // Подписка на события прогресса - adbService.ProgressChanged += OnProgressChanged; - adbService.StatusChanged += OnStatusChanged; - - // Получение информации об устройстве - var deviceInfo = adbService.GetDeviceInfo(); - Console.WriteLine($"Найдено устройство: {deviceInfo.SerialNumber}"); - Console.WriteLine($"Состояние: {deviceInfo.State}"); - Console.WriteLine($"Модель: {deviceInfo.Model} - {deviceInfo.Name}"); - Console.WriteLine(); - - // Создание объекта для отслеживания прогресса - var progress = new Progress(OnProgressReport); - - // Установка APK - await adbService.InstallApkAsync(installationRequest.ApkPath, progress); - Console.WriteLine(); - - // Копирование файла - await adbService.CopyFileAsync(installationRequest.ZipPath, outputPath, progress); - Console.WriteLine(); - - Console.WriteLine("Операция завершена успешно!"); - } - catch (Exception ex) - { - Console.WriteLine($"Ошибка: {ex.Message}"); - } - } - - private static void OnProgressChanged(object? sender, MetaforceInstaller.Core.Models.ProgressInfo e) - { - DrawProgressBar(e.PercentageComplete, e.BytesTransferred, e.TotalBytes); - } - - private static void OnStatusChanged(object? sender, string e) - { - Console.WriteLine(e); - } - - private static void OnProgressReport(MetaforceInstaller.Core.Models.ProgressInfo progressInfo) - { - if (progressInfo.TotalBytes > 0) - { - DrawProgressBar(progressInfo.PercentageComplete, progressInfo.BytesTransferred, progressInfo.TotalBytes); - } - else - { - // Для случаев без информации о байтах (например, установка APK) - DrawProgressBar(progressInfo.PercentageComplete, 0, 100); - } - } - - static void ShowUsage() - { - Console.WriteLine("Использование:"); - Console.WriteLine( - " MetaforceInstaller.exe --apk <путь_к_apk> --content <путь_к_zip> --output <путь_для контента>"); - Console.WriteLine(" MetaforceInstaller.exe -a <путь_к_apk> -c <путь_к_zip> -o <путь_для_контента>"); - Console.WriteLine(); - Console.WriteLine("Параметры:"); - Console.WriteLine(" --apk, -a Путь к APK файлу"); - Console.WriteLine(" --content, -c Путь к ZIP файлу с контентом"); - Console.WriteLine(" --output, -o Путь для копирования контента"); - Console.WriteLine(" --help, -h Показать эту справку"); - Console.WriteLine(); - Console.WriteLine("Пример:"); - Console.WriteLine( - " MetaforceInstaller.exe --apk \"C:\\app.apk\" --content \"C:\\data.zip\" --output \"/sdcard/data.zip\""); - Console.WriteLine(" MetaforceInstaller.exe -a app.apk -c data.zip -o /sdcard/data.zip"); - } - - private static void DrawProgressBar(int progress, long receivedBytes, long totalBytes) - { - Console.SetCursorPosition(0, Console.CursorTop); - - var barLength = 40; - var filledLength = (int)(barLength * progress / 100.0); - - var bar = "[" + new string('█', filledLength) + new string('░', barLength - filledLength) + "]"; - - string bytesText = ""; - if (totalBytes > 0) - { - bytesText = $" {FormatBytes(receivedBytes)} / {FormatBytes(totalBytes)}"; - } - - Console.Write($"\r{bar} {progress}%{bytesText}"); - } - - private static 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]}"; - } -} \ No newline at end of file diff --git a/MetaforceInstaller.Cli/Utils/ArgumentParser.cs b/MetaforceInstaller.Cli/Utils/ArgumentParser.cs deleted file mode 100644 index ffdb561..0000000 --- a/MetaforceInstaller.Cli/Utils/ArgumentParser.cs +++ /dev/null @@ -1,53 +0,0 @@ -using MetaforceInstaller.Core.Models; - -namespace MetaforceInstaller.Cli.Utils; - -public static class ArgumentParser -{ - public static InstallationRequest? ParseArguments(string[] args) - { - var result = new InstallationRequest(); - - for (var i = 0; i < args.Length; i++) - { - switch (args[i].ToLower()) - { - case "--apk": - case "-a": - if (i + 1 < args.Length) - { - result.ApkPath = args[i + 1]; - i++; - } - - break; - - case "--content": - case "-c": - if (i + 1 < args.Length) - { - result.ZipPath = args[i + 1]; - i++; - } - - break; - - case "--output": - case "-o": - if (i + 1 < args.Length) - { - result.OutputPath = args[i + 1]; - i++; - } - - break; - - case "--help": - case "-h": - return null; - } - } - - return result; - } -} \ No newline at end of file diff --git a/MetaforceInstaller.Cloud/ICloudService.cs b/MetaforceInstaller.Cloud/ICloudService.cs new file mode 100644 index 0000000..a179bba --- /dev/null +++ b/MetaforceInstaller.Cloud/ICloudService.cs @@ -0,0 +1,8 @@ +using MetaforceInstaller.Cloud.Models; + +namespace MetaforceInstaller.Cloud; + +public interface ICloudService +{ + Task> GetObjects(string webLink); +} \ No newline at end of file diff --git a/MetaforceInstaller.Cloud/Implementations/MailRu/DTO/CloudObjectResponse.cs b/MetaforceInstaller.Cloud/Implementations/MailRu/DTO/CloudObjectResponse.cs new file mode 100644 index 0000000..7f2bdb3 --- /dev/null +++ b/MetaforceInstaller.Cloud/Implementations/MailRu/DTO/CloudObjectResponse.cs @@ -0,0 +1,181 @@ +using System.Text.Json; +using System.Text.Json.Serialization; + +namespace MetaforceInstaller.Cloud.Implementations.MailRu.DTO; + +public sealed class CloudObjectsResponse +{ + [JsonPropertyName("count")] + public CountInfo? Count { get; init; } + + [JsonPropertyName("name")] + public string? Name { get; init; } + + [JsonPropertyName("weblink")] + public string? WebLink { get; init; } + + [JsonPropertyName("size")] + public long? Size { get; init; } + + [JsonPropertyName("rev")] + public long? Rev { get; init; } + + [JsonPropertyName("kind")] + public string? Kind { get; init; } + + [JsonPropertyName("type")] + public string? Type { get; init; } + + [JsonPropertyName("public")] + public PublicInfo? Public { get; init; } + + [JsonPropertyName("list")] + public List? List { get; init; } + + [JsonPropertyName("owner")] + public OwnerInfo? Owner { get; init; } +} + +public sealed class CountInfo +{ + [JsonPropertyName("folders")] + public int? Folders { get; init; } + + [JsonPropertyName("files")] + public int? Files { get; init; } +} + +public sealed class PublicInfo +{ + [JsonPropertyName("type")] + public string? Type { get; init; } + + [JsonPropertyName("name")] + public string? Name { get; init; } + + [JsonPropertyName("id")] + public string? Id { get; init; } + + [JsonPropertyName("ctime")] + public long? CTime { get; init; } + + [JsonPropertyName("views")] + public long? Views { get; init; } + + [JsonPropertyName("downloads")] + public long? Downloads { get; init; } +} + +public sealed class OwnerInfo +{ + [JsonPropertyName("email")] + public string? Email { get; init; } + + [JsonPropertyName("user_flags")] + public UserFlags? UserFlags { get; init; } +} + +public sealed class UserFlags +{ + [JsonPropertyName("PAID_ACCOUNT")] + public bool? PaidAccount { get; init; } +} + +/// +/// Базовый тип элемента из "list". Конкретный тип выбирается по полю "type". +/// +[JsonConverter(typeof(CloudObjectJsonConverter))] +public abstract class CloudObjectBase +{ + [JsonPropertyName("name")] + public string? Name { get; init; } + + [JsonPropertyName("weblink")] + public string? WebLink { get; init; } + + [JsonPropertyName("size")] + public long? Size { get; init; } + + [JsonPropertyName("kind")] + public string? Kind { get; init; } + + [JsonPropertyName("type")] + public string? Type { get; init; } +} + +public sealed class CloudFolderObject : CloudObjectBase +{ + [JsonPropertyName("count")] + public CountInfo? Count { get; init; } + + [JsonPropertyName("rev")] + public long? Rev { get; init; } +} + +public sealed class CloudFileObject : CloudObjectBase +{ + [JsonPropertyName("mtime")] + public long? MTime { get; init; } + + [JsonPropertyName("hash")] + public string? Hash { get; init; } +} + +public sealed class ZipWebLinkRequest +{ + [JsonPropertyName("x-email")] + public string XEmail { get; init; } + + [JsonPropertyName("weblink_list")] + public IReadOnlyList WeblinkList { get; init; } + + [JsonPropertyName("name")] + public string Name { get; init; } +} + +public sealed class ZipWebLinkResponse +{ + [JsonPropertyName("key")] + public string Key { get; init; } +} + +/// +/// Конвертер, который смотрит на поле "type" и десериализует в CloudFolderObject или CloudFileObject. +/// +public sealed class CloudObjectJsonConverter : JsonConverter +{ + public override CloudObjectBase Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) + { + using var doc = JsonDocument.ParseValue(ref reader); + + var root = doc.RootElement; + if (!root.TryGetProperty("type", out var typeProp)) + throw new JsonException("Missing required property 'type' for cloud object."); + + var type = typeProp.GetString(); + + return type switch + { + "folder" => root.Deserialize(options) + ?? throw new JsonException("Failed to deserialize folder object."), + "file" => root.Deserialize(options) + ?? throw new JsonException("Failed to deserialize file object."), + _ => throw new JsonException($"Unknown cloud object type '{type}'.") + }; + } + + public override void Write(Utf8JsonWriter writer, CloudObjectBase value, JsonSerializerOptions options) + { + switch (value) + { + case CloudFolderObject folder: + JsonSerializer.Serialize(writer, folder, options); + break; + case CloudFileObject file: + JsonSerializer.Serialize(writer, file, options); + break; + default: + throw new JsonException($"Unknown runtime type '{value.GetType().Name}'."); + } + } +} \ No newline at end of file diff --git a/MetaforceInstaller.Cloud/Implementations/MailRu/MailRuCloudService.cs b/MetaforceInstaller.Cloud/Implementations/MailRu/MailRuCloudService.cs new file mode 100644 index 0000000..d7ae0ca --- /dev/null +++ b/MetaforceInstaller.Cloud/Implementations/MailRu/MailRuCloudService.cs @@ -0,0 +1,116 @@ +using System.Text; +using System.Text.Json; +using System.Web; +using MetaforceInstaller.Cloud.Implementations.MailRu.DTO; +using MetaforceInstaller.Cloud.Models; + +namespace MetaforceInstaller.Cloud.Implementations.MailRu; + +public class MailRuCloudService : ICloudService +{ + private const string BaseUrl = "https://cloud.mail.ru"; + + private static readonly JsonSerializerOptions JsonOptions = new() + { + PropertyNameCaseInsensitive = true + }; + + private readonly HttpClient _httpClient; + + public MailRuCloudService(HttpClient httpClient) + { + _httpClient = httpClient; + } + + public async Task> GetObjects(string webLink) + { + var dto = await GetFromPublicApi( + path: "/api/v4/public/list", + query: new Dictionary + { + ["weblink"] = webLink, + ["sort"] = "name", + ["order"] = "asc", + ["offset"] = "0", + ["limit"] = "500", + ["version"] = "4" + }).ConfigureAwait(false); + + if (dto?.List is null || dto.List.Count == 0) + return []; + + var result = new List(dto.List.Count); + foreach (var entry in dto.List) + result.Add(Map(entry)); + + return result; + } + + public async Task GetDownloadLink(IEnumerable webLinks, string outputFileName = "archive") + { + var result = await PostToPublicApi( + path: "/api/v3/zip/weblink", + query: new Dictionary(), + new ZipWebLinkRequest + { + XEmail = "anonym", + WeblinkList = webLinks.ToList(), + Name = outputFileName + } + ); + + return result?.Key; + } + + private async Task GetFromPublicApi(string path, IReadOnlyDictionary query) + { + var uri = BuildUri(path, query); + + using var response = await _httpClient.GetAsync(uri).ConfigureAwait(false); + response.EnsureSuccessStatusCode(); + + var json = await response.Content.ReadAsStringAsync().ConfigureAwait(false); + return JsonSerializer.Deserialize(json, JsonOptions); + } + + private async Task PostToPublicApi(string path, IReadOnlyDictionary query, + object body) + { + var uri = BuildUri(path, query); + + var jsonBody = JsonSerializer.Serialize(body, JsonOptions); + using var content = new StringContent(jsonBody, Encoding.UTF8, "application/json"); + + using var response = await _httpClient.PostAsync(uri, content).ConfigureAwait(false); + response.EnsureSuccessStatusCode(); + + var json = await response.Content.ReadAsStringAsync().ConfigureAwait(false); + return JsonSerializer.Deserialize(json, JsonOptions); + } + + private static Uri BuildUri(string path, IReadOnlyDictionary query) + { + var builder = new UriBuilder(BaseUrl) + { + Port = -1, + Path = path + }; + + var qs = HttpUtility.ParseQueryString(builder.Query); + foreach (var (key, value) in query) + qs[key] = value; + + builder.Query = qs.ToString(); + return builder.Uri; + } + + private static CloudObject Map(CloudObjectBase entry) + { + return new CloudObject + { + Name = entry.Name, + WebLink = entry.WebLink, + Type = entry.Type == "folder" ? CloudObjectType.Folder : CloudObjectType.File + }; + } +} \ No newline at end of file diff --git a/MetaforceInstaller.Cloud/MetaforceInstaller.Cloud.csproj b/MetaforceInstaller.Cloud/MetaforceInstaller.Cloud.csproj new file mode 100644 index 0000000..17b910f --- /dev/null +++ b/MetaforceInstaller.Cloud/MetaforceInstaller.Cloud.csproj @@ -0,0 +1,9 @@ + + + + net9.0 + enable + enable + + + diff --git a/MetaforceInstaller.Cloud/Models/CloudObject.cs b/MetaforceInstaller.Cloud/Models/CloudObject.cs new file mode 100644 index 0000000..643a9d5 --- /dev/null +++ b/MetaforceInstaller.Cloud/Models/CloudObject.cs @@ -0,0 +1,14 @@ +namespace MetaforceInstaller.Cloud.Models; + +public class CloudObject +{ + public string Name { get; set; } + public string WebLink { get; set; } + public CloudObjectType Type { get; set; } +} + +public enum CloudObjectType +{ + Folder, + File +} \ No newline at end of file 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/IAdbService.cs b/MetaforceInstaller.Core/Intefaces/IAdbService.cs deleted file mode 100644 index 444c237..0000000 --- a/MetaforceInstaller.Core/Intefaces/IAdbService.cs +++ /dev/null @@ -1,18 +0,0 @@ -using MetaforceInstaller.Core.Models; -using MetaforceInstaller.Core.Models; - -namespace MetaforceInstaller.Core.Intefaces; - -public interface IAdbService -{ - event EventHandler? ProgressChanged; - event EventHandler? StatusChanged; - - Task InstallApkAsync(string apkPath, IProgress? progress = null, CancellationToken cancellationToken = default); - Task CopyFileAsync(string localPath, string remotePath, IProgress? progress = null, CancellationToken cancellationToken = default); - DeviceInfo GetDeviceInfo(); - - // Синхронные версии для обратной совместимости - void InstallApk(string apkPath); - void CopyFile(string localPath, string remotePath); -} \ 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 deleted file mode 100644 index 0b0eeda..0000000 --- a/MetaforceInstaller.Core/MetaforceInstaller.Core.csproj +++ /dev/null @@ -1,32 +0,0 @@ - - - - net8.0 - enable - enable - - - - - - PreserveNewest - AdbWinApi.dll - - - PreserveNewest - AdbWinUsbApi.dll - - - - - - - - - - - - - - - diff --git a/MetaforceInstaller.Core/Models/ApkInfo.cs b/MetaforceInstaller.Core/Models/ApkInfo.cs deleted file mode 100644 index 9f042bf..0000000 --- a/MetaforceInstaller.Core/Models/ApkInfo.cs +++ /dev/null @@ -1,3 +0,0 @@ -namespace MetaforceInstaller.Core.Models; - -public record ApkInfo(string PackageName, string VersionName, string VersionCode); \ No newline at end of file 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/DeviceInfo.cs b/MetaforceInstaller.Core/Models/DeviceInfo.cs deleted file mode 100644 index 802cd3c..0000000 --- a/MetaforceInstaller.Core/Models/DeviceInfo.cs +++ /dev/null @@ -1,8 +0,0 @@ -namespace MetaforceInstaller.Core.Models; - -public record DeviceInfo( - string SerialNumber, - string State, - string Model, - string Name -); \ 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/Models/InstallationRequest.cs b/MetaforceInstaller.Core/Models/InstallationRequest.cs deleted file mode 100644 index c64b271..0000000 --- a/MetaforceInstaller.Core/Models/InstallationRequest.cs +++ /dev/null @@ -1,8 +0,0 @@ -namespace MetaforceInstaller.Core.Models; - -public class InstallationRequest -{ - public string ApkPath { get; set; } - public string ZipPath { get; set; } - public string OutputPath { get; set; } -} \ No newline at end of file diff --git a/MetaforceInstaller.Core/Models/ProgressInfo.cs b/MetaforceInstaller.Core/Models/ProgressInfo.cs deleted file mode 100644 index cc09a74..0000000 --- a/MetaforceInstaller.Core/Models/ProgressInfo.cs +++ /dev/null @@ -1,19 +0,0 @@ -namespace MetaforceInstaller.Core.Models; - -public class ProgressInfo -{ - public int PercentageComplete { get; set; } - public long BytesTransferred { get; set; } - public long TotalBytes { get; set; } - public string? Message { get; set; } - public string? CurrentFile { get; set; } - public ProgressType Type { get; set; } -} - -public enum ProgressType -{ - Installation, - FileCopy, - Extraction, - General -} diff --git a/MetaforceInstaller.Core/Services/AdbService.cs b/MetaforceInstaller.Core/Services/AdbService.cs deleted file mode 100644 index 07ca0ed..0000000 --- a/MetaforceInstaller.Core/Services/AdbService.cs +++ /dev/null @@ -1,263 +0,0 @@ -using System.Reflection; -using AdvancedSharpAdbClient; -using AdvancedSharpAdbClient.DeviceCommands; -using AdvancedSharpAdbClient.Models; -using AdvancedSharpAdbClient.Receivers; -using MetaforceInstaller.Core.Intefaces; -using MetaforceInstaller.Core.Models; -using Microsoft.Extensions.Logging; -using Microsoft.Extensions.Logging.Abstractions; - -namespace MetaforceInstaller.Core.Services; - -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) - { - _logger = logger ?? new NullLogger(); - var adbPath = GetAdbPath(); - var server = new AdbServer(); - 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() - { - var devices = _adbClient.GetDevices(); - _deviceData = devices.FirstOrDefault(); - } - - private void ExtractResource(string resourceName, string outputPath) - { - _logger.LogInformation($"Extracting resource: {resourceName} to {outputPath}"); - using var stream = Assembly.GetAssembly(typeof(AdbService)).GetManifestResourceStream(resourceName); - using var fileStream = File.Create(outputPath); - stream.CopyTo(fileStream); - _logger.LogInformation($"Resource extracted: {resourceName} to {outputPath}"); - } - - private string GetAdbPath() - { - var tempDir = Path.Combine(Path.GetTempPath(), "MetaforceInstaller", "adb"); - Directory.CreateDirectory(tempDir); - - var adbPath = Path.Combine(tempDir, "adb.exe"); - - if (File.Exists(adbPath)) return adbPath; - ExtractResource("MetaforceInstaller.Core.adb.adb.exe", adbPath); - ExtractResource("MetaforceInstaller.Core.adb.AdbWinApi.dll", Path.Combine(tempDir, "AdbWinApi.dll")); - ExtractResource("MetaforceInstaller.Core.adb.AdbWinUsbApi.dll", Path.Combine(tempDir, "AdbWinUsbApi.dll")); - - return adbPath; - } - - private void OnProgressChanged(ProgressInfo progressInfo) - { - ProgressChanged?.Invoke(this, progressInfo); - } - - private void OnStatusChanged(string status) - { - StatusChanged?.Invoke(this, status); - } - - public void InstallApk(string apkPath) - { - InstallApkAsync(apkPath).Wait(); - } - - public async Task InstallApkAsync(string apkPath, IProgress? progress = null, - CancellationToken cancellationToken = default) - { - try - { - if (!File.Exists(apkPath)) - { - _logger.LogCritical("Error: Could not find APK file."); - return; - } - - OnStatusChanged("Начинаем установку APK..."); - _logger.LogInformation($"Installing APK: {apkPath}"); - - progress?.Report(new ProgressInfo - { - PercentageComplete = 0, - Message = "Подготовка к установке APK...", - Type = ProgressType.Installation, - CurrentFile = Path.GetFileName(apkPath) - }); - - var packageManager = new PackageManager(_adbClient, _deviceData); - - await Task.Run(() => - { - packageManager.InstallPackage(apkPath, installProgress => - { - var progressInfo = new ProgressInfo - { - PercentageComplete = (int)installProgress.UploadProgress, - Message = $"Установка APK: {installProgress.UploadProgress:F1}%", - Type = ProgressType.Installation, - CurrentFile = Path.GetFileName(apkPath) - }; - - progress?.Report(progressInfo); - OnProgressChanged(progressInfo); - }); - }, cancellationToken); - - OnStatusChanged("APK успешно установлен!"); - _logger.LogInformation("APK successfully installed!"); - } - catch (Exception ex) - { - _logger.LogCritical($"Error: {ex.Message}"); - throw; - } - } - - public void CopyFile(string localPath, string remotePath) - { - CopyFileAsync(localPath, remotePath).Wait(); - } - - public async Task CopyFileAsync(string localPath, string remotePath, IProgress? progress = null, - CancellationToken cancellationToken = default) - { - try - { - if (!File.Exists(localPath)) - { - _logger.LogCritical($"Error: Could not find file: {localPath}"); - return; - } - - OnStatusChanged("Начинаем копирование файла..."); - _logger.LogInformation($"Copying file: {localPath} to {remotePath}"); - - var fileInfo = new FileInfo(localPath); - - progress?.Report(new ProgressInfo - { - PercentageComplete = 0, - Message = "Подготовка к копированию файла...", - Type = ProgressType.FileCopy, - CurrentFile = Path.GetFileName(localPath), - TotalBytes = fileInfo.Length - }); - - var remoteDir = Path.GetDirectoryName(remotePath)?.Replace('\\', '/'); - if (!string.IsNullOrEmpty(remoteDir)) - { - var reciever = new ConsoleOutputReceiver(); - await Task.Run( - () => { _adbClient.ExecuteRemoteCommand($"mkdir -p \"{remoteDir}\"", _deviceData, reciever); }, - cancellationToken); - } - - _logger.LogInformation($"Ensured remote directory: {remoteDir}"); - - await Task.Run(() => - { - using var fileStream = File.OpenRead(localPath); - var syncService = new SyncService(_adbClient, _deviceData); - - syncService.Push(fileStream, remotePath, UnixFileStatus.DefaultFileMode, DateTime.Now, - copyProgress => - { - var progressInfo = new ProgressInfo - { - PercentageComplete = (int)copyProgress.ProgressPercentage, - BytesTransferred = copyProgress.ReceivedBytesSize, - TotalBytes = copyProgress.TotalBytesToReceive, - Message = $"Копирование: {copyProgress.ProgressPercentage:F1}%", - Type = ProgressType.FileCopy, - CurrentFile = Path.GetFileName(localPath) - }; - - progress?.Report(progressInfo); - OnProgressChanged(progressInfo); - }); - }, cancellationToken); - - OnStatusChanged("Файл успешно скопирован!"); - _logger.LogInformation("File successfully copied!"); - } - catch (Exception ex) - { - _logger.LogCritical($"Error: {ex.Message}"); - throw; - } - } - - public DeviceInfo GetDeviceInfo() - { - 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/ApkScrapper.cs b/MetaforceInstaller.Core/Services/ApkScrapper.cs deleted file mode 100644 index c06c543..0000000 --- a/MetaforceInstaller.Core/Services/ApkScrapper.cs +++ /dev/null @@ -1,19 +0,0 @@ -using AlphaOmega.Debug; -using MetaforceInstaller.Core.Models; - -namespace MetaforceInstaller.Core.Services; - -public static class ApkScrapper -{ - public static ApkInfo GetApkInfo(string apkPath) - { - using var apk = new ApkFile(apkPath); - if (apk is { IsValid: true, AndroidManifest: not null }) - { - return new ApkInfo(apk.AndroidManifest.Package, apk.AndroidManifest.VersionName, - apk.AndroidManifest.VersionCode); - } - - throw new Exception("Invalid APK file"); - } -} \ 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.Core/adb/AdbWinApi.dll b/MetaforceInstaller.Core/adb/AdbWinApi.dll deleted file mode 100644 index 7abe26c..0000000 Binary files a/MetaforceInstaller.Core/adb/AdbWinApi.dll and /dev/null differ diff --git a/MetaforceInstaller.Core/adb/AdbWinUsbApi.dll b/MetaforceInstaller.Core/adb/AdbWinUsbApi.dll deleted file mode 100644 index e7a6de1..0000000 Binary files a/MetaforceInstaller.Core/adb/AdbWinUsbApi.dll and /dev/null differ diff --git a/MetaforceInstaller.Core/adb/adb.exe b/MetaforceInstaller.Core/adb/adb.exe deleted file mode 100644 index 85bfeaa..0000000 Binary files a/MetaforceInstaller.Core/adb/adb.exe and /dev/null differ diff --git a/MetaforceInstaller.UI/App.axaml b/MetaforceInstaller.UI/App.axaml deleted file mode 100644 index d947dd9..0000000 --- a/MetaforceInstaller.UI/App.axaml +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - \ No newline at end of file diff --git a/MetaforceInstaller.UI/App.axaml.cs b/MetaforceInstaller.UI/App.axaml.cs deleted file mode 100644 index 38eec17..0000000 --- a/MetaforceInstaller.UI/App.axaml.cs +++ /dev/null @@ -1,25 +0,0 @@ -using Avalonia; -using Avalonia.Controls.ApplicationLifetimes; -using Avalonia.Markup.Xaml; -using MetaforceInstaller.UI.Windows; - -namespace MetaforceInstaller.UI; - -public partial class App : Application -{ - public override void Initialize() - { - AvaloniaXamlLoader.Load(this); - } - - public override void OnFrameworkInitializationCompleted() - { - Lang.Resources.Culture = System.Globalization.CultureInfo.CurrentCulture; - if (ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktop) - { - desktop.MainWindow = new MainWindow(); - } - - base.OnFrameworkInitializationCompleted(); - } -} \ No newline at end of file diff --git a/MetaforceInstaller.UI/Images/logo_black.svg b/MetaforceInstaller.UI/Images/logo_black.svg deleted file mode 100644 index d41fcc9..0000000 --- a/MetaforceInstaller.UI/Images/logo_black.svg +++ /dev/null @@ -1,16 +0,0 @@ - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/MetaforceInstaller.UI/Images/logo_red.svg b/MetaforceInstaller.UI/Images/logo_red.svg deleted file mode 100644 index 1b73fdc..0000000 --- a/MetaforceInstaller.UI/Images/logo_red.svg +++ /dev/null @@ -1,31 +0,0 @@ - - - - - - - - - - - - - - - diff --git a/MetaforceInstaller.UI/Images/logo_white.svg b/MetaforceInstaller.UI/Images/logo_white.svg deleted file mode 100644 index 12ba8d1..0000000 --- a/MetaforceInstaller.UI/Images/logo_white.svg +++ /dev/null @@ -1,23 +0,0 @@ - - - - - - - - - - - - - - - - - - - \ No newline at end of file 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/MetaforceInstaller.UI.csproj b/MetaforceInstaller.UI/MetaforceInstaller.UI.csproj deleted file mode 100644 index 3a83cb5..0000000 --- a/MetaforceInstaller.UI/MetaforceInstaller.UI.csproj +++ /dev/null @@ -1,52 +0,0 @@ - - - WinExe - net8.0 - enable - true - true - true - app.manifest - true - 2.0.0-b1 - - - - - - - - - - None - All - - - - - - - - - - - - - - - - - PublicResXFileCodeGenerator - Resources.Designer.cs - - - - - - True - True - Resources.resx - - - - diff --git a/MetaforceInstaller.UI/Program.cs b/MetaforceInstaller.UI/Program.cs deleted file mode 100644 index c77ddc1..0000000 --- a/MetaforceInstaller.UI/Program.cs +++ /dev/null @@ -1,21 +0,0 @@ -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/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 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -