From 3c937c38275a994913cadca2692ebc4d03d23e23 Mon Sep 17 00:00:00 2001 From: Chris Estreich Date: Thu, 17 Apr 2025 15:28:11 -0700 Subject: [PATCH] Task header theme fixes (#2721) --- evals/packages/db/scripts/copy-run.mts | 12 ++- webview-ui/src/components/chat/ChatRow.tsx | 92 ++++--------------- .../src/components/chat/FollowUpSuggest.tsx | 67 +++++++------- webview-ui/src/components/chat/TaskHeader.tsx | 43 ++++----- webview-ui/src/components/ui/badge.tsx | 2 +- webview-ui/src/components/ui/button.tsx | 4 +- 6 files changed, 85 insertions(+), 135 deletions(-) diff --git a/evals/packages/db/scripts/copy-run.mts b/evals/packages/db/scripts/copy-run.mts index 9901058d7a..fa82907181 100644 --- a/evals/packages/db/scripts/copy-run.mts +++ b/evals/packages/db/scripts/copy-run.mts @@ -57,7 +57,17 @@ const copyRun = async (runId: number) => { tasks, async (task) => { // eslint-disable-next-line @typescript-eslint/no-unused-vars - const { id: _, ...newTaskMetricsValues } = task.taskMetrics! + const { id: _, ...newTaskMetricsValues } = task.taskMetrics || { + duration: 0, + tokensIn: 0, + tokensOut: 0, + tokensContext: 0, + cacheWrites: 0, + cacheReads: 0, + cost: 0, + createdAt: new Date(), + } + const [newTaskMetrics] = await destDb.insert(schema.taskMetrics).values(newTaskMetricsValues).returning() if (!newTaskMetrics) { diff --git a/webview-ui/src/components/chat/ChatRow.tsx b/webview-ui/src/components/chat/ChatRow.tsx index e2c7495b65..60526e11d1 100644 --- a/webview-ui/src/components/chat/ChatRow.tsx +++ b/webview-ui/src/components/chat/ChatRow.tsx @@ -1,9 +1,12 @@ -import { VSCodeBadge, VSCodeButton, VSCodeProgressRing } from "@vscode/webview-ui-toolkit/react" -import deepEqual from "fast-deep-equal" import React, { memo, useEffect, useMemo, useRef, useState } from "react" import { useSize } from "react-use" -import { useCopyToClipboard } from "../../utils/clipboard" import { useTranslation, Trans } from "react-i18next" +import deepEqual from "fast-deep-equal" +import { VSCodeBadge, VSCodeButton, VSCodeProgressRing } from "@vscode/webview-ui-toolkit/react" + +import { Button } from "@/components/ui" + +import { useCopyToClipboard } from "../../utils/clipboard" import { safeJsonParse } from "../../utils/json" import { ClineApiReqInfo, @@ -25,7 +28,7 @@ import McpResourceRow from "../mcp/McpResourceRow" import McpToolRow from "../mcp/McpToolRow" import { highlightMentions } from "./TaskHeader" import { CheckpointSaved } from "./checkpoints/CheckpointSaved" -import FollowUpSuggest from "./FollowUpSuggest" +import { FollowUpSuggest } from "./FollowUpSuggest" interface ChatRowProps { message: ClineMessage @@ -230,7 +233,8 @@ export const ChatRowContent = ({ return [ , + style={{ color: normalColor, marginBottom: "-1.5px" }} + />, {t("chat:questions.hasQuestion")}, ] default: @@ -795,39 +799,6 @@ export const ChatRowContent = ({ )}

- - {/* {apiProvider === "" && ( -
- - - Uh-oh, this could be a problem on end. We've been alerted and - will resolve this ASAP. You can also{" "} - - contact us - - . - -
- )} */} )} @@ -853,46 +824,19 @@ export const ChatRowContent = ({ ) case "user_feedback": return ( -
-
- - {highlightMentions(message.text)} - - +
+
{highlightMentions(message.text)}
+
{message.images && message.images.length > 0 && ( diff --git a/webview-ui/src/components/chat/FollowUpSuggest.tsx b/webview-ui/src/components/chat/FollowUpSuggest.tsx index 25371dc502..b300add5fb 100644 --- a/webview-ui/src/components/chat/FollowUpSuggest.tsx +++ b/webview-ui/src/components/chat/FollowUpSuggest.tsx @@ -1,7 +1,8 @@ import { useCallback } from "react" -import { cn } from "../../lib/utils" -import { Button } from "../ui/button" -import { Edit } from "lucide-react" +import { ArrowRight, Edit } from "lucide-react" + +import { Button } from "@/components/ui" + import { useAppTranslation } from "../../i18n/TranslationContext" interface FollowUpSuggestProps { @@ -10,7 +11,7 @@ interface FollowUpSuggestProps { ts: number } -const FollowUpSuggest = ({ suggestions = [], onSuggestionClick, ts = 1 }: FollowUpSuggestProps) => { +export const FollowUpSuggest = ({ suggestions = [], onSuggestionClick, ts = 1 }: FollowUpSuggestProps) => { const { t } = useAppTranslation() const handleSuggestionClick = useCallback( (suggestion: string, event: React.MouseEvent) => { @@ -19,45 +20,39 @@ const FollowUpSuggest = ({ suggestions = [], onSuggestionClick, ts = 1 }: Follow [onSuggestionClick], ) - // Don't render if there are no suggestions or no click handler + // Don't render if there are no suggestions or no click handler. if (!suggestions?.length || !onSuggestionClick) { return null } return ( -
-
-
- {suggestions.map((suggestion) => ( -
- -
{ - e.stopPropagation() - // Simulate shift-click by directly calling the handler with shiftKey=true - onSuggestionClick?.(suggestion, { ...e, shiftKey: true }) - }} - title={t("chat:followUpSuggest.copyToInput")}> - -
+
+ {suggestions.map((suggestion) => ( +
+ +
{ + e.stopPropagation() + // Simulate shift-click by directly calling the handler with shiftKey=true. + onSuggestionClick?.(suggestion, { ...e, shiftKey: true }) + }} + title={t("chat:followUpSuggest.copyToInput")}> + +
-
+ ))}
) } - -export default FollowUpSuggest diff --git a/webview-ui/src/components/chat/TaskHeader.tsx b/webview-ui/src/components/chat/TaskHeader.tsx index 6a2c91b303..3053099b10 100644 --- a/webview-ui/src/components/chat/TaskHeader.tsx +++ b/webview-ui/src/components/chat/TaskHeader.tsx @@ -1,13 +1,12 @@ import React, { memo, useMemo, useRef, useState } from "react" import { useWindowSize } from "react-use" -import { VSCodeButton } from "@vscode/webview-ui-toolkit/react" import prettyBytes from "pretty-bytes" import { useTranslation } from "react-i18next" import { vscode } from "@/utils/vscode" import { formatLargeNumber } from "@/utils/format" import { calculateTokenDistribution, getMaxTokensForModel } from "@/utils/model-utils" -import { Button } from "@/components/ui" +import { Button, Badge } from "@/components/ui" import { ClineMessage } from "../../../../src/shared/ExtensionMessage" import { mentionRegexGlobal } from "../../../../src/shared/context-mentions" @@ -17,6 +16,7 @@ import { useExtensionState } from "../../context/ExtensionStateContext" import Thumbnails from "../common/Thumbnails" import { normalizeApiConfiguration } from "../settings/ApiOptions" import { DeleteTaskDialog } from "../history/DeleteTaskDialog" +import { cn } from "@/lib/utils" interface TaskHeaderProps { task: ClineMessage @@ -55,10 +55,15 @@ const TaskHeader: React.FC = ({ const shouldShowPromptCacheInfo = doesModelSupportPromptCache && apiConfiguration?.apiProvider !== "openrouter" return ( -
+
-
+ className={cn( + "rounded-xs p-2.5 flex flex-col gap-1.5 relative z-1 border", + !!isTaskExpanded + ? "border-vscode-panel-border text-vscode-foreground" + : "border-vscode-panel-border/80 text-vscode-foreground/80", + )}> +
setIsTaskExpanded(!isTaskExpanded)}> @@ -73,14 +78,14 @@ const TaskHeader: React.FC = ({ {!isTaskExpanded && {highlightMentions(task.text, false)}}
- - - - + title={t("chat:task.closeAndStart")} + className="shrink-0 w-5 h-5"> + +
{/* Collapsed state: Track context and cost if we have any */} {!isTaskExpanded && contextWindow > 0 && ( @@ -90,11 +95,7 @@ const TaskHeader: React.FC = ({ contextTokens={contextTokens || 0} maxTokens={getMaxTokensForModel(selectedModelInfo, apiConfiguration)} /> - {!!totalCost && ( -
- ${totalCost?.toFixed(2)} -
- )} + {!!totalCost && ${totalCost.toFixed(2)}}
)} {/* Expanded state: Show task text and images */} @@ -271,7 +272,7 @@ const ContextWindowProgress = ({ contextWindow, contextTokens, maxTokens }: Cont
{/* Invisible overlay for hover area */}
@@ -282,7 +283,7 @@ const ContextWindowProgress = ({ contextWindow, contextTokens, maxTokens }: Cont
{/* Invisible overlay for current tokens section */}
{/* Invisible overlay for reserved section */}
{/* Invisible overlay for available space */}