CI / Go Backend (push) Canceled after 0s
初始化 monorepo: Go后端(7微服务) + Unity客户端(9模块) + 启动器 HTML5原型: Three.js 3D体素世界, Perlin噪声地形, 原版材质, 22种方块 Minecraft创造模式背包: 双栏布局, 拖拽移动物品, 方向性元件引脚 AI助搭策划文档 + 客户端/服务端骨架 + Docker Compose + CI
413 lines
20 KiB
C#
413 lines
20 KiB
C#
using System.Windows;
|
||
using System.Windows.Controls;
|
||
using System.Windows.Threading;
|
||
using PCL.Network;
|
||
using PCL.Core.App.Localization;
|
||
|
||
namespace PCL;
|
||
|
||
public partial class PageSpeedLeft
|
||
{
|
||
private const int watcherInterval = 300;
|
||
|
||
// 定时器任务
|
||
private readonly Dictionary<string, MyCard> rightCards = new();
|
||
|
||
// 初始化
|
||
private bool isLoad;
|
||
|
||
public PageSpeedLeft()
|
||
{
|
||
InitializeComponent();
|
||
Loaded += Page_Loaded;
|
||
}
|
||
|
||
private void Page_Loaded(object sender, RoutedEventArgs e)
|
||
{
|
||
// 进入时就刷新一次显示
|
||
Watcher();
|
||
|
||
// 如果在页面切换动画的 “上一页消失” 部分已经完成了下载,就直接尝试返回
|
||
TryReturnToHome();
|
||
|
||
if (isLoad)
|
||
return;
|
||
isLoad = true;
|
||
|
||
// 监控定时器
|
||
var timer = new DispatcherTimer { Interval = new TimeSpan(0, 0, 0, 0, watcherInterval) };
|
||
timer.Tick += (_, _) => Watcher();
|
||
timer.Start();
|
||
|
||
// 非调试模式隐藏线程数
|
||
if (!ModBase.modeDebug)
|
||
{
|
||
RowDefinitions[12].Height = new GridLength(0d);
|
||
RowDefinitions[13].Height = new GridLength(0d);
|
||
RowDefinitions[14].Height = new GridLength(0d);
|
||
RowDefinitions[15].Height = new GridLength(0d);
|
||
}
|
||
}
|
||
|
||
private void Watcher()
|
||
{
|
||
if (ModMain.frmMain.pageCurrent != FormMain.PageType.TaskManager)
|
||
return;
|
||
try
|
||
{
|
||
#region 更新左边栏
|
||
|
||
if (!ModLoader.loaderTaskbar.Any())
|
||
{
|
||
// 无任务
|
||
LabProgress.Text = Lang.Number(1d, "P0");
|
||
LabSpeed.Text = ModBase.GetString(0) + "/s";
|
||
LabFile.Text = Lang.Number(0, "N0");
|
||
LabThread.Text = Lang.Number(0, "N0") + " / " + Lang.Number(ModNet.NetTaskThreadLimit, "N0");
|
||
}
|
||
else
|
||
{
|
||
// 有任务,输出基本信息
|
||
var tasks = ModLoader.loaderTaskbar.Where(l => l.show).ToList(); // 筛选掉启动 MC 的任务(#6270)
|
||
var rawPercent = tasks.Any()
|
||
? ModBase.MathClamp(
|
||
tasks.Average(l => l.Progress),
|
||
0, 1)
|
||
: 1d;
|
||
var predictText = Lang.Number(rawPercent, "P2");
|
||
LabProgress.Text = rawPercent > 0.999999d ? Lang.Number(1d, "P0") : predictText;
|
||
LabSpeed.Text = ModBase.GetString(ModNet.NetManager.Speed) + "/s";
|
||
LabFile.Text = ModNet.NetManager.FileRemain < 0 ? "0*" : Lang.Number(ModNet.NetManager.FileRemain, "N0");
|
||
LabThread.Text = Lang.Number(ModNet.NetManager.ThreadCount, "N0") + " / " +
|
||
Lang.Number(ModNet.NetTaskThreadLimit, "N0");
|
||
}
|
||
}
|
||
|
||
#endregion
|
||
|
||
catch (Exception ex)
|
||
{
|
||
ModBase.Log(
|
||
ex,
|
||
"任务管理左栏监视出错",
|
||
ModBase.LogLevel.Feedback,
|
||
userSummary: Lang.Text("Speed.Error.OperationFailed"));
|
||
}
|
||
|
||
if (ModMain.frmSpeedRight is null || ModMain.frmSpeedRight.PanMain is null)
|
||
return;
|
||
try
|
||
{
|
||
foreach (var Loader in ModLoader.loaderTaskbar.ToList())
|
||
TaskRefresh(Loader);
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
ModBase.Log(
|
||
ex,
|
||
"任务管理右栏监视出错",
|
||
ModBase.LogLevel.Feedback,
|
||
userSummary: Lang.Text("Speed.Error.OperationFailed"));
|
||
}
|
||
}
|
||
|
||
public void TaskRefresh(ModLoader.LoaderBase loader)
|
||
{
|
||
if (loader is null || !loader.show)
|
||
return;
|
||
try
|
||
{
|
||
// 获取实际加载器列表
|
||
var loaderList = ((ModLoader.LoaderCombo)loader).GetLoaderList();
|
||
if (rightCards.ContainsKey(loader.name))
|
||
{
|
||
// 已有此卡片
|
||
Grid card = rightCards[loader.name];
|
||
var newValue = loader.Progress + (double)loader.State;
|
||
if (ModBase.Val(card.Tag) == newValue)
|
||
return;
|
||
card.Tag = newValue;
|
||
if (card.Children.Count <= 3)
|
||
{
|
||
ModBase.Log("[Watcher] 元素不足的卡片:" + loader.name, ModBase.LogLevel.Debug);
|
||
return;
|
||
}
|
||
|
||
card = (Grid)card.Children[3];
|
||
try
|
||
{
|
||
switch (loader.State)
|
||
{
|
||
case ModBase.LoadState.Failed:
|
||
{
|
||
#region 失败,更新卡片
|
||
|
||
card.RowDefinitions.Clear();
|
||
card.Children.Clear();
|
||
card.Children.Add((UIElement)ModBase.GetObjectFromXML(
|
||
"<Path xmlns=\"http://schemas.microsoft.com/winfx/2006/xaml/presentation\" Stretch=\"Uniform\" Tag=\"Failed\" Data=\"F1 M2.5,0 L0,2.5 7.5,10 0,17.5 2.5,20 10,12.5 17.5,20 20,17.5 12.5,10 20,2.5 17.5,0 10,7.5 2.5,0Z\" Height=\"15\" Width=\"15\" HorizontalAlignment=\"Center\" Grid.Column=\"0\" Grid.Row=\"0\" Fill=\"{DynamicResource ColorBrush3}\" Margin=\"0,1,0,0\" VerticalAlignment=\"Top\"/>"));
|
||
var tb = (TextBlock)ModBase.GetObjectFromXML(
|
||
"<TextBlock xmlns=\"http://schemas.microsoft.com/winfx/2006/xaml/presentation\" TextWrapping=\"Wrap\" HorizontalAlignment=\"Left\" ToolTip=\"" + Lang.Text("Speed.Error.ClickToCopy") + "\" Grid.Column=\"1\" Grid.Row=\"0\" Margin=\"0,0,0,5\" />");
|
||
tb.Text = loader.Error.ToString();
|
||
tb.MouseLeftButtonDown += (sender, _) =>
|
||
{
|
||
ModBase.ClipboardSet(((TextBlock)sender).Text, false);
|
||
HintService.Hint(Lang.Text("Speed.Error.Copied"), HintType.Success);
|
||
};
|
||
card.Children.Add(tb);
|
||
break;
|
||
}
|
||
|
||
#endregion
|
||
|
||
case ModBase.LoadState.Finished:
|
||
{
|
||
#region 完成,销毁卡片并返回
|
||
|
||
ModAnimation.AniDispose((MyCard)card.Parent, true, _ => TryReturnToHome());
|
||
break;
|
||
}
|
||
|
||
#endregion
|
||
|
||
case ModBase.LoadState.Loading:
|
||
case ModBase.LoadState.Waiting:
|
||
{
|
||
#region 进度不同,更新卡片
|
||
|
||
do
|
||
{
|
||
try
|
||
{
|
||
if (card.Children.Count < loaderList.Count * 2)
|
||
{
|
||
ModBase.Log(
|
||
$"[Watcher] 刷新任务管理卡片 {loader.name} 失败:卡片中仅有 {card.Children.Count} 个子项,要求至少有 {loaderList.Count * 2} 个子项",
|
||
ModBase.LogLevel.Debug);
|
||
break;
|
||
}
|
||
|
||
var row = 0;
|
||
foreach (var SubTask in loaderList)
|
||
{
|
||
switch (SubTask.State)
|
||
{
|
||
case ModBase.LoadState.Waiting:
|
||
{
|
||
if ((string)((FrameworkElement)card.Children[row * 2]).Tag != "Waiting")
|
||
{
|
||
card.Children.RemoveAt(row * 2);
|
||
card.Children.Insert(row * 2,
|
||
(UIElement)ModBase.GetObjectFromXML(
|
||
"<Path xmlns=\"http://schemas.microsoft.com/winfx/2006/xaml/presentation\" xmlns:x=\"http://schemas.microsoft.com/winfx/2006/xaml\" xmlns:local=\"clr-namespace:PCL;assembly=Plain Craft Launcher 2\" Stretch=\"Uniform\" Tag=\"Waiting\" Data=\"F1 M5,0 a5,5 360 1 0 0,0.0001 m15,0 a5,5 360 1 0 0,0.0001 m15,0 a5,5 360 1 0 0,0.0001 Z\" Width=\"18\" HorizontalAlignment=\"Center\" Grid.Column=\"0\" Grid.Row=\"" +
|
||
row +
|
||
"\" Fill=\"{DynamicResource ColorBrush3}\" Margin=\"0,7,0,0\" VerticalAlignment=\"Top\" Height=\"6\"/>"));
|
||
}
|
||
|
||
break;
|
||
}
|
||
case ModBase.LoadState.Loading:
|
||
{
|
||
if ((string)((FrameworkElement)card.Children[row * 2]).Tag != "Loading")
|
||
{
|
||
card.Children.RemoveAt(row * 2);
|
||
card.Children.Insert(row * 2,
|
||
(UIElement)ModBase.GetObjectFromXML(
|
||
$"<TextBlock xmlns=\"http://schemas.microsoft.com/winfx/2006/xaml/presentation\" xmlns:x=\"http://schemas.microsoft.com/winfx/2006/xaml\" xmlns:local=\"clr-namespace:PCL;assembly=Plain Craft Launcher 2\" Text=\"{Lang.Number(SubTask.Progress, "P0")}\" Tag=\"Loading\" HorizontalAlignment=\"Center\" Grid.Column=\"0\" Grid.Row=\"{row}\" Foreground=\"{{DynamicResource ColorBrush3}}\"/>"));
|
||
}
|
||
else
|
||
{
|
||
((TextBlock)card.Children[row * 2]).Text =
|
||
$"{Lang.Number(SubTask.Progress, "P0")}";
|
||
}
|
||
|
||
break;
|
||
}
|
||
case ModBase.LoadState.Finished:
|
||
{
|
||
if ((string)((FrameworkElement)card.Children[row * 2]).Tag != "Finished")
|
||
{
|
||
card.Children.RemoveAt(row * 2);
|
||
card.Children.Insert(row * 2,
|
||
(UIElement)ModBase.GetObjectFromXML(
|
||
$"<Path xmlns=\"http://schemas.microsoft.com/winfx/2006/xaml/presentation\" xmlns:x=\"http://schemas.microsoft.com/winfx/2006/xaml\" xmlns:local=\"clr-namespace:PCL;assembly=Plain Craft Launcher 2\" Stretch=\"Uniform\" Tag=\"Finished\" Data=\"F1 M 23.7501,33.25L 34.8334,44.3333L 52.2499,22.1668L 56.9999,26.9168L 34.8334,53.8333L 19.0001,38L 23.7501,33.25 Z\" Height=\"16\" Width=\"15\" HorizontalAlignment=\"Center\" Grid.Column=\"0\" Grid.Row=\"{row}\" Fill=\"{{DynamicResource ColorBrush3}}\" Margin=\"0,3,0,0\" VerticalAlignment=\"Top\"/>"));
|
||
}
|
||
|
||
break;
|
||
}
|
||
}
|
||
|
||
row += 1;
|
||
}
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
ModBase.Log(
|
||
ex,
|
||
$"刷新任务管理卡片 {loader.name} 失败",
|
||
ModBase.LogLevel.Feedback,
|
||
userSummary: Lang.Text("Speed.Error.OperationFailed"));
|
||
}
|
||
} while (false);
|
||
|
||
break;
|
||
}
|
||
|
||
#endregion
|
||
}
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
ModBase.Log(
|
||
ex,
|
||
$"更新任务管理显示失败({loader.State})",
|
||
ModBase.LogLevel.Feedback,
|
||
userSummary: Lang.Text("Speed.Error.OperationFailed"));
|
||
}
|
||
}
|
||
else if (!(loader.State == ModBase.LoadState.Aborted || loader.State == ModBase.LoadState.Finished))
|
||
{
|
||
try
|
||
{
|
||
#region 没有卡片且未中断或完成,添加新的卡片
|
||
|
||
var cardXAML = $@"
|
||
<local:MyCard xmlns=""http://schemas.microsoft.com/winfx/2006/xaml/presentation"" xmlns:x=""http://schemas.microsoft.com/winfx/2006/xaml"" xmlns:local=""clr-namespace:PCL;assembly=Plain Craft Launcher 2""
|
||
Tag=""{loader.Progress + (double)loader.State}"" Title=""{ModBase.EscapeXML(loader.name)}"" Margin=""0,0,0,15"">
|
||
<Grid Margin=""14,40,15,10"">
|
||
<Grid.ColumnDefinitions>
|
||
<ColumnDefinition Width=""50""/>
|
||
<ColumnDefinition/>
|
||
</Grid.ColumnDefinitions>
|
||
<Grid.RowDefinitions>";
|
||
foreach (var SubTask in loaderList)
|
||
cardXAML += "<RowDefinition Height=\"26\"/>";
|
||
cardXAML += "</Grid.RowDefinitions>";
|
||
var row = 0;
|
||
foreach (var SubTask in loaderList)
|
||
{
|
||
switch (SubTask.State)
|
||
{
|
||
case ModBase.LoadState.Waiting:
|
||
{
|
||
cardXAML +=
|
||
$"<Path Stretch=\"Uniform\" Tag=\"Waiting\" Data=\"F1 M5,0 a5,5 360 1 0 0,0.0001 m15,0 a5,5 360 1 0 0,0.0001 m15,0 a5,5 360 1 0 0,0.0001 Z\" Width=\"18\" HorizontalAlignment=\"Center\" Grid.Column=\"0\" Grid.Row=\"{row}\" Fill=\"{{DynamicResource ColorBrush3}}\" Margin=\"0,7,0,0\" VerticalAlignment=\"Top\" Height=\"6\"/>";
|
||
break;
|
||
}
|
||
case ModBase.LoadState.Loading:
|
||
{
|
||
cardXAML += $"<TextBlock Text=\"{Lang.Number(SubTask.Progress, "P0")}\" Tag=\"Loading\" HorizontalAlignment=\"Center\" Grid.Column=\"0\" Grid.Row=\"{row}\" Foreground=\"{{DynamicResource ColorBrush3}}\" />";
|
||
break;
|
||
}
|
||
case ModBase.LoadState.Finished:
|
||
{
|
||
cardXAML +=
|
||
$"<Path Stretch=\"Uniform\" Tag=\"Finished\" Data=\"F1 M 23.7501,33.25L 34.8334,44.3333L 52.2499,22.1668L 56.9999,26.9168L 34.8334,53.8333L 19.0001,38L 23.7501,33.25 Z\" Height=\"16\" Width=\"15\" HorizontalAlignment=\"Center\" Grid.Column=\"0\" Grid.Row=\"{row}\" Fill=\"{{DynamicResource ColorBrush3}}\" Margin=\"0,3,0,0\" VerticalAlignment=\"Top\"/>";
|
||
break;
|
||
}
|
||
|
||
default:
|
||
{
|
||
cardXAML +=
|
||
$"<Path Stretch=\"Uniform\" Tag=\"Failed\" Data=\"F1 M2.5,0 L0,2.5 7.5,10 0,17.5 2.5,20 10,12.5 17.5,20 20,17.5 12.5,10 20,2.5 17.5,0 10,7.5 2.5,0Z\" Height=\"15\" Width=\"15\" HorizontalAlignment=\"Center\" Grid.Column=\"0\" Grid.Row=\"{row}\" Fill=\"{{DynamicResource ColorBrush3}}\" Margin=\"0,1,0,0\" VerticalAlignment=\"Top\"/>";
|
||
break;
|
||
}
|
||
}
|
||
|
||
cardXAML += $"<TextBlock Text=\"{ModBase.EscapeXML(SubTask.name)}\" HorizontalAlignment=\"Left\" Grid.Column=\"1\" Grid.Row=\"{row}\"/>";
|
||
row += 1;
|
||
}
|
||
|
||
cardXAML += "</Grid></local:MyCard>";
|
||
// 实例化控件
|
||
MyCard card;
|
||
try
|
||
{
|
||
card = (MyCard)ModBase.GetObjectFromXML(cardXAML);
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
ModBase.Log(ex, "新建任务管理卡片失败");
|
||
ModBase.Log($"出错的卡片内容:\r\n{cardXAML}");
|
||
throw;
|
||
}
|
||
|
||
ModMain.frmSpeedRight.PanMain.Children.Insert(0, card);
|
||
rightCards.Add(loader.name, card);
|
||
ModBase.Log($"[Watcher] 新建任务管理卡片:{loader.name}");
|
||
// 添加取消按钮
|
||
var cancel = new MyIconButton
|
||
{
|
||
Name = "BtnCancel",
|
||
SvgIcon = "lucide/x", Height = 25d, Width = 25d,
|
||
Margin = new Thickness(0d, 10d, 10d, 0d), LogoScale = 1.1d,
|
||
HorizontalAlignment = HorizontalAlignment.Right, VerticalAlignment = VerticalAlignment.Top
|
||
};
|
||
card.Children.Add(cancel);
|
||
cancel.Click += (sender, e) =>
|
||
{
|
||
ModAnimation.AniDispose((MyIconButton)sender, false);
|
||
ModAnimation.AniDispose(card, true, _ =>
|
||
{
|
||
if (ModMain.frmSpeedRight.PanMain.Children.Count == 0 &&
|
||
ModMain.frmMain.pageCurrent == FormMain.PageType.TaskManager)
|
||
ModMain.frmMain.PageBack();
|
||
});
|
||
rightCards.Remove(loader.name);
|
||
ModLoader.loaderTaskbar.Remove(loader);
|
||
ModBase.Log($"[Taskbar] 关闭任务管理卡片:{loader.name},且移出任务列表");
|
||
ModBase.RunInThread(() => loader.Abort());
|
||
};
|
||
// 如果已经失败,再刷新一次,修改成失败的控件
|
||
if (loader.State == ModBase.LoadState.Failed)
|
||
{
|
||
card.Tag = null; // 避免重复导致刷新无效
|
||
TaskRefresh(loader);
|
||
}
|
||
}
|
||
|
||
#endregion
|
||
|
||
catch (Exception ex)
|
||
{
|
||
ModBase.Log(
|
||
ex,
|
||
"添加任务管理卡片失败",
|
||
ModBase.LogLevel.Feedback,
|
||
userSummary: Lang.Text("Speed.Error.OperationFailed"));
|
||
}
|
||
}
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
ModBase.Log(
|
||
ex,
|
||
"刷新任务管理显示失败",
|
||
ModBase.LogLevel.Feedback,
|
||
userSummary: Lang.Text("Speed.Error.OperationFailed"));
|
||
}
|
||
}
|
||
|
||
public void TaskRemove(ModLoader.LoaderBase loader)
|
||
{
|
||
if (rightCards.ContainsKey(loader.name))
|
||
ModBase.RunInUiWait(() =>
|
||
{
|
||
// 移除已有的卡片
|
||
Grid card = rightCards[loader.name];
|
||
ModMain.frmSpeedRight.PanMain.Children.Remove(card);
|
||
rightCards.Remove(loader.name);
|
||
ModBase.Log($"[Watcher] 移除任务管理卡片:{loader.name}");
|
||
});
|
||
}
|
||
|
||
/// <summary>
|
||
/// 若没有任务,尝试返回主页。
|
||
/// </summary>
|
||
private void TryReturnToHome()
|
||
{
|
||
if (ModMain.frmSpeedRight.PanMain.Children.Count == 0 &&
|
||
ModMain.frmMain.pageCurrent == FormMain.PageType.TaskManager) ModMain.frmMain.PageBack();
|
||
}
|
||
}
|