Handle previews
This commit is contained in:
+46
-46
@@ -146,49 +146,51 @@ function InnerApp() {
|
||||
<QueryProvider currentDid={currentAccount?.did}>
|
||||
<PolicyUpdateOverlayProvider>
|
||||
<StatsigProvider>
|
||||
<AgeAssuranceV2Provider>
|
||||
<ComposerProvider>
|
||||
<MessagesProvider>
|
||||
{/* LabelDefsProvider MUST come before ModerationOptsProvider */}
|
||||
<LabelDefsProvider>
|
||||
<ModerationOptsProvider>
|
||||
<LoggedOutViewProvider>
|
||||
<SelectedFeedProvider>
|
||||
<HiddenRepliesProvider>
|
||||
<HomeBadgeProvider>
|
||||
<UnreadNotifsProvider>
|
||||
<BackgroundNotificationPreferencesProvider>
|
||||
<MutedThreadsProvider>
|
||||
<ProgressGuideProvider>
|
||||
<ServiceAccountManager>
|
||||
<EmailVerificationProvider>
|
||||
<HideBottomBarBorderProvider>
|
||||
<GestureHandlerRootView
|
||||
style={s.h100pct}>
|
||||
<GlobalGestureEventsProvider>
|
||||
<IntentDialogProvider>
|
||||
<TestCtrls />
|
||||
<Shell />
|
||||
<ToastOutlet />
|
||||
</IntentDialogProvider>
|
||||
</GlobalGestureEventsProvider>
|
||||
</GestureHandlerRootView>
|
||||
</HideBottomBarBorderProvider>
|
||||
</EmailVerificationProvider>
|
||||
</ServiceAccountManager>
|
||||
</ProgressGuideProvider>
|
||||
</MutedThreadsProvider>
|
||||
</BackgroundNotificationPreferencesProvider>
|
||||
</UnreadNotifsProvider>
|
||||
</HomeBadgeProvider>
|
||||
</HiddenRepliesProvider>
|
||||
</SelectedFeedProvider>
|
||||
</LoggedOutViewProvider>
|
||||
</ModerationOptsProvider>
|
||||
</LabelDefsProvider>
|
||||
</MessagesProvider>
|
||||
</ComposerProvider>
|
||||
</AgeAssuranceV2Provider>
|
||||
<LiveEventsProvider>
|
||||
<AgeAssuranceV2Provider>
|
||||
<ComposerProvider>
|
||||
<MessagesProvider>
|
||||
{/* LabelDefsProvider MUST come before ModerationOptsProvider */}
|
||||
<LabelDefsProvider>
|
||||
<ModerationOptsProvider>
|
||||
<LoggedOutViewProvider>
|
||||
<SelectedFeedProvider>
|
||||
<HiddenRepliesProvider>
|
||||
<HomeBadgeProvider>
|
||||
<UnreadNotifsProvider>
|
||||
<BackgroundNotificationPreferencesProvider>
|
||||
<MutedThreadsProvider>
|
||||
<ProgressGuideProvider>
|
||||
<ServiceAccountManager>
|
||||
<EmailVerificationProvider>
|
||||
<HideBottomBarBorderProvider>
|
||||
<GestureHandlerRootView
|
||||
style={s.h100pct}>
|
||||
<GlobalGestureEventsProvider>
|
||||
<IntentDialogProvider>
|
||||
<TestCtrls />
|
||||
<Shell />
|
||||
<ToastOutlet />
|
||||
</IntentDialogProvider>
|
||||
</GlobalGestureEventsProvider>
|
||||
</GestureHandlerRootView>
|
||||
</HideBottomBarBorderProvider>
|
||||
</EmailVerificationProvider>
|
||||
</ServiceAccountManager>
|
||||
</ProgressGuideProvider>
|
||||
</MutedThreadsProvider>
|
||||
</BackgroundNotificationPreferencesProvider>
|
||||
</UnreadNotifsProvider>
|
||||
</HomeBadgeProvider>
|
||||
</HiddenRepliesProvider>
|
||||
</SelectedFeedProvider>
|
||||
</LoggedOutViewProvider>
|
||||
</ModerationOptsProvider>
|
||||
</LabelDefsProvider>
|
||||
</MessagesProvider>
|
||||
</ComposerProvider>
|
||||
</AgeAssuranceV2Provider>
|
||||
</LiveEventsProvider>
|
||||
</StatsigProvider>
|
||||
</PolicyUpdateOverlayProvider>
|
||||
</QueryProvider>
|
||||
@@ -235,9 +237,7 @@ function App() {
|
||||
<StarterPackProvider>
|
||||
<SafeAreaProvider
|
||||
initialMetrics={initialWindowMetrics}>
|
||||
<LiveEventsProvider>
|
||||
<InnerApp />
|
||||
</LiveEventsProvider>
|
||||
<InnerApp />
|
||||
</SafeAreaProvider>
|
||||
</StarterPackProvider>
|
||||
</BottomSheetProvider>
|
||||
|
||||
+42
-42
@@ -122,45 +122,47 @@ function InnerApp() {
|
||||
<QueryProvider currentDid={currentAccount?.did}>
|
||||
<PolicyUpdateOverlayProvider>
|
||||
<StatsigProvider>
|
||||
<AgeAssuranceV2Provider>
|
||||
<ComposerProvider>
|
||||
<MessagesProvider>
|
||||
{/* LabelDefsProvider MUST come before ModerationOptsProvider */}
|
||||
<LabelDefsProvider>
|
||||
<ModerationOptsProvider>
|
||||
<LoggedOutViewProvider>
|
||||
<SelectedFeedProvider>
|
||||
<HiddenRepliesProvider>
|
||||
<HomeBadgeProvider>
|
||||
<UnreadNotifsProvider>
|
||||
<BackgroundNotificationPreferencesProvider>
|
||||
<MutedThreadsProvider>
|
||||
<SafeAreaProvider>
|
||||
<ProgressGuideProvider>
|
||||
<ServiceConfigProvider>
|
||||
<EmailVerificationProvider>
|
||||
<HideBottomBarBorderProvider>
|
||||
<IntentDialogProvider>
|
||||
<Shell />
|
||||
<ToastOutlet />
|
||||
</IntentDialogProvider>
|
||||
</HideBottomBarBorderProvider>
|
||||
</EmailVerificationProvider>
|
||||
</ServiceConfigProvider>
|
||||
</ProgressGuideProvider>
|
||||
</SafeAreaProvider>
|
||||
</MutedThreadsProvider>
|
||||
</BackgroundNotificationPreferencesProvider>
|
||||
</UnreadNotifsProvider>
|
||||
</HomeBadgeProvider>
|
||||
</HiddenRepliesProvider>
|
||||
</SelectedFeedProvider>
|
||||
</LoggedOutViewProvider>
|
||||
</ModerationOptsProvider>
|
||||
</LabelDefsProvider>
|
||||
</MessagesProvider>
|
||||
</ComposerProvider>
|
||||
</AgeAssuranceV2Provider>
|
||||
<LiveEventsProvider>
|
||||
<AgeAssuranceV2Provider>
|
||||
<ComposerProvider>
|
||||
<MessagesProvider>
|
||||
{/* LabelDefsProvider MUST come before ModerationOptsProvider */}
|
||||
<LabelDefsProvider>
|
||||
<ModerationOptsProvider>
|
||||
<LoggedOutViewProvider>
|
||||
<SelectedFeedProvider>
|
||||
<HiddenRepliesProvider>
|
||||
<HomeBadgeProvider>
|
||||
<UnreadNotifsProvider>
|
||||
<BackgroundNotificationPreferencesProvider>
|
||||
<MutedThreadsProvider>
|
||||
<SafeAreaProvider>
|
||||
<ProgressGuideProvider>
|
||||
<ServiceConfigProvider>
|
||||
<EmailVerificationProvider>
|
||||
<HideBottomBarBorderProvider>
|
||||
<IntentDialogProvider>
|
||||
<Shell />
|
||||
<ToastOutlet />
|
||||
</IntentDialogProvider>
|
||||
</HideBottomBarBorderProvider>
|
||||
</EmailVerificationProvider>
|
||||
</ServiceConfigProvider>
|
||||
</ProgressGuideProvider>
|
||||
</SafeAreaProvider>
|
||||
</MutedThreadsProvider>
|
||||
</BackgroundNotificationPreferencesProvider>
|
||||
</UnreadNotifsProvider>
|
||||
</HomeBadgeProvider>
|
||||
</HiddenRepliesProvider>
|
||||
</SelectedFeedProvider>
|
||||
</LoggedOutViewProvider>
|
||||
</ModerationOptsProvider>
|
||||
</LabelDefsProvider>
|
||||
</MessagesProvider>
|
||||
</ComposerProvider>
|
||||
</AgeAssuranceV2Provider>
|
||||
</LiveEventsProvider>
|
||||
</StatsigProvider>
|
||||
</PolicyUpdateOverlayProvider>
|
||||
</QueryProvider>
|
||||
@@ -203,9 +205,7 @@ function App() {
|
||||
<LightboxStateProvider>
|
||||
<PortalProvider>
|
||||
<StarterPackProvider>
|
||||
<LiveEventsProvider>
|
||||
<InnerApp />
|
||||
</LiveEventsProvider>
|
||||
<InnerApp />
|
||||
</StarterPackProvider>
|
||||
</PortalProvider>
|
||||
</LightboxStateProvider>
|
||||
|
||||
+12
-17
@@ -12,26 +12,15 @@ import {
|
||||
LiveEventFeedOptionsMenu,
|
||||
useDialogControl,
|
||||
} from '#/features/liveEvents/components/LiveEventFeedOptionsMenu'
|
||||
import {useLiveEvents} from '#/features/liveEvents/context'
|
||||
import {useLiveEventPreferences} from '#/features/liveEvents/preferences'
|
||||
import {useUserPreferencedLiveEvents} from '#/features/liveEvents/context'
|
||||
import {type LiveEventFeed} from '#/features/liveEvents/types'
|
||||
|
||||
export function DiscoverFeedLiveEventFeedsAndTrendingBanner() {
|
||||
const t = useTheme()
|
||||
const {_} = useLingui()
|
||||
const events = useLiveEvents()
|
||||
const events = useUserPreferencedLiveEvents()
|
||||
const {rightNavVisible} = useLayoutBreakpoints()
|
||||
const {trendingDisabled} = useTrendingSettings()
|
||||
const optionsMenuControl = useDialogControl()
|
||||
const {data, isLoading} = useLiveEventPreferences()
|
||||
|
||||
// user prefs should be loaded by now, but for TS-sake
|
||||
if (isLoading) return null
|
||||
|
||||
const {hideAllFeeds, hiddenFeedIds} = data
|
||||
const feed = events.feeds.at(0)
|
||||
const feedHidden = feed?.id ? hiddenFeedIds.includes(feed?.id || '') : false
|
||||
|
||||
if (!feed || hideAllFeeds || feedHidden) {
|
||||
if (!events.feeds.length) {
|
||||
if (!rightNavVisible && !trendingDisabled) {
|
||||
// only show trending on mobile when live event banner is not shown
|
||||
return <TrendingInterstitial />
|
||||
@@ -44,7 +33,13 @@ export function DiscoverFeedLiveEventFeedsAndTrendingBanner() {
|
||||
// On desktop, we show in the sidebar
|
||||
if (rightNavVisible) return null
|
||||
|
||||
const image = feed.images.wide
|
||||
return events.feeds.map(feed => <Inner feed={feed} key={feed.id} />)
|
||||
}
|
||||
|
||||
function Inner({feed}: {feed: LiveEventFeed}) {
|
||||
const t = useTheme()
|
||||
const {_} = useLingui()
|
||||
const optionsMenuControl = useDialogControl()
|
||||
|
||||
return (
|
||||
<>
|
||||
@@ -76,7 +71,7 @@ export function DiscoverFeedLiveEventFeedsAndTrendingBanner() {
|
||||
<EllipsisIcon
|
||||
size="sm"
|
||||
fill={
|
||||
image.textColor === 'light'
|
||||
feed.images.wide.textColor === 'light'
|
||||
? t.palette.white
|
||||
: t.palette.black
|
||||
}
|
||||
|
||||
@@ -28,6 +28,7 @@ export function LiveEventFeedCardWide({
|
||||
const {gtPhone} = useBreakpoints()
|
||||
|
||||
const image = feed.images.wide
|
||||
const textColor = feed.images.wide.textColor === 'light' ? 'white' : 'black'
|
||||
const url = useMemo(() => {
|
||||
// Validated in multiple places on the backend
|
||||
if (isBskyCustomFeedUrl(feed.url)) {
|
||||
@@ -106,16 +107,20 @@ export function LiveEventFeedCardWide({
|
||||
style={[
|
||||
a.leading_snug,
|
||||
gtPhone ? a.text_xs : a.text_2xs,
|
||||
{color: 'white', opacity: 0.8},
|
||||
{color: textColor, opacity: 0.8},
|
||||
]}>
|
||||
<Trans>Happening now</Trans>
|
||||
{feed.preview ? (
|
||||
<Trans>Preview</Trans>
|
||||
) : (
|
||||
<Trans>Happening now</Trans>
|
||||
)}
|
||||
</Text>
|
||||
<Text
|
||||
style={[
|
||||
a.leading_snug,
|
||||
a.font_bold,
|
||||
gtPhone ? a.text_3xl : a.text_lg,
|
||||
{color: 'white'},
|
||||
{color: textColor},
|
||||
]}>
|
||||
{feed.title}
|
||||
</Text>
|
||||
|
||||
@@ -1,12 +1,19 @@
|
||||
import {createContext, useContext} from 'react'
|
||||
import {QueryClient, useQuery} from '@tanstack/react-query'
|
||||
|
||||
import {useIsBskyTeam} from '#/lib/hooks/useIsBskyTeam'
|
||||
import {IS_DEV, LIVE_EVENTS_URL} from '#/env'
|
||||
import {useLiveEventPreferences} from '#/features/liveEvents/preferences'
|
||||
import {type LiveEventsWorkerResponse} from '#/features/liveEvents/types'
|
||||
import {useDevMode} from '#/storage/hooks/dev-mode'
|
||||
|
||||
const qc = new QueryClient()
|
||||
const liveEventsQueryKey = ['live-events']
|
||||
|
||||
export const DEFAULT_LIVE_EVENTS = {
|
||||
feeds: [],
|
||||
}
|
||||
|
||||
async function fetchLiveEvents(): Promise<LiveEventsWorkerResponse | null> {
|
||||
try {
|
||||
const res = await fetch(`${LIVE_EVENTS_URL}/config`)
|
||||
@@ -18,17 +25,29 @@ async function fetchLiveEvents(): Promise<LiveEventsWorkerResponse | null> {
|
||||
}
|
||||
}
|
||||
|
||||
const Context = createContext<LiveEventsWorkerResponse>({
|
||||
feeds: [],
|
||||
})
|
||||
const Context = createContext<LiveEventsWorkerResponse>(DEFAULT_LIVE_EVENTS)
|
||||
|
||||
export function Provider({children}: React.PropsWithChildren<{}>) {
|
||||
const [isDevMode] = useDevMode()
|
||||
const isBskyTeam = useIsBskyTeam()
|
||||
const {data} = useQuery(
|
||||
{
|
||||
staleTime: IS_DEV ? 5e3 : 1000 * 60,
|
||||
queryKey: liveEventsQueryKey,
|
||||
async queryFn() {
|
||||
return fetchLiveEvents()
|
||||
const events = await fetchLiveEvents()
|
||||
if (!events) return null
|
||||
const feeds = events.feeds.filter(f => {
|
||||
if (f.preview && !isBskyTeam) {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
})
|
||||
return {
|
||||
...events,
|
||||
// only one at a time for now, unless bsky team and dev mode
|
||||
feeds: isBskyTeam && isDevMode ? feeds : feeds.slice(0, 1),
|
||||
}
|
||||
},
|
||||
},
|
||||
qc,
|
||||
@@ -53,3 +72,19 @@ export function useLiveEvents() {
|
||||
}
|
||||
return ctx
|
||||
}
|
||||
|
||||
export function useUserPreferencedLiveEvents() {
|
||||
const events = useLiveEvents()
|
||||
const {data, isLoading} = useLiveEventPreferences()
|
||||
if (isLoading) return DEFAULT_LIVE_EVENTS
|
||||
const {hideAllFeeds, hiddenFeedIds} = data
|
||||
return {
|
||||
...events,
|
||||
feeds: hideAllFeeds
|
||||
? []
|
||||
: events.feeds.filter(f => {
|
||||
const hidden = f?.id ? hiddenFeedIds.includes(f?.id || '') : false
|
||||
return !hidden
|
||||
}),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
import {useMemo} from 'react'
|
||||
|
||||
import {useGate} from '#/lib/statsig/statsig'
|
||||
|
||||
export function useIsBskyTeam() {
|
||||
const gate = useGate()
|
||||
return useMemo(() => gate('is_bsky_team_member'), [gate])
|
||||
}
|
||||
@@ -7,6 +7,7 @@ export type Gate =
|
||||
| 'disable_settings_find_contacts'
|
||||
| 'explore_show_suggested_feeds'
|
||||
| 'feed_reply_button_open_thread'
|
||||
| 'is_bsky_team_member' // special, do not remove
|
||||
| 'old_postonboarding'
|
||||
| 'onboarding_add_video_feed'
|
||||
| 'onboarding_suggested_starterpacks'
|
||||
|
||||
Reference in New Issue
Block a user