Bluesky app fork with some witchin' additions 💫
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

[Session] Add `useAgent` hook and replace (#3706)

* Hook it up

* Memoize getAgent method

* Use one shared reference

---------

Co-authored-by: Dan Abramov <dan.abramov@gmail.com>

authored by

Eric Bailey
Dan Abramov
and committed by
GitHub
45d354cd d8c8e1e8

+231 -114
+3 -1
src/components/ReportDialog/SubmitView.tsx
··· 6 6 7 7 import {getLabelingServiceTitle} from '#/lib/moderation' 8 8 import {ReportOption} from '#/lib/moderation/useReportOptions' 9 - import {getAgent} from '#/state/session' 9 + import {useAgent} from '#/state/session' 10 10 import {CharProgress} from '#/view/com/composer/char-progress/CharProgress' 11 11 import * as Toast from '#/view/com/util/Toast' 12 12 import {atoms as a, native, useTheme} from '#/alf' ··· 35 35 }) { 36 36 const t = useTheme() 37 37 const {_} = useLingui() 38 + const {getAgent} = useAgent() 38 39 const [details, setDetails] = React.useState<string>('') 39 40 const [submitting, setSubmitting] = React.useState<boolean>(false) 40 41 const [selectedServices, setSelectedServices] = React.useState<string[]>([ ··· 90 91 selectedServices, 91 92 onSubmitComplete, 92 93 setError, 94 + getAgent, 93 95 ]) 94 96 95 97 return (
+3 -2
src/components/hooks/useRichText.ts
··· 1 1 import React from 'react' 2 2 import {RichText as RichTextAPI} from '@atproto/api' 3 3 4 - import {getAgent} from '#/state/session' 4 + import {useAgent} from '#/state/session' 5 5 6 6 export function useRichText(text: string): [RichTextAPI, boolean] { 7 7 const [prevText, setPrevText] = React.useState(text) 8 8 const [rawRT, setRawRT] = React.useState(() => new RichTextAPI({text})) 9 9 const [resolvedRT, setResolvedRT] = React.useState<RichTextAPI | null>(null) 10 + const {getAgent} = useAgent() 10 11 if (text !== prevText) { 11 12 setPrevText(text) 12 13 setRawRT(new RichTextAPI({text})) ··· 27 28 return () => { 28 29 ignore = true 29 30 } 30 - }, [text]) 31 + }, [text, getAgent]) 31 32 const isResolving = resolvedRT === null 32 33 return [resolvedRT ?? rawRT, isResolving] 33 34 }
+2 -1
src/components/moderation/LabelsOnMeDialog.tsx
··· 7 7 import {useLabelInfo} from '#/lib/moderation/useLabelInfo' 8 8 import {makeProfileLink} from '#/lib/routes/links' 9 9 import {sanitizeHandle} from '#/lib/strings/handles' 10 - import {getAgent} from '#/state/session' 10 + import {useAgent} from '#/state/session' 11 11 import * as Toast from '#/view/com/util/Toast' 12 12 import {atoms as a, useBreakpoints, useTheme} from '#/alf' 13 13 import {Button, ButtonText} from '#/components/Button' ··· 173 173 const {gtMobile} = useBreakpoints() 174 174 const [details, setDetails] = React.useState('') 175 175 const isAccountReport = 'did' in subject 176 + const {getAgent} = useAgent() 176 177 177 178 const onSubmit = async () => { 178 179 try {
+17 -10
src/screens/Deactivated.tsx
··· 1 1 import React from 'react' 2 2 import {View} from 'react-native' 3 3 import {useSafeAreaInsets} from 'react-native-safe-area-context' 4 - import {useLingui} from '@lingui/react' 5 4 import {msg, Trans} from '@lingui/macro' 6 - import {useOnboardingDispatch} from '#/state/shell' 7 - import {getAgent, isSessionDeactivated, useSessionApi} from '#/state/session' 8 - import {logger} from '#/logger' 9 - import {pluralize} from '#/lib/strings/helpers' 5 + import {useLingui} from '@lingui/react' 10 6 11 - import {atoms as a, useTheme, useBreakpoints} from '#/alf' 12 - import {Button, ButtonIcon, ButtonText} from '#/components/Button' 13 - import {Text, P} from '#/components/Typography' 7 + import {pluralize} from '#/lib/strings/helpers' 8 + import {logger} from '#/logger' 14 9 import {isWeb} from '#/platform/detection' 10 + import {isSessionDeactivated, useAgent, useSessionApi} from '#/state/session' 11 + import {useOnboardingDispatch} from '#/state/shell' 15 12 import {ScrollView} from '#/view/com/util/Views' 13 + import {Logo} from '#/view/icons/Logo' 14 + import {atoms as a, useBreakpoints, useTheme} from '#/alf' 15 + import {Button, ButtonIcon, ButtonText} from '#/components/Button' 16 16 import {Loader} from '#/components/Loader' 17 - import {Logo} from '#/view/icons/Logo' 17 + import {P, Text} from '#/components/Typography' 18 18 19 19 const COL_WIDTH = 400 20 20 ··· 25 25 const {gtMobile} = useBreakpoints() 26 26 const onboardingDispatch = useOnboardingDispatch() 27 27 const {logout} = useSessionApi() 28 + const {getAgent} = useAgent() 28 29 29 30 const [isProcessing, setProcessing] = React.useState(false) 30 31 const [estimatedTime, setEstimatedTime] = React.useState<string | undefined>( ··· 56 57 } finally { 57 58 setProcessing(false) 58 59 } 59 - }, [setProcessing, setEstimatedTime, setPlaceInQueue, onboardingDispatch]) 60 + }, [ 61 + setProcessing, 62 + setEstimatedTime, 63 + setPlaceInQueue, 64 + onboardingDispatch, 65 + getAgent, 66 + ]) 60 67 61 68 React.useEffect(() => { 62 69 checkStatus()
+3 -2
src/screens/Onboarding/StepFinished.tsx
··· 8 8 import {logEvent} from '#/lib/statsig/statsig' 9 9 import {logger} from '#/logger' 10 10 import {useSetSaveFeedsMutation} from '#/state/queries/preferences' 11 - import {getAgent} from '#/state/session' 11 + import {useAgent} from '#/state/session' 12 12 import {useOnboardingDispatch} from '#/state/shell' 13 13 import { 14 14 DescriptionText, ··· 38 38 const onboardDispatch = useOnboardingDispatch() 39 39 const [saving, setSaving] = React.useState(false) 40 40 const {mutateAsync: saveFeeds} = useSetSaveFeedsMutation() 41 + const {getAgent} = useAgent() 41 42 42 43 const finishOnboarding = React.useCallback(async () => { 43 44 setSaving(true) ··· 81 82 track('OnboardingV2:StepFinished:End') 82 83 track('OnboardingV2:Complete') 83 84 logEvent('onboarding:finished:nextPressed', {}) 84 - }, [state, dispatch, onboardDispatch, setSaving, saveFeeds, track]) 85 + }, [state, dispatch, onboardDispatch, setSaving, saveFeeds, track, getAgent]) 85 86 86 87 React.useEffect(() => { 87 88 track('OnboardingV2:StepFinished:Start')
+2 -1
src/screens/Onboarding/StepInterests/index.tsx
··· 8 8 import {logEvent} from '#/lib/statsig/statsig' 9 9 import {capitalize} from '#/lib/strings/capitalize' 10 10 import {logger} from '#/logger' 11 - import {getAgent} from '#/state/session' 11 + import {useAgent} from '#/state/session' 12 12 import {useOnboardingDispatch} from '#/state/shell' 13 13 import { 14 14 DescriptionText, ··· 39 39 state.interestsStepResults.selectedInterests.map(i => i), 40 40 ) 41 41 const onboardDispatch = useOnboardingDispatch() 42 + const {getAgent} = useAgent() 42 43 const {isLoading, isError, error, data, refetch, isFetching} = useQuery({ 43 44 queryKey: ['interests'], 44 45 queryFn: async () => {
+3 -1
src/screens/Signup/index.tsx
··· 9 9 import {logEvent} from '#/lib/statsig/statsig' 10 10 import {createFullHandle} from '#/lib/strings/handles' 11 11 import {useServiceQuery} from '#/state/queries/service' 12 - import {getAgent} from '#/state/session' 12 + import {useAgent} from '#/state/session' 13 13 import {LoggedOutLayout} from '#/view/com/util/layouts/LoggedOutLayout' 14 14 import { 15 15 initialState, ··· 35 35 const [state, dispatch] = React.useReducer(reducer, initialState) 36 36 const submit = useSubmitSignup({state, dispatch}) 37 37 const {gtMobile} = useBreakpoints() 38 + const {getAgent} = useAgent() 38 39 39 40 const { 40 41 data: serviceInfo, ··· 113 114 state.serviceDescription?.phoneVerificationRequired, 114 115 state.userDomain, 115 116 submit, 117 + getAgent, 116 118 ]) 117 119 118 120 const onBackPress = React.useCallback(() => {
+4 -2
src/state/queries/actor-autocomplete.ts
··· 5 5 import {isJustAMute} from '#/lib/moderation' 6 6 import {logger} from '#/logger' 7 7 import {STALE} from '#/state/queries' 8 - import {getAgent} from '#/state/session' 8 + import {useAgent} from '#/state/session' 9 9 import {DEFAULT_LOGGED_OUT_PREFERENCES, useModerationOpts} from './preferences' 10 10 11 11 const DEFAULT_MOD_OPTS = { ··· 18 18 19 19 export function useActorAutocompleteQuery(prefix: string) { 20 20 const moderationOpts = useModerationOpts() 21 + const {getAgent} = useAgent() 21 22 22 23 prefix = prefix.toLowerCase() 23 24 ··· 46 47 export function useActorAutocompleteFn() { 47 48 const queryClient = useQueryClient() 48 49 const moderationOpts = useModerationOpts() 50 + const {getAgent} = useAgent() 49 51 50 52 return React.useCallback( 51 53 async ({query, limit = 8}: {query: string; limit?: number}) => { ··· 74 76 moderationOpts || DEFAULT_MOD_OPTS, 75 77 ) 76 78 }, 77 - [queryClient, moderationOpts], 79 + [queryClient, moderationOpts, getAgent], 78 80 ) 79 81 } 80 82
+2 -1
src/state/queries/actor-search.ts
··· 2 2 import {QueryClient, useQuery} from '@tanstack/react-query' 3 3 4 4 import {STALE} from '#/state/queries' 5 - import {getAgent} from '#/state/session' 5 + import {useAgent} from '#/state/session' 6 6 7 7 const RQKEY_ROOT = 'actor-search' 8 8 export const RQKEY = (query: string) => [RQKEY_ROOT, query] ··· 14 14 query: string 15 15 enabled?: boolean 16 16 }) { 17 + const {getAgent} = useAgent() 17 18 return useQuery<AppBskyActorDefs.ProfileView[]>({ 18 19 staleTime: STALE.MINUTES.ONE, 19 20 queryKey: RQKEY(query || ''),
+4 -1
src/state/queries/app-passwords.ts
··· 2 2 import {useMutation, useQuery, useQueryClient} from '@tanstack/react-query' 3 3 4 4 import {STALE} from '#/state/queries' 5 - import {getAgent} from '../session' 5 + import {useAgent} from '../session' 6 6 7 7 const RQKEY_ROOT = 'app-passwords' 8 8 export const RQKEY = () => [RQKEY_ROOT] 9 9 10 10 export function useAppPasswordsQuery() { 11 + const {getAgent} = useAgent() 11 12 return useQuery({ 12 13 staleTime: STALE.MINUTES.FIVE, 13 14 queryKey: RQKEY(), ··· 20 21 21 22 export function useAppPasswordCreateMutation() { 22 23 const queryClient = useQueryClient() 24 + const {getAgent} = useAgent() 23 25 return useMutation< 24 26 ComAtprotoServerCreateAppPassword.OutputSchema, 25 27 Error, ··· 42 44 43 45 export function useAppPasswordDeleteMutation() { 44 46 const queryClient = useQueryClient() 47 + const {getAgent} = useAgent() 45 48 return useMutation<void, Error, {name: string}>({ 46 49 mutationFn: async ({name}) => { 47 50 await getAgent().com.atproto.server.revokeAppPassword({
+5 -1
src/state/queries/feed.ts
··· 17 17 import {sanitizeHandle} from '#/lib/strings/handles' 18 18 import {STALE} from '#/state/queries' 19 19 import {usePreferencesQuery} from '#/state/queries/preferences' 20 - import {getAgent, useSession} from '#/state/session' 20 + import {useAgent, useSession} from '#/state/session' 21 21 import {router} from '#/routes' 22 22 23 23 export type FeedSourceFeedInfo = { ··· 140 140 141 141 export function useFeedSourceInfoQuery({uri}: {uri: string}) { 142 142 const type = getFeedTypeFromUri(uri) 143 + const {getAgent} = useAgent() 143 144 144 145 return useQuery({ 145 146 staleTime: STALE.INFINITY, ··· 166 167 export const useGetPopularFeedsQueryKey = ['getPopularFeeds'] 167 168 168 169 export function useGetPopularFeedsQuery() { 170 + const {getAgent} = useAgent() 169 171 return useInfiniteQuery< 170 172 AppBskyUnspeccedGetPopularFeedGenerators.OutputSchema, 171 173 Error, ··· 187 189 } 188 190 189 191 export function useSearchPopularFeedsMutation() { 192 + const {getAgent} = useAgent() 190 193 return useMutation({ 191 194 mutationFn: async (query: string) => { 192 195 const res = await getAgent().app.bsky.unspecced.getPopularFeedGenerators({ ··· 238 241 239 242 export function usePinnedFeedsInfos() { 240 243 const {hasSession} = useSession() 244 + const {getAgent} = useAgent() 241 245 const {data: preferences, isLoading: isLoadingPrefs} = usePreferencesQuery() 242 246 const pinnedUris = preferences?.feeds?.pinned ?? [] 243 247
+6 -3
src/state/queries/handle.ts
··· 2 2 import {useMutation, useQueryClient} from '@tanstack/react-query' 3 3 4 4 import {STALE} from '#/state/queries' 5 - import {getAgent} from '#/state/session' 5 + import {useAgent} from '#/state/session' 6 6 7 7 const handleQueryKeyRoot = 'handle' 8 8 const fetchHandleQueryKey = (handleOrDid: string) => [ ··· 14 14 15 15 export function useFetchHandle() { 16 16 const queryClient = useQueryClient() 17 + const {getAgent} = useAgent() 17 18 18 19 return React.useCallback( 19 20 async (handleOrDid: string) => { ··· 27 28 } 28 29 return handleOrDid 29 30 }, 30 - [queryClient], 31 + [queryClient, getAgent], 31 32 ) 32 33 } 33 34 34 35 export function useUpdateHandleMutation() { 35 36 const queryClient = useQueryClient() 37 + const {getAgent} = useAgent() 36 38 37 39 return useMutation({ 38 40 mutationFn: async ({handle}: {handle: string}) => { ··· 48 50 49 51 export function useFetchDid() { 50 52 const queryClient = useQueryClient() 53 + const {getAgent} = useAgent() 51 54 52 55 return React.useCallback( 53 56 async (handleOrDid: string) => { ··· 64 67 }, 65 68 }) 66 69 }, 67 - [queryClient], 70 + [queryClient, getAgent], 68 71 ) 69 72 }
+2 -1
src/state/queries/invites.ts
··· 3 3 4 4 import {cleanError} from '#/lib/strings/errors' 5 5 import {STALE} from '#/state/queries' 6 - import {getAgent} from '#/state/session' 6 + import {useAgent} from '#/state/session' 7 7 8 8 function isInviteAvailable(invite: ComAtprotoServerDefs.InviteCode): boolean { 9 9 return invite.available - invite.uses.length > 0 && !invite.disabled ··· 16 16 undefined 17 17 > 18 18 export function useInviteCodesQuery() { 19 + const {getAgent} = useAgent() 19 20 return useQuery({ 20 21 staleTime: STALE.MINUTES.FIVE, 21 22 queryKey: [inviteCodesQueryKeyRoot],
+5 -1
src/state/queries/labeler.ts
··· 5 5 import {labelersDetailedInfoQueryKeyRoot} from '#/lib/react-query' 6 6 import {STALE} from '#/state/queries' 7 7 import {preferencesQueryKey} from '#/state/queries/preferences' 8 - import {getAgent} from '#/state/session' 8 + import {useAgent} from '#/state/session' 9 9 10 10 const labelerInfoQueryKeyRoot = 'labeler-info' 11 11 export const labelerInfoQueryKey = (did: string) => [ ··· 31 31 did?: string 32 32 enabled?: boolean 33 33 }) { 34 + const {getAgent} = useAgent() 34 35 return useQuery({ 35 36 enabled: !!did && enabled !== false, 36 37 queryKey: labelerInfoQueryKey(did as string), ··· 45 46 } 46 47 47 48 export function useLabelersInfoQuery({dids}: {dids: string[]}) { 49 + const {getAgent} = useAgent() 48 50 return useQuery({ 49 51 enabled: !!dids.length, 50 52 queryKey: labelersInfoQueryKey(dids), ··· 56 58 } 57 59 58 60 export function useLabelersDetailedInfoQuery({dids}: {dids: string[]}) { 61 + const {getAgent} = useAgent() 59 62 return useQuery({ 60 63 enabled: !!dids.length, 61 64 queryKey: labelersDetailedInfoQueryKey(dids), ··· 73 76 74 77 export function useLabelerSubscriptionMutation() { 75 78 const queryClient = useQueryClient() 79 + const {getAgent} = useAgent() 76 80 77 81 return useMutation({ 78 82 async mutationFn({did, subscribe}: {did: string; subscribe: boolean}) {
+3 -1
src/state/queries/like.ts
··· 1 1 import {useMutation} from '@tanstack/react-query' 2 2 3 - import {getAgent} from '#/state/session' 3 + import {useAgent} from '#/state/session' 4 4 5 5 export function useLikeMutation() { 6 + const {getAgent} = useAgent() 6 7 return useMutation({ 7 8 mutationFn: async ({uri, cid}: {uri: string; cid: string}) => { 8 9 const res = await getAgent().like(uri, cid) ··· 12 13 } 13 14 14 15 export function useUnlikeMutation() { 16 + const {getAgent} = useAgent() 15 17 return useMutation({ 16 18 mutationFn: async ({uri}: {uri: string}) => { 17 19 await getAgent().deleteLike(uri)
+2 -1
src/state/queries/list-members.ts
··· 7 7 } from '@tanstack/react-query' 8 8 9 9 import {STALE} from '#/state/queries' 10 - import {getAgent} from '#/state/session' 10 + import {useAgent} from '#/state/session' 11 11 12 12 const PAGE_SIZE = 30 13 13 type RQPageParam = string | undefined ··· 16 16 export const RQKEY = (uri: string) => [RQKEY_ROOT, uri] 17 17 18 18 export function useListMembersQuery(uri: string) { 19 + const {getAgent} = useAgent() 19 20 return useInfiniteQuery< 20 21 AppBskyGraphGetList.OutputSchema, 21 22 Error,
+4 -1
src/state/queries/list-memberships.ts
··· 19 19 20 20 import {STALE} from '#/state/queries' 21 21 import {RQKEY as LIST_MEMBERS_RQKEY} from '#/state/queries/list-members' 22 - import {getAgent, useSession} from '#/state/session' 22 + import {useAgent, useSession} from '#/state/session' 23 23 24 24 // sanity limit is SANITY_PAGE_LIMIT*PAGE_SIZE total records 25 25 const SANITY_PAGE_LIMIT = 1000 ··· 40 40 */ 41 41 export function useDangerousListMembershipsQuery() { 42 42 const {currentAccount} = useSession() 43 + const {getAgent} = useAgent() 43 44 return useQuery<ListMembersip[]>({ 44 45 staleTime: STALE.MINUTES.FIVE, 45 46 queryKey: RQKEY(), ··· 91 92 92 93 export function useListMembershipAddMutation() { 93 94 const {currentAccount} = useSession() 95 + const {getAgent} = useAgent() 94 96 const queryClient = useQueryClient() 95 97 return useMutation< 96 98 {uri: string; cid: string}, ··· 149 151 150 152 export function useListMembershipRemoveMutation() { 151 153 const {currentAccount} = useSession() 154 + const {getAgent} = useAgent() 152 155 const queryClient = useQueryClient() 153 156 return useMutation< 154 157 void,
+7 -1
src/state/queries/list.ts
··· 13 13 import {uploadBlob} from '#/lib/api' 14 14 import {until} from '#/lib/async/until' 15 15 import {STALE} from '#/state/queries' 16 - import {getAgent, useSession} from '../session' 16 + import {useAgent, useSession} from '../session' 17 17 import {invalidate as invalidateMyLists} from './my-lists' 18 18 import {RQKEY as PROFILE_LISTS_RQKEY} from './profile-lists' 19 19 ··· 21 21 export const RQKEY = (uri: string) => [RQKEY_ROOT, uri] 22 22 23 23 export function useListQuery(uri?: string) { 24 + const {getAgent} = useAgent() 24 25 return useQuery<AppBskyGraphDefs.ListView, Error>({ 25 26 staleTime: STALE.MINUTES.ONE, 26 27 queryKey: RQKEY(uri || ''), ··· 48 49 export function useListCreateMutation() { 49 50 const {currentAccount} = useSession() 50 51 const queryClient = useQueryClient() 52 + const {getAgent} = useAgent() 51 53 return useMutation<{uri: string; cid: string}, Error, ListCreateMutateParams>( 52 54 { 53 55 async mutationFn({ ··· 114 116 } 115 117 export function useListMetadataMutation() { 116 118 const {currentAccount} = useSession() 119 + const {getAgent} = useAgent() 117 120 const queryClient = useQueryClient() 118 121 return useMutation< 119 122 {uri: string; cid: string}, ··· 181 184 182 185 export function useListDeleteMutation() { 183 186 const {currentAccount} = useSession() 187 + const {getAgent} = useAgent() 184 188 const queryClient = useQueryClient() 185 189 return useMutation<void, Error, {uri: string}>({ 186 190 mutationFn: async ({uri}) => { ··· 249 253 250 254 export function useListMuteMutation() { 251 255 const queryClient = useQueryClient() 256 + const {getAgent} = useAgent() 252 257 return useMutation<void, Error, {uri: string; mute: boolean}>({ 253 258 mutationFn: async ({uri, mute}) => { 254 259 if (mute) { ··· 275 280 276 281 export function useListBlockMutation() { 277 282 const queryClient = useQueryClient() 283 + const {getAgent} = useAgent() 278 284 return useMutation<void, Error, {uri: string; block: boolean}>({ 279 285 mutationFn: async ({uri, block}) => { 280 286 if (block) {
+2 -1
src/state/queries/my-blocked-accounts.ts
··· 6 6 useInfiniteQuery, 7 7 } from '@tanstack/react-query' 8 8 9 - import {getAgent} from '#/state/session' 9 + import {useAgent} from '#/state/session' 10 10 11 11 const RQKEY_ROOT = 'my-blocked-accounts' 12 12 export const RQKEY = () => [RQKEY_ROOT] 13 13 type RQPageParam = string | undefined 14 14 15 15 export function useMyBlockedAccountsQuery() { 16 + const {getAgent} = useAgent() 16 17 return useInfiniteQuery< 17 18 AppBskyGraphGetBlocks.OutputSchema, 18 19 Error,
+2 -1
src/state/queries/my-lists.ts
··· 3 3 4 4 import {accumulate} from '#/lib/async/accumulate' 5 5 import {STALE} from '#/state/queries' 6 - import {getAgent, useSession} from '#/state/session' 6 + import {useAgent, useSession} from '#/state/session' 7 7 8 8 export type MyListsFilter = 9 9 | 'all' ··· 16 16 17 17 export function useMyListsQuery(filter: MyListsFilter) { 18 18 const {currentAccount} = useSession() 19 + const {getAgent} = useAgent() 19 20 return useQuery<AppBskyGraphDefs.ListView[]>({ 20 21 staleTime: STALE.MINUTES.ONE, 21 22 queryKey: RQKEY(filter),
+2 -1
src/state/queries/my-muted-accounts.ts
··· 6 6 useInfiniteQuery, 7 7 } from '@tanstack/react-query' 8 8 9 - import {getAgent} from '#/state/session' 9 + import {useAgent} from '#/state/session' 10 10 11 11 const RQKEY_ROOT = 'my-muted-accounts' 12 12 export const RQKEY = () => [RQKEY_ROOT] 13 13 type RQPageParam = string | undefined 14 14 15 15 export function useMyMutedAccountsQuery() { 16 + const {getAgent} = useAgent() 16 17 return useInfiniteQuery< 17 18 AppBskyGraphGetMutes.OutputSchema, 18 19 Error,
+2 -1
src/state/queries/notifications/feed.ts
··· 27 27 } from '@tanstack/react-query' 28 28 29 29 import {useMutedThreads} from '#/state/muted-threads' 30 - import {getAgent} from '#/state/session' 30 + import {useAgent} from '#/state/session' 31 31 import {STALE} from '..' 32 32 import {useModerationOpts} from '../preferences' 33 33 import {embedViewRecordToPostView, getEmbeddedPost} from '../util' ··· 47 47 } 48 48 49 49 export function useNotificationFeedQuery(opts?: {enabled?: boolean}) { 50 + const {getAgent} = useAgent() 50 51 const queryClient = useQueryClient() 51 52 const moderationOpts = useModerationOpts() 52 53 const threadMutes = useMutedThreads()
+3 -2
src/state/queries/notifications/unread.tsx
··· 12 12 import {logger} from '#/logger' 13 13 import {isNative} from '#/platform/detection' 14 14 import {useMutedThreads} from '#/state/muted-threads' 15 - import {getAgent, useSession} from '#/state/session' 15 + import {useAgent, useSession} from '#/state/session' 16 16 import {useModerationOpts} from '../preferences' 17 17 import {truncateAndInvalidate} from '../util' 18 18 import {RQKEY as RQKEY_NOTIFS} from './feed' ··· 46 46 47 47 export function Provider({children}: React.PropsWithChildren<{}>) { 48 48 const {hasSession} = useSession() 49 + const {getAgent} = useAgent() 49 50 const queryClient = useQueryClient() 50 51 const moderationOpts = useModerationOpts() 51 52 const threadMutes = useMutedThreads() ··· 197 198 } 198 199 }, 199 200 } 200 - }, [setNumUnread, queryClient, moderationOpts, threadMutes]) 201 + }, [setNumUnread, queryClient, moderationOpts, threadMutes, getAgent]) 201 202 checkUnreadRef.current = api.checkUnread 202 203 203 204 return (
+6 -1
src/state/queries/post-feed.ts
··· 4 4 AppBskyFeedDefs, 5 5 AppBskyFeedPost, 6 6 AtUri, 7 + BskyAgent, 7 8 ModerationDecision, 8 9 } from '@atproto/api' 9 10 import { ··· 19 20 import {logger} from '#/logger' 20 21 import {STALE} from '#/state/queries' 21 22 import {DEFAULT_LOGGED_OUT_PREFERENCES} from '#/state/queries/preferences/const' 22 - import {getAgent} from '#/state/session' 23 + import {useAgent} from '#/state/session' 23 24 import {AuthorFeedAPI} from 'lib/api/feed/author' 24 25 import {CustomFeedAPI} from 'lib/api/feed/custom' 25 26 import {FollowingFeedAPI} from 'lib/api/feed/following' ··· 104 105 const queryClient = useQueryClient() 105 106 const feedTuners = useFeedTuners(feedDesc) 106 107 const moderationOpts = useModerationOpts() 108 + const {getAgent} = useAgent() 107 109 const enabled = opts?.enabled !== false && Boolean(moderationOpts) 108 110 const lastRun = useRef<{ 109 111 data: InfiniteData<FeedPageUnselected> ··· 142 144 feedDesc, 143 145 feedParams: params || {}, 144 146 feedTuners, 147 + getAgent, 145 148 }), 146 149 cursor: undefined, 147 150 } ··· 372 375 feedDesc, 373 376 feedParams, 374 377 feedTuners, 378 + getAgent, 375 379 }: { 376 380 feedDesc: FeedDescriptor 377 381 feedParams: FeedParams 378 382 feedTuners: FeedTunerFn[] 383 + getAgent: () => BskyAgent 379 384 }) { 380 385 if (feedDesc === 'home') { 381 386 if (feedParams.mergeFeedEnabled) {
+2 -1
src/state/queries/post-liked-by.ts
··· 6 6 useInfiniteQuery, 7 7 } from '@tanstack/react-query' 8 8 9 - import {getAgent} from '#/state/session' 9 + import {useAgent} from '#/state/session' 10 10 11 11 const PAGE_SIZE = 30 12 12 type RQPageParam = string | undefined ··· 16 16 export const RQKEY = (resolvedUri: string) => [RQKEY_ROOT, resolvedUri] 17 17 18 18 export function useLikedByQuery(resolvedUri: string | undefined) { 19 + const {getAgent} = useAgent() 19 20 return useInfiniteQuery< 20 21 AppBskyFeedGetLikes.OutputSchema, 21 22 Error,
+2 -1
src/state/queries/post-reposted-by.ts
··· 6 6 useInfiniteQuery, 7 7 } from '@tanstack/react-query' 8 8 9 - import {getAgent} from '#/state/session' 9 + import {useAgent} from '#/state/session' 10 10 11 11 const PAGE_SIZE = 30 12 12 type RQPageParam = string | undefined ··· 16 16 export const RQKEY = (resolvedUri: string) => [RQKEY_ROOT, resolvedUri] 17 17 18 18 export function usePostRepostedByQuery(resolvedUri: string | undefined) { 19 + const {getAgent} = useAgent() 19 20 return useInfiniteQuery< 20 21 AppBskyFeedGetRepostedBy.OutputSchema, 21 22 Error,
+2 -1
src/state/queries/post-thread.ts
··· 7 7 import {QueryClient, useQuery, useQueryClient} from '@tanstack/react-query' 8 8 9 9 import {UsePreferencesQueryResponse} from '#/state/queries/preferences/types' 10 - import {getAgent} from '#/state/session' 10 + import {useAgent} from '#/state/session' 11 11 import {findAllPostsInQueryData as findAllPostsInSearchQueryData} from 'state/queries/search-posts' 12 12 import {findAllPostsInQueryData as findAllPostsInNotifsQueryData} from './notifications/feed' 13 13 import {findAllPostsInQueryData as findAllPostsInFeedQueryData} from './post-feed' ··· 66 66 67 67 export function usePostThreadQuery(uri: string | undefined) { 68 68 const queryClient = useQueryClient() 69 + const {getAgent} = useAgent() 69 70 return useQuery<ThreadNode, Error>({ 70 71 gcTime: 0, 71 72 queryKey: RQKEY(uri || ''),
+9 -2
src/state/queries/post.ts
··· 7 7 import {logEvent, LogEvents, toClout} from '#/lib/statsig/statsig' 8 8 import {updatePostShadow} from '#/state/cache/post-shadow' 9 9 import {Shadow} from '#/state/cache/types' 10 - import {getAgent, useSession} from '#/state/session' 10 + import {useAgent, useSession} from '#/state/session' 11 11 import {findProfileQueryData} from './profile' 12 12 13 13 const RQKEY_ROOT = 'post' 14 14 export const RQKEY = (postUri: string) => [RQKEY_ROOT, postUri] 15 15 16 16 export function usePostQuery(uri: string | undefined) { 17 + const {getAgent} = useAgent() 17 18 return useQuery<AppBskyFeedDefs.PostView>({ 18 19 queryKey: RQKEY(uri || ''), 19 20 async queryFn() { ··· 30 31 31 32 export function useGetPost() { 32 33 const queryClient = useQueryClient() 34 + const {getAgent} = useAgent() 33 35 return useCallback( 34 36 async ({uri}: {uri: string}) => { 35 37 return queryClient.fetchQuery({ ··· 56 58 }, 57 59 }) 58 60 }, 59 - [queryClient], 61 + [queryClient, getAgent], 60 62 ) 61 63 } 62 64 ··· 125 127 const {currentAccount} = useSession() 126 128 const queryClient = useQueryClient() 127 129 const postAuthor = post.author 130 + const {getAgent} = useAgent() 128 131 return useMutation< 129 132 {uri: string}, // responds with the uri of the like 130 133 Error, ··· 162 165 function usePostUnlikeMutation( 163 166 logContext: LogEvents['post:unlike']['logContext'], 164 167 ) { 168 + const {getAgent} = useAgent() 165 169 return useMutation<void, Error, {postUri: string; likeUri: string}>({ 166 170 mutationFn: ({likeUri}) => { 167 171 logEvent('post:unlike', {logContext}) ··· 234 238 function usePostRepostMutation( 235 239 logContext: LogEvents['post:repost']['logContext'], 236 240 ) { 241 + const {getAgent} = useAgent() 237 242 return useMutation< 238 243 {uri: string}, // responds with the uri of the repost 239 244 Error, ··· 252 257 function usePostUnrepostMutation( 253 258 logContext: LogEvents['post:unrepost']['logContext'], 254 259 ) { 260 + const {getAgent} = useAgent() 255 261 return useMutation<void, Error, {postUri: string; repostUri: string}>({ 256 262 mutationFn: ({repostUri}) => { 257 263 logEvent('post:unrepost', {logContext}) ··· 265 271 266 272 export function usePostDeleteMutation() { 267 273 const queryClient = useQueryClient() 274 + const {getAgent} = useAgent() 268 275 return useMutation<void, Error, {uri: string}>({ 269 276 mutationFn: async ({uri}) => { 270 277 await getAgent().deletePost(uri)
+17 -1
src/state/queries/preferences/index.ts
··· 22 22 ThreadViewPreferences, 23 23 UsePreferencesQueryResponse, 24 24 } from '#/state/queries/preferences/types' 25 - import {getAgent, useSession} from '#/state/session' 25 + import {useAgent, useSession} from '#/state/session' 26 26 import {saveLabelers} from '#/state/session/agent-config' 27 27 28 28 export * from '#/state/queries/preferences/const' ··· 33 33 export const preferencesQueryKey = [preferencesQueryKeyRoot] 34 34 35 35 export function usePreferencesQuery() { 36 + const {getAgent} = useAgent() 36 37 return useQuery({ 37 38 staleTime: STALE.SECONDS.FIFTEEN, 38 39 structuralSharing: true, ··· 118 119 119 120 export function useClearPreferencesMutation() { 120 121 const queryClient = useQueryClient() 122 + const {getAgent} = useAgent() 121 123 122 124 return useMutation({ 123 125 mutationFn: async () => { ··· 131 133 } 132 134 133 135 export function usePreferencesSetContentLabelMutation() { 136 + const {getAgent} = useAgent() 134 137 const queryClient = useQueryClient() 135 138 136 139 return useMutation< ··· 150 153 151 154 export function useSetContentLabelMutation() { 152 155 const queryClient = useQueryClient() 156 + const {getAgent} = useAgent() 153 157 154 158 return useMutation({ 155 159 mutationFn: async ({ ··· 172 176 173 177 export function usePreferencesSetAdultContentMutation() { 174 178 const queryClient = useQueryClient() 179 + const {getAgent} = useAgent() 175 180 176 181 return useMutation<void, unknown, {enabled: boolean}>({ 177 182 mutationFn: async ({enabled}) => { ··· 186 191 187 192 export function usePreferencesSetBirthDateMutation() { 188 193 const queryClient = useQueryClient() 194 + const {getAgent} = useAgent() 189 195 190 196 return useMutation<void, unknown, {birthDate: Date}>({ 191 197 mutationFn: async ({birthDate}: {birthDate: Date}) => { ··· 200 206 201 207 export function useSetFeedViewPreferencesMutation() { 202 208 const queryClient = useQueryClient() 209 + const {getAgent} = useAgent() 203 210 204 211 return useMutation<void, unknown, Partial<BskyFeedViewPreference>>({ 205 212 mutationFn: async prefs => { ··· 214 221 215 222 export function useSetThreadViewPreferencesMutation() { 216 223 const queryClient = useQueryClient() 224 + const {getAgent} = useAgent() 217 225 218 226 return useMutation<void, unknown, Partial<ThreadViewPreferences>>({ 219 227 mutationFn: async prefs => { ··· 228 236 229 237 export function useSetSaveFeedsMutation() { 230 238 const queryClient = useQueryClient() 239 + const {getAgent} = useAgent() 231 240 232 241 return useMutation< 233 242 void, ··· 246 255 247 256 export function useSaveFeedMutation() { 248 257 const queryClient = useQueryClient() 258 + const {getAgent} = useAgent() 249 259 250 260 return useMutation<void, unknown, {uri: string}>({ 251 261 mutationFn: async ({uri}) => { ··· 261 271 262 272 export function useRemoveFeedMutation() { 263 273 const queryClient = useQueryClient() 274 + const {getAgent} = useAgent() 264 275 265 276 return useMutation<void, unknown, {uri: string}>({ 266 277 mutationFn: async ({uri}) => { ··· 276 287 277 288 export function usePinFeedMutation() { 278 289 const queryClient = useQueryClient() 290 + const {getAgent} = useAgent() 279 291 280 292 return useMutation<void, unknown, {uri: string}>({ 281 293 mutationFn: async ({uri}) => { ··· 291 303 292 304 export function useUnpinFeedMutation() { 293 305 const queryClient = useQueryClient() 306 + const {getAgent} = useAgent() 294 307 295 308 return useMutation<void, unknown, {uri: string}>({ 296 309 mutationFn: async ({uri}) => { ··· 306 319 307 320 export function useUpsertMutedWordsMutation() { 308 321 const queryClient = useQueryClient() 322 + const {getAgent} = useAgent() 309 323 310 324 return useMutation({ 311 325 mutationFn: async (mutedWords: AppBskyActorDefs.MutedWord[]) => { ··· 320 334 321 335 export function useUpdateMutedWordMutation() { 322 336 const queryClient = useQueryClient() 337 + const {getAgent} = useAgent() 323 338 324 339 return useMutation({ 325 340 mutationFn: async (mutedWord: AppBskyActorDefs.MutedWord) => { ··· 334 349 335 350 export function useRemoveMutedWordMutation() { 336 351 const queryClient = useQueryClient() 352 + const {getAgent} = useAgent() 337 353 338 354 return useMutation({ 339 355 mutationFn: async (mutedWord: AppBskyActorDefs.MutedWord) => {
+2 -1
src/state/queries/profile-feedgens.ts
··· 1 1 import {AppBskyFeedGetActorFeeds} from '@atproto/api' 2 2 import {InfiniteData, QueryKey, useInfiniteQuery} from '@tanstack/react-query' 3 3 4 - import {getAgent} from '#/state/session' 4 + import {useAgent} from '#/state/session' 5 5 6 6 const PAGE_SIZE = 30 7 7 type RQPageParam = string | undefined ··· 15 15 opts?: {enabled?: boolean}, 16 16 ) { 17 17 const enabled = opts?.enabled !== false 18 + const {getAgent} = useAgent() 18 19 return useInfiniteQuery< 19 20 AppBskyFeedGetActorFeeds.OutputSchema, 20 21 Error,
+2 -1
src/state/queries/profile-followers.ts
··· 6 6 useInfiniteQuery, 7 7 } from '@tanstack/react-query' 8 8 9 - import {getAgent} from '#/state/session' 9 + import {useAgent} from '#/state/session' 10 10 11 11 const PAGE_SIZE = 30 12 12 type RQPageParam = string | undefined ··· 15 15 export const RQKEY = (did: string) => [RQKEY_ROOT, did] 16 16 17 17 export function useProfileFollowersQuery(did: string | undefined) { 18 + const {getAgent} = useAgent() 18 19 return useInfiniteQuery< 19 20 AppBskyGraphGetFollowers.OutputSchema, 20 21 Error,
+2 -1
src/state/queries/profile-follows.ts
··· 7 7 } from '@tanstack/react-query' 8 8 9 9 import {STALE} from '#/state/queries' 10 - import {getAgent} from '#/state/session' 10 + import {useAgent} from '#/state/session' 11 11 12 12 const PAGE_SIZE = 30 13 13 type RQPageParam = string | undefined ··· 17 17 export const RQKEY = (did: string) => [RQKEY_ROOT, did] 18 18 19 19 export function useProfileFollowsQuery(did: string | undefined) { 20 + const {getAgent} = useAgent() 20 21 return useInfiniteQuery< 21 22 AppBskyGraphGetFollows.OutputSchema, 22 23 Error,
+2 -1
src/state/queries/profile-lists.ts
··· 1 1 import {AppBskyGraphGetLists} from '@atproto/api' 2 2 import {InfiniteData, QueryKey, useInfiniteQuery} from '@tanstack/react-query' 3 3 4 - import {getAgent} from '#/state/session' 4 + import {useAgent} from '#/state/session' 5 5 6 6 const PAGE_SIZE = 30 7 7 type RQPageParam = string | undefined ··· 11 11 12 12 export function useProfileListsQuery(did: string, opts?: {enabled?: boolean}) { 13 13 const enabled = opts?.enabled !== false 14 + const {getAgent} = useAgent() 14 15 return useInfiniteQuery< 15 16 AppBskyGraphGetLists.OutputSchema, 16 17 Error,
+12 -2
src/state/queries/profile.ts
··· 26 26 import {STALE} from '#/state/queries' 27 27 import {resetProfilePostsQueries} from '#/state/queries/post-feed' 28 28 import {updateProfileShadow} from '../cache/profile-shadow' 29 - import {getAgent, useSession} from '../session' 29 + import {useAgent, useSession} from '../session' 30 30 import {RQKEY as RQKEY_MY_BLOCKED} from './my-blocked-accounts' 31 31 import {RQKEY as RQKEY_MY_MUTED} from './my-muted-accounts' 32 32 import {ThreadNode} from './post-thread' ··· 54 54 staleTime?: number 55 55 }) { 56 56 const queryClient = useQueryClient() 57 + const {getAgent} = useAgent() 57 58 return useQuery<AppBskyActorDefs.ProfileViewDetailed>({ 58 59 // WARNING 59 60 // this staleTime is load-bearing ··· 78 79 } 79 80 80 81 export function useProfilesQuery({handles}: {handles: string[]}) { 82 + const {getAgent} = useAgent() 81 83 return useQuery({ 82 84 staleTime: STALE.MINUTES.FIVE, 83 85 queryKey: profilesQueryKey(handles), ··· 89 91 } 90 92 91 93 export function usePrefetchProfileQuery() { 94 + const {getAgent} = useAgent() 92 95 const queryClient = useQueryClient() 93 96 const prefetchProfileQuery = useCallback( 94 97 async (did: string) => { ··· 100 103 }, 101 104 }) 102 105 }, 103 - [queryClient], 106 + [queryClient, getAgent], 104 107 ) 105 108 return prefetchProfileQuery 106 109 } ··· 116 119 } 117 120 export function useProfileUpdateMutation() { 118 121 const queryClient = useQueryClient() 122 + const {getAgent} = useAgent() 119 123 return useMutation<void, Error, ProfileUpdateParams>({ 120 124 mutationFn: async ({ 121 125 profile, ··· 257 261 profile: Shadow<AppBskyActorDefs.ProfileViewDetailed>, 258 262 ) { 259 263 const {currentAccount} = useSession() 264 + const {getAgent} = useAgent() 260 265 const queryClient = useQueryClient() 261 266 return useMutation<{uri: string; cid: string}, Error, {did: string}>({ 262 267 mutationFn: async ({did}) => { ··· 283 288 function useProfileUnfollowMutation( 284 289 logContext: LogEvents['profile:unfollow']['logContext'], 285 290 ) { 291 + const {getAgent} = useAgent() 286 292 return useMutation<void, Error, {did: string; followUri: string}>({ 287 293 mutationFn: async ({followUri}) => { 288 294 logEvent('profile:unfollow', {logContext}) ··· 343 349 344 350 function useProfileMuteMutation() { 345 351 const queryClient = useQueryClient() 352 + const {getAgent} = useAgent() 346 353 return useMutation<void, Error, {did: string}>({ 347 354 mutationFn: async ({did}) => { 348 355 await getAgent().mute(did) ··· 355 362 356 363 function useProfileUnmuteMutation() { 357 364 const queryClient = useQueryClient() 365 + const {getAgent} = useAgent() 358 366 return useMutation<void, Error, {did: string}>({ 359 367 mutationFn: async ({did}) => { 360 368 await getAgent().unmute(did) ··· 421 429 422 430 function useProfileBlockMutation() { 423 431 const {currentAccount} = useSession() 432 + const {getAgent} = useAgent() 424 433 const queryClient = useQueryClient() 425 434 return useMutation<{uri: string; cid: string}, Error, {did: string}>({ 426 435 mutationFn: async ({did}) => { ··· 441 450 442 451 function useProfileUnblockMutation() { 443 452 const {currentAccount} = useSession() 453 + const {getAgent} = useAgent() 444 454 const queryClient = useQueryClient() 445 455 return useMutation<void, Error, {did: string; blockUri: string}>({ 446 456 mutationFn: async ({blockUri}) => {
+2 -1
src/state/queries/resolve-uri.ts
··· 2 2 import {useQuery, useQueryClient, UseQueryResult} from '@tanstack/react-query' 3 3 4 4 import {STALE} from '#/state/queries' 5 - import {getAgent} from '#/state/session' 5 + import {useAgent} from '#/state/session' 6 6 import {profileBasicQueryKey as RQKEY_PROFILE_BASIC} from './profile' 7 7 8 8 const RQKEY_ROOT = 'resolved-did' ··· 24 24 25 25 export function useResolveDidQuery(didOrHandle: string | undefined) { 26 26 const queryClient = useQueryClient() 27 + const {getAgent} = useAgent() 27 28 28 29 return useQuery<string, Error>({ 29 30 staleTime: STALE.HOURS.ONE,
+2 -1
src/state/queries/search-posts.ts
··· 6 6 useInfiniteQuery, 7 7 } from '@tanstack/react-query' 8 8 9 - import {getAgent} from '#/state/session' 9 + import {useAgent} from '#/state/session' 10 10 import {embedViewRecordToPostView, getEmbeddedPost} from './util' 11 11 12 12 const searchPostsQueryKeyRoot = 'search-posts' ··· 25 25 sort?: 'top' | 'latest' 26 26 enabled?: boolean 27 27 }) { 28 + const {getAgent} = useAgent() 28 29 return useInfiniteQuery< 29 30 AppBskyFeedSearchPosts.OutputSchema, 30 31 Error,
+2 -1
src/state/queries/suggested-feeds.ts
··· 2 2 import {InfiniteData, QueryKey, useInfiniteQuery} from '@tanstack/react-query' 3 3 4 4 import {STALE} from '#/state/queries' 5 - import {getAgent} from '#/state/session' 5 + import {useAgent} from '#/state/session' 6 6 7 7 const suggestedFeedsQueryKeyRoot = 'suggestedFeeds' 8 8 export const suggestedFeedsQueryKey = [suggestedFeedsQueryKeyRoot] 9 9 10 10 export function useSuggestedFeedsQuery() { 11 + const {getAgent} = useAgent() 11 12 return useInfiniteQuery< 12 13 AppBskyFeedGetSuggestedFeeds.OutputSchema, 13 14 Error,
+3 -1
src/state/queries/suggested-follows.ts
··· 14 14 15 15 import {STALE} from '#/state/queries' 16 16 import {useModerationOpts} from '#/state/queries/preferences' 17 - import {getAgent, useSession} from '#/state/session' 17 + import {useAgent, useSession} from '#/state/session' 18 18 19 19 const suggestedFollowsQueryKeyRoot = 'suggested-follows' 20 20 const suggestedFollowsQueryKey = [suggestedFollowsQueryKeyRoot] ··· 27 27 28 28 export function useSuggestedFollowsQuery() { 29 29 const {currentAccount} = useSession() 30 + const {getAgent} = useAgent() 30 31 const moderationOpts = useModerationOpts() 31 32 32 33 return useInfiniteQuery< ··· 77 78 } 78 79 79 80 export function useSuggestedFollowsByActorQuery({did}: {did: string}) { 81 + const {getAgent} = useAgent() 80 82 return useQuery<AppBskyGraphGetSuggestedFollowsByActor.OutputSchema, Error>({ 81 83 queryKey: suggestedFollowsByActorQueryKey(did), 82 84 queryFn: async () => {
+5 -7
src/state/session/index.tsx
··· 23 23 24 24 let __globalAgent: BskyAgent = PUBLIC_BSKY_AGENT 25 25 26 - /** 27 - * NOTE 28 - * Never hold on to the object returned by this function. 29 - * Call `getAgent()` at the time of invocation to ensure 30 - * that you never have a stale agent. 31 - */ 32 - export function getAgent() { 26 + function __getAgent() { 33 27 return __globalAgent 28 + } 29 + 30 + export function useAgent() { 31 + return React.useMemo(() => ({getAgent: __getAgent}), []) 34 32 } 35 33 36 34 export type SessionAccount = persisted.PersistedAccount
+2 -1
src/view/com/composer/Composer.tsx
··· 32 32 import {useProfileQuery} from '#/state/queries/profile' 33 33 import {Gif} from '#/state/queries/tenor' 34 34 import {ThreadgateSetting} from '#/state/queries/threadgate' 35 - import {getAgent, useSession} from '#/state/session' 35 + import {useAgent, useSession} from '#/state/session' 36 36 import {useComposerControls} from '#/state/shell/composer' 37 37 import {useAnalytics} from 'lib/analytics/analytics' 38 38 import * as apilib from 'lib/api/index' ··· 83 83 imageUris: initImageUris, 84 84 }: Props) { 85 85 const {currentAccount} = useSession() 86 + const {getAgent} = useAgent() 86 87 const {data: currentProfile} = useProfileQuery({did: currentAccount!.did}) 87 88 const {isModalActive} = useModals() 88 89 const {closeComposer} = useComposerControls()
+5 -3
src/view/com/composer/useExternalLinkFetch.e2e.ts
··· 1 - import {useState, useEffect} from 'react' 1 + import {useEffect, useState} from 'react' 2 + 3 + import {useAgent} from '#/state/session' 2 4 import * as apilib from 'lib/api/index' 3 5 import {getLinkMeta} from 'lib/link-meta/link-meta' 4 6 import {ComposerOpts} from 'state/shell/composer' 5 - import {getAgent} from '#/state/session' 6 7 7 8 export function useExternalLinkFetch({}: { 8 9 setQuote: (opts: ComposerOpts['quote']) => void 9 10 }) { 11 + const {getAgent} = useAgent() 10 12 const [extLink, setExtLink] = useState<apilib.ExternalEmbedDraft | undefined>( 11 13 undefined, 12 14 ) ··· 39 41 }) 40 42 } 41 43 return cleanup 42 - }, [extLink]) 44 + }, [extLink, getAgent]) 43 45 44 46 return {extLink, setExtLink} 45 47 }
+13 -11
src/view/com/composer/useExternalLinkFetch.ts
··· 1 - import {useState, useEffect} from 'react' 2 - import {ImageModel} from 'state/models/media/image' 1 + import {useEffect, useState} from 'react' 2 + 3 + import {logger} from '#/logger' 4 + import {useFetchDid} from '#/state/queries/handle' 5 + import {useGetPost} from '#/state/queries/post' 6 + import {useAgent} from '#/state/session' 3 7 import * as apilib from 'lib/api/index' 4 - import {getLinkMeta} from 'lib/link-meta/link-meta' 8 + import {POST_IMG_MAX} from 'lib/constants' 5 9 import { 6 - getPostAsQuote, 7 10 getFeedAsEmbed, 8 11 getListAsEmbed, 12 + getPostAsQuote, 9 13 } from 'lib/link-meta/bsky' 14 + import {getLinkMeta} from 'lib/link-meta/link-meta' 10 15 import {downloadAndResize} from 'lib/media/manip' 11 16 import { 12 - isBskyPostUrl, 13 17 isBskyCustomFeedUrl, 14 18 isBskyListUrl, 19 + isBskyPostUrl, 15 20 } from 'lib/strings/url-helpers' 21 + import {ImageModel} from 'state/models/media/image' 16 22 import {ComposerOpts} from 'state/shell/composer' 17 - import {POST_IMG_MAX} from 'lib/constants' 18 - import {logger} from '#/logger' 19 - import {getAgent} from '#/state/session' 20 - import {useGetPost} from '#/state/queries/post' 21 - import {useFetchDid} from '#/state/queries/handle' 22 23 23 24 export function useExternalLinkFetch({ 24 25 setQuote, ··· 30 31 ) 31 32 const getPost = useGetPost() 32 33 const fetchDid = useFetchDid() 34 + const {getAgent} = useAgent() 33 35 34 36 useEffect(() => { 35 37 let aborted = false ··· 135 137 }) 136 138 } 137 139 return cleanup 138 - }, [extLink, setQuote, getPost, fetchDid]) 140 + }, [extLink, setQuote, getPost, fetchDid, getAgent]) 139 141 140 142 return {extLink, setExtLink} 141 143 }
+13 -11
src/view/com/modals/ChangeEmail.tsx
··· 1 1 import React, {useState} from 'react' 2 2 import {ActivityIndicator, SafeAreaView, StyleSheet, View} from 'react-native' 3 - import {ScrollView, TextInput} from './util' 4 - import {Text} from '../util/text/Text' 5 - import {Button} from '../util/forms/Button' 6 - import {ErrorMessage} from '../util/error/ErrorMessage' 7 - import * as Toast from '../util/Toast' 8 - import {s, colors} from 'lib/styles' 3 + import {msg, Trans} from '@lingui/macro' 4 + import {useLingui} from '@lingui/react' 5 + 6 + import {useModalControls} from '#/state/modals' 7 + import {useAgent, useSession, useSessionApi} from '#/state/session' 9 8 import {usePalette} from 'lib/hooks/usePalette' 10 - import {isWeb} from 'platform/detection' 11 9 import {useWebMediaQueries} from 'lib/hooks/useWebMediaQueries' 12 10 import {cleanError} from 'lib/strings/errors' 13 - import {Trans, msg} from '@lingui/macro' 14 - import {useLingui} from '@lingui/react' 15 - import {useModalControls} from '#/state/modals' 16 - import {useSession, useSessionApi, getAgent} from '#/state/session' 11 + import {colors, s} from 'lib/styles' 12 + import {isWeb} from 'platform/detection' 13 + import {ErrorMessage} from '../util/error/ErrorMessage' 14 + import {Button} from '../util/forms/Button' 15 + import {Text} from '../util/text/Text' 16 + import * as Toast from '../util/Toast' 17 + import {ScrollView, TextInput} from './util' 17 18 18 19 enum Stages { 19 20 InputEmail, ··· 26 27 export function Component() { 27 28 const pal = usePalette('default') 28 29 const {currentAccount} = useSession() 30 + const {getAgent} = useAgent() 29 31 const {updateCurrentAccount} = useSessionApi() 30 32 const {_} = useLingui() 31 33 const [stage, setStage] = useState<Stages>(Stages.InputEmail)
+2 -1
src/view/com/modals/ChangeHandle.tsx
··· 16 16 import {useFetchDid, useUpdateHandleMutation} from '#/state/queries/handle' 17 17 import {useServiceQuery} from '#/state/queries/service' 18 18 import { 19 - getAgent, 20 19 SessionAccount, 20 + useAgent, 21 21 useSession, 22 22 useSessionApi, 23 23 } from '#/state/session' ··· 40 40 41 41 export function Component(props: Props) { 42 42 const {currentAccount} = useSession() 43 + const {getAgent} = useAgent() 43 44 const { 44 45 isLoading, 45 46 data: serviceInfo,
+15 -13
src/view/com/modals/ChangePassword.tsx
··· 6 6 TouchableOpacity, 7 7 View, 8 8 } from 'react-native' 9 - import {ScrollView} from './util' 10 9 import {FontAwesomeIcon} from '@fortawesome/react-native-fontawesome' 11 - import {TextInput} from './util' 12 - import {Text} from '../util/text/Text' 13 - import {Button} from '../util/forms/Button' 14 - import {ErrorMessage} from '../util/error/ErrorMessage' 15 - import {s, colors} from 'lib/styles' 10 + import {msg, Trans} from '@lingui/macro' 11 + import {useLingui} from '@lingui/react' 12 + import * as EmailValidator from 'email-validator' 13 + 14 + import {logger} from '#/logger' 15 + import {useModalControls} from '#/state/modals' 16 + import {useAgent, useSession} from '#/state/session' 16 17 import {usePalette} from 'lib/hooks/usePalette' 17 - import {isAndroid, isWeb} from 'platform/detection' 18 18 import {useWebMediaQueries} from 'lib/hooks/useWebMediaQueries' 19 19 import {cleanError, isNetworkError} from 'lib/strings/errors' 20 20 import {checkAndFormatResetCode} from 'lib/strings/password' 21 - import {Trans, msg} from '@lingui/macro' 22 - import {useLingui} from '@lingui/react' 23 - import {useModalControls} from '#/state/modals' 24 - import {useSession, getAgent} from '#/state/session' 25 - import * as EmailValidator from 'email-validator' 26 - import {logger} from '#/logger' 21 + import {colors, s} from 'lib/styles' 22 + import {isAndroid, isWeb} from 'platform/detection' 23 + import {ErrorMessage} from '../util/error/ErrorMessage' 24 + import {Button} from '../util/forms/Button' 25 + import {Text} from '../util/text/Text' 26 + import {ScrollView} from './util' 27 + import {TextInput} from './util' 27 28 28 29 enum Stages { 29 30 RequestCode, ··· 36 37 export function Component() { 37 38 const pal = usePalette('default') 38 39 const {currentAccount} = useSession() 40 + const {getAgent} = useAgent() 39 41 const {_} = useLingui() 40 42 const [stage, setStage] = useState<Stages>(Stages.RequestCode) 41 43 const [isProcessing, setIsProcessing] = useState<boolean>(false)
+3 -1
src/view/com/modals/CreateOrEditList.tsx
··· 25 25 useListCreateMutation, 26 26 useListMetadataMutation, 27 27 } from '#/state/queries/list' 28 - import {getAgent} from '#/state/session' 28 + import {useAgent} from '#/state/session' 29 29 import {useAnalytics} from 'lib/analytics/analytics' 30 30 import {usePalette} from 'lib/hooks/usePalette' 31 31 import {useWebMediaQueries} from 'lib/hooks/useWebMediaQueries' ··· 62 62 const {_} = useLingui() 63 63 const listCreateMutation = useListCreateMutation() 64 64 const listMetadataMutation = useListMetadataMutation() 65 + const {getAgent} = useAgent() 65 66 66 67 const activePurpose = useMemo(() => { 67 68 if (list?.purpose) { ··· 228 229 listMetadataMutation, 229 230 listCreateMutation, 230 231 _, 232 + getAgent, 231 233 ]) 232 234 233 235 return (
+2 -1
src/view/com/modals/DeleteAccount.tsx
··· 11 11 import {useLingui} from '@lingui/react' 12 12 13 13 import {useModalControls} from '#/state/modals' 14 - import {getAgent, useSession, useSessionApi} from '#/state/session' 14 + import {useAgent, useSession, useSessionApi} from '#/state/session' 15 15 import {usePalette} from 'lib/hooks/usePalette' 16 16 import {useWebMediaQueries} from 'lib/hooks/useWebMediaQueries' 17 17 import {cleanError} from 'lib/strings/errors' ··· 30 30 const pal = usePalette('default') 31 31 const theme = useTheme() 32 32 const {currentAccount} = useSession() 33 + const {getAgent} = useAgent() 33 34 const {clearCurrentAccount, removeAccount} = useSessionApi() 34 35 const {_} = useLingui() 35 36 const {closeModal} = useModalControls()
+2 -1
src/view/com/modals/VerifyEmail.tsx
··· 13 13 14 14 import {logger} from '#/logger' 15 15 import {useModalControls} from '#/state/modals' 16 - import {getAgent, useSession, useSessionApi} from '#/state/session' 16 + import {useAgent, useSession, useSessionApi} from '#/state/session' 17 17 import {usePalette} from 'lib/hooks/usePalette' 18 18 import {useWebMediaQueries} from 'lib/hooks/useWebMediaQueries' 19 19 import {cleanError} from 'lib/strings/errors' ··· 41 41 onSuccess?: () => void 42 42 }) { 43 43 const pal = usePalette('default') 44 + const {getAgent} = useAgent() 44 45 const {currentAccount} = useSession() 45 46 const {updateCurrentAccount} = useSessionApi() 46 47 const {_} = useLingui()
+3 -2
src/view/screens/Profile.tsx
··· 19 19 import {useModerationOpts} from '#/state/queries/preferences' 20 20 import {useProfileQuery} from '#/state/queries/profile' 21 21 import {useResolveDidQuery} from '#/state/queries/resolve-uri' 22 - import {getAgent, useSession} from '#/state/session' 22 + import {useAgent, useSession} from '#/state/session' 23 23 import {useSetDrawerSwipeDisabled, useSetMinimalShellMode} from '#/state/shell' 24 24 import {useComposerControls} from '#/state/shell/composer' 25 25 import {useAnalytics} from 'lib/analytics/analytics' ··· 472 472 } 473 473 474 474 function useRichText(text: string): [RichTextAPI, boolean] { 475 + const {getAgent} = useAgent() 475 476 const [prevText, setPrevText] = React.useState(text) 476 477 const [rawRT, setRawRT] = React.useState(() => new RichTextAPI({text})) 477 478 const [resolvedRT, setResolvedRT] = React.useState<RichTextAPI | null>(null) ··· 495 496 return () => { 496 497 ignore = true 497 498 } 498 - }, [text]) 499 + }, [text, getAgent]) 499 500 const isResolving = resolvedRT === null 500 501 return [resolvedRT ?? rawRT, isResolving] 501 502 }
+2 -1
src/view/screens/Settings/DisableEmail2FADialog.tsx
··· 5 5 6 6 import {cleanError} from '#/lib/strings/errors' 7 7 import {isNative} from '#/platform/detection' 8 - import {getAgent, useSession, useSessionApi} from '#/state/session' 8 + import {useAgent, useSession, useSessionApi} from '#/state/session' 9 9 import {ErrorMessage} from '#/view/com/util/error/ErrorMessage' 10 10 import * as Toast from '#/view/com/util/Toast' 11 11 import {atoms as a, useBreakpoints, useTheme} from '#/alf' ··· 31 31 const {gtMobile} = useBreakpoints() 32 32 const {currentAccount} = useSession() 33 33 const {updateCurrentAccount} = useSessionApi() 34 + const {getAgent} = useAgent() 34 35 35 36 const [stage, setStage] = useState<Stages>(Stages.Email) 36 37 const [confirmationCode, setConfirmationCode] = useState<string>('')
+3 -2
src/view/screens/Settings/Email2FAToggle.tsx
··· 3 3 import {useLingui} from '@lingui/react' 4 4 5 5 import {useModalControls} from '#/state/modals' 6 - import {getAgent, useSession, useSessionApi} from '#/state/session' 6 + import {useAgent, useSession, useSessionApi} from '#/state/session' 7 7 import {ToggleButton} from 'view/com/util/forms/ToggleButton' 8 8 import {useDialogControl} from '#/components/Dialog' 9 9 import {DisableEmail2FADialog} from './DisableEmail2FADialog' ··· 14 14 const {updateCurrentAccount} = useSessionApi() 15 15 const {openModal} = useModalControls() 16 16 const disableDialogCtrl = useDialogControl() 17 + const {getAgent} = useAgent() 17 18 18 19 const enableEmailAuthFactor = React.useCallback(async () => { 19 20 if (currentAccount?.email) { ··· 25 26 emailAuthFactor: true, 26 27 }) 27 28 } 28 - }, [currentAccount, updateCurrentAccount]) 29 + }, [currentAccount, updateCurrentAccount, getAgent]) 29 30 30 31 const onToggle = React.useCallback(() => { 31 32 if (!currentAccount) {
+3 -2
src/view/screens/Settings/ExportCarDialog.tsx
··· 3 3 import {msg, Trans} from '@lingui/macro' 4 4 import {useLingui} from '@lingui/react' 5 5 6 - import {getAgent, useSession} from '#/state/session' 6 + import {useAgent, useSession} from '#/state/session' 7 7 import {atoms as a, useBreakpoints, useTheme} from '#/alf' 8 8 import {Button, ButtonText} from '#/components/Button' 9 9 import * as Dialog from '#/components/Dialog' ··· 19 19 const t = useTheme() 20 20 const {gtMobile} = useBreakpoints() 21 21 const {currentAccount} = useSession() 22 + const {getAgent} = useAgent() 22 23 23 24 const downloadUrl = React.useMemo(() => { 24 25 const agent = getAgent() ··· 30 31 url.pathname = '/xrpc/com.atproto.sync.getRepo' 31 32 url.searchParams.set('did', agent.session.did) 32 33 return url.toString() 33 - }, [currentAccount]) 34 + }, [currentAccount, getAgent]) 34 35 35 36 return ( 36 37 <Dialog.Outer control={control}>
+3 -2
src/view/shell/index.tsx
··· 13 13 import {StatusBar} from 'expo-status-bar' 14 14 import {useNavigationState} from '@react-navigation/native' 15 15 16 - import {getAgent, useSession} from '#/state/session' 16 + import {useAgent, useSession} from '#/state/session' 17 17 import { 18 18 useIsDrawerOpen, 19 19 useIsDrawerSwipeDisabled, ··· 57 57 ) 58 58 const canGoBack = useNavigationState(state => !isStateAtTabRoot(state)) 59 59 const {hasSession, currentAccount} = useSession() 60 + const {getAgent} = useAgent() 60 61 const closeAnyActiveElement = useCloseAnyActiveElement() 61 62 const {importantForAccessibility} = useDialogStateContext() 62 63 // start undefined ··· 85 86 ) 86 87 return unsub 87 88 } 88 - }, [currentAccount]) 89 + }, [currentAccount, getAgent]) 89 90 90 91 return ( 91 92 <>