import { Pressable } from '@ankhorage/surface'; import React from 'react'; import type { ChatListAvatar, ChatListItemProps } from '../../../../types/chat'; import { Avatar } from '../../../avatar/public'; import { Badge } from '../../../badge/public'; import { View } from '../../../layout/public'; import { withZoraThemeScope } from '../../../theme/adapters/inbound/withZoraThemeScope'; import { useZoraTheme } from '../../../theme/composition/useZoraTheme'; import { Text } from '../../../typography/public'; function resolveAvatarName({ avatar, title, }: { avatar: ChatListAvatar | undefined; title: React.ReactNode; }): string | undefined { if (avatar?.name) { return avatar.name; } return typeof title === 'string' ? title : undefined; } function resolvePadding(compact: boolean) { return compact ? { px: 'm' as const, py: 's' as const } : { px: 'm' as const, py: 'm' as const }; } function resolveContainerStyles({ theme, selected, pressed, hovered, disabled, }: { theme: ReturnType['theme']; selected: boolean; pressed: boolean; hovered: boolean; disabled: boolean; }) { const borderColor = selected ? theme.semantics.border.focus : 'transparent'; return { bg: pressed ? theme.semantics.neutral.surfaceActive : hovered ? theme.semantics.neutral.surfaceHover : selected ? theme.semantics.neutral.surface : 'transparent', borderColor, borderWidth: selected ? 1 : 0, opacity: disabled ? 0.72 : 1, }; } function renderUnreadCount(unreadCount: React.ReactNode) { if (unreadCount == null) { return null; } return ( {unreadCount} ); } function ChatListItemInner({ themeId: _themeId, mode: _mode, interactionPolicy, testID, title, preview, meta, timestamp, avatar, leading, trailing, unread = false, unreadCount, selected = false, disabled = false, compact = false, accessibilityLabel, onPress, }: ChatListItemProps) { const { theme } = useZoraTheme(); const padding = resolvePadding(compact); const avatarName = resolveAvatarName({ avatar, title }); const isInteractive = Boolean(onPress); const hasTimestamp = timestamp != null; const hasPreview = preview != null; const hasMeta = meta != null; const hasTrailing = trailing != null; const hasUnreadCount = unreadCount != null; const hasSecondaryRow = hasPreview || hasMeta || hasUnreadCount || hasTrailing; const content = ({ pressed, hovered }: { pressed: boolean; hovered: boolean }) => { const styles = resolveContainerStyles({ theme, selected, pressed, hovered, disabled, }); return ( {leading ?? ( )} {title} {hasTimestamp ? ( {timestamp} ) : null} {hasSecondaryRow ? ( {hasPreview ? ( {preview} ) : null} {hasMeta ? ( {meta} ) : null} {hasUnreadCount || hasTrailing ? ( {renderUnreadCount(unreadCount)} {trailing} ) : null} ) : null} ); }; if (!isInteractive) { return {content({ pressed: false, hovered: false })}; } return ( {(state) => content({ pressed: state.pressed, hovered: state.hovered, }) } ); } /*** * Chat-style list row with avatar, title, preview text, and unread indicators. * */ export const ChatListItem = withZoraThemeScope(ChatListItemInner);