PageLaunchRight.xaml.vb 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265
  1. Public Class PageLaunchRight
  2. Implements IRefreshable
  3. Private Sub Init() Handles Me.Loaded
  4. PanBack.ScrollToHome()
  5. PanScroll = PanBack '不知道为啥不能在 XAML 设置
  6. PanLog.Visibility = If(ModeDebug, Visibility.Visible, Visibility.Collapsed)
  7. '快照版提示
  8. #If BETA Then
  9. PanHint.Visibility = Visibility.Collapsed
  10. #Else
  11. PanHint.Visibility = If(ThemeCheckGold(), Visibility.Collapsed, Visibility.Visible)
  12. LabHint1.Text = "快照版包含尚未正式发布的测试功能,仅用于赞助者本人尝鲜。请不要发给其他人或者用来制作整合包哦!"
  13. LabHint2.Text = $"若已累积赞助¥23.33,在爱发电私信发送 {vbLQ}解锁码{vbRQ} 即可永久隐藏此提示。"
  14. #End If
  15. End Sub
  16. '暂时关闭快照版提示
  17. #If Not BETA Then
  18. Private Sub BtnHintClose_Click(sender As Object, e As EventArgs) Handles BtnHintClose.Click
  19. AniDispose(PanHint, True)
  20. End Sub
  21. #End If
  22. #Region "主页"
  23. ''' <summary>
  24. ''' 刷新主页。
  25. ''' </summary>
  26. Private Sub Refresh() Handles Me.Loaded
  27. RunInNewThread(
  28. Sub()
  29. Try
  30. SyncLock RefreshLock
  31. RefreshReal()
  32. End SyncLock
  33. Catch ex As Exception
  34. Log(ex, "加载 PCL 主页自定义信息失败", If(ModeDebug, LogLevel.Msgbox, LogLevel.Hint))
  35. End Try
  36. End Sub, $"刷新主页 #{GetUuid()}")
  37. End Sub
  38. Private Sub RefreshReal()
  39. Dim Content As String = ""
  40. Dim Url As String
  41. Select Case Setup.Get("UiCustomType")
  42. Case 1
  43. '加载本地文件
  44. Log("[Page] 主页自定义数据来源:本地文件")
  45. Content = ReadFile(Path & "PCL\Custom.xaml") 'ReadFile 会进行存在检测
  46. Case 2
  47. Url = Setup.Get("UiCustomNet")
  48. Download:
  49. '加载联网文件
  50. If String.IsNullOrWhiteSpace(Url) Then Exit Select
  51. If Url = Setup.Get("CacheSavedPageUrl") AndAlso File.Exists(PathTemp & "Cache\Custom.xaml") Then
  52. '缓存可用
  53. Log("[Page] 主页自定义数据来源:联网缓存文件")
  54. Content = ReadFile(PathTemp & "Cache\Custom.xaml")
  55. '后台更新缓存
  56. OnlineLoader.Start(Url)
  57. Else
  58. '缓存不可用
  59. Log("[Page] 主页自定义数据来源:联网全新下载")
  60. Hint("正在加载主页……")
  61. RunInUiWait(Sub() LoadContent("")) '在加载结束前清空页面
  62. Setup.Set("CacheSavedPageVersion", "")
  63. OnlineLoader.Start(Url) '下载完成后将会再次触发更新
  64. Return
  65. End If
  66. Case 3
  67. Select Case Setup.Get("UiCustomPreset")
  68. Case 0
  69. Log("[Page] 主页预设:你知道吗")
  70. Content = "
  71. <local:MyCard Title=""你知道吗?"" Margin=""0,0,0,15"">
  72. <TextBlock Margin=""25,38,23,15"" FontSize=""13.5"" IsHitTestVisible=""False"" Text=""{hint}"" TextWrapping=""Wrap"" Foreground=""{DynamicResource ColorBrush1}"" />
  73. <local:MyIconButton Height=""22"" Width=""22"" Margin=""9"" VerticalAlignment=""Top"" HorizontalAlignment=""Right""
  74. EventType=""刷新主页"" EventData=""/""
  75. Logo=""M875.52 148.48C783.36 56.32 655.36 0 512 0 291.84 0 107.52 138.24 30.72 332.8l122.88 46.08C204.8 230.4 348.16 128 512 128c107.52 0 199.68 40.96 271.36 112.64L640 384h384V0L875.52 148.48zM512 896c-107.52 0-199.68-40.96-271.36-112.64L384 640H0v384l148.48-148.48C240.64 967.68 368.64 1024 512 1024c220.16 0 404.48-138.24 481.28-332.8L870.4 645.12C819.2 793.6 675.84 896 512 896z"" />
  76. </local:MyCard>"
  77. Case 1
  78. Log("[Page] 主页预设:回声洞")
  79. Content = "
  80. <local:MyCard Title=""回声洞"" Margin=""0,0,0,15"">
  81. <TextBlock Margin=""25,38,23,15"" FontSize=""13.5"" IsHitTestVisible=""False"" Text=""{cave}"" TextWrapping=""Wrap"" Foreground=""{DynamicResource ColorBrush1}"" />
  82. <local:MyIconButton Height=""22"" Width=""22"" Margin=""9"" VerticalAlignment=""Top"" HorizontalAlignment=""Right""
  83. EventType=""刷新主页"" EventData=""/""
  84. Logo=""M875.52 148.48C783.36 56.32 655.36 0 512 0 291.84 0 107.52 138.24 30.72 332.8l122.88 46.08C204.8 230.4 348.16 128 512 128c107.52 0 199.68 40.96 271.36 112.64L640 384h384V0L875.52 148.48zM512 896c-107.52 0-199.68-40.96-271.36-112.64L384 640H0v384l148.48-148.48C240.64 967.68 368.64 1024 512 1024c220.16 0 404.48-138.24 481.28-332.8L870.4 645.12C819.2 793.6 675.84 896 512 896z"" />
  85. </local:MyCard>"
  86. Case 2
  87. Log("[Page] 主页预设:Minecraft 新闻")
  88. Url = "https://pcl.mcnews.thestack.top"
  89. GoTo Download
  90. Case 3
  91. Log("[Page] 主页预设:简单主页")
  92. Url = "https://pclhomeplazaoss.lingyunawa.top:26994/d/Homepages/MFn233/Custom.xaml"
  93. GoTo Download
  94. Case 4
  95. Log("[Page] 主页预设:每日整合包推荐")
  96. Url = "https://pclsub.sodamc.com/"
  97. GoTo Download
  98. Case 5
  99. Log("[Page] 主页预设:Minecraft 皮肤推荐")
  100. Url = "https://forgepixel.com/pcl_sub_file"
  101. GoTo Download
  102. Case 6
  103. Log("[Page] 主页预设:OpenBMCLAPI 仪表盘 Lite")
  104. Url = "https://pcl-bmcl.milu.ink/"
  105. GoTo Download
  106. Case 7
  107. Log("[Page] 主页预设:主页市场")
  108. Url = "https://pclhomeplazaoss.lingyunawa.top:26994/d/Homepages/JingHai-Lingyun/Custom.xaml"
  109. GoTo Download
  110. Case 8
  111. Log("[Page] 主页预设:更新日志")
  112. Url = "https://pclhomeplazaoss.lingyunawa.top:26994/d/Homepages/Joker2184/UpdateHomepage.xaml"
  113. GoTo Download
  114. Case 9
  115. Log("[Page] 主页预设:PCL 新功能说明书")
  116. Url = "https://raw.gitcode.com/WForst-Breeze/WhatsNewPCL/raw/main/Custom.xaml"
  117. GoTo Download
  118. Case 10
  119. Log("[Page] 主页预设:OpenMCIM Dashboard")
  120. Url = "https://files.mcimirror.top/PCL"
  121. GoTo Download
  122. Case 11
  123. Log("[Page] 主页预设:杂志主页")
  124. Url = "https://pclhomeplazaoss.lingyunawa.top:26994/d/Homepages/Ext1nguisher/Custom.xaml"
  125. GoTo Download
  126. Case 12
  127. Log("[Page] 主页预设:PCL GitHub 仪表盘")
  128. Url = "https://ddf.pcl-community.org/Custom.xaml"
  129. GoTo Download
  130. End Select
  131. End Select
  132. RunInUi(Sub() LoadContent(Content))
  133. End Sub
  134. Private RefreshLock As New Object
  135. '联网获取主页文件
  136. Private OnlineLoader As New LoaderTask(Of String, Integer)("下载主页", AddressOf OnlineLoaderSub) With {.ReloadTimeout = 10 * 60 * 1000}
  137. Private Sub OnlineLoaderSub(Task As LoaderTask(Of String, Integer))
  138. Dim Address As String = Task.Input '#3721 中连续触发两次导致内容变化
  139. Try
  140. '获取版本校验地址
  141. Dim VersionAddress As String
  142. If Address.Contains(".xaml") Then
  143. VersionAddress = Address.Replace(".xaml", ".xaml.ini")
  144. Else
  145. VersionAddress = Address.BeforeFirst("?")
  146. If Not VersionAddress.EndsWith("/") Then VersionAddress += "/"
  147. VersionAddress += "version"
  148. If Address.Contains("?") Then VersionAddress += "?" & Address.AfterFirst("?")
  149. End If
  150. '校验版本
  151. Dim Version As String = ""
  152. Dim NeedDownload As Boolean = True
  153. Try
  154. Version = NetRequestByClientRetry(VersionAddress)
  155. If Version.Length > 1000 Then Throw New Exception($"获取的主页版本过长({Version.Length} 字符)")
  156. Dim CurrentVersion As String = Setup.Get("CacheSavedPageVersion")
  157. If Version <> "" AndAlso CurrentVersion <> "" AndAlso Version = CurrentVersion Then
  158. Log($"[Page] 当前缓存的主页已为最新,当前版本:{Version},检查源:{VersionAddress}")
  159. NeedDownload = False
  160. Else
  161. Log($"[Page] 需要下载联网主页,当前版本:{Version},检查源:{VersionAddress}")
  162. End If
  163. Catch exx As Exception
  164. Log(exx, $"联网获取主页版本失败", LogLevel.Developer)
  165. Log($"[Page] 无法检查联网主页版本,将直接下载,检查源:{VersionAddress}")
  166. End Try
  167. '实际下载
  168. If NeedDownload Then
  169. Dim FileContent As String = NetRequestByClientRetry(Address)
  170. Log($"[Page] 已联网下载主页,内容长度:{FileContent.Length},来源:{Address}")
  171. Setup.Set("CacheSavedPageUrl", Address)
  172. Setup.Set("CacheSavedPageVersion", Version)
  173. WriteFile(PathTemp & "Cache\Custom.xaml", FileContent)
  174. End If
  175. '要求刷新
  176. RunInUi(AddressOf Refresh) '不直接调用 Refresh,以防止死循环(#6245)
  177. Catch ex As Exception
  178. Log(ex, $"下载主页失败({Address})", If(ModeDebug, LogLevel.Msgbox, LogLevel.Hint))
  179. End Try
  180. End Sub
  181. ''' <summary>
  182. ''' 立即强制刷新主页。
  183. ''' 必须在 UI 线程调用。
  184. ''' </summary>
  185. Public Sub ForceRefresh() Implements IRefreshable.Refresh
  186. Log("[Page] 要求强制刷新主页")
  187. ClearCache()
  188. '实际的刷新
  189. If FrmMain.PageCurrent.Page = FormMain.PageType.Launch Then
  190. PanBack.ScrollToHome()
  191. Refresh()
  192. Else
  193. FrmMain.PageChange(FormMain.PageType.Launch)
  194. End If
  195. End Sub
  196. ''' <summary>
  197. ''' 清空主页缓存信息。
  198. ''' </summary>
  199. Private Sub ClearCache()
  200. LoadedContentHash = -1
  201. OnlineLoader.Input = ""
  202. Setup.Set("CacheSavedPageUrl", "")
  203. Setup.Set("CacheSavedPageVersion", "")
  204. Log("[Page] 已清空主页缓存")
  205. End Sub
  206. ''' <summary>
  207. ''' 从文本内容中加载主页。
  208. ''' 必须在 UI 线程调用。
  209. ''' </summary>
  210. Private Sub LoadContent(Content As String)
  211. SyncLock LoadContentLock
  212. '如果加载目标内容一致则不加载
  213. Dim Hash = Content.GetHashCode()
  214. If Hash = LoadedContentHash Then Return
  215. LoadedContentHash = Hash
  216. '实际加载内容
  217. PanCustom.Children.Clear()
  218. If String.IsNullOrWhiteSpace(Content) Then
  219. Log($"[Page] 实例化:清空主页 UI,来源为空")
  220. Return
  221. End If
  222. Dim LoadStartTime As Date = Date.Now
  223. Try
  224. '修改时应同时修改 PageOtherHelpDetail.Init
  225. Content = HelpArgumentReplace(Content)
  226. Do While Content.Contains("xmlns")
  227. Content = Content.RegexReplace("xmlns[^""']*(""|')[^""']*(""|')", "").Replace("xmlns", "") '禁止声明命名空间
  228. Loop
  229. Content = "<StackPanel xmlns=""http://schemas.microsoft.com/winfx/2006/xaml/presentation"" xmlns:sys=""clr-namespace:System;assembly=mscorlib"" xmlns:x=""http://schemas.microsoft.com/winfx/2006/xaml"" xmlns:local=""clr-namespace:PCL;assembly=Plain Craft Launcher 2"">" & Content & "</StackPanel>"
  230. Log($"[Page] 实例化:加载主页 UI 开始,最终内容长度:{Content.Count}")
  231. PanCustom.Children.Add(GetObjectFromXML(Content))
  232. Catch ex As Exception
  233. If ModeDebug Then
  234. Log(ex, "加载失败的主页内容:" & vbCrLf & Content)
  235. If MyMsgBox(If(TypeOf ex Is UnauthorizedAccessException, ex.Message, $"主页内容编写有误,请根据下列错误信息进行检查:{vbCrLf}{GetExceptionSummary(ex)}"),
  236. "加载主页界面失败", "重试", "取消") = 1 Then
  237. GoTo Refresh '防止 SyncLock 死锁
  238. End If
  239. Else
  240. Log(ex, "加载主页界面失败", LogLevel.Hint)
  241. End If
  242. Return
  243. End Try
  244. Dim LoadCostTime = (Date.Now - LoadStartTime).Milliseconds
  245. Log($"[Page] 实例化:加载主页 UI 完成,耗时 {LoadCostTime}ms")
  246. If LoadCostTime > 3000 Then Hint($"主页加载过于缓慢(花费了 {Math.Round(LoadCostTime / 1000, 1)} 秒),请向主页作者反馈此问题,或暂时停止使用该主页")
  247. End SyncLock
  248. Return
  249. Refresh:
  250. ForceRefresh()
  251. End Sub
  252. Private LoadedContentHash As Integer = -1
  253. Private LoadContentLock As New Object
  254. #End Region
  255. End Class