refactor(vscode-ide-companion): 优化代码结构和性能

- 移除未使用的依赖项 qwen-code
- 优化 completion 刷新逻辑,避免渲染循环
- 更新 CompletionMenu 组件,增加空状态提示
This commit is contained in:
yiliang114
2025-11-28 10:04:29 +08:00
parent 9cc48f12da
commit 627f5fb43a
3 changed files with 30 additions and 29 deletions

View File

@@ -2323,12 +2323,6 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
License text not found. License text not found.
============================================================
@qwen-code/qwen-code@undefined
(git+https://github.com/QwenLM/qwen-code.git)
License text not found.
============================================================ ============================================================
react@19.1.0 react@19.1.0
(https://github.com/facebook/react.git) (https://github.com/facebook/react.git)

View File

@@ -138,11 +138,16 @@ export const App: React.FC = () => {
const completion = useCompletionTrigger(inputFieldRef, getCompletionItems); const completion = useCompletionTrigger(inputFieldRef, getCompletionItems);
// When workspace files update while menu open for @, refresh items so the first @ shows the list // When workspace files update while menu open for @, refresh items so the first @ shows the list
// Note: Avoid depending on the entire `completion` object here, since its identity
// changes on every render which would retrigger this effect and can cause a refresh loop.
useEffect(() => { useEffect(() => {
if (completion.isOpen && completion.triggerChar === '@') { if (completion.isOpen && completion.triggerChar === '@') {
// Only refresh items; do not change other completion state to avoid re-renders loops
completion.refreshCompletion(); completion.refreshCompletion();
} }
}, [fileContext.workspaceFiles, completion]); // Only re-run when the actual data source changes, not on every render
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [fileContext.workspaceFiles, completion.isOpen, completion.triggerChar]);
// Message submission // Message submission
const handleSubmit = useMessageSubmit({ const handleSubmit = useMessageSubmit({

View File

@@ -97,9 +97,7 @@ export const CompletionMenu: React.FC<CompletionMenuProps> = ({
} }
}, [selected]); }, [selected]);
if (items.length === 0) { const isEmpty = items.length === 0;
return null;
}
return ( return (
<div <div
@@ -111,27 +109,31 @@ export const CompletionMenu: React.FC<CompletionMenuProps> = ({
}} }}
> >
<div className="completion-menu-items"> <div className="completion-menu-items">
{items.map((item, index) => ( {isEmpty ? (
<div <div className="completion-menu-empty">Type to search files</div>
key={item.id} ) : (
data-index={index} items.map((item, index) => (
className={`completion-menu-item ${index === selected ? 'selected' : ''}`} <div
onClick={() => onSelect(item)} key={item.id}
onMouseEnter={() => setSelected(index)} data-index={index}
> className={`completion-menu-item ${index === selected ? 'selected' : ''}`}
{item.icon && ( onClick={() => onSelect(item)}
<div className="completion-item-icon">{item.icon}</div> onMouseEnter={() => setSelected(index)}
)} >
<div className="completion-item-content"> {item.icon && (
<div className="completion-item-label">{item.label}</div> <div className="completion-item-icon">{item.icon}</div>
{item.description && (
<div className="completion-item-description">
{item.description}
</div>
)} )}
<div className="completion-item-content">
<div className="completion-item-label">{item.label}</div>
{item.description && (
<div className="completion-item-description">
{item.description}
</div>
)}
</div>
</div> </div>
</div> ))
))} )}
</div> </div>
</div> </div>
); );