diff --git a/apps/mobile/src/components/ComposerAttachmentStrip.tsx b/apps/mobile/src/components/ComposerAttachmentStrip.tsx index 8cac0b59cfdf9..35dd3f0b82268 100644 --- a/apps/mobile/src/components/ComposerAttachmentStrip.tsx +++ b/apps/mobile/src/components/ComposerAttachmentStrip.tsx @@ -46,7 +46,6 @@ type ComposerAttachmentThumbnailProps = { readonly attachment: DraftComposerAttachment; readonly size: number; readonly borderRadius: number; - readonly compact?: boolean; readonly onPressPreview?: (source: FilePreviewSource) => void; readonly onPressVideo?: ( attachment: DraftComposerFileAttachment, @@ -55,7 +54,7 @@ type ComposerAttachmentThumbnailProps = { readonly onPressDocument?: (attachment: DraftComposerFileAttachment) => void; }; -export function ComposerAttachmentThumbnail(props: ComposerAttachmentThumbnailProps) { +function ComposerAttachmentThumbnail(props: ComposerAttachmentThumbnailProps) { const upload = useComposerAttachmentUploadState(props.environmentId, props.attachment.id); return ( @@ -78,15 +77,13 @@ export function ComposerAttachmentThumbnail(props: ComposerAttachmentThumbnailPr > - {!props.compact ? ( - - {upload.status === "failed" ? "Retry" : `${Math.floor(upload.progress * 100)}%`} - - ) : null} + + {upload.status === "failed" ? "Retry" : `${Math.floor(upload.progress * 100)}%`} + ) : null} @@ -248,19 +245,13 @@ function ComposerFileAttachment( }) : onPressDocument?.(attachment) } - className={ - props.compact - ? "items-center justify-center bg-subtle" - : "items-center justify-center gap-1 bg-subtle px-2" - } + className="items-center justify-center gap-1 bg-subtle px-2" style={style} > - - {!props.compact ? ( - - {attachment.name} - - ) : null} + + + {attachment.name} + @@ -271,7 +262,6 @@ function ComposerVideoAttachment(props: { readonly attachment: DraftComposerFileAttachment; readonly size: number; readonly borderRadius: number; - readonly compact?: boolean; readonly onPressVideo: ( attachment: DraftComposerFileAttachment, sourceIdentifier: string, @@ -295,7 +285,6 @@ function ComposerVideoAttachment(props: { name={attachment.name} sourceIdentifier={sourceIdentifier} thumbnailSource={attachment} - compact={props.compact} onPress={() => props.onPressVideo(attachment, sourceIdentifier)} actionsSource={actionsSource} style={style} diff --git a/apps/mobile/src/features/threads/ThreadComposer.tsx b/apps/mobile/src/features/threads/ThreadComposer.tsx index 9f94ecd2edc93..c7827ec468034 100644 --- a/apps/mobile/src/features/threads/ThreadComposer.tsx +++ b/apps/mobile/src/features/threads/ThreadComposer.tsx @@ -41,7 +41,6 @@ import { } from "../../state/composer-attachment-uploads"; import Animated, { FadeIn, - FadeOut, type LayoutAnimationFunction, ReduceMotion, useAnimatedStyle, @@ -67,10 +66,7 @@ import { scopeProjectRef } from "@t3tools/client-runtime/environment"; import { AppText as Text } from "../../components/ui/AppText"; import { ComposerAttachmentButton } from "./ComposerAttachmentButton"; -import { - ComposerAttachmentStrip, - ComposerAttachmentThumbnail, -} from "../../components/ComposerAttachmentStrip"; +import { ComposerAttachmentStrip } from "../../components/ComposerAttachmentStrip"; import { VideoPreviewModal, type VideoPreviewSource } from "../../components/VideoPreviewModal"; import { GlassSurface } from "../../components/ui/GlassSurface"; import { ComposerEditor, type ComposerEditorHandle } from "../../components/ComposerEditor"; @@ -598,9 +594,11 @@ export const ThreadComposer = function ThreadComposer(props: ThreadComposerProps const isExpanded = isFocused || settingsSheetPresentation.keepsComposerExpanded; const { setComposerEditing } = useAdaptiveWorkspaceLayout(); const hasSidebarTabBar = useSidebarWorkspaceTabs() === "picker"; - const [compactRowWidth, setCompactRowWidth] = useState(0); - const compactAttachmentLimit = compactRowWidth >= 500 ? 3 : 1; const compactEditor = useCompactComposerEditor(bodyText, draftMessage); + const attachmentsHeight = useSharedValue(-1); + const attachmentsStyle = useAnimatedStyle(() => ({ + height: Math.max(0, attachmentsHeight.value), + })); const showsCompactDictation = isVoiceInputPresented; const isToolbarVisible = isVoiceInputPresented; const hasEditingAttachments = @@ -804,11 +802,7 @@ export const ThreadComposer = function ThreadComposer(props: ThreadComposerProps const editingAttachments = hasEditingAttachments ? ( <> {queuedEdit !== null && queuedEdit.existingAttachments.length > 0 ? ( - + ) : null} {stripAttachments.length > 0 ? ( - + - {isExpanded ? editingAttachments : null} - { - compactEditor.onRowLayout(event); - setCompactRowWidth(event.nativeEvent.layout.width); - }} - > + + { + const height = event.nativeEvent.layout.height; + attachmentsHeight.set( + attachmentsHeight.get() < 0 || Platform.OS === "android" + ? height + : withTiming(height, { + duration: COMPOSER_TRANSITION_DURATION_MS, + reduceMotion: ReduceMotion.System, + }), + ); + }} + > + {editingAttachments} + + + 0 - ? 0 - : INLINE_EDITOR_MIN_WIDTH, + minWidth: compactEditor.isExpanded ? 0 : INLINE_EDITOR_MIN_WIDTH, }, compactEditor.containerStyle, compactEditor.isExpanded ? { flex: 0, width: 0 } : undefined, ]} > - {!isExpanded && stripAttachments.length > 0 ? ( - - {stripAttachments.slice(0, compactAttachmentLimit).map((attachment) => ( - - ))} - {stripAttachments.length > compactAttachmentLimit ? ( - - - +{stripAttachments.length - compactAttachmentLimit} - - - ) : null} - - ) : null}