KI-AGENT: Call UX im Chat verbessern
This commit is contained in:
@@ -146,6 +146,18 @@ const matrixCallDurationLabel = computed(() => {
|
|||||||
return `${minutes}:${seconds}`
|
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(() =>
|
const roomCreateKeyPreview = computed(() =>
|
||||||
normalizeRoomKey(roomCreateForm.value.key || roomCreateForm.value.name)
|
normalizeRoomKey(roomCreateForm.value.key || roomCreateForm.value.name)
|
||||||
)
|
)
|
||||||
@@ -396,6 +408,9 @@ const replyPreview = (message) => {
|
|||||||
return message.body || message.attachment?.fileName || "Nachricht"
|
return message.body || message.attachment?.fileName || "Nachricht"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const participantInitial = (tile) =>
|
||||||
|
(tile?.name || tile?.identity || "?").slice(0, 1).toUpperCase()
|
||||||
|
|
||||||
const setReplyTarget = (message) => {
|
const setReplyTarget = (message) => {
|
||||||
matrixEditingMessage.value = null
|
matrixEditingMessage.value = null
|
||||||
matrixReplyTarget.value = {
|
matrixReplyTarget.value = {
|
||||||
@@ -1766,15 +1781,43 @@ onBeforeUnmount(() => {
|
|||||||
v-if="matrixLiveKitRoom && matrixCallConnected"
|
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"
|
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">
|
<p class="truncate text-sm font-medium text-highlighted">
|
||||||
{{ matrixCallTitle }} läuft in {{ activeRoom.name }}
|
{{ matrixCallTitle }} läuft in {{ activeRoom.name }}
|
||||||
</p>
|
</p>
|
||||||
<p class="truncate text-xs text-muted">
|
<p class="truncate text-xs text-muted">
|
||||||
{{ matrixCallParticipantCount }} Teilnehmer · {{ matrixCallDurationLabel }} · {{ matrixCallStateLabel }}
|
{{ matrixCallParticipantCount }} Teilnehmer · {{ matrixCallDurationLabel }} · {{ matrixCallStateLabel }}
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</button>
|
||||||
<div class="flex items-center gap-2">
|
<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
|
<UButton
|
||||||
icon="i-heroicons-arrow-top-right-on-square"
|
icon="i-heroicons-arrow-top-right-on-square"
|
||||||
color="primary"
|
color="primary"
|
||||||
@@ -2232,44 +2275,17 @@ onBeforeUnmount(() => {
|
|||||||
class="h-[100dvh]"
|
class="h-[100dvh]"
|
||||||
>
|
>
|
||||||
<template #content>
|
<template #content>
|
||||||
<div class="flex h-[100dvh] flex-col bg-default">
|
<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-default px-4 py-3">
|
<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">
|
<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 }}
|
{{ matrixCallTitle }} · {{ activeRoom.name }}
|
||||||
</h3>
|
</h3>
|
||||||
<p class="truncate text-xs text-muted">
|
<p class="truncate text-xs text-white/60">
|
||||||
{{ activeRoomMatrixAddress }}
|
{{ matrixCallParticipantCount }} Teilnehmer · {{ matrixCallDurationLabel }} · {{ matrixCallStateLabel }}
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
<div class="flex items-center gap-2">
|
<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
|
<UButton
|
||||||
icon="i-heroicons-arrows-pointing-in"
|
icon="i-heroicons-arrows-pointing-in"
|
||||||
color="neutral"
|
color="neutral"
|
||||||
@@ -2296,10 +2312,10 @@ onBeforeUnmount(() => {
|
|||||||
</div>
|
</div>
|
||||||
</header>
|
</header>
|
||||||
|
|
||||||
<div class="min-h-0 flex-1 bg-muted">
|
<div class="min-h-0 flex-1 bg-black">
|
||||||
<div
|
<div
|
||||||
v-if="matrixCallLoading"
|
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...
|
Besprechung wird gestartet...
|
||||||
</div>
|
</div>
|
||||||
@@ -2319,21 +2335,73 @@ onBeforeUnmount(() => {
|
|||||||
v-else-if="canStartMatrixCall"
|
v-else-if="canStartMatrixCall"
|
||||||
class="flex h-full flex-col"
|
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">
|
<div class="flex min-h-0 flex-1 flex-col gap-3 p-3 lg:flex-row">
|
||||||
<span>{{ matrixCallParticipantCount }} Teilnehmer · {{ matrixCallDurationLabel }}</span>
|
<div class="relative min-h-0 flex-1 overflow-hidden rounded-lg bg-zinc-950">
|
||||||
<span>{{ matrixCallStateLabel }}</span>
|
<template v-if="matrixCallPrimaryTile">
|
||||||
</div>
|
<video
|
||||||
<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">
|
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
|
<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"
|
: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' : ''"
|
:class="tile.speaking ? 'ring-2 ring-primary' : ''"
|
||||||
>
|
>
|
||||||
<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"
|
class="h-full min-h-28 w-full"
|
||||||
:class="tile.screenSharing ? 'object-contain bg-black' : 'object-cover'"
|
:class="tile.screenSharing ? 'object-contain bg-black' : 'object-cover'"
|
||||||
autoplay
|
autoplay
|
||||||
playsinline
|
playsinline
|
||||||
@@ -2341,37 +2409,59 @@ onBeforeUnmount(() => {
|
|||||||
/>
|
/>
|
||||||
<div
|
<div
|
||||||
v-else
|
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">
|
<span class="flex size-12 items-center justify-center rounded-lg bg-primary/15 text-lg font-semibold text-primary">
|
||||||
{{ (tile.name || tile.identity || "?").slice(0, 1).toUpperCase() }}
|
{{ participantInitial(tile) }}
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</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">
|
<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">
|
<span class="truncate">{{ tile.name }}</span>
|
||||||
{{ 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">
|
|
||||||
<UIcon
|
<UIcon
|
||||||
v-if="tile.screenSharing"
|
:name="tile.screenSharing ? 'i-heroicons-computer-desktop' : (tile.microphoneEnabled ? 'i-heroicons-microphone' : 'i-heroicons-microphone-slash')"
|
||||||
name="i-heroicons-computer-desktop"
|
class="size-3.5 shrink-0"
|
||||||
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"
|
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</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>
|
||||||
<div ref="matrixCallAudioContainer" class="hidden" />
|
<div ref="matrixCallAudioContainer" class="hidden" />
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
Reference in New Issue
Block a user