-
Notifications
You must be signed in to change notification settings - Fork 1.1k
Expand file tree
/
Copy pathConversationPanel.tsx
More file actions
126 lines (117 loc) · 4.75 KB
/
ConversationPanel.tsx
File metadata and controls
126 lines (117 loc) · 4.75 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
import cx from 'classnames'
import { FC, useCallback, useMemo, useState } from 'react'
import { useTranslation } from 'react-i18next'
import clearIcon from '~/assets/icons/clear.svg'
import historyIcon from '~/assets/icons/history.svg'
import shareIcon from '~/assets/icons/share.svg'
import { CHATBOTS } from '~app/consts'
import { ConversationContext, ConversationContextValue } from '~app/context'
import { trackEvent } from '~app/plausible'
import { ChatMessageModel } from '~types'
import { BotId } from '../../bots'
import Button from '../Button'
import HistoryDialog from '../History/Dialog'
import ShareDialog from '../Share/Dialog'
import SwitchBotDropdown from '../SwitchBotDropdown'
import ChatMessageInput, { Message } from './ChatMessageInput'
import ChatMessageList from './ChatMessageList'
interface Props {
botId: BotId
messages: ChatMessageModel[]
onUserSendMessage: (message: Message, botId: BotId) => void
resetConversation: () => void
generating: boolean
stopGenerating: () => void
mode?: 'full' | 'compact'
index?: number
}
const ConversationPanel: FC<Props> = (props) => {
const { t } = useTranslation()
const botInfo = CHATBOTS[props.botId]
const mode = props.mode || 'full'
const marginClass = 'mx-5'
const [showHistory, setShowHistory] = useState(false)
const [showShareDialog, setShowShareDialog] = useState(false)
const context: ConversationContextValue = useMemo(() => {
return {
reset: props.resetConversation,
}
}, [props.resetConversation])
const onSubmit = useCallback(
async (message: Message) => {
props.onUserSendMessage(message, props.botId)
},
[props],
)
const resetConversation = useCallback(() => {
if (!props.generating) {
props.resetConversation()
}
}, [props])
const openHistoryDialog = useCallback(() => {
setShowHistory(true)
trackEvent('open_history_dialog', { botId: props.botId })
}, [props.botId])
const openShareDialog = useCallback(() => {
setShowShareDialog(true)
trackEvent('open_share_dialog', { botId: props.botId })
}, [props.botId])
return (
<ConversationContext.Provider value={context}>
<div className={cx('flex flex-col overflow-hidden bg-primary-background h-full rounded-[20px]')}>
<div
className={cx(
'border-b border-solid border-primary-border flex flex-row items-center justify-between gap-2 py-3',
marginClass,
)}
>
<div className="flex flex-row items-center gap-2">
<img src={botInfo.avatar} className="w-5 h-5 object-contain rounded-full" />
<span className="font-semibold text-primary-text text-sm">{botInfo.name}</span>
{mode === 'compact' && <SwitchBotDropdown excludeBotId={props.botId} index={props.index!} />}
</div>
<div className="flex flex-row items-center gap-3">
<img src={shareIcon} className="w-5 h-5 cursor-pointer" onClick={openShareDialog} />
<img
src={clearIcon}
className={cx('w-5 h-5', props.generating ? 'cursor-not-allowed' : 'cursor-pointer')}
onClick={resetConversation}
/>
<img src={historyIcon} className="w-5 h-5 cursor-pointer" onClick={openHistoryDialog} />
</div>
</div>
<ChatMessageList botId={props.botId} messages={props.messages} className={marginClass} />
<div className={cx('mt-3 flex flex-col', marginClass, mode === 'full' ? 'mb-3' : 'mb-[10px]')}>
<div className={cx('flex flex-row items-center gap-[5px]', mode === 'full' ? 'mb-3' : 'mb-0')}>
{mode === 'compact' && <span className="font-medium text-xs text-light-text">Send to {botInfo.name}</span>}
<hr className="grow border-primary-border" />
</div>
<ChatMessageInput
mode={mode}
disabled={props.generating}
placeholder={mode === 'compact' ? '' : 'Ask me anything...'}
onSubmit={onSubmit}
autoFocus={mode === 'full'}
actionButton={
props.generating ? (
<Button
text={t('Stop')}
color="flat"
size={mode === 'full' ? 'normal' : 'small'}
onClick={props.stopGenerating}
/>
) : (
mode === 'full' && <Button text={t('Send')} color="primary" type="submit" />
)
}
/>
</div>
</div>
{showHistory && <HistoryDialog botId={props.botId} open={true} onClose={() => setShowHistory(false)} />}
{showShareDialog && (
<ShareDialog open={true} onClose={() => setShowShareDialog(false)} messages={props.messages} />
)}
</ConversationContext.Provider>
)
}
export default ConversationPanel