Add a composer prompt on home
This commit is contained in:
@@ -9,5 +9,6 @@ export type Gate =
|
||||
| 'onboarding_add_video_feed'
|
||||
| 'onboarding_suggested_starterpacks'
|
||||
| 'remove_show_latest_button'
|
||||
| 'show_composer_prompt'
|
||||
| 'test_gate_1'
|
||||
| 'test_gate_2'
|
||||
|
||||
@@ -202,6 +202,7 @@ export type MetricEvents = {
|
||||
|
||||
'composer:gif:open': {}
|
||||
'composer:gif:select': {}
|
||||
'postComposer:click': {}
|
||||
|
||||
// Data events
|
||||
'account:create:begin': {}
|
||||
|
||||
@@ -0,0 +1,115 @@
|
||||
import React, {useState} from 'react'
|
||||
import {Pressable, StyleSheet, View} from 'react-native'
|
||||
import {msg} from '@lingui/macro'
|
||||
import {useLingui} from '@lingui/react'
|
||||
|
||||
import {useOpenComposer} from '#/lib/hooks/useOpenComposer'
|
||||
import {sanitizeDisplayName} from '#/lib/strings/display-names'
|
||||
import {sanitizeHandle} from '#/lib/strings/handles'
|
||||
import {logger} from '#/logger'
|
||||
import {useCurrentAccountProfile} from '#/state/queries/useCurrentAccountProfile'
|
||||
import {UserAvatar} from '#/view/com/util/UserAvatar'
|
||||
import {atoms as a, native, useTheme, web} from '#/alf'
|
||||
import {SubtleHover} from '#/components/SubtleHover'
|
||||
import {Text} from '#/components/Typography'
|
||||
|
||||
export function FeedComposerPrompt() {
|
||||
const {_} = useLingui()
|
||||
const t = useTheme()
|
||||
const {openComposer} = useOpenComposer()
|
||||
const profile = useCurrentAccountProfile()
|
||||
const [hover, setHover] = useState(false)
|
||||
|
||||
const onPress = React.useCallback(() => {
|
||||
logger.metric('postComposer:click', {})
|
||||
openComposer({})
|
||||
}, [openComposer])
|
||||
|
||||
if (!profile) {
|
||||
return null
|
||||
}
|
||||
|
||||
const displayName = sanitizeDisplayName(
|
||||
profile.displayName || sanitizeHandle(profile.handle),
|
||||
)
|
||||
const handle = sanitizeHandle(profile.handle, '@')
|
||||
|
||||
return (
|
||||
<Pressable
|
||||
onPress={onPress}
|
||||
android_ripple={null}
|
||||
accessibilityRole="button"
|
||||
accessibilityLabel={_(msg`Compose new post`)}
|
||||
accessibilityHint={_(msg`Opens the post composer`)}
|
||||
onPointerEnter={() => setHover(true)}
|
||||
onPointerLeave={() => setHover(false)}
|
||||
style={({pressed}) => [
|
||||
a.relative,
|
||||
a.flex_row,
|
||||
a.align_start,
|
||||
{
|
||||
paddingLeft: 18,
|
||||
paddingRight: 15,
|
||||
},
|
||||
a.py_md,
|
||||
native({
|
||||
paddingTop: 15,
|
||||
paddingBottom: 15,
|
||||
}),
|
||||
{
|
||||
borderTopWidth: StyleSheet.hairlineWidth,
|
||||
borderColor: t.atoms.border_contrast_low.borderColor,
|
||||
},
|
||||
web({
|
||||
cursor: 'pointer',
|
||||
outline: 'none',
|
||||
}),
|
||||
pressed && web({outline: 'none'}),
|
||||
]}>
|
||||
<SubtleHover hover={hover} />
|
||||
<UserAvatar
|
||||
avatar={profile.avatar}
|
||||
size={40}
|
||||
type={profile.associated?.labeler ? 'labeler' : 'user'}
|
||||
/>
|
||||
<View style={[a.flex_1, a.ml_md]}>
|
||||
<View style={[a.flex_row, a.align_center, a.gap_xs, a.mb_sm]}>
|
||||
<Text
|
||||
emoji
|
||||
style={[a.text_md, a.font_semi_bold, a.flex_shrink]}
|
||||
numberOfLines={1}>
|
||||
{displayName}
|
||||
</Text>
|
||||
<Text
|
||||
style={[a.text_md, t.atoms.text_contrast_medium, a.flex_shrink]}
|
||||
numberOfLines={1}>
|
||||
{handle}
|
||||
</Text>
|
||||
</View>
|
||||
<View
|
||||
style={[
|
||||
a.flex_row,
|
||||
a.align_center,
|
||||
a.px_md,
|
||||
{
|
||||
height: 40,
|
||||
borderRadius: 20,
|
||||
},
|
||||
t.atoms.bg_contrast_50,
|
||||
]}>
|
||||
<Text
|
||||
style={[
|
||||
t.atoms.text_contrast_medium,
|
||||
a.text_md,
|
||||
{
|
||||
lineHeight: a.text_md.fontSize,
|
||||
includeFontPadding: false,
|
||||
},
|
||||
]}>
|
||||
{_(msg`What's up?`)}
|
||||
</Text>
|
||||
</View>
|
||||
</View>
|
||||
</Pressable>
|
||||
)
|
||||
}
|
||||
@@ -69,6 +69,7 @@ import {
|
||||
} from '#/components/feeds/PostFeedVideoGridRow'
|
||||
import {TrendingInterstitial} from '#/components/interstitials/Trending'
|
||||
import {TrendingVideos as TrendingVideosInterstitial} from '#/components/interstitials/TrendingVideos'
|
||||
import {FeedComposerPrompt} from '../feeds/FeedComposerPrompt'
|
||||
import {DiscoverFallbackHeader} from './DiscoverFallbackHeader'
|
||||
import {FeedShutdownMsg} from './FeedShutdownMsg'
|
||||
import {PostFeedErrorMessage} from './PostFeedErrorMessage'
|
||||
@@ -149,6 +150,10 @@ type FeedRow =
|
||||
type: 'ageAssuranceBanner'
|
||||
key: string
|
||||
}
|
||||
| {
|
||||
type: 'composerPrompt'
|
||||
key: string
|
||||
}
|
||||
|
||||
export function getItemsForFeedback(feedRow: FeedRow): {
|
||||
item: FeedPostSliceItem
|
||||
@@ -501,6 +506,18 @@ let PostFeed = ({
|
||||
'interstitial2-' + sliceIndex + '-' + lastFetchedAt,
|
||||
})
|
||||
}
|
||||
// Add composer prompt for Discover and Following feeds (after trending bar if it exists)
|
||||
// Feature gate disabled - always show
|
||||
if (
|
||||
hasSession &&
|
||||
(feedUriOrActorDid === DISCOVER_FEED_URI ||
|
||||
feed === 'following')
|
||||
) {
|
||||
arr.push({
|
||||
type: 'composerPrompt',
|
||||
key: 'composerPrompt-' + sliceIndex,
|
||||
})
|
||||
}
|
||||
} else if (sliceIndex === 15) {
|
||||
if (areVideoFeedsEnabled && !trendingVideoDisabled) {
|
||||
arr.push({
|
||||
@@ -622,6 +639,7 @@ let PostFeed = ({
|
||||
isEmpty,
|
||||
lastFetchedAt,
|
||||
data,
|
||||
feed,
|
||||
feedType,
|
||||
feedUriOrActorDid,
|
||||
feedTab,
|
||||
@@ -726,6 +744,8 @@ let PostFeed = ({
|
||||
return <AgeAssuranceDismissibleFeedBanner />
|
||||
} else if (row.type === 'interstitialTrending') {
|
||||
return <TrendingInterstitial />
|
||||
} else if (row.type === 'composerPrompt') {
|
||||
return <FeedComposerPrompt />
|
||||
} else if (row.type === 'interstitialTrendingVideos') {
|
||||
return <TrendingVideosInterstitial />
|
||||
} else if (row.type === 'fallbackMarker') {
|
||||
|
||||
Reference in New Issue
Block a user