Skip to content

Commit 441023a

Browse files
committed
feat(message-settings): add copy, show raw code, delete message btns
1 parent cbd8da0 commit 441023a

File tree

7 files changed

+58
-17
lines changed

7 files changed

+58
-17
lines changed

src/components/Main.astro

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ import Conversation from './main/Conversation'
1212
<main class="flex-1 mt-14 flex flex-col overflow-hidden">
1313
<!-- <ConversationConfiguration /> -->
1414
<div class="flex-1 relative overflow-hidden">
15-
<Conversation client:only />
15+
<Conversation client:load />
1616
</div>
1717
</main>
1818
<Send client:load />

src/components/Markdown.tsx

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import 'katex/dist/katex.min.css'
1111
interface Props {
1212
class?: string
1313
text: string
14+
showRawCode?: boolean
1415
}
1516

1617
const parseMarkdown = (raw: string) => {
@@ -27,11 +28,11 @@ const parseMarkdown = (raw: string) => {
2728
}
2829

2930
export default (props: Props) => {
30-
const htmlString = () => parseMarkdown(props.text)
31+
const htmlString = () => props.showRawCode ? props.text : parseMarkdown(props.text)
3132

3233
return (
3334
<div
34-
class={props.class ?? ''}
35+
class={`${props.class ?? ''} ${props.showRawCode ? 'whitespace-pre-wrap overflow-auto my-0' : ''}`}
3536
innerHTML={htmlString()}
3637
/>
3738
)

src/components/StreamableText.tsx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import Markdown from './Markdown'
77
interface Props {
88
class?: string
99
text: string
10+
showRawCode?: boolean
1011
streamInfo?: () => {
1112
conversationId: string
1213
messageId: string
@@ -47,6 +48,7 @@ export default (props: Props) => {
4748
<Markdown
4849
class={`prose prose-neutral dark:prose-invert fg-base! max-w-3xl -my-4 ${props.class ?? ''}`}
4950
text={localText()}
51+
showRawCode={props.showRawCode}
5052
/>
5153
)
5254
}

src/components/main/MessageItem.tsx

Lines changed: 34 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
import { For } from 'solid-js/web'
2+
import { createSignal } from 'solid-js'
3+
import { useClipboardCopy } from '@/hooks'
4+
import { deleteMessageByConversationId } from '@/stores/messages'
25
import StreamableText from '../StreamableText'
3-
import { DropDownMenu, Tooltip } from '../ui/base'
6+
import { Tooltip } from '../ui/base'
47
import type { MenuItem } from '../ui/base'
58
import type { MessageInstance } from '@/types/message'
69

@@ -18,18 +21,29 @@ export default (props: Props) => {
1821
assistant: 'bg-gradient-to-b from-[#fccb90] to-[#d57eeb]',
1922
}
2023

21-
const handleCopyMessage = () => {
24+
const [copied, copy] = useClipboardCopy(props.message.content)
25+
const [showRawCode, setShowRawCode] = createSignal(false)
2226

27+
const handleDeleteMessageItem = () => {
28+
deleteMessageByConversationId(props.conversationId, props.message)
2329
}
2430

25-
const menuList: MenuItem[] = [
26-
{ id: 'retry', label: 'Retry message', icon: 'i-ion:refresh-outline' },
27-
{ id: 'show', label: 'Show raw code', icon: 'i-carbon-code' },
28-
{ id: 'share', label: 'Share message', icon: 'i-ion:ios-share-alt' },
29-
{ id: 'edit', label: 'Edit message', icon: 'i-ion:md-create' },
30-
{ id: 'copy', label: 'Copy message', icon: 'i-carbon-copy' },
31-
{ id: 'delete', label: 'Delete message', icon: 'i-carbon-trash-can' },
32-
]
31+
const [menuList, setMenuList] = createSignal<MenuItem[]>([
32+
// TODO: Retry send message
33+
// { id: 'retry', label: 'Retry send', icon: 'i-ion:refresh-outline', role: 'all' },
34+
{ id: 'raw', label: 'Show raw code', icon: 'i-carbon-code', role: 'system', action: () => setShowRawCode(!showRawCode()) },
35+
// TODO: Share message
36+
// { id: 'share', label: 'Share message', icon: 'i-ion:ios-share-alt' },
37+
// TODO: Edit message
38+
// { id: 'edit', label: 'Edit message', icon: 'i-ion:md-create', role: 'user' },
39+
{ id: 'copy', label: 'Copy message', icon: 'i-carbon-copy', role: 'all', action: copy },
40+
{ id: 'delete', label: 'Delete message', icon: 'i-carbon-trash-can', role: 'all', action: handleDeleteMessageItem },
41+
])
42+
43+
if (props.message.role === 'user')
44+
setMenuList(menuList().filter(item => ['all', 'user'].includes(item.role!)))
45+
else
46+
setMenuList(menuList().filter(item => ['all', 'system'].includes(item.role!)))
3347

3448
return (
3549
<div
@@ -48,8 +62,15 @@ export default (props: Props) => {
4862
</div>
4963
<div class={`hidden sm:block absolute right-6 -top-4 ${!props.index && 'top-0'}`}>
5064
<div class="op-0 group-hover:op-80 fcc space-x-2 !bg-base px-4 py-1 rounded-xl b border-base transition-opacity duration-400">
51-
<For each={menuList}>
52-
{item => (<Tooltip tip={item.label}><div class={`${item.icon} menu-icon`} /></Tooltip>)}
65+
<For each={menuList()}>
66+
{item => (
67+
<Tooltip tip={item.label} handleChildClick={item.action}>
68+
{
69+
item.id === 'copy'
70+
? <div class={`menu-icon ${copied() ? 'i-carbon-checkmark !text-emerald-400' : 'i-carbon-copy'}`} />
71+
: <div class={`${item.icon} menu-icon`} />
72+
}
73+
</Tooltip>)}
5374
</For>
5475
</div>
5576
</div>
@@ -63,6 +84,7 @@ export default (props: Props) => {
6384
handleStreaming: props.handleStreaming,
6485
})
6586
: undefined}
87+
showRawCode={showRawCode()}
6688
/>
6789
</div>
6890

src/components/ui/base/DropdownMenu.tsx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@ export interface MenuItem {
1010
icon?: string
1111
// TODO: nested menu
1212
children?: MenuItem[]
13+
role?: string
14+
action?: (params?: any) => void
1315
}
1416

1517
interface Props {

src/components/ui/base/Tooltip.tsx

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ interface Props {
99
children: JSX.Element
1010
openDelay?: number
1111
closeDelay?: number
12+
handleChildClick?: () => void
1213
placement?: 'top' | 'bottom' | 'left' | 'right' | 'top-start' | 'top-end' | 'bottom-start' | 'bottom-end' | 'left-start' | 'left-end' | 'right-start' | 'right-end'
1314
}
1415

@@ -30,9 +31,9 @@ export const Tooltip = (props: Props) => {
3031
const resolvedChild = () => {
3132
const child = children(() => props.children)
3233
createEffect(() => {
33-
spread(child() as Element, { ...api().triggerProps })
34+
spread(child() as Element, { ...api().triggerProps, onClick: props.handleChildClick })
3435
})
35-
return child
36+
return child()
3637
}
3738

3839
return (

src/stores/messages.ts

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,3 +60,16 @@ export const clearMessagesByConversationId = action(
6060
})
6161
},
6262
)
63+
64+
export const deleteMessageByConversationId = action(
65+
conversationMessagesMap,
66+
'deleteMessageByConversationId',
67+
(map, id: string, payload: MessageInstance) => {
68+
const oldMessages = map.get()[id] || []
69+
map.setKey(id, [...oldMessages.filter(message => message.id !== payload.id)])
70+
db.setItem(id, [...oldMessages.filter(message => message.id !== payload.id)])
71+
updateConversationById(id, {
72+
lastUseTime: Date.now(),
73+
})
74+
},
75+
)

0 commit comments

Comments
 (0)