* Base work for public view

* Make default moderation settings more restrictive

* Fix type

* Handle showing sign-in on authed actions

* Fix hoc logic

* Simplify prefs logic

* Remove duplicate method

* Add todo

* Clean up RepostButton.web

* Fix x button color

* Add todo

* Retain existing label prefs for now, use separate logged out settings

* Clean up useAuthedMethod, rename to useRequireAuth

* Add todos

* Move dismiss logic to withAuthRequired

* Ooops add web

* Block public view in prod

* Add todo

* Fix bad import
zio/stable
Eric Bailey 2023-11-21 10:57:34 -06:00 committed by GitHub
parent 71b59021b9
commit f18b9b32b0
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
25 changed files with 1026 additions and 755 deletions

View File

@ -2,6 +2,7 @@ import {
UsePreferencesQueryResponse,
ThreadViewPreferences,
} from '#/state/queries/preferences/types'
import {DEFAULT_LOGGED_OUT_LABEL_PREFERENCES} from '#/state/queries/preferences/moderation'
export const DEFAULT_HOME_FEED_PREFS: UsePreferencesQueryResponse['feedViewPrefs'] =
{
@ -25,3 +26,26 @@ export const DEFAULT_PROD_FEEDS = {
pinned: [DEFAULT_PROD_FEED_PREFIX('whats-hot')],
saved: [DEFAULT_PROD_FEED_PREFIX('whats-hot')],
}
export const DEFAULT_LOGGED_OUT_PREFERENCES: UsePreferencesQueryResponse = {
birthDate: new Date('2022-11-17'), // TODO(pwi)
adultContentEnabled: false,
feeds: {
saved: [],
pinned: [],
unpinned: [],
},
// labels are undefined until set by user
contentLabels: {
nsfw: DEFAULT_LOGGED_OUT_LABEL_PREFERENCES.nsfw,
nudity: DEFAULT_LOGGED_OUT_LABEL_PREFERENCES.nudity,
suggestive: DEFAULT_LOGGED_OUT_LABEL_PREFERENCES.suggestive,
gore: DEFAULT_LOGGED_OUT_LABEL_PREFERENCES.gore,
hate: DEFAULT_LOGGED_OUT_LABEL_PREFERENCES.hate,
spam: DEFAULT_LOGGED_OUT_LABEL_PREFERENCES.spam,
impersonation: DEFAULT_LOGGED_OUT_LABEL_PREFERENCES.impersonation,
},
feedViewPrefs: DEFAULT_HOME_FEED_PREFS,
threadViewPrefs: DEFAULT_THREAD_VIEW_PREFS,
userAge: 13, // TODO(pwi)
}

View File

@ -15,6 +15,7 @@ import {temp__migrateLabelPref} from '#/state/queries/preferences/util'
import {
DEFAULT_HOME_FEED_PREFS,
DEFAULT_THREAD_VIEW_PREFS,
DEFAULT_LOGGED_OUT_PREFERENCES,
} from '#/state/queries/preferences/const'
import {getModerationOpts} from '#/state/queries/preferences/moderation'
import {STALE} from '#/state/queries'
@ -23,16 +24,19 @@ export * from '#/state/queries/preferences/types'
export * from '#/state/queries/preferences/moderation'
export * from '#/state/queries/preferences/const'
export const usePreferencesQueryKey = ['getPreferences']
export const preferencesQueryKey = ['getPreferences']
export function usePreferencesQuery() {
const {hasSession} = useSession()
return useQuery({
enabled: hasSession,
staleTime: STALE.MINUTES.ONE,
queryKey: usePreferencesQueryKey,
queryKey: preferencesQueryKey,
queryFn: async () => {
const res = await getAgent().getPreferences()
const agent = getAgent()
if (agent.session?.did === undefined) {
return DEFAULT_LOGGED_OUT_PREFERENCES
} else {
const res = await agent.getPreferences()
const preferences: UsePreferencesQueryResponse = {
...res,
feeds: {
@ -80,6 +84,7 @@ export function usePreferencesQuery() {
userAge: res.birthDate ? getAge(res.birthDate) : undefined,
}
return preferences
}
},
})
}
@ -107,7 +112,7 @@ export function useClearPreferencesMutation() {
await getAgent().app.bsky.actor.putPreferences({preferences: []})
// triggers a refetch
await queryClient.invalidateQueries({
queryKey: usePreferencesQueryKey,
queryKey: preferencesQueryKey,
})
},
})
@ -125,7 +130,7 @@ export function usePreferencesSetContentLabelMutation() {
await getAgent().setContentLabelPref(labelGroup, visibility)
// triggers a refetch
await queryClient.invalidateQueries({
queryKey: usePreferencesQueryKey,
queryKey: preferencesQueryKey,
})
},
})
@ -139,7 +144,7 @@ export function usePreferencesSetAdultContentMutation() {
await getAgent().setAdultContentEnabled(enabled)
// triggers a refetch
await queryClient.invalidateQueries({
queryKey: usePreferencesQueryKey,
queryKey: preferencesQueryKey,
})
},
})
@ -153,7 +158,7 @@ export function usePreferencesSetBirthDateMutation() {
await getAgent().setPersonalDetails({birthDate})
// triggers a refetch
await queryClient.invalidateQueries({
queryKey: usePreferencesQueryKey,
queryKey: preferencesQueryKey,
})
},
})
@ -167,7 +172,7 @@ export function useSetFeedViewPreferencesMutation() {
await getAgent().setFeedViewPrefs('home', prefs)
// triggers a refetch
await queryClient.invalidateQueries({
queryKey: usePreferencesQueryKey,
queryKey: preferencesQueryKey,
})
},
})
@ -181,7 +186,7 @@ export function useSetThreadViewPreferencesMutation() {
await getAgent().setThreadViewPrefs(prefs)
// triggers a refetch
await queryClient.invalidateQueries({
queryKey: usePreferencesQueryKey,
queryKey: preferencesQueryKey,
})
},
})
@ -199,7 +204,7 @@ export function useSetSaveFeedsMutation() {
await getAgent().setSavedFeeds(saved, pinned)
// triggers a refetch
await queryClient.invalidateQueries({
queryKey: usePreferencesQueryKey,
queryKey: preferencesQueryKey,
})
},
})
@ -214,7 +219,7 @@ export function useSaveFeedMutation() {
track('CustomFeed:Save')
// triggers a refetch
await queryClient.invalidateQueries({
queryKey: usePreferencesQueryKey,
queryKey: preferencesQueryKey,
})
},
})
@ -229,7 +234,7 @@ export function useRemoveFeedMutation() {
track('CustomFeed:Unsave')
// triggers a refetch
await queryClient.invalidateQueries({
queryKey: usePreferencesQueryKey,
queryKey: preferencesQueryKey,
})
},
})
@ -244,7 +249,7 @@ export function usePinFeedMutation() {
track('CustomFeed:Pin', {uri})
// triggers a refetch
await queryClient.invalidateQueries({
queryKey: usePreferencesQueryKey,
queryKey: preferencesQueryKey,
})
},
})
@ -259,7 +264,7 @@ export function useUnpinFeedMutation() {
track('CustomFeed:Unpin', {uri})
// triggers a refetch
await queryClient.invalidateQueries({
queryKey: usePreferencesQueryKey,
queryKey: preferencesQueryKey,
})
},
})

View File

@ -34,6 +34,24 @@ export const DEFAULT_LABEL_PREFERENCES: Record<
impersonation: 'hide',
}
/**
* More strict than our default settings for logged in users.
*
* TODO(pwi)
*/
export const DEFAULT_LOGGED_OUT_LABEL_PREFERENCES: Record<
ConfigurableLabelGroup,
LabelPreference
> = {
nsfw: 'hide',
nudity: 'hide',
suggestive: 'hide',
gore: 'hide',
hate: 'hide',
spam: 'hide',
impersonation: 'hide',
}
export const ILLEGAL_LABEL_GROUP: LabelGroupConfig = {
id: 'illegal',
title: 'Illegal Content',

View File

@ -43,7 +43,10 @@ export type UsePreferencesQueryResponse = Omit<
}
}
export type ThreadViewPreferences = Omit<BskyThreadViewPreference, 'sort'> & {
export type ThreadViewPreferences = Pick<
BskyThreadViewPreference,
'prioritizeFollowedUsers'
> & {
sort: 'oldest' | 'newest' | 'most-likes' | 'random' | string
lab_treeViewEnabled?: boolean
}

View File

@ -8,6 +8,7 @@ import * as persisted from '#/state/persisted'
import {PUBLIC_BSKY_AGENT} from '#/state/queries'
import {IS_PROD} from '#/lib/constants'
import {emitSessionLoaded, emitSessionDropped} from '../events'
import {useLoggedOutViewControls} from '#/state/shell/logged-out'
let __globalAgent: BskyAgent = PUBLIC_BSKY_AGENT
@ -515,3 +516,19 @@ export function useSession() {
export function useSessionApi() {
return React.useContext(ApiContext)
}
export function useRequireAuth() {
const {hasSession} = useSession()
const {setShowLoggedOut} = useLoggedOutViewControls()
return React.useCallback(
(fn: () => void) => {
if (hasSession) {
fn()
} else {
setShowLoggedOut(true)
}
},
[hasSession, setShowLoggedOut],
)
}

View File

@ -7,6 +7,7 @@ import {Provider as ColorModeProvider} from './color-mode'
import {Provider as OnboardingProvider} from './onboarding'
import {Provider as ComposerProvider} from './composer'
import {Provider as TickEveryMinuteProvider} from './tick-every-minute'
import {Provider as LoggedOutViewProvider} from './logged-out'
export {useIsDrawerOpen, useSetDrawerOpen} from './drawer-open'
export {
@ -22,19 +23,23 @@ export {useTickEveryMinute} from './tick-every-minute'
export function Provider({children}: React.PropsWithChildren<{}>) {
return (
<ShellLayoutProvder>
<LoggedOutViewProvider>
<DrawerOpenProvider>
<DrawerSwipableProvider>
<MinimalModeProvider>
<ColorModeProvider>
<OnboardingProvider>
<ComposerProvider>
<TickEveryMinuteProvider>{children}</TickEveryMinuteProvider>
<TickEveryMinuteProvider>
{children}
</TickEveryMinuteProvider>
</ComposerProvider>
</OnboardingProvider>
</ColorModeProvider>
</MinimalModeProvider>
</DrawerSwipableProvider>
</DrawerOpenProvider>
</LoggedOutViewProvider>
</ShellLayoutProvder>
)
}

View File

@ -0,0 +1,37 @@
import React from 'react'
type StateContext = {
showLoggedOut: boolean
}
const StateContext = React.createContext<StateContext>({
showLoggedOut: false,
})
const ControlsContext = React.createContext<{
setShowLoggedOut: (show: boolean) => void
}>({
setShowLoggedOut: () => {},
})
export function Provider({children}: React.PropsWithChildren<{}>) {
const [showLoggedOut, setShowLoggedOut] = React.useState(false)
const state = React.useMemo(() => ({showLoggedOut}), [showLoggedOut])
const controls = React.useMemo(() => ({setShowLoggedOut}), [setShowLoggedOut])
return (
<StateContext.Provider value={state}>
<ControlsContext.Provider value={controls}>
{children}
</ControlsContext.Provider>
</StateContext.Provider>
)
}
export function useLoggedOutView() {
return React.useContext(StateContext)
}
export function useLoggedOutViewControls() {
return React.useContext(ControlsContext)
}

View File

@ -15,7 +15,7 @@ enum ScreenState {
S_CreateAccount,
}
export function LoggedOut() {
export function LoggedOut({onDismiss}: {onDismiss?: () => void}) {
const pal = usePalette('default')
const setMinimalShellMode = useSetMinimalShellMode()
const {screen} = useAnalytics()
@ -31,6 +31,7 @@ export function LoggedOut() {
if (screenState === ScreenState.S_LoginOrCreateAccount) {
return (
<SplashScreen
onDismiss={onDismiss}
onPressSignin={() => setScreenState(ScreenState.S_Login)}
onPressCreateAccount={() => setScreenState(ScreenState.S_CreateAccount)}
/>

View File

@ -1,5 +1,12 @@
import React from 'react'
import {SafeAreaView, StyleSheet, TouchableOpacity, View} from 'react-native'
import {
SafeAreaView,
StyleSheet,
TouchableOpacity,
Pressable,
View,
} from 'react-native'
import {FontAwesomeIcon} from '@fortawesome/react-native-fontawesome'
import {Text} from 'view/com/util/text/Text'
import {ErrorBoundary} from 'view/com/util/ErrorBoundary'
import {s, colors} from 'lib/styles'
@ -9,9 +16,11 @@ import {Trans, msg} from '@lingui/macro'
import {useLingui} from '@lingui/react'
export const SplashScreen = ({
onDismiss,
onPressSignin,
onPressCreateAccount,
}: {
onDismiss?: () => void
onPressSignin: () => void
onPressCreateAccount: () => void
}) => {
@ -20,6 +29,27 @@ export const SplashScreen = ({
return (
<CenteredView style={[styles.container, pal.view]}>
{onDismiss && (
<Pressable
accessibilityRole="button"
style={{
position: 'absolute',
top: 20,
right: 20,
padding: 20,
zIndex: 100,
}}
onPress={onDismiss}>
<FontAwesomeIcon
icon="x"
size={24}
style={{
color: String(pal.text.color),
}}
/>
</Pressable>
)}
<SafeAreaView testID="noSessionView" style={styles.container}>
<ErrorBoundary>
<View style={styles.hero}>

View File

@ -1,5 +1,6 @@
import React from 'react'
import {StyleSheet, TouchableOpacity, View} from 'react-native'
import {StyleSheet, TouchableOpacity, View, Pressable} from 'react-native'
import {FontAwesomeIcon} from '@fortawesome/react-native-fontawesome'
import {Text} from 'view/com/util/text/Text'
import {TextLink} from '../util/Link'
import {ErrorBoundary} from 'view/com/util/ErrorBoundary'
@ -11,9 +12,11 @@ import {useWebMediaQueries} from 'lib/hooks/useWebMediaQueries'
import {Trans} from '@lingui/macro'
export const SplashScreen = ({
onDismiss,
onPressSignin,
onPressCreateAccount,
}: {
onDismiss?: () => void
onPressSignin: () => void
onPressCreateAccount: () => void
}) => {
@ -23,6 +26,28 @@ export const SplashScreen = ({
const isMobileWeb = isWeb && isTabletOrMobile
return (
<>
{onDismiss && (
<Pressable
accessibilityRole="button"
style={{
position: 'absolute',
top: 20,
right: 20,
padding: 20,
zIndex: 100,
}}
onPress={onDismiss}>
<FontAwesomeIcon
icon="x"
size={24}
style={{
color: String(pal.text.color),
}}
/>
</Pressable>
)}
<CenteredView style={[styles.container, pal.view]}>
<View
testID="noSessionView"
@ -64,6 +89,7 @@ export const SplashScreen = ({
</View>
<Footer styles={styles} />
</CenteredView>
</>
)
}

View File

@ -13,19 +13,34 @@ import {usePalette} from 'lib/hooks/usePalette'
import {STATUS_PAGE_URL} from 'lib/constants'
import {useOnboardingState} from '#/state/shell'
import {useSession} from '#/state/session'
import {
useLoggedOutView,
useLoggedOutViewControls,
} from '#/state/shell/logged-out'
import {IS_PROD} from '#/env'
export const withAuthRequired = <P extends object>(
Component: React.ComponentType<P>,
options: {
isPublic?: boolean // TODO(pwi) need to enable in TF somehow
} = {},
): React.FC<P> =>
function AuthRequired(props: P) {
const {isInitialLoad, hasSession} = useSession()
const onboardingState = useOnboardingState()
const {showLoggedOut} = useLoggedOutView()
const {setShowLoggedOut} = useLoggedOutViewControls()
if (isInitialLoad) {
return <Loading />
}
if (!hasSession) {
if (showLoggedOut) {
return <LoggedOut onDismiss={() => setShowLoggedOut(false)} />
} else if (!options?.isPublic || IS_PROD) {
return <LoggedOut />
}
}
if (onboardingState.isActive) {
return <Onboarding />
}

View File

@ -25,6 +25,7 @@ import {
} from '#/state/queries/post'
import {useComposerControls} from '#/state/shell/composer'
import {Shadow} from '#/state/cache/types'
import {useRequireAuth} from '#/state/session'
export function PostCtrls({
big,
@ -46,6 +47,7 @@ export function PostCtrls({
const postUnlikeMutation = usePostUnlikeMutation()
const postRepostMutation = usePostRepostMutation()
const postUnrepostMutation = usePostUnrepostMutation()
const requireAuth = useRequireAuth()
const defaultCtrlColor = React.useMemo(
() => ({
@ -107,7 +109,9 @@ export function PostCtrls({
<TouchableOpacity
testID="replyBtn"
style={[styles.ctrl, !big && styles.ctrlPad, {paddingLeft: 0}]}
onPress={onPressReply}
onPress={() => {
requireAuth(() => onPressReply())
}}
accessibilityRole="button"
accessibilityLabel={`Reply (${post.replyCount} ${
post.replyCount === 1 ? 'reply' : 'replies'
@ -135,7 +139,9 @@ export function PostCtrls({
<TouchableOpacity
testID="likeBtn"
style={[styles.ctrl, !big && styles.ctrlPad]}
onPress={onPressToggleLike}
onPress={() => {
requireAuth(() => onPressToggleLike())
}}
accessibilityRole="button"
accessibilityLabel={`${post.viewer?.like ? 'Unlike' : 'Like'} (${
post.likeCount

View File

@ -7,6 +7,7 @@ import {Text} from '../text/Text'
import {pluralize} from 'lib/strings/helpers'
import {HITSLOP_10, HITSLOP_20} from 'lib/constants'
import {useModalControls} from '#/state/modals'
import {useRequireAuth} from '#/state/session'
interface Props {
isReposted: boolean
@ -25,6 +26,7 @@ export const RepostButton = ({
}: Props) => {
const theme = useTheme()
const {openModal} = useModalControls()
const requireAuth = useRequireAuth()
const defaultControlColor = React.useMemo(
() => ({
@ -45,7 +47,9 @@ export const RepostButton = ({
return (
<TouchableOpacity
testID="repostBtn"
onPress={onPressToggleRepostWrapper}
onPress={() => {
requireAuth(() => onPressToggleRepostWrapper())
}}
style={[styles.control, !big && styles.controlPad]}
accessibilityRole="button"
accessibilityLabel={`${

View File

@ -1,5 +1,5 @@
import React from 'react'
import {StyleProp, StyleSheet, View, ViewStyle} from 'react-native'
import {StyleProp, StyleSheet, View, ViewStyle, Pressable} from 'react-native'
import {RepostIcon} from 'lib/icons'
import {colors} from 'lib/styles'
import {useTheme} from 'lib/ThemeContext'
@ -12,6 +12,8 @@ import {
import {EventStopper} from '../EventStopper'
import {useLingui} from '@lingui/react'
import {msg} from '@lingui/macro'
import {useRequireAuth} from '#/state/session'
import {useSession} from '#/state/session'
interface Props {
isReposted: boolean
@ -31,6 +33,8 @@ export const RepostButton = ({
}: Props) => {
const theme = useTheme()
const {_} = useLingui()
const {hasSession} = useSession()
const requireAuth = useRequireAuth()
const defaultControlColor = React.useMemo(
() => ({
@ -62,12 +66,7 @@ export const RepostButton = ({
},
]
return (
<EventStopper>
<NativeDropdown
items={dropdownItems}
accessibilityLabel={_(msg`Repost or quote post`)}
accessibilityHint="">
const inner = (
<View
style={[
styles.control,
@ -86,8 +85,27 @@ export const RepostButton = ({
</Text>
) : undefined}
</View>
)
return hasSession ? (
<EventStopper>
<NativeDropdown
items={dropdownItems}
accessibilityLabel={_(msg`Repost or quote post`)}
accessibilityHint="">
{inner}
</NativeDropdown>
</EventStopper>
) : (
<Pressable
accessibilityRole="button"
onPress={() => {
requireAuth(() => {})
}}
accessibilityLabel={_(msg`Repost or quote post`)}
accessibilityHint="">
{inner}
</Pressable>
)
}

View File

@ -87,9 +87,8 @@ type FlatlistSlice =
key: string
}
export const FeedsScreen = withAuthRequired(function FeedsScreenImpl(
_props: Props,
) {
export const FeedsScreen = withAuthRequired(
function FeedsScreenImpl(_props: Props) {
const pal = usePalette('default')
const {openComposer} = useComposerControls()
const {isMobile, isTabletOrDesktop} = useWebMediaQueries()
@ -284,7 +283,9 @@ export const FeedsScreen = withAuthRequired(function FeedsScreenImpl(
for (const page of popularFeeds.pages || []) {
slices = slices.concat(
page.feeds
.filter(feed => !preferences?.feeds?.saved.includes(feed.uri))
.filter(
feed => !preferences?.feeds?.saved.includes(feed.uri),
)
.map(feed => ({
key: `popularFeed:${feed.uri}`,
type: 'popularFeed',
@ -506,7 +507,9 @@ export const FeedsScreen = withAuthRequired(function FeedsScreenImpl(
/>
</View>
)
})
},
{isPublic: true},
)
function SavedFeed({feedUri}: {feedUri: string}) {
const pal = usePalette('default')

View File

@ -14,12 +14,18 @@ import {useSetMinimalShellMode, useSetDrawerSwipeDisabled} from '#/state/shell'
import {usePreferencesQuery} from '#/state/queries/preferences'
import {UsePreferencesQueryResponse} from '#/state/queries/preferences/types'
import {emitSoftReset} from '#/state/events'
import {useSession} from '#/state/session'
type Props = NativeStackScreenProps<HomeTabNavigatorParams, 'Home'>
export const HomeScreen = withAuthRequired(function HomeScreenImpl(
props: Props,
) {
export const HomeScreen = withAuthRequired(
function HomeScreenImpl(props: Props) {
const {hasSession} = useSession()
const {data: preferences} = usePreferencesQuery()
if (!hasSession) {
return <HomeScreenPublic />
}
if (preferences) {
return <HomeScreenReady {...props} preferences={preferences} />
} else {
@ -29,7 +35,35 @@ export const HomeScreen = withAuthRequired(function HomeScreenImpl(
</View>
)
}
})
},
{
isPublic: true,
},
)
function HomeScreenPublic() {
const setMinimalShellMode = useSetMinimalShellMode()
const setDrawerSwipeDisabled = useSetDrawerSwipeDisabled()
const renderCustomFeedEmptyState = React.useCallback(() => {
return <CustomFeedEmptyState />
}, [])
useFocusEffect(
React.useCallback(() => {
setMinimalShellMode(false)
setDrawerSwipeDisabled(false)
}, [setDrawerSwipeDisabled, setMinimalShellMode]),
)
return (
<FeedPage
isPageFocused
feed={`feedgen|at://did:plc:z72i7hdynmk6r22z27h6tvur/app.bsky.feed.generator/whats-hot`}
renderEmptyState={renderCustomFeedEmptyState}
/>
)
}
function HomeScreenReady({
preferences,
@ -83,6 +117,7 @@ function HomeScreenReady({
emitSoftReset()
}, [])
// TODO(pwi) may need this in public view
const onPageScrollStateChanged = React.useCallback(
(state: 'idle' | 'dragging' | 'settling') => {
if (state === 'dragging') {

View File

@ -11,7 +11,8 @@ import {msg} from '@lingui/macro'
import {useLingui} from '@lingui/react'
type Props = NativeStackScreenProps<CommonNavigatorParams, 'PostLikedBy'>
export const PostLikedByScreen = withAuthRequired(({route}: Props) => {
export const PostLikedByScreen = withAuthRequired(
({route}: Props) => {
const setMinimalShellMode = useSetMinimalShellMode()
const {name, rkey} = route.params
const uri = makeRecordUri(name, 'app.bsky.feed.post', rkey)
@ -29,4 +30,6 @@ export const PostLikedByScreen = withAuthRequired(({route}: Props) => {
<PostLikedByComponent uri={uri} />
</View>
)
})
},
{isPublic: true},
)

View File

@ -11,7 +11,8 @@ import {useLingui} from '@lingui/react'
import {msg} from '@lingui/macro'
type Props = NativeStackScreenProps<CommonNavigatorParams, 'PostRepostedBy'>
export const PostRepostedByScreen = withAuthRequired(({route}: Props) => {
export const PostRepostedByScreen = withAuthRequired(
({route}: Props) => {
const {name, rkey} = route.params
const uri = makeRecordUri(name, 'app.bsky.feed.post', rkey)
const setMinimalShellMode = useSetMinimalShellMode()
@ -29,4 +30,6 @@ export const PostRepostedByScreen = withAuthRequired(({route}: Props) => {
<PostRepostedByComponent uri={uri} />
</View>
)
})
},
{isPublic: true},
)

View File

@ -27,9 +27,8 @@ import {CenteredView} from '../com/util/Views'
import {useComposerControls} from '#/state/shell/composer'
type Props = NativeStackScreenProps<CommonNavigatorParams, 'PostThread'>
export const PostThreadScreen = withAuthRequired(function PostThreadScreenImpl({
route,
}: Props) {
export const PostThreadScreen = withAuthRequired(
function PostThreadScreenImpl({route}: Props) {
const queryClient = useQueryClient()
const {_} = useLingui()
const {fabMinimalShellTransform} = useMinimalShellMode()
@ -104,7 +103,9 @@ export const PostThreadScreen = withAuthRequired(function PostThreadScreenImpl({
)}
</View>
)
})
},
{isPublic: true},
)
const styles = StyleSheet.create({
prompt: {

View File

@ -43,9 +43,8 @@ interface SectionRef {
}
type Props = NativeStackScreenProps<CommonNavigatorParams, 'Profile'>
export const ProfileScreen = withAuthRequired(function ProfileScreenImpl({
route,
}: Props) {
export const ProfileScreen = withAuthRequired(
function ProfileScreenImpl({route}: Props) {
const {currentAccount} = useSession()
const name =
route.params.name === 'me' ? currentAccount?.did : route.params.name
@ -118,7 +117,11 @@ export const ProfileScreen = withAuthRequired(function ProfileScreenImpl({
/>
</CenteredView>
)
})
},
{
isPublic: true,
},
)
function ProfileScreenLoaded({
profile: profileUnshadowed,

View File

@ -129,6 +129,9 @@ export const ProfileFeedScreen = withAuthRequired(
</CenteredView>
)
},
{
isPublic: true,
},
)
function ProfileFeedScreenIntermediate({feedUri}: {feedUri: string}) {

View File

@ -11,7 +11,8 @@ import {useLingui} from '@lingui/react'
import {msg} from '@lingui/macro'
type Props = NativeStackScreenProps<CommonNavigatorParams, 'ProfileFeedLikedBy'>
export const ProfileFeedLikedByScreen = withAuthRequired(({route}: Props) => {
export const ProfileFeedLikedByScreen = withAuthRequired(
({route}: Props) => {
const setMinimalShellMode = useSetMinimalShellMode()
const {name, rkey} = route.params
const uri = makeRecordUri(name, 'app.bsky.feed.generator', rkey)
@ -29,4 +30,6 @@ export const ProfileFeedLikedByScreen = withAuthRequired(({route}: Props) => {
<PostLikedByComponent uri={uri} />
</View>
)
})
},
{isPublic: true},
)

View File

@ -10,7 +10,8 @@ import {useLingui} from '@lingui/react'
import {msg} from '@lingui/macro'
type Props = NativeStackScreenProps<CommonNavigatorParams, 'ProfileFollowers'>
export const ProfileFollowersScreen = withAuthRequired(({route}: Props) => {
export const ProfileFollowersScreen = withAuthRequired(
({route}: Props) => {
const {name} = route.params
const setMinimalShellMode = useSetMinimalShellMode()
const {_} = useLingui()
@ -27,4 +28,6 @@ export const ProfileFollowersScreen = withAuthRequired(({route}: Props) => {
<ProfileFollowersComponent name={name} />
</View>
)
})
},
{isPublic: true},
)

View File

@ -10,7 +10,8 @@ import {useLingui} from '@lingui/react'
import {msg} from '@lingui/macro'
type Props = NativeStackScreenProps<CommonNavigatorParams, 'ProfileFollows'>
export const ProfileFollowsScreen = withAuthRequired(({route}: Props) => {
export const ProfileFollowsScreen = withAuthRequired(
({route}: Props) => {
const {name} = route.params
const setMinimalShellMode = useSetMinimalShellMode()
const {_} = useLingui()
@ -27,4 +28,6 @@ export const ProfileFollowsScreen = withAuthRequired(({route}: Props) => {
<ProfileFollowsComponent name={name} />
</View>
)
})
},
{isPublic: true},
)

View File

@ -33,7 +33,7 @@ import {
usePinFeedMutation,
useUnpinFeedMutation,
useSetSaveFeedsMutation,
usePreferencesQueryKey,
preferencesQueryKey,
UsePreferencesQueryResponse,
} from '#/state/queries/preferences'
@ -182,8 +182,9 @@ function ListItem({
const onPressUp = React.useCallback(async () => {
if (!isPinned) return
const feeds = queryClient.getQueryData<UsePreferencesQueryResponse>(
usePreferencesQueryKey,
const feeds =
queryClient.getQueryData<UsePreferencesQueryResponse>(
preferencesQueryKey,
)?.feeds
const pinned = feeds?.pinned ?? []
const index = pinned.indexOf(feedUri)
@ -206,8 +207,9 @@ function ListItem({
const onPressDown = React.useCallback(async () => {
if (!isPinned) return
const feeds = queryClient.getQueryData<UsePreferencesQueryResponse>(
usePreferencesQueryKey,
const feeds =
queryClient.getQueryData<UsePreferencesQueryResponse>(
preferencesQueryKey,
)?.feeds
const pinned = feeds?.pinned ?? []
const index = pinned.indexOf(feedUri)