feat: add member to chat input reply
This commit is contained in:
parent
c2ecb7ed78
commit
9a009ddc4e
|
@ -1,6 +1,6 @@
|
||||||
import React, { createContext, useContext, useMemo, useReducer } from 'react'
|
import React, { createContext, useContext, useMemo, useReducer } from 'react'
|
||||||
|
|
||||||
import type { Message } from '../protocol/use-messages'
|
import type { Member, Message } from '../protocol'
|
||||||
import type { Dispatch, Reducer } from 'react'
|
import type { Dispatch, Reducer } from 'react'
|
||||||
|
|
||||||
type Context = {
|
type Context = {
|
||||||
|
@ -12,25 +12,27 @@ const ChatContext = createContext<Context | undefined>(undefined)
|
||||||
|
|
||||||
interface State {
|
interface State {
|
||||||
message?: Message
|
message?: Message
|
||||||
|
member?: Member
|
||||||
}
|
}
|
||||||
|
|
||||||
type Action =
|
type Action =
|
||||||
| { type: 'SET_REPLY'; message?: Message }
|
| { type: 'SET_REPLY'; message?: Message; member?: Member }
|
||||||
| { type: 'CANCEL_REPLY' }
|
| { type: 'DELETE_REPLY' }
|
||||||
|
|
||||||
const reducer: Reducer<State, Action> = (state, action) => {
|
const reducer: Reducer<State, Action> = (state, action) => {
|
||||||
switch (action.type) {
|
switch (action.type) {
|
||||||
case 'SET_REPLY': {
|
case 'SET_REPLY': {
|
||||||
return { ...state, message: action.message }
|
return { ...state, message: action.message, member: action.member }
|
||||||
}
|
}
|
||||||
case 'CANCEL_REPLY': {
|
case 'DELETE_REPLY': {
|
||||||
return { ...state, message: undefined }
|
return { ...initialState }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const initialState: State = {
|
const initialState: State = {
|
||||||
message: undefined,
|
message: undefined,
|
||||||
|
member: undefined,
|
||||||
}
|
}
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
|
@ -41,6 +43,7 @@ export const ChatProvider = (props: Props) => {
|
||||||
const { children } = props
|
const { children } = props
|
||||||
|
|
||||||
const [state, dispatch] = useReducer(reducer, initialState)
|
const [state, dispatch] = useReducer(reducer, initialState)
|
||||||
|
|
||||||
const value = useMemo(() => ({ state, dispatch }), [state])
|
const value = useMemo(() => ({ state, dispatch }), [state])
|
||||||
|
|
||||||
return <ChatContext.Provider value={value}>{children}</ChatContext.Provider>
|
return <ChatContext.Provider value={value}>{children}</ChatContext.Provider>
|
||||||
|
|
|
@ -21,7 +21,7 @@ export const ChatInput = (props: Props) => {
|
||||||
const { value, editing, onSubmit } = props
|
const { value, editing, onSubmit } = props
|
||||||
|
|
||||||
const [inputValue, setInputValue] = useState(value ?? '')
|
const [inputValue, setInputValue] = useState(value ?? '')
|
||||||
const { state } = useChatContext()
|
const { state, dispatch } = useChatContext()
|
||||||
|
|
||||||
const inputRef = useRef<HTMLInputElement>(null)
|
const inputRef = useRef<HTMLInputElement>(null)
|
||||||
|
|
||||||
|
@ -37,6 +37,7 @@ export const ChatInput = (props: Props) => {
|
||||||
if (event.key === 'Enter' && event.shiftKey === false) {
|
if (event.key === 'Enter' && event.shiftKey === false) {
|
||||||
onSubmit(inputValue)
|
onSubmit(inputValue)
|
||||||
setInputValue('')
|
setInputValue('')
|
||||||
|
dispatch({ type: 'DELETE_REPLY' })
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -48,7 +49,9 @@ export const ChatInput = (props: Props) => {
|
||||||
</IconButton>
|
</IconButton>
|
||||||
</Box>
|
</Box>
|
||||||
<Bubble>
|
<Bubble>
|
||||||
{state.message && <InputReply message={state.message} />}
|
{state.message && (
|
||||||
|
<InputReply message={state.message} member={state.member} />
|
||||||
|
)}
|
||||||
<InputWrapper>
|
<InputWrapper>
|
||||||
<Input
|
<Input
|
||||||
ref={inputRef}
|
ref={inputRef}
|
||||||
|
|
|
@ -4,34 +4,30 @@ import { useChatContext } from '~/src/contexts/chat-context'
|
||||||
import { CrossIcon } from '~/src/icons/cross-icon'
|
import { CrossIcon } from '~/src/icons/cross-icon'
|
||||||
import { ReplyIcon } from '~/src/icons/reply-icon'
|
import { ReplyIcon } from '~/src/icons/reply-icon'
|
||||||
import { styled } from '~/src/styles/config'
|
import { styled } from '~/src/styles/config'
|
||||||
import { Box, Flex, Icon, IconButton, Image, Text } from '~/src/system'
|
import { Flex, Icon, IconButton, Image, Text } from '~/src/system'
|
||||||
|
|
||||||
import type { Message } from '~/src/protocol/use-messages'
|
import type { Member, Message } from '~/src/protocol'
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
message: Message
|
message: Message
|
||||||
|
member: Member
|
||||||
}
|
}
|
||||||
|
|
||||||
export const InputReply = (props: Props) => {
|
export const InputReply = (props: Props) => {
|
||||||
const { dispatch } = useChatContext()
|
const { dispatch } = useChatContext()
|
||||||
|
|
||||||
const { message } = props
|
const { message, member } = props
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Wrapper>
|
<Wrapper>
|
||||||
<Flex align="center" justify="between">
|
<Flex align="center" justify="between">
|
||||||
<Flex gap={1}>
|
<Text size="13" weight="500" truncate={false}>
|
||||||
<Icon hidden>
|
{member.username}
|
||||||
<ReplyIcon />
|
</Text>
|
||||||
</Icon>
|
|
||||||
<Text size="13" weight="500" truncate={false}>
|
|
||||||
TODO: Add name
|
|
||||||
</Text>
|
|
||||||
</Flex>
|
|
||||||
|
|
||||||
<IconButton
|
<IconButton
|
||||||
label="Cancel reply"
|
label="Cancel reply"
|
||||||
onClick={() => dispatch({ type: 'CANCEL_REPLY' })}
|
onClick={() => dispatch({ type: 'DELETE_REPLY' })}
|
||||||
>
|
>
|
||||||
<CrossIcon />
|
<CrossIcon />
|
||||||
</IconButton>
|
</IconButton>
|
||||||
|
|
|
@ -85,7 +85,7 @@ export const ChatMessage = (props: Props) => {
|
||||||
}
|
}
|
||||||
|
|
||||||
const handleReplyClick = () => {
|
const handleReplyClick = () => {
|
||||||
dispatch({ type: 'SET_REPLY', message })
|
dispatch({ type: 'SET_REPLY', message, member })
|
||||||
}
|
}
|
||||||
|
|
||||||
const handlePinClick = () => {
|
const handlePinClick = () => {
|
||||||
|
|
Loading…
Reference in New Issue