Replace the FAB with a compose prompt at the top of the feed
parent
39058cd36a
commit
8e3dc52536
|
@ -0,0 +1,63 @@
|
|||
import React from 'react'
|
||||
import {StyleSheet, Text, TouchableOpacity, View} from 'react-native'
|
||||
import {FontAwesomeIcon} from '@fortawesome/react-native-fontawesome'
|
||||
import {colors} from '../../lib/styles'
|
||||
import {useStores} from '../../../state'
|
||||
import {UserAvatar} from '../util/UserAvatar'
|
||||
|
||||
export function ComposePrompt({onPressCompose}: {onPressCompose: () => void}) {
|
||||
const store = useStores()
|
||||
const onPressAvatar = () => {
|
||||
store.nav.navigate(`/profile/${store.me.handle}`)
|
||||
}
|
||||
return (
|
||||
<TouchableOpacity style={styles.container} onPress={onPressCompose}>
|
||||
<TouchableOpacity style={styles.avatar} onPress={onPressAvatar}>
|
||||
<UserAvatar
|
||||
size={50}
|
||||
handle={store.me.handle || ''}
|
||||
displayName={store.me.displayName}
|
||||
/>
|
||||
</TouchableOpacity>
|
||||
<View style={styles.textContainer}>
|
||||
<Text style={styles.text}>What's happening?</Text>
|
||||
</View>
|
||||
<View style={styles.btn}>
|
||||
<Text style={styles.btnText}>Post</Text>
|
||||
</View>
|
||||
</TouchableOpacity>
|
||||
)
|
||||
}
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
container: {
|
||||
borderRadius: 6,
|
||||
margin: 2,
|
||||
marginBottom: 0,
|
||||
paddingHorizontal: 10,
|
||||
paddingVertical: 10,
|
||||
flexDirection: 'row',
|
||||
alignItems: 'center',
|
||||
backgroundColor: colors.white,
|
||||
},
|
||||
avatar: {
|
||||
width: 50,
|
||||
},
|
||||
textContainer: {
|
||||
marginLeft: 10,
|
||||
flex: 1,
|
||||
},
|
||||
text: {
|
||||
color: colors.gray4,
|
||||
fontSize: 17,
|
||||
},
|
||||
btn: {
|
||||
backgroundColor: colors.gray1,
|
||||
paddingVertical: 6,
|
||||
paddingHorizontal: 14,
|
||||
borderRadius: 30,
|
||||
},
|
||||
btnText: {
|
||||
color: colors.gray5,
|
||||
},
|
||||
})
|
|
@ -6,23 +6,34 @@ import {EmptyState} from '../util/EmptyState'
|
|||
import {ErrorMessage} from '../util/ErrorMessage'
|
||||
import {FeedModel, FeedItemModel} from '../../../state/models/feed-view'
|
||||
import {FeedItem} from './FeedItem'
|
||||
import {ComposePrompt} from '../composer/Prompt'
|
||||
|
||||
const COMPOSE_PROMPT_ITEM = {_reactKey: '__prompt__'}
|
||||
|
||||
export const Feed = observer(function Feed({
|
||||
feed,
|
||||
style,
|
||||
scrollElRef,
|
||||
onPressCompose,
|
||||
onPressTryAgain,
|
||||
}: {
|
||||
feed: FeedModel
|
||||
style?: StyleProp<ViewStyle>
|
||||
scrollElRef?: MutableRefObject<FlatList<any> | null>
|
||||
onPressCompose?: () => void
|
||||
onPressTryAgain?: () => void
|
||||
}) {
|
||||
// TODO optimize renderItem or FeedItem, we're getting this notice from RN: -prf
|
||||
// VirtualizedList: You have a large list that is slow to update - make sure your
|
||||
// renderItem function renders components that follow React performance best practices
|
||||
// like PureComponent, shouldComponentUpdate, etc
|
||||
const renderItem = ({item}: {item: FeedItemModel}) => <FeedItem item={item} />
|
||||
const renderItem = ({item}: {item: FeedItemModel}) => {
|
||||
if (item === COMPOSE_PROMPT_ITEM) {
|
||||
return <ComposePrompt onPressCompose={onPressCompose} />
|
||||
} else {
|
||||
return <FeedItem item={item} />
|
||||
}
|
||||
}
|
||||
const onRefresh = () => {
|
||||
feed.refresh().catch(err => console.error('Failed to refresh', err))
|
||||
}
|
||||
|
@ -45,7 +56,7 @@ export const Feed = observer(function Feed({
|
|||
{feed.hasContent && (
|
||||
<FlatList
|
||||
ref={scrollElRef}
|
||||
data={feed.feed.slice()}
|
||||
data={[COMPOSE_PROMPT_ITEM].concat(feed.feed.slice())}
|
||||
keyExtractor={item => item._reactKey}
|
||||
renderItem={renderItem}
|
||||
refreshing={feed.isRefreshing}
|
||||
|
|
|
@ -65,7 +65,7 @@ export const Home = observer(function Home({
|
|||
}
|
||||
}, [visible, store])
|
||||
|
||||
const onComposePress = () => {
|
||||
const onPressCompose = () => {
|
||||
store.shell.openComposer({onPost: onCreatePost})
|
||||
}
|
||||
const onCreatePost = () => {
|
||||
|
@ -81,12 +81,12 @@ export const Home = observer(function Home({
|
|||
|
||||
return (
|
||||
<View style={s.flex1}>
|
||||
<ViewHeader title="Bluesky" subtitle="Private Beta" />
|
||||
<Feed
|
||||
key="default"
|
||||
feed={defaultFeedView}
|
||||
scrollElRef={scrollElRef}
|
||||
style={{flex: 1}}
|
||||
onPressCompose={onPressCompose}
|
||||
onPressTryAgain={onPressTryAgain}
|
||||
/>
|
||||
{defaultFeedView.hasNewLatest ? (
|
||||
|
@ -95,7 +95,6 @@ export const Home = observer(function Home({
|
|||
<Text style={styles.loadLatestText}>Load new posts</Text>
|
||||
</TouchableOpacity>
|
||||
) : undefined}
|
||||
<FAB icon="pen-nib" onPress={onComposePress} />
|
||||
</View>
|
||||
)
|
||||
})
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
import React, {useState, useEffect} from 'react'
|
||||
import {View} from 'react-native'
|
||||
import {ViewHeader} from '../com/util/ViewHeader'
|
||||
import {FAB} from '../com/util/FloatingActionButton'
|
||||
import {Feed} from '../com/notifications/Feed'
|
||||
import {useStores} from '../../state'
|
||||
import {NotificationsViewModel} from '../../state/models/notifications-view'
|
||||
|
@ -37,9 +36,6 @@ export const Notifications = ({navIdx, visible}: ScreenParams) => {
|
|||
}
|
||||
}, [visible, store])
|
||||
|
||||
const onComposePress = () => {
|
||||
store.shell.openComposer({})
|
||||
}
|
||||
const onPressTryAgain = () => {
|
||||
notesView?.refresh()
|
||||
}
|
||||
|
@ -48,7 +44,6 @@ export const Notifications = ({navIdx, visible}: ScreenParams) => {
|
|||
<View style={{flex: 1}}>
|
||||
<ViewHeader title="Notifications" />
|
||||
{notesView && <Feed view={notesView} onPressTryAgain={onPressTryAgain} />}
|
||||
<FAB icon="pen-nib" onPress={onComposePress} />
|
||||
</View>
|
||||
)
|
||||
}
|
||||
|
|
|
@ -3,7 +3,6 @@ import {StyleSheet, Text, View} from 'react-native'
|
|||
import {observer} from 'mobx-react-lite'
|
||||
import {FontAwesomeIcon} from '@fortawesome/react-native-fontawesome'
|
||||
import {ViewSelector} from '../com/util/ViewSelector'
|
||||
import {FAB} from '../com/util/FloatingActionButton'
|
||||
import {ScreenParams} from '../routes'
|
||||
import {ProfileUiModel, Sections} from '../../state/models/profile-ui'
|
||||
import {MembershipItem} from '../../state/models/memberships-view'
|
||||
|
@ -86,9 +85,6 @@ export const Profile = observer(({navIdx, visible, params}: ScreenParams) => {
|
|||
),
|
||||
)
|
||||
}
|
||||
const onComposePress = () => {
|
||||
store.shell.openComposer({})
|
||||
}
|
||||
|
||||
// rendering
|
||||
// =
|
||||
|
@ -241,7 +237,6 @@ export const Profile = observer(({navIdx, visible, params}: ScreenParams) => {
|
|||
) : (
|
||||
renderHeader()
|
||||
)}
|
||||
<FAB icon="pen-nib" onPress={onComposePress} />
|
||||
</View>
|
||||
)
|
||||
})
|
||||
|
|
Loading…
Reference in New Issue