From 4345b9370e540681f194fdf2adc46018cfd53120 Mon Sep 17 00:00:00 2001
From: yiliang114 <1204183885@qq.com>
Date: Wed, 10 Dec 2025 00:46:22 +0800
Subject: [PATCH] feat(vscode-ide-companion): enhance panel manager group
tracking and ui improvements
chore(vscode-ide-companion): remove unused todo comment in auth state manager
---
.../src/services/authStateManager.ts | 1 -
.../vscode-ide-companion/src/webview/App.tsx | 20 ++++++++------
.../src/webview/PanelManager.ts | 26 +++++++++++++------
.../messages/Waiting/WaitingMessage.tsx | 16 +++---------
.../src/webview/styles/App.css | 22 +++++++++++-----
5 files changed, 49 insertions(+), 36 deletions(-)
diff --git a/packages/vscode-ide-companion/src/services/authStateManager.ts b/packages/vscode-ide-companion/src/services/authStateManager.ts
index 9614cae6..566a4afb 100644
--- a/packages/vscode-ide-companion/src/services/authStateManager.ts
+++ b/packages/vscode-ide-companion/src/services/authStateManager.ts
@@ -21,7 +21,6 @@ export class AuthStateManager {
private static context: vscode.ExtensionContext | null = null;
private static readonly AUTH_STATE_KEY = 'qwen.authState';
private static readonly AUTH_CACHE_DURATION = 24 * 60 * 60 * 1000; // 24 hours
- //TODO:
private constructor() {}
/**
diff --git a/packages/vscode-ide-companion/src/webview/App.tsx b/packages/vscode-ide-companion/src/webview/App.tsx
index 23860c47..4b51d6b6 100644
--- a/packages/vscode-ide-companion/src/webview/App.tsx
+++ b/packages/vscode-ide-companion/src/webview/App.tsx
@@ -646,8 +646,7 @@ export const App: React.FC = () => {
{!hasContent ? (
@@ -655,12 +654,17 @@ export const App: React.FC = () => {
<>
{/* Render all messages and tool calls */}
{renderMessages()}
- {messageHandling.isWaitingForResponse &&
- messageHandling.loadingMessage && (
-
- )}
+ {/* Flow-in persistent slot: keeps a small constant height so toggling */}
+ {/* the waiting message doesn't change list height to zero. When */}
+ {/* active, render the waiting message inline (not fixed). */}
+
+ {messageHandling.isWaitingForResponse &&
+ messageHandling.loadingMessage && (
+
+ )}
+
>
diff --git a/packages/vscode-ide-companion/src/webview/PanelManager.ts b/packages/vscode-ide-companion/src/webview/PanelManager.ts
index 72c7fa7b..44f1a6ec 100644
--- a/packages/vscode-ide-companion/src/webview/PanelManager.ts
+++ b/packages/vscode-ide-companion/src/webview/PanelManager.ts
@@ -201,8 +201,17 @@ export class PanelManager {
*/
revealPanel(preserveFocus: boolean = true): void {
if (this.panel) {
- // Reveal without forcing a specific column to avoid reflowing groups.
- this.panel.reveal(undefined, preserveFocus);
+ // Prefer revealing in the currently tracked group to avoid reflowing groups.
+ const trackedColumn = (
+ this.panelTab as unknown as {
+ group?: { viewColumn?: vscode.ViewColumn };
+ }
+ )?.group?.viewColumn as vscode.ViewColumn | undefined;
+ const targetColumn: vscode.ViewColumn =
+ trackedColumn ??
+ this.panelGroupViewColumn ??
+ vscode.window.tabGroups.activeTabGroup.viewColumn;
+ this.panel.reveal(targetColumn, preserveFocus);
}
}
@@ -236,7 +245,7 @@ export class PanelManager {
group?: { viewColumn?: vscode.ViewColumn };
}
)?.group?.viewColumn;
- if (groupViewColumn != null) {
+ if (groupViewColumn !== null) {
this.panelGroupViewColumn = groupViewColumn as vscode.ViewColumn;
}
} catch {
@@ -257,7 +266,7 @@ export class PanelManager {
this.panel.onDidDispose(
() => {
// Capture the group we intend to clean up before we clear fields
- const targetColumn =
+ const targetColumn: vscode.ViewColumn | null =
// Prefer the group from the captured tab if available
((
this.panelTab as unknown as {
@@ -266,7 +275,7 @@ export class PanelManager {
)?.group?.viewColumn as vscode.ViewColumn | undefined) ??
// Fall back to our last-known group column
this.panelGroupViewColumn ??
- undefined;
+ null;
this.panel = null;
this.panelTab = null;
@@ -275,18 +284,19 @@ export class PanelManager {
// After VS Code updates its tab model, check if that group is now
// empty (and typically locked for Qwen). If so, close the group to
// avoid leaving an empty locked column when the user closes Qwen.
- if (targetColumn != null) {
+ if (targetColumn !== null) {
+ const column: vscode.ViewColumn = targetColumn;
setTimeout(async () => {
try {
const groups = vscode.window.tabGroups.all;
- const group = groups.find((g) => g.viewColumn === targetColumn);
+ const group = groups.find((g) => g.viewColumn === column);
// If the group that hosted Qwen is now empty, close it to avoid
// leaving an empty locked column around. VS Code's stable API
// does not expose the lock state on TabGroup, so we only check
// for emptiness here.
if (group && group.tabs.length === 0) {
// Focus the group we want to close
- await this.focusGroupByColumn(targetColumn);
+ await this.focusGroupByColumn(column);
// Try closeGroup first; fall back to removeActiveEditorGroup
try {
await vscode.commands.executeCommand(
diff --git a/packages/vscode-ide-companion/src/webview/components/messages/Waiting/WaitingMessage.tsx b/packages/vscode-ide-companion/src/webview/components/messages/Waiting/WaitingMessage.tsx
index fceeaaa8..68aceac8 100644
--- a/packages/vscode-ide-companion/src/webview/components/messages/Waiting/WaitingMessage.tsx
+++ b/packages/vscode-ide-companion/src/webview/components/messages/Waiting/WaitingMessage.tsx
@@ -65,20 +65,10 @@ export const WaitingMessage: React.FC
= ({
}, [phrases]);
return (
-
+
{/* Use the same left status icon (pseudo-element) style as assistant-message-container */}
-
-
+
+
{phrases[index]}
diff --git a/packages/vscode-ide-companion/src/webview/styles/App.css b/packages/vscode-ide-companion/src/webview/styles/App.css
index 888c4ce3..e4ce12ea 100644
--- a/packages/vscode-ide-companion/src/webview/styles/App.css
+++ b/packages/vscode-ide-companion/src/webview/styles/App.css
@@ -47,9 +47,15 @@
--app-input-highlight: var(--app-qwen-theme);
/* Code Highlighting */
- --app-code-background: var(--vscode-textCodeBlock-background, rgba(0, 0, 0, 0.05));
- --app-link-foreground: var(--vscode-textLink-foreground, #007ACC);
- --app-link-active-foreground: var(--vscode-textLink-activeForeground, #005A9E);
+ --app-code-background: var(
+ --vscode-textCodeBlock-background,
+ rgba(0, 0, 0, 0.05)
+ );
+ --app-link-foreground: var(--vscode-textLink-foreground, #007acc);
+ --app-link-active-foreground: var(
+ --vscode-textLink-activeForeground,
+ #005a9e
+ );
/* List Styles */
--app-list-hover-background: var(--vscode-list-hoverBackground);
@@ -167,7 +173,8 @@ button {
}
@keyframes pulse {
- 0%, 100% {
+ 0%,
+ 100% {
opacity: 1;
}
50% {
@@ -176,7 +183,9 @@ button {
}
@keyframes typingPulse {
- 0%, 60%, 100% {
+ 0%,
+ 60%,
+ 100% {
transform: scale(0.7);
opacity: 0.6;
}
@@ -251,7 +260,8 @@ button {
/* Animation for in-progress status (used by pseudo bullets and spinners) */
@keyframes pulse {
- 0%, 100% {
+ 0%,
+ 100% {
opacity: 1;
}
50% {