import * as React from 'react'; import { Badge, IconButton, ListDivider, ListItem, ListItemDecorator, Menu, MenuItem, Option, Select, Sheet, Stack, Switch, Typography, useColorScheme } from '@mui/joy'; import { SxProps } from '@mui/joy/styles/types'; import AddIcon from '@mui/icons-material/Add'; import DarkModeIcon from '@mui/icons-material/DarkMode'; import DeleteOutlineIcon from '@mui/icons-material/DeleteOutline'; import ExitToAppIcon from '@mui/icons-material/ExitToApp'; import KeyboardArrowDownIcon from '@mui/icons-material/KeyboardArrowDown'; import LunchDiningIcon from '@mui/icons-material/LunchDining'; import MenuIcon from '@mui/icons-material/Menu'; import MoreVertIcon from '@mui/icons-material/MoreVert'; import SettingsOutlinedIcon from '@mui/icons-material/SettingsOutlined'; import SettingsSuggestIcon from '@mui/icons-material/SettingsSuggest'; import SwapVertIcon from '@mui/icons-material/SwapVert'; import WidthFullIcon from '@mui/icons-material/WidthFull'; import WidthWideIcon from '@mui/icons-material/WidthWide'; import { ChatModelId, ChatModels, SystemPurposeId, SystemPurposes } from '@/lib/data'; import { Link } from '@/components/util/Link'; import { foolsMode } from '@/lib/theme'; import { useActiveConfiguration, useChatStore, useConversationNames } from '@/lib/store-chats'; import { useSettingsStore } from '@/lib/store-settings'; /** * A Select component that blends-in nicely (cleaner, easier to the eyes) */ function Dropdown(props: { value: TValue, items: Record, onChange: (event: any, value: TValue | null) => void, sx?: SxProps }) { return ( ); } /** * FIXME - TEMPORARY - placeholder for a proper Pages Drawer */ function PagesMenu(props: { pagesMenuAnchor: HTMLElement | null, onClose: () => void, onClearConversation: (e: React.MouseEvent, conversationId: string) => void }) { // external state const setActiveConversation = useChatStore(state => state.setActiveConversationId); const conversationNames: { id: string; name: string, systemPurposeId: SystemPurposeId }[] = useConversationNames(); const handleConversationClicked = (conversationId: string) => setActiveConversation(conversationId); return Active chats {conversationNames.map((conversation) => ( handleConversationClicked(conversation.id)} > {SystemPurposes[conversation.systemPurposeId]?.symbol || ''} {conversation.name} props.onClearConversation(e, conversation.id)}> ))} New chat (soon) {/* We need stable Chat and Message IDs, and one final review to the data structure of Conversation for future-proofing */} Scratchpad Feature #17 ; } /** * The top bar of the application, with the model and purpose selection, and menu/settings icons */ export function ApplicationBar({ onClearConversation, onExportConversation, onShowSettings, sx }: { onClearConversation: (conversationId: (string | null)) => void; onExportConversation: (conversationId: (string | null)) => void; onShowSettings: () => void; sx?: SxProps }) { // state const [pagesMenuAnchor, setPagesMenuAnchor] = React.useState(null); const [actionsMenuAnchor, setActionsMenuAnchor] = React.useState(null); // external state const { mode: colorMode, setMode: setColorMode } = useColorScheme(); const { freeScroll, setFreeScroll, setShowSystemMessages, setWideMode, showSystemMessages, wideMode } = useSettingsStore(); const { chatModelId, setChatModelId, setSystemPurposeId, systemPurposeId } = useActiveConfiguration(); const handleChatModelChange = (event: any, value: ChatModelId | null) => value && setChatModelId(value); const handleSystemPurposeChange = (event: any, value: SystemPurposeId | null) => value && setSystemPurposeId(value); const closePagesMenu = () => setPagesMenuAnchor(null); const closeActionsMenu = () => setActionsMenuAnchor(null); const handleDarkModeToggle = () => setColorMode(colorMode === 'dark' ? 'light' : 'dark'); const handleWideModeToggle = () => setWideMode(!wideMode); const handleScrollModeToggle = () => setFreeScroll(!freeScroll); const handleSystemMessagesToggle = () => setShowSystemMessages(!showSystemMessages); const handleActionShowSettings = (e: React.MouseEvent) => { e.stopPropagation(); onShowSettings(); closeActionsMenu(); }; const handleActionExportChat = (e: React.MouseEvent) => { e.stopPropagation(); onExportConversation(null); }; const handleActionClearConversation = (e: React.MouseEvent, id: string | null) => { e.stopPropagation(); onClearConversation(id || null); }; return <> {/* Top Bar with 2 icons and Model/Purpose selectors */} setPagesMenuAnchor(event.currentTarget)}> {foolsMode ? : } setActionsMenuAnchor(event.currentTarget)}> {/* Left menu */} {} {/* Right menu */} Dark {wideMode ? : } Wide System text Free scroll Settings Share via paste.gg handleActionClearConversation(e, null)}> Clear conversation ; }