mirror of
https://github.com/QwenLM/qwen-code.git
synced 2025-12-19 09:33:53 +00:00
feat(vscode-ide-companion/diff): implement diff auto-open functionality in preferred editor group
This commit is contained in:
@@ -12,6 +12,10 @@ import { type JSONRPCNotification } from '@modelcontextprotocol/sdk/types.js';
|
||||
import * as path from 'node:path';
|
||||
import * as vscode from 'vscode';
|
||||
import { DIFF_SCHEME } from './extension.js';
|
||||
import {
|
||||
findLeftGroupOfChatWebview,
|
||||
ensureLeftGroupOfChatWebview,
|
||||
} from './utils/editorGroupUtils.js';
|
||||
|
||||
export class DiffContentProvider implements vscode.TextDocumentContentProvider {
|
||||
private content = new Map<string, string>();
|
||||
@@ -110,13 +114,28 @@ export class DiffManager {
|
||||
true,
|
||||
);
|
||||
|
||||
// Prefer opening the diff adjacent to the chat webview (so we don't
|
||||
// replace content inside the locked webview group). We try the group to
|
||||
// the left of the chat webview first; if none exists we fall back to
|
||||
// ViewColumn.Beside. With the chat locked in the leftmost group, this
|
||||
// fallback opens diffs to the right of the chat.
|
||||
let targetViewColumn = findLeftGroupOfChatWebview();
|
||||
if (targetViewColumn === undefined) {
|
||||
// If there is no left neighbor, create one to satisfy the requirement of
|
||||
// opening diffs to the left of the chat webview.
|
||||
targetViewColumn = await ensureLeftGroupOfChatWebview();
|
||||
}
|
||||
|
||||
await vscode.commands.executeCommand(
|
||||
'vscode.diff',
|
||||
leftDocUri,
|
||||
rightDocUri,
|
||||
diffTitle,
|
||||
{
|
||||
viewColumn: vscode.ViewColumn.Beside,
|
||||
// If a left-of-webview group was found, target it explicitly so the
|
||||
// diff opens there while keeping focus on the webview. Otherwise, use
|
||||
// the default "open to side" behavior.
|
||||
viewColumn: targetViewColumn ?? vscode.ViewColumn.Beside,
|
||||
preview: false,
|
||||
preserveFocus: true,
|
||||
},
|
||||
|
||||
115
packages/vscode-ide-companion/src/utils/editorGroupUtils.ts
Normal file
115
packages/vscode-ide-companion/src/utils/editorGroupUtils.ts
Normal file
@@ -0,0 +1,115 @@
|
||||
/**
|
||||
* @license
|
||||
* Copyright 2025 Qwen Team
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
import * as vscode from 'vscode';
|
||||
|
||||
/**
|
||||
* Find the editor group immediately to the left of the Qwen chat webview.
|
||||
* - If the chat webview group is the leftmost group, returns undefined.
|
||||
* - Uses the webview tab viewType 'mainThreadWebview-qwenCode.chat'.
|
||||
*/
|
||||
export function findLeftGroupOfChatWebview(): vscode.ViewColumn | undefined {
|
||||
try {
|
||||
const groups = vscode.window.tabGroups.all;
|
||||
|
||||
// Locate the group that contains our chat webview
|
||||
const webviewGroup = groups.find((group) =>
|
||||
group.tabs.some((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 (!webviewGroup) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
// Among all groups to the left (smaller viewColumn), choose the one with
|
||||
// the largest viewColumn value (i.e. the immediate neighbor on the left).
|
||||
let candidate:
|
||||
| { group: vscode.TabGroup; viewColumn: vscode.ViewColumn }
|
||||
| undefined;
|
||||
for (const g of groups) {
|
||||
if (g.viewColumn < webviewGroup.viewColumn) {
|
||||
if (!candidate || g.viewColumn > candidate.viewColumn) {
|
||||
candidate = { group: g, viewColumn: g.viewColumn };
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return candidate?.viewColumn;
|
||||
} catch (_err) {
|
||||
// Best-effort only; fall back to default behavior if anything goes wrong
|
||||
return undefined;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensure there is an editor group directly to the left of the Qwen chat webview.
|
||||
* - If one exists, return its ViewColumn.
|
||||
* - If none exists, focus the chat panel and create a new group on its left,
|
||||
* then return the new group's ViewColumn (which equals the chat's previous column).
|
||||
* - If the chat webview cannot be located, returns undefined.
|
||||
*/
|
||||
export async function ensureLeftGroupOfChatWebview(): Promise<
|
||||
vscode.ViewColumn | undefined
|
||||
> {
|
||||
// First try to find an existing left neighbor
|
||||
const existing = findLeftGroupOfChatWebview();
|
||||
if (existing !== undefined) {
|
||||
return existing;
|
||||
}
|
||||
|
||||
// Locate the chat webview group
|
||||
const groups = vscode.window.tabGroups.all;
|
||||
const webviewGroup = groups.find((group) =>
|
||||
group.tabs.some((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 (!webviewGroup) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
const previousChatColumn = webviewGroup.viewColumn;
|
||||
|
||||
// Make the chat group active by revealing the panel
|
||||
try {
|
||||
await vscode.commands.executeCommand('qwenCode.openChat');
|
||||
} catch {
|
||||
// Best-effort; continue even if this fails
|
||||
}
|
||||
|
||||
// Create a new group to the left of the chat group
|
||||
try {
|
||||
await vscode.commands.executeCommand('workbench.action.newGroupLeft');
|
||||
} catch {
|
||||
// If we fail to create a group, fall back to default behavior
|
||||
return undefined;
|
||||
}
|
||||
|
||||
// Restore focus to chat (optional), so we don't disturb user focus
|
||||
try {
|
||||
await vscode.commands.executeCommand('qwenCode.openChat');
|
||||
} catch {
|
||||
// Ignore
|
||||
}
|
||||
|
||||
// The new left group's column equals the chat's previous column
|
||||
return previousChatColumn;
|
||||
}
|
||||
Reference in New Issue
Block a user