Enhance swipe UI and add chat date separators

This commit is contained in:
jjbrunton committed 2026-01-03 18:37:18 +00:00
1 parent 7e686c147a
commit a567fba349
12 files changed
+507 -286

No files matched your search

+1 -1
View File
@@ -282,7 +282,7 @@ export const ChatScreen: React.FC = () => {
user={user}
match={match}
insets={insets}
onBack={() => router.back()}
onBack={() => router.push('/(app)/matches')}
/>
<ChatMessages
@@ -5,6 +5,7 @@ import Animated, { FadeIn } from 'react-native-reanimated';
import { MessageBubble } from './MessageBubble';
import { MessageContent } from './MessageContent';
import { DateSeparator } from './DateSeparator';
import { UploadProgress } from './UploadProgress';
import { TypingIndicator } from './TypingIndicator';
import { DecorativeSeparator } from '../../../components/ui';
@@ -29,6 +30,17 @@ interface ChatMessagesProps {
const ACCENT = colors.premium.gold;
const ACCENT_RGBA = 'rgba(212, 175, 55, ';
/**
* Check if two dates are on the same calendar day
*/
function isSameDay(date1: Date, date2: Date): boolean {
return (
date1.getFullYear() === date2.getFullYear() &&
date1.getMonth() === date2.getMonth() &&
date1.getDate() === date2.getDate()
);
}
export const ChatMessages: React.FC<ChatMessagesProps> = ({
messages,
userId,
@@ -43,22 +55,35 @@ export const ChatMessages: React.FC<ChatMessagesProps> = ({
const renderMessage = ({ item, index }: { item: Message; index: number }) => {
const isMe = item.user_id === userId;
const messageDate = new Date(item.created_at!);
// Determine if we should show a date separator above this message
// In an inverted list, index 0 is newest (bottom), higher indices are older (top)
// Show separator when this message's date differs from the next (older) message
const nextMessage = messages[index + 1];
const showDateSeparator = !nextMessage || (
nextMessage.created_at &&
!isSameDay(messageDate, new Date(nextMessage.created_at))
);
return (
<MessageBubble
isMe={isMe}
index={index}
onLongPress={() => onMessageLongPress(item, isMe)}
>
<MessageContent
item={item}
<>
<MessageBubble
isMe={isMe}
currentUserId={userId || ''}
revealMessage={revealMessage}
onImagePress={onImagePress}
onVideoFullScreen={onVideoFullScreen}
index={index}
onLongPress={() => onMessageLongPress(item, isMe)}
/>
</MessageBubble>
>
<MessageContent
item={item}
isMe={isMe}
currentUserId={userId || ''}
revealMessage={revealMessage}
onImagePress={onImagePress}
onVideoFullScreen={onVideoFullScreen}
/>
</MessageBubble>
{showDateSeparator && <DateSeparator date={messageDate} />}
</>
);
};
@@ -0,0 +1,84 @@
import React from 'react';
import { View, Text, StyleSheet } from 'react-native';
import { colors, spacing, typography, radius } from '../../../theme';
interface DateSeparatorProps {
date: Date;
}
/**
* Formats a date for display in chat, similar to WhatsApp/Signal:
* - "Today" for today's date
* - "Yesterday" for yesterday
* - "Monday" through "Saturday" for the past week
* - "Jan 3, 2024" for older dates
*/
function formatDateLabel(date: Date): string {
const now = new Date();
const today = new Date(now.getFullYear(), now.getMonth(), now.getDate());
const messageDate = new Date(date.getFullYear(), date.getMonth(), date.getDate());
const diffTime = today.getTime() - messageDate.getTime();
const diffDays = Math.floor(diffTime / (1000 * 60 * 60 * 24));
if (diffDays === 0) {
return 'Today';
}
if (diffDays === 1) {
return 'Yesterday';
}
// Within the last week, show day name
if (diffDays < 7) {
return date.toLocaleDateString(undefined, { weekday: 'long' });
}
// Same year - show "Jan 3"
if (date.getFullYear() === now.getFullYear()) {
return date.toLocaleDateString(undefined, {
month: 'short',
day: 'numeric'
});
}
// Different year - show "Jan 3, 2024"
return date.toLocaleDateString(undefined, {
month: 'short',
day: 'numeric',
year: 'numeric'
});
}
export const DateSeparator: React.FC<DateSeparatorProps> = ({ date }) => {
const label = formatDateLabel(date);
return (
<View style={styles.container}>
<View style={styles.pill}>
<Text style={styles.text}>{label}</Text>
</View>
</View>
);
};
const styles = StyleSheet.create({
container: {
alignItems: 'center',
justifyContent: 'center',
paddingVertical: spacing.md,
},
pill: {
backgroundColor: colors.glass.background,
borderRadius: radius.full,
paddingHorizontal: spacing.md,
paddingVertical: spacing.xs + 2,
borderWidth: 1,
borderColor: colors.glass.border,
},
text: {
...typography.caption1,
color: colors.textSecondary,
textAlign: 'center',
},
});