fix(dm): render system messages in sidebar preview instead of raw JSON
DmLastMessagePreview lacked a `type` field, so the sidebar rendered
`lastMessage.content` verbatim — surfacing JSON like
`{"event":"space_invite",...}` for space invites and member-add events.
Adds `type` to the preview payload (populated server-side from
`dm_messages.type`) and routes all sidebar call sites through a single
`formatDmSidebarPreview` helper that renders human-readable text for
each system event and skips the group `Sender:` prefix on system rows.
This commit is contained in:
@@ -2,7 +2,7 @@ import type { DmChannel, User } from '@backspace/shared';
|
||||
import { Avatar } from '../ui/Avatar';
|
||||
import { Tooltip } from '../ui/Tooltip';
|
||||
import { parseFederatedUsername, isSelf } from '../../utils/identity';
|
||||
import { formatDmTimestamp, formatDmPreview } from '../../utils/dmFormatters';
|
||||
import { formatDmTimestamp, formatDmSidebarPreview } from '../../utils/dmFormatters';
|
||||
import { getRejectedPeerOrigins, getAwaitingApprovalPeerOrigins } from '../../hooks/useWebSocket';
|
||||
|
||||
function isMemberUnreachable(homeInstance: string | null | undefined): boolean {
|
||||
@@ -98,19 +98,11 @@ export function DmListItem({ dm, isActive, isUnread, user, onSelect, onClose, on
|
||||
} text-txt-tertiary hover:text-txt-primary transition-opacity flex-shrink-0 ml-1`;
|
||||
|
||||
// ── Preview text ──────────────────────────────────────────────────────
|
||||
const preview = formatDmPreview(dm.lastMessage ?? null);
|
||||
let previewText: string | null = null;
|
||||
if (isGroup) {
|
||||
const lastMsg = dm.lastMessage;
|
||||
const senderName = (lastMsg && 'user' in lastMsg ? lastMsg.user?.displayName : undefined)
|
||||
?? dm.members.find(m => m.id === lastMsg?.userId)?.displayName
|
||||
?? 'Unknown';
|
||||
previewText = preview
|
||||
? `${senderName}: ${preview}`
|
||||
: `${dm.members.length} Members`;
|
||||
} else {
|
||||
previewText = preview;
|
||||
}
|
||||
// formatDmSidebarPreview handles user/system messages and applies the
|
||||
// sender prefix for group user-messages. We only need to provide the
|
||||
// empty-group fallback ourselves.
|
||||
const preview = formatDmSidebarPreview(dm, user);
|
||||
const previewText = preview ?? (isGroup ? `${dm.members.length} Members` : null);
|
||||
|
||||
const itemJsx = (
|
||||
<div
|
||||
|
||||
@@ -10,6 +10,7 @@ import { Mascot } from '../ui/Mascot';
|
||||
import { resolveAssetUrl } from '../../utils/assetUrls';
|
||||
import { useNavigate } from 'react-router-dom';
|
||||
import { parseFederatedUsername } from '../../utils/identity';
|
||||
import { formatDmSidebarPreview } from '../../utils/dmFormatters';
|
||||
|
||||
export function MobileDmsScreen() {
|
||||
const pushMobileScreen = useUIStore((s) => s.pushMobileScreen);
|
||||
@@ -151,11 +152,10 @@ export function MobileDmsScreen() {
|
||||
const readState = readStates.get(dm.id);
|
||||
const isUnread = lastMsgId && (!readState || readState < lastMsgId);
|
||||
|
||||
const preview = dm.lastMessage?.content;
|
||||
// formatDmSidebarPreview returns the full preview line (system messages
|
||||
// get human-readable text; group user-messages get the "Sender: " prefix).
|
||||
const preview = formatDmSidebarPreview(dm, authUser ?? null);
|
||||
const previewTime = dm.lastMessage?.createdAt;
|
||||
const previewSender = dm.lastMessage
|
||||
? dm.members.find(m => m.id === dm.lastMessage!.userId)
|
||||
: null;
|
||||
|
||||
const mainUser = otherMembers[0];
|
||||
const avatarUrl = mainUser?.avatar
|
||||
@@ -206,9 +206,7 @@ export function MobileDmsScreen() {
|
||||
})()}
|
||||
{preview && (
|
||||
<p className={`text-xs truncate mt-0.5 ${isUnread ? 'text-txt-secondary font-medium' : 'text-txt-tertiary'}`}>
|
||||
{previewSender && previewSender.id !== authUser?.id
|
||||
? `${previewSender.displayName ?? parseFederatedUsername(previewSender.username).baseName}: ${preview}`
|
||||
: preview}
|
||||
{preview}
|
||||
</p>
|
||||
)}
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user