KI-AGENT: Call UX im Chat verbessern
This commit is contained in:
@@ -146,6 +146,18 @@ const matrixCallDurationLabel = computed(() => {
|
||||
return `${minutes}:${seconds}`
|
||||
})
|
||||
|
||||
const matrixCallPrimaryTile = computed(() =>
|
||||
matrixCallTiles.value.find((tile) => tile.screenSharing) ||
|
||||
matrixCallTiles.value.find((tile) => !tile.local && tile.videoTrack) ||
|
||||
matrixCallTiles.value.find((tile) => tile.videoTrack) ||
|
||||
matrixCallTiles.value[0] ||
|
||||
null
|
||||
)
|
||||
|
||||
const matrixCallSecondaryTiles = computed(() =>
|
||||
matrixCallTiles.value.filter((tile) => tile.id !== matrixCallPrimaryTile.value?.id)
|
||||
)
|
||||
|
||||
const roomCreateKeyPreview = computed(() =>
|
||||
normalizeRoomKey(roomCreateForm.value.key || roomCreateForm.value.name)
|
||||
)
|
||||
@@ -396,6 +408,9 @@ const replyPreview = (message) => {
|
||||
return message.body || message.attachment?.fileName || "Nachricht"
|
||||
}
|
||||
|
||||
const participantInitial = (tile) =>
|
||||
(tile?.name || tile?.identity || "?").slice(0, 1).toUpperCase()
|
||||
|
||||
const setReplyTarget = (message) => {
|
||||
matrixEditingMessage.value = null
|
||||
matrixReplyTarget.value = {
|
||||
@@ -1766,15 +1781,43 @@ onBeforeUnmount(() => {
|
||||
v-if="matrixLiveKitRoom && matrixCallConnected"
|
||||
class="flex shrink-0 flex-wrap items-center justify-between gap-3 border-b border-primary/20 bg-primary/10 px-4 py-3"
|
||||
>
|
||||
<div class="min-w-0">
|
||||
<button
|
||||
type="button"
|
||||
class="min-w-0 text-left"
|
||||
@click="matrixCallOpen = true"
|
||||
>
|
||||
<p class="truncate text-sm font-medium text-highlighted">
|
||||
{{ matrixCallTitle }} läuft in {{ activeRoom.name }}
|
||||
</p>
|
||||
<p class="truncate text-xs text-muted">
|
||||
{{ matrixCallParticipantCount }} Teilnehmer · {{ matrixCallDurationLabel }} · {{ matrixCallStateLabel }}
|
||||
</p>
|
||||
</div>
|
||||
<div class="flex items-center gap-2">
|
||||
</button>
|
||||
<div class="flex flex-wrap items-center gap-2">
|
||||
<UButton
|
||||
:icon="matrixCallMicEnabled ? 'i-heroicons-microphone' : 'i-heroicons-microphone-slash'"
|
||||
color="neutral"
|
||||
:variant="matrixCallMicEnabled ? 'soft' : 'outline'"
|
||||
size="sm"
|
||||
:disabled="!matrixLiveKitRoom"
|
||||
@click="toggleMatrixCallMic"
|
||||
/>
|
||||
<UButton
|
||||
:icon="matrixCallCameraEnabled ? 'i-heroicons-video-camera' : 'i-heroicons-video-camera-slash'"
|
||||
color="neutral"
|
||||
:variant="matrixCallCameraEnabled ? 'soft' : 'outline'"
|
||||
size="sm"
|
||||
:disabled="!matrixLiveKitRoom"
|
||||
@click="toggleMatrixCallCamera"
|
||||
/>
|
||||
<UButton
|
||||
:icon="matrixCallScreenShareEnabled ? 'i-heroicons-computer-desktop' : 'i-heroicons-arrow-up-tray'"
|
||||
color="neutral"
|
||||
:variant="matrixCallScreenShareEnabled ? 'soft' : 'outline'"
|
||||
size="sm"
|
||||
:disabled="!matrixLiveKitRoom"
|
||||
@click="toggleMatrixCallScreenShare"
|
||||
/>
|
||||
<UButton
|
||||
icon="i-heroicons-arrow-top-right-on-square"
|
||||
color="primary"
|
||||
@@ -2232,44 +2275,17 @@ onBeforeUnmount(() => {
|
||||
class="h-[100dvh]"
|
||||
>
|
||||
<template #content>
|
||||
<div class="flex h-[100dvh] flex-col bg-default">
|
||||
<header class="flex shrink-0 items-center justify-between gap-3 border-b border-default px-4 py-3">
|
||||
<div class="flex h-[100dvh] flex-col bg-inverted text-inverted">
|
||||
<header class="flex shrink-0 items-center justify-between gap-3 border-b border-white/10 bg-black px-4 py-3">
|
||||
<div class="min-w-0">
|
||||
<h3 class="truncate text-base font-semibold text-highlighted">
|
||||
<h3 class="truncate text-base font-semibold text-white">
|
||||
{{ matrixCallTitle }} · {{ activeRoom.name }}
|
||||
</h3>
|
||||
<p class="truncate text-xs text-muted">
|
||||
{{ activeRoomMatrixAddress }}
|
||||
<p class="truncate text-xs text-white/60">
|
||||
{{ matrixCallParticipantCount }} Teilnehmer · {{ matrixCallDurationLabel }} · {{ matrixCallStateLabel }}
|
||||
</p>
|
||||
</div>
|
||||
<div class="flex items-center gap-2">
|
||||
<UButton
|
||||
icon="i-heroicons-microphone"
|
||||
color="neutral"
|
||||
:variant="matrixCallMicEnabled ? 'soft' : 'outline'"
|
||||
:disabled="!matrixLiveKitRoom"
|
||||
@click="toggleMatrixCallMic"
|
||||
>
|
||||
{{ matrixCallMicEnabled ? "Mikro an" : "Mikro aus" }}
|
||||
</UButton>
|
||||
<UButton
|
||||
icon="i-heroicons-video-camera"
|
||||
color="neutral"
|
||||
:variant="matrixCallCameraEnabled ? 'soft' : 'outline'"
|
||||
:disabled="!matrixLiveKitRoom"
|
||||
@click="toggleMatrixCallCamera"
|
||||
>
|
||||
{{ matrixCallCameraEnabled ? "Kamera an" : "Kamera aus" }}
|
||||
</UButton>
|
||||
<UButton
|
||||
icon="i-heroicons-computer-desktop"
|
||||
color="neutral"
|
||||
:variant="matrixCallScreenShareEnabled ? 'soft' : 'outline'"
|
||||
:disabled="!matrixLiveKitRoom"
|
||||
@click="toggleMatrixCallScreenShare"
|
||||
>
|
||||
{{ matrixCallScreenShareEnabled ? "Freigabe an" : "Freigeben" }}
|
||||
</UButton>
|
||||
<UButton
|
||||
icon="i-heroicons-arrows-pointing-in"
|
||||
color="neutral"
|
||||
@@ -2296,10 +2312,10 @@ onBeforeUnmount(() => {
|
||||
</div>
|
||||
</header>
|
||||
|
||||
<div class="min-h-0 flex-1 bg-muted">
|
||||
<div class="min-h-0 flex-1 bg-black">
|
||||
<div
|
||||
v-if="matrixCallLoading"
|
||||
class="flex h-full items-center justify-center text-sm text-muted"
|
||||
class="flex h-full items-center justify-center text-sm text-white/70"
|
||||
>
|
||||
Besprechung wird gestartet...
|
||||
</div>
|
||||
@@ -2319,21 +2335,73 @@ onBeforeUnmount(() => {
|
||||
v-else-if="canStartMatrixCall"
|
||||
class="flex h-full flex-col"
|
||||
>
|
||||
<div class="flex shrink-0 items-center justify-between border-b border-default bg-default px-4 py-2 text-xs text-muted">
|
||||
<span>{{ matrixCallParticipantCount }} Teilnehmer · {{ matrixCallDurationLabel }}</span>
|
||||
<span>{{ matrixCallStateLabel }}</span>
|
||||
</div>
|
||||
<div class="grid min-h-0 flex-1 auto-rows-fr gap-3 overflow-y-auto p-3 sm:grid-cols-2 xl:grid-cols-3">
|
||||
<div class="flex min-h-0 flex-1 flex-col gap-3 p-3 lg:flex-row">
|
||||
<div class="relative min-h-0 flex-1 overflow-hidden rounded-lg bg-zinc-950">
|
||||
<template v-if="matrixCallPrimaryTile">
|
||||
<video
|
||||
v-if="matrixCallPrimaryTile.videoTrack"
|
||||
:ref="(element) => setMatrixCallVideoElement(matrixCallPrimaryTile.id, element)"
|
||||
class="h-full min-h-[60dvh] w-full"
|
||||
:class="matrixCallPrimaryTile.screenSharing ? 'object-contain bg-black' : 'object-cover'"
|
||||
autoplay
|
||||
playsinline
|
||||
:muted="matrixCallPrimaryTile.local"
|
||||
/>
|
||||
<div
|
||||
v-for="tile in matrixCallTiles"
|
||||
v-else
|
||||
class="flex h-full min-h-[60dvh] items-center justify-center bg-zinc-900"
|
||||
>
|
||||
<span class="flex size-24 items-center justify-center rounded-lg bg-primary/15 text-3xl font-semibold text-primary">
|
||||
{{ participantInitial(matrixCallPrimaryTile) }}
|
||||
</span>
|
||||
</div>
|
||||
<div class="absolute inset-x-0 bottom-0 flex items-center justify-between bg-black/65 px-4 py-3 text-sm text-white">
|
||||
<span class="truncate font-medium">
|
||||
{{ matrixCallPrimaryTile.name }}
|
||||
<span v-if="matrixCallPrimaryTile.screenSharing" class="ml-1 text-xs text-white/70">teilt Bildschirm</span>
|
||||
</span>
|
||||
<div class="flex items-center gap-2 text-white/80">
|
||||
<UIcon
|
||||
v-if="matrixCallPrimaryTile.screenSharing"
|
||||
name="i-heroicons-computer-desktop"
|
||||
class="size-4"
|
||||
/>
|
||||
<UIcon
|
||||
v-if="!matrixCallPrimaryTile.screenSharing"
|
||||
:name="matrixCallPrimaryTile.microphoneEnabled ? 'i-heroicons-microphone' : 'i-heroicons-microphone-slash'"
|
||||
class="size-4"
|
||||
/>
|
||||
<UIcon
|
||||
v-if="!matrixCallPrimaryTile.screenSharing"
|
||||
:name="matrixCallPrimaryTile.cameraEnabled ? 'i-heroicons-video-camera' : 'i-heroicons-video-camera-slash'"
|
||||
class="size-4"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<div
|
||||
v-else
|
||||
class="flex h-full min-h-[60dvh] items-center justify-center text-sm text-white/60"
|
||||
>
|
||||
Warte auf Medien...
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div
|
||||
v-if="matrixCallSecondaryTiles.length"
|
||||
class="grid max-h-48 shrink-0 grid-cols-2 gap-2 overflow-y-auto lg:max-h-none lg:w-72 lg:grid-cols-1"
|
||||
>
|
||||
<button
|
||||
v-for="tile in matrixCallSecondaryTiles"
|
||||
:key="tile.id"
|
||||
class="relative min-h-52 overflow-hidden rounded-lg bg-inverted text-inverted"
|
||||
type="button"
|
||||
class="relative min-h-28 overflow-hidden rounded-lg bg-zinc-900 text-left"
|
||||
:class="tile.speaking ? 'ring-2 ring-primary' : ''"
|
||||
>
|
||||
<video
|
||||
v-if="tile.videoTrack"
|
||||
:ref="(element) => setMatrixCallVideoElement(tile.id, element)"
|
||||
class="h-full w-full"
|
||||
class="h-full min-h-28 w-full"
|
||||
:class="tile.screenSharing ? 'object-contain bg-black' : 'object-cover'"
|
||||
autoplay
|
||||
playsinline
|
||||
@@ -2341,37 +2409,59 @@ onBeforeUnmount(() => {
|
||||
/>
|
||||
<div
|
||||
v-else
|
||||
class="flex h-full min-h-52 items-center justify-center bg-elevated text-highlighted"
|
||||
class="flex h-full min-h-28 items-center justify-center"
|
||||
>
|
||||
<span class="flex size-16 items-center justify-center rounded-lg bg-primary/10 text-xl font-semibold text-primary">
|
||||
{{ (tile.name || tile.identity || "?").slice(0, 1).toUpperCase() }}
|
||||
<span class="flex size-12 items-center justify-center rounded-lg bg-primary/15 text-lg font-semibold text-primary">
|
||||
{{ participantInitial(tile) }}
|
||||
</span>
|
||||
</div>
|
||||
<div class="absolute inset-x-0 bottom-0 flex items-center justify-between bg-black/55 px-3 py-2 text-sm text-white">
|
||||
<span class="truncate">
|
||||
{{ tile.name }}
|
||||
<span v-if="tile.screenSharing" class="ml-1 text-xs opacity-80">teilt Bildschirm</span>
|
||||
</span>
|
||||
<div class="flex items-center gap-2">
|
||||
<div class="absolute inset-x-0 bottom-0 flex items-center justify-between bg-black/60 px-2 py-1 text-xs text-white">
|
||||
<span class="truncate">{{ tile.name }}</span>
|
||||
<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'"
|
||||
class="size-4"
|
||||
:class="tile.microphoneEnabled ? 'opacity-100' : 'opacity-35'"
|
||||
/>
|
||||
<UIcon
|
||||
v-if="!tile.screenSharing"
|
||||
:name="tile.cameraEnabled ? 'i-heroicons-video-camera' : 'i-heroicons-video-camera-slash'"
|
||||
class="size-4"
|
||||
:name="tile.screenSharing ? 'i-heroicons-computer-desktop' : (tile.microphoneEnabled ? 'i-heroicons-microphone' : 'i-heroicons-microphone-slash')"
|
||||
class="size-3.5 shrink-0"
|
||||
/>
|
||||
</div>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="flex shrink-0 flex-wrap items-center justify-center gap-2 border-t border-white/10 bg-black px-4 py-3">
|
||||
<UButton
|
||||
:icon="matrixCallMicEnabled ? 'i-heroicons-microphone' : 'i-heroicons-microphone-slash'"
|
||||
color="neutral"
|
||||
:variant="matrixCallMicEnabled ? 'soft' : 'outline'"
|
||||
:disabled="!matrixLiveKitRoom"
|
||||
@click="toggleMatrixCallMic"
|
||||
>
|
||||
{{ matrixCallMicEnabled ? "Mikro an" : "Mikro aus" }}
|
||||
</UButton>
|
||||
<UButton
|
||||
:icon="matrixCallCameraEnabled ? 'i-heroicons-video-camera' : 'i-heroicons-video-camera-slash'"
|
||||
color="neutral"
|
||||
:variant="matrixCallCameraEnabled ? 'soft' : 'outline'"
|
||||
:disabled="!matrixLiveKitRoom"
|
||||
@click="toggleMatrixCallCamera"
|
||||
>
|
||||
{{ matrixCallCameraEnabled ? "Kamera an" : "Kamera aus" }}
|
||||
</UButton>
|
||||
<UButton
|
||||
:icon="matrixCallScreenShareEnabled ? 'i-heroicons-computer-desktop' : 'i-heroicons-arrow-up-tray'"
|
||||
color="neutral"
|
||||
:variant="matrixCallScreenShareEnabled ? 'soft' : 'outline'"
|
||||
:disabled="!matrixLiveKitRoom"
|
||||
@click="toggleMatrixCallScreenShare"
|
||||
>
|
||||
{{ matrixCallScreenShareEnabled ? "Freigabe beenden" : "Bildschirm teilen" }}
|
||||
</UButton>
|
||||
<UButton
|
||||
icon="i-heroicons-phone-x-mark"
|
||||
color="error"
|
||||
variant="solid"
|
||||
@click="closeMatrixCall"
|
||||
>
|
||||
Auflegen
|
||||
</UButton>
|
||||
</div>
|
||||
<div ref="matrixCallAudioContainer" class="hidden" />
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user