feat(chat): redesign chat list + conversation view
- RoomCard / chat.tsx DmItem: cleaner list rows (48px avatar, minHeight 68, consistent padding, time next to name, TouchableOpacity) - ChatBubble: timestamp inline under content (no absolute-position hack), borderRadius 20, 28px avatar, lighter backdrop - ChatInput: surface bg, hairline-bordered input pill, 38px send button Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
7369912d60
commit
2dcff6408c
@ -3,7 +3,6 @@ import {
|
||||
View,
|
||||
Text,
|
||||
FlatList,
|
||||
Pressable,
|
||||
TouchableOpacity,
|
||||
ActivityIndicator,
|
||||
Image,
|
||||
@ -45,51 +44,51 @@ function DmItem({ conv, onPress }: { conv: DmConversation; onPress: () => void }
|
||||
const hasUnread = conv.unreadCount > 0;
|
||||
|
||||
return (
|
||||
<Pressable onPress={onPress} android_ripple={{ color: '#f5f5f5' }}>
|
||||
<TouchableOpacity onPress={onPress} activeOpacity={0.7}>
|
||||
<View style={styles.dmRow}>
|
||||
<View style={styles.dmAvatar}>
|
||||
{conv.partnerAvatar ? (
|
||||
<Image source={{ uri: conv.partnerAvatar }} style={styles.dmAvatarImg} />
|
||||
) : (
|
||||
<Text style={styles.dmAvatarInitials}>
|
||||
{conv.partnerName.slice(0, 2).toUpperCase()}
|
||||
</Text>
|
||||
<View style={styles.dmAvatar}>
|
||||
{conv.partnerAvatar ? (
|
||||
<Image source={{ uri: conv.partnerAvatar }} style={styles.dmAvatarImg} />
|
||||
) : (
|
||||
<Text style={styles.dmAvatarInitials}>
|
||||
{conv.partnerName.slice(0, 2).toUpperCase()}
|
||||
</Text>
|
||||
)}
|
||||
</View>
|
||||
<View style={styles.dmInfo}>
|
||||
<View style={styles.dmHeaderRow}>
|
||||
<Text style={styles.dmName} numberOfLines={1}>
|
||||
{conv.partnerName}
|
||||
</Text>
|
||||
<Text style={[styles.dmTime, { color: hasUnread ? '#007AFF' : colors.textMuted }]}>
|
||||
{formatTime(conv.lastMessageAt, t('chat.just_now'))}
|
||||
</Text>
|
||||
</View>
|
||||
<View style={styles.dmBottomRow}>
|
||||
<Text
|
||||
numberOfLines={1}
|
||||
style={[
|
||||
styles.dmLast,
|
||||
{
|
||||
fontFamily: hasUnread ? 'Nunito_600SemiBold' : 'Nunito_400Regular',
|
||||
color: hasUnread ? colors.text : colors.textMuted,
|
||||
},
|
||||
]}
|
||||
>
|
||||
{conv.isOwn ? `${t('chat.you')} ` : ''}
|
||||
{conv.lastMessage}
|
||||
</Text>
|
||||
{hasUnread && (
|
||||
<View style={styles.unreadBadge}>
|
||||
<Text style={styles.unreadBadgeText}>
|
||||
{conv.unreadCount > 99 ? '99+' : conv.unreadCount}
|
||||
</Text>
|
||||
</View>
|
||||
)}
|
||||
</View>
|
||||
<View style={styles.dmInfo}>
|
||||
<View style={styles.dmHeaderRow}>
|
||||
<Text style={styles.dmName} numberOfLines={1}>
|
||||
{conv.partnerName}
|
||||
</Text>
|
||||
<Text
|
||||
style={[styles.dmTime, { color: hasUnread ? '#007AFF' : '#a3a3a3' }]}
|
||||
>
|
||||
{formatTime(conv.lastMessageAt, t('chat.just_now'))}
|
||||
</Text>
|
||||
</View>
|
||||
<View style={styles.dmBottomRow}>
|
||||
<Text
|
||||
numberOfLines={1}
|
||||
style={[
|
||||
styles.dmLast,
|
||||
{
|
||||
fontFamily: hasUnread ? 'Nunito_600SemiBold' : 'Nunito_400Regular',
|
||||
color: hasUnread ? '#171717' : '#a3a3a3',
|
||||
},
|
||||
]}
|
||||
>
|
||||
{conv.isOwn ? t('chat.you') : ''}
|
||||
{conv.lastMessage}
|
||||
</Text>
|
||||
{hasUnread && (
|
||||
<View style={styles.unreadBadge}>
|
||||
<Text style={styles.unreadBadgeText}>{conv.unreadCount}</Text>
|
||||
</View>
|
||||
)}
|
||||
</View>
|
||||
</View>
|
||||
</View>
|
||||
</View>
|
||||
</Pressable>
|
||||
</TouchableOpacity>
|
||||
);
|
||||
}
|
||||
|
||||
@ -352,28 +351,29 @@ function makeStyles(colors: ReturnType<typeof useColors>) {
|
||||
marginTop: 12,
|
||||
},
|
||||
dmRow: {
|
||||
width: '100%',
|
||||
flexDirection: 'row',
|
||||
alignItems: 'center',
|
||||
paddingHorizontal: 14,
|
||||
paddingVertical: 11,
|
||||
paddingHorizontal: 16,
|
||||
paddingVertical: 12,
|
||||
backgroundColor: colors.bg,
|
||||
borderBottomWidth: StyleSheet.hairlineWidth,
|
||||
borderBottomColor: colors.border,
|
||||
minHeight: 68,
|
||||
},
|
||||
dmAvatar: {
|
||||
width: 42,
|
||||
height: 42,
|
||||
borderRadius: 21,
|
||||
width: 48,
|
||||
height: 48,
|
||||
borderRadius: 24,
|
||||
backgroundColor: colors.surfaceElevated,
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center',
|
||||
overflow: 'hidden',
|
||||
marginRight: 10,
|
||||
marginRight: 12,
|
||||
flexShrink: 0,
|
||||
},
|
||||
dmAvatarImg: { width: 42, height: 42 },
|
||||
dmAvatarImg: { width: 48, height: 48 },
|
||||
dmAvatarInitials: {
|
||||
fontSize: 13,
|
||||
fontSize: 15,
|
||||
fontFamily: 'Nunito_700Bold',
|
||||
color: colors.textMuted,
|
||||
},
|
||||
@ -384,13 +384,13 @@ function makeStyles(colors: ReturnType<typeof useColors>) {
|
||||
justifyContent: 'space-between',
|
||||
},
|
||||
dmName: {
|
||||
fontSize: 14,
|
||||
fontSize: 15,
|
||||
fontFamily: 'Nunito_700Bold',
|
||||
color: colors.text,
|
||||
flexShrink: 1,
|
||||
marginRight: 6,
|
||||
},
|
||||
dmTime: { fontSize: 11, fontFamily: 'Nunito_600SemiBold' },
|
||||
dmTime: { fontSize: 11, fontFamily: 'Nunito_500Medium' },
|
||||
dmBottomRow: {
|
||||
flexDirection: 'row',
|
||||
alignItems: 'center',
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
import { useState, useRef } from 'react';
|
||||
import { useState } from 'react';
|
||||
import {
|
||||
View,
|
||||
Text,
|
||||
@ -7,7 +7,6 @@ import {
|
||||
Image,
|
||||
StyleSheet,
|
||||
Modal,
|
||||
Alert,
|
||||
Platform,
|
||||
} from 'react-native';
|
||||
import * as Clipboard from 'expo-clipboard';
|
||||
@ -68,7 +67,6 @@ export function ChatBubble({
|
||||
const colors = useColors();
|
||||
const styles = makeStyles(colors);
|
||||
const [actionsOpen, setActionsOpen] = useState(false);
|
||||
const longPressTimer = useRef<ReturnType<typeof setTimeout> | null>(null);
|
||||
|
||||
const isImageOnly =
|
||||
!!msg.attachmentUrl && msg.attachmentType === 'image' && !msg.content && !msg.replyTo;
|
||||
@ -234,24 +232,25 @@ export function ChatBubble({
|
||||
<Text
|
||||
style={[
|
||||
styles.content,
|
||||
{ color: msg.isOwn ? '#ffffff' : '#171717', paddingRight: 48 },
|
||||
{ color: msg.isOwn ? '#ffffff' : colors.text },
|
||||
]}
|
||||
>
|
||||
{msg.content}
|
||||
</Text>
|
||||
)}
|
||||
|
||||
{/* Footer */}
|
||||
{/* Footer: timestamp + read-receipt inline below content */}
|
||||
{!isImageOnly && (
|
||||
<View style={styles.footer}>
|
||||
<View style={[styles.footer, { justifyContent: msg.isOwn ? 'flex-end' : 'flex-start' }]}>
|
||||
{msg.likesCount > 0 && (
|
||||
<View style={{ flexDirection: 'row', alignItems: 'center', marginRight: 3 }}>
|
||||
<Ionicons name="heart" size={9} color="#f87171" />
|
||||
<View style={{ flexDirection: 'row', alignItems: 'center', marginRight: 4 }}>
|
||||
<Ionicons name="heart" size={10} color="#f87171" />
|
||||
<Text
|
||||
style={{
|
||||
fontSize: 9,
|
||||
marginLeft: 1,
|
||||
color: msg.isOwn ? 'rgba(255,255,255,0.7)' : '#a3a3a3',
|
||||
fontSize: 10,
|
||||
marginLeft: 2,
|
||||
fontFamily: 'Nunito_600SemiBold',
|
||||
color: msg.isOwn ? 'rgba(255,255,255,0.75)' : '#a3a3a3',
|
||||
}}
|
||||
>
|
||||
{msg.likesCount}
|
||||
@ -260,8 +259,9 @@ export function ChatBubble({
|
||||
)}
|
||||
<Text
|
||||
style={{
|
||||
fontSize: 9,
|
||||
color: msg.isOwn ? 'rgba(255,255,255,0.65)' : '#a3a3a3',
|
||||
fontSize: 10,
|
||||
fontFamily: 'Nunito_400Regular',
|
||||
color: msg.isOwn ? 'rgba(255,255,255,0.7)' : colors.textMuted,
|
||||
}}
|
||||
>
|
||||
{formatTime(msg.createdAt)}
|
||||
@ -269,9 +269,9 @@ export function ChatBubble({
|
||||
{msg.isOwn && !hideReadStatus && (
|
||||
<Ionicons
|
||||
name={msg.readAt ? 'checkmark-done' : 'checkmark'}
|
||||
size={11}
|
||||
color={msg.readAt ? '#93c5fd' : 'rgba(255,255,255,0.65)'}
|
||||
style={{ marginLeft: 2 }}
|
||||
size={12}
|
||||
color={msg.readAt ? '#93c5fd' : 'rgba(255,255,255,0.7)'}
|
||||
style={{ marginLeft: 3 }}
|
||||
/>
|
||||
)}
|
||||
</View>
|
||||
@ -335,36 +335,37 @@ function makeStyles(colors: ReturnType<typeof useColors>) {
|
||||
return StyleSheet.create({
|
||||
row: {
|
||||
flexDirection: 'row',
|
||||
paddingHorizontal: 8,
|
||||
paddingHorizontal: 10,
|
||||
},
|
||||
avatarSlot: {
|
||||
width: 30,
|
||||
marginRight: 4,
|
||||
width: 32,
|
||||
marginRight: 6,
|
||||
justifyContent: 'flex-end',
|
||||
},
|
||||
avatar: {
|
||||
width: 26,
|
||||
height: 26,
|
||||
borderRadius: 13,
|
||||
width: 28,
|
||||
height: 28,
|
||||
borderRadius: 14,
|
||||
backgroundColor: colors.surfaceElevated,
|
||||
},
|
||||
bubbleCol: {
|
||||
maxWidth: '78%',
|
||||
maxWidth: '76%',
|
||||
},
|
||||
nickname: {
|
||||
fontSize: 10,
|
||||
fontSize: 11,
|
||||
fontFamily: 'Nunito_700Bold',
|
||||
color: '#007AFF',
|
||||
marginBottom: 2,
|
||||
marginLeft: 10,
|
||||
marginBottom: 3,
|
||||
marginLeft: 12,
|
||||
},
|
||||
bubble: {
|
||||
borderRadius: 18,
|
||||
paddingHorizontal: 12,
|
||||
paddingVertical: 6,
|
||||
borderRadius: 20,
|
||||
paddingHorizontal: 14,
|
||||
paddingTop: 8,
|
||||
paddingBottom: 6,
|
||||
shadowColor: '#000',
|
||||
shadowOpacity: 0.05,
|
||||
shadowRadius: 1,
|
||||
shadowOpacity: 0.06,
|
||||
shadowRadius: 2,
|
||||
shadowOffset: { width: 0, height: 1 },
|
||||
},
|
||||
bubbleOwn: {
|
||||
@ -380,10 +381,10 @@ function makeStyles(colors: ReturnType<typeof useColors>) {
|
||||
borderRadius: 8,
|
||||
paddingHorizontal: 8,
|
||||
paddingVertical: 4,
|
||||
marginBottom: 4,
|
||||
marginBottom: 6,
|
||||
},
|
||||
imageWrap: {
|
||||
borderRadius: 12,
|
||||
borderRadius: 14,
|
||||
overflow: 'hidden',
|
||||
position: 'relative',
|
||||
},
|
||||
@ -405,27 +406,26 @@ function makeStyles(colors: ReturnType<typeof useColors>) {
|
||||
},
|
||||
content: {
|
||||
fontSize: 14,
|
||||
lineHeight: 20,
|
||||
lineHeight: 21,
|
||||
fontFamily: 'Nunito_400Regular',
|
||||
},
|
||||
footer: {
|
||||
position: 'absolute',
|
||||
bottom: 4,
|
||||
right: 8,
|
||||
flexDirection: 'row',
|
||||
alignItems: 'center',
|
||||
gap: 3,
|
||||
marginTop: 4,
|
||||
},
|
||||
sheetBackdrop: {
|
||||
flex: 1,
|
||||
backgroundColor: 'rgba(0,0,0,0.5)',
|
||||
backgroundColor: 'rgba(0,0,0,0.35)',
|
||||
justifyContent: 'flex-end',
|
||||
},
|
||||
sheet: {
|
||||
backgroundColor: colors.bg,
|
||||
borderTopLeftRadius: 20,
|
||||
borderTopRightRadius: 20,
|
||||
borderTopLeftRadius: 22,
|
||||
borderTopRightRadius: 22,
|
||||
padding: 8,
|
||||
paddingBottom: Platform.OS === 'ios' ? 32 : 16,
|
||||
paddingBottom: Platform.OS === 'ios' ? 34 : 16,
|
||||
},
|
||||
sheetGrabber: {
|
||||
width: 36,
|
||||
|
||||
@ -240,7 +240,7 @@ function decodeBase64(base64: string): Uint8Array {
|
||||
function makeStyles(colors: ReturnType<typeof useColors>) {
|
||||
return StyleSheet.create({
|
||||
container: {
|
||||
backgroundColor: colors.bg,
|
||||
backgroundColor: colors.surface,
|
||||
borderTopWidth: StyleSheet.hairlineWidth,
|
||||
borderTopColor: colors.border,
|
||||
},
|
||||
@ -315,24 +315,26 @@ function makeStyles(colors: ReturnType<typeof useColors>) {
|
||||
},
|
||||
inputWrap: {
|
||||
flex: 1,
|
||||
backgroundColor: colors.surfaceElevated,
|
||||
backgroundColor: colors.bg,
|
||||
borderRadius: 22,
|
||||
borderWidth: StyleSheet.hairlineWidth,
|
||||
borderColor: colors.border,
|
||||
paddingHorizontal: 14,
|
||||
minHeight: 36,
|
||||
minHeight: 38,
|
||||
maxHeight: 120,
|
||||
justifyContent: 'center',
|
||||
},
|
||||
input: {
|
||||
fontSize: 14,
|
||||
lineHeight: 19,
|
||||
fontSize: 15,
|
||||
lineHeight: 20,
|
||||
fontFamily: 'Nunito_400Regular',
|
||||
color: colors.text,
|
||||
paddingVertical: Platform.OS === 'ios' ? 8 : 4,
|
||||
paddingVertical: Platform.OS === 'ios' ? 9 : 5,
|
||||
},
|
||||
sendBtn: {
|
||||
width: 36,
|
||||
height: 36,
|
||||
borderRadius: 18,
|
||||
width: 38,
|
||||
height: 38,
|
||||
borderRadius: 19,
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center',
|
||||
marginLeft: 6,
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
import { View, Text, Pressable, Image, StyleSheet } from 'react-native';
|
||||
import { View, Text, TouchableOpacity, Image, StyleSheet } from 'react-native';
|
||||
import { Ionicons } from '@expo/vector-icons';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { useColors } from '../../lib/theme';
|
||||
@ -39,25 +39,21 @@ export function RoomCard({ room, onPress }: Props) {
|
||||
.join('');
|
||||
|
||||
return (
|
||||
<Pressable onPress={onPress} android_ripple={{ color: '#f5f5f5' }}>
|
||||
<TouchableOpacity onPress={onPress} activeOpacity={0.7}>
|
||||
<View style={styles.row}>
|
||||
<View
|
||||
style={[
|
||||
styles.avatar,
|
||||
{ backgroundColor: room.isPublic ? colors.surface : colors.surfaceElevated },
|
||||
]}
|
||||
>
|
||||
{room.avatarUrl ? (
|
||||
<Image source={{ uri: room.avatarUrl }} style={styles.avatarImg} />
|
||||
) : !room.isPublic ? (
|
||||
<Text style={styles.avatarInitials}>{initials}</Text>
|
||||
) : (
|
||||
<Ionicons name="globe-outline" size={20} color="#007AFF" />
|
||||
)}
|
||||
</View>
|
||||
<View style={[styles.avatar, { backgroundColor: room.isPublic ? '#EFF6FF' : colors.surfaceElevated }]}>
|
||||
{room.avatarUrl ? (
|
||||
<Image source={{ uri: room.avatarUrl }} style={styles.avatarImg} />
|
||||
) : !room.isPublic ? (
|
||||
<Text style={styles.avatarInitials}>{initials}</Text>
|
||||
) : (
|
||||
<Ionicons name="people" size={22} color="#3B82F6" />
|
||||
)}
|
||||
</View>
|
||||
|
||||
<View style={styles.info}>
|
||||
<View style={styles.headerRow}>
|
||||
<View style={styles.info}>
|
||||
<View style={styles.headerRow}>
|
||||
<View style={styles.nameWrap}>
|
||||
<Text style={styles.name} numberOfLines={1}>
|
||||
{room.name}
|
||||
</Text>
|
||||
@ -66,29 +62,32 @@ export function RoomCard({ room, onPress }: Props) {
|
||||
<Text style={styles.defaultBadgeText}>Standard</Text>
|
||||
</View>
|
||||
)}
|
||||
</View>
|
||||
<View style={styles.metaRight}>
|
||||
{room.lastMessage && (
|
||||
<Text style={styles.time}>
|
||||
{formatTime(room.lastMessage.createdAt, t('chat.just_now'))}
|
||||
</Text>
|
||||
)}
|
||||
</View>
|
||||
<View style={styles.footerRow}>
|
||||
<View style={styles.footerTextWrap}>
|
||||
{room.lastMessage ? (
|
||||
<Text style={styles.lastMessage} numberOfLines={1}>
|
||||
<Text style={{ fontFamily: 'Nunito_700Bold' }}>
|
||||
{room.lastMessage.senderName}:{' '}
|
||||
</Text>
|
||||
{room.lastMessage.content}
|
||||
</Text>
|
||||
) : room.description ? (
|
||||
<Text style={styles.description} numberOfLines={1}>
|
||||
{room.description}
|
||||
</Text>
|
||||
) : null}
|
||||
</View>
|
||||
</View>
|
||||
|
||||
<View style={styles.footerRow}>
|
||||
<View style={styles.footerTextWrap}>
|
||||
{room.lastMessage ? (
|
||||
<Text style={styles.lastMessage} numberOfLines={1}>
|
||||
<Text style={styles.senderName}>{room.lastMessage.senderName}: </Text>
|
||||
{room.lastMessage.content}
|
||||
</Text>
|
||||
) : room.description ? (
|
||||
<Text style={styles.description} numberOfLines={1}>
|
||||
{room.description}
|
||||
</Text>
|
||||
) : null}
|
||||
</View>
|
||||
<View style={styles.footerRight}>
|
||||
<View style={styles.metaPill}>
|
||||
<Ionicons name="people" size={11} color="#a3a3a3" />
|
||||
<Ionicons name="people" size={10} color={colors.textMuted} />
|
||||
<Text style={styles.memberCount}>{room.memberCount}</Text>
|
||||
</View>
|
||||
{!room.isMember && (
|
||||
@ -98,38 +97,40 @@ export function RoomCard({ room, onPress }: Props) {
|
||||
)}
|
||||
</View>
|
||||
</View>
|
||||
</View>
|
||||
</View>
|
||||
</Pressable>
|
||||
</TouchableOpacity>
|
||||
);
|
||||
}
|
||||
|
||||
function makeStyles(colors: ReturnType<typeof useColors>) {
|
||||
return StyleSheet.create({
|
||||
row: {
|
||||
width: '100%',
|
||||
flexDirection: 'row',
|
||||
alignItems: 'center',
|
||||
paddingHorizontal: 14,
|
||||
paddingVertical: 11,
|
||||
paddingHorizontal: 16,
|
||||
paddingVertical: 12,
|
||||
backgroundColor: colors.bg,
|
||||
borderBottomWidth: StyleSheet.hairlineWidth,
|
||||
borderBottomColor: colors.border,
|
||||
minHeight: 68,
|
||||
},
|
||||
avatar: {
|
||||
width: 42,
|
||||
height: 42,
|
||||
borderRadius: 21,
|
||||
width: 48,
|
||||
height: 48,
|
||||
borderRadius: 24,
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center',
|
||||
overflow: 'hidden',
|
||||
marginRight: 10,
|
||||
marginRight: 12,
|
||||
flexShrink: 0,
|
||||
},
|
||||
avatarImg: {
|
||||
width: 42,
|
||||
height: 42,
|
||||
width: 48,
|
||||
height: 48,
|
||||
},
|
||||
avatarInitials: {
|
||||
fontSize: 13,
|
||||
fontSize: 15,
|
||||
fontFamily: 'Nunito_700Bold',
|
||||
color: colors.textMuted,
|
||||
},
|
||||
@ -140,79 +141,93 @@ function makeStyles(colors: ReturnType<typeof useColors>) {
|
||||
headerRow: {
|
||||
flexDirection: 'row',
|
||||
alignItems: 'center',
|
||||
marginBottom: 3,
|
||||
},
|
||||
nameWrap: {
|
||||
flex: 1,
|
||||
flexDirection: 'row',
|
||||
alignItems: 'center',
|
||||
gap: 6,
|
||||
minWidth: 0,
|
||||
},
|
||||
metaRight: {
|
||||
marginLeft: 8,
|
||||
flexShrink: 0,
|
||||
},
|
||||
footerRow: {
|
||||
flexDirection: 'row',
|
||||
alignItems: 'center',
|
||||
marginTop: 3,
|
||||
},
|
||||
footerTextWrap: {
|
||||
flex: 1,
|
||||
minWidth: 0,
|
||||
},
|
||||
metaPill: {
|
||||
footerRight: {
|
||||
flexDirection: 'row',
|
||||
alignItems: 'center',
|
||||
gap: 6,
|
||||
marginLeft: 8,
|
||||
paddingHorizontal: 6,
|
||||
paddingVertical: 2,
|
||||
borderRadius: 8,
|
||||
backgroundColor: colors.surfaceElevated,
|
||||
flexShrink: 0,
|
||||
},
|
||||
name: {
|
||||
fontSize: 14,
|
||||
fontSize: 15,
|
||||
fontFamily: 'Nunito_700Bold',
|
||||
color: colors.text,
|
||||
flexShrink: 1,
|
||||
},
|
||||
defaultBadge: {
|
||||
marginLeft: 6,
|
||||
paddingHorizontal: 6,
|
||||
paddingVertical: 1,
|
||||
backgroundColor: colors.surface,
|
||||
borderRadius: 8,
|
||||
paddingVertical: 2,
|
||||
backgroundColor: '#EFF6FF',
|
||||
borderRadius: 6,
|
||||
flexShrink: 0,
|
||||
},
|
||||
defaultBadgeText: {
|
||||
fontSize: 9,
|
||||
fontFamily: 'Nunito_700Bold',
|
||||
color: '#007AFF',
|
||||
color: '#3B82F6',
|
||||
},
|
||||
lastMessage: {
|
||||
fontSize: 12,
|
||||
fontSize: 13,
|
||||
fontFamily: 'Nunito_400Regular',
|
||||
color: colors.textMuted,
|
||||
},
|
||||
senderName: {
|
||||
fontFamily: 'Nunito_600SemiBold',
|
||||
color: colors.textMuted,
|
||||
},
|
||||
description: {
|
||||
fontSize: 12,
|
||||
fontSize: 13,
|
||||
fontFamily: 'Nunito_400Regular',
|
||||
color: colors.textMuted,
|
||||
},
|
||||
right: {
|
||||
alignItems: 'flex-end',
|
||||
marginLeft: 8,
|
||||
metaPill: {
|
||||
flexDirection: 'row',
|
||||
alignItems: 'center',
|
||||
gap: 3,
|
||||
paddingHorizontal: 6,
|
||||
paddingVertical: 3,
|
||||
borderRadius: 8,
|
||||
backgroundColor: colors.surfaceElevated,
|
||||
},
|
||||
memberCount: {
|
||||
fontSize: 11,
|
||||
fontFamily: 'Nunito_700Bold',
|
||||
color: colors.textMuted,
|
||||
marginLeft: 3,
|
||||
},
|
||||
time: {
|
||||
fontSize: 10,
|
||||
fontSize: 11,
|
||||
fontFamily: 'Nunito_500Medium',
|
||||
color: colors.textMuted,
|
||||
marginLeft: 'auto',
|
||||
paddingLeft: 6,
|
||||
},
|
||||
joinBadge: {
|
||||
marginLeft: 6,
|
||||
paddingHorizontal: 8,
|
||||
paddingVertical: 3,
|
||||
backgroundColor: colors.surface,
|
||||
backgroundColor: '#EFF6FF',
|
||||
borderRadius: 10,
|
||||
},
|
||||
joinBadgeText: {
|
||||
fontSize: 10,
|
||||
fontSize: 11,
|
||||
fontFamily: 'Nunito_700Bold',
|
||||
color: '#007AFF',
|
||||
},
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user