1
0

MyLocalModItem.xaml.vb 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541
  1. Imports System.Windows.Forms
  2. Public Class MyLocalModItem
  3. #Region "基础属性"
  4. Public Uuid As Integer = GetUuid()
  5. 'Logo
  6. Private _Logo As String = ""
  7. Public Property Logo As String
  8. Get
  9. Return _Logo
  10. End Get
  11. Set(value As String)
  12. If _Logo = value OrElse value Is Nothing Then Exit Property
  13. _Logo = value
  14. Dim FileAddress = PathTemp & "CompLogo\" & GetHash(_Logo) & ".png"
  15. Try
  16. If _Logo.StartsWithF("http", True) Then
  17. '网络图片
  18. If File.Exists(FileAddress) Then
  19. PathLogo.Source = New MyBitmap(FileAddress)
  20. Else
  21. PathLogo.Source = New MyBitmap(PathImage & "Icons/NoIcon.png")
  22. RunInNewThread(Sub() LogoLoader(FileAddress), "Comp Logo Loader " & Uuid & "#", ThreadPriority.BelowNormal)
  23. End If
  24. Else
  25. '位图
  26. PathLogo.Source = New MyBitmap(_Logo)
  27. End If
  28. Catch ex As IOException
  29. Log(ex, "加载本地 Mod 图标时读取失败(" & FileAddress & ")")
  30. Catch ex As ArgumentException
  31. '考虑缓存的图片本身可能有误
  32. Log(ex, "可视化本地 Mod 图标失败(" & FileAddress & ")")
  33. Try
  34. File.Delete(FileAddress)
  35. Log("[LocalModItem] 已清理损坏的本地 Mod 图标:" & FileAddress)
  36. Catch exx As Exception
  37. Log(exx, "清理损坏的本地 Mod 图标缓存失败(" & FileAddress & ")", LogLevel.Hint)
  38. End Try
  39. Catch ex As Exception
  40. Log(ex, "加载本地 Mod 图标失败(" & value & ")")
  41. End Try
  42. End Set
  43. End Property
  44. '后台加载 Logo
  45. Private Sub LogoLoader(LocalFileAddress As String)
  46. Dim Retried As Boolean = False
  47. Dim DownloadEnd As String = GetUuid()
  48. RetryStart:
  49. Try
  50. 'CurseForge 图片使用缩略图
  51. Dim Url As String = _Logo
  52. If Url.Contains("/256/256/") AndAlso GetPixelSize(1) <= 1.25 AndAlso Not Retried Then
  53. Url = Url.Replace("/256/256/", "/64/64/") '#3075:部分 Mod 不存在 64x64 图标,所以重试时不再缩小
  54. End If
  55. '下载图片
  56. NetDownload(Url, LocalFileAddress & DownloadEnd, True)
  57. If Url.EndsWithF("webp") Then
  58. Log($"[Comp] Webp 格式转换:{LocalFileAddress}")
  59. Dim dec = New Imazen.WebP.SimpleDecoder()
  60. Dim picFile = File.ReadAllBytes(LocalFileAddress & DownloadEnd)
  61. dec.DecodeFromBytes(picFile, picFile.Length).Save(LocalFileAddress & DownloadEnd)
  62. End If
  63. Dim LoadError As Exception = Nothing
  64. RunInUiWait(
  65. Sub()
  66. Try
  67. '在地址更换时取消加载
  68. If LocalFileAddress <> $"{PathTemp}CompLogo\{GetHash(_Logo)}.png" Then Exit Sub
  69. '在完成正常加载后才保存缓存图片
  70. PathLogo.Source = New MyBitmap(LocalFileAddress & DownloadEnd)
  71. Catch ex As Exception
  72. Log(ex, "读取本地 Mod 图标失败(" & LocalFileAddress & ")")
  73. File.Delete(LocalFileAddress & DownloadEnd)
  74. LoadError = ex
  75. End Try
  76. End Sub)
  77. If LoadError IsNot Nothing Then Throw LoadError
  78. If File.Exists(LocalFileAddress) Then
  79. File.Delete(LocalFileAddress & DownloadEnd)
  80. Else
  81. FileIO.FileSystem.MoveFile(LocalFileAddress & DownloadEnd, LocalFileAddress)
  82. End If
  83. Catch ex As Exception
  84. If Not Retried Then
  85. Retried = True
  86. GoTo RetryStart
  87. Else
  88. Log(ex, $"下载本地 Mod 图标失败({_Logo})")
  89. RunInUi(Sub() PathLogo.Source = New MyBitmap(PathImage & "Icons/NoIcon.png"))
  90. End If
  91. End Try
  92. End Sub
  93. '标题
  94. Private _Title As String
  95. Public Property Title As String
  96. Get
  97. Return _Title
  98. End Get
  99. Set(value As String)
  100. Dim RawValue = value
  101. Select Case Entry.State
  102. Case McMod.McModState.Fine
  103. LabTitle.TextDecorations = Nothing
  104. Case McMod.McModState.Disabled
  105. LabTitle.TextDecorations = TextDecorations.Strikethrough
  106. Case McMod.McModState.Unavaliable
  107. LabTitle.TextDecorations = TextDecorations.Strikethrough
  108. value &= " [错误]"
  109. End Select
  110. If LabTitle.Text = value Then Exit Property
  111. LabTitle.Text = value
  112. _Title = RawValue
  113. End Set
  114. End Property
  115. '副标题
  116. Public Property SubTitle As String
  117. Get
  118. Return If(LabTitleRaw?.Text, "")
  119. End Get
  120. Set(value As String)
  121. If LabTitleRaw.Text = value Then Exit Property
  122. LabTitleRaw.Text = value
  123. LabTitleRaw.Visibility = If(value = "", Visibility.Collapsed, Visibility.Visible)
  124. End Set
  125. End Property
  126. '描述
  127. Public Property Description As String
  128. Get
  129. Return LabInfo.Text
  130. End Get
  131. Set(value As String)
  132. If LabInfo.Text = value Then Exit Property
  133. LabInfo.Text = value
  134. End Set
  135. End Property
  136. 'Tag
  137. Public WriteOnly Property Tags As List(Of String)
  138. Set(value As List(Of String))
  139. PanTags.Children.Clear()
  140. PanTags.Visibility = If(value.Any(), Visibility.Visible, Visibility.Collapsed)
  141. For Each TagText In value
  142. Dim NewTag = GetObjectFromXML(
  143. "<Border xmlns=""http://schemas.microsoft.com/winfx/2006/xaml/presentation""
  144. Background=""#11000000"" Padding=""3,1"" CornerRadius=""3"" Margin=""0,0,3,0""
  145. SnapsToDevicePixels=""True"" UseLayoutRounding=""False"">
  146. <TextBlock Text=""" & TagText & """ Foreground=""#868686"" FontSize=""11"" />
  147. </Border>")
  148. PanTags.Children.Add(NewTag)
  149. Next
  150. End Set
  151. End Property
  152. '相关联的 Mod
  153. Public Property Entry As McMod
  154. Get
  155. Return Tag
  156. End Get
  157. Set(value As McMod)
  158. Tag = value
  159. End Set
  160. End Property
  161. #End Region
  162. #Region "点击与勾选"
  163. '触发点击事件
  164. Public Event Click(sender As Object, e As MouseButtonEventArgs)
  165. Private Sub Button_MouseUp(sender As Object, e As MouseButtonEventArgs) Handles Me.PreviewMouseLeftButtonUp
  166. If IsMouseDown Then
  167. RaiseEvent Click(sender, e)
  168. If e.Handled Then Exit Sub
  169. Log("[Control] 按下本地 Mod 列表项:" & LabTitle.Text)
  170. End If
  171. End Sub
  172. '鼠标点击判定
  173. Private IsMouseDown As Boolean = False
  174. Private Sub Button_MouseDown(sender As Object, e As MouseButtonEventArgs) Handles Me.PreviewMouseLeftButtonDown
  175. If Not IsMouseDirectlyOver Then Exit Sub
  176. IsMouseDown = True
  177. If ButtonStack IsNot Nothing Then ButtonStack.IsHitTestVisible = False
  178. End Sub
  179. Private Sub Button_MouseLeave(sender As Object, e As Object) Handles Me.MouseLeave, Me.PreviewMouseLeftButtonUp
  180. IsMouseDown = False
  181. If ButtonStack IsNot Nothing Then ButtonStack.IsHitTestVisible = True
  182. End Sub
  183. '滑动选中
  184. Private Shared SwipeStart As Integer, SwipeEnd As Integer
  185. Private Shared Swiping As Boolean = False
  186. Private Shared SwipToState As Boolean '被滑动到的目标应将 Checked 改为此值
  187. Private Sub Button_MouseSwipeStart(sender As Object, e As Object) Handles Me.MouseLeftButtonDown
  188. If Parent Is Nothing Then Exit Sub 'Mod 可能已被删除(#3824)
  189. '开始滑动
  190. Dim Index = CType(Parent, StackPanel).Children.IndexOf(Me)
  191. SwipeStart = Index
  192. SwipeEnd = Index
  193. Swiping = True
  194. SwipToState = Not Checked
  195. FrmVersionMod.CardSelect.IsHitTestVisible = False '暂时禁用下边栏
  196. End Sub
  197. Private Sub Button_MouseSwipe(sender As Object, e As Object) Handles Me.MouseEnter, Me.MouseLeave, Me.MouseLeftButtonUp
  198. If Parent Is Nothing Then Exit Sub 'Mod 可能已被删除(#3824)
  199. '结束滑动
  200. If Mouse.LeftButton <> MouseButtonState.Pressed OrElse Not Swiping Then
  201. Swiping = False
  202. FrmVersionMod.CardSelect.IsHitTestVisible = True
  203. Exit Sub
  204. End If
  205. '计算滑动范围
  206. Dim Index = CType(Parent, StackPanel).Children.IndexOf(Me)
  207. SwipeStart = Math.Min(SwipeStart, Index)
  208. SwipeEnd = Math.Max(SwipeEnd, Index)
  209. '勾选所有范围中的项
  210. If SwipeStart = SwipeEnd Then Exit Sub
  211. For i = SwipeStart To SwipeEnd
  212. Dim Item As MyLocalModItem = CType(Parent, StackPanel).Children(i)
  213. Item.InitLate(Item, e)
  214. Item.Checked = SwipToState
  215. Next
  216. End Sub
  217. '勾选状态
  218. Public Event Check(sender As Object, e As RouteEventArgs)
  219. Public Event Changed(sender As Object, e As RouteEventArgs)
  220. Private _Checked As Boolean = False
  221. Public Property Checked As Boolean
  222. Get
  223. Return _Checked
  224. End Get
  225. Set(value As Boolean)
  226. Try
  227. '触发属性值修改
  228. Dim RawValue = _Checked
  229. If value = _Checked Then Exit Property
  230. _Checked = value
  231. Dim ChangedEventArgs As New RouteEventArgs(False)
  232. If IsInitialized Then
  233. RaiseEvent Changed(Me, ChangedEventArgs)
  234. If ChangedEventArgs.Handled Then
  235. _Checked = RawValue
  236. Exit Property
  237. End If
  238. End If
  239. If value Then
  240. Dim CheckEventArgs As New RouteEventArgs(False)
  241. RaiseEvent Check(Me, CheckEventArgs)
  242. If CheckEventArgs.Handled Then Exit Property
  243. End If
  244. '更改动画
  245. If IsVisibleInForm() Then
  246. Dim Anim As New List(Of AniData)
  247. If Checked Then
  248. '由无变有
  249. Dim Delta = 32 - RectCheck.ActualHeight
  250. Anim.Add(AaHeight(RectCheck, Delta * 0.4, 200,, New AniEaseOutFluent(AniEasePower.Weak)))
  251. Anim.Add(AaHeight(RectCheck, Delta * 0.6, 300,, New AniEaseOutBack(AniEasePower.Weak)))
  252. Anim.Add(AaOpacity(RectCheck, 1 - RectCheck.Opacity, 30))
  253. RectCheck.VerticalAlignment = VerticalAlignment.Center
  254. RectCheck.Margin = New Thickness(-3, 0, 0, 0)
  255. Anim.Add(AaColor(LabTitle, TextBlock.ForegroundProperty, If(Entry.State = McMod.McModState.Fine, "ColorBrush2", "ColorBrush5"), 200))
  256. Else
  257. '由有变无
  258. Anim.Add(AaHeight(RectCheck, -RectCheck.ActualHeight, 120,, New AniEaseInFluent(AniEasePower.Weak)))
  259. Anim.Add(AaOpacity(RectCheck, -RectCheck.Opacity, 70, 40))
  260. RectCheck.VerticalAlignment = VerticalAlignment.Center
  261. Anim.Add(AaColor(LabTitle, TextBlock.ForegroundProperty, If(LabTitle.TextDecorations Is Nothing, "ColorBrush1", "ColorBrushGray4"), 120))
  262. End If
  263. AniStart(Anim, "MyLocalModItem Checked " & Uuid)
  264. Else
  265. '不在窗口上时直接设置
  266. RectCheck.VerticalAlignment = VerticalAlignment.Center
  267. RectCheck.Margin = New Thickness(-3, 0, 0, 0)
  268. If Checked Then
  269. RectCheck.Height = 32
  270. RectCheck.Opacity = 1
  271. LabTitle.SetResourceReference(TextBlock.ForegroundProperty, If(Entry.State = McMod.McModState.Fine, "ColorBrush2", "ColorBrush5"))
  272. Else
  273. RectCheck.Height = 0
  274. RectCheck.Opacity = 0
  275. LabTitle.SetResourceReference(TextBlock.ForegroundProperty, If(Entry.State = McMod.McModState.Fine, "ColorBrush1", "ColorBrushGray4"))
  276. End If
  277. AniStop("MyLocalModItem Checked " & Uuid)
  278. End If
  279. Catch ex As Exception
  280. Log(ex, "设置 Checked 失败")
  281. End Try
  282. End Set
  283. End Property
  284. #End Region
  285. #Region "后加载内容"
  286. '右下角状态指示图标
  287. Private ImgState As Image
  288. '指向背景
  289. Private _RectBack As Border = Nothing
  290. Public ReadOnly Property RectBack As Border
  291. Get
  292. If _RectBack Is Nothing Then
  293. Dim Rect As New Border With {
  294. .Name = "RectBack",
  295. .CornerRadius = New CornerRadius(3),
  296. .RenderTransform = New ScaleTransform(0.8, 0.8),
  297. .RenderTransformOrigin = New Point(0.5, 0.5),
  298. .BorderThickness = New Thickness(GetWPFSize(1)),
  299. .SnapsToDevicePixels = True,
  300. .IsHitTestVisible = False,
  301. .Opacity = 0
  302. }
  303. Rect.SetResourceReference(Border.BackgroundProperty, "ColorBrush7")
  304. Rect.SetResourceReference(Border.BorderBrushProperty, "ColorBrush6")
  305. SetColumnSpan(Rect, 999)
  306. SetRowSpan(Rect, 999)
  307. Children.Insert(0, Rect)
  308. _RectBack = Rect
  309. '<!--<Border x:Name = "RectBack" CornerRadius="3" RenderTransformOrigin="0.5,0.5" SnapsToDevicePixels="True"
  310. 'IsHitTestVisible = "False" Opacity="0" BorderThickness="1"
  311. 'Grid.ColumnSpan = "4" Background="{DynamicResource ColorBrush7}" BorderBrush="{DynamicResource ColorBrush6}"/>-->
  312. End If
  313. Return _RectBack
  314. End Get
  315. End Property
  316. '按钮
  317. Public ButtonHandler As Action(Of MyLocalModItem, EventArgs)
  318. Public ButtonStack As FrameworkElement
  319. Private _Buttons As IEnumerable(Of MyIconButton)
  320. Public Property Buttons As IEnumerable(Of MyIconButton)
  321. Get
  322. Return _Buttons
  323. End Get
  324. Set(value As IEnumerable(Of MyIconButton))
  325. _Buttons = value
  326. '移除原 Stack
  327. If ButtonStack IsNot Nothing Then
  328. Children.Remove(ButtonStack)
  329. ButtonStack = Nothing
  330. End If
  331. If Not value.Any() Then Exit Property
  332. '添加新 Stack
  333. ButtonStack = New StackPanel With {.Opacity = 0, .Margin = New Thickness(0, 0, 5, 0), .SnapsToDevicePixels = False, .Orientation = Orientation.Horizontal,
  334. .HorizontalAlignment = HorizontalAlignment.Right, .VerticalAlignment = VerticalAlignment.Center, .UseLayoutRounding = False}
  335. SetColumnSpan(ButtonStack, 10) : SetRowSpan(ButtonStack, 10)
  336. '构造按钮
  337. For Each Btn As MyIconButton In value
  338. If Btn.Height.Equals(Double.NaN) Then Btn.Height = 25
  339. If Btn.Width.Equals(Double.NaN) Then Btn.Width = 25
  340. CType(ButtonStack, StackPanel).Children.Add(Btn)
  341. Next
  342. Children.Add(ButtonStack)
  343. End Set
  344. End Property
  345. '勾选条
  346. Private _RectCheck As Border
  347. Public ReadOnly Property RectCheck As Border
  348. Get
  349. If _RectCheck Is Nothing Then
  350. _RectCheck = New Border With {.Width = 5, .Height = If(Checked, Double.NaN, 0), .CornerRadius = New CornerRadius(2, 2, 2, 2),
  351. .VerticalAlignment = If(Checked, VerticalAlignment.Stretch, VerticalAlignment.Center),
  352. .HorizontalAlignment = HorizontalAlignment.Left, .UseLayoutRounding = False, .SnapsToDevicePixels = False,
  353. .Margin = If(Checked, New Thickness(-3, 6, 0, 6), New Thickness(-3, 0, 0, 0))}
  354. _RectCheck.SetResourceReference(Border.BackgroundProperty, "ColorBrush3")
  355. SetRowSpan(_RectCheck, 10)
  356. Children.Add(_RectCheck)
  357. End If
  358. Return _RectCheck
  359. End Get
  360. End Property
  361. #End Region
  362. Public Sub Refresh()
  363. RunInUi(
  364. Sub()
  365. '更新
  366. If Entry.CanUpdate Then
  367. BtnUpdate.Visibility = Visibility.Visible
  368. Dim CurrentName = Entry.CompFile.FileName.Replace(".jar", "")
  369. Dim NewestName = Entry.UpdateFile.FileName.Replace(".jar", "")
  370. '简化名称对比
  371. Dim CurrentSegs = CurrentName.Split("-"c).ToList()
  372. Dim NewestSegs = NewestName.Split("-"c).ToList()
  373. Dim Shortened As Boolean = False
  374. For Each Seg In CurrentSegs.ToList()
  375. If Not NewestSegs.Contains(Seg) Then Continue For
  376. CurrentSegs.Remove(Seg)
  377. NewestSegs.Remove(Seg)
  378. Shortened = True
  379. Next
  380. If Shortened AndAlso CurrentSegs.Any() AndAlso NewestSegs.Any() Then
  381. CurrentName = Join(CurrentSegs, "-")
  382. NewestName = Join(NewestSegs, "-")
  383. Entry._Version = CurrentName '使用网络信息作为显示的版本号
  384. End If
  385. BtnUpdate.ToolTip = $"当前版本:{CurrentName} ({Entry.CompFile.ReleaseDate:yyyy/MM/dd HH:mm:ss}){vbCrLf}最新版本:{NewestName} ({Entry.UpdateFile.ReleaseDate:yyyy/MM/dd HH:mm:ss}){vbCrLf}点击以更新,右键查看更新日志。"
  386. Else
  387. BtnUpdate.Visibility = Visibility.Collapsed
  388. End If
  389. '标题
  390. If Entry.Comp Is Nothing Then
  391. Title = Entry.Name
  392. SubTitle = If(Entry.Version Is Nothing, "", " | " & Entry.Version)
  393. Else
  394. Dim Titles = Entry.Comp.GetControlTitle(False)
  395. Title = Titles.Key
  396. SubTitle = Titles.Value & If(Entry.Version Is Nothing, "", " | " & Entry.Version)
  397. End If
  398. If Checked Then
  399. LabTitle.SetResourceReference(TextBlock.ForegroundProperty, If(Entry.State = McMod.McModState.Fine, "ColorBrush2", "ColorBrush5"))
  400. Else
  401. LabTitle.SetResourceReference(TextBlock.ForegroundProperty, If(Entry.State = McMod.McModState.Fine, "ColorBrush1", "ColorBrushGray4"))
  402. End If
  403. '描述
  404. Dim NewDescription As String
  405. Select Case Entry.State
  406. Case McMod.McModState.Fine
  407. NewDescription = GetFileNameWithoutExtentionFromPath(Entry.Path)
  408. Case McMod.McModState.Disabled
  409. NewDescription = GetFileNameWithoutExtentionFromPath(Entry.Path.Replace(".disabled", "").Replace(".old", ""))
  410. Case Else 'McMod.McModState.Unavaliable
  411. NewDescription = GetFileNameFromPath(Entry.Path)
  412. End Select
  413. If Entry.Comp IsNot Nothing Then
  414. NewDescription += ": " & Entry.Comp.Description.Replace(vbCr, "").Replace(vbLf, "")
  415. ElseIf Entry.Description IsNot Nothing Then
  416. NewDescription += ": " & Entry.Description.Replace(vbCr, "").Replace(vbLf, "")
  417. ElseIf Not Entry.IsFileAvailable Then
  418. NewDescription += ": " & "存在错误,无法获取信息"
  419. End If
  420. Description = NewDescription
  421. '主 Logo
  422. Logo = If(Entry.Comp Is Nothing, PathImage & "Icons/NoIcon.png", Entry.Comp.GetControlLogo())
  423. '图标右下角的 Logo
  424. If Entry.State = McMod.McModState.Fine Then
  425. If ImgState IsNot Nothing Then
  426. Children.Remove(ImgState)
  427. ImgState = Nothing
  428. End If
  429. Else
  430. If ImgState Is Nothing Then
  431. ImgState = New Image With {
  432. .Width = 20, .Height = 20, .Margin = New Thickness(0, 0, -5, -3), .IsHitTestVisible = False,
  433. .HorizontalAlignment = HorizontalAlignment.Right, .VerticalAlignment = VerticalAlignment.Bottom
  434. }
  435. RenderOptions.SetBitmapScalingMode(ImgState, BitmapScalingMode.HighQuality)
  436. SetColumn(ImgState, 1) : SetRow(ImgState, 1) : SetRowSpan(ImgState, 2)
  437. Children.Add(ImgState)
  438. '<Image x:Name="ImgState" RenderOptions.BitmapScalingMode="HighQuality" Width="16" Height="16" Margin="0,0,-3,-1"
  439. ' Grid.Column="1" Grid.Row="1" Grid.RowSpan="2" IsHitTestVisible="False"
  440. ' HorizontalAlignment="Right" VerticalAlignment="Bottom"
  441. ' Source="/Images/Icons/Unavaliable.png" />
  442. End If
  443. ImgState.Source = New MyBitmap(PathImage & $"Icons/{Entry.State}.png")
  444. End If
  445. '标签
  446. If Entry.Comp IsNot Nothing Then Tags = Entry.Comp.Tags
  447. End Sub)
  448. End Sub
  449. Public Sub RefreshColor(sender As Object, e As EventArgs) Handles Me.MouseEnter, Me.MouseLeave, Me.MouseLeftButtonDown, Me.MouseLeftButtonUp, Me.Changed
  450. InitLate(sender, e)
  451. '触发颜色动画
  452. Dim Time As Integer = If(IsMouseOver, 120, 180)
  453. Dim Ani As New List(Of AniData)
  454. 'ButtonStack
  455. If ButtonStack IsNot Nothing Then
  456. If IsMouseOver Then
  457. Ani.Add(AaOpacity(ButtonStack, 1 - ButtonStack.Opacity, Time * 0.7, Time * 0.3))
  458. Ani.Add(AaDouble(Sub(i) ColumnPaddingRight.Width = New GridLength(Math.Max(0, ColumnPaddingRight.Width.Value + i)),
  459. 5 + Buttons.Count * 25 - ColumnPaddingRight.Width.Value, Time * 0.3, Time * 0.7))
  460. Else
  461. Ani.Add(AaOpacity(ButtonStack, -ButtonStack.Opacity, Time * 0.4))
  462. Ani.Add(AaDouble(Sub(i) ColumnPaddingRight.Width = New GridLength(Math.Max(0, ColumnPaddingRight.Width.Value + i)),
  463. 4 - ColumnPaddingRight.Width.Value, Time * 0.4))
  464. End If
  465. End If
  466. 'RectBack
  467. If IsMouseOver OrElse Checked Then
  468. Ani.AddRange({
  469. AaColor(RectBack, Border.BackgroundProperty, If(IsMouseDown, "ColorBrush6", "ColorBrushBg1"), Time),
  470. AaOpacity(RectBack, 1 - RectBack.Opacity, Time,, New AniEaseOutFluent)
  471. })
  472. If IsMouseDown Then
  473. Ani.Add(AaScaleTransform(RectBack, 0.996 - CType(RectBack.RenderTransform, ScaleTransform).ScaleX, Time * 1.2,, New AniEaseOutFluent))
  474. Else
  475. Ani.Add(AaScaleTransform(RectBack, 1 - CType(RectBack.RenderTransform, ScaleTransform).ScaleX, Time * 1.2,, New AniEaseOutFluent))
  476. End If
  477. Else
  478. Ani.AddRange({
  479. AaOpacity(RectBack, -RectBack.Opacity, Time),
  480. AaScaleTransform(RectBack, 0.996 - CType(RectBack.RenderTransform, ScaleTransform).ScaleX, Time,, New AniEaseOutFluent),
  481. AaScaleTransform(RectBack, -0.196, 1,,, True)
  482. })
  483. End If
  484. AniStart(Ani, "LocalModItem Color " & Uuid)
  485. End Sub
  486. '触发虚拟化内容
  487. Private Sub InitLate(sender As Object, e As EventArgs)
  488. If ButtonHandler IsNot Nothing Then
  489. ButtonHandler(sender, e)
  490. ButtonHandler = Nothing
  491. End If
  492. End Sub
  493. '显示更新日志
  494. Private Sub ShowUpdateLog(sender As Object, e As MouseButtonEventArgs) Handles BtnUpdate.PreviewMouseRightButtonUp
  495. e.Handled = True
  496. Dim CurseForgeUrl As String = Entry.ChangelogUrls.FirstOrDefault(Function(x) x.Contains("curseforge.com"))
  497. Dim ModrinthUrl As String = Entry.ChangelogUrls.FirstOrDefault(Function(x) x.Contains("modrinth.com"))
  498. If CurseForgeUrl Is Nothing OrElse ModrinthUrl Is Nothing Then
  499. OpenWebsite(Entry.ChangelogUrls.First)
  500. Else
  501. Select Case MyMsgBox("要在哪个网站上查看更新日志?", "查看更新日志", "Modrinth", "CurseForge", "取消")
  502. Case 1
  503. OpenWebsite(ModrinthUrl)
  504. Case 2
  505. OpenWebsite(CurseForgeUrl)
  506. End Select
  507. End If
  508. End Sub
  509. '触发更新
  510. Private Sub BtnUpdate_Click(sender As Object, e As EventArgs) Handles BtnUpdate.Click
  511. FrmVersionMod.UpdateMods({Entry})
  512. End Sub
  513. End Class