Skip to content

Commit 243a034

Browse files
committed
fix(settings): move FCO toggle to Experimental, adopt debounced action hook, clean up UISettings and SettingsView imports/tests; fix lint unused args in FilesChangedOverview
1 parent c39b916 commit 243a034

File tree

6 files changed

+79
-222
lines changed

6 files changed

+79
-222
lines changed

webview-ui/src/components/file-changes/FilesChangedOverview.tsx

Lines changed: 6 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,7 @@ import { FileChangeset, FileChange } from "@roo-code/types"
33
import { useTranslation } from "react-i18next"
44
import { useExtensionState } from "@/context/ExtensionStateContext"
55
import { vscode } from "@/utils/vscode"
6-
7-
// eslint-disable-next-line @typescript-eslint/no-empty-object-type
8-
interface FilesChangedOverviewProps {}
6+
import { useDebouncedAction } from "@/components/ui/hooks/useDebouncedAction"
97

108
interface _CheckpointEventData {
119
type: "checkpoint_created" | "checkpoint_restored"
@@ -18,7 +16,7 @@ interface _CheckpointEventData {
1816
* and displays file changes. It manages its own state and communicates with the backend
1917
* through VS Code message passing.
2018
*/
21-
const FilesChangedOverview: React.FC<FilesChangedOverviewProps> = () => {
19+
const FilesChangedOverview: React.FC = () => {
2220
const { t } = useTranslation()
2321
const { filesChangedEnabled } = useExtensionState()
2422

@@ -52,24 +50,13 @@ const FilesChangedOverview: React.FC<FilesChangedOverviewProps> = () => {
5250
const totalHeight = shouldVirtualize ? files.length * ITEM_HEIGHT : "auto"
5351
const offsetY = shouldVirtualize ? Math.floor(scrollTop / ITEM_HEIGHT) * ITEM_HEIGHT : 0
5452

55-
// Simple double-click prevention
56-
const [isProcessing, setIsProcessing] = React.useState(false)
57-
const timeoutRef = React.useRef<NodeJS.Timeout | null>(null)
58-
59-
// Cleanup timeout on unmount
60-
React.useEffect(() => {
61-
return () => {
62-
if (timeoutRef.current) {
63-
clearTimeout(timeoutRef.current)
64-
}
65-
}
66-
}, [])
53+
// Debounced click handling for double-click prevention
54+
const { isProcessing, handleWithDebounce } = useDebouncedAction(300)
6755

6856
// FCO initialization logic
6957
const checkInit = React.useCallback(
70-
(baseCheckpoint: string) => {
58+
(_baseCheckpoint: string) => {
7159
if (!isInitialized) {
72-
console.log("[FCO] Initializing with base checkpoint:", baseCheckpoint)
7360
setIsInitialized(true)
7461
}
7562
},
@@ -94,9 +81,7 @@ const FilesChangedOverview: React.FC<FilesChangedOverviewProps> = () => {
9481
)
9582

9683
// Handle checkpoint restoration with the 4 examples logic
97-
const handleCheckpointRestored = React.useCallback((restoredCheckpoint: string) => {
98-
console.log("[FCO] Handling checkpoint restore to:", restoredCheckpoint)
99-
84+
const handleCheckpointRestored = React.useCallback((_restoredCheckpoint: string) => {
10085
// Request file changes after checkpoint restore
10186
// Backend should calculate changes from initial baseline to restored checkpoint
10287
vscode.postMessage({ type: "filesChangedRequest" })
@@ -128,25 +113,6 @@ const FilesChangedOverview: React.FC<FilesChangedOverviewProps> = () => {
128113
// Backend will send updated filesChanged message with filtered results
129114
}, [files])
130115

131-
const handleWithDebounce = React.useCallback(
132-
async (operation: () => void) => {
133-
if (isProcessing) return
134-
setIsProcessing(true)
135-
try {
136-
operation()
137-
} catch (_error) {
138-
// Silently handle any errors to prevent crashing
139-
// Debug logging removed for production
140-
}
141-
// Brief delay to prevent double-clicks
142-
if (timeoutRef.current) {
143-
clearTimeout(timeoutRef.current)
144-
}
145-
timeoutRef.current = setTimeout(() => setIsProcessing(false), 300)
146-
},
147-
[isProcessing],
148-
)
149-
150116
/**
151117
* Handles scroll events for virtualization
152118
* Updates scrollTop state to calculate visible items
@@ -167,14 +133,12 @@ const FilesChangedOverview: React.FC<FilesChangedOverviewProps> = () => {
167133

168134
// Guard against null/undefined/malformed messages
169135
if (!message || typeof message !== "object" || !message.type) {
170-
console.debug("[FCO] Ignoring malformed message:", message)
171136
return
172137
}
173138

174139
switch (message.type) {
175140
case "filesChanged":
176141
if (message.filesChanged) {
177-
console.log("[FCO] Received filesChanged message:", message.filesChanged)
178142
checkInit(message.filesChanged.baseCheckpoint)
179143
updateChangeset(message.filesChanged)
180144
} else {
@@ -183,11 +147,9 @@ const FilesChangedOverview: React.FC<FilesChangedOverviewProps> = () => {
183147
}
184148
break
185149
case "checkpoint_created":
186-
console.log("[FCO] Checkpoint created:", message.checkpoint)
187150
handleCheckpointCreated(message.checkpoint, message.previousCheckpoint)
188151
break
189152
case "checkpoint_restored":
190-
console.log("[FCO] Checkpoint restored:", message.checkpoint)
191153
handleCheckpointRestored(message.checkpoint)
192154
break
193155
}

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

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,19 +8,25 @@ import { EXPERIMENT_IDS, experimentConfigsMap } from "@roo/experiments"
88
import { useAppTranslation } from "@src/i18n/TranslationContext"
99
import { cn } from "@src/lib/utils"
1010

11-
import { SetExperimentEnabled } from "./types"
11+
import { SetExperimentEnabled, SetCachedStateField } from "./types"
1212
import { SectionHeader } from "./SectionHeader"
1313
import { Section } from "./Section"
1414
import { ExperimentalFeature } from "./ExperimentalFeature"
15+
import { VSCodeCheckbox } from "@vscode/webview-ui-toolkit/react"
1516

1617
type ExperimentalSettingsProps = HTMLAttributes<HTMLDivElement> & {
1718
experiments: Experiments
1819
setExperimentEnabled: SetExperimentEnabled
20+
// Include Files Changed Overview toggle in Experimental section per review feedback
21+
filesChangedEnabled?: boolean
22+
setCachedStateField?: SetCachedStateField<"filesChangedEnabled">
1923
}
2024

2125
export const ExperimentalSettings = ({
2226
experiments,
2327
setExperimentEnabled,
28+
filesChangedEnabled,
29+
setCachedStateField,
2430
className,
2531
...props
2632
}: ExperimentalSettingsProps) => {
@@ -35,6 +41,24 @@ export const ExperimentalSettings = ({
3541
</div>
3642
</SectionHeader>
3743

44+
{/* Files Changed Overview (moved from UI section to Experimental) */}
45+
{typeof filesChangedEnabled !== "undefined" && setCachedStateField && (
46+
<Section>
47+
<div>
48+
<VSCodeCheckbox
49+
checked={filesChangedEnabled}
50+
onChange={(e: any) => setCachedStateField("filesChangedEnabled", e.target.checked)}
51+
data-testid="files-changed-enabled-checkbox">
52+
{/* Reuse existing translation keys to avoid i18n churn */}
53+
<label className="block font-medium mb-1">{t("settings:ui.filesChanged.label")}</label>
54+
</VSCodeCheckbox>
55+
<div className="text-vscode-descriptionForeground text-sm mt-1 mb-3">
56+
{t("settings:ui.filesChanged.description")}
57+
</div>
58+
</div>
59+
</Section>
60+
)}
61+
3862
<Section>
3963
{Object.entries(experimentConfigsMap)
4064
.filter(([key]) => key in EXPERIMENT_IDS)

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

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -50,8 +50,9 @@ import {
5050
} from "@src/components/ui"
5151

5252
import { Tab, TabContent, TabHeader, TabList, TabTrigger } from "../common/Tab"
53-
import { SetCachedStateField, SetExperimentEnabled } from "./types"
53+
import { SetExperimentEnabled } from "./types"
5454
import { SectionHeader } from "./SectionHeader"
55+
import type { SetCachedStateField } from "./types"
5556
import ApiConfigManager from "./ApiConfigManager"
5657
import ApiOptions from "./ApiOptions"
5758
import { AutoApproveSettings } from "./AutoApproveSettings"
@@ -693,12 +694,7 @@ const SettingsView = forwardRef<SettingsViewRef, SettingsViewProps>(({ onDone, t
693694
)}
694695

695696
{/* UI Section */}
696-
{activeTab === "ui" && (
697-
<UISettings
698-
filesChangedEnabled={filesChangedEnabled}
699-
setCachedStateField={setCachedStateField}
700-
/>
701-
)}
697+
{activeTab === "ui" && <UISettings />}
702698

703699
{/* Terminal Section */}
704700
{activeTab === "terminal" && (
@@ -732,7 +728,12 @@ const SettingsView = forwardRef<SettingsViewRef, SettingsViewProps>(({ onDone, t
732728

733729
{/* Experimental Section */}
734730
{activeTab === "experimental" && (
735-
<ExperimentalSettings setExperimentEnabled={setExperimentEnabled} experiments={experiments} />
731+
<ExperimentalSettings
732+
setExperimentEnabled={setExperimentEnabled}
733+
experiments={experiments}
734+
filesChangedEnabled={filesChangedEnabled}
735+
setCachedStateField={setCachedStateField as SetCachedStateField<"filesChangedEnabled">}
736+
/>
736737
)}
737738

738739
{/* Language Section */}
Lines changed: 2 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,15 @@
11
import { HTMLAttributes } from "react"
22
import React from "react"
33
import { useAppTranslation } from "@/i18n/TranslationContext"
4-
import { VSCodeCheckbox } from "@vscode/webview-ui-toolkit/react"
54
import { Monitor } from "lucide-react"
65

76
import { cn } from "@/lib/utils"
87

9-
import { SetCachedStateField } from "./types"
108
import { SectionHeader } from "./SectionHeader"
11-
import { Section } from "./Section"
129

13-
type UISettingsProps = HTMLAttributes<HTMLDivElement> & {
14-
filesChangedEnabled?: boolean
15-
setCachedStateField: SetCachedStateField<"filesChangedEnabled">
16-
}
10+
type UISettingsProps = HTMLAttributes<HTMLDivElement>
1711

18-
export const UISettings = ({ filesChangedEnabled, setCachedStateField, className, ...props }: UISettingsProps) => {
12+
export const UISettings = ({ className, ...props }: UISettingsProps) => {
1913
const { t } = useAppTranslation()
2014

2115
return (
@@ -26,20 +20,6 @@ export const UISettings = ({ filesChangedEnabled, setCachedStateField, className
2620
<div>{t("settings:sections.ui")}</div>
2721
</div>
2822
</SectionHeader>
29-
30-
<Section>
31-
<div>
32-
<VSCodeCheckbox
33-
checked={filesChangedEnabled}
34-
onChange={(e: any) => setCachedStateField("filesChangedEnabled", e.target.checked)}
35-
data-testid="files-changed-enabled-checkbox">
36-
<label className="block font-medium mb-1">{t("settings:ui.filesChanged.label")}</label>
37-
</VSCodeCheckbox>
38-
<div className="text-vscode-descriptionForeground text-sm mt-1 mb-3">
39-
{t("settings:ui.filesChanged.description")}
40-
</div>
41-
</div>
42-
</Section>
4323
</div>
4424
)
4525
}

0 commit comments

Comments
 (0)