using System.Reflection;
using Serilog;
namespace YZWater.Core.Services;
///
/// 在线升级服务(借鉴 AutoFMA UpdateService,委托注入模式)
///
/// 设计原则:
/// 1. Core 层只负责版本管理和更新触发,不依赖具体 UI 框架
/// 2. 实际的更新检查/下载/安装逻辑由 UI 层通过 SetTriggerAction 注入
/// 3. config.json 配置 Update.Enabled / CheckOnStartup / CheckIntervalHours
///
/// Avalonia 无 AutoUpdater.NET 官方支持,UI 层可接入 Squirrel 或自研下载器后注入。
///
public static class UpdateService
{
private static DateTime? _lastCheckTime;
private static Action? _triggerAction;
private static System.Threading.Timer? _checkTimer;
///
/// 更新配置
///
public class UpdateConfig
{
/// 是否启用在线更新
public bool Enabled { get; set; }
/// 更新清单地址(appcast URL)
public string AppcastUrl { get; set; } = string.Empty;
/// 启动时是否检查更新
public bool CheckOnStartup { get; set; } = true;
/// 检查间隔(小时,默认 24)
public int CheckIntervalHours { get; set; } = 24;
}
///
/// 当前程序版本(Major.Minor.Build)
///
public static string GetCurrentVersion()
{
var version = Assembly.GetEntryAssembly()?.GetName().Version;
return version != null ? $"{version.Major}.{version.Minor}.{version.Build}" : "0.0.0";
}
/// 上次检查时间
public static DateTime? LastCheckTime => _lastCheckTime;
/// 更新触发器是否已注入
public static bool IsTriggerRegistered => _triggerAction != null;
///
/// 注入实际更新触发逻辑(由 UI 层调用,如 Squirrel 下载安装流程)
///
public static void SetTriggerAction(Action triggerAction)
{
_triggerAction = triggerAction;
Log.Information("在线更新触发器已注入");
}
///
/// 触发在线更新
///
public static bool TriggerUpdate()
{
if (_triggerAction == null)
{
Log.Warning("更新触发器未注入,无法执行在线更新");
return false;
}
Log.Information("触发在线更新,当前版本: {Version}", GetCurrentVersion());
_lastCheckTime = DateTime.Now;
try
{
_triggerAction();
return true;
}
catch (Exception ex)
{
Log.Error(ex, "触发在线更新失败");
return false;
}
}
///
/// 启动定期检查(启动时检查一次 + 按 CheckIntervalHours 定时)
///
public static void StartPeriodicCheck(Action onCheckDue)
{
var config = ConfigService.GetConfig()?.Update;
if (config is not { Enabled: true })
{
Log.Debug("在线更新未启用,跳过定期检查");
return;
}
var interval = TimeSpan.FromHours(Math.Max(1, config.CheckIntervalHours));
// 启动时检查一次
if (config.CheckOnStartup)
{
Task.Run(() =>
{
try
{
_lastCheckTime = DateTime.Now;
onCheckDue();
}
catch (Exception ex)
{
Log.Error(ex, "启动时检查更新失败");
}
});
}
// 定时检查
_checkTimer ??= new System.Threading.Timer(_ =>
{
try
{
_lastCheckTime = DateTime.Now;
onCheckDue();
}
catch (Exception ex)
{
Log.Error(ex, "定时检查更新失败");
}
}, null, interval, interval);
Log.Information("在线更新定期检查已启动,间隔 {Hours} 小时", config.CheckIntervalHours);
}
///
/// 停止定期检查
///
public static void StopPeriodicCheck()
{
_checkTimer?.Dispose();
_checkTimer = null;
}
}