mirror of
https://github.com/QwenLM/qwen-code.git
synced 2025-12-19 09:33:53 +00:00
feat(vscode-ide-companion): 优化 Qwen Code 聊天窗口创建逻辑
- 修改 createPanel 方法返回值类型,使其支持异步操作 - 实现聚焦当前激活编辑器的功能 - 优化多窗口创建逻辑,允许在已有 Qwen Code 窗口旁边创建新窗口 - 移除自动锁定编辑器组的功能,以支持多个 Qwen Code 标签页 - 在 UI 中添加聚焦当前文件的按钮
This commit is contained in:
@@ -117,7 +117,7 @@ export class WebViewProvider {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Create new panel
|
// Create new panel
|
||||||
const isNewPanel = this.panelManager.createPanel();
|
const isNewPanel = await this.panelManager.createPanel();
|
||||||
|
|
||||||
if (!isNewPanel) {
|
if (!isNewPanel) {
|
||||||
return; // Failed to create panel
|
return; // Failed to create panel
|
||||||
|
|||||||
@@ -1048,12 +1048,33 @@ export const App: React.FC = () => {
|
|||||||
<span>{getEditModeInfo().text}</span>
|
<span>{getEditModeInfo().text}</span>
|
||||||
</button>
|
</button>
|
||||||
{activeFileName && (
|
{activeFileName && (
|
||||||
<span
|
<button
|
||||||
className="active-file-indicator"
|
type="button"
|
||||||
|
className="action-button active-file-indicator"
|
||||||
title={`Showing Qwen Code your current file selection: ${activeFileName}`}
|
title={`Showing Qwen Code your current file selection: ${activeFileName}`}
|
||||||
|
onClick={() => {
|
||||||
|
// Request to focus/reveal the active file
|
||||||
|
vscode.postMessage({
|
||||||
|
type: 'focusActiveEditor',
|
||||||
|
data: {},
|
||||||
|
});
|
||||||
|
}}
|
||||||
>
|
>
|
||||||
{activeFileName}
|
<svg
|
||||||
</span>
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
viewBox="0 0 20 20"
|
||||||
|
fill="currentColor"
|
||||||
|
aria-hidden="true"
|
||||||
|
data-slot="icon"
|
||||||
|
>
|
||||||
|
<path
|
||||||
|
fillRule="evenodd"
|
||||||
|
d="M6.28 5.22a.75.75 0 0 1 0 1.06L2.56 10l3.72 3.72a.75.75 0 0 1-1.06 1.06L.97 10.53a.75.75 0 0 1 0-1.06l4.25-4.25a.75.75 0 0 1 1.06 0Zm7.44 0a.75.75 0 0 1 1.06 0l4.25 4.25a.75.75 0 0 1 0 1.06l-4.25 4.25a.75.75 0 0 1-1.06-1.06L17.44 10l-3.72-3.72a.75.75 0 0 1 0-1.06ZM11.377 2.011a.75.75 0 0 1 .612.867l-2.5 14.5a.75.75 0 0 1-1.478-.255l2.5-14.5a.75.75 0 0 1 .866-.612Z"
|
||||||
|
clipRule="evenodd"
|
||||||
|
></path>
|
||||||
|
</svg>
|
||||||
|
<span>{activeFileName}</span>
|
||||||
|
</button>
|
||||||
)}
|
)}
|
||||||
<div className="action-divider"></div>
|
<div className="action-divider"></div>
|
||||||
<button
|
<button
|
||||||
|
|||||||
@@ -141,6 +141,18 @@ export class MessageHandler {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case 'focusActiveEditor': {
|
||||||
|
// 聚焦到当前激活的编辑器
|
||||||
|
const activeEditor = vscode.window.activeTextEditor;
|
||||||
|
if (activeEditor) {
|
||||||
|
vscode.window.showTextDocument(activeEditor.document, {
|
||||||
|
viewColumn: activeEditor.viewColumn,
|
||||||
|
preserveFocus: false,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
case 'switchQwenSession':
|
case 'switchQwenSession':
|
||||||
await this.handleSwitchQwenSession((data?.sessionId as string) || '');
|
await this.handleSwitchQwenSession((data?.sessionId as string) || '');
|
||||||
break;
|
break;
|
||||||
|
|||||||
@@ -37,17 +37,65 @@ export class PanelManager {
|
|||||||
* 创建新的 WebView Panel
|
* 创建新的 WebView Panel
|
||||||
* @returns 是否是新创建的 Panel
|
* @returns 是否是新创建的 Panel
|
||||||
*/
|
*/
|
||||||
createPanel(): boolean {
|
async createPanel(): Promise<boolean> {
|
||||||
if (this.panel) {
|
if (this.panel) {
|
||||||
return false; // Panel already exists
|
return false; // Panel already exists
|
||||||
}
|
}
|
||||||
|
|
||||||
// Find if there's already a Qwen Code webview tab open and get its view column
|
// Find if there's already a Qwen Code webview tab open and get its view column
|
||||||
const existingQwenViewColumn = this.findExistingQwenCodeViewColumn();
|
const existingQwenInfo = this.findExistingQwenCodeGroup();
|
||||||
|
|
||||||
// If we found an existing Qwen Code tab, open in the same view column
|
// If we found an existing Qwen Code tab, open in the same view column
|
||||||
// Otherwise, open beside the active editor
|
// Otherwise, open beside the active editor
|
||||||
const targetViewColumn = existingQwenViewColumn ?? vscode.ViewColumn.Beside;
|
const targetViewColumn =
|
||||||
|
existingQwenInfo?.viewColumn ?? vscode.ViewColumn.Beside;
|
||||||
|
console.log('[PanelManager] existingQwenInfo', existingQwenInfo);
|
||||||
|
console.log('[PanelManager] targetViewColumn', targetViewColumn);
|
||||||
|
|
||||||
|
// If there's an existing Qwen Code group, ensure it's unlocked so we can add new tabs
|
||||||
|
// We try to unlock regardless of current state - if already unlocked, this is a no-op
|
||||||
|
if (existingQwenInfo?.group) {
|
||||||
|
console.log(
|
||||||
|
"[PanelManager] Found existing Qwen Code group, ensuring it's unlocked...",
|
||||||
|
);
|
||||||
|
|
||||||
|
try {
|
||||||
|
// We need to make the target group active first
|
||||||
|
// Find a Qwen Code tab in that group
|
||||||
|
const firstQwenTab = existingQwenInfo.group.tabs.find((tab) => {
|
||||||
|
const input: unknown = (tab as { input?: unknown }).input;
|
||||||
|
const isWebviewInput = (inp: unknown): inp is { viewType: string } =>
|
||||||
|
!!inp && typeof inp === 'object' && 'viewType' in inp;
|
||||||
|
return (
|
||||||
|
isWebviewInput(input) &&
|
||||||
|
input.viewType === 'mainThreadWebview-qwenCode.chat'
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
if (firstQwenTab) {
|
||||||
|
// Make the group active by focusing on one of its tabs
|
||||||
|
const activeTabGroup = vscode.window.tabGroups.activeTabGroup;
|
||||||
|
if (activeTabGroup !== existingQwenInfo.group) {
|
||||||
|
// Switch to the target group
|
||||||
|
await vscode.commands.executeCommand(
|
||||||
|
'workbench.action.focusFirstEditorGroup',
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Try to unlock the group (will be no-op if already unlocked)
|
||||||
|
await vscode.commands.executeCommand(
|
||||||
|
'workbench.action.unlockEditorGroup',
|
||||||
|
);
|
||||||
|
console.log('[PanelManager] Unlock command executed');
|
||||||
|
} catch (error) {
|
||||||
|
console.warn(
|
||||||
|
'[PanelManager] Failed to unlock group, continuing anyway:',
|
||||||
|
error,
|
||||||
|
);
|
||||||
|
// Continue anyway - the group might not be locked
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
this.panel = vscode.window.createWebviewPanel(
|
this.panel = vscode.window.createWebviewPanel(
|
||||||
'qwenCode.chat',
|
'qwenCode.chat',
|
||||||
@@ -77,23 +125,33 @@ export class PanelManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 查找已存在的 Qwen Code webview 所在的 view column
|
* 查找已存在的 Qwen Code webview 所在的 group 和 view column
|
||||||
* @returns 找到的 view column,如果没有则返回 undefined
|
* @returns 找到的 group 和 view column,如果没有则返回 undefined
|
||||||
*/
|
*/
|
||||||
private findExistingQwenCodeViewColumn(): vscode.ViewColumn | undefined {
|
private findExistingQwenCodeGroup():
|
||||||
const allTabs = vscode.window.tabGroups.all.flatMap((g) => g.tabs);
|
| { group: vscode.TabGroup; viewColumn: vscode.ViewColumn }
|
||||||
|
| undefined {
|
||||||
|
for (const group of vscode.window.tabGroups.all) {
|
||||||
|
for (const tab of group.tabs) {
|
||||||
|
const input: unknown = (tab as { input?: unknown }).input;
|
||||||
|
const isWebviewInput = (inp: unknown): inp is { viewType: string } =>
|
||||||
|
!!inp && typeof inp === 'object' && 'viewType' in inp;
|
||||||
|
|
||||||
for (const tab of allTabs) {
|
if (
|
||||||
const input: unknown = (tab as { input?: unknown }).input;
|
isWebviewInput(input) &&
|
||||||
const isWebviewInput = (inp: unknown): inp is { viewType: string } =>
|
input.viewType === 'mainThreadWebview-qwenCode.chat'
|
||||||
!!inp && typeof inp === 'object' && 'viewType' in inp;
|
) {
|
||||||
|
// Found an existing Qwen Code tab
|
||||||
if (isWebviewInput(input) && input.viewType === 'qwenCode.chat') {
|
console.log('[PanelManager] Found existing Qwen Code group:', {
|
||||||
// Found an existing Qwen Code tab, get its view column
|
viewColumn: group.viewColumn,
|
||||||
const tabGroup = vscode.window.tabGroups.all.find((g) =>
|
tabCount: group.tabs.length,
|
||||||
g.tabs.includes(tab),
|
isActive: group.isActive,
|
||||||
);
|
});
|
||||||
return tabGroup?.viewColumn;
|
return {
|
||||||
|
group,
|
||||||
|
viewColumn: group.viewColumn,
|
||||||
|
};
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -102,23 +160,30 @@ export class PanelManager {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* 自动锁定编辑器组(仅在新创建 Panel 时调用)
|
* 自动锁定编辑器组(仅在新创建 Panel 时调用)
|
||||||
|
* 注意:我们不再自动锁定 Qwen Code group,以允许用户创建多个 Qwen Code tab
|
||||||
*/
|
*/
|
||||||
async autoLockEditorGroup(): Promise<void> {
|
async autoLockEditorGroup(): Promise<void> {
|
||||||
if (!this.panel) {
|
if (!this.panel) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
console.log('[PanelManager] Auto-locking editor group for Qwen Code chat');
|
// We don't auto-lock anymore to allow multiple Qwen Code tabs in the same group
|
||||||
try {
|
console.log(
|
||||||
// Reveal panel without preserving focus to make it the active group
|
'[PanelManager] Skipping auto-lock to allow multiple Qwen Code tabs',
|
||||||
this.revealPanel(false);
|
);
|
||||||
|
|
||||||
await vscode.commands.executeCommand('workbench.action.lockEditorGroup');
|
// If you want to enable auto-locking for the first tab, uncomment the following:
|
||||||
console.log('[PanelManager] Editor group locked successfully');
|
// const existingQwenInfo = this.findExistingQwenCodeGroup();
|
||||||
} catch (error) {
|
// if (!existingQwenInfo) {
|
||||||
console.warn('[PanelManager] Failed to lock editor group:', error);
|
// console.log('[PanelManager] First Qwen Code tab, locking editor group');
|
||||||
// Non-fatal error, continue anyway
|
// try {
|
||||||
}
|
// this.revealPanel(false);
|
||||||
|
// await vscode.commands.executeCommand('workbench.action.lockEditorGroup');
|
||||||
|
// console.log('[PanelManager] Editor group locked successfully');
|
||||||
|
// } catch (error) {
|
||||||
|
// console.warn('[PanelManager] Failed to lock editor group:', error);
|
||||||
|
// }
|
||||||
|
// }
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
Reference in New Issue
Block a user