From 274eec8cc219a324afbfaa0e3b81b0386e7fc905 Mon Sep 17 00:00:00 2001 From: Eric Bailey Date: Sun, 5 Apr 2026 16:36:19 -0500 Subject: [PATCH] FIx anchorRef handling --- package.json | 2 +- src/components/Composer/index.tsx | 16 ++++++++++------ .../Messages/components/MessageComposer.tsx | 11 +++++------ yarn.lock | 8 ++++---- 4 files changed, 20 insertions(+), 17 deletions(-) diff --git a/package.json b/package.json index c8fb86c3ef..ecf8495d94 100644 --- a/package.json +++ b/package.json @@ -88,7 +88,7 @@ "@bsky.app/expo-image-crop-tool": "^0.5.0", "@bsky.app/expo-translate-text": "^0.2.9", "@bsky.app/react-native-mmkv": "2.12.5", - "@bsky.app/sift": "^0.2.8", + "@bsky.app/sift": "^0.2.9", "@bsky.app/tapper": "^0.4.2", "@discord/bottom-sheet": "bluesky-social/react-native-bottom-sheet", "@emoji-mart/data": "^1.2.1", diff --git a/src/components/Composer/index.tsx b/src/components/Composer/index.tsx index c260f58757..ab97f88065 100644 --- a/src/components/Composer/index.tsx +++ b/src/components/Composer/index.tsx @@ -69,7 +69,6 @@ export type ComposerInternalApi = { input?: ReturnType['input'] clear: () => void insert(text: string): void - setAnchorRef(ref: View | null): void } export function useComposerInternalApiRef() { @@ -91,7 +90,8 @@ export type ComposerProps = Omit< | 'onSubmitEditing' > & { label: string - ref?: React.Ref + ref?: React.RefObject + autocompleteAnchorRef?: React.RefObject internalApiRef?: React.Ref outerStyle?: ViewStyleProp['style'] contentTextStyle?: TextStyleProp['style'] @@ -116,6 +116,7 @@ export function Composer({ label, ref, internalApiRef, + autocompleteAnchorRef, outerStyle, contentTextStyle, contentPaddingStyle, @@ -173,13 +174,16 @@ export function Composer({ inputScrollSharedValue.value = 0 }, insert: tapper.insert, - setAnchorRef: (ref: View | null) => { - sift.refs.setAnchor(ref) - }, }), - [tapper.input, tapper.insert, inputScrollSharedValue, sift.refs], + [tapper.input, tapper.insert, inputScrollSharedValue], ) + useEffect(() => { + if (autocompleteAnchorRef) { + sift.refs.setAnchor(autocompleteAnchorRef.current) + } + }, [sift.refs]) + /* * Skip the initial mount to avoid an unnecessary re-render — the parent * already knows the initial value since it passed `initialText`. diff --git a/src/screens/Messages/components/MessageComposer.tsx b/src/screens/Messages/components/MessageComposer.tsx index 623839f704..9ed85505ba 100644 --- a/src/screens/Messages/components/MessageComposer.tsx +++ b/src/screens/Messages/components/MessageComposer.tsx @@ -1,4 +1,4 @@ -import {useCallback, useEffect, useState} from 'react' +import {useCallback, useEffect, useRef, useState} from 'react' import {Pressable, View} from 'react-native' import {useLingui} from '@lingui/react/macro' import {countGraphemes} from 'unicode-segmenter/grapheme' @@ -46,6 +46,7 @@ export function MessageComposer({ isOpen: false, pos: {top: 0, left: 0, right: 0, bottom: 0, nextFocusRef: null}, }) + const anchorRef = useRef(null) const composerInternalApiRef = useComposerInternalApiRef() const {state: focused, onIn: onFocus, onOut: onBlur} = useInteractionState() @@ -109,11 +110,8 @@ export function MessageComposer({ {children} { - if (!IS_WEB && node) { - composerInternalApiRef.current?.setAnchorRef(node) - } - }} + collapsable={false} + ref={IS_WEB ? undefined : anchorRef} // @ts-expect-error web only onMouseEnter={onHoverIn} onMouseLeave={onHoverOut} @@ -173,6 +171,7 @@ export function MessageComposer({ label={l`Message input field`} placeholder={l`Write a message`} autocompletePlacement="top-start" + autocompleteAnchorRef={anchorRef} internalApiRef={composerInternalApiRef} defaultValue={text} editable={editable} diff --git a/yarn.lock b/yarn.lock index 577c214816..8255b66f06 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2413,10 +2413,10 @@ resolved "https://registry.yarnpkg.com/@bsky.app/react-native-mmkv/-/react-native-mmkv-2.12.5.tgz#eb17d31a6158c74393f617a1763ac223ff3f83a6" integrity sha512-3vUz1nQY1DiKIPAWRkpp5ZGxH5f2G6Ui0UuQuEYjYv81xx1qFcSzS9KQ2sHcOKYdkOM9amWV2Q8TQCxt1lrAHg== -"@bsky.app/sift@^0.2.8": - version "0.2.8" - resolved "https://registry.yarnpkg.com/@bsky.app/sift/-/sift-0.2.8.tgz#58cb8ed82e6402061a1e2315a03e1aaec66e6718" - integrity sha512-CVBo0fp8kpSPhiGYO1H0J8aaEREQ87fzoXdL2qaH64GgX+tqFJT9BlS4EvEyhJoyMHdRWinGgTTubf4Gkvcg/Q== +"@bsky.app/sift@^0.2.9": + version "0.2.9" + resolved "https://registry.yarnpkg.com/@bsky.app/sift/-/sift-0.2.9.tgz#517710b850551846482e68c201750d1dfd549792" + integrity sha512-6eQzQ+xKkc0HcGzs96HaadKx+YfaCQwWO52S5VReyxuSii4Xz+bFZ4pjtHnH0NU/lB9W3llMLmjrV+Y5hGozhA== "@bsky.app/tapper@^0.4.2": version "0.4.2"