mirror of
https://github.com/enricoros/big-AGI.git
synced 2026-05-11 14:10:15 -07:00
bits
This commit is contained in:
@@ -474,14 +474,15 @@ export function ChatMessage(props: {
|
||||
{/* [aside A] Editing: Apply */}
|
||||
{isEditingText && (
|
||||
<Box sx={messageAsideColumnSx}>
|
||||
{/*<Typography level='body-xs'> </Typography>*/}
|
||||
<Tooltip arrow disableInteractive title='Apply Edits'>
|
||||
<IconButton variant='solid' color='warning' onClick={handleEditsApply}>
|
||||
<IconButton size='sm' variant='solid' color='warning' onClick={handleEditsApply} sx={{ mt: 0.25 }}>
|
||||
<CheckRoundedIcon />
|
||||
</IconButton>
|
||||
</Tooltip>
|
||||
{/*<Typography level='body-xs' sx={{ overflowWrap: 'anywhere' }}>*/}
|
||||
{/* Save*/}
|
||||
{/*</Typography>*/}
|
||||
<Typography level='body-xs' sx={{ overflowWrap: 'anywhere', mt: 0.25 }}>
|
||||
Done
|
||||
</Typography>
|
||||
</Box>
|
||||
)}
|
||||
|
||||
@@ -583,11 +584,8 @@ export function ChatMessage(props: {
|
||||
|
||||
{/* If editing and there's no content, have a button to create a new TextContentFragment */}
|
||||
{isEditingText && !contentFragments.length && (
|
||||
<Button variant='plain' color='neutral' onClick={handleFragmentNew} sx={{
|
||||
ml: fromAssistant ? undefined : 'auto',
|
||||
mr: fromAssistant ? 'auto' : undefined,
|
||||
}}>
|
||||
Add text
|
||||
<Button variant='plain' color='neutral' onClick={handleFragmentNew} sx={{ justifyContent: 'flex-start' }}>
|
||||
add text ...
|
||||
</Button>
|
||||
)}
|
||||
|
||||
@@ -618,14 +616,15 @@ export function ChatMessage(props: {
|
||||
{/* Editing: Cancel */}
|
||||
{isEditingText && (
|
||||
<Box sx={messageAsideColumnSx}>
|
||||
{/*<Typography level='body-xs'> </Typography>*/}
|
||||
<Tooltip arrow disableInteractive title='Discard Edits'>
|
||||
<IconButton onClick={handleEditsCancel}>
|
||||
<IconButton size='md' onClick={handleEditsCancel}>
|
||||
<CloseRoundedIcon />
|
||||
</IconButton>
|
||||
</Tooltip>
|
||||
{/*<Typography level='body-xs' sx={{ overflowWrap: 'anywhere' }}>*/}
|
||||
{/* Close*/}
|
||||
{/*</Typography>*/}
|
||||
<Typography level='body-xs' sx={{ overflowWrap: 'anywhere' }}>
|
||||
Cancel
|
||||
</Typography>
|
||||
</Box>
|
||||
)}
|
||||
|
||||
|
||||
+3
-3
@@ -13,7 +13,7 @@ import type { DMessageRole } from '~/common/stores/chat/chat.message';
|
||||
import { createTextAttachmentFragment, DMessageAttachmentFragment, DMessageFragmentId } from '~/common/stores/chat/chat.fragments';
|
||||
import { marshallWrapText } from '~/common/stores/chat/chat.tokens';
|
||||
|
||||
import { ContentPartTextEdit } from '../fragments-content/ContentPartTextEdit';
|
||||
import { PartTextEdit } from '../fragments-content/PartTextEdit';
|
||||
|
||||
|
||||
export function DocumentFragmentEditor(props: {
|
||||
@@ -85,8 +85,8 @@ export function DocumentFragmentEditor(props: {
|
||||
|
||||
{isEditing ? (
|
||||
// Document Editor
|
||||
<ContentPartTextEdit
|
||||
textPart={part}
|
||||
<PartTextEdit
|
||||
textPartText={part.text}
|
||||
fragmentId={fragmentId}
|
||||
contentScaling={props.contentScaling}
|
||||
editedText={props.editedText}
|
||||
|
||||
@@ -11,7 +11,7 @@ import type { ChatMessageTextPartEditState } from '../ChatMessage';
|
||||
import { ContentPartImageRef } from './ContentPartImageRef';
|
||||
import { ContentPartPlaceholder } from './ContentPartPlaceholder';
|
||||
import { ContentPartText } from './ContentPartText';
|
||||
import { ContentPartTextEdit } from './ContentPartTextEdit';
|
||||
import { PartTextEdit } from './PartTextEdit';
|
||||
|
||||
|
||||
const editLayoutSx: SxProps = {
|
||||
@@ -66,6 +66,10 @@ export function ContentFragments(props: {
|
||||
const isEditingText = !!props.textEditsState;
|
||||
const isMonoFragment = props.fragments.length < 2;
|
||||
|
||||
// if no fragments, don't box them
|
||||
if (!props.fragments.length)
|
||||
return null;
|
||||
|
||||
return <Box aria-label='message body' sx={isEditingText ? editLayoutSx : fromAssistant ? startLayoutSx : endLayoutSx}>
|
||||
{props.fragments.map((fragment) => {
|
||||
|
||||
@@ -76,9 +80,9 @@ export function ContentFragments(props: {
|
||||
switch (fragment.part.pt) {
|
||||
case 'text':
|
||||
return props.textEditsState ? (
|
||||
<ContentPartTextEdit
|
||||
<PartTextEdit
|
||||
key={'edit-' + fragment.fId}
|
||||
textPart={fragment.part}
|
||||
textPartText={fragment.part.text}
|
||||
fragmentId={fragment.fId}
|
||||
contentScaling={props.contentScaling}
|
||||
editedText={props.textEditsState[fragment.fId]}
|
||||
@@ -125,12 +129,22 @@ export function ContentFragments(props: {
|
||||
messageRole={props.messageRole}
|
||||
contentScaling={props.contentScaling}
|
||||
showAsItalic
|
||||
// showAsProgress
|
||||
/>
|
||||
);
|
||||
|
||||
case 'error':
|
||||
return (
|
||||
return props.textEditsState ? (
|
||||
<PartTextEdit
|
||||
key={'edit-' + fragment.fId}
|
||||
textPartText={fragment.part.error}
|
||||
fragmentId={fragment.fId}
|
||||
contentScaling={props.contentScaling}
|
||||
editedText={props.textEditsState[fragment.fId]}
|
||||
setEditedText={props.setEditedText}
|
||||
onEnterPressed={props.onEditsApply}
|
||||
onEscapePressed={props.onEditsCancel}
|
||||
/>
|
||||
) : (
|
||||
<ContentPartPlaceholder
|
||||
key={fragment.fId}
|
||||
placeholderText={fragment.part.error}
|
||||
|
||||
+4
-4
@@ -6,7 +6,7 @@ import { Textarea } from '@mui/joy';
|
||||
import { blocksRendererSx } from '~/modules/blocks/BlocksRenderer';
|
||||
|
||||
import type { ContentScaling } from '~/common/app.theme';
|
||||
import type { DMessageFragmentId, DMessageTextPart } from '~/common/stores/chat/chat.fragments';
|
||||
import type { DMessageFragmentId } from '~/common/stores/chat/chat.fragments';
|
||||
|
||||
|
||||
const textEditAreaSx: SxProps = {
|
||||
@@ -26,9 +26,9 @@ const textEditAreaSx: SxProps = {
|
||||
* Very similar to <InlineTextArea /> but with externally controlled state rather than internal.
|
||||
* Made it for as the editing alternative for <ContentPartText />.
|
||||
*/
|
||||
export function ContentPartTextEdit(props: {
|
||||
export function PartTextEdit(props: {
|
||||
// current value
|
||||
textPart: DMessageTextPart,
|
||||
textPartText: string,
|
||||
fragmentId: DMessageFragmentId,
|
||||
|
||||
// visual
|
||||
@@ -77,7 +77,7 @@ export function ContentPartTextEdit(props: {
|
||||
size={props.contentScaling !== 'md' ? 'sm' : undefined}
|
||||
value={(props.editedText !== undefined)
|
||||
? props.editedText /* self-text */
|
||||
: props.textPart.text /* DMessageTextPart text */
|
||||
: props.textPartText /* DMessageTextPart text */
|
||||
}
|
||||
onChange={handleEditTextChanged}
|
||||
onKeyDown={handleEditKeyDown}
|
||||
@@ -33,7 +33,7 @@ export async function runImageGenerationUpdatingState(cHandler: ConversationHand
|
||||
imageText = imageText.replace(/x(\d+)$|\[(\d+)]$/, '').trim(); // Remove the "xN" or "[N]" part from the imageText
|
||||
|
||||
const { assistantMessageId, placeholderFragmentId } = cHandler.messageAppendAssistantPlaceholder(
|
||||
`Give me ${t2iProvider.vendor === 'openai' ? 'a dozen' : 'a few'} seconds while I draw ${imageText?.length > 20 ? 'that' : '"' + imageText + '"'}...`,
|
||||
`Give me ${t2iProvider.vendor === 'openai' ? 'a minute' : 'a few seconds'} while I draw ${imageText?.length > 20 ? 'that' : '"' + imageText + '"'} with ${t2iProvider.painter}...`,
|
||||
{ originLLM: t2iProvider.painter },
|
||||
);
|
||||
|
||||
|
||||
@@ -188,7 +188,7 @@ export const themeScalingMap: Record<ContentScaling, ContentScalingOptions> = {
|
||||
blockFontSize: 'xs',
|
||||
blockImageGap: 1,
|
||||
blockLineHeight: 1.666667,
|
||||
chatMessagePadding: 1.25,
|
||||
chatMessagePadding: 1,
|
||||
fragmentButtonFontSize: 'xs',
|
||||
chatDrawerItemSx: { '--ListItem-minHeight': '2.25rem', fontSize: 'sm' }, // 36px
|
||||
chatDrawerItemFolderSx: { '--ListItem-minHeight': '2.5rem', fontSize: 'sm' }, // 40px
|
||||
|
||||
@@ -366,7 +366,7 @@ export const useChatStore = create<ConversationsStore>()(devtools(
|
||||
// replace the Content.Pl[part.pt='ph'] fragments with Error fragments, to show the aborted ops (instead of just empty blocks)
|
||||
message.fragments = message.fragments.map((fragment: DMessageFragment): DMessageFragment =>
|
||||
(isContentFragment(fragment) && fragment.part.pt === 'ph')
|
||||
? createErrorContentFragment(`Interrupted: ${fragment.part.pText}`)
|
||||
? createErrorContentFragment(`${fragment.part.pText} (did not complete)`)
|
||||
: fragment,
|
||||
);
|
||||
// cleanup pre-v4 properties
|
||||
|
||||
Reference in New Issue
Block a user