Compare commits
3 commits
b4ce64456e
...
13a076ad79
| Author | SHA1 | Date | |
|---|---|---|---|
| 13a076ad79 | |||
| 3dc9c8c279 | |||
| c29658e7e4 |
11 changed files with 550 additions and 236 deletions
9
MetaforceInstaller.Core/Intefaces/IStorageService.cs
Normal file
9
MetaforceInstaller.Core/Intefaces/IStorageService.cs
Normal file
|
|
@ -0,0 +1,9 @@
|
||||||
|
using MetaforceInstaller.Core.Models;
|
||||||
|
|
||||||
|
namespace MetaforceInstaller.Core.Intefaces;
|
||||||
|
|
||||||
|
public interface IStorageService
|
||||||
|
{
|
||||||
|
AppData Load();
|
||||||
|
void Save(AppData data);
|
||||||
|
}
|
||||||
6
MetaforceInstaller.Core/Models/AppData.cs
Normal file
6
MetaforceInstaller.Core/Models/AppData.cs
Normal file
|
|
@ -0,0 +1,6 @@
|
||||||
|
namespace MetaforceInstaller.Core.Models;
|
||||||
|
|
||||||
|
public class AppData
|
||||||
|
{
|
||||||
|
public List<InstallationData> Installations { get; set; } = new();
|
||||||
|
}
|
||||||
10
MetaforceInstaller.Core/Models/InstallationData.cs
Normal file
10
MetaforceInstaller.Core/Models/InstallationData.cs
Normal file
|
|
@ -0,0 +1,10 @@
|
||||||
|
namespace MetaforceInstaller.Core.Models;
|
||||||
|
|
||||||
|
public class InstallationData
|
||||||
|
{
|
||||||
|
public Guid Id { get; set; } = Guid.NewGuid();
|
||||||
|
public string Title { get; set; }
|
||||||
|
public string AndroidPackagePath { get; set; }
|
||||||
|
public string WindowsServerPackagePath { get; set; }
|
||||||
|
public string WindowsAdminPackagePath { get; set; }
|
||||||
|
}
|
||||||
12
MetaforceInstaller.Core/Models/InstallationParts.cs
Normal file
12
MetaforceInstaller.Core/Models/InstallationParts.cs
Normal file
|
|
@ -0,0 +1,12 @@
|
||||||
|
namespace MetaforceInstaller.Core.Models;
|
||||||
|
|
||||||
|
public record InstallationParts
|
||||||
|
{
|
||||||
|
public bool OculusClientExists { get; init; }
|
||||||
|
public bool PicoClientExists { get; init; }
|
||||||
|
public bool AndroidAdminExists { get; init; }
|
||||||
|
public bool AndroidContentExists { get; init; }
|
||||||
|
public bool WindowsContentExists { get; init; }
|
||||||
|
public bool WindowsAdminExists { get; init; }
|
||||||
|
public bool WindowsServerExists { get; init; }
|
||||||
|
}
|
||||||
36
MetaforceInstaller.Core/Services/StorageService.cs
Normal file
36
MetaforceInstaller.Core/Services/StorageService.cs
Normal file
|
|
@ -0,0 +1,36 @@
|
||||||
|
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 appData = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData);
|
||||||
|
var appDirectory = Path.Combine(appData, "MetaforceInstaller");
|
||||||
|
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<AppData>(json) ?? new AppData();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Save(AppData data)
|
||||||
|
{
|
||||||
|
var json = JsonSerializer.Serialize(data, new JsonSerializerOptions
|
||||||
|
{
|
||||||
|
WriteIndented = true
|
||||||
|
});
|
||||||
|
File.WriteAllText(_storagePath, json);
|
||||||
|
}
|
||||||
|
}
|
||||||
89
MetaforceInstaller.Core/Services/ZipScrapper.cs
Normal file
89
MetaforceInstaller.Core/Services/ZipScrapper.cs
Normal file
|
|
@ -0,0 +1,89 @@
|
||||||
|
using System.IO.Compression;
|
||||||
|
using MetaforceInstaller.Core.Models;
|
||||||
|
|
||||||
|
namespace MetaforceInstaller.Core.Services;
|
||||||
|
|
||||||
|
public class ZipScrapper
|
||||||
|
{
|
||||||
|
public static InstallationParts PeekFiles(ZipArchive archive)
|
||||||
|
{
|
||||||
|
return new InstallationParts
|
||||||
|
{
|
||||||
|
AndroidContentExists = DoesAndroidContentExists(archive),
|
||||||
|
OculusClientExists = DoesOculusClientExists(archive),
|
||||||
|
PicoClientExists = DoesPicoClientExists(archive),
|
||||||
|
AndroidAdminExists = DoesAndroidAdminExists(archive),
|
||||||
|
WindowsAdminExists = DoesPcAdminExists(archive),
|
||||||
|
WindowsContentExists = DoesWindowsContentExists(archive),
|
||||||
|
WindowsServerExists = DoesServerExists(archive),
|
||||||
|
};
|
||||||
|
// Console.WriteLine($"Contents of {archive}:");
|
||||||
|
// Console.WriteLine("----------------------------------");
|
||||||
|
//
|
||||||
|
// foreach (ZipArchiveEntry entry in archive.Entries)
|
||||||
|
// {
|
||||||
|
// // You can access properties like entry.Name, entry.FullName, entry.Length (uncompressed size), entry.CompressedLength
|
||||||
|
// Console.WriteLine($"Entry: {entry.FullName}");
|
||||||
|
// Console.WriteLine($" Uncompressed Size: {entry.Length} bytes");
|
||||||
|
// Console.WriteLine($" Compressed Size: {entry.CompressedLength} bytes");
|
||||||
|
// Console.WriteLine("----------------------------------");
|
||||||
|
// }
|
||||||
|
}
|
||||||
|
|
||||||
|
public static string ExtractZip(ZipArchive archive, string outputPath)
|
||||||
|
{
|
||||||
|
archive.ExtractToDirectory(outputPath);
|
||||||
|
return outputPath;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static bool DoesPicoClientExists(ZipArchive archive)
|
||||||
|
{
|
||||||
|
return archive.Entries
|
||||||
|
.Any(entry => entry.Name.Contains("MetaforcePico")
|
||||||
|
&& entry.Name.EndsWith(".apk"));
|
||||||
|
}
|
||||||
|
|
||||||
|
private static bool DoesOculusClientExists(ZipArchive archive)
|
||||||
|
{
|
||||||
|
return archive.Entries
|
||||||
|
.Any(entry => entry.Name.Contains("MetaforceOculus")
|
||||||
|
&& entry.Name.EndsWith(".apk"));
|
||||||
|
}
|
||||||
|
|
||||||
|
private static bool DoesAndroidAdminExists(ZipArchive archive)
|
||||||
|
{
|
||||||
|
return archive.Entries
|
||||||
|
.Any(entry => entry.Name.Contains("MetaforceAdmin")
|
||||||
|
&& entry.Name.EndsWith(".apk"));
|
||||||
|
}
|
||||||
|
|
||||||
|
private static bool DoesAndroidContentExists(ZipArchive archive)
|
||||||
|
{
|
||||||
|
return archive.Entries
|
||||||
|
.Any(entry => entry.Name.Contains("Content_Android")
|
||||||
|
&& entry.Name.EndsWith(".zip"));
|
||||||
|
}
|
||||||
|
|
||||||
|
private static bool DoesWindowsContentExists(ZipArchive archive)
|
||||||
|
{
|
||||||
|
return archive.Entries
|
||||||
|
.Any(entry => entry.Name.Contains("Content_StandaloneWindows")
|
||||||
|
&& entry.Name.EndsWith(".zip"));
|
||||||
|
}
|
||||||
|
|
||||||
|
private static bool DoesPcAdminExists(ZipArchive archive)
|
||||||
|
{
|
||||||
|
return archive.Entries
|
||||||
|
.Any(entry => entry.FullName.Contains("MetaforceAdminPC")
|
||||||
|
&& entry.Name.EndsWith(".exe") && !entry.Name.Contains("UnityCrashHandler") &&
|
||||||
|
!entry.Name.Contains("crashpad_handler"));
|
||||||
|
}
|
||||||
|
|
||||||
|
private static bool DoesServerExists(ZipArchive archive)
|
||||||
|
{
|
||||||
|
return archive.Entries
|
||||||
|
.Any(entry => entry.FullName.Contains("MetaforceServer")
|
||||||
|
&& entry.Name.EndsWith(".exe") && !entry.Name.Contains("UnityCrashHandler") &&
|
||||||
|
!entry.Name.Contains("crashpad_handler"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -10,11 +10,11 @@
|
||||||
<ResourceDictionary>
|
<ResourceDictionary>
|
||||||
<ResourceDictionary.ThemeDictionaries>
|
<ResourceDictionary.ThemeDictionaries>
|
||||||
<ResourceDictionary x:Key="Light">
|
<ResourceDictionary x:Key="Light">
|
||||||
<SvgImage x:Key="Logo" Source="/Images/logo_red.svg"/>
|
<SvgImage x:Key="Logo" Source="/Images/logo_red.svg" />
|
||||||
</ResourceDictionary>
|
</ResourceDictionary>
|
||||||
|
|
||||||
<ResourceDictionary x:Key="Dark">
|
<ResourceDictionary x:Key="Dark">
|
||||||
<SvgImage x:Key="Logo" Source="/Images/logo_red.svg"/>
|
<SvgImage x:Key="Logo" Source="/Images/logo_red.svg" />
|
||||||
</ResourceDictionary>
|
</ResourceDictionary>
|
||||||
</ResourceDictionary.ThemeDictionaries>
|
</ResourceDictionary.ThemeDictionaries>
|
||||||
</ResourceDictionary>
|
</ResourceDictionary>
|
||||||
|
|
@ -22,49 +22,44 @@
|
||||||
|
|
||||||
<Grid>
|
<Grid>
|
||||||
<Grid.RowDefinitions>
|
<Grid.RowDefinitions>
|
||||||
|
<RowDefinition Height="96" />
|
||||||
<RowDefinition Height="*" />
|
<RowDefinition Height="*" />
|
||||||
<RowDefinition Height="Auto" />
|
|
||||||
</Grid.RowDefinitions>
|
</Grid.RowDefinitions>
|
||||||
|
|
||||||
<!-- Main Content Area -->
|
<Image Grid.Row="0"
|
||||||
<Grid Grid.Row="0" Margin="8">
|
Margin="20"
|
||||||
<Grid.ColumnDefinitions>
|
VerticalAlignment="Center"
|
||||||
<ColumnDefinition Width="3*" /> <!-- 30% -->
|
Source="{DynamicResource Logo}"
|
||||||
<ColumnDefinition Width="7*" /> <!-- 70% -->
|
HorizontalAlignment="Left">
|
||||||
</Grid.ColumnDefinitions>
|
</Image>
|
||||||
|
|
||||||
<!-- Left Panel - Buttons -->
|
<Button Grid.Row="0" Name="NewInstallationButton" Margin="20" VerticalAlignment="Center"
|
||||||
<StackPanel Grid.Column="0" Margin="20" Spacing="15">
|
HorizontalAlignment="Right">
|
||||||
<Button Name="ChooseApkButton" Content="Choose .apk"
|
+ Add new installation
|
||||||
HorizontalAlignment="Stretch" />
|
</Button>
|
||||||
|
|
||||||
<Button Name="ChooseContentButton" Content="Choose .zip"
|
<ScrollViewer Grid.Row="1">
|
||||||
HorizontalAlignment="Stretch" />
|
<StackPanel Margin="10">
|
||||||
|
<Expander Header="Item 1" Margin="0,5" HorizontalAlignment="Stretch">
|
||||||
|
<TextBlock Text="Content for item 1" Margin="10" />
|
||||||
|
</Expander>
|
||||||
|
|
||||||
<Button Name="InstallButton" Content="Install"
|
<Expander Header="Item 2" Margin="0,5" HorizontalAlignment="Stretch">
|
||||||
HorizontalAlignment="Stretch" />
|
<TextBlock Text="Content for item 2" Margin="10" />
|
||||||
|
</Expander>
|
||||||
|
|
||||||
|
<Expander Header="Item 3" Margin="0,5" HorizontalAlignment="Stretch">
|
||||||
|
<TextBlock Text="Content for item 3" Margin="10" />
|
||||||
|
</Expander>
|
||||||
|
|
||||||
|
<Expander Header="Item 4" Margin="0,5" HorizontalAlignment="Stretch">
|
||||||
|
<TextBlock Text="Content for item 4" Margin="10" />
|
||||||
|
</Expander>
|
||||||
|
|
||||||
|
<Expander Header="Item 5" Margin="0,5" HorizontalAlignment="Stretch">
|
||||||
|
<TextBlock Text="Content for item 5" Margin="10" />
|
||||||
|
</Expander>
|
||||||
</StackPanel>
|
</StackPanel>
|
||||||
|
</ScrollViewer>
|
||||||
<Image Grid.Column="0"
|
|
||||||
Margin="20"
|
|
||||||
VerticalAlignment="Bottom"
|
|
||||||
Source="{DynamicResource Logo}"
|
|
||||||
HorizontalAlignment="Center">
|
|
||||||
</Image>
|
|
||||||
|
|
||||||
<!-- Right Panel - Logs -->
|
|
||||||
<TextBox Grid.Column="1" Name="LogsTextBox"
|
|
||||||
IsReadOnly="True"
|
|
||||||
AcceptsReturn="True"
|
|
||||||
TextWrapping="Wrap"
|
|
||||||
FontFamily="Consolas,Courier New,monospace"
|
|
||||||
Focusable="False"
|
|
||||||
Margin="4,0,0,0" />
|
|
||||||
</Grid>
|
|
||||||
|
|
||||||
<!-- Progress Bar at Bottom -->
|
|
||||||
<ProgressBar Grid.Row="1" Name="InstallProgressBar"
|
|
||||||
Height="20" Minimum="0" Maximum="100" Value="0"
|
|
||||||
Margin="8" />
|
|
||||||
</Grid>
|
</Grid>
|
||||||
</Window>
|
</Window>
|
||||||
|
|
@ -26,205 +26,211 @@ public partial class MainWindow : Window
|
||||||
public MainWindow()
|
public MainWindow()
|
||||||
{
|
{
|
||||||
InitializeComponent();
|
InitializeComponent();
|
||||||
|
NewInstallationButton.Click += OnNewInstalltionClick;
|
||||||
LogMessage("MetaforceInstaller by slavagm");
|
// LogMessage("MetaforceInstaller by slavagm");
|
||||||
|
//
|
||||||
_adbService = new AdbService();
|
// _adbService = new AdbService();
|
||||||
_adbService.ProgressChanged += OnAdbProgressChanged;
|
// _adbService.ProgressChanged += OnAdbProgressChanged;
|
||||||
_adbService.StatusChanged += OnAdbStatusChanged;
|
// _adbService.StatusChanged += OnAdbStatusChanged;
|
||||||
|
//
|
||||||
CheckAndEnableInstallButton();
|
// CheckAndEnableInstallButton();
|
||||||
|
//
|
||||||
ChooseApkButton.Click += OnChooseApkClicked;
|
// ChooseApkButton.Click += OnChooseApkClicked;
|
||||||
ChooseContentButton.Click += OnChooseContentClicked;
|
// ChooseContentButton.Click += OnChooseContentClicked;
|
||||||
InstallButton.Click += OnInstallClicked;
|
// InstallButton.Click += OnInstallClicked;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnAdbProgressChanged(object? sender, ProgressInfo e)
|
public async void OnNewInstalltionClick(object? sender, RoutedEventArgs e)
|
||||||
{
|
{
|
||||||
Dispatcher.UIThread.InvokeAsync(() =>
|
var newInstallationDialog = new NewInstallationDialog();
|
||||||
{
|
await newInstallationDialog.ShowDialog<NewInstallationDialog>(this);
|
||||||
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)
|
// private void OnAdbProgressChanged(object? sender, ProgressInfo e)
|
||||||
{
|
// {
|
||||||
Dispatcher.UIThread.InvokeAsync(() =>
|
// Dispatcher.UIThread.InvokeAsync(() =>
|
||||||
{
|
// {
|
||||||
if (progressInfo.PercentageComplete != _lastUpdatedProgress &&
|
// if (e.PercentageComplete != _lastUpdatedProgress &&
|
||||||
progressInfo.PercentageComplete % PROGRESS_UPDATE_STEP == 0)
|
// e.PercentageComplete % PROGRESS_UPDATE_STEP == 0)
|
||||||
{
|
// {
|
||||||
InstallProgressBar.Value = progressInfo.PercentageComplete;
|
// InstallProgressBar.Value = e.PercentageComplete;
|
||||||
_lastUpdatedProgress = progressInfo.PercentageComplete;
|
// _lastUpdatedProgress = e.PercentageComplete;
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
|
// if (e.PercentageComplete != _lastLoggedProgress &&
|
||||||
if (progressInfo.PercentageComplete != _lastLoggedProgress &&
|
// e.PercentageComplete % PROGRESS_LOG_STEP == 0 || e.PercentageComplete == 100)
|
||||||
(progressInfo.PercentageComplete % PROGRESS_LOG_STEP == 0 || progressInfo.PercentageComplete == 100))
|
// {
|
||||||
{
|
// LogMessage(
|
||||||
LogMessage(
|
// e.TotalBytes > 0
|
||||||
progressInfo.TotalBytes > 0
|
// ? $"Прогресс: {e.PercentageComplete}% ({FormatBytes(e.BytesTransferred)} / {FormatBytes(e.TotalBytes)})"
|
||||||
? $"Прогресс: {progressInfo.PercentageComplete}% ({FormatBytes(progressInfo.BytesTransferred)} / {FormatBytes(progressInfo.TotalBytes)})"
|
// : $"Прогресс: {e.PercentageComplete}%");
|
||||||
: $"Прогресс: {progressInfo.PercentageComplete}%");
|
//
|
||||||
|
// _lastLoggedProgress = e.PercentageComplete;
|
||||||
_lastLoggedProgress = progressInfo.PercentageComplete;
|
// }
|
||||||
}
|
// });
|
||||||
});
|
// }
|
||||||
}
|
//
|
||||||
|
// private void OnProgressReport(ProgressInfo progressInfo)
|
||||||
private void OnAdbStatusChanged(object? sender, string e)
|
// {
|
||||||
{
|
// Dispatcher.UIThread.InvokeAsync(() =>
|
||||||
Dispatcher.UIThread.InvokeAsync(() =>
|
// {
|
||||||
{
|
// if (progressInfo.PercentageComplete != _lastUpdatedProgress &&
|
||||||
InstallProgressBar.Value = 0;
|
// progressInfo.PercentageComplete % PROGRESS_UPDATE_STEP == 0)
|
||||||
_lastLoggedProgress = -1;
|
// {
|
||||||
_lastUpdatedProgress = -1;
|
// InstallProgressBar.Value = progressInfo.PercentageComplete;
|
||||||
LogMessage(e);
|
// _lastUpdatedProgress = progressInfo.PercentageComplete;
|
||||||
});
|
// }
|
||||||
}
|
//
|
||||||
|
//
|
||||||
private string FormatBytes(long bytes)
|
// if (progressInfo.PercentageComplete != _lastLoggedProgress &&
|
||||||
{
|
// (progressInfo.PercentageComplete % PROGRESS_LOG_STEP == 0 || progressInfo.PercentageComplete == 100))
|
||||||
string[] suffixes = ["B", "KB", "MB", "GB", "TB"];
|
// {
|
||||||
var counter = 0;
|
// LogMessage(
|
||||||
double number = bytes;
|
// progressInfo.TotalBytes > 0
|
||||||
|
// ? $"Прогресс: {progressInfo.PercentageComplete}% ({FormatBytes(progressInfo.BytesTransferred)} / {FormatBytes(progressInfo.TotalBytes)})"
|
||||||
while (Math.Round(number / 1024) >= 1)
|
// : $"Прогресс: {progressInfo.PercentageComplete}%");
|
||||||
{
|
//
|
||||||
number /= 1024;
|
// _lastLoggedProgress = progressInfo.PercentageComplete;
|
||||||
counter++;
|
// }
|
||||||
}
|
// });
|
||||||
|
// }
|
||||||
return $"{number:N1} {suffixes[counter]}";
|
//
|
||||||
}
|
// private void OnAdbStatusChanged(object? sender, string e)
|
||||||
|
// {
|
||||||
|
// Dispatcher.UIThread.InvokeAsync(() =>
|
||||||
private async void CheckAndEnableInstallButton()
|
// {
|
||||||
{
|
// InstallProgressBar.Value = 0;
|
||||||
InstallButton.IsEnabled = !string.IsNullOrEmpty(_apkPath) && !string.IsNullOrEmpty(_zipPath);
|
// _lastLoggedProgress = -1;
|
||||||
}
|
// _lastUpdatedProgress = -1;
|
||||||
|
// LogMessage(e);
|
||||||
private async void OnChooseApkClicked(object? sender, RoutedEventArgs e)
|
// });
|
||||||
{
|
// }
|
||||||
var topLevel = GetTopLevel(this);
|
//
|
||||||
var files = await topLevel!.StorageProvider.OpenFilePickerAsync(new FilePickerOpenOptions
|
// private string FormatBytes(long bytes)
|
||||||
{
|
// {
|
||||||
Title = "Выберите APK файл",
|
// string[] suffixes = ["B", "KB", "MB", "GB", "TB"];
|
||||||
AllowMultiple = false,
|
// var counter = 0;
|
||||||
FileTypeFilter = new[]
|
// double number = bytes;
|
||||||
{
|
//
|
||||||
new FilePickerFileType("APK Files")
|
// while (Math.Round(number / 1024) >= 1)
|
||||||
{
|
// {
|
||||||
Patterns = new[] { "*.apk" }
|
// number /= 1024;
|
||||||
}
|
// counter++;
|
||||||
}
|
// }
|
||||||
});
|
//
|
||||||
|
// return $"{number:N1} {suffixes[counter]}";
|
||||||
if (files.Count >= 1)
|
// }
|
||||||
{
|
//
|
||||||
_apkPath = files[0].Path.LocalPath;
|
//
|
||||||
LogMessage($"APK выбран: {Path.GetFileName(_apkPath)}");
|
// private async void CheckAndEnableInstallButton()
|
||||||
}
|
// {
|
||||||
|
// InstallButton.IsEnabled = !string.IsNullOrEmpty(_apkPath) && !string.IsNullOrEmpty(_zipPath);
|
||||||
CheckAndEnableInstallButton();
|
// }
|
||||||
}
|
//
|
||||||
|
// private async void OnChooseApkClicked(object? sender, RoutedEventArgs e)
|
||||||
private async void OnChooseContentClicked(object? sender, RoutedEventArgs e)
|
// {
|
||||||
{
|
// var topLevel = GetTopLevel(this);
|
||||||
var topLevel = GetTopLevel(this);
|
// var files = await topLevel!.StorageProvider.OpenFilePickerAsync(new FilePickerOpenOptions
|
||||||
var files = await topLevel!.StorageProvider.OpenFilePickerAsync(new FilePickerOpenOptions
|
// {
|
||||||
{
|
// Title = "Выберите APK файл",
|
||||||
Title = "Выберите архив с контентом",
|
// AllowMultiple = false,
|
||||||
AllowMultiple = false,
|
// FileTypeFilter = new[]
|
||||||
FileTypeFilter = new[]
|
// {
|
||||||
{
|
// new FilePickerFileType("APK Files")
|
||||||
new FilePickerFileType("ZIP Files")
|
// {
|
||||||
{
|
// Patterns = new[] { "*.apk" }
|
||||||
Patterns = new[] { "*.zip" }
|
// }
|
||||||
}
|
// }
|
||||||
}
|
// });
|
||||||
});
|
//
|
||||||
|
// if (files.Count >= 1)
|
||||||
if (files.Count >= 1)
|
// {
|
||||||
{
|
// _apkPath = files[0].Path.LocalPath;
|
||||||
_zipPath = files[0].Path.LocalPath;
|
// LogMessage($"APK выбран: {Path.GetFileName(_apkPath)}");
|
||||||
LogMessage($"Контент выбран: {Path.GetFileName(_zipPath)}");
|
// }
|
||||||
}
|
//
|
||||||
|
// CheckAndEnableInstallButton();
|
||||||
CheckAndEnableInstallButton();
|
// }
|
||||||
}
|
//
|
||||||
|
// private async void OnChooseContentClicked(object? sender, RoutedEventArgs e)
|
||||||
private async void OnInstallClicked(object? sender, RoutedEventArgs e)
|
// {
|
||||||
{
|
// var topLevel = GetTopLevel(this);
|
||||||
if (string.IsNullOrEmpty(_apkPath) || string.IsNullOrEmpty(_zipPath))
|
// var files = await topLevel!.StorageProvider.OpenFilePickerAsync(new FilePickerOpenOptions
|
||||||
{
|
// {
|
||||||
LogMessage("Ошибка: Выберите APK файл и папку с контентом");
|
// Title = "Выберите архив с контентом",
|
||||||
return;
|
// AllowMultiple = false,
|
||||||
}
|
// FileTypeFilter = new[]
|
||||||
|
// {
|
||||||
_adbService.RefreshDeviceData();
|
// new FilePickerFileType("ZIP Files")
|
||||||
|
// {
|
||||||
InstallButton.IsEnabled = false;
|
// Patterns = new[] { "*.zip" }
|
||||||
InstallProgressBar.Value = 0;
|
// }
|
||||||
|
// }
|
||||||
try
|
// });
|
||||||
{
|
//
|
||||||
LogMessage("Начинаем установку...");
|
// if (files.Count >= 1)
|
||||||
|
// {
|
||||||
var deviceInfo = _adbService.GetDeviceInfo();
|
// _zipPath = files[0].Path.LocalPath;
|
||||||
LogMessage($"Найдено устройство: {deviceInfo.SerialNumber}");
|
// LogMessage($"Контент выбран: {Path.GetFileName(_zipPath)}");
|
||||||
LogMessage($"Состояние: {deviceInfo.State}");
|
// }
|
||||||
LogMessage($"Модель: {deviceInfo.Model} - {deviceInfo.Name}");
|
//
|
||||||
|
// CheckAndEnableInstallButton();
|
||||||
var progress = new Progress<ProgressInfo>(OnProgressReport);
|
// }
|
||||||
|
//
|
||||||
await _adbService.InstallApkAsync(_apkPath, progress);
|
// private async void OnInstallClicked(object? sender, RoutedEventArgs e)
|
||||||
|
// {
|
||||||
var apkInfo = ApkScrapper.GetApkInfo(_apkPath);
|
// if (string.IsNullOrEmpty(_apkPath) || string.IsNullOrEmpty(_zipPath))
|
||||||
LogMessage($"Ставим {apkInfo.PackageName} версии {apkInfo.VersionName}");
|
// {
|
||||||
var zipName = Path.GetFileName(_zipPath);
|
// LogMessage("Ошибка: Выберите APK файл и папку с контентом");
|
||||||
var outputPath =
|
// return;
|
||||||
@$"/storage/emulated/0/Android/data/{apkInfo.PackageName}/files/{zipName}";
|
// }
|
||||||
LogMessage($"Начинаем копирование контента в {outputPath}");
|
//
|
||||||
|
// _adbService.RefreshDeviceData();
|
||||||
await _adbService.CopyFileAsync(_zipPath, outputPath, progress);
|
//
|
||||||
|
// InstallButton.IsEnabled = false;
|
||||||
LogMessage("Установка завершена успешно!");
|
// InstallProgressBar.Value = 0;
|
||||||
}
|
//
|
||||||
catch (Exception ex)
|
// try
|
||||||
{
|
// {
|
||||||
LogMessage($"Ошибка установки: {ex.Message}");
|
// LogMessage("Начинаем установку...");
|
||||||
}
|
//
|
||||||
finally
|
// var deviceInfo = _adbService.GetDeviceInfo();
|
||||||
{
|
// LogMessage($"Найдено устройство: {deviceInfo.SerialNumber}");
|
||||||
InstallButton.IsEnabled = true;
|
// LogMessage($"Состояние: {deviceInfo.State}");
|
||||||
InstallProgressBar.Value = 0;
|
// LogMessage($"Модель: {deviceInfo.Model} - {deviceInfo.Name}");
|
||||||
}
|
//
|
||||||
}
|
// var progress = new Progress<ProgressInfo>(OnProgressReport);
|
||||||
|
//
|
||||||
private void LogMessage(string message)
|
// await _adbService.InstallApkAsync(_apkPath, progress);
|
||||||
{
|
//
|
||||||
var timestamp = DateTime.Now.ToString("HH:mm:ss");
|
// var apkInfo = ApkScrapper.GetApkInfo(_apkPath);
|
||||||
LogsTextBox.Text += $"[{timestamp}] {message}\n";
|
// LogMessage($"Ставим {apkInfo.PackageName} версии {apkInfo.VersionName}");
|
||||||
|
// var zipName = Path.GetFileName(_zipPath);
|
||||||
var scrollViewer = LogsTextBox.FindAncestorOfType<ScrollViewer>();
|
// var outputPath =
|
||||||
scrollViewer?.ScrollToEnd();
|
// @$"/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>();
|
||||||
|
// scrollViewer?.ScrollToEnd();
|
||||||
|
// }
|
||||||
}
|
}
|
||||||
24
MetaforceInstaller.UI/NewInstallationDialog.axaml
Normal file
24
MetaforceInstaller.UI/NewInstallationDialog.axaml
Normal file
|
|
@ -0,0 +1,24 @@
|
||||||
|
<Window xmlns="https://github.com/avaloniaui"
|
||||||
|
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||||
|
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||||
|
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||||
|
mc:Ignorable="d" d:DesignWidth="200" d:DesignHeight="400"
|
||||||
|
x:Class="MetaforceInstaller.UI.NewInstallationDialog"
|
||||||
|
Title="MetaforceInstaller">
|
||||||
|
|
||||||
|
<StackPanel Margin="24" Spacing="12">
|
||||||
|
<Label FontSize="36">Add new installation</Label>
|
||||||
|
<TextBox />
|
||||||
|
<Button Name="ChooseZip">Choose .zip with installation</Button>
|
||||||
|
<CheckBox Name="ServerCheckBox">Install server</CheckBox>
|
||||||
|
<CheckBox Name="PcAdminCheckBox">Install admin</CheckBox>
|
||||||
|
<CheckBox Name="AndroidAdminCheckbox">Save android admin</CheckBox>
|
||||||
|
<CheckBox Name="VrClientCheckbox">Save VR client</CheckBox>
|
||||||
|
|
||||||
|
<StackPanel Orientation="Horizontal" HorizontalAlignment="Right" VerticalAlignment="Bottom" Spacing="8">
|
||||||
|
<Button Name="InstallButton">Install</Button>
|
||||||
|
<Button Name="CancelButton">Cancel</Button>
|
||||||
|
</StackPanel>
|
||||||
|
</StackPanel>
|
||||||
|
|
||||||
|
</Window>
|
||||||
118
MetaforceInstaller.UI/NewInstallationDialog.axaml.cs
Normal file
118
MetaforceInstaller.UI/NewInstallationDialog.axaml.cs
Normal file
|
|
@ -0,0 +1,118 @@
|
||||||
|
using System.IO.Compression;
|
||||||
|
using Avalonia.Controls;
|
||||||
|
using Avalonia.Interactivity;
|
||||||
|
using Avalonia.Platform.Storage;
|
||||||
|
using MetaforceInstaller.Core.Models;
|
||||||
|
using MetaforceInstaller.Core.Services;
|
||||||
|
|
||||||
|
namespace MetaforceInstaller.UI;
|
||||||
|
|
||||||
|
public partial class NewInstallationDialog : Window
|
||||||
|
{
|
||||||
|
private string? _zipPath;
|
||||||
|
private InstallationParts? _installationParts;
|
||||||
|
|
||||||
|
public NewInstallationDialog()
|
||||||
|
{
|
||||||
|
InitializeComponent();
|
||||||
|
RefreshCheckboxes();
|
||||||
|
CancelButton.Click += OnCancelClick;
|
||||||
|
ChooseZip.Click += OnChooseZipClick;
|
||||||
|
InstallButton.IsEnabled = false;
|
||||||
|
InstallButton.Click += OnInstallClick;
|
||||||
|
}
|
||||||
|
|
||||||
|
private async void RefreshCheckboxes()
|
||||||
|
{
|
||||||
|
var serverCheckbox = ServerCheckBox;
|
||||||
|
var pcAdminCheckbox = PcAdminCheckBox;
|
||||||
|
var androidAdminCheckbox = AndroidAdminCheckbox;
|
||||||
|
var vrClientCheckbox = VrClientCheckbox;
|
||||||
|
serverCheckbox.Content = TextDefaults.InstallServer;
|
||||||
|
serverCheckbox.IsEnabled = true;
|
||||||
|
pcAdminCheckbox.Content = TextDefaults.InstallAdmin;
|
||||||
|
pcAdminCheckbox.IsEnabled = true;
|
||||||
|
androidAdminCheckbox.Content = TextDefaults.SaveAndroidAdmin;
|
||||||
|
androidAdminCheckbox.IsEnabled = true;
|
||||||
|
vrClientCheckbox.Content = TextDefaults.SaveVRClient;
|
||||||
|
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);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private void UpdateCheckboxes()
|
||||||
|
{
|
||||||
|
RefreshCheckboxes();
|
||||||
|
var serverCheckbox = ServerCheckBox;
|
||||||
|
var pcAdminCheckbox = PcAdminCheckBox;
|
||||||
|
var androidAdminCheckbox = AndroidAdminCheckbox;
|
||||||
|
var vrClientCheckbox = VrClientCheckbox;
|
||||||
|
|
||||||
|
if (!_installationParts.WindowsServerExists)
|
||||||
|
{
|
||||||
|
serverCheckbox.IsEnabled = false;
|
||||||
|
serverCheckbox.Content += "\nCouldn't find directory with server";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!_installationParts.WindowsAdminExists)
|
||||||
|
{
|
||||||
|
pcAdminCheckbox.IsEnabled = false;
|
||||||
|
pcAdminCheckbox.Content += "\nCouldn't find directory with PC admin";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!_installationParts.WindowsContentExists)
|
||||||
|
{
|
||||||
|
pcAdminCheckbox.IsEnabled = false;
|
||||||
|
pcAdminCheckbox.Content += "\nCouldn't find windows content";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!_installationParts.AndroidContentExists)
|
||||||
|
{
|
||||||
|
vrClientCheckbox.IsEnabled = false;
|
||||||
|
vrClientCheckbox.Content += "\nCouldn't find android content";
|
||||||
|
androidAdminCheckbox.IsEnabled = false;
|
||||||
|
androidAdminCheckbox.Content += "\nCouldn't find android content";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!_installationParts.PicoClientExists && !_installationParts.OculusClientExists)
|
||||||
|
{
|
||||||
|
vrClientCheckbox.IsEnabled = false;
|
||||||
|
vrClientCheckbox.Content += "\nCouldn't find any VR clients";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnCancelClick(object? sender, RoutedEventArgs e)
|
||||||
|
{
|
||||||
|
Close();
|
||||||
|
}
|
||||||
|
}
|
||||||
9
MetaforceInstaller.UI/TextDefaults.cs
Normal file
9
MetaforceInstaller.UI/TextDefaults.cs
Normal file
|
|
@ -0,0 +1,9 @@
|
||||||
|
namespace MetaforceInstaller.UI;
|
||||||
|
|
||||||
|
public static class TextDefaults
|
||||||
|
{
|
||||||
|
public static readonly string InstallServer = "Install Server";
|
||||||
|
public static readonly string InstallAdmin = "Install Admin";
|
||||||
|
public static readonly string SaveAndroidAdmin = "Save Android admin";
|
||||||
|
public static readonly string SaveVRClient = "Save VR client";
|
||||||
|
}
|
||||||
Loading…
Add table
Add a link
Reference in a new issue