PageVersionMod.xaml.vb 29 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633
  1. Public Class PageVersionMod
  2. #Region "初始化"
  3. Private IsLoad As Boolean = False
  4. Public Sub PageOther_Loaded() Handles Me.Loaded
  5. If FrmMain.PageLast.Page <> FormMain.PageType.CompDetail Then PanBack.ScrollToHome()
  6. AniControlEnabled += 1
  7. SelectedMods.Clear()
  8. RefreshList()
  9. ChangeAllSelected(False)
  10. AniControlEnabled -= 1
  11. '非重复加载部分
  12. If IsLoad Then Exit Sub
  13. IsLoad = True
  14. #If DEBUG Then
  15. BtnManageCheck.Visibility = Visibility.Visible
  16. #End If
  17. End Sub
  18. ''' <summary>
  19. ''' 刷新 Mod 列表。
  20. ''' </summary>
  21. Public Sub RefreshList(Optional ForceReload As Boolean = False)
  22. If McModLoader.State = LoadState.Loading Then Exit Sub
  23. If LoaderFolderRun(McModLoader, PageVersionLeft.Version.PathIndie & "mods\", If(ForceReload, LoaderFolderRunType.ForceRun, LoaderFolderRunType.RunOnUpdated)) Then
  24. Log("[System] 已刷新 Mod 列表")
  25. PanBack.ScrollToHome()
  26. SearchBox.Text = ""
  27. End If
  28. End Sub
  29. Private Sub LoaderInit() Handles Me.Initialized
  30. PageLoaderInit(Load, PanLoad, PanAllBack, Nothing, McModLoader, AddressOf Load_Finish, AutoRun:=False)
  31. End Sub
  32. Private Sub Load_Click(sender As Object, e As MouseButtonEventArgs) Handles Load.Click
  33. If McModLoader.State = LoadState.Failed Then
  34. LoaderFolderRun(McModLoader, PageVersionLeft.Version.PathIndie & "mods\", LoaderFolderRunType.ForceRun)
  35. End If
  36. End Sub
  37. #End Region
  38. #Region "UI 化"
  39. Private PanItems As StackPanel
  40. ''' <summary>
  41. ''' 将 Mod 列表加载为 UI。
  42. ''' </summary>
  43. Private Sub Load_Finish(Loader As LoaderTask(Of String, List(Of McMod)))
  44. Dim List As List(Of McMod) = Loader.Output
  45. Try
  46. PanList.Children.Clear()
  47. '判断应该显示哪一个页面
  48. If List.Count = 0 Then
  49. PanEmpty.Visibility = Visibility.Visible
  50. PanBack.Visibility = Visibility.Collapsed
  51. Exit Sub
  52. Else
  53. PanBack.Visibility = Visibility.Visible
  54. PanEmpty.Visibility = Visibility.Collapsed
  55. End If
  56. SearchBox.Text = ""
  57. '建立 StackPanel
  58. PanItems = New StackPanel With {.Margin = New Thickness(20, 38, 18, If(List.Count > 0, 20, 0)), .VerticalAlignment = VerticalAlignment.Top, .RenderTransform = New TranslateTransform(0, 0)}
  59. For Each ModEntity As McMod In List
  60. PanItems.Children.Add(McModListItem(ModEntity))
  61. Next
  62. '建立 MyCard
  63. Dim NewCard As New MyCard With {.Title = McModGetTitle(List), .Margin = New Thickness(0, 0, 0, 15)}
  64. NewCard.Children.Add(PanItems)
  65. PanList.Children.Add(NewCard)
  66. Catch ex As Exception
  67. Log(ex, "加载 Mod 列表 UI 失败", LogLevel.Feedback)
  68. End Try
  69. End Sub
  70. ''' <summary>
  71. ''' 获取 Card 的标题。
  72. ''' </summary>
  73. Private Function McModGetTitle(List As List(Of McMod)) As String
  74. Dim Counter = {0, 0, 0}
  75. For Each ModEntity As McMod In List
  76. Counter(ModEntity.State) += 1
  77. Next
  78. If List.Count = 0 Then Return "未找到任何 Mod"
  79. Dim TypeList As New List(Of String)
  80. If Counter(McMod.McModState.Fine) > 0 Then TypeList.Add("启用 " & Counter(McMod.McModState.Fine))
  81. If Counter(McMod.McModState.Disabled) > 0 Then TypeList.Add("禁用 " & Counter(McMod.McModState.Disabled))
  82. If Counter(McMod.McModState.Unavaliable) > 0 Then TypeList.Add("错误 " & Counter(McMod.McModState.Unavaliable))
  83. Return "Mod 列表(" & Join(TypeList, ",") & ")"
  84. End Function
  85. Private Function McModListItem(Entry As McMod) As MyLocalModItem
  86. AniControlEnabled += 1
  87. Dim NewItem As New MyLocalModItem With {.SnapsToDevicePixels = True, .Entry = Entry,
  88. .ButtonHandler = AddressOf McModContent, .Checked = SelectedMods.Contains(Entry.RawFileName)}
  89. AddHandler Entry.OnGetCompProject, AddressOf NewItem.Refresh
  90. NewItem.Refresh()
  91. AniControlEnabled -= 1
  92. Return NewItem
  93. End Function
  94. Private Sub McModContent(sender As MyLocalModItem, e As EventArgs)
  95. '点击事件
  96. AddHandler sender.Changed, AddressOf CheckChanged
  97. AddHandler sender.Click, Sub(ss As MyLocalModItem, ee As EventArgs) ss.Checked = Not ss.Checked
  98. '图标按钮
  99. Dim BtnOpen As New MyIconButton With {.LogoScale = 1.15, .Logo = Logo.IconButtonOpen, .Tag = sender}
  100. BtnOpen.ToolTip = "打开文件位置"
  101. ToolTipService.SetPlacement(BtnOpen, Primitives.PlacementMode.Center)
  102. ToolTipService.SetVerticalOffset(BtnOpen, 30)
  103. ToolTipService.SetHorizontalOffset(BtnOpen, 2)
  104. AddHandler BtnOpen.Click, AddressOf Open_Click
  105. Dim BtnCont As New MyIconButton With {.LogoScale = 1.05, .Logo = Logo.IconButtonInfo, .Tag = sender}
  106. BtnCont.ToolTip = "详情"
  107. ToolTipService.SetPlacement(BtnCont, Primitives.PlacementMode.Center)
  108. ToolTipService.SetVerticalOffset(BtnCont, 30)
  109. ToolTipService.SetHorizontalOffset(BtnCont, 2)
  110. AddHandler BtnCont.Click, AddressOf Info_Click
  111. AddHandler sender.MouseRightButtonDown, AddressOf Info_Click
  112. Dim BtnDelete As New MyIconButton With {.LogoScale = 1.1, .Logo = Logo.IconButtonDelete, .Tag = sender}
  113. BtnDelete.ToolTip = "删除"
  114. ToolTipService.SetPlacement(BtnDelete, Primitives.PlacementMode.Center)
  115. ToolTipService.SetVerticalOffset(BtnDelete, 30)
  116. ToolTipService.SetHorizontalOffset(BtnDelete, 2)
  117. AddHandler BtnDelete.Click, AddressOf Delete_Click
  118. Dim BtnED As New MyIconButton With {.LogoScale = 1.1, .Logo = If(sender.Entry.State = McMod.McModState.Fine,
  119. "M508 990.4c-261.6 0-474.4-212-474.4-474.4S246.4 41.6 508 41.6s474.4 212 474.4 474.4S769.6 990.4 508 990.4zM508 136.8c-209.6 0-379.2 169.6-379.2 379.2 0 209.6 169.6 379.2 379.2 379.2s379.2-169.6 379.2-379.2C887.2 306.4 717.6 136.8 508 136.8zM697.6 563.2 318.4 563.2c-26.4 0-47.2-21.6-47.2-47.2 0-26.4 21.6-47.2 47.2-47.2l379.2 0c26.4 0 47.2 21.6 47.2 47.2C744.8 542.4 724 563.2 697.6 563.2z",
  120. "M512 0a512 512 0 1 0 512 512A512 512 0 0 0 512 0z m0 921.6a409.6 409.6 0 1 1 409.6-409.6 409.6 409.6 0 0 1-409.6 409.6z M716.8 339.968l-256 253.44L328.192 460.8A51.2 51.2 0 0 0 256 532.992l168.448 168.96a51.2 51.2 0 0 0 72.704 0l289.28-289.792A51.2 51.2 0 0 0 716.8 339.968z"),
  121. .Tag = sender}
  122. BtnED.ToolTip = If(sender.Entry.State = McMod.McModState.Fine, "禁用", "启用")
  123. ToolTipService.SetPlacement(BtnED, Primitives.PlacementMode.Center)
  124. ToolTipService.SetVerticalOffset(BtnED, 30)
  125. ToolTipService.SetHorizontalOffset(BtnED, 2)
  126. AddHandler BtnED.Click, AddressOf ED_Click
  127. If sender.Entry.State = McMod.McModState.Unavaliable Then
  128. sender.Buttons = {BtnCont, BtnOpen, BtnDelete}
  129. Else
  130. sender.Buttons = {BtnCont, BtnOpen, BtnED, BtnDelete}
  131. End If
  132. End Sub
  133. #End Region
  134. #Region "管理"
  135. ''' <summary>
  136. ''' 打开 Mods 文件夹。
  137. ''' </summary>
  138. Private Sub BtnManageOpen_Click(sender As Object, e As EventArgs) Handles BtnManageOpen.Click, BtnHintOpen.Click
  139. Try
  140. Directory.CreateDirectory(PageVersionLeft.Version.PathIndie & "mods\")
  141. OpenExplorer("""" & PageVersionLeft.Version.PathIndie & "mods\""")
  142. Catch ex As Exception
  143. Log(ex, "打开 Mods 文件夹失败", LogLevel.Msgbox)
  144. End Try
  145. End Sub
  146. #If DEBUG Then
  147. ''' <summary>
  148. ''' 检查 Mod。
  149. ''' </summary>
  150. Private Sub BtnManageCheck_Click(sender As Object, e As EventArgs) Handles BtnManageCheck.Click
  151. Try
  152. Dim Result = McModCheck(PageVersionLeft.Version, McModLoader.Output)
  153. If Result.Count > 0 Then
  154. MyMsgBox(Join(Result, vbCrLf & vbCrLf), "Mod 检查结果")
  155. Else
  156. Hint("Mod 检查完成,未发现任何问题!", HintType.Finish)
  157. End If
  158. Catch ex As Exception
  159. Log(ex, "进行 Mod 检查时出错", LogLevel.Feedback)
  160. End Try
  161. End Sub
  162. #End If
  163. ''' <summary>
  164. ''' 全选。
  165. ''' </summary>
  166. Private Sub BtnManageSelectAll_Click(sender As Object, e As MouseButtonEventArgs) Handles BtnManageSelectAll.Click
  167. If SelectedMods.Count < If(IsSearching, PanSearchList.Children.Count, McModLoader.Output.Count) Then
  168. ChangeAllSelected(True)
  169. Else
  170. ChangeAllSelected(False)
  171. End If
  172. End Sub
  173. ''' <summary>
  174. ''' 安装 Mod。
  175. ''' </summary>
  176. Private Sub BtnManageInstall_Click(sender As Object, e As MouseButtonEventArgs) Handles BtnManageInstall.Click
  177. Hint("将 Mod 文件直接拖入 PCL 窗口即可安装!")
  178. End Sub
  179. #End Region
  180. #Region "选择"
  181. '选择的 Mod 的路径(不含 .disabled)
  182. Public SelectedMods As New List(Of String)
  183. '单项切换选择状态
  184. Public Sub CheckChanged(sender As MyLocalModItem, e As RouteEventArgs)
  185. If AniControlEnabled <> 0 Then Return
  186. '更新选择了的内容
  187. Dim SelectedKey As String = sender.Entry.RawFileName
  188. If sender.Checked Then
  189. If Not SelectedMods.Contains(SelectedKey) Then SelectedMods.Add(SelectedKey)
  190. Else
  191. SelectedMods.Remove(SelectedKey)
  192. End If
  193. '更新下边栏 UI
  194. RefreshBottomBar()
  195. End Sub
  196. '改变下边栏状态
  197. Private ShownCount As Integer = 0
  198. Private Sub RefreshBottomBar()
  199. '计数
  200. Dim NewCount As Integer = SelectedMods.Count
  201. Dim Selected = NewCount > 0
  202. If Selected Then LabSelect.Text = $"已选择 {NewCount} 个文件" '取消所有选择时不更新数字
  203. '按钮可用性
  204. If Selected Then
  205. Dim HasEnabled As Boolean = False
  206. Dim HasDisabled As Boolean = False
  207. For Each ModEntity In McModLoader.Output
  208. If SelectedMods.Contains(ModEntity.RawFileName) Then
  209. If ModEntity.State = McMod.McModState.Fine Then
  210. HasEnabled = True
  211. ElseIf ModEntity.State = McMod.McModState.Disabled Then
  212. HasDisabled = True
  213. End If
  214. End If
  215. Next
  216. BtnSelectDisable.IsEnabled = HasEnabled
  217. BtnSelectEnable.IsEnabled = HasDisabled
  218. End If
  219. '更新显示状态
  220. CardSelect.IsHitTestVisible = Selected
  221. If AniControlEnabled = 0 Then
  222. If Selected Then
  223. '仅在数量增加时播放出现/跳跃动画
  224. If ShownCount >= NewCount Then
  225. ShownCount = NewCount
  226. Return
  227. Else
  228. ShownCount = NewCount
  229. End If
  230. '出现/跳跃动画
  231. CardSelect.Visibility = Visibility.Visible
  232. AniStart({
  233. AaOpacity(CardSelect, 1 - CardSelect.Opacity, 60),
  234. AaTranslateY(CardSelect, -27 - TransSelect.Y, 120, Ease:=New AniEaseOutFluent(AniEasePower.Weak)),
  235. AaTranslateY(CardSelect, 3, 150, 120, Ease:=New AniEaseInoutFluent(AniEasePower.Weak)),
  236. AaTranslateY(CardSelect, -1, 90, 270, Ease:=New AniEaseInoutFluent(AniEasePower.Weak))
  237. }, "Mod Sidebar")
  238. Else
  239. '不重复播放隐藏动画
  240. If ShownCount = 0 Then Return
  241. ShownCount = 0
  242. '隐藏动画
  243. AniStart({
  244. AaOpacity(CardSelect, -CardSelect.Opacity, 90),
  245. AaTranslateY(CardSelect, -10 - TransSelect.Y, 90, Ease:=New AniEaseInFluent(AniEasePower.Weak)),
  246. AaCode(Sub() CardSelect.Visibility = Visibility.Collapsed, After:=True)
  247. }, "Mod Sidebar")
  248. End If
  249. Else
  250. AniStop("Mod Sidebar")
  251. ShownCount = NewCount
  252. If Selected Then
  253. CardSelect.Visibility = Visibility.Visible
  254. CardSelect.Opacity = 1
  255. TransSelect.Y = -25
  256. Else
  257. CardSelect.Visibility = Visibility.Collapsed
  258. CardSelect.Opacity = 0
  259. TransSelect.Y = -10
  260. End If
  261. End If
  262. End Sub
  263. '切换所有项的选择状态
  264. Private Sub ChangeAllSelected(Value As Boolean)
  265. AniControlEnabled += 1
  266. SelectedMods.Clear()
  267. If IsSearching Then
  268. '搜索中
  269. For Each Item As MyLocalModItem In PanSearchList.Children
  270. Item.Checked = Value
  271. If Value Then SelectedMods.Add(Item.Entry.RawFileName)
  272. Next
  273. If Not Value Then '只取消选择
  274. If PanItems IsNot Nothing Then
  275. For Each Item As MyLocalModItem In PanItems.Children
  276. Item.Checked = Value
  277. Next
  278. End If
  279. End If
  280. Else
  281. '非搜索中
  282. If PanItems IsNot Nothing Then
  283. For Each Item As MyLocalModItem In PanItems.Children
  284. Item.Checked = Value
  285. If Value Then SelectedMods.Add(Item.Entry.RawFileName)
  286. Next
  287. End If
  288. End If
  289. AniControlEnabled -= 1
  290. '更新下边栏 UI
  291. RefreshBottomBar()
  292. End Sub
  293. Private Sub UnselectedAllWithAnimation() Handles Load.StateChanged, Me.PageExit
  294. Dim CacheAniControlEnabled = AniControlEnabled
  295. AniControlEnabled = 0
  296. ChangeAllSelected(False)
  297. AniControlEnabled += CacheAniControlEnabled
  298. End Sub
  299. Private Sub PageVersionMod_KeyDown(sender As Object, e As KeyEventArgs) Handles Me.KeyDown
  300. If My.Computer.Keyboard.CtrlKeyDown AndAlso e.Key = Key.A Then ChangeAllSelected(True)
  301. End Sub
  302. #End Region
  303. #Region "下边栏"
  304. '启用 / 禁用
  305. Private Sub BtnSelectED_Click(sender As MyIconTextButton, e As RouteEventArgs) Handles BtnSelectEnable.Click, BtnSelectDisable.Click
  306. EDMods(McModLoader.Output.Where(Function(m) SelectedMods.Contains(m.RawFileName)).ToList(),
  307. Not sender.Equals(BtnSelectDisable))
  308. ChangeAllSelected(False)
  309. End Sub
  310. Private Sub EDMods(ModList As List(Of McMod), IsEnable As Boolean)
  311. Dim IsSuccessful As Boolean = True
  312. For Each ModEntity In ModList
  313. Dim NewPath As String = Nothing
  314. If ModEntity.State = McMod.McModState.Fine AndAlso Not IsEnable Then
  315. '禁用
  316. NewPath = ModEntity.Path & ".disabled"
  317. ElseIf ModEntity.State = McMod.McModState.Disabled AndAlso IsEnable Then
  318. '启用
  319. NewPath = ModEntity.Path.Replace(".disabled", "").Replace(".old", "")
  320. Else
  321. Continue For
  322. End If
  323. '重命名
  324. Try
  325. If File.Exists(NewPath) AndAlso Not File.Exists(ModEntity.Path) Then Continue For '因为未知原因 Mod 的状态已经切换完了
  326. File.Delete(NewPath)
  327. FileSystem.Rename(ModEntity.Path, NewPath)
  328. Catch ex As FileNotFoundException
  329. Log(ex, $"未找到需要重命名的 Mod({If(ModEntity.Path, "null")})", LogLevel.Feedback)
  330. RefreshList(True)
  331. Return
  332. Catch ex As Exception
  333. Log(ex, $"重命名 Mod 失败({If(ModEntity.Path, "null")})")
  334. IsSuccessful = False
  335. End Try
  336. '更改 Loader 和 UI 中的列表
  337. Dim NewModEntity As New McMod(NewPath)
  338. NewModEntity.Comp = ModEntity.Comp
  339. Dim IndexOfLoader As Integer = McModLoader.Output.IndexOf(ModEntity)
  340. McModLoader.Output.RemoveAt(IndexOfLoader)
  341. McModLoader.Output.Insert(IndexOfLoader, NewModEntity)
  342. Dim List = If(IsSearching, PanSearchList, PanItems).Children
  343. Dim IndexOfUi As Integer = List.IndexOf(List.OfType(Of MyLocalModItem).FirstOrDefault(Function(i) i.Entry Is ModEntity))
  344. If IndexOfUi = -1 Then Continue For '因为未知原因 Mod 的状态已经切换完了
  345. List.RemoveAt(IndexOfUi)
  346. List.Insert(IndexOfUi, McModListItem(NewModEntity))
  347. Next
  348. If Not IsSearching Then
  349. '改变禁用数量的显示
  350. CType(PanItems.Parent, MyCard).Title = McModGetTitle(McModLoader.Output)
  351. '更新加载器状态
  352. LoaderFolderRun(McModLoader, PageVersionLeft.Version.PathIndie & "mods\", LoaderFolderRunType.UpdateOnly)
  353. End If
  354. If Not IsSuccessful Then
  355. Hint("由于文件被占用,Mod 的状态切换失败,请尝试关闭正在运行的游戏后再试!", HintType.Critical)
  356. RefreshList(True)
  357. Else
  358. RefreshBottomBar()
  359. End If
  360. End Sub
  361. '删除
  362. Private Sub BtnSelectDelete_Click() Handles BtnSelectDelete.Click
  363. Dim DeleteList As List(Of McMod) = McModLoader.Output.Where(Function(m) SelectedMods.Contains(m.RawFileName)).ToList()
  364. DeleteMods(DeleteList)
  365. End Sub
  366. Private Sub DeleteMods(ModList As IEnumerable(Of McMod))
  367. Try
  368. Dim IsSuccessful As Boolean = True
  369. Dim IsShiftPressed As Boolean = My.Computer.Keyboard.ShiftKeyDown
  370. For Each ModEntity In ModList
  371. '删除
  372. Try
  373. If IsShiftPressed Then
  374. File.Delete(ModEntity.Path)
  375. Else
  376. My.Computer.FileSystem.DeleteFile(ModEntity.Path, FileIO.UIOption.OnlyErrorDialogs, FileIO.RecycleOption.SendToRecycleBin)
  377. End If
  378. Catch ex As OperationCanceledException
  379. Log(ex, "删除 Mod 被主动取消")
  380. RefreshList(True)
  381. Return
  382. Catch ex As Exception
  383. Log(ex, $"删除 Mod 失败({ModEntity.Path})", LogLevel.Msgbox)
  384. IsSuccessful = False
  385. End Try
  386. '取消选中
  387. SelectedMods.Remove(ModEntity.RawFileName)
  388. '更改 Loader 和 UI 中的列表
  389. McModLoader.Output.Remove(ModEntity)
  390. Dim Parent As StackPanel = If(IsSearching, PanSearchList, PanItems)
  391. Dim IndexOfUi As Integer = Parent.Children.IndexOf(Parent.Children.OfType(Of MyLocalModItem).First(Function(i) i.Entry Is ModEntity))
  392. Parent.Children.RemoveAt(IndexOfUi)
  393. Next
  394. If Not IsSearching Then
  395. '改变禁用数量的显示
  396. CType(PanItems.Parent, MyCard).Title = McModGetTitle(McModLoader.Output)
  397. '更新加载器状态
  398. LoaderFolderRun(McModLoader, PageVersionLeft.Version.PathIndie & "mods\", LoaderFolderRunType.UpdateOnly)
  399. End If
  400. If Not IsSuccessful Then
  401. Hint("由于文件被占用,Mod 删除失败,请尝试关闭正在运行的游戏后再试!", HintType.Critical)
  402. RefreshList(True)
  403. ElseIf If(IsSearching, PanSearchList, PanItems).Children.Count = 0 Then
  404. RefreshList(True)
  405. Else
  406. RefreshBottomBar()
  407. End If
  408. '显示结果提示
  409. If Not IsSuccessful Then Exit Sub
  410. If IsShiftPressed Then
  411. If ModList.Count = 1 Then
  412. Hint($"已彻底删除 {ModList.Single.FileName}!", HintType.Finish)
  413. Else
  414. Hint($"已彻底删除 {ModList.Count} 个文件!", HintType.Finish)
  415. End If
  416. Else
  417. If ModList.Count = 1 Then
  418. Hint($"已将 {ModList.Single.FileName} 删除到回收站!", HintType.Finish)
  419. Else
  420. Hint($"已将 {ModList.Count} 个文件删除到回收站!", HintType.Finish)
  421. End If
  422. End If
  423. Catch ex As OperationCanceledException
  424. Log(ex, "删除 Mod 被主动取消")
  425. RefreshList(True)
  426. Catch ex As Exception
  427. Log(ex, "删除 Mod 出现未知错误", LogLevel.Feedback)
  428. RefreshList(True)
  429. End Try
  430. End Sub
  431. '取消选择
  432. Private Sub BtnSelectCancel_Click() Handles BtnSelectCancel.Click
  433. ChangeAllSelected(False)
  434. End Sub
  435. #End Region
  436. #Region "单个 Mod 项"
  437. '详情
  438. Public Sub Info_Click(sender As Object, e As EventArgs)
  439. Try
  440. Dim ModEntry As McMod = CType(If(TypeOf sender Is MyIconButton, sender.Tag, sender), MyLocalModItem).Entry
  441. '加载失败信息
  442. If ModEntry.State = McMod.McModState.Unavaliable Then
  443. MyMsgBox("无法读取此 Mod 的信息。" & vbCrLf & vbCrLf & "详细的错误信息:" & GetExceptionDetail(ModEntry.FileUnavailableReason), "Mod 读取失败")
  444. Return
  445. End If
  446. If ModEntry.Comp IsNot Nothing Then
  447. '跳转到 Mod 下载页面
  448. FrmMain.PageChange(New FormMain.PageStackData With {.Page = FormMain.PageType.CompDetail,
  449. .Additional = {ModEntry.Comp, New List(Of String), PageVersionLeft.Version.Version.McName,
  450. If(PageVersionLeft.Version.Version.HasForge, CompModLoaderType.Forge, If(PageVersionLeft.Version.Version.HasFabric, CompModLoaderType.Fabric, CompModLoaderType.Any))}})
  451. Else
  452. '获取信息
  453. Dim ContentLines As New List(Of String)
  454. If ModEntry.Description IsNot Nothing Then ContentLines.Add(ModEntry.Description & vbCrLf)
  455. If ModEntry.Authors IsNot Nothing Then ContentLines.Add("作者:" & ModEntry.Authors)
  456. ContentLines.Add("文件:" & ModEntry.FileName & "(" & GetString(New FileInfo(ModEntry.Path).Length) & ")")
  457. If ModEntry.Version IsNot Nothing Then ContentLines.Add("版本:" & ModEntry.Version)
  458. Dim DebugInfo As New List(Of String)
  459. If ModEntry.ModId IsNot Nothing Then
  460. DebugInfo.Add("Mod ID:" & ModEntry.ModId)
  461. End If
  462. If ModEntry.Dependencies.Count > 0 Then
  463. DebugInfo.Add("依赖于:")
  464. For Each Dep In ModEntry.Dependencies
  465. DebugInfo.Add(" - " & Dep.Key & If(Dep.Value Is Nothing, "", ",版本:" & Dep.Value))
  466. Next
  467. End If
  468. If DebugInfo.Count > 0 Then
  469. ContentLines.Add("")
  470. ContentLines.AddRange(DebugInfo)
  471. End If
  472. '获取用于搜索的 Mod 名称
  473. Dim ModOriginalName As String = ModEntry.Name.Replace(" ", "+")
  474. Dim ModSearchName As String = ModOriginalName.Substring(0, 1)
  475. For i = 1 To ModOriginalName.Count - 1
  476. Dim IsLastLower As Boolean = ModOriginalName(i - 1).ToString.ToLower.Equals(ModOriginalName(i - 1).ToString)
  477. Dim IsCurrentLower As Boolean = ModOriginalName(i).ToString.ToLower.Equals(ModOriginalName(i).ToString)
  478. If IsLastLower AndAlso Not IsCurrentLower Then
  479. '上一个字母为小写,这一个字母为大写
  480. ModSearchName += "+"
  481. End If
  482. ModSearchName += ModOriginalName(i)
  483. Next
  484. ModSearchName = ModSearchName.Replace("++", "+").Replace("pti+Fine", "ptiFine")
  485. '显示
  486. If ModEntry.Url Is Nothing Then
  487. If MyMsgBox(Join(ContentLines, vbCrLf), ModEntry.Name, "百科搜索", "返回") = 1 Then
  488. OpenWebsite("https://www.mcmod.cn/s?key=" & ModSearchName & "&site=all&filter=0")
  489. End If
  490. Else
  491. Select Case MyMsgBox(Join(ContentLines, vbCrLf), ModEntry.Name, "打开官网", "百科搜索", "返回")
  492. Case 1
  493. OpenWebsite(ModEntry.Url)
  494. Case 2
  495. OpenWebsite("https://www.mcmod.cn/s?key=" & ModSearchName & "&site=all&filter=0")
  496. End Select
  497. End If
  498. End If
  499. Catch ex As Exception
  500. Log(ex, "获取 Mod 详情失败", LogLevel.Feedback)
  501. End Try
  502. End Sub
  503. '打开文件所在的位置
  504. Public Sub Open_Click(sender As MyIconButton, e As EventArgs)
  505. Try
  506. Dim ListItem As MyLocalModItem = sender.Tag
  507. OpenExplorer("/select,""" & ListItem.Entry.Path & """")
  508. Catch ex As Exception
  509. Log(ex, "打开 Mod 文件位置失败", LogLevel.Feedback)
  510. End Try
  511. End Sub
  512. '删除
  513. Public Sub Delete_Click(sender As MyIconButton, e As EventArgs)
  514. Dim ListItem As MyLocalModItem = sender.Tag
  515. DeleteMods({ListItem.Entry})
  516. End Sub
  517. '启用 / 禁用
  518. Public Sub ED_Click(sender As MyIconButton, e As EventArgs)
  519. Dim ListItem As MyLocalModItem = sender.Tag
  520. EDMods(New List(Of McMod) From {ListItem.Entry}, ListItem.Entry.State = McMod.McModState.Disabled)
  521. End Sub
  522. #End Region
  523. #Region "搜索"
  524. Public ReadOnly Property IsSearching As Boolean
  525. Get
  526. Return Not String.IsNullOrWhiteSpace(SearchBox.Text)
  527. End Get
  528. End Property
  529. Public Sub SearchRun() Handles SearchBox.TextChanged
  530. ChangeAllSelected(False)
  531. If IsSearching Then
  532. '构造请求
  533. Dim QueryList As New List(Of SearchEntry(Of McMod))
  534. For Each Entry As McMod In McModLoader.Output
  535. Dim SearchSource As New List(Of KeyValuePair(Of String, Double))
  536. SearchSource.Add(New KeyValuePair(Of String, Double)(Entry.Name, 1))
  537. SearchSource.Add(New KeyValuePair(Of String, Double)(Entry.FileName, 1))
  538. If Entry.Version IsNot Nothing Then
  539. SearchSource.Add(New KeyValuePair(Of String, Double)(Entry.Version, 0.2))
  540. End If
  541. If Entry.Description IsNot Nothing AndAlso Entry.Description <> "" Then
  542. SearchSource.Add(New KeyValuePair(Of String, Double)(Entry.Description, 0.4))
  543. End If
  544. If Entry.Comp IsNot Nothing Then
  545. If Entry.Comp.RawName <> Entry.Name Then SearchSource.Add(New KeyValuePair(Of String, Double)(Entry.Comp.RawName, 1))
  546. If Entry.Comp.TranslatedName <> Entry.Comp.RawName Then SearchSource.Add(New KeyValuePair(Of String, Double)(Entry.Comp.TranslatedName, 1))
  547. If Entry.Comp.Description <> Entry.Description Then SearchSource.Add(New KeyValuePair(Of String, Double)(Entry.Comp.Description, 0.4))
  548. SearchSource.Add(New KeyValuePair(Of String, Double)(String.Join("", Entry.Comp.Tags), 0.2))
  549. End If
  550. QueryList.Add(New SearchEntry(Of McMod) With {.Item = Entry, .SearchSource = SearchSource})
  551. Next
  552. '进行搜索,构造列表
  553. Dim SearchResult = Search(QueryList, SearchBox.Text, MaxBlurCount:=6, MinBlurSimilarity:=0.35)
  554. PanSearchList.Children.Clear()
  555. If SearchResult.Count = 0 Then
  556. PanSearch.Title = "无搜索结果"
  557. PanSearchList.Visibility = Visibility.Collapsed
  558. Else
  559. PanSearch.Title = "搜索结果"
  560. For Each Result In SearchResult
  561. Dim Item = McModListItem(Result.Item)
  562. If ModeDebug Then Item.Description = If(Result.AbsoluteRight, "完全匹配,", "") & "相似度:" & Math.Round(Result.Similarity, 3) & "," & Item.Description
  563. PanSearchList.Children.Add(Item)
  564. Next
  565. PanSearchList.Visibility = Visibility.Visible
  566. End If
  567. '显示
  568. AniStart({
  569. AaOpacity(PanList, -PanList.Opacity, 100),
  570. AaCode(Sub()
  571. PanList.Visibility = Visibility.Collapsed
  572. PanSearch.Visibility = Visibility.Visible
  573. PanSearch.TriggerForceResize()
  574. End Sub,, True),
  575. AaOpacity(PanSearch, 1 - PanSearch.Opacity, 200, 60)
  576. }, "FrmVersionMod Search Switch", True)
  577. Else
  578. '隐藏
  579. LoaderFolderRun(McModLoader, PageVersionLeft.Version.PathIndie & "mods\", LoaderFolderRunType.RunOnUpdated)
  580. AniStart({
  581. AaOpacity(PanSearch, -PanSearch.Opacity, 100),
  582. AaCode(Sub()
  583. PanSearch.Height = 0
  584. PanSearch.Visibility = Visibility.Collapsed
  585. PanList.Visibility = Visibility.Visible
  586. End Sub,, True),
  587. AaOpacity(PanList, 1 - PanList.Opacity, 150, 30)
  588. }, "FrmVersionMod Search Switch", True)
  589. End If
  590. End Sub
  591. #End Region
  592. End Class