Add a composer prompt on home
This commit is contained in:
@@ -9,5 +9,6 @@ export type Gate =
|
|||||||
| 'onboarding_add_video_feed'
|
| 'onboarding_add_video_feed'
|
||||||
| 'onboarding_suggested_starterpacks'
|
| 'onboarding_suggested_starterpacks'
|
||||||
| 'remove_show_latest_button'
|
| 'remove_show_latest_button'
|
||||||
|
| 'show_composer_prompt'
|
||||||
| 'test_gate_1'
|
| 'test_gate_1'
|
||||||
| 'test_gate_2'
|
| 'test_gate_2'
|
||||||
|
|||||||
@@ -202,6 +202,7 @@ export type MetricEvents = {
|
|||||||
|
|
||||||
'composer:gif:open': {}
|
'composer:gif:open': {}
|
||||||
'composer:gif:select': {}
|
'composer:gif:select': {}
|
||||||
|
'postComposer:click': {}
|
||||||
|
|
||||||
// Data events
|
// Data events
|
||||||
'account:create:begin': {}
|
'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'
|
} from '#/components/feeds/PostFeedVideoGridRow'
|
||||||
import {TrendingInterstitial} from '#/components/interstitials/Trending'
|
import {TrendingInterstitial} from '#/components/interstitials/Trending'
|
||||||
import {TrendingVideos as TrendingVideosInterstitial} from '#/components/interstitials/TrendingVideos'
|
import {TrendingVideos as TrendingVideosInterstitial} from '#/components/interstitials/TrendingVideos'
|
||||||
|
import {FeedComposerPrompt} from '../feeds/FeedComposerPrompt'
|
||||||
import {DiscoverFallbackHeader} from './DiscoverFallbackHeader'
|
import {DiscoverFallbackHeader} from './DiscoverFallbackHeader'
|
||||||
import {FeedShutdownMsg} from './FeedShutdownMsg'
|
import {FeedShutdownMsg} from './FeedShutdownMsg'
|
||||||
import {PostFeedErrorMessage} from './PostFeedErrorMessage'
|
import {PostFeedErrorMessage} from './PostFeedErrorMessage'
|
||||||
@@ -149,6 +150,10 @@ type FeedRow =
|
|||||||
type: 'ageAssuranceBanner'
|
type: 'ageAssuranceBanner'
|
||||||
key: string
|
key: string
|
||||||
}
|
}
|
||||||
|
| {
|
||||||
|
type: 'composerPrompt'
|
||||||
|
key: string
|
||||||
|
}
|
||||||
|
|
||||||
export function getItemsForFeedback(feedRow: FeedRow): {
|
export function getItemsForFeedback(feedRow: FeedRow): {
|
||||||
item: FeedPostSliceItem
|
item: FeedPostSliceItem
|
||||||
@@ -501,6 +506,18 @@ let PostFeed = ({
|
|||||||
'interstitial2-' + sliceIndex + '-' + lastFetchedAt,
|
'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) {
|
} else if (sliceIndex === 15) {
|
||||||
if (areVideoFeedsEnabled && !trendingVideoDisabled) {
|
if (areVideoFeedsEnabled && !trendingVideoDisabled) {
|
||||||
arr.push({
|
arr.push({
|
||||||
@@ -622,6 +639,7 @@ let PostFeed = ({
|
|||||||
isEmpty,
|
isEmpty,
|
||||||
lastFetchedAt,
|
lastFetchedAt,
|
||||||
data,
|
data,
|
||||||
|
feed,
|
||||||
feedType,
|
feedType,
|
||||||
feedUriOrActorDid,
|
feedUriOrActorDid,
|
||||||
feedTab,
|
feedTab,
|
||||||
@@ -726,6 +744,8 @@ let PostFeed = ({
|
|||||||
return <AgeAssuranceDismissibleFeedBanner />
|
return <AgeAssuranceDismissibleFeedBanner />
|
||||||
} else if (row.type === 'interstitialTrending') {
|
} else if (row.type === 'interstitialTrending') {
|
||||||
return <TrendingInterstitial />
|
return <TrendingInterstitial />
|
||||||
|
} else if (row.type === 'composerPrompt') {
|
||||||
|
return <FeedComposerPrompt />
|
||||||
} else if (row.type === 'interstitialTrendingVideos') {
|
} else if (row.type === 'interstitialTrendingVideos') {
|
||||||
return <TrendingVideosInterstitial />
|
return <TrendingVideosInterstitial />
|
||||||
} else if (row.type === 'fallbackMarker') {
|
} else if (row.type === 'fallbackMarker') {
|
||||||
|
|||||||
Reference in New Issue
Block a user