koishi-plugin-chat-patch 3.0.2 → 5.0.0
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.
- package/client/vue/index.vue +60 -634
- package/client/web/env.d.ts +56 -0
- package/client/web/index.html +21 -0
- package/client/web/package-lock.json +3419 -0
- package/client/web/package.json +62 -0
- package/client/web/public/bcui/css/color-dark.css +35 -0
- package/client/web/public/bcui/css/color-light.css +35 -0
- package/client/web/public/bcui/css/style.css +468 -0
- package/client/web/public/bcui/js/main.js +193 -0
- package/client/web/public/css/append-dark.css +13 -0
- package/client/web/public/css/append-light.css +13 -0
- package/client/web/public/css/append-napcat-dark.css +14 -0
- package/client/web/public/css/append-napcat-light.css +14 -0
- package/client/web/public/favicon.ico +0 -0
- package/client/web/public/img/icons/icon-for-fuck-apple.png +0 -0
- package/client/web/public/img/icons/icon-maskable.png +0 -0
- package/client/web/public/img/icons/icon.png +0 -0
- package/client/web/public/img/icons/icon.svg +10 -0
- package/client/web/public/robots.txt +2 -0
- package/client/web/public/sw.js +58 -0
- package/client/web/scripts/copy-bcui.mjs +17 -0
- package/client/web/src/App.vue +1127 -0
- package/client/web/src/assets/css/append/append_darwin.css +68 -0
- package/client/web/src/assets/css/append/append_full_vibrancy.css +290 -0
- package/client/web/src/assets/css/append/append_linux.css +125 -0
- package/client/web/src/assets/css/append/append_linux_vibrancy.css +22 -0
- package/client/web/src/assets/css/append/append_napcat.css +35 -0
- package/client/web/src/assets/css/append/append_new.css +843 -0
- package/client/web/src/assets/css/append/append_vibrancy.css +113 -0
- package/client/web/src/assets/css/append/append_win32.css +109 -0
- package/client/web/src/assets/css/append/mobile/append_mobile_horizontal.css +349 -0
- package/client/web/src/assets/css/append/mobile/append_mobile_vertical.css +96 -0
- package/client/web/src/assets/css/chat.css +2104 -0
- package/client/web/src/assets/css/msg.css +941 -0
- package/client/web/src/assets/css/options.css +811 -0
- package/client/web/src/assets/css/sys_notice.css +62 -0
- package/client/web/src/assets/css/view.css +2105 -0
- package/client/web/src/assets/font//346/226/271/346/255/243/345/226/265/345/221/234/344/275/223.ttf +0 -0
- package/client/web/src/assets/img/Vue.png +0 -0
- package/client/web/src/assets/img/cakes.svg +189 -0
- package/client/web/src/assets/img/icons/AppIcon.png +0 -0
- package/client/web/src/assets/img/icons/AppIconDark.png +0 -0
- package/client/web/src/assets/img/icons/CapacitorAppIcon.png +0 -0
- package/client/web/src/assets/img/icons/CapacitorAppIconDark.png +0 -0
- package/client/web/src/assets/img/icons/NapcatAppIcon.png +0 -0
- package/client/web/src/assets/img/icons/NapcatAppIconDark.png +0 -0
- package/client/web/src/assets/img/icons/exit.png +0 -0
- package/client/web/src/assets/img/icons/pen.png +0 -0
- package/client/web/src/assets/img/stars.svg +89 -0
- package/client/web/src/assets/img//346/234/237/345/276/205.png +0 -0
- package/client/web/src/assets/l10n/_About I10n.md +35 -0
- package/client/web/src/assets/l10n/_l10nconfig.json +7 -0
- package/client/web/src/assets/l10n/zh-CN.po +1941 -0
- package/client/web/src/assets/logo.png +0 -0
- package/client/web/src/assets/pathMap/LLOneBot.yaml +2 -0
- package/client/web/src/assets/pathMap/Lagrange.OneBot.yaml +180 -0
- package/client/web/src/assets/pathMap/NapCat.Onebot.yaml +224 -0
- package/client/web/src/assets/pathMap/SnowLuma.yaml +80 -0
- package/client/web/src/assets/qed.txt +1 -0
- package/client/web/src/components/AboutPan.vue +197 -0
- package/client/web/src/components/BulletinBody.vue +129 -0
- package/client/web/src/components/DepPan.vue +310 -0
- package/client/web/src/components/EmojiFace.vue +32 -0
- package/client/web/src/components/FacePan.vue +461 -0
- package/client/web/src/components/FileBody.vue +129 -0
- package/client/web/src/components/FileManager.vue +532 -0
- package/client/web/src/components/FriendBody.vue +54 -0
- package/client/web/src/components/GlobalSessionSearchBar.vue +301 -0
- package/client/web/src/components/History.vue +49 -0
- package/client/web/src/components/LazyLottie.vue +82 -0
- package/client/web/src/components/MergePan.vue +127 -0
- package/client/web/src/components/MsgBody.vue +1478 -0
- package/client/web/src/components/MusicPlayer.vue +549 -0
- package/client/web/src/components/NoticeBody.vue +168 -0
- package/client/web/src/components/QzonePermissionPan.vue +150 -0
- package/client/web/src/components/RawMsgRenderPreviewPan.vue +190 -0
- package/client/web/src/components/ThemeColorPickerPan.vue +420 -0
- package/client/web/src/components/TinySessionBody.vue +51 -0
- package/client/web/src/components/UmamiInfoPan.vue +1549 -0
- package/client/web/src/components/UpdatePan.vue +263 -0
- package/client/web/src/components/ViewerCom.vue +1360 -0
- package/client/web/src/components/VoiceMsg.vue +626 -0
- package/client/web/src/components/WelPan.vue +894 -0
- package/client/web/src/components/msg-body/.gitkeep +0 -0
- package/client/web/src/components/msg-component/JsonSegComp.vue +138 -0
- package/client/web/src/components/msg-component/XmlSegComp.vue +132 -0
- package/client/web/src/components/msg-component/jsonComp/AutoReply.vue +97 -0
- package/client/web/src/components/msg-component/jsonComp/Contact.lua.vue +129 -0
- package/client/web/src/components/msg-component/jsonComp/Feed.lua.vue +94 -0
- package/client/web/src/components/msg-component/jsonComp/Forum.vue +84 -0
- package/client/web/src/components/msg-component/jsonComp/Mannounce.vue +111 -0
- package/client/web/src/components/msg-component/jsonComp/Map.vue +52 -0
- package/client/web/src/components/msg-component/jsonComp/Miniapp.lua.vue +53 -0
- package/client/web/src/components/msg-component/jsonComp/Miniapp.vue +69 -0
- package/client/web/src/components/msg-component/jsonComp/Music.lua.vue +135 -0
- package/client/web/src/components/msg-component/jsonComp/Tuwen.lua.vue +56 -0
- package/client/web/src/components/notice-component/.gitkeep +0 -0
- package/client/web/src/components/notice-component/MealHungryPan.vue +119 -0
- package/client/web/src/components/tooltip/CustomFaceTooltip.vue +22 -0
- package/client/web/src/components/tooltip/Tooltip.vue +50 -0
- package/client/web/src/components/tooltip/Tooltips.vue +14 -0
- package/client/web/src/components/tooltip/UserInfoTooltip.vue +69 -0
- package/client/web/src/function/base.ts +238 -0
- package/client/web/src/function/connect.ts +2042 -0
- package/client/web/src/function/debug.ts +10 -0
- package/client/web/src/function/elements/information.ts +141 -0
- package/client/web/src/function/elements/system.ts +101 -0
- package/client/web/src/function/elements/vueComp.ts +62 -0
- package/client/web/src/function/favicon.ts +76 -0
- package/client/web/src/function/input.ts +69 -0
- package/client/web/src/function/model/emoji.ts +127 -0
- package/client/web/src/function/model/img.ts +150 -0
- package/client/web/src/function/model/msg-body.ts +51 -0
- package/client/web/src/function/msg.ts +2674 -0
- package/client/web/src/function/notify.ts +225 -0
- package/client/web/src/function/option.ts +749 -0
- package/client/web/src/function/satori-model.ts +818 -0
- package/client/web/src/function/satori.ts +325 -0
- package/client/web/src/function/sender.ts +178 -0
- package/client/web/src/function/tooltip.ts +49 -0
- package/client/web/src/function/utils/appUtil.ts +2288 -0
- package/client/web/src/function/utils/avatarUtil.ts +31 -0
- package/client/web/src/function/utils/backgroundUtil.ts +110 -0
- package/client/web/src/function/utils/linkViewUtil.ts +101 -0
- package/client/web/src/function/utils/localHistoryUtil.ts +517 -0
- package/client/web/src/function/utils/msgUtil.ts +1242 -0
- package/client/web/src/function/utils/pinyin.ts +141 -0
- package/client/web/src/function/utils/recordUtil.ts +187 -0
- package/client/web/src/function/utils/sessionUtil.ts +114 -0
- package/client/web/src/function/utils/systemUtil.ts +664 -0
- package/client/web/src/main.ts +91 -0
- package/client/web/src/pages/Chat.vue +3453 -0
- package/client/web/src/pages/Friends.vue +636 -0
- package/client/web/src/pages/Info.vue +717 -0
- package/client/web/src/pages/Messages.vue +875 -0
- package/client/web/src/pages/Options.vue +82 -0
- package/client/web/src/pages/Qzone.vue +1178 -0
- package/client/web/src/pages/chat-view/ChatDanmaku.vue +759 -0
- package/client/web/src/pages/chat-view/ChatGlagame.vue +642 -0
- package/client/web/src/pages/chat-view/ChatTerminal.vue +1044 -0
- package/client/web/src/pages/chat-view/SystemNotice.vue +171 -0
- package/client/web/src/pages/options/OptAccount.vue +107 -0
- package/client/web/src/pages/options/OptAddon.vue +185 -0
- package/client/web/src/pages/options/OptDev.vue +704 -0
- package/client/web/src/pages/options/OptFunction.vue +403 -0
- package/client/web/src/pages/options/OptInfo.vue +165 -0
- package/client/web/src/pages/options/OptView.vue +846 -0
- package/client/web/src/runtime/backend.ts +310 -0
- package/client/web/src/state/auth.ts +14 -0
- package/client/web/src/state/chat.ts +36 -0
- package/client/web/src/state/connection.ts +20 -0
- package/client/web/src/state/contact.ts +37 -0
- package/client/web/src/state/qzone.ts +18 -0
- package/client/web/src/state/sessionHistory.ts +25 -0
- package/client/web/src/state/settings.ts +18 -0
- package/client/web/src/state/sticker.ts +10 -0
- package/client/web/src/state/ui.ts +56 -0
- package/client/web/tsconfig.json +27 -0
- package/client/web/tsconfig.tsbuildinfo +1 -0
- package/client/web/vite.config.ts +33 -0
- package/dist/index.js +1 -12
- package/dist/style.css +1 -1
- package/lib/index.js +2070 -2077
- package/package.json +15 -2
- package/readme.md +0 -22
- package/src/bootstrap.ts +71 -0
- package/src/cache.ts +319 -0
- package/src/config.ts +23 -35
- package/src/database.ts +650 -0
- package/src/index.ts +27 -59
- package/src/media.ts +302 -0
- package/src/recorder.ts +175 -0
- package/src/self-message.ts +456 -0
- package/src/server.d.ts +26 -0
- package/src/types.ts +108 -48
- package/src/web.ts +712 -0
- package/client/vue/chat-logic.ts +0 -683
- package/client/vue/composables/useChatActions.ts +0 -61
- package/client/vue/composables/useChatData.ts +0 -185
- package/client/vue/composables/useImageCache.ts +0 -281
- package/client/vue/composables/useVideoCache.ts +0 -125
- package/client/vue/types.ts +0 -72
- package/lib/api-handlers.d.ts +0 -25
- package/lib/config.d.ts +0 -14
- package/lib/file-manager.d.ts +0 -124
- package/lib/index.d.ts +0 -17
- package/lib/logger.d.ts +0 -9
- package/lib/message-handler.d.ts +0 -35
- package/lib/types.d.ts +0 -57
- package/lib/utils.d.ts +0 -18
- package/src/api-handlers.ts +0 -646
- package/src/file-manager.ts +0 -1436
- package/src/message-handler.ts +0 -507
- 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,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
|
+
})
|