diff --git a/src/state/queries/invites.ts b/src/state/queries/invites.ts
index c42ba29d52..367917af5b 100644
--- a/src/state/queries/invites.ts
+++ b/src/state/queries/invites.ts
@@ -3,6 +3,7 @@ import {useQuery} from '@tanstack/react-query'
import {getAgent} from '#/state/session'
import {STALE} from '#/state/queries'
+import {cleanError} from '#/lib/strings/errors'
function isInviteAvailable(invite: ComAtprotoServerDefs.InviteCode): boolean {
return invite.available - invite.uses.length > 0 && !invite.disabled
@@ -17,7 +18,24 @@ export function useInviteCodesQuery() {
staleTime: STALE.HOURS.ONE,
queryKey: ['inviteCodes'],
queryFn: async () => {
- const res = await getAgent().com.atproto.server.getAccountInviteCodes({})
+ const res = await getAgent()
+ .com.atproto.server.getAccountInviteCodes({})
+ .catch(e => {
+ if (cleanError(e) === 'Bad token scope') {
+ return null
+ } else {
+ throw e
+ }
+ })
+
+ if (res === null) {
+ return {
+ disabled: true,
+ all: [],
+ available: [],
+ used: [],
+ }
+ }
if (!res.data?.codes) {
throw new Error(`useInviteCodesQuery: no codes returned`)
@@ -27,6 +45,7 @@ export function useInviteCodesQuery() {
const used = res.data.codes.filter(code => !isInviteAvailable(code))
return {
+ disabled: false,
all: [...available, ...used],
available,
used,
diff --git a/src/view/screens/Settings.tsx b/src/view/screens/Settings.tsx
index 88cc2d5320..944f5e81a0 100644
--- a/src/view/screens/Settings.tsx
+++ b/src/view/screens/Settings.tsx
@@ -36,7 +36,6 @@ import {useWebMediaQueries} from 'lib/hooks/useWebMediaQueries'
import {useAccountSwitcher} from 'lib/hooks/useAccountSwitcher'
import {useAnalytics} from 'lib/analytics/analytics'
import {NavigationProp} from 'lib/routes/types'
-import {pluralize} from 'lib/strings/helpers'
import {HandIcon, HashtagIcon} from 'lib/icons'
import {formatCount} from 'view/com/util/numeric/format'
import Clipboard from '@react-native-clipboard/clipboard'
@@ -71,7 +70,7 @@ import {clearLegacyStorage} from '#/state/persisted/legacy'
// -prf
import {useDebugHeaderSetting} from 'lib/api/debug-appview-proxy-header'
import {STATUS_PAGE_URL} from 'lib/constants'
-import {Trans, msg} from '@lingui/macro'
+import {Plural, Trans, msg} from '@lingui/macro'
import {useLingui} from '@lingui/react'
import {useQueryClient} from '@tanstack/react-query'
@@ -385,7 +384,8 @@ export function SettingsScreen({}: Props) {
onPress={isSwitchingAccounts ? undefined : onPressInviteCodes}
accessibilityRole="button"
accessibilityLabel={_(msg`Invite`)}
- accessibilityHint="Opens invite code list">
+ accessibilityHint="Opens invite code list"
+ disabled={invites?.disabled}>
0 ? pal.link : pal.text}>
- {formatCount(invitesAvailable)} invite{' '}
- {pluralize(invitesAvailable, 'code')} available
+ {invites?.disabled ? (
+
+ Your invite codes are hidden when logged in using an App
+ Password
+
+ ) : (
+
+ )}
diff --git a/src/view/shell/Drawer.tsx b/src/view/shell/Drawer.tsx
index 9df9b70b31..ee6c980b84 100644
--- a/src/view/shell/Drawer.tsx
+++ b/src/view/shell/Drawer.tsx
@@ -42,7 +42,7 @@ import {NavigationProp} from 'lib/routes/types'
import {useNavigationTabState} from 'lib/hooks/useNavigationTabState'
import {isWeb} from 'platform/detection'
import {formatCount, formatCountShortOnly} from 'view/com/util/numeric/format'
-import {Trans, msg} from '@lingui/macro'
+import {Plural, Trans, msg, plural} from '@lingui/macro'
import {useLingui} from '@lingui/react'
import {useSetDrawerOpen} from '#/state/shell'
import {useModalControls} from '#/state/modals'
@@ -486,23 +486,28 @@ function InviteCodes({style}: {style?: StyleProp}) {
const {data: invites} = useInviteCodesQuery()
const invitesAvailable = invites?.available?.length ?? 0
const {openModal} = useModalControls()
+ const {_} = useLingui()
+
const onPress = React.useCallback(() => {
track('Menu:ItemClicked', {url: '#invite-codes'})
setDrawerOpen(false)
openModal({name: 'invite-codes'})
}, [openModal, track, setDrawerOpen])
+
return (
+ accessibilityLabel={_(
+ plural(invitesAvailable, {
+ one: 'Invite codes: # available',
+ other: 'Invite codes: # available',
+ }),
+ )}
+ accessibilityHint={_(msg`Opens list of invite codes`)}
+ disabled={invites?.disabled}>
}) {
0 ? pal.link : pal.textLight}>
- {formatCount(invitesAvailable)} invite{' '}
- {pluralize(invitesAvailable, 'code')}
+ {invites?.disabled ? (
+
+ Your invite codes are hidden when logged in using an App Password
+
+ ) : (
+
+ )}
)
@@ -592,10 +606,11 @@ const styles = StyleSheet.create({
paddingLeft: 22,
paddingVertical: 8,
flexDirection: 'row',
- alignItems: 'center',
},
inviteCodesIcon: {
marginRight: 6,
+ flexShrink: 0,
+ marginTop: 2,
},
footer: {
diff --git a/src/view/shell/desktop/RightNav.tsx b/src/view/shell/desktop/RightNav.tsx
index 7087a4397f..9a51865496 100644
--- a/src/view/shell/desktop/RightNav.tsx
+++ b/src/view/shell/desktop/RightNav.tsx
@@ -9,11 +9,10 @@ import {TextLink} from 'view/com/util/Link'
import {FEEDBACK_FORM_URL, HELP_DESK_URL} from 'lib/constants'
import {s} from 'lib/styles'
import {useWebMediaQueries} from 'lib/hooks/useWebMediaQueries'
-import {pluralize} from 'lib/strings/helpers'
import {formatCount} from 'view/com/util/numeric/format'
import {useModalControls} from '#/state/modals'
import {useLingui} from '@lingui/react'
-import {msg} from '@lingui/macro'
+import {Plural, Trans, msg, plural} from '@lingui/macro'
import {useSession} from '#/state/session'
import {useInviteCodesQuery} from '#/state/queries/invites'
@@ -106,21 +105,45 @@ function InviteCodes() {
const {openModal} = useModalControls()
const {data: invites} = useInviteCodesQuery()
const invitesAvailable = invites?.available?.length ?? 0
+ const {_} = useLingui()
const onPress = React.useCallback(() => {
openModal({name: 'invite-codes'})
}, [openModal])
+
+ if (!invites) {
+ return null
+ }
+
+ if (invites?.disabled) {
+ return (
+
+
+
+
+ Your invite codes are hidden when logged in using an App Password
+
+
+
+ )
+ }
+
return (
+ accessibilityLabel={_(
+ plural(invitesAvailable, {
+ one: 'Invite codes: # available',
+ other: 'Invite codes: # available',
+ }),
+ )}
+ accessibilityHint={_(msg`Opens list of invite codes`)}>
0 ? pal.link : pal.textLight}>
- {formatCount(invitesAvailable)} invite{' '}
- {pluralize(invitesAvailable, 'code')} available
+
)
@@ -163,9 +189,10 @@ const styles = StyleSheet.create({
paddingHorizontal: 16,
paddingVertical: 12,
flexDirection: 'row',
- alignItems: 'center',
},
inviteCodesIcon: {
+ marginTop: 2,
marginRight: 6,
+ flexShrink: 0,
},
})