Skip to content

Commit 017055d

Browse files
committed
feat: add select message logic
1 parent 85bb70f commit 017055d

File tree

9 files changed

+80
-24
lines changed

9 files changed

+80
-24
lines changed

src/components/ModalsLayer.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ export default () => {
4242
<ShareModal />
4343
</div>
4444
</Modal>
45-
<Modal bindValue={showSelectMessageModal} direction="bottom" closeBtnClass="top-4 right-4">
45+
<Modal bindValue={showSelectMessageModal} direction="bottom" closeBtnClass="top-4 right-4" closeCallback={() => { showShareModal.set(true) }}>
4646
<div class="max-h-[70vh] w-full">
4747
<SelectMessageModal />
4848
</div>

src/components/ui/Modal.tsx

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ interface Props {
1111
direction: 'top' | 'bottom' | 'left' | 'right'
1212
children: JSXElement
1313
closeBtnClass?: string
14+
closeCallback?: () => void
1415
}
1516

1617
export default (props: Props) => {
@@ -19,6 +20,9 @@ export default (props: Props) => {
1920
// TODO: set it to true will cause the modal closes exceptionally
2021
// https://github.com/chakra-ui/zag/issues/596
2122
closeOnOutsideClick: false,
23+
onClose: () => {
24+
props.closeCallback && props.closeCallback()
25+
},
2226
}))
2327
const api = createMemo(() => dialog.connect(state, send, normalizeProps))
2428

Lines changed: 44 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,31 +1,65 @@
11
import { useStore } from '@nanostores/solid'
2-
import { For } from 'solid-js'
2+
import { For, createSignal } from 'solid-js'
33
import { useI18n } from '@/hooks'
44
import { currentConversationId } from '@/stores/conversation'
5-
import { getMessagesByConversationId } from '@/stores/messages'
5+
import { getMessagesByConversationId, updateMessage } from '@/stores/messages'
6+
import { showSelectMessageModal, showShareModal } from '@/stores/ui'
67
import { Checkbox } from '../ui/base'
78

89
export default () => {
910
const { t } = useI18n()
1011
const $currentConversationId = useStore(currentConversationId)
1112
const messages = getMessagesByConversationId($currentConversationId())
13+
const [checkAll, setCheckAll] = createSignal(messages.every(item => item.isSelected))
14+
const [selectedMessages, setSelectedMessages] = createSignal(messages)
15+
16+
console.log(messages, selectedMessages())
17+
18+
const handleToggleMessages = (id: string) => {
19+
messages.forEach((item) => {
20+
if (item.id === id)
21+
item.isSelected = !item.isSelected
22+
})
23+
setSelectedMessages(messages)
24+
}
25+
26+
const handleSelectAll = () => {
27+
messages.forEach((item) => {
28+
item.isSelected = !checkAll()
29+
})
30+
setSelectedMessages(messages)
31+
setCheckAll(!checkAll())
32+
console.log(selectedMessages(), checkAll())
33+
}
34+
35+
const handleSaveContext = () => {
36+
messages.forEach((item) => {
37+
updateMessage($currentConversationId(), item.id, { isSelected: item.isSelected })
38+
})
39+
showSelectMessageModal.set(false)
40+
showShareModal.set(true)
41+
}
1242

13-
console.log($currentConversationId(), messages)
1443
return (
1544
<div class="w-full">
1645
<div class="fi px-6 py-4 border-base b-b-1">
1746
<div class="text-base">{t('conversations.share.messages.title')}</div>
1847
</div>
1948
<div class="flex flex-col p-6 h-100 overflow-auto relative">
20-
<For each={messages}>
21-
{item => (
22-
<div class="border border-base b-b-0 last:b-b-1 p-4" >
23-
<Checkbox initValue label={`${item.role}: ${item.content}`} />
24-
</div>
25-
)}
49+
<div class="border border-base b-b-0 last:b-b-1 p-4 hv-base">
50+
<Checkbox setValue={() => handleSelectAll()} initValue={checkAll()} label={`${t('conversations.share.messages.selectAll')}`} />
51+
</div>
52+
<For each={selectedMessages()}>
53+
{(item) => {
54+
return (
55+
<div class="border border-base b-b-0 last:b-b-1 p-4 hv-base">
56+
<Checkbox setValue={() => handleToggleMessages(item.id)} initValue={item.isSelected} label={`${item.role}: ${item.content}`} />
57+
</div>
58+
)
59+
}}
2660
</For>
2761
</div>
28-
<div class="fcc px-2 py-2 bg-darker border border-base hv-base hover:border-base-100" >{t('settings.save')}</div>
62+
<div class="fcc px-2 py-2 bg-darker border border-base hv-base hover:border-base-100" onClick={() => handleSaveContext()}>{t('settings.save')}</div>
2963
</div>
3064
)
3165
}

src/components/ui/ShareModal.tsx

Lines changed: 17 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ import type { TabItem } from './base/Tabs'
1010
export default () => {
1111
const { t } = useI18n()
1212
const $currentConversationId = useStore(currentConversationId)
13-
const messages = getMessagesByConversationId($currentConversationId())
13+
const messages = getMessagesByConversationId($currentConversationId()).filter(item => item.isSelected)
1414

1515
console.log($currentConversationId(), messages)
1616

@@ -21,15 +21,21 @@ export default () => {
2121
value: 'context',
2222
label: t('conversations.share.tabs.context'),
2323
content: <div class="flex flex-col gap-2">
24-
<div class="emerald-light-button mt-0 cursor-pointer mb-2" onClick={() => copy()}>{copied() ? t('copyed') : t('conversations.share.copy')}</div>
25-
<For each={messages}>
26-
{item => (
27-
<div class="flex space-x-2">
28-
<div class="font-bold w-20 text-left">{item.role}:</div>
29-
<div class="text-left flex-1 whitespace-normal overflow-auto">{item.content}</div>
24+
{messages.length
25+
? (
26+
<div class="flex flex-col gap-2">
27+
<div class="emerald-light-button mt-0 cursor-pointer mb-2" onClick={() => copy()}>{copied() ? t('copyed') : t('conversations.share.copy')}</div>
28+
<For each={messages}>
29+
{item => (
30+
<div class="flex space-x-2">
31+
<div class="font-bold w-20 text-left">{item.role}:</div>
32+
<div class="text-left flex-1 whitespace-normal overflow-auto">{item.content}</div>
33+
</div>
34+
)}
35+
</For>
3036
</div>
31-
)}
32-
</For>
37+
)
38+
: <div class="text-center text-sm">{t('empty')}</div>}
3339
</div>,
3440
},
3541
{
@@ -49,12 +55,12 @@ export default () => {
4955
<div
5056
class="border w-full border-base fi justify-between box-border p-4 rounded-md hv-base"
5157
onclick={() => {
52-
showShareModal.set(false)
5358
showSelectMessageModal.set(true)
59+
showShareModal.set(false)
5460
}}
5561
>
5662
<span class="text-xs">{t('conversations.share.messages.selected')}</span>
57-
<span class="text-xs op-60">2 Messages</span>
63+
<span class="text-xs op-60">{messages.length ? `${messages.length} Messages` : t('conversations.share.messages.title')}</span>
5864
</div>
5965
<Tabs tabs={tabs} sticky tabClass="bg-base-100" />
6066
</div>

src/components/ui/base/Checkbox.tsx

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,26 @@
11
import * as checkbox from '@zag-js/checkbox'
22
import { normalizeProps, useMachine } from '@zag-js/solid'
3-
import { createMemo, createUniqueId } from 'solid-js'
3+
import { createEffect, createMemo, createUniqueId } from 'solid-js'
44

55
interface Props {
66
initValue?: boolean
77
label: string
8+
setValue: (v?: boolean) => void
89
}
910

1011
export const Checkbox = (props: Props) => {
1112
const [state, send] = useMachine(checkbox.machine({
1213
id: createUniqueId(),
1314
checked: props.initValue ?? false,
1415
onChange(detail) {
15-
console.log('onChange', detail)
16+
props.setValue(detail.checked as boolean)
1617
},
1718
}))
1819

20+
createEffect(() => {
21+
console.log('props', props.initValue)
22+
})
23+
1924
const api = createMemo(() => checkbox.connect(state, send, normalizeProps))
2025

2126
return (

src/locale/lang/en.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,13 +42,15 @@ export const en = {
4242
messages: {
4343
title: 'Select Message',
4444
selected: 'Selected Messages',
45+
selectAll: 'Select All',
4546
},
4647
tabs: {
4748
context: 'Share Context',
4849
image: 'Share Image',
4950
},
5051
},
5152
},
53+
empty: 'No data',
5254
send: {
5355
placeholder: 'Enter Something...',
5456
},

src/locale/lang/zh-cn.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,13 +42,15 @@ export const zhCN = {
4242
messages: {
4343
title: '选择消息',
4444
selected: '已选择的消息',
45+
selectAll: '全选',
4546
},
4647
tabs: {
4748
context: '分享上下文',
4849
image: '分享图片',
4950
},
5051
},
5152
},
53+
empty: '暂无数据',
5254
send: {
5355
placeholder: '输入内容...',
5456
},

src/logics/conversation.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ export const handlePrompt = async(conversation: Conversation, prompt?: string, s
2828
role: 'user',
2929
content: prompt,
3030
dateTime: new Date().getTime(),
31+
isSelected: false,
3132
})
3233
}
3334

@@ -80,6 +81,7 @@ export const handlePrompt = async(conversation: Conversation, prompt?: string, s
8081
content: typeof providerResponse === 'string' ? providerResponse : '',
8182
stream: providerResponse instanceof ReadableStream,
8283
dateTime: new Date().getTime(),
84+
isSelected: false,
8385
})
8486
}
8587
setLoadingStateByConversationId(conversation.id, false)

src/types/message.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ export interface MessageInstance extends Message {
88
id: string
99
stream?: boolean
1010
dateTime?: number
11+
isSelected?: boolean
1112
}
1213

1314
export interface ErrorMessage {

0 commit comments

Comments
 (0)