Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(closes #141): Direct messages #386

Merged
merged 21 commits into from
Dec 5, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
b6ab1e6
feat(#141): put public key in accordion
jeremyckahn Nov 18, 2024
d90598e
refactor(#141): [wip] [skip ci] move useRoom out of Room component
jeremyckahn Nov 18, 2024
e43b465
Revert "refactor(#141): [wip] [skip ci] move useRoom out of Room comp…
jeremyckahn Nov 19, 2024
7f72663
reafactor(#141): reuse room ref
jeremyckahn Nov 19, 2024
9b74b0b
refactor(variables): rename PeerActions to PeerAction
jeremyckahn Nov 22, 2024
e355200
feat(#141): [wip] render direct message room
jeremyckahn Nov 22, 2024
f0e0b93
refactor(#141): [wip] centralize room actions
jeremyckahn Nov 23, 2024
1ad316f
fixup! refactor(#141): [wip] centralize room actions
jeremyckahn Nov 24, 2024
70cba74
Revert "fixup! refactor(#141): [wip] centralize room actions"
jeremyckahn Nov 24, 2024
1318e58
Revert "refactor(#141): [wip] centralize room actions"
jeremyckahn Nov 24, 2024
6b587e1
refactor(#141): [wip] enable multiple action receivers
jeremyckahn Nov 24, 2024
bc65e30
fixup! feat(#141): [wip] render direct message room
jeremyckahn Dec 2, 2024
6f164c3
feat(#141): improve DM room display
jeremyckahn Dec 2, 2024
2fa8681
fix(#141): keep app in small viewports when peer list is expanded
jeremyckahn Dec 3, 2024
5806589
fix(#141): prevent scrolling on small viewports when navigation menu …
jeremyckahn Dec 3, 2024
bf7dc89
feat(#141): show peer dialog in full screen for small viewports
jeremyckahn Dec 3, 2024
feac11f
fix(#141): only show typing indicators in correct channels
jeremyckahn Dec 4, 2024
3f3dde6
refactor(#141): cleanup
jeremyckahn Dec 4, 2024
a53eacc
refactor(#141): improve types
jeremyckahn Dec 4, 2024
8c86140
fix(#141): peer verification stability regression
jeremyckahn Dec 5, 2024
60be4fb
fix(#141): make file transfers work again
jeremyckahn Dec 5, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ Open https://chitchatter.im/ and join a room to start chatting with anyone else
- Public and private rooms.
- Video and audio chatting.
- Screen sharing.
- Direct messaging.
- File sharing:
- Unlimited file size transfers.
- Files are encrypted prior to sending and decrypted by the receiver (the key is the room name).
Expand Down
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
)
})
})
70 changes: 42 additions & 28 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,12 +44,14 @@ export function Room({
roomId,
password,
userId,
targetPeerId,
}: RoomProps) {
const theme = useTheme()
const settingsContext = useContext(SettingsContext)
const { showActiveTypingStatus, publicKey } =
settingsContext.getUserSettings()
const {
isDirectMessageRoom,
isMessageSending,
handleInlineMediaUpload,
handleMessageChange,
Expand All @@ -72,6 +75,7 @@ export function Room({
publicKey,
encryptionService,
timeService,
targetPeerId,
}
)

Expand Down Expand Up @@ -105,32 +109,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,15 +163,23 @@ export function Room({
height: landscape ? '100%' : '40%',
}}
>
<ChatTranscript messageLog={messageLog} userId={userId} />
<ChatTranscript
messageLog={messageLog}
userId={userId}
sx={{ ...(isDirectMessageRoom && { pt: 1 }) }}
/>
<Divider />
<Box>
<MessageForm
onMessageSubmit={handleMessageSubmit}
isMessageSending={isMessageSending}
onMessageChange={handleMessageChange}
/>
{showActiveTypingStatus ? <TypingStatusBar /> : null}
{showActiveTypingStatus ? (
<TypingStatusBar
isDirectMessageRoom={isDirectMessageRoom}
/>
) : null}
</Box>
</Box>
)}
Expand Down
11 changes: 9 additions & 2 deletions src/components/Room/TypingStatusBar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,16 @@ import {
PeerNameDisplayProps,
} from 'components/PeerNameDisplay/PeerNameDisplay'

export const TypingStatusBar = () => {
export const TypingStatusBar = ({
isDirectMessageRoom,
}: {
isDirectMessageRoom: boolean
}) => {
const { peerList } = useContext(ShellContext)
const typingPeers = peerList.filter(({ isTyping }) => isTyping)
const typingPeers = peerList.filter(
({ isTypingGroupMessage, isTypingDirectMessage }) =>
isDirectMessageRoom ? isTypingDirectMessage : isTypingGroupMessage
)

const peerNameDisplayProps: Partial<PeerNameDisplayProps> = {
variant: 'caption',
Expand Down
Loading
Loading