Files

413 lines
20 KiB
C#
Raw Permalink Normal View History

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();
}
}