add composer local sources and convo members

This commit is contained in:
vineyardbovines
2026-07-14 19:45:00 -04:00
parent 34b6631087
commit e740f60fc8
3 changed files with 41 additions and 1 deletions
+10 -1
View File
@@ -29,6 +29,7 @@ import {
Autocomplete as AutocompleteBase,
AutocompleteItemEmoji,
AutocompleteItemProfile,
type LocalSource,
parseAutocompleteItemType,
useAutocomplete,
} from '#/components/Autocomplete'
@@ -101,6 +102,8 @@ export type ComposerProps = Omit<
undefined
>['placement']
disableEmojiFacets?: boolean
/** Local datasets weighted above remote results in the mention typeahead. */
localSources?: LocalSource[]
}
export function Composer({
@@ -117,6 +120,7 @@ export function Composer({
autocompletePlacement,
defaultValue,
disableEmojiFacets = !IS_WEB,
localSources,
...rest
}: ComposerProps) {
const {theme: t, fonts} = useAlf()
@@ -377,6 +381,7 @@ export function Composer({
inverted={autocompletePlacement?.startsWith('top')}
sift={sift}
activeFacet={activeFacet}
localSources={localSources}
onDismiss={() => setActiveFacet(null)}
/>
)}
@@ -392,16 +397,20 @@ function AutocompleteInner({
inverted,
sift,
activeFacet,
localSources,
onDismiss,
}: {
inverted?: boolean
sift: UseSiftReturn
activeFacet: TapperActiveFacet
localSources?: LocalSource[]
onDismiss: () => void
}) {
const itemType = parseAutocompleteItemType(activeFacet.type)
const {items} = useAutocomplete({
type: parseAutocompleteItemType(activeFacet.type),
type: itemType,
query: activeFacet.value,
sources: itemType === 'profile' ? localSources : undefined,
})
useEffect(() => {
@@ -0,0 +1,26 @@
import {useConvo} from '#/state/messages/convo'
import {useSession} from '#/state/session'
import {type LocalSource} from '#/components/Autocomplete/types'
/**
* Members of the active conversation as an autocomplete LocalSource, so the
* mention typeahead in a chat prioritizes the people in it. Must be used
* within a ConvoProvider.
*/
export function useConvoMembersSource(): LocalSource {
const convo = useConvo()
const {currentAccount} = useSession()
const members = convo.convo?.members ?? []
return {
key: 'convo-members',
items: members
.filter(member => member.did !== currentAccount?.did)
.map(member => ({
key: member.did,
type: 'profile' as const,
value: '@' + member.handle,
profile: member,
})),
}
}
@@ -37,6 +37,8 @@ import {PaperPlaneVertical_Filled_Stroke2_Corner1_Rounded as PaperPlaneIcon} fro
import {Loader} from '#/components/Loader'
import * as Toast from '#/components/Toast'
import {IS_ANDROID, IS_IOS, IS_LIQUID_GLASS, IS_NATIVE, IS_WEB} from '#/env'
import {useConvoMembersSource} from '#/features/autocomplete/useConvoMembersSource'
import {useFollowsSource} from '#/features/autocomplete/useFollowsSource'
import {type MessageEmbedState} from './MessageInputEmbed'
const MIN_HEIGHT = 40
@@ -71,6 +73,8 @@ export function MessageComposer({
const [text, setText] = useState(getDraft)
useSaveMessageDraft(text)
const convoMembers = useConvoMembersSource()
const follows = useFollowsSource()
useEffect(() => {
if (!replyTo) return
@@ -255,6 +259,7 @@ export function MessageComposer({
: l({message: 'Message', context: 'description'})
}
autocompletePlacement="top-start"
localSources={[convoMembers, follows]}
internalApiRef={composerInternalApiRef}
defaultValue={text}
editable={editable}