AppChat: Draw: support N images

This commit is contained in:
Enrico Ros
2025-02-23 00:57:38 -08:00
parent 87d8c10905
commit 7327f1440e
2 changed files with 76 additions and 2 deletions
@@ -68,6 +68,7 @@ import { ButtonAttachScreenCaptureMemo } from './buttons/ButtonAttachScreenCaptu
import { ButtonAttachWebMemo } from './buttons/ButtonAttachWeb';
import { ButtonBeamMemo } from './buttons/ButtonBeam';
import { ButtonCallMemo } from './buttons/ButtonCall';
import { ButtonGroupDrawRepeat } from './buttons/ButtonGroupDrawRepeat';
import { ButtonMicContinuationMemo } from './buttons/ButtonMicContinuation';
import { ButtonMicMemo } from './buttons/ButtonMic';
import { ButtonMultiChatMemo } from './buttons/ButtonMultiChat';
@@ -115,6 +116,7 @@ export function Composer(props: {
// state
const [composeText, debouncedText, setComposeText] = useDebouncer('', 300, 1200, true);
const [drawRepeat, setDrawRepeat] = React.useState(1);
const [micContinuation, setMicContinuation] = React.useState(false);
const [speechInterimResult, setSpeechInterimResult] = React.useState<SpeechResult | null>(null);
const [sendStarted, setSendStarted] = React.useState(false);
@@ -210,6 +212,8 @@ export function Composer(props: {
const noConversation = !targetConversationId;
const showChatAttachments = chatExecuteModeCanAttach(chatExecuteMode);
const composerTextSuffix = chatExecuteMode === 'generate-image' && isDesktop && drawRepeat > 1 ? ` x${drawRepeat}` : '';
const micIsRunning = !!speechInterimResult;
// more mic way below, as we use complex hooks
@@ -298,7 +302,7 @@ export function Composer(props: {
// prepare the fragments: content (if any) and attachments (if allowed, and any)
const fragments: (DMessageContentFragment | DMessageAttachmentFragment)[] = [];
if (composerText)
fragments.push(createTextContentFragment(composerText));
fragments.push(createTextContentFragment(composerText + composerTextSuffix));
const canAttach = chatExecuteModeCanAttach(_chatExecuteMode);
if (canAttach) {
@@ -319,7 +323,7 @@ export function Composer(props: {
if (enqueued)
_handleClearText();
return enqueued;
}, [attachmentsTakeAllFragments, confirmProceedIfAttachmentsNotSupported, _handleClearText, inReferenceTo, onAction, targetConversationId]);
}, [attachmentsTakeAllFragments, composerTextSuffix, confirmProceedIfAttachmentsNotSupported, _handleClearText, inReferenceTo, onAction, targetConversationId]);
const handleSendAction = React.useCallback(async (chatExecuteMode: ChatExecuteMode, composerText: string): Promise<boolean> => {
setSendStarted(true);
@@ -1060,6 +1064,9 @@ export function Composer(props: {
</Box>
{/* [desktop] Draw mode N buttons */}
{isDesktop && isDraw && <ButtonGroupDrawRepeat drawRepeat={drawRepeat} setDrawRepeat={setDrawRepeat} />}
{/* [desktop] Multicast switch (under the Chat button) */}
{isDesktop && props.isMulticast !== null && <ButtonMultiChatMemo multiChat={props.isMulticast} onSetMultiChat={props.setIsMulticast} />}
@@ -0,0 +1,67 @@
import * as React from 'react';
import { Box, FormControl, IconButton } from '@mui/joy';
const _styles = {
control: {
gap: 1,
mt: 1,
} as const,
buttonGroup: {
display: 'flex',
justifyContent: 'space-evenly',
} as const,
button: {
borderRadius: 'sm',
// boxShadow: drawRepeat === n ? '0px 2px 8px 0px rgb(var(--joy-palette-warning-mainChannel) / 40%)' : 'none',
// fontWeight: drawRepeat === n ? 'xl' : 400, /* reset, from 600 */
transition: 'transform 0.14s, box-shadow 0.14s',
'&:hover': {
transform: 'translateY(-1px)',
// backgroundColor: drawRepeat === n ? 'background.popup' : 'background.surface',
// boxShadow: '0 0 8px 1px rgb(var(--joy-palette-warning-mainChannel) / 40%)',
} as const,
} as const,
text: {
mx: 'auto',
fontSize: 'xs',
opacity: '0.5',
} as const,
} as const;
export function ButtonGroupDrawRepeat(props: {
drawRepeat: number,
setDrawRepeat: (n: number) => void,
}) {
const { drawRepeat, setDrawRepeat } = props;
return (
<FormControl sx={_styles.control}>
<Box sx={_styles.buttonGroup}>
{[1, 2, 4, 5, 10].map((n) => (
<IconButton
key={n}
size='sm'
color='warning'
variant={drawRepeat === n ? 'solid' : 'soft'}
onClick={() => setDrawRepeat(n)}
sx={_styles.button}
>
{n}
</IconButton>
))}
</Box>
<Box sx={_styles.text}>
{drawRepeat > 1
? `Create ${drawRepeat} Images`
: 'Number of Images'}
</Box>
</FormControl>
);
}