From 032de17537d91dca7d6aafb06023697e783b1e51 Mon Sep 17 00:00:00 2001 From: Mohamed Boudra Date: Fri, 24 Apr 2026 02:34:54 +0700 Subject: [PATCH] chore(lint): memoize inline styles in autocomplete, message-input, composer --- packages/app/src/components/composer.tsx | 33 +++++++++--- packages/app/src/components/message-input.tsx | 53 ++++++++++++------- .../app/src/components/ui/autocomplete.tsx | 15 ++++-- 3 files changed, 69 insertions(+), 32 deletions(-) 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} - +