mirror of
https://github.com/enricoros/big-AGI.git
synced 2026-05-11 06:00:15 -07:00
102 lines
3.8 KiB
TypeScript
102 lines
3.8 KiB
TypeScript
import * as React from 'react';
|
|
|
|
import { Box, Button, Checkbox, IconButton, ListItem, Sheet, Typography, useTheme } from '@mui/joy';
|
|
import ClearIcon from '@mui/icons-material/Clear';
|
|
import DeleteOutlineIcon from '@mui/icons-material/DeleteOutline';
|
|
|
|
import { DMessage } from '@/lib/stores/store-chats';
|
|
import { TokenBadge } from '@/components/util/TokenBadge';
|
|
import { makeAvatar, messageBackground } from '@/components/ChatMessage';
|
|
|
|
|
|
/**
|
|
* Header bar for controlling the operations during the Selection mode
|
|
*/
|
|
export const MessagesSelectionHeader = (props: { hasSelected: boolean, isBottom: boolean, onClose: () => void, onSelectAll: (selected: boolean) => void, onDeleteMessages: () => void }) =>
|
|
<Sheet color='neutral' variant='solid' invertedColors sx={{
|
|
display: 'flex', flexDirection: 'row', alignItems: 'center',
|
|
gap: { xs: 1, sm: 2 }, px: { xs: 1, md: 2 }, py: 1,
|
|
}}>
|
|
<Checkbox size='md' onChange={event => props.onSelectAll(event.target.checked)} sx={{ minWidth: 24, justifyContent: 'center' }} />
|
|
|
|
<Box>Select All</Box>
|
|
|
|
<Button variant='solid' disabled={!props.hasSelected} onClick={props.onDeleteMessages} sx={{ ml: 'auto', mr: 'auto', minWidth: 150 }} endDecorator={<DeleteOutlineIcon />}>
|
|
Delete
|
|
</Button>
|
|
|
|
<IconButton variant='plain' onClick={props.onClose}>
|
|
<ClearIcon />
|
|
</IconButton>
|
|
</Sheet>;
|
|
|
|
|
|
/**
|
|
* Small representation of a ChatMessage, used when in selection mode
|
|
*
|
|
* Shall look similarly to the main ChatMessage, for consistency, but just allow a simple checkbox selection
|
|
*/
|
|
export function ChatMessageSelectable(props: { message: DMessage, isBottom: boolean, selected: boolean, onToggleSelected: (messageId: string, selected: boolean) => void }) {
|
|
// external state
|
|
const theme = useTheme();
|
|
|
|
const {
|
|
id: messageId,
|
|
text: messageText,
|
|
sender: messageSender,
|
|
avatar: messageAvatar,
|
|
typing: messageTyping,
|
|
role: messageRole,
|
|
purposeId: messagePurposeId,
|
|
// originLLM: messageModelId,
|
|
tokenCount: messageTokenCount,
|
|
updated: messageUpdated,
|
|
} = props.message;
|
|
|
|
const fromAssistant = messageRole === 'assistant';
|
|
|
|
const isAssistantError = fromAssistant && (messageText.startsWith('[Issue] ') || messageText.startsWith('[OpenAI Issue]'));
|
|
|
|
const background = messageBackground(theme, messageRole, !!messageUpdated, isAssistantError);
|
|
|
|
const avatarEl: JSX.Element | null = React.useMemo(() =>
|
|
makeAvatar(messageAvatar, messageRole, messagePurposeId, messageSender, messageTyping, 'sm'),
|
|
[messageAvatar, messagePurposeId, messageRole, messageSender, messageTyping],
|
|
);
|
|
|
|
const handleCheckedChange = (event: React.ChangeEvent<HTMLInputElement>) => props.onToggleSelected(messageId, event.target.checked);
|
|
|
|
return (
|
|
<ListItem sx={{
|
|
display: 'flex', flexDirection: !fromAssistant ? 'row' : 'row', alignItems: 'center',
|
|
gap: { xs: 1, sm: 2 }, px: { xs: 1, md: 2 }, py: 2,
|
|
background,
|
|
borderBottom: `1px solid ${theme.vars.palette.divider}`,
|
|
// position: 'relative',
|
|
...(props.isBottom && { mb: 'auto' }),
|
|
'&:hover > button': { opacity: 1 },
|
|
}}>
|
|
|
|
<Box sx={{ display: 'flex', minWidth: 24, justifyContent: 'center' }}>
|
|
<Checkbox size='md' checked={props.selected} onChange={handleCheckedChange} />
|
|
</Box>
|
|
|
|
<Box sx={{ display: 'flex', minWidth: { xs: 40, sm: 48 }, justifyContent: 'center' }}>
|
|
{avatarEl}
|
|
</Box>
|
|
|
|
<Typography level='body2' sx={{ minWidth: 64 }}>
|
|
{messageRole}
|
|
</Typography>
|
|
|
|
<Box sx={{ display: 'flex', minWidth: { xs: 32, sm: 45 }, justifyContent: 'flex-end' }}>
|
|
<TokenBadge directTokens={messageTokenCount} tokenLimit={12345} inline />
|
|
</Box>
|
|
|
|
<Typography level='body1' sx={{ flexGrow: 1, textOverflow: 'ellipsis', overflow: 'hidden', whiteSpace: 'nowrap' }}>
|
|
{messageText}
|
|
</Typography>
|
|
|
|
</ListItem>
|
|
);
|
|
} |