mirror of
https://git.mirrors.martin98.com/https://github.com/langgenius/dify.git
synced 2025-08-12 16:59:04 +08:00
feat: optimize conversation operation (#479)
This commit is contained in:
parent
a87f6f2837
commit
838825d747
@ -56,16 +56,14 @@ export default function AppNavItem({
|
|||||||
<div className='overflow-hidden text-ellipsis whitespace-nowrap'>{name}</div>
|
<div className='overflow-hidden text-ellipsis whitespace-nowrap'>{name}</div>
|
||||||
</div>
|
</div>
|
||||||
{
|
{
|
||||||
!isSelected && (
|
<div className={cn(s.opBtn, 'shrink-0')} onClick={e => e.stopPropagation()}>
|
||||||
<div className={cn(s.opBtn, 'shrink-0')} onClick={e => e.stopPropagation()}>
|
<ItemOperation
|
||||||
<ItemOperation
|
isPinned={isPinned}
|
||||||
isPinned={isPinned}
|
togglePin={togglePin}
|
||||||
togglePin={togglePin}
|
isShowDelete={!uninstallable && !isSelected}
|
||||||
isShowDelete={!uninstallable}
|
onDelete={() => onDelete(id)}
|
||||||
onDelete={() => onDelete(id)}
|
/>
|
||||||
/>
|
</div>
|
||||||
</div>
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
|
@ -67,6 +67,8 @@ const Main: FC<IMainProps> = ({
|
|||||||
* conversation info
|
* conversation info
|
||||||
*/
|
*/
|
||||||
const [allConversationList, setAllConversationList] = useState<ConversationItem[]>([])
|
const [allConversationList, setAllConversationList] = useState<ConversationItem[]>([])
|
||||||
|
const [isClearConversationList, { setTrue: clearConversationListTrue, setFalse: clearConversationListFalse }] = useBoolean(false)
|
||||||
|
const [isClearPinnedConversationList, { setTrue: clearPinnedConversationListTrue, setFalse: clearPinnedConversationListFalse }] = useBoolean(false)
|
||||||
const {
|
const {
|
||||||
conversationList,
|
conversationList,
|
||||||
setConversationList,
|
setConversationList,
|
||||||
@ -89,18 +91,32 @@ const Main: FC<IMainProps> = ({
|
|||||||
const [hasPinnedMore, setHasPinnedMore] = useState<boolean>(true)
|
const [hasPinnedMore, setHasPinnedMore] = useState<boolean>(true)
|
||||||
const onMoreLoaded = ({ data: conversations, has_more }: any) => {
|
const onMoreLoaded = ({ data: conversations, has_more }: any) => {
|
||||||
setHasMore(has_more)
|
setHasMore(has_more)
|
||||||
setConversationList([...conversationList, ...conversations])
|
if (isClearConversationList) {
|
||||||
|
setConversationList(conversations)
|
||||||
|
clearConversationListFalse()
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
setConversationList([...conversationList, ...conversations])
|
||||||
|
}
|
||||||
}
|
}
|
||||||
const onPinnedMoreLoaded = ({ data: conversations, has_more }: any) => {
|
const onPinnedMoreLoaded = ({ data: conversations, has_more }: any) => {
|
||||||
setHasPinnedMore(has_more)
|
setHasPinnedMore(has_more)
|
||||||
setPinnedConversationList([...pinnedConversationList, ...conversations])
|
if (isClearPinnedConversationList) {
|
||||||
|
setPinnedConversationList(conversations)
|
||||||
|
clearPinnedConversationListFalse()
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
setPinnedConversationList([...pinnedConversationList, ...conversations])
|
||||||
|
}
|
||||||
}
|
}
|
||||||
const [controlUpdateConversationList, setControlUpdateConversationList] = useState(0)
|
const [controlUpdateConversationList, setControlUpdateConversationList] = useState(0)
|
||||||
const noticeUpdateList = () => {
|
const noticeUpdateList = () => {
|
||||||
setConversationList([])
|
|
||||||
setHasMore(true)
|
setHasMore(true)
|
||||||
setPinnedConversationList([])
|
clearConversationListTrue()
|
||||||
|
|
||||||
setHasPinnedMore(true)
|
setHasPinnedMore(true)
|
||||||
|
clearPinnedConversationListTrue()
|
||||||
|
|
||||||
setControlUpdateConversationList(Date.now())
|
setControlUpdateConversationList(Date.now())
|
||||||
}
|
}
|
||||||
const handlePin = async (id: string) => {
|
const handlePin = async (id: string) => {
|
||||||
@ -126,6 +142,9 @@ const Main: FC<IMainProps> = ({
|
|||||||
await delConversation(isInstalledApp, installedAppInfo?.id, toDeleteConversationId)
|
await delConversation(isInstalledApp, installedAppInfo?.id, toDeleteConversationId)
|
||||||
notify({ type: 'success', message: t('common.api.success') })
|
notify({ type: 'success', message: t('common.api.success') })
|
||||||
hideConfirm()
|
hideConfirm()
|
||||||
|
if (currConversationId === toDeleteConversationId)
|
||||||
|
handleConversationIdChange('-1')
|
||||||
|
|
||||||
noticeUpdateList()
|
noticeUpdateList()
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -496,7 +515,9 @@ const Main: FC<IMainProps> = ({
|
|||||||
return (
|
return (
|
||||||
<Sidebar
|
<Sidebar
|
||||||
list={conversationList}
|
list={conversationList}
|
||||||
|
isClearConversationList={isClearConversationList}
|
||||||
pinnedList={pinnedConversationList}
|
pinnedList={pinnedConversationList}
|
||||||
|
isClearPinnedConversationList={isClearPinnedConversationList}
|
||||||
onMoreLoaded={onMoreLoaded}
|
onMoreLoaded={onMoreLoaded}
|
||||||
onPinnedMoreLoaded={onPinnedMoreLoaded}
|
onPinnedMoreLoaded={onPinnedMoreLoaded}
|
||||||
isNoMore={!hasMore}
|
isNoMore={!hasMore}
|
||||||
|
@ -17,7 +17,9 @@ export type ISidebarProps = {
|
|||||||
currentId: string
|
currentId: string
|
||||||
onCurrentIdChange: (id: string) => void
|
onCurrentIdChange: (id: string) => void
|
||||||
list: ConversationItem[]
|
list: ConversationItem[]
|
||||||
|
isClearConversationList: boolean
|
||||||
pinnedList: ConversationItem[]
|
pinnedList: ConversationItem[]
|
||||||
|
isClearPinnedConversationList: boolean
|
||||||
isInstalledApp: boolean
|
isInstalledApp: boolean
|
||||||
installedAppId?: string
|
installedAppId?: string
|
||||||
siteInfo: SiteInfo
|
siteInfo: SiteInfo
|
||||||
@ -36,7 +38,9 @@ const Sidebar: FC<ISidebarProps> = ({
|
|||||||
currentId,
|
currentId,
|
||||||
onCurrentIdChange,
|
onCurrentIdChange,
|
||||||
list,
|
list,
|
||||||
|
isClearConversationList,
|
||||||
pinnedList,
|
pinnedList,
|
||||||
|
isClearPinnedConversationList,
|
||||||
isInstalledApp,
|
isInstalledApp,
|
||||||
installedAppId,
|
installedAppId,
|
||||||
siteInfo,
|
siteInfo,
|
||||||
@ -92,16 +96,17 @@ const Sidebar: FC<ISidebarProps> = ({
|
|||||||
<PencilSquareIcon className="mr-2 h-4 w-4" /> {t('share.chat.newChat')}
|
<PencilSquareIcon className="mr-2 h-4 w-4" /> {t('share.chat.newChat')}
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
<div className='flex-grow h-0 overflow-y-auto overflow-x-hidden'>
|
<div className={'flex-grow flex flex-col h-0 overflow-y-auto overflow-x-hidden'}>
|
||||||
{/* pinned list */}
|
{/* pinned list */}
|
||||||
{hasPinned && (
|
{hasPinned && (
|
||||||
<div className='mt-4 px-4'>
|
<div className={cn('mt-4 px-4', list.length === 0 && 'flex flex-col flex-grow')}>
|
||||||
<div className='mb-1.5 leading-[18px] text-xs text-gray-500 font-medium uppercase'>{t('share.chat.pinnedTitle')}</div>
|
<div className='mb-1.5 leading-[18px] text-xs text-gray-500 font-medium uppercase'>{t('share.chat.pinnedTitle')}</div>
|
||||||
<List
|
<List
|
||||||
className={maxListHeight}
|
className={cn(list.length > 0 ? maxListHeight : 'flex-grow')}
|
||||||
currentId={currentId}
|
currentId={currentId}
|
||||||
onCurrentIdChange={onCurrentIdChange}
|
onCurrentIdChange={onCurrentIdChange}
|
||||||
list={pinnedList}
|
list={pinnedList}
|
||||||
|
isClearConversationList={isClearPinnedConversationList}
|
||||||
isInstalledApp={isInstalledApp}
|
isInstalledApp={isInstalledApp}
|
||||||
installedAppId={installedAppId}
|
installedAppId={installedAppId}
|
||||||
onMoreLoaded={onPinnedMoreLoaded}
|
onMoreLoaded={onPinnedMoreLoaded}
|
||||||
@ -114,8 +119,8 @@ const Sidebar: FC<ISidebarProps> = ({
|
|||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
{/* unpinned list */}
|
{/* unpinned list */}
|
||||||
<div className='mt-4 px-4'>
|
<div className={cn('mt-4 px-4', !hasPinned && 'flex flex-col flex-grow')}>
|
||||||
{hasPinned && (
|
{(hasPinned && list.length > 0) && (
|
||||||
<div className='mb-1.5 leading-[18px] text-xs text-gray-500 font-medium uppercase'>{t('share.chat.unpinnedTitle')}</div>
|
<div className='mb-1.5 leading-[18px] text-xs text-gray-500 font-medium uppercase'>{t('share.chat.unpinnedTitle')}</div>
|
||||||
)}
|
)}
|
||||||
<List
|
<List
|
||||||
@ -123,6 +128,7 @@ const Sidebar: FC<ISidebarProps> = ({
|
|||||||
currentId={currentId}
|
currentId={currentId}
|
||||||
onCurrentIdChange={onCurrentIdChange}
|
onCurrentIdChange={onCurrentIdChange}
|
||||||
list={list}
|
list={list}
|
||||||
|
isClearConversationList={isClearConversationList}
|
||||||
isInstalledApp={isInstalledApp}
|
isInstalledApp={isInstalledApp}
|
||||||
installedAppId={installedAppId}
|
installedAppId={installedAppId}
|
||||||
onMoreLoaded={onMoreLoaded}
|
onMoreLoaded={onMoreLoaded}
|
||||||
@ -133,6 +139,7 @@ const Sidebar: FC<ISidebarProps> = ({
|
|||||||
onDelete={onDelete}
|
onDelete={onDelete}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
<div className="flex flex-shrink-0 pr-4 pb-4 pl-4">
|
<div className="flex flex-shrink-0 pr-4 pb-4 pl-4">
|
||||||
<div className="text-gray-400 font-normal text-xs">© {copyRight} {(new Date()).getFullYear()}</div>
|
<div className="text-gray-400 font-normal text-xs">© {copyRight} {(new Date()).getFullYear()}</div>
|
||||||
|
@ -17,6 +17,7 @@ export type IListProps = {
|
|||||||
currentId: string
|
currentId: string
|
||||||
onCurrentIdChange: (id: string) => void
|
onCurrentIdChange: (id: string) => void
|
||||||
list: ConversationItem[]
|
list: ConversationItem[]
|
||||||
|
isClearConversationList: boolean
|
||||||
isInstalledApp: boolean
|
isInstalledApp: boolean
|
||||||
installedAppId?: string
|
installedAppId?: string
|
||||||
onMoreLoaded: (res: { data: ConversationItem[]; has_more: boolean }) => void
|
onMoreLoaded: (res: { data: ConversationItem[]; has_more: boolean }) => void
|
||||||
@ -32,6 +33,7 @@ const List: FC<IListProps> = ({
|
|||||||
currentId,
|
currentId,
|
||||||
onCurrentIdChange,
|
onCurrentIdChange,
|
||||||
list,
|
list,
|
||||||
|
isClearConversationList,
|
||||||
isInstalledApp,
|
isInstalledApp,
|
||||||
installedAppId,
|
installedAppId,
|
||||||
onMoreLoaded,
|
onMoreLoaded,
|
||||||
@ -46,7 +48,7 @@ const List: FC<IListProps> = ({
|
|||||||
useInfiniteScroll(
|
useInfiniteScroll(
|
||||||
async () => {
|
async () => {
|
||||||
if (!isNoMore) {
|
if (!isNoMore) {
|
||||||
const lastId = list[list.length - 1]?.id
|
const lastId = !isClearConversationList ? list[list.length - 1]?.id : undefined
|
||||||
const { data: conversations, has_more }: any = await fetchConversations(isInstalledApp, installedAppId, lastId, isPinned)
|
const { data: conversations, has_more }: any = await fetchConversations(isInstalledApp, installedAppId, lastId, isPinned)
|
||||||
onMoreLoaded({ data: conversations, has_more })
|
onMoreLoaded({ data: conversations, has_more })
|
||||||
}
|
}
|
||||||
@ -63,7 +65,7 @@ const List: FC<IListProps> = ({
|
|||||||
return (
|
return (
|
||||||
<nav
|
<nav
|
||||||
ref={listRef}
|
ref={listRef}
|
||||||
className={cn(className, 'shrink-0 space-y-1 bg-white pb-[60px] overflow-y-auto')}
|
className={cn(className, 'shrink-0 space-y-1 bg-white pb-[85px] overflow-y-auto')}
|
||||||
>
|
>
|
||||||
{list.map((item) => {
|
{list.map((item) => {
|
||||||
const isCurrent = item.id === currentId
|
const isCurrent = item.id === currentId
|
||||||
@ -93,18 +95,16 @@ const List: FC<IListProps> = ({
|
|||||||
<span>{item.name}</span>
|
<span>{item.name}</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{
|
{item.id !== '-1' && (
|
||||||
!isCurrent && (
|
<div className={cn(s.opBtn, 'shrink-0')} onClick={e => e.stopPropagation()}>
|
||||||
<div className={cn(s.opBtn, 'shrink-0')} onClick={e => e.stopPropagation()}>
|
<ItemOperation
|
||||||
<ItemOperation
|
isPinned={isPinned}
|
||||||
isPinned={isPinned}
|
togglePin={() => onPinChanged(item.id)}
|
||||||
togglePin={() => onPinChanged(item.id)}
|
isShowDelete
|
||||||
isShowDelete
|
onDelete={() => onDelete(item.id)}
|
||||||
onDelete={() => onDelete(item.id)}
|
/>
|
||||||
/>
|
</div>
|
||||||
</div>
|
)}
|
||||||
)
|
|
||||||
}
|
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
})}
|
})}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user