fix: handle long thread title without space (#3107)

* fix: handle long thread title without space, and make searchbar autofocus inside model dropdown

* feat: enable right click to show setting on thread items (#3108)
This commit is contained in:
Faisal Amir 2024-06-27 09:45:08 +07:00 committed by Louis
parent e77f651273
commit a2a203b40d
No known key found for this signature in database
GPG Key ID: 44FA9F4D33C37DE2
6 changed files with 79 additions and 12 deletions

View File

@ -1,4 +1,4 @@
import { useState, useMemo, useEffect, useCallback } from 'react'
import { useState, useMemo, useEffect, useCallback, useRef } from 'react'
import { InferenceEngine } from '@janhq/core'
import { Badge, Input, ScrollArea, Select, useClickOutside } from '@janhq/joi'
@ -70,7 +70,7 @@ const ModelDropdown = ({
const downloadStates = useAtomValue(modelDownloadStateAtom)
const setThreadModelParams = useSetAtom(setThreadModelParamsAtom)
const { updateModelParameter } = useUpdateModelParameters()
const searchInputRef = useRef<HTMLInputElement>(null)
const configuredModels = useAtomValue(configuredModelsAtom)
const featuredModel = configuredModels.filter((x) =>
x.metadata.tags.includes('Featured')
@ -108,6 +108,12 @@ const ModelDropdown = ({
[configuredModels, searchText, searchFilter]
)
useEffect(() => {
if (open && searchInputRef.current) {
searchInputRef.current.focus()
}
}, [open])
useEffect(() => {
if (!activeThread) return
let model = downloadedModels.find(
@ -258,6 +264,7 @@ const ModelDropdown = ({
<Input
placeholder="Search"
value={searchText}
ref={searchInputRef}
className="rounded-none border-x-0 border-t-0 focus-within:ring-0 hover:border-b-[hsla(var(--app-border))]"
onChange={(e) => setSearchText(e.target.value)}
suffixIcon={

View File

@ -7,9 +7,10 @@ import useDeleteThread from '@/hooks/useDeleteThread'
type Props = {
threadId: string
closeContextMenu?: () => void
}
const ModalCleanThread = ({ threadId }: Props) => {
const ModalCleanThread = ({ threadId, closeContextMenu }: Props) => {
const { cleanThread } = useDeleteThread()
const onCleanThreadClick = useCallback(
(e: React.MouseEvent<HTMLButtonElement, MouseEvent>) => {
@ -22,6 +23,11 @@ const ModalCleanThread = ({ threadId }: Props) => {
return (
<Modal
title="Clean Thread"
onOpenChange={(open) => {
if (open && closeContextMenu) {
closeContextMenu()
}
}}
trigger={
<div
className="flex cursor-pointer items-center space-x-2 px-4 py-2 hover:bg-[hsla(var(--dropdown-menu-hover-bg))]"

View File

@ -7,10 +7,12 @@ import useDeleteThread from '@/hooks/useDeleteThread'
type Props = {
threadId: string
closeContextMenu?: () => void
}
const ModalDeleteThread = ({ threadId }: Props) => {
const ModalDeleteThread = ({ threadId, closeContextMenu }: Props) => {
const { deleteThread } = useDeleteThread()
const onDeleteThreadClick = useCallback(
(e: React.MouseEvent<HTMLButtonElement, MouseEvent>) => {
e.stopPropagation()
@ -22,6 +24,11 @@ const ModalDeleteThread = ({ threadId }: Props) => {
return (
<Modal
title="Delete Thread"
onOpenChange={(open) => {
if (open && closeContextMenu) {
closeContextMenu()
}
}}
trigger={
<div
className="flex cursor-pointer items-center space-x-2 px-4 py-2 hover:bg-[hsla(var(--dropdown-menu-hover-bg))]"

View File

@ -8,9 +8,10 @@ import { useCreateNewThread } from '@/hooks/useCreateNewThread'
type Props = {
thread: Thread
closeContextMenu?: () => void
}
const ModalEditTitleThread = ({ thread }: Props) => {
const ModalEditTitleThread = ({ thread, closeContextMenu }: Props) => {
const [title, setTitle] = useState(thread.title)
const { updateThreadMetadata } = useCreateNewThread()
@ -30,6 +31,11 @@ const ModalEditTitleThread = ({ thread }: Props) => {
return (
<Modal
title="Edit title thread"
onOpenChange={(open) => {
if (open && closeContextMenu) {
closeContextMenu()
}
}}
trigger={
<div
className="flex cursor-pointer items-center space-x-2 px-4 py-2 hover:bg-[hsla(var(--dropdown-menu-hover-bg))]"

View File

@ -1,4 +1,4 @@
import { useCallback, useEffect } from 'react'
import { useCallback, useEffect, useState } from 'react'
import { Thread } from '@janhq/core'
@ -43,6 +43,14 @@ const ThreadLeftPanel = () => {
const setEditMessage = useSetAtom(editMessageAtom)
const { recommendedModel, downloadedModels } = useRecommendedModel()
const [contextMenu, setContextMenu] = useState<{
visible: boolean
thread?: Thread
}>({
visible: false,
thread: undefined,
})
const onThreadClick = useCallback(
(thread: Thread) => {
setActiveThread(thread)
@ -91,6 +99,21 @@ const ThreadLeftPanel = () => {
}
}
const onContextMenu = (event: React.MouseEvent, thread: Thread) => {
event.preventDefault()
setContextMenu({
visible: true,
thread,
})
}
const closeContextMenu = () => {
setContextMenu({
visible: false,
thread: undefined,
})
}
return (
<LeftPanelContainer>
{threads.length === 0 ? (
@ -124,8 +147,10 @@ const ThreadLeftPanel = () => {
onClick={() => {
onThreadClick(thread)
}}
onContextMenu={(e) => onContextMenu(e, thread)}
onMouseLeave={closeContextMenu}
>
<div className="relative z-10 p-2">
<div className="relative z-10 break-all p-2">
<h1
className={twMerge(
'line-clamp-1 pr-2 font-medium group-hover/message:pr-6',
@ -143,10 +168,26 @@ const ThreadLeftPanel = () => {
<Button theme="icon" className="mt-2">
<MoreHorizontalIcon />
</Button>
<div className="invisible absolute -right-1 z-50 w-40 overflow-hidden rounded-lg border border-[hsla(var(--app-border))] bg-[hsla(var(--app-bg))] shadow-lg group-hover/icon:visible">
<ModalEditTitleThread thread={thread} />
<ModalCleanThread threadId={thread.id} />
<ModalDeleteThread threadId={thread.id} />
<div
className={twMerge(
'invisible absolute -right-1 z-50 w-40 overflow-hidden rounded-lg border border-[hsla(var(--app-border))] bg-[hsla(var(--app-bg))] shadow-lg group-hover/icon:visible',
contextMenu.visible &&
contextMenu.thread?.id === thread.id &&
'visible'
)}
>
<ModalEditTitleThread
thread={thread}
closeContextMenu={closeContextMenu}
/>
<ModalCleanThread
threadId={thread.id}
closeContextMenu={closeContextMenu}
/>
<ModalDeleteThread
threadId={thread.id}
closeContextMenu={closeContextMenu}
/>
</div>
</div>
{activeThreadId === thread.id && (

View File

@ -166,7 +166,7 @@ const Tools = () => {
<div className="mb-2 flex items-center">
<label
id="vector-database"
className="inline-block font-medium"
className="inline-flex items-center font-medium"
>
Vector Database
<Tooltip