Add live event feed card to Explore
This commit is contained in:
@@ -0,0 +1,17 @@
|
|||||||
|
import {View} from 'react-native'
|
||||||
|
|
||||||
|
import {atoms as a, useTheme} from '#/alf'
|
||||||
|
import {LiveEventFeedCardWide} from '#/features/liveEvents/components/LiveEventFeedCardWide'
|
||||||
|
import {useLiveEvents} from '#/features/liveEvents/context'
|
||||||
|
|
||||||
|
export function ExploreScreenLiveEventFeedsBanner() {
|
||||||
|
const t = useTheme()
|
||||||
|
const events = useLiveEvents()
|
||||||
|
const feed = events.feeds.at(0)
|
||||||
|
if (!feed) return null
|
||||||
|
return (
|
||||||
|
<View style={[a.p_lg, a.border_b, t.atoms.border_contrast_low]}>
|
||||||
|
<LiveEventFeedCardWide feed={feed} />
|
||||||
|
</View>
|
||||||
|
)
|
||||||
|
}
|
||||||
@@ -0,0 +1,113 @@
|
|||||||
|
import {useMemo} from 'react'
|
||||||
|
import {View} from 'react-native'
|
||||||
|
import {Image} from 'expo-image'
|
||||||
|
import {LinearGradient} from 'expo-linear-gradient'
|
||||||
|
import {msg, Trans} from '@lingui/macro'
|
||||||
|
import {useLingui} from '@lingui/react'
|
||||||
|
|
||||||
|
import {isBskyCustomFeedUrl} from '#/lib/strings/url-helpers'
|
||||||
|
import {atoms as a, useBreakpoints, utils} from '#/alf'
|
||||||
|
import {Link} from '#/components/Link'
|
||||||
|
import {Text} from '#/components/Typography'
|
||||||
|
import {type LiveEventFeed} from '#/features/liveEvents/types'
|
||||||
|
|
||||||
|
const roundedStyles = [a.rounded_lg, a.curve_continuous]
|
||||||
|
|
||||||
|
export function LiveEventFeedCardWide({feed}: {feed: LiveEventFeed}) {
|
||||||
|
const {_} = useLingui()
|
||||||
|
const {gtPhone} = useBreakpoints()
|
||||||
|
|
||||||
|
const image = feed.images.wide
|
||||||
|
const url = useMemo(() => {
|
||||||
|
// Validated in multiple places on the backend
|
||||||
|
if (isBskyCustomFeedUrl(feed.url)) {
|
||||||
|
return new URL(feed.url).pathname
|
||||||
|
}
|
||||||
|
return '/'
|
||||||
|
}, [feed.url])
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Link
|
||||||
|
to={url}
|
||||||
|
label={_(msg`Live event happening now: ${feed.title}`)}
|
||||||
|
style={[a.w_full]}>
|
||||||
|
{({hovered, pressed}) => (
|
||||||
|
<View style={[roundedStyles, a.shadow_md, a.w_full]}>
|
||||||
|
<View
|
||||||
|
style={[
|
||||||
|
a.align_start,
|
||||||
|
roundedStyles,
|
||||||
|
a.overflow_hidden,
|
||||||
|
{
|
||||||
|
aspectRatio: gtPhone ? 576 / 144 : 369 / 100,
|
||||||
|
},
|
||||||
|
]}>
|
||||||
|
<Image
|
||||||
|
accessibilityIgnoresInvertColors
|
||||||
|
source={{
|
||||||
|
uri: image.url,
|
||||||
|
blurhash: image.blurhash,
|
||||||
|
}}
|
||||||
|
style={[a.absolute, a.inset_0]}
|
||||||
|
contentFit="cover"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<LinearGradient
|
||||||
|
colors={[image.overlayColor, utils.alpha(image.overlayColor, 0)]}
|
||||||
|
locations={[0, 1]}
|
||||||
|
start={{x: 0, y: 0}}
|
||||||
|
end={{x: 1, y: 0}}
|
||||||
|
style={[
|
||||||
|
a.absolute,
|
||||||
|
a.inset_0,
|
||||||
|
a.transition_opacity,
|
||||||
|
{
|
||||||
|
transitionDuration: '200ms',
|
||||||
|
opacity: hovered || pressed ? 0.6 : 0,
|
||||||
|
},
|
||||||
|
]}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<View style={[a.flex_1, a.justify_end]}>
|
||||||
|
<LinearGradient
|
||||||
|
colors={[
|
||||||
|
image.overlayColor,
|
||||||
|
utils.alpha(image.overlayColor, 0),
|
||||||
|
]}
|
||||||
|
locations={[0, 1]}
|
||||||
|
start={{x: 0, y: 0}}
|
||||||
|
end={{x: 1, y: 0}}
|
||||||
|
style={[a.absolute, a.inset_0]}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<View
|
||||||
|
style={[
|
||||||
|
a.z_10,
|
||||||
|
gtPhone ? [a.pl_xl, a.pb_lg] : [a.pl_lg, a.pb_md],
|
||||||
|
{paddingRight: 64},
|
||||||
|
]}>
|
||||||
|
<Text
|
||||||
|
style={[
|
||||||
|
a.leading_snug,
|
||||||
|
gtPhone ? a.text_xs : a.text_2xs,
|
||||||
|
{color: 'white', opacity: 0.8},
|
||||||
|
]}>
|
||||||
|
<Trans>Happening now</Trans>
|
||||||
|
</Text>
|
||||||
|
<Text
|
||||||
|
style={[
|
||||||
|
a.leading_snug,
|
||||||
|
a.font_bold,
|
||||||
|
gtPhone ? a.text_3xl : a.text_lg,
|
||||||
|
{color: 'white'},
|
||||||
|
]}>
|
||||||
|
{feed.title}
|
||||||
|
</Text>
|
||||||
|
</View>
|
||||||
|
</View>
|
||||||
|
</View>
|
||||||
|
</View>
|
||||||
|
)}
|
||||||
|
</Link>
|
||||||
|
)
|
||||||
|
}
|
||||||
@@ -68,6 +68,7 @@ import {Loader} from '#/components/Loader'
|
|||||||
import * as ProfileCard from '#/components/ProfileCard'
|
import * as ProfileCard from '#/components/ProfileCard'
|
||||||
import {SubtleHover} from '#/components/SubtleHover'
|
import {SubtleHover} from '#/components/SubtleHover'
|
||||||
import {Text} from '#/components/Typography'
|
import {Text} from '#/components/Typography'
|
||||||
|
import {ExploreScreenLiveEventFeedsBanner} from '#/features/liveEvents/components/ExploreScreenLiveEventFeedsBanner'
|
||||||
import * as ModuleHeader from './components/ModuleHeader'
|
import * as ModuleHeader from './components/ModuleHeader'
|
||||||
import {
|
import {
|
||||||
SuggestedAccountsTabBar,
|
SuggestedAccountsTabBar,
|
||||||
@@ -201,6 +202,10 @@ type ExploreScreenItems =
|
|||||||
type: 'interests-card'
|
type: 'interests-card'
|
||||||
key: 'interests-card'
|
key: 'interests-card'
|
||||||
}
|
}
|
||||||
|
| {
|
||||||
|
type: 'liveEventFeedsBanner'
|
||||||
|
key: string
|
||||||
|
}
|
||||||
|
|
||||||
export function Explore({
|
export function Explore({
|
||||||
focusSearchInput,
|
focusSearchInput,
|
||||||
@@ -684,6 +689,8 @@ export function Explore({
|
|||||||
i.push(topBorder)
|
i.push(topBorder)
|
||||||
i.push(...interestsNuxModule)
|
i.push(...interestsNuxModule)
|
||||||
|
|
||||||
|
i.push({type: 'liveEventFeedsBanner', key: 'liveEventFeedsBanner'})
|
||||||
|
|
||||||
if (useFullExperience) {
|
if (useFullExperience) {
|
||||||
i.push(trendingTopicsModule)
|
i.push(trendingTopicsModule)
|
||||||
i.push(...suggestedFeedsModule)
|
i.push(...suggestedFeedsModule)
|
||||||
@@ -998,6 +1005,9 @@ export function Explore({
|
|||||||
case 'interests-card': {
|
case 'interests-card': {
|
||||||
return <ExploreInterestsCard />
|
return <ExploreInterestsCard />
|
||||||
}
|
}
|
||||||
|
case 'liveEventFeedsBanner': {
|
||||||
|
return <ExploreScreenLiveEventFeedsBanner />
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
[
|
[
|
||||||
|
|||||||
Reference in New Issue
Block a user