diff --git a/src/components/FeedInterstitials.tsx b/src/components/FeedInterstitials.tsx
index eca1c86f00..e37d2c3e0e 100644
--- a/src/components/FeedInterstitials.tsx
+++ b/src/components/FeedInterstitials.tsx
@@ -133,16 +133,26 @@ function useExperimentalSuggestedUsersQuery() {
const {currentAccount} = useSession()
const userActionSnapshot = userActionHistory.useActionHistorySnapshot()
const dids = React.useMemo(() => {
- const {likes, follows, seen} = userActionSnapshot
+ const {likes, follows, followSuggestions, seen} = userActionSnapshot
const likeDids = likes
.map(l => new AtUri(l))
.map(uri => uri.host)
.filter(did => !follows.includes(did))
+ let suggestedDids: string[] = []
+ if (followSuggestions.length > 0) {
+ suggestedDids = [
+ // It's ok if these will pick the same item (weighed by its frequency)
+ followSuggestions[Math.floor(Math.random() * followSuggestions.length)],
+ followSuggestions[Math.floor(Math.random() * followSuggestions.length)],
+ followSuggestions[Math.floor(Math.random() * followSuggestions.length)],
+ followSuggestions[Math.floor(Math.random() * followSuggestions.length)],
+ ]
+ }
const seenDids = seen
.sort(sortSeenPosts)
.map(l => new AtUri(l.uri))
.map(uri => uri.host)
- return [...new Set([...likeDids, ...seenDids])].filter(
+ return [...new Set([...suggestedDids, ...likeDids, ...seenDids])].filter(
did => did !== currentAccount?.did,
)
}, [userActionSnapshot, currentAccount])
diff --git a/src/components/moderation/ContentHider.tsx b/src/components/moderation/ContentHider.tsx
index 45122a4efe..f2d13f6424 100644
--- a/src/components/moderation/ContentHider.tsx
+++ b/src/components/moderation/ContentHider.tsx
@@ -1,5 +1,5 @@
import React from 'react'
-import {StyleProp, StyleSheet, View, ViewStyle} from 'react-native'
+import {StyleProp, View, ViewStyle} from 'react-native'
import {ModerationUI} from '@atproto/api'
import {msg, Trans} from '@lingui/macro'
import {useLingui} from '@lingui/react'
@@ -40,7 +40,7 @@ export function ContentHider({
if (!blur || (ignoreMute && isJustAMute(modui))) {
return (
-
+
{children}
)
@@ -163,21 +163,3 @@ export function ContentHider({
)
}
-
-const styles = StyleSheet.create({
- outer: {},
- cover: {
- flexDirection: 'row',
- alignItems: 'center',
- gap: 6,
- borderRadius: 8,
- marginTop: 4,
- paddingVertical: 14,
- paddingLeft: 14,
- paddingRight: 18,
- },
- showBtn: {
- marginLeft: 'auto',
- alignSelf: 'center',
- },
-})
diff --git a/src/lib/notifications/notifications.ts b/src/lib/notifications/notifications.ts
index fafc66143a..88b9eee3a5 100644
--- a/src/lib/notifications/notifications.ts
+++ b/src/lib/notifications/notifications.ts
@@ -5,7 +5,7 @@ import {BskyAgent} from '@atproto/api'
import {logger} from '#/logger'
import {SessionAccount, useAgent, useSession} from '#/state/session'
-import {logEvent, useGate} from 'lib/statsig/statsig'
+import {logEvent} from 'lib/statsig/statsig'
import {devicePlatform, isAndroid, isNative} from 'platform/detection'
import BackgroundNotificationHandler from '../../../modules/expo-background-notification-handler'
@@ -86,7 +86,6 @@ export function useNotificationsRegistration() {
}
export function useRequestNotificationsPermission() {
- const gate = useGate()
const {currentAccount} = useSession()
const agent = useAgent()
@@ -102,16 +101,7 @@ export function useRequestNotificationsPermission() {
) {
return
}
- if (
- context === 'StartOnboarding' &&
- gate('request_notifications_permission_after_onboarding_v2')
- ) {
- return
- }
- if (
- context === 'AfterOnboarding' &&
- !gate('request_notifications_permission_after_onboarding_v2')
- ) {
+ if (context === 'AfterOnboarding') {
return
}
if (context === 'Home' && !currentAccount) {
diff --git a/src/lib/statsig/events.ts b/src/lib/statsig/events.ts
index 997a366a41..9a427ad40f 100644
--- a/src/lib/statsig/events.ts
+++ b/src/lib/statsig/events.ts
@@ -159,6 +159,7 @@ export type LogEvents = {
| 'AvatarButton'
| 'StarterPackProfilesList'
| 'FeedInterstitial'
+ | 'ProfileHeaderSuggestedFollows'
}
'profile:unfollow': {
logContext:
@@ -173,6 +174,7 @@ export type LogEvents = {
| 'AvatarButton'
| 'StarterPackProfilesList'
| 'FeedInterstitial'
+ | 'ProfileHeaderSuggestedFollows'
}
'chat:create': {
logContext: 'ProfileHeader' | 'NewChatDialog' | 'SendViaChatDialog'
@@ -211,6 +213,8 @@ export type LogEvents = {
'feed:interstitial:profileCard:press': {}
'feed:interstitial:feedCard:press': {}
+ 'profile:header:suggestedFollowsCard:press': {}
+
'debug:followingPrefs': {
followingShowRepliesFromPref: 'all' | 'following' | 'off'
followingRepliesMinLikePref: number
diff --git a/src/lib/statsig/gates.ts b/src/lib/statsig/gates.ts
index 4b482b47dc..5ae6bd5300 100644
--- a/src/lib/statsig/gates.ts
+++ b/src/lib/statsig/gates.ts
@@ -1,18 +1,10 @@
export type Gate =
// Keep this alphabetic please.
| 'debug_show_feedcontext'
- | 'explore_page_profile_card_social_proof'
- | 'native_pwi_disabled'
| 'new_user_guided_tour'
- | 'new_user_progress_guide'
| 'onboarding_minimum_interests'
- | 'request_notifications_permission_after_onboarding_v2'
| 'session_withproxy_fix'
- | 'show_avi_follow_button'
| 'show_follow_back_label_v2'
| 'suggested_feeds_interstitial'
- | 'suggested_follows_interstitial'
- | 'ungroup_follow_backs'
| 'video_debug'
| 'videos'
- | 'small_avi_thumb'
diff --git a/src/screens/Profile/Header/ProfileHeaderStandard.tsx b/src/screens/Profile/Header/ProfileHeaderStandard.tsx
index b275b31910..2b6353b276 100644
--- a/src/screens/Profile/Header/ProfileHeaderStandard.tsx
+++ b/src/screens/Profile/Header/ProfileHeaderStandard.tsx
@@ -157,7 +157,7 @@ let ProfileHeaderStandard = ({
hideBackButton={hideBackButton}
isPlaceholderProfile={isPlaceholderProfile}>
gate('ungroup_follow_backs'),
priority,
})
page = fetchedPage
diff --git a/src/state/queries/notifications/unread.tsx b/src/state/queries/notifications/unread.tsx
index b5f7d0d60b..7bb325ea98 100644
--- a/src/state/queries/notifications/unread.tsx
+++ b/src/state/queries/notifications/unread.tsx
@@ -8,7 +8,6 @@ import {useQueryClient} from '@tanstack/react-query'
import EventEmitter from 'eventemitter3'
import BroadcastChannel from '#/lib/broadcast'
-import {useGate} from '#/lib/statsig/statsig'
import {logger} from '#/logger'
import {useAgent, useSession} from '#/state/session'
import {resetBadgeCount} from 'lib/notifications/notifications'
@@ -48,7 +47,6 @@ export function Provider({children}: React.PropsWithChildren<{}>) {
const agent = useAgent()
const queryClient = useQueryClient()
const moderationOpts = useModerationOpts()
- const gate = useGate()
const [numUnread, setNumUnread] = React.useState('')
@@ -151,7 +149,6 @@ export function Provider({children}: React.PropsWithChildren<{}>) {
// only fetch subjects when the page is going to be used
// in the notifications query, otherwise skip it
fetchAdditionalData: !!invalidate,
- shouldUngroupFollowBacks: () => gate('ungroup_follow_backs'),
})
const unreadCount = countUnread(page)
const unreadCountStr =
@@ -192,7 +189,7 @@ export function Provider({children}: React.PropsWithChildren<{}>) {
}
},
}
- }, [setNumUnread, queryClient, moderationOpts, agent, gate])
+ }, [setNumUnread, queryClient, moderationOpts, agent])
checkUnreadRef.current = api.checkUnread
return (
diff --git a/src/state/queries/notifications/util.ts b/src/state/queries/notifications/util.ts
index 7651e414a4..e0ee02294e 100644
--- a/src/state/queries/notifications/util.ts
+++ b/src/state/queries/notifications/util.ts
@@ -30,7 +30,6 @@ export async function fetchPage({
queryClient,
moderationOpts,
fetchAdditionalData,
- shouldUngroupFollowBacks,
}: {
agent: BskyAgent
cursor: string | undefined
@@ -38,7 +37,6 @@ export async function fetchPage({
queryClient: QueryClient
moderationOpts: ModerationOpts | undefined
fetchAdditionalData: boolean
- shouldUngroupFollowBacks?: () => boolean
priority?: boolean
}): Promise<{
page: FeedPage
@@ -58,7 +56,7 @@ export async function fetchPage({
)
// group notifications which are essentially similar (follows, likes on a post)
- let notifsGrouped = groupNotifications(notifs, {shouldUngroupFollowBacks})
+ let notifsGrouped = groupNotifications(notifs)
// we fetch subjects of notifications (usually posts) now instead of lazily
// in the UI to avoid relayouts
@@ -117,7 +115,6 @@ export function shouldFilterNotif(
export function groupNotifications(
notifs: AppBskyNotificationListNotifications.Notification[],
- options?: {shouldUngroupFollowBacks?: () => boolean},
): FeedNotification[] {
const groupedNotifs: FeedNotification[] = []
for (const notif of notifs) {
@@ -137,9 +134,7 @@ export function groupNotifications(
const prevIsFollowBack =
groupedNotif.notification.reason === 'follow' &&
groupedNotif.notification.author.viewer?.following
- const shouldUngroup =
- (nextIsFollowBack || prevIsFollowBack) &&
- options?.shouldUngroupFollowBacks?.()
+ const shouldUngroup = nextIsFollowBack || prevIsFollowBack
if (!shouldUngroup) {
groupedNotif.additional = groupedNotif.additional || []
groupedNotif.additional.push(notif)
diff --git a/src/state/queries/post-thread.ts b/src/state/queries/post-thread.ts
index c01b96ed81..fd419d1c44 100644
--- a/src/state/queries/post-thread.ts
+++ b/src/state/queries/post-thread.ts
@@ -137,6 +137,7 @@ export function sortThread(
opts: UsePreferencesQueryResponse['threadViewPrefs'],
modCache: ThreadModerationCache,
currentDid: string | undefined,
+ justPostedUris: Set,
): ThreadNode {
if (node.type !== 'post') {
return node
@@ -150,6 +151,20 @@ export function sortThread(
return -1
}
+ if (node.ctx.isHighlightedPost || opts.lab_treeViewEnabled) {
+ const aIsJustPosted =
+ a.post.author.did === currentDid && justPostedUris.has(a.post.uri)
+ const bIsJustPosted =
+ b.post.author.did === currentDid && justPostedUris.has(b.post.uri)
+ if (aIsJustPosted && bIsJustPosted) {
+ return a.post.indexedAt.localeCompare(b.post.indexedAt) // oldest
+ } else if (aIsJustPosted) {
+ return -1 // reply while onscreen
+ } else if (bIsJustPosted) {
+ return 1 // reply while onscreen
+ }
+ }
+
const aIsByOp = a.post.author.did === node.post?.author.did
const bIsByOp = b.post.author.did === node.post?.author.did
if (aIsByOp && bIsByOp) {
@@ -206,7 +221,9 @@ export function sortThread(
}
return b.post.indexedAt.localeCompare(a.post.indexedAt)
})
- node.replies.forEach(reply => sortThread(reply, opts, modCache, currentDid))
+ node.replies.forEach(reply =>
+ sortThread(reply, opts, modCache, currentDid, justPostedUris),
+ )
}
return node
}
diff --git a/src/state/queries/profile-lists.ts b/src/state/queries/profile-lists.ts
index 75e3dd6e48..03c983ff80 100644
--- a/src/state/queries/profile-lists.ts
+++ b/src/state/queries/profile-lists.ts
@@ -40,18 +40,10 @@ export function useProfileListsQuery(did: string, opts?: {enabled?: boolean}) {
pages: data.pages.map(page => {
return {
...page,
- lists: page.lists
- /*
- * Starter packs use a reference list, which we do not want to
- * show on profiles. At some point we could probably just filter
- * this out on the backend instead of in the client.
- */
- .filter(l => l.purpose !== 'app.bsky.graph.defs#referencelist')
- // filter by labels
- .filter(list => {
- const decision = moderateUserList(list, moderationOpts!)
- return !decision.ui('contentList').filter
- }),
+ lists: page.lists.filter(list => {
+ const decision = moderateUserList(list, moderationOpts!)
+ return !decision.ui('contentList').filter
+ }),
}
}),
}
diff --git a/src/state/queries/profile.ts b/src/state/queries/profile.ts
index 1f866d26d2..6682cf3c89 100644
--- a/src/state/queries/profile.ts
+++ b/src/state/queries/profile.ts
@@ -222,6 +222,7 @@ export function useProfileFollowMutationQueue(
logContext: LogEvents['profile:follow']['logContext'] &
LogEvents['profile:unfollow']['logContext'],
) {
+ const agent = useAgent()
const queryClient = useQueryClient()
const did = profile.did
const initialFollowingUri = profile.viewer?.following
@@ -253,6 +254,20 @@ export function useProfileFollowMutationQueue(
updateProfileShadow(queryClient, did, {
followingUri: finalFollowingUri,
})
+
+ if (finalFollowingUri) {
+ agent.app.bsky.graph
+ .getSuggestedFollowsByActor({
+ actor: did,
+ })
+ .then(res => {
+ const dids = res.data.suggestions
+ .filter(a => !a.viewer?.following)
+ .map(a => a.did)
+ .slice(0, 8)
+ userActionHistory.followSuggestion(dids)
+ })
+ }
},
})
diff --git a/src/state/queries/suggested-follows.ts b/src/state/queries/suggested-follows.ts
index a1244721a2..f5d51a974a 100644
--- a/src/state/queries/suggested-follows.ts
+++ b/src/state/queries/suggested-follows.ts
@@ -106,6 +106,7 @@ export function useSuggestedFollowsQuery(options?: SuggestedFollowsOptions) {
export function useSuggestedFollowsByActorQuery({did}: {did: string}) {
const agent = useAgent()
return useQuery({
+ gcTime: 0,
queryKey: suggestedFollowsByActorQueryKey(did),
queryFn: async () => {
const res = await agent.app.bsky.graph.getSuggestedFollowsByActor({
diff --git a/src/state/shell/composer.tsx b/src/state/shell/composer.tsx
index 5b4e505439..e28d6b4ac0 100644
--- a/src/state/shell/composer.tsx
+++ b/src/state/shell/composer.tsx
@@ -1,10 +1,11 @@
import React from 'react'
import {
+ AppBskyActorDefs,
AppBskyEmbedRecord,
AppBskyRichtextFacet,
ModerationDecision,
- AppBskyActorDefs,
} from '@atproto/api'
+
import {useNonReactiveCallback} from '#/lib/hooks/useNonReactiveCallback'
export interface ComposerOptsPostRef {
@@ -31,7 +32,7 @@ export interface ComposerOptsQuote {
}
export interface ComposerOpts {
replyTo?: ComposerOptsPostRef
- onPost?: () => void
+ onPost?: (postUri: string | undefined) => void
quote?: ComposerOptsQuote
mention?: string // handle of user to mention
openPicker?: (pos: DOMRect | undefined) => void
diff --git a/src/state/shell/progress-guide.tsx b/src/state/shell/progress-guide.tsx
index c9b42a263e..d64e9984f5 100644
--- a/src/state/shell/progress-guide.tsx
+++ b/src/state/shell/progress-guide.tsx
@@ -2,7 +2,6 @@ import React from 'react'
import {msg} from '@lingui/macro'
import {useLingui} from '@lingui/react'
-import {useGate} from '#/lib/statsig/statsig'
import {
ProgressGuideToast,
ProgressGuideToastRef,
@@ -61,7 +60,6 @@ export function Provider({children}: React.PropsWithChildren<{}>) {
const {data: preferences} = usePreferencesQuery()
const {mutateAsync, variables, isPending} =
useSetActiveProgressGuideMutation()
- const gate = useGate()
const activeProgressGuide = (
isPending ? variables : preferences?.bskyAppState?.activeProgressGuide
@@ -89,9 +87,6 @@ export function Provider({children}: React.PropsWithChildren<{}>) {
const controls = React.useMemo(() => {
return {
startProgressGuide(guide: ProgressGuideName) {
- if (!gate('new_user_progress_guide')) {
- return
- }
if (guide === 'like-10-and-follow-7') {
const guideObj = {
guide: 'like-10-and-follow-7',
@@ -148,7 +143,7 @@ export function Provider({children}: React.PropsWithChildren<{}>) {
mutateAsync(guide?.isComplete ? undefined : guide)
},
}
- }, [activeProgressGuide, mutateAsync, gate, setLocalGuideState])
+ }, [activeProgressGuide, mutateAsync, setLocalGuideState])
return (
diff --git a/src/state/userActionHistory.ts b/src/state/userActionHistory.ts
index d82b3723a4..8ffe7241e6 100644
--- a/src/state/userActionHistory.ts
+++ b/src/state/userActionHistory.ts
@@ -2,6 +2,7 @@ import React from 'react'
const LIKE_WINDOW = 100
const FOLLOW_WINDOW = 100
+const FOLLOW_SUGGESTION_WINDOW = 100
const SEEN_WINDOW = 100
export type SeenPost = {
@@ -22,6 +23,10 @@ export type UserActionHistory = {
* The last 100 DIDs the user has followed
*/
follows: string[]
+ /*
+ * The last 100 DIDs of suggested follows based on last follows
+ */
+ followSuggestions: string[]
/**
* The last 100 post URIs the user has seen from the Discover feed only
*/
@@ -31,6 +36,7 @@ export type UserActionHistory = {
const userActionHistory: UserActionHistory = {
likes: [],
follows: [],
+ followSuggestions: [],
seen: [],
}
@@ -58,6 +64,13 @@ export function follow(dids: string[]) {
.concat(dids)
.slice(-FOLLOW_WINDOW)
}
+
+export function followSuggestion(dids: string[]) {
+ userActionHistory.followSuggestions = userActionHistory.followSuggestions
+ .concat(dids)
+ .slice(-FOLLOW_SUGGESTION_WINDOW)
+}
+
export function unfollow(dids: string[]) {
userActionHistory.follows = userActionHistory.follows.filter(
uri => !dids.includes(uri),
diff --git a/src/view/com/auth/LoggedOut.tsx b/src/view/com/auth/LoggedOut.tsx
index cc71f648e9..cc57238053 100644
--- a/src/view/com/auth/LoggedOut.tsx
+++ b/src/view/com/auth/LoggedOut.tsx
@@ -1,25 +1,20 @@
import React from 'react'
import {Pressable, View} from 'react-native'
import {FontAwesomeIcon} from '@fortawesome/react-native-fontawesome'
-import {msg, Trans} from '@lingui/macro'
+import {msg} from '@lingui/macro'
import {useLingui} from '@lingui/react'
-import {useNavigation} from '@react-navigation/native'
import {useAnalytics} from '#/lib/analytics/analytics'
import {usePalette} from '#/lib/hooks/usePalette'
import {logEvent} from '#/lib/statsig/statsig'
import {s} from '#/lib/styles'
-import {isIOS, isNative} from '#/platform/detection'
-import {useSession} from '#/state/session'
+import {isIOS} from '#/platform/detection'
import {
useLoggedOutView,
useLoggedOutViewControls,
} from '#/state/shell/logged-out'
import {useSetMinimalShellMode} from '#/state/shell/minimal-mode'
-import {NavigationProp} from 'lib/routes/types'
-import {useGate} from 'lib/statsig/statsig'
import {ErrorBoundary} from '#/view/com/util/ErrorBoundary'
-import {Text} from '#/view/com/util/text/Text'
import {Login} from '#/screens/Login'
import {Signup} from '#/screens/Signup'
import {LandingScreen} from '#/screens/StarterPack/StarterPackLandingScreen'
@@ -34,7 +29,6 @@ enum ScreenState {
export {ScreenState as LoggedOutScreenState}
export function LoggedOut({onDismiss}: {onDismiss?: () => void}) {
- const {hasSession} = useSession()
const {_} = useLingui()
const pal = usePalette('default')
const setMinimalShellMode = useSetMinimalShellMode()
@@ -52,10 +46,7 @@ export function LoggedOut({onDismiss}: {onDismiss?: () => void}) {
}
})
const {clearRequestedAccount} = useLoggedOutViewControls()
- const navigation = useNavigation()
- const gate = useGate()
- const isFirstScreen = screenState === ScreenState.S_LoginOrCreateAccount
React.useEffect(() => {
screen('Login')
setMinimalShellMode(true)
@@ -68,10 +59,6 @@ export function LoggedOut({onDismiss}: {onDismiss?: () => void}) {
clearRequestedAccount()
}, [clearRequestedAccount, onDismiss])
- const onPressSearch = React.useCallback(() => {
- navigation.navigate(`SearchTab`)
- }, [navigation])
-
return (
@@ -98,39 +85,6 @@ export function LoggedOut({onDismiss}: {onDismiss?: () => void}) {
}}
/>
- ) : isNative &&
- !hasSession &&
- isFirstScreen &&
- !gate('native_pwi_disabled') ? (
-
-
- Search{' '}
-
-
-
) : null}
{screenState === ScreenState.S_StarterPack ? (
diff --git a/src/view/com/composer/Composer.tsx b/src/view/com/composer/Composer.tsx
index 08ce4441f0..dba37d82bf 100644
--- a/src/view/com/composer/Composer.tsx
+++ b/src/view/com/composer/Composer.tsx
@@ -392,7 +392,7 @@ export const ComposePost = observer(function ComposePost({
emitPostCreated()
}
setLangPrefs.savePostLanguageToHistory()
- onPost?.()
+ onPost?.(postUri)
onClose()
Toast.show(
replyTo
diff --git a/src/view/com/composer/ComposerReplyTo.tsx b/src/view/com/composer/ComposerReplyTo.tsx
index 6b38caff03..d4ba1f3a86 100644
--- a/src/view/com/composer/ComposerReplyTo.tsx
+++ b/src/view/com/composer/ComposerReplyTo.tsx
@@ -91,7 +91,7 @@ export function ComposerReplyTo({replyTo}: {replyTo: ComposerOptsPostRef}) {
type={replyTo.author.associated?.labeler ? 'labeler' : 'user'}
/>
-
+
{sanitizeDisplayName(
replyTo.author.displayName || sanitizeHandle(replyTo.author.handle),
)}
diff --git a/src/view/com/notifications/FeedItem.tsx b/src/view/com/notifications/FeedItem.tsx
index eac9c3ad10..5ecefa8c26 100644
--- a/src/view/com/notifications/FeedItem.tsx
+++ b/src/view/com/notifications/FeedItem.tsx
@@ -25,7 +25,6 @@ import {useLingui} from '@lingui/react'
import {useNavigation} from '@react-navigation/native'
import {useQueryClient} from '@tanstack/react-query'
-import {useGate} from '#/lib/statsig/statsig'
import {parseTenorGif} from '#/lib/strings/embed-player'
import {logger} from '#/logger'
import {FeedNotification} from '#/state/queries/notifications/feed'
@@ -87,7 +86,6 @@ let FeedItem = ({
const pal = usePalette('default')
const {_} = useLingui()
const t = useTheme()
- const gate = useGate()
const [isAuthorsExpanded, setAuthorsExpanded] = useState(false)
const itemHref = useMemo(() => {
if (item.type === 'post-like' || item.type === 'repost') {
@@ -275,7 +273,7 @@ let FeedItem = ({
}
}
- if (isFollowBack && gate('ungroup_follow_backs')) {
+ if (isFollowBack) {
a11yLabel =
authors.length > 1
? _(
@@ -404,6 +402,7 @@ let FeedItem = ({
borderColor: pal.colors.unreadNotifBorder,
},
{borderTopWidth: hideTopBorder ? 0 : StyleSheet.hairlineWidth},
+ a.overflow_hidden,
]}
href={itemHref}
noFeedback
@@ -676,7 +675,7 @@ function ExpandedAuthorsList({
}, [heightInterp, visible])
return (
-
+
{visible &&
authors.map(author => (
{
return item._reactKey
}
-export function PostThread({
- uri,
- onCanReply,
- onPressReply,
-}: {
- uri: string | undefined
- onCanReply: (canReply: boolean) => void
- onPressReply: () => unknown
-}) {
+export function PostThread({uri}: {uri: string | undefined}) {
const {hasSession, currentAccount} = useSession()
const {_} = useLingui()
const t = useTheme()
@@ -163,12 +160,22 @@ export function PostThread({
return cache
}, [thread, moderationOpts])
+ const [justPostedUris, setJustPostedUris] = React.useState(
+ () => new Set(),
+ )
+
const skeleton = React.useMemo(() => {
const threadViewPrefs = preferences?.threadViewPrefs
if (!threadViewPrefs || !thread) return null
return createThreadSkeleton(
- sortThread(thread, threadViewPrefs, threadModerationCache, currentDid),
+ sortThread(
+ thread,
+ threadViewPrefs,
+ threadModerationCache,
+ currentDid,
+ justPostedUris,
+ ),
!!currentDid,
treeView,
threadModerationCache,
@@ -181,6 +188,7 @@ export function PostThread({
treeView,
threadModerationCache,
hiddenRepliesState,
+ justPostedUris,
])
const error = React.useMemo(() => {
@@ -210,14 +218,6 @@ export function PostThread({
return null
}, [thread, skeleton?.highlightedPost, isThreadError, _, threadError])
- useEffect(() => {
- if (error) {
- onCanReply(false)
- } else if (rootPost) {
- onCanReply(!rootPost.viewer?.replyDisabled)
- }
- }, [rootPost, onCanReply, error])
-
// construct content
const posts = React.useMemo(() => {
if (!skeleton) return []
@@ -313,6 +313,38 @@ export function PostThread({
setMaxReplies(prev => prev + 50)
}, [isFetching, maxReplies, posts.length])
+ const onPostReply = React.useCallback(
+ (postUri: string | undefined) => {
+ refetch()
+ if (postUri) {
+ setJustPostedUris(set => {
+ const nextSet = new Set(set)
+ nextSet.add(postUri)
+ return nextSet
+ })
+ }
+ },
+ [refetch],
+ )
+
+ const {openComposer} = useComposerControls()
+ const onPressReply = React.useCallback(() => {
+ if (thread?.type !== 'post') {
+ return
+ }
+ openComposer({
+ replyTo: {
+ uri: thread.post.uri,
+ cid: thread.post.cid,
+ text: thread.record.text,
+ author: thread.post.author,
+ embed: thread.post.embed,
+ },
+ onPost: onPostReply,
+ })
+ }, [openComposer, thread, onPostReply])
+
+ const canReply = !error && rootPost && !rootPost.viewer?.replyDisabled
const hasParents =
skeleton?.highlightedPost?.type === 'post' &&
(skeleton.highlightedPost.ctx.isParentLoading ||
@@ -324,7 +356,9 @@ export function PostThread({
if (item === REPLY_PROMPT && hasSession) {
return (
- {!isMobile && }
+ {!isMobile && (
+
+ )}
)
} else if (item === SHOW_HIDDEN_REPLIES || item === SHOW_MUTED_REPLIES) {
@@ -406,7 +440,7 @@ export function PostThread({
HiddenRepliesState.ShowAndOverridePostHider &&
item.ctx.depth > 0
}
- onPostReply={refetch}
+ onPostReply={onPostReply}
hideTopBorder={index === 0 && !item.ctx.isParentLoading}
/>
@@ -473,10 +507,30 @@ export function PostThread({
sideBorders={false}
/>
+ {isMobile && canReply && hasSession && (
+
+ )}
)
}
+function MobileComposePrompt({onPressReply}: {onPressReply: () => unknown}) {
+ const safeAreaInsets = useSafeAreaInsets()
+ const fabMinimalShellTransform = useMinimalShellFabTransform()
+ return (
+
+
+
+ )
+}
+
function isThreadPost(v: unknown): v is ThreadPost {
return !!v && typeof v === 'object' && 'type' in v && v.type === 'post'
}
@@ -622,3 +676,12 @@ function hasBranchingReplies(node?: ThreadNode) {
}
return true
}
+
+const styles = StyleSheet.create({
+ prompt: {
+ // @ts-ignore web-only
+ position: isWeb ? 'fixed' : 'absolute',
+ left: 0,
+ right: 0,
+ },
+})
diff --git a/src/view/com/composer/Prompt.tsx b/src/view/com/post-thread/PostThreadComposePrompt.tsx
similarity index 94%
rename from src/view/com/composer/Prompt.tsx
rename to src/view/com/post-thread/PostThreadComposePrompt.tsx
index 20637c7e9f..62b28cc759 100644
--- a/src/view/com/composer/Prompt.tsx
+++ b/src/view/com/post-thread/PostThreadComposePrompt.tsx
@@ -10,7 +10,11 @@ import {useWebMediaQueries} from 'lib/hooks/useWebMediaQueries'
import {Text} from '../util/text/Text'
import {UserAvatar} from '../util/UserAvatar'
-export function ComposePrompt({onPressCompose}: {onPressCompose: () => void}) {
+export function PostThreadComposePrompt({
+ onPressCompose,
+}: {
+ onPressCompose: () => void
+}) {
const {currentAccount} = useSession()
const {data: profile} = useProfileQuery({did: currentAccount?.did})
const pal = usePalette('default')
diff --git a/src/view/com/post-thread/PostThreadItem.tsx b/src/view/com/post-thread/PostThreadItem.tsx
index 63dac300a8..8adbb17e29 100644
--- a/src/view/com/post-thread/PostThreadItem.tsx
+++ b/src/view/com/post-thread/PostThreadItem.tsx
@@ -75,7 +75,7 @@ export function PostThreadItem({
showParentReplyLine?: boolean
hasPrecedingItem: boolean
overrideBlur: boolean
- onPostReply: () => void
+ onPostReply: (postUri: string | undefined) => void
hideTopBorder?: boolean
}) {
const postShadowed = usePostShadow(post)
@@ -169,7 +169,7 @@ let PostThreadItemLoaded = ({
showParentReplyLine?: boolean
hasPrecedingItem: boolean
overrideBlur: boolean
- onPostReply: () => void
+ onPostReply: (postUri: string | undefined) => void
hideTopBorder?: boolean
}): React.ReactNode => {
const pal = usePalette('default')
@@ -742,6 +742,7 @@ const styles = StyleSheet.create({
flexWrap: 'wrap',
paddingBottom: 4,
paddingRight: 10,
+ overflow: 'hidden',
},
postTextLargeContainer: {
paddingHorizontal: 0,
diff --git a/src/view/com/post/Post.tsx b/src/view/com/post/Post.tsx
index ade0e7f10f..8121b8abcc 100644
--- a/src/view/com/post/Post.tsx
+++ b/src/view/com/post/Post.tsx
@@ -12,17 +12,17 @@ import {msg, Trans} from '@lingui/macro'
import {useLingui} from '@lingui/react'
import {useQueryClient} from '@tanstack/react-query'
+import {MAX_POST_LINES} from '#/lib/constants'
+import {usePalette} from '#/lib/hooks/usePalette'
import {moderatePost_wrapped as moderatePost} from '#/lib/moderatePost_wrapped'
+import {makeProfileLink} from '#/lib/routes/links'
+import {countLines} from '#/lib/strings/helpers'
+import {colors, s} from '#/lib/styles'
import {POST_TOMBSTONE, Shadow, usePostShadow} from '#/state/cache/post-shadow'
import {useModerationOpts} from '#/state/preferences/moderation-opts'
+import {precacheProfile} from '#/state/queries/profile'
import {useSession} from '#/state/session'
import {useComposerControls} from '#/state/shell/composer'
-import {MAX_POST_LINES} from 'lib/constants'
-import {usePalette} from 'lib/hooks/usePalette'
-import {makeProfileLink} from 'lib/routes/links'
-import {countLines} from 'lib/strings/helpers'
-import {colors, s} from 'lib/styles'
-import {precacheProfile} from 'state/queries/profile'
import {AviFollowButton} from '#/view/com/posts/AviFollowButton'
import {atoms as a} from '#/alf'
import {ProfileHoverCard} from '#/components/ProfileHoverCard'
@@ -280,6 +280,7 @@ const styles = StyleSheet.create({
flexDirection: 'row',
alignItems: 'center',
flexWrap: 'wrap',
+ overflow: 'hidden',
},
replyLine: {
position: 'absolute',
diff --git a/src/view/com/posts/AviFollowButton.tsx b/src/view/com/posts/AviFollowButton.tsx
index f7141ee421..00428cbe61 100644
--- a/src/view/com/posts/AviFollowButton.tsx
+++ b/src/view/com/posts/AviFollowButton.tsx
@@ -7,7 +7,6 @@ import {useNavigation} from '@react-navigation/native'
import {createHitslop} from '#/lib/constants'
import {NavigationProp} from '#/lib/routes/types'
-import {useGate} from '#/lib/statsig/statsig'
import {sanitizeDisplayName} from '#/lib/strings/display-names'
import {useProfileShadow} from '#/state/cache/profile-shadow'
import {useSession} from '#/state/session'
@@ -37,7 +36,6 @@ export function AviFollowButton({
profile: profile,
logContext: 'AvatarButton',
})
- const gate = useGate()
const {currentAccount, hasSession} = useSession()
const navigation = useNavigation()
@@ -80,7 +78,7 @@ export function AviFollowButton({
},
]
- return hasSession && gate('show_avi_follow_button') ? (
+ return hasSession ? (
{children}
diff --git a/src/view/com/posts/Feed.tsx b/src/view/com/posts/Feed.tsx
index ef46333193..54ea9b1400 100644
--- a/src/view/com/posts/Feed.tsx
+++ b/src/view/com/posts/Feed.tsx
@@ -349,8 +349,7 @@ let Feed = ({
const shouldShow =
(interstitial.type === feedInterstitialType &&
gate('suggested_feeds_interstitial')) ||
- (interstitial.type === followInterstitialType &&
- gate('suggested_follows_interstitial')) ||
+ interstitial.type === followInterstitialType ||
interstitial.type === progressGuideInterstitialType
if (shouldShow) {
diff --git a/src/view/com/posts/FeedItem.tsx b/src/view/com/posts/FeedItem.tsx
index 6660a8d9d6..8592f0bec2 100644
--- a/src/view/com/posts/FeedItem.tsx
+++ b/src/view/com/posts/FeedItem.tsx
@@ -544,6 +544,7 @@ const styles = StyleSheet.create({
alignItems: 'center',
flexWrap: 'wrap',
paddingBottom: 2,
+ overflow: 'hidden',
},
contentHiderChild: {
marginTop: 6,
diff --git a/src/view/com/profile/ProfileHeaderSuggestedFollows.tsx b/src/view/com/profile/ProfileHeaderSuggestedFollows.tsx
index c7df4d75be..356b3f09cf 100644
--- a/src/view/com/profile/ProfileHeaderSuggestedFollows.tsx
+++ b/src/view/com/profile/ProfileHeaderSuggestedFollows.tsx
@@ -1,32 +1,60 @@
import React from 'react'
-import {Pressable, ScrollView, StyleSheet, View} from 'react-native'
-import {AppBskyActorDefs, moderateProfile} from '@atproto/api'
-import {
- FontAwesomeIcon,
- FontAwesomeIconStyle,
-} from '@fortawesome/react-native-fontawesome'
+import {ScrollView, View} from 'react-native'
import {msg, Trans} from '@lingui/macro'
import {useLingui} from '@lingui/react'
-import {useProfileShadow} from '#/state/cache/profile-shadow'
+import {logEvent} from '#/lib/statsig/statsig'
import {useModerationOpts} from '#/state/preferences/moderation-opts'
-import {useProfileFollowMutationQueue} from '#/state/queries/profile'
import {useSuggestedFollowsByActorQuery} from '#/state/queries/suggested-follows'
-import {useAnalytics} from 'lib/analytics/analytics'
-import {usePalette} from 'lib/hooks/usePalette'
-import {makeProfileLink} from 'lib/routes/links'
-import {sanitizeDisplayName} from 'lib/strings/display-names'
-import {sanitizeHandle} from 'lib/strings/handles'
import {isWeb} from 'platform/detection'
-import {Button} from 'view/com/util/forms/Button'
-import {Link} from 'view/com/util/Link'
-import {Text} from 'view/com/util/text/Text'
-import {PreviewableUserAvatar} from 'view/com/util/UserAvatar'
-import * as Toast from '../util/Toast'
+import {atoms as a, useTheme, ViewStyleProp} from '#/alf'
+import {Button, ButtonIcon} from '#/components/Button'
+import {TimesLarge_Stroke2_Corner0_Rounded as X} from '#/components/icons/Times'
+import * as ProfileCard from '#/components/ProfileCard'
+import {Text} from '#/components/Typography'
-const OUTER_PADDING = 10
-const INNER_PADDING = 14
-const TOTAL_HEIGHT = 250
+const OUTER_PADDING = a.p_md.padding
+const INNER_PADDING = a.p_lg.padding
+const TOTAL_HEIGHT = 232
+const MOBILE_CARD_WIDTH = 300
+
+function CardOuter({
+ children,
+ style,
+}: {children: React.ReactNode | React.ReactNode[]} & ViewStyleProp) {
+ const t = useTheme()
+ return (
+
+ {children}
+
+ )
+}
+
+export function SuggestedFollowPlaceholder() {
+ const t = useTheme()
+ return (
+
+
+
+
+
+
+
+
+ )
+}
export function ProfileHeaderSuggestedFollows({
actorDid,
@@ -35,47 +63,55 @@ export function ProfileHeaderSuggestedFollows({
actorDid: string
requestDismiss: () => void
}) {
- const pal = usePalette('default')
- const {isLoading, data} = useSuggestedFollowsByActorQuery({
- did: actorDid,
- })
+ const t = useTheme()
+ const {_} = useLingui()
+ const {isLoading: isSuggestionsLoading, data} =
+ useSuggestedFollowsByActorQuery({
+ did: actorDid,
+ })
+ const moderationOpts = useModerationOpts()
+ const isLoading = isSuggestionsLoading || !moderationOpts
+
return (
+ style={[
+ t.atoms.bg_contrast_25,
+ {
+ height: '100%',
+ paddingTop: INNER_PADDING / 2,
+ },
+ ]}>
-
- Suggested for you
+ style={[
+ a.flex_row,
+ a.justify_between,
+ a.align_center,
+ a.pt_xs,
+ {
+ paddingBottom: INNER_PADDING / 2,
+ paddingLeft: INNER_PADDING,
+ paddingRight: INNER_PADDING / 2,
+ },
+ ]}>
+
+ Similar accounts
-
-
-
+ label={_(msg`Dismiss`)}
+ size="xsmall"
+ variant="ghost"
+ color="secondary"
+ shape="round">
+
+
- {isLoading ? (
- <>
-
-
-
-
-
-
- >
- ) : data ? (
- data.suggestions
- .filter(s => (s.associated?.labeler ? false : true))
- .map(profile => (
-
- ))
- ) : (
-
- )}
+ snapToInterval={MOBILE_CARD_WIDTH + a.gap_sm.gap}
+ decelerationRate="fast">
+
+ {isLoading ? (
+ <>
+
+
+
+
+
+ >
+ ) : data ? (
+ data.suggestions
+ .filter(s => (s.associated?.labeler ? false : true))
+ .map(profile => (
+ {
+ logEvent('profile:header:suggestedFollowsCard:press', {})
+ }}
+ style={[a.flex_1]}>
+ {({hovered, pressed}) => (
+
+
+
+
+
+
+
+
+
+
+ )}
+
+ ))
+ ) : (
+
+ )}
+
)
}
-
-function SuggestedFollowSkeleton() {
- const pal = usePalette('default')
- return (
-
-
-
-
-
-
- )
-}
-
-function SuggestedFollow({
- profile: profileUnshadowed,
-}: {
- profile: AppBskyActorDefs.ProfileView
-}) {
- const {track} = useAnalytics()
- const pal = usePalette('default')
- const {_} = useLingui()
- const moderationOpts = useModerationOpts()
- const profile = useProfileShadow(profileUnshadowed)
- const [queueFollow, queueUnfollow] = useProfileFollowMutationQueue(
- profile,
- 'ProfileHeaderSuggestedFollows',
- )
-
- const onPressFollow = React.useCallback(async () => {
- try {
- track('ProfileHeader:SuggestedFollowFollowed')
- await queueFollow()
- } catch (e: any) {
- if (e?.name !== 'AbortError') {
- Toast.show(_(msg`An issue occurred, please try again.`), 'xmark')
- }
- }
- }, [queueFollow, track, _])
-
- const onPressUnfollow = React.useCallback(async () => {
- try {
- await queueUnfollow()
- } catch (e: any) {
- if (e?.name !== 'AbortError') {
- Toast.show(_(msg`An issue occurred, please try again.`), 'xmark')
- }
- }
- }, [queueUnfollow, _])
-
- if (!moderationOpts) {
- return null
- }
- const moderation = moderateProfile(profile, moderationOpts)
- const following = profile.viewer?.following
- return (
-
-
-
-
-
-
- {sanitizeDisplayName(
- profile.displayName || sanitizeHandle(profile.handle),
- moderation.ui('displayName'),
- )}
-
-
- {sanitizeHandle(profile.handle, '@')}
-
-
-
-
-
-
- )
-}
-
-const styles = StyleSheet.create({
- suggestedFollowCardOuter: {
- marginHorizontal: INNER_PADDING / 2,
- paddingTop: 10,
- paddingBottom: 12,
- paddingHorizontal: 10,
- borderRadius: 8,
- width: 130,
- alignItems: 'center',
- overflow: 'hidden',
- flexShrink: 1,
- },
-})
diff --git a/src/view/com/util/UserAvatar.tsx b/src/view/com/util/UserAvatar.tsx
index 8862bd0e4a..66c9708bfc 100644
--- a/src/view/com/util/UserAvatar.tsx
+++ b/src/view/com/util/UserAvatar.tsx
@@ -8,7 +8,6 @@ import {msg, Trans} from '@lingui/macro'
import {useLingui} from '@lingui/react'
import {useQueryClient} from '@tanstack/react-query'
-import {useGate} from '#/lib/statsig/statsig'
import {logger} from '#/logger'
import {usePalette} from 'lib/hooks/usePalette'
import {
@@ -179,7 +178,6 @@ let UserAvatar = ({
const pal = usePalette('default')
const backgroundColor = pal.colors.backgroundLight
const finalShape = overrideShape ?? (type === 'user' ? 'circle' : 'square')
- const gate = useGate()
const aviStyle = useMemo(() => {
if (finalShape === 'square') {
@@ -223,10 +221,7 @@ let UserAvatar = ({
style={aviStyle}
resizeMode="cover"
source={{
- uri: hackModifyThumbnailPath(
- avatar,
- size < 90 && gate('small_avi_thumb'),
- ),
+ uri: hackModifyThumbnailPath(avatar, size < 90),
}}
blurRadius={moderation?.blur ? BLUR_AMOUNT : 0}
/>
@@ -236,10 +231,7 @@ let UserAvatar = ({
style={aviStyle}
contentFit="cover"
source={{
- uri: hackModifyThumbnailPath(
- avatar,
- size < 90 && gate('small_avi_thumb'),
- ),
+ uri: hackModifyThumbnailPath(avatar, size < 90),
}}
blurRadius={moderation?.blur ? BLUR_AMOUNT : 0}
/>
diff --git a/src/view/screens/PostThread.tsx b/src/view/screens/PostThread.tsx
index 89234c46b8..88d0726c12 100644
--- a/src/view/screens/PostThread.tsx
+++ b/src/view/screens/PostThread.tsx
@@ -1,39 +1,19 @@
import React from 'react'
-import {StyleSheet, View} from 'react-native'
-import Animated from 'react-native-reanimated'
-import {useSafeAreaInsets} from 'react-native-safe-area-context'
+import {View} from 'react-native'
import {useFocusEffect} from '@react-navigation/native'
-import {useQueryClient} from '@tanstack/react-query'
-import {clamp} from 'lodash'
-import {isWeb} from '#/platform/detection'
-import {
- RQKEY as POST_THREAD_RQKEY,
- ThreadNode,
-} from '#/state/queries/post-thread'
-import {useSession} from '#/state/session'
import {useSetMinimalShellMode} from '#/state/shell'
-import {useComposerControls} from '#/state/shell/composer'
-import {useMinimalShellFabTransform} from 'lib/hooks/useMinimalShellTransform'
-import {useWebMediaQueries} from 'lib/hooks/useWebMediaQueries'
import {CommonNavigatorParams, NativeStackScreenProps} from 'lib/routes/types'
import {makeRecordUri} from 'lib/strings/url-helpers'
import {s} from 'lib/styles'
-import {ComposePrompt} from 'view/com/composer/Prompt'
import {PostThread as PostThreadComponent} from '../com/post-thread/PostThread'
type Props = NativeStackScreenProps
export function PostThreadScreen({route}: Props) {
- const queryClient = useQueryClient()
- const {hasSession} = useSession()
- const fabMinimalShellTransform = useMinimalShellFabTransform()
const setMinimalShellMode = useSetMinimalShellMode()
- const {openComposer} = useComposerControls()
- const safeAreaInsets = useSafeAreaInsets()
+
const {name, rkey} = route.params
- const {isMobile} = useWebMediaQueries()
const uri = makeRecordUri(name, 'app.bsky.feed.post', rkey)
- const [canReply, setCanReply] = React.useState(false)
useFocusEffect(
React.useCallback(() => {
@@ -41,59 +21,11 @@ export function PostThreadScreen({route}: Props) {
}, [setMinimalShellMode]),
)
- const onPressReply = React.useCallback(() => {
- if (!uri) {
- return
- }
- const thread = queryClient.getQueryData(POST_THREAD_RQKEY(uri))
- if (thread?.type !== 'post') {
- return
- }
- openComposer({
- replyTo: {
- uri: thread.post.uri,
- cid: thread.post.cid,
- text: thread.record.text,
- author: thread.post.author,
- embed: thread.post.embed,
- },
- onPost: () =>
- queryClient.invalidateQueries({
- queryKey: POST_THREAD_RQKEY(uri),
- }),
- })
- }, [openComposer, queryClient, uri])
-
return (
-
+
- {isMobile && canReply && hasSession && (
-
-
-
- )}
)
}
-
-const styles = StyleSheet.create({
- prompt: {
- // @ts-ignore web-only
- position: isWeb ? 'fixed' : 'absolute',
- left: 0,
- right: 0,
- },
-})
diff --git a/src/view/screens/Search/Explore.tsx b/src/view/screens/Search/Explore.tsx
index 5510fbee25..a36c404444 100644
--- a/src/view/screens/Search/Explore.tsx
+++ b/src/view/screens/Search/Explore.tsx
@@ -10,7 +10,6 @@ import {
import {msg, Trans} from '@lingui/macro'
import {useLingui} from '@lingui/react'
-import {useGate} from '#/lib/statsig/statsig'
import {logger} from '#/logger'
import {isWeb} from '#/platform/detection'
import {useModerationOpts} from '#/state/preferences/moderation-opts'
@@ -293,7 +292,6 @@ export function Explore() {
error: feedsError,
fetchNextPage: fetchNextFeedsPage,
} = useGetPopularFeedsQuery({limit: 10})
- const gate = useGate()
const isLoadingMoreProfiles = isFetchingNextProfilesPage && !isLoadingProfiles
const onLoadMoreProfiles = React.useCallback(async () => {
@@ -499,9 +497,7 @@ export function Explore() {
profile={item.profile}
noBg
noBorder
- showKnownFollowers={gate(
- 'explore_page_profile_card_social_proof',
- )}
+ showKnownFollowers
/>
)
@@ -565,7 +561,7 @@ export function Explore() {
}
}
},
- [t, moderationOpts, gate],
+ [t, moderationOpts],
)
return (
diff --git a/src/view/shell/createNativeStackNavigatorWithAuth.tsx b/src/view/shell/createNativeStackNavigatorWithAuth.tsx
index 203e7e5077..7951eef75b 100644
--- a/src/view/shell/createNativeStackNavigatorWithAuth.tsx
+++ b/src/view/shell/createNativeStackNavigatorWithAuth.tsx
@@ -29,7 +29,6 @@ import {
useLoggedOutView,
useLoggedOutViewControls,
} from '#/state/shell/logged-out'
-import {useGate} from 'lib/statsig/statsig'
import {isNative, isWeb} from 'platform/detection'
import {Deactivated} from '#/screens/Deactivated'
import {Onboarding} from '#/screens/Onboarding'
@@ -51,7 +50,6 @@ function NativeStackNavigator({
screenOptions,
...rest
}: NativeStackNavigatorProps) {
- const gate = useGate()
// --- this is copy and pasted from the original native stack navigator ---
const {state, descriptors, navigation, NavigationContent} =
useNavigationBuilder<
@@ -102,12 +100,7 @@ function NativeStackNavigator({
const {showLoggedOut} = useLoggedOutView()
const {setShowLoggedOut} = useLoggedOutViewControls()
const {isMobile, isTabletOrMobile} = useWebMediaQueries()
- if (
- !hasSession &&
- (!PWI_ENABLED ||
- activeRouteRequiresAuth ||
- (isNative && gate('native_pwi_disabled')))
- ) {
+ if (!hasSession && (!PWI_ENABLED || activeRouteRequiresAuth || isNative)) {
return
}
if (hasSession && currentAccount?.signupQueued) {