koishi-plugin-chat-patch 5.0.3 → 5.3.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 (32) hide show
  1. package/client/web/dist/assets/Chat-B448YOeN.js +28 -0
  2. package/client/web/dist/assets/{MsgBody-LNGNGtE3.js → MsgBody-DDacjWJ9.js} +1 -1
  3. package/client/web/dist/assets/MsgBody.vue_vue_type_script_setup_true_lang-B1dWyCB0.js +67 -0
  4. package/client/web/dist/assets/{index-CwyyQN13.js → index-BlLut5xn.js} +121 -129
  5. package/client/web/dist/assets/index-fW_zcub3.css +1 -0
  6. package/client/web/dist/assets/pinyin-Dsq98249.js +157657 -0
  7. package/client/web/dist/index.html +2 -2
  8. package/client/web/dist/notice_local.json +1 -0
  9. package/client/web/package-lock.json +49 -0
  10. package/client/web/package.json +1 -0
  11. package/client/web/public/notice_local.json +1 -0
  12. package/client/web/src/components/EmojiFace.vue +0 -6
  13. package/client/web/src/components/FacePan.vue +0 -12
  14. package/client/web/src/components/MsgBody.vue +3 -4
  15. package/client/web/src/components/SettingsTab.vue +133 -0
  16. package/client/web/src/function/connect.ts +42 -21
  17. package/client/web/src/function/model/emoji.ts +7 -67
  18. package/client/web/src/function/msg.ts +74 -23
  19. package/client/web/src/function/satori-model.ts +4 -3
  20. package/client/web/src/function/utils/appUtil.ts +1 -4
  21. package/client/web/src/function/utils/msgUtil.ts +121 -87
  22. package/client/web/src/function/utils/pinyin.ts +25 -65
  23. package/client/web/src/function/utils/sessionUtil.ts +107 -9
  24. package/client/web/src/pages/Friends.vue +49 -13
  25. package/client/web/src/pages/Messages.vue +45 -14
  26. package/client/web/src/pages/Options.vue +4 -4
  27. package/client/web/src/pages/options/OptDev.vue +1 -14
  28. package/package.json +1 -1
  29. package/src/web.ts +712 -712
  30. package/client/web/dist/assets/Chat-CXjwWCiV.js +0 -28
  31. package/client/web/dist/assets/MsgBody.vue_vue_type_script_setup_true_lang-BK5okBfM.js +0 -67
  32. package/client/web/dist/assets/index-BgOX_tNa.css +0 -1
@@ -87,11 +87,14 @@ import { useUIStore } from '../state/ui'
87
87
  import { useSettingsStore } from '../state/settings'
88
88
  import { useQzoneStore } from '../state/qzone'
89
89
  import {
90
+ findSessionContact,
90
91
  getSessionId,
91
92
  getMissingGroupPreviewSessions,
92
93
  mergeEarlySessionContacts,
94
+ normalizeGroupId,
93
95
  normalizeSessionId,
94
96
  resolveIncomingSession,
97
+ setSessionContact,
95
98
  } from './utils/sessionUtil'
96
99
 
97
100
  const popInfo = new PopInfo()
@@ -117,6 +120,11 @@ function getString(value: unknown): string {
117
120
  return typeof value === 'string' ? value : String(value)
118
121
  }
119
122
 
123
+ function normalizeChannelForMatch(value: string): string {
124
+ if (/^(?:private|direct):/i.test(value)) return value.replace(/^(?:private|direct):/i, '')
125
+ return normalizeGroupId(value)
126
+ }
127
+
120
128
  // 其他 tag
121
129
  let listLoadTimes = 0
122
130
  const logger = new Logger()
@@ -961,9 +969,11 @@ const msgFunctions = {
961
969
  )
962
970
  // 更新消息列表
963
971
  const onmsg = contactStore.baseOnMsgList.get(normalizeSessionId(id))
972
+ ?? findSessionContact(Array.from(contactStore.baseOnMsgList.values()), id)
964
973
  if (onmsg && list[0]) {
974
+ const canonicalId = normalizeSessionId(getSessionId(onmsg))
965
975
  Object.assign(onmsg, formatMessageData(list[0], Boolean(onmsg.group_id)))
966
- contactStore.baseOnMsgList.set(normalizeSessionId(id), onmsg)
976
+ contactStore.baseOnMsgList.set(canonicalId, onmsg)
967
977
  updateBaseOnMsgList()
968
978
  }
969
979
  }
@@ -1604,7 +1614,18 @@ function saveUser(msg: { [key: string]: any }, type: string) {
1604
1614
  list = list.filter((item, index, arr) => {
1605
1615
  return (
1606
1616
  arr.findIndex((item2) => {
1607
- return item2.group_id == item.group_id
1617
+ const channelA = String(item2.channel_id ?? item2.channelId ?? '')
1618
+ const channelB = String(item.channel_id ?? item.channelId ?? '')
1619
+ const groupA = String(item2.group_id ?? item2.id ?? item2.guild_id ?? '')
1620
+ const groupB = String(item.group_id ?? item.id ?? item.guild_id ?? '')
1621
+ if (channelA && channelB) {
1622
+ return normalizeGroupId(channelA) === normalizeGroupId(channelB)
1623
+ }
1624
+ if (channelA || channelB) {
1625
+ return normalizeGroupId(channelA || channelB)
1626
+ === normalizeGroupId(groupA || groupB)
1627
+ }
1628
+ return normalizeGroupId(groupA) === normalizeGroupId(groupB)
1608
1629
  }) == index
1609
1630
  )
1610
1631
  })
@@ -1674,15 +1695,34 @@ function saveUser(msg: { [key: string]: any }, type: string) {
1674
1695
  list,
1675
1696
  contactStore.baseOnMsgList,
1676
1697
  )
1677
- const existingIds = new Set(
1678
- contactStore.userList.map((item) => {
1679
- return String(item.user_id ?? item.group_id ?? '')
1680
- }),
1681
- )
1698
+ const sessionDedupKey = (item: any): string => {
1699
+ const channel = String(item.channel_id ?? item.channelId ?? '')
1700
+ const group = String(item.group_id ?? '')
1701
+ const user = String(item.user_id ?? '')
1702
+ if (group) return `group:${normalizeGroupId(channel || group)}`
1703
+ return `user:${String(user).replace(/^(?:private|direct):/i, '')}`
1704
+ }
1705
+ const existingIds = new Set(contactStore.userList.map(sessionDedupKey))
1682
1706
  const freshList = list.filter((item) => {
1683
- return !existingIds.has(String(item.user_id ?? item.group_id ?? ''))
1707
+ return !existingIds.has(sessionDedupKey(item))
1684
1708
  })
1685
- contactStore.userList = contactStore.userList.concat(freshList)
1709
+ const mergedContacts = [...contactStore.userList, ...freshList] as (UserFriendElem & UserGroupElem)[]
1710
+ const userMap = new Map<string, UserFriendElem & UserGroupElem>()
1711
+ for (const item of mergedContacts) {
1712
+ const key = sessionDedupKey(item)
1713
+ const existing = userMap.get(key)
1714
+ if (existing) {
1715
+ const pyName = existing.py_name
1716
+ const pyStart = existing.py_start
1717
+ Object.assign(existing, item)
1718
+ if (pyName) existing.py_name = pyName
1719
+ if (pyStart) existing.py_start = pyStart
1720
+ userMap.set(key, existing)
1721
+ } else {
1722
+ userMap.set(key, item)
1723
+ }
1724
+ }
1725
+ contactStore.userList = [...userMap.values()]
1686
1726
  if (
1687
1727
  settingsStore.sysConfig.session_display_mode === 'all' ||
1688
1728
  didMergeEarlySessions
@@ -1851,13 +1891,11 @@ async function saveMsg(msg: any, append = undefined as undefined | string) {
1851
1891
  const lastMsg =
1852
1892
  chatStore.messageList[chatStore.messageList.length - 1]
1853
1893
  if (lastMsg) {
1854
- const user = contactStore.userList.find((item) => {
1855
- return (
1856
- item.group_id == chatStore.chatInfo.show.id ||
1857
- item.user_id == chatStore.chatInfo.show.id
1858
- )
1859
- })
1860
- const sessionId = normalizeSessionId(chatStore.chatInfo.show.id)
1894
+ const user = findSessionContact(contactStore.userList, chatStore.chatInfo.show.id)
1895
+ const sessionId = normalizeSessionId(
1896
+ chatStore.chatInfo.show.channel_id
1897
+ ?? chatStore.chatInfo.show.id,
1898
+ )
1861
1899
  const session = contactStore.baseOnMsgList.get(sessionId) ?? user
1862
1900
  if (session) {
1863
1901
  const preview = formatMessageData(
@@ -2295,6 +2333,7 @@ function newMsg(_: string, data: any) {
2295
2333
  getString(getDataObject(data.channel).id)
2296
2334
  const loginId = String(authStore.loginInfo.uin ?? '')
2297
2335
  const showId = String(chatStore.chatInfo.show.id ?? '')
2336
+ const showChannelId = getString(chatStore.chatInfo.show.channel_id)
2298
2337
  const sender = getString(rawInfo.sender) ||
2299
2338
  getString(getDataObject(data.sender).user_id) ||
2300
2339
  getString(data.user_id)
@@ -2316,6 +2355,16 @@ function newMsg(_: string, data: any) {
2316
2355
  const sessionChannelId = getString(rawInfo.channel_id) || getString(data.channel_id)
2317
2356
  const sessionGuildId = getString(rawInfo.guild_id) || getString(data.guild_id)
2318
2357
  if (!id || id === '0') return
2358
+ const isCurrentSession = Boolean(
2359
+ (
2360
+ sessionChannelId &&
2361
+ showChannelId &&
2362
+ normalizeChannelForMatch(sessionChannelId) === normalizeChannelForMatch(showChannelId)
2363
+ ) || (
2364
+ (!sessionChannelId || !showChannelId) &&
2365
+ (id === showId || targetId === showId || String(sessionChannelId || sessionGuildId || '') === showId)
2366
+ ),
2367
+ )
2319
2368
  // 在好友列表里找一下他
2320
2369
  const senderInfo = contactStore.userList.find((item) => {
2321
2370
  return String(item.user_id ?? '') === sender
@@ -2370,7 +2419,7 @@ function newMsg(_: string, data: any) {
2370
2419
  }
2371
2420
 
2372
2421
  // 显示消息 ============================================
2373
- if (id && (id === showId || targetId === showId)) {
2422
+ if (id && isCurrentSession) {
2374
2423
  // 如果有正在输入的提示,清除它
2375
2424
  chatStore.chatInfo.show.appendInfo = undefined
2376
2425
  const cachedAvatar = getCachedUserAvatar(
@@ -2474,8 +2523,10 @@ function newMsg(_: string, data: any) {
2474
2523
 
2475
2524
  // 会话状态更新 ============================================
2476
2525
  const sessionId = isTempGroupMessage ? sender : id
2477
- const normalizedSessionId = normalizeSessionId(sessionId)
2526
+ const sessionKey = String(sessionChannelId || sessionId)
2527
+ const normalizedSessionId = normalizeSessionId(sessionKey)
2478
2528
  let session = contactStore.baseOnMsgList.get(normalizedSessionId)
2529
+ ?? contactStore.baseOnMsgList.get(normalizeSessionId(sessionId))
2479
2530
  if (!session) {
2480
2531
  if (isTempGroupMessage) {
2481
2532
  session = {
@@ -2508,7 +2559,7 @@ function newMsg(_: string, data: any) {
2508
2559
  sender != loginId &&
2509
2560
  sender !== '' &&
2510
2561
  sender !== '0' &&
2511
- sessionId !== showId &&
2562
+ !isCurrentSession &&
2512
2563
  allowGroupInnerNotice
2513
2564
  ) {
2514
2565
  if (!session.new_msg) {
@@ -2516,12 +2567,12 @@ function newMsg(_: string, data: any) {
2516
2567
  contactStore.newMsgCount++
2517
2568
  }
2518
2569
  }
2519
- if (sessionId !== showId && allowGroupInnerNotice) {
2570
+ if (!isCurrentSession && allowGroupInnerNotice) {
2520
2571
  if (data.atme) { session.highlight = $t('[有人@你]') }
2521
2572
  if (data.atall) { session.highlight = $t('[@全体]') }
2522
2573
  if (isImportant) { session.highlight = $t('[特別关心]') }
2523
2574
  }
2524
- contactStore.baseOnMsgList.set(normalizedSessionId, session)
2575
+ setSessionContact(contactStore.baseOnMsgList, session)
2525
2576
  updateBaseOnMsgList()
2526
2577
  }
2527
2578
 
@@ -2533,7 +2584,7 @@ function newMsg(_: string, data: any) {
2533
2584
  allowGroupSystemNotice
2534
2585
  ) {
2535
2586
  logger.add(LogType.DEBUG, '通知判定:', {
2536
- notShow: sessionId !== showId,
2587
+ notShow: !isCurrentSession,
2537
2588
  notFocus: !document.hasFocus(),
2538
2589
  hidden: document.hidden,
2539
2590
  isImportant: isImportant
@@ -2545,7 +2596,7 @@ function newMsg(_: string, data: any) {
2545
2596
  if (
2546
2597
  forceGroupSystemNotice ||
2547
2598
  forceImportantNotice ||
2548
- sessionId !== showId ||
2599
+ !isCurrentSession ||
2549
2600
  !document.hasFocus() ||
2550
2601
  document.hidden
2551
2602
  ) {
@@ -443,7 +443,7 @@ export function satoriEventToOneBot(
443
443
  const userId = getString(user.id)
444
444
  || (isGroup ? '' : getString(channel.id).replace(/^private:/, ''))
445
445
  const groupId = isGroup
446
- ? getString(guild.id) || normalizeGroupId(getString(channel.id))
446
+ ? normalizeGroupId(getString(guild.id)) || normalizeGroupId(getString(channel.id))
447
447
  : ''
448
448
  const directChannelId = isGroup ? groupId : userId
449
449
  const nickname = getString(user.name) || getString(user.nick) || userId
@@ -685,7 +685,7 @@ function messageListFromResponse(data: unknown): unknown[] {
685
685
  const member = getObject(message.member)
686
686
  const isGroup = isGroupChannel(channel, guild)
687
687
  const groupId = isGroup
688
- ? getString(guild.id) || normalizeGroupId(getString(channel.id))
688
+ ? normalizeGroupId(getString(guild.id)) || normalizeGroupId(getString(channel.id))
689
689
  : ''
690
690
  const userId = getString(user.id)
691
691
  || (isGroup ? '' : getString(channel.id).replace(/^private:/, ''))
@@ -740,7 +740,8 @@ export function satoriResponseToOneBot(
740
740
  const mapped = list.map((item) => {
741
741
  const value = getObject(item)
742
742
  const user = getObject(value.user)
743
- const id = getString(value.id)
743
+ const rawId = getString(value.id)
744
+ const id = action === 'get_group_list' ? normalizeGroupId(rawId) : rawId
744
745
  const friendName = getString(user.name)
745
746
  || getString(user.nick)
746
747
  || getString(value.name)
@@ -1026,10 +1026,7 @@ export function checkOpenTimes() {
1026
1026
  */
1027
1027
  export function checkNotice() {
1028
1028
  const uiStore = useUIStore()
1029
- let url = 'https://lib.stapxs.cn/download/stapxs-qq-lite/notice-config.json'
1030
- if (import.meta.env.DEV) {
1031
- url = 'notice_local.json'
1032
- }
1029
+ const url = 'notice_local.json'
1033
1030
  const version = 3
1034
1031
  const fetchData = {
1035
1032
  time: new Date().getTime().toString(),
@@ -20,11 +20,14 @@ import { useContactStore } from '../../state/contact'
20
20
  import { useUIStore } from '../../state/ui'
21
21
  import { useAuthStore } from '../../state/auth'
22
22
  import { useChatStore } from '../../state/chat'
23
- import {
24
- findSessionContact,
25
- getSessionId,
26
- normalizeSessionId,
27
- } from './sessionUtil'
23
+ import {
24
+ findSessionContact,
25
+ getSessionAliases,
26
+ getSessionDedupKey,
27
+ getSessionId,
28
+ mergeSessionState,
29
+ normalizeSessionId,
30
+ } from './sessionUtil'
28
31
 
29
32
  const logger = new Logger()
30
33
 
@@ -295,15 +298,15 @@ export function getMsgRawTxt(data: any): string {
295
298
  const atText = String(message[i].text)
296
299
  back += atText.startsWith('@') ? atText : '@' + atText
297
300
  break
298
- case 'text':
299
- back += message[i].text
300
- .replaceAll('\n', ' ')
301
- .replaceAll('\r', ' ')
302
- break
303
- case 'i18n':
304
- back += message[i].path || '[i18n]'
305
- break
306
- case 'forward':
301
+ case 'text':
302
+ back += message[i].text
303
+ .replaceAll('\n', ' ')
304
+ .replaceAll('\r', ' ')
305
+ break
306
+ case 'i18n':
307
+ back += message[i].path || '[i18n]'
308
+ break
309
+ case 'forward':
307
310
  back += '[' + $t('聊天记录') + ']'
308
311
  break
309
312
  case 'face':
@@ -365,7 +368,7 @@ export function hasAtMe(data: any): boolean {
365
368
  * @param data
366
369
  * @returns CQCode 字符串
367
370
  */
368
- export function parseJSONCQCode(data: any) {
371
+ export function parseJSONCQCode(data: any) {
369
372
  let back = ''
370
373
  data.forEach((item: any) => {
371
374
  if (item.type != 'text') {
@@ -380,9 +383,9 @@ export function parseJSONCQCode(data: any) {
380
383
  }
381
384
  })
382
385
  return back
383
- }
384
-
385
- /**
386
+ }
387
+
388
+ /**
386
389
  * 将扁平的 CQCode 消息处理成消息对象
387
390
  * @param msg CQCode 消息
388
391
  * @returns 消息对象
@@ -425,10 +428,10 @@ export function parseCQ(data: any) {
425
428
  .substring(RegExp.$2.lastIndexOf('=') + 1)
426
429
  .replaceAll('\\n', '\n')
427
430
  // 对 html 转义字符进行反转义
428
- const a = document.createElement('a')
429
- a.innerHTML = info.text
430
- info.text = a.innerText
431
- }
431
+ const a = document.createElement('a')
432
+ a.innerHTML = info.text
433
+ info.text = a.innerText
434
+ }
432
435
  // 对回复消息进行特殊处理
433
436
  if (info.type == 'reply') {
434
437
  data.source = {
@@ -604,15 +607,15 @@ async function persistBase64Media(msg: string | any[] | undefined): Promise<stri
604
607
  }))
605
608
  }
606
609
 
607
- export async function sendMsgRaw(
608
- id: string,
609
- type: string,
610
- msg: string | any[] | undefined,
611
- preShow = false,
612
- echo = 'sendMsgBack',
613
- targetChannelId?: string,
614
- targetGuildId?: string,
615
- ) {
610
+ export async function sendMsgRaw(
611
+ id: string,
612
+ type: string,
613
+ msg: string | any[] | undefined,
614
+ preShow = false,
615
+ echo = 'sendMsgBack',
616
+ targetChannelId?: string,
617
+ targetGuildId?: string,
618
+ ) {
616
619
  const chatStore = useChatStore()
617
620
  const authStore = useAuthStore()
618
621
  const contactStore = useContactStore()
@@ -742,11 +745,11 @@ export async function sendMsgRaw(
742
745
  Connector.send(
743
746
  authStore.jsonMap.message_list.name_group_send ??
744
747
  'send_msg',
745
- {
746
- group_id: id,
747
- guild_id: String(targetGuildId ?? chatStore.chatInfo.show.guild_id ?? id),
748
- channel_id: String(targetChannelId ?? chatStore.chatInfo.show.channel_id ?? id),
749
- message: msg,
748
+ {
749
+ group_id: id,
750
+ guild_id: String(targetGuildId ?? chatStore.chatInfo.show.guild_id ?? id),
751
+ channel_id: String(targetChannelId ?? chatStore.chatInfo.show.channel_id ?? id),
752
+ message: msg,
750
753
  },
751
754
  echo + '_uuid_' + msgUUID,
752
755
  )
@@ -757,9 +760,9 @@ export async function sendMsgRaw(
757
760
  authStore.jsonMap.message_list.name_temp_send ??
758
761
  'send_temp_msg',
759
762
  {
760
- user_id: id.split('/')[0],
761
- group_id: id.split('/')[1],
762
- channel_id: String(targetChannelId ?? chatStore.chatInfo.show.channel_id ?? `private:${String(id).split('/')[0]}`),
763
+ user_id: id.split('/')[0],
764
+ group_id: id.split('/')[1],
765
+ channel_id: String(targetChannelId ?? chatStore.chatInfo.show.channel_id ?? `private:${String(id).split('/')[0]}`),
763
766
  message: msg,
764
767
  },
765
768
  echo + '_uuid_' + msgUUID,
@@ -769,8 +772,8 @@ export async function sendMsgRaw(
769
772
  authStore.jsonMap.message_list.name_user_send ??
770
773
  'send_msg',
771
774
  {
772
- user_id: id,
773
- channel_id: String(targetChannelId ?? chatStore.chatInfo.show.channel_id ?? (/^(?:group|room|chat|channel|guild|private):/i.test(String(id)) ? String(id) : `private:${String(id)}`)),
775
+ user_id: id,
776
+ channel_id: String(targetChannelId ?? chatStore.chatInfo.show.channel_id ?? (/^(?:group|room|chat|channel|guild|private):/i.test(String(id)) ? String(id) : `private:${String(id)}`)),
774
777
  message: msg,
775
778
  },
776
779
  echo + '_uuid_' + msgUUID,
@@ -787,8 +790,9 @@ export function updateLastestHistory(item: UserFriendElem & UserGroupElem) {
787
790
  const authStore = useAuthStore()
788
791
  // 发起获取历史消息请求
789
792
  const type = item.user_id ? 'user' : 'group'
790
- const id = item.user_id ? item.user_id : item.group_id
791
- let name
793
+ const id = item.user_id ? item.user_id : item.group_id
794
+ const sessionId = normalizeSessionId(getSessionId(item))
795
+ let name
792
796
  if (authStore.jsonMap.message_list && type != 'group') {
793
797
  name = authStore.jsonMap.message_list.private_name
794
798
  } else {
@@ -804,7 +808,7 @@ export function updateLastestHistory(item: UserFriendElem & UserGroupElem) {
804
808
  message_id: 0,
805
809
  count: 1,
806
810
  },
807
- 'getChatHistoryOnMsg_' + id,
811
+ 'getChatHistoryOnMsg_' + sessionId,
808
812
  )
809
813
  }
810
814
 
@@ -817,47 +821,75 @@ function getSessionSortName(item: UserFriendElem & UserGroupElem) {
817
821
  return item.py_start ?? getShowName(item.group_name ?? item.nickname ?? '', item.remark ?? '')
818
822
  }
819
823
 
820
- function normalizeBaseSessionMap() {
821
- const contactStore = useContactStore()
822
- let needNormalize = false
823
- for (const id of contactStore.baseOnMsgList.keys()) {
824
- if (typeof id !== 'string') {
825
- needNormalize = true
826
- break
827
- }
828
- }
829
- if (!needNormalize) return
830
-
831
- const normalized = new Map<string, UserFriendElem & UserGroupElem>()
832
- contactStore.baseOnMsgList.forEach((item, id) => {
833
- normalized.set(normalizeSessionId(id), item)
834
- })
835
- contactStore.baseOnMsgList.clear()
836
- for (const [id, item] of normalized) {
837
- contactStore.baseOnMsgList.set(id, item)
838
- }
839
- }
840
-
841
- function getSessionList() {
842
- const contactStore = useContactStore()
843
- const settingsStore = useSettingsStore()
844
- const sessionMap = new Map<string, UserFriendElem & UserGroupElem>()
845
-
846
- if (settingsStore.sysConfig.session_display_mode === 'all') {
847
- contactStore.userList.forEach((item) => {
848
- const id = normalizeSessionId(getSessionId(item))
849
- if (id !== '0' && id !== '') {
850
- sessionMap.set(id, item)
851
- }
852
- })
853
- }
854
-
855
- contactStore.baseOnMsgList.forEach((item, id) => {
856
- sessionMap.set(normalizeSessionId(id), item)
857
- })
824
+ function normalizeBaseSessionMap() {
825
+ const contactStore = useContactStore()
826
+ let needNormalize = false
827
+ const seen = new Map<string, UserFriendElem & UserGroupElem>()
828
+ for (const [rawKey, item] of contactStore.baseOnMsgList) {
829
+ const id = getSessionDedupKey(item)
830
+ if (id.endsWith(':0') || id.endsWith(':')) continue
831
+ const existing = seen.get(id)
832
+ if (existing && existing !== item) {
833
+ needNormalize = true
834
+ continue
835
+ }
836
+ seen.set(id, item)
837
+ if (
838
+ typeof rawKey !== 'string' ||
839
+ !getSessionAliases(item).includes(normalizeSessionId(rawKey))
840
+ ) {
841
+ needNormalize = true
842
+ }
843
+ }
844
+ if (!needNormalize) return
845
+
846
+ const canonical = new Map<string, UserFriendElem & UserGroupElem>()
847
+ contactStore.baseOnMsgList.forEach((item) => {
848
+ const id = getSessionDedupKey(item)
849
+ if (id === 'group:0' || id === 'group:' || id === 'user:0' || id === 'user:') return
850
+ const existing = canonical.get(id)
851
+ if (existing && existing !== item) {
852
+ canonical.set(id, mergeSessionState(existing, item))
853
+ } else if (!existing) {
854
+ canonical.set(id, item)
855
+ }
856
+ })
857
+ contactStore.baseOnMsgList.clear()
858
+ for (const [id, item] of canonical) {
859
+ for (const alias of getSessionAliases(item)) {
860
+ contactStore.baseOnMsgList.set(alias, item)
861
+ }
862
+ }
863
+ }
858
864
 
859
- return [...sessionMap.values()]
860
- }
865
+ function getSessionList() {
866
+ const contactStore = useContactStore()
867
+ const settingsStore = useSettingsStore()
868
+ const sessionMap = new Map<string, UserFriendElem & UserGroupElem>()
869
+
870
+ const addSession = (item: UserFriendElem & UserGroupElem) => {
871
+ const id = getSessionDedupKey(item)
872
+ if (id === 'group:0' || id === 'group:' || id === 'user:0' || id === 'user:') return
873
+ const existing = sessionMap.get(id)
874
+ if (existing && existing !== item) {
875
+ sessionMap.set(id, mergeSessionState(existing, item))
876
+ } else if (!existing) {
877
+ sessionMap.set(id, item)
878
+ }
879
+ }
880
+
881
+ if (settingsStore.sysConfig.session_display_mode === 'all') {
882
+ contactStore.userList.forEach((item) => {
883
+ addSession(item)
884
+ })
885
+ }
886
+
887
+ contactStore.baseOnMsgList.forEach((item) => {
888
+ addSession(item)
889
+ })
890
+
891
+ return [...sessionMap.values()]
892
+ }
861
893
 
862
894
  /**
863
895
  * 刷新消息列表排序
@@ -890,9 +922,11 @@ export function updateBaseOnMsgList() {
890
922
  let groupAssistList = [] as any[]
891
923
  if (settingsStore.sysConfig.bubble_sort_user) {
892
924
  // 将 normalList 进行拆分
893
- const shouldShowInMainList = (item: UserFriendElem & UserGroupElem) => {
894
- return item.user_id || item.always_top
895
- }
925
+ const shouldShowInMainList = (item: UserFriendElem & UserGroupElem) => {
926
+ return item.group_id
927
+ ? item.always_top
928
+ : Boolean(item.user_id) || item.always_top
929
+ }
896
930
  onMsgList = topList.concat(normalList.filter((item) => {
897
931
  return shouldShowInMainList(item)
898
932
  }))