Add dates (#10)

This commit is contained in:
Alex
2020-10-19 00:18:23 +02:00
committed by GitHub
parent db837b9270
commit 5398785e73
10 changed files with 116 additions and 37 deletions

View File

@@ -2,11 +2,11 @@ import { MessageType, Size, User } from '../src/types'
export const fileMessage: MessageType.File = {
authorId: 'userId',
id: 'uuidv4',
fileName: 'flyer.pdf',
id: 'file-uuidv4',
mimeType: 'application/pdf',
name: 'flyer.pdf',
size: 15000,
timestamp: 0,
timestamp: 2000000,
type: 'file',
url: 'file:///Users/admin/flyer.pdf',
}
@@ -14,7 +14,9 @@ export const fileMessage: MessageType.File = {
export const imageMessage: MessageType.Image = {
authorId: 'userId',
height: 100,
id: 'uuidv4',
id: 'image-uuidv4',
imageName: 'imageName',
size: 15000,
timestamp: 0,
type: 'image',
url: 'https://avatars1.githubusercontent.com/u/59206044',

View File

@@ -23,6 +23,7 @@
"dependencies": {
"@flyerhq/react-native-keyboard-accessory-view": "^1.5.1",
"@flyerhq/react-native-link-preview": "^1.0.2",
"dayjs": "^1.9.1",
"react-native-image-viewing": "^0.2.0",
"react-native-parsed-text": "^0.0.22"
},

View File

@@ -2,6 +2,8 @@ import {
useComponentSize,
usePanResponder,
} from '@flyerhq/react-native-keyboard-accessory-view'
import dayjs from 'dayjs'
import calendar from 'dayjs/plugin/calendar'
import * as React from 'react'
import {
FlatList,
@@ -10,6 +12,7 @@ import {
StatusBar,
StatusBarProps,
StyleSheet,
Text,
View,
} from 'react-native'
import ImageView from 'react-native-image-viewing'
@@ -19,6 +22,8 @@ import { Input, InputAdditionalProps, InputTopLevelProps } from '../Input'
import { Message, MessageTopLevelProps } from '../Message'
import styles from './styles'
dayjs.extend(calendar)
export type ChatTopLevelProps = InputTopLevelProps & MessageTopLevelProps
export interface ChatProps extends ChatTopLevelProps {
@@ -92,22 +97,64 @@ export const Chat = ({
index: number
}) => {
const messageWidth = Math.floor(Math.min(size.width * 0.77, 440))
const previousMessageSameAuthor =
messages[index - 1]?.authorId === message.authorId
// TODO: Update the logic after pagination is introduced
const isFirst = index === 0
const isLast = index === messages.length - 1
const previousMessage = messages[index - 1]
const nextMessage = messages[index + 1]
let nextMessageDifferentDay = false
let nextMessageSameAuthor = false
let previousMessageSameAuthor = false
let previousMessageWithinTimeRange = false
if (!isLast) {
nextMessageDifferentDay = !dayjs
.unix(message.timestamp)
.isSame(dayjs.unix(nextMessage.timestamp), 'day')
nextMessageSameAuthor = nextMessage.authorId === message.authorId
}
if (!isFirst) {
previousMessageSameAuthor = previousMessage.authorId === message.authorId
previousMessageWithinTimeRange =
previousMessageSameAuthor &&
previousMessage.timestamp - message.timestamp < 3600
}
return (
<Message
{...{
message,
messageWidth,
onFilePress,
onImagePress: handleImagePress,
previousMessageSameAuthor,
renderFileMessage,
renderImageMessage,
renderTextMessage,
}}
/>
<>
<Message
{...{
message,
messageWidth,
onFilePress,
onImagePress: handleImagePress,
previousMessageSameAuthor,
previousMessageWithinTimeRange,
renderFileMessage,
renderImageMessage,
renderTextMessage,
}}
/>
{(nextMessageDifferentDay || isLast) && (
<Text
style={StyleSheet.flatten([
styles.dateDivider,
{ marginTop: nextMessageSameAuthor ? 24 : 16 },
])}
>
{dayjs.unix(message.timestamp).calendar(undefined, {
sameDay: '[Today]',
nextDay: 'DD MMMM',
nextWeek: 'DD MMMM',
lastDay: '[Yesterday]',
lastWeek: 'DD MMMM',
sameElse: 'DD MMMM',
})}
</Text>
)}
</>
)
}

View File

@@ -11,7 +11,7 @@ import { Chat } from '../Chat'
describe('chat', () => {
it('renders image preview', async () => {
expect.assertions(1)
const messages = [imageMessage]
const messages = [textMessage, fileMessage, imageMessage]
const onSendPress = jest.fn()
const { getByRole, getByText } = render(
<Chat messages={messages} onSendPress={onSendPress} user={user} />
@@ -25,7 +25,7 @@ describe('chat', () => {
it('sends a text message', () => {
expect.assertions(1)
const messages = [textMessage]
const messages = [textMessage, fileMessage, imageMessage]
const onSendPress = jest.fn()
const { getByLabelText } = render(
<Chat
@@ -42,7 +42,7 @@ describe('chat', () => {
it('opens file on a file message tap', () => {
expect.assertions(1)
const messages = [fileMessage]
const messages = [textMessage, fileMessage, imageMessage]
const onSendPress = jest.fn()
const onFilePress = jest.fn()
const { getByLabelText } = render(

View File

@@ -4,8 +4,16 @@ export default StyleSheet.create({
container: {
flex: 1,
},
dateDivider: {
color: '#1d1c21',
fontSize: 12,
fontWeight: 'bold',
lineHeight: 16,
marginBottom: 32,
textAlign: 'center',
},
footer: {
height: 24,
height: 16,
},
list: {
backgroundColor: '#fff',

View File

@@ -31,7 +31,6 @@ export const ImageMessage = ({
const aspectRatio = size.width / (size.height || 1)
const isMinimized = aspectRatio < 0.1 || aspectRatio > 10
const {
background,
image,
minimizedImage,
minimizedImageContainer,
@@ -80,11 +79,7 @@ export const ImageMessage = ({
</View>
</View>
) : (
<ImageBackground
blurRadius={26}
source={{ uri: message.url }}
style={background}
>
<ImageBackground blurRadius={26} source={{ uri: message.url }} style={{}}>
<TouchableWithoutFeedback onPress={handlePress}>
{renderImage()}
</TouchableWithoutFeedback>

View File

@@ -13,9 +13,6 @@ const styles = ({
user?: User
}) =>
StyleSheet.create({
background: {
flex: 1,
},
image: {
aspectRatio,
maxHeight: messageWidth,

View File

@@ -1,5 +1,6 @@
import dayjs from 'dayjs'
import * as React from 'react'
import { View } from 'react-native'
import { Text, View } from 'react-native'
import { MessageType } from '../../types'
import { UserContext } from '../../utils'
import { FileMessage } from '../FileMessage'
@@ -28,6 +29,7 @@ export interface MessageProps extends MessageTopLevelProps {
messageWidth: number
onImagePress: (url: string) => void
previousMessageSameAuthor: boolean
previousMessageWithinTimeRange: boolean
}
export const Message = ({
@@ -36,15 +38,17 @@ export const Message = ({
onFilePress,
onImagePress,
previousMessageSameAuthor,
previousMessageWithinTimeRange,
renderFileMessage,
renderImageMessage,
renderTextMessage,
}: MessageProps) => {
const user = React.useContext(UserContext)
const { container, contentContainer } = styles({
const { container, contentContainer, statusContainer, time } = styles({
message,
messageWidth,
previousMessageSameAuthor,
previousMessageWithinTimeRange,
user,
})
@@ -78,6 +82,13 @@ export const Message = ({
return (
<View style={container}>
<View style={contentContainer}>{renderMessage()}</View>
{!previousMessageWithinTimeRange && (
<View style={statusContainer}>
<Text style={time}>
{dayjs.unix(message.timestamp).format('h:mm a')}
</Text>
</View>
)}
</View>
)
}

View File

@@ -5,19 +5,22 @@ const styles = ({
message,
messageWidth,
previousMessageSameAuthor,
previousMessageWithinTimeRange,
user,
}: {
message: MessageType.Any
messageWidth: number
previousMessageSameAuthor: boolean
previousMessageWithinTimeRange: boolean
user?: User
}) =>
StyleSheet.create({
container: {
alignSelf: user?.id === message.authorId ? 'flex-end' : 'flex-start',
flex: 1,
flexDirection: 'row',
justifyContent: user?.id === message.authorId ? 'flex-end' : 'flex-start',
marginBottom: previousMessageSameAuthor ? 8 : 24,
marginBottom:
previousMessageSameAuthor || previousMessageWithinTimeRange ? 8 : 16,
marginHorizontal: 24,
},
contentContainer: {
backgroundColor:
@@ -27,10 +30,20 @@ const styles = ({
borderBottomLeftRadius: user?.id === message.authorId ? 20 : 0,
borderBottomRightRadius: user?.id === message.authorId ? 0 : 20,
borderRadius: 20,
marginHorizontal: 24,
maxWidth: messageWidth,
overflow: 'hidden',
},
statusContainer: {
alignSelf: 'flex-end',
marginRight: 8,
marginTop: 8,
},
time: {
color: '#9e9cab',
fontSize: 12,
fontWeight: '500',
lineHeight: 16,
},
})
export default styles

View File

@@ -2407,6 +2407,11 @@ dayjs@^1.8.15:
resolved "https://registry.yarnpkg.com/dayjs/-/dayjs-1.8.36.tgz#be36e248467afabf8f5a86bae0de0cdceecced50"
integrity sha512-3VmRXEtw7RZKAf+4Tv1Ym9AGeo8r8+CjDi26x+7SYQil1UqtqdaokhzoEJohqlzt0m5kacJSDhJQkG/LWhpRBw==
dayjs@^1.9.1:
version "1.9.1"
resolved "https://registry.yarnpkg.com/dayjs/-/dayjs-1.9.1.tgz#201a755f7db5103ed6de63ba93a984141c754541"
integrity sha512-01NCTBg8cuMJG1OQc6PR7T66+AFYiPwgDvdJmvJBn29NGzIG+DIFxPLNjHzwz3cpFIvG+NcwIjP9hSaPVoOaDg==
debug@2.6.9, debug@^2.2.0, debug@^2.3.3:
version "2.6.9"
resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f"