feat: 为过时的脚本仓库弹窗提醒,提供更新按钮并避免直接打开 (#2460)

This commit is contained in:
ShadowLemoon
2025-11-14 21:45:26 +08:00
committed by GitHub
parent 3e114d8d60
commit 00dc48d847
4 changed files with 283 additions and 6 deletions

View File

@@ -0,0 +1,85 @@
<ui:FluentWindow x:Class="BetterGenshinImpact.View.Windows.RepoUpdateDialog"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:ui="http://schemas.lepo.co/wpfui/2022/xaml"
Width="520"
Height="280"
MinWidth="400"
MinHeight="240"
ui:Design.Background="{DynamicResource ApplicationBackgroundBrush}"
ui:Design.Foreground="{DynamicResource TextFillColorPrimaryBrush}"
ExtendsContentIntoTitleBar="True"
FontFamily="{DynamicResource TextThemeFontFamily}"
ResizeMode="NoResize"
WindowStartupLocation="CenterOwner"
WindowStyle="SingleBorderWindow"
mc:Ignorable="d">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<!-- 标题栏 -->
<ui:TitleBar Grid.Row="0"
Title="{Binding Title, RelativeSource={RelativeSource AncestorType=Window}}"
ShowMaximize="False"
ShowMinimize="False">
<ui:TitleBar.Icon>
<ui:ImageIcon Source="pack://application:,,,/Resources/Images/logo.png" />
</ui:TitleBar.Icon>
</ui:TitleBar>
<!-- 内容区域 -->
<Grid Grid.Row="1" Margin="24,12,24,12">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<!-- 图标 -->
<ui:SymbolIcon Grid.Column="0"
Symbol="Warning24"
FontSize="48"
Foreground="{DynamicResource SystemFillColorAttentionBrush}"
VerticalAlignment="Center"
Margin="0,0,16,0" />
<!-- 消息内容 -->
<ui:TextBlock Grid.Column="1"
x:Name="MessageTextBlock"
TextAlignment="Left"
TextWrapping="Wrap"
FontSize="14"
VerticalAlignment="Center"
Foreground="{DynamicResource TextFillColorPrimaryBrush}" />
</Grid>
<!-- 按钮区域 -->
<StackPanel Grid.Row="2"
Orientation="Horizontal"
HorizontalAlignment="Center"
Margin="24,0,24,24">
<!-- 立即更新按钮 -->
<ui:Button x:Name="PrimaryButton"
Content="立即更新"
Appearance="Primary"
MinWidth="100"
Margin="0,0,8,0"
Click="PrimaryButton_Click" />
<!-- 直接打开按钮 -->
<ui:Button x:Name="SecondaryButton"
Content="直接打开"
Appearance="Secondary"
MinWidth="100"
IsEnabled="False"
Click="SecondaryButton_Click" />
</StackPanel>
</Grid>
</ui:FluentWindow>

View File

@@ -0,0 +1,125 @@
using System;
using System.Threading.Tasks;
using System.Windows;
using BetterGenshinImpact.Helpers.Ui;
using MessageBoxResult = Wpf.Ui.Controls.MessageBoxResult;
namespace BetterGenshinImpact.View.Windows;
/// <summary>
/// 仓库更新提示对话框
/// </summary>
public partial class RepoUpdateDialog : Wpf.Ui.Controls.FluentWindow
{
private System.Windows.Threading.DispatcherTimer? _dialogTimer;
private int _remainingSeconds;
private readonly int _daysSinceUpdate;
private TaskCompletionSource<MessageBoxResult>? _taskCompletionSource;
/// <summary>
/// 初始化仓库更新提示对话框
/// </summary>
/// <param name="daysSinceUpdate">距上次更新的天数</param>
public RepoUpdateDialog(int daysSinceUpdate)
{
_daysSinceUpdate = daysSinceUpdate;
InitializeComponent();
// 配置窗口属性
Title = "仓库更新提示";
MessageTextBlock.Text = $"脚本仓库已经 {daysSinceUpdate} 天未更新\n\n温馨提示\n脚本内容跟随仓库版本旧版仓库会订阅到旧版脚本。\n更新仓库后需要重新订阅脚本以更新脚本内容。\n\n是否立即更新";
Owner = Application.Current.MainWindow;
// 注册事件
SourceInitialized += OnSourceInitialized;
Loaded += OnLoaded;
Closed += OnClosed;
}
private void OnSourceInitialized(object? sender, EventArgs e)
{
WindowHelper.TryApplySystemBackdrop(this);
}
private void OnLoaded(object sender, RoutedEventArgs e)
{
// 计算倒计时秒数30 天为 5 秒,超过 30 天每多 2 天增加 1 秒
_remainingSeconds = 5 + (_daysSinceUpdate - 30) / 2;
SecondaryButton.Content = $"直接打开 ({_remainingSeconds}s)";
StartDialogTimer();
}
private void OnClosed(object? sender, EventArgs e)
{
StopDialogTimer();
_taskCompletionSource?.TrySetResult(MessageBoxResult.None);
}
/// <summary>
/// 显示对话框并等待结果
/// </summary>
public Task<MessageBoxResult> ShowDialogAsync()
{
_taskCompletionSource = new TaskCompletionSource<MessageBoxResult>();
ShowDialog();
return _taskCompletionSource.Task;
}
private void PrimaryButton_Click(object sender, RoutedEventArgs e)
{
_taskCompletionSource?.TrySetResult(MessageBoxResult.Primary);
Close();
}
private void SecondaryButton_Click(object sender, RoutedEventArgs e)
{
_taskCompletionSource?.TrySetResult(MessageBoxResult.Secondary);
Close();
}
/// <summary>
/// 启动对话框定时器
/// </summary>
private void StartDialogTimer()
{
// 创建定时器
_dialogTimer = new System.Windows.Threading.DispatcherTimer
{
Interval = TimeSpan.FromSeconds(1)
};
_dialogTimer.Tick += OnTimerTick;
_dialogTimer.Start();
}
private void OnTimerTick(object? sender, EventArgs e)
{
_remainingSeconds--;
if (_remainingSeconds > 0)
{
SecondaryButton.Content = $"直接打开 ({_remainingSeconds}s)";
}
else
{
// 倒计时结束,启用按钮
SecondaryButton.Content = "直接打开";
SecondaryButton.IsEnabled = true;
_dialogTimer?.Stop();
}
}
/// <summary>
/// 停止对话框定时器
/// </summary>
private void StopDialogTimer()
{
if (_dialogTimer != null)
{
_dialogTimer.Tick -= OnTimerTick;
_dialogTimer.Stop();
_dialogTimer = null;
}
}
}

View File

@@ -315,7 +315,8 @@
Command="{Binding OpenLocalScriptRepoCommand}"
Content="打开仓库"
Icon="{ui:SymbolIcon BookStar24}"
HorizontalAlignment="Center" />
HorizontalAlignment="Center"
IsEnabled="{Binding IsUpdating, Converter={StaticResource InverseBooleanConverter}}" />
</Grid>
</Grid>
</Grid>

View File

@@ -256,7 +256,7 @@ public partial class ScriptRepoWindow
IsUpdating = true;
UpdateProgressValue = 0;
UpdateProgressText = "准备更新,请耐心等待...";
// 执行更新
var (_, updated) = await ScriptRepoUpdater.Instance.UpdateCenterRepoByGit(repoUrl,
(path, steps, totalSteps) =>
@@ -289,11 +289,77 @@ public partial class ScriptRepoWindow
}
[RelayCommand]
private void OpenLocalScriptRepo()
private async Task OpenLocalScriptRepo()
{
TaskContext.Instance().Config.ScriptConfig.ScriptRepoHintDotVisible = false;
ScriptRepoUpdater.Instance.OpenLocalRepoInWebView();
Close();
// 检查是否需要提示用户更新仓库
var shouldContinue = await CheckAndPromptRepoUpdate();
if (shouldContinue)
{
TaskContext.Instance().Config.ScriptConfig.ScriptRepoHintDotVisible = false;
ScriptRepoUpdater.Instance.OpenLocalRepoInWebView();
Close();
}
}
/// <summary>
/// 检查仓库更新时间并提示用户
/// </summary>
/// <returns>是否继续打开仓库true: 继续打开, false: 取消操作)</returns>
private async Task<bool> CheckAndPromptRepoUpdate()
{
TimeSpan timeSinceUpdate;
try
{
// 检查仓库文件夹是否存在
if (!Directory.Exists(ScriptRepoUpdater.CenterRepoPath))
{
return true;
}
// 查找 repo.json 文件
var repoJsonPath = Directory.GetFiles(ScriptRepoUpdater.CenterRepoPath, "repo.json", SearchOption.AllDirectories).FirstOrDefault();
if (repoJsonPath == null || !File.Exists(repoJsonPath))
{
return true;
}
// 获取 repo.json 文件的最后修改时间
var repoJsonFile = new FileInfo(repoJsonPath);
DateTime lastUpdateTime = repoJsonFile.LastWriteTime;
// 检查是否超过 30 天
timeSinceUpdate = DateTime.Now - lastUpdateTime;
if (timeSinceUpdate.TotalDays <= 30)
{
return true;
}
}
catch
{
// 出现异常时,继续打开仓库
return true;
}
// 提示用户更新
var dialog = new RepoUpdateDialog((int)timeSinceUpdate.TotalDays);
var result = await dialog.ShowDialogAsync();
if (result == Wpf.Ui.Controls.MessageBoxResult.Primary)
{
// 用户选择"立即更新"
await UpdateRepo();
return false;
}
else if (result == Wpf.Ui.Controls.MessageBoxResult.Secondary)
{
// 用户选择"直接打开"
return true;
}
else
{
// 用户关闭对话框(点击 X 或按 ESC
return false;
}
}
[RelayCommand]