Get feed source info for video feeds
This commit is contained in:
@@ -70,6 +70,7 @@ import {
|
||||
useFeedFeedbackContext,
|
||||
} from '#/state/feed-feedback'
|
||||
import {useFeedFeedback} from '#/state/feed-feedback'
|
||||
import {useFeedInfo} from '#/state/queries/feed'
|
||||
import {usePostLikeMutationQueue} from '#/state/queries/post'
|
||||
import {
|
||||
type AuthorFilter,
|
||||
@@ -199,7 +200,9 @@ function Feed() {
|
||||
throw new Error(`Invalid video feed params ${JSON.stringify(params)}`)
|
||||
}
|
||||
}, [params])
|
||||
const feedFeedback = useFeedFeedback(feedDesc, hasSession)
|
||||
const feedUri = params.type === 'feedgen' ? params.uri : undefined
|
||||
const {data: feedInfo} = useFeedInfo(feedUri)
|
||||
const feedFeedback = useFeedFeedback(feedInfo, hasSession)
|
||||
const {data, error, hasNextPage, isFetchingNextPage, fetchNextPage} =
|
||||
usePostFeedQuery(
|
||||
feedDesc,
|
||||
|
||||
+24
-67
@@ -16,11 +16,14 @@ import {
|
||||
FEEDBACK_FEEDS,
|
||||
type FeedbackInteraction,
|
||||
isFeedbackInteraction,
|
||||
STAGING_FEEDS,
|
||||
} from '#/lib/constants'
|
||||
import {logEvent} from '#/lib/statsig/statsig'
|
||||
import {Logger} from '#/logger'
|
||||
import {type FeedSourceInfo} from '#/state/queries/feed'
|
||||
import {
|
||||
type FeedSourceFeedInfo,
|
||||
type FeedSourceInfo,
|
||||
isFeedSourceFeedInfo,
|
||||
} from '#/state/queries/feed'
|
||||
import {
|
||||
type FeedDescriptor,
|
||||
type FeedPostSliceItem,
|
||||
@@ -46,24 +49,21 @@ const stateContext = createContext<StateContext>({
|
||||
feedSourceInfo: undefined,
|
||||
})
|
||||
|
||||
// All info needed to send feedback to a feed
|
||||
type FeedInfo = {
|
||||
feedDescriptor: FeedDescriptor
|
||||
acceptsInteractions: boolean
|
||||
isDiscover: boolean
|
||||
proxyDid: string
|
||||
}
|
||||
|
||||
export function useFeedFeedback(
|
||||
feed: FeedSourceInfo | FeedDescriptor | undefined,
|
||||
feedSourceInfo: FeedSourceInfo | undefined,
|
||||
hasSession: boolean,
|
||||
) {
|
||||
const agent = useAgent()
|
||||
|
||||
const feedInfo = feed ? buildFeedInfo(feed) : null
|
||||
const enabled = !!feedInfo && feedInfo.acceptsInteractions && hasSession
|
||||
const feed =
|
||||
!!feedSourceInfo && isFeedSourceFeedInfo(feedSourceInfo)
|
||||
? feedSourceInfo
|
||||
: undefined
|
||||
|
||||
const enabledInteractions = getEnabledInteractions(enabled, feedInfo)
|
||||
const isDiscover = isDiscoverFeed(feed?.feedDescriptor)
|
||||
const acceptsInteractions = isDiscover || (feed?.acceptsInteractions ?? false)
|
||||
const enabled = !!feed && acceptsInteractions && hasSession
|
||||
const enabledInteractions = getEnabledInteractions(enabled, feed, isDiscover)
|
||||
|
||||
const queue = useRef<Set<string>>(new Set())
|
||||
const history = useRef<
|
||||
@@ -97,6 +97,8 @@ export function useFeedFeedback(
|
||||
return
|
||||
}
|
||||
|
||||
const proxyDid = feed?.view?.did
|
||||
|
||||
// Send to the feed
|
||||
agent.app.bsky.feed
|
||||
.sendInteractions(
|
||||
@@ -104,7 +106,7 @@ export function useFeedFeedback(
|
||||
{
|
||||
encoding: 'application/json',
|
||||
headers: {
|
||||
'atproto-proxy': `${feedInfo?.proxyDid}#bsky_fg`,
|
||||
'atproto-proxy': `${proxyDid}#bsky_fg`,
|
||||
},
|
||||
},
|
||||
)
|
||||
@@ -122,7 +124,7 @@ export function useFeedFeedback(
|
||||
)
|
||||
throttledFlushAggregatedStats()
|
||||
logger.debug('flushed')
|
||||
}, [agent, throttledFlushAggregatedStats, feedInfo, enabledInteractions])
|
||||
}, [agent, throttledFlushAggregatedStats, feed, enabledInteractions])
|
||||
|
||||
const sendToFeed = useMemo(
|
||||
() =>
|
||||
@@ -194,10 +196,10 @@ export function useFeedFeedback(
|
||||
// call on various events
|
||||
// queues the event to be sent with the throttled sendToFeed call
|
||||
sendInteraction,
|
||||
feedDescriptor: feedInfo?.feedDescriptor,
|
||||
feedDescriptor: feed?.feedDescriptor,
|
||||
feedSourceInfo: typeof feed === 'object' ? feed : undefined,
|
||||
}
|
||||
}, [enabled, onItemSeen, sendInteraction, feedInfo, feed])
|
||||
}, [enabled, onItemSeen, sendInteraction, feed])
|
||||
}
|
||||
|
||||
export const FeedFeedbackProvider = stateContext.Provider
|
||||
@@ -215,60 +217,15 @@ function isDiscoverFeed(feed?: FeedDescriptor) {
|
||||
return !!feed && FEEDBACK_FEEDS.includes(feed)
|
||||
}
|
||||
|
||||
function buildFeedInfo(feed: FeedSourceInfo | FeedDescriptor): FeedInfo | null {
|
||||
// Build FeedInfo object from either a feed source info object or a feed descriptor string
|
||||
// Only discover feeds are supported for feed descriptor strings
|
||||
if (typeof feed === 'object') {
|
||||
if (feed.type !== 'feed') {
|
||||
// Don't send feedback to non-feed sources
|
||||
return null
|
||||
}
|
||||
const feedDescriptor = feed.feedDescriptor
|
||||
const isDiscover = isDiscoverFeed(feed.feedDescriptor)
|
||||
const proxyDid = feed.view?.did
|
||||
if (!proxyDid) {
|
||||
logger.warn(`No proxy did found for feed: ${feedDescriptor}.`)
|
||||
return null
|
||||
}
|
||||
let acceptsInteractions = feed.acceptsInteractions ?? false
|
||||
if (isDiscover) {
|
||||
// Discover feed doesn't have acceptsInteractions: true, so hardcode this for now
|
||||
acceptsInteractions = true
|
||||
}
|
||||
return {
|
||||
feedDescriptor,
|
||||
isDiscover,
|
||||
proxyDid,
|
||||
acceptsInteractions,
|
||||
}
|
||||
} else {
|
||||
const feedDescriptor = feed
|
||||
const isDiscover = isDiscoverFeed(feedDescriptor)
|
||||
if (!isDiscover) {
|
||||
return null
|
||||
}
|
||||
const proxyDid = STAGING_FEEDS.includes(feedDescriptor)
|
||||
? 'did:web:algo.pop2.bsky.app'
|
||||
: 'did:web:discover.bsky.app'
|
||||
return {
|
||||
feedDescriptor,
|
||||
isDiscover,
|
||||
proxyDid,
|
||||
acceptsInteractions: true,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function getEnabledInteractions(
|
||||
enabled: boolean,
|
||||
feedInfo: FeedInfo | null,
|
||||
feed: FeedSourceFeedInfo | undefined,
|
||||
isDiscover: boolean,
|
||||
): readonly FeedbackInteraction[] {
|
||||
if (!enabled || !feedInfo) {
|
||||
if (!enabled || !feed) {
|
||||
return []
|
||||
}
|
||||
return feedInfo.isDiscover
|
||||
? ALL_FEEDBACK_INTERACTIONS
|
||||
: DIRECT_FEEDBACK_INTERACTIONS
|
||||
return isDiscover ? ALL_FEEDBACK_INTERACTIONS : DIRECT_FEEDBACK_INTERACTIONS
|
||||
}
|
||||
|
||||
function toString(interaction: AppBskyFeedDefs.Interaction): string {
|
||||
|
||||
@@ -74,6 +74,12 @@ export type FeedSourceListInfo = {
|
||||
|
||||
export type FeedSourceInfo = FeedSourceFeedInfo | FeedSourceListInfo
|
||||
|
||||
export function isFeedSourceFeedInfo(
|
||||
feed: FeedSourceInfo,
|
||||
): feed is FeedSourceFeedInfo {
|
||||
return feed.type === 'feed'
|
||||
}
|
||||
|
||||
const feedSourceInfoQueryKeyRoot = 'getFeedSourceInfo'
|
||||
export const feedSourceInfoQueryKey = ({uri}: {uri: string}) => [
|
||||
feedSourceInfoQueryKeyRoot,
|
||||
@@ -621,6 +627,29 @@ export function useSavedFeeds() {
|
||||
})
|
||||
}
|
||||
|
||||
const feedInfoQueryKeyRoot = 'feedInfo'
|
||||
|
||||
export function useFeedInfo(feedUri: string | undefined) {
|
||||
const agent = useAgent()
|
||||
|
||||
return useQuery({
|
||||
staleTime: STALE.INFINITY,
|
||||
queryKey: [feedInfoQueryKeyRoot, feedUri],
|
||||
queryFn: async () => {
|
||||
if (!feedUri) {
|
||||
return undefined
|
||||
}
|
||||
|
||||
const res = await agent.app.bsky.feed.getFeedGenerator({
|
||||
feed: feedUri,
|
||||
})
|
||||
|
||||
const feedSourceInfo = hydrateFeedGenerator(res.data.view)
|
||||
return feedSourceInfo
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
function precacheFeed(queryClient: QueryClient, hydratedFeed: FeedSourceInfo) {
|
||||
precacheResolvedUri(
|
||||
queryClient,
|
||||
|
||||
Reference in New Issue
Block a user