Get feed source info for video feeds
This commit is contained in:
@@ -70,6 +70,7 @@ import {
|
|||||||
useFeedFeedbackContext,
|
useFeedFeedbackContext,
|
||||||
} from '#/state/feed-feedback'
|
} from '#/state/feed-feedback'
|
||||||
import {useFeedFeedback} from '#/state/feed-feedback'
|
import {useFeedFeedback} from '#/state/feed-feedback'
|
||||||
|
import {useFeedInfo} from '#/state/queries/feed'
|
||||||
import {usePostLikeMutationQueue} from '#/state/queries/post'
|
import {usePostLikeMutationQueue} from '#/state/queries/post'
|
||||||
import {
|
import {
|
||||||
type AuthorFilter,
|
type AuthorFilter,
|
||||||
@@ -199,7 +200,9 @@ function Feed() {
|
|||||||
throw new Error(`Invalid video feed params ${JSON.stringify(params)}`)
|
throw new Error(`Invalid video feed params ${JSON.stringify(params)}`)
|
||||||
}
|
}
|
||||||
}, [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} =
|
const {data, error, hasNextPage, isFetchingNextPage, fetchNextPage} =
|
||||||
usePostFeedQuery(
|
usePostFeedQuery(
|
||||||
feedDesc,
|
feedDesc,
|
||||||
|
|||||||
+24
-67
@@ -16,11 +16,14 @@ import {
|
|||||||
FEEDBACK_FEEDS,
|
FEEDBACK_FEEDS,
|
||||||
type FeedbackInteraction,
|
type FeedbackInteraction,
|
||||||
isFeedbackInteraction,
|
isFeedbackInteraction,
|
||||||
STAGING_FEEDS,
|
|
||||||
} from '#/lib/constants'
|
} from '#/lib/constants'
|
||||||
import {logEvent} from '#/lib/statsig/statsig'
|
import {logEvent} from '#/lib/statsig/statsig'
|
||||||
import {Logger} from '#/logger'
|
import {Logger} from '#/logger'
|
||||||
import {type FeedSourceInfo} from '#/state/queries/feed'
|
import {
|
||||||
|
type FeedSourceFeedInfo,
|
||||||
|
type FeedSourceInfo,
|
||||||
|
isFeedSourceFeedInfo,
|
||||||
|
} from '#/state/queries/feed'
|
||||||
import {
|
import {
|
||||||
type FeedDescriptor,
|
type FeedDescriptor,
|
||||||
type FeedPostSliceItem,
|
type FeedPostSliceItem,
|
||||||
@@ -46,24 +49,21 @@ const stateContext = createContext<StateContext>({
|
|||||||
feedSourceInfo: undefined,
|
feedSourceInfo: undefined,
|
||||||
})
|
})
|
||||||
|
|
||||||
// All info needed to send feedback to a feed
|
|
||||||
type FeedInfo = {
|
|
||||||
feedDescriptor: FeedDescriptor
|
|
||||||
acceptsInteractions: boolean
|
|
||||||
isDiscover: boolean
|
|
||||||
proxyDid: string
|
|
||||||
}
|
|
||||||
|
|
||||||
export function useFeedFeedback(
|
export function useFeedFeedback(
|
||||||
feed: FeedSourceInfo | FeedDescriptor | undefined,
|
feedSourceInfo: FeedSourceInfo | undefined,
|
||||||
hasSession: boolean,
|
hasSession: boolean,
|
||||||
) {
|
) {
|
||||||
const agent = useAgent()
|
const agent = useAgent()
|
||||||
|
|
||||||
const feedInfo = feed ? buildFeedInfo(feed) : null
|
const feed =
|
||||||
const enabled = !!feedInfo && feedInfo.acceptsInteractions && hasSession
|
!!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 queue = useRef<Set<string>>(new Set())
|
||||||
const history = useRef<
|
const history = useRef<
|
||||||
@@ -97,6 +97,8 @@ export function useFeedFeedback(
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const proxyDid = feed?.view?.did
|
||||||
|
|
||||||
// Send to the feed
|
// Send to the feed
|
||||||
agent.app.bsky.feed
|
agent.app.bsky.feed
|
||||||
.sendInteractions(
|
.sendInteractions(
|
||||||
@@ -104,7 +106,7 @@ export function useFeedFeedback(
|
|||||||
{
|
{
|
||||||
encoding: 'application/json',
|
encoding: 'application/json',
|
||||||
headers: {
|
headers: {
|
||||||
'atproto-proxy': `${feedInfo?.proxyDid}#bsky_fg`,
|
'atproto-proxy': `${proxyDid}#bsky_fg`,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
@@ -122,7 +124,7 @@ export function useFeedFeedback(
|
|||||||
)
|
)
|
||||||
throttledFlushAggregatedStats()
|
throttledFlushAggregatedStats()
|
||||||
logger.debug('flushed')
|
logger.debug('flushed')
|
||||||
}, [agent, throttledFlushAggregatedStats, feedInfo, enabledInteractions])
|
}, [agent, throttledFlushAggregatedStats, feed, enabledInteractions])
|
||||||
|
|
||||||
const sendToFeed = useMemo(
|
const sendToFeed = useMemo(
|
||||||
() =>
|
() =>
|
||||||
@@ -194,10 +196,10 @@ export function useFeedFeedback(
|
|||||||
// call on various events
|
// call on various events
|
||||||
// queues the event to be sent with the throttled sendToFeed call
|
// queues the event to be sent with the throttled sendToFeed call
|
||||||
sendInteraction,
|
sendInteraction,
|
||||||
feedDescriptor: feedInfo?.feedDescriptor,
|
feedDescriptor: feed?.feedDescriptor,
|
||||||
feedSourceInfo: typeof feed === 'object' ? feed : undefined,
|
feedSourceInfo: typeof feed === 'object' ? feed : undefined,
|
||||||
}
|
}
|
||||||
}, [enabled, onItemSeen, sendInteraction, feedInfo, feed])
|
}, [enabled, onItemSeen, sendInteraction, feed])
|
||||||
}
|
}
|
||||||
|
|
||||||
export const FeedFeedbackProvider = stateContext.Provider
|
export const FeedFeedbackProvider = stateContext.Provider
|
||||||
@@ -215,60 +217,15 @@ function isDiscoverFeed(feed?: FeedDescriptor) {
|
|||||||
return !!feed && FEEDBACK_FEEDS.includes(feed)
|
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(
|
function getEnabledInteractions(
|
||||||
enabled: boolean,
|
enabled: boolean,
|
||||||
feedInfo: FeedInfo | null,
|
feed: FeedSourceFeedInfo | undefined,
|
||||||
|
isDiscover: boolean,
|
||||||
): readonly FeedbackInteraction[] {
|
): readonly FeedbackInteraction[] {
|
||||||
if (!enabled || !feedInfo) {
|
if (!enabled || !feed) {
|
||||||
return []
|
return []
|
||||||
}
|
}
|
||||||
return feedInfo.isDiscover
|
return isDiscover ? ALL_FEEDBACK_INTERACTIONS : DIRECT_FEEDBACK_INTERACTIONS
|
||||||
? ALL_FEEDBACK_INTERACTIONS
|
|
||||||
: DIRECT_FEEDBACK_INTERACTIONS
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function toString(interaction: AppBskyFeedDefs.Interaction): string {
|
function toString(interaction: AppBskyFeedDefs.Interaction): string {
|
||||||
|
|||||||
@@ -74,6 +74,12 @@ export type FeedSourceListInfo = {
|
|||||||
|
|
||||||
export type FeedSourceInfo = FeedSourceFeedInfo | FeedSourceListInfo
|
export type FeedSourceInfo = FeedSourceFeedInfo | FeedSourceListInfo
|
||||||
|
|
||||||
|
export function isFeedSourceFeedInfo(
|
||||||
|
feed: FeedSourceInfo,
|
||||||
|
): feed is FeedSourceFeedInfo {
|
||||||
|
return feed.type === 'feed'
|
||||||
|
}
|
||||||
|
|
||||||
const feedSourceInfoQueryKeyRoot = 'getFeedSourceInfo'
|
const feedSourceInfoQueryKeyRoot = 'getFeedSourceInfo'
|
||||||
export const feedSourceInfoQueryKey = ({uri}: {uri: string}) => [
|
export const feedSourceInfoQueryKey = ({uri}: {uri: string}) => [
|
||||||
feedSourceInfoQueryKeyRoot,
|
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) {
|
function precacheFeed(queryClient: QueryClient, hydratedFeed: FeedSourceInfo) {
|
||||||
precacheResolvedUri(
|
precacheResolvedUri(
|
||||||
queryClient,
|
queryClient,
|
||||||
|
|||||||
Reference in New Issue
Block a user