mirror of
https://github.com/RooVetGit/Roo-Code.git
synced 2026-08-28 05:27:24 +00:00
Adds maxTasksHomeScreen UI setting
This commit is contained in:
parent
47e3b606f2
commit
acdf4febe0
6 changed files with 164 additions and 33 deletions
99
src/core/config/__tests__/maxTasksHomeScreen.test.ts
Normal file
99
src/core/config/__tests__/maxTasksHomeScreen.test.ts
Normal file
|
|
@ -0,0 +1,99 @@
|
|||
import { describe, it, expect, beforeEach, vi } from "vitest"
|
||||
import * as vscode from "vscode"
|
||||
import { ContextProxy } from "../ContextProxy"
|
||||
|
||||
describe("maxTasksHomeScreen setting", () => {
|
||||
let mockContext: vscode.ExtensionContext
|
||||
let contextProxy: ContextProxy
|
||||
|
||||
beforeEach(async () => {
|
||||
// Create mock VSCode context
|
||||
const mockGlobalState = new Map<string, any>()
|
||||
const mockSecrets = new Map<string, string>()
|
||||
|
||||
mockContext = {
|
||||
globalState: {
|
||||
get: vi.fn((key: string) => mockGlobalState.get(key)),
|
||||
update: vi.fn(async (key: string, value: any) => {
|
||||
mockGlobalState.set(key, value)
|
||||
}),
|
||||
keys: vi.fn(() => Array.from(mockGlobalState.keys())),
|
||||
setKeysForSync: vi.fn(),
|
||||
},
|
||||
secrets: {
|
||||
get: vi.fn(async (key: string) => mockSecrets.get(key)),
|
||||
store: vi.fn(async (key: string, value: string) => {
|
||||
mockSecrets.set(key, value)
|
||||
}),
|
||||
delete: vi.fn(async (key: string) => {
|
||||
mockSecrets.delete(key)
|
||||
}),
|
||||
onDidChange: vi.fn(),
|
||||
},
|
||||
extensionUri: {} as vscode.Uri,
|
||||
extensionPath: "/test/path",
|
||||
globalStorageUri: {} as vscode.Uri,
|
||||
logUri: {} as vscode.Uri,
|
||||
extension: {} as vscode.Extension<any>,
|
||||
extensionMode: 3, // vscode.ExtensionMode.Test
|
||||
} as unknown as vscode.ExtensionContext
|
||||
|
||||
contextProxy = new ContextProxy(mockContext)
|
||||
await contextProxy.initialize()
|
||||
})
|
||||
|
||||
it("should save maxTasksHomeScreen value", async () => {
|
||||
// Set the value
|
||||
await contextProxy.setValue("maxTasksHomeScreen", 10)
|
||||
|
||||
// Verify it was saved
|
||||
expect(mockContext.globalState.update).toHaveBeenCalledWith("maxTasksHomeScreen", 10)
|
||||
})
|
||||
|
||||
it("should retrieve maxTasksHomeScreen value", async () => {
|
||||
// Set the value
|
||||
await contextProxy.setValue("maxTasksHomeScreen", 15)
|
||||
|
||||
// Get the value
|
||||
const value = contextProxy.getValue("maxTasksHomeScreen")
|
||||
|
||||
// Verify it matches
|
||||
expect(value).toBe(15)
|
||||
})
|
||||
|
||||
it("should persist maxTasksHomeScreen across initialization", async () => {
|
||||
// Set the value
|
||||
await contextProxy.setValue("maxTasksHomeScreen", 8)
|
||||
|
||||
// Create a new instance (simulating restart)
|
||||
const newContextProxy = new ContextProxy(mockContext)
|
||||
await newContextProxy.initialize()
|
||||
|
||||
// Get the value from the new instance
|
||||
const value = newContextProxy.getValue("maxTasksHomeScreen")
|
||||
|
||||
// Verify it was persisted
|
||||
expect(value).toBe(8)
|
||||
})
|
||||
|
||||
it("should handle default value of 4", async () => {
|
||||
// Don't set any value, should use default
|
||||
const values = contextProxy.getValues()
|
||||
|
||||
// maxTasksHomeScreen should be undefined or 4 (depending on implementation)
|
||||
expect(values.maxTasksHomeScreen === undefined || values.maxTasksHomeScreen === 4).toBe(true)
|
||||
})
|
||||
|
||||
it("should validate min/max bounds", async () => {
|
||||
// The schema should enforce min=0, max=20
|
||||
// Try setting valid values
|
||||
await contextProxy.setValue("maxTasksHomeScreen", 0)
|
||||
expect(contextProxy.getValue("maxTasksHomeScreen")).toBe(0)
|
||||
|
||||
await contextProxy.setValue("maxTasksHomeScreen", 20)
|
||||
expect(contextProxy.getValue("maxTasksHomeScreen")).toBe(20)
|
||||
|
||||
await contextProxy.setValue("maxTasksHomeScreen", 10)
|
||||
expect(contextProxy.getValue("maxTasksHomeScreen")).toBe(10)
|
||||
})
|
||||
})
|
||||
|
|
@ -1916,6 +1916,7 @@ export class ClineProvider
|
|||
includeDiagnosticMessages,
|
||||
maxDiagnosticMessages,
|
||||
includeTaskHistoryInEnhance,
|
||||
maxTasksHomeScreen,
|
||||
includeCurrentTime,
|
||||
includeCurrentCost,
|
||||
taskSyncEnabled,
|
||||
|
|
@ -2080,6 +2081,7 @@ export class ClineProvider
|
|||
includeDiagnosticMessages: includeDiagnosticMessages ?? true,
|
||||
maxDiagnosticMessages: maxDiagnosticMessages ?? 50,
|
||||
includeTaskHistoryInEnhance: includeTaskHistoryInEnhance ?? true,
|
||||
maxTasksHomeScreen: maxTasksHomeScreen ?? 4,
|
||||
includeCurrentTime: includeCurrentTime ?? true,
|
||||
includeCurrentCost: includeCurrentCost ?? true,
|
||||
taskSyncEnabled,
|
||||
|
|
@ -2295,6 +2297,7 @@ export class ClineProvider
|
|||
includeDiagnosticMessages: stateValues.includeDiagnosticMessages ?? true,
|
||||
maxDiagnosticMessages: stateValues.maxDiagnosticMessages ?? 50,
|
||||
includeTaskHistoryInEnhance: stateValues.includeTaskHistoryInEnhance ?? true,
|
||||
maxTasksHomeScreen: stateValues.maxTasksHomeScreen ?? 4,
|
||||
includeCurrentTime: stateValues.includeCurrentTime ?? true,
|
||||
includeCurrentCost: stateValues.includeCurrentCost ?? true,
|
||||
taskSyncEnabled,
|
||||
|
|
|
|||
|
|
@ -0,0 +1,28 @@
|
|||
import { describe, it, expect } from "vitest"
|
||||
import type { ExtensionState } from "../../../shared/ExtensionMessage"
|
||||
|
||||
/**
|
||||
* Integration test for maxTasksHomeScreen setting
|
||||
* This test verifies that the setting is properly typed in ExtensionState
|
||||
*/
|
||||
describe("maxTasksHomeScreen integration", () => {
|
||||
it("should be a valid ExtensionState property", () => {
|
||||
// Type-level test: This will fail to compile if maxTasksHomeScreen is not in ExtensionState
|
||||
const state: Partial<ExtensionState> = {
|
||||
maxTasksHomeScreen: 10,
|
||||
}
|
||||
|
||||
expect(state.maxTasksHomeScreen).toBe(10)
|
||||
})
|
||||
|
||||
it("should accept valid range values", () => {
|
||||
const validValues = [0, 4, 10, 15, 20]
|
||||
|
||||
validValues.forEach((value) => {
|
||||
const state: Partial<ExtensionState> = {
|
||||
maxTasksHomeScreen: value,
|
||||
}
|
||||
expect(state.maxTasksHomeScreen).toBe(value)
|
||||
})
|
||||
})
|
||||
})
|
||||
|
|
@ -1,9 +1,11 @@
|
|||
import { HTMLAttributes } from "react"
|
||||
import { useAppTranslation } from "@/i18n/TranslationContext"
|
||||
import { VSCodeCheckbox, VSCodeTextField } from "@vscode/webview-ui-toolkit/react"
|
||||
import { VSCodeCheckbox } from "@vscode/webview-ui-toolkit/react"
|
||||
import { Glasses } from "lucide-react"
|
||||
import { telemetryClient } from "@/utils/TelemetryClient"
|
||||
|
||||
import { Slider } from "@/components/ui"
|
||||
|
||||
import { SetCachedStateField } from "./types"
|
||||
import { SectionHeader } from "./SectionHeader"
|
||||
import { Section } from "./Section"
|
||||
|
|
@ -32,16 +34,13 @@ export const UISettings = ({
|
|||
})
|
||||
}
|
||||
|
||||
const handleMaxTasksHomeScreenChange = (value: string) => {
|
||||
const numValue = parseInt(value, 10)
|
||||
if (!isNaN(numValue) && numValue >= 0 && numValue <= 20) {
|
||||
setCachedStateField("maxTasksHomeScreen", numValue)
|
||||
const handleMaxTasksHomeScreenChange = (value: number) => {
|
||||
setCachedStateField("maxTasksHomeScreen", value)
|
||||
|
||||
// Track telemetry event
|
||||
telemetryClient.capture("ui_settings_max_tasks_home_screen_changed", {
|
||||
value: numValue,
|
||||
})
|
||||
}
|
||||
// Track telemetry event
|
||||
telemetryClient.capture("ui_settings_max_tasks_home_screen_changed", {
|
||||
value: value,
|
||||
})
|
||||
}
|
||||
|
||||
return (
|
||||
|
|
@ -70,18 +69,17 @@ export const UISettings = ({
|
|||
|
||||
{/* Maximum Tasks in Home Screen Setting */}
|
||||
<div className="flex flex-col gap-1">
|
||||
<label htmlFor="max-tasks-home-screen" className="font-medium">
|
||||
{t("settings:ui.maxTasksHomeScreen.label")}
|
||||
</label>
|
||||
<VSCodeTextField
|
||||
id="max-tasks-home-screen"
|
||||
value={maxTasksHomeScreen.toString()}
|
||||
onChange={(e: any) => handleMaxTasksHomeScreenChange(e.target.value)}
|
||||
data-testid="max-tasks-home-screen-input"
|
||||
className="w-32"
|
||||
/>
|
||||
<div className="text-vscode-descriptionForeground text-sm mt-1">
|
||||
{t("settings:ui.maxTasksHomeScreen.description")}
|
||||
<label className="block font-medium mb-1">{t("settings:ui.maxTasksHomeScreen.label")}</label>
|
||||
<div className="flex items-center gap-2">
|
||||
<Slider
|
||||
min={0}
|
||||
max={20}
|
||||
step={1}
|
||||
value={[maxTasksHomeScreen]}
|
||||
onValueChange={([value]) => handleMaxTasksHomeScreenChange(value)}
|
||||
data-testid="max-tasks-home-screen-slider"
|
||||
/>
|
||||
<span className="w-10">{maxTasksHomeScreen}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -15,10 +15,10 @@ describe("UISettings", () => {
|
|||
expect(checkbox).toBeTruthy()
|
||||
})
|
||||
|
||||
it("renders the max tasks home screen input", () => {
|
||||
it("renders the max tasks home screen slider", () => {
|
||||
const { getByTestId } = render(<UISettings {...defaultProps} />)
|
||||
const input = getByTestId("max-tasks-home-screen-input")
|
||||
expect(input).toBeTruthy()
|
||||
const slider = getByTestId("max-tasks-home-screen-slider")
|
||||
expect(slider).toBeTruthy()
|
||||
})
|
||||
|
||||
it("displays the correct initial state for collapse thinking", () => {
|
||||
|
|
@ -29,8 +29,9 @@ describe("UISettings", () => {
|
|||
|
||||
it("displays the correct initial value for max tasks", () => {
|
||||
const { getByTestId } = render(<UISettings {...defaultProps} maxTasksHomeScreen={10} />)
|
||||
const input = getByTestId("max-tasks-home-screen-input") as HTMLInputElement
|
||||
expect(input.value).toBe("10")
|
||||
const slider = getByTestId("max-tasks-home-screen-slider")
|
||||
const thumb = slider.querySelector('[role="slider"]') as HTMLElement
|
||||
expect(thumb.getAttribute("aria-valuenow")).toBe("10")
|
||||
})
|
||||
|
||||
it("calls setCachedStateField when checkbox is toggled", async () => {
|
||||
|
|
@ -54,12 +55,15 @@ describe("UISettings", () => {
|
|||
expect(checkbox.checked).toBe(true)
|
||||
})
|
||||
|
||||
it("updates input value when maxTasksHomeScreen prop changes", () => {
|
||||
it("updates slider value when maxTasksHomeScreen prop changes", () => {
|
||||
const { getByTestId, rerender } = render(<UISettings {...defaultProps} maxTasksHomeScreen={4} />)
|
||||
const input = getByTestId("max-tasks-home-screen-input") as HTMLInputElement
|
||||
expect(input.value).toBe("4")
|
||||
let slider = getByTestId("max-tasks-home-screen-slider")
|
||||
let thumb = slider.querySelector('[role="slider"]') as HTMLElement
|
||||
expect(thumb.getAttribute("aria-valuenow")).toBe("4")
|
||||
|
||||
rerender(<UISettings {...defaultProps} maxTasksHomeScreen={10} />)
|
||||
expect(input.value).toBe("10")
|
||||
slider = getByTestId("max-tasks-home-screen-slider")
|
||||
thumb = slider.querySelector('[role="slider"]') as HTMLElement
|
||||
expect(thumb.getAttribute("aria-valuenow")).toBe("10")
|
||||
})
|
||||
})
|
||||
|
|
|
|||
|
|
@ -44,8 +44,7 @@
|
|||
"description": "When enabled, thinking blocks will be collapsed by default until you interact with them"
|
||||
},
|
||||
"maxTasksHomeScreen": {
|
||||
"label": "Maximum number of tasks in home screen",
|
||||
"description": "Number of recent tasks to show on the home screen (0-20). Set to 0 to hide the history preview entirely."
|
||||
"label": "Maximum number of tasks in home screen"
|
||||
}
|
||||
},
|
||||
"prompts": {
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue