Browse Source

Condensing fixes (#4107)

* Add missing telemetry types

* Give IconButton the pointer cursor when enabled

* Change context condensing to use a Lucide icon

* Mock Lucide icons globally
Matt Rubens 7 months ago
parent
commit
337b5dac88

+ 2 - 0
packages/types/src/telemetry.ts

@@ -109,6 +109,8 @@ export const rooCodeTelemetryEventSchema = z.discriminatedUnion("type", [
 			TelemetryEventName.DIFF_APPLICATION_ERROR,
 			TelemetryEventName.SHELL_INTEGRATION_ERROR,
 			TelemetryEventName.CONSECUTIVE_MISTAKE_ERROR,
+			TelemetryEventName.CONTEXT_CONDENSED,
+			TelemetryEventName.SLIDING_WINDOW_TRUNCATION,
 		]),
 		properties: telemetryPropertiesSchema,
 	}),

+ 1 - 1
webview-ui/jest.config.cjs

@@ -6,7 +6,7 @@ module.exports = {
 	moduleFileExtensions: ["ts", "tsx", "js", "jsx", "json", "node"],
 	transform: { "^.+\\.(ts|tsx)$": ["ts-jest", { tsconfig: { jsx: "react-jsx", module: "ESNext" } }] },
 	testMatch: ["<rootDir>/src/**/__tests__/**/*.{js,jsx,ts,tsx}", "<rootDir>/src/**/*.{spec,test}.{js,jsx,ts,tsx}"],
-	setupFilesAfterEnv: ["<rootDir>/src/setupTests.ts"],
+	setupFilesAfterEnv: ["<rootDir>/src/setupTests.tsx"],
 	moduleNameMapper: {
 		"\\.(css|less|scss|sass)$": "identity-obj-proxy",
 		"^vscrui$": "<rootDir>/src/__mocks__/vscrui.ts",

+ 1 - 0
webview-ui/src/components/chat/IconButton.tsx

@@ -27,6 +27,7 @@ export const IconButton: React.FC<IconButtonProps> = ({
 		"hover:opacity-100 hover:bg-[rgba(255,255,255,0.03)] hover:border-[rgba(255,255,255,0.15)]",
 		"focus:outline-none focus-visible:ring-1 focus-visible:ring-vscode-focusBorder",
 		"active:bg-[rgba(255,255,255,0.1)]",
+		!disabled && "cursor-pointer",
 		disabled &&
 			"opacity-40 cursor-not-allowed grayscale-[30%] hover:bg-transparent hover:border-[rgba(255,255,255,0.08)] active:bg-transparent",
 		className,

+ 5 - 6
webview-ui/src/components/chat/TaskHeader.tsx

@@ -2,7 +2,7 @@ import { memo, useRef, useState } from "react"
 import { useWindowSize } from "react-use"
 import { useTranslation } from "react-i18next"
 import { VSCodeBadge } from "@vscode/webview-ui-toolkit/react"
-import { CloudUpload, CloudDownload } from "lucide-react"
+import { CloudUpload, CloudDownload, FoldVertical } from "lucide-react"
 
 import type { ClineMessage } from "@roo-code/types"
 
@@ -19,7 +19,6 @@ import Thumbnails from "../common/Thumbnails"
 import { TaskActions } from "./TaskActions"
 import { ContextWindowProgress } from "./ContextWindowProgress"
 import { Mention } from "./Mention"
-import { IconButton } from "./IconButton"
 
 export interface TaskHeaderProps {
 	task: ClineMessage
@@ -108,13 +107,13 @@ const TaskHeader = ({
 									: undefined
 							}
 						/>
-						<IconButton
-							iconClass="codicon-fold"
+						<button
 							title={t("chat:task.condenseContext")}
 							disabled={buttonsDisabled}
 							onClick={() => currentTaskItem && handleCondenseContext(currentTaskItem.id)}
-							className="shrink-0 min-h-[20px] min-w-[20px] p-[2px]"
-						/>
+							className="shrink-0 min-h-[20px] min-w-[20px] p-[2px] cursor-pointer disabled:cursor-not-allowed opacity-85 hover:opacity-100 bg-transparent border-none rounded-md">
+							<FoldVertical size={16} />
+						</button>
 						{!!totalCost && <VSCodeBadge>${totalCost.toFixed(2)}</VSCodeBadge>}
 					</div>
 				)}

+ 0 - 16
webview-ui/src/components/common/__tests__/CodeBlock.test.tsx

@@ -28,22 +28,6 @@ jest.mock("shiki", () => ({
 	},
 }))
 
-// Mock all lucide-react icons with a proxy to handle any icon requested
-jest.mock("lucide-react", () => {
-	return new Proxy(
-		{},
-		{
-			get: function (_obj, prop) {
-				// Return a component factory for any icon that's requested
-				if (prop === "__esModule") {
-					return true
-				}
-				return () => <div data-testid={`${String(prop)}-icon`}>{String(prop)}</div>
-			},
-		},
-	)
-})
-
 // Mock the highlighter utility
 jest.mock("../../../utils/highlighter", () => {
 	const mockHighlighter = {

+ 0 - 16
webview-ui/src/components/modes/__tests__/ModesView.test.tsx

@@ -12,22 +12,6 @@ jest.mock("@src/utils/vscode", () => ({
 	},
 }))
 
-// Mock all lucide-react icons with a proxy to handle any icon requested
-jest.mock("lucide-react", () => {
-	return new Proxy(
-		{},
-		{
-			get: function (_obj, prop) {
-				// Return a component factory for any icon that's requested
-				if (prop === "__esModule") {
-					return true
-				}
-				return () => <div data-testid={`${String(prop)}-icon`}>{String(prop)}</div>
-			},
-		},
-	)
-})
-
 const mockExtensionState = {
 	customModePrompts: {},
 	listApiConfigMeta: [

+ 2 - 2
webview-ui/src/components/settings/ContextManagementSettings.tsx

@@ -1,7 +1,7 @@
 import { HTMLAttributes } from "react"
 import { useAppTranslation } from "@/i18n/TranslationContext"
 import { VSCodeCheckbox, VSCodeTextArea } from "@vscode/webview-ui-toolkit/react"
-import { Database } from "lucide-react"
+import { Database, FoldVertical } from "lucide-react"
 
 import { cn } from "@/lib/utils"
 import { Button, Input, Select, SelectContent, SelectItem, SelectTrigger, SelectValue, Slider } from "@/components/ui"
@@ -197,7 +197,7 @@ export const ContextManagementSettings = ({
 				{autoCondenseContext && (
 					<div className="flex flex-col gap-3 pl-3 border-l-2 border-vscode-button-background">
 						<div className="flex items-center gap-4 font-bold">
-							<span className="codicon codicon-fold" />
+							<FoldVertical size={16} />
 							<div>{t("settings:contextManagement.autoCondenseContextPercent.label")}</div>
 						</div>
 						<div>

+ 0 - 14
webview-ui/src/components/settings/__tests__/ContextManagementSettings.test.tsx

@@ -13,20 +13,6 @@ class MockResizeObserver {
 
 global.ResizeObserver = MockResizeObserver
 
-// Mock lucide-react icons - these don't work well in Jest/JSDOM environment
-jest.mock("lucide-react", () => {
-	return {
-		Database: React.forwardRef((props: any, ref: any) => <div ref={ref} data-testid="database-icon" {...props} />),
-		ChevronDown: React.forwardRef((props: any, ref: any) => (
-			<div ref={ref} data-testid="chevron-down-icon" {...props} />
-		)),
-		ChevronUp: React.forwardRef((props: any, ref: any) => (
-			<div ref={ref} data-testid="chevron-up-icon" {...props} />
-		)),
-		Check: React.forwardRef((props: any, ref: any) => <div ref={ref} data-testid="check-icon" {...props} />),
-	}
-})
-
 // Mock translation hook to return the key as the translation
 jest.mock("@/i18n/TranslationContext", () => ({
 	useAppTranslation: () => ({

+ 0 - 16
webview-ui/src/components/settings/__tests__/SettingsView.test.tsx

@@ -10,22 +10,6 @@ import SettingsView from "../SettingsView"
 // Mock vscode API
 jest.mock("@src/utils/vscode", () => ({ vscode: { postMessage: jest.fn() } }))
 
-// Mock all lucide-react icons with a proxy to handle any icon requested
-jest.mock("lucide-react", () => {
-	return new Proxy(
-		{},
-		{
-			get: function (_obj, prop) {
-				// Return a component factory for any icon that's requested
-				if (prop === "__esModule") {
-					return true
-				}
-				return () => <div data-testid={`${String(prop)}-icon`}>{String(prop)}</div>
-			},
-		},
-	)
-})
-
 // Mock ApiConfigManager component
 jest.mock("../ApiConfigManager", () => ({
 	__esModule: true,

+ 20 - 0
webview-ui/src/setupTests.ts → webview-ui/src/setupTests.tsx

@@ -30,3 +30,23 @@ Object.defineProperty(window, "matchMedia", {
 		dispatchEvent: jest.fn(),
 	})),
 })
+
+// Mock lucide-react icons globally using Proxy for dynamic icon handling
+jest.mock("lucide-react", () => {
+	return new Proxy(
+		{},
+		{
+			get: function (_obj, prop) {
+				// Return a component factory for any icon that's requested
+				if (prop === "__esModule") {
+					return true
+				}
+				return (props: any) => (
+					<div {...props} data-testid={`${String(prop)}-icon`}>
+						{String(prop)}
+					</div>
+				)
+			},
+		},
+	)
+})