Skip to content

Commit

Permalink
feat(#141): [wip] render direct message room
Browse files Browse the repository at this point in the history
  • Loading branch information
jeremyckahn committed Nov 21, 2024
1 parent ff54d0b commit a811aa9
Show file tree
Hide file tree
Showing 7 changed files with 119 additions and 56 deletions.
37 changes: 22 additions & 15 deletions src/components/ChatTranscript/ChatTranscript.tsx
Original file line number Diff line number Diff line change
@@ -1,17 +1,21 @@
import { HTMLAttributes, useRef, useEffect, useState, useContext } from 'react'
import Box from '@mui/material/Box'
import { useRef, useEffect, useState, useContext } from 'react'
import Box, { BoxProps } from '@mui/material/Box'
import useTheme from '@mui/material/styles/useTheme'

import { Message as IMessage, InlineMedia } from 'models/chat'
import { Message } from 'components/Message'
import { ShellContext } from 'contexts/ShellContext'

export interface ChatTranscriptProps extends HTMLAttributes<HTMLDivElement> {
export interface ChatTranscriptProps extends BoxProps {
messageLog: Array<IMessage | InlineMedia>
userId: string
}

export const ChatTranscript = ({ messageLog, userId }: ChatTranscriptProps) => {
export const ChatTranscript = ({
messageLog,
userId,
sx,
}: ChatTranscriptProps) => {
const { showRoomControls } = useContext(ShellContext)
const theme = useTheme()
const boxRef = useRef<HTMLDivElement>(null)
Expand Down Expand Up @@ -62,17 +66,20 @@ export const ChatTranscript = ({ messageLog, userId }: ChatTranscriptProps) => {
<Box
ref={boxRef}
className="ChatTranscript"
sx={{
display: 'flex',
flexDirection: 'column',
flexGrow: 1,
overflow: 'auto',
pb: transcriptMinPadding,
pt: showRoomControls ? theme.spacing(10) : theme.spacing(2),
px: `max(${transcriptPaddingX}, ${transcriptMinPadding})`,
transition: `padding-top ${theme.transitions.duration.short}ms ${theme.transitions.easing.easeInOut}`,
width: '100%',
}}
sx={[
{
display: 'flex',
flexDirection: 'column',
flexGrow: 1,
overflow: 'auto',
pb: transcriptMinPadding,
pt: showRoomControls ? theme.spacing(10) : theme.spacing(2),
px: `max(${transcriptPaddingX}, ${transcriptMinPadding})`,
transition: `padding-top ${theme.transitions.duration.short}ms ${theme.transitions.easing.easeInOut}`,
width: '100%',
},
...(Array.isArray(sx) ? sx : [sx]),
]}
>
{messageLog.map((message, idx) => {
const previousMessage = messageLog[idx - 1]
Expand Down
17 changes: 10 additions & 7 deletions src/components/Room/Room.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,7 @@ describe('Room', () => {
expect(textInput).toHaveValue('')
})

test('message is sent to peer', async () => {
test('message is sent to peers', async () => {
render(
<RouteStub>
<RoomStub
Expand All @@ -136,11 +136,14 @@ describe('Room', () => {
await userEvent.type(textInput, 'hello')
await userEvent.click(sendButton)

expect(mockMessagedSender).toHaveBeenCalledWith({
authorId: mockUserId,
text: 'hello',
timeSent: mockNowTime,
id: 'abc123',
})
expect(mockMessagedSender).toHaveBeenCalledWith(
{
authorId: mockUserId,
text: 'hello',
timeSent: mockNowTime,
id: 'abc123',
},
null
)
})
})
65 changes: 38 additions & 27 deletions src/components/Room/Room.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ export interface RoomProps {
userId: string
encryptionService?: typeof encryption
timeService?: typeof time
targetPeerId?: string
}

export function Room({
Expand All @@ -43,6 +44,7 @@ export function Room({
roomId,
password,
userId,
targetPeerId,
}: RoomProps) {
const theme = useTheme()
const settingsContext = useContext(SettingsContext)
Expand Down Expand Up @@ -72,9 +74,12 @@ export function Room({
publicKey,
encryptionService,
timeService,
targetPeerId,
}
)

const isDirectMessageRoom = typeof targetPeerId === 'string'

const handleMessageSubmit = async (message: string) => {
await sendMessage(message)
}
Expand Down Expand Up @@ -105,32 +110,34 @@ export function Room({
overflow: 'auto',
}}
>
<Zoom in={showRoomControls}>
<Box
sx={{
alignItems: 'flex-start',
display: 'flex',
justifyContent: 'center',
overflow: 'visible',
height: 0,
position: 'relative',
top: theme.spacing(1),
}}
>
<RoomAudioControls peerRoom={peerRoom} />
<RoomVideoControls peerRoom={peerRoom} />
<RoomScreenShareControls peerRoom={peerRoom} />
<RoomFileUploadControls
peerRoom={peerRoom}
onInlineMediaUpload={handleInlineMediaUpload}
/>
<Zoom in={showVideoDisplay} mountOnEnter unmountOnExit>
<span>
<RoomShowMessagesControls />
</span>
</Zoom>
</Box>
</Zoom>
{!isDirectMessageRoom && (
<Zoom in={showRoomControls}>
<Box
sx={{
alignItems: 'flex-start',
display: 'flex',
justifyContent: 'center',
overflow: 'visible',
height: 0,
position: 'relative',
top: theme.spacing(1),
}}
>
<RoomAudioControls peerRoom={peerRoom} />
<RoomVideoControls peerRoom={peerRoom} />
<RoomScreenShareControls peerRoom={peerRoom} />
<RoomFileUploadControls
peerRoom={peerRoom}
onInlineMediaUpload={handleInlineMediaUpload}
/>
<Zoom in={showVideoDisplay} mountOnEnter unmountOnExit>
<span>
<RoomShowMessagesControls />
</span>
</Zoom>
</Box>
</Zoom>
)}
<Box
sx={{
display: 'flex',
Expand All @@ -157,7 +164,11 @@ export function Room({
height: landscape ? '100%' : '40%',
}}
>
<ChatTranscript messageLog={messageLog} userId={userId} />
<ChatTranscript
messageLog={messageLog}
userId={userId}
sx={{ pt: 1 }}
/>
<Divider />
<Box>
<MessageForm
Expand Down
26 changes: 20 additions & 6 deletions src/components/Room/useRoom.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ interface UseRoomConfig {
getUuid?: typeof uuid
encryptionService?: typeof encryption
timeService?: typeof time
targetPeerId?: string | null
}

interface UserMetadata extends Record<string, any> {
Expand All @@ -58,13 +59,16 @@ export function useRoom(
roomId,
userId,
publicKey,
targetPeerId = null,
getUuid = uuid,
encryptionService = encryption,
timeService = time,
}: UseRoomConfig
) {
const isPrivate = password !== undefined

const isDirectMessageRoom = typeof targetPeerId === 'string'

const {
peerList,
setPeerList,
Expand All @@ -76,6 +80,8 @@ export function useRoom(
customUsername,
updatePeer,
peerRoomRef,
messageLog,
setMessageLog: shellSetMessageLog,
} = useContext(ShellContext)

const [peerRoom] = useState(
Expand All @@ -89,9 +95,6 @@ export function useRoom(
const settingsContext = useContext(SettingsContext)
const { showActiveTypingStatus } = settingsContext.getUserSettings()
const [isMessageSending, setIsMessageSending] = useState(false)
const [messageLog, _setMessageLog] = useState<Array<Message | InlineMedia>>(
[]
)
const [newMessageAudio] = useState(() => new Audio('/sounds/new-message.aac'))

const { getDisplayUsername } = usePeerNameDisplay()
Expand All @@ -113,7 +116,7 @@ export function useRoom(
}
}

_setMessageLog(messages.slice(-messageTranscriptSizeLimit))
shellSetMessageLog(messages.slice(-messageTranscriptSizeLimit))
}

const [isShowingMessages, setIsShowingMessages] = useState(true)
Expand Down Expand Up @@ -191,12 +194,22 @@ export function useRoom(

useEffect(() => {
return () => {
if (isDirectMessageRoom) return

sendTypingStatusChange({ isTyping: false })
peerRoom.leaveRoom()
peerRoomRef.current = null
setPeerList([])
shellSetMessageLog([])
}
}, [peerRoom, setPeerList, sendTypingStatusChange, peerRoomRef])
}, [
peerRoom,
setPeerList,
sendTypingStatusChange,
peerRoomRef,
isDirectMessageRoom,
shellSetMessageLog,
])

useEffect(() => {
setPassword(password)
Expand Down Expand Up @@ -252,7 +265,8 @@ export function useRoom(
setIsTyping(false)
setIsMessageSending(true)
setMessageLog([...messageLog, unsentMessage])
await sendPeerMessage(unsentMessage)

await sendPeerMessage(unsentMessage, targetPeerId)

setMessageLog([
...messageLog,
Expand Down
17 changes: 16 additions & 1 deletion src/components/Shell/PeerListItem.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,18 +16,21 @@ import ListItem from '@mui/material/ListItem'
import ListItemText from '@mui/material/ListItemText'
import Tooltip from '@mui/material/Tooltip'
import Typography from '@mui/material/Typography'
import { useState } from 'react'
import useTheme from '@mui/material/styles/useTheme'
import { useContext, useState } from 'react'

import { AudioVolume } from 'components/AudioVolume'
import { PeerNameDisplay } from 'components/PeerNameDisplay'
import { PublicKey } from 'components/PublicKey'
import { Room } from 'components/Room'
import { PeerConnectionType } from 'lib/PeerRoom'
import {
AudioChannel,
AudioChannelName,
Peer,
PeerVerificationState,
} from 'models/chat'
import { SettingsContext } from 'contexts/SettingsContext'

import { PeerDownloadFileButton } from './PeerDownloadFileButton'

Expand Down Expand Up @@ -62,6 +65,9 @@ export const PeerListItem = ({
peerConnectionTypes,
peerAudioChannels,
}: PeerListItemProps) => {
const theme = useTheme()
const { getUserSettings } = useContext(SettingsContext)
const { userId } = getUserSettings()
const [showPeerDialog, setShowPeerDialog] = useState(false)

const hasPeerConnection = peer.peerId in peerConnectionTypes
Expand Down Expand Up @@ -169,6 +175,15 @@ export const PeerListItem = ({
<PublicKey publicKey={peer.publicKey} />
</AccordionDetails>
</Accordion>
<Box
mt={1}
display="flex"
flexDirection="column"
minHeight="350px"
bgcolor={theme.palette.background.paper}
>
<Room roomId="" userId={userId} targetPeerId={peer.peerId} />
</Box>
</DialogContent>
<DialogActions>
<Button onClick={handleDialogClose}>Close</Button>
Expand Down
7 changes: 7 additions & 0 deletions src/components/Shell/Shell.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@ import {
AudioChannel,
PeerAudioChannelState,
AudioChannelName,
InlineMedia,
Message,
} from 'models/chat'
import { ErrorBoundary } from 'components/ErrorBoundary'
import { PeerConnectionType, PeerRoom } from 'lib/PeerRoom'
Expand Down Expand Up @@ -102,6 +104,7 @@ export const Shell = ({ appNeedsUpdate, children, userPeerId }: ShellProps) => {
const [peerAudioChannels, setPeerAudioChannels] = useState<
Record<string, AudioChannel>
>({})
const [messageLog, setMessageLog] = useState<Array<Message | InlineMedia>>([])

const showAlert = useCallback((message: string, options?: AlertOptions) => {
setAlertText(message)
Expand Down Expand Up @@ -162,6 +165,8 @@ export const Shell = ({ appNeedsUpdate, children, userPeerId }: ShellProps) => {
connectionTestResults,
updatePeer,
peerRoomRef,
messageLog,
setMessageLog,
}),
[
isEmbedded,
Expand Down Expand Up @@ -193,6 +198,8 @@ export const Shell = ({ appNeedsUpdate, children, userPeerId }: ShellProps) => {
connectionTestResults,
updatePeer,
peerRoomRef,
messageLog,
setMessageLog,
]
)

Expand Down
6 changes: 6 additions & 0 deletions src/contexts/ShellContext.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ import {
AudioChannel,
AudioChannelName,
AudioState,
InlineMedia,
Message,
Peer,
PeerAudioChannelState,
ScreenShareState,
Expand Down Expand Up @@ -53,6 +55,8 @@ interface ShellContextProps {
connectionTestResults: ConnectionTestResults
updatePeer: (peerId: string, updatedProperties: Partial<Peer>) => void
peerRoomRef: MutableRefObject<PeerRoom | null>
messageLog: Array<Message | InlineMedia>
setMessageLog: React.Dispatch<React.SetStateAction<(Message | InlineMedia)[]>>
}

export const ShellContext = createContext<ShellContextProps>({
Expand Down Expand Up @@ -94,4 +98,6 @@ export const ShellContext = createContext<ShellContextProps>({
},
updatePeer: () => {},
peerRoomRef: { current: null },
messageLog: [],
setMessageLog: () => {},
})

0 comments on commit a811aa9

Please sign in to comment.