|
@@ -5,11 +5,12 @@ import { validateApiConfiguration, validateModelId } from "../../utils/validate"
|
|
|
import { vscode } from "../../utils/vscode"
|
|
import { vscode } from "../../utils/vscode"
|
|
|
import ApiOptions from "./ApiOptions"
|
|
import ApiOptions from "./ApiOptions"
|
|
|
import ExperimentalFeature from "./ExperimentalFeature"
|
|
import ExperimentalFeature from "./ExperimentalFeature"
|
|
|
-import { EXPERIMENT_IDS, experimentConfigsMap } from "../../../../src/shared/experiments"
|
|
|
|
|
|
|
+import { EXPERIMENT_IDS, experimentConfigsMap, ExperimentId } from "../../../../src/shared/experiments"
|
|
|
import ApiConfigManager from "./ApiConfigManager"
|
|
import ApiConfigManager from "./ApiConfigManager"
|
|
|
import { Dropdown } from "vscrui"
|
|
import { Dropdown } from "vscrui"
|
|
|
import type { DropdownOption } from "vscrui"
|
|
import type { DropdownOption } from "vscrui"
|
|
|
import { ApiConfiguration } from "../../../../src/shared/api"
|
|
import { ApiConfiguration } from "../../../../src/shared/api"
|
|
|
|
|
+import ConfirmDialog from "../ui/comfirm-dialog"
|
|
|
|
|
|
|
|
type SettingsViewProps = {
|
|
type SettingsViewProps = {
|
|
|
onDone: () => void
|
|
onDone: () => void
|
|
@@ -21,6 +22,7 @@ const SettingsView = ({ onDone }: SettingsViewProps) => {
|
|
|
const [modelIdErrorMessage, setModelIdErrorMessage] = useState<string | undefined>(undefined)
|
|
const [modelIdErrorMessage, setModelIdErrorMessage] = useState<string | undefined>(undefined)
|
|
|
const [commandInput, setCommandInput] = useState("")
|
|
const [commandInput, setCommandInput] = useState("")
|
|
|
const prevApiConfigName = useRef(extensionState.currentApiConfigName)
|
|
const prevApiConfigName = useRef(extensionState.currentApiConfigName)
|
|
|
|
|
+ const [isDiscardDialogShow, setDiscardDialogShow] = useState(false)
|
|
|
|
|
|
|
|
// TODO: Reduce WebviewMessage/ExtensionState complexity
|
|
// TODO: Reduce WebviewMessage/ExtensionState complexity
|
|
|
const [cachedState, setCachedState] = useState(extensionState)
|
|
const [cachedState, setCachedState] = useState(extensionState)
|
|
@@ -67,7 +69,7 @@ const SettingsView = ({ onDone }: SettingsViewProps) => {
|
|
|
}, [currentApiConfigName, extensionState, isChangeDetected])
|
|
}, [currentApiConfigName, extensionState, isChangeDetected])
|
|
|
|
|
|
|
|
const setCachedStateField = useCallback(
|
|
const setCachedStateField = useCallback(
|
|
|
- <K extends keyof ExtensionStateContextType>(field: K, value: ExtensionStateContextType[K]) =>
|
|
|
|
|
|
|
+ <K extends keyof ExtensionStateContextType>(field: K, value: ExtensionStateContextType[K]) => {
|
|
|
setCachedState((prevState) => {
|
|
setCachedState((prevState) => {
|
|
|
if (prevState[field] === value) {
|
|
if (prevState[field] === value) {
|
|
|
return prevState
|
|
return prevState
|
|
@@ -77,7 +79,8 @@ const SettingsView = ({ onDone }: SettingsViewProps) => {
|
|
|
...prevState,
|
|
...prevState,
|
|
|
[field]: value,
|
|
[field]: value,
|
|
|
}
|
|
}
|
|
|
- }),
|
|
|
|
|
|
|
+ })
|
|
|
|
|
+ },
|
|
|
[],
|
|
[],
|
|
|
)
|
|
)
|
|
|
|
|
|
|
@@ -91,20 +94,27 @@ const SettingsView = ({ onDone }: SettingsViewProps) => {
|
|
|
return {
|
|
return {
|
|
|
...prevState,
|
|
...prevState,
|
|
|
apiConfiguration: {
|
|
apiConfiguration: {
|
|
|
- ...apiConfiguration,
|
|
|
|
|
|
|
+ ...prevState.apiConfiguration,
|
|
|
[field]: value,
|
|
[field]: value,
|
|
|
},
|
|
},
|
|
|
}
|
|
}
|
|
|
})
|
|
})
|
|
|
},
|
|
},
|
|
|
- [apiConfiguration],
|
|
|
|
|
|
|
+ [],
|
|
|
)
|
|
)
|
|
|
|
|
|
|
|
- const setExperimentEnabled = useCallback(
|
|
|
|
|
- (id: string, enabled: boolean) =>
|
|
|
|
|
- setCachedStateField("experiments", { ...cachedState.experiments, [id]: enabled }),
|
|
|
|
|
- [cachedState.experiments, setCachedStateField],
|
|
|
|
|
- )
|
|
|
|
|
|
|
+ const setExperimentEnabled = useCallback((id: ExperimentId, enabled: boolean) => {
|
|
|
|
|
+ setCachedState((prevState) => {
|
|
|
|
|
+ if (prevState.experiments?.[id] === enabled) {
|
|
|
|
|
+ return prevState
|
|
|
|
|
+ }
|
|
|
|
|
+ setChangeDetected(true)
|
|
|
|
|
+ return {
|
|
|
|
|
+ ...prevState,
|
|
|
|
|
+ experiments: { ...prevState.experiments, [id]: enabled },
|
|
|
|
|
+ }
|
|
|
|
|
+ })
|
|
|
|
|
+ }, [])
|
|
|
|
|
|
|
|
const handleSubmit = () => {
|
|
const handleSubmit = () => {
|
|
|
const apiValidationResult = validateApiConfiguration(apiConfiguration)
|
|
const apiValidationResult = validateApiConfiguration(apiConfiguration)
|
|
@@ -171,6 +181,24 @@ const SettingsView = ({ onDone }: SettingsViewProps) => {
|
|
|
setModelIdErrorMessage(modelIdValidationResult)
|
|
setModelIdErrorMessage(modelIdValidationResult)
|
|
|
}, [apiConfiguration, extensionState.glamaModels, extensionState.openRouterModels])
|
|
}, [apiConfiguration, extensionState.glamaModels, extensionState.openRouterModels])
|
|
|
|
|
|
|
|
|
|
+ const confirmDialogHandler = useRef<() => void>()
|
|
|
|
|
+ const onConfirmDialogResult = useCallback((confirm: boolean) => {
|
|
|
|
|
+ if (confirm) {
|
|
|
|
|
+ confirmDialogHandler.current?.()
|
|
|
|
|
+ }
|
|
|
|
|
+ }, [])
|
|
|
|
|
+ const checkUnsaveChanges = useCallback(
|
|
|
|
|
+ (then: () => void) => {
|
|
|
|
|
+ if (isChangeDetected) {
|
|
|
|
|
+ confirmDialogHandler.current = then
|
|
|
|
|
+ setDiscardDialogShow(true)
|
|
|
|
|
+ } else {
|
|
|
|
|
+ then()
|
|
|
|
|
+ }
|
|
|
|
|
+ },
|
|
|
|
|
+ [isChangeDetected],
|
|
|
|
|
+ )
|
|
|
|
|
+
|
|
|
const handleResetState = () => {
|
|
const handleResetState = () => {
|
|
|
vscode.postMessage({ type: "resetState" })
|
|
vscode.postMessage({ type: "resetState" })
|
|
|
}
|
|
}
|
|
@@ -215,6 +243,14 @@ const SettingsView = ({ onDone }: SettingsViewProps) => {
|
|
|
flexDirection: "column",
|
|
flexDirection: "column",
|
|
|
overflow: "hidden",
|
|
overflow: "hidden",
|
|
|
}}>
|
|
}}>
|
|
|
|
|
+ <ConfirmDialog
|
|
|
|
|
+ icon="codicon-warning"
|
|
|
|
|
+ title="Unsaved changes"
|
|
|
|
|
+ message="Do you want to discard changes and continue?"
|
|
|
|
|
+ show={isDiscardDialogShow}
|
|
|
|
|
+ onResult={onConfirmDialogResult}
|
|
|
|
|
+ onClose={() => setDiscardDialogShow(false)}
|
|
|
|
|
+ aria-labelledby="unsave-warning-dialog"></ConfirmDialog>
|
|
|
<div
|
|
<div
|
|
|
style={{
|
|
style={{
|
|
|
display: "flex",
|
|
display: "flex",
|
|
@@ -240,7 +276,7 @@ const SettingsView = ({ onDone }: SettingsViewProps) => {
|
|
|
<VSCodeButton
|
|
<VSCodeButton
|
|
|
appearance="secondary"
|
|
appearance="secondary"
|
|
|
title="Discard unsaved changes and close settings panel"
|
|
title="Discard unsaved changes and close settings panel"
|
|
|
- onClick={onDone}>
|
|
|
|
|
|
|
+ onClick={() => checkUnsaveChanges(onDone)}>
|
|
|
Done
|
|
Done
|
|
|
</VSCodeButton>
|
|
</VSCodeButton>
|
|
|
</div>
|
|
</div>
|
|
@@ -254,9 +290,11 @@ const SettingsView = ({ onDone }: SettingsViewProps) => {
|
|
|
currentApiConfigName={currentApiConfigName}
|
|
currentApiConfigName={currentApiConfigName}
|
|
|
listApiConfigMeta={extensionState.listApiConfigMeta}
|
|
listApiConfigMeta={extensionState.listApiConfigMeta}
|
|
|
onSelectConfig={(configName: string) => {
|
|
onSelectConfig={(configName: string) => {
|
|
|
- vscode.postMessage({
|
|
|
|
|
- type: "loadApiConfiguration",
|
|
|
|
|
- text: configName,
|
|
|
|
|
|
|
+ checkUnsaveChanges(() => {
|
|
|
|
|
+ vscode.postMessage({
|
|
|
|
|
+ type: "loadApiConfiguration",
|
|
|
|
|
+ text: configName,
|
|
|
|
|
+ })
|
|
|
})
|
|
})
|
|
|
}}
|
|
}}
|
|
|
onDeleteConfig={(configName: string) => {
|
|
onDeleteConfig={(configName: string) => {
|