gaoluyang
2026-06-29 27cd042df9aca0383a49f3514bc21958dd890912
src/views/im/home/composables/useGroupCallMembers.ts
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,53 @@
import { computed, type ComputedRef, type Ref } from 'vue'
import { ImConversationType } from '../../utils/constants'
import { getSenderAvatar, getSenderDisplayName } from '../../utils/user'
import { useRtcStore } from '../store/rtcStore'
/** ç¾¤é€šè¯æˆå‘˜è§†å›¾æ¨¡åž‹ï¼šå·²åŠ å…¥ + æŽ¥å…¥ä¸­ï¼›pending å¤´åƒ UI åŠé€æ˜Žï¼Œjoined ä¸é€æ˜Ž */
export interface GroupCallMember {
  userId: number
  nickname: string
  avatar?: string
  pending: boolean
}
/**
 * ç¾¤é€šè¯æˆå‘˜åˆ—表 computed:joined åœ¨å‰ï¼Œæœª joined çš„ invitee åœ¨åŽï¼›
 * ç¼“存为空(来电首屏渲染早于 syncGroupActiveCall å›žå†™ï¼‰æ—¶ç”¨ fallback ä¸»å«å…œåº•,避免空白
 *
 * @param groupId ç¾¤ç¼–号
 * @param fallbackInviterId å…œåº•主叫;缓存为空时填一个头像,标记为已加入而非 pending
 */
export function useGroupCallMembers(
  groupId: Ref<number | undefined>,
  fallbackInviterId?: Ref<number | undefined>
): ComputedRef<GroupCallMember[]> {
  const rtcStore = useRtcStore()
  return computed(() => {
    const gid = groupId.value
    if (!gid) {
      return []
    }
    const groupCall = rtcStore.getGroupCall(gid)
    const joinedIds = groupCall?.joinedUserIds ?? []
    const inviteeIds = groupCall?.inviteeIds ?? []
    const joinedSet = new Set(joinedIds)
    const orderedIds = [...joinedIds, ...inviteeIds.filter((id) => !joinedSet.has(id))]
    if (orderedIds.length > 0) {
      return orderedIds.map((userId) => toVM(userId, gid, !joinedSet.has(userId)))
    }
    const fallback = fallbackInviterId?.value
    return fallback ? [toVM(fallback, gid, false)] : []
  })
}
/** æŠŠ userId ç¿»è¯‘成视图模型,统一走 user.ts helper è§£æžæ˜µç§° / å¤´åƒ */
function toVM(userId: number, groupId: number, pending: boolean): GroupCallMember {
  return {
    userId,
    nickname: getSenderDisplayName(userId, ImConversationType.GROUP, groupId),
    avatar: getSenderAvatar(userId, ImConversationType.GROUP, groupId) || undefined,
    pending
  }
}