[SDK] Migrate the notifications cluster to the lex clients (#11362)
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
@@ -2,10 +2,10 @@ import {useMemo, useState} from 'react'
|
|||||||
import {View} from 'react-native'
|
import {View} from 'react-native'
|
||||||
import {
|
import {
|
||||||
type AppBskyNotificationDefs,
|
type AppBskyNotificationDefs,
|
||||||
type AppBskyNotificationListActivitySubscriptions,
|
|
||||||
type ModerationOpts,
|
type ModerationOpts,
|
||||||
type Un$Typed,
|
type Un$Typed,
|
||||||
} from '@atproto/api'
|
} from '@atproto/api'
|
||||||
|
import {type DidString} from '@atproto/syntax'
|
||||||
import {msg} from '@lingui/core/macro'
|
import {msg} from '@lingui/core/macro'
|
||||||
import {useLingui} from '@lingui/react'
|
import {useLingui} from '@lingui/react'
|
||||||
import {Trans} from '@lingui/react/macro'
|
import {Trans} from '@lingui/react/macro'
|
||||||
@@ -20,7 +20,7 @@ import {cleanError} from '#/lib/strings/errors'
|
|||||||
import {sanitizeHandle} from '#/lib/strings/handles'
|
import {sanitizeHandle} from '#/lib/strings/handles'
|
||||||
import {updateProfileShadow} from '#/state/cache/profile-shadow'
|
import {updateProfileShadow} from '#/state/cache/profile-shadow'
|
||||||
import {RQKEY_getActivitySubscriptions} from '#/state/queries/activity-subscriptions'
|
import {RQKEY_getActivitySubscriptions} from '#/state/queries/activity-subscriptions'
|
||||||
import {useAgent} from '#/state/session'
|
import {useAppviewClient} from '#/state/session'
|
||||||
import {atoms as a, platform, useTheme, web} from '#/alf'
|
import {atoms as a, platform, useTheme, web} from '#/alf'
|
||||||
import {Admonition} from '#/components/Admonition'
|
import {Admonition} from '#/components/Admonition'
|
||||||
import {
|
import {
|
||||||
@@ -37,6 +37,7 @@ import * as Toast from '#/components/Toast'
|
|||||||
import {Text} from '#/components/Typography'
|
import {Text} from '#/components/Typography'
|
||||||
import {useAnalytics} from '#/analytics'
|
import {useAnalytics} from '#/analytics'
|
||||||
import {IS_WEB} from '#/env'
|
import {IS_WEB} from '#/env'
|
||||||
|
import {app} from '#/lexicons'
|
||||||
import type * as bsky from '#/types/bsky'
|
import type * as bsky from '#/types/bsky'
|
||||||
|
|
||||||
export function SubscribeProfileDialog({
|
export function SubscribeProfileDialog({
|
||||||
@@ -74,7 +75,7 @@ function DialogInner({
|
|||||||
const ax = useAnalytics()
|
const ax = useAnalytics()
|
||||||
const {_} = useLingui()
|
const {_} = useLingui()
|
||||||
const t = useTheme()
|
const t = useTheme()
|
||||||
const agent = useAgent()
|
const client = useAppviewClient()
|
||||||
const control = Dialog.useDialogContext()
|
const control = Dialog.useDialogContext()
|
||||||
const queryClient = useQueryClient()
|
const queryClient = useQueryClient()
|
||||||
const initialState = parseActivitySubscription(
|
const initialState = parseActivitySubscription(
|
||||||
@@ -122,8 +123,9 @@ function DialogInner({
|
|||||||
mutationFn: async (
|
mutationFn: async (
|
||||||
activitySubscription: Un$Typed<AppBskyNotificationDefs.ActivitySubscription>,
|
activitySubscription: Un$Typed<AppBskyNotificationDefs.ActivitySubscription>,
|
||||||
) => {
|
) => {
|
||||||
await agent.app.bsky.notification.putActivitySubscription({
|
await client.call(app.bsky.notification.putActivitySubscription, {
|
||||||
subject: profile.did,
|
// the profile view carries an already-resolved did
|
||||||
|
subject: profile.did as DidString,
|
||||||
activitySubscription,
|
activitySubscription,
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
@@ -148,7 +150,7 @@ function DialogInner({
|
|||||||
queryClient.setQueryData(
|
queryClient.setQueryData(
|
||||||
RQKEY_getActivitySubscriptions,
|
RQKEY_getActivitySubscriptions,
|
||||||
(
|
(
|
||||||
old?: InfiniteData<AppBskyNotificationListActivitySubscriptions.OutputSchema>,
|
old?: InfiniteData<app.bsky.notification.listActivitySubscriptions.$OutputBody>,
|
||||||
) => {
|
) => {
|
||||||
if (!old) return old
|
if (!old) return old
|
||||||
return {
|
return {
|
||||||
|
|||||||
Vendored
+10
-5
@@ -5,9 +5,11 @@ import {
|
|||||||
useEffect,
|
useEffect,
|
||||||
useState,
|
useState,
|
||||||
} from 'react'
|
} from 'react'
|
||||||
|
import {type AtUriString} from '@atproto/syntax'
|
||||||
|
|
||||||
import * as persisted from '#/state/persisted'
|
import * as persisted from '#/state/persisted'
|
||||||
import {useAgent, useSession} from '../session'
|
import {app} from '#/lexicons'
|
||||||
|
import {useAppviewClient, useSession} from '../session'
|
||||||
|
|
||||||
type StateContext = Map<string, boolean>
|
type StateContext = Map<string, boolean>
|
||||||
type SetStateContext = (uri: string, value: boolean) => void
|
type SetStateContext = (uri: string, value: boolean) => void
|
||||||
@@ -56,7 +58,7 @@ export function useSetThreadMute() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function useMigrateMutes(setThreadMute: SetStateContext) {
|
function useMigrateMutes(setThreadMute: SetStateContext) {
|
||||||
const agent = useAgent()
|
const client = useAppviewClient()
|
||||||
const {currentAccount} = useSession()
|
const {currentAccount} = useSession()
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
@@ -87,8 +89,11 @@ function useMigrateMutes(setThreadMute: SetStateContext) {
|
|||||||
|
|
||||||
setThreadMute(root, true)
|
setThreadMute(root, true)
|
||||||
|
|
||||||
await agent.api.app.bsky.graph
|
await client
|
||||||
.muteThread({root})
|
.call(app.bsky.graph.muteThread, {
|
||||||
|
// the persisted list only ever holds post at-uris
|
||||||
|
root: root as AtUriString,
|
||||||
|
})
|
||||||
// not a big deal if this fails, since the post might have been deleted
|
// not a big deal if this fails, since the post might have been deleted
|
||||||
.catch(console.error)
|
.catch(console.error)
|
||||||
}
|
}
|
||||||
@@ -100,5 +105,5 @@ function useMigrateMutes(setThreadMute: SetStateContext) {
|
|||||||
cancelled = true
|
cancelled = true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}, [agent, currentAccount, setThreadMute])
|
}, [client, currentAccount, setThreadMute])
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
import {
|
import {
|
||||||
type AppBskyActorDefs,
|
type AppBskyActorDefs,
|
||||||
type AppBskyNotificationDeclaration,
|
type AppBskyNotificationDeclaration,
|
||||||
type AppBskyNotificationListActivitySubscriptions,
|
|
||||||
} from '@atproto/api'
|
} from '@atproto/api'
|
||||||
import {t} from '@lingui/core/macro'
|
import {t} from '@lingui/core/macro'
|
||||||
import {
|
import {
|
||||||
@@ -13,23 +12,23 @@ import {
|
|||||||
useQueryClient,
|
useQueryClient,
|
||||||
} from '@tanstack/react-query'
|
} from '@tanstack/react-query'
|
||||||
|
|
||||||
import {useAgent, useSession} from '#/state/session'
|
import {useAgent, useAppviewClient, useSession} from '#/state/session'
|
||||||
import * as Toast from '#/components/Toast'
|
import * as Toast from '#/components/Toast'
|
||||||
|
import {app} from '#/lexicons'
|
||||||
|
|
||||||
export const RQKEY_getActivitySubscriptions = ['activity-subscriptions']
|
export const RQKEY_getActivitySubscriptions = ['activity-subscriptions']
|
||||||
export const RQKEY_getNotificationDeclaration = ['notification-declaration']
|
export const RQKEY_getNotificationDeclaration = ['notification-declaration']
|
||||||
|
|
||||||
export function useActivitySubscriptionsQuery() {
|
export function useActivitySubscriptionsQuery() {
|
||||||
const agent = useAgent()
|
const client = useAppviewClient()
|
||||||
|
|
||||||
return useInfiniteQuery({
|
return useInfiniteQuery({
|
||||||
queryKey: RQKEY_getActivitySubscriptions,
|
queryKey: RQKEY_getActivitySubscriptions,
|
||||||
queryFn: async ({pageParam}) => {
|
queryFn: async ({pageParam}) => {
|
||||||
const response =
|
return await client.call(
|
||||||
await agent.app.bsky.notification.listActivitySubscriptions({
|
app.bsky.notification.listActivitySubscriptions,
|
||||||
cursor: pageParam,
|
{cursor: pageParam},
|
||||||
})
|
)
|
||||||
return response.data
|
|
||||||
},
|
},
|
||||||
initialPageParam: undefined as string | undefined,
|
initialPageParam: undefined as string | undefined,
|
||||||
getNextPageParam: prev => prev.cursor,
|
getNextPageParam: prev => prev.cursor,
|
||||||
@@ -111,7 +110,7 @@ export function* findAllProfilesInQueryData(
|
|||||||
did: string,
|
did: string,
|
||||||
): Generator<AppBskyActorDefs.ProfileView, void> {
|
): Generator<AppBskyActorDefs.ProfileView, void> {
|
||||||
const queryDatas = queryClient.getQueriesData<
|
const queryDatas = queryClient.getQueriesData<
|
||||||
InfiniteData<AppBskyNotificationListActivitySubscriptions.OutputSchema>
|
InfiniteData<app.bsky.notification.listActivitySubscriptions.$OutputBody>
|
||||||
>({
|
>({
|
||||||
queryKey: RQKEY_getActivitySubscriptions,
|
queryKey: RQKEY_getActivitySubscriptions,
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -33,7 +33,7 @@ import {
|
|||||||
|
|
||||||
import {useModerationOpts} from '#/state/preferences/moderation-opts'
|
import {useModerationOpts} from '#/state/preferences/moderation-opts'
|
||||||
import {STALE} from '#/state/queries'
|
import {STALE} from '#/state/queries'
|
||||||
import {useAgent} from '#/state/session'
|
import {useAppviewClient} from '#/state/session'
|
||||||
import {useThreadgateHiddenReplyUris} from '#/state/threadgate-hidden-replies'
|
import {useThreadgateHiddenReplyUris} from '#/state/threadgate-hidden-replies'
|
||||||
import type * as bsky from '#/types/bsky'
|
import type * as bsky from '#/types/bsky'
|
||||||
import {
|
import {
|
||||||
@@ -60,7 +60,7 @@ export function useNotificationFeedQuery(opts: {
|
|||||||
enabled?: boolean
|
enabled?: boolean
|
||||||
filter: 'all' | 'mentions'
|
filter: 'all' | 'mentions'
|
||||||
}) {
|
}) {
|
||||||
const agent = useAgent()
|
const client = useAppviewClient()
|
||||||
const queryClient = useQueryClient()
|
const queryClient = useQueryClient()
|
||||||
const moderationOpts = useModerationOpts()
|
const moderationOpts = useModerationOpts()
|
||||||
const unreads = useUnreadNotificationsApi()
|
const unreads = useUnreadNotificationsApi()
|
||||||
@@ -106,7 +106,7 @@ export function useNotificationFeedQuery(opts: {
|
|||||||
]
|
]
|
||||||
}
|
}
|
||||||
const {page: fetchedPage} = await fetchPage({
|
const {page: fetchedPage} = await fetchPage({
|
||||||
agent,
|
client,
|
||||||
limit: PAGE_SIZE,
|
limit: PAGE_SIZE,
|
||||||
cursor: pageParam,
|
cursor: pageParam,
|
||||||
queryClient,
|
queryClient,
|
||||||
|
|||||||
@@ -10,10 +10,10 @@ import {
|
|||||||
useQueryClient,
|
useQueryClient,
|
||||||
} from '@tanstack/react-query'
|
} from '@tanstack/react-query'
|
||||||
|
|
||||||
import {DM_SERVICE_HEADERS} from '#/lib/constants'
|
|
||||||
import {logger} from '#/logger'
|
import {logger} from '#/logger'
|
||||||
import {useAgent} from '#/state/session'
|
import {useAppviewClient, useChatClient} from '#/state/session'
|
||||||
import * as Toast from '#/components/Toast'
|
import * as Toast from '#/components/Toast'
|
||||||
|
import {app, chat} from '#/lexicons'
|
||||||
|
|
||||||
const RQKEY_ROOT = 'notification-settings'
|
const RQKEY_ROOT = 'notification-settings'
|
||||||
const RQKEY_APP = [RQKEY_ROOT, 'app']
|
const RQKEY_APP = [RQKEY_ROOT, 'app']
|
||||||
@@ -67,13 +67,13 @@ type ChatNotificationSettingsUpdate =
|
|||||||
export function useNotificationSettingsQuery({
|
export function useNotificationSettingsQuery({
|
||||||
enabled,
|
enabled,
|
||||||
}: {enabled?: boolean} = {}) {
|
}: {enabled?: boolean} = {}) {
|
||||||
const agent = useAgent()
|
const client = useAppviewClient()
|
||||||
|
|
||||||
return useQuery({
|
return useQuery({
|
||||||
queryKey: RQKEY_APP,
|
queryKey: RQKEY_APP,
|
||||||
queryFn: async (): Promise<AppNotificationSettingsPreferences> => {
|
queryFn: async (): Promise<AppNotificationSettingsPreferences> => {
|
||||||
const res = await agent.app.bsky.notification.getPreferences()
|
const data = await client.call(app.bsky.notification.getPreferences)
|
||||||
return appPreferencesWithoutChat(res.data.preferences)
|
return appPreferencesWithoutChat(data.preferences)
|
||||||
},
|
},
|
||||||
enabled,
|
enabled,
|
||||||
})
|
})
|
||||||
@@ -82,21 +82,24 @@ export function useNotificationSettingsQuery({
|
|||||||
export function useChatNotificationSettingsQuery({
|
export function useChatNotificationSettingsQuery({
|
||||||
enabled,
|
enabled,
|
||||||
}: {enabled?: boolean} = {}) {
|
}: {enabled?: boolean} = {}) {
|
||||||
const agent = useAgent()
|
const client = useChatClient()
|
||||||
|
|
||||||
return useQuery({
|
return useQuery({
|
||||||
queryKey: RQKEY_CHAT,
|
queryKey: RQKEY_CHAT,
|
||||||
queryFn: async (): Promise<ChatNotificationSettingsPreferences> => {
|
queryFn: async (): Promise<ChatNotificationSettingsPreferences> => {
|
||||||
const res = await agent.chat.bsky.notification.getPreferences(undefined, {
|
const data = await client.call(chat.bsky.notification.getPreferences)
|
||||||
headers: DM_SERVICE_HEADERS,
|
return chatPreferencesForSettings(data.preferences)
|
||||||
})
|
|
||||||
return chatPreferencesForSettings(res.data.preferences)
|
|
||||||
},
|
},
|
||||||
enabled,
|
enabled,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
export function useNotificationSettingsUpdateMutation() {
|
export function useNotificationSettingsUpdateMutation() {
|
||||||
const agent = useAgent()
|
/*
|
||||||
|
* App preferences live on the appview and chat preferences on the chat
|
||||||
|
* service, so a combined update fans out over both clients.
|
||||||
|
*/
|
||||||
|
const appviewClient = useAppviewClient()
|
||||||
|
const chatClient = useChatClient()
|
||||||
const queryClient = useQueryClient()
|
const queryClient = useQueryClient()
|
||||||
|
|
||||||
return useMutation({
|
return useMutation({
|
||||||
@@ -104,13 +107,13 @@ export function useNotificationSettingsUpdateMutation() {
|
|||||||
const {appUpdate, chatUpdate} = splitNotificationSettingsUpdate(update)
|
const {appUpdate, chatUpdate} = splitNotificationSettingsUpdate(update)
|
||||||
await Promise.all([
|
await Promise.all([
|
||||||
hasUpdates(appUpdate)
|
hasUpdates(appUpdate)
|
||||||
? agent.app.bsky.notification.putPreferencesV2(appUpdate)
|
? appviewClient.call(
|
||||||
|
app.bsky.notification.putPreferencesV2,
|
||||||
|
appUpdate,
|
||||||
|
)
|
||||||
: undefined,
|
: undefined,
|
||||||
hasUpdates(chatUpdate)
|
hasUpdates(chatUpdate)
|
||||||
? agent.chat.bsky.notification.putPreferences(chatUpdate, {
|
? chatClient.call(chat.bsky.notification.putPreferences, chatUpdate)
|
||||||
headers: DM_SERVICE_HEADERS,
|
|
||||||
encoding: 'application/json',
|
|
||||||
})
|
|
||||||
: undefined,
|
: undefined,
|
||||||
])
|
])
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ import {
|
|||||||
useState,
|
useState,
|
||||||
} from 'react'
|
} from 'react'
|
||||||
import {AppState} from 'react-native'
|
import {AppState} from 'react-native'
|
||||||
|
import {type ISODatetimeString} from '@atproto/syntax'
|
||||||
import {useQueryClient} from '@tanstack/react-query'
|
import {useQueryClient} from '@tanstack/react-query'
|
||||||
import {EventEmitter} from 'eventemitter3'
|
import {EventEmitter} from 'eventemitter3'
|
||||||
|
|
||||||
@@ -18,7 +19,8 @@ import BroadcastChannel from '#/lib/broadcast'
|
|||||||
import {resetBadgeCount} from '#/lib/notifications/notifications'
|
import {resetBadgeCount} from '#/lib/notifications/notifications'
|
||||||
import {useModerationOpts} from '#/state/preferences/moderation-opts'
|
import {useModerationOpts} from '#/state/preferences/moderation-opts'
|
||||||
import {truncateAndInvalidate} from '#/state/queries/util'
|
import {truncateAndInvalidate} from '#/state/queries/util'
|
||||||
import {useAgent, useSession} from '#/state/session'
|
import {useAppviewClient, useSession} from '#/state/session'
|
||||||
|
import {app} from '#/lexicons'
|
||||||
import {RQKEY as RQKEY_NOTIFS} from './feed'
|
import {RQKEY as RQKEY_NOTIFS} from './feed'
|
||||||
import {type CachedFeedPage, type FeedPage} from './types'
|
import {type CachedFeedPage, type FeedPage} from './types'
|
||||||
import {fetchPage} from './util'
|
import {fetchPage} from './util'
|
||||||
@@ -52,7 +54,7 @@ apiContext.displayName = 'NotificationsUnreadApiContext'
|
|||||||
|
|
||||||
export function Provider({children}: React.PropsWithChildren<{}>) {
|
export function Provider({children}: React.PropsWithChildren<{}>) {
|
||||||
const {hasSession} = useSession()
|
const {hasSession} = useSession()
|
||||||
const agent = useAgent()
|
const client = useAppviewClient()
|
||||||
const queryClient = useQueryClient()
|
const queryClient = useQueryClient()
|
||||||
const moderationOpts = useModerationOpts()
|
const moderationOpts = useModerationOpts()
|
||||||
|
|
||||||
@@ -120,9 +122,10 @@ export function Provider({children}: React.PropsWithChildren<{}>) {
|
|||||||
return {
|
return {
|
||||||
async markAllRead() {
|
async markAllRead() {
|
||||||
// update server
|
// update server
|
||||||
await agent.updateSeenNotifications(
|
await client.call(app.bsky.notification.updateSeen, {
|
||||||
cacheRef.current.syncedAt.toISOString(),
|
// toISOString always emits the Z-suffixed form the format requires
|
||||||
)
|
seenAt: cacheRef.current.syncedAt.toISOString() as ISODatetimeString,
|
||||||
|
})
|
||||||
|
|
||||||
// update & broadcast
|
// update & broadcast
|
||||||
setNumUnread('')
|
setNumUnread('')
|
||||||
@@ -135,7 +138,7 @@ export function Provider({children}: React.PropsWithChildren<{}>) {
|
|||||||
isPoll,
|
isPoll,
|
||||||
}: {invalidate?: boolean; isPoll?: boolean} = {}) {
|
}: {invalidate?: boolean; isPoll?: boolean} = {}) {
|
||||||
try {
|
try {
|
||||||
if (!agent.session) return
|
if (!hasSession) return
|
||||||
if (AppState.currentState !== 'active') {
|
if (AppState.currentState !== 'active') {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@@ -156,7 +159,7 @@ export function Provider({children}: React.PropsWithChildren<{}>) {
|
|||||||
|
|
||||||
// count
|
// count
|
||||||
const {page, indexedAt: lastIndexed} = await fetchPage({
|
const {page, indexedAt: lastIndexed} = await fetchPage({
|
||||||
agent,
|
client,
|
||||||
cursor: undefined,
|
cursor: undefined,
|
||||||
limit: 40,
|
limit: 40,
|
||||||
queryClient,
|
queryClient,
|
||||||
@@ -207,7 +210,7 @@ export function Provider({children}: React.PropsWithChildren<{}>) {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}, [setNumUnread, queryClient, moderationOpts, agent])
|
}, [setNumUnread, queryClient, moderationOpts, client, hasSession])
|
||||||
checkUnreadRef.current = api.checkUnread
|
checkUnreadRef.current = api.checkUnread
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|||||||
@@ -6,15 +6,17 @@ import {
|
|||||||
type AppBskyGraphDefs,
|
type AppBskyGraphDefs,
|
||||||
AppBskyGraphStarterpack,
|
AppBskyGraphStarterpack,
|
||||||
type AppBskyNotificationListNotifications,
|
type AppBskyNotificationListNotifications,
|
||||||
type AtpAgent,
|
|
||||||
hasMutedWord,
|
hasMutedWord,
|
||||||
moderateNotification,
|
moderateNotification,
|
||||||
type ModerationOpts,
|
type ModerationOpts,
|
||||||
} from '@atproto/api'
|
} from '@atproto/api'
|
||||||
|
import {type Client} from '@atproto/lex'
|
||||||
|
import {type AtUriString} from '@atproto/syntax'
|
||||||
import {type QueryClient} from '@tanstack/react-query'
|
import {type QueryClient} from '@tanstack/react-query'
|
||||||
import chunk from 'lodash.chunk'
|
import chunk from 'lodash.chunk'
|
||||||
|
|
||||||
import {labelIsHideableOffense} from '#/lib/moderation'
|
import {labelIsHideableOffense} from '#/lib/moderation'
|
||||||
|
import {app} from '#/lexicons'
|
||||||
import * as bsky from '#/types/bsky'
|
import * as bsky from '#/types/bsky'
|
||||||
import {precacheProfile} from '../profile'
|
import {precacheProfile} from '../profile'
|
||||||
import {
|
import {
|
||||||
@@ -38,7 +40,7 @@ const MS_2DAY = MS_1HR * 48
|
|||||||
// =
|
// =
|
||||||
|
|
||||||
export async function fetchPage({
|
export async function fetchPage({
|
||||||
agent,
|
client,
|
||||||
cursor,
|
cursor,
|
||||||
limit,
|
limit,
|
||||||
queryClient,
|
queryClient,
|
||||||
@@ -46,7 +48,7 @@ export async function fetchPage({
|
|||||||
fetchAdditionalData,
|
fetchAdditionalData,
|
||||||
reasons,
|
reasons,
|
||||||
}: {
|
}: {
|
||||||
agent: AtpAgent
|
client: Client
|
||||||
cursor: string | undefined
|
cursor: string | undefined
|
||||||
limit: number
|
limit: number
|
||||||
queryClient: QueryClient
|
queryClient: QueryClient
|
||||||
@@ -57,16 +59,16 @@ export async function fetchPage({
|
|||||||
page: FeedPage
|
page: FeedPage
|
||||||
indexedAt: string | undefined
|
indexedAt: string | undefined
|
||||||
}> {
|
}> {
|
||||||
const res = await agent.listNotifications({
|
const data = await client.call(app.bsky.notification.listNotifications, {
|
||||||
limit,
|
limit,
|
||||||
cursor,
|
cursor,
|
||||||
reasons,
|
reasons,
|
||||||
})
|
})
|
||||||
|
|
||||||
const indexedAt = res.data.notifications[0]?.indexedAt
|
const indexedAt = data.notifications[0]?.indexedAt
|
||||||
|
|
||||||
// filter out notifs by mod rules
|
// filter out notifs by mod rules
|
||||||
const notifs = res.data.notifications.filter(
|
const notifs = data.notifications.filter(
|
||||||
notif => !shouldFilterNotif(notif, moderationOpts),
|
notif => !shouldFilterNotif(notif, moderationOpts),
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -76,7 +78,7 @@ export async function fetchPage({
|
|||||||
// we fetch subjects of notifications (usually posts) now instead of lazily
|
// we fetch subjects of notifications (usually posts) now instead of lazily
|
||||||
// in the UI to avoid relayouts
|
// in the UI to avoid relayouts
|
||||||
if (fetchAdditionalData) {
|
if (fetchAdditionalData) {
|
||||||
const subjects = await fetchSubjects(agent, notifsGrouped)
|
const subjects = await fetchSubjects(client, notifsGrouped)
|
||||||
for (const notif of notifsGrouped) {
|
for (const notif of notifsGrouped) {
|
||||||
if (notif.subjectUri) {
|
if (notif.subjectUri) {
|
||||||
if (
|
if (
|
||||||
@@ -96,17 +98,17 @@ export async function fetchPage({
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let seenAt = res.data.seenAt ? new Date(res.data.seenAt) : new Date()
|
let seenAt = data.seenAt ? new Date(data.seenAt) : new Date()
|
||||||
if (Number.isNaN(seenAt.getTime())) {
|
if (Number.isNaN(seenAt.getTime())) {
|
||||||
seenAt = new Date()
|
seenAt = new Date()
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
page: {
|
page: {
|
||||||
cursor: res.data.cursor,
|
cursor: data.cursor,
|
||||||
seenAt,
|
seenAt,
|
||||||
items: notifsGrouped,
|
items: notifsGrouped,
|
||||||
priority: res.data.priority ?? false,
|
priority: data.priority ?? false,
|
||||||
},
|
},
|
||||||
indexedAt,
|
indexedAt,
|
||||||
}
|
}
|
||||||
@@ -207,7 +209,7 @@ export function groupNotifications(
|
|||||||
}
|
}
|
||||||
|
|
||||||
async function fetchSubjects(
|
async function fetchSubjects(
|
||||||
agent: AtpAgent,
|
client: Client,
|
||||||
groupedNotifs: FeedNotification[],
|
groupedNotifs: FeedNotification[],
|
||||||
): Promise<{
|
): Promise<{
|
||||||
posts: Map<string, AppBskyFeedDefs.PostView>
|
posts: Map<string, AppBskyFeedDefs.PostView>
|
||||||
@@ -224,18 +226,22 @@ async function fetchSubjects(
|
|||||||
packUris.add(notif.notification.reasonSubject)
|
packUris.add(notif.notification.reasonSubject)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
const postUriChunks = chunk(Array.from(postUris), 25)
|
/*
|
||||||
const packUriChunks = chunk(Array.from(packUris), 25)
|
* Both uri sets are collected from notification fields the server already
|
||||||
|
* validated as at-uris, so the branded cast reflects what the values are.
|
||||||
|
*/
|
||||||
|
const postUriChunks = chunk(Array.from(postUris) as AtUriString[], 25)
|
||||||
|
const packUriChunks = chunk(Array.from(packUris) as AtUriString[], 25)
|
||||||
const postsChunks = await Promise.all(
|
const postsChunks = await Promise.all(
|
||||||
postUriChunks.map(uris =>
|
postUriChunks.map(uris =>
|
||||||
agent.app.bsky.feed.getPosts({uris}).then(res => res.data.posts),
|
client.call(app.bsky.feed.getPosts, {uris}).then(data => data.posts),
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
const packsChunks = await Promise.all(
|
const packsChunks = await Promise.all(
|
||||||
packUriChunks.map(uris =>
|
packUriChunks.map(uris =>
|
||||||
agent.app.bsky.graph
|
client
|
||||||
.getStarterPacks({uris})
|
.call(app.bsky.graph.getStarterPacks, {uris})
|
||||||
.then(res => res.data.starterPacks),
|
.then(data => data.starterPacks),
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
const postsMap = new Map<string, AppBskyFeedDefs.PostView>()
|
const postsMap = new Map<string, AppBskyFeedDefs.PostView>()
|
||||||
|
|||||||
@@ -21,12 +21,13 @@ import {
|
|||||||
type ModerationOpts,
|
type ModerationOpts,
|
||||||
} from '@atproto/api'
|
} from '@atproto/api'
|
||||||
import {TID} from '@atproto/common-web'
|
import {TID} from '@atproto/common-web'
|
||||||
|
import {type DidString} from '@atproto/syntax'
|
||||||
import {plural} from '@lingui/core/macro'
|
import {plural} from '@lingui/core/macro'
|
||||||
import {Plural, Trans, useLingui} from '@lingui/react/macro'
|
import {Plural, Trans, useLingui} from '@lingui/react/macro'
|
||||||
import {useNavigation} from '@react-navigation/native'
|
import {useNavigation} from '@react-navigation/native'
|
||||||
import {useQueryClient} from '@tanstack/react-query'
|
import {useQueryClient} from '@tanstack/react-query'
|
||||||
|
|
||||||
import {DM_SERVICE_HEADERS, MAX_POST_LINES} from '#/lib/constants'
|
import {MAX_POST_LINES} from '#/lib/constants'
|
||||||
import {useAnimatedValue} from '#/lib/hooks/useAnimatedValue'
|
import {useAnimatedValue} from '#/lib/hooks/useAnimatedValue'
|
||||||
import {makeProfileLink} from '#/lib/routes/links'
|
import {makeProfileLink} from '#/lib/routes/links'
|
||||||
import {type NavigationProp} from '#/lib/routes/types'
|
import {type NavigationProp} from '#/lib/routes/types'
|
||||||
@@ -38,7 +39,7 @@ import {useProfileShadow} from '#/state/cache/profile-shadow'
|
|||||||
import {type FeedNotification} from '#/state/queries/notifications/feed'
|
import {type FeedNotification} from '#/state/queries/notifications/feed'
|
||||||
import {useProfileFollowMutationQueue} from '#/state/queries/profile'
|
import {useProfileFollowMutationQueue} from '#/state/queries/profile'
|
||||||
import {unstableCacheProfileView} from '#/state/queries/unstable-profile-cache'
|
import {unstableCacheProfileView} from '#/state/queries/unstable-profile-cache'
|
||||||
import {useAgent, useSession} from '#/state/session'
|
import {useChatClient, useSession} from '#/state/session'
|
||||||
import {FeedSourceCard} from '#/view/com/feeds/FeedSourceCard'
|
import {FeedSourceCard} from '#/view/com/feeds/FeedSourceCard'
|
||||||
import {Post} from '#/view/com/post/Post'
|
import {Post} from '#/view/com/post/Post'
|
||||||
import {formatCount} from '#/view/com/util/numeric/format'
|
import {formatCount} from '#/view/com/util/numeric/format'
|
||||||
@@ -73,6 +74,7 @@ import * as Toast from '#/components/Toast'
|
|||||||
import {Text} from '#/components/Typography'
|
import {Text} from '#/components/Typography'
|
||||||
import {useAnalytics} from '#/analytics'
|
import {useAnalytics} from '#/analytics'
|
||||||
import {IS_WEB} from '#/env'
|
import {IS_WEB} from '#/env'
|
||||||
|
import {chat} from '#/lexicons'
|
||||||
import * as bsky from '#/types/bsky'
|
import * as bsky from '#/types/bsky'
|
||||||
|
|
||||||
const MAX_AUTHORS = 5
|
const MAX_AUTHORS = 5
|
||||||
@@ -911,21 +913,21 @@ function FollowBackButton({profile}: {profile: AppBskyActorDefs.ProfileView}) {
|
|||||||
|
|
||||||
function SayHelloBtn({profile}: {profile: AppBskyActorDefs.ProfileView}) {
|
function SayHelloBtn({profile}: {profile: AppBskyActorDefs.ProfileView}) {
|
||||||
const {t: l} = useLingui()
|
const {t: l} = useLingui()
|
||||||
const agent = useAgent()
|
const client = useChatClient()
|
||||||
|
const {currentAccount} = useSession()
|
||||||
const navigation = useNavigation<NavigationProp>()
|
const navigation = useNavigation<NavigationProp>()
|
||||||
const [isLoading, setIsLoading] = useState(false)
|
const [isLoading, setIsLoading] = useState(false)
|
||||||
|
|
||||||
const onPress = async () => {
|
const onPress = async () => {
|
||||||
try {
|
try {
|
||||||
setIsLoading(true)
|
setIsLoading(true)
|
||||||
const res = await agent.api.chat.bsky.convo.getConvoForMembers(
|
const data = await client.call(chat.bsky.convo.getConvoForMembers, {
|
||||||
{
|
// both dids are already resolved - one from the profile view, one from
|
||||||
members: [profile.did, agent.session!.did],
|
// the active session
|
||||||
},
|
members: [profile.did, currentAccount!.did] as DidString[],
|
||||||
{headers: DM_SERVICE_HEADERS},
|
})
|
||||||
)
|
|
||||||
navigation.navigate('MessagesConversation', {
|
navigation.navigate('MessagesConversation', {
|
||||||
conversation: res.data.convo.id,
|
conversation: data.convo.id,
|
||||||
})
|
})
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
logger.error('Failed to get conversation', {safeMessage: e})
|
logger.error('Failed to get conversation', {safeMessage: e})
|
||||||
|
|||||||
Reference in New Issue
Block a user