PageDownloadMod.xaml.vb 8.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181
  1. Public Class PageDownloadMod
  2. Public Const PageSize = 40
  3. ''' <summary>
  4. ''' 在切换到该页面时自动设置的目标版本。
  5. ''' </summary>
  6. Public Shared TargetVersion As McVersion = Nothing
  7. '加载器信息
  8. Public Shared Loader As New LoaderTask(Of CompProjectRequest, Integer)("CompProject Mod", AddressOf CompProjectsGet, AddressOf LoaderInput) With {.ReloadTimeout = 60 * 1000}
  9. Public Shared Storage As New CompProjectStorage
  10. Public Shared Page As Integer = 0
  11. Private IsLoaderInited As Boolean = False
  12. Private Sub PageDownloadMod_Inited(sender As Object, e As EventArgs) Handles Me.Loaded
  13. '不知道从 Initialized 改成 Loaded 会不会有问题,但用 Initialized 会导致初始的筛选器修改被覆盖回默认值
  14. If TargetVersion IsNot Nothing Then
  15. '设置目标
  16. ResetFilter() '重置筛选器
  17. TextSearchVersion.Text = TargetVersion.Version.McName
  18. Dim GetTargetItemByName =
  19. Function(Name As String) As MyComboBoxItem
  20. For Each Item As MyComboBoxItem In ComboSearchLoader.Items
  21. If Item.Content = Name Then Return Item
  22. Next
  23. Return ComboSearchLoader.Items(0)
  24. End Function
  25. If TargetVersion.Version.HasForge Then
  26. ComboSearchLoader.SelectedItem = GetTargetItemByName("Forge")
  27. ElseIf TargetVersion.Version.HasFabric Then
  28. ComboSearchLoader.SelectedItem = GetTargetItemByName("Fabric")
  29. ElseIf TargetVersion.Version.HasNeoForge Then
  30. ComboSearchLoader.SelectedItem = GetTargetItemByName("NeoForge")
  31. End If
  32. TargetVersion = Nothing
  33. '如果已经完成请求,则重新开始
  34. If IsLoaderInited Then StartNewSearch()
  35. PanScroll.ScrollToHome()
  36. End If
  37. '加载器初始化
  38. If IsLoaderInited Then Return
  39. IsLoaderInited = True
  40. PageLoaderInit(Load, PanLoad, PanContent, PanAlways, Loader, AddressOf Load_OnFinish, AddressOf LoaderInput)
  41. If McVersionHighest = -1 Then McVersionHighest = Math.Max(McVersionHighest, Integer.Parse(CType(TextSearchVersion.Items(1), MyComboBoxItem).Content.ToString.Split(".")(1)))
  42. End Sub
  43. Private Shared Function LoaderInput() As CompProjectRequest
  44. Dim Request As New CompProjectRequest(CompType.Mod, Storage, (Page + 1) * PageSize)
  45. If FrmDownloadMod IsNot Nothing Then
  46. Dim ModLoader As CompModLoaderType = Val(FrmDownloadMod.ComboSearchLoader.SelectedItem.Tag)
  47. Dim GameVersion As String = If(FrmDownloadMod.TextSearchVersion.Text = "全部 (也可自行输入)", Nothing,
  48. If(FrmDownloadMod.TextSearchVersion.Text.Contains(".") OrElse FrmDownloadMod.TextSearchVersion.Text.Contains("w"), FrmDownloadMod.TextSearchVersion.Text, Nothing))
  49. If GameVersion IsNot Nothing AndAlso GameVersion.Contains(".") AndAlso Val(GameVersion.Split(".")(1)) < 14 AndAlso '1.14-
  50. ModLoader = CompModLoaderType.Forge Then '选择了 Forge
  51. ModLoader = CompModLoaderType.Any '此时,视作没有筛选 Mod Loader(因为部分老 Mod 没有设置自己支持的加载器)
  52. End If
  53. With Request
  54. .SearchText = FrmDownloadMod.TextSearchName.Text
  55. .GameVersion = GameVersion
  56. .Tag = FrmDownloadMod.ComboSearchTag.SelectedItem.Tag
  57. .ModLoader = ModLoader
  58. .Source = CType(Val(FrmDownloadMod.ComboSearchSource.SelectedItem.Tag), CompSourceType)
  59. End With
  60. End If
  61. Return Request
  62. End Function
  63. '结果 UI 化
  64. Private Sub Load_OnFinish()
  65. Try
  66. Log($"[Comp] 开始可视化 Mod 列表,已储藏 {Storage.Results.Count} 个结果,当前在第 {Page + 1} 页")
  67. '列表项
  68. PanProjects.Children.Clear()
  69. For i = Math.Min(Page * PageSize, Storage.Results.Count - 1) To Math.Min((Page + 1) * PageSize - 1, Storage.Results.Count - 1)
  70. PanProjects.Children.Add(Storage.Results(i).ToCompItem(Loader.Input.GameVersion Is Nothing, Loader.Input.ModLoader = CompModLoaderType.Any))
  71. Next
  72. '页码
  73. CardPages.Visibility = If(Storage.Results.Count > 40 OrElse
  74. Storage.CurseForgeOffset < Storage.CurseForgeTotal OrElse Storage.ModrinthOffset < Storage.ModrinthTotal,
  75. Visibility.Visible, Visibility.Collapsed)
  76. LabPage.Text = Page + 1
  77. BtnPageFirst.IsEnabled = Page > 1
  78. BtnPageFirst.Opacity = If(Page > 1, 1, 0.2)
  79. BtnPageLeft.IsEnabled = Page > 0
  80. BtnPageLeft.Opacity = If(Page > 0, 1, 0.2)
  81. Dim IsRightEnabled As Boolean = '由于 WPF 的未知 bug,读取到的 IsEnabled 可能是错误的值(#3319)
  82. Storage.Results.Count > PageSize * (Page + 1) OrElse
  83. Storage.CurseForgeOffset < Storage.CurseForgeTotal OrElse Storage.ModrinthOffset < Storage.ModrinthTotal
  84. BtnPageRight.IsEnabled = IsRightEnabled
  85. BtnPageRight.Opacity = If(IsRightEnabled, 1, 0.2)
  86. '错误信息
  87. If Storage.ErrorMessage Is Nothing Then
  88. HintError.Visibility = Visibility.Collapsed
  89. Else
  90. HintError.Visibility = Visibility.Visible
  91. HintError.Text = Storage.ErrorMessage
  92. End If
  93. '强制返回顶部
  94. PanBack.ScrollToTop()
  95. Catch ex As Exception
  96. Log(ex, "可视化 Mod 列表出错", LogLevel.Feedback)
  97. End Try
  98. End Sub
  99. '自动重试
  100. Private Sub Load_State(sender As Object, state As MyLoading.MyLoadingState, oldState As MyLoading.MyLoadingState) Handles Load.StateChanged
  101. Select Case Loader.State
  102. Case LoadState.Failed
  103. Dim ErrorMessage As String = ""
  104. If Loader.Error IsNot Nothing Then ErrorMessage = Loader.Error.Message
  105. If ErrorMessage.Contains("不是有效的 json 文件") Then
  106. Log("[Download] 下载的 Mod 列表 json 文件损坏,已自动重试", LogLevel.Debug)
  107. PageLoaderRestart()
  108. End If
  109. End Select
  110. End Sub
  111. '切换页码
  112. Private Sub BtnPageFirst_Click(sender As Object, e As RoutedEventArgs) Handles BtnPageFirst.Click
  113. ChangePage(0)
  114. End Sub
  115. Private Sub BtnPageLeft_Click(sender As Object, e As RoutedEventArgs) Handles BtnPageLeft.Click
  116. ChangePage(Page - 1)
  117. End Sub
  118. Private Sub BtnPageRight_Click(sender As Object, e As RoutedEventArgs) Handles BtnPageRight.Click
  119. ChangePage(Page + 1)
  120. End Sub
  121. Private Sub ChangePage(NewPage As Integer)
  122. CardPages.IsEnabled = False
  123. Page = NewPage
  124. FrmMain.BackToTop()
  125. Log($"[Download] Mod 切换到第 {Page + 1} 页")
  126. RunInThread(
  127. Sub()
  128. Thread.Sleep(100) '等待向上滚的动画结束
  129. RunInUi(Sub() CardPages.IsEnabled = True)
  130. Loader.Start()
  131. End Sub)
  132. End Sub
  133. #Region "搜索"
  134. '搜索按钮
  135. Private Sub StartNewSearch() Handles BtnSearchRun.Click
  136. Page = 0
  137. If Loader.ShouldStart(LoaderInput()) Then Storage = New CompProjectStorage '避免连续搜索两次使得 CompProjectStorage 引用丢失(#1311)
  138. Loader.Start()
  139. End Sub
  140. Private Sub EnterTrigger(sender As Object, e As KeyEventArgs) Handles TextSearchName.KeyDown, TextSearchVersion.KeyDown
  141. If e.Key = Key.Enter Then StartNewSearch()
  142. End Sub
  143. '重置按钮
  144. Private Sub ResetFilter() Handles BtnSearchReset.Click
  145. TextSearchName.Text = ""
  146. TextSearchVersion.Text = "全部 (也可自行输入)"
  147. TextSearchVersion.SelectedIndex = 0
  148. ComboSearchSource.SelectedIndex = 0
  149. ComboSearchTag.SelectedIndex = 0
  150. ComboSearchLoader.SelectedIndex = 0
  151. Loader.LastFinishedTime = 0 '要求强制重新开始
  152. End Sub
  153. '版本选择
  154. '#3067:当下拉菜单展开时,程序会被 WPF 挂起,因而无法更新 Grid 布局,所以必须延迟到下拉菜单收起后才能更新
  155. Private Sub TextSearchVersion_TextChanged() Handles TextSearchVersion.TextChanged
  156. If Not TextSearchVersion.IsDropDownOpen Then UpdateSearchLoaderVisibility()
  157. End Sub
  158. Private Sub UpdateSearchLoaderVisibility() Handles TextSearchVersion.DropDownClosed
  159. If TextSearchVersion.Text.Contains(".") OrElse TextSearchVersion.Text.Contains("w") Then
  160. ComboSearchLoader.Visibility = Visibility.Visible
  161. Grid.SetColumnSpan(TextSearchVersion, 1)
  162. Else
  163. ComboSearchLoader.Visibility = Visibility.Collapsed
  164. Grid.SetColumnSpan(TextSearchVersion, 2)
  165. ComboSearchLoader.SelectedIndex = 0
  166. End If
  167. End Sub
  168. #End Region
  169. End Class