diff options
Diffstat (limited to 'src/state/queries')
-rw-r--r-- | src/state/queries/actor-autocomplete.ts | 2 | ||||
-rw-r--r-- | src/state/queries/app-passwords.ts | 1 | ||||
-rw-r--r-- | src/state/queries/feed.ts | 3 | ||||
-rw-r--r-- | src/state/queries/invites.ts | 1 | ||||
-rw-r--r-- | src/state/queries/list.ts | 15 | ||||
-rw-r--r-- | src/state/queries/notifications/types.ts | 1 | ||||
-rw-r--r-- | src/state/queries/notifications/unread.tsx | 37 | ||||
-rw-r--r-- | src/state/queries/post-feed.ts | 11 | ||||
-rw-r--r-- | src/state/queries/preferences/index.ts | 2 | ||||
-rw-r--r-- | src/state/queries/profile.ts | 2 |
10 files changed, 63 insertions, 12 deletions
diff --git a/src/state/queries/actor-autocomplete.ts b/src/state/queries/actor-autocomplete.ts index 785e29765..ba9f97004 100644 --- a/src/state/queries/actor-autocomplete.ts +++ b/src/state/queries/actor-autocomplete.ts @@ -24,6 +24,8 @@ export function useActorAutocompleteQuery(prefix: string) { const {data: follows, isFetching} = useMyFollowsQuery() const moderationOpts = useModerationOpts() + prefix = prefix.toLowerCase() + return useQuery<AppBskyActorDefs.ProfileViewBasic[]>({ staleTime: STALE.MINUTES.ONE, queryKey: RQKEY(prefix || ''), diff --git a/src/state/queries/app-passwords.ts b/src/state/queries/app-passwords.ts index 4b9e09a8d..014244f01 100644 --- a/src/state/queries/app-passwords.ts +++ b/src/state/queries/app-passwords.ts @@ -9,7 +9,6 @@ export const RQKEY = () => ['app-passwords'] export function useAppPasswordsQuery() { return useQuery({ staleTime: STALE.MINUTES.FIVE, - refetchInterval: STALE.MINUTES.ONE, queryKey: RQKEY(), queryFn: async () => { const res = await getAgent().com.atproto.server.listAppPasswords({}) diff --git a/src/state/queries/feed.ts b/src/state/queries/feed.ts index 7a55b4e18..4acc7179a 100644 --- a/src/state/queries/feed.ts +++ b/src/state/queries/feed.ts @@ -272,7 +272,8 @@ export function usePinnedFeedsInfos(): { }, }) } catch (e) { - logger.warn(`usePinnedFeedsInfos: failed to fetch ${uri}`, { + // expected failure + logger.info(`usePinnedFeedsInfos: failed to fetch ${uri}`, { error: e, }) } diff --git a/src/state/queries/invites.ts b/src/state/queries/invites.ts index bfea402e1..9ae9c707f 100644 --- a/src/state/queries/invites.ts +++ b/src/state/queries/invites.ts @@ -16,7 +16,6 @@ export type InviteCodesQueryResponse = Exclude< export function useInviteCodesQuery() { return useQuery({ staleTime: STALE.MINUTES.FIVE, - refetchInterval: STALE.MINUTES.FIVE, queryKey: ['inviteCodes'], queryFn: async () => { const res = await getAgent() diff --git a/src/state/queries/list.ts b/src/state/queries/list.ts index 013a69076..845658a27 100644 --- a/src/state/queries/list.ts +++ b/src/state/queries/list.ts @@ -3,6 +3,7 @@ import { AppBskyGraphGetList, AppBskyGraphList, AppBskyGraphDefs, + Facet, } from '@atproto/api' import {Image as RNImage} from 'react-native-image-crop-picker' import {useQuery, useMutation, useQueryClient} from '@tanstack/react-query' @@ -38,6 +39,7 @@ export interface ListCreateMutateParams { purpose: string name: string description: string + descriptionFacets: Facet[] | undefined avatar: RNImage | null | undefined } export function useListCreateMutation() { @@ -45,7 +47,13 @@ export function useListCreateMutation() { const queryClient = useQueryClient() return useMutation<{uri: string; cid: string}, Error, ListCreateMutateParams>( { - async mutationFn({purpose, name, description, avatar}) { + async mutationFn({ + purpose, + name, + description, + descriptionFacets, + avatar, + }) { if (!currentAccount) { throw new Error('Not logged in') } @@ -59,6 +67,7 @@ export function useListCreateMutation() { purpose, name, description, + descriptionFacets, avatar: undefined, createdAt: new Date().toISOString(), } @@ -93,6 +102,7 @@ export interface ListMetadataMutateParams { uri: string name: string description: string + descriptionFacets: Facet[] | undefined avatar: RNImage | null | undefined } export function useListMetadataMutation() { @@ -103,7 +113,7 @@ export function useListMetadataMutation() { Error, ListMetadataMutateParams >({ - async mutationFn({uri, name, description, avatar}) { + async mutationFn({uri, name, description, descriptionFacets, avatar}) { const {hostname, rkey} = new AtUri(uri) if (!currentAccount) { throw new Error('Not logged in') @@ -121,6 +131,7 @@ export function useListMetadataMutation() { // update the fields record.name = name record.description = description + record.descriptionFacets = descriptionFacets if (avatar) { const blobRes = await uploadBlob(getAgent(), avatar.path, avatar.mime) record.avatar = blobRes.data.blob diff --git a/src/state/queries/notifications/types.ts b/src/state/queries/notifications/types.ts index 86a9bb139..812236cf0 100644 --- a/src/state/queries/notifications/types.ts +++ b/src/state/queries/notifications/types.ts @@ -35,4 +35,5 @@ export interface CachedFeedPage { usableInFeed: boolean syncedAt: Date data: FeedPage | undefined + unreadCount: number } diff --git a/src/state/queries/notifications/unread.tsx b/src/state/queries/notifications/unread.tsx index abaabbf0e..a96b56225 100644 --- a/src/state/queries/notifications/unread.tsx +++ b/src/state/queries/notifications/unread.tsx @@ -15,6 +15,7 @@ import {useMutedThreads} from '#/state/muted-threads' import {RQKEY as RQKEY_NOTIFS} from './feed' import {logger} from '#/logger' import {truncateAndInvalidate} from '../util' +import {AppState} from 'react-native' const UPDATE_INTERVAL = 30 * 1e3 // 30sec @@ -24,7 +25,10 @@ type StateContext = string interface ApiContext { markAllRead: () => Promise<void> - checkUnread: (opts?: {invalidate?: boolean}) => Promise<void> + checkUnread: (opts?: { + invalidate?: boolean + isPoll?: boolean + }) => Promise<void> getCachedUnreadPage: () => FeedPage | undefined } @@ -49,6 +53,7 @@ export function Provider({children}: React.PropsWithChildren<{}>) { usableInFeed: false, syncedAt: new Date(), data: undefined, + unreadCount: 0, }) // periodic sync @@ -57,7 +62,10 @@ export function Provider({children}: React.PropsWithChildren<{}>) { return } checkUnreadRef.current() // fire on init - const interval = setInterval(checkUnreadRef.current, UPDATE_INTERVAL) + const interval = setInterval( + () => checkUnreadRef.current?.({isPoll: true}), + UPDATE_INTERVAL, + ) return () => clearInterval(interval) }, [hasSession]) @@ -68,6 +76,12 @@ export function Provider({children}: React.PropsWithChildren<{}>) { usableInFeed: false, syncedAt: new Date(), data: undefined, + unreadCount: + data.event === '30+' + ? 30 + : data.event === '' + ? 0 + : parseInt(data.event, 10) || 1, } setNumUnread(data.event) } @@ -94,9 +108,23 @@ export function Provider({children}: React.PropsWithChildren<{}>) { } }, - async checkUnread({invalidate}: {invalidate?: boolean} = {}) { + async checkUnread({ + invalidate, + isPoll, + }: {invalidate?: boolean; isPoll?: boolean} = {}) { try { if (!getAgent().session) return + if (AppState.currentState !== 'active') { + return + } + + // reduce polling if unread count is set + if (isPoll && cacheRef.current?.unreadCount !== 0) { + // if hit 30+ then don't poll, otherwise reduce polling by 50% + if (cacheRef.current?.unreadCount >= 30 || Math.random() >= 0.5) { + return + } + } // count const page = await fetchPage({ @@ -129,6 +157,7 @@ export function Provider({children}: React.PropsWithChildren<{}>) { usableInFeed: !!invalidate, // will be used immediately data: page, syncedAt: !lastIndexed || now > lastIndexed ? now : lastIndexed, + unreadCount, } // update & broadcast @@ -138,7 +167,7 @@ export function Provider({children}: React.PropsWithChildren<{}>) { } broadcast.postMessage({event: unreadCountStr}) } catch (e) { - logger.error('Failed to check unread notifications', {error: e}) + logger.warn('Failed to check unread notifications', {error: e}) } }, diff --git a/src/state/queries/post-feed.ts b/src/state/queries/post-feed.ts index 0e943622a..82acf3974 100644 --- a/src/state/queries/post-feed.ts +++ b/src/state/queries/post-feed.ts @@ -1,4 +1,5 @@ import React, {useCallback, useEffect, useRef} from 'react' +import {AppState} from 'react-native' import {AppBskyFeedDefs, AppBskyFeedPost, PostModeration} from '@atproto/api' import { useInfiniteQuery, @@ -17,6 +18,7 @@ import {LikesFeedAPI} from 'lib/api/feed/likes' import {CustomFeedAPI} from 'lib/api/feed/custom' import {ListFeedAPI} from 'lib/api/feed/list' import {MergeFeedAPI} from 'lib/api/feed/merge' +import {HomeFeedAPI} from '#/lib/api/feed/home' import {logger} from '#/logger' import {STALE} from '#/state/queries' import {precacheFeedPosts as precacheResolvedUris} from './resolve-uri' @@ -312,6 +314,9 @@ export async function pollLatest(page: FeedPage | undefined) { if (!page) { return false } + if (AppState.currentState !== 'active') { + return + } logger.debug('usePostFeedQuery: pollLatest') const post = await page.api.peekLatest() @@ -334,7 +339,11 @@ function createApi( feedTuners: FeedTunerFn[], ) { if (feedDesc === 'home') { - return new MergeFeedAPI(params, feedTuners) + if (params.mergeFeedEnabled) { + return new MergeFeedAPI(params, feedTuners) + } else { + return new HomeFeedAPI() + } } else if (feedDesc === 'following') { return new FollowingFeedAPI() } else if (feedDesc.startsWith('author')) { diff --git a/src/state/queries/preferences/index.ts b/src/state/queries/preferences/index.ts index a9aa7f26e..632d31a13 100644 --- a/src/state/queries/preferences/index.ts +++ b/src/state/queries/preferences/index.ts @@ -31,7 +31,7 @@ export function usePreferencesQuery() { return useQuery({ staleTime: STALE.SECONDS.FIFTEEN, structuralSharing: true, - refetchInterval: STALE.SECONDS.FIFTEEN, + refetchOnWindowFocus: true, queryKey: preferencesQueryKey, queryFn: async () => { const agent = getAgent() diff --git a/src/state/queries/profile.ts b/src/state/queries/profile.ts index 40ba0653c..21e2e5775 100644 --- a/src/state/queries/profile.ts +++ b/src/state/queries/profile.ts @@ -35,7 +35,7 @@ export function useProfileQuery({did}: {did: string | undefined}) { // if you remove it, the UI infinite-loops // -prf staleTime: isCurrentAccount ? STALE.SECONDS.THIRTY : STALE.MINUTES.FIVE, - refetchInterval: STALE.MINUTES.FIVE, + refetchOnWindowFocus: true, queryKey: RQKEY(did || ''), queryFn: async () => { const res = await getAgent().getProfile({actor: did || ''}) |