Skip to content
Open
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions PCL.Core/App/Localization/Languages/en-US.xaml
Original file line number Diff line number Diff line change
Expand Up @@ -757,6 +757,7 @@
<sys:String x:Key="Download.Version.LoadingList">Getting version list...</sys:String>
<sys:String x:Key="Download.Version.Changelog">Changelog</sys:String>
<sys:String x:Key="Download.Version.SaveAs">Save as</sys:String>
<sys:String x:Key="Download.Version.Download">Download</sys:String>
<sys:String x:Key="Download.Version.DownloadServer">Download server</sys:String>
<sys:String x:Key="Download.Version.ViewAllVersions">Show all versions</sys:String>
<sys:String x:Key="Download.Version.SaveInstaller">Save installer</sys:String>
Expand Down Expand Up @@ -1057,6 +1058,11 @@
<sys:String x:Key="Download.Comp.Detail.FileList.Updated">Updated {0}</sys:String>
<sys:String x:Key="Download.Comp.Detail.FileList.RequiredDependencies">Required dependencies</sys:String>
<sys:String x:Key="Download.Comp.Detail.FileList.OptionalDependencies">Optional dependencies</sys:String>
<sys:String x:Key="Download.Comp.Detail.VersionPopup.Title">Version details</sys:String>
<sys:String x:Key="Download.Comp.Detail.VersionPopup.ButtonInstall">Install to current instance</sys:String>
<sys:String x:Key="Download.Comp.Detail.VersionPopup.ButtonSaveAs">Choose download location</sys:String>
<sys:String x:Key="Download.Comp.Detail.VersionPopup.NoInstance">Please select a Minecraft instance first</sys:String>
<sys:String x:Key="Download.Comp.Detail.VersionPopup.NoDeps">None</sys:String>
<sys:String x:Key="Download.Comp.Detail.FileList.VersionList">Version list</sys:String>
<sys:String x:Key="Download.Comp.Detail.FileList.ReleaseType.Release">Release</sys:String>
<sys:String x:Key="Download.Comp.Detail.FileList.ReleaseType.Beta">Beta</sys:String>
Expand Down
6 changes: 6 additions & 0 deletions PCL.Core/App/Localization/Languages/zh-CN.xaml
Original file line number Diff line number Diff line change
Expand Up @@ -803,6 +803,7 @@
<sys:String x:Key="Download.Version.Fresh.Stable">最新稳定版</sys:String>
<sys:String x:Key="Download.Version.Fresh.Development">最新测试版</sys:String>
<sys:String x:Key="Download.Version.SelectSaveLocation">选择保存位置</sys:String>
<sys:String x:Key="Download.Version.Download">下载</sys:String>
<sys:String x:Key="Download.Version.Installer.Fabric.Filter">Fabric 安装器 (*.jar)|*.jar</sys:String>
<sys:String x:Key="Download.Version.Installer.LegacyFabric.Filter">LegacyFabric 安装器 (*.jar)|*.jar</sys:String>
<sys:String x:Key="Download.Version.Installer.Quilt.Filter">Quilt 安装器 (*.jar)|*.jar</sys:String>
Expand Down Expand Up @@ -1057,6 +1058,11 @@
<sys:String x:Key="Download.Comp.Detail.FileList.Updated">更新于 {0}</sys:String>
<sys:String x:Key="Download.Comp.Detail.FileList.RequiredDependencies">必要前置资源</sys:String>
<sys:String x:Key="Download.Comp.Detail.FileList.OptionalDependencies">可选前置资源</sys:String>
<sys:String x:Key="Download.Comp.Detail.VersionPopup.Title">版本详情</sys:String>
<sys:String x:Key="Download.Comp.Detail.VersionPopup.ButtonInstall">安装到当前实例</sys:String>
<sys:String x:Key="Download.Comp.Detail.VersionPopup.ButtonSaveAs">选择下载位置</sys:String>
<sys:String x:Key="Download.Comp.Detail.VersionPopup.NoInstance">请先选择一个 Minecraft 实例</sys:String>
<sys:String x:Key="Download.Comp.Detail.VersionPopup.NoDeps">无</sys:String>
<sys:String x:Key="Download.Comp.Detail.FileList.VersionList">版本列表</sys:String>
<sys:String x:Key="Download.Comp.Detail.FileList.ReleaseType.Release">正式版</sys:String>
<sys:String x:Key="Download.Comp.Detail.FileList.ReleaseType.Beta">测试版</sys:String>
Expand Down
3 changes: 3 additions & 0 deletions Plain Craft Launcher 2/Controls/MyListItem.xaml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ public partial class MyListItem : IMyRadio
public event IMyRadio.ChangedEventHandler? Changed;

public event ClickEventHandler? Click;
public event ClickEventHandler? RightClick;
public event LogoClickEventHandler? LogoClick;

public void RefreshColor(object sender, EventArgs e)
Expand Down Expand Up @@ -474,6 +475,8 @@ public MyListItem()
PreviewMouseLeftButtonDown += Button_MouseDown;
MouseLeave += Button_MouseLeave;
PreviewMouseLeftButtonUp += Button_MouseLeave;
// 右键事件(用于触发 RightClick,例如模组版本项右键直接另存为)
PreviewMouseRightButtonUp += (_, e) => RightClick?.Invoke(this, e);
MouseEnter += RefreshColor;
MouseLeave += RefreshColor;
MouseLeftButtonDown += RefreshColor;
Expand Down
53 changes: 53 additions & 0 deletions Plain Craft Launcher 2/Controls/MyMsg/ModDependencyMsgBox.xaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
<Grid x:Class="PCL.ModDependencyMsgBox"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:my="clr-namespace:PCL"
RenderTransformOrigin="0,0.5" UseLayoutRounding="True" SnapsToDevicePixels="True" MinWidth="420" MaxWidth="620"
HorizontalAlignment="Center" VerticalAlignment="Center" Margin="25">
<Grid.RenderTransform>
<TransformGroup>
<RotateTransform x:Name="TransformRotate" Angle="-4" />
<TranslateTransform x:Name="TransformPos" X="0" Y="40" />
</TransformGroup>
</Grid.RenderTransform>
<Border Name="PanBorder" CornerRadius="7" Background="{DynamicResource ColorBrushBackground}">
<Border.Effect>
<DropShadowEffect Color="{DynamicResource ColorObjectMsgBoxShadow}" BlurRadius="20" ShadowDepth="2"
RenderingBias="Performance" Opacity="0.8" x:Name="EffectShadow" />
</Border.Effect>
<Grid Name="PanMain" VerticalAlignment="Top" Margin="22,22,22,23">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="2" />
<RowDefinition Height="13" />
<RowDefinition Height="1*" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<TextBlock Grid.Row="0" FontSize="23" TextTrimming="None" Foreground="{DynamicResource ColorBrush2}"
HorizontalAlignment="Left" Name="LabTitle" Margin="7,-1,70,9" Text="版本详情"
VerticalAlignment="Top" SnapsToDevicePixels="False" UseLayoutRounding="False" />
<Rectangle x:Name="ShapeLine" Grid.Row="1" Height="2" Fill="{Binding Foreground, ElementName=LabTitle}" />
<my:MyScrollViewer Grid.Row="3" VerticalAlignment="Top" x:Name="PanCaption" Margin="0,0,0,17"
Padding="7,0,15,0" MaxHeight="460"
VerticalScrollBarVisibility="Auto" HorizontalScrollBarVisibility="Disabled"
DeltaMult="0.7">
<StackPanel Orientation="Vertical">
<TextBlock Name="LabVersionInfo" FontSize="13" TextWrapping="Wrap" Margin="2,0,2,12" Opacity="0.8" />
<TextBlock Name="LabReqTitle" FontSize="14" FontWeight="Bold" Margin="2,8,0,4" />
<StackPanel Name="PanReqDeps" Orientation="Vertical" />
<TextBlock Name="LabOptTitle" FontSize="14" FontWeight="Bold" Margin="2,8,0,4" />
<StackPanel Name="PanOptDeps" Orientation="Vertical" />
</StackPanel>
</my:MyScrollViewer>
<StackPanel Grid.Row="4" Name="PanBtn" VerticalAlignment="Top" HorizontalAlignment="Right"
Margin="150,0,8,0" Orientation="Horizontal">
<my:MyButton ColorType="Normal" x:FieldModifier="public" Text="安装到当前实例" x:Name="Btn1" Margin="12,0,0,0"
TextPadding="7" SnapsToDevicePixels="False" Padding="5,0" UseLayoutRounding="False" />
<my:MyButton ColorType="Normal" x:FieldModifier="public" Text="选择下载位置" x:Name="Btn2" Margin="12,0,0,0"
TextPadding="7" SnapsToDevicePixels="False" Padding="5,0" UseLayoutRounding="False" />
<my:MyButton ColorType="Normal" x:FieldModifier="public" Text="取消" x:Name="Btn3" Margin="12,0,0,0"
TextPadding="7" SnapsToDevicePixels="False" Padding="5,0" UseLayoutRounding="False" />
</StackPanel>
</Grid>
</Border>
</Grid>
208 changes: 208 additions & 0 deletions Plain Craft Launcher 2/Controls/MyMsg/ModDependencyMsgBox.xaml.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,208 @@
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Interop;
using PCL.Core.App.Localization;
using PCL.Core.UI.Controls;

namespace PCL;

/// <summary>
/// 模组版本的「前置详情」弹窗:展示该版本的版本信息、必要前置 / 可选前置,
/// 并提供「安装到当前实例」/「选择下载位置」两个动作。点击某个前置项会关闭弹窗并返回该前置工程。
/// 布局由 XAML 定义,调用方只需传入 CompFile 数据(由 <see cref="ModMain.ModDependencyMsgBox" /> 触发)。
/// </summary>
public partial class ModDependencyMsgBox
{
private readonly ModMain.MyMsgBoxConverter myConverter;
private readonly int uuid = ModBase.GetUuid();

public ModDependencyMsgBox(ModMain.MyMsgBoxConverter converter)
{
try
{
InitializeComponent();
AppendUniqueNameSuffix(Btn1);
AppendUniqueNameSuffix(Btn2);
AppendUniqueNameSuffix(Btn3);
myConverter = converter;
LabTitle.Text = Lang.Text("Download.Comp.Detail.VersionPopup.Title");
Btn1.Text = Lang.Text("Download.Comp.Detail.VersionPopup.ButtonInstall");
Btn2.Text = Lang.Text("Download.Comp.Detail.VersionPopup.ButtonSaveAs");
Btn3.Text = Lang.Text("Common.Action.Cancel");
ShapeLine.StrokeThickness = ModBase.GetWPFSize(1d);
if (converter.Content is ModComp.CompFile file)
Populate(file);
}
catch (Exception ex)
{
ModBase.Log(ex, "前置弹窗初始化失败", ModBase.LogLevel.Hint);
}

Loaded += Load;
Btn1.Click += Btn1_Click;
Btn2.Click += Btn2_Click;
Btn3.Click += Btn3_Click;
LabTitle.MouseLeftButtonDown += Drag;
PanBorder.MouseLeftButtonDown += Drag;
}

private void AppendUniqueNameSuffix(FrameworkElement element)
{
element.Name += ModBase.GetUuid();
}

/// <summary>
/// 填充版本信息与必要 / 可选前置项。
/// </summary>
private void Populate(ModComp.CompFile file)
{
// 1. 版本信息
var info = new List<string>();
if (!string.IsNullOrEmpty(file.FileName))
info.Add(file.FileName);
if (file.GameVersions.Any())
info.Add(Lang.Text("Download.Comp.Detail.FileList.GameVersion", string.Join("、", file.GameVersions)));
if (file.ModLoaders.Any())
info.Add(string.Join(" / ", file.ModLoaders));
info.Add(Lang.Text("Download.Comp.Detail.FileList.Updated", Lang.TimeSpan(file.ReleaseDate - DateTime.Now)));
if (file.Status != ModComp.CompFileStatus.Release)
info.Add(file.StatusDescription);
LabVersionInfo.Text = string.Join(" | ", info);

// 2. 必要前置 / 可选前置
FillDependencySection(LabReqTitle, PanReqDeps, file.Dependencies,
Lang.Text("Download.Comp.Detail.FileList.RequiredDependencies"));
FillDependencySection(LabOptTitle, PanOptDeps, file.OptionalDependencies,
Lang.Text("Download.Comp.Detail.FileList.OptionalDependencies"));
}

/// <summary>
/// 填充一个前置分区:标题 + 可点击的前置项(点击以该前置工程关闭弹窗)。
/// </summary>
private void FillDependencySection(TextBlock header, StackPanel panel, List<string> depIds, string title)
{
var projects = new List<ModComp.CompProject>();
foreach (var id in depIds)
if (ModComp.compProjectCache.TryGetValue(id, out var project))
projects.Add(project);

header.Text = $"{title}({projects.Count})";

if (!projects.Any())
{
panel.Children.Add(new TextBlock
{
Text = Lang.Text("Download.Comp.Detail.VersionPopup.NoDeps"),
FontSize = 13d,
Margin = new Thickness(14d, 0d, 0d, 4d),
Opacity = 0.6d
});
return;
}

foreach (var project in projects)
{
var captured = project;
var item = new MyListItem
{
Title = string.IsNullOrEmpty(project.TranslatedName) ? project.RawName : project.TranslatedName,
Info = project.FromCurseForge ? "CurseForge" : "Modrinth",
Logo = project.LogoUrl ?? "",
Height = 40,
Type = MyListItem.CheckType.Clickable
};
item.Click += (_, _) => ReturnResult(captured);
panel.Children.Add(item);
}
}

/// <summary>
/// 以指定返回值关闭弹窗:按钮返回 1 / 2,前置项返回对应 CompProject。
/// </summary>
private void ReturnResult(object result)
{
if (myConverter.IsExited)
return;
myConverter.IsExited = true;
myConverter.Result = result;
Close();
}

private void Load(object sender, EventArgs e)
{
try
{
// UI 初始化
if (Btn2.IsVisible && !(Btn1.ColorType == MyButton.ColorState.Red))
Btn1.ColorType = MyButton.ColorState.Highlight;
Btn1.Focus();
// 动画
Opacity = 0d;
ModAnimation.AniStart(
ModAnimation.AaColor(ModMain.frmMain.PanMsgBackground, BlurBorder.BackgroundProperty,
new ModBase.MyColor(90d, 0d, 0d, 0d) - ModMain.frmMain.PanMsgBackground.Background, 200),
"PanMsgBackground Background");
ModAnimation.AniStart(
new[]
{
ModAnimation.AaOpacity(this, 1d, 120, 60),
ModAnimation.AaDouble(i => TransformPos.Y += (double)i,
-TransformPos.Y, 300, 60, new ModAnimation.AniEaseOutBack(ModAnimation.AniEasePower.Weak)),
ModAnimation.AaDouble(i => TransformRotate.Angle += (double)i,
-TransformRotate.Angle, 300, 60,
new ModAnimation.AniEaseOutFluent(ModAnimation.AniEasePower.Weak))
}, "MyMsgBox " + uuid);
ModBase.Log("[Control] 前置详情弹窗:" + LabTitle.Text);
}
catch (Exception ex)
{
ModBase.Log(ex, "前置详情弹窗加载失败", ModBase.LogLevel.Hint);
}
}

private void Close()
{
// 结束线程阻塞
myConverter.WaitFrame.Continue = false;
ComponentDispatcher.PopModal();
// 动画
ModAnimation.AniStart(new[]
{
ModAnimation.AaCode(() =>
{
if (!ModMain.WaitingMyMsgBox.Any())
ModAnimation.AniStart(ModAnimation.AaColor(ModMain.frmMain.PanMsgBackground,
BlurBorder.BackgroundProperty,
new ModBase.MyColor(0d, 0d, 0d, 0d) - ModMain.frmMain.PanMsgBackground.Background, 200,
ease: new ModAnimation.AniEaseOutFluent(ModAnimation.AniEasePower.Weak)));
}, 30),
ModAnimation.AaOpacity(this, -Opacity, 80, 20),
ModAnimation.AaDouble(i => TransformPos.Y += (double)i, 20d - TransformPos.Y,
150, 0, new ModAnimation.AniEaseOutFluent()),
ModAnimation.AaDouble(i => TransformRotate.Angle += (double)i,
6d - TransformRotate.Angle, 150, 0, new ModAnimation.AniEaseInFluent(ModAnimation.AniEasePower.Weak)),
ModAnimation.AaCode(() => ((Grid)Parent).Children.Remove(this), after: true)
}, "MyMsgBox " + uuid);
}

public void Btn1_Click(object sender, MouseButtonEventArgs e) => ReturnResult(1);

public void Btn2_Click(object sender, MouseButtonEventArgs e) => ReturnResult(2);

public void Btn3_Click(object sender, MouseButtonEventArgs e) => ReturnResult(null);

private void Drag(object sender, MouseButtonEventArgs e)
{
try
{
if (e.LeftButton == MouseButtonState.Pressed)
if (e.GetPosition(ShapeLine).Y <= 2d)
ModMain.frmMain.DragMove();
}
catch (Exception ex)
{
ModBase.Log(ex, "拖拽移动失败", ModBase.LogLevel.Hint);
}
}
}
Loading
Loading