feat(video): add provider settings component and layout
Implement provider selection dropdown in video settings panel Add shared setting components for consistent styling Update video page layout to accommodate settings sidebar
This commit is contained in:
@@ -1,16 +1,30 @@
|
||||
// interface VideoPageProps {}
|
||||
|
||||
import { Divider } from '@heroui/react'
|
||||
import { Navbar, NavbarCenter } from '@renderer/components/app/Navbar'
|
||||
import { SystemProviderIds } from '@renderer/types'
|
||||
import { useState } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
|
||||
import { ProviderSetting } from './settings/ProviderSetting'
|
||||
|
||||
export const VideoPage = () => {
|
||||
const { t } = useTranslation()
|
||||
const [providerId, setProviderId] = useState<string>(SystemProviderIds.openai)
|
||||
return (
|
||||
<div className="flex flex-1 flex-col">
|
||||
<Navbar>
|
||||
<NavbarCenter style={{ borderRight: 'none' }}>{t('video.title')}</NavbarCenter>
|
||||
</Navbar>
|
||||
<div className="flex flex-1">video page</div>
|
||||
<div id="content-container" className="flex flex-1">
|
||||
<div className="flex w-70 flex-col p-2">
|
||||
<ProviderSetting providerId={providerId} setProviderId={setProviderId} />
|
||||
</div>
|
||||
<Divider orientation="vertical" />
|
||||
<div className="flex-1 p-2"></div>
|
||||
<Divider orientation="vertical" />
|
||||
<div className="w-25"></div>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -0,0 +1,59 @@
|
||||
import { Select, SelectItem } from '@heroui/react'
|
||||
import { ProviderAvatar } from '@renderer/components/ProviderAvatar'
|
||||
import { useProviders } from '@renderer/hooks/useProvider'
|
||||
import { Provider, SystemProviderId } from '@renderer/types'
|
||||
import { getFancyProviderName } from '@renderer/utils'
|
||||
import { Dispatch, SetStateAction } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
|
||||
import { SettingItem, SettingTitle } from './shared'
|
||||
|
||||
export interface ProviderSettingProps {
|
||||
providerId: string
|
||||
setProviderId: Dispatch<SetStateAction<string>>
|
||||
}
|
||||
|
||||
interface ProviderSelectItem extends Provider {
|
||||
key: string
|
||||
label: string
|
||||
}
|
||||
|
||||
export const ProviderSetting = ({ providerId, setProviderId }: ProviderSettingProps) => {
|
||||
const { t } = useTranslation()
|
||||
// Support limited providers.
|
||||
const supportedProviderIds = ['openai'] satisfies SystemProviderId[]
|
||||
const { providers } = useProviders()
|
||||
const items: ProviderSelectItem[] = providers
|
||||
.filter((p) => supportedProviderIds.some((id) => id === p.id))
|
||||
.map((p) => ({ ...p, key: p.id, label: getFancyProviderName(p) }))
|
||||
|
||||
return (
|
||||
<SettingItem>
|
||||
<SettingTitle name={t('common.provider')} />
|
||||
<Select
|
||||
selectionMode="single"
|
||||
items={items}
|
||||
defaultSelectedKeys={[providerId]}
|
||||
disallowEmptySelection
|
||||
onSelectionChange={(keys) => {
|
||||
if (keys.currentKey) setProviderId(keys.currentKey)
|
||||
}}
|
||||
renderValue={(items) => {
|
||||
const provider = items[0].data
|
||||
if (!provider) return null
|
||||
return (
|
||||
<div className="flex items-center gap-2">
|
||||
<ProviderAvatar provider={provider} size={16} />
|
||||
<span>{provider.label}</span>
|
||||
</div>
|
||||
)
|
||||
}}>
|
||||
{(provider) => (
|
||||
<SelectItem textValue={provider.label} startContent={<ProviderAvatar provider={provider} size={16} />}>
|
||||
<span>{provider.label}</span>
|
||||
</SelectItem>
|
||||
)}
|
||||
</Select>
|
||||
</SettingItem>
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
import { cn, Divider } from '@heroui/react'
|
||||
import { PropsWithChildren, ReactNode } from 'react'
|
||||
|
||||
export const SettingItem = ({ children, divider = true }: PropsWithChildren<{ divider?: boolean }>) => {
|
||||
return (
|
||||
<>
|
||||
<div className="mb-2">{children}</div>
|
||||
{divider && <Divider className="my-2" />}
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
export const SettingTitle = ({ name, footer }: { name: string; footer?: ReactNode }) => {
|
||||
return (
|
||||
<div className={cn('mb-2 flex items-center', footer ? 'justify-between' : 'justify-start')}>
|
||||
<span className="font-bold">{name}</span>
|
||||
{footer}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
Reference in New Issue
Block a user