improve:用户体验分级
This commit is contained in:
@@ -20,7 +20,7 @@ namespace Ink_Canvas.Helpers
|
||||
{
|
||||
// 定义超时时间为10秒
|
||||
private static readonly TimeSpan RequestTimeout = TimeSpan.FromSeconds(10);
|
||||
private static string updatesFolderPath = Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), "AutoUpdate");
|
||||
private static readonly string updatesFolderPath = Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), "AutoUpdate");
|
||||
private static string statusFilePath = null;
|
||||
|
||||
// 线路组结构体(包含版本、下载、日志地址)
|
||||
@@ -395,6 +395,47 @@ namespace Ink_Canvas.Helpers
|
||||
}
|
||||
}
|
||||
|
||||
// 通过GitHub API获取指定版本的Release信息
|
||||
private static async Task<(string version, string downloadUrl, string releaseNotes, DateTime? releaseTime)> GetGithubReleaseByVersion(string targetVersion, UpdateChannel channel)
|
||||
{
|
||||
try
|
||||
{
|
||||
string apiUrl = channel == UpdateChannel.Beta
|
||||
? "https://api.github.com/repos/InkCanvasForClass/community-beta/releases"
|
||||
: "https://api.github.com/repos/InkCanvasForClass/community/releases";
|
||||
using (var client = new HttpClient())
|
||||
{
|
||||
client.DefaultRequestHeaders.Add("User-Agent", "ICC-CE Auto Updater");
|
||||
var response = await client.GetStringAsync(apiUrl);
|
||||
var releases = JArray.Parse(response);
|
||||
|
||||
foreach (var release in releases)
|
||||
{
|
||||
string version = release["tag_name"]?.ToString();
|
||||
if (version == targetVersion || version == $"v{targetVersion}" || version == $"V{targetVersion}")
|
||||
{
|
||||
string releaseNotes = release["body"]?.ToString();
|
||||
string downloadUrl = release["assets"]?.First?["browser_download_url"]?.ToString();
|
||||
|
||||
// 解析发布时间
|
||||
DateTime? releaseTime = null;
|
||||
if (release["published_at"] != null && DateTime.TryParse(release["published_at"].ToString(), out DateTime parsedTime))
|
||||
{
|
||||
releaseTime = parsedTime;
|
||||
}
|
||||
|
||||
return (version, downloadUrl, releaseNotes, releaseTime);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogHelper.WriteLogToFile($"AutoUpdate | GitHub Releases API 获取版本 {targetVersion} 失败: {ex.Message}", LogHelper.LogType.Warning);
|
||||
}
|
||||
return (null, null, null, null);
|
||||
}
|
||||
|
||||
// 通过GitHub API获取最新Release信息
|
||||
private static async Task<(string version, string downloadUrl, string releaseNotes, DateTime? releaseTime)> GetLatestGithubRelease(UpdateChannel channel)
|
||||
{
|
||||
@@ -454,17 +495,23 @@ namespace Ink_Canvas.Helpers
|
||||
if (remote > local || alwaysGetRemote)
|
||||
{
|
||||
LogHelper.WriteLogToFile($"AutoUpdate | 通过GitHub Releases API发现新版本: {apiVersion}");
|
||||
|
||||
|
||||
// 检查是否应该根据用户优先级推送更新(版本修复功能不受限制)
|
||||
if (!isVersionFix)
|
||||
{
|
||||
DateTime releaseTime = apiReleaseTime ?? DateTime.Now;
|
||||
bool shouldPush = DeviceIdentifier.ShouldPushUpdate(apiVersion, releaseTime, true); // 明确标记为自动更新
|
||||
|
||||
// 尝试获取当前版本的发布时间
|
||||
DateTime? currentVersionReleaseTime = await GetVersionReleaseTime(localVersion, channel);
|
||||
|
||||
bool shouldPush = DeviceIdentifier.ShouldPushUpdate(apiVersion, releaseTime, true, currentVersionReleaseTime); // 明确标记为自动更新
|
||||
if (!shouldPush)
|
||||
{
|
||||
var priority = DeviceIdentifier.GetUpdatePriority();
|
||||
var daysSinceRelease = (DateTime.Now - releaseTime).TotalDays;
|
||||
LogHelper.WriteLogToFile($"AutoUpdate | 根据用户优先级({priority}),暂不推送更新 {apiVersion},发布时间: {releaseTime:yyyy-MM-dd HH:mm:ss},已过 {daysSinceRelease:F1} 天");
|
||||
var daysBetweenVersions = currentVersionReleaseTime.HasValue
|
||||
? (releaseTime - currentVersionReleaseTime.Value).TotalDays
|
||||
: (DateTime.Now - releaseTime).TotalDays;
|
||||
LogHelper.WriteLogToFile($"AutoUpdate | 根据用户优先级({priority}),暂不推送更新 {apiVersion},版本间隔: {daysBetweenVersions:F1} 天");
|
||||
var group = (await GetAvailableLineGroupsOrdered(channel)).FirstOrDefault();
|
||||
return (null, group, apiReleaseNotes); // 返回null表示不推送
|
||||
}
|
||||
@@ -506,11 +553,14 @@ namespace Ink_Canvas.Helpers
|
||||
if (remote > local || alwaysGetRemote)
|
||||
{
|
||||
LogHelper.WriteLogToFile($"AutoUpdate | 发现新版本或强制获取: {remoteVersion}");
|
||||
|
||||
|
||||
// 检查是否应该根据用户优先级推送更新(版本修复功能不受限制)
|
||||
if (!isVersionFix)
|
||||
{
|
||||
bool shouldPush = DeviceIdentifier.ShouldPushUpdate(remoteVersion, DateTime.Now, true); // 明确标记为自动更新
|
||||
// 尝试获取当前版本的发布时间
|
||||
DateTime? currentVersionReleaseTime = await GetVersionReleaseTime(localVersion, channel);
|
||||
|
||||
bool shouldPush = DeviceIdentifier.ShouldPushUpdate(remoteVersion, DateTime.Now, true, currentVersionReleaseTime); // 明确标记为自动更新
|
||||
if (!shouldPush)
|
||||
{
|
||||
var priority = DeviceIdentifier.GetUpdatePriority();
|
||||
@@ -1501,6 +1551,26 @@ namespace Ink_Canvas.Helpers
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取指定版本的发布时间
|
||||
/// </summary>
|
||||
/// <param name="version">版本号</param>
|
||||
/// <param name="channel">更新通道</param>
|
||||
/// <returns>版本发布时间,如果获取失败则返回null</returns>
|
||||
public static async Task<DateTime?> GetVersionReleaseTime(string version, UpdateChannel channel = UpdateChannel.Release)
|
||||
{
|
||||
try
|
||||
{
|
||||
var (_, _, _, releaseTime) = await GetGithubReleaseByVersion(version, channel);
|
||||
return releaseTime;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogHelper.WriteLogToFile($"AutoUpdate | 获取版本 {version} 发布时间失败: {ex.Message}", LogHelper.LogType.Warning);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 启动手动指定版本的多线路多线程下载并自动安装(用于历史版本回滚等场景)
|
||||
/// </summary>
|
||||
|
||||
@@ -1747,10 +1747,11 @@ namespace Ink_Canvas.Helpers
|
||||
/// 根据优先级决定是否应该推送更新(仅适用于自动更新,版本修复功能不受影响)
|
||||
/// </summary>
|
||||
/// <param name="updateVersion">更新版本号</param>
|
||||
/// <param name="releaseTime">发布时间</param>
|
||||
/// <param name="releaseTime">新版本发布时间</param>
|
||||
/// <param name="isAutoUpdate">是否为自动更新检查(默认true,false表示版本修复)</param>
|
||||
/// <param name="currentVersionReleaseTime">当前版本发布时间</param>
|
||||
/// <returns>是否应该推送更新</returns>
|
||||
public static bool ShouldPushUpdate(string updateVersion, DateTime releaseTime, bool isAutoUpdate = true)
|
||||
public static bool ShouldPushUpdate(string updateVersion, DateTime releaseTime, bool isAutoUpdate = true, DateTime? currentVersionReleaseTime = null)
|
||||
{
|
||||
try
|
||||
{
|
||||
@@ -1769,17 +1770,27 @@ namespace Ink_Canvas.Helpers
|
||||
var frequency = GetUsageFrequency();
|
||||
var stats = LoadUsageStats();
|
||||
|
||||
// 计算发布时间到现在的天数
|
||||
var daysSinceRelease = (DateTime.Now - releaseTime).TotalDays;
|
||||
// 计算版本间的时间差
|
||||
double daysBetweenVersions;
|
||||
if (currentVersionReleaseTime.HasValue)
|
||||
{
|
||||
// 使用当前版本发布时间与新版本发布时间的差异
|
||||
daysBetweenVersions = (releaseTime - currentVersionReleaseTime.Value).TotalDays;
|
||||
}
|
||||
else
|
||||
{
|
||||
// 如果没有当前版本发布时间,回退到使用新版本发布时间到现在的天数
|
||||
daysBetweenVersions = (DateTime.Now - releaseTime).TotalDays;
|
||||
}
|
||||
|
||||
// 计算最近活跃度(最后一次使用距今的天数)
|
||||
var daysSinceLastUse = (DateTime.Now - stats.LastLaunchTime).TotalDays;
|
||||
|
||||
// 综合判断逻辑(仅适用于自动更新)
|
||||
var shouldPush = ShouldPushUpdateComprehensive(priority, frequency, daysSinceRelease, daysSinceLastUse, stats, updateType);
|
||||
var shouldPush = ShouldPushUpdateComprehensive(priority, frequency, daysBetweenVersions, daysSinceLastUse, stats, updateType);
|
||||
|
||||
LogHelper.WriteLogToFile($"DeviceIdentifier | 自动更新推送判断 - 版本: {updateVersion}, 类型: {updateType}, " +
|
||||
$"优先级: {priority}, 频率: {frequency}, 发布天数: {daysSinceRelease:F1}, " +
|
||||
$"优先级: {priority}, 频率: {frequency}, 版本间隔: {daysBetweenVersions:F1}天, " +
|
||||
$"最后使用: {daysSinceLastUse:F1}天前, 结果: {shouldPush}");
|
||||
|
||||
return shouldPush;
|
||||
@@ -1844,8 +1855,15 @@ namespace Ink_Canvas.Helpers
|
||||
/// <summary>
|
||||
/// 综合时间和使用频率的自动更新推送判断逻辑(不影响版本修复)
|
||||
/// </summary>
|
||||
/// <param name="priority">用户更新优先级</param>
|
||||
/// <param name="frequency">用户使用频率</param>
|
||||
/// <param name="daysBetweenVersions">当前版本与新版本之间的天数差异</param>
|
||||
/// <param name="daysSinceLastUse">距离最后使用的天数</param>
|
||||
/// <param name="stats">使用统计数据</param>
|
||||
/// <param name="updateType">更新类型</param>
|
||||
/// <returns>是否应该推送更新</returns>
|
||||
private static bool ShouldPushUpdateComprehensive(UpdatePriority priority, UsageFrequency frequency,
|
||||
double daysSinceRelease, double daysSinceLastUse, UsageStats stats, UpdateType updateType)
|
||||
double daysBetweenVersions, double daysSinceLastUse, UsageStats stats, UpdateType updateType)
|
||||
{
|
||||
// 考虑用户的总体使用模式
|
||||
var isHeavyUser = stats.TotalUsageMinutes > 3000; // 超过50小时的重度用户
|
||||
@@ -1860,12 +1878,12 @@ namespace Ink_Canvas.Helpers
|
||||
// 热修复和重要更新优先推送
|
||||
if (updateType == UpdateType.Hotfix)
|
||||
{
|
||||
return daysSinceRelease >= 1; // 热修复1天后推送
|
||||
return daysBetweenVersions >= 1; // 热修复版本间隔1天后推送
|
||||
}
|
||||
|
||||
// 但如果是重度用户,仍然要适当推送
|
||||
var baseDelay = isHeavyUser ? 7 : 14;
|
||||
return daysSinceRelease >= (baseDelay / urgencyMultiplier);
|
||||
return daysBetweenVersions >= (baseDelay / urgencyMultiplier);
|
||||
}
|
||||
|
||||
// 如果用户最近很活跃(3天内使用过)
|
||||
@@ -1880,19 +1898,19 @@ namespace Ink_Canvas.Helpers
|
||||
// 结合使用频率和优先级判断
|
||||
if (frequency == UsageFrequency.High || isHeavyUser)
|
||||
{
|
||||
return daysSinceRelease >= Math.Max(0, 1 / urgencyMultiplier); // 高频用户优先推送
|
||||
return daysBetweenVersions >= Math.Max(0, 1 / urgencyMultiplier); // 高频用户优先推送
|
||||
}
|
||||
|
||||
switch (priority)
|
||||
{
|
||||
case UpdatePriority.High:
|
||||
return daysSinceRelease >= Math.Max(0, 1 / urgencyMultiplier);
|
||||
return daysBetweenVersions >= Math.Max(0, 1 / urgencyMultiplier);
|
||||
|
||||
case UpdatePriority.Medium:
|
||||
return daysSinceRelease >= Math.Max(1, 2 / urgencyMultiplier);
|
||||
return daysBetweenVersions >= Math.Max(1, 2 / urgencyMultiplier);
|
||||
|
||||
case UpdatePriority.Low:
|
||||
return daysSinceRelease >= Math.Max(2, 3 / urgencyMultiplier);
|
||||
return daysBetweenVersions >= Math.Max(2, 3 / urgencyMultiplier);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1902,25 +1920,25 @@ namespace Ink_Canvas.Helpers
|
||||
// 热修复优先推送
|
||||
if (updateType == UpdateType.Hotfix)
|
||||
{
|
||||
return daysSinceRelease >= 1;
|
||||
return daysBetweenVersions >= 1;
|
||||
}
|
||||
|
||||
// 频繁用户优先推送
|
||||
if (isFrequentUser && frequency == UsageFrequency.High)
|
||||
{
|
||||
return daysSinceRelease >= Math.Max(1, 2 / urgencyMultiplier);
|
||||
return daysBetweenVersions >= Math.Max(1, 2 / urgencyMultiplier);
|
||||
}
|
||||
|
||||
switch (priority)
|
||||
{
|
||||
case UpdatePriority.High:
|
||||
return daysSinceRelease >= Math.Max(1, 2 / urgencyMultiplier);
|
||||
return daysBetweenVersions >= Math.Max(1, 2 / urgencyMultiplier);
|
||||
|
||||
case UpdatePriority.Medium:
|
||||
return daysSinceRelease >= Math.Max(2, 4 / urgencyMultiplier);
|
||||
return daysBetweenVersions >= Math.Max(2, 4 / urgencyMultiplier);
|
||||
|
||||
case UpdatePriority.Low:
|
||||
return daysSinceRelease >= Math.Max(4, 7 / urgencyMultiplier);
|
||||
return daysBetweenVersions >= Math.Max(4, 7 / urgencyMultiplier);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1931,16 +1949,16 @@ namespace Ink_Canvas.Helpers
|
||||
switch (priority)
|
||||
{
|
||||
case UpdatePriority.High:
|
||||
return daysSinceRelease >= Math.Max(2, 3 * delayMultiplier / urgencyMultiplier);
|
||||
return daysBetweenVersions >= Math.Max(2, 3 * delayMultiplier / urgencyMultiplier);
|
||||
|
||||
case UpdatePriority.Medium:
|
||||
return daysSinceRelease >= Math.Max(4, 7 * delayMultiplier / urgencyMultiplier);
|
||||
return daysBetweenVersions >= Math.Max(4, 7 * delayMultiplier / urgencyMultiplier);
|
||||
|
||||
case UpdatePriority.Low:
|
||||
return daysSinceRelease >= Math.Max(7, 14 * delayMultiplier / urgencyMultiplier);
|
||||
return daysBetweenVersions >= Math.Max(7, 14 * delayMultiplier / urgencyMultiplier);
|
||||
|
||||
default:
|
||||
return daysSinceRelease >= 7;
|
||||
return daysBetweenVersions >= 7;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -49,5 +49,5 @@ using System.Windows;
|
||||
// You can specify all the values or you can default the Build and Revision Numbers
|
||||
// by using the '*' as shown below:
|
||||
// [assembly: AssemblyVersion("1.0.*")]
|
||||
[assembly: AssemblyVersion("1.7.2.1")]
|
||||
[assembly: AssemblyFileVersion("1.7.2.1")]
|
||||
[assembly: AssemblyVersion("1.7.1.14")]
|
||||
[assembly: AssemblyFileVersion("1.7.1.14")]
|
||||
|
||||
Reference in New Issue
Block a user