diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/state/queries/invites.ts | 21 | ||||
-rw-r--r-- | src/view/screens/Settings.tsx | 20 | ||||
-rw-r--r-- | src/view/shell/Drawer.tsx | 35 | ||||
-rw-r--r-- | src/view/shell/desktop/RightNav.tsx | 49 |
4 files changed, 98 insertions, 27 deletions
diff --git a/src/state/queries/invites.ts b/src/state/queries/invites.ts index c42ba29d5..367917af5 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 579a04b01..6e2f8dbfe 100644 --- a/src/view/screens/Settings.tsx +++ b/src/view/screens/Settings.tsx @@ -32,7 +32,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' @@ -67,7 +66,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' import {useLoggedOutViewControls} from '#/state/shell/logged-out' @@ -383,7 +382,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}> <View style={[ styles.iconContainer, @@ -399,8 +399,18 @@ export function SettingsScreen({}: Props) { /> </View> <Text type="lg" style={invitesAvailable > 0 ? pal.link : pal.text}> - {formatCount(invitesAvailable)} invite{' '} - {pluralize(invitesAvailable, 'code')} available + {invites?.disabled ? ( + <Trans> + Your invite codes are hidden when logged in using an App + Password + </Trans> + ) : ( + <Plural + value={formatCount(invitesAvailable)} + one="# invite code available" + other="# invite codes available" + /> + )} </Text> </TouchableOpacity> diff --git a/src/view/shell/Drawer.tsx b/src/view/shell/Drawer.tsx index b2bb6ea1e..a72f3fe36 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<ViewStyle>}) { 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 ( <TouchableOpacity testID="menuItemInviteCodes" style={[styles.inviteCodes, style]} onPress={onPress} accessibilityRole="button" - accessibilityLabel={ - invitesAvailable === 1 - ? 'Invite codes: 1 available' - : `Invite codes: ${invitesAvailable} available` - } - accessibilityHint="Opens list of invite codes"> + accessibilityLabel={_( + plural(invitesAvailable, { + one: 'Invite codes: # available', + other: 'Invite codes: # available', + }), + )} + accessibilityHint={_(msg`Opens list of invite codes`)} + disabled={invites?.disabled}> <FontAwesomeIcon icon="ticket" style={[ @@ -514,8 +519,17 @@ function InviteCodes({style}: {style?: StyleProp<ViewStyle>}) { <Text type="lg-medium" style={invitesAvailable > 0 ? pal.link : pal.textLight}> - {formatCount(invitesAvailable)} invite{' '} - {pluralize(invitesAvailable, 'code')} + {invites?.disabled ? ( + <Trans> + Your invite codes are hidden when logged in using an App Password + </Trans> + ) : ( + <Plural + value={formatCount(invitesAvailable)} + one="# invite code available" + other="# invite codes available" + /> + )} </Text> </TouchableOpacity> ) @@ -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 7087a4397..9a5186549 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 ( + <View style={[styles.inviteCodes, pal.border]}> + <FontAwesomeIcon + icon="ticket" + style={[styles.inviteCodesIcon, pal.textLight]} + size={16} + /> + <Text type="md-medium" style={pal.textLight}> + <Trans> + Your invite codes are hidden when logged in using an App Password + </Trans> + </Text> + </View> + ) + } + return ( <TouchableOpacity style={[styles.inviteCodes, pal.border]} onPress={onPress} accessibilityRole="button" - accessibilityLabel={ - invitesAvailable === 1 - ? 'Invite codes: 1 available' - : `Invite codes: ${invitesAvailable} available` - } - accessibilityHint="Opens list of invite codes"> + accessibilityLabel={_( + plural(invitesAvailable, { + one: 'Invite codes: # available', + other: 'Invite codes: # available', + }), + )} + accessibilityHint={_(msg`Opens list of invite codes`)}> <FontAwesomeIcon icon="ticket" style={[ @@ -132,8 +155,11 @@ function InviteCodes() { <Text type="md-medium" style={invitesAvailable > 0 ? pal.link : pal.textLight}> - {formatCount(invitesAvailable)} invite{' '} - {pluralize(invitesAvailable, 'code')} available + <Plural + value={formatCount(invitesAvailable)} + one="# invite code available" + other="# invite codes available" + /> </Text> </TouchableOpacity> ) @@ -163,9 +189,10 @@ const styles = StyleSheet.create({ paddingHorizontal: 16, paddingVertical: 12, flexDirection: 'row', - alignItems: 'center', }, inviteCodesIcon: { + marginTop: 2, marginRight: 6, + flexShrink: 0, }, }) |