* Fix home feed positioning for floating header * Fix positioning of errors in home feed * Fix lint
This commit is contained in:
+16
-17
@@ -17,8 +17,8 @@ import {OnScrollCb} from '../../lib/hooks/useOnMainScroll'
|
|||||||
import {s} from '../../lib/styles'
|
import {s} from '../../lib/styles'
|
||||||
import {useAnalytics} from '@segment/analytics-react-native'
|
import {useAnalytics} from '@segment/analytics-react-native'
|
||||||
|
|
||||||
const HEADER_SPACER_ITEM = {_reactKey: '__spacer__'}
|
|
||||||
const EMPTY_FEED_ITEM = {_reactKey: '__empty__'}
|
const EMPTY_FEED_ITEM = {_reactKey: '__empty__'}
|
||||||
|
const ERROR_FEED_ITEM = {_reactKey: '__error__'}
|
||||||
|
|
||||||
export const Feed = observer(function Feed({
|
export const Feed = observer(function Feed({
|
||||||
feed,
|
feed,
|
||||||
@@ -27,7 +27,7 @@ export const Feed = observer(function Feed({
|
|||||||
onPressTryAgain,
|
onPressTryAgain,
|
||||||
onScroll,
|
onScroll,
|
||||||
testID,
|
testID,
|
||||||
headerSpacer,
|
headerOffset = 0,
|
||||||
}: {
|
}: {
|
||||||
feed: FeedModel
|
feed: FeedModel
|
||||||
style?: StyleProp<ViewStyle>
|
style?: StyleProp<ViewStyle>
|
||||||
@@ -35,7 +35,7 @@ export const Feed = observer(function Feed({
|
|||||||
onPressTryAgain?: () => void
|
onPressTryAgain?: () => void
|
||||||
onScroll?: OnScrollCb
|
onScroll?: OnScrollCb
|
||||||
testID?: string
|
testID?: string
|
||||||
headerSpacer?: boolean
|
headerOffset?: number
|
||||||
}) {
|
}) {
|
||||||
const {screen, track} = useAnalytics()
|
const {screen, track} = useAnalytics()
|
||||||
|
|
||||||
@@ -56,12 +56,12 @@ export const Feed = observer(function Feed({
|
|||||||
style={styles.emptyState}
|
style={styles.emptyState}
|
||||||
/>
|
/>
|
||||||
)
|
)
|
||||||
|
} else if (item === ERROR_FEED_ITEM) {
|
||||||
|
return (
|
||||||
|
<ErrorMessage message={feed.error} onPressTryAgain={onPressTryAgain} />
|
||||||
|
)
|
||||||
}
|
}
|
||||||
if (item === HEADER_SPACER_ITEM) {
|
return <FeedItem item={item} />
|
||||||
return <View style={styles.headerSpacer} />
|
|
||||||
} else {
|
|
||||||
return <FeedItem item={item} />
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
const onRefresh = () => {
|
const onRefresh = () => {
|
||||||
track('Feed:onRefresh')
|
track('Feed:onRefresh')
|
||||||
@@ -77,13 +77,13 @@ export const Feed = observer(function Feed({
|
|||||||
.loadMore()
|
.loadMore()
|
||||||
.catch(err => feed.rootStore.log.error('Failed to load more posts', err))
|
.catch(err => feed.rootStore.log.error('Failed to load more posts', err))
|
||||||
}
|
}
|
||||||
let data = []
|
let data: any[] = []
|
||||||
if (headerSpacer) {
|
if (feed.hasError) {
|
||||||
data.push(HEADER_SPACER_ITEM)
|
data = data.concat([ERROR_FEED_ITEM])
|
||||||
}
|
}
|
||||||
if (feed.hasLoaded) {
|
if (feed.hasLoaded) {
|
||||||
if (feed.isEmpty) {
|
if (feed.isEmpty) {
|
||||||
data.push(EMPTY_FEED_ITEM)
|
data = data.concat([EMPTY_FEED_ITEM])
|
||||||
} else {
|
} else {
|
||||||
data = data.concat(feed.feed)
|
data = data.concat(feed.feed)
|
||||||
}
|
}
|
||||||
@@ -99,10 +99,7 @@ export const Feed = observer(function Feed({
|
|||||||
return (
|
return (
|
||||||
<View testID={testID} style={style}>
|
<View testID={testID} style={style}>
|
||||||
{feed.isLoading && !data && <PostFeedLoadingPlaceholder />}
|
{feed.isLoading && !data && <PostFeedLoadingPlaceholder />}
|
||||||
{feed.hasError && (
|
{data && (
|
||||||
<ErrorMessage message={feed.error} onPressTryAgain={onPressTryAgain} />
|
|
||||||
)}
|
|
||||||
{feed.hasLoaded && data && (
|
|
||||||
<FlatList
|
<FlatList
|
||||||
ref={scrollElRef}
|
ref={scrollElRef}
|
||||||
data={data}
|
data={data}
|
||||||
@@ -115,6 +112,9 @@ export const Feed = observer(function Feed({
|
|||||||
onRefresh={onRefresh}
|
onRefresh={onRefresh}
|
||||||
onEndReached={onEndReached}
|
onEndReached={onEndReached}
|
||||||
removeClippedSubviews={true}
|
removeClippedSubviews={true}
|
||||||
|
contentInset={{top: headerOffset}}
|
||||||
|
contentOffset={{x: 0, y: headerOffset * -1}}
|
||||||
|
progressViewOffset={headerOffset}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
</View>
|
</View>
|
||||||
@@ -122,7 +122,6 @@ export const Feed = observer(function Feed({
|
|||||||
})
|
})
|
||||||
|
|
||||||
const styles = StyleSheet.create({
|
const styles = StyleSheet.create({
|
||||||
headerSpacer: {height: 42},
|
|
||||||
feedFooter: {paddingTop: 20},
|
feedFooter: {paddingTop: 20},
|
||||||
emptyState: {paddingVertical: 40},
|
emptyState: {paddingVertical: 40},
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -15,6 +15,7 @@ import {useOnMainScroll} from '../lib/hooks/useOnMainScroll'
|
|||||||
import {clamp} from 'lodash'
|
import {clamp} from 'lodash'
|
||||||
import {useAnalytics} from '@segment/analytics-react-native'
|
import {useAnalytics} from '@segment/analytics-react-native'
|
||||||
|
|
||||||
|
const HEADER_HEIGHT = 42
|
||||||
const HITSLOP = {left: 20, top: 20, right: 20, bottom: 20}
|
const HITSLOP = {left: 20, top: 20, right: 20, bottom: 20}
|
||||||
|
|
||||||
export const Home = observer(function Home({navIdx, visible}: ScreenParams) {
|
export const Home = observer(function Home({navIdx, visible}: ScreenParams) {
|
||||||
@@ -42,12 +43,14 @@ export const Home = observer(function Home({navIdx, visible}: ScreenParams) {
|
|||||||
[appState, visible, store],
|
[appState, visible, store],
|
||||||
)
|
)
|
||||||
|
|
||||||
const onSoftReset = () => {
|
const scrollToTop = React.useCallback(() => {
|
||||||
scrollElRef.current?.scrollToOffset({offset: 0})
|
// NOTE: the feed is offset by the height of the collapsing header,
|
||||||
}
|
// so we scroll to the negative of that height -prf
|
||||||
|
scrollElRef.current?.scrollToOffset({offset: -HEADER_HEIGHT})
|
||||||
|
}, [scrollElRef])
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const softResetSub = store.onScreenSoftReset(onSoftReset)
|
const softResetSub = store.onScreenSoftReset(scrollToTop)
|
||||||
const feedCleanup = store.me.mainFeed.registerListeners()
|
const feedCleanup = store.me.mainFeed.registerListeners()
|
||||||
const pollInterval = setInterval(() => doPoll(), 15e3)
|
const pollInterval = setInterval(() => doPoll(), 15e3)
|
||||||
const cleanup = () => {
|
const cleanup = () => {
|
||||||
@@ -72,7 +75,7 @@ export const Home = observer(function Home({navIdx, visible}: ScreenParams) {
|
|||||||
store.me.mainFeed.setup()
|
store.me.mainFeed.setup()
|
||||||
}
|
}
|
||||||
return cleanup
|
return cleanup
|
||||||
}, [visible, store, store.me.mainFeed, navIdx, doPoll, wasVisible])
|
}, [visible, store, store.me.mainFeed, navIdx, doPoll, wasVisible, scrollToTop])
|
||||||
|
|
||||||
const onPressCompose = (imagesOpen?: boolean) => {
|
const onPressCompose = (imagesOpen?: boolean) => {
|
||||||
track('Home:ComposeButtonPressed')
|
track('Home:ComposeButtonPressed')
|
||||||
@@ -83,7 +86,7 @@ export const Home = observer(function Home({navIdx, visible}: ScreenParams) {
|
|||||||
}
|
}
|
||||||
const onPressLoadLatest = () => {
|
const onPressLoadLatest = () => {
|
||||||
store.me.mainFeed.refresh()
|
store.me.mainFeed.refresh()
|
||||||
scrollElRef?.current?.scrollToOffset({offset: 0})
|
scrollToTop()
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@@ -96,7 +99,7 @@ export const Home = observer(function Home({navIdx, visible}: ScreenParams) {
|
|||||||
style={s.h100pct}
|
style={s.h100pct}
|
||||||
onPressTryAgain={onPressTryAgain}
|
onPressTryAgain={onPressTryAgain}
|
||||||
onScroll={onMainScroll}
|
onScroll={onMainScroll}
|
||||||
headerSpacer
|
headerOffset={HEADER_HEIGHT}
|
||||||
/>
|
/>
|
||||||
<ViewHeader title="Bluesky" canGoBack={false} hideOnScroll />
|
<ViewHeader title="Bluesky" canGoBack={false} hideOnScroll />
|
||||||
{store.me.mainFeed.hasNewLatest && !store.me.mainFeed.isRefreshing ? (
|
{store.me.mainFeed.hasNewLatest && !store.me.mainFeed.isRefreshing ? (
|
||||||
|
|||||||
Reference in New Issue
Block a user