Update load latest to show when there's new activity with an indicator
parent
6f02548bca
commit
e89103915d
|
@ -290,7 +290,9 @@ export class NotificationsFeedModel {
|
||||||
}
|
}
|
||||||
|
|
||||||
get hasNewLatest() {
|
get hasNewLatest() {
|
||||||
return this.queuedNotifications && this.queuedNotifications?.length > 0
|
return Boolean(
|
||||||
|
this.queuedNotifications && this.queuedNotifications?.length > 0,
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
get unreadCountLabel(): string {
|
get unreadCountLabel(): string {
|
||||||
|
|
|
@ -1,24 +1,32 @@
|
||||||
import React from 'react'
|
import React from 'react'
|
||||||
import {StyleSheet, TouchableOpacity} from 'react-native'
|
import {StyleSheet, TouchableOpacity, View} from 'react-native'
|
||||||
import {FontAwesomeIcon} from '@fortawesome/react-native-fontawesome'
|
import {FontAwesomeIcon} from '@fortawesome/react-native-fontawesome'
|
||||||
import {Text} from '../text/Text'
|
import {Text} from '../text/Text'
|
||||||
import {usePalette} from 'lib/hooks/usePalette'
|
import {usePalette} from 'lib/hooks/usePalette'
|
||||||
import {UpIcon} from 'lib/icons'
|
|
||||||
import {LoadLatestBtn as LoadLatestBtnMobile} from './LoadLatestBtnMobile'
|
import {LoadLatestBtn as LoadLatestBtnMobile} from './LoadLatestBtnMobile'
|
||||||
import {isMobileWeb} from 'platform/detection'
|
import {isMobileWeb} from 'platform/detection'
|
||||||
|
import {colors} from 'lib/styles'
|
||||||
|
|
||||||
const HITSLOP = {left: 20, top: 20, right: 20, bottom: 20}
|
const HITSLOP = {left: 20, top: 20, right: 20, bottom: 20}
|
||||||
|
|
||||||
export const LoadLatestBtn = ({
|
export const LoadLatestBtn = ({
|
||||||
onPress,
|
onPress,
|
||||||
label,
|
label,
|
||||||
|
showIndicator,
|
||||||
}: {
|
}: {
|
||||||
onPress: () => void
|
onPress: () => void
|
||||||
label: string
|
label: string
|
||||||
|
showIndicator: boolean
|
||||||
}) => {
|
}) => {
|
||||||
const pal = usePalette('default')
|
const pal = usePalette('default')
|
||||||
if (isMobileWeb) {
|
if (isMobileWeb) {
|
||||||
return <LoadLatestBtnMobile onPress={onPress} label={label} />
|
return (
|
||||||
|
<LoadLatestBtnMobile
|
||||||
|
onPress={onPress}
|
||||||
|
label={label}
|
||||||
|
showIndicator={showIndicator}
|
||||||
|
/>
|
||||||
|
)
|
||||||
}
|
}
|
||||||
return (
|
return (
|
||||||
<TouchableOpacity
|
<TouchableOpacity
|
||||||
|
@ -35,6 +43,7 @@ export const LoadLatestBtn = ({
|
||||||
style={[pal.text, styles.icon]}
|
style={[pal.text, styles.icon]}
|
||||||
/>
|
/>
|
||||||
</Text>
|
</Text>
|
||||||
|
{showIndicator && <View style={styles.indicator} />}
|
||||||
</TouchableOpacity>
|
</TouchableOpacity>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -58,4 +67,13 @@ const styles = StyleSheet.create({
|
||||||
position: 'relative',
|
position: 'relative',
|
||||||
top: 2,
|
top: 2,
|
||||||
},
|
},
|
||||||
|
indicator: {
|
||||||
|
position: 'absolute',
|
||||||
|
top: 3,
|
||||||
|
right: 3,
|
||||||
|
backgroundColor: colors.blue3,
|
||||||
|
width: 10,
|
||||||
|
height: 10,
|
||||||
|
borderRadius: 6,
|
||||||
|
},
|
||||||
})
|
})
|
||||||
|
|
|
@ -1,16 +1,26 @@
|
||||||
import React from 'react'
|
import React from 'react'
|
||||||
import {StyleSheet, TouchableOpacity} from 'react-native'
|
import {StyleSheet, TouchableOpacity, View} from 'react-native'
|
||||||
import {observer} from 'mobx-react-lite'
|
import {observer} from 'mobx-react-lite'
|
||||||
import {FontAwesomeIcon} from '@fortawesome/react-native-fontawesome'
|
import {FontAwesomeIcon} from '@fortawesome/react-native-fontawesome'
|
||||||
import {useSafeAreaInsets} from 'react-native-safe-area-context'
|
import {useSafeAreaInsets} from 'react-native-safe-area-context'
|
||||||
import {clamp} from 'lodash'
|
import {clamp} from 'lodash'
|
||||||
import {useStores} from 'state/index'
|
import {useStores} from 'state/index'
|
||||||
import {usePalette} from 'lib/hooks/usePalette'
|
import {usePalette} from 'lib/hooks/usePalette'
|
||||||
|
import {useColorSchemeStyle} from 'lib/hooks/useColorSchemeStyle'
|
||||||
|
import {colors} from 'lib/styles'
|
||||||
|
|
||||||
const HITSLOP = {left: 20, top: 20, right: 20, bottom: 20}
|
const HITSLOP = {left: 20, top: 20, right: 20, bottom: 20}
|
||||||
|
|
||||||
export const LoadLatestBtn = observer(
|
export const LoadLatestBtn = observer(
|
||||||
({onPress, label}: {onPress: () => void; label: string}) => {
|
({
|
||||||
|
onPress,
|
||||||
|
label,
|
||||||
|
showIndicator,
|
||||||
|
}: {
|
||||||
|
onPress: () => void
|
||||||
|
label: string
|
||||||
|
showIndicator: boolean
|
||||||
|
}) => {
|
||||||
const store = useStores()
|
const store = useStores()
|
||||||
const pal = usePalette('default')
|
const pal = usePalette('default')
|
||||||
const safeAreaInsets = useSafeAreaInsets()
|
const safeAreaInsets = useSafeAreaInsets()
|
||||||
|
@ -30,6 +40,7 @@ export const LoadLatestBtn = observer(
|
||||||
accessibilityLabel={label}
|
accessibilityLabel={label}
|
||||||
accessibilityHint="">
|
accessibilityHint="">
|
||||||
<FontAwesomeIcon icon="angle-up" color={pal.colors.text} size={19} />
|
<FontAwesomeIcon icon="angle-up" color={pal.colors.text} size={19} />
|
||||||
|
{showIndicator && <View style={[styles.indicator, pal.borderDark]} />}
|
||||||
</TouchableOpacity>
|
</TouchableOpacity>
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
|
@ -48,4 +59,14 @@ const styles = StyleSheet.create({
|
||||||
alignItems: 'center',
|
alignItems: 'center',
|
||||||
justifyContent: 'center',
|
justifyContent: 'center',
|
||||||
},
|
},
|
||||||
|
indicator: {
|
||||||
|
position: 'absolute',
|
||||||
|
top: 3,
|
||||||
|
right: 3,
|
||||||
|
backgroundColor: colors.blue3,
|
||||||
|
width: 12,
|
||||||
|
height: 12,
|
||||||
|
borderRadius: 6,
|
||||||
|
borderWidth: 1,
|
||||||
|
},
|
||||||
})
|
})
|
||||||
|
|
|
@ -246,6 +246,7 @@ const FeedPage = observer(
|
||||||
feed.refresh()
|
feed.refresh()
|
||||||
}, [feed, scrollToTop])
|
}, [feed, scrollToTop])
|
||||||
|
|
||||||
|
const hasNew = feed.hasNewLatest && !feed.isRefreshing
|
||||||
return (
|
return (
|
||||||
<View testID={testID} style={s.h100pct}>
|
<View testID={testID} style={s.h100pct}>
|
||||||
<Feed
|
<Feed
|
||||||
|
@ -260,8 +261,12 @@ const FeedPage = observer(
|
||||||
renderEmptyState={renderEmptyState}
|
renderEmptyState={renderEmptyState}
|
||||||
headerOffset={HEADER_OFFSET}
|
headerOffset={HEADER_OFFSET}
|
||||||
/>
|
/>
|
||||||
{isScrolledDown && (
|
{(isScrolledDown || hasNew) && (
|
||||||
<LoadLatestBtn onPress={onPressLoadLatest} label="Load new posts" />
|
<LoadLatestBtn
|
||||||
|
onPress={onPressLoadLatest}
|
||||||
|
label="Load new posts"
|
||||||
|
showIndicator={hasNew}
|
||||||
|
/>
|
||||||
)}
|
)}
|
||||||
<FAB
|
<FAB
|
||||||
testID="composeFAB"
|
testID="composeFAB"
|
||||||
|
|
|
@ -88,6 +88,9 @@ export const NotificationsScreen = withAuthRequired(
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const hasNew =
|
||||||
|
store.me.notifications.hasNewLatest &&
|
||||||
|
!store.me.notifications.isRefreshing
|
||||||
return (
|
return (
|
||||||
<View testID="notificationsScreen" style={s.hContentRegion}>
|
<View testID="notificationsScreen" style={s.hContentRegion}>
|
||||||
<ViewHeader title="Notifications" canGoBack={false} />
|
<ViewHeader title="Notifications" canGoBack={false} />
|
||||||
|
@ -98,10 +101,11 @@ export const NotificationsScreen = withAuthRequired(
|
||||||
onScroll={onMainScroll}
|
onScroll={onMainScroll}
|
||||||
scrollElRef={scrollElRef}
|
scrollElRef={scrollElRef}
|
||||||
/>
|
/>
|
||||||
{isScrolledDown && (
|
{(isScrolledDown || hasNew) && (
|
||||||
<LoadLatestBtn
|
<LoadLatestBtn
|
||||||
onPress={onPressLoadLatest}
|
onPress={onPressLoadLatest}
|
||||||
label="Load new notifications"
|
label="Load new notifications"
|
||||||
|
showIndicator={hasNew}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
</View>
|
</View>
|
||||||
|
|
Loading…
Reference in New Issue