elfisa-pharmacy/src/Elfisa.Avalonia/ViewModels/UpdateViewModel.cs
Exest e8357bab1e версия 2.0.4: авто-обновление в Avalonia-клиенте
- UpdateService (Core): проверка Gitea releases/latest + скачивание установщика с CDN
- UpdateWindow/VM: уведомление «доступно обновление», тихая установка поверх с перезапуском
- ShellView: проверка при старте (один раз, офлайн/ошибки игнорируются)

Закрывает пробел: Avalonia-клиент раньше не умел обновляться (апдейтер был только в WinForms).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-08-13 10:10:13 +03:00

96 lines
3.2 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

using System;
using System.Diagnostics;
using System.Threading.Tasks;
using Avalonia.Controls.ApplicationLifetimes;
using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;
using Elfisa.Core;
namespace Elfisa.Avalonia.ViewModels;
/// <summary>Окно «Доступно обновление»: скачивает установщик и запускает его.</summary>
public partial class UpdateViewModel : ViewModelBase
{
private readonly UpdateInfo _info;
private readonly Action _close;
public UpdateViewModel(UpdateInfo info, Action close)
{
_info = info;
_close = close;
}
public string Message =>
$"Установлена версия {_info.CurrentVersion}.\nДоступна новая версия {_info.LatestVersion}.";
[ObservableProperty] private bool _busy;
[ObservableProperty] private double _progress;
[ObservableProperty] private string _status = "";
[RelayCommand]
private void Later() => _close();
[RelayCommand]
private async Task UpdateAsync()
{
// Не-Windows: установщика нет — открываем страницу релиза в браузере.
if (!OperatingSystem.IsWindows())
{
OpenUrl(string.IsNullOrWhiteSpace(_info.ReleaseUrl) ? "https://cdn.24pharmdata.ru" : _info.ReleaseUrl);
_close();
return;
}
try
{
Busy = true;
Status = "Скачивание обновления…";
var progress = new Progress<double>(p =>
{
Progress = p;
Status = $"Скачивание обновления… {p:0}%";
});
var setupPath = await UpdateService.DownloadSetupAsync(progress);
Status = "Запуск установки…";
LaunchInstallerAndExit(setupPath);
}
catch (Exception ex)
{
Busy = false;
Status = "Не удалось обновить: " + ex.Message;
}
}
/// <summary>Тихая установка поверх + перезапуск приложения, затем закрываем себя.</summary>
private void LaunchInstallerAndExit(string setupPath)
{
var exe = Process.GetCurrentProcess().MainModule?.FileName;
var inner = $"\"{setupPath}\" /VERYSILENT /SUPPRESSMSGBOXES /NORESTART";
if (!string.IsNullOrEmpty(exe))
inner += $" && start \"\" \"{exe}\"";
Process.Start(new ProcessStartInfo("cmd.exe")
{
Arguments = "/c \"" + inner + "\"",
UseShellExecute = false,
CreateNoWindow = true,
});
// Закрываем приложение, чтобы установщик заменил файлы (CloseApplications=yes).
if (global::Avalonia.Application.Current?.ApplicationLifetime is IClassicDesktopStyleApplicationLifetime d)
d.Shutdown();
else
Environment.Exit(0);
}
private static void OpenUrl(string url)
{
try
{
Process.Start(new ProcessStartInfo(url) { UseShellExecute = true });
}
catch { /* игнорируем */ }
}
}