Only poll feed when feed page is focused (#2064)

* Do no poll when screen is not focused

* Avoid polling unless focused

* Handle homepage in background

* Fix the intl:check to ignore comments in diffs

---------

Co-authored-by: Paul Frazee <pfrazee@gmail.com>
zio/stable
Eric Bailey 2023-12-01 15:40:50 -06:00 committed by GitHub
parent f80bd30ef4
commit 9dec9d7276
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 26 additions and 13 deletions

View File

@ -30,7 +30,7 @@
"perf:test:results": "NODE_ENV=test flashlight report .perf/results.json", "perf:test:results": "NODE_ENV=test flashlight report .perf/results.json",
"perf:measure": "NODE_ENV=test flashlight measure", "perf:measure": "NODE_ENV=test flashlight measure",
"intl:build": "yarn intl:check && yarn intl:compile", "intl:build": "yarn intl:check && yarn intl:compile",
"intl:check": "yarn intl:extract && git diff-index --quiet HEAD || (echo '\n⚠ i18n detected un-extracted translations\n' && exit 1)", "intl:check": "yarn intl:extract && git diff-index -G'(^[^\\*# /])|(^#\\w)|(^\\s+[^\\*#/])' HEAD || (echo '\n⚠ i18n detected un-extracted translations\n' && exit 1)",
"intl:extract": "lingui extract", "intl:extract": "lingui extract",
"intl:compile": "lingui compile" "intl:compile": "lingui compile"
}, },

View File

@ -158,9 +158,9 @@ export function FeedPage({
<View testID={testID} style={s.h100pct}> <View testID={testID} style={s.h100pct}>
<Feed <Feed
testID={testID ? `${testID}-feed` : undefined} testID={testID ? `${testID}-feed` : undefined}
enabled={isPageFocused}
feed={feed} feed={feed}
feedParams={feedParams} feedParams={feedParams}
enabled={isPageFocused}
pollInterval={POLL_FREQ} pollInterval={POLL_FREQ}
scrollElRef={scrollElRef} scrollElRef={scrollElRef}
onScroll={onMainScroll} onScroll={onMainScroll}

View File

@ -89,7 +89,7 @@ let Feed = ({
const isEmpty = !isFetching && !data?.pages[0]?.slices.length const isEmpty = !isFetching && !data?.pages[0]?.slices.length
const checkForNew = React.useCallback(async () => { const checkForNew = React.useCallback(async () => {
if (!data?.pages[0] || isFetching || !onHasNew) { if (!data?.pages[0] || isFetching || !onHasNew || !enabled) {
return return
} }
try { try {
@ -99,7 +99,7 @@ let Feed = ({
} catch (e) { } catch (e) {
logger.error('Poll latest failed', {feed, error: String(e)}) logger.error('Poll latest failed', {feed, error: String(e)})
} }
}, [feed, data, isFetching, onHasNew]) }, [feed, data, isFetching, onHasNew, enabled])
React.useEffect(() => { React.useEffect(() => {
// we store the interval handler in a ref to avoid needless // we store the interval handler in a ref to avoid needless

View File

@ -1,6 +1,6 @@
import React from 'react' import React from 'react'
import {View, ActivityIndicator, StyleSheet} from 'react-native' import {View, ActivityIndicator, StyleSheet} from 'react-native'
import {useFocusEffect} from '@react-navigation/native' import {useFocusEffect, useIsFocused} from '@react-navigation/native'
import {NativeStackScreenProps, HomeTabNavigatorParams} from 'lib/routes/types' import {NativeStackScreenProps, HomeTabNavigatorParams} from 'lib/routes/types'
import {FeedDescriptor, FeedParams} from '#/state/queries/post-feed' import {FeedDescriptor, FeedParams} from '#/state/queries/post-feed'
import {FollowingEmptyState} from 'view/com/posts/FollowingEmptyState' import {FollowingEmptyState} from 'view/com/posts/FollowingEmptyState'
@ -39,6 +39,7 @@ function HomeScreenReady({
const setMinimalShellMode = useSetMinimalShellMode() const setMinimalShellMode = useSetMinimalShellMode()
const setDrawerSwipeDisabled = useSetDrawerSwipeDisabled() const setDrawerSwipeDisabled = useSetDrawerSwipeDisabled()
const [selectedPage, setSelectedPage] = React.useState(0) const [selectedPage, setSelectedPage] = React.useState(0)
const isPageFocused = useIsFocused()
/** /**
* Used to ensure that we re-compute `customFeeds` AND force a re-render of * Used to ensure that we re-compute `customFeeds` AND force a re-render of
@ -132,7 +133,7 @@ function HomeScreenReady({
<FeedPage <FeedPage
key="1" key="1"
testID="followingFeedPage" testID="followingFeedPage"
isPageFocused={selectedPage === 0} isPageFocused={selectedPage === 0 && isPageFocused}
feed={homeFeedParams.mergeFeedEnabled ? 'home' : 'following'} feed={homeFeedParams.mergeFeedEnabled ? 'home' : 'following'}
feedParams={homeFeedParams} feedParams={homeFeedParams}
renderEmptyState={renderFollowingEmptyState} renderEmptyState={renderFollowingEmptyState}
@ -143,7 +144,7 @@ function HomeScreenReady({
<FeedPage <FeedPage
key={f} key={f}
testID="customFeedPage" testID="customFeedPage"
isPageFocused={selectedPage === 1 + index} isPageFocused={selectedPage === 1 + index && isPageFocused}
feed={f} feed={f}
renderEmptyState={renderCustomFeedEmptyState} renderEmptyState={renderCustomFeedEmptyState}
/> />
@ -159,7 +160,7 @@ function HomeScreenReady({
tabBarPosition="top"> tabBarPosition="top">
<FeedPage <FeedPage
testID="customFeedPage" testID="customFeedPage"
isPageFocused isPageFocused={isPageFocused}
feed={`feedgen|at://did:plc:z72i7hdynmk6r22z27h6tvur/app.bsky.feed.generator/whats-hot`} feed={`feedgen|at://did:plc:z72i7hdynmk6r22z27h6tvur/app.bsky.feed.generator/whats-hot`}
renderEmptyState={renderCustomFeedEmptyState} renderEmptyState={renderCustomFeedEmptyState}
/> />

View File

@ -420,6 +420,7 @@ const FeedSection = React.forwardRef<SectionRef, FeedSectionProps>(
<View> <View>
<Feed <Feed
testID="postsFeed" testID="postsFeed"
enabled={isFocused}
feed={feed} feed={feed}
pollInterval={30e3} pollInterval={30e3}
scrollElRef={scrollElRef} scrollElRef={scrollElRef}
@ -428,7 +429,6 @@ const FeedSection = React.forwardRef<SectionRef, FeedSectionProps>(
scrollEventThrottle={1} scrollEventThrottle={1}
renderEmptyState={renderPostsEmpty} renderEmptyState={renderPostsEmpty}
headerOffset={headerHeight} headerOffset={headerHeight}
enabled={isFocused}
/> />
{(isScrolledDown || hasNew) && ( {(isScrolledDown || hasNew) && (
<LoadLatestBtn <LoadLatestBtn

View File

@ -402,7 +402,7 @@ export function ProfileFeedScreenInner({
isHeaderReady={true} isHeaderReady={true}
renderHeader={renderHeader} renderHeader={renderHeader}
onCurrentPageSelected={onCurrentPageSelected}> onCurrentPageSelected={onCurrentPageSelected}>
{({onScroll, headerHeight, isScrolledDown, scrollElRef}) => {({onScroll, headerHeight, isScrolledDown, scrollElRef, isFocused}) =>
isPublic ? ( isPublic ? (
<FeedSection <FeedSection
ref={feedSectionRef} ref={feedSectionRef}
@ -413,6 +413,7 @@ export function ProfileFeedScreenInner({
scrollElRef={ scrollElRef={
scrollElRef as React.MutableRefObject<FlatList<any> | null> scrollElRef as React.MutableRefObject<FlatList<any> | null>
} }
isFocused={isFocused}
/> />
) : ( ) : (
<CenteredView sideBorders style={[{paddingTop: headerHeight}]}> <CenteredView sideBorders style={[{paddingTop: headerHeight}]}>
@ -492,10 +493,11 @@ interface FeedSectionProps {
headerHeight: number headerHeight: number
isScrolledDown: boolean isScrolledDown: boolean
scrollElRef: React.MutableRefObject<FlatList<any> | null> scrollElRef: React.MutableRefObject<FlatList<any> | null>
isFocused: boolean
} }
const FeedSection = React.forwardRef<SectionRef, FeedSectionProps>( const FeedSection = React.forwardRef<SectionRef, FeedSectionProps>(
function FeedSectionImpl( function FeedSectionImpl(
{feed, onScroll, headerHeight, isScrolledDown, scrollElRef}, {feed, onScroll, headerHeight, isScrolledDown, scrollElRef, isFocused},
ref, ref,
) { ) {
const [hasNew, setHasNew] = React.useState(false) const [hasNew, setHasNew] = React.useState(false)
@ -518,6 +520,7 @@ const FeedSection = React.forwardRef<SectionRef, FeedSectionProps>(
return ( return (
<View> <View>
<Feed <Feed
enabled={isFocused}
feed={feed} feed={feed}
pollInterval={30e3} pollInterval={30e3}
scrollElRef={scrollElRef} scrollElRef={scrollElRef}

View File

@ -159,7 +159,13 @@ function ProfileListScreenLoaded({
isHeaderReady={true} isHeaderReady={true}
renderHeader={renderHeader} renderHeader={renderHeader}
onCurrentPageSelected={onCurrentPageSelected}> onCurrentPageSelected={onCurrentPageSelected}>
{({onScroll, headerHeight, isScrolledDown, scrollElRef}) => ( {({
onScroll,
headerHeight,
isScrolledDown,
scrollElRef,
isFocused,
}) => (
<FeedSection <FeedSection
ref={feedSectionRef} ref={feedSectionRef}
feed={`list|${uri}`} feed={`list|${uri}`}
@ -169,6 +175,7 @@ function ProfileListScreenLoaded({
onScroll={onScroll} onScroll={onScroll}
headerHeight={headerHeight} headerHeight={headerHeight}
isScrolledDown={isScrolledDown} isScrolledDown={isScrolledDown}
isFocused={isFocused}
/> />
)} )}
{({onScroll, headerHeight, isScrolledDown, scrollElRef}) => ( {({onScroll, headerHeight, isScrolledDown, scrollElRef}) => (
@ -519,10 +526,11 @@ interface FeedSectionProps {
headerHeight: number headerHeight: number
isScrolledDown: boolean isScrolledDown: boolean
scrollElRef: React.MutableRefObject<FlatList<any> | null> scrollElRef: React.MutableRefObject<FlatList<any> | null>
isFocused: boolean
} }
const FeedSection = React.forwardRef<SectionRef, FeedSectionProps>( const FeedSection = React.forwardRef<SectionRef, FeedSectionProps>(
function FeedSectionImpl( function FeedSectionImpl(
{feed, scrollElRef, onScroll, headerHeight, isScrolledDown}, {feed, scrollElRef, onScroll, headerHeight, isScrolledDown, isFocused},
ref, ref,
) { ) {
const queryClient = useQueryClient() const queryClient = useQueryClient()
@ -545,6 +553,7 @@ const FeedSection = React.forwardRef<SectionRef, FeedSectionProps>(
<View> <View>
<Feed <Feed
testID="listFeed" testID="listFeed"
enabled={isFocused}
feed={feed} feed={feed}
pollInterval={30e3} pollInterval={30e3}
scrollElRef={scrollElRef} scrollElRef={scrollElRef}