Skip to content

Commit b6d183c

Browse files
committed
use regular vscode checkbox to be sure we do not have weird caching issues
1 parent 7e622a0 commit b6d183c

File tree

4 files changed

+99
-134
lines changed

4 files changed

+99
-134
lines changed

webview-ui/src/components/kilocode/common/ControlledCheckbox.tsx

Lines changed: 0 additions & 49 deletions
This file was deleted.

webview-ui/src/components/kilocode/settings/GhostServiceSettings.tsx

Lines changed: 31 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,27 @@
11
//kilocode_change - new file
2-
import { HTMLAttributes } from "react"
2+
import { HTMLAttributes, useCallback } from "react"
33
import { useAppTranslation } from "@/i18n/TranslationContext"
44
import { Trans } from "react-i18next"
55
import { Bot, Zap } from "lucide-react"
66
import { cn } from "@/lib/utils"
77
import { SectionHeader } from "../../settings/SectionHeader"
88
import { Section } from "../../settings/Section"
99
import { GhostServiceSettings } from "@roo-code/types"
10-
import { SetCachedStateField } from "../../settings/types"
1110
import { vscode } from "@/utils/vscode"
12-
import { ControlledCheckbox } from "../common/ControlledCheckbox"
11+
import { VSCodeCheckbox } from "@vscode/webview-ui-toolkit/react"
1312
import { useKeybindings } from "@/hooks/useKeybindings"
1413

1514
type GhostServiceSettingsViewProps = HTMLAttributes<HTMLDivElement> & {
1615
ghostServiceSettings: GhostServiceSettings
17-
setCachedStateField: SetCachedStateField<"ghostServiceSettings">
16+
onGhostServiceSettingsChange: <K extends keyof NonNullable<GhostServiceSettings>>(
17+
field: K,
18+
value: NonNullable<GhostServiceSettings>[K],
19+
) => void
1820
}
1921

2022
export const GhostServiceSettingsView = ({
2123
ghostServiceSettings,
22-
setCachedStateField,
24+
onGhostServiceSettingsChange,
2325
className,
2426
...props
2527
}: GhostServiceSettingsViewProps) => {
@@ -28,26 +30,26 @@ export const GhostServiceSettingsView = ({
2830
ghostServiceSettings || {}
2931
const keybindings = useKeybindings(["kilo-code.addToContextAndFocus", "kilo-code.ghost.generateSuggestions"])
3032

31-
const onEnableAutoTriggerChange = (newValue: boolean) => {
32-
setCachedStateField("ghostServiceSettings", {
33-
...ghostServiceSettings,
34-
enableAutoTrigger: newValue,
35-
})
36-
}
33+
const onEnableAutoTriggerChange = useCallback(
34+
(e: any) => {
35+
onGhostServiceSettingsChange("enableAutoTrigger", e.target.checked)
36+
},
37+
[onGhostServiceSettingsChange],
38+
)
3739

38-
const onEnableQuickInlineTaskKeybindingChange = (newValue: boolean) => {
39-
setCachedStateField("ghostServiceSettings", {
40-
...ghostServiceSettings,
41-
enableQuickInlineTaskKeybinding: newValue,
42-
})
43-
}
40+
const onEnableQuickInlineTaskKeybindingChange = useCallback(
41+
(e: any) => {
42+
onGhostServiceSettingsChange("enableQuickInlineTaskKeybinding", e.target.checked)
43+
},
44+
[onGhostServiceSettingsChange],
45+
)
4446

45-
const onEnableSmartInlineTaskKeybindingChange = (newValue: boolean) => {
46-
setCachedStateField("ghostServiceSettings", {
47-
...ghostServiceSettings,
48-
enableSmartInlineTaskKeybinding: newValue,
49-
})
50-
}
47+
const onEnableSmartInlineTaskKeybindingChange = useCallback(
48+
(e: any) => {
49+
onGhostServiceSettingsChange("enableSmartInlineTaskKeybinding", e.target.checked)
50+
},
51+
[onGhostServiceSettingsChange],
52+
)
5153

5254
const openGlobalKeybindings = (filter?: string) => {
5355
vscode.postMessage({ type: "openGlobalKeybindings", text: filter })
@@ -72,24 +74,24 @@ export const GhostServiceSettingsView = ({
7274
</div>
7375

7476
<div className="flex flex-col gap-1">
75-
<ControlledCheckbox checked={enableAutoTrigger || false} onChange={onEnableAutoTriggerChange}>
77+
<VSCodeCheckbox checked={enableAutoTrigger || false} onChange={onEnableAutoTriggerChange}>
7678
<span className="font-medium">{t("kilocode:ghost.settings.enableAutoTrigger.label")}</span>
77-
</ControlledCheckbox>
79+
</VSCodeCheckbox>
7880
<div className="text-vscode-descriptionForeground text-sm mt-1">
7981
<Trans i18nKey="kilocode:ghost.settings.enableAutoTrigger.description" />
8082
</div>
8183
</div>
8284

8385
<div className="flex flex-col gap-1">
84-
<ControlledCheckbox
86+
<VSCodeCheckbox
8587
checked={enableQuickInlineTaskKeybinding || false}
8688
onChange={onEnableQuickInlineTaskKeybindingChange}>
8789
<span className="font-medium">
8890
{t("kilocode:ghost.settings.enableQuickInlineTaskKeybinding.label", {
8991
keybinding: keybindings["kilo-code.addToContextAndFocus"],
9092
})}
9193
</span>
92-
</ControlledCheckbox>
94+
</VSCodeCheckbox>
9395
<div className="text-vscode-descriptionForeground text-sm mt-1">
9496
<Trans
9597
i18nKey="kilocode:ghost.settings.enableQuickInlineTaskKeybinding.description"
@@ -105,15 +107,15 @@ export const GhostServiceSettingsView = ({
105107
</div>
106108
</div>
107109
<div className="flex flex-col gap-1">
108-
<ControlledCheckbox
110+
<VSCodeCheckbox
109111
checked={enableSmartInlineTaskKeybinding || false}
110112
onChange={onEnableSmartInlineTaskKeybindingChange}>
111113
<span className="font-medium">
112114
{t("kilocode:ghost.settings.enableSmartInlineTaskKeybinding.label", {
113115
keybinding: keybindings["kilo-code.ghost.generateSuggestions"],
114116
})}
115117
</span>
116-
</ControlledCheckbox>
118+
</VSCodeCheckbox>
117119
<div className="text-vscode-descriptionForeground text-sm mt-1">
118120
<Trans
119121
i18nKey="kilocode:ghost.settings.enableSmartInlineTaskKeybinding.description"

webview-ui/src/components/kilocode/settings/__tests__/GhostServiceSettings.spec.tsx

Lines changed: 41 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -41,11 +41,23 @@ vi.mock("@/utils/vscode", () => ({
4141
},
4242
}))
4343

44-
// Mock ControlledCheckbox
45-
vi.mock("../../common/ControlledCheckbox", () => ({
46-
ControlledCheckbox: ({ children, checked, onChange }: any) => (
44+
// Mock useKeybindings hook
45+
vi.mock("@/hooks/useKeybindings", () => ({
46+
useKeybindings: () => ({
47+
"kilo-code.addToContextAndFocus": "Cmd+K",
48+
"kilo-code.ghost.generateSuggestions": "Cmd+Shift+G",
49+
}),
50+
}))
51+
52+
// Mock VSCodeCheckbox to render as regular HTML checkbox for testing
53+
vi.mock("@vscode/webview-ui-toolkit/react", () => ({
54+
VSCodeCheckbox: ({ checked, onChange, children }: any) => (
4755
<label>
48-
<input type="checkbox" checked={checked} onChange={(e) => onChange(e.target.checked)} />
56+
<input
57+
type="checkbox"
58+
checked={checked}
59+
onChange={(e) => onChange({ target: { checked: e.target.checked } })}
60+
/>
4961
{children}
5062
</label>
5163
),
@@ -83,7 +95,7 @@ const defaultGhostServiceSettings: GhostServiceSettings = {
8395
const renderComponent = (props = {}) => {
8496
const defaultProps = {
8597
ghostServiceSettings: defaultGhostServiceSettings,
86-
setCachedStateField: vi.fn(),
98+
onGhostServiceSettingsChange: vi.fn(),
8799
...props,
88100
}
89101

@@ -119,69 +131,43 @@ describe("GhostServiceSettingsView", () => {
119131
})
120132

121133
it("toggles auto trigger checkbox correctly", () => {
122-
const setCachedStateField = vi.fn()
123-
renderComponent({ setCachedStateField })
134+
const onGhostServiceSettingsChange = vi.fn()
135+
renderComponent({ onGhostServiceSettingsChange })
124136

125-
// Find and click the auto trigger checkbox
126-
const checkbox = screen
127-
.getByText(/kilocode:ghost.settings.enableAutoTrigger.label/)
128-
.closest("label")
129-
?.querySelector("input[type='checkbox']")
130-
131-
if (checkbox) {
132-
fireEvent.click(checkbox)
133-
}
134-
135-
expect(setCachedStateField).toHaveBeenCalledWith(
136-
"ghostServiceSettings",
137-
expect.objectContaining({
138-
enableAutoTrigger: true,
139-
}),
140-
)
137+
const checkboxLabel = screen.getByText(/kilocode:ghost.settings.enableAutoTrigger.label/).closest("label")
138+
const checkbox = checkboxLabel?.querySelector('input[type="checkbox"]') as HTMLInputElement
139+
140+
fireEvent.click(checkbox)
141+
142+
expect(onGhostServiceSettingsChange).toHaveBeenCalledWith("enableAutoTrigger", true)
141143
})
142144

143145
it("toggles quick inline task keybinding checkbox correctly", () => {
144-
const setCachedStateField = vi.fn()
145-
renderComponent({ setCachedStateField })
146+
const onGhostServiceSettingsChange = vi.fn()
147+
renderComponent({ onGhostServiceSettingsChange })
146148

147-
// Find and click the quick inline task keybinding checkbox
148-
const checkbox = screen
149+
const checkboxLabel = screen
149150
.getByText(/kilocode:ghost.settings.enableQuickInlineTaskKeybinding.label/)
150151
.closest("label")
151-
?.querySelector("input[type='checkbox']")
152-
153-
if (checkbox) {
154-
fireEvent.click(checkbox)
155-
}
156-
157-
expect(setCachedStateField).toHaveBeenCalledWith(
158-
"ghostServiceSettings",
159-
expect.objectContaining({
160-
enableQuickInlineTaskKeybinding: true,
161-
}),
162-
)
152+
const checkbox = checkboxLabel?.querySelector('input[type="checkbox"]') as HTMLInputElement
153+
154+
fireEvent.click(checkbox)
155+
156+
expect(onGhostServiceSettingsChange).toHaveBeenCalledWith("enableQuickInlineTaskKeybinding", true)
163157
})
164158

165159
it("toggles smart inline task keybinding checkbox correctly", () => {
166-
const setCachedStateField = vi.fn()
167-
renderComponent({ setCachedStateField })
160+
const onGhostServiceSettingsChange = vi.fn()
161+
renderComponent({ onGhostServiceSettingsChange })
168162

169-
// Find and click the smart inline task keybinding checkbox
170-
const checkbox = screen
163+
const checkboxLabel = screen
171164
.getByText(/kilocode:ghost.settings.enableSmartInlineTaskKeybinding.label/)
172165
.closest("label")
173-
?.querySelector("input[type='checkbox']")
174-
175-
if (checkbox) {
176-
fireEvent.click(checkbox)
177-
}
178-
179-
expect(setCachedStateField).toHaveBeenCalledWith(
180-
"ghostServiceSettings",
181-
expect.objectContaining({
182-
enableSmartInlineTaskKeybinding: true,
183-
}),
184-
)
166+
const checkbox = checkboxLabel?.querySelector('input[type="checkbox"]') as HTMLInputElement
167+
168+
fireEvent.click(checkbox)
169+
170+
expect(onGhostServiceSettingsChange).toHaveBeenCalledWith("enableSmartInlineTaskKeybinding", true)
185171
})
186172

187173
it("renders Trans components with proper structure", () => {

webview-ui/src/components/settings/SettingsView.tsx

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -302,6 +302,32 @@ const SettingsView = forwardRef<SettingsViewRef, SettingsViewProps>(({ onDone, t
302302
})
303303
}, [])
304304

305+
// kilocode_change start
306+
const setGhostServiceSettingsField = useCallback(
307+
<K extends keyof NonNullable<ExtensionStateContextType["ghostServiceSettings"]>>(
308+
field: K,
309+
value: NonNullable<ExtensionStateContextType["ghostServiceSettings"]>[K],
310+
) => {
311+
setCachedState((prevState) => {
312+
const currentSettings = prevState.ghostServiceSettings || {}
313+
if (currentSettings[field] === value) {
314+
return prevState
315+
}
316+
317+
setChangeDetected(true)
318+
return {
319+
...prevState,
320+
ghostServiceSettings: {
321+
...currentSettings,
322+
[field]: value,
323+
},
324+
}
325+
})
326+
},
327+
[],
328+
)
329+
// kilocode_change end
330+
305331
const setApiConfigurationField = useCallback(
306332
<K extends keyof ProviderSettings>(field: K, value: ProviderSettings[K], isUserAction: boolean = true) => {
307333
setCachedState((prevState) => {
@@ -862,7 +888,7 @@ const SettingsView = forwardRef<SettingsViewRef, SettingsViewProps>(({ onDone, t
862888
{activeTab === "ghost" && (
863889
<GhostServiceSettingsView
864890
ghostServiceSettings={ghostServiceSettings}
865-
setCachedStateField={setCachedStateField}
891+
onGhostServiceSettingsChange={setGhostServiceSettingsField}
866892
/>
867893
)}
868894
{/* kilocode_change end display section */}

0 commit comments

Comments
 (0)