Skip to content

Commit

Permalink
feat: provider-bot support
Browse files Browse the repository at this point in the history
  • Loading branch information
ddiu8081 committed May 1, 2023
1 parent bbbb916 commit b66ef2c
Show file tree
Hide file tree
Showing 22 changed files with 167 additions and 205 deletions.
7 changes: 0 additions & 7 deletions src/components/ModalsLayer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,10 @@ import {
showConversationEditModal,
showConversationSidebar,
showSettingsSidebar,
showSystemInfoModel,
} from '@/stores/ui'
import ConversationSidebar from './conversations/ConversationSidebar'
import SettingsSidebar from './settings/SettingsSidebar'
import ConversationEditModal from './conversations/ConversationEditModal'
import ConversationEdit from './conversations/ConversationEdit'
import Modal from './ui/Modal'

export default () => {
Expand All @@ -28,11 +26,6 @@ export default () => {
<ConversationEditModal />
</div>
</Modal>
<Modal bindValue={showSystemInfoModel} direction="bottom" closeBtnClass="top-6 right-6">
<div class="max-h-[70vh] w-full">
<ConversationEditModal />
</div>
</Modal>
</>
)
}
71 changes: 11 additions & 60 deletions src/components/conversations/ConversationEdit.tsx
Original file line number Diff line number Diff line change
@@ -1,49 +1,21 @@
import { Show, createSignal } from 'solid-js'
import { showSystemInfoModel } from '@/stores/ui'
import { providerMetaList } from '@/stores/provider'
import { Select } from '@/components/ui/base'
import type { Conversation, ConversationType } from '@/types/conversation'

const typeSelectList = [
{
value: 'continuous' as const,
label: 'Continuous Conversation',
icon: 'i-carbon-edt-loop',
},
{
value: 'single' as const,
label: 'Single Conversation',
icon: 'i-carbon-connect',
},
{
value: 'image' as const,
label: 'Image Generation',
icon: 'i-carbon-image',
},
]
import BotSelect from '@/components/ui/BotSelect'
import { getBotMetaById } from '@/stores/provider'
import type { Conversation } from '@/types/conversation'

interface Props {
conversation: Conversation
handleChange: (payload: Partial<Conversation>) => void
}

export default (props: Props) => {
const [selectProviderId, setSelectProviderId] = createSignal(props.conversation.providerId || providerMetaList[0]?.id)
const [selectConversationType, setSelectConversationType] = createSignal<ConversationType>(props.conversation.conversationType || 'continuous')
const selectProvider = () => providerMetaList.find(item => item.id === selectProviderId()) || null
const supportedConversationType = () => typeSelectList.filter(item => selectProvider()?.supportConversationType.includes(item.value))

const handleProviderChange = (id: string) => {
setSelectProviderId(id)
props.handleChange({ providerId: id })
// TODO: This will crash the app
// setSelectConversationType(selectProvider()?.supportConversationType[0] || 'continuous')
}
const [providerBot, setProviderBot] = createSignal(props.conversation.bot || '')
const botMeta = () => getBotMetaById(providerBot()) || null

const handleConversationTypeChange = (type: ConversationType) => {
setSelectConversationType(type)
const payload: Partial<Conversation> = { conversationType: type }
if (type === 'image') {
const handleProviderBotChange = (e: string) => {
setProviderBot(e)
const payload: Partial<Conversation> = { bot: e }
if (botMeta()?.type === 'image_generation') {
payload.systemInfo = undefined
payload.mockMessages = undefined
}
Expand All @@ -54,10 +26,6 @@ export default (props: Props) => {
// TODO: Icon selector by `emoji-mart`
}

const handleOpenSystemInfoSettings = () => {
showSystemInfoModel.set(true)
}

const handleOpenMockMessages = () => {
// TODO
}
Expand All @@ -75,25 +43,8 @@ export default (props: Props) => {
value={props.conversation.name}
onBlur={e => props.handleChange({ name: e.currentTarget.value })}
/>
<div class="py-1 border bg-base-50 border-base rounded-lg text-sm">
<div class="fi justify-between gap-10 px-4 h-10">
<h3 class="op-80 shrink-0">Provider</h3>
<Select
options={providerMetaList.map(item => ({ value: item.id, label: item.name, icon: item.icon }))}
value={selectProviderId}
setValue={handleProviderChange}
/>
</div>
<div class="fi justify-between gap-10 px-4 h-10">
<h3 class="op-80 shrink-0">Conversation Type</h3>
<Select
options={supportedConversationType()}
value={selectConversationType}
setValue={handleConversationTypeChange}
/>
</div>
</div>
<Show when={selectConversationType() !== 'image'}>
<BotSelect value={props.conversation.bot} onChange={handleProviderBotChange} />
<Show when={botMeta()?.type !== 'image_generation'}>
<div class="py-1 border bg-base-50 border-base rounded-lg text-sm">
<div class="px-4 py-2">
<h3 class="op-80 shrink-0">System Info</h3>
Expand Down
4 changes: 2 additions & 2 deletions src/components/conversations/ConversationEditModal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ export default () => {

const handleButtonClick = () => {
if (Object.keys(modifiedConversationPayload).length)
updateConversationById($currentConversation().id, modifiedConversationPayload)
updateConversationById($currentConversation()!.id, modifiedConversationPayload)
showConversationEditModal.set(false)
}

Expand All @@ -25,7 +25,7 @@ export default () => {
<div class="p-6">
<main class="flex flex-col gap-3 mt-3">
<ConversationEdit
conversation={$currentConversation()}
conversation={$currentConversation()!}
handleChange={handleChange}
/>
</main>
Expand Down
10 changes: 7 additions & 3 deletions src/components/main/Conversation.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { useStore } from '@nanostores/solid'
import { conversationMap, currentConversationId } from '@/stores/conversation'
import { conversationMessagesMap } from '@/stores/messages'
import { loadingStateMap, streamsMap } from '@/stores/streams'
import { getBotMetaById } from '@/stores/provider'
import ConversationEmpty from './ConversationEmpty'
import Welcome from './Welcome'
import Continuous from './Continuous'
Expand All @@ -19,6 +20,9 @@ export default () => {
const currentConversation = () => {
return $conversationMap()[$currentConversationId()]
}
const currentBot = () => {
return getBotMetaById(currentConversation()?.bot)
}
const currentConversationMessages = () => {
return $conversationMessagesMap()[$currentConversationId()] || []
}
Expand All @@ -34,19 +38,19 @@ export default () => {
<Match when={$currentConversationId() && !currentConversationMessages().length}>
<ConversationEmpty conversation={currentConversation()} />
</Match>
<Match when={currentConversation()?.conversationType === 'continuous'}>
<Match when={currentBot()?.type === 'chat_continuous'}>
<Continuous
conversationId={$currentConversationId()}
messages={currentConversationMessages}
/>
</Match>
<Match when={currentConversation()?.conversationType === 'single'}>
<Match when={currentBot()?.type === 'chat_single'}>
<Single
conversationId={$currentConversationId()}
messages={currentConversationMessages}
/>
</Match>
<Match when={currentConversation()?.conversationType === 'image'}>
<Match when={currentBot()?.type === 'image_generation'}>
<Image
// conversationId={$currentConversationId()}
messages={currentConversationMessages}
Expand Down
4 changes: 0 additions & 4 deletions src/components/main/Welcome.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,12 @@ import { For, Show } from 'solid-js'
import { useStore } from '@nanostores/solid'
import { addConversation, conversationMapSortList, currentConversationId } from '@/stores/conversation'

// TODO: Test area
import BotSelect from '../ui/BotSelect'

export default () => {
const $conversationMapSortList = useStore(conversationMapSortList)

return (
<div class="fcc h-full">
<div class="flex flex-col gap-4 w-full max-w-md mx-12 sm:mx-18 overflow-hidden">
<BotSelect />
<div class="px-6 py-4 bg-base-100 border border-base rounded-lg">
<h2 class="text-xs op-30 uppercase my-2">Recents</h2>
<div class="flex flex-col items-start">
Expand Down
1 change: 0 additions & 1 deletion src/components/settings/ProviderGlobalSettings.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,6 @@ export default ({ config, settingsValue, setSettings }: Props) => {
}

const handleClick = () => {
console.log('providerGlobalSetting set', editFormData())
setSettings(formData())
setEditing(false)
}
Expand Down
44 changes: 13 additions & 31 deletions src/components/ui/BotSelect.tsx
Original file line number Diff line number Diff line change
@@ -1,39 +1,21 @@
import { createSignal } from 'solid-js'
import { providerMetaList } from '@/stores/provider'
import { onMount } from 'solid-js'
import { botMetaList } from '@/stores/provider'
import { Select } from '../ui/base'
import type { ConversationType } from '@/types/conversation'

interface BotMeta {
interface Props {
value: string
type: ConversationType
label: string
provider: {
id: string
name: string
icon: string
}
onChange: (value: string) => void
}

const botMetaList: BotMeta[] = providerMetaList.map((provider) => {
return provider.bots.map(bot => ({
value: bot.id,
type: bot.type,
label: bot.name,
provider: {
id: provider.id,
name: provider.name,
icon: provider.icon,
},
}))
}).flat()

export default () => {
const [value, setValue] = createSignal('')

export default (props: Props) => {
onMount(() => {
if (!props.value && props.onChange)
props.onChange(botMetaList[0].value)
})
return (
<Select
value={value()}
onChange={setValue}
value={props.value}
onChange={props.onChange}
options={botMetaList}
selectedComponent={item => (
<div class="fi gap-2">
Expand All @@ -44,9 +26,9 @@ export default () => {
itemComponent={(item, isSelected) => (
<div class="fi gap-2 w-full px-2 py-1 border-b border-b-base hv-base">
{item.provider.icon && <div class={item.provider.icon} />}
<div class="flex-1">{item.provider.name} / {item.label}</div>
<div class="flex-1">{item.provider?.name} / {item.label}</div>
{isSelected && (
<div i-carbon-checkmark />
<div i-carbon-checkmark />
)}
</div>
)}
Expand Down
1 change: 0 additions & 1 deletion src/components/ui/ThemeToggle.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@ export default () => {
})

const handleDarkChanged = () => {
console.log('handleDarkChanged')
const dark = !isDark()
document.querySelector('meta[name="theme-color"]')?.setAttribute('content', dark ? '#222222' : '#fafafa')
setIsDark(dark)
Expand Down
17 changes: 12 additions & 5 deletions src/components/ui/base/Select.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { createEffect, createMemo, createUniqueId, mergeProps, on } from 'solid-js'
import { createEffect, createMemo, createSignal, createUniqueId, mergeProps, on } from 'solid-js'
import * as select from '@zag-js/select'
import { normalizeProps, useMachine } from '@zag-js/solid'
import type { JSXElement } from 'solid-js'
Expand All @@ -15,23 +15,30 @@ interface Props<T> {
}

export const Select = <T extends SelectOptionType>(inputProps: Props<T>) => {
const [selectedItem, setSelectedItem] = createSignal<T | null>(null)
const props = mergeProps({
placeholder: 'Select option',
}, inputProps)
const [state, send] = useMachine(select.machine({
id: createUniqueId(),
selectedOption: props.options.find(o => o.value === props.value),
readOnly: props.readonly,
onChange: (details) => {
details && props.onChange(details.value)
onChange: (detail) => {
if (detail) {
setSelectedItem(props.options.find(o => o.value === detail.value))
props.onChange(detail.value)
}
},
}))

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

createEffect(on(() => props.value, () => {
const option = props.options.find(o => o.value === props.value)
option && api().setSelectedOption(option)
if (option) {
api().setSelectedOption(option)
setSelectedItem(option)
}
}))

const selectedComponent = (item: T | null) => {
Expand Down Expand Up @@ -67,7 +74,7 @@ export const Select = <T extends SelectOptionType>(inputProps: Props<T>) => {
class={`fi justify-between w-full px-2 py-1 border border-base ${props.readonly ? '' : 'hv-base'}`}
{...api().triggerProps}
>
{selectedComponent(api().selectedOption as T)}
{selectedComponent(selectedItem())}
{!props.readonly && <div i-carbon-caret-down />}
</button>
</div>
Expand Down
Loading

0 comments on commit b66ef2c

Please sign in to comment.