Skip to content

Commit

Permalink
feat: add select message logic
Browse files Browse the repository at this point in the history
  • Loading branch information
yzh990918 committed Jun 9, 2023
1 parent 85bb70f commit 017055d
Show file tree
Hide file tree
Showing 9 changed files with 80 additions and 24 deletions.
2 changes: 1 addition & 1 deletion src/components/ModalsLayer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ export default () => {
<ShareModal />
</div>
</Modal>
<Modal bindValue={showSelectMessageModal} direction="bottom" closeBtnClass="top-4 right-4">
<Modal bindValue={showSelectMessageModal} direction="bottom" closeBtnClass="top-4 right-4" closeCallback={() => { showShareModal.set(true) }}>
<div class="max-h-[70vh] w-full">
<SelectMessageModal />
</div>
Expand Down
4 changes: 4 additions & 0 deletions src/components/ui/Modal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ interface Props {
direction: 'top' | 'bottom' | 'left' | 'right'
children: JSXElement
closeBtnClass?: string
closeCallback?: () => void
}

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

Expand Down
54 changes: 44 additions & 10 deletions src/components/ui/SelectMessageModal.tsx
Original file line number Diff line number Diff line change
@@ -1,31 +1,65 @@
import { useStore } from '@nanostores/solid'
import { For } from 'solid-js'
import { For, createSignal } from 'solid-js'
import { useI18n } from '@/hooks'
import { currentConversationId } from '@/stores/conversation'
import { getMessagesByConversationId } from '@/stores/messages'
import { getMessagesByConversationId, updateMessage } from '@/stores/messages'
import { showSelectMessageModal, showShareModal } from '@/stores/ui'
import { Checkbox } from '../ui/base'

export default () => {
const { t } = useI18n()
const $currentConversationId = useStore(currentConversationId)
const messages = getMessagesByConversationId($currentConversationId())
const [checkAll, setCheckAll] = createSignal(messages.every(item => item.isSelected))
const [selectedMessages, setSelectedMessages] = createSignal(messages)

console.log(messages, selectedMessages())

const handleToggleMessages = (id: string) => {
messages.forEach((item) => {
if (item.id === id)
item.isSelected = !item.isSelected
})
setSelectedMessages(messages)
}

const handleSelectAll = () => {
messages.forEach((item) => {
item.isSelected = !checkAll()
})
setSelectedMessages(messages)
setCheckAll(!checkAll())
console.log(selectedMessages(), checkAll())
}

const handleSaveContext = () => {
messages.forEach((item) => {
updateMessage($currentConversationId(), item.id, { isSelected: item.isSelected })
})
showSelectMessageModal.set(false)
showShareModal.set(true)
}

console.log($currentConversationId(), messages)
return (
<div class="w-full">
<div class="fi px-6 py-4 border-base b-b-1">
<div class="text-base">{t('conversations.share.messages.title')}</div>
</div>
<div class="flex flex-col p-6 h-100 overflow-auto relative">
<For each={messages}>
{item => (
<div class="border border-base b-b-0 last:b-b-1 p-4" >
<Checkbox initValue label={`${item.role}: ${item.content}`} />
</div>
)}
<div class="border border-base b-b-0 last:b-b-1 p-4 hv-base">
<Checkbox setValue={() => handleSelectAll()} initValue={checkAll()} label={`${t('conversations.share.messages.selectAll')}`} />
</div>
<For each={selectedMessages()}>
{(item) => {
return (
<div class="border border-base b-b-0 last:b-b-1 p-4 hv-base">
<Checkbox setValue={() => handleToggleMessages(item.id)} initValue={item.isSelected} label={`${item.role}: ${item.content}`} />
</div>
)
}}
</For>
</div>
<div class="fcc px-2 py-2 bg-darker border border-base hv-base hover:border-base-100" >{t('settings.save')}</div>
<div class="fcc px-2 py-2 bg-darker border border-base hv-base hover:border-base-100" onClick={() => handleSaveContext()}>{t('settings.save')}</div>
</div>
)
}
28 changes: 17 additions & 11 deletions src/components/ui/ShareModal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import type { TabItem } from './base/Tabs'
export default () => {
const { t } = useI18n()
const $currentConversationId = useStore(currentConversationId)
const messages = getMessagesByConversationId($currentConversationId())
const messages = getMessagesByConversationId($currentConversationId()).filter(item => item.isSelected)

console.log($currentConversationId(), messages)

Expand All @@ -21,15 +21,21 @@ export default () => {
value: 'context',
label: t('conversations.share.tabs.context'),
content: <div class="flex flex-col gap-2">
<div class="emerald-light-button mt-0 cursor-pointer mb-2" onClick={() => copy()}>{copied() ? t('copyed') : t('conversations.share.copy')}</div>
<For each={messages}>
{item => (
<div class="flex space-x-2">
<div class="font-bold w-20 text-left">{item.role}:</div>
<div class="text-left flex-1 whitespace-normal overflow-auto">{item.content}</div>
{messages.length
? (
<div class="flex flex-col gap-2">
<div class="emerald-light-button mt-0 cursor-pointer mb-2" onClick={() => copy()}>{copied() ? t('copyed') : t('conversations.share.copy')}</div>
<For each={messages}>
{item => (
<div class="flex space-x-2">
<div class="font-bold w-20 text-left">{item.role}:</div>
<div class="text-left flex-1 whitespace-normal overflow-auto">{item.content}</div>
</div>
)}
</For>
</div>
)}
</For>
)
: <div class="text-center text-sm">{t('empty')}</div>}
</div>,
},
{
Expand All @@ -49,12 +55,12 @@ export default () => {
<div
class="border w-full border-base fi justify-between box-border p-4 rounded-md hv-base"
onclick={() => {
showShareModal.set(false)
showSelectMessageModal.set(true)
showShareModal.set(false)
}}
>
<span class="text-xs">{t('conversations.share.messages.selected')}</span>
<span class="text-xs op-60">2 Messages</span>
<span class="text-xs op-60">{messages.length ? `${messages.length} Messages` : t('conversations.share.messages.title')}</span>
</div>
<Tabs tabs={tabs} sticky tabClass="bg-base-100" />
</div>
Expand Down
9 changes: 7 additions & 2 deletions src/components/ui/base/Checkbox.tsx
Original file line number Diff line number Diff line change
@@ -1,21 +1,26 @@
import * as checkbox from '@zag-js/checkbox'
import { normalizeProps, useMachine } from '@zag-js/solid'
import { createMemo, createUniqueId } from 'solid-js'
import { createEffect, createMemo, createUniqueId } from 'solid-js'

interface Props {
initValue?: boolean
label: string
setValue: (v?: boolean) => void
}

export const Checkbox = (props: Props) => {
const [state, send] = useMachine(checkbox.machine({
id: createUniqueId(),
checked: props.initValue ?? false,
onChange(detail) {
console.log('onChange', detail)
props.setValue(detail.checked as boolean)
},
}))

createEffect(() => {
console.log('props', props.initValue)
})

const api = createMemo(() => checkbox.connect(state, send, normalizeProps))

return (
Expand Down
2 changes: 2 additions & 0 deletions src/locale/lang/en.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,13 +42,15 @@ export const en = {
messages: {
title: 'Select Message',
selected: 'Selected Messages',
selectAll: 'Select All',
},
tabs: {
context: 'Share Context',
image: 'Share Image',
},
},
},
empty: 'No data',
send: {
placeholder: 'Enter Something...',
},
Expand Down
2 changes: 2 additions & 0 deletions src/locale/lang/zh-cn.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,13 +42,15 @@ export const zhCN = {
messages: {
title: '选择消息',
selected: '已选择的消息',
selectAll: '全选',
},
tabs: {
context: '分享上下文',
image: '分享图片',
},
},
},
empty: '暂无数据',
send: {
placeholder: '输入内容...',
},
Expand Down
2 changes: 2 additions & 0 deletions src/logics/conversation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ export const handlePrompt = async(conversation: Conversation, prompt?: string, s
role: 'user',
content: prompt,
dateTime: new Date().getTime(),
isSelected: false,
})
}

Expand Down Expand Up @@ -80,6 +81,7 @@ export const handlePrompt = async(conversation: Conversation, prompt?: string, s
content: typeof providerResponse === 'string' ? providerResponse : '',
stream: providerResponse instanceof ReadableStream,
dateTime: new Date().getTime(),
isSelected: false,
})
}
setLoadingStateByConversationId(conversation.id, false)
Expand Down
1 change: 1 addition & 0 deletions src/types/message.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ export interface MessageInstance extends Message {
id: string
stream?: boolean
dateTime?: number
isSelected?: boolean
}

export interface ErrorMessage {
Expand Down

0 comments on commit 017055d

Please sign in to comment.