доработаный

This commit is contained in:
2026-09-14 21:02:45 +02:00
parent ab5e6e7422
commit 263be52245
5 changed files with 726 additions and 181 deletions
+291 -45
View File
@@ -11,40 +11,102 @@ namespace SpotXInstaller.ViewModels;
public partial class MainViewModel : ViewModelBase
{
private readonly InstallerService _installer = new();
private CancellationTokenSource? _cts;
// --- СОСТОЯНИЯ ЭКРАНОВ ---
[ObservableProperty] private bool _isStepLoading = true;
[ObservableProperty] private bool _isStepHome;
[ObservableProperty] private bool _isStepSettings;
[ObservableProperty] private bool _isStepProgress;
// ---------------------------------------------------------
// SCREEN STATES
// ---------------------------------------------------------
// --- POPUP ---
[ObservableProperty] private bool _showPopup;
[ObservableProperty] private string _popupTitle = "";
[ObservableProperty] private string _popupMessage = "";
[ObservableProperty] private string _popupColor = "#8B5CF6";
[ObservableProperty]
private bool _isStepLoading = true;
// --- ГАЛОЧКИ ---
[ObservableProperty] private bool _blockUpdates = true;
[ObservableProperty] private bool _hidePodcasts = true;
[ObservableProperty] private bool _hidePremium = true;
[ObservableProperty] private bool _clearCache;
[ObservableProperty]
private bool _isStepHome;
// --- ПРОГРЕСС ---
[ObservableProperty] private double _progressValue;
[ObservableProperty] private string _progressStatus = "Подготовка...";
[ObservableProperty] private string _miniLog = "";
[ObservableProperty]
private bool _isStepSettings;
public MainViewModel() => _ = BootAsync();
[ObservableProperty]
private bool _isStepProgress;
// ---------------------------------------------------------
// POPUP
// ---------------------------------------------------------
[ObservableProperty]
private bool _showPopup;
[ObservableProperty]
private string _popupTitle = "";
[ObservableProperty]
private string _popupMessage = "";
[ObservableProperty]
private string _popupColor = "#8B5CF6";
// ---------------------------------------------------------
// SETTINGS
// ---------------------------------------------------------
[ObservableProperty]
private bool _blockUpdates = true;
[ObservableProperty]
private bool _hidePodcasts = true;
[ObservableProperty]
private bool _hidePremium = true;
[ObservableProperty]
private bool _clearCache;
// ---------------------------------------------------------
// PROGRESS
// ---------------------------------------------------------
[ObservableProperty]
private double _progressValue;
[ObservableProperty]
private string _progressStatus = "Подготовка...";
[ObservableProperty]
private string _miniLog = "";
// ---------------------------------------------------------
// STATE
// ---------------------------------------------------------
[ObservableProperty]
private bool _isInstalling;
public MainViewModel()
{
_ = BootAsync();
}
// ---------------------------------------------------------
// BOOT
// ---------------------------------------------------------
private async Task BootAsync()
{
await Task.Delay(3000);
SwitchTo(home: true);
}
private void SwitchTo(bool loading = false, bool home = false, bool settings = false, bool progress = false)
// ---------------------------------------------------------
// NAVIGATION
// ---------------------------------------------------------
private void SwitchTo(
bool loading = false,
bool home = false,
bool settings = false,
bool progress = false)
{
IsStepLoading = loading;
IsStepHome = home;
@@ -52,9 +114,33 @@ public partial class MainViewModel : ViewModelBase
IsStepProgress = progress;
}
[RelayCommand] private void GoToSettings() => SwitchTo(settings: true);
[RelayCommand] private void GoBackToHome() => SwitchTo(home: true);
[RelayCommand] private void ClosePopup() => ShowPopup = false;
[RelayCommand]
private void GoToSettings()
{
if (IsInstalling)
return;
SwitchTo(settings: true);
}
[RelayCommand]
private void GoBackToHome()
{
if (IsInstalling)
return;
SwitchTo(home: true);
}
[RelayCommand]
private void ClosePopup()
{
ShowPopup = false;
}
// ---------------------------------------------------------
// INSTALL
// ---------------------------------------------------------
[RelayCommand]
private async Task StartInstallAsync()
@@ -62,68 +148,228 @@ public partial class MainViewModel : ViewModelBase
await RunInstallerAsync(isUninstall: false);
}
// ---------------------------------------------------------
// UNINSTALL
// ---------------------------------------------------------
[RelayCommand]
private async Task StartUninstallAsync()
{
await RunInstallerAsync(isUninstall: true);
}
// ---------------------------------------------------------
// CANCEL BUTTON
// ---------------------------------------------------------
[RelayCommand]
private async Task CancelInstallAsync()
{
if (!IsInstalling)
return;
ProgressStatus = "Отмена установки...";
try
{
_cts?.Cancel();
}
catch
{
// Ignore.
}
await Task.CompletedTask;
}
// ---------------------------------------------------------
// WINDOW CLOSE
// ---------------------------------------------------------
public async Task CancelInstallationAsync()
{
if (!IsInstalling)
return;
try
{
ProgressStatus = "Завершение процессов...";
_cts?.Cancel();
// Даём process tree время корректно завершиться.
await Task.Delay(150);
}
catch
{
// Ignore.
}
}
// ---------------------------------------------------------
// MAIN INSTALLER
// ---------------------------------------------------------
private async Task RunInstallerAsync(bool isUninstall)
{
if (IsInstalling)
return;
ProgressValue = 0;
MiniLog = "";
ProgressStatus = isUninstall ? "Подготовка восстановления..." : "Подготовка установки...";
ProgressStatus = isUninstall
? "Подготовка восстановления..."
: "Подготовка установки...";
SwitchTo(progress: true);
_cts?.Dispose();
_cts = new CancellationTokenSource();
var progress = new Progress<(int Percent, string Status)>(p =>
{
ProgressValue = p.Percent;
ProgressStatus = p.Status;
});
var log = new Progress<string>(l => MiniLog = l);
IsInstalling = true;
var progress =
new Progress<(int Percent, string Status)>(
p =>
{
ProgressValue = p.Percent;
ProgressStatus = p.Status;
});
var log =
new Progress<string>(
line =>
{
MiniLog = line;
});
try
{
int code = isUninstall
? await _installer.UninstallAsync(progress, log, _cts.Token)
: await _installer.InstallAsync(
new InstallOptions(BlockUpdates, HidePodcasts, HidePremium, ClearCache),
progress, log, _cts.Token);
int code;
if (isUninstall)
{
code = await _installer.UninstallAsync(
progress,
log,
_cts.Token);
}
else
{
code = await _installer.InstallAsync(
new InstallOptions(
BlockUpdates,
HidePodcasts,
HidePremium,
ClearCache),
progress,
log,
_cts.Token);
}
IsInstalling = false;
SwitchTo(home: true);
if (code == 0)
{
ShowNotification(
isUninstall ? "ГОТОВО" : "УСПЕХ",
isUninstall
? "ГОТОВО"
: "УСПЕХ",
isUninstall
? "Оригинальный клиент Spotify восстановлен."
: "SpotX успешно установлен.",
isUninstall ? "#8B5CF6" : "#00E676");
else
ShowNotification("ОШИБКА",
$"Скрипт завершился с кодом {code}.\n\n{MiniLog[..Math.Min(200, MiniLog.Length)]}",
"#FF3B30");
isUninstall
? "#8B5CF6"
: "#00E676");
}
else
{
string errorText =
MiniLog.Length > 500
? MiniLog[..500]
: MiniLog;
ShowNotification(
"ОШИБКА",
$"Скрипт завершился с кодом {code}.\n\n{errorText}",
"#FF3B30");
}
}
catch (OperationCanceledException)
{
IsInstalling = false;
SwitchTo(home: true);
ShowNotification("ОТМЕНЕНО", "Операция прервана.", "#FFB300");
ShowNotification(
"ОТМЕНЕНО",
"Установка была отменена.",
"#FFB300");
}
catch (Exception ex)
{
IsInstalling = false;
SwitchTo(home: true);
ShowNotification("ОШИБКА", ex.Message, "#FF3B30");
ShowNotification(
"ОШИБКА",
ex.Message,
"#FF3B30");
}
finally
{
IsInstalling = false;
_cts?.Dispose();
_cts = null;
}
}
private void ShowNotification(string title, string message, string hexColor)
// ---------------------------------------------------------
// POPUP
// ---------------------------------------------------------
private void ShowNotification(
string title,
string message,
string hexColor)
{
PopupTitle = title;
PopupMessage = message;
PopupColor = hexColor;
ShowPopup = true;
}
// ---------------------------------------------------------
// DISPOSE
// ---------------------------------------------------------
public async Task DisposeAsync()
{
if (!IsInstalling)
return;
try
{
_cts?.Cancel();
await Task.Delay(150);
}
catch
{
// Ignore.
}
_cts?.Dispose();
_cts = null;
IsInstalling = false;
}
}