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}