import React, { useMemo } from 'react'; import { useUIStore } from '../../stores/uiStore'; import { useSpaceStore } from '../../stores/spaceStore'; import { useChatStore } from '../../stores/chatStore'; import { useAuthStore } from '../../stores/authStore'; import { useSocialStore } from '../../stores/socialStore'; import { Avatar } from '../ui/Avatar'; import { resolveAssetUrl } from '../../utils/assetUrls'; import { useNavigate } from 'react-router-dom'; export function MobileDmsScreen() { const pushMobileScreen = useUIStore((s) => s.pushMobileScreen); const openModal = useUIStore((s) => s.openModal); const dmChannels = useSpaceStore((s) => s.dmChannels); const readStates = useChatStore((s) => s.readStates); const authUser = useAuthStore((s) => s.user); const friends = useSocialStore((s) => s.friends); const navigate = useNavigate(); // Online friends for the activity row const onlineFriends = useMemo(() => friends.filter(f => f.status === 'online' || f.status === 'idle' || f.status === 'dnd'), [friends] ); // Sort DMs by last message time (newest first) const sortedDms = useMemo(() => [...dmChannels].sort((a, b) => { const aTime = a.lastMessage?.createdAt ?? a.createdAt; const bTime = b.lastMessage?.createdAt ?? b.createdAt; return bTime - aTime; }), [dmChannels] ); const handleDmTap = (dmId: string) => { navigate(`/channels/@me/${dmId}`); pushMobileScreen('channel-chat', { channelId: dmId, spaceId: '@me' }); }; const formatTimestamp = (ts: number): string => { const now = Date.now(); const diff = now - ts; if (diff < 60_000) return 'now'; if (diff < 3600_000) return `${Math.floor(diff / 60_000)}m`; if (diff < 86400_000) return `${Math.floor(diff / 3600_000)}h`; if (diff < 604800_000) return `${Math.floor(diff / 86400_000)}d`; return new Date(ts).toLocaleDateString(undefined, { month: 'short', day: 'numeric' }); }; return (
{/* Header */}

Messages

{/* Activity row — online friends */} {onlineFriends.length > 0 && (
{onlineFriends.map(friend => { const avatarUrl = friend.avatar ? resolveAssetUrl(friend.avatar, friend._instanceOrigin) ?? `/api/uploads/${friend.avatar}` : null; return ( ); })}
)} {/* DM list */}
{sortedDms.map(dm => { const otherMembers = dm.members.filter(m => m.id !== authUser?.id); const isGroup = dm.members.length > 2; const name = isGroup ? otherMembers.map(m => m.displayName ?? m.username).join(', ') : otherMembers[0]?.displayName ?? otherMembers[0]?.username ?? 'Unknown'; const lastMsgId = dm.lastMessage?.id; const readState = readStates.get(dm.id); const isUnread = lastMsgId && (!readState || readState < lastMsgId); const preview = dm.lastMessage?.content; 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 ? `/api/uploads/${mainUser.avatar}` : null; return ( ); })} {sortedDms.length === 0 && (
No conversations yet
)}
{/* FAB — New DM */}
); }