Use a post and handle-resolution cache to enable quick postthread loading (#1097)
* Use a post and handle-resolution cache to enable quick postthread loading * Fix positioning of thread when loaded from cache and give more visual cues * Include parent posts in cache * Include notifications in cache
This commit is contained in:
parent
7256169506
commit
a63f97aef2
9 changed files with 167 additions and 18 deletions
|
@ -20,25 +20,37 @@ import {ComposePrompt} from '../composer/Prompt'
|
|||
import {ErrorMessage} from '../util/error/ErrorMessage'
|
||||
import {Text} from '../util/text/Text'
|
||||
import {s} from 'lib/styles'
|
||||
import {isDesktopWeb, isMobileWeb} from 'platform/detection'
|
||||
import {isIOS, isDesktopWeb, isMobileWeb} from 'platform/detection'
|
||||
import {usePalette} from 'lib/hooks/usePalette'
|
||||
import {useSetTitle} from 'lib/hooks/useSetTitle'
|
||||
import {useNavigation} from '@react-navigation/native'
|
||||
import {NavigationProp} from 'lib/routes/types'
|
||||
import {sanitizeDisplayName} from 'lib/strings/display-names'
|
||||
|
||||
const MAINTAIN_VISIBLE_CONTENT_POSITION = {minIndexForVisible: 0}
|
||||
|
||||
const PARENT_SPINNER = {
|
||||
_reactKey: '__parent_spinner__',
|
||||
_isHighlightedPost: false,
|
||||
}
|
||||
const REPLY_PROMPT = {_reactKey: '__reply__', _isHighlightedPost: false}
|
||||
const DELETED = {_reactKey: '__deleted__', _isHighlightedPost: false}
|
||||
const BLOCKED = {_reactKey: '__blocked__', _isHighlightedPost: false}
|
||||
const CHILD_SPINNER = {
|
||||
_reactKey: '__child_spinner__',
|
||||
_isHighlightedPost: false,
|
||||
}
|
||||
const BOTTOM_COMPONENT = {
|
||||
_reactKey: '__bottom_component__',
|
||||
_isHighlightedPost: false,
|
||||
}
|
||||
type YieldedItem =
|
||||
| PostThreadItemModel
|
||||
| typeof PARENT_SPINNER
|
||||
| typeof REPLY_PROMPT
|
||||
| typeof DELETED
|
||||
| typeof BLOCKED
|
||||
| typeof PARENT_SPINNER
|
||||
|
||||
export const PostThread = observer(function PostThread({
|
||||
uri,
|
||||
|
@ -55,10 +67,19 @@ export const PostThread = observer(function PostThread({
|
|||
const navigation = useNavigation<NavigationProp>()
|
||||
const posts = React.useMemo(() => {
|
||||
if (view.thread) {
|
||||
return Array.from(flattenThread(view.thread)).concat([BOTTOM_COMPONENT])
|
||||
const arr = Array.from(flattenThread(view.thread))
|
||||
if (view.isLoadingFromCache) {
|
||||
if (view.thread?.postRecord?.reply) {
|
||||
arr.unshift(PARENT_SPINNER)
|
||||
}
|
||||
arr.push(CHILD_SPINNER)
|
||||
} else {
|
||||
arr.push(BOTTOM_COMPONENT)
|
||||
}
|
||||
return arr
|
||||
}
|
||||
return []
|
||||
}, [view.thread])
|
||||
}, [view.isLoadingFromCache, view.thread])
|
||||
useSetTitle(
|
||||
view.thread?.postRecord &&
|
||||
`${sanitizeDisplayName(
|
||||
|
@ -80,17 +101,15 @@ export const PostThread = observer(function PostThread({
|
|||
setIsRefreshing(false)
|
||||
}, [view, setIsRefreshing])
|
||||
|
||||
const onLayout = React.useCallback(() => {
|
||||
const onContentSizeChange = React.useCallback(() => {
|
||||
const index = posts.findIndex(post => post._isHighlightedPost)
|
||||
if (index !== -1) {
|
||||
ref.current?.scrollToIndex({
|
||||
index,
|
||||
animated: false,
|
||||
viewOffset: 40,
|
||||
})
|
||||
}
|
||||
}, [posts, ref])
|
||||
|
||||
const onScrollToIndexFailed = React.useCallback(
|
||||
(info: {
|
||||
index: number
|
||||
|
@ -115,7 +134,13 @@ export const PostThread = observer(function PostThread({
|
|||
|
||||
const renderItem = React.useCallback(
|
||||
({item}: {item: YieldedItem}) => {
|
||||
if (item === REPLY_PROMPT) {
|
||||
if (item === PARENT_SPINNER) {
|
||||
return (
|
||||
<View style={styles.parentSpinner}>
|
||||
<ActivityIndicator />
|
||||
</View>
|
||||
)
|
||||
} else if (item === REPLY_PROMPT) {
|
||||
return <ComposePrompt onPressCompose={onPressReply} />
|
||||
} else if (item === DELETED) {
|
||||
return (
|
||||
|
@ -150,6 +175,12 @@ export const PostThread = observer(function PostThread({
|
|||
]}
|
||||
/>
|
||||
)
|
||||
} else if (item === CHILD_SPINNER) {
|
||||
return (
|
||||
<View style={styles.childSpinner}>
|
||||
<ActivityIndicator />
|
||||
</View>
|
||||
)
|
||||
} else if (item instanceof PostThreadItemModel) {
|
||||
return <PostThreadItem item={item} onPostReply={onRefresh} />
|
||||
}
|
||||
|
@ -247,6 +278,9 @@ export const PostThread = observer(function PostThread({
|
|||
ref={ref}
|
||||
data={posts}
|
||||
initialNumToRender={posts.length}
|
||||
maintainVisibleContentPosition={
|
||||
view.isFromCache ? MAINTAIN_VISIBLE_CONTENT_POSITION : undefined
|
||||
}
|
||||
keyExtractor={item => item._reactKey}
|
||||
renderItem={renderItem}
|
||||
refreshControl={
|
||||
|
@ -257,10 +291,12 @@ export const PostThread = observer(function PostThread({
|
|||
titleColor={pal.colors.text}
|
||||
/>
|
||||
}
|
||||
onLayout={onLayout}
|
||||
onContentSizeChange={
|
||||
!isIOS || !view.isFromCache ? onContentSizeChange : undefined
|
||||
}
|
||||
onScrollToIndexFailed={onScrollToIndexFailed}
|
||||
style={s.hContentRegion}
|
||||
contentContainerStyle={s.contentContainerExtra}
|
||||
contentContainerStyle={styles.contentContainerExtra}
|
||||
/>
|
||||
)
|
||||
})
|
||||
|
@ -307,10 +343,17 @@ const styles = StyleSheet.create({
|
|||
paddingHorizontal: 18,
|
||||
paddingVertical: 18,
|
||||
},
|
||||
parentSpinner: {
|
||||
paddingVertical: 10,
|
||||
},
|
||||
childSpinner: {},
|
||||
bottomBorder: {
|
||||
borderBottomWidth: 1,
|
||||
},
|
||||
bottomSpacer: {
|
||||
height: 200,
|
||||
height: 400,
|
||||
},
|
||||
contentContainerExtra: {
|
||||
paddingBottom: 500,
|
||||
},
|
||||
})
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue