diff options
Diffstat (limited to 'src')
35 files changed, 876 insertions, 767 deletions
diff --git a/src/components/Button.tsx b/src/components/Button.tsx index 123e6ee42..2d6ddc834 100644 --- a/src/components/Button.tsx +++ b/src/components/Button.tsx @@ -1,23 +1,23 @@ import React from 'react' import { - AccessibilityProps, - GestureResponderEvent, - MouseEvent, - NativeSyntheticEvent, + type AccessibilityProps, + type GestureResponderEvent, + type MouseEvent, + type NativeSyntheticEvent, Pressable, - PressableProps, - StyleProp, + type PressableProps, + type StyleProp, StyleSheet, - TargetedEvent, - TextProps, - TextStyle, + type TargetedEvent, + type TextProps, + type TextStyle, View, - ViewStyle, + type ViewStyle, } from 'react-native' import {LinearGradient} from 'expo-linear-gradient' import {atoms as a, flatten, select, tokens, useTheme} from '#/alf' -import {Props as SVGIconProps} from '#/components/icons/common' +import {type Props as SVGIconProps} from '#/components/icons/common' import {Text} from '#/components/Typography' export type ButtonVariant = 'solid' | 'outline' | 'ghost' | 'gradient' @@ -597,7 +597,7 @@ export function useSharedButtonTextStyles() { if (variant === 'solid' || variant === 'gradient') { if (!disabled) { baseStyles.push({ - color: t.palette.contrast_100, + color: t.palette.contrast_50, }) } else { baseStyles.push({ diff --git a/src/components/Dialog/context.ts b/src/components/Dialog/context.ts index 331ff3f33..eb892403f 100644 --- a/src/components/Dialog/context.ts +++ b/src/components/Dialog/context.ts @@ -2,9 +2,9 @@ import React from 'react' import {useDialogStateContext} from '#/state/dialogs' import { - DialogContextProps, - DialogControlRefProps, - DialogOuterProps, + type DialogContextProps, + type DialogControlRefProps, + type DialogOuterProps, } from '#/components/Dialog/types' import {BottomSheetSnapPoint} from '../../../modules/bottom-sheet/src/BottomSheet.types' diff --git a/src/components/Dialog/index.web.tsx b/src/components/Dialog/index.web.tsx index 153954691..12bd8819b 100644 --- a/src/components/Dialog/index.web.tsx +++ b/src/components/Dialog/index.web.tsx @@ -1,17 +1,15 @@ import React, {useImperativeHandle} from 'react' import { FlatList, - FlatListProps, - StyleProp, + type FlatListProps, + type StyleProp, TouchableWithoutFeedback, View, - ViewStyle, + type ViewStyle, } from 'react-native' import {msg} from '@lingui/macro' import {useLingui} from '@lingui/react' -import {DismissableLayer} from '@radix-ui/react-dismissable-layer' -import {useFocusGuards} from '@radix-ui/react-focus-guards' -import {FocusScope} from '@radix-ui/react-focus-scope' +import {DismissableLayer, FocusGuards, FocusScope} from 'radix-ui/internal' import {RemoveScrollBar} from 'react-remove-scroll-bar' import {logger} from '#/logger' @@ -21,9 +19,9 @@ import {atoms as a, flatten, useBreakpoints, useTheme, web} from '#/alf' import {Button, ButtonIcon} from '#/components/Button' import {Context} from '#/components/Dialog/context' import { - DialogControlProps, - DialogInnerProps, - DialogOuterProps, + type DialogControlProps, + type DialogInnerProps, + type DialogOuterProps, } from '#/components/Dialog/types' import {TimesLarge_Stroke2_Corner0_Rounded as X} from '#/components/icons/Times' import {Portal} from '#/components/Portal' @@ -162,9 +160,9 @@ export function Inner({ const {close} = React.useContext(Context) const {gtMobile} = useBreakpoints() const {reduceMotionEnabled} = useA11y() - useFocusGuards() + FocusGuards.useFocusGuards() return ( - <FocusScope loop asChild trapped> + <FocusScope.FocusScope loop asChild trapped> <View role="dialog" aria-role="dialog" @@ -191,7 +189,7 @@ export function Inner({ !reduceMotionEnabled && a.zoom_fade_in, style, ])}> - <DismissableLayer + <DismissableLayer.DismissableLayer onInteractOutside={preventDefault} onFocusOutside={preventDefault} onDismiss={close} @@ -200,9 +198,9 @@ export function Inner({ <View style={[gtMobile ? a.p_2xl : a.p_xl, contentContainerStyle]}> {children} </View> - </DismissableLayer> + </DismissableLayer.DismissableLayer> </View> - </FocusScope> + </FocusScope.FocusScope> ) } diff --git a/src/components/Menu/index.web.tsx b/src/components/Menu/index.web.tsx index ae021dcf1..27678bf2f 100644 --- a/src/components/Menu/index.web.tsx +++ b/src/components/Menu/index.web.tsx @@ -1,12 +1,12 @@ import React from 'react' -import {Pressable, StyleProp, View, ViewStyle} from 'react-native' +import {Pressable, type StyleProp, View, type ViewStyle} from 'react-native' import {msg} from '@lingui/macro' import {useLingui} from '@lingui/react' -import * as DropdownMenu from '@radix-ui/react-dropdown-menu' +import {DropdownMenu} from 'radix-ui' import {useA11y} from '#/state/a11y' import {atoms as a, flatten, useTheme, web} from '#/alf' -import * as Dialog from '#/components/Dialog' +import type * as Dialog from '#/components/Dialog' import {useInteractionState} from '#/components/hooks/useInteractionState' import { Context, @@ -15,13 +15,13 @@ import { useMenuItemContext, } from '#/components/Menu/context' import { - ContextType, - GroupProps, - ItemIconProps, - ItemProps, - ItemTextProps, - RadixPassThroughTriggerProps, - TriggerProps, + type ContextType, + type GroupProps, + type ItemIconProps, + type ItemProps, + type ItemTextProps, + type RadixPassThroughTriggerProps, + type TriggerProps, } from '#/components/Menu/types' import {Portal} from '#/components/Portal' import {Text} from '#/components/Typography' diff --git a/src/components/Prompt.tsx b/src/components/Prompt.tsx index ed8c15f15..f21c98ff8 100644 --- a/src/components/Prompt.tsx +++ b/src/components/Prompt.tsx @@ -52,9 +52,7 @@ export function Outer({ <Dialog.ScrollableInner accessibilityLabelledBy={titleId} accessibilityDescribedBy={descriptionId} - style={[ - gtMobile ? {width: 'auto', maxWidth: 400, minWidth: 200} : a.w_full, - ]}> + style={[gtMobile ? {width: 400} : a.w_full]}> {children} </Dialog.ScrollableInner> </Context.Provider> diff --git a/src/components/dialogs/Context.tsx b/src/components/dialogs/Context.tsx index c9dff9a99..fda904b8b 100644 --- a/src/components/dialogs/Context.tsx +++ b/src/components/dialogs/Context.tsx @@ -1,32 +1,66 @@ -import React from 'react' +import {createContext, useContext, useMemo, useState} from 'react' import * as Dialog from '#/components/Dialog' -type Control = Dialog.DialogOuterProps['control'] +type Control = Dialog.DialogControlProps + +export type StatefulControl<T> = { + control: Control + open: (value: T) => void + clear: () => void + value: T | undefined +} type ControlsContext = { mutedWordsDialogControl: Control signinDialogControl: Control + inAppBrowserConsentControl: StatefulControl<string> } -const ControlsContext = React.createContext({ - mutedWordsDialogControl: {} as Control, - signinDialogControl: {} as Control, -}) +const ControlsContext = createContext<ControlsContext | null>(null) export function useGlobalDialogsControlContext() { - return React.useContext(ControlsContext) + const ctx = useContext(ControlsContext) + if (!ctx) { + throw new Error( + 'useGlobalDialogsControlContext must be used within a Provider', + ) + } + return ctx } export function Provider({children}: React.PropsWithChildren<{}>) { const mutedWordsDialogControl = Dialog.useDialogControl() const signinDialogControl = Dialog.useDialogControl() - const ctx = React.useMemo<ControlsContext>( - () => ({mutedWordsDialogControl, signinDialogControl}), - [mutedWordsDialogControl, signinDialogControl], + const inAppBrowserConsentControl = useStatefulDialogControl<string>() + + const ctx = useMemo<ControlsContext>( + () => ({ + mutedWordsDialogControl, + signinDialogControl, + inAppBrowserConsentControl, + }), + [mutedWordsDialogControl, signinDialogControl, inAppBrowserConsentControl], ) return ( <ControlsContext.Provider value={ctx}>{children}</ControlsContext.Provider> ) } + +function useStatefulDialogControl<T>(initialValue?: T): StatefulControl<T> { + const [value, setValue] = useState(initialValue) + const control = Dialog.useDialogControl() + return useMemo( + () => ({ + control, + open: (v: T) => { + setValue(v) + control.open() + }, + clear: () => setValue(initialValue), + value, + }), + [control, value, initialValue], + ) +} diff --git a/src/components/dialogs/InAppBrowserConsent.tsx b/src/components/dialogs/InAppBrowserConsent.tsx new file mode 100644 index 000000000..4459c64db --- /dev/null +++ b/src/components/dialogs/InAppBrowserConsent.tsx @@ -0,0 +1,111 @@ +import {useCallback} from 'react' +import {View} from 'react-native' +import {msg, Trans} from '@lingui/macro' +import {useLingui} from '@lingui/react' + +import {useOpenLink} from '#/lib/hooks/useOpenLink' +import {isWeb} from '#/platform/detection' +import {useSetInAppBrowser} from '#/state/preferences/in-app-browser' +import {atoms as a, useTheme} from '#/alf' +import {Button, ButtonIcon, ButtonText} from '#/components/Button' +import * as Dialog from '#/components/Dialog' +import {SquareArrowTopRight_Stroke2_Corner0_Rounded as External} from '#/components/icons/SquareArrowTopRight' +import {Text} from '#/components/Typography' +import {useGlobalDialogsControlContext} from './Context' + +export function InAppBrowserConsentDialog() { + const {inAppBrowserConsentControl} = useGlobalDialogsControlContext() + + if (isWeb) return null + + return ( + <Dialog.Outer + control={inAppBrowserConsentControl.control} + nativeOptions={{preventExpansion: true}} + onClose={inAppBrowserConsentControl.clear}> + <Dialog.Handle /> + <InAppBrowserConsentInner href={inAppBrowserConsentControl.value} /> + </Dialog.Outer> + ) +} + +function InAppBrowserConsentInner({href}: {href?: string}) { + const control = Dialog.useDialogContext() + const {_} = useLingui() + const t = useTheme() + const setInAppBrowser = useSetInAppBrowser() + const openLink = useOpenLink() + + const onUseIAB = useCallback(() => { + control.close(() => { + setInAppBrowser(true) + if (href) { + openLink(href, true) + } + }) + }, [control, setInAppBrowser, href, openLink]) + + const onUseLinking = useCallback(() => { + control.close(() => { + setInAppBrowser(false) + if (href) { + openLink(href, false) + } + }) + }, [control, setInAppBrowser, href, openLink]) + + const onCancel = useCallback(() => { + control.close() + }, [control]) + + return ( + <Dialog.ScrollableInner label={_(msg`How should we open this link?`)}> + <View style={[a.gap_2xl]}> + <View style={[a.gap_sm]}> + <Text style={[a.font_heavy, a.text_2xl]}> + <Trans>How should we open this link?</Trans> + </Text> + <Text style={[t.atoms.text_contrast_high, a.leading_snug, a.text_md]}> + <Trans> + Your choice will be remembered for future links. You can change it + at any time in settings. + </Trans> + </Text> + </View> + <View style={[a.gap_sm]}> + <Button + label={_(msg`Use in-app browser`)} + onPress={onUseIAB} + size="large" + variant="solid" + color="primary"> + <ButtonText> + <Trans>Use in-app browser</Trans> + </ButtonText> + </Button> + <Button + label={_(msg`Use my default browser`)} + onPress={onUseLinking} + size="large" + variant="solid" + color="secondary"> + <ButtonText> + <Trans>Use my default browser</Trans> + </ButtonText> + <ButtonIcon position="right" icon={External} /> + </Button> + <Button + label={_(msg`Cancel`)} + onPress={onCancel} + size="large" + variant="ghost" + color="secondary"> + <ButtonText> + <Trans>Cancel</Trans> + </ButtonText> + </Button> + </View> + </View> + </Dialog.ScrollableInner> + ) +} diff --git a/src/components/dms/EmojiReactionPicker.web.tsx b/src/components/dms/EmojiReactionPicker.web.tsx index d9e1c87f7..cdd3ce414 100644 --- a/src/components/dms/EmojiReactionPicker.web.tsx +++ b/src/components/dms/EmojiReactionPicker.web.tsx @@ -4,10 +4,10 @@ import {type ChatBskyConvoDefs} from '@atproto/api' import EmojiPicker from '@emoji-mart/react' import {msg} from '@lingui/macro' import {useLingui} from '@lingui/react' -import * as DropdownMenu from '@radix-ui/react-dropdown-menu' +import {DropdownMenu} from 'radix-ui' import {useSession} from '#/state/session' -import {type Emoji} from '#/view/com/composer/text-input/web/EmojiPicker.web' +import {type Emoji} from '#/view/com/composer/text-input/web/EmojiPicker' import {useWebPreloadEmoji} from '#/view/com/composer/text-input/web/useWebPreloadEmoji' import {atoms as a, flatten, useTheme} from '#/alf' import {DotGrid_Stroke2_Corner0_Rounded as DotGridIcon} from '#/components/icons/DotGrid' diff --git a/src/components/icons/VerifiedCheck.tsx b/src/components/icons/VerifiedCheck.tsx index 9299eb6e3..9d0aa9158 100644 --- a/src/components/icons/VerifiedCheck.tsx +++ b/src/components/icons/VerifiedCheck.tsx @@ -18,12 +18,12 @@ export const VerifiedCheck = React.forwardRef<Svg, Props>(function LogoImpl( width={size} height={size} style={[style]}> - <Circle cx="12" cy="12" r="12" fill={fill} /> + <Circle cx="12" cy="12" r="11.5" fill={fill} /> <Path fill="#fff" fillRule="evenodd" clipRule="evenodd" - d="M18.311 7.421a1.437 1.437 0 0 1 0 2.033l-6.571 6.571a1.437 1.437 0 0 1-2.033 0L6.42 12.74a1.438 1.438 0 0 1 2.033-2.033l2.27 2.269 5.554-5.555a1.437 1.437 0 0 1 2.033 0Z" + d="M17.659 8.175a1.361 1.361 0 0 1 0 1.925l-6.224 6.223a1.361 1.361 0 0 1-1.925 0L6.4 13.212a1.361 1.361 0 0 1 1.925-1.925l2.149 2.148 5.26-5.26a1.361 1.361 0 0 1 1.925 0Z" /> </Svg> ) diff --git a/src/components/icons/VerifierCheck.tsx b/src/components/icons/VerifierCheck.tsx index 7c3a0149d..143c24b97 100644 --- a/src/components/icons/VerifierCheck.tsx +++ b/src/components/icons/VerifierCheck.tsx @@ -22,13 +22,13 @@ export const VerifierCheck = React.forwardRef<Svg, Props>(function LogoImpl( fill={fill} fillRule="evenodd" clipRule="evenodd" - d="M8.792 1.54a4.11 4.11 0 0 1 6.416 0 4.128 4.128 0 0 0 3.146 1.54c2.616.04 4.544 2.5 4 5.1a4.277 4.277 0 0 0 .777 3.462c1.6 2.104.912 5.17-1.427 6.36a4.21 4.21 0 0 0-2.177 2.774c-.62 2.584-3.408 3.948-5.781 2.83a4.092 4.092 0 0 0-3.492 0c-2.373 1.118-5.16-.246-5.78-2.83a4.21 4.21 0 0 0-2.178-2.775c-2.34-1.19-3.028-4.256-1.427-6.36a4.277 4.277 0 0 0 .776-3.46c-.543-2.602 1.385-5.06 4.001-5.1a4.128 4.128 0 0 0 3.146-1.54Z" + d="M8.792 1.615a4.154 4.154 0 0 1 6.416 0 4.154 4.154 0 0 0 3.146 1.515 4.154 4.154 0 0 1 4 5.017 4.154 4.154 0 0 0 .777 3.404 4.154 4.154 0 0 1-1.427 6.255 4.153 4.153 0 0 0-2.177 2.73 4.154 4.154 0 0 1-5.781 2.784 4.154 4.154 0 0 0-3.492 0 4.154 4.154 0 0 1-5.78-2.784 4.154 4.154 0 0 0-2.178-2.73A4.154 4.154 0 0 1 .87 11.551a4.154 4.154 0 0 0 .776-3.404A4.154 4.154 0 0 1 5.646 3.13a4.154 4.154 0 0 0 3.146-1.515Z" /> <Path fill="#fff" fillRule="evenodd" clipRule="evenodd" - d="M17.659 8.399a1.361 1.361 0 0 1 0 1.925l-6.224 6.223a1.361 1.361 0 0 1-1.925 0L6.4 13.435a1.361 1.361 0 1 1 1.925-1.925l2.149 2.15 5.26-5.261a1.361 1.361 0 0 1 1.925 0Z" + d="M17.861 8.26a1.438 1.438 0 0 1 0 2.033l-6.571 6.571a1.437 1.437 0 0 1-2.033 0L5.97 13.58a1.438 1.438 0 0 1 2.033-2.033l2.27 2.269 5.554-5.555a1.437 1.437 0 0 1 2.033 0Z" /> </Svg> ) diff --git a/src/components/verification/VerificationCreatePrompt.tsx b/src/components/verification/VerificationCreatePrompt.tsx index 39ac6dbf6..eb57d7c36 100644 --- a/src/components/verification/VerificationCreatePrompt.tsx +++ b/src/components/verification/VerificationCreatePrompt.tsx @@ -1,15 +1,19 @@ -import {useCallback} from 'react' +import {useCallback, useState} from 'react' import {View} from 'react-native' -import {msg} from '@lingui/macro' +import {msg, Trans} from '@lingui/macro' import {useLingui} from '@lingui/react' import {logger} from '#/logger' import {useModerationOpts} from '#/state/preferences/moderation-opts' import {useVerificationCreateMutation} from '#/state/queries/verification/useVerificationCreateMutation' import * as Toast from '#/view/com/util/Toast' -import {atoms as a} from '#/alf' +import {atoms as a, useBreakpoints} from '#/alf' +import {Admonition} from '#/components/Admonition' +import {Button, ButtonIcon, ButtonText} from '#/components/Button' import {type DialogControlProps} from '#/components/Dialog' +import * as Dialog from '#/components/Dialog' import {VerifiedCheck} from '#/components/icons/VerifiedCheck' +import {Loader} from '#/components/Loader' import * as ProfileCard from '#/components/ProfileCard' import * as Prompt from '#/components/Prompt' import type * as bsky from '#/types/bsky' @@ -22,19 +26,22 @@ export function VerificationCreatePrompt({ profile: bsky.profile.AnyProfileView }) { const {_} = useLingui() + const {gtMobile} = useBreakpoints() const moderationOpts = useModerationOpts() - const {mutateAsync: create} = useVerificationCreateMutation() + const {mutateAsync: create, isPending} = useVerificationCreateMutation() + const [error, setError] = useState(``) const onConfirm = useCallback(async () => { try { await create({profile}) Toast.show(_(msg`Successfully verified`)) + control.close() } catch (e) { - Toast.show(_(msg`Failed to create a verification`), 'xmark') + setError(_(msg`Verification failed, please try again.`)) logger.error('Failed to create a verification', { safeMessage: e, }) } - }, [_, profile, create]) + }, [_, profile, create, control]) return ( <Prompt.Outer control={control}> @@ -47,24 +54,51 @@ export function VerificationCreatePrompt({ <Prompt.DescriptionText> {_(msg`This action can be undone at any time.`)} </Prompt.DescriptionText> - <View style={[a.pb_xl]}> - {moderationOpts ? ( - <ProfileCard.Header> - <ProfileCard.Avatar - profile={profile} - moderationOpts={moderationOpts} - /> - <ProfileCard.NameAndHandle - profile={profile} - moderationOpts={moderationOpts} - /> - </ProfileCard.Header> - ) : null} + + {moderationOpts ? ( + <ProfileCard.Header> + <ProfileCard.Avatar + profile={profile} + moderationOpts={moderationOpts} + /> + <ProfileCard.NameAndHandle + profile={profile} + moderationOpts={moderationOpts} + /> + </ProfileCard.Header> + ) : null} + + {error && ( + <View style={[a.pt_lg]}> + <Admonition type="error">{error}</Admonition> + </View> + )} + + <View style={[a.pt_xl]}> + {profile.displayName ? ( + <Prompt.Actions> + <Button + variant="solid" + color="primary" + size={gtMobile ? 'small' : 'large'} + label={_(msg`Verify account`)} + onPress={onConfirm}> + <ButtonText>{_(msg`Verify account`)}</ButtonText> + {isPending && <ButtonIcon icon={Loader} />} + </Button> + <Prompt.Cancel /> + </Prompt.Actions> + ) : ( + <Admonition type="warning"> + <Trans> + This user does not have a display name, and therefore cannot be + verified. + </Trans> + </Admonition> + )} </View> - <Prompt.Actions> - <Prompt.Action cta={_(msg`Verify account`)} onPress={onConfirm} /> - <Prompt.Cancel /> - </Prompt.Actions> + + <Dialog.Close /> </Prompt.Outer> ) } diff --git a/src/lib/hooks/useOpenLink.ts b/src/lib/hooks/useOpenLink.ts index a949dacc6..28c1bca3d 100644 --- a/src/lib/hooks/useOpenLink.ts +++ b/src/lib/hooks/useOpenLink.ts @@ -12,16 +12,18 @@ import { toNiceDomain, } from '#/lib/strings/url-helpers' import {isNative} from '#/platform/detection' -import {useModalControls} from '#/state/modals' import {useInAppBrowser} from '#/state/preferences/in-app-browser' import {useTheme} from '#/alf' +import {useDialogContext} from '#/components/Dialog' import {useSheetWrapper} from '#/components/Dialog/sheet-wrapper' +import {useGlobalDialogsControlContext} from '#/components/dialogs/Context' export function useOpenLink() { - const {openModal} = useModalControls() const enabled = useInAppBrowser() const t = useTheme() const sheetWrapper = useSheetWrapper() + const dialogContext = useDialogContext() + const {inAppBrowserConsentControl} = useGlobalDialogsControlContext() const openLink = useCallback( async (url: string, override?: boolean, shouldProxy?: boolean) => { @@ -42,10 +44,17 @@ export function useOpenLink() { if (isNative && !url.startsWith('mailto:')) { if (override === undefined && enabled === undefined) { - openModal({ - name: 'in-app-browser-consent', - href: url, - }) + // consent dialog is a global dialog, and while it's possible to nest dialogs, + // the actual components need to be nested. sibling dialogs on iOS are not supported. + // thus, check if we're in a dialog, and if so, close the existing dialog before opening the + // consent dialog -sfn + if (dialogContext.isWithinDialog) { + dialogContext.close(() => { + inAppBrowserConsentControl.open(url) + }) + } else { + inAppBrowserConsentControl.open(url) + } return } else if (override ?? enabled) { await sheetWrapper( @@ -62,7 +71,7 @@ export function useOpenLink() { } Linking.openURL(url) }, - [enabled, openModal, t, sheetWrapper], + [enabled, inAppBrowserConsentControl, t, sheetWrapper, dialogContext], ) return openLink diff --git a/src/lib/media/manip.ts b/src/lib/media/manip.ts index 7f052068d..f6ef8347d 100644 --- a/src/lib/media/manip.ts +++ b/src/lib/media/manip.ts @@ -178,15 +178,20 @@ async function doResize(localUri: string, opts: DoResizeOpts): Promise<Image> { height: imageRes.height, }) - for (let i = 0; i < 9; i++) { - // nearest 10th - const quality = Math.round((1 - 0.1 * i) * 10) / 10 + let minQualityPercentage = 0 + let maxQualityPercentage = 101 // exclusive + let newDataUri + + while (maxQualityPercentage - minQualityPercentage > 1) { + const qualityPercentage = Math.round( + (maxQualityPercentage + minQualityPercentage) / 2, + ) const resizeRes = await manipulateAsync( localUri, [{resize: newDimensions}], { format: SaveFormat.JPEG, - compress: quality, + compress: qualityPercentage / 100, }, ) @@ -198,8 +203,8 @@ async function doResize(localUri: string, opts: DoResizeOpts): Promise<Image> { } if (fileInfo.size < opts.maxSize) { - safeDeleteAsync(imageRes.uri) - return { + minQualityPercentage = qualityPercentage + newDataUri = { path: normalizePath(resizeRes.uri), mime: 'image/jpeg', size: fileInfo.size, @@ -207,9 +212,17 @@ async function doResize(localUri: string, opts: DoResizeOpts): Promise<Image> { height: resizeRes.height, } } else { - safeDeleteAsync(resizeRes.uri) + maxQualityPercentage = qualityPercentage } + + safeDeleteAsync(resizeRes.uri) } + + if (newDataUri) { + safeDeleteAsync(imageRes.uri) + return newDataUri + } + throw new Error( `This image is too big! We couldn't compress it down to ${opts.maxSize} bytes`, ) diff --git a/src/lib/media/manip.web.ts b/src/lib/media/manip.web.ts index 4761f2fe0..ffef7314d 100644 --- a/src/lib/media/manip.web.ts +++ b/src/lib/media/manip.web.ts @@ -72,17 +72,28 @@ interface DoResizeOpts { async function doResize(dataUri: string, opts: DoResizeOpts): Promise<RNImage> { let newDataUri - for (let i = 0; i <= 10; i++) { - newDataUri = await createResizedImage(dataUri, { + let minQualityPercentage = 0 + let maxQualityPercentage = 101 //exclusive + + while (maxQualityPercentage - minQualityPercentage > 1) { + const qualityPercentage = Math.round( + (maxQualityPercentage + minQualityPercentage) / 2, + ) + const tempDataUri = await createResizedImage(dataUri, { width: opts.width, height: opts.height, - quality: 1 - i * 0.1, + quality: qualityPercentage / 100, mode: opts.mode, }) - if (getDataUriSize(newDataUri) < opts.maxSize) { - break + + if (getDataUriSize(tempDataUri) < opts.maxSize) { + minQualityPercentage = qualityPercentage + newDataUri = tempDataUri + } else { + maxQualityPercentage = qualityPercentage } } + if (!newDataUri) { throw new Error('Failed to compress image') } diff --git a/src/locale/locales/en/messages.po b/src/locale/locales/en/messages.po index d5c02a4cd..6ad7d50f3 100644 --- a/src/locale/locales/en/messages.po +++ b/src/locale/locales/en/messages.po @@ -22,8 +22,7 @@ msgstr "" msgid "(contains embedded content)" msgstr "" -#: src/screens/Settings/AccountSettings.tsx:65 -#: src/view/com/modals/VerifyEmail.tsx:150 +#: src/screens/Settings/AccountSettings.tsx:67 msgid "(no email)" msgstr "" @@ -417,7 +416,7 @@ msgstr "" msgid "<0>You</0> and<1> </1><2>{0} </2>are included in your starter pack" msgstr "" -#: src/screens/Profile/Header/Handle.tsx:52 +#: src/screens/Profile/Header/Handle.tsx:53 msgid "⚠Invalid Handle" msgstr "" @@ -446,10 +445,10 @@ msgstr "" msgid "A new form of verification" msgstr "" -#: src/Navigation.tsx:400 +#: src/Navigation.tsx:401 #: src/screens/Settings/AboutSettings.tsx:72 -#: src/screens/Settings/Settings.tsx:223 -#: src/screens/Settings/Settings.tsx:226 +#: src/screens/Settings/Settings.tsx:224 +#: src/screens/Settings/Settings.tsx:227 msgid "About" msgstr "" @@ -468,20 +467,20 @@ msgid "Accept Request" msgstr "" #: src/screens/Settings/AccessibilitySettings.tsx:46 -#: src/screens/Settings/Settings.tsx:199 -#: src/screens/Settings/Settings.tsx:202 +#: src/screens/Settings/Settings.tsx:200 +#: src/screens/Settings/Settings.tsx:203 msgid "Accessibility" msgstr "" -#: src/Navigation.tsx:352 +#: src/Navigation.tsx:353 msgid "Accessibility Settings" msgstr "" -#: src/Navigation.tsx:368 +#: src/Navigation.tsx:369 #: src/screens/Login/LoginForm.tsx:194 -#: src/screens/Settings/AccountSettings.tsx:45 -#: src/screens/Settings/Settings.tsx:161 -#: src/screens/Settings/Settings.tsx:164 +#: src/screens/Settings/AccountSettings.tsx:47 +#: src/screens/Settings/Settings.tsx:162 +#: src/screens/Settings/Settings.tsx:165 msgid "Account" msgstr "" @@ -512,11 +511,11 @@ msgstr "" msgid "Account Muted by List" msgstr "" -#: src/screens/Settings/Settings.tsx:480 +#: src/screens/Settings/Settings.tsx:499 msgid "Account options" msgstr "" -#: src/screens/Settings/Settings.tsx:516 +#: src/screens/Settings/Settings.tsx:535 msgid "Account removed from quick access" msgstr "" @@ -584,8 +583,8 @@ msgstr "" msgid "Add alt text (optional)" msgstr "" -#: src/screens/Settings/Settings.tsx:423 -#: src/screens/Settings/Settings.tsx:426 +#: src/screens/Settings/Settings.tsx:442 +#: src/screens/Settings/Settings.tsx:445 #: src/view/shell/desktop/LeftNav.tsx:281 #: src/view/shell/desktop/LeftNav.tsx:285 msgid "Add another account" @@ -713,6 +712,10 @@ msgstr "" msgid "Advanced" msgstr "" +#: src/components/dialogs/ChangeEmailDialog.tsx:143 +msgid "alice@example.com" +msgstr "" + #: src/view/screens/Notifications.tsx:86 msgid "All" msgstr "" @@ -792,15 +795,14 @@ msgid "Alt text will be truncated. {MAX_ALT_TEXT, plural, other {Limit: {0} char msgstr "" #: src/screens/Settings/components/DisableEmail2FADialog.tsx:93 -#: src/view/com/modals/VerifyEmail.tsx:132 msgid "An email has been sent to {0}. It includes a confirmation code which you can enter below." msgstr "" -#: src/view/com/modals/ChangeEmail.tsx:114 -msgid "An email has been sent to your previous address, {0}. It includes a confirmation code which you can enter below." +#: src/components/dialogs/ChangeEmailDialog.tsx:59 +msgid "An email has been sent to your previous address, {currentEmail}. It includes a confirmation code which you can enter below." msgstr "" -#: src/components/dialogs/VerifyEmailDialog.tsx:91 +#: src/components/dialogs/VerifyEmailDialog.tsx:120 msgid "An email has been sent! Please enter the confirmation code included in the email below." msgstr "" @@ -916,7 +918,7 @@ msgstr "" msgid "Anybody can interact" msgstr "" -#: src/Navigation.tsx:408 +#: src/Navigation.tsx:409 #: src/screens/Settings/AppIconSettings/index.tsx:67 #: src/screens/Settings/AppIconSettings/SettingsListItem.tsx:18 #: src/screens/Settings/AppIconSettings/SettingsListItem.tsx:23 @@ -953,7 +955,7 @@ msgstr "" msgid "App passwords" msgstr "" -#: src/Navigation.tsx:320 +#: src/Navigation.tsx:321 #: src/screens/Settings/AppPasswords.tsx:51 msgid "App Passwords" msgstr "" @@ -989,10 +991,10 @@ msgstr "" msgid "Appeal this decision" msgstr "" -#: src/Navigation.tsx:360 +#: src/Navigation.tsx:361 #: src/screens/Settings/AppearanceSettings.tsx:85 -#: src/screens/Settings/Settings.tsx:191 -#: src/screens/Settings/Settings.tsx:194 +#: src/screens/Settings/Settings.tsx:192 +#: src/screens/Settings/Settings.tsx:195 msgid "Appearance" msgstr "" @@ -1128,7 +1130,7 @@ msgid "Before you may message another user, you must first verify your email." msgstr "" #: src/components/dialogs/BirthDateSettings.tsx:103 -#: src/screens/Settings/AccountSettings.tsx:109 +#: src/screens/Settings/AccountSettings.tsx:111 msgid "Birthday" msgstr "" @@ -1195,8 +1197,8 @@ msgstr "" msgid "Blocked accounts" msgstr "" -#: src/Navigation.tsx:161 -#: src/view/screens/ModerationBlockedAccounts.tsx:110 +#: src/Navigation.tsx:162 +#: src/view/screens/ModerationBlockedAccounts.tsx:104 msgid "Blocked Accounts" msgstr "" @@ -1205,7 +1207,7 @@ msgstr "" msgid "Blocked accounts cannot reply in your threads, mention you, or otherwise interact with you." msgstr "" -#: src/view/screens/ModerationBlockedAccounts.tsx:121 +#: src/view/screens/ModerationBlockedAccounts.tsx:190 msgid "Blocked accounts cannot reply in your threads, mention you, or otherwise interact with you. You will not see their content and they will be prevented from seeing yours." msgstr "" @@ -1373,9 +1375,11 @@ msgstr "" msgid "Camera" msgstr "" +#: src/components/dialogs/InAppBrowserConsent.tsx:98 +#: src/components/dialogs/InAppBrowserConsent.tsx:104 #: src/components/Menu/index.tsx:306 +#: src/components/Prompt.tsx:138 #: src/components/Prompt.tsx:140 -#: src/components/Prompt.tsx:142 #: src/screens/Deactivated.tsx:158 #: src/screens/Profile/Header/EditProfileDialog.tsx:227 #: src/screens/Profile/Header/EditProfileDialog.tsx:235 @@ -1384,24 +1388,18 @@ msgstr "" #: src/screens/Settings/AppIconSettings/index.tsx:225 #: src/screens/Settings/components/ChangeHandleDialog.tsx:78 #: src/screens/Settings/components/ChangeHandleDialog.tsx:85 -#: src/screens/Settings/Settings.tsx:268 +#: src/screens/Settings/Settings.tsx:269 #: src/screens/Takendown.tsx:99 #: src/screens/Takendown.tsx:102 #: src/view/com/composer/Composer.tsx:937 #: src/view/com/composer/Composer.tsx:948 -#: src/view/com/modals/ChangeEmail.tsx:213 -#: src/view/com/modals/ChangeEmail.tsx:215 #: src/view/com/modals/ChangePassword.tsx:279 #: src/view/com/modals/ChangePassword.tsx:282 #: src/view/com/modals/CreateOrEditList.tsx:335 #: src/view/com/modals/CropImage.web.tsx:97 #: src/view/com/modals/EditProfile.tsx:269 -#: src/view/com/modals/InAppBrowserConsent.tsx:75 -#: src/view/com/modals/InAppBrowserConsent.tsx:77 #: src/view/com/modals/LinkWarning.tsx:105 #: src/view/com/modals/LinkWarning.tsx:107 -#: src/view/com/modals/VerifyEmail.tsx:255 -#: src/view/com/modals/VerifyEmail.tsx:261 #: src/view/com/util/post-ctrls/RepostButton.tsx:213 #: src/view/shell/desktop/LeftNav.tsx:209 msgid "Cancel" @@ -1459,8 +1457,7 @@ msgstr "" msgid "Captions & alt text" msgstr "" -#: src/screens/Settings/components/Email2FAToggle.tsx:60 -#: src/view/com/modals/VerifyEmail.tsx:160 +#: src/screens/Settings/components/Email2FAToggle.tsx:76 msgid "Change" msgstr "" @@ -1473,13 +1470,13 @@ msgstr "" msgid "Change app icon to \"{0}\"" msgstr "" -#: src/screens/Settings/AccountSettings.tsx:97 -#: src/screens/Settings/AccountSettings.tsx:101 +#: src/screens/Settings/AccountSettings.tsx:99 +#: src/screens/Settings/AccountSettings.tsx:103 msgid "Change email" msgstr "" -#: src/components/dialogs/VerifyEmailDialog.tsx:162 -#: src/components/dialogs/VerifyEmailDialog.tsx:187 +#: src/components/dialogs/VerifyEmailDialog.tsx:200 +#: src/components/dialogs/VerifyEmailDialog.tsx:225 msgid "Change email address" msgstr "" @@ -1492,10 +1489,6 @@ msgstr "" msgid "Change moderation service" msgstr "" -#: src/view/com/modals/VerifyEmail.tsx:155 -msgid "Change my email" -msgstr "" - #: src/view/com/modals/ChangePassword.tsx:153 msgid "Change Password" msgstr "" @@ -1508,11 +1501,11 @@ msgstr "" msgid "Change report reason" msgstr "" -#: src/view/com/modals/ChangeEmail.tsx:104 +#: src/components/dialogs/ChangeEmailDialog.tsx:53 msgid "Change Your Email" msgstr "" -#: src/components/dialogs/VerifyEmailDialog.tsx:171 +#: src/components/dialogs/VerifyEmailDialog.tsx:209 msgid "Change your email address" msgstr "" @@ -1525,7 +1518,7 @@ msgstr "" msgid "Changes hosting provider" msgstr "" -#: src/Navigation.tsx:425 +#: src/Navigation.tsx:426 #: src/view/shell/bottom-bar/BottomBar.tsx:205 #: src/view/shell/desktop/LeftNav.tsx:535 #: src/view/shell/Drawer.tsx:438 @@ -1543,7 +1536,7 @@ msgctxt "toast" msgid "Chat muted" msgstr "" -#: src/Navigation.tsx:435 +#: src/Navigation.tsx:436 #: src/screens/Messages/components/InboxPreview.tsx:24 msgid "Chat request inbox" msgstr "" @@ -1554,7 +1547,7 @@ msgid "Chat requests" msgstr "" #: src/components/dms/ConvoMenu.tsx:75 -#: src/Navigation.tsx:430 +#: src/Navigation.tsx:431 #: src/screens/Messages/ChatList.tsx:328 msgid "Chat settings" msgstr "" @@ -1626,11 +1619,11 @@ msgstr "" msgid "Choose your username" msgstr "" -#: src/screens/Settings/Settings.tsx:401 +#: src/screens/Settings/Settings.tsx:420 msgid "Clear all storage data" msgstr "" -#: src/screens/Settings/Settings.tsx:403 +#: src/screens/Settings/Settings.tsx:422 msgid "Clear all storage data (restart after this)" msgstr "" @@ -1671,11 +1664,14 @@ msgstr "" msgid "Clip 🐴 clop 🐴" msgstr "" +#: src/components/dialogs/ChangeEmailDialog.tsx:244 +#: src/components/dialogs/ChangeEmailDialog.tsx:250 #: src/components/dialogs/GifSelect.tsx:281 #: src/components/dialogs/nuxs/InitialVerificationAnnouncement.tsx:174 #: src/components/dialogs/nuxs/InitialVerificationAnnouncement.tsx:183 #: src/components/dialogs/SearchablePeopleList.tsx:295 -#: src/components/dialogs/VerifyEmailDialog.tsx:289 +#: src/components/dialogs/VerifyEmailDialog.tsx:346 +#: src/components/dialogs/VerifyEmailDialog.tsx:352 #: src/components/dms/EmojiPopup.android.tsx:58 #: src/components/dms/ReportDialog.tsx:381 #: src/components/dms/ReportDialog.tsx:390 @@ -1692,8 +1688,8 @@ msgstr "" msgid "Close" msgstr "" -#: src/components/Dialog/index.web.tsx:113 -#: src/components/Dialog/index.web.tsx:261 +#: src/components/Dialog/index.web.tsx:111 +#: src/components/Dialog/index.web.tsx:259 msgid "Close active dialog" msgstr "" @@ -1715,8 +1711,8 @@ msgstr "" msgid "Close drawer menu" msgstr "" -#: src/view/com/composer/text-input/web/EmojiPicker.web.tsx:137 -#: src/view/com/composer/text-input/web/EmojiPicker.web.tsx:173 +#: src/view/com/composer/text-input/web/EmojiPicker.web.tsx:136 +#: src/view/com/composer/text-input/web/EmojiPicker.web.tsx:172 msgid "Close emoji picker" msgstr "" @@ -1750,8 +1746,8 @@ msgstr "" msgid "Closes post composer and discards post draft" msgstr "" -#: src/view/com/composer/text-input/web/EmojiPicker.web.tsx:138 -#: src/view/com/composer/text-input/web/EmojiPicker.web.tsx:174 +#: src/view/com/composer/text-input/web/EmojiPicker.web.tsx:137 +#: src/view/com/composer/text-input/web/EmojiPicker.web.tsx:173 msgid "Closes the emoji picker" msgstr "" @@ -1786,7 +1782,7 @@ msgstr "" msgid "Comics" msgstr "" -#: src/Navigation.tsx:310 +#: src/Navigation.tsx:311 #: src/view/screens/CommunityGuidelines.tsx:34 msgid "Community Guidelines" msgstr "" @@ -1823,23 +1819,17 @@ msgstr "" msgid "Configured in <0>moderation settings</0>." msgstr "" -#: src/components/dialogs/VerifyEmailDialog.tsx:253 -#: src/components/dialogs/VerifyEmailDialog.tsx:260 -#: src/components/dialogs/VerifyEmailDialog.tsx:283 -#: src/components/Prompt.tsx:183 -#: src/components/Prompt.tsx:186 +#: src/components/dialogs/ChangeEmailDialog.tsx:203 +#: src/components/dialogs/ChangeEmailDialog.tsx:210 +#: src/components/dialogs/VerifyEmailDialog.tsx:316 +#: src/components/dialogs/VerifyEmailDialog.tsx:323 +#: src/components/Prompt.tsx:181 +#: src/components/Prompt.tsx:184 #: src/screens/Settings/components/DisableEmail2FADialog.tsx:185 #: src/screens/Settings/components/DisableEmail2FADialog.tsx:188 -#: src/view/com/modals/VerifyEmail.tsx:239 -#: src/view/com/modals/VerifyEmail.tsx:241 msgid "Confirm" msgstr "" -#: src/view/com/modals/ChangeEmail.tsx:188 -#: src/view/com/modals/ChangeEmail.tsx:190 -msgid "Confirm Change" -msgstr "" - #: src/view/com/modals/lang-settings/ConfirmLanguagesButton.tsx:34 msgid "Confirm content language settings" msgstr "" @@ -1856,18 +1846,18 @@ msgstr "" msgid "Confirm your birthdate" msgstr "" -#: src/components/dialogs/VerifyEmailDialog.tsx:214 +#: src/components/dialogs/ChangeEmailDialog.tsx:160 +#: src/components/dialogs/ChangeEmailDialog.tsx:164 +#: src/components/dialogs/VerifyEmailDialog.tsx:252 #: src/screens/Login/LoginForm.tsx:274 #: src/screens/Settings/components/DisableEmail2FADialog.tsx:144 #: src/screens/Settings/components/DisableEmail2FADialog.tsx:150 -#: src/view/com/modals/ChangeEmail.tsx:152 #: src/view/com/modals/DeleteAccount.tsx:220 #: src/view/com/modals/DeleteAccount.tsx:226 -#: src/view/com/modals/VerifyEmail.tsx:173 msgid "Confirmation code" msgstr "" -#: src/components/dialogs/VerifyEmailDialog.tsx:210 +#: src/components/dialogs/VerifyEmailDialog.tsx:248 msgid "Confirmation Code" msgstr "" @@ -1885,12 +1875,12 @@ msgid "Content & Media" msgstr "" #: src/screens/Settings/AccessibilitySettings.tsx:109 -#: src/screens/Settings/Settings.tsx:183 -#: src/screens/Settings/Settings.tsx:186 +#: src/screens/Settings/Settings.tsx:184 +#: src/screens/Settings/Settings.tsx:187 msgid "Content and media" msgstr "" -#: src/Navigation.tsx:384 +#: src/Navigation.tsx:385 msgid "Content and Media" msgstr "" @@ -2063,7 +2053,7 @@ msgstr "" msgid "Copy TXT record value" msgstr "" -#: src/Navigation.tsx:315 +#: src/Navigation.tsx:316 #: src/view/screens/CopyrightPolicy.tsx:31 msgid "Copyright Policy" msgstr "" @@ -2099,7 +2089,7 @@ msgstr "" #: src/components/StarterPack/ProfileStarterPacks.tsx:178 #: src/components/StarterPack/ProfileStarterPacks.tsx:274 -#: src/Navigation.tsx:460 +#: src/Navigation.tsx:461 msgid "Create a starter pack" msgstr "" @@ -2204,13 +2194,13 @@ msgstr "" msgid "Date of birth" msgstr "" -#: src/screens/Settings/AccountSettings.tsx:146 -#: src/screens/Settings/AccountSettings.tsx:151 +#: src/screens/Settings/AccountSettings.tsx:148 +#: src/screens/Settings/AccountSettings.tsx:153 #: src/screens/Settings/components/DeactivateAccountDialog.tsx:73 msgid "Deactivate account" msgstr "" -#: src/screens/Settings/Settings.tsx:382 +#: src/screens/Settings/Settings.tsx:394 msgid "Debug Moderation" msgstr "" @@ -2237,8 +2227,8 @@ msgstr "" msgid "Delete" msgstr "" -#: src/screens/Settings/AccountSettings.tsx:156 -#: src/screens/Settings/AccountSettings.tsx:161 +#: src/screens/Settings/AccountSettings.tsx:158 +#: src/screens/Settings/AccountSettings.tsx:163 msgid "Delete account" msgstr "" @@ -2259,7 +2249,7 @@ msgstr "" msgid "Delete chat" msgstr "" -#: src/screens/Settings/Settings.tsx:389 +#: src/screens/Settings/Settings.tsx:401 msgid "Delete chat declaration record" msgstr "" @@ -2370,8 +2360,8 @@ msgctxt "toast" msgid "Developer mode enabled" msgstr "" -#: src/screens/Settings/Settings.tsx:250 -#: src/screens/Settings/Settings.tsx:253 +#: src/screens/Settings/Settings.tsx:251 +#: src/screens/Settings/Settings.tsx:254 msgid "Developer options" msgstr "" @@ -2610,7 +2600,7 @@ msgstr "" msgid "Each code works once. You'll receive more invite codes periodically." msgstr "" -#: src/screens/Settings/AccountSettings.tsx:112 +#: src/screens/Settings/AccountSettings.tsx:114 #: src/screens/StarterPack/StarterPackScreen.tsx:583 #: src/screens/StarterPack/Wizard/index.tsx:534 #: src/screens/StarterPack/Wizard/index.tsx:541 @@ -2656,7 +2646,7 @@ msgstr "" msgid "Edit Moderation List" msgstr "" -#: src/Navigation.tsx:325 +#: src/Navigation.tsx:326 #: src/view/screens/Feeds.tsx:515 msgid "Edit My Feeds" msgstr "" @@ -2706,7 +2696,7 @@ msgstr "" msgid "Edit your profile description" msgstr "" -#: src/Navigation.tsx:465 +#: src/Navigation.tsx:466 msgid "Edit your starter pack" msgstr "" @@ -2719,9 +2709,8 @@ msgstr "" msgid "Either the creator of this list has blocked you or you have blocked the creator." msgstr "" -#: src/screens/Settings/AccountSettings.tsx:60 +#: src/screens/Settings/AccountSettings.tsx:62 #: src/screens/Signup/StepInfo/index.tsx:193 -#: src/view/com/modals/ChangeEmail.tsx:136 msgid "Email" msgstr "" @@ -2742,19 +2731,8 @@ msgstr "" msgid "Email Resent" msgstr "" -#: src/view/com/modals/ChangeEmail.tsx:54 -#: src/view/com/modals/ChangeEmail.tsx:83 -msgctxt "toast" -msgid "Email updated" -msgstr "" - -#: src/view/com/modals/ChangeEmail.tsx:106 -msgid "Email Updated" -msgstr "" - -#: src/view/com/modals/VerifyEmail.tsx:85 -msgctxt "toast" -msgid "Email verified" +#: src/components/dialogs/ChangeEmailDialog.tsx:63 +msgid "Email Updated!" msgstr "" #: src/components/intents/VerifyEmailIntentDialog.tsx:79 @@ -2780,8 +2758,8 @@ msgstr "" msgid "Embedded video player" msgstr "" -#: src/screens/Settings/components/Email2FAToggle.tsx:56 #: src/screens/Settings/components/Email2FAToggle.tsx:60 +#: src/screens/Settings/components/Email2FAToggle.tsx:76 msgid "Enable" msgstr "" @@ -2793,7 +2771,7 @@ msgstr "" msgid "Enable adult content" msgstr "" -#: src/screens/Settings/components/Email2FAToggle.tsx:53 +#: src/screens/Settings/components/Email2FAToggle.tsx:57 msgid "Enable Email 2FA" msgstr "" @@ -2855,14 +2833,10 @@ msgstr "" msgid "Enter a word or tag" msgstr "" -#: src/components/dialogs/VerifyEmailDialog.tsx:89 +#: src/components/dialogs/VerifyEmailDialog.tsx:118 msgid "Enter Code" msgstr "" -#: src/view/com/modals/VerifyEmail.tsx:113 -msgid "Enter Confirmation Code" -msgstr "" - #: src/view/com/util/post-embeds/VideoEmbedInner/web-controls/VideoControls.tsx:405 msgid "Enter fullscreen" msgstr "" @@ -2892,11 +2866,7 @@ msgstr "" msgid "Enter your email address" msgstr "" -#: src/view/com/modals/ChangeEmail.tsx:42 -msgid "Enter your new email above" -msgstr "" - -#: src/view/com/modals/ChangeEmail.tsx:112 +#: src/components/dialogs/ChangeEmailDialog.tsx:138 msgid "Enter your new email address below." msgstr "" @@ -3035,15 +3005,15 @@ msgstr "" msgid "Explicit sexual images." msgstr "" -#: src/Navigation.tsx:649 +#: src/Navigation.tsx:650 #: src/screens/Search/Shell.tsx:307 #: src/view/shell/desktop/LeftNav.tsx:617 #: src/view/shell/Drawer.tsx:386 msgid "Explore" msgstr "" -#: src/screens/Settings/AccountSettings.tsx:137 -#: src/screens/Settings/AccountSettings.tsx:141 +#: src/screens/Settings/AccountSettings.tsx:139 +#: src/screens/Settings/AccountSettings.tsx:143 msgid "Export my data" msgstr "" @@ -3066,7 +3036,7 @@ msgstr "" msgid "External media may allow websites to collect information about you and your device. No information is sent or requested until you press the \"play\" button." msgstr "" -#: src/Navigation.tsx:344 +#: src/Navigation.tsx:345 #: src/screens/Settings/ExternalMediaPreferences.tsx:31 msgid "External Media Preferences" msgstr "" @@ -3085,10 +3055,6 @@ msgstr "" msgid "Failed to change handle. Please try again." msgstr "" -#: src/components/verification/VerificationCreatePrompt.tsx:32 -msgid "Failed to create a verification" -msgstr "" - #: src/screens/Settings/components/AddAppPasswordDialog.tsx:173 msgid "Failed to create app password. Please try again." msgstr "" @@ -3218,7 +3184,7 @@ msgstr "" msgid "Failed to verify handle. Please try again." msgstr "" -#: src/Navigation.tsx:260 +#: src/Navigation.tsx:261 msgid "Feed" msgstr "" @@ -3247,7 +3213,7 @@ msgctxt "toast" msgid "Feedback sent!" msgstr "" -#: src/Navigation.tsx:445 +#: src/Navigation.tsx:446 #: src/screens/Search/SearchResults.tsx:68 #: src/screens/StarterPack/StarterPackScreen.tsx:185 #: src/view/screens/Feeds.tsx:508 @@ -3412,7 +3378,7 @@ msgstr "" msgid "Followed by <0>{0}</0>, <1>{1}</1>, and {2, plural, one {# other} other {# others}}" msgstr "" -#: src/Navigation.tsx:214 +#: src/Navigation.tsx:215 msgid "Followers of @{0} that you know" msgstr "" @@ -3451,7 +3417,7 @@ msgstr "" msgid "Following feed preferences" msgstr "" -#: src/Navigation.tsx:331 +#: src/Navigation.tsx:332 #: src/screens/Settings/FollowingFeedPreferences.tsx:53 msgid "Following Feed Preferences" msgstr "" @@ -3536,9 +3502,9 @@ msgstr "" msgid "Get help" msgstr "" -#: src/view/com/modals/VerifyEmail.tsx:197 -#: src/view/com/modals/VerifyEmail.tsx:199 -msgid "Get Started" +#: src/components/dialogs/VerifyEmailDialog.tsx:263 +#: src/components/dialogs/VerifyEmailDialog.tsx:269 +msgid "Get started" msgstr "" #: src/components/ProgressGuide/List.tsx:35 @@ -3633,8 +3599,8 @@ msgstr "" msgid "Half way there!" msgstr "" -#: src/screens/Settings/AccountSettings.tsx:126 -#: src/screens/Settings/AccountSettings.tsx:131 +#: src/screens/Settings/AccountSettings.tsx:128 +#: src/screens/Settings/AccountSettings.tsx:133 msgid "Handle" msgstr "" @@ -3660,7 +3626,7 @@ msgstr "" msgid "Harassment, trolling, or intolerance" msgstr "" -#: src/Navigation.tsx:415 +#: src/Navigation.tsx:416 msgid "Hashtag" msgstr "" @@ -3672,8 +3638,8 @@ msgstr "" msgid "Having trouble?" msgstr "" -#: src/screens/Settings/Settings.tsx:215 -#: src/screens/Settings/Settings.tsx:219 +#: src/screens/Settings/Settings.tsx:216 +#: src/screens/Settings/Settings.tsx:220 #: src/view/shell/desktop/RightNav.tsx:120 #: src/view/shell/desktop/RightNav.tsx:121 #: src/view/shell/Drawer.tsx:353 @@ -3812,8 +3778,8 @@ msgstr "" msgid "Hold up! We’re gradually giving access to video, and you’re still waiting in line. Check back soon!" msgstr "" -#: src/Navigation.tsx:644 -#: src/Navigation.tsx:664 +#: src/Navigation.tsx:645 +#: src/Navigation.tsx:665 #: src/view/shell/bottom-bar/BottomBar.tsx:162 #: src/view/shell/desktop/LeftNav.tsx:599 #: src/view/shell/Drawer.tsx:412 @@ -3840,25 +3806,20 @@ msgstr "" msgid "Hot replies first" msgstr "" -#: src/view/com/modals/InAppBrowserConsent.tsx:41 +#: src/components/dialogs/InAppBrowserConsent.tsx:62 +#: src/components/dialogs/InAppBrowserConsent.tsx:66 msgid "How should we open this link?" msgstr "" +#: src/components/dialogs/ChangeEmailDialog.tsx:189 +#: src/components/dialogs/ChangeEmailDialog.tsx:196 +#: src/components/dialogs/VerifyEmailDialog.tsx:302 +#: src/components/dialogs/VerifyEmailDialog.tsx:309 #: src/screens/Settings/components/DisableEmail2FADialog.tsx:133 #: src/screens/Settings/components/DisableEmail2FADialog.tsx:136 -#: src/view/com/modals/VerifyEmail.tsx:222 msgid "I have a code" msgstr "" -#: src/components/dialogs/VerifyEmailDialog.tsx:239 -#: src/components/dialogs/VerifyEmailDialog.tsx:246 -msgid "I Have a Code" -msgstr "" - -#: src/view/com/modals/VerifyEmail.tsx:224 -msgid "I have a confirmation code" -msgstr "" - #: src/screens/Settings/components/ChangeHandleDialog.tsx:280 #: src/screens/Settings/components/ChangeHandleDialog.tsx:286 msgid "I have my own domain" @@ -4095,13 +4056,13 @@ msgstr "" msgid "Language selection" msgstr "" -#: src/Navigation.tsx:187 +#: src/Navigation.tsx:188 msgid "Language Settings" msgstr "" #: src/screens/Settings/LanguageSettings.tsx:71 -#: src/screens/Settings/Settings.tsx:207 -#: src/screens/Settings/Settings.tsx:210 +#: src/screens/Settings/Settings.tsx:208 +#: src/screens/Settings/Settings.tsx:211 msgid "Languages" msgstr "" @@ -4246,8 +4207,8 @@ msgstr "" msgid "Like this labeler" msgstr "" -#: src/Navigation.tsx:265 -#: src/Navigation.tsx:270 +#: src/Navigation.tsx:266 +#: src/Navigation.tsx:271 msgid "Liked by" msgstr "" @@ -4282,7 +4243,7 @@ msgstr "" msgid "Linear" msgstr "" -#: src/Navigation.tsx:220 +#: src/Navigation.tsx:221 msgid "List" msgstr "" @@ -4340,7 +4301,7 @@ msgctxt "toast" msgid "List unmuted" msgstr "" -#: src/Navigation.tsx:141 +#: src/Navigation.tsx:142 #: src/view/screens/Lists.tsx:62 #: src/view/screens/Profile.tsx:221 #: src/view/screens/Profile.tsx:229 @@ -4376,7 +4337,7 @@ msgstr "" msgid "Loading..." msgstr "" -#: src/Navigation.tsx:290 +#: src/Navigation.tsx:291 msgid "Log" msgstr "" @@ -4450,6 +4411,11 @@ msgstr "" msgid "Marked all as read" msgstr "" +#: src/components/dialogs/VerifyEmailDialog.tsx:273 +#: src/components/dialogs/VerifyEmailDialog.tsx:281 +msgid "Maybe later" +msgstr "" + #: src/view/screens/Profile.tsx:224 msgid "Media" msgstr "" @@ -4508,7 +4474,7 @@ msgstr "" msgid "Message options" msgstr "" -#: src/Navigation.tsx:659 +#: src/Navigation.tsx:660 msgid "Messages" msgstr "" @@ -4527,10 +4493,10 @@ msgstr "" msgid "Misleading Post" msgstr "" -#: src/Navigation.tsx:146 +#: src/Navigation.tsx:147 #: src/screens/Moderation/index.tsx:93 -#: src/screens/Settings/Settings.tsx:175 -#: src/screens/Settings/Settings.tsx:178 +#: src/screens/Settings/Settings.tsx:176 +#: src/screens/Settings/Settings.tsx:179 msgid "Moderation" msgstr "" @@ -4566,7 +4532,7 @@ msgstr "" msgid "Moderation lists" msgstr "" -#: src/Navigation.tsx:151 +#: src/Navigation.tsx:152 #: src/view/screens/ModerationModlists.tsx:62 msgid "Moderation Lists" msgstr "" @@ -4575,7 +4541,7 @@ msgstr "" msgid "moderation settings" msgstr "" -#: src/Navigation.tsx:280 +#: src/Navigation.tsx:281 msgid "Moderation states" msgstr "" @@ -4698,12 +4664,12 @@ msgstr "" msgid "Muted accounts" msgstr "" -#: src/Navigation.tsx:156 -#: src/view/screens/ModerationMutedAccounts.tsx:123 +#: src/Navigation.tsx:157 +#: src/view/screens/ModerationMutedAccounts.tsx:118 msgid "Muted Accounts" msgstr "" -#: src/view/screens/ModerationMutedAccounts.tsx:135 +#: src/view/screens/ModerationMutedAccounts.tsx:204 msgid "Muted accounts have their posts removed from your feed and from your notifications. Mutes are completely private." msgstr "" @@ -4771,7 +4737,7 @@ msgstr "" msgid "Navigates to your profile" msgstr "" -#: src/components/dialogs/VerifyEmailDialog.tsx:196 +#: src/components/dialogs/VerifyEmailDialog.tsx:234 msgid "Need to change it?" msgstr "" @@ -4804,6 +4770,10 @@ msgstr "" msgid "New chat" msgstr "" +#: src/components/dialogs/ChangeEmailDialog.tsx:142 +msgid "New email address" +msgstr "" + #: src/components/dialogs/nuxs/InitialVerificationAnnouncement.tsx:63 msgid "New Feature" msgstr "" @@ -5027,16 +4997,11 @@ msgstr "" msgid "Not followed by anyone you're following" msgstr "" -#: src/Navigation.tsx:136 +#: src/Navigation.tsx:137 #: src/view/screens/Profile.tsx:122 msgid "Not Found" msgstr "" -#: src/view/com/modals/VerifyEmail.tsx:254 -#: src/view/com/modals/VerifyEmail.tsx:260 -msgid "Not right now" -msgstr "" - #: src/view/com/profile/ProfileMenu.tsx:442 #: src/view/com/util/forms/PostDropdownBtnMenuItems.tsx:791 #: src/view/com/util/post-ctrls/PostCtrls.tsx:361 @@ -5055,7 +5020,7 @@ msgstr "" msgid "Notification filters" msgstr "" -#: src/Navigation.tsx:440 +#: src/Navigation.tsx:441 #: src/view/screens/Notifications.tsx:134 msgid "Notification settings" msgstr "" @@ -5072,7 +5037,7 @@ msgstr "" msgid "Notification Sounds" msgstr "" -#: src/Navigation.tsx:654 +#: src/Navigation.tsx:655 #: src/view/screens/Notifications.tsx:128 #: src/view/shell/bottom-bar/BottomBar.tsx:236 #: src/view/shell/desktop/LeftNav.tsx:636 @@ -5135,7 +5100,7 @@ msgstr "" msgid "on<0><1/><2><3/></2></0>" msgstr "" -#: src/screens/Settings/Settings.tsx:354 +#: src/screens/Settings/Settings.tsx:355 msgid "Onboarding reset" msgstr "" @@ -5232,7 +5197,7 @@ msgstr "" msgid "Open message options" msgstr "" -#: src/screens/Settings/Settings.tsx:380 +#: src/screens/Settings/Settings.tsx:392 msgid "Open moderation debug page" msgstr "" @@ -5252,12 +5217,12 @@ msgstr "" msgid "Open starter pack menu" msgstr "" -#: src/screens/Settings/Settings.tsx:373 -#: src/screens/Settings/Settings.tsx:387 +#: src/screens/Settings/Settings.tsx:385 +#: src/screens/Settings/Settings.tsx:399 msgid "Open storybook page" msgstr "" -#: src/screens/Settings/Settings.tsx:366 +#: src/screens/Settings/Settings.tsx:378 msgid "Open system log" msgstr "" @@ -5289,7 +5254,7 @@ msgstr "" msgid "Opens captions and alt text dialog" msgstr "" -#: src/screens/Settings/AccountSettings.tsx:127 +#: src/screens/Settings/AccountSettings.tsx:129 msgid "Opens change handle dialog" msgstr "" @@ -5319,7 +5284,7 @@ msgstr "" msgid "Opens GIF select dialog" msgstr "" -#: src/screens/Settings/Settings.tsx:216 +#: src/screens/Settings/Settings.tsx:217 msgid "Opens helpdesk in browser" msgstr "" @@ -5413,8 +5378,8 @@ msgid "Page Not Found" msgstr "" #: src/screens/Login/LoginForm.tsx:228 -#: src/screens/Settings/AccountSettings.tsx:117 -#: src/screens/Settings/AccountSettings.tsx:121 +#: src/screens/Settings/AccountSettings.tsx:119 +#: src/screens/Settings/AccountSettings.tsx:123 #: src/screens/Signup/StepInfo/index.tsx:228 #: src/view/com/modals/DeleteAccount.tsx:239 #: src/view/com/modals/DeleteAccount.tsx:246 @@ -5453,11 +5418,11 @@ msgstr "" msgid "People" msgstr "" -#: src/Navigation.tsx:207 +#: src/Navigation.tsx:208 msgid "People followed by @{0}" msgstr "" -#: src/Navigation.tsx:200 +#: src/Navigation.tsx:201 msgid "People following @{0}" msgstr "" @@ -5577,10 +5542,6 @@ msgstr "" msgid "Please complete the verification captcha." msgstr "" -#: src/view/com/modals/ChangeEmail.tsx:65 -msgid "Please confirm your email before changing it. This is a temporary requirement while email-updating tools are added, and it will soon be removed." -msgstr "" - #: src/screens/Signup/StepInfo/index.tsx:109 msgid "Please double-check that you have entered your email address correctly." msgstr "" @@ -5643,7 +5604,7 @@ msgstr "" msgid "Please sign in as @{0}" msgstr "" -#: src/view/com/modals/VerifyEmail.tsx:109 +#: src/components/dialogs/VerifyEmailDialog.tsx:108 msgid "Please Verify Your Email" msgstr "" @@ -5676,10 +5637,10 @@ msgstr "" msgid "Post by {0}" msgstr "" -#: src/Navigation.tsx:233 -#: src/Navigation.tsx:240 -#: src/Navigation.tsx:247 -#: src/Navigation.tsx:254 +#: src/Navigation.tsx:234 +#: src/Navigation.tsx:241 +#: src/Navigation.tsx:248 +#: src/Navigation.tsx:255 msgid "Post by @{0}" msgstr "" @@ -5714,7 +5675,7 @@ msgstr "" msgid "Post interaction settings" msgstr "" -#: src/Navigation.tsx:167 +#: src/Navigation.tsx:168 #: src/screens/ModerationInteractionSettings/index.tsx:34 msgid "Post Interaction Settings" msgstr "" @@ -5802,17 +5763,17 @@ msgstr "" msgid "Privacy" msgstr "" -#: src/screens/Settings/Settings.tsx:169 -#: src/screens/Settings/Settings.tsx:172 +#: src/screens/Settings/Settings.tsx:170 +#: src/screens/Settings/Settings.tsx:173 msgid "Privacy and security" msgstr "" -#: src/Navigation.tsx:376 +#: src/Navigation.tsx:377 #: src/screens/Settings/PrivacyAndSecuritySettings.tsx:36 msgid "Privacy and Security" msgstr "" -#: src/Navigation.tsx:300 +#: src/Navigation.tsx:301 #: src/screens/Settings/AboutSettings.tsx:89 #: src/screens/Settings/AboutSettings.tsx:92 #: src/view/screens/PrivacyPolicy.tsx:31 @@ -6017,7 +5978,7 @@ msgstr "" #: src/components/FeedCard.tsx:343 #: src/components/StarterPack/Wizard/WizardListCard.tsx:102 #: src/components/StarterPack/Wizard/WizardListCard.tsx:109 -#: src/screens/Settings/Settings.tsx:518 +#: src/screens/Settings/Settings.tsx:537 #: src/view/com/feeds/FeedSourceCard.tsx:322 #: src/view/com/modals/UserAddRemoveLists.tsx:235 #: src/view/com/posts/PostFeedErrorMessage.tsx:213 @@ -6032,8 +5993,8 @@ msgstr "" msgid "Remove {historyItem}" msgstr "" -#: src/screens/Settings/Settings.tsx:497 -#: src/screens/Settings/Settings.tsx:500 +#: src/screens/Settings/Settings.tsx:516 +#: src/screens/Settings/Settings.tsx:519 msgid "Remove account" msgstr "" @@ -6074,7 +6035,7 @@ msgstr "" msgid "Remove from my feeds" msgstr "" -#: src/screens/Settings/Settings.tsx:510 +#: src/screens/Settings/Settings.tsx:529 msgid "Remove from quick access?" msgstr "" @@ -6377,9 +6338,9 @@ msgstr "" msgid "Reposts of this post" msgstr "" -#: src/view/com/modals/ChangeEmail.tsx:176 -#: src/view/com/modals/ChangeEmail.tsx:178 -msgid "Request Change" +#: src/components/dialogs/ChangeEmailDialog.tsx:175 +#: src/components/dialogs/ChangeEmailDialog.tsx:182 +msgid "Request change" msgstr "" #: src/view/com/modals/ChangePassword.tsx:253 @@ -6392,7 +6353,7 @@ msgstr "" msgid "Require alt text before posting" msgstr "" -#: src/screens/Settings/components/Email2FAToggle.tsx:54 +#: src/screens/Settings/components/Email2FAToggle.tsx:58 msgid "Require an email code to sign in to your account." msgstr "" @@ -6404,13 +6365,15 @@ msgstr "" msgid "Required in your region" msgstr "" +#: src/components/dialogs/ChangeEmailDialog.tsx:217 +#: src/components/dialogs/ChangeEmailDialog.tsx:227 +#: src/components/dialogs/VerifyEmailDialog.tsx:330 +#: src/components/dialogs/VerifyEmailDialog.tsx:340 #: src/screens/Settings/components/DisableEmail2FADialog.tsx:173 #: src/screens/Settings/components/DisableEmail2FADialog.tsx:176 msgid "Resend email" msgstr "" -#: src/components/dialogs/VerifyEmailDialog.tsx:267 -#: src/components/dialogs/VerifyEmailDialog.tsx:277 #: src/components/intents/VerifyEmailIntentDialog.tsx:130 msgid "Resend Email" msgstr "" @@ -6427,8 +6390,8 @@ msgstr "" msgid "Reset Code" msgstr "" -#: src/screens/Settings/Settings.tsx:394 -#: src/screens/Settings/Settings.tsx:396 +#: src/screens/Settings/Settings.tsx:406 +#: src/screens/Settings/Settings.tsx:408 msgid "Reset onboarding state" msgstr "" @@ -6597,7 +6560,7 @@ msgstr "" msgid "Search" msgstr "" -#: src/Navigation.tsx:226 +#: src/Navigation.tsx:227 #: src/screens/Profile/ProfileSearch.tsx:37 msgid "Search @{0}'s posts" msgstr "" @@ -6670,7 +6633,7 @@ msgstr "" msgid "Searches for profiles" msgstr "" -#: src/view/com/modals/ChangeEmail.tsx:105 +#: src/components/dialogs/ChangeEmailDialog.tsx:57 msgid "Security Step Required" msgstr "" @@ -6804,19 +6767,14 @@ msgstr "" msgid "Send a neat website!" msgstr "" -#: src/components/dialogs/VerifyEmailDialog.tsx:232 -msgid "Send Confirmation" +#: src/components/dialogs/VerifyEmailDialog.tsx:295 +msgid "Send confirmation" msgstr "" -#: src/components/dialogs/VerifyEmailDialog.tsx:225 +#: src/components/dialogs/VerifyEmailDialog.tsx:288 msgid "Send confirmation email" msgstr "" -#: src/view/com/modals/VerifyEmail.tsx:210 -#: src/view/com/modals/VerifyEmail.tsx:212 -msgid "Send Confirmation Email" -msgstr "" - #: src/view/com/modals/DeleteAccount.tsx:145 msgid "Send email" msgstr "" @@ -6892,8 +6850,8 @@ msgstr "" msgid "Sets email for password reset" msgstr "" -#: src/Navigation.tsx:182 -#: src/screens/Settings/Settings.tsx:88 +#: src/Navigation.tsx:183 +#: src/screens/Settings/Settings.tsx:89 #: src/view/shell/desktop/LeftNav.tsx:709 #: src/view/shell/Drawer.tsx:555 msgid "Settings" @@ -6981,7 +6939,7 @@ msgstr "" msgid "Share your favorite feed!" msgstr "" -#: src/Navigation.tsx:285 +#: src/Navigation.tsx:286 msgid "Shared Preferences Tester" msgstr "" @@ -7097,7 +7055,7 @@ msgstr "" msgid "Shows information about when this post was created" msgstr "" -#: src/screens/Settings/Settings.tsx:112 +#: src/screens/Settings/Settings.tsx:113 msgid "Shows other accounts you can switch to" msgstr "" @@ -7149,9 +7107,9 @@ msgstr "" msgid "Sign in to Bluesky or create a new account" msgstr "" -#: src/screens/Settings/Settings.tsx:233 -#: src/screens/Settings/Settings.tsx:235 -#: src/screens/Settings/Settings.tsx:267 +#: src/screens/Settings/Settings.tsx:234 +#: src/screens/Settings/Settings.tsx:236 +#: src/screens/Settings/Settings.tsx:268 #: src/screens/SignupQueued.tsx:93 #: src/screens/SignupQueued.tsx:96 #: src/screens/Takendown.tsx:85 @@ -7165,7 +7123,7 @@ msgstr "" msgid "Sign Out" msgstr "" -#: src/screens/Settings/Settings.tsx:264 +#: src/screens/Settings/Settings.tsx:265 #: src/view/shell/desktop/LeftNav.tsx:205 msgid "Sign out?" msgstr "" @@ -7197,6 +7155,10 @@ msgstr "" msgid "Smaller" msgstr "" +#: src/components/dialogs/VerifyEmailDialog.tsx:274 +msgid "Snoozes the reminder" +msgstr "" + #: src/screens/Onboarding/index.tsx:37 #: src/screens/Onboarding/state.ts:100 msgid "Software Dev" @@ -7313,8 +7275,8 @@ msgstr "" msgid "Start chat with {displayName}" msgstr "" -#: src/Navigation.tsx:450 -#: src/Navigation.tsx:455 +#: src/Navigation.tsx:451 +#: src/Navigation.tsx:456 #: src/screens/StarterPack/Wizard/index.tsx:186 msgid "Starter Pack" msgstr "" @@ -7354,12 +7316,12 @@ msgstr "" msgid "Step {0} of {1}" msgstr "" -#: src/screens/Settings/Settings.tsx:359 +#: src/screens/Settings/Settings.tsx:360 msgid "Storage cleared, you need to restart the app now." msgstr "" -#: src/Navigation.tsx:275 -#: src/screens/Settings/Settings.tsx:375 +#: src/Navigation.tsx:276 +#: src/screens/Settings/Settings.tsx:387 msgid "Storybook" msgstr "" @@ -7404,11 +7366,11 @@ msgstr "" msgid "Subscribe to this list" msgstr "" -#: src/components/dialogs/VerifyEmailDialog.tsx:95 +#: src/components/dialogs/VerifyEmailDialog.tsx:124 msgid "Success!" msgstr "" -#: src/components/verification/VerificationCreatePrompt.tsx:30 +#: src/components/verification/VerificationCreatePrompt.tsx:36 msgid "Successfully verified" msgstr "" @@ -7435,15 +7397,15 @@ msgctxt "Name of app icon variant" msgid "Sunset" msgstr "" -#: src/Navigation.tsx:295 +#: src/Navigation.tsx:296 #: src/view/screens/Support.tsx:31 #: src/view/screens/Support.tsx:34 msgid "Support" msgstr "" -#: src/screens/Settings/Settings.tsx:110 -#: src/screens/Settings/Settings.tsx:124 -#: src/screens/Settings/Settings.tsx:462 +#: src/screens/Settings/Settings.tsx:111 +#: src/screens/Settings/Settings.tsx:125 +#: src/screens/Settings/Settings.tsx:481 #: src/view/shell/desktop/LeftNav.tsx:243 msgid "Switch account" msgstr "" @@ -7470,7 +7432,7 @@ msgstr "" #: src/screens/Settings/AboutSettings.tsx:104 #: src/screens/Settings/AboutSettings.tsx:107 -#: src/screens/Settings/Settings.tsx:368 +#: src/screens/Settings/Settings.tsx:380 msgid "System log" msgstr "" @@ -7522,7 +7484,7 @@ msgstr "" msgid "Terms" msgstr "" -#: src/Navigation.tsx:305 +#: src/Navigation.tsx:306 #: src/screens/Settings/AboutSettings.tsx:81 #: src/screens/Settings/AboutSettings.tsx:84 #: src/view/screens/TermsOfService.tsx:31 @@ -7555,7 +7517,7 @@ msgstr "" msgid "Text input field" msgstr "" -#: src/components/dialogs/VerifyEmailDialog.tsx:96 +#: src/components/dialogs/VerifyEmailDialog.tsx:125 msgid "Thank you! Your email has been successfully verified." msgstr "" @@ -7627,6 +7589,10 @@ msgstr "" msgid "The Discover feed now knows what you like" msgstr "" +#: src/components/dialogs/ChangeEmailDialog.tsx:74 +msgid "The email address you entered is the same as your current email address." +msgstr "" + #: src/screens/StarterPack/StarterPackLandingScreen.tsx:324 msgid "The experience is better in the app. Download Bluesky now and we'll pick back up where you left off." msgstr "" @@ -7815,7 +7781,7 @@ msgstr "" msgid "This account is blocked by one or more of your moderation lists. To unblock, please visit the lists directly and remove this user." msgstr "" -#: src/components/verification/VerificationCreatePrompt.tsx:48 +#: src/components/verification/VerificationCreatePrompt.tsx:55 msgid "This action can be undone at any time." msgstr "" @@ -7890,10 +7856,6 @@ msgstr "" msgid "This information is not shared with other users." msgstr "" -#: src/view/com/modals/VerifyEmail.tsx:127 -msgid "This is important in case you ever need to change your email or reset your password." -msgstr "" - #: src/components/moderation/ModerationDetailsDialog.tsx:168 msgid "This label was applied by the author." msgstr "" @@ -7967,6 +7929,10 @@ msgstr "" msgid "This should create a domain record at:" msgstr "" +#: src/components/verification/VerificationCreatePrompt.tsx:93 +msgid "This user does not have a display name, and therefore cannot be verified." +msgstr "" + #: src/view/com/profile/ProfileFollowers.tsx:95 msgid "This user doesn't have any followers." msgstr "" @@ -8004,7 +7970,7 @@ msgstr "" msgid "This will delete \"{0}\" from your muted words. You can always add it back later." msgstr "" -#: src/screens/Settings/Settings.tsx:512 +#: src/screens/Settings/Settings.tsx:531 msgid "This will remove @{0} from the quick access list." msgstr "" @@ -8035,7 +8001,7 @@ msgstr "" msgid "Threaded mode" msgstr "" -#: src/Navigation.tsx:338 +#: src/Navigation.tsx:339 msgid "Threads Preferences" msgstr "" @@ -8081,7 +8047,7 @@ msgstr "" msgid "Top" msgstr "" -#: src/Navigation.tsx:420 +#: src/Navigation.tsx:421 msgid "Topic" msgstr "" @@ -8302,6 +8268,11 @@ msgstr "" msgid "Unpinned from your feeds" msgstr "" +#: src/screens/Settings/Settings.tsx:413 +#: src/screens/Settings/Settings.tsx:415 +msgid "Unsnooze email reminder" +msgstr "" + #: src/screens/Profile/Header/ProfileHeaderLabeler.tsx:246 msgid "Unsubscribe" msgstr "" @@ -8410,8 +8381,8 @@ msgstr "" msgid "Use default provider" msgstr "" -#: src/view/com/modals/InAppBrowserConsent.tsx:53 -#: src/view/com/modals/InAppBrowserConsent.tsx:55 +#: src/components/dialogs/InAppBrowserConsent.tsx:77 +#: src/components/dialogs/InAppBrowserConsent.tsx:83 msgid "Use in-app browser" msgstr "" @@ -8420,8 +8391,8 @@ msgstr "" msgid "Use in-app browser to open links" msgstr "" -#: src/view/com/modals/InAppBrowserConsent.tsx:63 -#: src/view/com/modals/InAppBrowserConsent.tsx:65 +#: src/components/dialogs/InAppBrowserConsent.tsx:87 +#: src/components/dialogs/InAppBrowserConsent.tsx:93 msgid "Use my default browser" msgstr "" @@ -8514,11 +8485,15 @@ msgstr "" msgid "Value:" msgstr "" +#: src/components/verification/VerificationCreatePrompt.tsx:39 +msgid "Verification failed, please try again." +msgstr "" + #: src/screens/Moderation/index.tsx:288 msgid "Verification settings" msgstr "" -#: src/Navigation.tsx:175 +#: src/Navigation.tsx:176 #: src/screens/Moderation/VerificationSettings.tsx:32 msgid "Verification Settings" msgstr "" @@ -8535,7 +8510,8 @@ msgstr "" msgid "Verified email required" msgstr "" -#: src/components/verification/VerificationCreatePrompt.tsx:65 +#: src/components/verification/VerificationCreatePrompt.tsx:84 +#: src/components/verification/VerificationCreatePrompt.tsx:86 #: src/view/com/profile/ProfileMenu.tsx:308 #: src/view/com/profile/ProfileMenu.tsx:311 msgid "Verify account" @@ -8546,14 +8522,15 @@ msgstr "" msgid "Verify DNS Record" msgstr "" -#: src/components/dialogs/VerifyEmailDialog.tsx:134 -#: src/components/intents/VerifyEmailIntentDialog.tsx:67 -msgid "Verify email dialog" +#: src/components/dialogs/ChangeEmailDialog.tsx:234 +#: src/components/dialogs/ChangeEmailDialog.tsx:240 +msgid "Verify email" msgstr "" -#: src/view/com/modals/ChangeEmail.tsx:200 -#: src/view/com/modals/ChangeEmail.tsx:202 -msgid "Verify New Email" +#: src/components/dialogs/ChangeEmailDialog.tsx:122 +#: src/components/dialogs/VerifyEmailDialog.tsx:163 +#: src/components/intents/VerifyEmailIntentDialog.tsx:67 +msgid "Verify email dialog" msgstr "" #: src/view/com/composer/videos/SelectVideoBtn.tsx:131 @@ -8565,17 +8542,16 @@ msgstr "" msgid "Verify Text File" msgstr "" -#: src/components/verification/VerificationCreatePrompt.tsx:44 +#: src/components/verification/VerificationCreatePrompt.tsx:51 msgid "Verify this account?" msgstr "" -#: src/screens/Settings/AccountSettings.tsx:75 -#: src/screens/Settings/AccountSettings.tsx:91 +#: src/screens/Settings/AccountSettings.tsx:77 +#: src/screens/Settings/AccountSettings.tsx:93 msgid "Verify your email" msgstr "" -#: src/components/dialogs/VerifyEmailDialog.tsx:85 -#: src/view/com/modals/VerifyEmail.tsx:111 +#: src/components/dialogs/VerifyEmailDialog.tsx:114 msgid "Verify Your Email" msgstr "" @@ -8593,7 +8569,7 @@ msgstr "" msgid "Video failed to process" msgstr "" -#: src/Navigation.tsx:471 +#: src/Navigation.tsx:472 msgid "Video Feed" msgstr "" @@ -9170,11 +9146,11 @@ msgstr "" msgid "You have no lists." msgstr "" -#: src/view/screens/ModerationBlockedAccounts.tsx:138 +#: src/view/screens/ModerationBlockedAccounts.tsx:164 msgid "You have not blocked any accounts yet. To block an account, go to their profile and select \"Block account\" from the menu on their account." msgstr "" -#: src/view/screens/ModerationMutedAccounts.tsx:151 +#: src/view/screens/ModerationMutedAccounts.tsx:179 msgid "You have not muted any accounts yet. To mute an account, go to their profile and select \"Mute account\" from the menu on their account." msgstr "" @@ -9239,10 +9215,18 @@ msgstr "" msgid "You must select at least one labeler for a report" msgstr "" +#: src/screens/Settings/components/Email2FAToggle.tsx:67 +msgid "You need to verify your email address before you can enable email 2FA." +msgstr "" + #: src/screens/Deactivated.tsx:128 msgid "You previously deactivated @{0}." msgstr "" +#: src/screens/Settings/Settings.tsx:371 +msgid "You probably want to restart the app now." +msgstr "" + #: src/components/dms/MessageItem.tsx:135 msgid "You reacted {0}" msgstr "" @@ -9251,7 +9235,7 @@ msgstr "" msgid "You reacted {0} to {1}" msgstr "" -#: src/screens/Settings/Settings.tsx:265 +#: src/screens/Settings/Settings.tsx:266 #: src/view/shell/desktop/LeftNav.tsx:206 msgid "You will be signed out of all your accounts." msgstr "" @@ -9296,7 +9280,7 @@ msgstr "" msgid "You'll follow these people right away" msgstr "" -#: src/components/dialogs/VerifyEmailDialog.tsx:178 +#: src/components/dialogs/VerifyEmailDialog.tsx:216 msgid "You'll receive an email at <0>{0}</0> to verify it's you." msgstr "" @@ -9382,14 +9366,18 @@ msgstr "" msgid "Your chats have been disabled" msgstr "" -#: src/view/com/modals/InAppBrowserConsent.tsx:44 -msgid "Your choice will be saved, but can be changed later in settings." +#: src/components/dialogs/InAppBrowserConsent.tsx:69 +msgid "Your choice will be remembered for future links. You can change it at any time in settings." msgstr "" #: src/screens/Settings/components/ChangeHandleDialog.tsx:513 msgid "Your current handle <0>{0}</0> will automatically remain reserved for you. You can switch back to it at any time from this account." msgstr "" +#: src/components/dialogs/ChangeEmailDialog.tsx:65 +msgid "Your email address has been updated but it is not yet verified. As a next step, please verify your new email." +msgstr "" + #: src/screens/Login/ForgotPasswordForm.tsx:51 #: src/screens/Signup/state.ts:270 #: src/screens/Signup/StepInfo/index.tsx:98 @@ -9397,11 +9385,7 @@ msgstr "" msgid "Your email appears to be invalid." msgstr "" -#: src/view/com/modals/ChangeEmail.tsx:120 -msgid "Your email has been updated but not verified. As a next step, please verify your new email." -msgstr "" - -#: src/view/com/modals/VerifyEmail.tsx:122 +#: src/components/dialogs/VerifyEmailDialog.tsx:110 msgid "Your email has not yet been verified. This is an important security step which we recommend." msgstr "" @@ -9425,7 +9409,7 @@ msgstr "" msgid "Your full username will be <0>@{0}</0>" msgstr "" -#: src/Navigation.tsx:392 +#: src/Navigation.tsx:393 #: src/screens/Search/modules/ExploreInterestsCard.tsx:67 #: src/screens/Settings/ContentAndMediaSettings.tsx:92 #: src/screens/Settings/ContentAndMediaSettings.tsx:95 diff --git a/src/screens/Messages/components/MessageInput.tsx b/src/screens/Messages/components/MessageInput.tsx index 69cba07f7..6cde1d4fe 100644 --- a/src/screens/Messages/components/MessageInput.tsx +++ b/src/screens/Messages/components/MessageInput.tsx @@ -24,7 +24,7 @@ import { useMessageDraft, useSaveMessageDraft, } from '#/state/messages/message-drafts' -import {type EmojiPickerPosition} from '#/view/com/composer/text-input/web/EmojiPicker.web' +import {type EmojiPickerPosition} from '#/view/com/composer/text-input/web/EmojiPicker' import * as Toast from '#/view/com/util/Toast' import {android, atoms as a, useTheme} from '#/alf' import {useSharedInputStyles} from '#/components/forms/TextField' diff --git a/src/screens/Messages/components/MessageInput.web.tsx b/src/screens/Messages/components/MessageInput.web.tsx index bac163685..0dce99ad6 100644 --- a/src/screens/Messages/components/MessageInput.web.tsx +++ b/src/screens/Messages/components/MessageInput.web.tsx @@ -15,9 +15,9 @@ import { } from '#/state/messages/message-drafts' import {textInputWebEmitter} from '#/view/com/composer/text-input/textInputWebEmitter' import { - Emoji, - EmojiPickerPosition, -} from '#/view/com/composer/text-input/web/EmojiPicker.web' + type Emoji, + type EmojiPickerPosition, +} from '#/view/com/composer/text-input/web/EmojiPicker' import * as Toast from '#/view/com/util/Toast' import {atoms as a, useTheme} from '#/alf' import {Button} from '#/components/Button' diff --git a/src/screens/Messages/components/MessagesList.tsx b/src/screens/Messages/components/MessagesList.tsx index b400bc578..ce33ca3aa 100644 --- a/src/screens/Messages/components/MessagesList.tsx +++ b/src/screens/Messages/components/MessagesList.tsx @@ -1,5 +1,5 @@ import {useCallback, useEffect, useRef, useState} from 'react' -import {LayoutChangeEvent, View} from 'react-native' +import {type LayoutChangeEvent, View} from 'react-native' import {useKeyboardHandler} from 'react-native-keyboard-controller' import Animated, { runOnJS, @@ -8,10 +8,10 @@ import Animated, { useAnimatedStyle, useSharedValue, } from 'react-native-reanimated' -import {ReanimatedScrollEvent} from 'react-native-reanimated/lib/typescript/hook/commonTypes' +import {type ReanimatedScrollEvent} from 'react-native-reanimated/lib/typescript/hook/commonTypes' import { - $Typed, - AppBskyEmbedRecord, + type $Typed, + type AppBskyEmbedRecord, AppBskyRichtextFacet, RichText, } from '@atproto/api' @@ -26,19 +26,23 @@ import {logger} from '#/logger' import {isNative} from '#/platform/detection' import {isWeb} from '#/platform/detection' import { - ActiveConvoStates, + type ActiveConvoStates, isConvoActive, useConvoActive, } from '#/state/messages/convo' -import {ConvoItem, ConvoState, ConvoStatus} from '#/state/messages/convo/types' +import { + type ConvoItem, + type ConvoState, + ConvoStatus, +} from '#/state/messages/convo/types' import {useGetPost} from '#/state/queries/post' import {useAgent} from '#/state/session' import {useShellLayout} from '#/state/shell/shell-layout' import { EmojiPicker, - EmojiPickerState, -} from '#/view/com/composer/text-input/web/EmojiPicker.web' -import {List, ListMethods} from '#/view/com/util/List' + type EmojiPickerState, +} from '#/view/com/composer/text-input/web/EmojiPicker' +import {List, type ListMethods} from '#/view/com/util/List' import {ChatDisabled} from '#/screens/Messages/components/ChatDisabled' import {MessageInput} from '#/screens/Messages/components/MessageInput' import {MessageListError} from '#/screens/Messages/components/MessageListError' diff --git a/src/screens/Search/modules/ExploreTrendingTopics.tsx b/src/screens/Search/modules/ExploreTrendingTopics.tsx index 167f6d193..1d3bc2d86 100644 --- a/src/screens/Search/modules/ExploreTrendingTopics.tsx +++ b/src/screens/Search/modules/ExploreTrendingTopics.tsx @@ -265,12 +265,12 @@ export function TrendingTopicRowSkeleton({}: {withPosts: boolean}) { style={[a.rounded_full]} /> </View> - <LoadingPlaceholder width={90} height={18} /> + <LoadingPlaceholder width={90} height={17} /> </View> <View style={[a.flex_row, a.gap_sm, a.align_center, {paddingLeft: 20}]}> - <LoadingPlaceholder width={70} height={18} /> - <LoadingPlaceholder width={40} height={18} /> - <LoadingPlaceholder width={60} height={18} /> + <LoadingPlaceholder width={70} height={16} /> + <LoadingPlaceholder width={40} height={16} /> + <LoadingPlaceholder width={60} height={16} /> </View> </View> <View style={[a.flex_shrink_0]}> diff --git a/src/state/gallery.ts b/src/state/gallery.ts index f4c8b712e..f03ed2afe 100644 --- a/src/state/gallery.ts +++ b/src/state/gallery.ts @@ -5,8 +5,8 @@ import { moveAsync, } from 'expo-file-system' import { - Action, - ActionCrop, + type Action, + type ActionCrop, manipulateAsync, SaveFormat, } from 'expo-image-manipulator' @@ -210,17 +210,21 @@ export async function compressImage(img: ComposerImage): Promise<ImageMeta> { const source = img.transformed || img.source const [w, h] = containImageRes(source.width, source.height, POST_IMG_MAX) - const cacheDir = isNative && getImageCacheDirectory() - for (let i = 10; i > 0; i--) { - // Float precision - const factor = i / 10 + let minQualityPercentage = 0 + let maxQualityPercentage = 101 // exclusive + let newDataUri + + while (maxQualityPercentage - minQualityPercentage > 1) { + const qualityPercentage = Math.round( + (maxQualityPercentage + minQualityPercentage) / 2, + ) const res = await manipulateAsync( source.path, [{resize: {width: w, height: h}}], { - compress: factor, + compress: qualityPercentage / 100, format: SaveFormat.JPEG, base64: true, }, @@ -229,17 +233,20 @@ export async function compressImage(img: ComposerImage): Promise<ImageMeta> { const base64 = res.base64 if (base64 !== undefined && getDataUriSize(base64) <= POST_IMG_MAX.size) { - return { + minQualityPercentage = qualityPercentage + newDataUri = { path: await moveIfNecessary(res.uri), width: res.width, height: res.height, mime: 'image/jpeg', } + } else { + maxQualityPercentage = qualityPercentage } + } - if (cacheDir) { - await deleteAsync(res.uri) - } + if (newDataUri) { + return newDataUri } throw new Error(`Unable to compress image`) diff --git a/src/state/modals/index.tsx b/src/state/modals/index.tsx index 45c4fb467..f79f6213f 100644 --- a/src/state/modals/index.tsx +++ b/src/state/modals/index.tsx @@ -66,11 +66,6 @@ export interface LinkWarningModal { share?: boolean } -export interface InAppBrowserConsentModal { - name: 'in-app-browser-consent' - href: string -} - export type Modal = // Account | DeleteAccountModal @@ -96,7 +91,6 @@ export type Modal = // Generic | LinkWarningModal - | InAppBrowserConsentModal const ModalContext = React.createContext<{ isModalActive: boolean diff --git a/src/state/shell/composer/index.tsx b/src/state/shell/composer/index.tsx index 33634c047..b425873fc 100644 --- a/src/state/shell/composer/index.tsx +++ b/src/state/shell/composer/index.tsx @@ -1,8 +1,8 @@ import React from 'react' import { - AppBskyActorDefs, - AppBskyFeedDefs, - ModerationDecision, + type AppBskyActorDefs, + type AppBskyFeedDefs, + type ModerationDecision, } from '@atproto/api' import {msg} from '@lingui/macro' import {useLingui} from '@lingui/react' @@ -12,7 +12,7 @@ import {useNonReactiveCallback} from '#/lib/hooks/useNonReactiveCallback' import {postUriToRelativePath, toBskyAppUrl} from '#/lib/strings/url-helpers' import {purgeTemporaryImageFiles} from '#/state/gallery' import {precacheResolveLinkQuery} from '#/state/queries/resolve-link' -import type {EmojiPickerPosition} from '#/view/com/composer/text-input/web/EmojiPicker.web' +import {type EmojiPickerPosition} from '#/view/com/composer/text-input/web/EmojiPicker' import * as Toast from '#/view/com/util/Toast' export interface ComposerOptsPostRef { diff --git a/src/view/com/composer/text-input/TextInput.web.tsx b/src/view/com/composer/text-input/TextInput.web.tsx index 8ec4fefa8..06ff9836c 100644 --- a/src/view/com/composer/text-input/TextInput.web.tsx +++ b/src/view/com/composer/text-input/TextInput.web.tsx @@ -12,14 +12,14 @@ import {Placeholder} from '@tiptap/extension-placeholder' import {Text as TiptapText} from '@tiptap/extension-text' import {generateJSON} from '@tiptap/html' import {Fragment, Node, Slice} from '@tiptap/pm/model' -import {EditorContent, JSONContent, useEditor} from '@tiptap/react' +import {EditorContent, type JSONContent, useEditor} from '@tiptap/react' import {useColorSchemeStyle} from '#/lib/hooks/useColorSchemeStyle' import {usePalette} from '#/lib/hooks/usePalette' import {blobToDataUri, isUriImage} from '#/lib/media/util' import {useActorAutocompleteFn} from '#/state/queries/actor-autocomplete' import { - LinkFacetMatch, + type LinkFacetMatch, suggestLinkCardUri, } from '#/view/com/composer/text-input/text-input-util' import {textInputWebEmitter} from '#/view/com/composer/text-input/textInputWebEmitter' @@ -28,7 +28,7 @@ import {normalizeTextStyles} from '#/alf/typography' import {Portal} from '#/components/Portal' import {Text} from '../../util/text/Text' import {createSuggestion} from './web/Autocomplete' -import {Emoji} from './web/EmojiPicker.web' +import {type Emoji} from './web/EmojiPicker' import {LinkDecorator} from './web/LinkDecorator' import {TagDecorator} from './web/TagDecorator' diff --git a/src/view/com/composer/text-input/web/EmojiPicker.tsx b/src/view/com/composer/text-input/web/EmojiPicker.tsx new file mode 100644 index 000000000..5001753a5 --- /dev/null +++ b/src/view/com/composer/text-input/web/EmojiPicker.tsx @@ -0,0 +1,37 @@ +export type Emoji = { + aliases?: string[] + emoticons: string[] + id: string + keywords: string[] + name: string + native: string + shortcodes?: string + unified: string +} + +export interface EmojiPickerPosition { + top: number + left: number + right: number + bottom: number + nextFocusRef: React.MutableRefObject<HTMLElement> | null +} + +export interface EmojiPickerState { + isOpen: boolean + pos: EmojiPickerPosition +} + +interface IProps { + state: EmojiPickerState + close: () => void + /** + * If `true`, overrides position and ensures picker is pinned to the top of + * the target element. + */ + pinToTop?: boolean +} + +export function EmojiPicker(_opts: IProps) { + return null +} diff --git a/src/view/com/composer/text-input/web/EmojiPicker.web.tsx b/src/view/com/composer/text-input/web/EmojiPicker.web.tsx index b3659f22d..c0cae620f 100644 --- a/src/view/com/composer/text-input/web/EmojiPicker.web.tsx +++ b/src/view/com/composer/text-input/web/EmojiPicker.web.tsx @@ -3,8 +3,7 @@ import {Pressable, useWindowDimensions, View} from 'react-native' import Picker from '@emoji-mart/react' import {msg} from '@lingui/macro' import {useLingui} from '@lingui/react' -import {DismissableLayer} from '@radix-ui/react-dismissable-layer' -import {FocusScope} from '@radix-ui/react-focus-scope' +import {DismissableLayer, FocusScope} from 'radix-ui/internal' import {textInputWebEmitter} from '#/view/com/composer/text-input/textInputWebEmitter' import {atoms as a, flatten} from '#/alf' @@ -121,7 +120,7 @@ export function EmojiPicker({state, close, pinToTop}: IProps) { return ( <Portal> - <FocusScope + <FocusScope.FocusScope loop trapped onUnmountAutoFocus={e => { @@ -154,7 +153,7 @@ export function EmojiPicker({state, close, pinToTop}: IProps) { }, ])}> <View style={[{position: 'absolute'}, position]}> - <DismissableLayer + <DismissableLayer.DismissableLayer onFocusOutside={evt => evt.preventDefault()} onDismiss={close}> <Picker @@ -164,7 +163,7 @@ export function EmojiPicker({state, close, pinToTop}: IProps) { onEmojiSelect={onInsert} autoFocus={true} /> - </DismissableLayer> + </DismissableLayer.DismissableLayer> </View> </View> @@ -175,7 +174,7 @@ export function EmojiPicker({state, close, pinToTop}: IProps) { onPress={close} style={[a.fixed, a.inset_0]} /> - </FocusScope> + </FocusScope.FocusScope> </Portal> ) } diff --git a/src/view/com/modals/InAppBrowserConsent.tsx b/src/view/com/modals/InAppBrowserConsent.tsx deleted file mode 100644 index 105edfbc6..000000000 --- a/src/view/com/modals/InAppBrowserConsent.tsx +++ /dev/null @@ -1,99 +0,0 @@ -import React from 'react' -import {StyleSheet, View} from 'react-native' -import {msg, Trans} from '@lingui/macro' -import {useLingui} from '@lingui/react' - -import {useOpenLink} from '#/lib/hooks/useOpenLink' -import {usePalette} from '#/lib/hooks/usePalette' -import {s} from '#/lib/styles' -import {useModalControls} from '#/state/modals' -import {useSetInAppBrowser} from '#/state/preferences/in-app-browser' -import {ScrollView} from '#/view/com/modals/util' -import {Button} from '#/view/com/util/forms/Button' -import {Text} from '#/view/com/util/text/Text' - -export const snapPoints = [350] - -export function Component({href}: {href: string}) { - const pal = usePalette('default') - const {closeModal} = useModalControls() - const {_} = useLingui() - const setInAppBrowser = useSetInAppBrowser() - const openLink = useOpenLink() - - const onUseIAB = React.useCallback(() => { - setInAppBrowser(true) - closeModal() - openLink(href, true) - }, [closeModal, setInAppBrowser, href, openLink]) - - const onUseLinking = React.useCallback(() => { - setInAppBrowser(false) - closeModal() - openLink(href, false) - }, [closeModal, setInAppBrowser, href, openLink]) - - return ( - <ScrollView - testID="inAppBrowserConsentModal" - style={[s.flex1, pal.view, {paddingHorizontal: 20, paddingTop: 10}]}> - <Text style={[pal.text, styles.title]}> - <Trans>How should we open this link?</Trans> - </Text> - <Text style={pal.text}> - <Trans> - Your choice will be saved, but can be changed later in settings. - </Trans> - </Text> - <View style={[styles.btnContainer]}> - <Button - testID="confirmBtn" - type="inverted" - onPress={onUseIAB} - accessibilityLabel={_(msg`Use in-app browser`)} - accessibilityHint="" - label={_(msg`Use in-app browser`)} - labelContainerStyle={{justifyContent: 'center', padding: 8}} - labelStyle={[s.f18]} - /> - <Button - testID="confirmBtn" - type="inverted" - onPress={onUseLinking} - accessibilityLabel={_(msg`Use my default browser`)} - accessibilityHint="" - label={_(msg`Use my default browser`)} - labelContainerStyle={{justifyContent: 'center', padding: 8}} - labelStyle={[s.f18]} - /> - <Button - testID="cancelBtn" - type="default" - onPress={() => { - closeModal() - }} - accessibilityLabel={_(msg`Cancel`)} - accessibilityHint="" - label={_(msg`Cancel`)} - labelContainerStyle={{justifyContent: 'center', padding: 8}} - labelStyle={[s.f18]} - /> - </View> - </ScrollView> - ) -} - -const styles = StyleSheet.create({ - title: { - textAlign: 'center', - fontWeight: '600', - fontSize: 24, - marginBottom: 12, - }, - btnContainer: { - marginTop: 20, - flexDirection: 'column', - justifyContent: 'center', - rowGap: 10, - }, -}) diff --git a/src/view/com/modals/Modal.tsx b/src/view/com/modals/Modal.tsx index d0b50c857..8fd927f16 100644 --- a/src/view/com/modals/Modal.tsx +++ b/src/view/com/modals/Modal.tsx @@ -11,7 +11,6 @@ import * as ChangePasswordModal from './ChangePassword' import * as CreateOrEditListModal from './CreateOrEditList' import * as DeleteAccountModal from './DeleteAccount' import * as EditProfileModal from './EditProfile' -import * as InAppBrowserConsentModal from './InAppBrowserConsent' import * as InviteCodesModal from './InviteCodes' import * as ContentLanguagesSettingsModal from './lang-settings/ContentLanguagesSettings' import * as PostLanguagesSettingsModal from './lang-settings/PostLanguagesSettings' @@ -76,9 +75,6 @@ export function ModalsContainer() { } else if (activeModal?.name === 'link-warning') { snapPoints = LinkWarningModal.snapPoints element = <LinkWarningModal.Component {...activeModal} /> - } else if (activeModal?.name === 'in-app-browser-consent') { - snapPoints = InAppBrowserConsentModal.snapPoints - element = <InAppBrowserConsentModal.Component {...activeModal} /> } else { return null } diff --git a/src/view/com/util/PostMeta.tsx b/src/view/com/util/PostMeta.tsx index d5af32236..fd8e3a38b 100644 --- a/src/view/com/util/PostMeta.tsx +++ b/src/view/com/util/PostMeta.tsx @@ -107,11 +107,11 @@ let PostMeta = (opts: PostMetaOpts): React.ReactNode => { a.pl_2xs, a.self_center, { - marginTop: platform({web: -1, ios: -1, android: -2}), + marginTop: platform({web: 0, ios: 0, android: -1}), }, ]}> <VerificationCheck - width={14} + width={platform({android: 13, default: 12})} verifier={verification.role === 'verifier'} /> </View> diff --git a/src/view/com/util/forms/NativeDropdown.web.tsx b/src/view/com/util/forms/NativeDropdown.web.tsx index b3ec319e3..9b4a84e05 100644 --- a/src/view/com/util/forms/NativeDropdown.web.tsx +++ b/src/view/com/util/forms/NativeDropdown.web.tsx @@ -1,9 +1,15 @@ import React from 'react' -import {Pressable, StyleSheet, Text, View, ViewStyle} from 'react-native' -import {IconProp} from '@fortawesome/fontawesome-svg-core' +import { + Pressable, + StyleSheet, + Text, + type View, + type ViewStyle, +} from 'react-native' +import {type IconProp} from '@fortawesome/fontawesome-svg-core' import {FontAwesomeIcon} from '@fortawesome/react-native-fontawesome' -import * as DropdownMenu from '@radix-ui/react-dropdown-menu' -import {MenuItemCommonProps} from 'zeego/lib/typescript/menu' +import {DropdownMenu} from 'radix-ui' +import {type MenuItemCommonProps} from 'zeego/lib/typescript/menu' import {HITSLOP_10} from '#/lib/constants' import {usePalette} from '#/lib/hooks/usePalette' diff --git a/src/view/screens/ModerationBlockedAccounts.tsx b/src/view/screens/ModerationBlockedAccounts.tsx index cefa29f6c..bb94f8083 100644 --- a/src/view/screens/ModerationBlockedAccounts.tsx +++ b/src/view/screens/ModerationBlockedAccounts.tsx @@ -1,19 +1,10 @@ -import React from 'react' -import { - ActivityIndicator, - FlatList, - RefreshControl, - StyleSheet, - View, -} from 'react-native' +import {useCallback, useMemo, useState} from 'react' +import {type StyleProp, View, type ViewStyle} from 'react-native' import {type AppBskyActorDefs as ActorDefs} from '@atproto/api' -import {msg, Trans} from '@lingui/macro' -import {useLingui} from '@lingui/react' +import {Trans} from '@lingui/macro' import {useFocusEffect} from '@react-navigation/native' import {type NativeStackScreenProps} from '@react-navigation/native-stack' -import {usePalette} from '#/lib/hooks/usePalette' -import {useWebMediaQueries} from '#/lib/hooks/useWebMediaQueries' import {type CommonNavigatorParams} from '#/lib/routes/types' import {cleanError} from '#/lib/strings/errors' import {logger} from '#/logger' @@ -21,11 +12,12 @@ import {useModerationOpts} from '#/state/preferences/moderation-opts' import {useMyBlockedAccountsQuery} from '#/state/queries/my-blocked-accounts' import {useSetMinimalShellMode} from '#/state/shell' import {ErrorScreen} from '#/view/com/util/error/ErrorScreen' -import {Text} from '#/view/com/util/text/Text' -import {ViewHeader} from '#/view/com/util/ViewHeader' +import {List} from '#/view/com/util/List' import {atoms as a, useTheme} from '#/alf' import * as Layout from '#/components/Layout' +import {ListFooter} from '#/components/Lists' import * as ProfileCard from '#/components/ProfileCard' +import {Text} from '#/components/Typography' type Props = NativeStackScreenProps< CommonNavigatorParams, @@ -33,13 +25,10 @@ type Props = NativeStackScreenProps< > export function ModerationBlockedAccounts({}: Props) { const t = useTheme() - const pal = usePalette('default') - const {_} = useLingui() const setMinimalShellMode = useSetMinimalShellMode() - const {isTabletOrDesktop} = useWebMediaQueries() const moderationOpts = useModerationOpts() - const [isPTRing, setIsPTRing] = React.useState(false) + const [isPTRing, setIsPTRing] = useState(false) const { data, isFetching, @@ -51,7 +40,7 @@ export function ModerationBlockedAccounts({}: Props) { isFetchingNextPage, } = useMyBlockedAccountsQuery() const isEmpty = !isFetching && !data?.pages[0]?.blocks.length - const profiles = React.useMemo(() => { + const profiles = useMemo(() => { if (data?.pages) { return data.pages.flatMap(page => page.blocks) } @@ -59,12 +48,12 @@ export function ModerationBlockedAccounts({}: Props) { }, [data]) useFocusEffect( - React.useCallback(() => { + useCallback(() => { setMinimalShellMode(false) }, [setMinimalShellMode]), ) - const onRefresh = React.useCallback(async () => { + const onRefresh = useCallback(async () => { setIsPTRing(true) try { await refetch() @@ -74,7 +63,7 @@ export function ModerationBlockedAccounts({}: Props) { setIsPTRing(false) }, [refetch, setIsPTRing]) - const onEndReached = React.useCallback(async () => { + const onEndReached = useCallback(async () => { if (isFetching || !hasNextPage || isError) return try { @@ -104,28 +93,22 @@ export function ModerationBlockedAccounts({}: Props) { </View> ) } + return ( <Layout.Screen testID="blockedAccountsScreen"> - <Layout.Center style={[a.flex_1, {paddingBottom: 100}]}> - <ViewHeader title={_(msg`Blocked Accounts`)} showOnDesktop /> - <Text - type="sm" - style={[ - styles.description, - pal.text, - isTabletOrDesktop && styles.descriptionDesktop, - { - marginTop: 20, - }, - ]}> - <Trans> - Blocked accounts cannot reply in your threads, mention you, or - otherwise interact with you. You will not see their content and they - will be prevented from seeing yours. - </Trans> - </Text> + <Layout.Center> + <Layout.Header.Outer> + <Layout.Header.BackButton /> + <Layout.Header.Content> + <Layout.Header.TitleText> + <Trans>Blocked Accounts</Trans> + </Layout.Header.TitleText> + </Layout.Header.Content> + <Layout.Header.Slot /> + </Layout.Header.Outer> {isEmpty ? ( - <View style={[pal.border]}> + <View> + <Info style={[a.border_b]} /> {isError ? ( <ErrorScreen title="Oops!" @@ -133,42 +116,29 @@ export function ModerationBlockedAccounts({}: Props) { onPressTryAgain={refetch} /> ) : ( - <View style={[styles.empty, pal.viewLight]}> - <Text type="lg" style={[pal.text, styles.emptyText]}> - <Trans> - You have not blocked any accounts yet. To block an account, - go to their profile and select "Block account" from the menu - on their account. - </Trans> - </Text> - </View> + <Empty /> )} </View> ) : ( - <FlatList - style={[!isTabletOrDesktop && styles.flex1]} + <List data={profiles} keyExtractor={(item: ActorDefs.ProfileView) => item.did} - refreshControl={ - <RefreshControl - refreshing={isPTRing} - onRefresh={onRefresh} - tintColor={pal.colors.text} - titleColor={pal.colors.text} - /> - } + refreshing={isPTRing} + onRefresh={onRefresh} onEndReached={onEndReached} renderItem={renderItem} initialNumToRender={15} // FIXME(dan) - ListFooterComponent={() => ( - <View style={styles.footer}> - {(isFetching || isFetchingNextPage) && <ActivityIndicator />} - </View> - )} - // @ts-ignore our .web version only -prf - desktopFixedHeight + ListHeaderComponent={Info} + ListFooterComponent={ + <ListFooter + isFetchingNextPage={isFetchingNextPage} + hasNextPage={hasNextPage} + error={cleanError(error)} + onRetry={fetchNextPage} + /> + } /> )} </Layout.Center> @@ -176,37 +146,53 @@ export function ModerationBlockedAccounts({}: Props) { ) } -const styles = StyleSheet.create({ - title: { - textAlign: 'center', - marginTop: 12, - marginBottom: 12, - }, - description: { - textAlign: 'center', - paddingHorizontal: 30, - marginBottom: 14, - }, - descriptionDesktop: { - marginTop: 14, - }, - - flex1: { - flex: 1, - }, - empty: { - paddingHorizontal: 20, - paddingVertical: 20, - borderRadius: 16, - marginHorizontal: 24, - marginTop: 10, - }, - emptyText: { - textAlign: 'center', - }, +function Empty() { + const t = useTheme() + return ( + <View style={[a.pt_2xl, a.px_xl, a.align_center]}> + <View + style={[ + a.py_md, + a.px_lg, + a.rounded_sm, + t.atoms.bg_contrast_25, + a.border, + t.atoms.border_contrast_low, + {maxWidth: 400}, + ]}> + <Text style={[a.text_sm, a.text_center, t.atoms.text_contrast_high]}> + <Trans> + You have not blocked any accounts yet. To block an account, go to + their profile and select "Block account" from the menu on their + account. + </Trans> + </Text> + </View> + </View> + ) +} - footer: { - height: 200, - paddingTop: 20, - }, -}) +function Info({style}: {style?: StyleProp<ViewStyle>}) { + const t = useTheme() + return ( + <View + style={[ + a.w_full, + t.atoms.bg_contrast_25, + a.py_md, + a.px_xl, + a.border_t, + {marginTop: a.border.borderWidth * -1}, + t.atoms.border_contrast_low, + style, + ]}> + <Text style={[a.text_center, a.text_sm, t.atoms.text_contrast_high]}> + <Trans> + Blocked accounts cannot reply in your threads, mention you, or + otherwise interact with you. You will not see their content and they + will be prevented from seeing yours. + </Trans> + </Text> + </View> + ) +} diff --git a/src/view/screens/ModerationMutedAccounts.tsx b/src/view/screens/ModerationMutedAccounts.tsx index f49337b7c..11d787ca1 100644 --- a/src/view/screens/ModerationMutedAccounts.tsx +++ b/src/view/screens/ModerationMutedAccounts.tsx @@ -1,19 +1,11 @@ -import React from 'react' -import { - ActivityIndicator, - FlatList, - RefreshControl, - StyleSheet, - View, -} from 'react-native' +import {useCallback, useMemo, useState} from 'react' +import {type StyleProp, View, type ViewStyle} from 'react-native' import {type AppBskyActorDefs as ActorDefs} from '@atproto/api' -import {msg, Trans} from '@lingui/macro' +import {Trans} from '@lingui/macro' import {useLingui} from '@lingui/react' import {useFocusEffect} from '@react-navigation/native' import {type NativeStackScreenProps} from '@react-navigation/native-stack' -import {usePalette} from '#/lib/hooks/usePalette' -import {useWebMediaQueries} from '#/lib/hooks/useWebMediaQueries' import {type CommonNavigatorParams} from '#/lib/routes/types' import {cleanError} from '#/lib/strings/errors' import {logger} from '#/logger' @@ -21,11 +13,12 @@ import {useModerationOpts} from '#/state/preferences/moderation-opts' import {useMyMutedAccountsQuery} from '#/state/queries/my-muted-accounts' import {useSetMinimalShellMode} from '#/state/shell' import {ErrorScreen} from '#/view/com/util/error/ErrorScreen' -import {Text} from '#/view/com/util/text/Text' -import {ViewHeader} from '#/view/com/util/ViewHeader' +import {List} from '#/view/com/util/List' import {atoms as a, useTheme} from '#/alf' import * as Layout from '#/components/Layout' +import {ListFooter} from '#/components/Lists' import * as ProfileCard from '#/components/ProfileCard' +import {Text} from '#/components/Typography' type Props = NativeStackScreenProps< CommonNavigatorParams, @@ -33,13 +26,11 @@ type Props = NativeStackScreenProps< > export function ModerationMutedAccounts({}: Props) { const t = useTheme() - const pal = usePalette('default') + const moderationOpts = useModerationOpts() const {_} = useLingui() const setMinimalShellMode = useSetMinimalShellMode() - const {isTabletOrDesktop} = useWebMediaQueries() - const moderationOpts = useModerationOpts() - const [isPTRing, setIsPTRing] = React.useState(false) + const [isPTRing, setIsPTRing] = useState(false) const { data, isFetching, @@ -51,7 +42,7 @@ export function ModerationMutedAccounts({}: Props) { isFetchingNextPage, } = useMyMutedAccountsQuery() const isEmpty = !isFetching && !data?.pages[0]?.mutes.length - const profiles = React.useMemo(() => { + const profiles = useMemo(() => { if (data?.pages) { return data.pages.flatMap(page => page.mutes) } @@ -59,12 +50,12 @@ export function ModerationMutedAccounts({}: Props) { }, [data]) useFocusEffect( - React.useCallback(() => { + useCallback(() => { setMinimalShellMode(false) }, [setMinimalShellMode]), ) - const onRefresh = React.useCallback(async () => { + const onRefresh = useCallback(async () => { setIsPTRing(true) try { await refetch() @@ -74,7 +65,7 @@ export function ModerationMutedAccounts({}: Props) { setIsPTRing(false) }, [refetch, setIsPTRing]) - const onEndReached = React.useCallback(async () => { + const onEndReached = useCallback(async () => { if (isFetching || !hasNextPage || isError) return try { @@ -120,25 +111,19 @@ export function ModerationMutedAccounts({}: Props) { } return ( <Layout.Screen testID="mutedAccountsScreen"> - <ViewHeader title={_(msg`Muted Accounts`)} showOnDesktop /> - <Layout.Center style={[a.flex_1, {paddingBottom: 100}]}> - <Text - type="sm" - style={[ - styles.description, - pal.text, - isTabletOrDesktop && styles.descriptionDesktop, - { - marginTop: 20, - }, - ]}> - <Trans> - Muted accounts have their posts removed from your feed and from your - notifications. Mutes are completely private. - </Trans> - </Text> + <Layout.Header.Outer> + <Layout.Header.BackButton /> + <Layout.Header.Content> + <Layout.Header.TitleText> + <Trans>Muted Accounts</Trans> + </Layout.Header.TitleText> + </Layout.Header.Content> + <Layout.Header.Slot /> + </Layout.Header.Outer> + <Layout.Center> {isEmpty ? ( - <View style={[pal.border]}> + <View> + <Info style={[a.border_b]} /> {isError ? ( <ErrorScreen title="Oops!" @@ -146,42 +131,29 @@ export function ModerationMutedAccounts({}: Props) { onPressTryAgain={refetch} /> ) : ( - <View style={[styles.empty, pal.viewLight]}> - <Text type="lg" style={[pal.text, styles.emptyText]}> - <Trans> - You have not muted any accounts yet. To mute an account, go - to their profile and select "Mute account" from the menu on - their account. - </Trans> - </Text> - </View> + <Empty /> )} </View> ) : ( - <FlatList - style={[!isTabletOrDesktop && styles.flex1]} + <List data={profiles} keyExtractor={item => item.did} - refreshControl={ - <RefreshControl - refreshing={isPTRing} - onRefresh={onRefresh} - tintColor={pal.colors.text} - titleColor={pal.colors.text} - /> - } + refreshing={isPTRing} + onRefresh={onRefresh} onEndReached={onEndReached} renderItem={renderItem} initialNumToRender={15} // FIXME(dan) - ListFooterComponent={() => ( - <View style={styles.footer}> - {(isFetching || isFetchingNextPage) && <ActivityIndicator />} - </View> - )} - // @ts-ignore our .web version only -prf - desktopFixedHeight + ListHeaderComponent={Info} + ListFooterComponent={ + <ListFooter + isFetchingNextPage={isFetchingNextPage} + hasNextPage={hasNextPage} + error={cleanError(error)} + onRetry={fetchNextPage} + /> + } /> )} </Layout.Center> @@ -189,37 +161,51 @@ export function ModerationMutedAccounts({}: Props) { ) } -const styles = StyleSheet.create({ - title: { - textAlign: 'center', - marginTop: 12, - marginBottom: 12, - }, - description: { - textAlign: 'center', - paddingHorizontal: 30, - marginBottom: 14, - }, - descriptionDesktop: { - marginTop: 14, - }, - - flex1: { - flex: 1, - }, - empty: { - paddingHorizontal: 20, - paddingVertical: 20, - borderRadius: 16, - marginHorizontal: 24, - marginTop: 10, - }, - emptyText: { - textAlign: 'center', - }, +function Empty() { + const t = useTheme() + return ( + <View style={[a.pt_2xl, a.px_xl, a.align_center]}> + <View + style={[ + a.py_md, + a.px_lg, + a.rounded_sm, + t.atoms.bg_contrast_25, + a.border, + t.atoms.border_contrast_low, + {maxWidth: 400}, + ]}> + <Text style={[a.text_sm, a.text_center, t.atoms.text_contrast_high]}> + <Trans> + You have not muted any accounts yet. To mute an account, go to their + profile and select "Mute account" from the menu on their account. + </Trans> + </Text> + </View> + </View> + ) +} - footer: { - height: 200, - paddingTop: 20, - }, -}) +function Info({style}: {style?: StyleProp<ViewStyle>}) { + const t = useTheme() + return ( + <View + style={[ + a.w_full, + t.atoms.bg_contrast_25, + a.py_md, + a.px_xl, + a.border_t, + {marginTop: a.border.borderWidth * -1}, + t.atoms.border_contrast_low, + style, + ]}> + <Text style={[a.text_center, a.text_sm, t.atoms.text_contrast_high]}> + <Trans> + Muted accounts have their posts removed from your feed and from your + notifications. Mutes are completely private. + </Trans> + </Text> + </View> + ) +} diff --git a/src/view/shell/Composer.web.tsx b/src/view/shell/Composer.web.tsx index b76e88372..ce3695212 100644 --- a/src/view/shell/Composer.web.tsx +++ b/src/view/shell/Composer.web.tsx @@ -1,18 +1,16 @@ import React from 'react' import {StyleSheet, View} from 'react-native' -import {DismissableLayer} from '@radix-ui/react-dismissable-layer' -import {useFocusGuards} from '@radix-ui/react-focus-guards' -import {FocusScope} from '@radix-ui/react-focus-scope' +import {DismissableLayer, FocusGuards, FocusScope} from 'radix-ui/internal' import {RemoveScrollBar} from 'react-remove-scroll-bar' import {useA11y} from '#/state/a11y' import {useModals} from '#/state/modals' -import {ComposerOpts, useComposerState} from '#/state/shell/composer' +import {type ComposerOpts, useComposerState} from '#/state/shell/composer' import { EmojiPicker, - EmojiPickerPosition, - EmojiPickerState, -} from '#/view/com/composer/text-input/web/EmojiPicker.web' + type EmojiPickerPosition, + type EmojiPickerState, +} from '#/view/com/composer/text-input/web/EmojiPicker' import {atoms as a, flatten, useBreakpoints, useTheme} from '#/alf' import {ComposePost, useComposerCancelRef} from '../com/composer/Composer' @@ -66,11 +64,11 @@ function Inner({state}: {state: ComposerOpts}) { })) }, []) - useFocusGuards() + FocusGuards.useFocusGuards() return ( - <FocusScope loop trapped asChild> - <DismissableLayer + <FocusScope.FocusScope loop trapped asChild> + <DismissableLayer.DismissableLayer role="dialog" aria-modal style={flatten([ @@ -114,8 +112,8 @@ function Inner({state}: {state: ComposerOpts}) { /> </View> <EmojiPicker state={pickerState} close={onClosePicker} /> - </DismissableLayer> - </FocusScope> + </DismissableLayer.DismissableLayer> + </FocusScope.FocusScope> ) } diff --git a/src/view/shell/createNativeStackNavigatorWithAuth.tsx b/src/view/shell/createNativeStackNavigatorWithAuth.tsx index 11beaa2e9..868bba5b0 100644 --- a/src/view/shell/createNativeStackNavigatorWithAuth.tsx +++ b/src/view/shell/createNativeStackNavigatorWithAuth.tsx @@ -5,21 +5,21 @@ import {View} from 'react-native' // Copyright (c) 2017 React Navigation Contributors import { createNavigatorFactory, - EventArg, - ParamListBase, - StackActionHelpers, + type EventArg, + type ParamListBase, + type StackActionHelpers, StackActions, - StackNavigationState, + type StackNavigationState, StackRouter, - StackRouterOptions, + type StackRouterOptions, useNavigationBuilder, } from '@react-navigation/native' -import type { - NativeStackNavigationEventMap, - NativeStackNavigationOptions, +import { + type NativeStackNavigationEventMap, + type NativeStackNavigationOptions, } from '@react-navigation/native-stack' import {NativeStackView} from '@react-navigation/native-stack' -import type {NativeStackNavigatorProps} from '@react-navigation/native-stack/src/types' +import {type NativeStackNavigatorProps} from '@react-navigation/native-stack/src/types' import {PWI_ENABLED} from '#/lib/build-flags' import {useWebMediaQueries} from '#/lib/hooks/useWebMediaQueries' @@ -35,7 +35,7 @@ import {Deactivated} from '#/screens/Deactivated' import {Onboarding} from '#/screens/Onboarding' import {SignupQueued} from '#/screens/SignupQueued' import {Takendown} from '#/screens/Takendown' -import {atoms as a} from '#/alf' +import {atoms as a, useLayoutBreakpoints} from '#/alf' import {BottomBarWeb} from './bottom-bar/BottomBarWeb' import {DesktopLeftNav} from './desktop/LeftNav' import {DesktopRightNav} from './desktop/RightNav' @@ -101,7 +101,8 @@ function NativeStackNavigator({ const onboardingState = useOnboardingState() const {showLoggedOut} = useLoggedOutView() const {setShowLoggedOut} = useLoggedOutViewControls() - const {isMobile, isTabletOrMobile} = useWebMediaQueries() + const {isMobile} = useWebMediaQueries() + const {leftNavMinimal} = useLayoutBreakpoints() if (!hasSession && (!PWI_ENABLED || activeRouteRequiresAuth || isNative)) { return <LoggedOut /> } @@ -138,7 +139,7 @@ function NativeStackNavigator({ // Show the bottom bar if we have a session only on mobile web. If we don't have a session, we want to show it // on both tablet and mobile web so that we see the create account CTA. - const showBottomBar = hasSession ? isMobile : isTabletOrMobile + const showBottomBar = hasSession ? isMobile : leftNavMinimal return ( <NavigationContent> diff --git a/src/view/shell/desktop/LeftNav.tsx b/src/view/shell/desktop/LeftNav.tsx index 5cef18ebf..7d7c0ac8d 100644 --- a/src/view/shell/desktop/LeftNav.tsx +++ b/src/view/shell/desktop/LeftNav.tsx @@ -571,7 +571,7 @@ export function DesktopLeftNav() { ]}> {hasSession ? ( <ProfileCard /> - ) : isDesktop ? ( + ) : !leftNavMinimal ? ( <View style={[a.pt_xl]}> <NavSignupCard /> </View> diff --git a/src/view/shell/index.tsx b/src/view/shell/index.tsx index 3d3a5520c..1e34f6da5 100644 --- a/src/view/shell/index.tsx +++ b/src/view/shell/index.tsx @@ -25,6 +25,7 @@ import {ModalsContainer} from '#/view/com/modals/Modal' import {ErrorBoundary} from '#/view/com/util/ErrorBoundary' import {atoms as a, select, useTheme} from '#/alf' import {setSystemUITheme} from '#/alf/util/systemUI' +import {InAppBrowserConsentDialog} from '#/components/dialogs/InAppBrowserConsent' import {MutedWordsDialog} from '#/components/dialogs/MutedWords' import {SigninDialog} from '#/components/dialogs/Signin' import {Outlet as PortalOutlet} from '#/components/Portal' @@ -151,6 +152,7 @@ function ShellInner() { <ModalsContainer /> <MutedWordsDialog /> <SigninDialog /> + <InAppBrowserConsentDialog /> <Lightbox /> <PortalOutlet /> <BottomSheetOutlet /> |