SettingsView.tsx 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138
  1. import { ApiConfiguration } from "@shared/api"
  2. import { VSCodeButton, VSCodeDivider, VSCodeLink, VSCodeTextField } from "@vscode/webview-ui-toolkit/react"
  3. import React, { useEffect, useState } from "react"
  4. import { validateApiConfiguration, validateMaxRequestsPerTask } from "../utils/validate"
  5. import { vscode } from "../utils/vscode"
  6. import ApiOptions from "./ApiOptions"
  7. type SettingsViewProps = {
  8. apiConfiguration?: ApiConfiguration
  9. setApiConfiguration: React.Dispatch<React.SetStateAction<ApiConfiguration | undefined>>
  10. maxRequestsPerTask: string
  11. setMaxRequestsPerTask: React.Dispatch<React.SetStateAction<string>>
  12. onDone: () => void
  13. }
  14. const SettingsView = ({
  15. apiConfiguration,
  16. setApiConfiguration,
  17. maxRequestsPerTask,
  18. setMaxRequestsPerTask,
  19. onDone,
  20. }: SettingsViewProps) => {
  21. const [apiErrorMessage, setApiErrorMessage] = useState<string | undefined>(undefined)
  22. const [maxRequestsErrorMessage, setMaxRequestsErrorMessage] = useState<string | undefined>(undefined)
  23. const handleSubmit = () => {
  24. const apiValidationResult = validateApiConfiguration(apiConfiguration)
  25. const maxRequestsValidationResult = validateMaxRequestsPerTask(maxRequestsPerTask)
  26. setApiErrorMessage(apiValidationResult)
  27. setMaxRequestsErrorMessage(maxRequestsValidationResult)
  28. if (!apiValidationResult && !maxRequestsValidationResult) {
  29. vscode.postMessage({ type: "apiConfiguration", apiConfiguration })
  30. vscode.postMessage({ type: "maxRequestsPerTask", text: maxRequestsPerTask })
  31. onDone()
  32. }
  33. }
  34. useEffect(() => {
  35. setApiErrorMessage(undefined)
  36. }, [apiConfiguration])
  37. useEffect(() => {
  38. setMaxRequestsErrorMessage(undefined)
  39. }, [maxRequestsPerTask])
  40. // validate as soon as the component is mounted
  41. /*
  42. useEffect will use stale values of variables if they are not included in the dependency array. so trying to use useEffect with a dependency array of only one value for example will use any other variables' old values. In most cases you don't want this, and should opt to use react-use hooks.
  43. useEffect(() => {
  44. // uses someVar and anotherVar
  45. // eslint-disable-next-line react-hooks/exhaustive-deps
  46. }, [someVar])
  47. If we only want to run code once on mount we can use react-use's useEffectOnce or useMount
  48. */
  49. return (
  50. <div style={{ margin: "0 auto", paddingTop: "10px" }}>
  51. <div
  52. style={{
  53. display: "flex",
  54. justifyContent: "space-between",
  55. alignItems: "center",
  56. marginBottom: "17px",
  57. }}>
  58. <h3 style={{ color: "var(--vscode-foreground)", margin: 0 }}>Settings</h3>
  59. <VSCodeButton onClick={handleSubmit}>Done</VSCodeButton>
  60. </div>
  61. <div style={{ marginBottom: 5 }}>
  62. <ApiOptions apiConfiguration={apiConfiguration} setApiConfiguration={setApiConfiguration} />
  63. {apiErrorMessage && (
  64. <p
  65. style={{
  66. margin: "-5px 0 12px 0",
  67. fontSize: "12px",
  68. color: "var(--vscode-errorForeground)",
  69. }}>
  70. {apiErrorMessage}
  71. </p>
  72. )}
  73. </div>
  74. <div style={{ marginBottom: "20px" }}>
  75. <VSCodeTextField
  76. value={maxRequestsPerTask}
  77. style={{ width: "100%" }}
  78. placeholder="20"
  79. onInput={(e: any) => setMaxRequestsPerTask(e.target?.value)}>
  80. <span style={{ fontWeight: "500" }}>Maximum # Requests Per Task</span>
  81. </VSCodeTextField>
  82. <p
  83. style={{
  84. fontSize: "12px",
  85. marginTop: "5px",
  86. color: "var(--vscode-descriptionForeground)",
  87. }}>
  88. If Claude Dev reaches this limit, it will pause and ask for your permission before making additional
  89. requests.
  90. </p>
  91. {maxRequestsErrorMessage && (
  92. <p
  93. style={{
  94. fontSize: "12px",
  95. marginTop: "5px",
  96. color: "var(--vscode-errorForeground)",
  97. }}>
  98. {maxRequestsErrorMessage}
  99. </p>
  100. )}
  101. </div>
  102. <VSCodeDivider />
  103. <div
  104. style={{
  105. marginTop: "20px",
  106. textAlign: "center",
  107. color: "var(--vscode-descriptionForeground)",
  108. fontSize: "12px",
  109. lineHeight: "1.2",
  110. }}>
  111. <p style={{ wordWrap: "break-word" }}>
  112. If you have any questions or feedback, feel free to open an issue at{" "}
  113. <VSCodeLink href="https://github.com/saoudrizwan/claude-dev" style={{ display: "inline" }}>
  114. https://github.com/saoudrizwan/claude-dev
  115. </VSCodeLink>
  116. </p>
  117. <p style={{ fontStyle: "italic" }}>v1.0.98</p>
  118. </div>
  119. </div>
  120. )
  121. }
  122. export default SettingsView