PageVersionExport.xaml.vb 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322
  1. Public Class PageVersionExport
  2. Private CurrentVer As String = ""
  3. Private Sub PageVersionExport_Loaded(sender As Object, e As RoutedEventArgs) Handles Me.Loaded
  4. Reload()
  5. End Sub
  6. Public ItemVersion As MyListItem
  7. Public Sub Reload()
  8. AniControlEnabled += 1
  9. If CurrentVer <> PageVersionLeft.Version.Path Then
  10. '说明切换到另一个版本了,所有的绝对路径都要重置,否则爆炸
  11. CurrentPath = ""
  12. Selected = New List(Of String)
  13. CurrentVer = PageVersionLeft.Version.Path
  14. End If
  15. TbExportName.ShowValidateResult = True
  16. TbExportName.ValidateRules = New ObjectModel.Collection(Of Validate) From {New ValidateFileName() With {.AllowNull = True}}
  17. TbExportName.Validate()
  18. TbExportName.HintText = PageVersionLeft.Version.Name
  19. TbExportDesc.HintText = PageVersionLeft.Version.Info
  20. PanDisplayItem.Children.Clear()
  21. ItemVersion = PageSelectRight.McVersionListItem(PageVersionLeft.Version.Load())
  22. ItemVersion.IsHitTestVisible = False
  23. If Not String.IsNullOrEmpty(CustomLogo) Then ItemVersion.Logo = CustomLogo
  24. PanDisplayItem.Children.Add(ItemVersion)
  25. ItemVersion.Title = If(String.IsNullOrWhiteSpace(TbExportName.Text), PageVersionLeft.Version.Name, TbExportName.Text)
  26. ItemVersion.Info = If(String.IsNullOrWhiteSpace(TbExportDesc.Text), PageVersionLeft.Version.Info, TbExportDesc.Text)
  27. #If BETA Then
  28. CheckIncludePCL.IsEnabled = True
  29. #Else
  30. CheckIncludePCL.IsEnabled = False
  31. TbHint.Text = "你可以在此勾选需要包含进整合包的文件或文件夹,其他文件或文件夹在高级选项添加。" & vbCrLf & "你当前的 PCL 不是正式版,有二次分发的限制,因此整合包不能包含 PCL 程序。"
  32. #End If
  33. CheckIncludeSetup.IsEnabled = CheckIncludePCL.IsEnabled
  34. ReloadFileList(CurrentPath)
  35. AniControlEnabled -= 1
  36. End Sub
  37. #Region "文件列表"
  38. ''' <summary>
  39. ''' 当前所在的文件夹。注意是绝对路径!以 \ 结尾。
  40. ''' </summary>
  41. Private CurrentPath As String = ""
  42. Private Sub ReloadFileList(Optional NewPath As String = "")
  43. If String.IsNullOrWhiteSpace(NewPath) OrElse NewPath = PathMcFolder Then NewPath = PageVersionLeft.Version.Path
  44. If Not NewPath.EndsWithF("\") Then NewPath &= "\"
  45. Dim tb As TextBlock = PanFileList.Children(0)
  46. PanFileList.Children.Clear()
  47. PanFileList.Children.Add(tb)
  48. If NewPath <> PageVersionLeft.Version.Path Then
  49. Dim listItem As New MyListItem With {.Title = "返回上一级目录", .Tag = "..", .Height = 35, .Type = MyListItem.CheckType.Clickable}
  50. AddHandler listItem.Click, AddressOf ListItem_Click
  51. PanFileList.Children.Add(listItem)
  52. End If
  53. Dim fileCount As Integer = 0
  54. Dim directories = Directory.EnumerateDirectories(NewPath)
  55. Dim files = Directory.EnumerateFiles(NewPath)
  56. If (NewPath = PageVersionLeft.Version.Path) AndAlso PageVersionLeft.Version.PathIndie = PathMcFolder Then
  57. '未开启版本隔离时 .minecraft 下的文件
  58. directories = directories.Concat(Directory.EnumerateDirectories(PathMcFolder))
  59. files = files.Concat(Directory.EnumerateFiles(PathMcFolder))
  60. End If
  61. For Each d In directories
  62. If Directory.EnumerateFileSystemEntries(d).Count = 0 Then Continue For
  63. If IsVerRedundant(d) OrElse IsMustExport(d) Then Continue For
  64. Dim title As String = ""
  65. Dim listItem As New MyListItem
  66. If Titles.TryGetValue(GetFolderNameFromPath(d), title) Then 'title 作为引用类型传入
  67. listItem.Title = title
  68. Else
  69. listItem.Title = GetFolderNameFromPath(d)
  70. End If
  71. listItem.Info = d
  72. '图标按钮
  73. Dim btnSwap As New MyIconButton
  74. btnSwap.Logo = Logo.IconButtonRight
  75. btnSwap.LogoScale = 1.0
  76. btnSwap.Tag = d & "\"
  77. AddHandler btnSwap.Click, AddressOf BtnSwap_Click
  78. listItem.Buttons = {btnSwap}
  79. listItem.Type = MyListItem.CheckType.CheckBox
  80. listItem.Height = 35
  81. listItem.Logo = Logo.IconButtonOpen
  82. listItem.Tag = d & "\"
  83. Select Case IsSelected(d & "\")
  84. Case 1
  85. listItem.Half = True
  86. Case 2
  87. listItem.Checked = True
  88. End Select
  89. AddHandler listItem.Click, AddressOf ListItem_Click
  90. PanFileList.Children.Add(listItem)
  91. fileCount += 1
  92. Next
  93. For Each f In files
  94. If IsVerRedundant(f) OrElse IsMustExport(f) Then Continue For
  95. Dim title As String = ""
  96. Dim listItem As New MyListItem
  97. If Titles.TryGetValue(f, title) Then 'title 作为引用类型传入
  98. listItem.Title = title
  99. Else
  100. listItem.Title = GetFileNameFromPath(f)
  101. End If
  102. listItem.Info = f
  103. listItem.Type = MyListItem.CheckType.CheckBox
  104. listItem.Height = 35
  105. listItem.Tag = f
  106. listItem.Checked = (IsSelected(f) = 2)
  107. AddHandler listItem.Click, AddressOf ListItem_Click
  108. PanFileList.Children.Add(listItem)
  109. fileCount += 1
  110. Next
  111. CurrentPath = NewPath
  112. CardMore.Title = If(NewPath = PageVersionLeft.Version.Path, "高级选项", $"高级选项 ({NewPath.Replace(PageVersionLeft.Version.Path, "").TrimEnd("\")})")
  113. End Sub
  114. Private Titles As New Dictionary(Of String, String) From {
  115. {"saves", "存档"},
  116. {"resourcepacks", "资源包"},
  117. {"config", "Mod 配置"},
  118. {"shaderpacks", "光影包"},
  119. {"options.txt", "游戏配置"},
  120. {"servers.dat", "服务器列表"}
  121. }
  122. Private Sub BtnSwap_Click(sender As MyIconButton, e As Object)
  123. Dim actualPath As String = sender.Tag
  124. 'Dim relative As String = actualPath.Replace(PageVersionLeft.Version.Path, "")
  125. If Not Directory.Exists(actualPath) Then
  126. Hint($"找不到目录:{actualPath}", HintType.Critical)
  127. Exit Sub
  128. End If
  129. ReloadFileList(actualPath)
  130. End Sub
  131. ''' <summary>
  132. ''' 选中的文件列表,绝对路径。
  133. ''' </summary>
  134. Private Selected As New List(Of String)
  135. Private Sub SelectedChange(IsAdd As Boolean, TargetPath As String)
  136. If File.Exists(TargetPath) Then
  137. If IsAdd Then Selected.Add(TargetPath) Else Selected.Remove(TargetPath)
  138. Exit Sub
  139. End If
  140. If Directory.Exists(TargetPath) Then
  141. For Each d In Directory.EnumerateDirectories(TargetPath)
  142. SelectedChange(IsAdd, d)
  143. Next
  144. For Each f In Directory.EnumerateFiles(TargetPath)
  145. If IsAdd Then Selected.Add(f) Else Selected.Remove(f)
  146. Next
  147. End If
  148. Selected = Selected.Distinct().ToList()
  149. End Sub
  150. ''' <summary>
  151. ''' 获取 TargetPath 是否选中。
  152. ''' </summary>
  153. ''' <returns>全部未选中为 0,部分选中为 1,全部选中为 2。</returns>
  154. Private Function IsSelected(TargetPath As String, Optional AllowEmpty As Boolean = False) As Integer
  155. If File.Exists(TargetPath) Then
  156. Return If(Selected.Contains(TargetPath), 2, 0)
  157. End If
  158. If Directory.Exists(TargetPath) Then
  159. Dim di As New DirectoryInfo(TargetPath)
  160. If di.GetDirectories.Length + di.GetFiles.Length = 0 Then Return If(AllowEmpty, 2, 0)
  161. '如果有一个文件不在列表,则 hasExclude = True
  162. Dim hasExclude As Boolean = False
  163. '如果有一个文件在列表,则 hasInclude = True
  164. Dim hasInclude As Boolean = False
  165. For Each d In Directory.EnumerateDirectories(TargetPath)
  166. If Directory.EnumerateFileSystemEntries(d).Count = 0 Then Continue For
  167. Select Case IsSelected(d, True)
  168. Case 0
  169. hasExclude = True
  170. Case 1
  171. Return 1
  172. Case 2
  173. hasInclude = True
  174. End Select
  175. If hasInclude AndAlso hasExclude Then Return 1 '如果有文件在、有文件不在列表中,可以断定部分选中
  176. Next
  177. For Each f In Directory.EnumerateFiles(TargetPath)
  178. If Selected.Contains(f) Then hasInclude = True Else hasExclude = True
  179. If hasInclude AndAlso hasExclude Then Return 1 '如果有文件在、有文件不在列表中,可以断定部分选中
  180. Next
  181. If hasExclude AndAlso Not hasInclude Then Return 0
  182. If hasInclude AndAlso Not hasExclude Then Return 2
  183. End If
  184. Return 0
  185. End Function
  186. Private Sub ListItem_Click(sender As MyListItem, e As Object)
  187. If sender.Tag = ".." Then '回到上一级目录
  188. ReloadFileList(GetPathFromFullPath(CurrentPath))
  189. Exit Sub
  190. End If
  191. SelectedChange(Not sender.Checked, '非常难绷的逻辑,很难描述清楚,自己打断点看 Checked 属性值吧……
  192. sender.Tag)
  193. End Sub
  194. 'Private ReadOnly Property Saves As List(Of String)
  195. ' Get
  196. ' If Directory.Exists(PageVersionLeft.Version.Path & "saves\") Then
  197. ' Return Directory.EnumerateDirectories(PageVersionLeft.Version.Path & "saves\").ToList
  198. ' End If
  199. ' Return New List(Of String)
  200. ' End Get
  201. 'End Property
  202. '复选框与高级选项同步
  203. Private Sub PanCommonFiles_MouseLeftButtonUp(sender As Object, e As MouseButtonEventArgs) Handles PanCommonFiles.MouseLeftButtonUp
  204. For Each c In PanCommonFiles.Children
  205. If TypeOf c IsNot MyCheckBox Then Continue For
  206. If String.IsNullOrEmpty(c.Tag) Then Continue For
  207. For Each l In PanFileList.Children
  208. If TypeOf l Is MyListItem Then
  209. If l.Tag.Replace("\", "") = c.Tag Then
  210. l.Checked = c.Checked
  211. SelectedChange(c.Checked, PageVersionLeft.Version.Path & c.Tag)
  212. End If
  213. End If
  214. Next
  215. Next
  216. End Sub
  217. '高级选项与复选框同步
  218. Private Sub PanFileList_MouseLeftButtonUp(sender As Object, e As MouseButtonEventArgs) Handles PanFileList.MouseLeftButtonUp
  219. For Each c In PanCommonFiles.Children
  220. If TypeOf c Is MyCheckBox Then
  221. c.Checked = IsSelected(PageVersionLeft.Version.Path & c.Tag) = 2 OrElse IsSelected(PathMcFolder & c.Tag) = 2
  222. End If
  223. Next
  224. End Sub
  225. #End Region
  226. #Region "整合包信息 & 预览栏"
  227. Private Sub TbExportName_TextChanged(sender As MyTextBox, e As TextChangedEventArgs) Handles TbExportName.TextChanged
  228. If String.IsNullOrEmpty(TbExportName.ValidateResult) Then
  229. ItemVersion.Title = If(String.IsNullOrWhiteSpace(sender.Text), PageVersionLeft.Version.Name, sender.Text)
  230. End If
  231. End Sub
  232. Private Sub TbExportDesc_TextChanged(sender As MyTextBox, e As TextChangedEventArgs) Handles TbExportDesc.TextChanged
  233. ItemVersion.Info = If(String.IsNullOrWhiteSpace(sender.Text), PageVersionLeft.Version.Info, sender.Text)
  234. End Sub
  235. Private CustomLogoVal As String
  236. ''' <summary>
  237. ''' 自定义 Logo 的路径。
  238. ''' </summary>
  239. Public Property CustomLogo() As String
  240. Get
  241. Return CustomLogoVal
  242. End Get
  243. Set(value As String)
  244. If AniControlEnabled <> 0 Then Exit Property
  245. CustomLogoVal = value
  246. ItemVersion.Logo = value
  247. Reload()
  248. End Set
  249. End Property
  250. Private Sub ComboDisplayLogo_SelectionChanged(sender As MyComboBox, e As SelectionChangedEventArgs) Handles ComboDisplayLogo.SelectionChanged
  251. If Not AniControlEnabled = 0 Then Exit Sub
  252. '选择 自定义 时修改图片
  253. If ComboDisplayLogo.SelectedItem Is ItemDisplayLogoCustom Then
  254. Dim FileName As String = SelectFile("常用图片文件(*.png;*.jpg;*.gif)|*.png;*.jpg;*.gif", "选择图片")
  255. If String.IsNullOrWhiteSpace(FileName) Then Exit Sub
  256. CustomLogo = FileName
  257. Else
  258. CustomLogo = sender.SelectedItem.Tag
  259. End If
  260. End Sub
  261. #End Region
  262. #Region "基本信息"
  263. Private Sub CheckIncludePCL_Change(sender As Object, user As Boolean) Handles CheckIncludePCL.Change
  264. CheckIncludeSetup.IsEnabled = CheckIncludePCL.IsEnabled
  265. End Sub
  266. #End Region
  267. #Region "导出"
  268. 'Private Sub ComboExportType_Change(sender As ComboBox, e As SelectionChangedEventArgs) Handles ComboExportType.SelectionChanged
  269. ' If AniControlEnabled <> 0 Then Exit Sub
  270. ' Type = sender.SelectedIndex
  271. ' Select Case Type
  272. ' Case ModpackType.Modrinth
  273. ' If IncludePCL() Then 'TODO:修改这里的条件
  274. ' If GridCompressed IsNot Nothing Then GridCompressed.Visibility = Visibility.Visible
  275. ' If GridModrinth IsNot Nothing Then GridModrinth.Visibility = Visibility.Collapsed
  276. ' Else
  277. ' If GridCompressed IsNot Nothing Then GridCompressed.Visibility = Visibility.Collapsed
  278. ' If GridModrinth IsNot Nothing Then GridModrinth.Visibility = Visibility.Visible
  279. ' End If
  280. ' End Select
  281. ' CardExport.TriggerForceResize()
  282. 'End Sub
  283. Private Sub BtnExportExport_Click() Handles BtnExportExport.Click
  284. Dim savePath As String = SelectAs(
  285. "选择导出位置", $"整合包 - {If(String.IsNullOrWhiteSpace(TbExportName.Text), PageVersionLeft.Version.Name, TbExportName.Text)}" & If(CheckIncludePCL.Checked, ".zip", ".mrpack"),
  286. If(CheckIncludePCL.Checked, "整合包文件(*.zip)|*.zip", "Modrinth 整合包(*.mrpack)|*.mrpack"))
  287. If String.IsNullOrEmpty(savePath) Then Exit Sub
  288. '获取需要包含的文件
  289. Dim contains As List(Of String) = Selected
  290. For Each c In PanCommonFiles.Children
  291. If TypeOf c IsNot MyCheckBox Then Continue For
  292. If String.IsNullOrEmpty(c.Tag) Then Continue For
  293. If c.Checked Then contains.Add(PageVersionLeft.Version.Path & c.Tag)
  294. Next
  295. ModpackExport(New ExportOptions(PageVersionLeft.Version, savePath, CheckIncludePCL.Checked, contains.Distinct.ToArray,
  296. PCLSetupGlobal:=CheckIncludeSetup.Checked, Name:=TbExportName.Text, VerID:=TbExportVersion.Text))
  297. End Sub
  298. #End Region
  299. End Class