KI-AGENT: Kamera und Bildschirmfreigabe getrennt anzeigen

This commit is contained in:
2026-05-18 19:28:53 +02:00
parent 77eabe7e18
commit 24c09d7891

View File

@@ -91,7 +91,9 @@ const matrixCallStateLabel = computed(() => {
return labels[String(matrixCallState.value).toLowerCase()] || matrixCallState.value return labels[String(matrixCallState.value).toLowerCase()] || matrixCallState.value
}) })
const matrixCallParticipantCount = computed(() => matrixCallTiles.value.length) const matrixCallParticipantCount = computed(() =>
new Set(matrixCallTiles.value.map((tile) => tile.identity)).size
)
const matrixCallDurationLabel = computed(() => { const matrixCallDurationLabel = computed(() => {
if (!matrixCallStartedAt.value) return "00:00" if (!matrixCallStartedAt.value) return "00:00"
@@ -410,7 +412,7 @@ const openMatrixCall = async (mode = "video") => {
} }
} }
const getParticipantTile = (participant, local = false) => { const getParticipantTiles = (participant, local = false) => {
const publications = participant.getTrackPublications?.() || [] const publications = participant.getTrackPublications?.() || []
const screenSharePublication = publications.find((publication) => const screenSharePublication = publications.find((publication) =>
publication.kind === Track.Kind.Video && publication.kind === Track.Kind.Video &&
@@ -425,20 +427,40 @@ const getParticipantTile = (participant, local = false) => {
const audioPublication = publications.find((publication) => const audioPublication = publications.find((publication) =>
publication.kind === Track.Kind.Audio && publication.track publication.kind === Track.Kind.Audio && publication.track
) )
const videoPublication = screenSharePublication || cameraPublication const participantId = local ? "local" : participant.sid || participant.identity
const name = local ? "Du" : participant.name || participant.identity
return { const participantTile = {
id: local ? "local" : participant.sid || participant.identity, id: `${participantId}-camera`,
identity: participant.identity, identity: participant.identity,
name: local ? "Du" : participant.name || participant.identity, name,
local, local,
speaking: participant.isSpeaking, speaking: participant.isSpeaking,
screenSharing: Boolean(screenSharePublication?.track), screenSharing: false,
videoTrack: videoPublication?.track || null, videoTrack: cameraPublication?.track || null,
audioTrack: audioPublication?.track || null, audioTrack: audioPublication?.track || null,
cameraEnabled: participant.isCameraEnabled, cameraEnabled: participant.isCameraEnabled,
microphoneEnabled: participant.isMicrophoneEnabled, microphoneEnabled: participant.isMicrophoneEnabled,
} }
if (!screenSharePublication?.track) {
return [participantTile]
}
return [
{
id: `${participantId}-screen`,
identity: participant.identity,
name,
local,
speaking: false,
screenSharing: true,
videoTrack: screenSharePublication.track,
audioTrack: null,
cameraEnabled: participant.isCameraEnabled,
microphoneEnabled: participant.isMicrophoneEnabled,
},
participantTile
]
} }
const attachMatrixCallMedia = async () => { const attachMatrixCallMedia = async () => {
@@ -468,9 +490,9 @@ const refreshMatrixCallTiles = async () => {
matrixCallAudioContainer.value?.replaceChildren() matrixCallAudioContainer.value?.replaceChildren()
matrixCallTiles.value = [ matrixCallTiles.value = [
getParticipantTile(matrixLiveKitRoom.localParticipant, true), ...getParticipantTiles(matrixLiveKitRoom.localParticipant, true),
...Array.from(matrixLiveKitRoom.remoteParticipants.values()).map((participant) => ...Array.from(matrixLiveKitRoom.remoteParticipants.values()).flatMap((participant) =>
getParticipantTile(participant) getParticipantTiles(participant)
) )
].sort((a, b) => Number(b.screenSharing) - Number(a.screenSharing)) ].sort((a, b) => Number(b.screenSharing) - Number(a.screenSharing))
@@ -1360,7 +1382,8 @@ onBeforeUnmount(() => {
<video <video
v-if="tile.videoTrack" v-if="tile.videoTrack"
:ref="(element) => setMatrixCallVideoElement(tile.id, element)" :ref="(element) => setMatrixCallVideoElement(tile.id, element)"
class="h-full w-full object-cover" class="h-full w-full"
:class="tile.screenSharing ? 'object-contain bg-black' : 'object-cover'"
autoplay autoplay
playsinline playsinline
:muted="tile.local" :muted="tile.local"
@@ -1380,11 +1403,18 @@ onBeforeUnmount(() => {
</span> </span>
<div class="flex items-center gap-2"> <div class="flex items-center gap-2">
<UIcon <UIcon
v-if="tile.screenSharing"
name="i-heroicons-computer-desktop"
class="size-4"
/>
<UIcon
v-if="!tile.screenSharing"
:name="tile.microphoneEnabled ? 'i-heroicons-microphone' : 'i-heroicons-microphone'" :name="tile.microphoneEnabled ? 'i-heroicons-microphone' : 'i-heroicons-microphone'"
class="size-4" class="size-4"
:class="tile.microphoneEnabled ? 'opacity-100' : 'opacity-35'" :class="tile.microphoneEnabled ? 'opacity-100' : 'opacity-35'"
/> />
<UIcon <UIcon
v-if="!tile.screenSharing"
:name="tile.cameraEnabled ? 'i-heroicons-video-camera' : 'i-heroicons-video-camera-slash'" :name="tile.cameraEnabled ? 'i-heroicons-video-camera' : 'i-heroicons-video-camera-slash'"
class="size-4" class="size-4"
/> />