feat: show animation when message is successfully sent

This commit is contained in:
Jeremy Kahn 2022-08-22 21:57:45 -05:00
parent 3be1f2e88a
commit 0d28df82c2
6 changed files with 64 additions and 32 deletions

View File

@ -5,7 +5,7 @@ export const joinRoom: typeof trysteroJoinRoom = (
_roomId: string
) => {
const room: Room = {
makeAction: () => [() => {}, () => {}, () => {}],
makeAction: () => [() => Promise.resolve([]), () => {}, () => {}],
ping: () => Promise.resolve(0),
leave: () => {},
getPeers: () => [],

View File

@ -1,6 +1,6 @@
import Typography from '@mui/material/Typography'
import { UnsentMessage, ReceivedMessage } from 'models/chat'
import { isMessageReceived, UnsentMessage, ReceivedMessage } from 'models/chat'
export interface ChatTranscriptProps {
messageLog: Array<UnsentMessage | ReceivedMessage>
@ -10,24 +10,35 @@ export interface ChatTranscriptProps {
export const ChatTranscript = ({ messageLog, userId }: ChatTranscriptProps) => {
return (
<div className="ChatTranscript flex flex-col">
{messageLog.map((message, idx) => (
<div className="block">
{messageLog.map(message => {
let backgroundColor: string
if (message.authorId === userId) {
backgroundColor = isMessageReceived(message)
? 'primary.dark'
: 'primary.main'
} else {
backgroundColor = 'grey.700'
}
return (
<div className="block" key={message.id}>
<Typography
key={`${idx}_${message}`}
variant="body1"
sx={{
backgroundColor:
message.authorId === userId ? 'primary.dark' : 'grey.700',
backgroundColor,
margin: 0.5,
padding: 1,
borderRadius: 4,
borderRadius: 6,
float: message.authorId === userId ? 'right' : 'left',
transition: 'background-color 1s',
}}
>
{message.text}
</Typography>
</div>
))}
)
})}
</div>
)
}

View File

@ -1,5 +1,5 @@
import { PropsWithChildren } from 'react'
import { render, screen } from '@testing-library/react'
import { waitFor, render, screen } from '@testing-library/react'
import userEvent from '@testing-library/user-event'
import { MemoryRouter as Router, Route, Routes } from 'react-router-dom'
@ -8,7 +8,9 @@ import { Room } from './'
const stubUserId = 'user-id'
const mockGetUuid = jest.fn()
const mockMessagedSender = jest.fn()
const mockMessagedSender = jest
.fn()
.mockImplementation(() => Promise.resolve([]))
jest.mock('trystero', () => ({
joinRoom: () => ({
@ -73,7 +75,7 @@ describe('Room', () => {
expect(sendButton).not.toBeDisabled()
})
test('sending a message clears the text input', () => {
test('sending a message clears the text input', async () => {
render(
<RouteStub>
<Room userId={stubUserId} />
@ -83,11 +85,15 @@ describe('Room', () => {
const sendButton = screen.getByText('Send')
const textInput = screen.getByPlaceholderText('Your message')
userEvent.type(textInput, 'hello')
await waitFor(() => {
userEvent.click(sendButton)
})
expect(textInput).toHaveValue('')
})
test('message is sent to peer', () => {
test('message is sent to peer', async () => {
render(
<RouteStub>
<Room
@ -100,7 +106,11 @@ describe('Room', () => {
const sendButton = screen.getByText('Send')
const textInput = screen.getByPlaceholderText('Your message')
userEvent.type(textInput, 'hello')
await waitFor(() => {
userEvent.click(sendButton)
})
expect(mockMessagedSender).toHaveBeenCalledWith({
authorId: stubUserId,
text: 'hello',

View File

@ -24,6 +24,7 @@ export function Room({
}: RoomProps) {
const { roomId = '' } = useParams()
const [isMessageSending, setIsMessageSending] = useState(false)
const [textMessage, setTextMessage] = useState('')
const [messageLog, setMessageLog] = useState<
Array<ReceivedMessage | UnsentMessage>
@ -46,7 +47,7 @@ export function Room({
setTextMessage(value)
}
const handleMessageSubmit = (
const handleMessageSubmit = async (
event: React.SyntheticEvent<HTMLFormElement>
) => {
event.preventDefault()
@ -58,10 +59,16 @@ export function Room({
id: getUuid(),
}
sendMessage(unsentMessage)
setTextMessage('')
setIsMessageSending(true)
setMessageLog([...messageLog, unsentMessage])
await sendMessage(unsentMessage)
setMessageLog([
...messageLog,
{ ...unsentMessage, timeReceived: Date.now() },
])
setIsMessageSending(false)
}
receiveMessage(message => {
@ -85,7 +92,7 @@ export function Room({
<Button
variant="contained"
type="submit"
disabled={textMessage.length === 0}
disabled={textMessage.length === 0 || isMessageSending}
sx={{
marginTop: 2,
}}

View File

@ -8,3 +8,7 @@ export interface UnsentMessage {
export interface ReceivedMessage extends UnsentMessage {
timeReceived: number
}
export const isMessageReceived = (
message: UnsentMessage
): message is ReceivedMessage => 'timeReceived' in message

View File

@ -25,13 +25,13 @@ declare module 'trystero' {
export type RoomConfig = BaseRoomConfig &
(BitTorrentRoomConfig | FirebaseRoomConfig | IpfsRoomConfig)
export interface ActionSender<T> {
export interface ActionSender<T> extends Promise {
(
data: T,
targetPeers?: string[],
metadata?: Record,
progress?: (percent: number, peerId: string) => void
): void
): Promise<Array<undefined>>
}
export interface ActionReceiver<T> {