mirror of
https://github.com/enricoros/big-AGI.git
synced 2026-05-10 21:50:14 -07:00
Allow new attachments for previous messages in a chat. Fixes #945
This commit is contained in:
@@ -753,16 +753,16 @@ export function Composer(props: {
|
||||
{recognitionState.isAvailable && <ButtonMicMemo variant={micVariant} color={micColor === 'danger' ? 'danger' : showTint || micColor} errorMessage={recognitionState.errorMessage} onClick={handleToggleMic} />}
|
||||
|
||||
{/* [mobile] Attach file button (in draw with image mode) */}
|
||||
{showChatAttachments === 'only-images' && <ButtonAttachFilesMemo color={showTint} isMobile onAttachFiles={handleAttachFiles} fullWidth multiple />}
|
||||
{showChatAttachments === 'only-images' && <ButtonAttachFilesMemo color={showTint} isMobile onAttachFiles={handleAttachFiles} multiple />}
|
||||
|
||||
{/* [mobile] [+] attachment sources menu */}
|
||||
{showChatAttachments === true && (
|
||||
<AttachmentSourcesMemo
|
||||
mode='menu-compact'
|
||||
canBrowse={hasComposerBrowseCapability}
|
||||
hasScreenCapture={false}
|
||||
hasCamera={true}
|
||||
onlyImages={false}
|
||||
hasScreenCapture={supportsScreenCapture}
|
||||
hasCamera={supportsCameraCapture()}
|
||||
onlyImages={false /* because if yes, we only show the attach files above */}
|
||||
onAttachClipboard={attachAppendClipboardItems}
|
||||
onAttachFiles={handleAttachFiles}
|
||||
onAttachScreenCapture={handleAttachScreenCapture}
|
||||
|
||||
@@ -850,7 +850,7 @@ export function ChatMessage(props: {
|
||||
)}
|
||||
|
||||
{/* [Edit Mode] Add new attachments (right below the Document Fragments) */}
|
||||
{isEditingText && !!onMessageFragmentAppend && (
|
||||
{isEditingText && !fromAssistant && !!onMessageFragmentAppend && (
|
||||
<ChatMessageEditAttachments
|
||||
ref={attachmentsEditRef}
|
||||
isMobile={props.isMobile}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import * as React from 'react';
|
||||
|
||||
import { Box } from '@mui/joy';
|
||||
import type { SxProps } from '@mui/joy/styles/types';
|
||||
import { Sheet } from '@mui/joy';
|
||||
|
||||
import { useBrowseCapability } from '~/modules/browse/store-module-browsing';
|
||||
|
||||
@@ -27,6 +28,34 @@ export interface EditModeAttachmentsHandle {
|
||||
}
|
||||
|
||||
|
||||
const _styles = {
|
||||
box: {
|
||||
overflow: 'hidden',
|
||||
p: 0.5,
|
||||
|
||||
// looks - exactly from BoxTextArea - the Text editor
|
||||
boxShadow: 'inset 1px 0px 3px -2px var(--joy-palette-warning-softColor)',
|
||||
outline: '1px solid',
|
||||
outlineColor: 'var(--joy-palette-warning-solidBg)',
|
||||
borderRadius: 'sm',
|
||||
|
||||
// layout
|
||||
display: 'flex',
|
||||
flexWrap: 'wrap',
|
||||
alignItems: 'center',
|
||||
gap: 1,
|
||||
|
||||
// shade to the buttons inside this > div > div > button
|
||||
'& > div > div > button': {
|
||||
// backgroundColor: 'warning.softActiveBg',
|
||||
borderColor: 'warning.outlinedBorder',
|
||||
borderRadius: 'sm',
|
||||
boxShadow: 'sm',
|
||||
},
|
||||
},
|
||||
} as const satisfies Record<string, SxProps>;
|
||||
|
||||
|
||||
/**
|
||||
* Encapsulates all attachment wiring for ChatMessage edit mode.
|
||||
* Owns a standalone attachment drafts store (one per edit session).
|
||||
@@ -87,14 +116,15 @@ export const ChatMessageEditAttachments = React.forwardRef<EditModeAttachmentsHa
|
||||
|
||||
return <>
|
||||
|
||||
<Box sx={{ display: 'flex', flexWrap: 'wrap', alignItems: 'center', gap: 1 }}>
|
||||
<Sheet color='warning' variant='soft' sx={_styles.box}>
|
||||
|
||||
{/* [+] Attachment Sources menu */}
|
||||
<AttachmentSourcesMemo
|
||||
mode='menu-compact'
|
||||
canBrowse={browseCapability.inComposer}
|
||||
mode='menu-message'
|
||||
canBrowse={browseCapability.mayWork}
|
||||
hasScreenCapture={supportsScreenCapture}
|
||||
hasCamera={supportsCameraCapture()}
|
||||
// onlyImages={showAttachOnlyImages}
|
||||
onAttachClipboard={attachAppendClipboardItems}
|
||||
onAttachFiles={handleAttachFiles}
|
||||
onAttachScreenCapture={handleAttachScreenCapture}
|
||||
@@ -104,7 +134,7 @@ export const ChatMessageEditAttachments = React.forwardRef<EditModeAttachmentsHa
|
||||
/>
|
||||
|
||||
{/* Attachment Drafts list */}
|
||||
{attachmentDrafts.length > 0 && (
|
||||
{attachmentDrafts.length > 0 ? (
|
||||
<AttachmentDraftsList
|
||||
attachmentDraftsStoreApi={storeApiRef.current!}
|
||||
attachmentDrafts={attachmentDrafts}
|
||||
@@ -112,9 +142,9 @@ export const ChatMessageEditAttachments = React.forwardRef<EditModeAttachmentsHa
|
||||
renderDocViewer={renderDocViewer}
|
||||
renderImageViewer={renderImageViewer}
|
||||
/>
|
||||
)}
|
||||
) : null}
|
||||
|
||||
</Box>
|
||||
</Sheet>
|
||||
|
||||
{/* Modal portals */}
|
||||
{webInputDialogComponent}
|
||||
|
||||
@@ -155,7 +155,7 @@ export const AttachmentSourcesMemo = React.memo(AttachmentSources);
|
||||
|
||||
function AttachmentSources(props: {
|
||||
// mode
|
||||
mode: 'menu-compact' | 'menu-rich' | 'inline-buttons',
|
||||
mode: 'menu-compact' | 'menu-rich' | 'inline-buttons' | 'menu-message',
|
||||
color?: ColorPaletteProp, // menu-rich and inline-buttons
|
||||
richButtonStandOut?: boolean, // menu-rich only
|
||||
// source availability - note that hasGoogleDriveCapability is local
|
||||
@@ -206,7 +206,7 @@ function AttachmentSources(props: {
|
||||
return <>
|
||||
|
||||
{/* Files */}
|
||||
<ButtonAttachFilesMemo color={props.color} onAttachFiles={props.onAttachFiles} fullWidth multiple />
|
||||
<ButtonAttachFilesMemo color={props.color} onAttachFiles={props.onAttachFiles} /*fullWidth*/ multiple />
|
||||
|
||||
{/* Web */}
|
||||
{!props.onlyImages && <ButtonAttachWebMemo color={props.color} disabled={!props.canBrowse} onOpenWebInput={props.onOpenWebInput} />}
|
||||
@@ -235,13 +235,28 @@ function AttachmentSources(props: {
|
||||
|
||||
|
||||
// menu-compact mode (mobile) — simple icon trigger with flat menu items
|
||||
if (props.mode === 'menu-compact')
|
||||
if (props.mode === 'menu-compact' || props.mode === 'menu-message') {
|
||||
const isMessage = props.mode === 'menu-message';
|
||||
return <>
|
||||
|
||||
<Dropdown>
|
||||
<MenuButton slots={{ root: IconButton }}>
|
||||
<AddRoundedIcon />
|
||||
</MenuButton>
|
||||
{!isMessage ? (
|
||||
<MenuButton slots={{ root: IconButton }}>
|
||||
<AddRoundedIcon />
|
||||
</MenuButton>
|
||||
) : (
|
||||
<MenuButton slots={{ root: Button }} slotProps={{
|
||||
root: {
|
||||
size: 'sm',
|
||||
variant: 'soft',
|
||||
color: 'warning',
|
||||
startDecorator: <AddRoundedIcon />,
|
||||
sx: { minHeight: '2.25rem', m: -0.25 /* absorb parent's padding */ },
|
||||
},
|
||||
} as const}>
|
||||
Attach
|
||||
</MenuButton>
|
||||
)}
|
||||
<Menu sx={{ '--List-padding': '0.5rem' }}>
|
||||
|
||||
{/* Files */}
|
||||
@@ -252,7 +267,7 @@ function AttachmentSources(props: {
|
||||
<RichMenuItem name={props.onlyImages ? 'Images' : 'Files'} description='PDF, DOCX, images, code' color={props.color} icon={<AttachFileRoundedIcon />} onClick={handleAttachFilePicker} />
|
||||
|
||||
{/* Web */}
|
||||
{!props.onlyImages && (
|
||||
{!props.onlyImages && /*props.canBrowse &&*/ (
|
||||
// <MenuItem onClick={props.onOpenWebInput} disabled={!props.canBrowse}>
|
||||
// <ListItemDecorator><LanguageRoundedIcon /></ListItemDecorator>
|
||||
// Web
|
||||
@@ -288,21 +303,22 @@ function AttachmentSources(props: {
|
||||
)}
|
||||
|
||||
{/* Camera */}
|
||||
{/*{props.hasCamera && (*/}
|
||||
{/* // <MenuItem onClick={props.onOpenCamera}>*/}
|
||||
{/* // <ListItemDecorator><CameraAltOutlinedIcon /></ListItemDecorator>*/}
|
||||
{/* // Camera*/}
|
||||
{/* // </MenuItem>*/}
|
||||
{/* <RichMenuItem name='Camera' description='Capture photos and optional OCR' color={props.color} icon={<CameraAltOutlinedIcon />} onClick={props.onOpenCamera} />*/}
|
||||
{/*)}*/}
|
||||
{props.hasCamera && isMessage && (
|
||||
// <MenuItem onClick={props.onOpenCamera}>
|
||||
// <ListItemDecorator><CameraAltOutlinedIcon /></ListItemDecorator>
|
||||
// Camera
|
||||
// </MenuItem>
|
||||
<RichMenuItem name='Camera' description='Capture photos and optional OCR' color={props.color} icon={<CameraAltOutlinedIcon />} onClick={props.onOpenCamera} />
|
||||
)}
|
||||
|
||||
</Menu>
|
||||
</Dropdown>
|
||||
|
||||
{/* [mobile] Responsive Camera OCR button */}
|
||||
{props.hasCamera && <ButtonAttachCameraMemo isMobile color={props.color} onOpenCamera={props.onOpenCamera} />}
|
||||
{props.hasCamera && !isMessage && <ButtonAttachCameraMemo isMobile color={props.color} onOpenCamera={props.onOpenCamera} />}
|
||||
|
||||
</>;
|
||||
}
|
||||
|
||||
|
||||
// menu-rich mode (desktop) — labeled button trigger with animated, descriptive menu items
|
||||
@@ -369,7 +385,7 @@ function AttachmentSources(props: {
|
||||
/>
|
||||
|
||||
{/* Web/URL Attachment */}
|
||||
{!props.onlyImages && (
|
||||
{!props.onlyImages && /*props.canBrowse &&*/ (
|
||||
<RichMenuItem
|
||||
name='Web'
|
||||
icon={<LanguageRoundedIcon />}
|
||||
|
||||
Reference in New Issue
Block a user