about summary refs log tree commit diff
path: root/src/state/queries
diff options
context:
space:
mode:
Diffstat (limited to 'src/state/queries')
-rw-r--r--src/state/queries/actor-autocomplete.ts2
-rw-r--r--src/state/queries/app-passwords.ts1
-rw-r--r--src/state/queries/feed.ts3
-rw-r--r--src/state/queries/invites.ts1
-rw-r--r--src/state/queries/list.ts15
-rw-r--r--src/state/queries/notifications/types.ts1
-rw-r--r--src/state/queries/notifications/unread.tsx37
-rw-r--r--src/state/queries/post-feed.ts11
-rw-r--r--src/state/queries/preferences/index.ts2
-rw-r--r--src/state/queries/profile.ts2
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 || ''})