diff --git a/apps/desktop/src/components/MessageBubble.tsx b/apps/desktop/src/components/MessageBubble.tsx
index 2557f3d..4862c75 100644
--- a/apps/desktop/src/components/MessageBubble.tsx
+++ b/apps/desktop/src/components/MessageBubble.tsx
@@ -294,7 +294,14 @@ export function MessageBubble({
}
if (parsed.kind === 'call_event') {
- return ;
+ return (
+
+ );
}
return (
@@ -866,10 +873,15 @@ function CallEventRow({
parsed,
mine,
time,
+ senderDisplayName,
}: {
parsed: { status: string; mediaKind: string; durationSec: number };
mine: boolean;
time: string;
+ /** Discord-parity: in group chats the system pill should say WHO
+ * started/missed the call. Null means we don't know (fall back to the
+ * legacy generic labels). */
+ senderDisplayName: string | null;
}) {
const { t } = useTranslation(['app']);
const status = parsed.status;
@@ -880,16 +892,36 @@ function CallEventRow({
? 'border-rose-500/30 bg-rose-500/10 text-rose-700 dark:text-rose-200'
: 'border-emerald-500/30 bg-emerald-500/10 text-emerald-700 dark:text-emerald-200';
+ // For non-own events we prefer the name-aware label so group chats
+ // make it clear who triggered the call event. Own events stay generic
+ // ("Outgoing call" / "No answer") since the user already knows they
+ // were the initiator.
+ const hasName = !mine && !!senderDisplayName;
const label =
status === 'ended'
? mine
? t('app:chats.call_outgoing', { defaultValue: 'Outgoing call' })
- : t('app:chats.call_incoming', { defaultValue: 'Incoming call' })
+ : hasName
+ ? t('app:chats.call_started_by', {
+ name: senderDisplayName,
+ defaultValue: '{{name}} hat einen Anruf gestartet',
+ })
+ : t('app:chats.call_incoming', { defaultValue: 'Incoming call' })
: status === 'missed'
? mine
? t('app:chats.call_no_answer', { defaultValue: 'No answer' })
- : t('app:chats.call_missed', { defaultValue: 'Missed call' })
- : t('app:chats.call_declined', { defaultValue: 'Call declined' });
+ : hasName
+ ? t('app:chats.call_missed_by', {
+ name: senderDisplayName,
+ defaultValue: 'Verpasster Anruf von {{name}}',
+ })
+ : t('app:chats.call_missed', { defaultValue: 'Missed call' })
+ : hasName
+ ? t('app:chats.call_declined_by', {
+ name: senderDisplayName,
+ defaultValue: 'Anruf von {{name}} abgelehnt',
+ })
+ : t('app:chats.call_declined', { defaultValue: 'Call declined' });
const duration = parsed.durationSec > 0 ? formatDuration(parsed.durationSec) : null;