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.
Files changed (194) hide show
  1. package/client/vue/index.vue +60 -634
  2. package/client/web/env.d.ts +56 -0
  3. package/client/web/index.html +21 -0
  4. package/client/web/package-lock.json +3419 -0
  5. package/client/web/package.json +62 -0
  6. package/client/web/public/bcui/css/color-dark.css +35 -0
  7. package/client/web/public/bcui/css/color-light.css +35 -0
  8. package/client/web/public/bcui/css/style.css +468 -0
  9. package/client/web/public/bcui/js/main.js +193 -0
  10. package/client/web/public/css/append-dark.css +13 -0
  11. package/client/web/public/css/append-light.css +13 -0
  12. package/client/web/public/css/append-napcat-dark.css +14 -0
  13. package/client/web/public/css/append-napcat-light.css +14 -0
  14. package/client/web/public/favicon.ico +0 -0
  15. package/client/web/public/img/icons/icon-for-fuck-apple.png +0 -0
  16. package/client/web/public/img/icons/icon-maskable.png +0 -0
  17. package/client/web/public/img/icons/icon.png +0 -0
  18. package/client/web/public/img/icons/icon.svg +10 -0
  19. package/client/web/public/robots.txt +2 -0
  20. package/client/web/public/sw.js +58 -0
  21. package/client/web/scripts/copy-bcui.mjs +17 -0
  22. package/client/web/src/App.vue +1127 -0
  23. package/client/web/src/assets/css/append/append_darwin.css +68 -0
  24. package/client/web/src/assets/css/append/append_full_vibrancy.css +290 -0
  25. package/client/web/src/assets/css/append/append_linux.css +125 -0
  26. package/client/web/src/assets/css/append/append_linux_vibrancy.css +22 -0
  27. package/client/web/src/assets/css/append/append_napcat.css +35 -0
  28. package/client/web/src/assets/css/append/append_new.css +843 -0
  29. package/client/web/src/assets/css/append/append_vibrancy.css +113 -0
  30. package/client/web/src/assets/css/append/append_win32.css +109 -0
  31. package/client/web/src/assets/css/append/mobile/append_mobile_horizontal.css +349 -0
  32. package/client/web/src/assets/css/append/mobile/append_mobile_vertical.css +96 -0
  33. package/client/web/src/assets/css/chat.css +2104 -0
  34. package/client/web/src/assets/css/msg.css +941 -0
  35. package/client/web/src/assets/css/options.css +811 -0
  36. package/client/web/src/assets/css/sys_notice.css +62 -0
  37. package/client/web/src/assets/css/view.css +2105 -0
  38. package/client/web/src/assets/font//346/226/271/346/255/243/345/226/265/345/221/234/344/275/223.ttf +0 -0
  39. package/client/web/src/assets/img/Vue.png +0 -0
  40. package/client/web/src/assets/img/cakes.svg +189 -0
  41. package/client/web/src/assets/img/icons/AppIcon.png +0 -0
  42. package/client/web/src/assets/img/icons/AppIconDark.png +0 -0
  43. package/client/web/src/assets/img/icons/CapacitorAppIcon.png +0 -0
  44. package/client/web/src/assets/img/icons/CapacitorAppIconDark.png +0 -0
  45. package/client/web/src/assets/img/icons/NapcatAppIcon.png +0 -0
  46. package/client/web/src/assets/img/icons/NapcatAppIconDark.png +0 -0
  47. package/client/web/src/assets/img/icons/exit.png +0 -0
  48. package/client/web/src/assets/img/icons/pen.png +0 -0
  49. package/client/web/src/assets/img/stars.svg +89 -0
  50. package/client/web/src/assets/img//346/234/237/345/276/205.png +0 -0
  51. package/client/web/src/assets/l10n/_About I10n.md +35 -0
  52. package/client/web/src/assets/l10n/_l10nconfig.json +7 -0
  53. package/client/web/src/assets/l10n/zh-CN.po +1941 -0
  54. package/client/web/src/assets/logo.png +0 -0
  55. package/client/web/src/assets/pathMap/LLOneBot.yaml +2 -0
  56. package/client/web/src/assets/pathMap/Lagrange.OneBot.yaml +180 -0
  57. package/client/web/src/assets/pathMap/NapCat.Onebot.yaml +224 -0
  58. package/client/web/src/assets/pathMap/SnowLuma.yaml +80 -0
  59. package/client/web/src/assets/qed.txt +1 -0
  60. package/client/web/src/components/AboutPan.vue +197 -0
  61. package/client/web/src/components/BulletinBody.vue +129 -0
  62. package/client/web/src/components/DepPan.vue +310 -0
  63. package/client/web/src/components/EmojiFace.vue +32 -0
  64. package/client/web/src/components/FacePan.vue +461 -0
  65. package/client/web/src/components/FileBody.vue +129 -0
  66. package/client/web/src/components/FileManager.vue +532 -0
  67. package/client/web/src/components/FriendBody.vue +54 -0
  68. package/client/web/src/components/GlobalSessionSearchBar.vue +301 -0
  69. package/client/web/src/components/History.vue +49 -0
  70. package/client/web/src/components/LazyLottie.vue +82 -0
  71. package/client/web/src/components/MergePan.vue +127 -0
  72. package/client/web/src/components/MsgBody.vue +1478 -0
  73. package/client/web/src/components/MusicPlayer.vue +549 -0
  74. package/client/web/src/components/NoticeBody.vue +168 -0
  75. package/client/web/src/components/QzonePermissionPan.vue +150 -0
  76. package/client/web/src/components/RawMsgRenderPreviewPan.vue +190 -0
  77. package/client/web/src/components/ThemeColorPickerPan.vue +420 -0
  78. package/client/web/src/components/TinySessionBody.vue +51 -0
  79. package/client/web/src/components/UmamiInfoPan.vue +1549 -0
  80. package/client/web/src/components/UpdatePan.vue +263 -0
  81. package/client/web/src/components/ViewerCom.vue +1360 -0
  82. package/client/web/src/components/VoiceMsg.vue +626 -0
  83. package/client/web/src/components/WelPan.vue +894 -0
  84. package/client/web/src/components/msg-body/.gitkeep +0 -0
  85. package/client/web/src/components/msg-component/JsonSegComp.vue +138 -0
  86. package/client/web/src/components/msg-component/XmlSegComp.vue +132 -0
  87. package/client/web/src/components/msg-component/jsonComp/AutoReply.vue +97 -0
  88. package/client/web/src/components/msg-component/jsonComp/Contact.lua.vue +129 -0
  89. package/client/web/src/components/msg-component/jsonComp/Feed.lua.vue +94 -0
  90. package/client/web/src/components/msg-component/jsonComp/Forum.vue +84 -0
  91. package/client/web/src/components/msg-component/jsonComp/Mannounce.vue +111 -0
  92. package/client/web/src/components/msg-component/jsonComp/Map.vue +52 -0
  93. package/client/web/src/components/msg-component/jsonComp/Miniapp.lua.vue +53 -0
  94. package/client/web/src/components/msg-component/jsonComp/Miniapp.vue +69 -0
  95. package/client/web/src/components/msg-component/jsonComp/Music.lua.vue +135 -0
  96. package/client/web/src/components/msg-component/jsonComp/Tuwen.lua.vue +56 -0
  97. package/client/web/src/components/notice-component/.gitkeep +0 -0
  98. package/client/web/src/components/notice-component/MealHungryPan.vue +119 -0
  99. package/client/web/src/components/tooltip/CustomFaceTooltip.vue +22 -0
  100. package/client/web/src/components/tooltip/Tooltip.vue +50 -0
  101. package/client/web/src/components/tooltip/Tooltips.vue +14 -0
  102. package/client/web/src/components/tooltip/UserInfoTooltip.vue +69 -0
  103. package/client/web/src/function/base.ts +238 -0
  104. package/client/web/src/function/connect.ts +2042 -0
  105. package/client/web/src/function/debug.ts +10 -0
  106. package/client/web/src/function/elements/information.ts +141 -0
  107. package/client/web/src/function/elements/system.ts +101 -0
  108. package/client/web/src/function/elements/vueComp.ts +62 -0
  109. package/client/web/src/function/favicon.ts +76 -0
  110. package/client/web/src/function/input.ts +69 -0
  111. package/client/web/src/function/model/emoji.ts +127 -0
  112. package/client/web/src/function/model/img.ts +150 -0
  113. package/client/web/src/function/model/msg-body.ts +51 -0
  114. package/client/web/src/function/msg.ts +2674 -0
  115. package/client/web/src/function/notify.ts +225 -0
  116. package/client/web/src/function/option.ts +749 -0
  117. package/client/web/src/function/satori-model.ts +818 -0
  118. package/client/web/src/function/satori.ts +325 -0
  119. package/client/web/src/function/sender.ts +178 -0
  120. package/client/web/src/function/tooltip.ts +49 -0
  121. package/client/web/src/function/utils/appUtil.ts +2288 -0
  122. package/client/web/src/function/utils/avatarUtil.ts +31 -0
  123. package/client/web/src/function/utils/backgroundUtil.ts +110 -0
  124. package/client/web/src/function/utils/linkViewUtil.ts +101 -0
  125. package/client/web/src/function/utils/localHistoryUtil.ts +517 -0
  126. package/client/web/src/function/utils/msgUtil.ts +1242 -0
  127. package/client/web/src/function/utils/pinyin.ts +141 -0
  128. package/client/web/src/function/utils/recordUtil.ts +187 -0
  129. package/client/web/src/function/utils/sessionUtil.ts +114 -0
  130. package/client/web/src/function/utils/systemUtil.ts +664 -0
  131. package/client/web/src/main.ts +91 -0
  132. package/client/web/src/pages/Chat.vue +3453 -0
  133. package/client/web/src/pages/Friends.vue +636 -0
  134. package/client/web/src/pages/Info.vue +717 -0
  135. package/client/web/src/pages/Messages.vue +875 -0
  136. package/client/web/src/pages/Options.vue +82 -0
  137. package/client/web/src/pages/Qzone.vue +1178 -0
  138. package/client/web/src/pages/chat-view/ChatDanmaku.vue +759 -0
  139. package/client/web/src/pages/chat-view/ChatGlagame.vue +642 -0
  140. package/client/web/src/pages/chat-view/ChatTerminal.vue +1044 -0
  141. package/client/web/src/pages/chat-view/SystemNotice.vue +171 -0
  142. package/client/web/src/pages/options/OptAccount.vue +107 -0
  143. package/client/web/src/pages/options/OptAddon.vue +185 -0
  144. package/client/web/src/pages/options/OptDev.vue +704 -0
  145. package/client/web/src/pages/options/OptFunction.vue +403 -0
  146. package/client/web/src/pages/options/OptInfo.vue +165 -0
  147. package/client/web/src/pages/options/OptView.vue +846 -0
  148. package/client/web/src/runtime/backend.ts +310 -0
  149. package/client/web/src/state/auth.ts +14 -0
  150. package/client/web/src/state/chat.ts +36 -0
  151. package/client/web/src/state/connection.ts +20 -0
  152. package/client/web/src/state/contact.ts +37 -0
  153. package/client/web/src/state/qzone.ts +18 -0
  154. package/client/web/src/state/sessionHistory.ts +25 -0
  155. package/client/web/src/state/settings.ts +18 -0
  156. package/client/web/src/state/sticker.ts +10 -0
  157. package/client/web/src/state/ui.ts +56 -0
  158. package/client/web/tsconfig.json +27 -0
  159. package/client/web/tsconfig.tsbuildinfo +1 -0
  160. package/client/web/vite.config.ts +33 -0
  161. package/dist/index.js +1 -12
  162. package/dist/style.css +1 -1
  163. package/lib/index.js +2070 -2077
  164. package/package.json +15 -2
  165. package/readme.md +0 -22
  166. package/src/bootstrap.ts +71 -0
  167. package/src/cache.ts +319 -0
  168. package/src/config.ts +23 -35
  169. package/src/database.ts +650 -0
  170. package/src/index.ts +27 -59
  171. package/src/media.ts +302 -0
  172. package/src/recorder.ts +175 -0
  173. package/src/self-message.ts +456 -0
  174. package/src/server.d.ts +26 -0
  175. package/src/types.ts +108 -48
  176. package/src/web.ts +712 -0
  177. package/client/vue/chat-logic.ts +0 -683
  178. package/client/vue/composables/useChatActions.ts +0 -61
  179. package/client/vue/composables/useChatData.ts +0 -185
  180. package/client/vue/composables/useImageCache.ts +0 -281
  181. package/client/vue/composables/useVideoCache.ts +0 -125
  182. package/client/vue/types.ts +0 -72
  183. package/lib/api-handlers.d.ts +0 -25
  184. package/lib/config.d.ts +0 -14
  185. package/lib/file-manager.d.ts +0 -124
  186. package/lib/index.d.ts +0 -17
  187. package/lib/logger.d.ts +0 -9
  188. package/lib/message-handler.d.ts +0 -35
  189. package/lib/types.d.ts +0 -57
  190. package/lib/utils.d.ts +0 -18
  191. package/src/api-handlers.ts +0 -646
  192. package/src/file-manager.ts +0 -1436
  193. package/src/message-handler.ts +0 -507
  194. package/src/utils.ts +0 -189
@@ -0,0 +1,10 @@
1
+ export function isDebugMode(): boolean {
2
+ try {
3
+ const raw = localStorage.getItem('options')
4
+ if (!raw) return false
5
+ const parsed = JSON.parse(raw) as { log_level?: unknown }
6
+ return parsed.log_level === 'debug'
7
+ } catch {
8
+ return false
9
+ }
10
+ }
@@ -0,0 +1,141 @@
1
+ import { PinYinData } from '../utils/pinyin'
2
+
3
+ export enum BotMsgType {
4
+ CQCode,
5
+ Array
6
+ }
7
+
8
+ export interface ChatInfoElem {
9
+ show: BaseChatInfoElem
10
+ info: {
11
+ group_info: { [key: string]: any }
12
+ user_info: { [key: string]: any }
13
+ me_info: { [key: string]: any }
14
+ group_members: GroupMemberInfoElem[]
15
+ group_files: { [key: string]: any }
16
+ group_sub_files: { [key: string]: any }
17
+ group_notices?: { [key: string]: any }
18
+ now_member_info?: { [key: string]: any }
19
+ image_list?: { index: number; message_id: string; img_url: string }[]
20
+ jin_info: {
21
+ list: { [key: string]: any }[]
22
+ is_end?: boolean
23
+ pages: number
24
+ }
25
+ }
26
+ }
27
+
28
+ export interface BaseChatInfoElem {
29
+ type: string
30
+ id: number | string
31
+ name: string
32
+ avatar: string
33
+ appendInfo?: string
34
+ jump?: string
35
+ channel_id?: string
36
+ guild_id?: string
37
+ }
38
+
39
+ export interface UserElem {
40
+ new_msg?: boolean
41
+ raw_msg?: string
42
+ time?: number
43
+ always_top?: boolean
44
+ message_id?: string
45
+ highlight?: string
46
+ }
47
+
48
+ export interface UserFriendElem extends UserElem {
49
+ group_id: number | string
50
+ group_name: string
51
+ avatar?: string
52
+ channel_id?: string
53
+ channelId?: string
54
+ guild_id?: string
55
+ guildId?: string
56
+ py_name?: PinYinData
57
+ py_start?: string
58
+ member_count?: number
59
+ admin_flag?: boolean
60
+ }
61
+
62
+ export interface UserGroupElem extends UserElem {
63
+ user_id: number | string
64
+ nickname: string
65
+ remark: string
66
+ channel_id?: string
67
+ channelId?: string
68
+ guild_id?: string
69
+ guildId?: string
70
+ raw_msg_base?: string // 给群收纳箱用的
71
+ py_name?: PinYinData
72
+ py_start?: string
73
+ class_id?: number
74
+ class_name?: string
75
+ }
76
+
77
+ export interface GroupFileElem {
78
+ file_id: string
79
+ file_name: string
80
+ size: number
81
+ download_times: number
82
+ dead_time: number
83
+ upload_time: number
84
+ uploader_name: string
85
+
86
+ download_percent?: number
87
+ }
88
+
89
+ export interface GroupFileFolderElem {
90
+ folder_id: string
91
+ folder_name: string
92
+ count: number
93
+ create_time: number
94
+ creater_name: string
95
+
96
+ items?: GroupFileElem[]
97
+ show_items?: boolean
98
+ }
99
+
100
+ export interface GroupMemberInfoElem {
101
+ user_id: number | string
102
+ name?: string
103
+ avatar?: string
104
+ title: string
105
+ card: string
106
+ join_time: number
107
+ last_sent_time: number
108
+ level: number
109
+ nickname: string
110
+ rank: string
111
+ role: string
112
+ sex: string
113
+ shutup_time: number
114
+ py_start?: string
115
+ }
116
+
117
+ export interface SQCodeElem {
118
+ addText: boolean
119
+ addTop?: boolean
120
+ msgObj: MsgItemElem
121
+ }
122
+
123
+ export interface MsgItemElem {
124
+ type: string
125
+ [key: string]: any
126
+ }
127
+
128
+ export interface MergeStackData {
129
+ messageList: any[] // 消息列表
130
+ imageList: any[] // 图片列表
131
+ placeCache: number // 位置缓存
132
+ forwardMsg: any // 原合并转发消息
133
+ }
134
+
135
+ export interface MenuEventData {
136
+ x: number
137
+ y: number
138
+ target: HTMLElement
139
+ }
140
+
141
+ export type Session = UserGroupElem & UserFriendElem
@@ -0,0 +1,101 @@
1
+ /**
2
+ * 连接历史记录项
3
+ */
4
+ export interface ConnectionHistoryItem {
5
+ address: string
6
+ token: string
7
+ uin?: string
8
+ nickname?: string
9
+ lastConnected: number
10
+ }
11
+
12
+ /**
13
+ * 登录状态记录(地址、密钥、状态等)
14
+ */
15
+ export interface LoginCacheElem {
16
+ quickLogin: { address: string, port: number }[] | null
17
+ address: string
18
+ token: string
19
+ status: boolean,
20
+ creating: boolean
21
+ connectionHistory: ConnectionHistoryItem[]
22
+ satoriLogins?: {
23
+ platform: string
24
+ selfId: string
25
+ name: string
26
+ avatar?: string
27
+ status?: number
28
+ features?: string[]
29
+ }[]
30
+ selectedSatoriBot?: string
31
+ uin?: string
32
+ nickname?: string
33
+ platform?: string
34
+ }
35
+
36
+ export interface PopInfoElem {
37
+ id: number
38
+ svg: string
39
+ text: string
40
+ autoClose?: boolean
41
+ }
42
+
43
+ export interface BotActionElem {
44
+ action: string
45
+ params?: { [key: string]: any }
46
+ echo?: string
47
+ }
48
+
49
+ export interface MsgIdInfoElem {
50
+ gid?: number
51
+ uid?: number
52
+ seqid?: number
53
+ }
54
+
55
+ export interface ContributorElem {
56
+ url: string
57
+ link: string
58
+ title: string
59
+ contributions: number
60
+ isMe: boolean
61
+ isSuperThakns: boolean
62
+ }
63
+
64
+ export interface NotificationElem {
65
+ body: string
66
+ tag: string
67
+ icon: string
68
+ image?: string
69
+ requireInteraction: boolean
70
+ }
71
+
72
+ export interface NotifyInfo {
73
+ base_type: 'msg' | 'app',
74
+
75
+ title: string
76
+ body: string
77
+ tag: string
78
+ icon: string
79
+ image?: string
80
+ type: string
81
+ is_important: boolean
82
+ }
83
+
84
+ export interface NoticeBodyV3 {
85
+ version: 3
86
+ client: string // 渠道标识,对应 env 里的 VITE_APP_CLIENT_TAG
87
+ id: number
88
+ add_time: number
89
+ show_date: number[][] // 显示日期,二维数组,内层数组为[开始日期, 结束日期],日期格式为时间戳(毫秒)
90
+ pops: {
91
+ title?: string
92
+ html: string
93
+ template: string // 内嵌模板和 html 二选一
94
+ template_data?: { [key: string]: any }
95
+ link_url?: string // 链接地址,如果有这个参数将显示一个打开按钮
96
+ button_text?: string // 关闭按钮文字,默认“确定”
97
+ }[]
98
+ is_important: boolean // 是否重要公告,有这个属性的公告将每次启动都显示
99
+
100
+ is_show?: boolean
101
+ }
@@ -0,0 +1,62 @@
1
+ import { AllowedComponentProps, ExtractPropTypes, VNodeProps, ComponentPropsOptions, Component, VNode } from 'vue'
2
+
3
+ type Empty = Record<string, never>
4
+
5
+ type GetAllProps<T extends Component> = T extends new (...args: any) => { $props: infer P }
6
+ ? P
7
+ : T extends () => VNode
8
+ ? object
9
+ : T extends (props: infer P, ...args: any) => any
10
+ ? P
11
+ : T extends { props: infer P }
12
+ ? (P extends ComponentPropsOptions ? ExtractPropTypes<P> : P)
13
+ : any
14
+
15
+ type GetDefineProps<T extends Component> = GetAllProps<T> extends infer P & VNodeProps & AllowedComponentProps ? P : never
16
+
17
+ type GetModel<T extends Component> = GetDefineProps<T> extends infer P
18
+ ? 'modelValue' extends keyof P ? P['modelValue'] : undefined
19
+ : never
20
+
21
+ type GetEmit<T extends Component> = GetDefineProps<T> extends infer P ? {
22
+ [
23
+ Key in keyof P & string as Key extends `on${infer N}`
24
+ ? N extends 'Update:ModelValue' ? never : Uncapitalize<N>
25
+ : never
26
+ ]: P[Key]
27
+ } : never
28
+
29
+ type GetProps<T extends Component> = GetDefineProps<T> extends infer P ? {
30
+ [
31
+ Key in keyof P & string as Key extends `on${Capitalize<string>}`
32
+ ? never
33
+ : `onUpdate:${Key}` extends keyof P
34
+ ? never
35
+ : Key
36
+ ]: P[Key]
37
+ } : never
38
+
39
+ type GetEmitArgs<T extends Component> = GetEmit<T> extends infer E ? {
40
+ [K in keyof E]?: E[K]
41
+ } : never
42
+
43
+ type SetOptional<O extends Record<string, unknown>, T> = {
44
+ [K in keyof O as T extends O[K] ? K : never]?: O[K]
45
+ } & {
46
+ [K in keyof O as T extends O[K] ? never : K]: O[K]
47
+ }
48
+
49
+ type CreateOptionalKey<K extends string, Content> = Content extends Record<string, unknown>
50
+ ? SetOptional<Content, undefined> extends infer R
51
+ ? Empty extends R
52
+ ? { [P in K]?: R }
53
+ : { [P in K]: R }
54
+ : never
55
+ : Content extends undefined
56
+ ? { [P in K]?: Content }
57
+ : { [P in K]: Content }
58
+
59
+ export type VueCompData<T extends Component> = {
60
+ comp: T
61
+ emit?: GetEmitArgs<T>
62
+ } & CreateOptionalKey<'model', GetModel<T>> & CreateOptionalKey<'props', GetProps<T>>
@@ -0,0 +1,76 @@
1
+ import { useContactStore } from '../state/contact'
2
+ import { useSettingsStore } from '../state/settings'
3
+
4
+ let needRefreshFavicon = false
5
+
6
+ let cacheInfo = ''
7
+
8
+ /**
9
+ * 刷新 favicon
10
+ * @returns
11
+ */
12
+ export function refreshFavicon() {
13
+ if (needRefreshFavicon) return
14
+ needRefreshFavicon = true
15
+ setTimeout(() => {
16
+ needRefreshFavicon = false
17
+ let num = 0
18
+ if (useSettingsStore().sysConfig.use_favicon_notice === false) return main(0)
19
+ const contactStore = useContactStore()
20
+ for (const session of contactStore.onMsgList) {
21
+ if (session.new_msg) num ++
22
+ }
23
+ main(num)
24
+ }, 500)
25
+ }
26
+
27
+ function main(num: number) {
28
+ const width = num.toString().length * 150
29
+ const color1 = getComputedStyle(document.documentElement).getPropertyValue('--color-main').trim()
30
+ const color2 = getComputedStyle(document.documentElement).getPropertyValue('--color-card').trim()
31
+ const color3 = getComputedStyle(document.documentElement).getPropertyValue('--color-card-2').trim()
32
+ // 对比缓存
33
+ if (cacheInfo === `${num}-${color1}-${color2}-${color3}`) return
34
+ // 存储缓存信息
35
+ cacheInfo = `${num}-${color1}-${color2}-${color3}`
36
+ const svg = `
37
+ <svg width="1080" height="1080" viewBox="0 0 1080 1080" fill="none" xmlns="http://www.w3.org/2000/svg">
38
+ <path d="M537 1080C833.577 1080 1074 839.577 1074 543C1074 246.423 833.577 6 537 6C240.423 6 0 246.423 0 543C0 839.577 240.423 1080 537 1080Z" fill="${color1}"/>
39
+ <path d="M540.28 803.2C493.78 803.2 451.18 787.7 423.68 764.4C409.78 768.6 391.88 775.3 380.68 783.6C371.08 790.7 372.28 798 373.98 800.9C381.58 813.8 504.68 809.1 540.28 805.1V803.2ZM540.28 803.2C586.78 803.2 629.38 787.7 656.88 764.4C670.78 768.6 688.68 775.3 699.88 783.6C709.48 790.7 708.28 798 706.58 800.9C698.98 813.8 575.88 809.1 540.28 805.1V803.2Z" fill="${color2}"/>
40
+ <path d="M540.58 524.8C617.28 524.3 678.78 509.4 699.58 503.7C704.58 502.3 707.18 499.9 707.18 499.9C707.18 499.2 707.48 487.4 707.48 481.3C707.48 378.9 659.18 276 540.18 276C421.28 276 372.88 378.9 372.88 481.3C372.88 487.4 373.18 499.2 373.18 499.9C373.18 499.9 375.38 502.2 379.28 503.3C398.48 508.7 461.18 524.2 539.78 524.8H540.58ZM749.08 610.1C744.28 594.8 737.88 576.9 731.28 559.8C731.28 559.8 727.48 559.3 725.58 559.9C666.58 577 595.08 588 540.58 587.3H539.98C485.78 587.9 414.78 577.2 355.98 560.2C353.78 559.6 349.28 559.8 349.28 559.8C342.68 576.9 336.18 594.8 331.48 610.1C308.78 683.1 316.18 713.3 321.78 714C333.78 715.5 368.48 659.1 368.48 659.1C368.48 716.4 420.18 804.4 538.68 805.2H541.78C660.28 804.4 711.98 716.4 711.98 659.1C711.98 659.1 746.68 715.5 758.68 714C764.38 713.3 771.68 683.1 749.08 610.1Z" fill="${color2}"/>
41
+ <path d="M497.98 427.3C481.88 428 468.08 409.7 467.18 386.3C466.28 362.9 478.68 343.4 494.78 342.7C510.88 342 524.68 360.3 525.58 383.7C526.48 407.1 514.08 426.6 497.98 427.3ZM613.38 386.3C612.48 409.7 598.78 428 582.58 427.3C566.48 426.6 554.08 407 554.98 383.7C555.88 360.3 569.58 342 585.78 342.7C601.88 343.4 614.28 362.9 613.38 386.3Z" fill="${color2}"/>
42
+ <path d="M517.78 386.7C518.48 395.9 513.48 404.1 506.48 405C499.48 405.9 493.28 399.1 492.48 389.9C491.78 380.7 496.78 372.5 503.78 371.6C510.78 370.7 517.08 377.4 517.78 386.7ZM562.08 389.7C563.48 387.1 573.18 373.7 593.28 378.6C598.58 379.9 600.98 381.8 601.48 382.5C602.28 383.6 602.48 385.2 601.68 387.3C600.18 391.5 596.98 391.4 595.28 390.5C594.18 390 580.18 380.6 567.28 394.6C566.38 395.6 564.78 395.9 563.28 394.7C561.88 393.6 561.28 391.3 562.08 389.7Z" fill="${color2}"/>
43
+ <path d="M540.58 583.9H539.98C502.88 584.3 457.98 579.4 414.48 570.9C410.78 592.5 408.48 619.6 410.48 651.9C415.38 733.6 463.88 785 538.78 785.7H541.78C616.68 785 665.18 733.6 670.08 651.9C671.98 619.6 669.78 592.5 666.08 570.9C622.58 579.5 577.68 584.4 540.58 583.9Z" fill="${color2}"/>
44
+ <path d="M435.08 577.1V657.5C435.08 657.5 471.88 664.9 508.78 659.8V585.6C485.38 584.3 460.18 581.4 435.08 577.1Z" fill="${color3}"/>
45
+ <path d="M707.28 499.9C707.28 499.9 635.68 522.5 540.58 523.2H539.98C445.08 522.6 373.58 500 373.28 499.9L349.28 559.8C409.28 577.9 483.68 589.6 539.88 588.9H540.48C596.68 589.6 671.08 577.9 731.18 559.8L707.28 499.9Z" fill="${color3}"/>
46
+ ${num > 0 ? `
47
+ <!-- 新消息数量 -->
48
+ <path
49
+ d="M ${640-width} 400 L ${440+width} 400 L ${440+width} 1000 L ${640-width} 1000 Z"
50
+ style="fill: red"
51
+ />
52
+ <circle cx="${640 - width}" cy="700" r="300" style="fill: red" />
53
+ <circle cx="${440 + width}" cy="700" r="300" style="fill: red" />
54
+ <text
55
+ x="540"
56
+ y="925"
57
+ font-size="600"
58
+ text-anchor="middle"
59
+ style="fill: white; font-weight: bold;"
60
+ >
61
+ ${num}
62
+ </text>
63
+ ` : ''}
64
+ </svg>
65
+ `
66
+
67
+ const svgDataUrl = 'data:image/svg+xml;charset=utf8,' + encodeURIComponent(svg)
68
+ let link: HTMLLinkElement | null = document.querySelector('link[rel~="icon"]')
69
+ if (!link) {
70
+ link = document.createElement('link')
71
+ link.rel = 'icon'
72
+ document.head.appendChild(link)
73
+ }
74
+ link.href = svgDataUrl
75
+ link.type = 'image/svg+xml'
76
+ }
@@ -0,0 +1,69 @@
1
+ /**
2
+ * 触控板滚动蒙版
3
+ * 用来连续返回一系列滚动事件处理,自带中断处理
4
+ */
5
+ export function wheelMask(process: (event: WheelEvent) => boolean, removeHook?: ()=>void): Promise<void> {
6
+ // 中断回调
7
+ const mask = document.createElement('div')
8
+ let r!: () => void
9
+ const promise = new Promise<void>((resolve) => {
10
+ r = resolve
11
+ })
12
+ const remove = () => {
13
+ document.body.removeChild(mask)
14
+ removeHook?.()
15
+ r()
16
+ }
17
+ let wheelTimeOut = setTimeout(remove, 100) as unknown as number
18
+ mask.style.position = 'fixed'
19
+ mask.style.top = '0'
20
+ mask.style.left = '0'
21
+ mask.style.width = '100vw'
22
+ mask.style.height = '100vh'
23
+ mask.style.zIndex = '9999'
24
+ mask.style.backgroundColor = 'rgba(0, 0, 0, 0)'
25
+ mask.addEventListener('wheel', (event) => {
26
+ event.preventDefault()
27
+ if (!process(event)) return
28
+ // 中断回调
29
+ clearTimeout(wheelTimeOut)
30
+ wheelTimeOut = setTimeout(remove, 100) as unknown as number
31
+ }, { passive: false })
32
+ document.body.appendChild(mask)
33
+ return promise
34
+ }
35
+
36
+ export function mousemoveMask(process: (event: MouseEvent) => void, removeHook?: (event: MouseEvent)=>void): Promise<void> {
37
+ // 中断回调
38
+ const mask = document.createElement('div')
39
+ let r!: () => void
40
+ const promise = new Promise<void>((resolve) => {
41
+ r = resolve
42
+ })
43
+ const remove = (event: MouseEvent) => {
44
+ document.body.removeChild(mask)
45
+ removeHook?.(event)
46
+ r()
47
+ }
48
+ mask.id = 'mask'
49
+ mask.style.position = 'fixed'
50
+ mask.style.top = '0'
51
+ mask.style.left = '0'
52
+ mask.style.width = '100vw'
53
+ mask.style.height = '100vh'
54
+ mask.style.zIndex = '9999'
55
+ mask.style.backgroundColor = 'rgba(0, 0, 0, 0)'
56
+ const mousemoveFun = (event: MouseEvent) => {
57
+ event.preventDefault()
58
+ process(event)
59
+ }
60
+ const mouseupFun = (event: MouseEvent) => {
61
+ event.preventDefault()
62
+ remove(event)
63
+ }
64
+ mask.addEventListener('mousemove', mousemoveFun, { passive: false })
65
+ mask.addEventListener('mouseleave', mouseupFun, { passive: false })
66
+ mask.addEventListener('mouseup', mouseupFun, { passive: false })
67
+ document.body.appendChild(mask)
68
+ return promise
69
+ }
@@ -0,0 +1,127 @@
1
+ export default class Emoji {
2
+ static readonly apngMap = new Map<number, { super: boolean; suffix: number[] }>()
3
+ static readonly descMap = new Map<string, string>()
4
+ static readonly allList = new Set<number>()
5
+ static readonly allSuperList = new Set<number>()
6
+
7
+ static readonly superList: readonly number[] = [
8
+ 5, 311, 312, 314, 317, 318, 319, 320, 324, 325, 337,
9
+ 338, 339, 341, 342, 343, 344, 345, 346, 181, 74, 75,
10
+ 351, 349, 350, 395, 114, 326, 53, 137, 333, 424, 415,
11
+ 392, 425, 427, 426, 419, 429, 472, 474, 475, 476, 477,
12
+ 478, 479,
13
+ ]
14
+
15
+ static readonly normalList: readonly number[] = [
16
+ 14, 1, 2, 3, 4, 6, 7, 8, 9, 10, 11, 12, 13, 0, 15, 16,
17
+ 96, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30,
18
+ 31, 32, 33, 34, 35, 36, 37, 38, 39, 97, 98, 99, 100,
19
+ 101, 102, 103, 104, 105, 106, 107, 108, 305, 109, 110,
20
+ 111, 172, 182, 179, 173, 174, 212, 175, 178, 177, 176,
21
+ 183, 262, 263, 264, 265, 266, 267, 268, 269, 270, 271,
22
+ 272, 277, 307, 306, 281, 282, 283, 284, 285, 293, 286,
23
+ 287, 289, 294, 297, 298, 299, 300, 323, 332, 336, 353,
24
+ 355, 356, 354, 352, 357, 428, 334, 347, 303, 302, 295,
25
+ 49, 66, 63, 64, 187, 146, 116, 67, 60, 185, 76, 124,
26
+ 118, 78, 119, 79, 120, 121, 77, 123, 201, 273, 46, 112,
27
+ 56, 169, 171, 59, 144, 147, 148, 89, 41, 125, 42, 43, 86, 129,
28
+ 85,
29
+ ]
30
+
31
+ static readonly emojiList: readonly number[] = [
32
+ 128522, 128524, 128538, 128531, 128560, 128541, 128513, 128540,
33
+ 9786, 128525, 128532, 128516, 128527, 128530, 128563, 128536,
34
+ 128557, 128561, 128514, 128170, 128074, 128077, 128079, 128078,
35
+ 128591, 128076, 128070, 128064, 127836, 127847, 127838, 127866,
36
+ 127867, 9749, 127822, 127827, 127817, 128684, 127801, 127881,
37
+ 128157, 128163, 10024, 128168, 128166, 128293, 128164, 128169,
38
+ 128137, 128235, 128014, 128103, 128102, 128053, 128055, 128046,
39
+ 128020, 128056, 128123, 128027, 128054, 128051, 128098, 9728,
40
+ 10068, 128299, 128147, 127978,
41
+ ]
42
+
43
+ static readonly responseApngId: readonly number[] = [
44
+ 5, 314, 318, 319, 320, 324, 337, 338, 339, 341, 342, 343, 344,
45
+ 345, 346, 181, 74, 75, 351, 349, 350, 395, 326, 53, 333, 424,
46
+ 425, 427, 426, 14, 4, 8, 9, 10, 12, 16, 96, 21, 23, 24, 25, 26,
47
+ 27, 28, 29, 30, 32, 33, 34, 38, 39, 97, 98, 99, 100, 101, 102,
48
+ 103, 104, 106, 305, 109, 111, 182, 179, 173, 174, 212, 175, 176,
49
+ 183, 262, 264, 265, 266, 267, 268, 269, 270, 271, 272, 277, 307,
50
+ 306, 281, 282, 284, 285, 293, 287, 289, 294, 297, 298, 299, 332,
51
+ 336, 353, 355, 356, 354, 352, 357, 428, 334, 347, 303, 302, 295,
52
+ 49, 66, 63, 116, 60, 76, 124, 118, 78, 79, 120, 123, 201, 273,
53
+ 171, 144, 147, 89, 41, 125, 42, 43, 129, 85,
54
+ ]
55
+
56
+ static readonly responseEmojiId: readonly number[] = [
57
+ 128522, 128524, 128538, 128531, 128560, 128541, 128513, 128540,
58
+ 9786, 128532, 128516, 128527, 128530, 128563, 128536, 128557,
59
+ 128514, 128170, 128074, 128077, 128079, 128076, 127836, 127847,
60
+ 127838, 127866, 127867, 9749, 127822, 127827, 127817, 127801,
61
+ 127881, 128157, 10024, 128168, 128166, 128293, 128164, 128235,
62
+ 128103, 128102, 128053, 128046, 128027, 128051, 9728, 10068,
63
+ 128147,
64
+ ]
65
+
66
+ private suffixId?: number
67
+
68
+ private constructor(
69
+ public id: number,
70
+ public type: 'apng' | 'emoji',
71
+ public hasSuper: boolean,
72
+ public superSuffix: number[],
73
+ ) {
74
+ if (superSuffix.length > 0) {
75
+ this.suffixId = superSuffix[0]
76
+ }
77
+ }
78
+
79
+ static get(id: number): Emoji | undefined {
80
+ if (id < 5000) {
81
+ const value = this.apngMap.get(id)
82
+ return value ? new Emoji(id, 'apng', value.super, value.suffix) : undefined
83
+ }
84
+ return new Emoji(id, 'emoji', false, [])
85
+ }
86
+
87
+ static has(id: number): boolean {
88
+ return id >= 5000 || this.apngMap.has(id)
89
+ }
90
+
91
+ static init() {
92
+ for (const id of [...this.superList, ...this.normalList, ...this.responseApngId]) {
93
+ const isSuper = this.superList.includes(id)
94
+ this.apngMap.set(id, { super: isSuper, suffix: [] })
95
+ if (isSuper) this.allSuperList.add(id)
96
+ this.allList.add(id)
97
+ }
98
+ }
99
+
100
+ static get responseId(): readonly number[] {
101
+ return [...this.responseApngId, ...this.responseEmojiId]
102
+ }
103
+
104
+ get description(): string {
105
+ return Emoji.descMap.get(this.id.toString()) || '表情'
106
+ }
107
+
108
+ get value(): string {
109
+ return this.type === 'apng' ? this.getNormalUrl(this.id) : String.fromCodePoint(this.id)
110
+ }
111
+
112
+ get superValue(): string | undefined {
113
+ if (!this.hasSuper) return undefined
114
+ return this.getSuperUrl(this.id, this.suffixId)
115
+ }
116
+
117
+ private getNormalUrl(id: number): string {
118
+ return `https://lib.stapxs.cn/download/stapxs-qq-lite/qq_emoji/${id}/apng/${id}.png`
119
+ }
120
+
121
+ private getSuperUrl(id: number, suffix?: number): string {
122
+ const name = suffix ? `${id}_${suffix}` : `${id}`
123
+ return `https://lib.stapxs.cn/download/stapxs-qq-lite/qq_emoji/${id}/lottie/${name}.json`
124
+ }
125
+ }
126
+
127
+ setTimeout(Emoji.init.bind(Emoji), 0)