mirror of
https://github.com/jjbrunton/Sauci.git
synced 2026-11-01 18:19:43 +00:00
Enhance swipe UI and add chat date separators
This commit is contained in:
1 parent
7e686c147a
commit
a567fba349
12 files changed
+507
-286
No files matched your search
@@ -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',
|
||||
},
|
||||
});
|
||||
Reference in new issue
Block a user