koishi-plugin-chat-patch 3.0.2 → 5.0.1

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 (237) hide show
  1. package/client/vue/index.vue +60 -634
  2. package/client/web/dist/assets/AppIcon-DIku6-h0.png +0 -0
  3. package/client/web/dist/assets/AppIconDark-BYymN71t.png +0 -0
  4. package/client/web/dist/assets/CapacitorAppIcon-CSZwNhvi.png +0 -0
  5. package/client/web/dist/assets/CapacitorAppIconDark-BMvMOzsg.png +0 -0
  6. package/client/web/dist/assets/Chat-CTdyeaX2.css +1 -0
  7. package/client/web/dist/assets/Chat-DkZvD7d8.js +28 -0
  8. package/client/web/dist/assets/MealHungryPan-Beos3lRI.js +1 -0
  9. package/client/web/dist/assets/MsgBody-aZ4_aija.js +1 -0
  10. package/client/web/dist/assets/MsgBody.vue_vue_type_script_setup_true_lang-CPZjRLp6.js +67 -0
  11. package/client/web/dist/assets/NapcatAppIcon-C7VOAkW9.png +0 -0
  12. package/client/web/dist/assets/Vue-lEhHouxB.png +0 -0
  13. package/client/web/dist/assets/append_darwin-CqBNU62J.css +1 -0
  14. package/client/web/dist/assets/append_full_vibrancy-j0D2LM9m.css +1 -0
  15. package/client/web/dist/assets/append_linux-uhxeBqeC.css +1 -0
  16. package/client/web/dist/assets/append_linux_vibrancy-COiZq8MS.css +1 -0
  17. package/client/web/dist/assets/append_napcat-DV8CAyAd.css +1 -0
  18. package/client/web/dist/assets/append_new-407Lo5_V.css +1 -0
  19. package/client/web/dist/assets/append_vibrancy-6FHctkOY.css +1 -0
  20. package/client/web/dist/assets/append_win32-srmD-78y.css +1 -0
  21. package/client/web/dist/assets/cakes-CxTVKdnK.svg +189 -0
  22. package/client/web/dist/assets/core-DhEqZVGG.js +1 -0
  23. package/client/web/dist/assets/event-Cadp6m6J.js +1 -0
  24. package/client/web/dist/assets/index-CPTXiemn.js +4045 -0
  25. package/client/web/dist/assets/index-Cg_esKB0.js +1 -0
  26. package/client/web/dist/assets/index-Cln012sP.css +1 -0
  27. package/client/web/dist/assets//346/226/271/346/255/243/345/226/265/345/221/234/344/275/223-CJKIKBn3.ttf +0 -0
  28. package/client/web/dist/assets//346/234/237/345/276/205-C90_OY60.png +0 -0
  29. package/client/web/dist/bcui/css/color-dark.css +35 -0
  30. package/client/web/dist/bcui/css/color-light.css +35 -0
  31. package/client/web/dist/bcui/css/style.css +468 -0
  32. package/client/web/dist/bcui/js/main.js +193 -0
  33. package/client/web/dist/css/append-dark.css +13 -0
  34. package/client/web/dist/css/append-light.css +13 -0
  35. package/client/web/dist/css/append-napcat-dark.css +14 -0
  36. package/client/web/dist/css/append-napcat-light.css +14 -0
  37. package/client/web/dist/favicon.ico +0 -0
  38. package/client/web/dist/img/icons/icon-for-fuck-apple.png +0 -0
  39. package/client/web/dist/img/icons/icon-maskable.png +0 -0
  40. package/client/web/dist/img/icons/icon.png +0 -0
  41. package/client/web/dist/img/icons/icon.svg +10 -0
  42. package/client/web/dist/index.html +22 -0
  43. package/client/web/dist/robots.txt +2 -0
  44. package/client/web/dist/sw.js +58 -0
  45. package/client/web/env.d.ts +56 -0
  46. package/client/web/index.html +21 -0
  47. package/client/web/package-lock.json +3419 -0
  48. package/client/web/package.json +62 -0
  49. package/client/web/public/bcui/css/color-dark.css +35 -0
  50. package/client/web/public/bcui/css/color-light.css +35 -0
  51. package/client/web/public/bcui/css/style.css +468 -0
  52. package/client/web/public/bcui/js/main.js +193 -0
  53. package/client/web/public/css/append-dark.css +13 -0
  54. package/client/web/public/css/append-light.css +13 -0
  55. package/client/web/public/css/append-napcat-dark.css +14 -0
  56. package/client/web/public/css/append-napcat-light.css +14 -0
  57. package/client/web/public/favicon.ico +0 -0
  58. package/client/web/public/img/icons/icon-for-fuck-apple.png +0 -0
  59. package/client/web/public/img/icons/icon-maskable.png +0 -0
  60. package/client/web/public/img/icons/icon.png +0 -0
  61. package/client/web/public/img/icons/icon.svg +10 -0
  62. package/client/web/public/robots.txt +2 -0
  63. package/client/web/public/sw.js +58 -0
  64. package/client/web/scripts/copy-bcui.mjs +17 -0
  65. package/client/web/src/App.vue +1127 -0
  66. package/client/web/src/assets/css/append/append_darwin.css +68 -0
  67. package/client/web/src/assets/css/append/append_full_vibrancy.css +290 -0
  68. package/client/web/src/assets/css/append/append_linux.css +125 -0
  69. package/client/web/src/assets/css/append/append_linux_vibrancy.css +22 -0
  70. package/client/web/src/assets/css/append/append_napcat.css +35 -0
  71. package/client/web/src/assets/css/append/append_new.css +843 -0
  72. package/client/web/src/assets/css/append/append_vibrancy.css +113 -0
  73. package/client/web/src/assets/css/append/append_win32.css +109 -0
  74. package/client/web/src/assets/css/append/mobile/append_mobile_horizontal.css +349 -0
  75. package/client/web/src/assets/css/append/mobile/append_mobile_vertical.css +96 -0
  76. package/client/web/src/assets/css/chat.css +2104 -0
  77. package/client/web/src/assets/css/msg.css +941 -0
  78. package/client/web/src/assets/css/options.css +811 -0
  79. package/client/web/src/assets/css/sys_notice.css +62 -0
  80. package/client/web/src/assets/css/view.css +2105 -0
  81. package/client/web/src/assets/font//346/226/271/346/255/243/345/226/265/345/221/234/344/275/223.ttf +0 -0
  82. package/client/web/src/assets/img/Vue.png +0 -0
  83. package/client/web/src/assets/img/cakes.svg +189 -0
  84. package/client/web/src/assets/img/icons/AppIcon.png +0 -0
  85. package/client/web/src/assets/img/icons/AppIconDark.png +0 -0
  86. package/client/web/src/assets/img/icons/CapacitorAppIcon.png +0 -0
  87. package/client/web/src/assets/img/icons/CapacitorAppIconDark.png +0 -0
  88. package/client/web/src/assets/img/icons/NapcatAppIcon.png +0 -0
  89. package/client/web/src/assets/img/icons/NapcatAppIconDark.png +0 -0
  90. package/client/web/src/assets/img/icons/exit.png +0 -0
  91. package/client/web/src/assets/img/icons/pen.png +0 -0
  92. package/client/web/src/assets/img/stars.svg +89 -0
  93. package/client/web/src/assets/img//346/234/237/345/276/205.png +0 -0
  94. package/client/web/src/assets/l10n/_About I10n.md +35 -0
  95. package/client/web/src/assets/l10n/_l10nconfig.json +7 -0
  96. package/client/web/src/assets/l10n/zh-CN.po +1941 -0
  97. package/client/web/src/assets/logo.png +0 -0
  98. package/client/web/src/assets/pathMap/LLOneBot.yaml +2 -0
  99. package/client/web/src/assets/pathMap/Lagrange.OneBot.yaml +180 -0
  100. package/client/web/src/assets/pathMap/NapCat.Onebot.yaml +224 -0
  101. package/client/web/src/assets/pathMap/SnowLuma.yaml +80 -0
  102. package/client/web/src/assets/qed.txt +1 -0
  103. package/client/web/src/components/AboutPan.vue +197 -0
  104. package/client/web/src/components/BulletinBody.vue +129 -0
  105. package/client/web/src/components/DepPan.vue +310 -0
  106. package/client/web/src/components/EmojiFace.vue +32 -0
  107. package/client/web/src/components/FacePan.vue +461 -0
  108. package/client/web/src/components/FileBody.vue +129 -0
  109. package/client/web/src/components/FileManager.vue +532 -0
  110. package/client/web/src/components/FriendBody.vue +54 -0
  111. package/client/web/src/components/GlobalSessionSearchBar.vue +301 -0
  112. package/client/web/src/components/History.vue +49 -0
  113. package/client/web/src/components/LazyLottie.vue +82 -0
  114. package/client/web/src/components/MergePan.vue +127 -0
  115. package/client/web/src/components/MsgBody.vue +1478 -0
  116. package/client/web/src/components/MusicPlayer.vue +549 -0
  117. package/client/web/src/components/NoticeBody.vue +168 -0
  118. package/client/web/src/components/QzonePermissionPan.vue +150 -0
  119. package/client/web/src/components/RawMsgRenderPreviewPan.vue +190 -0
  120. package/client/web/src/components/ThemeColorPickerPan.vue +420 -0
  121. package/client/web/src/components/TinySessionBody.vue +51 -0
  122. package/client/web/src/components/UmamiInfoPan.vue +1549 -0
  123. package/client/web/src/components/UpdatePan.vue +263 -0
  124. package/client/web/src/components/ViewerCom.vue +1360 -0
  125. package/client/web/src/components/VoiceMsg.vue +626 -0
  126. package/client/web/src/components/WelPan.vue +894 -0
  127. package/client/web/src/components/msg-body/.gitkeep +0 -0
  128. package/client/web/src/components/msg-component/JsonSegComp.vue +138 -0
  129. package/client/web/src/components/msg-component/XmlSegComp.vue +132 -0
  130. package/client/web/src/components/msg-component/jsonComp/AutoReply.vue +97 -0
  131. package/client/web/src/components/msg-component/jsonComp/Contact.lua.vue +129 -0
  132. package/client/web/src/components/msg-component/jsonComp/Feed.lua.vue +94 -0
  133. package/client/web/src/components/msg-component/jsonComp/Forum.vue +84 -0
  134. package/client/web/src/components/msg-component/jsonComp/Mannounce.vue +111 -0
  135. package/client/web/src/components/msg-component/jsonComp/Map.vue +52 -0
  136. package/client/web/src/components/msg-component/jsonComp/Miniapp.lua.vue +53 -0
  137. package/client/web/src/components/msg-component/jsonComp/Miniapp.vue +69 -0
  138. package/client/web/src/components/msg-component/jsonComp/Music.lua.vue +135 -0
  139. package/client/web/src/components/msg-component/jsonComp/Tuwen.lua.vue +56 -0
  140. package/client/web/src/components/notice-component/.gitkeep +0 -0
  141. package/client/web/src/components/notice-component/MealHungryPan.vue +119 -0
  142. package/client/web/src/components/tooltip/CustomFaceTooltip.vue +22 -0
  143. package/client/web/src/components/tooltip/Tooltip.vue +50 -0
  144. package/client/web/src/components/tooltip/Tooltips.vue +14 -0
  145. package/client/web/src/components/tooltip/UserInfoTooltip.vue +69 -0
  146. package/client/web/src/function/base.ts +238 -0
  147. package/client/web/src/function/connect.ts +2042 -0
  148. package/client/web/src/function/debug.ts +10 -0
  149. package/client/web/src/function/elements/information.ts +141 -0
  150. package/client/web/src/function/elements/system.ts +101 -0
  151. package/client/web/src/function/elements/vueComp.ts +62 -0
  152. package/client/web/src/function/favicon.ts +76 -0
  153. package/client/web/src/function/input.ts +69 -0
  154. package/client/web/src/function/model/emoji.ts +127 -0
  155. package/client/web/src/function/model/img.ts +150 -0
  156. package/client/web/src/function/model/msg-body.ts +51 -0
  157. package/client/web/src/function/msg.ts +2674 -0
  158. package/client/web/src/function/notify.ts +225 -0
  159. package/client/web/src/function/option.ts +749 -0
  160. package/client/web/src/function/satori-model.ts +818 -0
  161. package/client/web/src/function/satori.ts +325 -0
  162. package/client/web/src/function/sender.ts +178 -0
  163. package/client/web/src/function/tooltip.ts +49 -0
  164. package/client/web/src/function/utils/appUtil.ts +2288 -0
  165. package/client/web/src/function/utils/avatarUtil.ts +31 -0
  166. package/client/web/src/function/utils/backgroundUtil.ts +110 -0
  167. package/client/web/src/function/utils/linkViewUtil.ts +101 -0
  168. package/client/web/src/function/utils/localHistoryUtil.ts +517 -0
  169. package/client/web/src/function/utils/msgUtil.ts +1242 -0
  170. package/client/web/src/function/utils/pinyin.ts +141 -0
  171. package/client/web/src/function/utils/recordUtil.ts +187 -0
  172. package/client/web/src/function/utils/sessionUtil.ts +114 -0
  173. package/client/web/src/function/utils/systemUtil.ts +664 -0
  174. package/client/web/src/main.ts +91 -0
  175. package/client/web/src/pages/Chat.vue +3453 -0
  176. package/client/web/src/pages/Friends.vue +636 -0
  177. package/client/web/src/pages/Info.vue +717 -0
  178. package/client/web/src/pages/Messages.vue +875 -0
  179. package/client/web/src/pages/Options.vue +82 -0
  180. package/client/web/src/pages/Qzone.vue +1178 -0
  181. package/client/web/src/pages/chat-view/ChatDanmaku.vue +759 -0
  182. package/client/web/src/pages/chat-view/ChatGlagame.vue +642 -0
  183. package/client/web/src/pages/chat-view/ChatTerminal.vue +1044 -0
  184. package/client/web/src/pages/chat-view/SystemNotice.vue +171 -0
  185. package/client/web/src/pages/options/OptAccount.vue +107 -0
  186. package/client/web/src/pages/options/OptAddon.vue +185 -0
  187. package/client/web/src/pages/options/OptDev.vue +704 -0
  188. package/client/web/src/pages/options/OptFunction.vue +403 -0
  189. package/client/web/src/pages/options/OptInfo.vue +165 -0
  190. package/client/web/src/pages/options/OptView.vue +846 -0
  191. package/client/web/src/runtime/backend.ts +310 -0
  192. package/client/web/src/state/auth.ts +14 -0
  193. package/client/web/src/state/chat.ts +36 -0
  194. package/client/web/src/state/connection.ts +20 -0
  195. package/client/web/src/state/contact.ts +37 -0
  196. package/client/web/src/state/qzone.ts +18 -0
  197. package/client/web/src/state/sessionHistory.ts +25 -0
  198. package/client/web/src/state/settings.ts +18 -0
  199. package/client/web/src/state/sticker.ts +10 -0
  200. package/client/web/src/state/ui.ts +56 -0
  201. package/client/web/tsconfig.json +27 -0
  202. package/client/web/tsconfig.tsbuildinfo +1 -0
  203. package/client/web/vite.config.ts +33 -0
  204. package/dist/index.js +1 -12
  205. package/dist/style.css +1 -1
  206. package/lib/index.js +2070 -2077
  207. package/package.json +15 -2
  208. package/readme.md +0 -22
  209. package/src/bootstrap.ts +71 -0
  210. package/src/cache.ts +319 -0
  211. package/src/config.ts +23 -35
  212. package/src/database.ts +650 -0
  213. package/src/index.ts +27 -59
  214. package/src/media.ts +302 -0
  215. package/src/recorder.ts +175 -0
  216. package/src/self-message.ts +456 -0
  217. package/src/server.d.ts +26 -0
  218. package/src/types.ts +108 -48
  219. package/src/web.ts +712 -0
  220. package/client/vue/chat-logic.ts +0 -683
  221. package/client/vue/composables/useChatActions.ts +0 -61
  222. package/client/vue/composables/useChatData.ts +0 -185
  223. package/client/vue/composables/useImageCache.ts +0 -281
  224. package/client/vue/composables/useVideoCache.ts +0 -125
  225. package/client/vue/types.ts +0 -72
  226. package/lib/api-handlers.d.ts +0 -25
  227. package/lib/config.d.ts +0 -14
  228. package/lib/file-manager.d.ts +0 -124
  229. package/lib/index.d.ts +0 -17
  230. package/lib/logger.d.ts +0 -9
  231. package/lib/message-handler.d.ts +0 -35
  232. package/lib/types.d.ts +0 -57
  233. package/lib/utils.d.ts +0 -18
  234. package/src/api-handlers.ts +0 -646
  235. package/src/file-manager.ts +0 -1436
  236. package/src/message-handler.ts +0 -507
  237. package/src/utils.ts +0 -189
@@ -0,0 +1,310 @@
1
+ import { i18n } from '../main'
2
+ import VConsole from 'vconsole'
3
+
4
+ import { IpcRenderer } from '@electron-toolkit/preload'
5
+ import { InvokeArgs, InvokeOptions } from '@tauri-apps/api/core'
6
+ import { CapacitorGlobal } from '@capacitor/core'
7
+ import { Logger, LogType, PopInfo, PopType } from '../function/base'
8
+ import { useSettingsStore } from '../state/settings'
9
+
10
+ const logger = new Logger()
11
+ const popInfo = new PopInfo()
12
+
13
+ type CapacitorPluginRegistry = Record<string, Record<string, (...args: any[]) => any>>
14
+
15
+ export const backend = {
16
+ type: 'web' as 'electron' | 'tauri' | 'capacitor' | 'web',
17
+ platform: undefined as 'win32' | 'darwin' | 'linux' | 'android' | 'ios' | 'web' | undefined,
18
+ release: '',
19
+ arch: '' as string | undefined,
20
+ proxy: undefined as number | undefined,
21
+
22
+ function: undefined as IpcRenderer |
23
+ {
24
+ invoke: <T>(cmd: string, args?: InvokeArgs, options?: InvokeOptions) => Promise<T>
25
+ } | {
26
+ capacitor: CapacitorGlobal & Record<string, any>,
27
+ plugins: CapacitorPluginRegistry,
28
+ vConsole: VConsole
29
+ } | undefined,
30
+ listener: undefined as ((event: string, ...args: any[]) => void) | undefined,
31
+
32
+ isDesktop() {
33
+ return this.type == 'electron' || this.type == 'tauri'
34
+ },
35
+ isMobile() {
36
+ return this.type == 'capacitor'
37
+ },
38
+ isWeb() {
39
+ return this.type == 'web'
40
+ },
41
+
42
+ /**
43
+ * 代理 URL 转换
44
+ * @param url 需要转换的 URL
45
+ * @returns 转换后的 URL
46
+ */
47
+ proxyUrl(url: string) {
48
+ if (!url || url.startsWith('data:') || url.startsWith('blob:')
49
+ || url.startsWith('/chat-patch/web/media') || url.startsWith('/chat-patch/api/media')) {
50
+ return url
51
+ }
52
+ if (url.startsWith('/vite/') || url.startsWith('/satori/')) {
53
+ return url
54
+ }
55
+ if (/^file:/i.test(url) || /^[a-z]:[\\/]/i.test(url) || url.startsWith('\\\\')) {
56
+ const fileName = url
57
+ .replace(/^file:\/\/\/?/i, '')
58
+ .split(/[\\/]/)
59
+ .pop() || url
60
+ return `/chat-patch/api/media?file=${encodeURIComponent(fileName)}`
61
+ }
62
+ if (this.proxy && url && url.startsWith('http')) {
63
+ return `http://localhost:${this.proxy}/proxy?url=${encodeURIComponent(url)}`
64
+ } else {
65
+ return `/chat-patch/web/media?url=${encodeURIComponent(url)}`
66
+ }
67
+ },
68
+
69
+ /**
70
+ * 代理图片 URL 转换
71
+ * 此方法在移动端还会会向后端直接索要图片的 base64 数据,以解决移动端的跨域问题
72
+ * @param url 需要转换的 URL
73
+ * @returns 转换后的 URL(移动端返回 data:image/...)
74
+ */
75
+ async proxyImageUrl(url: string) {
76
+ if (this.isMobile() && url) {
77
+ const dataUrl = await this.call('Onebot', 'sys:getImageData', true, { url })
78
+ if (typeof dataUrl === 'string' && dataUrl.startsWith('data:image')) {
79
+ return dataUrl
80
+ }
81
+ logger.add(LogType.DEBUG, '移动端图片代理失败,回退到普通代理 URL', { url })
82
+ }
83
+ return this.proxyUrl(url)
84
+ },
85
+
86
+ /**
87
+ * 反代理 URL 转换
88
+ * @param url 需要转换的 URL
89
+ * @returns 转换后的 URL
90
+ */
91
+ unProxyUrl(url: string) {
92
+ if (this.proxy && url && url.startsWith('http://localhost')) {
93
+ const urlObj = new URL(url)
94
+ if (urlObj.pathname == '/proxy') {
95
+ const realUrl = urlObj.searchParams.get('url')
96
+ if (realUrl) {
97
+ return decodeURIComponent(realUrl)
98
+ }
99
+ }
100
+ }
101
+ return url
102
+ },
103
+
104
+ /**
105
+ * 初始化后端功能
106
+ *
107
+ * @returns {Promise<void>}
108
+ */
109
+ async init() {
110
+ const $t = i18n.global.t
111
+ if (window.electron != undefined) {
112
+ this.type = 'electron';
113
+ this.function = window.electron.ipcRenderer;
114
+ this.listener = window.electron.ipcRenderer.on;
115
+ } else if (window.__TAURI_INTERNALS__ != undefined) {
116
+ this.type = 'tauri';
117
+ this.function = {
118
+ invoke: (await import('@tauri-apps/api/core')).invoke
119
+ }
120
+ this.listener = (await import('@tauri-apps/api/event')).listen;
121
+ } else if (window.Capacitor != undefined && window.Capacitor.isNativePlatform()) {
122
+ this.type = 'capacitor';
123
+ const capacitor = window.Capacitor as CapacitorGlobal & Record<string, any>
124
+ const plugins = (capacitor.Plugins ?? {}) as CapacitorPluginRegistry
125
+ this.function = {
126
+ capacitor,
127
+ plugins,
128
+ vConsole: new VConsole({
129
+ theme: useSettingsStore().darkMode ? 'dark' : 'light',
130
+ })
131
+ }
132
+ this.listener = (type: string, name: string, callBack: (...args: any[]) => void) => {
133
+ plugins[type]?.addListener?.(name, callBack)
134
+ }
135
+ }
136
+
137
+
138
+ this.platform = await this.call(undefined, 'sys:getPlatform', true)
139
+ const releaseData = await this.call('Onebot', 'sys:getRelease', true)
140
+ this.release = releaseData?.release || ''
141
+ this.arch = releaseData?.arch || undefined
142
+
143
+ if(this.type == 'web' && !this.platform) {
144
+ this.platform = 'web'
145
+ }
146
+
147
+ if (!this.release) {
148
+ let os = ''
149
+ let version = ''
150
+
151
+ // 优先使用 navigator.userAgentData(Chrome / Edge / Android)
152
+ if ((navigator as any).userAgentData) {
153
+ os = (navigator as any).userAgentData.platform || os
154
+ try {
155
+ const highEntropy = await (navigator as any).userAgentData.getHighEntropyValues(['platformVersion'])
156
+ version = highEntropy.platformVersion || version
157
+ } catch (e) {
158
+ // 如果获取失败,保持 Unknown
159
+ }
160
+ } else {
161
+ // fallback: 使用 navigator.userAgent
162
+ const ua = navigator.userAgent
163
+
164
+ if (/Windows NT (\d+\.\d+)/.test(ua)) {
165
+ os = 'Windows'
166
+ version = ua.match(/Windows NT (\d+\.\d+)/)?.[1] ?? 'Unknown'
167
+ } else if (/Mac OS X (\d+[_.]\d+[_.]?\d*)/.test(ua)) {
168
+ os = 'macOS'
169
+ version = ua.match(/Mac OS X (\d+[_.]\d+[_.]?\d*)/)?.[1]?.replace(/_/g, '.') ?? 'Unknown'
170
+ } else if (/Android (\d+(\.\d+)?)/.test(ua)) {
171
+ os = 'Android'
172
+ version = ua.match(/Android (\d+(\.\d+)?)/)?.[1] ?? 'Unknown'
173
+ } else if (/iPhone OS (\d+[_.]\d+[_.]?\d*)/.test(ua)) {
174
+ os = 'iOS'
175
+ version = ua.match(/iPhone OS (\d+[_.]\d+[_.]?\d*)/)?.[1]?.replace(/_/g, '.') ?? 'Unknown'
176
+ } else if (/Linux/.test(ua)) {
177
+ os = 'Linux'
178
+ version = 'Unknown'
179
+ }
180
+ }
181
+ this.release = `${os} ${version} (Web)`
182
+ }
183
+ this.proxy = await this.call(undefined, 'sys:runProxy', true)
184
+ if(this.type == 'tauri' && !this.proxy) {
185
+ logger.error(null, 'Tauri 代理服务似乎没有正常启动,此服务异常将会影响应用内的大部分外部资源的加载。')
186
+ popInfo.add(PopType.ERR, $t('Tauri 代理服务似乎没有正常启动'), false)
187
+ }
188
+ },
189
+
190
+ /**
191
+ * 调用后端方法
192
+ *
193
+ * #### 方法名称
194
+ * 请使用统一的 electron 方法名称,其余平台会自动转换
195
+ * - electron 将调用 sys: 前缀的名称如 > sys:getConfig
196
+ * - capacitor 将调用去除 sys: 前缀的名称如 > getConfig
197
+ * - tauri 将调用 sys_ 前缀加下划线小写的名称如 > sys_get_config
198
+ *
199
+ * #### 备注
200
+ * - 在 capacitor 和 tauri 中。args 必须是一个对象,如果你传递了其他类型的参数,此方法会自行转换为 ```{data: args[0]}```; 请在后端获取 data 在进行处理。
201
+ * - capacitor 的返回也必须是一个对象,此方法会主动将有且只有一个参数的返回值拆出来,不用特别在意获取。
202
+ * - 返回值如有大多为 Promise(在 electron 中一定是),请使用 async/await 调用。
203
+ *
204
+ * ---
205
+ *
206
+ * @param type capacitor:插件名
207
+ * @param name 方法名称
208
+ * @param needBack electron:是否需要返回值
209
+ * @param args 参数列表
210
+ * @returns 返回值
211
+ */
212
+ async call(type: string | undefined, name: string, needBack: boolean, ...args: any[]) {
213
+ if (this.function) {
214
+ // 处理名称
215
+ if (this.type == 'tauri') {
216
+ name = name.replaceAll(':', '_').replace(/([A-Z])/g, '_$1').toLowerCase()
217
+ }
218
+ if (this.type == 'capacitor' && name.includes(':')) {
219
+ name = name.split(':')[1]
220
+ }
221
+ // 调用对应方法
222
+ try {
223
+ if ('electron' == this.type && 'invoke' in this.function && 'send' in this.function) {
224
+ if (needBack) {
225
+ return await this.function.invoke(name, ...args)
226
+ } else {
227
+ this.function.send(name, ...args)
228
+ return undefined
229
+ }
230
+ } else if ('tauri' == this.type && 'invoke' in this.function) {
231
+ // tauri 这边必须传入一个字典
232
+ if (args.length == 0 || Object.prototype.toString.call(args[0]) !== '[object Object]') {
233
+ args = [{ data: args[0] }]
234
+ }
235
+ return await this.function.invoke(name, args[0])
236
+ } else if ('capacitor' == this.type && 'plugins' in this.function && 'capacitor' in this.function) {
237
+ // capacitor 这边必须传入一个字典
238
+ if (args.length == 0 || Object.prototype.toString.call(args[0]) !== '[object Object]') {
239
+ args = [{ data: args[0] }]
240
+ }
241
+ let functionGet = this.function.capacitor[name]
242
+ if (type != undefined && functionGet == undefined) {
243
+ functionGet = this.function.plugins[type][name] ?? this.function.capacitor[type][name]
244
+ }
245
+ const back = await functionGet(args[0])
246
+ if (Object.prototype.toString.call(back) === '[object Object]' && Object.keys(back).length == 1) {
247
+ return back[Object.keys(back)[0]]
248
+ } else {
249
+ return back
250
+ }
251
+ }
252
+ } catch (ex) {
253
+ logger.add(LogType.DEBUG, `调用后端方法 ${(type ?? '') + ' - '}${name} 失败`, ex)
254
+ return undefined
255
+ }
256
+ }
257
+ },
258
+
259
+ /**
260
+ * 调用后端方法(同步)
261
+ *
262
+ * #### 注意:此方法目前只支持 electron 平台
263
+ *
264
+ * @param name 方法名称
265
+ */
266
+ callSync(name: string, ...args: any[]) {
267
+ if (this.type == 'electron' && this.function && 'sendSync' in this.function) {
268
+ return this.function.sendSync(name, ...args)
269
+ } else {
270
+ logger.add(LogType.ERR, '调用后端方法失败', new Error('此方法只支持 electron 平台'))
271
+ return undefined
272
+ }
273
+ },
274
+
275
+ /**
276
+ * 添加后端监听,名称统一为 sys: 前缀
277
+ * @param type capacitor:插件类型
278
+ * @param name 事件名称
279
+ * @param callBack 回调函数
280
+ */
281
+ addListener(type: string | undefined, name: string, callBack: (...args: any[]) => void) {
282
+ if(this.listener) {
283
+ if(this.isDesktop()) {
284
+ this.listener(name, callBack)
285
+ return
286
+ } else if(this.isMobile() && type) {
287
+ this.listener(type, name, callBack)
288
+ return
289
+ }
290
+ } else if (this.isWeb()) {
291
+ // Web 模式没有原生事件桥,忽略监听注册
292
+ return
293
+ }
294
+ logger.error(null, `添加后端监听失败:${name}(${type})`)
295
+ },
296
+
297
+ /**
298
+ * 移除后端监听
299
+ * @param type capacitor:插件类型
300
+ * @param name 事件名称
301
+ * @param callBack 要移除的回调函数
302
+ */
303
+ removeListener(_type: string | undefined, name: string, callBack: (...args: any[]) => void) {
304
+ if(this.isDesktop() && this.function && 'removeListener' in this.function) {
305
+ this.function.removeListener(name, callBack)
306
+ return
307
+ }
308
+ // Capacitor 和 Web 不支持移除监听
309
+ },
310
+ }
@@ -0,0 +1,14 @@
1
+ import { defineStore } from 'pinia'
2
+ import { shallowReactive, ref } from 'vue'
3
+
4
+ export const useAuthStore = defineStore('auth', () => {
5
+ const loginInfo = shallowReactive<Record<string, any>>({})
6
+ const botInfo = shallowReactive<Record<string, any>>({})
7
+ const jsonMap = ref<any>(undefined)
8
+
9
+ return {
10
+ loginInfo,
11
+ botInfo,
12
+ jsonMap,
13
+ }
14
+ })
@@ -0,0 +1,36 @@
1
+ import { ChatInfoElem, MergeStackData } from '../function/elements/information'
2
+ import { defineStore } from 'pinia'
3
+ import { reactive, ref } from 'vue'
4
+
5
+ export const useChatStore = defineStore('chat', () => {
6
+ const chatInfo = ref<ChatInfoElem>({
7
+ show: { type: '', id: 0, name: '', avatar: '' },
8
+ info: {
9
+ group_info: {},
10
+ user_info: {},
11
+ me_info: {},
12
+ group_members: [],
13
+ group_files: {},
14
+ group_sub_files: {},
15
+ jin_info: {
16
+ list: [],
17
+ pages: 0,
18
+ },
19
+ },
20
+ })
21
+
22
+ const messageList = ref<any[]>([])
23
+ const mergeMsgStack = ref<MergeStackData[]>([])
24
+ const mergeMessageList = ref<any[] | undefined>(undefined)
25
+ const mergeMessageImgList = ref<any[] | undefined>(undefined)
26
+ const sessionMessageCache = reactive(new Map<string, any[]>())
27
+
28
+ return {
29
+ chatInfo,
30
+ messageList,
31
+ mergeMsgStack,
32
+ mergeMessageList,
33
+ mergeMessageImgList,
34
+ sessionMessageCache,
35
+ }
36
+ })
@@ -0,0 +1,20 @@
1
+ import { defineStore } from 'pinia'
2
+ import { ref } from 'vue'
3
+
4
+ export const useConnectionStore = defineStore('connection', () => {
5
+ const heartbeatTime = ref<number>(-1)
6
+ const oldHeartbeatTime = ref<number>(-1)
7
+ const lastHeartbeatTime = ref<number>(-1)
8
+ const backTimes = ref(0)
9
+ const metaEventWatchTimer = ref<ReturnType<typeof setTimeout> | undefined>(undefined)
10
+ const metaEventTimeoutTriggered = ref(false)
11
+
12
+ return {
13
+ heartbeatTime,
14
+ oldHeartbeatTime,
15
+ lastHeartbeatTime,
16
+ backTimes,
17
+ metaEventWatchTimer,
18
+ metaEventTimeoutTriggered,
19
+ }
20
+ })
@@ -0,0 +1,37 @@
1
+ import { UserFriendElem, UserGroupElem } from '../function/elements/information'
2
+ import { defineStore } from 'pinia'
3
+ import { shallowRef, reactive, ref } from 'vue'
4
+
5
+ export interface BotContactState {
6
+ userList: (UserFriendElem & UserGroupElem)[]
7
+ baseList: Array<[number | string, UserFriendElem & UserGroupElem]>
8
+ onMsgList: any[]
9
+ }
10
+
11
+ export const useContactStore = defineStore('contact', () => {
12
+ const userList = shallowRef<(UserFriendElem & UserGroupElem)[]>([])
13
+ const showList = shallowRef<(UserFriendElem & UserGroupElem)[]>([])
14
+ const groupAssistList = shallowRef<(UserFriendElem & UserGroupElem)[]>([])
15
+ const baseOnMsgList = reactive(new Map<number | string, UserFriendElem & UserGroupElem>())
16
+ const onMsgList = shallowRef<(UserFriendElem & UserGroupElem)[]>([])
17
+ const newMsgCount = ref(0)
18
+ const systemNoticesList = shallowRef<Record<string, any> | undefined>(undefined)
19
+ const friendLoading = ref(false)
20
+ const friendLoadedCount = ref(0)
21
+ const friendTotalCount = ref(0)
22
+ const botStates = reactive(new Map<string, BotContactState>())
23
+
24
+ return {
25
+ userList,
26
+ showList,
27
+ groupAssistList,
28
+ baseOnMsgList,
29
+ onMsgList,
30
+ newMsgCount,
31
+ systemNoticesList,
32
+ friendLoading,
33
+ friendLoadedCount,
34
+ friendTotalCount,
35
+ botStates,
36
+ }
37
+ })
@@ -0,0 +1,18 @@
1
+ import { defineStore } from 'pinia'
2
+ import { ref, shallowReactive } from 'vue'
3
+
4
+ export const useQzoneStore = defineStore('qzone', () => {
5
+ const qzoneFeedList = ref<any[]>([])
6
+ const state = shallowReactive({
7
+ currentView: 'feed' as 'feed' | 'my',
8
+ myPagePos: 0,
9
+ myPageSize: 10,
10
+ myHasMore: true,
11
+ myLoading: false,
12
+ })
13
+
14
+ return {
15
+ qzoneFeedList,
16
+ state
17
+ }
18
+ })
@@ -0,0 +1,25 @@
1
+ import { Session } from '../function/elements/information'
2
+ import { defineStore } from 'pinia'
3
+ import { shallowRef } from 'vue'
4
+
5
+ const MAX_LENGTH = 50
6
+
7
+ export const useSessionHistoryStore = defineStore('session-history', () => {
8
+ const record = shallowRef<Session[]>([])
9
+
10
+ function add(session: Session) {
11
+ record.value = [
12
+ session,
13
+ ...record.value.filter((i) => (i.user_id !== session.user_id) || (i.group_id !== session.group_id)),
14
+ ]
15
+ if (record.value.length > MAX_LENGTH) {
16
+ record.value.pop()
17
+ record.value = [...record.value]
18
+ }
19
+ }
20
+
21
+ return {
22
+ record,
23
+ add,
24
+ }
25
+ })
@@ -0,0 +1,18 @@
1
+ import { defineStore } from 'pinia'
2
+ import { shallowReactive, ref, shallowRef } from 'vue'
3
+
4
+ export const useSettingsStore = defineStore('settings', () => {
5
+ const sysConfig = shallowReactive<Record<string, any>>({})
6
+ const darkMode = ref(false)
7
+ const connectSsl = ref(false)
8
+ const firstLoad = ref(false)
9
+ const classes = shallowRef<any[]>([])
10
+
11
+ return {
12
+ sysConfig,
13
+ darkMode,
14
+ connectSsl,
15
+ firstLoad,
16
+ classes,
17
+ }
18
+ })
@@ -0,0 +1,10 @@
1
+ import { defineStore } from 'pinia'
2
+ import { ref } from 'vue'
3
+
4
+ export const useStickerStore = defineStore('sticker', () => {
5
+ const stickerCache = ref<any[] | undefined>([])
6
+
7
+ return {
8
+ stickerCache,
9
+ }
10
+ })
@@ -0,0 +1,56 @@
1
+ import { BotMsgType } from '../function/elements/information'
2
+ import { getInch } from '../function/utils/systemUtil'
3
+ import { defineStore } from 'pinia'
4
+ import { ref, markRaw, defineAsyncComponent } from 'vue'
5
+
6
+ export const useUIStore = defineStore('ui', () => {
7
+ const openSideBar = ref(true)
8
+ const nowGetHistory = ref(false)
9
+ const canLoadHistory = ref(true)
10
+ const loadHistoryFail = ref(false)
11
+ const historyBeforeTime = ref<number | undefined>(undefined)
12
+ const msgType = ref(BotMsgType.Array)
13
+
14
+ const popBoxList = ref<{
15
+ svg?: string
16
+ title?: string
17
+ html?: string
18
+ template?: any
19
+ templateValue?: any
20
+ data?: any
21
+ full?: boolean
22
+ onClose?: () => void
23
+ button?: {
24
+ master?: boolean
25
+ fun?: (value: any) => void
26
+ text: string
27
+ }[]
28
+ allowQuickClose?: boolean
29
+ allowClose?: boolean
30
+ }[]>([])
31
+
32
+ const pageView = {
33
+ chatView: markRaw(
34
+ defineAsyncComponent(() => import('../pages/Chat.vue')),
35
+ ),
36
+ msgView: markRaw(
37
+ defineAsyncComponent(
38
+ () => import('../components/MsgBody.vue'),
39
+ ),
40
+ ),
41
+ }
42
+
43
+ const inch = getInch()
44
+
45
+ return {
46
+ openSideBar,
47
+ nowGetHistory,
48
+ canLoadHistory,
49
+ loadHistoryFail,
50
+ historyBeforeTime,
51
+ msgType,
52
+ popBoxList,
53
+ pageView,
54
+ inch,
55
+ }
56
+ })
@@ -0,0 +1,27 @@
1
+ {
2
+ "compilerOptions": {
3
+ "target": "ES2022",
4
+ "module": "ESNext",
5
+ "moduleResolution": "Bundler",
6
+ "lib": [
7
+ "ES2023",
8
+ "DOM",
9
+ "DOM.Iterable"
10
+ ],
11
+ "strict": false,
12
+ "jsx": "preserve",
13
+ "skipLibCheck": true,
14
+ "esModuleInterop": true,
15
+ "allowSyntheticDefaultImports": true,
16
+ "resolveJsonModule": true,
17
+ "baseUrl": ".",
18
+ "types": [
19
+ "vite/client"
20
+ ]
21
+ },
22
+ "include": [
23
+ "src/**/*.ts",
24
+ "src/**/*.vue",
25
+ "env.d.ts"
26
+ ]
27
+ }
@@ -0,0 +1 @@
1
+ {"root":["./src/main.ts","./src/function/base.ts","./src/function/connect.ts","./src/function/favicon.ts","./src/function/input.ts","./src/function/msg.ts","./src/function/notify.ts","./src/function/option.ts","./src/function/satori-model.ts","./src/function/satori.ts","./src/function/sender.ts","./src/function/tooltip.ts","./src/function/elements/information.ts","./src/function/elements/system.ts","./src/function/elements/vuecomp.ts","./src/function/model/emoji.ts","./src/function/model/img.ts","./src/function/model/msg-body.ts","./src/function/utils/apputil.ts","./src/function/utils/avatarutil.ts","./src/function/utils/backgroundutil.ts","./src/function/utils/linkviewutil.ts","./src/function/utils/localhistoryutil.ts","./src/function/utils/msgutil.ts","./src/function/utils/pinyin.ts","./src/function/utils/recordutil.ts","./src/function/utils/sessionutil.ts","./src/function/utils/systemutil.ts","./src/runtime/backend.ts","./src/state/auth.ts","./src/state/chat.ts","./src/state/connection.ts","./src/state/contact.ts","./src/state/qzone.ts","./src/state/sessionhistory.ts","./src/state/settings.ts","./src/state/sticker.ts","./src/state/ui.ts","./env.d.ts"],"errors":true,"version":"5.9.3"}
@@ -0,0 +1,33 @@
1
+ import { fileURLToPath } from 'node:url'
2
+ import { resolve } from 'node:path'
3
+ import vue from '@vitejs/plugin-vue'
4
+ import ViteYaml from '@modyfi/vite-plugin-yaml'
5
+ import { defineConfig } from 'vite'
6
+
7
+ const webRoot = fileURLToPath(new URL('.', import.meta.url))
8
+
9
+ export default defineConfig({
10
+ root: webRoot,
11
+ base: './',
12
+ plugins: [vue(), ViteYaml()],
13
+ server: {
14
+ port: 5174,
15
+ strictPort: true,
16
+ proxy: {
17
+ '/satori': {
18
+ target: 'http://127.0.0.1:5140',
19
+ changeOrigin: true,
20
+ ws: true,
21
+ },
22
+ '/chat-patch': {
23
+ target: 'http://127.0.0.1:5140',
24
+ changeOrigin: true,
25
+ },
26
+ },
27
+ },
28
+ build: {
29
+ outDir: resolve(webRoot, 'dist'),
30
+ emptyOutDir: true,
31
+ chunkSizeWarningLimit: 1500,
32
+ },
33
+ })