Merge branch 'demo' into main
This commit is contained in:
@@ -0,0 +1,20 @@
|
||||
import {type AppBskyFeedDefs, type BskyAgent} from '@atproto/api'
|
||||
|
||||
import {DEMO_FEED} from '#/lib/demo'
|
||||
import {type FeedAPI, type FeedAPIResponse} from './types'
|
||||
|
||||
export class DemoFeedAPI implements FeedAPI {
|
||||
agent: BskyAgent
|
||||
|
||||
constructor({agent}: {agent: BskyAgent}) {
|
||||
this.agent = agent
|
||||
}
|
||||
|
||||
async peekLatest(): Promise<AppBskyFeedDefs.FeedViewPost> {
|
||||
return DEMO_FEED.feed[0]
|
||||
}
|
||||
|
||||
async fetch(): Promise<FeedAPIResponse> {
|
||||
return DEMO_FEED
|
||||
}
|
||||
}
|
||||
+202
@@ -0,0 +1,202 @@
|
||||
import {type AppBskyFeedGetFeed} from '@atproto/api'
|
||||
import {subDays, subMinutes} from 'date-fns'
|
||||
|
||||
const DID = `did:plc:z72i7hdynmk6r22z27h6tvur`
|
||||
const NOW = new Date()
|
||||
const POST_1_DATE = subMinutes(NOW, 2).toISOString()
|
||||
const POST_2_DATE = subMinutes(NOW, 4).toISOString()
|
||||
const POST_3_DATE = subMinutes(NOW, 5).toISOString()
|
||||
|
||||
export const DEMO_FEED = {
|
||||
feed: [
|
||||
{
|
||||
post: {
|
||||
uri: 'at://did:plc:pvooorihapc2lf2pijehgrdf/app.bsky.feed.post/3lniysofyll2d',
|
||||
cid: 'bafyreihwh3wxxme732ylbylhhdyz7ex6t4jtu6s3gjxxvnnh4feddhg3ku',
|
||||
author: {
|
||||
did: 'did:plc:pvooorihapc2lf2pijehgrdf',
|
||||
handle: 'forkedriverband.bsky.social',
|
||||
displayName: 'Forked River Band',
|
||||
avatar: 'https://bsky.social/about/adi/post_1_avi.jpg',
|
||||
viewer: {
|
||||
muted: false,
|
||||
blockedBy: false,
|
||||
following: `at://${DID}/app.bsky.graph.follow/post1`,
|
||||
},
|
||||
labels: [],
|
||||
createdAt: POST_1_DATE,
|
||||
verification: {
|
||||
verifications: [
|
||||
{
|
||||
issuer: DID,
|
||||
uri: `at://${DID}/app.bsky.graph.verification/post1`,
|
||||
isValid: true,
|
||||
createdAt: subDays(NOW, 11).toISOString(),
|
||||
},
|
||||
],
|
||||
verifiedStatus: 'valid',
|
||||
trustedVerifierStatus: 'none',
|
||||
},
|
||||
},
|
||||
record: {
|
||||
$type: 'app.bsky.feed.post',
|
||||
createdAt: POST_1_DATE,
|
||||
// embed: {
|
||||
// $type: 'app.bsky.embed.images',
|
||||
// images: [
|
||||
// {
|
||||
// alt: 'Fake flier for Sebastapol Bluegrass Fest',
|
||||
// aspectRatio: {
|
||||
// height: 1350,
|
||||
// width: 900,
|
||||
// },
|
||||
// image: {
|
||||
// $type: 'blob',
|
||||
// ref: {
|
||||
// $link:
|
||||
// 'bafkreig7gnirmz5guhhjutf3mqbjjzxzi3w4wvs5qy2gnxma5g3brbaidi',
|
||||
// },
|
||||
// mimeType: 'image/jpeg',
|
||||
// size: 562871,
|
||||
// },
|
||||
// },
|
||||
// ],
|
||||
// },
|
||||
langs: ['en'],
|
||||
text: 'Sonoma County folks: Come tip your hats our way and see us play new and old bluegrass tunes at Sebastopol Solstice Fest on June 20th.',
|
||||
},
|
||||
embed: {
|
||||
$type: 'app.bsky.embed.images#view',
|
||||
images: [
|
||||
{
|
||||
thumb: 'https://bsky.social/about/adi/post_1_image.jpg',
|
||||
fullsize: 'https://bsky.social/about/adi/post_1_image.jpg',
|
||||
alt: 'Fake flier for Sebastapol Bluegrass Fest',
|
||||
aspectRatio: {
|
||||
height: 1350,
|
||||
width: 900,
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
replyCount: 1,
|
||||
repostCount: 4,
|
||||
likeCount: 18,
|
||||
quoteCount: 0,
|
||||
indexedAt: POST_1_DATE,
|
||||
viewer: {
|
||||
threadMuted: false,
|
||||
embeddingDisabled: false,
|
||||
},
|
||||
labels: [],
|
||||
},
|
||||
},
|
||||
{
|
||||
post: {
|
||||
uri: 'at://did:plc:fhhqii56ppgyh5qcm2b3mokf/app.bsky.feed.post/3lnizc7fug52c',
|
||||
cid: 'bafyreienuabsr55rycirdf4ewue5tjcseg5lzqompcsh2brqzag6hvxllm',
|
||||
author: {
|
||||
did: 'did:plc:fhhqii56ppgyh5qcm2b3mokf',
|
||||
handle: 'dinh-designs.bsky.social',
|
||||
displayName: 'Rich Dinh Designs',
|
||||
avatar: 'https://bsky.social/about/adi/post_2_avi.jpg',
|
||||
viewer: {
|
||||
muted: false,
|
||||
blockedBy: false,
|
||||
following: `at://${DID}/app.bsky.graph.follow/post2`,
|
||||
},
|
||||
labels: [],
|
||||
createdAt: POST_2_DATE,
|
||||
},
|
||||
record: {
|
||||
$type: 'app.bsky.feed.post',
|
||||
createdAt: POST_2_DATE,
|
||||
// embed: {
|
||||
// $type: 'app.bsky.embed.images',
|
||||
// images: [
|
||||
// {
|
||||
// alt: 'Placeholder image of interior design',
|
||||
// aspectRatio: {
|
||||
// height: 872,
|
||||
// width: 598,
|
||||
// },
|
||||
// image: {
|
||||
// $type: 'blob',
|
||||
// ref: {
|
||||
// $link:
|
||||
// 'bafkreidcjc6bjb4jjjejruin5cldhj5zovsuu4tydulenyprneziq5rfeu',
|
||||
// },
|
||||
// mimeType: 'image/jpeg',
|
||||
// size: 296003,
|
||||
// },
|
||||
// },
|
||||
// ],
|
||||
// },
|
||||
langs: ['en'],
|
||||
text: 'Details from our install at the Lucas residence in Joshua Tree. We populated the space with rich, earthy tones and locally-sourced materials to suit the landscape.',
|
||||
},
|
||||
embed: {
|
||||
$type: 'app.bsky.embed.images#view',
|
||||
images: [
|
||||
{
|
||||
thumb: 'https://bsky.social/about/adi/post_2_image.jpg',
|
||||
fullsize: 'https://bsky.social/about/adi/post_2_image.jpg',
|
||||
alt: 'Placeholder image of interior design',
|
||||
aspectRatio: {
|
||||
height: 872,
|
||||
width: 598,
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
replyCount: 3,
|
||||
repostCount: 1,
|
||||
likeCount: 4,
|
||||
quoteCount: 0,
|
||||
indexedAt: POST_2_DATE,
|
||||
viewer: {
|
||||
threadMuted: false,
|
||||
embeddingDisabled: false,
|
||||
},
|
||||
labels: [],
|
||||
},
|
||||
},
|
||||
{
|
||||
post: {
|
||||
uri: 'at://did:plc:h7fwnfejmmifveeea5eyxgkc/app.bsky.feed.post/3lnizna3g4f2t',
|
||||
cid: 'bafyreiepn7obmlshliori4j34texpaukrqkyyu7cq6nmpzk4lkis7nqeae',
|
||||
author: {
|
||||
did: 'did:plc:h7fwnfejmmifveeea5eyxgkc',
|
||||
handle: 'rodyalbuerne.bsky.social',
|
||||
displayName: 'Rody Albuerne',
|
||||
avatar: 'https://bsky.social/about/adi/post_3_avi.jpg',
|
||||
viewer: {
|
||||
muted: false,
|
||||
blockedBy: false,
|
||||
following: `at://${DID}/app.bsky.graph.follow/post3`,
|
||||
},
|
||||
labels: [],
|
||||
createdAt: POST_3_DATE,
|
||||
},
|
||||
record: {
|
||||
$type: 'app.bsky.feed.post',
|
||||
createdAt: POST_3_DATE,
|
||||
langs: ['en'],
|
||||
text: 'Tinkering with the basics of traditional wooden joinery in my shop lately. Starting small with this ox, made using simple mortise and tenon joints.',
|
||||
},
|
||||
replyCount: 11,
|
||||
repostCount: 97,
|
||||
likeCount: 399,
|
||||
quoteCount: 0,
|
||||
indexedAt: POST_3_DATE,
|
||||
viewer: {
|
||||
threadMuted: false,
|
||||
embeddingDisabled: false,
|
||||
},
|
||||
labels: [],
|
||||
},
|
||||
},
|
||||
],
|
||||
} satisfies AppBskyFeedGetFeed.OutputSchema
|
||||
|
||||
export const BOTTOM_BAR_AVI = 'https://bsky.social/about/adi/user_avi.jpg'
|
||||
@@ -12,9 +12,10 @@ import {Statsig} from 'statsig-react-native-expo'
|
||||
import {appVersion, BUNDLE_DATE, bundleInfo} from '#/lib/app-info'
|
||||
import {STATUS_PAGE_URL} from '#/lib/constants'
|
||||
import {type CommonNavigatorParams} from '#/lib/routes/types'
|
||||
import {isAndroid, isNative} from '#/platform/detection'
|
||||
import {isAndroid, isIOS, isNative} from '#/platform/detection'
|
||||
import * as Toast from '#/view/com/util/Toast'
|
||||
import * as SettingsList from '#/screens/Settings/components/SettingsList'
|
||||
import {Atom_Stroke2_Corner0_Rounded as AtomIcon} from '#/components/icons/Atom'
|
||||
import {BroomSparkle_Stroke2_Corner2_Rounded as BroomSparkleIcon} from '#/components/icons/BroomSparkle'
|
||||
import {CodeLines_Stroke2_Corner2_Rounded as CodeLinesIcon} from '#/components/icons/CodeLines'
|
||||
import {Globe_Stroke2_Corner0_Rounded as GlobeIcon} from '#/components/icons/Globe'
|
||||
@@ -22,6 +23,7 @@ import {Newspaper_Stroke2_Corner2_Rounded as NewspaperIcon} from '#/components/i
|
||||
import {Wrench_Stroke2_Corner2_Rounded as WrenchIcon} from '#/components/icons/Wrench'
|
||||
import * as Layout from '#/components/Layout'
|
||||
import {Loader} from '#/components/Loader'
|
||||
import {useDemoMode} from '#/storage/hooks/demo-mode'
|
||||
import {useDevMode} from '#/storage/hooks/dev-mode'
|
||||
import {OTAInfo} from './components/OTAInfo'
|
||||
|
||||
@@ -29,6 +31,7 @@ type Props = NativeStackScreenProps<CommonNavigatorParams, 'AboutSettings'>
|
||||
export function AboutSettingsScreen({}: Props) {
|
||||
const {_, i18n} = useLingui()
|
||||
const [devModeEnabled, setDevModeEnabled] = useDevMode()
|
||||
const [demoModeEnabled, setDemoModeEnabled] = useDemoMode()
|
||||
const stableID = useMemo(() => Statsig.getStableID(), [])
|
||||
|
||||
const {mutate: onClearImageCache, isPending: isClearingImageCache} =
|
||||
@@ -153,7 +156,31 @@ export function AboutSettingsScreen({}: Props) {
|
||||
</SettingsList.ItemText>
|
||||
<SettingsList.BadgeText>{bundleInfo}</SettingsList.BadgeText>
|
||||
</SettingsList.PressableItem>
|
||||
{devModeEnabled && <OTAInfo />}
|
||||
{devModeEnabled && (
|
||||
<>
|
||||
<OTAInfo />
|
||||
{isIOS && (
|
||||
<SettingsList.PressableItem
|
||||
onPress={() => {
|
||||
const newDemoModeEnabled = !demoModeEnabled
|
||||
setDemoModeEnabled(newDemoModeEnabled)
|
||||
Toast.show(
|
||||
'Demo mode ' +
|
||||
(newDemoModeEnabled ? 'enabled' : 'disabled'),
|
||||
)
|
||||
}}
|
||||
label={
|
||||
demoModeEnabled ? 'Disable demo mode' : 'Enable demo mode'
|
||||
}
|
||||
disabled={isClearingImageCache}>
|
||||
<SettingsList.ItemIcon icon={AtomIcon} />
|
||||
<SettingsList.ItemText>
|
||||
{demoModeEnabled ? 'Disable demo mode' : 'Enable demo mode'}
|
||||
</SettingsList.ItemText>
|
||||
</SettingsList.PressableItem>
|
||||
)}
|
||||
</>
|
||||
)}
|
||||
</SettingsList.Container>
|
||||
</Layout.Content>
|
||||
</Layout.Screen>
|
||||
|
||||
@@ -1,31 +1,32 @@
|
||||
import React, {useCallback, useEffect, useRef} from 'react'
|
||||
import {AppState} from 'react-native'
|
||||
import {
|
||||
AppBskyActorDefs,
|
||||
type AppBskyActorDefs,
|
||||
AppBskyFeedDefs,
|
||||
AppBskyFeedPost,
|
||||
type AppBskyFeedPost,
|
||||
AtUri,
|
||||
BskyAgent,
|
||||
type BskyAgent,
|
||||
moderatePost,
|
||||
ModerationDecision,
|
||||
type ModerationDecision,
|
||||
} from '@atproto/api'
|
||||
import {
|
||||
InfiniteData,
|
||||
QueryClient,
|
||||
QueryKey,
|
||||
type InfiniteData,
|
||||
type QueryClient,
|
||||
type QueryKey,
|
||||
useInfiniteQuery,
|
||||
} from '@tanstack/react-query'
|
||||
|
||||
import {AuthorFeedAPI} from '#/lib/api/feed/author'
|
||||
import {CustomFeedAPI} from '#/lib/api/feed/custom'
|
||||
import {DemoFeedAPI} from '#/lib/api/feed/demo'
|
||||
import {FollowingFeedAPI} from '#/lib/api/feed/following'
|
||||
import {HomeFeedAPI} from '#/lib/api/feed/home'
|
||||
import {LikesFeedAPI} from '#/lib/api/feed/likes'
|
||||
import {ListFeedAPI} from '#/lib/api/feed/list'
|
||||
import {MergeFeedAPI} from '#/lib/api/feed/merge'
|
||||
import {FeedAPI, ReasonFeedSource} from '#/lib/api/feed/types'
|
||||
import {type FeedAPI, type ReasonFeedSource} from '#/lib/api/feed/types'
|
||||
import {aggregateUserInterests} from '#/lib/api/feed/utils'
|
||||
import {FeedTuner, FeedTunerFn} from '#/lib/api/feed-manip'
|
||||
import {FeedTuner, type FeedTunerFn} from '#/lib/api/feed-manip'
|
||||
import {DISCOVER_FEED_URI} from '#/lib/constants'
|
||||
import {BSKY_FEED_OWNER_DIDS} from '#/lib/constants'
|
||||
import {logger} from '#/logger'
|
||||
@@ -59,6 +60,7 @@ export type FeedDescriptor =
|
||||
| `feedgen|${FeedUri}`
|
||||
| `likes|${ActorDid}`
|
||||
| `list|${ListUri}`
|
||||
| 'demo'
|
||||
export interface FeedParams {
|
||||
mergeFeedEnabled?: boolean
|
||||
mergeFeedSources?: string[]
|
||||
@@ -483,6 +485,8 @@ function createApi({
|
||||
} else if (feedDesc.startsWith('list')) {
|
||||
const [_, list] = feedDesc.split('|')
|
||||
return new ListFeedAPI({agent, feedParams: {list}})
|
||||
} else if (feedDesc === 'demo') {
|
||||
return new DemoFeedAPI({agent})
|
||||
} else {
|
||||
// shouldnt happen
|
||||
return new FollowingFeedAPI({agent})
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
import {device, useStorage} from '#/storage'
|
||||
|
||||
export function useDemoMode() {
|
||||
const [demoMode = false, setDemoMode] = useStorage(device, ['demoMode'])
|
||||
|
||||
return [demoMode, setDemoMode] as const
|
||||
}
|
||||
@@ -10,6 +10,7 @@ export type Device = {
|
||||
}
|
||||
trendingBetaEnabled: boolean
|
||||
devMode: boolean
|
||||
demoMode: boolean
|
||||
}
|
||||
|
||||
export type Account = {
|
||||
|
||||
@@ -1,12 +1,16 @@
|
||||
import React from 'react'
|
||||
import {
|
||||
InteractionManager,
|
||||
StyleProp,
|
||||
type StyleProp,
|
||||
StyleSheet,
|
||||
View,
|
||||
ViewStyle,
|
||||
type ViewStyle,
|
||||
} from 'react-native'
|
||||
import {MeasuredDimensions, runOnJS, runOnUI} from 'react-native-reanimated'
|
||||
import {
|
||||
type MeasuredDimensions,
|
||||
runOnJS,
|
||||
runOnUI,
|
||||
} from 'react-native-reanimated'
|
||||
import {Image} from 'expo-image'
|
||||
import {
|
||||
AppBskyEmbedExternal,
|
||||
@@ -18,10 +22,10 @@ import {
|
||||
AppBskyGraphDefs,
|
||||
moderateFeedGenerator,
|
||||
moderateUserList,
|
||||
ModerationDecision,
|
||||
type ModerationDecision,
|
||||
} from '@atproto/api'
|
||||
|
||||
import {HandleRef, measureHandle} from '#/lib/hooks/useHandleRef'
|
||||
import {type HandleRef, measureHandle} from '#/lib/hooks/useHandleRef'
|
||||
import {usePalette} from '#/lib/hooks/usePalette'
|
||||
import {useLightboxControls} from '#/state/lightbox'
|
||||
import {useModerationOpts} from '#/state/preferences/moderation-opts'
|
||||
@@ -30,7 +34,7 @@ import {atoms as a, useTheme} from '#/alf'
|
||||
import * as ListCard from '#/components/ListCard'
|
||||
import {Embed as StarterPackCard} from '#/components/StarterPack/StarterPackCard'
|
||||
import {ContentHider} from '../../../../components/moderation/ContentHider'
|
||||
import {Dimensions} from '../../lightbox/ImageViewing/@types'
|
||||
import {type Dimensions} from '../../lightbox/ImageViewing/@types'
|
||||
import {AutoSizedImage} from '../images/AutoSizedImage'
|
||||
import {ImageLayoutGrid} from '../images/ImageLayoutGrid'
|
||||
import {ExternalLinkEmbed} from './ExternalLinkEmbed'
|
||||
|
||||
@@ -8,28 +8,36 @@ import {useOTAUpdates} from '#/lib/hooks/useOTAUpdates'
|
||||
import {useSetTitle} from '#/lib/hooks/useSetTitle'
|
||||
import {useRequestNotificationsPermission} from '#/lib/notifications/notifications'
|
||||
import {
|
||||
HomeTabNavigatorParams,
|
||||
NativeStackScreenProps,
|
||||
type HomeTabNavigatorParams,
|
||||
type NativeStackScreenProps,
|
||||
} from '#/lib/routes/types'
|
||||
import {logEvent} from '#/lib/statsig/statsig'
|
||||
import {isWeb} from '#/platform/detection'
|
||||
import {emitSoftReset} from '#/state/events'
|
||||
import {SavedFeedSourceInfo, usePinnedFeedsInfos} from '#/state/queries/feed'
|
||||
import {FeedDescriptor, FeedParams} from '#/state/queries/post-feed'
|
||||
import {
|
||||
type SavedFeedSourceInfo,
|
||||
usePinnedFeedsInfos,
|
||||
} from '#/state/queries/feed'
|
||||
import {type FeedDescriptor, type FeedParams} from '#/state/queries/post-feed'
|
||||
import {usePreferencesQuery} from '#/state/queries/preferences'
|
||||
import {UsePreferencesQueryResponse} from '#/state/queries/preferences/types'
|
||||
import {type UsePreferencesQueryResponse} from '#/state/queries/preferences/types'
|
||||
import {useSession} from '#/state/session'
|
||||
import {useSetMinimalShellMode} from '#/state/shell'
|
||||
import {useLoggedOutViewControls} from '#/state/shell/logged-out'
|
||||
import {useSelectedFeed, useSetSelectedFeed} from '#/state/shell/selected-feed'
|
||||
import {FeedPage} from '#/view/com/feeds/FeedPage'
|
||||
import {HomeHeader} from '#/view/com/home/HomeHeader'
|
||||
import {Pager, PagerRef, RenderTabBarFnProps} from '#/view/com/pager/Pager'
|
||||
import {
|
||||
Pager,
|
||||
type PagerRef,
|
||||
type RenderTabBarFnProps,
|
||||
} from '#/view/com/pager/Pager'
|
||||
import {CustomFeedEmptyState} from '#/view/com/posts/CustomFeedEmptyState'
|
||||
import {FollowingEmptyState} from '#/view/com/posts/FollowingEmptyState'
|
||||
import {FollowingEndOfFeed} from '#/view/com/posts/FollowingEndOfFeed'
|
||||
import {NoFeedsPinned} from '#/screens/Home/NoFeedsPinned'
|
||||
import * as Layout from '#/components/Layout'
|
||||
import {useDemoMode} from '#/storage/hooks/demo-mode'
|
||||
|
||||
type Props = NativeStackScreenProps<HomeTabNavigatorParams, 'Home' | 'Start'>
|
||||
export function HomeScreen(props: Props) {
|
||||
@@ -184,8 +192,22 @@ function HomeScreenReady({
|
||||
[setMinimalShellMode],
|
||||
)
|
||||
|
||||
const [demoMode] = useDemoMode()
|
||||
|
||||
const renderTabBar = React.useCallback(
|
||||
(props: RenderTabBarFnProps) => {
|
||||
if (demoMode) {
|
||||
return (
|
||||
<HomeHeader
|
||||
key="FEEDS_TAB_BAR"
|
||||
{...props}
|
||||
testID="homeScreenFeedTabs"
|
||||
onPressSelected={onPressSelected}
|
||||
// @ts-ignore
|
||||
feeds={[{displayName: 'Following'}, {displayName: 'Discover'}]}
|
||||
/>
|
||||
)
|
||||
}
|
||||
return (
|
||||
<HomeHeader
|
||||
key="FEEDS_TAB_BAR"
|
||||
@@ -196,7 +218,7 @@ function HomeScreenReady({
|
||||
/>
|
||||
)
|
||||
},
|
||||
[onPressSelected, pinnedFeedInfos],
|
||||
[onPressSelected, pinnedFeedInfos, demoMode],
|
||||
)
|
||||
|
||||
const renderFollowingEmptyState = React.useCallback(() => {
|
||||
@@ -218,6 +240,35 @@ function HomeScreenReady({
|
||||
}
|
||||
}, [preferences])
|
||||
|
||||
if (demoMode) {
|
||||
return (
|
||||
<Pager
|
||||
ref={pagerRef}
|
||||
testID="homeScreen"
|
||||
onPageSelected={onPageSelected}
|
||||
onPageScrollStateChanged={onPageScrollStateChanged}
|
||||
renderTabBar={renderTabBar}
|
||||
initialPage={selectedIndex}>
|
||||
<FeedPage
|
||||
testID="demoFeedPage"
|
||||
isPageFocused
|
||||
isPageAdjacent={false}
|
||||
feed="demo"
|
||||
renderEmptyState={renderCustomFeedEmptyState}
|
||||
feedInfo={pinnedFeedInfos[0]}
|
||||
/>
|
||||
<FeedPage
|
||||
testID="customFeedPage"
|
||||
isPageFocused
|
||||
isPageAdjacent={false}
|
||||
feed={`feedgen|${PROD_DEFAULT_FEED('whats-hot')}`}
|
||||
renderEmptyState={renderCustomFeedEmptyState}
|
||||
feedInfo={pinnedFeedInfos[0]}
|
||||
/>
|
||||
</Pager>
|
||||
)
|
||||
}
|
||||
|
||||
return hasSession ? (
|
||||
<Pager
|
||||
key={allFeeds.join(',')}
|
||||
|
||||
@@ -1,13 +1,14 @@
|
||||
import React, {ComponentProps} from 'react'
|
||||
import {GestureResponderEvent, View} from 'react-native'
|
||||
import React, {type ComponentProps} from 'react'
|
||||
import {type GestureResponderEvent, View} from 'react-native'
|
||||
import Animated from 'react-native-reanimated'
|
||||
import {useSafeAreaInsets} from 'react-native-safe-area-context'
|
||||
import {msg, plural, Trans} from '@lingui/macro'
|
||||
import {useLingui} from '@lingui/react'
|
||||
import {BottomTabBarProps} from '@react-navigation/bottom-tabs'
|
||||
import {type BottomTabBarProps} from '@react-navigation/bottom-tabs'
|
||||
import {StackActions} from '@react-navigation/native'
|
||||
|
||||
import {PressableScale} from '#/lib/custom-animations/PressableScale'
|
||||
import {BOTTOM_BAR_AVI} from '#/lib/demo'
|
||||
import {useHaptics} from '#/lib/haptics'
|
||||
import {useDedupe} from '#/lib/hooks/useDedupe'
|
||||
import {useMinimalShellFooterTransform} from '#/lib/hooks/useMinimalShellTransform'
|
||||
@@ -47,6 +48,7 @@ import {
|
||||
Message_Stroke2_Corner0_Rounded as Message,
|
||||
Message_Stroke2_Corner0_Rounded_Filled as MessageFilled,
|
||||
} from '#/components/icons/Message'
|
||||
import {useDemoMode} from '#/storage/hooks/demo-mode'
|
||||
import {styles} from './BottomBarStyles'
|
||||
|
||||
type TabOptions =
|
||||
@@ -124,6 +126,8 @@ export function BottomBar({navigation}: BottomTabBarProps) {
|
||||
accountSwitchControl.open()
|
||||
}, [accountSwitchControl, playHaptic])
|
||||
|
||||
const [demoMode] = useDemoMode()
|
||||
|
||||
return (
|
||||
<>
|
||||
<SwitchAccountDialog control={accountSwitchControl} />
|
||||
@@ -259,7 +263,7 @@ export function BottomBar({navigation}: BottomTabBarProps) {
|
||||
{borderColor: pal.text.color},
|
||||
]}>
|
||||
<UserAvatar
|
||||
avatar={profile?.avatar}
|
||||
avatar={demoMode ? BOTTOM_BAR_AVI : profile?.avatar}
|
||||
size={iconWidth - 3}
|
||||
// See https://github.com/bluesky-social/social-app/pull/1801:
|
||||
usePlainRNImage={true}
|
||||
@@ -270,7 +274,7 @@ export function BottomBar({navigation}: BottomTabBarProps) {
|
||||
<View
|
||||
style={[styles.ctrlIcon, pal.text, styles.profileIcon]}>
|
||||
<UserAvatar
|
||||
avatar={profile?.avatar}
|
||||
avatar={demoMode ? BOTTOM_BAR_AVI : profile?.avatar}
|
||||
size={iconWidth - 3}
|
||||
// See https://github.com/bluesky-social/social-app/pull/1801:
|
||||
usePlainRNImage={true}
|
||||
|
||||
Reference in New Issue
Block a user