import * as React from 'react';
import { shallow } from 'zustand/shallow';
import { Box, Button, FormControl, FormHelperText, FormLabel, IconButton, Input, Modal, ModalClose, ModalDialog, Slider, Stack, Switch, Typography } from '@mui/joy';
import KeyIcon from '@mui/icons-material/Key';
import KeyboardArrowDownIcon from '@mui/icons-material/KeyboardArrowDown';
import KeyboardArrowUpIcon from '@mui/icons-material/KeyboardArrowUp';
import { Link } from '@/components/util/Link';
import { useSettingsStore } from '@/lib/store-settings';
export const isValidOpenAIApiKey = (apiKey?: string) =>
!!apiKey && apiKey.startsWith('sk-') && apiKey.length > 40;
function Section(props: { title?: string; collapsible?: boolean, collapsed?: boolean, disclaimer?: string, children: React.ReactNode }) {
const [collapsed, setCollapsed] = React.useState(props.collapsed ?? false);
return <>
{!!props.title && (
{props.title}
)}
{!!props.collapsible && (
setCollapsed(!collapsed)}>
{!collapsed ? : }
)}
{!collapsed &&
{props.children}
}
{!!props.disclaimer && (
{props.disclaimer}
)}
>;
}
/**
* Component that allows the User to modify the application settings,
* persisted on the client via localStorage.
*
* @param {boolean} open Whether the Settings modal is open
* @param {() => void} onClose Call this to close the dialog from outside
*/
export function SettingsModal({ open, onClose }: { open: boolean, onClose: () => void; }) {
// external state
const { renderMarkdown, setRenderMarkdown, apiKey, setApiKey, modelTemperature, setModelTemperature, modelMaxResponseTokens, setModelMaxResponseTokens, modelApiHost, setModelApiHost } = useSettingsStore(state => ({
renderMarkdown: state.renderMarkdown, setRenderMarkdown: state.setRenderMarkdown,
apiKey: state.apiKey, setApiKey: state.setApiKey,
modelTemperature: state.modelTemperature, setModelTemperature: state.setModelTemperature,
modelMaxResponseTokens: state.modelMaxResponseTokens, setModelMaxResponseTokens: state.setModelMaxResponseTokens,
modelApiHost: state.modelApiHost, setModelApiHost: state.setModelApiHost,
}), shallow);
const handleApiKeyChange = (e: React.ChangeEvent) =>
setApiKey((e.target as HTMLInputElement).value);
const handleApiKeyDown = (e: React.KeyboardEvent) =>
(e.key === 'Enter') && onClose();
const handleTemperatureChange = (event: Event, newValue: number | number[]) => setModelTemperature(newValue as number);
const handleMaxTokensChange = (event: Event, newValue: number | number[]) => setModelMaxResponseTokens(newValue as number);
const handleModelApiHostChange = (e: React.ChangeEvent) => setModelApiHost((e.target as HTMLInputElement).value);
const handleRenderMarkdownChange = (event: React.ChangeEvent) => setRenderMarkdown(event.target.checked);
const needsApiKey = !!process.env.REQUIRE_USER_API_KEYS;
const isValidKey = isValidOpenAIApiKey(apiKey);
return (
Settings
Markdown
{renderMarkdown ? 'Best looks' : 'Raw text'}
{/* Advanced Settings */}
);
}