Skip to content

Commit

Permalink
feat: The conversation ui supports switching models and displaying title
Browse files Browse the repository at this point in the history
refactor: Optimize file name display in file list
  • Loading branch information
Amery2010 committed Feb 11, 2025
1 parent e0bddb3 commit 03665a4
Show file tree
Hide file tree
Showing 7 changed files with 133 additions and 17 deletions.
9 changes: 9 additions & 0 deletions app/globals.css
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,15 @@ body {
width: 20px;
height: 20px;
}
.text-line-clamp {
display: -webkit-box;
-webkit-line-clamp: 1;
line-clamp: 1;
-webkit-box-orient: vertical;
box-orient: vertical;
overflow: hidden;
text-overflow: ellipsis;
}
.text-line-clamp-2 {
display: -webkit-box;
-webkit-line-clamp: 2;
Expand Down
21 changes: 16 additions & 5 deletions app/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,7 @@ const AssistantRecommend = dynamic(() => import('@/components/AssistantRecommend
const Setting = dynamic(() => import('@/components/Setting'))
const FileUploader = dynamic(() => import('@/components/FileUploader'))
const PluginList = dynamic(() => import('@/components/PluginList'))
const ModelSelect = dynamic(() => import('@/components/ModelSelect'))

export default function Home() {
const { t } = useTranslation()
Expand All @@ -87,6 +88,7 @@ export default function Home() {
const stopGeneratingRef = useRef<boolean>(false)
const messagesRef = useRef(useMessageStore.getState().messages)
const messages = useMessageStore((state) => state.messages)
const title = useMessageStore((state) => state.title)
const systemInstruction = useMessageStore((state) => state.systemInstruction)
const systemInstructionEditMode = useMessageStore((state) => state.systemInstructionEditMode)
const chatLayout = useMessageStore((state) => state.chatLayout)
Expand All @@ -109,6 +111,7 @@ export default function Home() {
const [executingPlugins, setExecutingPlugins] = useState<string[]>([])
const [enablePlugin, setEnablePlugin] = useState<boolean>(true)
const [status, setStatus] = useState<'thinkng' | 'silence' | 'talking'>('silence')
const conversationTitle = useMemo(() => (title ? title : t('chatAnything')), [title, t])
const statusText = useMemo(() => {
switch (status) {
case 'silence':
Expand Down Expand Up @@ -934,12 +937,20 @@ export default function Home() {

return (
<main className="mx-auto flex h-screen max-h-[-webkit-fill-available] w-full max-w-screen-md flex-col justify-between overflow-hidden">
<div className="flex justify-between px-4 pb-2 pr-2 pt-10 max-md:pt-4 max-sm:pr-2 max-sm:pt-4">
<div className="flex flex-row text-xl leading-8 text-red-400 max-sm:text-base">
<MessageCircleHeart className="h-10 w-10 max-sm:h-8 max-sm:w-8" />
<div className="ml-2 font-bold leading-10 max-sm:ml-1 max-sm:leading-8">Gemini Next Chat</div>
<div className="flex w-full justify-between px-4 pb-2 pr-2 pt-10 max-md:pt-4 max-sm:pr-2 max-sm:pt-4">
<div className="flex items-center text-red-400">
<div>
<MessageCircleHeart className="h-10 w-10 max-sm:h-8 max-sm:w-8" />
</div>
<div className="ml-1 flex-1 max-sm:ml-0.5">
<h2 className="text-line-clamp break-all font-bold leading-6 max-sm:text-sm">{conversationTitle}</h2>
<ModelSelect
className="flex h-4 justify-start border-none px-0 py-0 leading-4 text-slate-500 hover:text-slate-700 dark:hover:text-slate-400"
defaultModel={model}
/>
</div>
</div>
<div className="flex items-center gap-1">
<div className="flex w-32 items-center gap-1 max-sm:gap-0">
<a href="https://github.com/u14app/gemini-next-chat" target="_blank">
<Button className="h-8 w-8" title={t('github')} variant="ghost" size="icon">
<Github className="h-5 w-5" />
Expand Down
20 changes: 11 additions & 9 deletions components/FileList.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -39,19 +39,21 @@ function FileList({ fileList, onRemove }: Props) {
)}
key={file.id}
>
<div className="relative mr-1.5 h-14 w-1/3">
<div className="relative mr-1.5 h-14 w-1/4">
{<FileCover file={file} />}
{file.status === 'PROCESSING' ? <Loader2 className="absolute left-4 top-4 h-6 w-6 animate-spin" /> : null}
</div>
<div className="relative h-14 w-2/3 flex-auto pr-4 text-sm">
<h4 className="text-line-clamp-2 font-medium leading-5" title={file.name}>
{file.name}
</h4>
<p>
<small>{formatSize(file.size)}</small>
</p>
<div className="flex h-14 w-3/4 flex-auto text-sm">
<div className="flex-1">
<h4 className="text-line-clamp-2 break-all font-medium leading-5" title={file.name}>
{file.name}
</h4>
<p>
<small>{formatSize(file.size)}</small>
</p>
</div>
{isFunction(onRemove) ? (
<X className="absolute -right-1 -top-0.5 h-5 w-5 cursor-pointer" onClick={() => onRemove(file.id)} />
<X className="relative -top-0.5 h-5 w-5 cursor-pointer" onClick={() => onRemove(file.id)} />
) : null}
</div>
</div>
Expand Down
94 changes: 94 additions & 0 deletions components/ModelSelect.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
import { useMemo, useCallback, memo } from 'react'
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '@/components/ui/select'
import { useSettingStore, useEnvStore } from '@/store/setting'
import { useModelStore } from '@/store/model'
import { Model } from '@/constant/model'
import { values, keys, find } from 'lodash-es'

type Props = {
className?: string
defaultModel: string
}

function ModelSelect({ className, defaultModel }: Props) {
const { models } = useModelStore()
const { update } = useSettingStore()
const { modelList: MODEL_LIST } = useEnvStore()

const modelOptions = useMemo(() => {
if (models.length > 0) {
const systemModels = values(Model)
models.forEach((item) => {
const modelName = item.name.replace('models/', '')
if (!systemModels.includes(modelName)) {
Model[modelName] = item.displayName
}
})
}

let modelList: string[] = []
const defaultModelList: string[] = keys(Model)
const userModels: string[] = MODEL_LIST ? MODEL_LIST.split(',') : []

userModels.forEach((modelName) => {
for (const name of defaultModelList) {
if (!modelList.includes(name)) modelList.push(name)
}
if (modelName === 'all' || modelName === '+all') {
} else if (modelName === '-all') {
modelList = modelList.filter((name) => !defaultModelList.includes(name))
} else if (modelName.startsWith('-')) {
modelList = modelList.filter((name) => name !== modelName.substring(1))
} else if (modelName.startsWith('@')) {
const name = modelName.substring(1)
if (!modelList.includes(name)) modelList.push(name)
} else {
modelList.push(modelName.startsWith('+') ? modelName.substring(1) : modelName)
}
})

return modelList.length > 0 ? modelList : defaultModelList
}, [models, MODEL_LIST])

const handleModelChange = useCallback(
(name: string) => {
const currentModel = find(models, { name: `models/${name}` })
if (currentModel) {
const values: Record<string, number> = {}
const { topP, topK, temperature, outputTokenLimit } = currentModel
if (topP) values.topP = topP
if (topK) values.topK = topK
if (temperature) values.temperature = temperature
if (outputTokenLimit) values.maxOutputTokens = outputTokenLimit
update({ model: name, ...values })
} else {
update({ model: name })
}
},
[update, models],
)

return (
<Select
defaultValue={defaultModel}
onValueChange={(value) => {
handleModelChange(value)
}}
>
<SelectTrigger className={className}>
<SelectValue placeholder="Model" />
</SelectTrigger>
<SelectContent>
{modelOptions.map((name) => {
return (
<SelectItem key={name} value={name}>
{name}
</SelectItem>
)
})}
</SelectContent>
</Select>
)
}

export default memo(ModelSelect)
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "gemini-next-chat",
"version": "1.8.0",
"version": "1.8.1",
"private": true,
"author": "Amery2010 <amery@xiangfa.org>",
"license": "MIT",
Expand Down
2 changes: 1 addition & 1 deletion src-tauri/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "gemini-next-chat"
version = "1.8.0"
version = "1.8.1"
description = "Your private Gemini application."
authors = ["Amery2010<amery@xiangfa.org>"]
license = "MIT"
Expand Down
2 changes: 1 addition & 1 deletion src-tauri/tauri.conf.json
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@
},
"productName": "gemini-next-chat",
"mainBinaryName": "gemini-next-chat",
"version": "1.8.0",
"version": "1.8.1",
"identifier": "com.u14.app",
"plugins": {},
"app": {
Expand Down

0 comments on commit 03665a4

Please sign in to comment.