-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
This cleans up a lot of the hacks that we did just to get things going along with updating the styling to make the Messages page at least look presentable
- Loading branch information
Tim Roberts
committed
Feb 10, 2024
1 parent
b93fb57
commit fc24735
Showing
8 changed files
with
657 additions
and
444 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,87 @@ | ||
import { useUser, useSession } from '@clerk/clerk-react' | ||
import { useState, useContext, useEffect } from 'react' | ||
import WebSocketContext from '../contexts/websocket' | ||
import { mapDatabaseToWebsocket, sortMessages } from '../pages/Messages/utils' | ||
import { | ||
getMessageGroupsForUser, | ||
getMessageForGroup, | ||
} from '../services/messages' | ||
import { MessageGroup } from '../services/messages.schema' | ||
import { WebSocketMessage } from './usewebsocket' | ||
|
||
import Log from '../log' | ||
|
||
const useGroupMessages = () => { | ||
const [messages, setMessages] = useState<WebSocketMessage[]>([]) | ||
const [groups, setGroups] = useState<MessageGroup[]>([]) | ||
const [selectedGroup, setSelectedGroup] = useState<MessageGroup>() | ||
|
||
const { sendMessage, lastMessage } = useContext(WebSocketContext) | ||
const { user } = useUser() | ||
const { session } = useSession() | ||
|
||
useEffect(() => { | ||
const getGroups = async () => { | ||
const token = await session?.getToken() | ||
|
||
if (token) { | ||
try { | ||
const result = await getMessageGroupsForUser(token) | ||
|
||
setGroups(result) | ||
} catch (err) { | ||
Log.warn({ err }, 'Error getting message groups') | ||
} | ||
} | ||
} | ||
|
||
if (session) { | ||
getGroups() | ||
} | ||
}, [session]) | ||
|
||
useEffect(() => { | ||
if (lastMessage) { | ||
setMessages((msgs) => [...msgs, lastMessage]) | ||
} | ||
}, [lastMessage]) | ||
|
||
useEffect(() => { | ||
const getPastMessages = async () => { | ||
const token = await session?.getToken() | ||
|
||
if (token && selectedGroup?._id) { | ||
try { | ||
const result = await getMessageForGroup(selectedGroup?._id, token) | ||
|
||
const mapped: WebSocketMessage[] = result.map(mapDatabaseToWebsocket) | ||
|
||
setMessages(() => { | ||
return mapped.sort(sortMessages) | ||
}) | ||
} catch (err) { | ||
Log.warn({ err }, 'Error when trying to get messages') | ||
} | ||
} else { | ||
setMessages([]) | ||
} | ||
} | ||
|
||
if (session && user) { | ||
getPastMessages() | ||
} | ||
}, [user, setMessages, selectedGroup?._id, session]) | ||
|
||
return { | ||
messages, | ||
groups, | ||
sendMessage, | ||
setSelectedGroup, | ||
selectedGroup, | ||
user, | ||
session, | ||
setGroups, | ||
} | ||
} | ||
|
||
export default useGroupMessages |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
import React, { FormEventHandler } from 'react' | ||
import styled from '@emotion/styled' | ||
import { Button, TextField } from '@mui/material' | ||
import GroupAddIcon from '@mui/icons-material/GroupAdd' | ||
const Form = styled.form` | ||
width: 100%; | ||
button { | ||
margin-top: 0.5rem; | ||
} | ||
` | ||
|
||
interface Props { | ||
createNewGroup: FormEventHandler<HTMLFormElement> | ||
} | ||
|
||
const GroupCreator = ({ createNewGroup }: Props) => { | ||
return ( | ||
<Form onSubmit={createNewGroup}> | ||
<TextField name="name" fullWidth label="New Group Name" required /> | ||
<Button | ||
type="submit" | ||
variant="contained" | ||
startIcon={<GroupAddIcon />} | ||
fullWidth | ||
> | ||
Create | ||
</Button> | ||
</Form> | ||
) | ||
} | ||
|
||
export default GroupCreator |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
import React from 'react' | ||
import styled from '@emotion/styled' | ||
import List from '@mui/material/List' | ||
import ListItemButton from '@mui/material/ListItemButton' | ||
import ListItemText from '@mui/material/ListItemText' | ||
|
||
const Form = styled.form` | ||
width: 100%; | ||
display: flex; | ||
flex-direction: column; | ||
margin-bottom: 5rem; | ||
` | ||
|
||
interface Props { | ||
selectedGroupId?: string | ||
groups: { | ||
_id: string | ||
name: string | ||
}[] | ||
setSelectedGroup: (group: { _id: string; name: string } | undefined) => void | ||
} | ||
|
||
const GroupSelector = ({ | ||
selectedGroupId, | ||
groups, | ||
setSelectedGroup, | ||
}: Props) => ( | ||
<List> | ||
{groups.map((group) => ( | ||
<ListItemButton | ||
key={group._id} | ||
selected={selectedGroupId === group._id} | ||
onClick={() => { | ||
setSelectedGroup(groups.find(({ _id }) => _id === group._id)) | ||
}} | ||
> | ||
<ListItemText primary={group.name} /> | ||
</ListItemButton> | ||
))} | ||
</List> | ||
) | ||
|
||
export default GroupSelector |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,54 @@ | ||
import React from 'react' | ||
import { MessageTimestamp, Message as MessageWrap } from './styled' | ||
import { formatDistanceToNow } from 'date-fns' | ||
import Markdown from 'react-markdown' | ||
import SyntaxHighlighter from 'react-syntax-highlighter' | ||
import { a11yDark } from 'react-syntax-highlighter/dist/esm/styles/hljs' | ||
import remarkGfm from 'remark-gfm' | ||
|
||
interface Props { | ||
payload: { | ||
message: string | ||
} | ||
metadata: { | ||
receivedAt: string | ||
} | ||
} | ||
|
||
const Message = ({ payload, metadata }: Props) => { | ||
return ( | ||
<MessageWrap> | ||
<Markdown | ||
remarkPlugins={[remarkGfm]} | ||
components={{ | ||
code({ node, inline, className, children, ...props }: any) { | ||
const match = /language-(\w+)/.exec(className || '') | ||
return !inline && match ? ( | ||
<SyntaxHighlighter | ||
style={a11yDark} | ||
language={match[1]} | ||
PreTag="div" | ||
{...props} | ||
> | ||
{String(children).replace(/\n$/, '')} | ||
</SyntaxHighlighter> | ||
) : ( | ||
<code className="md-post-code" {...props}> | ||
{children} | ||
</code> | ||
) | ||
}, | ||
}} | ||
> | ||
{payload.message} | ||
</Markdown> | ||
<MessageTimestamp dateTime={metadata.receivedAt}> | ||
{formatDistanceToNow(new Date(metadata.receivedAt), { | ||
addSuffix: true, | ||
})} | ||
</MessageTimestamp> | ||
</MessageWrap> | ||
) | ||
} | ||
|
||
export default Message |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
import React from 'react' | ||
import { TextField } from '@mui/material' | ||
import styled from '@emotion/styled' | ||
|
||
const Input = styled(TextField)` | ||
max-width: 95%; | ||
margin: 0 auto; | ||
margin-top: 4rem; | ||
` | ||
|
||
interface Props { | ||
handleUpdate: (value: any) => void | ||
onSend: () => void | ||
currentValue: any | ||
} | ||
|
||
const MessageInput = ({ handleUpdate, onSend, currentValue = '' }: Props) => ( | ||
<Input | ||
label="Message" | ||
name="message" | ||
multiline | ||
value={currentValue} | ||
onChange={handleUpdate} | ||
variant="filled" | ||
onKeyUp={(event) => { | ||
if (event.key.toLowerCase() == 'enter') { | ||
if (event.shiftKey) { | ||
// | ||
} else { | ||
onSend() | ||
} | ||
} | ||
}} | ||
fullWidth | ||
/> | ||
) | ||
|
||
export default MessageInput |
Oops, something went wrong.