@e-xi/xion 0.0.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (542) hide show
  1. package/README.md +1 -0
  2. package/dist/bin/icon-generator.d.ts +22 -0
  3. package/dist/bin/index.d.ts +5 -0
  4. package/dist/bin/index.js +92 -0
  5. package/dist/bin/logo-generator.d.ts +22 -0
  6. package/dist/chunk-files/chunk-34OODP7M.js +147 -0
  7. package/dist/chunk-files/chunk-3KBZWBNP.js +51 -0
  8. package/dist/chunk-files/chunk-3R6EJDYR.js +10 -0
  9. package/dist/chunk-files/chunk-3RVKOFMP.js +68 -0
  10. package/dist/chunk-files/chunk-3S5OTD47.js +35 -0
  11. package/dist/chunk-files/chunk-3XB4IEWO.js +195 -0
  12. package/dist/chunk-files/chunk-3XOVD6UX.js +8 -0
  13. package/dist/chunk-files/chunk-4HEDNQUP.js +426 -0
  14. package/dist/chunk-files/chunk-4SSGMLEE.js +934 -0
  15. package/dist/chunk-files/chunk-5PKWVAQP.js +92 -0
  16. package/dist/chunk-files/chunk-6BOPFOZD.js +19 -0
  17. package/dist/chunk-files/chunk-6FDO72PN.js +25 -0
  18. package/dist/chunk-files/chunk-6X74EPRM.js +0 -0
  19. package/dist/chunk-files/chunk-B2FI5WI5.js +67 -0
  20. package/dist/chunk-files/chunk-B7DTBTWQ.js +74 -0
  21. package/dist/chunk-files/chunk-BFD2LHLK.js +60 -0
  22. package/dist/chunk-files/chunk-BJOPQNB2.js +319 -0
  23. package/dist/chunk-files/chunk-BMOLIJ3W.js +89 -0
  24. package/dist/chunk-files/chunk-BPTFUGTP.js +97 -0
  25. package/dist/chunk-files/chunk-CSUNGWAE.js +405 -0
  26. package/dist/chunk-files/chunk-D5ZV4VMI.js +627 -0
  27. package/dist/chunk-files/chunk-DD6WZ4NY.js +841 -0
  28. package/dist/chunk-files/chunk-DEODEAKM.js +19 -0
  29. package/dist/chunk-files/chunk-DRMV3M5V.js +1970 -0
  30. package/dist/chunk-files/chunk-EQTU45UO.js +21 -0
  31. package/dist/chunk-files/chunk-F7YTK2MY.js +154 -0
  32. package/dist/chunk-files/chunk-FMQTZ3QV.js +17 -0
  33. package/dist/chunk-files/chunk-FPN7JYR4.js +67 -0
  34. package/dist/chunk-files/chunk-FULHNQ4O.js +1243 -0
  35. package/dist/chunk-files/chunk-GN2FNR3Z.js +259 -0
  36. package/dist/chunk-files/chunk-GROGDGEL.js +177 -0
  37. package/dist/chunk-files/chunk-GUOSVDXA.js +34 -0
  38. package/dist/chunk-files/chunk-HT5V5A7S.js +6 -0
  39. package/dist/chunk-files/chunk-ID3YDA2K.js +19 -0
  40. package/dist/chunk-files/chunk-IH3R2NDR.js +230 -0
  41. package/dist/chunk-files/chunk-IMGYTSWY.js +261 -0
  42. package/dist/chunk-files/chunk-J34MOWJP.js +26 -0
  43. package/dist/chunk-files/chunk-KFK47PDH.js +77 -0
  44. package/dist/chunk-files/chunk-KFV4GXVE.js +11 -0
  45. package/dist/chunk-files/chunk-LFHJJQW3.js +723 -0
  46. package/dist/chunk-files/chunk-LQ67F6EY.js +32 -0
  47. package/dist/chunk-files/chunk-MJ6Q3TIX.js +703 -0
  48. package/dist/chunk-files/chunk-OUFO3LM4.js +135 -0
  49. package/dist/chunk-files/chunk-P4CX6I4J.js +14 -0
  50. package/dist/chunk-files/chunk-PL5KNBCY.js +78 -0
  51. package/dist/chunk-files/chunk-PVWRRUOK.js +11 -0
  52. package/dist/chunk-files/chunk-Q7LCZIQP.js +15 -0
  53. package/dist/chunk-files/chunk-Q7YMMN7J.js +220 -0
  54. package/dist/chunk-files/chunk-RAVPJRBA.js +118 -0
  55. package/dist/chunk-files/chunk-RN7AI33H.js +26 -0
  56. package/dist/chunk-files/chunk-RODB64YF.js +148 -0
  57. package/dist/chunk-files/chunk-SVTZ4T6S.js +10 -0
  58. package/dist/chunk-files/chunk-T3QCAOCO.js +20 -0
  59. package/dist/chunk-files/chunk-U4XEWVBH.js +19 -0
  60. package/dist/chunk-files/chunk-UCMR6V67.js +746 -0
  61. package/dist/chunk-files/chunk-UFYEZIUE.js +1269 -0
  62. package/dist/chunk-files/chunk-UIJUY7QZ.js +18 -0
  63. package/dist/chunk-files/chunk-VGDNICVG.js +67 -0
  64. package/dist/chunk-files/chunk-W2I3I7U7.js +35 -0
  65. package/dist/chunk-files/chunk-WGYOMA43.js +33 -0
  66. package/dist/chunk-files/chunk-WKVLVI6N.js +44 -0
  67. package/dist/chunk-files/chunk-WOJ2UKI7.js +11 -0
  68. package/dist/chunk-files/chunk-Y3OEXVQ2.js +59 -0
  69. package/dist/chunk-files/chunk-YLZRRUY7.js +6 -0
  70. package/dist/chunk-files/chunk-YTHS2ZV7.js +51 -0
  71. package/dist/chunk-files/chunk-YXAEUJKJ.js +331 -0
  72. package/dist/chunk-files/chunk-YZOJOLFL.js +121 -0
  73. package/dist/main/app/app-lifecycle-abstract.d.ts +190 -0
  74. package/dist/main/app/app-lifecycle.d.ts +7 -0
  75. package/dist/main/app/icons/icon.ico +0 -0
  76. package/dist/main/app/index.d.ts +8 -0
  77. package/dist/main/app/index.js +1226 -0
  78. package/dist/main/app/types/app.d.ts +74 -0
  79. package/dist/main/app/xo-app-abstract.d.ts +464 -0
  80. package/dist/main/app/xo-app.d.ts +23 -0
  81. package/dist/main/auth/index.d.ts +8 -0
  82. package/dist/main/auth/index.js +109 -0
  83. package/dist/main/auth/jwt-auth-manager.d.ts +302 -0
  84. package/dist/main/auth/jwt-auth-provider-abstract.d.ts +100 -0
  85. package/dist/main/auth/jwt-auth-refresh-rejected-error.d.ts +12 -0
  86. package/dist/main/auth/jwt-auth-session-changed-error.d.ts +12 -0
  87. package/dist/main/auth/types/jwt-auth-manager.d.ts +13 -0
  88. package/dist/main/banner/banner-abstract.d.ts +38 -0
  89. package/dist/main/banner/banner-manager.d.ts +20 -0
  90. package/dist/main/banner/index.d.ts +6 -0
  91. package/dist/main/banner/index.js +10 -0
  92. package/dist/main/banner/types/banner.d.ts +17 -0
  93. package/dist/main/config/app-config.d.ts +6 -0
  94. package/dist/main/config/index.d.ts +13 -0
  95. package/dist/main/config/index.js +33 -0
  96. package/dist/main/config/logger-config.d.ts +6 -0
  97. package/dist/main/config/remote-service-config.d.ts +6 -0
  98. package/dist/main/config/tray-config.d.ts +6 -0
  99. package/dist/main/config/types/app.d.ts +38 -0
  100. package/dist/main/config/types/logger.d.ts +82 -0
  101. package/dist/main/config/types/window.d.ts +35 -0
  102. package/dist/main/config/updater-config.d.ts +6 -0
  103. package/dist/main/config/window/main-window-config.d.ts +6 -0
  104. package/dist/main/config/window/setting-window-config.d.ts +6 -0
  105. package/dist/main/file-association/file-association-handlers-abstract.d.ts +23 -0
  106. package/dist/main/file-association/file-association-manager-abstract.d.ts +87 -0
  107. package/dist/main/file-association/file-association-manager.d.ts +13 -0
  108. package/dist/main/file-association/handlers/app-file-association-handlers.d.ts +12 -0
  109. package/dist/main/file-association/index.d.ts +8 -0
  110. package/dist/main/file-association/index.js +13 -0
  111. package/dist/main/file-association/types/file-association.d.ts +31 -0
  112. package/dist/main/ipc/handlers/app-handlers.d.ts +13 -0
  113. package/dist/main/ipc/handlers/auth-handlers.d.ts +12 -0
  114. package/dist/main/ipc/handlers/clipboard-handlers.d.ts +13 -0
  115. package/dist/main/ipc/handlers/contex-menu-handlers.d.ts +13 -0
  116. package/dist/main/ipc/handlers/dialog-handlers.d.ts +13 -0
  117. package/dist/main/ipc/handlers/file-handlers.d.ts +13 -0
  118. package/dist/main/ipc/handlers/log-handlers.d.ts +45 -0
  119. package/dist/main/ipc/handlers/remote-service-handlers.d.ts +13 -0
  120. package/dist/main/ipc/handlers/shell-handlers.d.ts +13 -0
  121. package/dist/main/ipc/handlers/theme-handlers.d.ts +13 -0
  122. package/dist/main/ipc/handlers/updater-handlers.d.ts +13 -0
  123. package/dist/main/ipc/handlers/window-handlers.d.ts +13 -0
  124. package/dist/main/ipc/index.d.ts +20 -0
  125. package/dist/main/ipc/index.js +60 -0
  126. package/dist/main/ipc/ipc-handlers-abstract.d.ts +23 -0
  127. package/dist/main/ipc/ipc-manager-abstract.d.ts +46 -0
  128. package/dist/main/ipc/ipc-manager.d.ts +13 -0
  129. package/dist/main/ipc/types/ipc-handler.d.ts +22 -0
  130. package/dist/main/ipc/utils/ipc-handler-util.d.ts +24 -0
  131. package/dist/main/logger/index.d.ts +4 -0
  132. package/dist/main/logger/index.js +13 -0
  133. package/dist/main/logger/xo-logger.d.ts +113 -0
  134. package/dist/main/menu/consts/menu-type.d.ts +1 -0
  135. package/dist/main/menu/index.d.ts +8 -0
  136. package/dist/main/menu/index.js +28 -0
  137. package/dist/main/menu/menu-items.d.ts +192 -0
  138. package/dist/main/menu/menu-manager-abstract.d.ts +273 -0
  139. package/dist/main/menu/menu-manager.d.ts +12 -0
  140. package/dist/main/menu/types/menu.d.ts +101 -0
  141. package/dist/main/mode/app-mode.d.ts +32 -0
  142. package/dist/main/mode/index.d.ts +5 -0
  143. package/dist/main/mode/index.js +9 -0
  144. package/dist/main/mode/types/mode.d.ts +25 -0
  145. package/dist/main/protocol/consts/protocol-keys.d.ts +10 -0
  146. package/dist/main/protocol/handlers/app-protocol-handlers.d.ts +12 -0
  147. package/dist/main/protocol/index.d.ts +9 -0
  148. package/dist/main/protocol/index.js +15 -0
  149. package/dist/main/protocol/protocol-handlers-abstract.d.ts +23 -0
  150. package/dist/main/protocol/protocol-manager-abstract.d.ts +85 -0
  151. package/dist/main/protocol/protocol-manager.d.ts +13 -0
  152. package/dist/main/protocol/types/protocol.d.ts +33 -0
  153. package/dist/main/remote-service/consts/remote-service-methods.d.ts +5 -0
  154. package/dist/main/remote-service/index.d.ts +7 -0
  155. package/dist/main/remote-service/index.js +17 -0
  156. package/dist/main/remote-service/remote-service-manager-abstract.d.ts +303 -0
  157. package/dist/main/remote-service/remote-service-manager.d.ts +7 -0
  158. package/dist/main/remote-service/types/remote-service.d.ts +9 -0
  159. package/dist/main/renderer-protocol/handlers/renderer-remote-service-protocol-handlers.d.ts +130 -0
  160. package/dist/main/renderer-protocol/handlers/renderer-root-protocol-handlers.d.ts +65 -0
  161. package/dist/main/renderer-protocol/index.d.ts +9 -0
  162. package/dist/main/renderer-protocol/index.js +18 -0
  163. package/dist/main/renderer-protocol/renderer-protocol-handlers-abstract.d.ts +23 -0
  164. package/dist/main/renderer-protocol/renderer-protocol-manager-abstract.d.ts +78 -0
  165. package/dist/main/renderer-protocol/renderer-protocol-manager.d.ts +13 -0
  166. package/dist/main/renderer-protocol/types/renderer-protocol.d.ts +34 -0
  167. package/dist/main/shortcut/handlers/app-shortcut-handlers.d.ts +11 -0
  168. package/dist/main/shortcut/handlers/window-shortcut-handlers.d.ts +11 -0
  169. package/dist/main/shortcut/index.d.ts +9 -0
  170. package/dist/main/shortcut/index.js +17 -0
  171. package/dist/main/shortcut/shortcut-handlers-abstract.d.ts +18 -0
  172. package/dist/main/shortcut/shortcut-manager-abstract.d.ts +121 -0
  173. package/dist/main/shortcut/shortcut-manager.d.ts +12 -0
  174. package/dist/main/shortcut/types/shortcut.d.ts +50 -0
  175. package/dist/main/store/app-store.d.ts +179 -0
  176. package/dist/main/store/index.d.ts +7 -0
  177. package/dist/main/store/index.js +13 -0
  178. package/dist/main/store/jwt-auth-store.d.ts +36 -0
  179. package/dist/main/store/types/app-store.d.ts +46 -0
  180. package/dist/main/store/types/jwt-auth-store.d.ts +14 -0
  181. package/dist/main/theme/consts/theme-sources.d.ts +10 -0
  182. package/dist/main/theme/index.d.ts +7 -0
  183. package/dist/main/theme/index.js +16 -0
  184. package/dist/main/theme/theme-manager-abstract.d.ts +93 -0
  185. package/dist/main/theme/theme-manager.d.ts +7 -0
  186. package/dist/main/theme/types/theme.d.ts +38 -0
  187. package/dist/main/tray/consts/tray-animation-name.d.ts +1 -0
  188. package/dist/main/tray/consts/tray-icon-name.d.ts +1 -0
  189. package/dist/main/tray/icons/blur.ico +0 -0
  190. package/dist/main/tray/icons/error.ico +0 -0
  191. package/dist/main/tray/icons/focus.ico +0 -0
  192. package/dist/main/tray/icons/none.ico +0 -0
  193. package/dist/main/tray/icons/offline.ico +0 -0
  194. package/dist/main/tray/icons/online.ico +0 -0
  195. package/dist/main/tray/icons/success.ico +0 -0
  196. package/dist/main/tray/index.d.ts +11 -0
  197. package/dist/main/tray/index.js +27 -0
  198. package/dist/main/tray/tray-animation.d.ts +48 -0
  199. package/dist/main/tray/tray-icon.d.ts +51 -0
  200. package/dist/main/tray/tray-lifecycle-abstract.d.ts +154 -0
  201. package/dist/main/tray/tray-lifecycle.d.ts +7 -0
  202. package/dist/main/tray/tray-manager.d.ts +173 -0
  203. package/dist/main/tray/types/tray.d.ts +81 -0
  204. package/dist/main/updater/dev-app-update.yml +5 -0
  205. package/dist/main/updater/index.d.ts +6 -0
  206. package/dist/main/updater/index.js +20 -0
  207. package/dist/main/updater/types/updater.d.ts +167 -0
  208. package/dist/main/updater/updater-manager-abstract.d.ts +237 -0
  209. package/dist/main/updater/updater-manager.d.ts +7 -0
  210. package/dist/main/utils/file-association-util.d.ts +43 -0
  211. package/dist/main/utils/index.d.ts +14 -0
  212. package/dist/main/utils/index.js +105 -0
  213. package/dist/main/utils/menu-util.d.ts +12 -0
  214. package/dist/main/utils/protocol-util.d.ts +49 -0
  215. package/dist/main/utils/runtime-config-util.d.ts +75 -0
  216. package/dist/main/utils/shortcut-util.d.ts +38 -0
  217. package/dist/main/utils/tray-util.d.ts +18 -0
  218. package/dist/main/utils/window-util.d.ts +55 -0
  219. package/dist/main/utils/xo-app-root-util.d.ts +30 -0
  220. package/dist/main/utils/xo-app-util.d.ts +24 -0
  221. package/dist/main/utils/xo-path-util.d.ts +59 -0
  222. package/dist/main/utils/xo-util.d.ts +17 -0
  223. package/dist/main/window/index.d.ts +10 -0
  224. package/dist/main/window/index.js +36 -0
  225. package/dist/main/window/main/main-window-lifecycle.d.ts +7 -0
  226. package/dist/main/window/main/main-window-type.d.ts +5 -0
  227. package/dist/main/window/setting/setting-window-lifecycle.d.ts +7 -0
  228. package/dist/main/window/setting/setting-window-type.d.ts +5 -0
  229. package/dist/main/window/types/window.d.ts +86 -0
  230. package/dist/main/window/window-lifecycle-abstract.d.ts +514 -0
  231. package/dist/main/window/window-manager.d.ts +422 -0
  232. package/dist/preload/bridge/bridge-abstract.d.ts +11 -0
  233. package/dist/preload/bridge/bridge.d.ts +35 -0
  234. package/dist/preload/bridge/index.d.ts +6 -0
  235. package/dist/preload/bridge/index.js +117 -0
  236. package/dist/preload/bridge/preload.cjs +1706 -0
  237. package/dist/preload/bridge/preload.internal.d.ts +1 -0
  238. package/dist/preload/bridge/types/bridge.d.ts +19 -0
  239. package/dist/preload/bridges/app/app-bridge.d.ts +142 -0
  240. package/dist/preload/bridges/app/types/app.d.ts +65 -0
  241. package/dist/preload/bridges/auth/auth-bridge.d.ts +36 -0
  242. package/dist/preload/bridges/auth/types/auth.d.ts +23 -0
  243. package/dist/preload/bridges/clipboard/clipboard-bridge.d.ts +37 -0
  244. package/dist/preload/bridges/clipboard/types/clipboard.d.ts +23 -0
  245. package/dist/preload/bridges/context-menu/context-menu-bridge.d.ts +27 -0
  246. package/dist/preload/bridges/context-menu/types/context-menu.d.ts +19 -0
  247. package/dist/preload/bridges/dialog/dialog-bridge.d.ts +30 -0
  248. package/dist/preload/bridges/dialog/types/dialog.d.ts +41 -0
  249. package/dist/preload/bridges/file/file-bridge.d.ts +34 -0
  250. package/dist/preload/bridges/file/types/file.d.ts +21 -0
  251. package/dist/preload/bridges/index.d.ts +29 -0
  252. package/dist/preload/bridges/index.js +40 -0
  253. package/dist/preload/bridges/ipc/ipc-bridge.d.ts +43 -0
  254. package/dist/preload/bridges/ipc/types/ipc.d.ts +23 -0
  255. package/dist/preload/bridges/log/log-bridge.d.ts +52 -0
  256. package/dist/preload/bridges/log/types/log.d.ts +20 -0
  257. package/dist/preload/bridges/remote-service/remote-service-bridge.d.ts +55 -0
  258. package/dist/preload/bridges/remote-service/types/remote-service.d.ts +29 -0
  259. package/dist/preload/bridges/shell/shell-bridge.d.ts +27 -0
  260. package/dist/preload/bridges/shell/types/shell.d.ts +19 -0
  261. package/dist/preload/bridges/theme/theme-bridge.d.ts +32 -0
  262. package/dist/preload/bridges/theme/types/theme.d.ts +21 -0
  263. package/dist/preload/bridges/updater/types/updater.d.ts +35 -0
  264. package/dist/preload/bridges/updater/updater-bridge.d.ts +66 -0
  265. package/dist/preload/bridges/window/internal/route-redirect-buffer.d.ts +36 -0
  266. package/dist/preload/bridges/window/types/window.d.ts +53 -0
  267. package/dist/preload/bridges/window/window-bridge.d.ts +118 -0
  268. package/dist/preload/utils/bridge-util.d.ts +43 -0
  269. package/dist/preload/utils/index.d.ts +4 -0
  270. package/dist/preload/utils/index.js +7 -0
  271. package/dist/renderer/app/bootstrap-renderer.d.ts +6 -0
  272. package/dist/renderer/app/index.d.ts +5 -0
  273. package/dist/renderer/app/index.js +164 -0
  274. package/dist/renderer/app/styles-element-plus.internal.d.ts +2 -0
  275. package/dist/renderer/app/styles-xion.internal.d.ts +2 -0
  276. package/dist/renderer/app/types/app.d.ts +51 -0
  277. package/dist/renderer/components/captcha/internal/captcha-controller.d.ts +280 -0
  278. package/dist/renderer/components/captcha/internal/captcha-css-property.d.ts +25 -0
  279. package/dist/renderer/components/captcha/internal/captcha-defaults.d.ts +33 -0
  280. package/dist/renderer/components/captcha/internal/captcha-errors.d.ts +21 -0
  281. package/dist/renderer/components/captcha/internal/captcha-helper.d.ts +72 -0
  282. package/dist/renderer/components/captcha/internal/captcha-injector.d.ts +16 -0
  283. package/dist/renderer/components/captcha/internal/captcha-runtime-types.d.ts +153 -0
  284. package/dist/renderer/components/captcha/internal/captcha-service.d.ts +22 -0
  285. package/dist/renderer/components/captcha/internal/captcha-slide-types.d.ts +62 -0
  286. package/dist/renderer/components/captcha/internal/captcha-ui-patch.d.ts +43 -0
  287. package/dist/renderer/components/captcha/internal/captcha-wasm-loader.d.ts +36 -0
  288. package/dist/renderer/components/captcha/style/index.less +132 -0
  289. package/dist/renderer/components/captcha/types/captcha.d.ts +132 -0
  290. package/dist/renderer/components/captcha/xo-captcha-host.vue +151 -0
  291. package/dist/renderer/components/captcha/xo-captcha.vue +83 -0
  292. package/dist/renderer/components/captcha.d.ts +40 -0
  293. package/dist/renderer/components/context-menu/types/context-menu.d.ts +55 -0
  294. package/dist/renderer/components/context-menu/xo-context-menu-items.vue +112 -0
  295. package/dist/renderer/components/context-menu/xo-context-menu.vue +356 -0
  296. package/dist/renderer/components/context-menu.d.ts +32 -0
  297. package/dist/renderer/components/divider/types/divider.d.ts +31 -0
  298. package/dist/renderer/components/divider/xo-divider.vue +176 -0
  299. package/dist/renderer/components/form/types/form-flex-row.d.ts +21 -0
  300. package/dist/renderer/components/form/types/form-flex.d.ts +49 -0
  301. package/dist/renderer/components/form/xo-form-flex-row.vue +122 -0
  302. package/dist/renderer/components/form/xo-form-flex.vue +115 -0
  303. package/dist/renderer/components/index.d.ts +70 -0
  304. package/dist/renderer/components/index.js +1282 -0
  305. package/dist/renderer/components/layouts/types/app-layout.d.ts +29 -0
  306. package/dist/renderer/components/layouts/types/mini-layout.d.ts +23 -0
  307. package/dist/renderer/components/layouts/types/simple-layout.d.ts +17 -0
  308. package/dist/renderer/components/layouts/xo-app-layout.vue +350 -0
  309. package/dist/renderer/components/layouts/xo-mini-layout.vue +207 -0
  310. package/dist/renderer/components/layouts/xo-simple-layout.vue +43 -0
  311. package/dist/renderer/components/pages/types/app-page.d.ts +25 -0
  312. package/dist/renderer/components/pages/types/bootstrap-page.d.ts +35 -0
  313. package/dist/renderer/components/pages/types/dynamic-page.d.ts +20 -0
  314. package/dist/renderer/components/pages/types/settings-page.d.ts +23 -0
  315. package/dist/renderer/components/pages/xo-app-page.vue +230 -0
  316. package/dist/renderer/components/pages/xo-bootstrap-page.vue +93 -0
  317. package/dist/renderer/components/pages/xo-dynamic-page.vue +28 -0
  318. package/dist/renderer/components/pages/xo-settings-page.vue +143 -0
  319. package/dist/renderer/components/radio-group/types/radio-group.d.ts +30 -0
  320. package/dist/renderer/components/radio-group/xo-radio-group.vue +38 -0
  321. package/dist/renderer/components/service-status-bar/types/service-status-bar.d.ts +65 -0
  322. package/dist/renderer/components/service-status-bar/xo-service-status-bar.vue +193 -0
  323. package/dist/renderer/components/settings-components/types/setting-app-opacity.d.ts +19 -0
  324. package/dist/renderer/components/settings-components/types/setting-log-level.d.ts +23 -0
  325. package/dist/renderer/components/settings-components/types/setting-shortcut-keys-record-for-form-flex-rows.d.ts +47 -0
  326. package/dist/renderer/components/settings-components/types/setting-shortcut-keys-record.d.ts +23 -0
  327. package/dist/renderer/components/settings-components/types/setting-window-material.d.ts +23 -0
  328. package/dist/renderer/components/settings-components/xo-setting-app-opacity.vue +105 -0
  329. package/dist/renderer/components/settings-components/xo-setting-log-level.vue +84 -0
  330. package/dist/renderer/components/settings-components/xo-setting-shortcut-keys-record-for-form-flex-rows.vue +37 -0
  331. package/dist/renderer/components/settings-components/xo-setting-shortcut-keys-record.vue +74 -0
  332. package/dist/renderer/components/settings-components/xo-setting-window-material.vue +83 -0
  333. package/dist/renderer/components/settings-pages/types/setting-page-folder.d.ts +41 -0
  334. package/dist/renderer/components/settings-pages/types/setting-page-general.d.ts +23 -0
  335. package/dist/renderer/components/settings-pages/types/setting-page-remote-service.d.ts +19 -0
  336. package/dist/renderer/components/settings-pages/types/setting-page-updater.d.ts +27 -0
  337. package/dist/renderer/components/settings-pages/xo-setting-page-folder.vue +137 -0
  338. package/dist/renderer/components/settings-pages/xo-setting-page-general.vue +255 -0
  339. package/dist/renderer/components/settings-pages/xo-setting-page-remote-service.vue +183 -0
  340. package/dist/renderer/components/settings-pages/xo-setting-page-updater.vue +350 -0
  341. package/dist/renderer/components/shortcut-keys-record/types/shortcut-keys-record.d.ts +25 -0
  342. package/dist/renderer/components/shortcut-keys-record/xo-shortcut-keys-record.vue +161 -0
  343. package/dist/renderer/components/side-bar/types/sidebar-logo.d.ts +39 -0
  344. package/dist/renderer/components/side-bar/xo-sidebar-logo.vue +133 -0
  345. package/dist/renderer/components/spacing-line/types/spacing-line.d.ts +17 -0
  346. package/dist/renderer/components/spacing-line/xo-spacing-line.vue +53 -0
  347. package/dist/renderer/components/theme-switch/types/theme-switch-mini.d.ts +21 -0
  348. package/dist/renderer/components/theme-switch/types/theme-switch.d.ts +45 -0
  349. package/dist/renderer/components/theme-switch/xo-theme-switch-mini.vue +93 -0
  350. package/dist/renderer/components/theme-switch/xo-theme-switch.vue +200 -0
  351. package/dist/renderer/components/title-bar/types/title-bar.d.ts +58 -0
  352. package/dist/renderer/components/title-bar/xo-title-bar.vue +364 -0
  353. package/dist/renderer/components/types/sidebar-menu.d.ts +37 -0
  354. package/dist/renderer/components/types/vue.d.ts +9 -0
  355. package/dist/renderer/components/updater/types/updater.d.ts +97 -0
  356. package/dist/renderer/components/updater/xo-updater.vue +1190 -0
  357. package/dist/renderer/components/window-control/types/window-control.d.ts +17 -0
  358. package/dist/renderer/components/window-control/xo-window-control.vue +193 -0
  359. package/dist/renderer/composables/index.d.ts +7 -0
  360. package/dist/renderer/composables/index.js +570 -0
  361. package/dist/renderer/composables/use-xo-boolean.d.ts +14 -0
  362. package/dist/renderer/composables/use-xo-data-loader.d.ts +73 -0
  363. package/dist/renderer/composables/use-xo-form-control.d.ts +84 -0
  364. package/dist/renderer/composables/use-xo-updater-action.d.ts +25 -0
  365. package/dist/renderer/global/index.d.ts +4 -0
  366. package/dist/renderer/global/index.js +0 -0
  367. package/dist/renderer/global/types/window.d.ts +21 -0
  368. package/dist/renderer/icons/demo.css +539 -0
  369. package/dist/renderer/icons/iconfont.css +490 -0
  370. package/dist/renderer/services/index.d.ts +6 -0
  371. package/dist/renderer/services/index.js +444 -0
  372. package/dist/renderer/services/orval-axios-mutator.d.ts +9 -0
  373. package/dist/renderer/services/types/xo-api.d.ts +92 -0
  374. package/dist/renderer/services/xo-api-requester.d.ts +129 -0
  375. package/dist/renderer/store/app/app-store.d.ts +68 -0
  376. package/dist/renderer/store/auth/auth-store.d.ts +43 -0
  377. package/dist/renderer/store/index.d.ts +9 -0
  378. package/dist/renderer/store/index.js +595 -0
  379. package/dist/renderer/store/remote-service/remote-service-store.d.ts +52 -0
  380. package/dist/renderer/store/theme/theme-store.d.ts +52 -0
  381. package/dist/renderer/store/updater/updater-store.d.ts +88 -0
  382. package/dist/renderer/store/window/window-store.d.ts +58 -0
  383. package/dist/renderer/styles/css/element-plus.less +280 -0
  384. package/dist/renderer/styles/css/iconfont-patch.less +6 -0
  385. package/dist/renderer/styles/css/reset.less +83 -0
  386. package/dist/renderer/styles/css/scrollbar.less +56 -0
  387. package/dist/renderer/styles/index.less +35 -0
  388. package/dist/renderer/styles/mixin.less +144 -0
  389. package/dist/renderer/styles/var/element-plus/dark.less +32 -0
  390. package/dist/renderer/styles/var/element-plus/root.less +88 -0
  391. package/dist/renderer/styles/var/global/dark.less +10 -0
  392. package/dist/renderer/styles/var/global/root.less +46 -0
  393. package/dist/renderer/styles/var/layout/dark.less +7 -0
  394. package/dist/renderer/styles/var/layout/root.less +9 -0
  395. package/dist/renderer/styles/var/scrollbar/dark.less +13 -0
  396. package/dist/renderer/styles/var/scrollbar/root.less +35 -0
  397. package/dist/renderer/utils/auth-route-util.d.ts +117 -0
  398. package/dist/renderer/utils/context-util.d.ts +13 -0
  399. package/dist/renderer/utils/error-util.d.ts +12 -0
  400. package/dist/renderer/utils/index.d.ts +14 -0
  401. package/dist/renderer/utils/index.js +1522 -0
  402. package/dist/renderer/utils/keyboard-util.d.ts +86 -0
  403. package/dist/renderer/utils/message-util.d.ts +161 -0
  404. package/dist/renderer/utils/renderer-log-util.d.ts +44 -0
  405. package/dist/renderer/utils/renderer-util.d.ts +37 -0
  406. package/dist/renderer/utils/router-util.d.ts +186 -0
  407. package/dist/renderer/utils/shortcut-util.d.ts +20 -0
  408. package/dist/renderer/utils/storage-util.d.ts +85 -0
  409. package/dist/renderer/utils/types/vue-router.d.ts +17 -0
  410. package/dist/shared/app/consts/app-launch-mode.d.ts +9 -0
  411. package/dist/shared/app/consts/update-mode.d.ts +8 -0
  412. package/dist/shared/app/consts/window-close-behavior.d.ts +8 -0
  413. package/dist/shared/app/consts/window-material.d.ts +8 -0
  414. package/dist/shared/app/consts/xion-name.d.ts +5 -0
  415. package/dist/shared/app/electron-app-config.d.ts +5 -0
  416. package/dist/shared/app/index.d.ts +16 -0
  417. package/dist/shared/app/index.js +30 -0
  418. package/dist/shared/app/types/app-info.d.ts +32 -0
  419. package/dist/shared/app/types/app-launch-mode.d.ts +13 -0
  420. package/dist/shared/app/types/app-paths.d.ts +27 -0
  421. package/dist/shared/app/types/general-settings.d.ts +27 -0
  422. package/dist/shared/app/types/on-window-close.d.ts +13 -0
  423. package/dist/shared/app/types/update-mode.d.ts +13 -0
  424. package/dist/shared/app/types/window-material.d.ts +2 -0
  425. package/dist/shared/auth/const/auth-status.d.ts +2 -0
  426. package/dist/shared/auth/index.d.ts +5 -0
  427. package/dist/shared/auth/index.js +5 -0
  428. package/dist/shared/auth/types/auth.d.ts +78 -0
  429. package/dist/shared/color/consts/color.d.ts +5 -0
  430. package/dist/shared/color/index.d.ts +5 -0
  431. package/dist/shared/color/index.js +6 -0
  432. package/dist/shared/color/types/color.d.ts +26 -0
  433. package/dist/shared/electron-builder/index.d.ts +4 -0
  434. package/dist/shared/electron-builder/index.js +0 -0
  435. package/dist/shared/electron-builder/types/electron-builder-options.d.ts +34 -0
  436. package/dist/shared/errors/index.d.ts +4 -0
  437. package/dist/shared/errors/index.js +10 -0
  438. package/dist/shared/errors/ipc-invoke-error.d.ts +32 -0
  439. package/dist/shared/ipc/channels/app-channels.d.ts +56 -0
  440. package/dist/shared/ipc/channels/auth-channels.d.ts +14 -0
  441. package/dist/shared/ipc/channels/clipboard-channels.d.ts +14 -0
  442. package/dist/shared/ipc/channels/context-menu-channels.d.ts +10 -0
  443. package/dist/shared/ipc/channels/dialog-channels.d.ts +12 -0
  444. package/dist/shared/ipc/channels/file-channels.d.ts +12 -0
  445. package/dist/shared/ipc/channels/log-channels.d.ts +14 -0
  446. package/dist/shared/ipc/channels/remote-service-channels.d.ts +20 -0
  447. package/dist/shared/ipc/channels/shell-channels.d.ts +10 -0
  448. package/dist/shared/ipc/channels/theme-channels.d.ts +12 -0
  449. package/dist/shared/ipc/channels/updater-channels.d.ts +26 -0
  450. package/dist/shared/ipc/channels/window-channels.d.ts +44 -0
  451. package/dist/shared/ipc/consts/ipc-channel.d.ts +1 -0
  452. package/dist/shared/ipc/index.d.ts +19 -0
  453. package/dist/shared/ipc/index.js +46 -0
  454. package/dist/shared/ipc/ipc-result.d.ts +20 -0
  455. package/dist/shared/ipc/types/ipc-logger.d.ts +27 -0
  456. package/dist/shared/ipc/types/ipc.d.ts +61 -0
  457. package/dist/shared/logger/consts/log-levels.d.ts +14 -0
  458. package/dist/shared/logger/index.d.ts +4 -0
  459. package/dist/shared/logger/index.js +10 -0
  460. package/dist/shared/menu/consts/menu-command.d.ts +1 -0
  461. package/dist/shared/menu/index.d.ts +6 -0
  462. package/dist/shared/menu/index.js +10 -0
  463. package/dist/shared/menu/menu-command.d.ts +24 -0
  464. package/dist/shared/menu/types/menu.d.ts +72 -0
  465. package/dist/shared/mode/consts/command.d.ts +10 -0
  466. package/dist/shared/mode/consts/mode.d.ts +22 -0
  467. package/dist/shared/mode/index.d.ts +5 -0
  468. package/dist/shared/mode/index.js +18 -0
  469. package/dist/shared/remote-service/const/remote-service.d.ts +8 -0
  470. package/dist/shared/remote-service/index.d.ts +5 -0
  471. package/dist/shared/remote-service/index.js +38 -0
  472. package/dist/shared/remote-service/types/remote-service.d.ts +146 -0
  473. package/dist/shared/renderer/index.d.ts +7 -0
  474. package/dist/shared/renderer/index.js +0 -0
  475. package/dist/shared/renderer/types/element-plus.d.ts +20 -0
  476. package/dist/shared/renderer/types/input.d.ts +11 -0
  477. package/dist/shared/renderer/types/options.d.ts +22 -0
  478. package/dist/shared/renderer/types/switch.d.ts +11 -0
  479. package/dist/shared/renderer-protocol/consts/renderer-protocol-keys.d.ts +10 -0
  480. package/dist/shared/renderer-protocol/index.d.ts +5 -0
  481. package/dist/shared/renderer-protocol/index.js +6 -0
  482. package/dist/shared/renderer-protocol/types/renderer-protocol.d.ts +7 -0
  483. package/dist/shared/runtime/index.d.ts +4 -0
  484. package/dist/shared/runtime/index.js +0 -0
  485. package/dist/shared/runtime/types/runtime.d.ts +20 -0
  486. package/dist/shared/shortcut/consts/shortcut-handler-ids.d.ts +9 -0
  487. package/dist/shared/shortcut/consts/shortcut-id.d.ts +1 -0
  488. package/dist/shared/shortcut/index.d.ts +6 -0
  489. package/dist/shared/shortcut/index.js +10 -0
  490. package/dist/shared/shortcut/types/shortcut.d.ts +13 -0
  491. package/dist/shared/utils/bytes-util.d.ts +16 -0
  492. package/dist/shared/utils/index.d.ts +15 -0
  493. package/dist/shared/utils/index.js +42 -0
  494. package/dist/shared/utils/ipc-util.d.ts +12 -0
  495. package/dist/shared/utils/log-util.d.ts +33 -0
  496. package/dist/shared/utils/menu-util.d.ts +12 -0
  497. package/dist/shared/utils/number-util.d.ts +12 -0
  498. package/dist/shared/utils/object-util.d.ts +88 -0
  499. package/dist/shared/utils/regexp-util.d.ts +22 -0
  500. package/dist/shared/utils/shortcut-util.d.ts +12 -0
  501. package/dist/shared/utils/string-util.d.ts +14 -0
  502. package/dist/shared/utils/time-util.d.ts +32 -0
  503. package/dist/shared/utils/validator-util.d.ts +12 -0
  504. package/dist/shared/utils/window-shared-util.d.ts +26 -0
  505. package/dist/shared/window/consts/window-record-id.d.ts +2 -0
  506. package/dist/shared/window/consts/window-type-name.d.ts +1 -0
  507. package/dist/shared/window/identity/main-window-identity.d.ts +5 -0
  508. package/dist/shared/window/identity/setting-window-identity.d.ts +5 -0
  509. package/dist/shared/window/index.d.ts +8 -0
  510. package/dist/shared/window/index.js +23 -0
  511. package/dist/shared/window/types/window.d.ts +84 -0
  512. package/dist/types/index.d.ts +102 -0
  513. package/dist/types/index.js +0 -0
  514. package/dist/vite/build/build-chunk.d.ts +53 -0
  515. package/dist/vite/build/build-csp-update.d.ts +80 -0
  516. package/dist/vite/build/build-obfuscation.d.ts +33 -0
  517. package/dist/vite/build/component-map.d.ts +38 -0
  518. package/dist/vite/build/component-resolver.d.ts +6 -0
  519. package/dist/vite/build/index.d.ts +9 -0
  520. package/dist/vite/build/index.js +18 -0
  521. package/dist/vite/build/types/build.d.ts +13 -0
  522. package/dist/vite/config/electron-app-config.d.ts +6 -0
  523. package/dist/vite/config/electron-builder-config.d.ts +8 -0
  524. package/dist/vite/config/electron-vite-config.d.ts +9 -0
  525. package/dist/vite/config/index.d.ts +11 -0
  526. package/dist/vite/config/index.js +2259 -0
  527. package/dist/vite/config/types/electron-app-options.d.ts +22 -0
  528. package/dist/vite/config/types/electron-builder-options.d.ts +16 -0
  529. package/dist/vite/config/types/electron-vite-options.d.ts +43 -0
  530. package/dist/vite/config/types/vite-obfuscation.d.ts +36 -0
  531. package/dist/vite/config/vite-obfuscation-config.d.ts +6 -0
  532. package/dist/vite/mode/index.d.ts +4 -0
  533. package/dist/vite/mode/index.js +8 -0
  534. package/dist/vite/mode/vite-mode.d.ts +37 -0
  535. package/dist/vite/orval/index.d.ts +4 -0
  536. package/dist/vite/orval/index.js +75 -0
  537. package/dist/vite/orval/orval-global-types.d.ts +23 -0
  538. package/dist/vite/utils/file-write-vite-util.d.ts +30 -0
  539. package/dist/vite/utils/index.d.ts +5 -0
  540. package/dist/vite/utils/index.js +10 -0
  541. package/dist/vite/utils/runtime-config-vite-util.d.ts +39 -0
  542. package/package.json +287 -0
@@ -0,0 +1,1970 @@
1
+ import {
2
+ WindowUtil
3
+ } from "./chunk-YZOJOLFL.js";
4
+ import {
5
+ defineMainWindowConfig,
6
+ defineSettingWindowConfig
7
+ } from "./chunk-F7YTK2MY.js";
8
+ import {
9
+ FileAssociationUtil
10
+ } from "./chunk-VGDNICVG.js";
11
+ import {
12
+ MainWindowIdentity
13
+ } from "./chunk-KFV4GXVE.js";
14
+ import {
15
+ ContextMenuChannels,
16
+ WindowChannels
17
+ } from "./chunk-BFD2LHLK.js";
18
+ import {
19
+ SettingWindowIdentity
20
+ } from "./chunk-PVWRRUOK.js";
21
+ import {
22
+ ProtocolUtil
23
+ } from "./chunk-KFK47PDH.js";
24
+ import {
25
+ AppMode
26
+ } from "./chunk-GN2FNR3Z.js";
27
+
28
+ // src/main/window/window-lifecycle-abstract.ts
29
+ import { shell } from "electron";
30
+ var WindowLifecycleAbstract = class {
31
+ /**
32
+ * Xion 应用
33
+ * @type {XoAppAbstract}
34
+ * @protected
35
+ */
36
+ xoApp;
37
+ /**
38
+ * 构造函数
39
+ */
40
+ constructor(xoApp) {
41
+ this.xoApp = xoApp;
42
+ }
43
+ /**
44
+ * 创建窗口前
45
+ * @param {XoWindow.Type} type 窗口类型
46
+ * @param {Electron.BrowserWindowConstructorOptions} options 窗口配置
47
+ * @returns {Promise<void>}
48
+ */
49
+ async beforeCreate(type, options) {
50
+ }
51
+ /**
52
+ * 创建窗口后
53
+ * <p>项目中可以在此方法中处理窗口事件,如:</p>
54
+ * <p>record.window.on('always-on-top-changed', () => {})</p>
55
+ * <p>record.window.webContents.on('context-menu', () => {})</p>
56
+ * @param {XoWindow.Record} record 窗口实例
57
+ * @returns {Promise<void>}
58
+ */
59
+ async afterCreated(record) {
60
+ }
61
+ /**
62
+ * 加载窗口渲染进程
63
+ * @param {XoWindow.Record} record 窗口实例
64
+ * @returns {Promise<void>}
65
+ */
66
+ async loadIndex(record) {
67
+ if (AppMode.isDev()) {
68
+ await WindowUtil.loadUrl(this.xoApp, record);
69
+ return;
70
+ }
71
+ const rendererProtocolUrl = this.xoApp.getRendererProtocolManager().entryUrl(record.url);
72
+ if (rendererProtocolUrl) {
73
+ this.xoApp.getRendererProtocolManager().initializeSession(record.window.webContents.session);
74
+ await WindowUtil.loadProtocol(this.xoApp, record, rendererProtocolUrl);
75
+ return;
76
+ }
77
+ await WindowUtil.loadFile(this.xoApp, record);
78
+ }
79
+ /**
80
+ * 窗口准备显示
81
+ * @param {XoWindow.Record} record 窗口实例
82
+ * @returns {Promise<void>}
83
+ */
84
+ async onceReadyToShow(record) {
85
+ }
86
+ /**
87
+ * 页面加载完成
88
+ * @param {XoWindow.Record} record 窗口实例
89
+ * @returns {Promise<void>}
90
+ */
91
+ async onShow(record) {
92
+ this.isMainWindow(record) && this.xoApp.getTrayManager().setFocus();
93
+ }
94
+ /**
95
+ * 窗口隐藏
96
+ * @param {XoWindow.Record} record 窗口实例
97
+ * @returns {Promise<void>}
98
+ */
99
+ async onHide(record) {
100
+ this.isMainWindow(record) && this.xoApp.getTrayManager().setBlur();
101
+ }
102
+ /**
103
+ * 窗口获得焦点
104
+ * @param {Electron.Event} event 事件对象
105
+ * @param {XoWindow.Record} record 窗口实例
106
+ * @returns {Promise<void>}
107
+ */
108
+ async onFocus(event, record) {
109
+ }
110
+ /**
111
+ * 窗口失去焦点
112
+ * @param {Electron.Event} event 事件对象
113
+ * @param {XoWindow.Record} record 窗口实例
114
+ * @returns {Promise<void>}
115
+ */
116
+ async onBlur(event, record) {
117
+ }
118
+ /**
119
+ * 窗口尺寸变化
120
+ * @param {XoWindow.Record} record 窗口实例
121
+ * @returns {Promise<void>}
122
+ */
123
+ async onResize(record) {
124
+ }
125
+ /**
126
+ * 窗口尺寸变化完成
127
+ * @param {XoWindow.Record} record 窗口实例
128
+ * @returns {Promise<void>}
129
+ */
130
+ async onResized(record) {
131
+ this.xoApp.getAppStore().setWindowRectangle(record.type.name, this.getWindowRectangle(record));
132
+ }
133
+ /**
134
+ * 窗口位置变化
135
+ * @param {XoWindow.Record} record 窗口实例
136
+ * @returns {Promise<void>}
137
+ */
138
+ async onMove(record) {
139
+ }
140
+ /**
141
+ * 窗口位置移动完成
142
+ * @param {XoWindow.Record} record 窗口实例
143
+ * @returns {Promise<void>}
144
+ */
145
+ async onMoved(record) {
146
+ this.xoApp.getAppStore().setWindowRectangle(record.type.name, this.getWindowRectangle(record));
147
+ }
148
+ /**
149
+ * 窗口最大化
150
+ * @param {XoWindow.Record} record 窗口实例
151
+ * @returns {Promise<void>}
152
+ */
153
+ async onMaximize(record) {
154
+ }
155
+ /**
156
+ * 窗口退出最大化
157
+ * @param {XoWindow.Record} record 窗口实例
158
+ * @returns {Promise<void>}
159
+ */
160
+ async onUnmaximize(record) {
161
+ }
162
+ /**
163
+ * 窗口最小化
164
+ * @param {XoWindow.Record} record 窗口实例
165
+ * @returns {Promise<void>}
166
+ */
167
+ async onMinimize(record) {
168
+ this.isMainWindow(record) && this.xoApp.getTrayManager().setBlur();
169
+ }
170
+ /**
171
+ * 窗口恢复
172
+ * @param {XoWindow.Record} record 窗口实例
173
+ * @returns {Promise<void>}
174
+ */
175
+ async onRestore(record) {
176
+ this.isMainWindow(record) && this.xoApp.getTrayManager().setFocus();
177
+ }
178
+ /**
179
+ * 进入全屏
180
+ * @param {XoWindow.Record} record 窗口实例
181
+ * @returns {Promise<void>}
182
+ */
183
+ async onEnterFullScreen(record) {
184
+ }
185
+ /**
186
+ * 退出全屏
187
+ * @param {XoWindow.Record} record 窗口实例
188
+ * @returns {Promise<void>}
189
+ */
190
+ async onLeaveFullScreen(record) {
191
+ }
192
+ /**
193
+ * 窗口置顶状态变化
194
+ * @param {XoWindow.Record} record 窗口实例
195
+ * @returns {Promise<void>}
196
+ */
197
+ async onAlwaysOnTopChanged(record) {
198
+ }
199
+ /**
200
+ * 窗口关闭前
201
+ * @param {Electron.Event} event 事件对象
202
+ * @param {XoWindow.Record} record 窗口实例
203
+ * @returns {Promise<void>}
204
+ */
205
+ async onClose(event, record) {
206
+ if (this.xoApp.isQuitting()) {
207
+ return;
208
+ }
209
+ if (this.isMainWindow(record)) {
210
+ if (this.xoApp.getAppStore().getWindowCloseBehavior() === "quit") {
211
+ this.xoApp.quit();
212
+ return;
213
+ }
214
+ event.preventDefault();
215
+ record.window.hide();
216
+ return;
217
+ }
218
+ }
219
+ /**
220
+ * 窗口已关闭
221
+ * @param {XoWindow.Record} record 窗口实例
222
+ * @returns {Promise<void>}
223
+ */
224
+ async onClosed(record) {
225
+ this.xoApp.windowLog.info(`\u7A97\u53E3\u5DF2\u5173\u95ED`, WindowUtil.recordToUID(record));
226
+ }
227
+ /**
228
+ * 窗口无响应
229
+ * @param {XoWindow.Record} record 窗口实例
230
+ * @returns {Promise<void>}
231
+ */
232
+ async onUnresponsive(record) {
233
+ this.xoApp.windowLog.warn(`\u7A97\u53E3\u65E0\u54CD\u5E94`, WindowUtil.recordToUID(record));
234
+ }
235
+ /**
236
+ * 窗口恢复响应
237
+ * @param {XoWindow.Record} record 窗口实例
238
+ * @returns {Promise<void>}
239
+ */
240
+ async onResponsive(record) {
241
+ this.xoApp.windowLog.info("\u7A97\u53E3\u6062\u590D\u54CD\u5E94", WindowUtil.recordToUID(record));
242
+ }
243
+ /**
244
+ * 页面加载完成
245
+ * @param {XoWindow.Record} record 窗口实例
246
+ * @returns {Promise<void>}
247
+ */
248
+ async onWebContentsDidFinishLoad(record) {
249
+ if (this.isMainWindow(record) && this.xoApp.isWindowLaunchMode() && !this.isExternalLaunchMode()) {
250
+ this.xoApp.getWindowManager().showByWindow(record.window);
251
+ }
252
+ }
253
+ /**
254
+ * 页面开始加载
255
+ * @param {XoWindow.Record} record 窗口实例
256
+ * @returns {Promise<void>}
257
+ */
258
+ async onWebContentsDidStartLoading(record) {
259
+ }
260
+ /**
261
+ * 页面停止加载
262
+ * @param {XoWindow.Record} record 窗口实例
263
+ * @returns {Promise<void>}
264
+ */
265
+ async onWebContentsDidStopLoading(record) {
266
+ }
267
+ /**
268
+ * 页面 DOM 准备完成
269
+ * @param {XoWindow.Record} record 窗口实例
270
+ * @returns {Promise<void>}
271
+ */
272
+ async onWebContentsDomReady(record) {
273
+ }
274
+ /**
275
+ * 页面标题更新
276
+ * @param {Electron.Event} event 事件对象
277
+ * @param {XoWindow.Record} record 窗口实例
278
+ * @param {string} title 页面标题
279
+ * @param {boolean} explicitSet 是否显式设置标题
280
+ * @returns {Promise<void>}
281
+ */
282
+ async onWebContentsPageTitleUpdated(event, record, title, explicitSet) {
283
+ }
284
+ /**
285
+ * 页面图标更新
286
+ * @param {Electron.Event} event 事件对象
287
+ * @param {XoWindow.Record} record 窗口实例
288
+ * @param {string[]} favicons 图标地址
289
+ * @returns {Promise<void>}
290
+ */
291
+ async onWebContentsPageFaviconUpdated(event, record, favicons) {
292
+ }
293
+ /**
294
+ * webContents 焦点获得
295
+ * @param {XoWindow.Record} record 窗口实例
296
+ * @returns {Promise<void>}
297
+ */
298
+ async onWebContentsFocus(record) {
299
+ }
300
+ /**
301
+ * webContents 焦点失去
302
+ * @param {XoWindow.Record} record 窗口实例
303
+ * @returns {Promise<void>}
304
+ */
305
+ async onWebContentsBlur(record) {
306
+ }
307
+ /**
308
+ * webContents 主题色变化
309
+ * @param {Electron.Event} event 事件对象
310
+ * @param {XoWindow.Record} record 窗口实例
311
+ * @param {string | null} color 主题色
312
+ * @returns {Promise<void>}
313
+ */
314
+ async onWebContentsDidChangeThemeColor(event, record, color) {
315
+ }
316
+ /**
317
+ * webContents 目标地址变化
318
+ * @param {Electron.Event} event 事件对象
319
+ * @param {XoWindow.Record} record 窗口实例
320
+ * @param {string} url 目标地址
321
+ * @returns {Promise<void>}
322
+ */
323
+ async onWebContentsUpdateTargetUrl(event, record, url) {
324
+ }
325
+ /**
326
+ * webContents 即将跳转
327
+ * @param {Electron.Event} event 事件对象
328
+ * @param {XoWindow.Record} record 窗口实例
329
+ * @param {string} url 跳转地址
330
+ * @param {boolean} shouldOpenExternal 是否应使用系统浏览器打开
331
+ * @returns {Promise<void>}
332
+ */
333
+ async onWebContentsWillNavigate(event, record, url, shouldOpenExternal) {
334
+ if (shouldOpenExternal) {
335
+ event.preventDefault();
336
+ void shell.openExternal(url);
337
+ }
338
+ }
339
+ /**
340
+ * webContents 上下文菜单
341
+ * @param {Electron.Event} event 事件对象
342
+ * @param {XoWindow.Record} record 窗口实例
343
+ * @param {Electron.ContextMenuParams} params 上下文菜单参数
344
+ * @returns {Promise<void>}
345
+ */
346
+ async onWebContentsContextMenu(event, record, params) {
347
+ if (this.xoApp.getAppConfig()?.useContextMenuInRenderer) {
348
+ const contextMenu = this.xoApp.getMenuManager().resolveContextMenu(params, record.window);
349
+ record.window.webContents.send(ContextMenuChannels.onRequested, contextMenu);
350
+ return;
351
+ }
352
+ this.xoApp.getMenuManager().popupContextMenu(params, record.window);
353
+ }
354
+ /**
355
+ * webContents 按键前置事件
356
+ * @param {Electron.Event} event 事件对象
357
+ * @param {XoWindow.Record} record 窗口实例
358
+ * @param {Electron.Input} input 输入信息
359
+ * @returns {Promise<void>}
360
+ */
361
+ async onWebContentsBeforeInputEvent(event, record, input) {
362
+ }
363
+ /**
364
+ * webContents 输入事件
365
+ * @param {Electron.Event} event 事件对象
366
+ * @param {XoWindow.Record} record 窗口实例
367
+ * @param {Electron.InputEvent} inputEvent 输入事件
368
+ * @returns {Promise<void>}
369
+ */
370
+ async onWebContentsInputEvent(event, record, inputEvent) {
371
+ }
372
+ /**
373
+ * webContents DevTools 打开链接
374
+ * @param {Electron.Event} event 事件对象
375
+ * @param {XoWindow.Record} record 窗口实例
376
+ * @param {string} url 链接
377
+ * @returns {Promise<void>}
378
+ */
379
+ async onWebContentsDevtoolsOpenUrl(event, record, url) {
380
+ }
381
+ /**
382
+ * webContents DevTools 搜索
383
+ * @param {Electron.Event} event 事件对象
384
+ * @param {XoWindow.Record} record 窗口实例
385
+ * @param {string} query 关键字
386
+ * @returns {Promise<void>}
387
+ */
388
+ async onWebContentsDevtoolsSearchQuery(event, record, query) {
389
+ }
390
+ /**
391
+ * webContents DevTools 打开
392
+ * @param {XoWindow.Record} record 窗口实例
393
+ * @returns {Promise<void>}
394
+ */
395
+ async onWebContentsDevtoolsOpened(record) {
396
+ const openDevTools = record?.type?.windowConfig?.openDevTools;
397
+ if (openDevTools) {
398
+ const productName = this.xoApp.getAppConfig()?.eletronAppConfig?.productName;
399
+ record.window.webContents.setDevToolsTitle(`${productName ? `${productName} ` : ""}${openDevTools?.title ?? "\u5F00\u53D1\u8005\u5DE5\u5177"}`);
400
+ }
401
+ }
402
+ /**
403
+ * webContents DevTools 关闭
404
+ * @param {XoWindow.Record} record 窗口实例
405
+ * @returns {Promise<void>}
406
+ */
407
+ async onWebContentsDevtoolsClosed(record) {
408
+ }
409
+ /**
410
+ * webContents DevTools 聚焦
411
+ * @param {XoWindow.Record} record 窗口实例
412
+ * @returns {Promise<void>}
413
+ */
414
+ async onWebContentsDevtoolsFocused(record) {
415
+ }
416
+ /**
417
+ * webContents 证书错误
418
+ * @param {Electron.Event} event 事件对象
419
+ * @param {XoWindow.Record} record 窗口实例
420
+ * @param {string} url 请求地址
421
+ * @param {string} error 错误码
422
+ * @param {Electron.Certificate} certificate 证书
423
+ * @param {(isTrusted: boolean) => void} callback 回调函数
424
+ * @param {boolean} isMainFrame 是否主框架
425
+ * @returns {Promise<void>}
426
+ */
427
+ async onWebContentsCertificateError(event, record, url, error, certificate, callback, isMainFrame) {
428
+ }
429
+ /**
430
+ * webContents 选择客户端证书
431
+ * @param {Electron.Event} event 事件对象
432
+ * @param {XoWindow.Record} record 窗口实例
433
+ * @param {string} url 请求地址
434
+ * @param {Electron.Certificate[]} certificateList 证书列表
435
+ * @param {(certificate: Electron.Certificate) => void} callback 回调函数
436
+ * @returns {Promise<void>}
437
+ */
438
+ async onWebContentsSelectClientCertificate(event, record, url, certificateList, callback) {
439
+ }
440
+ /**
441
+ * webContents 登录
442
+ * @param {Electron.Event} event 事件对象
443
+ * @param {XoWindow.Record} record 窗口实例
444
+ * @param {Electron.LoginAuthenticationResponseDetails} authenticationResponseDetails 认证响应详情
445
+ * @param {Electron.AuthInfo} authInfo 认证信息
446
+ * @param {(username?: string, password?: string) => void} callback 回调函数
447
+ * @returns {Promise<void>}
448
+ */
449
+ async onWebContentsLogin(event, record, authenticationResponseDetails, authInfo, callback) {
450
+ }
451
+ /**
452
+ * webContents 查找结果
453
+ * @param {Electron.Event} event 事件对象
454
+ * @param {XoWindow.Record} record 窗口实例
455
+ * @param {Electron.Result} result 查找结果
456
+ * @returns {Promise<void>}
457
+ */
458
+ async onWebContentsFoundInPage(event, record, result) {
459
+ }
460
+ /**
461
+ * webContents 媒体开始播放
462
+ * @param {XoWindow.Record} record 窗口实例
463
+ * @returns {Promise<void>}
464
+ */
465
+ async onWebContentsMediaStartedPlaying(record) {
466
+ }
467
+ /**
468
+ * webContents 媒体暂停
469
+ * @param {XoWindow.Record} record 窗口实例
470
+ * @returns {Promise<void>}
471
+ */
472
+ async onWebContentsMediaPaused(record) {
473
+ }
474
+ /**
475
+ * webContents 音频状态变化
476
+ * @param {Electron.Event<Electron.WebContentsAudioStateChangedEventParams>} event 事件对象
477
+ * @param {XoWindow.Record} record 窗口实例
478
+ * @returns {Promise<void>}
479
+ */
480
+ async onWebContentsAudioStateChanged(event, record) {
481
+ }
482
+ /**
483
+ * webContents 控制台消息
484
+ * @param {Electron.Event<Electron.WebContentsConsoleMessageEventParams>} details 控制台详情
485
+ * @param {XoWindow.Record} record 窗口实例
486
+ * @returns {Promise<void>}
487
+ */
488
+ async onWebContentsConsoleMessage(details, record) {
489
+ }
490
+ /**
491
+ * webContents 预加载错误
492
+ * @param {Electron.Event} event 事件对象
493
+ * @param {XoWindow.Record} record 窗口实例
494
+ * @param {string} preloadPath 预加载脚本路径
495
+ * @param {Error} error 错误对象
496
+ * @returns {Promise<void>}
497
+ */
498
+ async onWebContentsPreloadError(event, record, preloadPath, error) {
499
+ }
500
+ /**
501
+ * webContents IPC 消息
502
+ * @param {Electron.IpcMainEvent} event 事件对象
503
+ * @param {XoWindow.Record} record 窗口实例
504
+ * @param {string} channel 通道
505
+ * @param {any[]} args 参数列表
506
+ * @returns {Promise<void>}
507
+ */
508
+ async onWebContentsIpcMessage(event, record, channel, ...args) {
509
+ }
510
+ /**
511
+ * webContents 同步 IPC 消息
512
+ * @param {Electron.IpcMainEvent} event 事件对象
513
+ * @param {XoWindow.Record} record 窗口实例
514
+ * @param {string} channel 通道
515
+ * @param {any[]} args 参数列表
516
+ * @returns {Promise<void>}
517
+ */
518
+ async onWebContentsIpcMessageSync(event, record, channel, ...args) {
519
+ }
520
+ /**
521
+ * webContents 预期尺寸变化
522
+ * @param {Electron.Event} event 事件对象
523
+ * @param {XoWindow.Record} record 窗口实例
524
+ * @param {Electron.Size} preferredSize 预期尺寸
525
+ * @returns {Promise<void>}
526
+ */
527
+ async onWebContentsPreferredSizeChanged(event, record, preferredSize) {
528
+ }
529
+ /**
530
+ * webContents frame 创建
531
+ * @param {Electron.Event} event 事件对象
532
+ * @param {XoWindow.Record} record 窗口实例
533
+ * @param {Electron.FrameCreatedDetails} details Frame详情
534
+ * @returns {Promise<void>}
535
+ */
536
+ async onWebContentsFrameCreated(event, record, details) {
537
+ }
538
+ /**
539
+ * webContents 即将挂载 webview
540
+ * @param {Electron.Event} event 事件对象
541
+ * @param {XoWindow.Record} record 窗口实例
542
+ * @param {Electron.WebPreferences} webPreferences Webview配置
543
+ * @param {Record<string, string>} params Webview参数
544
+ * @returns {Promise<void>}
545
+ */
546
+ async onWebContentsWillAttachWebview(event, record, webPreferences, params) {
547
+ }
548
+ /**
549
+ * webContents 已挂载 webview
550
+ * @param {Electron.Event} event 事件对象
551
+ * @param {XoWindow.Record} record 窗口实例
552
+ * @param {Electron.WebContents} webContents Guest WebContents
553
+ * @returns {Promise<void>}
554
+ */
555
+ async onWebContentsDidAttachWebview(event, record, webContents) {
556
+ }
557
+ /**
558
+ * webContents 绘制
559
+ * @param {Electron.Event<Electron.WebContentsPaintEventParams>} details 绘制详情
560
+ * @param {XoWindow.Record} record 窗口实例
561
+ * @param {Electron.Rectangle} dirtyRect 脏矩形
562
+ * @param {Electron.NativeImage} image 图像
563
+ * @returns {Promise<void>}
564
+ */
565
+ async onWebContentsPaint(details, record, dirtyRect, image) {
566
+ }
567
+ /**
568
+ * webContents DevTools 刷新页面
569
+ * @param {XoWindow.Record} record 窗口实例
570
+ * @returns {Promise<void>}
571
+ */
572
+ async onWebContentsDevtoolsReloadPage(record) {
573
+ }
574
+ /**
575
+ * webContents 销毁
576
+ * @param {XoWindow.Record} record 窗口实例
577
+ * @returns {Promise<void>}
578
+ */
579
+ async onWebContentsDestroyed(record) {
580
+ }
581
+ /**
582
+ * 页面加载失败
583
+ * @param {Electron.Event} event 事件对象
584
+ * @param {XoWindow.Record} record 窗口实例
585
+ * @param {XoWindow.DidFailLoadPayload} failPayload 失败信息
586
+ * @returns {Promise<void>}
587
+ */
588
+ async onWebContentsDidFailLoad(event, record, failPayload) {
589
+ this.xoApp.windowLog.error("\u7A97\u53E3\u9875\u9762\u52A0\u8F7D\u5931\u8D25", WindowUtil.recordToUID(record), { failPayload });
590
+ }
591
+ /**
592
+ * 渲染进程退出
593
+ * @param {Electron.Event} event 事件对象
594
+ * @param {XoWindow.Record} record 窗口实例
595
+ * @param {Electron.RenderProcessGoneDetails} details 详情
596
+ * @returns {Promise<void>}
597
+ */
598
+ async onWebContentsRenderProcessGone(event, record, details) {
599
+ this.xoApp.windowLog.error("\u7A97\u53E3\u6E32\u67D3\u8FDB\u7A0B\u5DF2\u9000\u51FA", WindowUtil.recordToUID(record), { details });
600
+ }
601
+ /**
602
+ * 进入 HTML 全屏
603
+ * @param {XoWindow.Record} record 窗口实例
604
+ * @returns {Promise<void>}
605
+ */
606
+ async onWebContentsEnterHtmlFullScreen(record) {
607
+ }
608
+ /**
609
+ * 退出 HTML 全屏
610
+ * @param {XoWindow.Record} record 窗口实例
611
+ * @returns {Promise<void>}
612
+ */
613
+ async onWebContentsLeaveHtmlFullScreen(record) {
614
+ }
615
+ /**
616
+ * 窗口生命周期错误
617
+ * @param {XoWindow.Record} record 窗口实例
618
+ * @param {XoWindow.LifecycleError} error 错误信息
619
+ * @returns {Promise<void>}
620
+ */
621
+ async onError(record, error) {
622
+ this.xoApp.windowLog.error(`[Lifecycle]`, WindowUtil.recordToUID(record), { error });
623
+ }
624
+ /**
625
+ * 是否是主窗口
626
+ * @param {XoWindow.Record} record 窗口实例
627
+ * @returns {boolean}
628
+ * @private
629
+ */
630
+ isMainWindow(record) {
631
+ return record.type.name === MainWindowIdentity.typeName;
632
+ }
633
+ /**
634
+ * 是否是设置窗口
635
+ * @param {XoWindow.Record} record 窗口实例
636
+ * @returns {boolean}
637
+ * @private
638
+ */
639
+ isSettingWindow(record) {
640
+ return record.type.name === SettingWindowIdentity.typeName;
641
+ }
642
+ /**
643
+ * 是否是设置窗口
644
+ * @param {XoWindow.Type} type 窗口类型
645
+ * @returns {boolean}
646
+ * @private
647
+ */
648
+ isSettingWindowByType(type) {
649
+ return type.name === SettingWindowIdentity.typeName;
650
+ }
651
+ /**
652
+ * 获取用于持久化的窗口位置和尺寸
653
+ * @param {XoWindow.Record} record 窗口实例
654
+ * @returns {Electron.Rectangle}
655
+ * @private
656
+ */
657
+ getWindowRectangle(record) {
658
+ const bounds = record.window.getBounds();
659
+ const options = record.type.windowConfig?.browserOptions;
660
+ if (options?.resizable === false) {
661
+ return {
662
+ ...bounds,
663
+ width: options.width ?? bounds.width,
664
+ height: options.height ?? bounds.height
665
+ };
666
+ }
667
+ return bounds;
668
+ }
669
+ /**
670
+ * 是否外部触发启动模式
671
+ * @returns {boolean}
672
+ * @private
673
+ */
674
+ isExternalLaunchMode() {
675
+ const appConfig = this.xoApp.getAppConfig();
676
+ return ProtocolUtil.hasProtocolUrl(process.argv, appConfig?.eletronAppConfig?.protocols) || FileAssociationUtil.hasAssociatedFile(process.argv, appConfig?.eletronAppConfig?.fileAssociationExtensions);
677
+ }
678
+ };
679
+
680
+ // src/main/window/main/main-window-lifecycle.ts
681
+ var MainWindowLifecycle = class extends WindowLifecycleAbstract {
682
+ };
683
+
684
+ // src/main/window/main/main-window-type.ts
685
+ var MainWindowType = {
686
+ name: MainWindowIdentity.typeName,
687
+ singleInstance: true,
688
+ windowConfig: defineMainWindowConfig(),
689
+ lifecycle: MainWindowLifecycle
690
+ };
691
+
692
+ // src/main/window/setting/setting-window-lifecycle.ts
693
+ var SettingWindowLifecycle = class extends WindowLifecycleAbstract {
694
+ };
695
+
696
+ // src/main/window/setting/setting-window-type.ts
697
+ var SettingWindowType = {
698
+ name: SettingWindowIdentity.typeName,
699
+ singleInstance: true,
700
+ windowConfig: defineSettingWindowConfig(),
701
+ lifecycle: SettingWindowLifecycle
702
+ };
703
+
704
+ // src/main/window/window-manager.ts
705
+ import { BrowserWindow, screen, shell as shell2 } from "electron";
706
+ var WindowManager = class {
707
+ //<editor-fold desc="内部属性">
708
+ /** Xion 应用 */
709
+ xoApp;
710
+ /** 窗口类型 */
711
+ types = /* @__PURE__ */ new Map();
712
+ /** 窗口记录 */
713
+ records = /* @__PURE__ */ new Map();
714
+ /** electron 窗口ID -> 窗口标识 */
715
+ identities = /* @__PURE__ */ new Map();
716
+ /** 窗口生命周期 */
717
+ lifecycles = /* @__PURE__ */ new Map();
718
+ /** 已完成渲染进程首屏渲染的窗口 */
719
+ rendererReadyWindows = /* @__PURE__ */ new WeakSet();
720
+ /** 等待渲染进程完成后显示的窗口 */
721
+ pendingShowWindows = /* @__PURE__ */ new WeakSet();
722
+ //</editor-fold>
723
+ //<editor-fold desc="构造函数">
724
+ /**
725
+ * 构造函数
726
+ * @param {XoAppAbstract} xoApp Xion 应用
727
+ * @param {XoWindow.Type[]} types 窗口类型
728
+ */
729
+ constructor(xoApp, types) {
730
+ this.xoApp = xoApp;
731
+ this.registerManyType(types);
732
+ this.registerType(MainWindowType);
733
+ this.registerType(SettingWindowType);
734
+ }
735
+ //</editor-fold>
736
+ //<editor-fold desc="窗口管理">
737
+ /**
738
+ * 复用或创建窗口(如不存在先创建),不显示窗口,仅复用或创建
739
+ * @param {XoWindow.Identity} identity 窗口标识
740
+ * @param {XoWindow.Query} query URL 查询参数
741
+ * @returns {Promise<Electron.BrowserWindow>}
742
+ */
743
+ async reuseOrCreate(identity, query) {
744
+ const type = this.ensureGetType(identity.typeName);
745
+ let record = type.singleInstance ? this.getRecords().find((record2) => record2.type.name === identity.typeName) : this.getRecord(identity.recordId);
746
+ if (record?.window?.isDestroyed()) {
747
+ this.removeRecord(record);
748
+ record = void 0;
749
+ }
750
+ const url = this.withQuery(identity.url, query);
751
+ if (record && record.window) {
752
+ if (record.url !== url) {
753
+ record.url = url;
754
+ await this.getLifecycleByType(record.type)?.loadIndex?.(record);
755
+ }
756
+ this.xoApp.windowLog.debug(`\u590D\u7528\u7A97\u53E3`, WindowUtil.recordToUID(record));
757
+ return record.window;
758
+ }
759
+ const window = await this.create({ ...identity, url });
760
+ record = this.getRecordByBrowserWindowId(window.id);
761
+ if (record?.window && !record?.window?.isDestroyed()) {
762
+ this.xoApp.windowLog.debug(`\u521B\u5EFA\u7A97\u53E3`, WindowUtil.recordToUID(record));
763
+ }
764
+ return window;
765
+ }
766
+ /**
767
+ * 创建窗口
768
+ * @param {XoWindow.Identity} identity 窗口标识
769
+ * @returns {Promise<Electron.BrowserWindow>}
770
+ */
771
+ async create(identity) {
772
+ let record;
773
+ let window;
774
+ try {
775
+ const type = this.ensureGetType(identity.typeName);
776
+ this.ensureSingleInstanceNotExist(type);
777
+ this.ensureRecordNotExist(identity.recordId);
778
+ const identityWinUID = WindowUtil.identityToUID(identity);
779
+ const options = await this.resolveWindowOptions(type);
780
+ this.xoApp.windowLog.debug("\u89E3\u6790\u7A97\u53E3\u9009\u9879\u5B8C\u6210", identityWinUID);
781
+ const lifecycle = this.getLifecycleByType(type);
782
+ await lifecycle?.beforeCreate(type, options);
783
+ this.xoApp.windowLog.debug("[\u7A97\u53E3\u521B\u5EFA\u524D]\u751F\u547D\u5468\u671F\u52A0\u8F7D\u5B8C\u6210", identityWinUID);
784
+ window = new BrowserWindow(options);
785
+ record = { id: identity.recordId, window, type, url: identity.url };
786
+ const winUID = WindowUtil.recordToUID(record);
787
+ this.xoApp.windowLog.debug(`\u7A97\u53E3\u521B\u5EFA\u5B8C\u6210`, winUID);
788
+ this.addRecord(record);
789
+ this.addIdentity(window.id, identity);
790
+ this.xoApp.getThemeManager().syncToWindow(window);
791
+ this.xoApp.getUpdaterManager().syncToWindowAndCheckForUpdates(window);
792
+ this.bindLifecycle(record);
793
+ this.xoApp.windowLog.debug("\u7A97\u53E3\u751F\u547D\u5468\u671F\u7ED1\u5B9A\u5B8C\u6210", winUID);
794
+ await lifecycle?.afterCreated(record);
795
+ this.xoApp.windowLog.debug("[\u7A97\u53E3\u521B\u5EFA\u540E]\u751F\u547D\u5468\u671F\u52A0\u8F7D\u5B8C\u6210", winUID);
796
+ await lifecycle?.loadIndex?.(record);
797
+ this.xoApp.windowLog.info(`\u7A97\u53E3\u52A0\u8F7D\u5B8C\u6210`, winUID);
798
+ } catch (error) {
799
+ this.removeRecord(record);
800
+ this.removeIdentity(window?.id);
801
+ this.destroyByWindow(window);
802
+ this.xoApp.windowLog.error(`\u7A97\u53E3\u521B\u5EFA\u5931\u8D25`, identity, error);
803
+ await this.dispatchError("WindowManager.create()", record, error);
804
+ throw error;
805
+ }
806
+ return window;
807
+ }
808
+ /**
809
+ * 追加 URL 查询参数
810
+ * @param {string} url 原始 URL
811
+ * @param {XoWindow.Query} query 查询参数
812
+ * @returns {string}
813
+ * @private
814
+ */
815
+ withQuery(url, query) {
816
+ if (!query) {
817
+ return url;
818
+ }
819
+ const [pathname, hash = ""] = url.split("#", 2);
820
+ const [base, search = ""] = pathname.split("?", 2);
821
+ const params = new URLSearchParams(search);
822
+ for (const [key, value] of Object.entries(query)) {
823
+ params.delete(key);
824
+ const values = Array.isArray(value) ? value : [value];
825
+ for (const item of values) {
826
+ if (item === null || item === void 0) {
827
+ continue;
828
+ }
829
+ params.append(key, String(item));
830
+ }
831
+ }
832
+ const nextSearch = params.toString();
833
+ const nextHash = hash ? `#${hash}` : "";
834
+ return `${base}${nextSearch ? `?${nextSearch}` : ""}${nextHash}`;
835
+ }
836
+ /**
837
+ * 显示并聚焦窗口
838
+ * @param {XoWindow.RecordID} id 窗口ID
839
+ */
840
+ show(id) {
841
+ const window = this.getBrowserWindow(id);
842
+ this.showByWindow(window);
843
+ }
844
+ /**
845
+ * 显示并聚焦窗口
846
+ * @param {Electron.BrowserWindow} window 窗口对象
847
+ */
848
+ showByWindow(window) {
849
+ if (!window || window.isDestroyed()) {
850
+ return;
851
+ }
852
+ if (this.shouldShowAfterRendererReady(window) && !this.rendererReadyWindows.has(window)) {
853
+ this.pendingShowWindows.add(window);
854
+ return;
855
+ }
856
+ if (window.isMinimized()) {
857
+ window.restore();
858
+ }
859
+ window.show();
860
+ window.focus();
861
+ }
862
+ /**
863
+ * 标记渲染进程已完成首屏渲染,并执行此前暂存的显示请求
864
+ * @param {Electron.BrowserWindow} window 窗口
865
+ */
866
+ rendererReady(window) {
867
+ if (!window || window.isDestroyed()) {
868
+ return;
869
+ }
870
+ this.rendererReadyWindows.add(window);
871
+ if (!this.pendingShowWindows.has(window)) {
872
+ return;
873
+ }
874
+ this.pendingShowWindows.delete(window);
875
+ this.showByWindow(window);
876
+ }
877
+ /**
878
+ * 首次渲染开始加载时保持窗口隐藏
879
+ * @param {Electron.BrowserWindow} window 窗口
880
+ * @private
881
+ */
882
+ rendererLoading(window) {
883
+ if (!window || window.isDestroyed()) {
884
+ return;
885
+ }
886
+ if (!this.shouldShowAfterRendererReady(window)) {
887
+ return;
888
+ }
889
+ if (this.rendererReadyWindows.has(window)) {
890
+ return;
891
+ }
892
+ if (!window.isVisible()) {
893
+ return;
894
+ }
895
+ this.pendingShowWindows.add(window);
896
+ window.hide();
897
+ }
898
+ /**
899
+ * 是否等待 Renderer 渲染完成后再显示窗口
900
+ * @param {Electron.BrowserWindow} window 窗口
901
+ * @returns {boolean}
902
+ */
903
+ shouldShowAfterRendererReady(window) {
904
+ if (!window || window.isDestroyed()) {
905
+ return true;
906
+ }
907
+ const record = this.getRecordByBrowserWindowId(window.id);
908
+ return record?.type.windowConfig?.showAfterRendererReady ?? true;
909
+ }
910
+ /**
911
+ * 隐藏窗口
912
+ * @param {XoWindow.RecordID} id 窗口ID
913
+ */
914
+ hide(id) {
915
+ const window = this.getBrowserWindow(id);
916
+ this.hideByWindow(window);
917
+ }
918
+ /**
919
+ * 隐藏窗口
920
+ * @param {Electron.BrowserWindow} window 窗口对象
921
+ */
922
+ hideByWindow(window) {
923
+ if (!window || window?.isDestroyed()) {
924
+ return;
925
+ }
926
+ if (window.isVisible() && !window.isMinimized()) {
927
+ window.hide();
928
+ }
929
+ }
930
+ /**
931
+ * 隐藏所有窗口
932
+ */
933
+ hideAll() {
934
+ BrowserWindow.getAllWindows().forEach((window) => {
935
+ this.hideByWindow(window);
936
+ });
937
+ }
938
+ /**
939
+ * 切换窗口置顶
940
+ * @param {XoWindow.RecordID} id 窗口ID
941
+ */
942
+ toggleAlwaysOnTop(id) {
943
+ const window = this.getBrowserWindow(id);
944
+ this.toggleAlwaysOnTopByWindow(window);
945
+ }
946
+ /**
947
+ * 切换窗口置顶
948
+ * @param {Electron.BrowserWindow} window 窗口对象
949
+ */
950
+ toggleAlwaysOnTopByWindow(window) {
951
+ if (!window || window.isDestroyed()) {
952
+ return;
953
+ }
954
+ const identity = this.getIdentityByBrowserWindowId(window.id);
955
+ if (!identity) {
956
+ return;
957
+ }
958
+ const isOnTop = window.isAlwaysOnTop();
959
+ window.setAlwaysOnTop(!isOnTop);
960
+ this.xoApp.getAppStore().setWindowOnTop(identity.typeName, !isOnTop);
961
+ const record = this.getRecordByBrowserWindowId(window.id);
962
+ record && this.notifyWindowState(record);
963
+ }
964
+ /**
965
+ * 设置全部窗口透明度
966
+ * @param {number} opacity 窗口透明度
967
+ */
968
+ setAllWindowOpacity(opacity) {
969
+ for (const window of this.getAllBrowserWindow()) {
970
+ if (!window.isDestroyed()) {
971
+ window.setOpacity(opacity);
972
+ }
973
+ }
974
+ }
975
+ /**
976
+ * 设置全部窗口材质,并实时更新窗口材质
977
+ * @param {XoApp.WindowMaterial} windowMaterial 窗口材质
978
+ */
979
+ setAllWindowMaterial(windowMaterial) {
980
+ windowMaterial ??= this.getAppWindowMaterial();
981
+ for (const window of this.getAllBrowserWindow()) {
982
+ if (window.isDestroyed()) {
983
+ continue;
984
+ }
985
+ const record = this.getRecordByBrowserWindowId(window.id);
986
+ const options = { ...record?.type.windowConfig?.browserOptions ?? {} };
987
+ const material = this.resolveWindowMaterial(record?.type, options, windowMaterial);
988
+ if (material !== void 0) {
989
+ this.applyWindowMaterialToOptions(options, material);
990
+ }
991
+ window.setBackgroundMaterial(options.backgroundMaterial ?? "none");
992
+ this.xoApp.getThemeManager().syncToWindow(window);
993
+ record && this.notifyWindowState(record);
994
+ }
995
+ }
996
+ /**
997
+ * 切换侧边栏折叠
998
+ * @param {XoWindow.RecordID} id 窗口ID
999
+ */
1000
+ toggleSidebarFold(id) {
1001
+ const window = this.getBrowserWindow(id);
1002
+ this.toggleSidebarFoldByWindow(window);
1003
+ }
1004
+ /**
1005
+ * 切换侧边栏折叠
1006
+ * @param {Electron.BrowserWindow} window 窗口对象
1007
+ */
1008
+ toggleSidebarFoldByWindow(window) {
1009
+ if (!window || window.isDestroyed()) {
1010
+ return;
1011
+ }
1012
+ const identity = this.getIdentityByBrowserWindowId(window.id);
1013
+ if (!identity) {
1014
+ return;
1015
+ }
1016
+ const isFold = this.xoApp.getAppStore().getSidebarFold(identity.typeName);
1017
+ this.xoApp.getAppStore().setSidebarFold(identity.typeName, !isFold);
1018
+ const record = this.getRecordByBrowserWindowId(window.id);
1019
+ record && this.notifyWindowState(record);
1020
+ }
1021
+ /**
1022
+ * 关闭窗口
1023
+ * @param {XoWindow.RecordID} id 窗口ID
1024
+ */
1025
+ close(id) {
1026
+ const window = this.getBrowserWindow(id);
1027
+ this.closeByWindow(window);
1028
+ }
1029
+ /**
1030
+ * 关闭窗口
1031
+ * @param {Electron.BrowserWindow} window 窗口对象
1032
+ */
1033
+ closeByWindow(window) {
1034
+ if (!window || window.isDestroyed()) {
1035
+ return;
1036
+ }
1037
+ window.close();
1038
+ }
1039
+ /**
1040
+ * 销毁窗口
1041
+ * @param {XoWindow.RecordID} id 窗口ID
1042
+ */
1043
+ destroy(id) {
1044
+ const window = this.getBrowserWindow(id);
1045
+ this.destroyByWindow(window);
1046
+ }
1047
+ /**
1048
+ * 销毁窗口
1049
+ * @param {BrowserWindow} window 窗口对象
1050
+ */
1051
+ destroyByWindow(window) {
1052
+ if (!window || window?.isDestroyed()) {
1053
+ return;
1054
+ }
1055
+ window.destroy();
1056
+ }
1057
+ /**
1058
+ * 关闭所有窗口
1059
+ */
1060
+ closeAll() {
1061
+ for (const window of this.getAllBrowserWindow()) {
1062
+ if (!window.isDestroyed()) {
1063
+ window.close();
1064
+ }
1065
+ }
1066
+ }
1067
+ /**
1068
+ * 重定向窗口路由
1069
+ * @param {XoWindow.RouteRedirectRequest} request 路由重定向请求
1070
+ * @returns {Promise<boolean>}
1071
+ */
1072
+ async redirectRoute(request) {
1073
+ const window = await this.reuseOrCreate(request.windowIdentity);
1074
+ if (window.isDestroyed() || window.webContents.isDestroyed()) {
1075
+ return false;
1076
+ }
1077
+ if (request.focus || request.focus === void 0) {
1078
+ this.showByWindow(window);
1079
+ }
1080
+ window.webContents.send(WindowChannels.onRouteRedirect, request);
1081
+ return true;
1082
+ }
1083
+ //</editor-fold>
1084
+ //<editor-fold desc="窗口类型管理">
1085
+ /**
1086
+ * 注册窗口类型
1087
+ * @param {XoWindow.Type} type 窗口类型
1088
+ */
1089
+ registerType(type) {
1090
+ if (!this.hasType(type.name)) {
1091
+ this.types.set(type.name, type);
1092
+ this.lifecycles.delete(type.name);
1093
+ }
1094
+ }
1095
+ /**
1096
+ * 注册多个窗口类型
1097
+ * @param {XoWindow.Type[]} types 窗口类型
1098
+ */
1099
+ registerManyType(types) {
1100
+ types ??= [];
1101
+ for (const type of types) {
1102
+ this.registerType(type);
1103
+ }
1104
+ }
1105
+ /**
1106
+ * 是否存在窗口类型
1107
+ * @param {XoWindow.TypeName} name 窗口类型名称
1108
+ * @returns {boolean} 是否存在窗口类型
1109
+ */
1110
+ hasType(name) {
1111
+ return this.types.has(name);
1112
+ }
1113
+ /**
1114
+ * 获取窗口类型
1115
+ * @param {XoWindow.TypeName} name 窗口类型名称
1116
+ * @returns {XoWindow.Type | undefined} 窗口类型
1117
+ */
1118
+ getType(name) {
1119
+ return this.types.get(name);
1120
+ }
1121
+ /**
1122
+ * 获取所有窗口类型
1123
+ * @returns {XoWindow.Type[]} 窗口类型
1124
+ */
1125
+ getTypes() {
1126
+ return [...this.types.values()];
1127
+ }
1128
+ /**
1129
+ * 确保获取到窗口类型(如果类型不存在则抛出错误)
1130
+ * @param {XoWindow.TypeName} name 窗口类型名称
1131
+ * @returns {XoWindow.Type} 窗口类型
1132
+ */
1133
+ ensureGetType(name) {
1134
+ const type = this.getType(name);
1135
+ if (type) {
1136
+ return type;
1137
+ }
1138
+ throw new Error(`\u7A97\u53E3\u7C7B\u578B\u672A\u6CE8\u518C: ${name}`);
1139
+ }
1140
+ //</editor-fold>
1141
+ //<editor-fold desc="窗口实例管理">
1142
+ /**
1143
+ * 获取窗口实例
1144
+ * @param {XoWindow.RecordID} id 窗口ID
1145
+ * @returns {XoWindow.Record | undefined}
1146
+ */
1147
+ getRecord(id) {
1148
+ return this.records.get(id);
1149
+ }
1150
+ /**
1151
+ * 获取所有窗口实例
1152
+ * @returns {XoWindow.Record[]}
1153
+ */
1154
+ getRecords() {
1155
+ return [...this.records.values()];
1156
+ }
1157
+ /**
1158
+ * 通过 electron 窗口ID获取窗口实例
1159
+ * @param {number} browserWindowId electron 窗口ID
1160
+ * @returns {XoWindow.Record | undefined}
1161
+ */
1162
+ getRecordByBrowserWindowId(browserWindowId) {
1163
+ const identity = this.getIdentityByBrowserWindowId(browserWindowId);
1164
+ return identity ? this.getRecord(identity.recordId) : void 0;
1165
+ }
1166
+ /**
1167
+ * 添加窗口实例
1168
+ * @param {XoWindow.Record} record 窗口实例
1169
+ */
1170
+ addRecord(record) {
1171
+ this.records.set(record.id, record);
1172
+ }
1173
+ /**
1174
+ * 移除窗口实例
1175
+ * @param {XoWindow.Record} record 窗口实例
1176
+ */
1177
+ removeRecord(record) {
1178
+ if (!record?.id) {
1179
+ return;
1180
+ }
1181
+ const current = this.records.get(record.id);
1182
+ if (current?.window === record?.window) {
1183
+ this.records.delete(record.id);
1184
+ this.removeIdentity(record.window?.id);
1185
+ }
1186
+ }
1187
+ /**
1188
+ * 确保窗口实例不存在,如果窗口实例存在则报错
1189
+ * @param {XoWindow.RecordID} id 窗口ID
1190
+ * @private
1191
+ */
1192
+ ensureRecordNotExist(id) {
1193
+ if (this.getRecord(id)) {
1194
+ throw new Error(`\u7A97\u53E3ID\u5DF2\u5B58\u5728: ${id}`);
1195
+ }
1196
+ }
1197
+ /**
1198
+ * 确保单例窗口不存在,如果单例窗口存在则报错
1199
+ * @param {XoWindow.Type} type 窗口类型
1200
+ * @private
1201
+ */
1202
+ ensureSingleInstanceNotExist(type) {
1203
+ if (!type.singleInstance) {
1204
+ return;
1205
+ }
1206
+ const record = this.getRecords().find((record2) => record2.type.name === type.name);
1207
+ if (record?.window?.isDestroyed()) {
1208
+ this.removeRecord(record);
1209
+ return;
1210
+ }
1211
+ if (record) {
1212
+ throw new Error(`\u5355\u4F8B\u7A97\u53E3\u5DF2\u5B58\u5728: ${type.name}`);
1213
+ }
1214
+ }
1215
+ //</editor-fold>
1216
+ //<editor-fold desc="electron 窗口对象">
1217
+ /**
1218
+ * 获取 electron 窗口对象
1219
+ * @param {XoWindow.RecordID} id 窗口ID
1220
+ * @returns {Electron.BrowserWindow | undefined}
1221
+ */
1222
+ getBrowserWindow(id) {
1223
+ return this.getRecord(id)?.window;
1224
+ }
1225
+ /**
1226
+ * 获取指定窗口类型的 electron 窗口对象(如果有多个,也仅返回第1个)
1227
+ * @param {XoWindow.TypeName} typeName 窗口类型名称
1228
+ * @returns {Electron.BrowserWindow | undefined}
1229
+ */
1230
+ getFirstBrowserWindowByType(typeName) {
1231
+ return this.getRecords().find((record) => record.type.name === typeName)?.window;
1232
+ }
1233
+ /**
1234
+ * 获取所有 electron 窗口对象
1235
+ * @returns {Electron.BrowserWindow[]}
1236
+ */
1237
+ getAllBrowserWindow() {
1238
+ return this.getRecords().map((record) => record.window);
1239
+ }
1240
+ /**
1241
+ * 获取窗口状态
1242
+ * @param {Electron.BrowserWindow} window 窗口对象
1243
+ * @returns {XoWindow.State}
1244
+ */
1245
+ getWindowState(window) {
1246
+ let isSidebarFolded = false;
1247
+ let windowMaterial;
1248
+ if (window && !window.isDestroyed()) {
1249
+ const identity = this.getIdentityByBrowserWindowId(window.id);
1250
+ if (identity) {
1251
+ isSidebarFolded = this.xoApp.getAppStore().getSidebarFold(identity.typeName);
1252
+ }
1253
+ const record = this.getRecordByBrowserWindowId(window.id);
1254
+ const options = { ...record?.type.windowConfig?.browserOptions ?? {} };
1255
+ windowMaterial = this.resolveWindowMaterial(record?.type, options);
1256
+ windowMaterial ??= "none";
1257
+ }
1258
+ return {
1259
+ windowMaterial,
1260
+ isSidebarFolded,
1261
+ isAlwaysOnTop: window?.isAlwaysOnTop() ?? false,
1262
+ isMaximized: window?.isMaximized() ?? false,
1263
+ isFullScreen: window?.isFullScreen() ?? false,
1264
+ isMinimized: window?.isMinimized() ?? false,
1265
+ isFullScreenable: window?.isFullScreenable() ?? false,
1266
+ isMinimizable: window?.isMinimizable() ?? false,
1267
+ isMaximizable: window?.isMaximizable() ?? false,
1268
+ isClosable: window?.isClosable() ?? false
1269
+ };
1270
+ }
1271
+ /**
1272
+ * 通知窗口状态
1273
+ * @param {XoWindow.Record} record 窗口实例
1274
+ */
1275
+ notifyWindowState(record) {
1276
+ setTimeout(() => {
1277
+ const window = record.window;
1278
+ if (window.isDestroyed() || window.webContents.isDestroyed()) {
1279
+ return;
1280
+ }
1281
+ window.webContents.send(WindowChannels.onState, this.getWindowState(window));
1282
+ });
1283
+ }
1284
+ /**
1285
+ * 解析窗口选项
1286
+ * @param {XoWindow.Type} type 窗口类型
1287
+ * @returns {Promise<Electron.BrowserWindowConstructorOptions>}
1288
+ * @private
1289
+ */
1290
+ async resolveWindowOptions(type) {
1291
+ const options = { ...type?.windowConfig?.browserOptions ?? {} };
1292
+ const productName = this.xoApp.getAppConfig()?.eletronAppConfig?.productName;
1293
+ if (options.title === void 0 && productName) {
1294
+ if (type.name === MainWindowType.name) {
1295
+ options.title = productName;
1296
+ } else if (type.name === SettingWindowType.name) {
1297
+ options.title = `${productName} \u8BBE\u7F6E`;
1298
+ }
1299
+ }
1300
+ const appStore = this.xoApp.getAppStore();
1301
+ const rectangle = appStore.getWindowRectangle(type.name);
1302
+ const isOnTop = appStore.getWindowOnTop(type.name);
1303
+ const opacity = appStore.getOpacity();
1304
+ const windowMaterial = this.resolveWindowMaterial(type, options);
1305
+ if (windowMaterial !== void 0) {
1306
+ this.applyWindowMaterialToOptions(options, windowMaterial);
1307
+ }
1308
+ if (!this.needsTransparentBackground(options)) {
1309
+ options.backgroundColor ??= this.xoApp.getThemeManager().titleBarOverlay().color;
1310
+ }
1311
+ options.opacity = opacity;
1312
+ options.alwaysOnTop = isOnTop;
1313
+ if (rectangle) {
1314
+ this.restoreWindowRectangle(options, rectangle);
1315
+ }
1316
+ return options;
1317
+ }
1318
+ /**
1319
+ * 是否需要透明窗口背景
1320
+ * @param {Electron.BrowserWindowConstructorOptions} options 窗口选项
1321
+ * @returns {boolean}
1322
+ * @private
1323
+ */
1324
+ needsTransparentBackground(options) {
1325
+ return options.transparent === true || options.backgroundMaterial !== void 0 && options.backgroundMaterial !== "none";
1326
+ }
1327
+ /**
1328
+ * 解析快捷窗口材质
1329
+ * @param {XoWindow.Type} type 窗口类型
1330
+ * @param {Electron.BrowserWindowConstructorOptions} options 窗口选项
1331
+ * @param {XoApp.WindowMaterial | undefined} appWindowMaterial APP 级窗口材质
1332
+ * @returns {XoApp.WindowMaterial | undefined}
1333
+ * @private
1334
+ */
1335
+ resolveWindowMaterial(type, options, appWindowMaterial = this.getAppWindowMaterial()) {
1336
+ if (options.backgroundMaterial !== void 0) {
1337
+ return void 0;
1338
+ }
1339
+ return type?.windowConfig?.windowMaterial ?? appWindowMaterial;
1340
+ }
1341
+ /**
1342
+ * 获取 APP 级快捷窗口材质
1343
+ * @returns {XoApp.WindowMaterial | undefined}
1344
+ * @private
1345
+ */
1346
+ getAppWindowMaterial() {
1347
+ return this.xoApp.getAppStore().getWindowMaterial() ?? this.xoApp.getAppConfig()?.windowMaterial;
1348
+ }
1349
+ /**
1350
+ * 利用快捷窗口材质更新窗口材质相关选项
1351
+ * @param {Electron.BrowserWindowConstructorOptions} options 窗口选项
1352
+ * @param {XoApp.WindowMaterial} windowMaterial 窗口材质
1353
+ * @private
1354
+ */
1355
+ applyWindowMaterialToOptions(options, windowMaterial) {
1356
+ if (windowMaterial === "transparent") {
1357
+ options.backgroundMaterial = "none";
1358
+ options.transparent = true;
1359
+ options.backgroundColor = "#00000000";
1360
+ options.frame = false;
1361
+ options.thickFrame = false;
1362
+ return;
1363
+ }
1364
+ if (windowMaterial === "none") {
1365
+ options.backgroundMaterial = "none";
1366
+ options.transparent = false;
1367
+ return;
1368
+ }
1369
+ options.backgroundMaterial = windowMaterial;
1370
+ options.transparent = false;
1371
+ options.backgroundColor = "#00000000";
1372
+ }
1373
+ /**
1374
+ * 确保窗口有足够区域在屏幕可视范围内
1375
+ * @param {Electron.BrowserWindow} window 窗口对象
1376
+ * @param {Electron.BrowserWindow} referenceWindow 参考窗口
1377
+ */
1378
+ ensureWindowRectangleVisible(window, referenceWindow) {
1379
+ if (!window || window.isDestroyed()) {
1380
+ return;
1381
+ }
1382
+ const rectangle = window.getBounds();
1383
+ if (referenceWindow && !referenceWindow.isDestroyed()) {
1384
+ const display = screen.getDisplayMatching(referenceWindow.getBounds());
1385
+ if (!this.isWindowRectangleVisibleInDisplay(rectangle, display)) {
1386
+ this.centerWindow(window, display);
1387
+ }
1388
+ return;
1389
+ }
1390
+ if (!this.isWindowRectangleVisible(rectangle)) {
1391
+ this.centerWindow(window, this.resolveCenterDisplay(rectangle));
1392
+ }
1393
+ }
1394
+ /**
1395
+ * 恢复窗口位置和尺寸
1396
+ * @param {Electron.BrowserWindowConstructorOptions} options 窗口选项
1397
+ * @param {Electron.Rectangle} rectangle 窗口位置和大小
1398
+ * @private
1399
+ */
1400
+ restoreWindowRectangle(options, rectangle) {
1401
+ if (options.resizable !== false) {
1402
+ options.width = rectangle.width ?? options.width;
1403
+ options.height = rectangle.height ?? options.height;
1404
+ }
1405
+ if (this.isWindowRectangleVisible(rectangle)) {
1406
+ options.x = rectangle.x;
1407
+ options.y = rectangle.y;
1408
+ return;
1409
+ }
1410
+ this.centerWindowOptions(options, this.resolveCenterDisplay(rectangle));
1411
+ }
1412
+ /**
1413
+ * 窗口是否有足够区域在屏幕可视范围内
1414
+ * @param {Electron.Rectangle} rectangle 窗口位置和大小
1415
+ * @returns {boolean}
1416
+ * @private
1417
+ */
1418
+ isWindowRectangleVisible(rectangle) {
1419
+ return screen.getAllDisplays().some((display) => this.isWindowRectangleVisibleInDisplay(rectangle, display));
1420
+ }
1421
+ /**
1422
+ * 窗口是否有足够区域在指定屏幕可视范围内
1423
+ * @param {Electron.Rectangle} rectangle 窗口位置和大小
1424
+ * @param {Electron.Display} display 屏幕
1425
+ * @returns {boolean}
1426
+ * @private
1427
+ */
1428
+ isWindowRectangleVisibleInDisplay(rectangle, display) {
1429
+ const minVisibleSize = 200;
1430
+ const area = display.workArea;
1431
+ const visibleWidth = Math.min(rectangle.x + rectangle.width, area.x + area.width) - Math.max(rectangle.x, area.x);
1432
+ const visibleHeight = Math.min(rectangle.y + rectangle.height, area.y + area.height) - Math.max(rectangle.y, area.y);
1433
+ return visibleWidth >= minVisibleSize && visibleHeight >= minVisibleSize;
1434
+ }
1435
+ /**
1436
+ * 解析居中目标屏幕
1437
+ * @param {Electron.Rectangle} rectangle 窗口位置和大小
1438
+ * @returns {Electron.Display}
1439
+ * @private
1440
+ */
1441
+ resolveCenterDisplay(rectangle) {
1442
+ const center = {
1443
+ x: rectangle.x + rectangle.width / 2,
1444
+ y: rectangle.y + rectangle.height / 2
1445
+ };
1446
+ if (!this.isPointInAnyDisplay(center)) {
1447
+ return screen.getPrimaryDisplay();
1448
+ }
1449
+ return screen.getDisplayNearestPoint(center);
1450
+ }
1451
+ /**
1452
+ * 坐标点是否在任一屏幕范围内
1453
+ * @param {Electron.Point} point 坐标点
1454
+ * @returns {boolean}
1455
+ * @private
1456
+ */
1457
+ isPointInAnyDisplay(point) {
1458
+ return screen.getAllDisplays().some((display) => {
1459
+ const bounds = display.bounds;
1460
+ return point.x >= bounds.x && point.x <= bounds.x + bounds.width && point.y >= bounds.y && point.y <= bounds.y + bounds.height;
1461
+ });
1462
+ }
1463
+ /**
1464
+ * 将窗口居中到指定屏幕
1465
+ * @param {Electron.BrowserWindow} window 窗口对象
1466
+ * @param {Electron.Display} display 屏幕
1467
+ * @private
1468
+ */
1469
+ centerWindow(window, display) {
1470
+ const area = display.workArea;
1471
+ const bounds = window.getBounds();
1472
+ const x = Math.round(area.x + (area.width - bounds.width) / 2);
1473
+ const y = Math.round(area.y + (area.height - bounds.height) / 2);
1474
+ window.setPosition(x, y);
1475
+ }
1476
+ /**
1477
+ * 将窗口选项居中到指定屏幕
1478
+ * @param {Electron.BrowserWindowConstructorOptions} options 窗口选项
1479
+ * @param {Electron.Display} display 屏幕
1480
+ * @private
1481
+ */
1482
+ centerWindowOptions(options, display) {
1483
+ const area = display.workArea;
1484
+ const width = options.width ?? 800;
1485
+ const height = options.height ?? 600;
1486
+ options.x = Math.round(area.x + (area.width - width) / 2);
1487
+ options.y = Math.round(area.y + (area.height - height) / 2);
1488
+ options.center = false;
1489
+ }
1490
+ //</editor-fold>
1491
+ //<editor-fold desc="窗口标识管理">
1492
+ /**
1493
+ * 添加窗口标识
1494
+ * @param {number} browserWindowId electron 窗口ID
1495
+ * @param {XoWindow.Identity} identity 窗口标识
1496
+ * @private
1497
+ */
1498
+ addIdentity(browserWindowId, identity) {
1499
+ this.identities.set(browserWindowId, identity);
1500
+ }
1501
+ /**
1502
+ * 移除窗口标识
1503
+ * @param {number | undefined} browserWindowId electron 窗口ID
1504
+ * @private
1505
+ */
1506
+ removeIdentity(browserWindowId) {
1507
+ if (browserWindowId === void 0) {
1508
+ return;
1509
+ }
1510
+ this.identities.delete(browserWindowId);
1511
+ }
1512
+ /**
1513
+ * 通过 electron 窗口ID获取窗口标识
1514
+ * @param {number} browserWindowId electron 窗口ID
1515
+ * @returns {XoWindow.Identity | undefined}
1516
+ */
1517
+ getIdentityByBrowserWindowId(browserWindowId) {
1518
+ return this.identities.get(browserWindowId);
1519
+ }
1520
+ /**
1521
+ * 获取当前已打开窗口标识
1522
+ * @returns {XoWindow.Identity[]}
1523
+ */
1524
+ getOpenedWindowIdentities() {
1525
+ return [...this.identities.values()];
1526
+ }
1527
+ //</editor-fold>
1528
+ //<editor-fold desc="生命周期">
1529
+ /**
1530
+ * 获取窗口生命周期
1531
+ * @param {XoWindow.Type} type 窗口类型
1532
+ * @returns {WindowLifecycleAbstract | undefined} 窗口生命周期
1533
+ * @private
1534
+ */
1535
+ getLifecycleByType(type) {
1536
+ if (!type.lifecycle) {
1537
+ return void 0;
1538
+ }
1539
+ let lifecycle = this.lifecycles.get(type.name);
1540
+ if (!lifecycle) {
1541
+ lifecycle = new type.lifecycle(this.xoApp);
1542
+ this.lifecycles.set(type.name, lifecycle);
1543
+ }
1544
+ return lifecycle;
1545
+ }
1546
+ /**
1547
+ * 绑定窗口生命周期
1548
+ * @param {XoWindow.Record} record 窗口记录
1549
+ */
1550
+ bindLifecycle(record) {
1551
+ const { type, window } = record;
1552
+ const winUID = WindowUtil.recordToUID(record);
1553
+ this.bindWindowOpenHandler(window);
1554
+ const lifecycle = this.getLifecycleByType(type);
1555
+ window.on("closed", () => {
1556
+ this.removeRecord(record);
1557
+ this.xoApp.windowLog.debug("on:closed", winUID);
1558
+ if (lifecycle) {
1559
+ this.catcher("on:closed", record, () => lifecycle.onClosed(record));
1560
+ }
1561
+ });
1562
+ if (!lifecycle) {
1563
+ return;
1564
+ }
1565
+ window.once("ready-to-show", () => {
1566
+ this.xoApp.windowLog.debug("once:ready-to-show", winUID);
1567
+ this.catcher("once:ready-to-show", record, () => lifecycle.onceReadyToShow(record));
1568
+ });
1569
+ window.on("show", () => {
1570
+ this.xoApp.windowLog.debug("on:show", winUID);
1571
+ this.catcher("on:show", record, () => lifecycle.onShow(record));
1572
+ });
1573
+ window.on("hide", () => {
1574
+ this.xoApp.windowLog.debug("on:hide", winUID);
1575
+ this.catcher("on:hide", record, () => lifecycle.onHide(record));
1576
+ });
1577
+ window.on("focus", (event) => {
1578
+ this.xoApp.windowLog.debug("on:focus", winUID);
1579
+ this.catcher("on:focus", record, () => lifecycle.onFocus(event, record));
1580
+ });
1581
+ window.on("blur", (event) => {
1582
+ this.xoApp.windowLog.debug("on:blur", winUID);
1583
+ this.catcher("on:blur", record, () => lifecycle.onBlur(event, record));
1584
+ });
1585
+ window.on("resize", () => {
1586
+ this.xoApp.windowLog.debug("on:resize", winUID);
1587
+ this.catcher("on:resize", record, () => lifecycle.onResize(record));
1588
+ });
1589
+ window.on("resized", () => {
1590
+ this.xoApp.windowLog.debug("on:resized", winUID);
1591
+ this.catcher("on:resized", record, () => lifecycle.onResized(record));
1592
+ });
1593
+ window.on("move", () => {
1594
+ if (type?.windowConfig?.debugPosition) {
1595
+ this.xoApp.windowLog.debug("on:move", winUID);
1596
+ }
1597
+ this.catcher("on:move", record, () => lifecycle.onMove(record));
1598
+ });
1599
+ window.on("moved", () => {
1600
+ if (type?.windowConfig?.debugPosition) {
1601
+ this.xoApp.windowLog.debug("on:moved", winUID);
1602
+ }
1603
+ this.catcher("on:moved", record, () => lifecycle.onMoved(record));
1604
+ });
1605
+ window.on("maximize", () => {
1606
+ this.xoApp.windowLog.debug("on:maximize", winUID);
1607
+ this.notifyWindowState(record);
1608
+ this.catcher("on:maximize", record, () => lifecycle.onMaximize(record));
1609
+ });
1610
+ window.on("unmaximize", () => {
1611
+ this.xoApp.windowLog.debug("on:unmaximize", winUID);
1612
+ this.notifyWindowState(record);
1613
+ this.catcher("on:unmaximize", record, () => lifecycle.onUnmaximize(record));
1614
+ });
1615
+ window.on("minimize", () => {
1616
+ this.xoApp.windowLog.debug("on:minimize", winUID);
1617
+ this.notifyWindowState(record);
1618
+ this.catcher("on:minimize", record, () => lifecycle.onMinimize(record));
1619
+ });
1620
+ window.on("restore", () => {
1621
+ this.xoApp.windowLog.debug("on:restore", winUID);
1622
+ this.notifyWindowState(record);
1623
+ this.catcher("on:restore", record, () => lifecycle.onRestore(record));
1624
+ });
1625
+ window.on("enter-full-screen", () => {
1626
+ this.xoApp.windowLog.debug("on:enter-full-screen", winUID);
1627
+ this.notifyWindowState(record);
1628
+ this.catcher("on:enter-full-screen", record, () => lifecycle.onEnterFullScreen(record));
1629
+ });
1630
+ window.on("leave-full-screen", () => {
1631
+ this.xoApp.windowLog.debug("on:leave-full-screen", winUID);
1632
+ this.notifyWindowState(record);
1633
+ this.catcher("on:leave-full-screen", record, () => lifecycle.onLeaveFullScreen(record));
1634
+ });
1635
+ window.on("always-on-top-changed", () => {
1636
+ this.xoApp.windowLog.debug("on:always-on-top-changed", winUID);
1637
+ this.notifyWindowState(record);
1638
+ this.catcher("on:always-on-top-changed", record, () => lifecycle.onAlwaysOnTopChanged(record));
1639
+ });
1640
+ window.on("close", (event) => {
1641
+ this.xoApp.windowLog.debug("on:close", winUID);
1642
+ this.catcher("on:close", record, () => lifecycle.onClose(event, record));
1643
+ });
1644
+ window.on("unresponsive", () => {
1645
+ this.xoApp.windowLog.debug("on:unresponsive", winUID);
1646
+ this.catcher("on:unresponsive", record, () => lifecycle.onUnresponsive(record));
1647
+ });
1648
+ window.on("responsive", () => {
1649
+ this.xoApp.windowLog.debug("on:responsive", winUID);
1650
+ this.catcher("on:responsive", record, () => lifecycle.onResponsive(record));
1651
+ });
1652
+ window.webContents.on("page-favicon-updated", (event, favicons) => {
1653
+ this.xoApp.windowLog.debug("on:page-favicon-updated", winUID);
1654
+ this.catcher("on:page-favicon-updated", record, () => lifecycle.onWebContentsPageFaviconUpdated(event, record, favicons));
1655
+ });
1656
+ window.webContents.on("focus", () => {
1657
+ this.xoApp.windowLog.debug("on:focus", winUID);
1658
+ this.catcher("on:focus", record, () => lifecycle.onWebContentsFocus(record));
1659
+ });
1660
+ window.webContents.on("blur", () => {
1661
+ this.xoApp.windowLog.debug("on:blur", winUID);
1662
+ this.catcher("on:blur", record, () => lifecycle.onWebContentsBlur(record));
1663
+ });
1664
+ window.webContents.on("did-change-theme-color", (event, color) => {
1665
+ this.xoApp.windowLog.debug("on:did-change-theme-color", winUID);
1666
+ this.catcher("on:did-change-theme-color", record, () => lifecycle.onWebContentsDidChangeThemeColor(event, record, color));
1667
+ });
1668
+ window.webContents.on("update-target-url", (event, url) => {
1669
+ this.xoApp.windowLog.debug("on:update-target-url", winUID);
1670
+ this.catcher("on:update-target-url", record, () => lifecycle.onWebContentsUpdateTargetUrl(event, record, url));
1671
+ });
1672
+ window.webContents.on("will-navigate", (event, url) => {
1673
+ const shouldOpenExternal = this.shouldOpenExternal(url, window.webContents.getURL());
1674
+ this.xoApp.windowLog.debug("on:will-navigate", winUID, { url, shouldOpenExternal });
1675
+ this.catcher("on:will-navigate", record, () => lifecycle.onWebContentsWillNavigate(event, record, url, shouldOpenExternal));
1676
+ });
1677
+ window.webContents.on("context-menu", (event, params) => {
1678
+ this.xoApp.windowLog.debug("on:context-menu", winUID);
1679
+ this.catcher("on:context-menu", record, () => lifecycle.onWebContentsContextMenu(event, record, params));
1680
+ });
1681
+ window.webContents.on("before-input-event", (event, input) => {
1682
+ this.xoApp.windowLog.debug("on:before-input-event", winUID);
1683
+ this.catcher("on:before-input-event", record, () => lifecycle.onWebContentsBeforeInputEvent(event, record, input));
1684
+ });
1685
+ window.webContents.on("input-event", (event, inputEvent) => {
1686
+ if (type?.windowConfig?.debugInputEvent) {
1687
+ this.xoApp.windowLog.debug("on:input-event", winUID);
1688
+ }
1689
+ this.catcher("on:input-event", record, () => lifecycle.onWebContentsInputEvent(event, record, inputEvent));
1690
+ });
1691
+ window.webContents.on("devtools-open-url", (event, url) => {
1692
+ this.xoApp.windowLog.debug("on:devtools-open-url", winUID);
1693
+ this.catcher("on:devtools-open-url", record, () => lifecycle.onWebContentsDevtoolsOpenUrl(event, record, url));
1694
+ });
1695
+ window.webContents.on("devtools-search-query", (event, query) => {
1696
+ this.xoApp.windowLog.debug("on:devtools-search-query", winUID);
1697
+ this.catcher("on:devtools-search-query", record, () => lifecycle.onWebContentsDevtoolsSearchQuery(event, record, query));
1698
+ });
1699
+ window.webContents.on("devtools-opened", () => {
1700
+ this.xoApp.windowLog.debug("on:devtools-opened", winUID);
1701
+ this.catcher("on:devtools-opened", record, () => lifecycle.onWebContentsDevtoolsOpened(record));
1702
+ });
1703
+ window.webContents.on("devtools-closed", () => {
1704
+ this.xoApp.windowLog.debug("on:devtools-closed", winUID);
1705
+ this.catcher("on:devtools-closed", record, () => lifecycle.onWebContentsDevtoolsClosed(record));
1706
+ });
1707
+ window.webContents.on("devtools-focused", () => {
1708
+ this.xoApp.windowLog.debug("on:devtools-focused", winUID);
1709
+ this.catcher("on:devtools-focused", record, () => lifecycle.onWebContentsDevtoolsFocused(record));
1710
+ });
1711
+ window.webContents.on("certificate-error", (event, url, error, certificate, callback, isMainFrame) => {
1712
+ this.xoApp.windowLog.debug("on:certificate-error", winUID);
1713
+ this.catcher("on:certificate-error", record, () => lifecycle.onWebContentsCertificateError(
1714
+ event,
1715
+ record,
1716
+ url,
1717
+ error,
1718
+ certificate,
1719
+ callback,
1720
+ isMainFrame
1721
+ ));
1722
+ });
1723
+ window.webContents.on("select-client-certificate", (event, url, certificateList, callback) => {
1724
+ this.xoApp.windowLog.debug("on:select-client-certificate", winUID);
1725
+ this.catcher("on:select-client-certificate", record, () => lifecycle.onWebContentsSelectClientCertificate(
1726
+ event,
1727
+ record,
1728
+ url,
1729
+ certificateList,
1730
+ callback
1731
+ ));
1732
+ });
1733
+ window.webContents.on("login", (event, authenticationResponseDetails, authInfo, callback) => {
1734
+ this.xoApp.windowLog.debug("on:login", winUID);
1735
+ this.catcher("on:login", record, () => lifecycle.onWebContentsLogin(
1736
+ event,
1737
+ record,
1738
+ authenticationResponseDetails,
1739
+ authInfo,
1740
+ callback
1741
+ ));
1742
+ });
1743
+ window.webContents.on("found-in-page", (event, result) => {
1744
+ this.xoApp.windowLog.debug("on:found-in-page", winUID);
1745
+ this.catcher("on:found-in-page", record, () => lifecycle.onWebContentsFoundInPage(event, record, result));
1746
+ });
1747
+ window.webContents.on("media-started-playing", () => {
1748
+ this.xoApp.windowLog.debug("on:media-started-playing", winUID);
1749
+ this.catcher("on:media-started-playing", record, () => lifecycle.onWebContentsMediaStartedPlaying(record));
1750
+ });
1751
+ window.webContents.on("media-paused", () => {
1752
+ this.xoApp.windowLog.debug("on:media-paused", winUID);
1753
+ this.catcher("on:media-paused", record, () => lifecycle.onWebContentsMediaPaused(record));
1754
+ });
1755
+ window.webContents.on("audio-state-changed", (event) => {
1756
+ this.xoApp.windowLog.debug("on:audio-state-changed", winUID);
1757
+ this.catcher("on:audio-state-changed", record, () => lifecycle.onWebContentsAudioStateChanged(event, record));
1758
+ });
1759
+ window.webContents.on("console-message", (details) => {
1760
+ if (type?.windowConfig?.debugConsole) {
1761
+ this.xoApp.windowLog.debug("on:console-message", winUID);
1762
+ }
1763
+ this.catcher("on:console-message", record, () => lifecycle.onWebContentsConsoleMessage(details, record));
1764
+ });
1765
+ window.webContents.on("preload-error", (event, preloadPath, error) => {
1766
+ this.xoApp.windowLog.debug("on:preload-error", winUID);
1767
+ this.catcher("on:preload-error", record, () => lifecycle.onWebContentsPreloadError(event, record, preloadPath, error));
1768
+ });
1769
+ window.webContents.on("ipc-message", (event, channel, ...args) => {
1770
+ if (type?.windowConfig?.debugIpcMessage) {
1771
+ this.xoApp.windowLog.debug("on:ipc-message", winUID);
1772
+ }
1773
+ this.catcher("on:ipc-message", record, () => lifecycle.onWebContentsIpcMessage(event, record, channel, ...args));
1774
+ });
1775
+ window.webContents.on("ipc-message-sync", (event, channel, ...args) => {
1776
+ if (type?.windowConfig?.debugIpcMessage) {
1777
+ this.xoApp.windowLog.debug("on:ipc-message-sync", winUID);
1778
+ }
1779
+ this.catcher("on:ipc-message-sync", record, () => lifecycle.onWebContentsIpcMessageSync(event, record, channel, ...args));
1780
+ });
1781
+ window.webContents.on("preferred-size-changed", (event, preferredSize) => {
1782
+ this.xoApp.windowLog.debug("on:preferred-size-changed", winUID);
1783
+ this.catcher("on:preferred-size-changed", record, () => lifecycle.onWebContentsPreferredSizeChanged(event, record, preferredSize));
1784
+ });
1785
+ window.webContents.on("frame-created", (event, details) => {
1786
+ this.xoApp.windowLog.debug("on:frame-created", winUID);
1787
+ this.catcher("on:frame-created", record, () => lifecycle.onWebContentsFrameCreated(event, record, details));
1788
+ });
1789
+ window.webContents.on("will-attach-webview", (event, webPreferences, params) => {
1790
+ this.xoApp.windowLog.debug("on:will-attach-webview", winUID);
1791
+ this.catcher("on:will-attach-webview", record, () => lifecycle.onWebContentsWillAttachWebview(
1792
+ event,
1793
+ record,
1794
+ webPreferences,
1795
+ params
1796
+ ));
1797
+ });
1798
+ window.webContents.on("did-attach-webview", (event, webContents) => {
1799
+ this.xoApp.windowLog.debug("on:did-attach-webview", winUID);
1800
+ this.catcher("on:did-attach-webview", record, () => lifecycle.onWebContentsDidAttachWebview(event, record, webContents));
1801
+ });
1802
+ window.webContents.on("paint", (details, dirtyRect, image) => {
1803
+ this.xoApp.windowLog.debug("on:paint", winUID);
1804
+ this.catcher("on:paint", record, () => lifecycle.onWebContentsPaint(details, record, dirtyRect, image));
1805
+ });
1806
+ window.webContents.on("devtools-reload-page", () => {
1807
+ this.xoApp.windowLog.debug("on:devtools-reload-page", winUID);
1808
+ this.catcher("on:devtools-reload-page", record, () => lifecycle.onWebContentsDevtoolsReloadPage(record));
1809
+ });
1810
+ window.webContents.on("destroyed", () => {
1811
+ this.xoApp.windowLog.debug("on:destroyed", winUID);
1812
+ this.catcher("on:destroyed", record, () => lifecycle.onWebContentsDestroyed(record));
1813
+ });
1814
+ window.webContents.on("did-finish-load", () => {
1815
+ this.xoApp.windowLog.debug("on:did-finish-load", winUID);
1816
+ this.catcher("on:did-finish-load", record, () => lifecycle.onWebContentsDidFinishLoad(record));
1817
+ });
1818
+ window.webContents.on("did-start-loading", () => {
1819
+ this.xoApp.windowLog.debug("on:did-start-loading", winUID);
1820
+ this.rendererLoading(window);
1821
+ this.catcher("on:did-start-loading", record, () => lifecycle.onWebContentsDidStartLoading(record));
1822
+ });
1823
+ window.webContents.on("did-stop-loading", () => {
1824
+ this.xoApp.windowLog.debug("on:did-stop-loading", winUID);
1825
+ this.catcher("on:did-stop-loading", record, () => lifecycle.onWebContentsDidStopLoading(record));
1826
+ });
1827
+ window.webContents.on("dom-ready", () => {
1828
+ this.xoApp.windowLog.debug("on:dom-ready", winUID);
1829
+ this.catcher("on:dom-ready", record, () => lifecycle.onWebContentsDomReady(record));
1830
+ });
1831
+ window.webContents.on("page-title-updated", (event, title, explicitSet) => {
1832
+ this.xoApp.windowLog.debug("on:page-title-updated", winUID);
1833
+ this.catcher("on:page-title-updated", record, () => lifecycle.onWebContentsPageTitleUpdated(event, record, title, explicitSet));
1834
+ });
1835
+ window.webContents.on("did-fail-load", (event, errorCode, errorDescription, validatedURL, isMainFrame, frameProcessId, frameRoutingId) => {
1836
+ const params = {
1837
+ errorCode,
1838
+ errorDescription,
1839
+ validatedURL,
1840
+ isMainFrame,
1841
+ frameProcessId,
1842
+ frameRoutingId
1843
+ };
1844
+ this.xoApp.windowLog.debug("on:did-fail-load", winUID, { ...params });
1845
+ this.catcher("on:did-fail-load", record, () => lifecycle.onWebContentsDidFailLoad(event, record, params));
1846
+ });
1847
+ window.webContents.on("enter-html-full-screen", () => {
1848
+ this.xoApp.windowLog.debug("on:enter-html-full-screen", winUID);
1849
+ this.catcher("on:enter-html-full-screen", record, () => lifecycle.onWebContentsEnterHtmlFullScreen(record));
1850
+ });
1851
+ window.webContents.on("leave-html-full-screen", () => {
1852
+ this.xoApp.windowLog.debug("on:leave-html-full-screen", winUID);
1853
+ this.catcher("on:leave-html-full-screen", record, () => lifecycle.onWebContentsLeaveHtmlFullScreen(record));
1854
+ });
1855
+ window.webContents.on("render-process-gone", (event, details) => {
1856
+ this.xoApp.windowLog.debug("on:render-process-gone", winUID, { details });
1857
+ this.catcher("on:render-process-gone", record, () => lifecycle.onWebContentsRenderProcessGone(event, record, details));
1858
+ });
1859
+ }
1860
+ /**
1861
+ * 绑定新窗口打开拦截
1862
+ * @param {Electron.BrowserWindow} window 窗口对象
1863
+ * @private
1864
+ */
1865
+ bindWindowOpenHandler(window) {
1866
+ window.webContents.setWindowOpenHandler((details) => {
1867
+ if (!this.shouldOpenExternal(details.url, window.webContents.getURL())) {
1868
+ return { action: "allow" };
1869
+ }
1870
+ void shell2.openExternal(details.url);
1871
+ return { action: "deny" };
1872
+ });
1873
+ }
1874
+ /**
1875
+ * 是否应使用系统浏览器打开
1876
+ * @param {string} targetURL 目标地址
1877
+ * @param {string} currentURL 当前地址
1878
+ * @returns {boolean}
1879
+ * @private
1880
+ */
1881
+ shouldOpenExternal(targetURL, currentURL) {
1882
+ const appConfig = this.xoApp.getAppConfig();
1883
+ if (!appConfig?.takeOverLinkNavigation) {
1884
+ return false;
1885
+ }
1886
+ if (this.isLinkNavigationWhiteListed(targetURL)) {
1887
+ return false;
1888
+ }
1889
+ const target = this.parseURL(targetURL);
1890
+ if (!target) {
1891
+ return false;
1892
+ }
1893
+ if (["mailto:", "tel:"].includes(target.protocol)) {
1894
+ return true;
1895
+ }
1896
+ if (!["http:", "https:"].includes(target.protocol)) {
1897
+ return false;
1898
+ }
1899
+ const current = this.parseURL(currentURL);
1900
+ if (!current) {
1901
+ return true;
1902
+ }
1903
+ return target.origin !== current.origin;
1904
+ }
1905
+ /**
1906
+ * 是否命中链接跳转白名单
1907
+ * @param {string} url 链接
1908
+ * @returns {boolean}
1909
+ * @private
1910
+ */
1911
+ isLinkNavigationWhiteListed(url) {
1912
+ return this.xoApp.getAppConfig()?.linkNavigationWhiteList?.some((pattern) => pattern.test(url)) ?? false;
1913
+ }
1914
+ /**
1915
+ * 解析 URL
1916
+ * @param {string} value URL
1917
+ * @returns {URL | undefined}
1918
+ * @private
1919
+ */
1920
+ parseURL(value) {
1921
+ try {
1922
+ return new URL(value);
1923
+ } catch {
1924
+ return void 0;
1925
+ }
1926
+ }
1927
+ //</editor-fold>
1928
+ //<editor-fold desc="错误管理">
1929
+ /**
1930
+ * 事件错误捕捉器
1931
+ * @param {string} source 事件来源
1932
+ * @param {XoWindow.Record} record 窗口实例
1933
+ * @param {() => (Promise<void> | void)} runner 事件处理器
1934
+ * @private
1935
+ */
1936
+ catcher(source, record, runner) {
1937
+ try {
1938
+ void Promise.resolve(runner()).catch((error) => {
1939
+ void this.getLifecycleByType(record.type)?.onError(record, { source, error });
1940
+ });
1941
+ } catch (error) {
1942
+ void this.getLifecycleByType(record.type)?.onError(record, { source, error });
1943
+ }
1944
+ }
1945
+ /**
1946
+ * 分发错误
1947
+ * @param {string} source 来源
1948
+ * @param {XoWindow.Record | undefined} record 窗口实例
1949
+ * @param {unknown} error 错误对象
1950
+ * @returns {Promise<void>}
1951
+ * @private
1952
+ */
1953
+ async dispatchError(source, record, error) {
1954
+ if (record) {
1955
+ await this.getLifecycleByType(record.type)?.onError(record, { source, error });
1956
+ return;
1957
+ }
1958
+ await this.xoApp.dispatchAppError({ source, error });
1959
+ }
1960
+ //</editor-fold>
1961
+ };
1962
+
1963
+ export {
1964
+ WindowLifecycleAbstract,
1965
+ MainWindowLifecycle,
1966
+ MainWindowType,
1967
+ SettingWindowLifecycle,
1968
+ SettingWindowType,
1969
+ WindowManager
1970
+ };