mirror of
https://github.com/CherryHQ/cherry-studio.git
synced 2026-01-04 03:40:33 +08:00
refactor: quick panel remove multi-select mode
This commit is contained in:
parent
559fcecf77
commit
d7002cda11
@ -27,6 +27,11 @@ export const QuickPanelProvider: React.FC<React.PropsWithChildren> = ({ children
|
|||||||
|
|
||||||
const clearTimer = useRef<NodeJS.Timeout | null>(null)
|
const clearTimer = useRef<NodeJS.Timeout | null>(null)
|
||||||
|
|
||||||
|
// 添加更新item选中状态的方法
|
||||||
|
const updateItemSelection = useCallback((targetItem: QuickPanelListItem, isSelected: boolean) => {
|
||||||
|
setList((prevList) => prevList.map((item) => (item === targetItem ? { ...item, isSelected } : item)))
|
||||||
|
}, [])
|
||||||
|
|
||||||
const open = useCallback((options: QuickPanelOpenOptions) => {
|
const open = useCallback((options: QuickPanelOpenOptions) => {
|
||||||
if (clearTimer.current) {
|
if (clearTimer.current) {
|
||||||
clearTimeout(clearTimer.current)
|
clearTimeout(clearTimer.current)
|
||||||
@ -77,6 +82,7 @@ export const QuickPanelProvider: React.FC<React.PropsWithChildren> = ({ children
|
|||||||
() => ({
|
() => ({
|
||||||
open,
|
open,
|
||||||
close,
|
close,
|
||||||
|
updateItemSelection,
|
||||||
|
|
||||||
isVisible,
|
isVisible,
|
||||||
symbol,
|
symbol,
|
||||||
@ -90,7 +96,21 @@ export const QuickPanelProvider: React.FC<React.PropsWithChildren> = ({ children
|
|||||||
beforeAction,
|
beforeAction,
|
||||||
afterAction
|
afterAction
|
||||||
}),
|
}),
|
||||||
[open, close, isVisible, symbol, list, title, defaultIndex, pageSize, multiple, onClose, beforeAction, afterAction]
|
[
|
||||||
|
open,
|
||||||
|
close,
|
||||||
|
updateItemSelection,
|
||||||
|
isVisible,
|
||||||
|
symbol,
|
||||||
|
list,
|
||||||
|
title,
|
||||||
|
defaultIndex,
|
||||||
|
pageSize,
|
||||||
|
multiple,
|
||||||
|
onClose,
|
||||||
|
beforeAction,
|
||||||
|
afterAction
|
||||||
|
]
|
||||||
)
|
)
|
||||||
|
|
||||||
return <QuickPanelContext value={value}>{children}</QuickPanelContext>
|
return <QuickPanelContext value={value}>{children}</QuickPanelContext>
|
||||||
|
|||||||
@ -52,6 +52,7 @@ export type QuickPanelListItem = {
|
|||||||
export interface QuickPanelContextType {
|
export interface QuickPanelContextType {
|
||||||
readonly open: (options: QuickPanelOpenOptions) => void
|
readonly open: (options: QuickPanelOpenOptions) => void
|
||||||
readonly close: (action?: QuickPanelCloseAction) => void
|
readonly close: (action?: QuickPanelCloseAction) => void
|
||||||
|
readonly updateItemSelection: (targetItem: QuickPanelListItem, isSelected: boolean) => void
|
||||||
readonly isVisible: boolean
|
readonly isVisible: boolean
|
||||||
readonly symbol: string
|
readonly symbol: string
|
||||||
readonly list: QuickPanelListItem[]
|
readonly list: QuickPanelListItem[]
|
||||||
|
|||||||
@ -50,7 +50,7 @@ export const QuickPanelView: React.FC<Props> = ({ setInputText }) => {
|
|||||||
const [isMouseOver, setIsMouseOver] = useState(false)
|
const [isMouseOver, setIsMouseOver] = useState(false)
|
||||||
|
|
||||||
const scrollTriggerRef = useRef<QuickPanelScrollTrigger>('initial')
|
const scrollTriggerRef = useRef<QuickPanelScrollTrigger>('initial')
|
||||||
const [_index, setIndex] = useState(ctx.defaultIndex)
|
const [_index, setIndex] = useState(-1)
|
||||||
const index = useDeferredValue(_index)
|
const index = useDeferredValue(_index)
|
||||||
const [historyPanel, setHistoryPanel] = useState<QuickPanelOpenOptions[]>([])
|
const [historyPanel, setHistoryPanel] = useState<QuickPanelOpenOptions[]>([])
|
||||||
|
|
||||||
@ -62,6 +62,10 @@ export const QuickPanelView: React.FC<Props> = ({ setInputText }) => {
|
|||||||
const searchText = useDeferredValue(_searchText)
|
const searchText = useDeferredValue(_searchText)
|
||||||
const searchTextRef = useRef('')
|
const searchTextRef = useRef('')
|
||||||
|
|
||||||
|
// 跟踪上一次的搜索文本和符号,用于判断是否需要重置index
|
||||||
|
const prevSearchTextRef = useRef('')
|
||||||
|
const prevSymbolRef = useRef('')
|
||||||
|
|
||||||
// 处理搜索,过滤列表
|
// 处理搜索,过滤列表
|
||||||
const list = useMemo(() => {
|
const list = useMemo(() => {
|
||||||
if (!ctx.isVisible && !ctx.symbol) return []
|
if (!ctx.isVisible && !ctx.symbol) return []
|
||||||
@ -104,7 +108,24 @@ export const QuickPanelView: React.FC<Props> = ({ setInputText }) => {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
setIndex(newList.length > 0 ? ctx.defaultIndex || 0 : -1)
|
// 只有在搜索文本变化或面板符号变化时才重置index
|
||||||
|
const isSearchChanged = prevSearchTextRef.current !== searchText
|
||||||
|
const isSymbolChanged = prevSymbolRef.current !== ctx.symbol
|
||||||
|
|
||||||
|
if (isSearchChanged || isSymbolChanged) {
|
||||||
|
setIndex(-1) // 不默认高亮任何项,让用户主动选择
|
||||||
|
} else {
|
||||||
|
// 如果当前index超出范围,调整到有效范围内
|
||||||
|
setIndex((prevIndex) => {
|
||||||
|
if (prevIndex >= newList.length) {
|
||||||
|
return newList.length > 0 ? newList.length - 1 : -1
|
||||||
|
}
|
||||||
|
return prevIndex
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
prevSearchTextRef.current = searchText
|
||||||
|
prevSymbolRef.current = ctx.symbol
|
||||||
|
|
||||||
return newList
|
return newList
|
||||||
}, [ctx.defaultIndex, ctx.isVisible, ctx.list, ctx.symbol, searchText])
|
}, [ctx.defaultIndex, ctx.isVisible, ctx.list, ctx.symbol, searchText])
|
||||||
@ -168,12 +189,33 @@ export const QuickPanelView: React.FC<Props> = ({ setInputText }) => {
|
|||||||
(item: QuickPanelListItem, action?: QuickPanelCloseAction) => {
|
(item: QuickPanelListItem, action?: QuickPanelCloseAction) => {
|
||||||
if (item.disabled) return
|
if (item.disabled) return
|
||||||
|
|
||||||
|
// 在多选模式下,先更新选中状态
|
||||||
|
if (ctx.multiple && !item.isMenu) {
|
||||||
|
const newSelectedState = !item.isSelected
|
||||||
|
ctx.updateItemSelection(item, newSelectedState)
|
||||||
|
|
||||||
|
// 创建更新后的item对象用于回调
|
||||||
|
const updatedItem = { ...item, isSelected: newSelectedState }
|
||||||
|
const quickPanelCallBackOptions: QuickPanelCallBackOptions = {
|
||||||
|
symbol: ctx.symbol,
|
||||||
|
action,
|
||||||
|
item: updatedItem,
|
||||||
|
searchText: searchText,
|
||||||
|
multiple: ctx.multiple
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx.beforeAction?.(quickPanelCallBackOptions)
|
||||||
|
item?.action?.(quickPanelCallBackOptions)
|
||||||
|
ctx.afterAction?.(quickPanelCallBackOptions)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
const quickPanelCallBackOptions: QuickPanelCallBackOptions = {
|
const quickPanelCallBackOptions: QuickPanelCallBackOptions = {
|
||||||
symbol: ctx.symbol,
|
symbol: ctx.symbol,
|
||||||
action,
|
action,
|
||||||
item,
|
item,
|
||||||
searchText: searchText,
|
searchText: searchText,
|
||||||
multiple: isAssistiveKeyPressed
|
multiple: ctx.multiple
|
||||||
}
|
}
|
||||||
|
|
||||||
ctx.beforeAction?.(quickPanelCallBackOptions)
|
ctx.beforeAction?.(quickPanelCallBackOptions)
|
||||||
@ -200,11 +242,12 @@ export const QuickPanelView: React.FC<Props> = ({ setInputText }) => {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ctx.multiple && isAssistiveKeyPressed) return
|
// 多选模式下不关闭面板
|
||||||
|
if (ctx.multiple) return
|
||||||
|
|
||||||
handleClose(action)
|
handleClose(action)
|
||||||
},
|
},
|
||||||
[ctx, searchText, isAssistiveKeyPressed, handleClose, clearSearchText, index]
|
[ctx, searchText, handleClose, clearSearchText, index]
|
||||||
)
|
)
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
@ -294,12 +337,16 @@ export const QuickPanelView: React.FC<Props> = ({ setInputText }) => {
|
|||||||
scrollTriggerRef.current = 'keyboard'
|
scrollTriggerRef.current = 'keyboard'
|
||||||
if (isAssistiveKeyPressed) {
|
if (isAssistiveKeyPressed) {
|
||||||
setIndex((prev) => {
|
setIndex((prev) => {
|
||||||
|
if (prev === -1) return list.length > 0 ? list.length - 1 : -1
|
||||||
const newIndex = prev - ctx.pageSize
|
const newIndex = prev - ctx.pageSize
|
||||||
if (prev === 0) return list.length - 1
|
if (prev === 0) return list.length - 1
|
||||||
return newIndex < 0 ? 0 : newIndex
|
return newIndex < 0 ? 0 : newIndex
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
setIndex((prev) => (prev > 0 ? prev - 1 : list.length - 1))
|
setIndex((prev) => {
|
||||||
|
if (prev === -1) return list.length > 0 ? list.length - 1 : -1
|
||||||
|
return prev > 0 ? prev - 1 : list.length - 1
|
||||||
|
})
|
||||||
}
|
}
|
||||||
break
|
break
|
||||||
|
|
||||||
@ -307,18 +354,23 @@ export const QuickPanelView: React.FC<Props> = ({ setInputText }) => {
|
|||||||
scrollTriggerRef.current = 'keyboard'
|
scrollTriggerRef.current = 'keyboard'
|
||||||
if (isAssistiveKeyPressed) {
|
if (isAssistiveKeyPressed) {
|
||||||
setIndex((prev) => {
|
setIndex((prev) => {
|
||||||
|
if (prev === -1) return list.length > 0 ? 0 : -1
|
||||||
const newIndex = prev + ctx.pageSize
|
const newIndex = prev + ctx.pageSize
|
||||||
if (prev + 1 === list.length) return 0
|
if (prev + 1 === list.length) return 0
|
||||||
return newIndex >= list.length ? list.length - 1 : newIndex
|
return newIndex >= list.length ? list.length - 1 : newIndex
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
setIndex((prev) => (prev < list.length - 1 ? prev + 1 : 0))
|
setIndex((prev) => {
|
||||||
|
if (prev === -1) return list.length > 0 ? 0 : -1
|
||||||
|
return prev < list.length - 1 ? prev + 1 : 0
|
||||||
|
})
|
||||||
}
|
}
|
||||||
break
|
break
|
||||||
|
|
||||||
case 'PageUp':
|
case 'PageUp':
|
||||||
scrollTriggerRef.current = 'keyboard'
|
scrollTriggerRef.current = 'keyboard'
|
||||||
setIndex((prev) => {
|
setIndex((prev) => {
|
||||||
|
if (prev === -1) return list.length > 0 ? Math.max(0, list.length - ctx.pageSize) : -1
|
||||||
const newIndex = prev - ctx.pageSize
|
const newIndex = prev - ctx.pageSize
|
||||||
return newIndex < 0 ? 0 : newIndex
|
return newIndex < 0 ? 0 : newIndex
|
||||||
})
|
})
|
||||||
@ -327,6 +379,7 @@ export const QuickPanelView: React.FC<Props> = ({ setInputText }) => {
|
|||||||
case 'PageDown':
|
case 'PageDown':
|
||||||
scrollTriggerRef.current = 'keyboard'
|
scrollTriggerRef.current = 'keyboard'
|
||||||
setIndex((prev) => {
|
setIndex((prev) => {
|
||||||
|
if (prev === -1) return list.length > 0 ? Math.min(ctx.pageSize - 1, list.length - 1) : -1
|
||||||
const newIndex = prev + ctx.pageSize
|
const newIndex = prev + ctx.pageSize
|
||||||
return newIndex >= list.length ? list.length - 1 : newIndex
|
return newIndex >= list.length ? list.length - 1 : newIndex
|
||||||
})
|
})
|
||||||
@ -421,10 +474,9 @@ export const QuickPanelView: React.FC<Props> = ({ setInputText }) => {
|
|||||||
(): VirtualizedRowData => ({
|
(): VirtualizedRowData => ({
|
||||||
list,
|
list,
|
||||||
focusedIndex: index,
|
focusedIndex: index,
|
||||||
handleItemAction,
|
handleItemAction
|
||||||
setIndex
|
|
||||||
}),
|
}),
|
||||||
[list, index, handleItemAction, setIndex]
|
[list, index, handleItemAction]
|
||||||
)
|
)
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@ -487,15 +539,6 @@ export const QuickPanelView: React.FC<Props> = ({ setInputText }) => {
|
|||||||
<Flex align="center" gap={4}>
|
<Flex align="center" gap={4}>
|
||||||
↩︎ {t('settings.quickPanel.confirm')}
|
↩︎ {t('settings.quickPanel.confirm')}
|
||||||
</Flex>
|
</Flex>
|
||||||
|
|
||||||
{ctx.multiple && (
|
|
||||||
<Flex align="center" gap={4}>
|
|
||||||
<span style={{ color: isAssistiveKeyPressed ? 'var(--color-primary)' : 'var(--color-text-3)' }}>
|
|
||||||
{ASSISTIVE_KEY}
|
|
||||||
</span>
|
|
||||||
+ ↩︎ {t('settings.quickPanel.multiple')}
|
|
||||||
</Flex>
|
|
||||||
)}
|
|
||||||
</QuickPanelFooterTips>
|
</QuickPanelFooterTips>
|
||||||
</QuickPanelFooter>
|
</QuickPanelFooter>
|
||||||
</QuickPanelBody>
|
</QuickPanelBody>
|
||||||
@ -507,7 +550,6 @@ interface VirtualizedRowData {
|
|||||||
list: QuickPanelListItem[]
|
list: QuickPanelListItem[]
|
||||||
focusedIndex: number
|
focusedIndex: number
|
||||||
handleItemAction: (item: QuickPanelListItem, action?: QuickPanelCloseAction) => void
|
handleItemAction: (item: QuickPanelListItem, action?: QuickPanelCloseAction) => void
|
||||||
setIndex: (index: number) => void
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -515,7 +557,7 @@ interface VirtualizedRowData {
|
|||||||
*/
|
*/
|
||||||
const VirtualizedRow = React.memo(
|
const VirtualizedRow = React.memo(
|
||||||
({ data, index, style }: { data: VirtualizedRowData; index: number; style: React.CSSProperties }) => {
|
({ data, index, style }: { data: VirtualizedRowData; index: number; style: React.CSSProperties }) => {
|
||||||
const { list, focusedIndex, handleItemAction, setIndex } = data
|
const { list, focusedIndex, handleItemAction } = data
|
||||||
const item = list[index]
|
const item = list[index]
|
||||||
if (!item) return null
|
if (!item) return null
|
||||||
|
|
||||||
@ -531,8 +573,7 @@ const VirtualizedRow = React.memo(
|
|||||||
onClick={(e) => {
|
onClick={(e) => {
|
||||||
e.stopPropagation()
|
e.stopPropagation()
|
||||||
handleItemAction(item, 'click')
|
handleItemAction(item, 'click')
|
||||||
}}
|
}}>
|
||||||
onMouseEnter={() => setIndex(index)}>
|
|
||||||
<QuickPanelItemLeft>
|
<QuickPanelItemLeft>
|
||||||
<QuickPanelItemIcon>{item.icon}</QuickPanelItemIcon>
|
<QuickPanelItemIcon>{item.icon}</QuickPanelItemIcon>
|
||||||
<QuickPanelItemLabel>{item.label}</QuickPanelItemLabel>
|
<QuickPanelItemLabel>{item.label}</QuickPanelItemLabel>
|
||||||
@ -651,11 +692,19 @@ const QuickPanelItem = styled.div`
|
|||||||
border-radius: 6px;
|
border-radius: 6px;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
transition: background-color 0.1s ease;
|
transition: background-color 0.1s ease;
|
||||||
|
|
||||||
|
&:hover:not(.disabled) {
|
||||||
|
background-color: var(--focused-color);
|
||||||
|
}
|
||||||
|
|
||||||
&.selected {
|
&.selected {
|
||||||
background-color: var(--selected-color);
|
background-color: var(--selected-color);
|
||||||
&.focused {
|
&.focused {
|
||||||
background-color: var(--selected-color-dark);
|
background-color: var(--selected-color-dark);
|
||||||
}
|
}
|
||||||
|
&:hover:not(.disabled) {
|
||||||
|
background-color: var(--selected-color-dark);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
&.focused {
|
&.focused {
|
||||||
background-color: var(--focused-color);
|
background-color: var(--focused-color);
|
||||||
|
|||||||
@ -122,7 +122,7 @@ describe('QuickPanelView', () => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
it('should focus on the first item after panel open', () => {
|
it('should not focus on any item after panel open by default', () => {
|
||||||
const list = createList(100)
|
const list = createList(100)
|
||||||
|
|
||||||
render(
|
render(
|
||||||
@ -134,11 +134,16 @@ describe('QuickPanelView', () => {
|
|||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
// 检查第一个 item 是否有 focused
|
// 检查是否没有任何 focused item
|
||||||
|
const panel = screen.getByTestId('quick-panel')
|
||||||
|
const focused = panel.querySelectorAll('.focused')
|
||||||
|
expect(focused.length).toBe(0)
|
||||||
|
|
||||||
|
// 检查第一个 item 存在但没有 focused 类
|
||||||
const item1 = screen.getByText('Item 1')
|
const item1 = screen.getByText('Item 1')
|
||||||
const focused = item1.closest('.focused')
|
|
||||||
expect(focused).not.toBeNull()
|
|
||||||
expect(item1).toBeInTheDocument()
|
expect(item1).toBeInTheDocument()
|
||||||
|
const focusedItem1 = item1.closest('.focused')
|
||||||
|
expect(focusedItem1).toBeNull()
|
||||||
})
|
})
|
||||||
|
|
||||||
it('should focus on the right item using ArrowUp, ArrowDown', async () => {
|
it('should focus on the right item using ArrowUp, ArrowDown', async () => {
|
||||||
@ -154,10 +159,11 @@ describe('QuickPanelView', () => {
|
|||||||
)
|
)
|
||||||
|
|
||||||
const keySequence = [
|
const keySequence = [
|
||||||
{ key: 'ArrowUp', expected: 'Item 100' },
|
{ key: 'ArrowDown', expected: 'Item 1' }, // 从未选中状态按 ArrowDown 会选中第一个
|
||||||
|
{ key: 'ArrowUp', expected: 'Item 100' }, // 从第一个按 ArrowUp 会循环到最后一个
|
||||||
{ key: 'ArrowUp', expected: 'Item 99' },
|
{ key: 'ArrowUp', expected: 'Item 99' },
|
||||||
{ key: 'ArrowDown', expected: 'Item 100' },
|
{ key: 'ArrowDown', expected: 'Item 100' },
|
||||||
{ key: 'ArrowDown', expected: 'Item 1' }
|
{ key: 'ArrowDown', expected: 'Item 1' } // 从最后一个按 ArrowDown 会循环到第一个
|
||||||
]
|
]
|
||||||
|
|
||||||
await runKeySequenceAndCheck(screen.getByTestId('quick-panel'), keySequence)
|
await runKeySequenceAndCheck(screen.getByTestId('quick-panel'), keySequence)
|
||||||
@ -176,11 +182,11 @@ describe('QuickPanelView', () => {
|
|||||||
)
|
)
|
||||||
|
|
||||||
const keySequence = [
|
const keySequence = [
|
||||||
{ key: 'PageUp', expected: 'Item 1' }, // 停留在顶部
|
{ key: 'PageDown', expected: `Item ${PAGE_SIZE}` }, // 从未选中状态按 PageDown 会选中第 pageSize 个项目
|
||||||
{ key: 'ArrowUp', expected: 'Item 100' },
|
{ key: 'PageUp', expected: 'Item 1' }, // PageUp 会选中第一个
|
||||||
{ key: 'PageDown', expected: 'Item 100' }, // 停留在底部
|
{ key: 'ArrowUp', expected: 'Item 100' }, // 从第一个按 ArrowUp 会到最后一个
|
||||||
{ key: 'PageUp', expected: `Item ${100 - PAGE_SIZE}` },
|
{ key: 'PageDown', expected: 'Item 100' }, // 从最后一个按 PageDown 仍然是最后一个
|
||||||
{ key: 'PageDown', expected: 'Item 100' }
|
{ key: 'PageUp', expected: `Item ${100 - PAGE_SIZE}` } // PageUp 会向上翻页,从索引99到92,对应Item 93
|
||||||
]
|
]
|
||||||
|
|
||||||
await runKeySequenceAndCheck(screen.getByTestId('quick-panel'), keySequence)
|
await runKeySequenceAndCheck(screen.getByTestId('quick-panel'), keySequence)
|
||||||
@ -199,10 +205,11 @@ describe('QuickPanelView', () => {
|
|||||||
)
|
)
|
||||||
|
|
||||||
const keySequence = [
|
const keySequence = [
|
||||||
{ key: 'ArrowDown', ctrlKey: true, expected: `Item ${PAGE_SIZE + 1}` },
|
{ key: 'ArrowDown', ctrlKey: true, expected: 'Item 1' }, // 从未选中状态按 Ctrl+ArrowDown 会选中第一个
|
||||||
{ key: 'ArrowUp', ctrlKey: true, expected: 'Item 1' },
|
{ key: 'ArrowDown', ctrlKey: true, expected: `Item ${PAGE_SIZE + 1}` }, // Ctrl+ArrowDown 会跳转 pageSize 个位置
|
||||||
{ key: 'ArrowUp', ctrlKey: true, expected: 'Item 100' },
|
{ key: 'ArrowUp', ctrlKey: true, expected: 'Item 1' }, // Ctrl+ArrowUp 会跳转回去
|
||||||
{ key: 'ArrowDown', ctrlKey: true, expected: 'Item 1' }
|
{ key: 'ArrowUp', ctrlKey: true, expected: 'Item 100' }, // 从第一个位置再按 Ctrl+ArrowUp 会循环到最后
|
||||||
|
{ key: 'ArrowDown', ctrlKey: true, expected: 'Item 1' } // 从最后位置按 Ctrl+ArrowDown 会循环到第一个
|
||||||
]
|
]
|
||||||
|
|
||||||
await runKeySequenceAndCheck(screen.getByTestId('quick-panel'), keySequence)
|
await runKeySequenceAndCheck(screen.getByTestId('quick-panel'), keySequence)
|
||||||
|
|||||||
@ -864,7 +864,10 @@ const Inputbar: FC<Props> = ({ assistant: _assistant, setActiveTopic, topic }) =
|
|||||||
onInput={onInput}
|
onInput={onInput}
|
||||||
disabled={searching}
|
disabled={searching}
|
||||||
onPaste={(e) => onPaste(e.nativeEvent)}
|
onPaste={(e) => onPaste(e.nativeEvent)}
|
||||||
onClick={() => searching && dispatch(setSearching(false))}
|
onClick={() => {
|
||||||
|
searching && dispatch(setSearching(false))
|
||||||
|
quickPanel.close()
|
||||||
|
}}
|
||||||
/>
|
/>
|
||||||
<DragHandle onMouseDown={handleDragStart}>
|
<DragHandle onMouseDown={handleDragStart}>
|
||||||
<HolderOutlined />
|
<HolderOutlined />
|
||||||
|
|||||||
@ -183,12 +183,15 @@ const MCPToolsButton: FC<Props> = ({ ref, setInputValue, resizeTextArea, Toolbar
|
|||||||
label: t('common.close'),
|
label: t('common.close'),
|
||||||
description: t('settings.mcp.disable.description'),
|
description: t('settings.mcp.disable.description'),
|
||||||
icon: <CircleX />,
|
icon: <CircleX />,
|
||||||
isSelected: !(assistant.mcpServers && assistant.mcpServers.length > 0),
|
isSelected: false,
|
||||||
action: () => updateMcpEnabled(false)
|
action: () => {
|
||||||
|
updateMcpEnabled(false)
|
||||||
|
quickPanel.close()
|
||||||
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
return newList
|
return newList
|
||||||
}, [activedMcpServers, t, assistant.mcpServers, assistantMcpServers, navigate, updateMcpEnabled])
|
}, [activedMcpServers, t, assistantMcpServers, navigate, updateMcpEnabled, quickPanel])
|
||||||
|
|
||||||
const openQuickPanel = useCallback(() => {
|
const openQuickPanel = useCallback(() => {
|
||||||
quickPanel.open({
|
quickPanel.open({
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user