Merge branch 'custom-algos' of https://github.com/bluesky-social/social-app into custom-algos

zio/stable
Ansh Nanda 2023-05-25 00:18:00 -07:00
commit 524f8b6abd
5 changed files with 103 additions and 23 deletions

View File

@ -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 {

View File

@ -3,7 +3,6 @@ import {StyleSheet, TouchableOpacity} 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'
@ -12,30 +11,60 @@ const HITSLOP = {left: 20, top: 20, right: 20, bottom: 20}
export const LoadLatestBtn = ({ export const LoadLatestBtn = ({
onPress, onPress,
label, label,
showIndicator,
minimalShellMode,
}: { }: {
onPress: () => void onPress: () => void
label: string label: string
showIndicator: boolean
minimalShellMode?: 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 <>
style={[pal.view, pal.borderDark, styles.loadLatest]} {showIndicator && (
onPress={onPress} <TouchableOpacity
hitSlop={HITSLOP} style={[
accessibilityRole="button" pal.view,
accessibilityLabel={label} pal.borderDark,
accessibilityHint=""> styles.loadLatestCentered,
<Text type="md-bold" style={pal.text}> minimalShellMode && styles.loadLatestCenteredMinimal,
<FontAwesomeIcon ]}
icon="angle-up" onPress={onPress}
size={21} hitSlop={HITSLOP}
style={[pal.text, styles.icon]} accessibilityRole="button"
/> accessibilityLabel={label}
</Text> accessibilityHint="">
</TouchableOpacity> <Text type="md-bold" style={pal.text}>
{label}
</Text>
</TouchableOpacity>
)}
<TouchableOpacity
style={[pal.view, pal.borderDark, styles.loadLatest]}
onPress={onPress}
hitSlop={HITSLOP}
accessibilityRole="button"
accessibilityLabel={label}
accessibilityHint="">
<Text type="md-bold" style={pal.text}>
<FontAwesomeIcon
icon="angle-up"
size={21}
style={[pal.text, styles.icon]}
/>
</Text>
</TouchableOpacity>
</>
) )
} }
@ -58,4 +87,21 @@ const styles = StyleSheet.create({
position: 'relative', position: 'relative',
top: 2, top: 2,
}, },
loadLatestCentered: {
flexDirection: 'row',
alignItems: 'center',
justifyContent: 'center',
position: 'absolute',
left: '50vw',
// @ts-ignore web only -prf
transform: 'translateX(-50%)',
top: 60,
paddingHorizontal: 24,
paddingVertical: 14,
borderRadius: 30,
borderWidth: 1,
},
loadLatestCenteredMinimal: {
top: 20,
},
}) })

View File

@ -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 {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
minimalShellMode?: boolean // NOTE not used on mobile -prf
}) => {
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,
},
}) })

View File

@ -240,6 +240,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
@ -254,8 +255,13 @@ 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}
minimalShellMode={store.shell.minimalShellMode}
/>
)} )}
<FAB <FAB
testID="composeFAB" testID="composeFAB"

View File

@ -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,12 @@ 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}
minimalShellMode={true}
/> />
)} )}
</View> </View>