add:用户体验分级
This commit is contained in:
@@ -432,6 +432,12 @@ namespace Ink_Canvas
|
|||||||
|
|
||||||
LogHelper.NewLog(string.Format("Ink Canvas Starting (Version: {0})", Assembly.GetExecutingAssembly().GetName().Version.ToString()));
|
LogHelper.NewLog(string.Format("Ink Canvas Starting (Version: {0})", Assembly.GetExecutingAssembly().GetName().Version.ToString()));
|
||||||
|
|
||||||
|
// 记录应用启动(设备标识符)
|
||||||
|
DeviceIdentifier.RecordAppLaunch();
|
||||||
|
LogHelper.WriteLogToFile($"App | 设备ID: {DeviceIdentifier.GetDeviceId()}");
|
||||||
|
LogHelper.WriteLogToFile($"App | 使用频率: {DeviceIdentifier.GetUsageFrequency()}");
|
||||||
|
LogHelper.WriteLogToFile($"App | 更新优先级: {DeviceIdentifier.GetUpdatePriority()}");
|
||||||
|
|
||||||
bool ret;
|
bool ret;
|
||||||
mutex = new System.Threading.Mutex(true, "InkCanvasForClass", out ret);
|
mutex = new System.Threading.Mutex(true, "InkCanvasForClass", out ret);
|
||||||
|
|
||||||
@@ -710,6 +716,17 @@ namespace Ink_Canvas
|
|||||||
string exitType = IsAppExitByUser ? "用户主动退出" : "应用程序退出";
|
string exitType = IsAppExitByUser ? "用户主动退出" : "应用程序退出";
|
||||||
WriteCrashLog($"{exitType},退出代码: {e.ApplicationExitCode}");
|
WriteCrashLog($"{exitType},退出代码: {e.ApplicationExitCode}");
|
||||||
|
|
||||||
|
// 记录应用退出(设备标识符)
|
||||||
|
try
|
||||||
|
{
|
||||||
|
DeviceIdentifier.RecordAppExit();
|
||||||
|
LogHelper.WriteLogToFile($"App | 应用运行时长: {(DateTime.Now - appStartTime).TotalMinutes:F1}分钟");
|
||||||
|
}
|
||||||
|
catch (Exception deviceEx)
|
||||||
|
{
|
||||||
|
LogHelper.WriteLogToFile($"记录设备标识符退出信息失败: {deviceEx.Message}", LogHelper.LogType.Error);
|
||||||
|
}
|
||||||
|
|
||||||
if (IsAppExitByUser)
|
if (IsAppExitByUser)
|
||||||
{
|
{
|
||||||
// 写入退出信号文件,通知看门狗正常退出
|
// 写入退出信号文件,通知看门狗正常退出
|
||||||
|
|||||||
@@ -396,7 +396,7 @@ namespace Ink_Canvas.Helpers
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 通过GitHub API获取最新Release信息
|
// 通过GitHub API获取最新Release信息
|
||||||
private static async Task<(string version, string downloadUrl, string releaseNotes)> GetLatestGithubRelease(UpdateChannel channel)
|
private static async Task<(string version, string downloadUrl, string releaseNotes, DateTime? releaseTime)> GetLatestGithubRelease(UpdateChannel channel)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
@@ -411,15 +411,23 @@ namespace Ink_Canvas.Helpers
|
|||||||
string version = json["tag_name"]?.ToString();
|
string version = json["tag_name"]?.ToString();
|
||||||
string releaseNotes = json["body"]?.ToString();
|
string releaseNotes = json["body"]?.ToString();
|
||||||
string downloadUrl = json["assets"]?.First?["browser_download_url"]?.ToString();
|
string downloadUrl = json["assets"]?.First?["browser_download_url"]?.ToString();
|
||||||
|
|
||||||
|
// 解析发布时间
|
||||||
|
DateTime? releaseTime = null;
|
||||||
|
if (json["published_at"] != null && DateTime.TryParse(json["published_at"].ToString(), out DateTime parsedTime))
|
||||||
|
{
|
||||||
|
releaseTime = parsedTime;
|
||||||
|
}
|
||||||
|
|
||||||
if (!string.IsNullOrEmpty(version) && !string.IsNullOrEmpty(downloadUrl))
|
if (!string.IsNullOrEmpty(version) && !string.IsNullOrEmpty(downloadUrl))
|
||||||
return (version, downloadUrl, releaseNotes);
|
return (version, downloadUrl, releaseNotes, releaseTime);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
LogHelper.WriteLogToFile($"AutoUpdate | GitHub Releases API 获取失败: {ex.Message}", LogHelper.LogType.Warning);
|
LogHelper.WriteLogToFile($"AutoUpdate | GitHub Releases API 获取失败: {ex.Message}", LogHelper.LogType.Warning);
|
||||||
}
|
}
|
||||||
return (null, null, null);
|
return (null, null, null, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 主要的更新检测方法(优先检测延迟,失败时自动切换线路组)
|
// 主要的更新检测方法(优先检测延迟,失败时自动切换线路组)
|
||||||
@@ -428,11 +436,17 @@ namespace Ink_Canvas.Helpers
|
|||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
// 记录更新检查时间
|
||||||
|
DeviceIdentifier.RecordUpdateCheck();
|
||||||
|
|
||||||
string localVersion = Assembly.GetExecutingAssembly().GetName().Version.ToString();
|
string localVersion = Assembly.GetExecutingAssembly().GetName().Version.ToString();
|
||||||
LogHelper.WriteLogToFile($"AutoUpdate | 本地版本: {localVersion}");
|
LogHelper.WriteLogToFile($"AutoUpdate | 本地版本: {localVersion}");
|
||||||
|
LogHelper.WriteLogToFile($"AutoUpdate | 设备ID: {DeviceIdentifier.GetDeviceId()}");
|
||||||
|
LogHelper.WriteLogToFile($"AutoUpdate | 更新优先级: {DeviceIdentifier.GetUpdatePriority()}");
|
||||||
LogHelper.WriteLogToFile($"AutoUpdate | 优先通过GitHub Releases API检测...");
|
LogHelper.WriteLogToFile($"AutoUpdate | 优先通过GitHub Releases API检测...");
|
||||||
|
|
||||||
// 1. 优先通过GitHub Releases API获取
|
// 1. 优先通过GitHub Releases API获取
|
||||||
var (apiVersion, _, apiReleaseNotes) = await GetLatestGithubRelease(channel);
|
var (apiVersion, _, apiReleaseNotes, apiReleaseTime) = await GetLatestGithubRelease(channel);
|
||||||
if (!string.IsNullOrEmpty(apiVersion))
|
if (!string.IsNullOrEmpty(apiVersion))
|
||||||
{
|
{
|
||||||
Version local = new Version(localVersion);
|
Version local = new Version(localVersion);
|
||||||
@@ -440,15 +454,29 @@ namespace Ink_Canvas.Helpers
|
|||||||
if (remote > local || alwaysGetRemote)
|
if (remote > local || alwaysGetRemote)
|
||||||
{
|
{
|
||||||
LogHelper.WriteLogToFile($"AutoUpdate | 通过GitHub Releases API发现新版本: {apiVersion}");
|
LogHelper.WriteLogToFile($"AutoUpdate | 通过GitHub Releases API发现新版本: {apiVersion}");
|
||||||
|
|
||||||
|
// 检查是否应该根据用户优先级推送更新
|
||||||
|
DateTime releaseTime = apiReleaseTime ?? DateTime.Now;
|
||||||
|
bool shouldPush = DeviceIdentifier.ShouldPushUpdate(apiVersion, releaseTime);
|
||||||
|
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 group = (await GetAvailableLineGroupsOrdered(channel)).FirstOrDefault();
|
||||||
|
return (null, group, apiReleaseNotes); // 返回null表示不推送
|
||||||
|
}
|
||||||
|
|
||||||
|
LogHelper.WriteLogToFile($"AutoUpdate | 根据用户优先级,推送更新 {apiVersion}");
|
||||||
// 只返回版本号和日志,不返回直链
|
// 只返回版本号和日志,不返回直链
|
||||||
var group = (await GetAvailableLineGroupsOrdered(channel)).FirstOrDefault();
|
var availableGroup = (await GetAvailableLineGroupsOrdered(channel)).FirstOrDefault();
|
||||||
return (apiVersion, group, apiReleaseNotes);
|
return (apiVersion, availableGroup, apiReleaseNotes);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
LogHelper.WriteLogToFile($"AutoUpdate | 当前版本已是最新 (GitHub Releases API)");
|
LogHelper.WriteLogToFile($"AutoUpdate | 当前版本已是最新 (GitHub Releases API)");
|
||||||
var group = (await GetAvailableLineGroupsOrdered(channel)).FirstOrDefault();
|
var availableGroup = (await GetAvailableLineGroupsOrdered(channel)).FirstOrDefault();
|
||||||
return (null, group, apiReleaseNotes);
|
return (null, availableGroup, apiReleaseNotes);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// 2. 回退到原有txt方案
|
// 2. 回退到原有txt方案
|
||||||
@@ -471,6 +499,17 @@ namespace Ink_Canvas.Helpers
|
|||||||
if (remote > local || alwaysGetRemote)
|
if (remote > local || alwaysGetRemote)
|
||||||
{
|
{
|
||||||
LogHelper.WriteLogToFile($"AutoUpdate | 发现新版本或强制获取: {remoteVersion}");
|
LogHelper.WriteLogToFile($"AutoUpdate | 发现新版本或强制获取: {remoteVersion}");
|
||||||
|
|
||||||
|
// 检查是否应该根据用户优先级推送更新
|
||||||
|
bool shouldPush = DeviceIdentifier.ShouldPushUpdate(remoteVersion, DateTime.Now);
|
||||||
|
if (!shouldPush)
|
||||||
|
{
|
||||||
|
var priority = DeviceIdentifier.GetUpdatePriority();
|
||||||
|
LogHelper.WriteLogToFile($"AutoUpdate | 根据用户优先级({priority}),暂不推送更新 {remoteVersion}");
|
||||||
|
return (null, group, null); // 返回null表示不推送
|
||||||
|
}
|
||||||
|
|
||||||
|
LogHelper.WriteLogToFile($"AutoUpdate | 根据用户优先级,推送更新 {remoteVersion}");
|
||||||
return (remoteVersion, group, null);
|
return (remoteVersion, group, null);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -2594,6 +2594,38 @@
|
|||||||
<TextBlock x:Name="AppVersionTextBlock" FontSize="18" FontWeight="Bold"
|
<TextBlock x:Name="AppVersionTextBlock" FontSize="18" FontWeight="Bold"
|
||||||
Text="1.X.X.X" />
|
Text="1.X.X.X" />
|
||||||
</ui:SimpleStackPanel>
|
</ui:SimpleStackPanel>
|
||||||
|
|
||||||
|
<!-- 设备信息 -->
|
||||||
|
<Border BorderBrush="#a1a1aa" BorderThickness="1" CornerRadius="8"
|
||||||
|
Background="#18181b" Padding="12">
|
||||||
|
<ui:SimpleStackPanel Spacing="8">
|
||||||
|
<TextBlock Text="设备信息" FontWeight="Bold" Foreground="#fafafa" FontSize="14" />
|
||||||
|
<ui:SimpleStackPanel Orientation="Horizontal">
|
||||||
|
<TextBlock Text="设备ID:" Foreground="#a1a1aa" FontSize="12" />
|
||||||
|
<TextBlock x:Name="DeviceIdTextBlock" Text="正在获取..." Foreground="#fafafa" FontSize="12" />
|
||||||
|
</ui:SimpleStackPanel>
|
||||||
|
<ui:SimpleStackPanel Orientation="Horizontal">
|
||||||
|
<TextBlock Text="使用频率:" Foreground="#a1a1aa" FontSize="12" />
|
||||||
|
<TextBlock x:Name="UsageFrequencyTextBlock" Text="正在获取..." Foreground="#fafafa" FontSize="12" />
|
||||||
|
</ui:SimpleStackPanel>
|
||||||
|
<ui:SimpleStackPanel Orientation="Horizontal">
|
||||||
|
<TextBlock Text="更新优先级:" Foreground="#a1a1aa" FontSize="12" />
|
||||||
|
<TextBlock x:Name="UpdatePriorityTextBlock" Text="正在获取..." Foreground="#fafafa" FontSize="12" />
|
||||||
|
</ui:SimpleStackPanel>
|
||||||
|
<ui:SimpleStackPanel Orientation="Horizontal">
|
||||||
|
<TextBlock Text="启动次数:" Foreground="#a1a1aa" FontSize="12" />
|
||||||
|
<TextBlock x:Name="LaunchCountTextBlock" Text="正在获取..." Foreground="#fafafa" FontSize="12" />
|
||||||
|
</ui:SimpleStackPanel>
|
||||||
|
<ui:SimpleStackPanel Orientation="Horizontal">
|
||||||
|
<TextBlock Text="总使用时长:" Foreground="#a1a1aa" FontSize="12" />
|
||||||
|
<TextBlock x:Name="TotalUsageTextBlock" Text="正在获取..." Foreground="#fafafa" FontSize="12" />
|
||||||
|
</ui:SimpleStackPanel>
|
||||||
|
<Button x:Name="RefreshDeviceInfoButton" Content="刷新设备信息"
|
||||||
|
Width="120" Height="30" Margin="0,8,0,0"
|
||||||
|
Click="RefreshDeviceInfo_Click" />
|
||||||
|
</ui:SimpleStackPanel>
|
||||||
|
</Border>
|
||||||
|
|
||||||
<TextBlock
|
<TextBlock
|
||||||
Text="# 使用和分发本软件前,请您应当且务必知晓相关开源协议,且您应当知晓本软件基于 https://github.com/WXRIW/Ink-Canvas 修改而成。"
|
Text="# 使用和分发本软件前,请您应当且务必知晓相关开源协议,且您应当知晓本软件基于 https://github.com/WXRIW/Ink-Canvas 修改而成。"
|
||||||
TextWrapping="Wrap" Foreground="#a1a1aa" />
|
TextWrapping="Wrap" Foreground="#a1a1aa" />
|
||||||
|
|||||||
@@ -854,6 +854,8 @@ namespace Ink_Canvas {
|
|||||||
{
|
{
|
||||||
// 切换到关于页面
|
// 切换到关于页面
|
||||||
ShowSettingsSection("about");
|
ShowSettingsSection("about");
|
||||||
|
// 刷新设备信息
|
||||||
|
RefreshDeviceInfo();
|
||||||
}
|
}
|
||||||
|
|
||||||
// 新增:个性化设置
|
// 新增:个性化设置
|
||||||
@@ -881,6 +883,99 @@ namespace Ink_Canvas {
|
|||||||
BorderSettingsMask.Background = null; // 确保清除蒙层背景
|
BorderSettingsMask.Background = null; // 确保清除蒙层背景
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 刷新设备信息按钮点击事件
|
||||||
|
/// </summary>
|
||||||
|
private void RefreshDeviceInfo_Click(object sender, RoutedEventArgs e)
|
||||||
|
{
|
||||||
|
RefreshDeviceInfo();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 刷新设备信息显示
|
||||||
|
/// </summary>
|
||||||
|
private void RefreshDeviceInfo()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
// 获取设备ID
|
||||||
|
string deviceId = DeviceIdentifier.GetDeviceId();
|
||||||
|
DeviceIdTextBlock.Text = deviceId;
|
||||||
|
|
||||||
|
// 获取使用频率
|
||||||
|
var usageFrequency = DeviceIdentifier.GetUsageFrequency();
|
||||||
|
string frequencyText;
|
||||||
|
switch (usageFrequency)
|
||||||
|
{
|
||||||
|
case DeviceIdentifier.UsageFrequency.High:
|
||||||
|
frequencyText = "高频用户";
|
||||||
|
break;
|
||||||
|
case DeviceIdentifier.UsageFrequency.Medium:
|
||||||
|
frequencyText = "中频用户";
|
||||||
|
break;
|
||||||
|
case DeviceIdentifier.UsageFrequency.Low:
|
||||||
|
frequencyText = "低频用户";
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
frequencyText = "未知";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
UsageFrequencyTextBlock.Text = frequencyText;
|
||||||
|
|
||||||
|
// 获取更新优先级
|
||||||
|
var updatePriority = DeviceIdentifier.GetUpdatePriority();
|
||||||
|
string priorityText;
|
||||||
|
switch (updatePriority)
|
||||||
|
{
|
||||||
|
case DeviceIdentifier.UpdatePriority.High:
|
||||||
|
priorityText = "高优先级(优先推送更新)";
|
||||||
|
break;
|
||||||
|
case DeviceIdentifier.UpdatePriority.Medium:
|
||||||
|
priorityText = "中优先级(正常推送更新)";
|
||||||
|
break;
|
||||||
|
case DeviceIdentifier.UpdatePriority.Low:
|
||||||
|
priorityText = "低优先级(延迟推送更新)";
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
priorityText = "未知";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
UpdatePriorityTextBlock.Text = priorityText;
|
||||||
|
|
||||||
|
// 获取使用统计
|
||||||
|
var (launchCount, totalMinutes, avgSession, _) = DeviceIdentifier.GetUsageStats();
|
||||||
|
LaunchCountTextBlock.Text = launchCount.ToString();
|
||||||
|
|
||||||
|
string totalUsageText;
|
||||||
|
if (totalMinutes < 60)
|
||||||
|
{
|
||||||
|
totalUsageText = $"{totalMinutes}分钟";
|
||||||
|
}
|
||||||
|
else if (totalMinutes < 1440)
|
||||||
|
{
|
||||||
|
totalUsageText = $"{totalMinutes / 60}小时{totalMinutes % 60}分钟";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
totalUsageText = $"{totalMinutes / 1440}天{(totalMinutes % 1440) / 60}小时";
|
||||||
|
}
|
||||||
|
TotalUsageTextBlock.Text = totalUsageText;
|
||||||
|
|
||||||
|
LogHelper.WriteLogToFile($"MainWindow | 设备信息已刷新 - ID: {deviceId}, 频率: {frequencyText}, 优先级: {priorityText}");
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
LogHelper.WriteLogToFile($"MainWindow | 刷新设备信息失败: {ex.Message}", LogHelper.LogType.Error);
|
||||||
|
|
||||||
|
// 显示错误信息
|
||||||
|
DeviceIdTextBlock.Text = "获取失败";
|
||||||
|
UsageFrequencyTextBlock.Text = "获取失败";
|
||||||
|
UpdatePriorityTextBlock.Text = "获取失败";
|
||||||
|
LaunchCountTextBlock.Text = "获取失败";
|
||||||
|
TotalUsageTextBlock.Text = "获取失败";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// 新增:折叠侧边栏
|
// 新增:折叠侧边栏
|
||||||
private void CollapseNavSidebar_Click(object sender, RoutedEventArgs e)
|
private void CollapseNavSidebar_Click(object sender, RoutedEventArgs e)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ TRACE;DEBUG;NETFRAMEWORK;NET472;;NET30_OR_GREATER;NET35_OR_GREATER;NET40_OR_GREA
|
|||||||
E:\ICC CE\ICC CE main\community\Ink Canvas\App.xaml
|
E:\ICC CE\ICC CE main\community\Ink Canvas\App.xaml
|
||||||
22-2143008179
|
22-2143008179
|
||||||
|
|
||||||
76-141727233
|
77-1409555929
|
||||||
471037513499
|
471037513499
|
||||||
Helpers\Plugins\BuiltIn\SuperLauncher\LauncherSettingsControl.xaml;Helpers\Plugins\BuiltIn\SuperLauncher\LauncherWindow.xaml;MainWindow.xaml;MainWindow_cs\MW_Eraser.xaml;Resources\DrawShapeImageDictionary.xaml;Resources\IconImageDictionary.xaml;Resources\SeewoImageDictionary.xaml;Resources\Styles\Dark.xaml;Resources\Styles\Light.xaml;Windows\AddCustomIconWindow.xaml;Windows\AddPickNameBackgroundWindow.xaml;Windows\CountdownTimerWindow.xaml;Windows\CustomIconWindow.xaml;Windows\CycleProcessBar.xaml;Windows\HasNewUpdateWindow.xaml;Windows\HistoryRollbackWindow.xaml;Windows\ManagePickNameBackgroundsWindow.xaml;Windows\NamesInputWindow.xaml;Windows\OperatingGuideWindow.xaml;Windows\PluginSettingsWindow.xaml;Windows\RandWindow.xaml;Windows\YesOrNoNotificationWindow.xaml;
|
Helpers\Plugins\BuiltIn\SuperLauncher\LauncherSettingsControl.xaml;Helpers\Plugins\BuiltIn\SuperLauncher\LauncherWindow.xaml;MainWindow.xaml;MainWindow_cs\MW_Eraser.xaml;Resources\DrawShapeImageDictionary.xaml;Resources\IconImageDictionary.xaml;Resources\SeewoImageDictionary.xaml;Resources\Styles\Dark.xaml;Resources\Styles\Light.xaml;Windows\AddCustomIconWindow.xaml;Windows\AddPickNameBackgroundWindow.xaml;Windows\CountdownTimerWindow.xaml;Windows\CustomIconWindow.xaml;Windows\CycleProcessBar.xaml;Windows\HasNewUpdateWindow.xaml;Windows\HistoryRollbackWindow.xaml;Windows\ManagePickNameBackgroundsWindow.xaml;Windows\NamesInputWindow.xaml;Windows\OperatingGuideWindow.xaml;Windows\PluginSettingsWindow.xaml;Windows\RandWindow.xaml;Windows\YesOrNoNotificationWindow.xaml;
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user