diff --git a/packages/app/src/components/composer.tsx b/packages/app/src/components/composer.tsx
index 990a98be6..3fbfed514 100644
--- a/packages/app/src/components/composer.tsx
+++ b/packages/app/src/components/composer.tsx
@@ -115,7 +115,7 @@ function QueuedMessageRow({ item, onEdit, onSendNow }: QueuedMessageRowProps) {
@@ -126,10 +126,11 @@ function QueuedMessageRow({ item, onEdit, onSendNow }: QueuedMessageRowProps) {
function ImageAttachmentThumbnail({ image }: { image: ImageAttachment }) {
const uri = useAttachmentPreviewUrl(image);
+ const source = useMemo(() => ({ uri: uri ?? "" }), [uri]);
if (!uri) {
return ;
}
- return ;
+ return ;
}
interface ImageAttachmentPillProps {
@@ -833,6 +834,14 @@ export function Composer({
[],
);
+ const cancelButtonStyle = useMemo(
+ () => [
+ styles.cancelButton as any,
+ (!isConnected || isCancellingAgent ? styles.buttonDisabled : undefined) as any,
+ ],
+ [isConnected, isCancellingAgent],
+ );
+
const cancelButton = useMemo(
() =>
isAgentRunning && !hasSendableContent && !isProcessing ? (
@@ -842,10 +851,7 @@ export function Composer({
disabled={!isConnected || isCancellingAgent}
accessibilityLabel={isCancellingAgent ? "Canceling agent" : "Stop agent"}
accessibilityRole="button"
- style={[
- styles.cancelButton as any,
- (!isConnected || isCancellingAgent ? styles.buttonDisabled : undefined) as any,
- ]}
+ style={cancelButtonStyle}
>
{isCancellingAgent ? (
@@ -1100,11 +1106,20 @@ export function Composer({
[voiceButtonDisabled],
);
+ const composerContainerStyle = useMemo(
+ () => [styles.container, keyboardAnimatedStyle],
+ [keyboardAnimatedStyle],
+ );
+ const inputAreaContainerStyle = useMemo(
+ () => [styles.inputAreaContainer, isComposerLocked && styles.inputAreaLocked],
+ [isComposerLocked],
+ );
+
return (
-
+
{/* Input area */}
-
+
{/* Queue list */}
{queuedMessages.length > 0 && (
@@ -1397,3 +1412,5 @@ const styles = StyleSheet.create(((theme: Theme) => ({
fontSize: theme.fontSize.sm,
},
})) as any) as Record;
+
+const QUEUE_SEND_BUTTON_STYLE = [styles.queueActionButton, styles.queueSendButton];
diff --git a/packages/app/src/components/message-input.tsx b/packages/app/src/components/message-input.tsx
index 1e8ccb873..74a72a6f8 100644
--- a/packages/app/src/components/message-input.tsx
+++ b/packages/app/src/components/message-input.tsx
@@ -15,6 +15,7 @@ import {
useEffect,
useLayoutEffect,
useImperativeHandle,
+ useMemo,
forwardRef,
} from "react";
import { StyleSheet, useUnistyles } from "react-native-unistyles";
@@ -981,13 +982,39 @@ export const MessageInput = forwardRef(funct
void handleStopRealtimeVoice();
}, [handleStopRealtimeVoice]);
+ const inputWrapperCombinedStyle = useMemo(
+ () => [styles.inputWrapper, inputWrapperStyle, inputAnimatedStyle],
+ [inputWrapperStyle, inputAnimatedStyle],
+ );
+ const textInputStyle = useMemo(
+ () => [
+ styles.textInput,
+ isWeb
+ ? {
+ height: inputHeight,
+ minHeight: MIN_INPUT_HEIGHT,
+ maxHeight: MAX_INPUT_HEIGHT,
+ }
+ : {
+ minHeight: MIN_INPUT_HEIGHT,
+ maxHeight: MAX_INPUT_HEIGHT,
+ },
+ ],
+ [inputHeight],
+ );
+ const sendButtonCombinedStyle = useMemo(
+ () => [styles.sendButton, isSendButtonDisabled && styles.buttonDisabled],
+ [isSendButtonDisabled],
+ );
+ const overlayContainerStyle = useMemo(
+ () => [styles.overlayContainer, overlayAnimatedStyle],
+ [overlayAnimatedStyle],
+ );
+
return (
{/* Regular input */}
-
+
{/* Text input */}
(funct
accessibilityLabel="Message agent..."
onFocus={handleInputFocus}
onBlur={handleInputBlur}
- style={[
- styles.textInput,
- isWeb
- ? {
- height: inputHeight,
- minHeight: MIN_INPUT_HEIGHT,
- maxHeight: MAX_INPUT_HEIGHT,
- }
- : {
- minHeight: MIN_INPUT_HEIGHT,
- maxHeight: MAX_INPUT_HEIGHT,
- },
- ]}
+ style={textInputStyle}
multiline
scrollEnabled={isWeb ? inputHeight >= MAX_INPUT_HEIGHT : true}
onContentSizeChange={handleContentSizeChange}
@@ -1148,7 +1163,7 @@ export const MessageInput = forwardRef(funct
disabled={isSendButtonDisabled}
accessibilityLabel={submitAccessibilityLabel}
accessibilityRole="button"
- style={[styles.sendButton, isSendButtonDisabled && styles.buttonDisabled]}
+ style={sendButtonCombinedStyle}
>
{isSubmitLoading ? (
@@ -1173,7 +1188,7 @@ export const MessageInput = forwardRef(funct
{/* Dictation overlay */}
-
+
{showDictationOverlay ? (
[styles.container, { maxHeight }],
+ [maxHeight],
+ );
+
if (isLoading) {
return (
-
+
{loadingText}
@@ -218,7 +223,7 @@ export function Autocomplete({
if (errorMessage) {
return (
-
+
Error: {errorMessage}
@@ -228,7 +233,7 @@ export function Autocomplete({
if (options.length === 0) {
return (
-
+
{emptyText}
@@ -253,7 +258,7 @@ export function Autocomplete({
) : null}
) : null}
-
+