Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add two columns Settings layout #592

Merged
merged 10 commits into from
Apr 23, 2024
2 changes: 1 addition & 1 deletion src/Chat/ChatBase.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ import { WebHandler } from "../lib/WebHandler";
import { ChatCraftCommandRegistry } from "../lib/commands";
import ChatHeader from "./ChatHeader";
import { FreeModelProvider } from "../lib/providers/DefaultProvider/FreeModelProvider";
import PreferencesModal from "../components/PreferencesModal";
import PreferencesModal from "../components/Preferences/PreferencesModal";

type ChatBaseProps = {
chat: ChatCraftChat;
Expand Down
96 changes: 0 additions & 96 deletions src/components/DefaultSystemPromptModal.tsx

This file was deleted.

26 changes: 1 addition & 25 deletions src/components/Header.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -25,11 +25,9 @@ import { TbSearch } from "react-icons/tb";
import { FiRss } from "react-icons/fi";
import { Form } from "react-router-dom";

import PreferencesModal from "./PreferencesModal";
import DefaultSystemPromptModal from "./DefaultSystemPromptModal";
import PreferencesModal from "./Preferences/PreferencesModal";
import { useUser } from "../hooks/use-user";
import useMobileBreakpoint from "../hooks/use-mobile-breakpoint";
import WebHandlersConfigModal from "./WebHandlersConfigModal";
import { useAlert } from "../hooks/use-alert";

type HeaderProps = {
Expand All @@ -46,16 +44,6 @@ function Header({ chatId, inputPromptRef, searchText, onToggleSidebar }: HeaderP
onOpen: onPrefModalOpen,
onClose: onPrefModalClose,
} = useDisclosure();
const {
isOpen: isWebHandlersModalOpen,
onOpen: onWebHandlersModalOpen,
onClose: onWebHandlersModalClose,
} = useDisclosure();
const {
isOpen: isSysPromptModalOpen,
onOpen: onSysPromptModalOpen,
onClose: onSysPromptModalClose,
} = useDisclosure();
const { user, login, logout } = useUser();
const { error } = useAlert();

Expand Down Expand Up @@ -179,8 +167,6 @@ function Header({ chatId, inputPromptRef, searchText, onToggleSidebar }: HeaderP
/>
<MenuList>
<MenuItem onClick={onPrefModalOpen}>Settings...</MenuItem>
<MenuItem onClick={onWebHandlersModalOpen}>Web Handlers</MenuItem>
<MenuItem onClick={onSysPromptModalOpen}>Default System Prompt...</MenuItem>
{user ? (
<MenuItem
onClick={() => {
Expand Down Expand Up @@ -230,16 +216,6 @@ function Header({ chatId, inputPromptRef, searchText, onToggleSidebar }: HeaderP
onClose={onPrefModalClose}
finalFocusRef={inputPromptRef}
/>
<WebHandlersConfigModal
isOpen={isWebHandlersModalOpen}
onClose={onWebHandlersModalClose}
finalFocusRef={inputPromptRef}
/>
<DefaultSystemPromptModal
isOpen={isSysPromptModalOpen}
onClose={onSysPromptModalClose}
finalFocusRef={inputPromptRef}
/>
</Flex>
);
}
Expand Down
137 changes: 137 additions & 0 deletions src/components/Preferences/CustomizationSettings.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,137 @@
import {
FormControl,
FormLabel,
Stack,
Slider,
SliderTrack,
SliderFilledTrack,
SliderThumb,
FormErrorMessage,
FormHelperText,
Kbd,
RadioGroup,
Radio,
Checkbox,
Box,
VStack,
} from "@chakra-ui/react";
import { isMac } from "../../lib/utils";
import { useSettings } from "../../hooks/use-settings";

function CustomizationSettings() {
const { settings, setSettings } = useSettings();

return (
<VStack gap={6} my={3}>
<FormControl>
<FormLabel>
When writing a prompt, press <Kbd>Enter</Kbd> to...
</FormLabel>
<RadioGroup
value={settings.enterBehaviour}
onChange={(nextValue) =>
setSettings({ ...settings, enterBehaviour: nextValue as EnterBehaviour })
}
>
<Stack>
<Radio value="send">Send the message</Radio>
<Radio value="newline">
Start a new line (use {isMac() ? <Kbd>Command ⌘</Kbd> : <Kbd>Ctrl</Kbd>} +
<Kbd>Enter</Kbd> to send)
</Radio>
</Stack>
</RadioGroup>
</FormControl>

<FormControl>
<Checkbox
isChecked={settings.countTokens}
onChange={(e) => setSettings({ ...settings, countTokens: e.target.checked })}
>
Track and Display Token Count and Cost
</Checkbox>
</FormControl>

<FormControl as="fieldset">
<FormLabel as="legend">Image Compression</FormLabel>
<Stack>
<Box px="6">
<FormControl>
<FormLabel>
Maximum file size after compression: {settings.maxCompressedFileSizeMB} (MB)
</FormLabel>
<Slider
id="max-compressed-file-size"
value={settings.maxCompressedFileSizeMB}
onChange={(value) => setSettings({ ...settings, maxCompressedFileSizeMB: value })}
min={1}
max={20}
step={1}
>
<SliderTrack>
<SliderFilledTrack />
</SliderTrack>
<SliderThumb />
</Slider>
<FormErrorMessage>Maximum file size must be between 1 and 20 MB.</FormErrorMessage>
<FormHelperText>
After compression, each attached image will be under your chosen maximum file size
(1-20 MB).
</FormHelperText>
</FormControl>
</Box>
<Box px="6">
<FormControl>
<FormLabel>Maximum image dimension: {settings.maxImageDimension} (px)</FormLabel>
<Slider
id="max-image-dimension"
value={settings.maxImageDimension}
onChange={(value) => setSettings({ ...settings, maxImageDimension: value })}
min={16}
max={2048}
step={16}
>
<SliderTrack>
<SliderFilledTrack />
</SliderTrack>
<SliderThumb />
</Slider>
<FormErrorMessage>
Maximum Image dimension must be between 16 and 2048
</FormErrorMessage>
<FormHelperText>
Your compressed image&apos;s maximum width or height will be within the dimension
you choose (16-2048 pixels).
</FormHelperText>
</FormControl>
</Box>
<Box px="6">
<FormControl>
<FormLabel>Compression factor: {settings.compressionFactor}</FormLabel>
<Slider
id="compression-factor"
value={settings.compressionFactor}
onChange={(value) => setSettings({ ...settings, compressionFactor: value })}
min={0.1}
max={1}
step={0.1}
>
<SliderTrack>
<SliderFilledTrack />
</SliderTrack>
<SliderThumb />
</Slider>
<FormErrorMessage>Compression factor must be between 0.1 and 1.0</FormErrorMessage>
<FormHelperText>
Set the maximum file size based on the original size multiplied by the factor you
choose (0.1-1.0).
</FormHelperText>
</FormControl>
</Box>
</Stack>
</FormControl>
</VStack>
);
}

export default CustomizationSettings;
74 changes: 74 additions & 0 deletions src/components/Preferences/DefaultSystemPrompt.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
import { useState } from "react";
import {
Button,
Flex,
FormControl,
VStack,
Text,
Textarea,
Tooltip,
Heading,
} from "@chakra-ui/react";
import debounce from "lodash-es/debounce";

import { useSettings } from "../../hooks/use-settings";
import { defaultSystemPrompt } from "../../lib/system-prompt";

function DefaultSystemPrompt() {
const [prompt, setPrompt] = useState(defaultSystemPrompt());
const { settings, setSettings } = useSettings();

// Update the default prompt, but not on every keystroke
const handleSave = debounce((value: string) => {
setSettings({ ...settings, customSystemPrompt: value });
}, 250);

// When the prompt changes, update state, and trigger a save for later
const handleUpdate = (value: string) => {
setPrompt(value);
handleSave(value);
};

// Reset the default system prompt back to the app's default
const handleReset = () => {
setSettings({ ...settings, customSystemPrompt: undefined });
setPrompt(defaultSystemPrompt());
};

return (
<VStack gap={4} my={3}>
<Text>
The default system prompt is used as the first message in every chat. It provides the LLM
important context, behavioral cues, and expectations about responses and desired response
formats.
</Text>

<Text as="em" fontSize="sm">
NOTE: changes to the default system prompt will take effect in new chats, but won&apos;t
affect existing ones.
</Text>

<Heading size={"md"} width={"100%"} fontWeight={"normal"}>
Default System Prompt
</Heading>
<FormControl>
<Textarea
autoFocus
variant="filled"
rows={16}
value={prompt}
onChange={(e) => handleUpdate(e.target.value)}
/>
</FormControl>
<Flex w="100%" justifyContent="flex-end">
<Tooltip hasArrow placement="left" label="Reset to the default ChatCraft system prompt">
<Button size="sm" colorScheme="red" onClick={() => handleReset()}>
Reset
</Button>
</Tooltip>
</Flex>
</VStack>
);
}

export default DefaultSystemPrompt;
Loading
Loading