migrate people lists off actor-autocomplete
This commit is contained in:
@@ -13,12 +13,12 @@ import {Plural, Trans, useLingui} from '@lingui/react/macro'
|
||||
import {createSanitizedDisplayName} from '#/lib/moderation/create-sanitized-display-name'
|
||||
import {sanitizeHandle} from '#/lib/strings/handles'
|
||||
import {useModerationOpts} from '#/state/preferences/moderation-opts'
|
||||
import {useActorAutocompleteQuery} from '#/state/queries/actor-autocomplete'
|
||||
import {useListConvosQuery} from '#/state/queries/messages/list-conversations'
|
||||
import {useProfileFollowsQuery} from '#/state/queries/profile-follows'
|
||||
import {useSession} from '#/state/session'
|
||||
import {type ListMethods} from '#/view/com/util/List'
|
||||
import {android, atoms as a, native, useTheme, web} from '#/alf'
|
||||
import {useAutocomplete} from '#/components/Autocomplete'
|
||||
import {Button, ButtonIcon} from '#/components/Button'
|
||||
import * as Dialog from '#/components/Dialog'
|
||||
import {
|
||||
@@ -106,10 +106,17 @@ export function SearchablePeopleList({
|
||||
const [searchText, setSearchText] = useState('')
|
||||
|
||||
const {
|
||||
data: results,
|
||||
items: autocompleteItems,
|
||||
isError,
|
||||
isFetching,
|
||||
} = useActorAutocompleteQuery(searchText, true, 12)
|
||||
} = useAutocomplete({
|
||||
type: 'profile',
|
||||
query: searchText,
|
||||
limit: 12,
|
||||
})
|
||||
const results = autocompleteItems
|
||||
.filter(item => item.type === 'profile')
|
||||
.map(item => item.profile)
|
||||
const {data: follows} = useProfileFollowsQuery(currentAccount?.did)
|
||||
const {data: convos} = useListConvosQuery({
|
||||
enabled: showRecentConvos,
|
||||
|
||||
@@ -10,12 +10,12 @@ import {LayoutAnimation, type TextInput, View} from 'react-native'
|
||||
import {Trans, useLingui} from '@lingui/react/macro'
|
||||
|
||||
import {useModerationOpts} from '#/state/preferences/moderation-opts'
|
||||
import {useActorAutocompleteQuery} from '#/state/queries/actor-autocomplete'
|
||||
import {useListConvoMembersQuery} from '#/state/queries/messages/list-convo-members'
|
||||
import {useProfileFollowsQuery} from '#/state/queries/profile-follows'
|
||||
import {useSession} from '#/state/session'
|
||||
import {type ListMethods} from '#/view/com/util/List'
|
||||
import {android, atoms as a, native, useTheme, web} from '#/alf'
|
||||
import {useAutocomplete} from '#/components/Autocomplete'
|
||||
import {Button, ButtonIcon, ButtonText} from '#/components/Button'
|
||||
import * as Dialog from '#/components/Dialog'
|
||||
import {canBeAddedToGroup, type ConvoWithDetails} from '#/components/dms/util'
|
||||
@@ -25,6 +25,7 @@ import {TimesLarge_Stroke2_Corner0_Rounded as XIcon} from '#/components/icons/Ti
|
||||
import {Loader} from '#/components/Loader'
|
||||
import {Text} from '#/components/Typography'
|
||||
import {IS_NATIVE, IS_WEB} from '#/env'
|
||||
import {useFollowsSource} from '#/features/autocomplete/useFollowsSource'
|
||||
import type * as bsky from '#/types/bsky'
|
||||
import {ChatProfileTabs} from './ChatProfileTabs'
|
||||
import {EmptyMemberList} from './components/EmptyMemberList'
|
||||
@@ -145,11 +146,20 @@ export function AddMembersFlow({
|
||||
},
|
||||
)
|
||||
|
||||
const followsSource = useFollowsSource()
|
||||
const {
|
||||
data: autocompleteResults,
|
||||
items: autocompleteItems,
|
||||
isError,
|
||||
isFetching: isAutocompleteFetching,
|
||||
} = useActorAutocompleteQuery(searchText, true, 12)
|
||||
} = useAutocomplete({
|
||||
type: 'profile',
|
||||
query: searchText,
|
||||
limit: 12,
|
||||
sources: [followsSource],
|
||||
})
|
||||
const autocompleteResults = autocompleteItems
|
||||
.filter(item => item.type === 'profile')
|
||||
.map(item => item.profile)
|
||||
const {data: follows} = useProfileFollowsQuery(currentAccount?.did)
|
||||
const {data: memberListData = [], isPending: isMemberListPending} =
|
||||
useListConvoMembersQuery({
|
||||
|
||||
@@ -15,12 +15,12 @@ import {sanitizeDisplayName} from '#/lib/strings/display-names'
|
||||
import {sanitizeHandle} from '#/lib/strings/handles'
|
||||
import {isOverMaxGraphemeCount} from '#/lib/strings/helpers'
|
||||
import {useModerationOpts} from '#/state/preferences/moderation-opts'
|
||||
import {useActorAutocompleteQuery} from '#/state/queries/actor-autocomplete'
|
||||
import {useChatActorStatusQuery} from '#/state/queries/messages/get-status'
|
||||
import {useProfileFollowsQuery} from '#/state/queries/profile-follows'
|
||||
import {useSession} from '#/state/session'
|
||||
import {type ListMethods} from '#/view/com/util/List'
|
||||
import {android, atoms as a, native, useTheme, web} from '#/alf'
|
||||
import {useAutocomplete} from '#/components/Autocomplete'
|
||||
import {Button, ButtonIcon, ButtonText} from '#/components/Button'
|
||||
import * as Dialog from '#/components/Dialog'
|
||||
import {canBeAddedToGroup, canBeMessaged} from '#/components/dms/util'
|
||||
@@ -38,6 +38,7 @@ import * as Prompt from '#/components/Prompt'
|
||||
import {Text} from '#/components/Typography'
|
||||
import {useAgeAssurance} from '#/ageAssurance'
|
||||
import {IS_NATIVE, IS_WEB} from '#/env'
|
||||
import {useFollowsSource} from '#/features/autocomplete/useFollowsSource'
|
||||
import type * as bsky from '#/types/bsky'
|
||||
import {ChatProfileTabs} from './ChatProfileTabs'
|
||||
import {EmptyMemberList} from './components/EmptyMemberList'
|
||||
@@ -253,11 +254,20 @@ export function InitiateChatFlow({
|
||||
searchText: '',
|
||||
})
|
||||
|
||||
const followsSource = useFollowsSource()
|
||||
const {
|
||||
data: results,
|
||||
items: autocompleteItems,
|
||||
isError,
|
||||
isFetching,
|
||||
} = useActorAutocompleteQuery(searchText, true, 12)
|
||||
} = useAutocomplete({
|
||||
type: 'profile',
|
||||
query: searchText,
|
||||
limit: 12,
|
||||
sources: [followsSource],
|
||||
})
|
||||
const results = autocompleteItems
|
||||
.filter(item => item.type === 'profile')
|
||||
.map(item => item.profile)
|
||||
const {data: follows} = useProfileFollowsQuery(currentAccount?.did)
|
||||
|
||||
const newGroupChatTitle = l`New group chat`
|
||||
|
||||
@@ -5,11 +5,11 @@ import {type ModerationOpts} from '@atproto/api'
|
||||
import {Trans} from '@lingui/react/macro'
|
||||
|
||||
import {useA11y} from '#/state/a11y'
|
||||
import {useActorAutocompleteQuery} from '#/state/queries/actor-autocomplete'
|
||||
import {useActorSearch} from '#/state/queries/actor-search'
|
||||
import {List} from '#/view/com/util/List'
|
||||
import {useWizardState} from '#/screens/StarterPack/Wizard/State'
|
||||
import {atoms as a, useTheme} from '#/alf'
|
||||
import {useAutocomplete} from '#/components/Autocomplete'
|
||||
import {SearchInput} from '#/components/forms/SearchInput'
|
||||
import {Loader} from '#/components/Loader'
|
||||
import {ScreenTransition} from '#/components/ScreenTransition'
|
||||
@@ -43,9 +43,16 @@ export function StepProfiles({
|
||||
.flatMap(p => p.actors)
|
||||
.filter(p => !p.associated?.labeler)
|
||||
|
||||
const {data: resultsUnfiltered, isFetching: isFetchingResults} =
|
||||
useActorAutocompleteQuery(query, true, 12)
|
||||
const results = resultsUnfiltered?.filter(p => !p.associated?.labeler)
|
||||
const {items: autocompleteItems, isFetching: isFetchingResults} =
|
||||
useAutocomplete({
|
||||
type: 'profile',
|
||||
query,
|
||||
limit: 12,
|
||||
})
|
||||
const results = autocompleteItems
|
||||
.filter(item => item.type === 'profile')
|
||||
.map(item => item.profile)
|
||||
.filter(profile => !profile.associated?.labeler)
|
||||
|
||||
const isLoading = isLoadingTopPages || isFetchingResults
|
||||
|
||||
|
||||
@@ -1,126 +0,0 @@
|
||||
import {useCallback} from 'react'
|
||||
import {
|
||||
type AppBskyActorDefs,
|
||||
moderateProfile,
|
||||
type ModerationOpts,
|
||||
} from '@atproto/api'
|
||||
import {keepPreviousData, useQuery, useQueryClient} from '@tanstack/react-query'
|
||||
|
||||
import {isJustAMute, moduiContainsHideableOffense} from '#/lib/moderation'
|
||||
import {logger} from '#/logger'
|
||||
import {STALE} from '#/state/queries'
|
||||
import {useAgent} from '#/state/session'
|
||||
import {useModerationOpts} from '../preferences/moderation-opts'
|
||||
import {DEFAULT_LOGGED_OUT_PREFERENCES} from './preferences'
|
||||
|
||||
const DEFAULT_MOD_OPTS = {
|
||||
userDid: undefined,
|
||||
prefs: DEFAULT_LOGGED_OUT_PREFERENCES.moderationPrefs,
|
||||
}
|
||||
|
||||
const RQKEY_ROOT = 'actor-autocomplete'
|
||||
export const RQKEY = (prefix: string) => [RQKEY_ROOT, prefix]
|
||||
|
||||
export function useActorAutocompleteQuery(
|
||||
prefix: string,
|
||||
maintainData?: boolean,
|
||||
limit?: number,
|
||||
) {
|
||||
const moderationOpts = useModerationOpts()
|
||||
const agent = useAgent()
|
||||
|
||||
prefix = prefix.toLowerCase().trim()
|
||||
if (prefix.endsWith('.')) {
|
||||
// Going from "foo" to "foo." should not clear matches.
|
||||
prefix = prefix.slice(0, -1)
|
||||
}
|
||||
|
||||
return useQuery<AppBskyActorDefs.ProfileViewBasic[]>({
|
||||
staleTime: STALE.MINUTES.ONE,
|
||||
queryKey: RQKEY(prefix || ''),
|
||||
async queryFn() {
|
||||
const res = prefix
|
||||
? await agent.searchActorsTypeahead({
|
||||
q: prefix,
|
||||
limit: limit || 8,
|
||||
})
|
||||
: undefined
|
||||
return res?.data.actors || []
|
||||
},
|
||||
select: useCallback(
|
||||
(data: AppBskyActorDefs.ProfileViewBasic[]) => {
|
||||
return computeSuggestions({
|
||||
q: prefix,
|
||||
searched: data,
|
||||
moderationOpts: moderationOpts || DEFAULT_MOD_OPTS,
|
||||
})
|
||||
},
|
||||
[prefix, moderationOpts],
|
||||
),
|
||||
placeholderData: maintainData ? keepPreviousData : undefined,
|
||||
})
|
||||
}
|
||||
|
||||
export type ActorAutocompleteFn = ReturnType<typeof useActorAutocompleteFn>
|
||||
export function useActorAutocompleteFn() {
|
||||
const queryClient = useQueryClient()
|
||||
const moderationOpts = useModerationOpts()
|
||||
const agent = useAgent()
|
||||
|
||||
return useCallback(
|
||||
async ({query, limit = 8}: {query: string; limit?: number}) => {
|
||||
query = query.toLowerCase()
|
||||
let res
|
||||
if (query) {
|
||||
try {
|
||||
res = await queryClient.fetchQuery({
|
||||
staleTime: STALE.MINUTES.ONE,
|
||||
queryKey: RQKEY(query || ''),
|
||||
queryFn: () =>
|
||||
agent.searchActorsTypeahead({
|
||||
q: query,
|
||||
limit,
|
||||
}),
|
||||
})
|
||||
} catch (e) {
|
||||
logger.error('useActorSearch: searchActorsTypeahead failed', {
|
||||
message: e,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
return computeSuggestions({
|
||||
q: query,
|
||||
searched: res?.data.actors,
|
||||
moderationOpts: moderationOpts || DEFAULT_MOD_OPTS,
|
||||
})
|
||||
},
|
||||
[queryClient, moderationOpts, agent],
|
||||
)
|
||||
}
|
||||
|
||||
function computeSuggestions({
|
||||
q,
|
||||
searched = [],
|
||||
moderationOpts,
|
||||
}: {
|
||||
q?: string
|
||||
searched?: AppBskyActorDefs.ProfileViewBasic[]
|
||||
moderationOpts: ModerationOpts
|
||||
}) {
|
||||
let items: AppBskyActorDefs.ProfileViewBasic[] = []
|
||||
for (const item of searched) {
|
||||
if (!items.find(item2 => item2.handle === item.handle)) {
|
||||
items.push(item)
|
||||
}
|
||||
}
|
||||
return items.filter(profile => {
|
||||
const modui = moderateProfile(profile, moderationOpts).ui('profileList')
|
||||
const isExactMatch = q && profile.handle.toLowerCase() === q
|
||||
return (
|
||||
(isExactMatch && !moduiContainsHideableOffense(modui)) ||
|
||||
!modui.filter ||
|
||||
isJustAMute(modui)
|
||||
)
|
||||
})
|
||||
}
|
||||
Reference in New Issue
Block a user