Implement FeedFeedback API (#3498)

* Implement onViewableItemsChanged on List.web.tsx

* Introduce onItemSeen to List API

* Add FeedFeedback tracker

* Add clickthrough interaction tracking

* Add engagement interaction tracking

* Reduce duplicate sends, introduce a flushAndReset to be triggered on refreshes, and modify the api design a bit

* Wire up SDK types and feedContext

* Avoid needless function allocations

* Fix schema usage

* Add show more / show less buttons

* Fix minor rendering issue on mobile menu

* Wire up sendInteractions()

* Fix logic error

* Fix: it's item not uri

* Update 'seen' to mean 3 seconds on-screen with some significant portion visible

* Fix non-reactive debounce

* Move methods out

* Use a WeakSet for deduping

* Reset timeout

* 3 -> 2 seconds

* Oopsie

* Throttle instead

* Fix divider

* Remove explicit flush calls

* Rm unused

---------

Co-authored-by: dan <dan.abramov@gmail.com>
This commit is contained in:
Paul Frazee 2024-05-06 19:08:33 -07:00 committed by GitHub
parent e264dfbb87
commit 4fad18b2fa
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
22 changed files with 516 additions and 64 deletions

View file

@ -1,5 +1,5 @@
import React, {memo} from 'react'
import {FlatListProps, RefreshControl} from 'react-native'
import {FlatListProps, RefreshControl, ViewToken} from 'react-native'
import {runOnJS, useSharedValue} from 'react-native-reanimated'
import {useAnimatedScrollHandler} from '#/lib/hooks/useAnimatedScrollHandler_FIXED'
@ -23,6 +23,7 @@ export type ListProps<ItemT> = Omit<
headerOffset?: number
refreshing?: boolean
onRefresh?: () => void
onItemSeen?: (item: ItemT) => void
containWeb?: boolean
}
export type ListRef = React.MutableRefObject<FlatList_INTERNAL | null>
@ -34,6 +35,7 @@ function ListImpl<ItemT>(
onScrolledDownChange,
refreshing,
onRefresh,
onItemSeen,
headerOffset,
style,
...props
@ -73,6 +75,25 @@ function ListImpl<ItemT>(
},
})
const [onViewableItemsChanged, viewabilityConfig] = React.useMemo(() => {
if (!onItemSeen) {
return [undefined, undefined]
}
return [
(info: {viewableItems: Array<ViewToken>; changed: Array<ViewToken>}) => {
for (const item of info.changed) {
if (item.isViewable) {
onItemSeen(item.item)
}
}
},
{
itemVisiblePercentThreshold: 40,
minimumViewTime: 2e3,
},
]
}, [onItemSeen])
let refreshControl
if (refreshing !== undefined || onRefresh !== undefined) {
refreshControl = (
@ -102,6 +123,8 @@ function ListImpl<ItemT>(
refreshControl={refreshControl}
onScroll={scrollHandler}
scrollEventThrottle={1}
onViewableItemsChanged={onViewableItemsChanged}
viewabilityConfig={viewabilityConfig}
style={style}
ref={ref}
/>