初始化 monorepo: Go后端(7微服务) + Unity客户端(9模块) + 启动器 HTML5原型: Three.js 3D体素世界, Perlin噪声地形, 原版材质, 22种方块 Minecraft创造模式背包: 双栏布局, 拖拽移动物品, 方向性元件引脚 AI助搭策划文档 + 客户端/服务端骨架 + Docker Compose + CI
This commit is contained in:
@@ -0,0 +1,631 @@
|
||||
using System.Collections;
|
||||
using System.IO;
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Controls.Primitives;
|
||||
using System.Windows.Input;
|
||||
using System.Windows.Media;
|
||||
using System.Windows.Threading;
|
||||
using Microsoft.VisualBasic;
|
||||
using Microsoft.VisualBasic.FileIO;
|
||||
using PCL.Core.App;
|
||||
using PCL.Core.App.Configuration;
|
||||
using PCL.Core.App.Configuration.Storage;
|
||||
using FileSystem = Microsoft.VisualBasic.FileIO.FileSystem;
|
||||
using PCL.Core.App.Localization;
|
||||
using PCL.Core.UI;
|
||||
|
||||
namespace PCL;
|
||||
|
||||
public partial class PageSelectRight
|
||||
{
|
||||
private const int normalDelay = 75; // 正常输入延迟0.075秒
|
||||
private const int quickDelay = 50; // 清空搜索框延迟0.05秒
|
||||
private bool isRefreshing;
|
||||
|
||||
private DateTime lastInputTime = DateTime.MinValue;
|
||||
private DispatcherTimer reloadTimer;
|
||||
|
||||
// 窗口属性
|
||||
/// <summary>
|
||||
/// 是否显示隐藏的 Minecraft 实例。
|
||||
/// </summary>
|
||||
public bool showHidden = false;
|
||||
|
||||
public PageSelectRight()
|
||||
{
|
||||
InitializeComponent();
|
||||
PanVerSearchBox.HintText = Lang.Text("Select.Instance.Search.Hint");
|
||||
Loaded += PageSelectRight_Loaded;
|
||||
Unloaded += PageSelectRight_Unloaded;
|
||||
LoaderInit();
|
||||
}
|
||||
|
||||
// 窗口基础
|
||||
private void PageSelectRight_Loaded(object sender, RoutedEventArgs e)
|
||||
{
|
||||
ModLoader.LoaderFolderRun(ModInstanceList.mcInstanceListLoader, ModFolder.mcFolderSelected,
|
||||
ModLoader.LoaderFolderRunType.RunOnUpdated, 1, @"versions\");
|
||||
PanBack.ScrollToHome();
|
||||
PanVerSearchBox.TextChanged += (a, b) => PanVerSearchBox_TextChanged(a, (TextChangedEventArgs)b);
|
||||
|
||||
reloadTimer = new DispatcherTimer { Interval = TimeSpan.FromMilliseconds(normalDelay) };
|
||||
reloadTimer.Tick += ReloadTimer_Tick;
|
||||
}
|
||||
|
||||
private void PanVerSearchBox_TextChanged(object sender, TextChangedEventArgs e)
|
||||
{
|
||||
// 记录最后一次输入时间
|
||||
lastInputTime = DateTime.Now;
|
||||
|
||||
isRefreshing = false;
|
||||
|
||||
// 动态调整延迟时间
|
||||
if (string.IsNullOrWhiteSpace(PanVerSearchBox.Text))
|
||||
{
|
||||
if (reloadTimer.Interval.TotalMilliseconds != quickDelay)
|
||||
reloadTimer.Interval = TimeSpan.FromMilliseconds(quickDelay);
|
||||
}
|
||||
else if (reloadTimer.Interval.TotalMilliseconds != normalDelay)
|
||||
{
|
||||
reloadTimer.Interval = TimeSpan.FromMilliseconds(normalDelay);
|
||||
}
|
||||
|
||||
|
||||
if (!reloadTimer.IsEnabled) reloadTimer.Start();
|
||||
}
|
||||
|
||||
private void ReloadTimer_Tick(object sender, EventArgs e)
|
||||
{
|
||||
// 检查是否超过当前设定的延迟时间没有新输入
|
||||
var elapsed = (DateTime.Now - lastInputTime).TotalMilliseconds;
|
||||
var currentDelay = reloadTimer.Interval.TotalMilliseconds;
|
||||
|
||||
if (elapsed >= currentDelay && ModInstanceList.mcInstanceListLoader.State == ModBase.LoadState.Finished &&
|
||||
!isRefreshing)
|
||||
{
|
||||
isRefreshing = true;
|
||||
|
||||
// 确保在UI线程执行刷新
|
||||
Dispatcher.BeginInvoke(new Action(() =>
|
||||
{
|
||||
McInstanceListUI(ModInstanceList.mcInstanceListLoader);
|
||||
isRefreshing = false;
|
||||
}));
|
||||
reloadTimer.Stop();
|
||||
}
|
||||
}
|
||||
|
||||
private void PageSelectRight_Unloaded(object sender, RoutedEventArgs e)
|
||||
{
|
||||
// 清理计时器
|
||||
if (reloadTimer is not null)
|
||||
{
|
||||
reloadTimer.Stop();
|
||||
reloadTimer.Tick -= ReloadTimer_Tick;
|
||||
reloadTimer = null;
|
||||
}
|
||||
}
|
||||
|
||||
private void LoaderInit()
|
||||
{
|
||||
PageLoaderInit(Load, PanLoad, PanAllBack, null, ModInstanceList.mcInstanceListLoader,
|
||||
a => this.McInstanceListUI((ModLoader.LoaderTask<string, int>)a),
|
||||
autoRun: false);
|
||||
}
|
||||
|
||||
private void Load_Click(object sender, MouseButtonEventArgs e)
|
||||
{
|
||||
if (ModInstanceList.mcInstanceListLoader.State == ModBase.LoadState.Failed)
|
||||
ModLoader.LoaderFolderRun(ModInstanceList.mcInstanceListLoader, ModFolder.mcFolderSelected,
|
||||
ModLoader.LoaderFolderRunType.ForceRun, 1, @"versions\");
|
||||
}
|
||||
|
||||
#region 结果 UI 化
|
||||
|
||||
private void McInstanceListUI(ModLoader.LoaderTask<string, int> loader)
|
||||
{
|
||||
try
|
||||
{
|
||||
var path = loader.input;
|
||||
// 加载 UI
|
||||
PanMain.Children.Clear();
|
||||
|
||||
var hasVisibleFolders = false;
|
||||
var searchText = PanVerSearchBox.Text.Trim().ToLower(); // 获取搜索框文本
|
||||
var hasAnyResults = false;
|
||||
var originalHasInstances = ModInstanceList.mcInstanceList.ToArray().Any(c => c.Value.Count > 0);
|
||||
|
||||
// 搜索无结果时显示 PanEmptySearch
|
||||
PanEmptySearch.Visibility = Visibility.Collapsed; // 默认隐藏
|
||||
|
||||
foreach (var Card in ModInstanceList.mcInstanceList.ToArray())
|
||||
{
|
||||
if ((Card.Key == McInstanceCardType.Hidden) ^ showHidden)
|
||||
continue;
|
||||
var filteredInstances = Card.Value.Where(v =>
|
||||
{
|
||||
if (string.IsNullOrEmpty(searchText))
|
||||
return true;
|
||||
return v.Name.ToLower().Contains(searchText) ||
|
||||
(v.Desc is not null && v.Desc.ToLower().Contains(searchText)) || v.GetDefaultDescription()
|
||||
.Replace(",", "").ToLower().Trim().Contains(searchText);
|
||||
}).ToList();
|
||||
if (filteredInstances.Count == 0)
|
||||
continue;
|
||||
|
||||
hasVisibleFolders = true;
|
||||
hasAnyResults = true;
|
||||
if (filteredInstances.Count == 0)
|
||||
continue;
|
||||
hasVisibleFolders = true;
|
||||
|
||||
#region 确认卡片名称
|
||||
|
||||
var cardName = "";
|
||||
switch (Card.Key)
|
||||
{
|
||||
case McInstanceCardType.OriginalLike:
|
||||
{
|
||||
cardName = Lang.Text("Select.Instance.Card.Regular");
|
||||
break;
|
||||
}
|
||||
case McInstanceCardType.API:
|
||||
{
|
||||
var isForgeExists = false;
|
||||
var isNeoForgeExists = false;
|
||||
var isFabricExists = false;
|
||||
var isQuiltExists = false;
|
||||
var isLiteExists = false;
|
||||
var isCleanroomExists = false;
|
||||
var isLabyModExists = false;
|
||||
foreach (var instance in Card.Value)
|
||||
{
|
||||
if (!instance.IsLoaded)
|
||||
instance.Load();
|
||||
if (instance.Info.HasFabric)
|
||||
isFabricExists = true;
|
||||
if (instance.Info.HasQuilt)
|
||||
isQuiltExists = true;
|
||||
if (instance.Info.HasLiteLoader)
|
||||
isLiteExists = true;
|
||||
if (instance.Info.HasForge)
|
||||
isForgeExists = true;
|
||||
if (instance.Info.HasNeoForge)
|
||||
isNeoForgeExists = true;
|
||||
if (instance.Info.HasCleanroom)
|
||||
isCleanroomExists = true;
|
||||
if (instance.Info.HasLabyMod)
|
||||
isLabyModExists = true;
|
||||
}
|
||||
|
||||
if ((isLiteExists ? 1 : 0) + (isForgeExists ? 1 : 0) + (isFabricExists ? 1 : 0) +
|
||||
(isNeoForgeExists ? 1 : 0) + (isQuiltExists ? 1 : 0) + (isCleanroomExists ? 1 : 0) +
|
||||
(isLabyModExists ? 1 : 0) > 1)
|
||||
cardName = Lang.Text("Select.Instance.Card.Modable");
|
||||
else if (isForgeExists)
|
||||
cardName = Lang.Text("Select.Instance.Card.Forge");
|
||||
else if (isNeoForgeExists)
|
||||
cardName = Lang.Text("Select.Instance.Card.NeoForge");
|
||||
else if (isCleanroomExists)
|
||||
cardName = Lang.Text("Select.Instance.Card.Cleanroom");
|
||||
else if (isLabyModExists)
|
||||
cardName = Lang.Text("Select.Instance.Card.LabyMod");
|
||||
else if (isLiteExists)
|
||||
cardName = Lang.Text("Select.Instance.Card.LiteLoader");
|
||||
else if (isQuiltExists)
|
||||
cardName = Lang.Text("Select.Instance.Card.Quilt");
|
||||
else
|
||||
cardName = Lang.Text("Select.Instance.Card.Fabric");
|
||||
|
||||
break;
|
||||
}
|
||||
case McInstanceCardType.Error:
|
||||
{
|
||||
cardName = Lang.Text("Select.Instance.Card.Error");
|
||||
break;
|
||||
}
|
||||
case McInstanceCardType.Hidden:
|
||||
{
|
||||
cardName = Lang.Text("Select.Instance.Card.Hidden");
|
||||
break;
|
||||
}
|
||||
case McInstanceCardType.Rubbish:
|
||||
{
|
||||
cardName = Lang.Text("Select.Instance.Card.LessUsed");
|
||||
break;
|
||||
}
|
||||
case McInstanceCardType.Star:
|
||||
{
|
||||
cardName = Lang.Text("Select.Instance.Card.Favorites");
|
||||
break;
|
||||
}
|
||||
case McInstanceCardType.Fool:
|
||||
{
|
||||
cardName = Lang.Text("Select.Instance.Card.AprilFools");
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
{
|
||||
throw new ArgumentException($"未知的卡片种类({(int)Card.Key})");
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
// 建立控件
|
||||
var cardTitle = $"{cardName}{(Card.Key == McInstanceCardType.Star ? "" : $" ({Lang.Number(filteredInstances.Count, "N0")})")}";
|
||||
var newCard = new MyCard { Title = cardTitle, Margin = new Thickness(0d, 0d, 0d, 15d) };
|
||||
var newStack = new StackPanel
|
||||
{
|
||||
Margin = new Thickness(20d, MyCard.SwapedHeight, 18d, 0d),
|
||||
VerticalAlignment = VerticalAlignment.Top, RenderTransform = new TranslateTransform(0d, 0d),
|
||||
Tag = filteredInstances
|
||||
};
|
||||
newCard.Children.Add(newStack);
|
||||
newCard.SwapControl = newStack;
|
||||
PanMain.Children.Add(newCard);
|
||||
|
||||
// 确定卡片是否展开
|
||||
void PutMethod(StackPanel stack)
|
||||
{
|
||||
foreach (var item in (IEnumerable)stack.Tag)
|
||||
stack.Children.Add(McVersionListItem((McInstance)item));
|
||||
}
|
||||
|
||||
;
|
||||
if (Card.Key == McInstanceCardType.Rubbish ||
|
||||
Card.Key == McInstanceCardType.Error ||
|
||||
Card.Key == McInstanceCardType.Fool)
|
||||
{
|
||||
newCard.IsSwapped = true;
|
||||
newCard.InstallMethod = PutMethod;
|
||||
}
|
||||
else
|
||||
{
|
||||
MyCard.StackInstall(ref newStack, PutMethod);
|
||||
}
|
||||
}
|
||||
|
||||
// 若只有一个卡片,则强制展开
|
||||
if (PanMain.Children.Count == 1 && ((MyCard)PanMain.Children[0]).IsSwapped)
|
||||
((MyCard)PanMain.Children[0]).IsSwapped = false;
|
||||
|
||||
PanVerSearchBox.Visibility = hasVisibleFolders ? Visibility.Visible : Visibility.Collapsed;
|
||||
|
||||
// 判断应该显示哪一个页面
|
||||
if (!hasAnyResults)
|
||||
{
|
||||
if (!originalHasInstances)
|
||||
{
|
||||
// 完全没有实例的情况
|
||||
PanEmpty.Visibility = Visibility.Visible;
|
||||
PanBack.Visibility = Visibility.Collapsed;
|
||||
if (showHidden)
|
||||
{
|
||||
LabEmptyTitle.Text = Lang.Text("Select.Instance.Hidden.EmptyTitle");
|
||||
LabEmptyContent.Text = Lang.Text("Select.Instance.Hidden.EmptyMessage");
|
||||
BtnEmptyDownload.Visibility = Visibility.Collapsed;
|
||||
}
|
||||
else
|
||||
{
|
||||
LabEmptyTitle.Text = Lang.Text("Select.Instance.Empty.Title");
|
||||
LabEmptyContent.Text = Lang.Text("Select.Instance.Empty.Message");
|
||||
BtnEmptyDownload.Visibility =
|
||||
Config.Preference.Hide.PageDownload && !PageSetupUI.HiddenForceShow
|
||||
? Visibility.Collapsed
|
||||
: Visibility.Visible;
|
||||
}
|
||||
}
|
||||
// 有实例但搜索无结果的情况
|
||||
else if (showHidden && ModInstanceList.mcInstanceList.ToArray().Any(c =>
|
||||
c.Key == McInstanceCardType.Hidden && c.Value.Count > 0))
|
||||
{
|
||||
// 有隐藏实例但搜索无结果 - 显示搜索无结果提示
|
||||
PanVerSearchBox.Visibility = Visibility.Visible;
|
||||
PanEmpty.Visibility = Visibility.Collapsed;
|
||||
PanBack.Visibility = Visibility.Visible;
|
||||
PanEmptySearch.Visibility = Visibility.Visible;
|
||||
LabEmptySearchTitle.Text = Lang.Text("Select.Instance.Hidden.EmptySearchTitle");
|
||||
LabEmptySearchContent.Text = string.IsNullOrWhiteSpace(searchText)
|
||||
? Lang.Text("Select.Instance.Search.EmptyInput")
|
||||
: Lang.Text("Select.Instance.Search.NoHiddenResult", searchText);
|
||||
}
|
||||
else if (showHidden)
|
||||
{
|
||||
// 无隐藏实例 - 显示"无隐藏实例"提示
|
||||
PanEmpty.Visibility = Visibility.Visible;
|
||||
PanBack.Visibility = Visibility.Collapsed;
|
||||
LabEmptyTitle.Text = Lang.Text("Select.Instance.Hidden.EmptyTitle");
|
||||
LabEmptyContent.Text = Lang.Text("Select.Instance.Hidden.EmptyMessage");
|
||||
BtnEmptyDownload.Visibility = Visibility.Collapsed;
|
||||
PanVerSearchBox.Visibility = Visibility.Collapsed;
|
||||
}
|
||||
else
|
||||
{
|
||||
// 普通模式下的搜索无结果
|
||||
PanVerSearchBox.Visibility = Visibility.Visible;
|
||||
PanEmpty.Visibility = Visibility.Collapsed;
|
||||
PanBack.Visibility = Visibility.Visible;
|
||||
PanEmptySearch.Visibility = Visibility.Visible;
|
||||
LabEmptySearchTitle.Text = Lang.Text("Select.Instance.EmptySearch.Title");
|
||||
LabEmptySearchContent.Text = string.IsNullOrWhiteSpace(searchText)
|
||||
? Lang.Text("Select.Instance.Search.EmptyInput")
|
||||
: Lang.Text("Select.Instance.Search.NoResult", searchText);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
PanBack.Visibility = Visibility.Visible;
|
||||
PanEmpty.Visibility = Visibility.Collapsed;
|
||||
PanEmptySearch.Visibility = Visibility.Collapsed;
|
||||
} // 有结果时隐藏
|
||||
}
|
||||
|
||||
|
||||
catch (Exception ex)
|
||||
{
|
||||
ModBase.Log(
|
||||
ex,
|
||||
Lang.Text("Select.Instance.Error.UiUpdate"),
|
||||
ModBase.LogLevel.Feedback,
|
||||
userSummary: Lang.Text("Select.Instance.Error.UiUpdate"));
|
||||
}
|
||||
}
|
||||
|
||||
public static MyListItem McVersionListItem(McInstance mcInstance)
|
||||
{
|
||||
var newItem = new MyListItem
|
||||
{
|
||||
Title = mcInstance.Name, Info = mcInstance.Desc, Height = 42d, Tag = mcInstance, SnapsToDevicePixels = true,
|
||||
Type = MyListItem.CheckType.Clickable
|
||||
};
|
||||
var instanceInfo = mcInstance.Info;
|
||||
var tags = new List<string>();
|
||||
tags.Add(instanceInfo.VanillaName);
|
||||
if (instanceInfo.HasForge)
|
||||
tags.Add("Forge " + instanceInfo.Forge);
|
||||
else if (instanceInfo.HasNeoForge)
|
||||
tags.Add("NeoForge " + instanceInfo.NeoForge);
|
||||
else if (instanceInfo.HasCleanroom)
|
||||
tags.Add("Cleanroom " + instanceInfo.Cleanroom);
|
||||
else if (instanceInfo.HasLabyMod)
|
||||
tags.Add("LabyMod " + instanceInfo.LabyMod);
|
||||
else if (instanceInfo.HasQuilt)
|
||||
tags.Add("Quilt " + instanceInfo.Quilt);
|
||||
else if (instanceInfo.HasFabric) tags.Add("Fabric " + instanceInfo.Fabric);
|
||||
if (instanceInfo.HasLiteLoader)
|
||||
tags.Add("LiteLoader");
|
||||
if (instanceInfo.HasOptiFine)
|
||||
tags.Add("OptiFine " + instanceInfo.OptiFine);
|
||||
newItem.Tags = tags;
|
||||
try
|
||||
{
|
||||
if (mcInstance.Logo.EndsWith(@"PCL\Logo.png"))
|
||||
newItem.Logo = mcInstance.PathInstance + @"PCL\Logo.png"; // 修复老版本中,存储的自定义 Logo 使用完整路径,导致移动后无法加载的 Bug
|
||||
else
|
||||
newItem.Logo = mcInstance.Logo;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
ModBase.Log(
|
||||
ex,
|
||||
Lang.Text("Select.Instance.Error.IconLoad"),
|
||||
ModBase.LogLevel.Hint,
|
||||
userSummary: Lang.Text("Select.Instance.Error.IconLoad"));
|
||||
newItem.Logo = "pack://application:,,,/images/Blocks/RedstoneBlock.png";
|
||||
}
|
||||
|
||||
newItem.ContentHandler = McVersionListContent;
|
||||
return newItem;
|
||||
}
|
||||
|
||||
private static void McVersionListContent(MyListItem sender, EventArgs e)
|
||||
{
|
||||
var version = (McInstance)sender.Tag;
|
||||
// 注册点击事件
|
||||
sender.Click += (a, b) => Item_Click((MyListItem)a, b);
|
||||
// 图标按钮
|
||||
var btnStar = new MyIconButton();
|
||||
if (version.IsStar)
|
||||
{
|
||||
btnStar.ToolTip = Lang.Text("Select.Instance.Unfavorite");
|
||||
ToolTipService.SetPlacement(btnStar, PlacementMode.Center);
|
||||
ToolTipService.SetVerticalOffset(btnStar, 30d);
|
||||
ToolTipService.SetHorizontalOffset(btnStar, 2d);
|
||||
btnStar.LogoScale = 1.1d;
|
||||
btnStar.SvgIcon = "lucide/heart-filled";
|
||||
}
|
||||
else
|
||||
{
|
||||
btnStar.ToolTip = Lang.Text("Select.Instance.Favorite");
|
||||
ToolTipService.SetPlacement(btnStar, PlacementMode.Center);
|
||||
ToolTipService.SetVerticalOffset(btnStar, 30d);
|
||||
ToolTipService.SetHorizontalOffset(btnStar, 2d);
|
||||
btnStar.LogoScale = 1.1d;
|
||||
btnStar.SvgIcon = "lucide/heart";
|
||||
}
|
||||
|
||||
btnStar.Click += (_, _) =>
|
||||
{
|
||||
States.Instance.Starred[version.PathInstance] = !version.IsStar;
|
||||
ModInstanceList.mcInstanceListForceRefresh = true;
|
||||
ModLoader.LoaderFolderRun(ModInstanceList.mcInstanceListLoader, ModFolder.mcFolderSelected,
|
||||
ModLoader.LoaderFolderRunType.ForceRun, 1, @"versions\");
|
||||
};
|
||||
var btnOpenFolder = new MyIconButton { LogoScale = 1.1d, SvgIcon = "lucide/folder-open" };
|
||||
btnOpenFolder.ToolTip = Lang.Text("Select.Instance.OpenFolder");
|
||||
ToolTipService.SetPlacement(btnOpenFolder, PlacementMode.Center);
|
||||
ToolTipService.SetVerticalOffset(btnOpenFolder, 30d);
|
||||
ToolTipService.SetHorizontalOffset(btnOpenFolder, 2d);
|
||||
btnOpenFolder.Click += (_, _) => PageInstanceOverall.OpenVersionFolder(version);
|
||||
var btnDel = new MyIconButton { LogoScale = 1.1d, SvgIcon = "lucide/trash-2" };
|
||||
btnDel.ToolTip = Lang.Text("Common.Action.Delete");
|
||||
ToolTipService.SetPlacement(btnDel, PlacementMode.Center);
|
||||
ToolTipService.SetVerticalOffset(btnDel, 30d);
|
||||
ToolTipService.SetHorizontalOffset(btnDel, 2d);
|
||||
btnDel.Click += (_, _) => DeleteVersion(sender, version);
|
||||
if (version.state != McInstanceState.Error)
|
||||
{
|
||||
var btnCont = new MyIconButton { LogoScale = 1.1d, SvgIcon = "lucide/settings" };
|
||||
btnCont.ToolTip = Lang.Text("Select.Instance.Settings");
|
||||
ToolTipService.SetPlacement(btnCont, PlacementMode.Center);
|
||||
ToolTipService.SetVerticalOffset(btnCont, 30d);
|
||||
ToolTipService.SetHorizontalOffset(btnCont, 2d);
|
||||
btnCont.Click += (_, _) =>
|
||||
{
|
||||
PageInstanceLeft.McInstance = version;
|
||||
ModMain.frmMain.PageChange(FormMain.PageType.InstanceSetup);
|
||||
};
|
||||
sender.MouseRightButtonUp += (_, _) =>
|
||||
{
|
||||
PageInstanceLeft.McInstance = version;
|
||||
ModMain.frmMain.PageChange(FormMain.PageType.InstanceSetup);
|
||||
};
|
||||
sender.Buttons = new[] { btnStar, btnOpenFolder, btnDel, btnCont };
|
||||
}
|
||||
else
|
||||
{
|
||||
var btnCont = new MyIconButton { LogoScale = 1.15d, SvgIcon = "lucide/folder-open" };
|
||||
btnCont.ToolTip = Lang.Text("Common.Action.OpenFolder");
|
||||
ToolTipService.SetPlacement(btnCont, PlacementMode.Center);
|
||||
ToolTipService.SetVerticalOffset(btnCont, 30d);
|
||||
ToolTipService.SetHorizontalOffset(btnCont, 2d);
|
||||
btnCont.Click += (_, _) => PageInstanceOverall.OpenVersionFolder(version);
|
||||
sender.MouseRightButtonUp += (_, _) => PageInstanceOverall.OpenVersionFolder(version);
|
||||
sender.Buttons = new[] { btnStar, btnOpenFolder, btnDel, btnCont };
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region 页面事件
|
||||
|
||||
// 点击选项
|
||||
public static void Item_Click(MyListItem sender, EventArgs e)
|
||||
{
|
||||
var instance = (McInstance)sender.Tag;
|
||||
if (new McInstance(instance.PathInstance).Check())
|
||||
{
|
||||
// 正常实例
|
||||
ModInstanceList.McMcInstanceSelected = instance;
|
||||
States.Game.SelectedInstance = ModInstanceList.McMcInstanceSelected.Name;
|
||||
ModMain.frmMain.PageBack();
|
||||
}
|
||||
else
|
||||
{
|
||||
// 错误实例
|
||||
PageInstanceOverall.OpenVersionFolder(instance);
|
||||
}
|
||||
}
|
||||
|
||||
private void BtnDownload_Click(object sender, MouseButtonEventArgs e)
|
||||
{
|
||||
ModMain.frmMain.PageChange(FormMain.PageType.Download, FormMain.PageSubType.DownloadInstall);
|
||||
}
|
||||
|
||||
// 修改此代码时,同时修改 PageInstanceOverall 中的代码
|
||||
public static void DeleteVersion(MyListItem item, McInstance mcInstance)
|
||||
{
|
||||
try
|
||||
{
|
||||
var isShiftPressed = Keyboard.IsKeyDown(Key.LeftShift) || Keyboard.IsKeyDown(Key.RightShift);
|
||||
var isHintIndie = mcInstance.state != McInstanceState.Error &&
|
||||
(mcInstance.PathIndie ?? "") != (ModFolder.mcFolderSelected ?? "");
|
||||
var confirmMsg = isShiftPressed
|
||||
? Lang.Text("Select.Instance.Delete.ConfirmPermanentMessage", mcInstance.Name)
|
||||
: Lang.Text("Select.Instance.Delete.ConfirmMessage", mcInstance.Name);
|
||||
var confirmFullMsg = confirmMsg +
|
||||
(isHintIndie ? "\r\n" + Lang.Text("Select.Instance.Delete.IsolatedWarning") : "");
|
||||
switch (ModMain.MyMsgBox(confirmFullMsg, Lang.Text("Select.Instance.Delete.ConfirmTitle"),
|
||||
button2: Lang.Text("Common.Action.Cancel"), isWarn: true))
|
||||
{
|
||||
case 1:
|
||||
{
|
||||
ModBase.IniClearCache(Path.Combine(mcInstance.PathIndie, "options.txt"));
|
||||
((DynamicCacheConfigStorage)ConfigService.GetProvider(ConfigSource.GameInstance)).InvalidateCache(
|
||||
mcInstance.PathInstance);
|
||||
if (isShiftPressed)
|
||||
{
|
||||
ModBase.DeleteDirectory(mcInstance.PathInstance);
|
||||
HintService.Hint(Lang.Text("Select.Instance.Delete.PermanentSuccess", mcInstance.Name),
|
||||
HintType.Success);
|
||||
}
|
||||
else
|
||||
{
|
||||
FileSystem.DeleteDirectory(mcInstance.PathInstance, UIOption.AllDialogs,
|
||||
RecycleOption.SendToRecycleBin);
|
||||
HintService.Hint(Lang.Text("Select.Instance.Delete.RecycleBinSuccess", mcInstance.Name),
|
||||
HintType.Success);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
case 2:
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// 从 UI 中移除
|
||||
if (mcInstance.displayType == McInstanceCardType.Hidden || !mcInstance.IsStar)
|
||||
{
|
||||
// 仅出现在当前卡片
|
||||
var parent = (StackPanel)item.Parent;
|
||||
if (parent.Children.Count > 2) // 当前的项目与一个占位符
|
||||
{
|
||||
// 删除后还有剩
|
||||
var card = (MyCard)parent.Parent;
|
||||
card.Title = card.Title.Replace(Lang.Number(parent.Children.Count - 1, "N0"),
|
||||
Lang.Number(parent.Children.Count - 2, "N0")); // 有一个占位符
|
||||
parent.Children.Remove(item);
|
||||
if (ModInstanceList.McMcInstanceSelected is not null && (mcInstance.PathInstance ?? "") ==
|
||||
(ModInstanceList.McMcInstanceSelected.PathInstance ?? ""))
|
||||
// 删除当前实例就更改选择
|
||||
ModInstanceList.McMcInstanceSelected = (McInstance)((MyListItem)parent.Children[0]).Tag;
|
||||
ModLoader.LoaderFolderRun(ModInstanceList.mcInstanceListLoader, ModFolder.mcFolderSelected,
|
||||
ModLoader.LoaderFolderRunType.UpdateOnly, 1, @"versions\");
|
||||
}
|
||||
else
|
||||
{
|
||||
// 删除后没剩了
|
||||
ModLoader.LoaderFolderRun(ModInstanceList.mcInstanceListLoader, ModFolder.mcFolderSelected,
|
||||
ModLoader.LoaderFolderRunType.ForceRun, 1, @"versions\");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// 同时出现在当前卡片与收藏夹
|
||||
ModLoader.LoaderFolderRun(ModInstanceList.mcInstanceListLoader, ModFolder.mcFolderSelected,
|
||||
ModLoader.LoaderFolderRunType.ForceRun, 1, @"versions\");
|
||||
}
|
||||
}
|
||||
catch (OperationCanceledException ex)
|
||||
{
|
||||
ModBase.Log(ex, $"删除实例 {mcInstance.Name} 被主动取消");
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
ModBase.Log(
|
||||
ex,
|
||||
Lang.Text("Select.Instance.Error.Delete", mcInstance.Name),
|
||||
ModBase.LogLevel.Msgbox,
|
||||
userSummary: Lang.Text("Select.Instance.Error.Delete", mcInstance.Name));
|
||||
}
|
||||
}
|
||||
|
||||
public void BtnEmptyDownload_Loaded()
|
||||
{
|
||||
var newVisibility = (Config.Preference.Hide.PageDownload && !PageSetupUI.HiddenForceShow) || showHidden
|
||||
? Visibility.Collapsed
|
||||
: Visibility.Visible;
|
||||
if (BtnEmptyDownload.Visibility != newVisibility)
|
||||
{
|
||||
BtnEmptyDownload.Visibility = newVisibility;
|
||||
PanLoad.TriggerForceResize();
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
Reference in New Issue
Block a user