use an env var for configurable proxy header (#8863)

This commit is contained in:
hailey
2025-08-26 17:13:11 -07:00
committed by GitHub
parent 39c6984c6e
commit a1ed59e0ee
21 changed files with 108 additions and 41 deletions
+3
View File
@@ -16,6 +16,9 @@ EXPO_PUBLIC_LOG_LEVEL=debug
# Enable debug logs for specific logger instances # Enable debug logs for specific logger instances
EXPO_PUBLIC_LOG_DEBUG=session EXPO_PUBLIC_LOG_DEBUG=session
# Bluesky appview DID
EXPO_PUBLIC_BLUESKY_PROXY_DID=
# Chat service DID # Chat service DID
EXPO_PUBLIC_CHAT_PROXY_DID= EXPO_PUBLIC_CHAT_PROXY_DID=
+6
View File
@@ -62,6 +62,12 @@ export const LOG_LEVEL = (process.env.EXPO_PUBLIC_LOG_LEVEL || 'info') as
*/ */
export const LOG_DEBUG: string = process.env.EXPO_PUBLIC_LOG_DEBUG || '' export const LOG_DEBUG: string = process.env.EXPO_PUBLIC_LOG_DEBUG || ''
/**
* The DID of the Bluesky appview to proxy to
*/
export const BLUESKY_PROXY_DID: Did =
process.env.EXPO_PUBLIC_BLUESKY_PROXY_DID || 'did:web:api.bsky.app'
/** /**
* The DID of the chat service to proxy to * The DID of the chat service to proxy to
*/ */
+13
View File
@@ -1,6 +1,9 @@
import {type Insets, Platform} from 'react-native' import {type Insets, Platform} from 'react-native'
import {type AppBskyActorDefs} from '@atproto/api' import {type AppBskyActorDefs} from '@atproto/api'
import {type ProxyHeaderValue} from '#/state/session/agent'
import {BLUESKY_PROXY_DID, CHAT_PROXY_DID} from '#/env'
export const LOCAL_DEV_SERVICE = export const LOCAL_DEV_SERVICE =
Platform.OS === 'android' ? 'http://10.0.2.2:2583' : 'http://localhost:2583' Platform.OS === 'android' ? 'http://10.0.2.2:2583' : 'http://localhost:2583'
export const STAGING_SERVICE = 'https://staging.bsky.dev' export const STAGING_SERVICE = 'https://staging.bsky.dev'
@@ -211,6 +214,16 @@ export const PUBLIC_STAGING_APPVIEW_DID = 'did:web:api.staging.bsky.dev'
export const DEV_ENV_APPVIEW = `http://localhost:2584` // always the same export const DEV_ENV_APPVIEW = `http://localhost:2584` // always the same
export const BLUESKY_PROXY_HEADER: ProxyHeaderValue = `${BLUESKY_PROXY_DID}#bsky_appview`
export const BLUESKY_SERVICE_HEADERS = {
'atproto-proxy': BLUESKY_PROXY_HEADER,
}
export const DM_SERVICE_HEADERS = {
'atproto-proxy': `${CHAT_PROXY_DID}#bsky_chat`,
}
export const webLinks = { export const webLinks = {
tos: `https://bsky.social/about/support/tos`, tos: `https://bsky.social/about/support/tos`,
privacy: `https://bsky.social/about/support/privacy-policy`, privacy: `https://bsky.social/about/support/privacy-policy`,
+3 -3
View File
@@ -1,7 +1,6 @@
import React, {useState} from 'react' import React, {useState} from 'react'
import {ActivityIndicator, Keyboard, View} from 'react-native' import {ActivityIndicator, Keyboard, View} from 'react-native'
import {ComAtprotoServerDescribeServer} from '@atproto/api' import {type ComAtprotoServerDescribeServer} from '@atproto/api'
import {BskyAgent} from '@atproto/api'
import {msg, Trans} from '@lingui/macro' import {msg, Trans} from '@lingui/macro'
import {useLingui} from '@lingui/react' import {useLingui} from '@lingui/react'
import * as EmailValidator from 'email-validator' import * as EmailValidator from 'email-validator'
@@ -9,6 +8,7 @@ import * as EmailValidator from 'email-validator'
import {isNetworkError} from '#/lib/strings/errors' import {isNetworkError} from '#/lib/strings/errors'
import {cleanError} from '#/lib/strings/errors' import {cleanError} from '#/lib/strings/errors'
import {logger} from '#/logger' import {logger} from '#/logger'
import {Agent} from '#/state/session/agent'
import {atoms as a, useTheme} from '#/alf' import {atoms as a, useTheme} from '#/alf'
import {Button, ButtonText} from '#/components/Button' import {Button, ButtonText} from '#/components/Button'
import {FormError} from '#/components/forms/FormError' import {FormError} from '#/components/forms/FormError'
@@ -55,7 +55,7 @@ export const ForgotPasswordForm = ({
setIsProcessing(true) setIsProcessing(true)
try { try {
const agent = new BskyAgent({service: serviceUrl}) const agent = new Agent(null, {service: serviceUrl})
await agent.com.atproto.server.requestPasswordReset({email}) await agent.com.atproto.server.requestPasswordReset({email})
onEmailSent() onEmailSent()
} catch (e: any) { } catch (e: any) {
+2 -2
View File
@@ -1,6 +1,5 @@
import {useState} from 'react' import {useState} from 'react'
import {ActivityIndicator, View} from 'react-native' import {ActivityIndicator, View} from 'react-native'
import {BskyAgent} from '@atproto/api'
import {msg, Trans} from '@lingui/macro' import {msg, Trans} from '@lingui/macro'
import {useLingui} from '@lingui/react' import {useLingui} from '@lingui/react'
@@ -9,6 +8,7 @@ import {isNetworkError} from '#/lib/strings/errors'
import {cleanError} from '#/lib/strings/errors' import {cleanError} from '#/lib/strings/errors'
import {checkAndFormatResetCode} from '#/lib/strings/password' import {checkAndFormatResetCode} from '#/lib/strings/password'
import {logger} from '#/logger' import {logger} from '#/logger'
import {Agent} from '#/state/session/agent'
import {atoms as a, useTheme} from '#/alf' import {atoms as a, useTheme} from '#/alf'
import {Button, ButtonText} from '#/components/Button' import {Button, ButtonText} from '#/components/Button'
import {FormError} from '#/components/forms/FormError' import {FormError} from '#/components/forms/FormError'
@@ -63,7 +63,7 @@ export const SetNewPasswordForm = ({
setIsProcessing(true) setIsProcessing(true)
try { try {
const agent = new BskyAgent({service: serviceUrl}) const agent = new Agent(null, {service: serviceUrl})
await agent.com.atproto.server.resetPassword({ await agent.com.atproto.server.resetPassword({
token: formattedCode, token: formattedCode,
password, password,
+1 -1
View File
@@ -10,6 +10,7 @@ import EventEmitter from 'eventemitter3'
import {nanoid} from 'nanoid/non-secure' import {nanoid} from 'nanoid/non-secure'
import {networkRetry} from '#/lib/async/retry' import {networkRetry} from '#/lib/async/retry'
import {DM_SERVICE_HEADERS} from '#/lib/constants'
import {isNetworkError} from '#/lib/strings/errors' import {isNetworkError} from '#/lib/strings/errors'
import {Logger} from '#/logger' import {Logger} from '#/logger'
import {isNative} from '#/platform/detection' import {isNative} from '#/platform/detection'
@@ -33,7 +34,6 @@ import {
} from '#/state/messages/convo/types' } from '#/state/messages/convo/types'
import {type MessagesEventBus} from '#/state/messages/events/agent' import {type MessagesEventBus} from '#/state/messages/events/agent'
import {type MessagesEventBusError} from '#/state/messages/events/types' import {type MessagesEventBusError} from '#/state/messages/events/types'
import {DM_SERVICE_HEADERS} from '#/state/queries/messages/const'
const logger = Logger.create(Logger.Context.ConversationAgent) const logger = Logger.create(Logger.Context.ConversationAgent)
+1 -1
View File
@@ -3,6 +3,7 @@ import EventEmitter from 'eventemitter3'
import {nanoid} from 'nanoid/non-secure' import {nanoid} from 'nanoid/non-secure'
import {networkRetry} from '#/lib/async/retry' import {networkRetry} from '#/lib/async/retry'
import {DM_SERVICE_HEADERS} from '#/lib/constants'
import {isNetworkError} from '#/lib/strings/errors' import {isNetworkError} from '#/lib/strings/errors'
import {Logger} from '#/logger' import {Logger} from '#/logger'
import { import {
@@ -17,7 +18,6 @@ import {
type MessagesEventBusParams, type MessagesEventBusParams,
MessagesEventBusStatus, MessagesEventBusStatus,
} from '#/state/messages/events/types' } from '#/state/messages/events/types'
import {DM_SERVICE_HEADERS} from '#/state/queries/messages/const'
const logger = Logger.create(Logger.Context.DMsAgent) const logger = Logger.create(Logger.Context.DMsAgent)
+4 -3
View File
@@ -1,4 +1,4 @@
import {Agent, ComAtprotoTempCheckHandleAvailability} from '@atproto/api' import {ComAtprotoTempCheckHandleAvailability} from '@atproto/api'
import {useQuery} from '@tanstack/react-query' import {useQuery} from '@tanstack/react-query'
import { import {
@@ -10,6 +10,7 @@ import {createFullHandle} from '#/lib/strings/handles'
import {logger} from '#/logger' import {logger} from '#/logger'
import {useDebouncedValue} from '#/components/live/utils' import {useDebouncedValue} from '#/components/live/utils'
import * as bsky from '#/types/bsky' import * as bsky from '#/types/bsky'
import {Agent} from '../session/agent'
export const RQKEY_handleAvailability = ( export const RQKEY_handleAvailability = (
handle: string, handle: string,
@@ -74,7 +75,7 @@ export async function checkHandleAvailability(
}, },
) { ) {
if (serviceDid === BSKY_SERVICE_DID) { if (serviceDid === BSKY_SERVICE_DID) {
const agent = new Agent({service: BSKY_SERVICE}) const agent = new Agent(null, {service: BSKY_SERVICE})
// entryway has a special API for handle availability // entryway has a special API for handle availability
const {data} = await agent.com.atproto.temp.checkHandleAvailability({ const {data} = await agent.com.atproto.temp.checkHandleAvailability({
handle, handle,
@@ -109,7 +110,7 @@ export async function checkHandleAvailability(
} }
} else { } else {
// 3rd party PDSes won't have this API so just try and resolve the handle // 3rd party PDSes won't have this API so just try and resolve the handle
const agent = new Agent({service: PUBLIC_BSKY_SERVICE}) const agent = new Agent(null, {service: PUBLIC_BSKY_SERVICE})
try { try {
const res = await agent.resolveHandle({ const res = await agent.resolveHandle({
handle, handle,
@@ -1,9 +1,12 @@
import {ChatBskyConvoAcceptConvo, ChatBskyConvoListConvos} from '@atproto/api' import {
type ChatBskyConvoAcceptConvo,
type ChatBskyConvoListConvos,
} from '@atproto/api'
import {useMutation, useQueryClient} from '@tanstack/react-query' import {useMutation, useQueryClient} from '@tanstack/react-query'
import {DM_SERVICE_HEADERS} from '#/lib/constants'
import {logger} from '#/logger' import {logger} from '#/logger'
import {useAgent} from '#/state/session' import {useAgent} from '#/state/session'
import {DM_SERVICE_HEADERS} from './const'
import { import {
RQKEY as CONVO_LIST_KEY, RQKEY as CONVO_LIST_KEY,
RQKEY_ROOT as CONVO_LIST_ROOT_KEY, RQKEY_ROOT as CONVO_LIST_ROOT_KEY,
-5
View File
@@ -1,5 +0,0 @@
import {CHAT_PROXY_DID} from '#/env'
export const DM_SERVICE_HEADERS = {
'atproto-proxy': `${CHAT_PROXY_DID}#bsky_chat`,
}
+4 -4
View File
@@ -1,17 +1,17 @@
import {ChatBskyConvoDefs} from '@atproto/api' import {type ChatBskyConvoDefs} from '@atproto/api'
import { import {
QueryClient, type QueryClient,
useMutation, useMutation,
useQuery, useQuery,
useQueryClient, useQueryClient,
} from '@tanstack/react-query' } from '@tanstack/react-query'
import {DM_SERVICE_HEADERS} from '#/lib/constants'
import {STALE} from '#/state/queries' import {STALE} from '#/state/queries'
import {DM_SERVICE_HEADERS} from '#/state/queries/messages/const'
import {useOnMarkAsRead} from '#/state/queries/messages/list-conversations' import {useOnMarkAsRead} from '#/state/queries/messages/list-conversations'
import {useAgent} from '#/state/session' import {useAgent} from '#/state/session'
import { import {
ConvoListQueryData, type ConvoListQueryData,
getConvoFromQueryData, getConvoFromQueryData,
RQKEY_ROOT as LIST_CONVOS_KEY, RQKEY_ROOT as LIST_CONVOS_KEY,
} from './list-conversations' } from './list-conversations'
@@ -1,6 +1,6 @@
import {useQuery} from '@tanstack/react-query' import {useQuery} from '@tanstack/react-query'
import {DM_SERVICE_HEADERS} from '#/state/queries/messages/const' import {DM_SERVICE_HEADERS} from '#/lib/constants'
import {useAgent} from '#/state/session' import {useAgent} from '#/state/session'
import {STALE} from '..' import {STALE} from '..'
@@ -1,8 +1,8 @@
import {ChatBskyConvoGetConvoForMembers} from '@atproto/api' import {type ChatBskyConvoGetConvoForMembers} from '@atproto/api'
import {useMutation, useQueryClient} from '@tanstack/react-query' import {useMutation, useQueryClient} from '@tanstack/react-query'
import {DM_SERVICE_HEADERS} from '#/lib/constants'
import {logger} from '#/logger' import {logger} from '#/logger'
import {DM_SERVICE_HEADERS} from '#/state/queries/messages/const'
import {useAgent} from '#/state/session' import {useAgent} from '#/state/session'
import {precacheConvoQuery} from './conversation' import {precacheConvoQuery} from './conversation'
@@ -1,13 +1,16 @@
import {useMemo} from 'react' import {useMemo} from 'react'
import {ChatBskyConvoLeaveConvo, ChatBskyConvoListConvos} from '@atproto/api' import {
type ChatBskyConvoLeaveConvo,
type ChatBskyConvoListConvos,
} from '@atproto/api'
import { import {
useMutation, useMutation,
useMutationState, useMutationState,
useQueryClient, useQueryClient,
} from '@tanstack/react-query' } from '@tanstack/react-query'
import {DM_SERVICE_HEADERS} from '#/lib/constants'
import {logger} from '#/logger' import {logger} from '#/logger'
import {DM_SERVICE_HEADERS} from '#/state/queries/messages/const'
import {useAgent} from '#/state/session' import {useAgent} from '#/state/session'
import {RQKEY_ROOT as CONVO_LIST_KEY} from './list-conversations' import {RQKEY_ROOT as CONVO_LIST_KEY} from './list-conversations'
@@ -13,10 +13,10 @@ import {
} from '@tanstack/react-query' } from '@tanstack/react-query'
import throttle from 'lodash.throttle' import throttle from 'lodash.throttle'
import {DM_SERVICE_HEADERS} from '#/lib/constants'
import {useCurrentConvoId} from '#/state/messages/current-convo-id' import {useCurrentConvoId} from '#/state/messages/current-convo-id'
import {useMessagesEventBus} from '#/state/messages/events' import {useMessagesEventBus} from '#/state/messages/events'
import {useModerationOpts} from '#/state/preferences/moderation-opts' import {useModerationOpts} from '#/state/preferences/moderation-opts'
import {DM_SERVICE_HEADERS} from '#/state/queries/messages/const'
import {useAgent, useSession} from '#/state/session' import {useAgent, useSession} from '#/state/session'
import {useLeftConvos} from './leave-conversation' import {useLeftConvos} from './leave-conversation'
@@ -1,11 +1,15 @@
import { import {
ChatBskyConvoDefs, type ChatBskyConvoDefs,
ChatBskyConvoListConvos, type ChatBskyConvoListConvos,
ChatBskyConvoMuteConvo, type ChatBskyConvoMuteConvo,
} from '@atproto/api' } from '@atproto/api'
import {InfiniteData, useMutation, useQueryClient} from '@tanstack/react-query' import {
type InfiniteData,
useMutation,
useQueryClient,
} from '@tanstack/react-query'
import {DM_SERVICE_HEADERS} from '#/state/queries/messages/const' import {DM_SERVICE_HEADERS} from '#/lib/constants'
import {useAgent} from '#/state/session' import {useAgent} from '#/state/session'
import {RQKEY as CONVO_KEY} from './conversation' import {RQKEY as CONVO_KEY} from './conversation'
import {RQKEY_ROOT as CONVO_LIST_KEY} from './list-conversations' import {RQKEY_ROOT as CONVO_LIST_KEY} from './list-conversations'
@@ -1,8 +1,8 @@
import {ChatBskyConvoListConvos} from '@atproto/api' import {type ChatBskyConvoListConvos} from '@atproto/api'
import {useMutation, useQueryClient} from '@tanstack/react-query' import {useMutation, useQueryClient} from '@tanstack/react-query'
import {DM_SERVICE_HEADERS} from '#/lib/constants'
import {logger} from '#/logger' import {logger} from '#/logger'
import {DM_SERVICE_HEADERS} from '#/state/queries/messages/const'
import {useAgent} from '#/state/session' import {useAgent} from '#/state/session'
import {RQKEY as CONVO_LIST_KEY} from './list-conversations' import {RQKEY as CONVO_LIST_KEY} from './list-conversations'
+3 -2
View File
@@ -1,6 +1,7 @@
import {BskyAgent} from '@atproto/api'
import {useQuery} from '@tanstack/react-query' import {useQuery} from '@tanstack/react-query'
import {Agent} from '../session/agent'
const RQKEY_ROOT = 'service' const RQKEY_ROOT = 'service'
export const RQKEY = (serviceUrl: string) => [RQKEY_ROOT, serviceUrl] export const RQKEY = (serviceUrl: string) => [RQKEY_ROOT, serviceUrl]
@@ -8,7 +9,7 @@ export function useServiceQuery(serviceUrl: string) {
return useQuery({ return useQuery({
queryKey: RQKEY(serviceUrl), queryKey: RQKEY(serviceUrl),
queryFn: async () => { queryFn: async () => {
const agent = new BskyAgent({service: serviceUrl}) const agent = new Agent(null, {service: serviceUrl})
const res = await agent.com.atproto.server.describeServer() const res = await agent.com.atproto.server.describeServer()
return res.data return res.data
}, },
+41 -3
View File
@@ -1,8 +1,19 @@
import {AtpSessionData, AtpSessionEvent, BskyAgent} from '@atproto/api' import {
Agent as BaseAgent,
type AtprotoServiceType,
type AtpSessionData,
type AtpSessionEvent,
BskyAgent,
type Did,
} from '@atproto/api'
import {type FetchHandler} from '@atproto/api/dist/agent'
import {type SessionManager} from '@atproto/api/dist/session-manager'
import {TID} from '@atproto/common-web' import {TID} from '@atproto/common-web'
import {type FetchHandlerOptions} from '@atproto/xrpc'
import {networkRetry} from '#/lib/async/retry' import {networkRetry} from '#/lib/async/retry'
import { import {
BLUESKY_PROXY_HEADER,
BSKY_SERVICE, BSKY_SERVICE,
DISCOVER_SAVED_FEED, DISCOVER_SAVED_FEED,
IS_PROD_SERVICE, IS_PROD_SERVICE,
@@ -19,12 +30,17 @@ import {
configureModerationForAccount, configureModerationForAccount,
configureModerationForGuest, configureModerationForGuest,
} from './moderation' } from './moderation'
import {SessionAccount} from './types' import {type SessionAccount} from './types'
import {isSessionExpired, isSignupQueued} from './util' import {isSessionExpired, isSignupQueued} from './util'
export type ProxyHeaderValue = `${Did}#${AtprotoServiceType}`
export function createPublicAgent() { export function createPublicAgent() {
configureModerationForGuest() // Side effect but only relevant for tests configureModerationForGuest() // Side effect but only relevant for tests
return new BskyAppAgent({service: PUBLIC_BSKY_SERVICE})
const agent = new BskyAppAgent({service: PUBLIC_BSKY_SERVICE})
agent.configureProxy(BLUESKY_PROXY_HEADER)
return agent
} }
export async function createAgentAndResume( export async function createAgentAndResume(
@@ -61,6 +77,8 @@ export async function createAgentAndResume(
} }
} }
agent.configureProxy(BLUESKY_PROXY_HEADER)
return agent.prepare(gates, moderation, onSessionChange) return agent.prepare(gates, moderation, onSessionChange)
} }
@@ -93,6 +111,9 @@ export async function createAgentAndLogin(
const account = agentToSessionAccountOrThrow(agent) const account = agentToSessionAccountOrThrow(agent)
const gates = tryFetchGates(account.did, 'prefer-fresh-gates') const gates = tryFetchGates(account.did, 'prefer-fresh-gates')
const moderation = configureModerationForAccount(agent, account) const moderation = configureModerationForAccount(agent, account)
agent.configureProxy(BLUESKY_PROXY_HEADER)
return agent.prepare(gates, moderation, onSessionChange) return agent.prepare(gates, moderation, onSessionChange)
} }
@@ -180,6 +201,8 @@ export async function createAgentAndCreateAccount(
logger.error(e, {message: `session: failed snoozeEmailConfirmationPrompt`}) logger.error(e, {message: `session: failed snoozeEmailConfirmationPrompt`})
} }
agent.configureProxy(BLUESKY_PROXY_HEADER)
return agent.prepare(gates, moderation, onSessionChange) return agent.prepare(gates, moderation, onSessionChange)
} }
@@ -234,7 +257,22 @@ export function sessionAccountToSession(
} }
} }
export class Agent extends BaseAgent {
constructor(
proxyHeader: ProxyHeaderValue | null,
options: SessionManager | FetchHandler | FetchHandlerOptions,
) {
super(options)
if (proxyHeader) {
this.configureProxy(proxyHeader)
}
}
}
// Not exported. Use factories above to create it. // Not exported. Use factories above to create it.
// WARN: In the factories above, we _manually set a proxy header_ for the agent after we do whatever it is we are supposed to do.
// Ideally, we wouldn't be doing this. However, since there is so much logic that requires making calls to the PDS right now, it
// feels safer to just let those run as-is and set the header afterward.
let realFetch = globalThis.fetch let realFetch = globalThis.fetch
class BskyAppAgent extends BskyAgent { class BskyAppAgent extends BskyAgent {
persistSessionHandler: ((event: AtpSessionEvent) => void) | undefined = persistSessionHandler: ((event: AtpSessionEvent) => void) | undefined =
+1 -1
View File
@@ -10,6 +10,7 @@ import {LinearGradient} from 'expo-linear-gradient'
import {msg, Trans} from '@lingui/macro' import {msg, Trans} from '@lingui/macro'
import {useLingui} from '@lingui/react' import {useLingui} from '@lingui/react'
import {DM_SERVICE_HEADERS} from '#/lib/constants'
import {usePalette} from '#/lib/hooks/usePalette' import {usePalette} from '#/lib/hooks/usePalette'
import {useWebMediaQueries} from '#/lib/hooks/useWebMediaQueries' import {useWebMediaQueries} from '#/lib/hooks/useWebMediaQueries'
import {cleanError} from '#/lib/strings/errors' import {cleanError} from '#/lib/strings/errors'
@@ -17,7 +18,6 @@ import {colors, gradients, s} from '#/lib/styles'
import {useTheme} from '#/lib/ThemeContext' import {useTheme} from '#/lib/ThemeContext'
import {isAndroid, isWeb} from '#/platform/detection' import {isAndroid, isWeb} from '#/platform/detection'
import {useModalControls} from '#/state/modals' import {useModalControls} from '#/state/modals'
import {DM_SERVICE_HEADERS} from '#/state/queries/messages/const'
import {useAgent, useSession, useSessionApi} from '#/state/session' import {useAgent, useSession, useSessionApi} from '#/state/session'
import {atoms as a, useTheme as useNewTheme} from '#/alf' import {atoms as a, useTheme as useNewTheme} from '#/alf'
import {CircleInfo_Stroke2_Corner0_Rounded as CircleInfo} from '#/components/icons/CircleInfo' import {CircleInfo_Stroke2_Corner0_Rounded as CircleInfo} from '#/components/icons/CircleInfo'
@@ -31,6 +31,7 @@ import {useNavigation} from '@react-navigation/native'
import {useQueryClient} from '@tanstack/react-query' import {useQueryClient} from '@tanstack/react-query'
import {MAX_POST_LINES} from '#/lib/constants' import {MAX_POST_LINES} from '#/lib/constants'
import {DM_SERVICE_HEADERS} from '#/lib/constants'
import {useAnimatedValue} from '#/lib/hooks/useAnimatedValue' import {useAnimatedValue} from '#/lib/hooks/useAnimatedValue'
import {usePalette} from '#/lib/hooks/usePalette' import {usePalette} from '#/lib/hooks/usePalette'
import {makeProfileLink} from '#/lib/routes/links' import {makeProfileLink} from '#/lib/routes/links'
@@ -41,7 +42,6 @@ import {sanitizeHandle} from '#/lib/strings/handles'
import {niceDate} from '#/lib/strings/time' import {niceDate} from '#/lib/strings/time'
import {s} from '#/lib/styles' import {s} from '#/lib/styles'
import {logger} from '#/logger' import {logger} from '#/logger'
import {DM_SERVICE_HEADERS} from '#/state/queries/messages/const'
import {type FeedNotification} from '#/state/queries/notifications/feed' import {type FeedNotification} from '#/state/queries/notifications/feed'
import {unstableCacheProfileView} from '#/state/queries/unstable-profile-cache' import {unstableCacheProfileView} from '#/state/queries/unstable-profile-cache'
import {useAgent} from '#/state/session' import {useAgent} from '#/state/session'