mirror of
https://github.com/pacnpal/Roo-Code.git
synced 2025-12-20 04:11:10 -05:00
Make fuzzy diff matching configurable (and default to off)
This commit is contained in:
5
.changeset/early-pigs-carry.md
Normal file
5
.changeset/early-pigs-carry.md
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
---
|
||||||
|
"roo-cline": patch
|
||||||
|
---
|
||||||
|
|
||||||
|
Make fuzzy diff matching configurable (and default to off)
|
||||||
@@ -67,6 +67,7 @@ export class Cline {
|
|||||||
private didEditFile: boolean = false
|
private didEditFile: boolean = false
|
||||||
customInstructions?: string
|
customInstructions?: string
|
||||||
diffStrategy?: DiffStrategy
|
diffStrategy?: DiffStrategy
|
||||||
|
diffEnabled: boolean = false
|
||||||
|
|
||||||
apiConversationHistory: Anthropic.MessageParam[] = []
|
apiConversationHistory: Anthropic.MessageParam[] = []
|
||||||
clineMessages: ClineMessage[] = []
|
clineMessages: ClineMessage[] = []
|
||||||
@@ -97,10 +98,11 @@ export class Cline {
|
|||||||
provider: ClineProvider,
|
provider: ClineProvider,
|
||||||
apiConfiguration: ApiConfiguration,
|
apiConfiguration: ApiConfiguration,
|
||||||
customInstructions?: string,
|
customInstructions?: string,
|
||||||
diffEnabled?: boolean,
|
enableDiff?: boolean,
|
||||||
task?: string,
|
fuzzyMatchThreshold?: number,
|
||||||
images?: string[],
|
task?: string | undefined,
|
||||||
historyItem?: HistoryItem,
|
images?: string[] | undefined,
|
||||||
|
historyItem?: HistoryItem | undefined,
|
||||||
) {
|
) {
|
||||||
this.providerRef = new WeakRef(provider)
|
this.providerRef = new WeakRef(provider)
|
||||||
this.api = buildApiHandler(apiConfiguration)
|
this.api = buildApiHandler(apiConfiguration)
|
||||||
@@ -109,8 +111,9 @@ export class Cline {
|
|||||||
this.browserSession = new BrowserSession(provider.context)
|
this.browserSession = new BrowserSession(provider.context)
|
||||||
this.diffViewProvider = new DiffViewProvider(cwd)
|
this.diffViewProvider = new DiffViewProvider(cwd)
|
||||||
this.customInstructions = customInstructions
|
this.customInstructions = customInstructions
|
||||||
if (diffEnabled && this.api.getModel().id) {
|
this.diffEnabled = enableDiff ?? false
|
||||||
this.diffStrategy = getDiffStrategy(this.api.getModel().id)
|
if (this.diffEnabled && this.api.getModel().id) {
|
||||||
|
this.diffStrategy = getDiffStrategy(this.api.getModel().id, fuzzyMatchThreshold ?? 1.0)
|
||||||
}
|
}
|
||||||
if (historyItem) {
|
if (historyItem) {
|
||||||
this.taskId = historyItem.id
|
this.taskId = historyItem.id
|
||||||
|
|||||||
@@ -248,7 +248,7 @@ describe('Cline', () => {
|
|||||||
// Setup mock API configuration
|
// Setup mock API configuration
|
||||||
mockApiConfig = {
|
mockApiConfig = {
|
||||||
apiProvider: 'anthropic',
|
apiProvider: 'anthropic',
|
||||||
apiModelId: 'claude-3-sonnet'
|
apiModelId: 'claude-3-5-sonnet-20241022'
|
||||||
};
|
};
|
||||||
|
|
||||||
// Mock provider methods
|
// Mock provider methods
|
||||||
@@ -278,20 +278,77 @@ describe('Cline', () => {
|
|||||||
mockProvider,
|
mockProvider,
|
||||||
mockApiConfig,
|
mockApiConfig,
|
||||||
'custom instructions',
|
'custom instructions',
|
||||||
false, // diffEnabled
|
false,
|
||||||
'test task', // task
|
0.95, // 95% threshold
|
||||||
undefined, // images
|
'test task'
|
||||||
undefined // historyItem
|
|
||||||
);
|
);
|
||||||
|
|
||||||
expect(cline.customInstructions).toBe('custom instructions');
|
expect(cline.customInstructions).toBe('custom instructions');
|
||||||
|
expect(cline.diffEnabled).toBe(false);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should use default fuzzy match threshold when not provided', () => {
|
||||||
|
const cline = new Cline(
|
||||||
|
mockProvider,
|
||||||
|
mockApiConfig,
|
||||||
|
'custom instructions',
|
||||||
|
true,
|
||||||
|
undefined,
|
||||||
|
'test task'
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(cline.diffEnabled).toBe(true);
|
||||||
|
// The diff strategy should be created with default threshold (1.0)
|
||||||
|
expect(cline.diffStrategy).toBeDefined();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should use provided fuzzy match threshold', () => {
|
||||||
|
const getDiffStrategySpy = jest.spyOn(require('../diff/DiffStrategy'), 'getDiffStrategy');
|
||||||
|
|
||||||
|
const cline = new Cline(
|
||||||
|
mockProvider,
|
||||||
|
mockApiConfig,
|
||||||
|
'custom instructions',
|
||||||
|
true,
|
||||||
|
0.9, // 90% threshold
|
||||||
|
'test task'
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(cline.diffEnabled).toBe(true);
|
||||||
|
expect(cline.diffStrategy).toBeDefined();
|
||||||
|
expect(getDiffStrategySpy).toHaveBeenCalledWith('claude-3-5-sonnet-20241022', 0.9);
|
||||||
|
|
||||||
|
getDiffStrategySpy.mockRestore();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should pass default threshold to diff strategy when not provided', () => {
|
||||||
|
const getDiffStrategySpy = jest.spyOn(require('../diff/DiffStrategy'), 'getDiffStrategy');
|
||||||
|
|
||||||
|
const cline = new Cline(
|
||||||
|
mockProvider,
|
||||||
|
mockApiConfig,
|
||||||
|
'custom instructions',
|
||||||
|
true,
|
||||||
|
undefined,
|
||||||
|
'test task'
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(cline.diffEnabled).toBe(true);
|
||||||
|
expect(cline.diffStrategy).toBeDefined();
|
||||||
|
expect(getDiffStrategySpy).toHaveBeenCalledWith('claude-3-5-sonnet-20241022', 1.0);
|
||||||
|
|
||||||
|
getDiffStrategySpy.mockRestore();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should require either task or historyItem', () => {
|
it('should require either task or historyItem', () => {
|
||||||
expect(() => {
|
expect(() => {
|
||||||
new Cline(
|
new Cline(
|
||||||
mockProvider,
|
mockProvider,
|
||||||
mockApiConfig
|
mockApiConfig,
|
||||||
|
undefined, // customInstructions
|
||||||
|
false, // diffEnabled
|
||||||
|
undefined, // fuzzyMatchThreshold
|
||||||
|
undefined // task
|
||||||
);
|
);
|
||||||
}).toThrow('Either historyItem or task/images must be provided');
|
}).toThrow('Either historyItem or task/images must be provided');
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -6,10 +6,10 @@ import { SearchReplaceDiffStrategy } from './strategies/search-replace'
|
|||||||
* @param model The name of the model being used (e.g., 'gpt-4', 'claude-3-opus')
|
* @param model The name of the model being used (e.g., 'gpt-4', 'claude-3-opus')
|
||||||
* @returns The appropriate diff strategy for the model
|
* @returns The appropriate diff strategy for the model
|
||||||
*/
|
*/
|
||||||
export function getDiffStrategy(model: string): DiffStrategy {
|
export function getDiffStrategy(model: string, fuzzyMatchThreshold?: number): DiffStrategy {
|
||||||
// For now, return SearchReplaceDiffStrategy for all models (with a fuzzy threshold of 0.9)
|
// For now, return SearchReplaceDiffStrategy for all models
|
||||||
// This architecture allows for future optimizations based on model capabilities
|
// This architecture allows for future optimizations based on model capabilities
|
||||||
return new SearchReplaceDiffStrategy(0.9)
|
return new SearchReplaceDiffStrategy(fuzzyMatchThreshold ?? 1.0)
|
||||||
}
|
}
|
||||||
|
|
||||||
export type { DiffStrategy }
|
export type { DiffStrategy }
|
||||||
|
|||||||
@@ -58,7 +58,9 @@ export class SearchReplaceDiffStrategy implements DiffStrategy {
|
|||||||
private bufferLines: number;
|
private bufferLines: number;
|
||||||
|
|
||||||
constructor(fuzzyThreshold?: number, bufferLines?: number) {
|
constructor(fuzzyThreshold?: number, bufferLines?: number) {
|
||||||
// Default to exact matching (1.0) unless fuzzy threshold specified
|
// Use provided threshold or default to exact matching (1.0)
|
||||||
|
// Note: fuzzyThreshold is inverted in UI (0% = 1.0, 10% = 0.9)
|
||||||
|
// so we use it directly here
|
||||||
this.fuzzyThreshold = fuzzyThreshold ?? 1.0;
|
this.fuzzyThreshold = fuzzyThreshold ?? 1.0;
|
||||||
this.bufferLines = bufferLines ?? BUFFER_LINES;
|
this.bufferLines = bufferLines ?? BUFFER_LINES;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -70,6 +70,7 @@ type GlobalStateKey =
|
|||||||
| "diffEnabled"
|
| "diffEnabled"
|
||||||
| "alwaysAllowMcp"
|
| "alwaysAllowMcp"
|
||||||
| "browserLargeViewport"
|
| "browserLargeViewport"
|
||||||
|
| "fuzzyMatchThreshold"
|
||||||
|
|
||||||
export const GlobalFileNames = {
|
export const GlobalFileNames = {
|
||||||
apiConversationHistory: "api_conversation_history.json",
|
apiConversationHistory: "api_conversation_history.json",
|
||||||
@@ -217,7 +218,8 @@ export class ClineProvider implements vscode.WebviewViewProvider {
|
|||||||
const {
|
const {
|
||||||
apiConfiguration,
|
apiConfiguration,
|
||||||
customInstructions,
|
customInstructions,
|
||||||
diffEnabled
|
diffEnabled,
|
||||||
|
fuzzyMatchThreshold
|
||||||
} = await this.getState()
|
} = await this.getState()
|
||||||
|
|
||||||
this.cline = new Cline(
|
this.cline = new Cline(
|
||||||
@@ -225,6 +227,7 @@ export class ClineProvider implements vscode.WebviewViewProvider {
|
|||||||
apiConfiguration,
|
apiConfiguration,
|
||||||
customInstructions,
|
customInstructions,
|
||||||
diffEnabled,
|
diffEnabled,
|
||||||
|
fuzzyMatchThreshold,
|
||||||
task,
|
task,
|
||||||
images
|
images
|
||||||
)
|
)
|
||||||
@@ -235,7 +238,8 @@ export class ClineProvider implements vscode.WebviewViewProvider {
|
|||||||
const {
|
const {
|
||||||
apiConfiguration,
|
apiConfiguration,
|
||||||
customInstructions,
|
customInstructions,
|
||||||
diffEnabled
|
diffEnabled,
|
||||||
|
fuzzyMatchThreshold
|
||||||
} = await this.getState()
|
} = await this.getState()
|
||||||
|
|
||||||
this.cline = new Cline(
|
this.cline = new Cline(
|
||||||
@@ -243,6 +247,7 @@ export class ClineProvider implements vscode.WebviewViewProvider {
|
|||||||
apiConfiguration,
|
apiConfiguration,
|
||||||
customInstructions,
|
customInstructions,
|
||||||
diffEnabled,
|
diffEnabled,
|
||||||
|
fuzzyMatchThreshold,
|
||||||
undefined,
|
undefined,
|
||||||
undefined,
|
undefined,
|
||||||
historyItem
|
historyItem
|
||||||
@@ -613,6 +618,10 @@ export class ClineProvider implements vscode.WebviewViewProvider {
|
|||||||
await this.updateGlobalState("browserLargeViewport", browserLargeViewport)
|
await this.updateGlobalState("browserLargeViewport", browserLargeViewport)
|
||||||
await this.postStateToWebview()
|
await this.postStateToWebview()
|
||||||
break
|
break
|
||||||
|
case "fuzzyMatchThreshold":
|
||||||
|
await this.updateGlobalState("fuzzyMatchThreshold", message.value)
|
||||||
|
await this.postStateToWebview()
|
||||||
|
break
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
null,
|
null,
|
||||||
@@ -1062,6 +1071,7 @@ export class ClineProvider implements vscode.WebviewViewProvider {
|
|||||||
diffEnabled,
|
diffEnabled,
|
||||||
soundVolume,
|
soundVolume,
|
||||||
browserLargeViewport,
|
browserLargeViewport,
|
||||||
|
fuzzyMatchThreshold,
|
||||||
] = await Promise.all([
|
] = await Promise.all([
|
||||||
this.getGlobalState("apiProvider") as Promise<ApiProvider | undefined>,
|
this.getGlobalState("apiProvider") as Promise<ApiProvider | undefined>,
|
||||||
this.getGlobalState("apiModelId") as Promise<string | undefined>,
|
this.getGlobalState("apiModelId") as Promise<string | undefined>,
|
||||||
@@ -1101,6 +1111,7 @@ export class ClineProvider implements vscode.WebviewViewProvider {
|
|||||||
this.getGlobalState("diffEnabled") as Promise<boolean | undefined>,
|
this.getGlobalState("diffEnabled") as Promise<boolean | undefined>,
|
||||||
this.getGlobalState("soundVolume") as Promise<number | undefined>,
|
this.getGlobalState("soundVolume") as Promise<number | undefined>,
|
||||||
this.getGlobalState("browserLargeViewport") as Promise<boolean | undefined>,
|
this.getGlobalState("browserLargeViewport") as Promise<boolean | undefined>,
|
||||||
|
this.getGlobalState("fuzzyMatchThreshold") as Promise<number | undefined>,
|
||||||
])
|
])
|
||||||
|
|
||||||
let apiProvider: ApiProvider
|
let apiProvider: ApiProvider
|
||||||
@@ -1158,6 +1169,7 @@ export class ClineProvider implements vscode.WebviewViewProvider {
|
|||||||
diffEnabled: diffEnabled ?? false,
|
diffEnabled: diffEnabled ?? false,
|
||||||
soundVolume,
|
soundVolume,
|
||||||
browserLargeViewport: browserLargeViewport ?? false,
|
browserLargeViewport: browserLargeViewport ?? false,
|
||||||
|
fuzzyMatchThreshold: fuzzyMatchThreshold ?? 1.0,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -54,6 +54,7 @@ export interface ExtensionState {
|
|||||||
soundVolume?: number
|
soundVolume?: number
|
||||||
diffEnabled?: boolean
|
diffEnabled?: boolean
|
||||||
browserLargeViewport?: boolean
|
browserLargeViewport?: boolean
|
||||||
|
fuzzyMatchThreshold?: number
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface ClineMessage {
|
export interface ClineMessage {
|
||||||
|
|||||||
@@ -39,6 +39,7 @@ export interface WebviewMessage {
|
|||||||
| "restartMcpServer"
|
| "restartMcpServer"
|
||||||
| "toggleToolAlwaysAllow"
|
| "toggleToolAlwaysAllow"
|
||||||
| "toggleMcpServer"
|
| "toggleMcpServer"
|
||||||
|
| "fuzzyMatchThreshold"
|
||||||
text?: string
|
text?: string
|
||||||
disabled?: boolean
|
disabled?: boolean
|
||||||
askResponse?: ClineAskResponse
|
askResponse?: ClineAskResponse
|
||||||
|
|||||||
@@ -33,16 +33,17 @@ const SettingsView = ({ onDone }: SettingsViewProps) => {
|
|||||||
setSoundVolume,
|
setSoundVolume,
|
||||||
diffEnabled,
|
diffEnabled,
|
||||||
setDiffEnabled,
|
setDiffEnabled,
|
||||||
browserLargeViewport = false,
|
browserLargeViewport,
|
||||||
setBrowserLargeViewport,
|
setBrowserLargeViewport,
|
||||||
openRouterModels,
|
openRouterModels,
|
||||||
setAllowedCommands,
|
setAllowedCommands,
|
||||||
allowedCommands,
|
allowedCommands,
|
||||||
|
fuzzyMatchThreshold,
|
||||||
|
setFuzzyMatchThreshold,
|
||||||
} = useExtensionState()
|
} = useExtensionState()
|
||||||
const [apiErrorMessage, setApiErrorMessage] = useState<string | undefined>(undefined)
|
const [apiErrorMessage, setApiErrorMessage] = useState<string | undefined>(undefined)
|
||||||
const [modelIdErrorMessage, setModelIdErrorMessage] = useState<string | undefined>(undefined)
|
const [modelIdErrorMessage, setModelIdErrorMessage] = useState<string | undefined>(undefined)
|
||||||
const [commandInput, setCommandInput] = useState("")
|
const [commandInput, setCommandInput] = useState("")
|
||||||
|
|
||||||
const handleSubmit = () => {
|
const handleSubmit = () => {
|
||||||
const apiValidationResult = validateApiConfiguration(apiConfiguration)
|
const apiValidationResult = validateApiConfiguration(apiConfiguration)
|
||||||
const modelIdValidationResult = validateModelId(apiConfiguration, openRouterModels)
|
const modelIdValidationResult = validateModelId(apiConfiguration, openRouterModels)
|
||||||
@@ -65,6 +66,7 @@ const SettingsView = ({ onDone }: SettingsViewProps) => {
|
|||||||
vscode.postMessage({ type: "soundVolume", value: soundVolume })
|
vscode.postMessage({ type: "soundVolume", value: soundVolume })
|
||||||
vscode.postMessage({ type: "diffEnabled", bool: diffEnabled })
|
vscode.postMessage({ type: "diffEnabled", bool: diffEnabled })
|
||||||
vscode.postMessage({ type: "browserLargeViewport", bool: browserLargeViewport })
|
vscode.postMessage({ type: "browserLargeViewport", bool: browserLargeViewport })
|
||||||
|
vscode.postMessage({ type: "fuzzyMatchThreshold", value: fuzzyMatchThreshold ?? 1.0 })
|
||||||
onDone()
|
onDone()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -166,6 +168,35 @@ const SettingsView = ({ onDone }: SettingsViewProps) => {
|
|||||||
}}>
|
}}>
|
||||||
When enabled, Cline will be able to edit files more quickly and will automatically reject truncated full-file writes. Works best with the latest Claude 3.5 Sonnet model.
|
When enabled, Cline will be able to edit files more quickly and will automatically reject truncated full-file writes. Works best with the latest Claude 3.5 Sonnet model.
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
|
{diffEnabled && (
|
||||||
|
<div style={{ marginTop: 10 }}>
|
||||||
|
<div style={{ display: 'flex', alignItems: 'center', gap: '5px' }}>
|
||||||
|
<span style={{ fontWeight: "500", minWidth: '100px' }}>Match precision</span>
|
||||||
|
<input
|
||||||
|
type="range"
|
||||||
|
min="0.9"
|
||||||
|
max="1"
|
||||||
|
step="0.005"
|
||||||
|
value={fuzzyMatchThreshold ?? 1.0}
|
||||||
|
onChange={(e) => {
|
||||||
|
setFuzzyMatchThreshold(parseFloat(e.target.value));
|
||||||
|
}}
|
||||||
|
style={{
|
||||||
|
flexGrow: 1,
|
||||||
|
accentColor: 'var(--vscode-button-background)',
|
||||||
|
height: '2px'
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
<span style={{ minWidth: '35px', textAlign: 'left' }}>
|
||||||
|
{Math.round((fuzzyMatchThreshold || 1) * 100)}%
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
<p style={{ fontSize: "12px", marginBottom: 10, color: "var(--vscode-descriptionForeground)" }}>
|
||||||
|
This slider controls how precisely code sections must match when applying diffs. Lower values allow more flexible matching but increase the risk of incorrect replacements. Use values below 100% with extreme caution.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div style={{ marginBottom: 5 }}>
|
<div style={{ marginBottom: 5 }}>
|
||||||
@@ -351,7 +382,7 @@ const SettingsView = ({ onDone }: SettingsViewProps) => {
|
|||||||
{soundEnabled && (
|
{soundEnabled && (
|
||||||
<div style={{ marginLeft: 0 }}>
|
<div style={{ marginLeft: 0 }}>
|
||||||
<div style={{ display: 'flex', alignItems: 'center', gap: '5px' }}>
|
<div style={{ display: 'flex', alignItems: 'center', gap: '5px' }}>
|
||||||
<span style={{ fontWeight: "500", minWidth: '50px' }}>Volume</span>
|
<span style={{ fontWeight: "500", minWidth: '100px' }}>Volume</span>
|
||||||
<input
|
<input
|
||||||
type="range"
|
type="range"
|
||||||
min="0"
|
min="0"
|
||||||
|
|||||||
@@ -32,6 +32,7 @@ export interface ExtensionStateContextType extends ExtensionState {
|
|||||||
setSoundVolume: (value: number) => void
|
setSoundVolume: (value: number) => void
|
||||||
setDiffEnabled: (value: boolean) => void
|
setDiffEnabled: (value: boolean) => void
|
||||||
setBrowserLargeViewport: (value: boolean) => void
|
setBrowserLargeViewport: (value: boolean) => void
|
||||||
|
setFuzzyMatchThreshold: (value: number) => void
|
||||||
}
|
}
|
||||||
|
|
||||||
const ExtensionStateContext = createContext<ExtensionStateContextType | undefined>(undefined)
|
const ExtensionStateContext = createContext<ExtensionStateContextType | undefined>(undefined)
|
||||||
@@ -46,6 +47,7 @@ export const ExtensionStateContextProvider: React.FC<{ children: React.ReactNode
|
|||||||
soundEnabled: false,
|
soundEnabled: false,
|
||||||
soundVolume: 0.5,
|
soundVolume: 0.5,
|
||||||
diffEnabled: false,
|
diffEnabled: false,
|
||||||
|
fuzzyMatchThreshold: 1.0,
|
||||||
})
|
})
|
||||||
const [didHydrateState, setDidHydrateState] = useState(false)
|
const [didHydrateState, setDidHydrateState] = useState(false)
|
||||||
const [showWelcome, setShowWelcome] = useState(false)
|
const [showWelcome, setShowWelcome] = useState(false)
|
||||||
@@ -133,6 +135,7 @@ export const ExtensionStateContextProvider: React.FC<{ children: React.ReactNode
|
|||||||
mcpServers,
|
mcpServers,
|
||||||
filePaths,
|
filePaths,
|
||||||
soundVolume: state.soundVolume,
|
soundVolume: state.soundVolume,
|
||||||
|
fuzzyMatchThreshold: state.fuzzyMatchThreshold,
|
||||||
setApiConfiguration: (value) => setState((prevState) => ({
|
setApiConfiguration: (value) => setState((prevState) => ({
|
||||||
...prevState,
|
...prevState,
|
||||||
apiConfiguration: value
|
apiConfiguration: value
|
||||||
@@ -149,6 +152,7 @@ export const ExtensionStateContextProvider: React.FC<{ children: React.ReactNode
|
|||||||
setSoundVolume: (value) => setState((prevState) => ({ ...prevState, soundVolume: value })),
|
setSoundVolume: (value) => setState((prevState) => ({ ...prevState, soundVolume: value })),
|
||||||
setDiffEnabled: (value) => setState((prevState) => ({ ...prevState, diffEnabled: value })),
|
setDiffEnabled: (value) => setState((prevState) => ({ ...prevState, diffEnabled: value })),
|
||||||
setBrowserLargeViewport: (value) => setState((prevState) => ({ ...prevState, browserLargeViewport: value })),
|
setBrowserLargeViewport: (value) => setState((prevState) => ({ ...prevState, browserLargeViewport: value })),
|
||||||
|
setFuzzyMatchThreshold: (value) => setState((prevState) => ({ ...prevState, fuzzyMatchThreshold: value })),
|
||||||
}
|
}
|
||||||
|
|
||||||
return <ExtensionStateContext.Provider value={contextValue}>{children}</ExtensionStateContext.Provider>
|
return <ExtensionStateContext.Provider value={contextValue}>{children}</ExtensionStateContext.Provider>
|
||||||
|
|||||||
Reference in New Issue
Block a user