mirror of
https://github.com/QwenLM/qwen-code.git
synced 2025-12-19 09:33:53 +00:00
feat(vscode-ide-companion): enhance panel manager group tracking and ui improvements
chore(vscode-ide-companion): remove unused todo comment in auth state manager
This commit is contained in:
@@ -21,7 +21,6 @@ export class AuthStateManager {
|
|||||||
private static context: vscode.ExtensionContext | null = null;
|
private static context: vscode.ExtensionContext | null = null;
|
||||||
private static readonly AUTH_STATE_KEY = 'qwen.authState';
|
private static readonly AUTH_STATE_KEY = 'qwen.authState';
|
||||||
private static readonly AUTH_CACHE_DURATION = 24 * 60 * 60 * 1000; // 24 hours
|
private static readonly AUTH_CACHE_DURATION = 24 * 60 * 60 * 1000; // 24 hours
|
||||||
//TODO:
|
|
||||||
private constructor() {}
|
private constructor() {}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -646,8 +646,7 @@ export const App: React.FC = () => {
|
|||||||
|
|
||||||
<div
|
<div
|
||||||
ref={messagesContainerRef}
|
ref={messagesContainerRef}
|
||||||
className="chat-messages flex-1 overflow-y-auto overflow-x-hidden pt-5 pr-5 pl-5 pb-[120px] flex flex-col relative min-w-0 focus:outline-none [&::-webkit-scrollbar]:w-2 [&::-webkit-scrollbar-track]:bg-transparent [&::-webkit-scrollbar-thumb]:bg-white/20 [&::-webkit-scrollbar-thumb]:rounded-sm [&::-webkit-scrollbar-thumb:hover]:bg-white/30 [&>*]:flex [&>*]:gap-0 [&>*]:items-start [&>*]:text-left [&>*]:py-2 [&>*:not(:last-child)]:pb-[8px] [&>*]:flex-col [&>*]:relative [&>*]:animate-[fadeIn_0.2s_ease-in]"
|
className="chat-messages messages-container flex-1 overflow-y-auto overflow-x-hidden pt-5 pr-5 pl-5 pb-[120px] flex flex-col relative min-w-0 focus:outline-none [&::-webkit-scrollbar]:w-2 [&::-webkit-scrollbar-track]:bg-transparent [&::-webkit-scrollbar-thumb]:bg-white/20 [&::-webkit-scrollbar-thumb]:rounded-sm [&::-webkit-scrollbar-thumb]:hover:bg-white/30 [&>*]:flex [&>*]:gap-0 [&>*]:items-start [&>*]:text-left [&>*]:py-2 [&>*:not(:last-child)]:pb-[8px] [&>*]:flex-col [&>*]:relative [&>*]:animate-[fadeIn_0.2s_ease-in]"
|
||||||
style={{ backgroundColor: 'var(--app-primary-background)' }}
|
|
||||||
>
|
>
|
||||||
{!hasContent ? (
|
{!hasContent ? (
|
||||||
<EmptyState />
|
<EmptyState />
|
||||||
@@ -655,12 +654,17 @@ export const App: React.FC = () => {
|
|||||||
<>
|
<>
|
||||||
{/* Render all messages and tool calls */}
|
{/* Render all messages and tool calls */}
|
||||||
{renderMessages()}
|
{renderMessages()}
|
||||||
{messageHandling.isWaitingForResponse &&
|
{/* Flow-in persistent slot: keeps a small constant height so toggling */}
|
||||||
messageHandling.loadingMessage && (
|
{/* the waiting message doesn't change list height to zero. When */}
|
||||||
<WaitingMessage
|
{/* active, render the waiting message inline (not fixed). */}
|
||||||
loadingMessage={messageHandling.loadingMessage}
|
<div className="waiting-message-slot min-h-[28px]">
|
||||||
/>
|
{messageHandling.isWaitingForResponse &&
|
||||||
)}
|
messageHandling.loadingMessage && (
|
||||||
|
<WaitingMessage
|
||||||
|
loadingMessage={messageHandling.loadingMessage}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
|
||||||
<div ref={messagesEndRef} />
|
<div ref={messagesEndRef} />
|
||||||
</>
|
</>
|
||||||
|
|||||||
@@ -201,8 +201,17 @@ export class PanelManager {
|
|||||||
*/
|
*/
|
||||||
revealPanel(preserveFocus: boolean = true): void {
|
revealPanel(preserveFocus: boolean = true): void {
|
||||||
if (this.panel) {
|
if (this.panel) {
|
||||||
// Reveal without forcing a specific column to avoid reflowing groups.
|
// Prefer revealing in the currently tracked group to avoid reflowing groups.
|
||||||
this.panel.reveal(undefined, preserveFocus);
|
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?: vscode.ViewColumn };
|
||||||
}
|
}
|
||||||
)?.group?.viewColumn;
|
)?.group?.viewColumn;
|
||||||
if (groupViewColumn != null) {
|
if (groupViewColumn !== null) {
|
||||||
this.panelGroupViewColumn = groupViewColumn as vscode.ViewColumn;
|
this.panelGroupViewColumn = groupViewColumn as vscode.ViewColumn;
|
||||||
}
|
}
|
||||||
} catch {
|
} catch {
|
||||||
@@ -257,7 +266,7 @@ export class PanelManager {
|
|||||||
this.panel.onDidDispose(
|
this.panel.onDidDispose(
|
||||||
() => {
|
() => {
|
||||||
// Capture the group we intend to clean up before we clear fields
|
// 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
|
// Prefer the group from the captured tab if available
|
||||||
((
|
((
|
||||||
this.panelTab as unknown as {
|
this.panelTab as unknown as {
|
||||||
@@ -266,7 +275,7 @@ export class PanelManager {
|
|||||||
)?.group?.viewColumn as vscode.ViewColumn | undefined) ??
|
)?.group?.viewColumn as vscode.ViewColumn | undefined) ??
|
||||||
// Fall back to our last-known group column
|
// Fall back to our last-known group column
|
||||||
this.panelGroupViewColumn ??
|
this.panelGroupViewColumn ??
|
||||||
undefined;
|
null;
|
||||||
|
|
||||||
this.panel = null;
|
this.panel = null;
|
||||||
this.panelTab = null;
|
this.panelTab = null;
|
||||||
@@ -275,18 +284,19 @@ export class PanelManager {
|
|||||||
// After VS Code updates its tab model, check if that group is now
|
// 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
|
// empty (and typically locked for Qwen). If so, close the group to
|
||||||
// avoid leaving an empty locked column when the user closes Qwen.
|
// avoid leaving an empty locked column when the user closes Qwen.
|
||||||
if (targetColumn != null) {
|
if (targetColumn !== null) {
|
||||||
|
const column: vscode.ViewColumn = targetColumn;
|
||||||
setTimeout(async () => {
|
setTimeout(async () => {
|
||||||
try {
|
try {
|
||||||
const groups = vscode.window.tabGroups.all;
|
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
|
// If the group that hosted Qwen is now empty, close it to avoid
|
||||||
// leaving an empty locked column around. VS Code's stable API
|
// leaving an empty locked column around. VS Code's stable API
|
||||||
// does not expose the lock state on TabGroup, so we only check
|
// does not expose the lock state on TabGroup, so we only check
|
||||||
// for emptiness here.
|
// for emptiness here.
|
||||||
if (group && group.tabs.length === 0) {
|
if (group && group.tabs.length === 0) {
|
||||||
// Focus the group we want to close
|
// Focus the group we want to close
|
||||||
await this.focusGroupByColumn(targetColumn);
|
await this.focusGroupByColumn(column);
|
||||||
// Try closeGroup first; fall back to removeActiveEditorGroup
|
// Try closeGroup first; fall back to removeActiveEditorGroup
|
||||||
try {
|
try {
|
||||||
await vscode.commands.executeCommand(
|
await vscode.commands.executeCommand(
|
||||||
|
|||||||
@@ -65,20 +65,10 @@ export const WaitingMessage: React.FC<WaitingMessageProps> = ({
|
|||||||
}, [phrases]);
|
}, [phrases]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="flex gap-0 items-start text-left py-2 flex-col opacity-85">
|
<div className="waiting-message-outer flex gap-0 items-start text-left py-2 flex-col opacity-85">
|
||||||
{/* Use the same left status icon (pseudo-element) style as assistant-message-container */}
|
{/* Use the same left status icon (pseudo-element) style as assistant-message-container */}
|
||||||
<div
|
<div className="assistant-message-container assistant-message-loading waiting-message-inner w-full items-start pl-[30px] relative">
|
||||||
className="assistant-message-container assistant-message-loading"
|
<span className="waiting-message-text opacity-70 italic loading-text-shimmer">
|
||||||
style={{
|
|
||||||
width: '100%',
|
|
||||||
alignItems: 'flex-start',
|
|
||||||
paddingLeft: '30px', // reserve space for ::before bullet
|
|
||||||
position: 'relative',
|
|
||||||
paddingTop: '8px',
|
|
||||||
paddingBottom: '8px',
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<span className="opacity-70 italic loading-text-shimmer">
|
|
||||||
{phrases[index]}
|
{phrases[index]}
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -47,9 +47,15 @@
|
|||||||
--app-input-highlight: var(--app-qwen-theme);
|
--app-input-highlight: var(--app-qwen-theme);
|
||||||
|
|
||||||
/* Code Highlighting */
|
/* Code Highlighting */
|
||||||
--app-code-background: var(--vscode-textCodeBlock-background, rgba(0, 0, 0, 0.05));
|
--app-code-background: var(
|
||||||
--app-link-foreground: var(--vscode-textLink-foreground, #007ACC);
|
--vscode-textCodeBlock-background,
|
||||||
--app-link-active-foreground: var(--vscode-textLink-activeForeground, #005A9E);
|
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 */
|
/* List Styles */
|
||||||
--app-list-hover-background: var(--vscode-list-hoverBackground);
|
--app-list-hover-background: var(--vscode-list-hoverBackground);
|
||||||
@@ -167,7 +173,8 @@ button {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@keyframes pulse {
|
@keyframes pulse {
|
||||||
0%, 100% {
|
0%,
|
||||||
|
100% {
|
||||||
opacity: 1;
|
opacity: 1;
|
||||||
}
|
}
|
||||||
50% {
|
50% {
|
||||||
@@ -176,7 +183,9 @@ button {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@keyframes typingPulse {
|
@keyframes typingPulse {
|
||||||
0%, 60%, 100% {
|
0%,
|
||||||
|
60%,
|
||||||
|
100% {
|
||||||
transform: scale(0.7);
|
transform: scale(0.7);
|
||||||
opacity: 0.6;
|
opacity: 0.6;
|
||||||
}
|
}
|
||||||
@@ -251,7 +260,8 @@ button {
|
|||||||
|
|
||||||
/* Animation for in-progress status (used by pseudo bullets and spinners) */
|
/* Animation for in-progress status (used by pseudo bullets and spinners) */
|
||||||
@keyframes pulse {
|
@keyframes pulse {
|
||||||
0%, 100% {
|
0%,
|
||||||
|
100% {
|
||||||
opacity: 1;
|
opacity: 1;
|
||||||
}
|
}
|
||||||
50% {
|
50% {
|
||||||
|
|||||||
Reference in New Issue
Block a user