diff options
Diffstat (limited to 'src/components')
-rw-r--r-- | src/components/Menu/index.tsx | 45 | ||||
-rw-r--r-- | src/components/Menu/index.web.tsx | 39 | ||||
-rw-r--r-- | src/components/PostControls/PostMenu/PostMenuItems.tsx | 15 | ||||
-rw-r--r-- | src/components/PostControls/ShareMenu/ShareMenuItems.tsx | 56 | ||||
-rw-r--r-- | src/components/PostControls/ShareMenu/ShareMenuItems.web.tsx | 133 |
5 files changed, 142 insertions, 146 deletions
diff --git a/src/components/Menu/index.tsx b/src/components/Menu/index.tsx index c5ccfa5ec..94438724c 100644 --- a/src/components/Menu/index.tsx +++ b/src/components/Menu/index.tsx @@ -1,5 +1,11 @@ -import React from 'react' -import {Pressable, StyleProp, View, ViewStyle} from 'react-native' +import {cloneElement, Fragment, isValidElement, useMemo} from 'react' +import { + Pressable, + type StyleProp, + type TextStyle, + View, + type ViewStyle, +} from 'react-native' import {msg, Trans} from '@lingui/macro' import {useLingui} from '@lingui/react' import flattenReactChildren from 'react-keyed-flatten-children' @@ -16,12 +22,12 @@ import { useMenuItemContext, } from '#/components/Menu/context' import { - ContextType, - GroupProps, - ItemIconProps, - ItemProps, - ItemTextProps, - TriggerProps, + type ContextType, + type GroupProps, + type ItemIconProps, + type ItemProps, + type ItemTextProps, + type TriggerProps, } from '#/components/Menu/types' import {Text} from '#/components/Typography' @@ -39,7 +45,7 @@ export function Root({ control?: Dialog.DialogControlProps }>) { const defaultControl = Dialog.useDialogControl() - const context = React.useMemo<ContextType>( + const context = useMemo<ContextType>( () => ({ control: control || defaultControl, }), @@ -276,16 +282,21 @@ export function ContainerItem({ ) } -export function LabelText({children}: {children: React.ReactNode}) { +export function LabelText({ + children, + style, +}: { + children: React.ReactNode + style?: StyleProp<TextStyle> +}) { const t = useTheme() return ( <Text style={[ a.font_bold, t.atoms.text_contrast_medium, - { - marginBottom: -8, - }, + {marginBottom: -8}, + style, ]}> {children} </Text> @@ -304,20 +315,20 @@ export function Group({children, style}: GroupProps) { style, ]}> {flattenReactChildren(children).map((child, i) => { - return React.isValidElement(child) && + return isValidElement(child) && (child.type === Item || child.type === ContainerItem) ? ( - <React.Fragment key={i}> + <Fragment key={i}> {i > 0 ? ( <View style={[a.border_b, t.atoms.border_contrast_low]} /> ) : null} - {React.cloneElement(child, { + {cloneElement(child, { // @ts-expect-error cloneElement is not aware of the types style: { borderRadius: 0, borderWidth: 0, }, })} - </React.Fragment> + </Fragment> ) : null })} </View> diff --git a/src/components/Menu/index.web.tsx b/src/components/Menu/index.web.tsx index 7d6e50556..8d26c8f03 100644 --- a/src/components/Menu/index.web.tsx +++ b/src/components/Menu/index.web.tsx @@ -1,5 +1,11 @@ -import React from 'react' -import {Pressable, type StyleProp, View, type ViewStyle} from 'react-native' +import {forwardRef, useCallback, useId, useMemo, useState} from 'react' +import { + Pressable, + type StyleProp, + type TextStyle, + View, + type ViewStyle, +} from 'react-native' import {msg} from '@lingui/macro' import {useLingui} from '@lingui/react' import {DropdownMenu} from 'radix-ui' @@ -29,10 +35,10 @@ import {Text} from '#/components/Typography' export {useMenuContext} export function useMenuControl(): Dialog.DialogControlProps { - const id = React.useId() - const [isOpen, setIsOpen] = React.useState(false) + const id = useId() + const [isOpen, setIsOpen] = useState(false) - return React.useMemo( + return useMemo( () => ({ id, ref: {current: null}, @@ -56,13 +62,13 @@ export function Root({ }>) { const {_} = useLingui() const defaultControl = useMenuControl() - const context = React.useMemo<ContextType>( + const context = useMemo<ContextType>( () => ({ control: control || defaultControl, }), [control, defaultControl], ) - const onOpenChange = React.useCallback( + const onOpenChange = useCallback( (open: boolean) => { if (context.control.isOpen && !open) { context.control.close() @@ -96,7 +102,7 @@ export function Root({ ) } -const RadixTriggerPassThrough = React.forwardRef( +const RadixTriggerPassThrough = forwardRef( ( props: { children: ( @@ -355,18 +361,23 @@ export function ItemRadio({selected}: {selected: boolean}) { ) } -export function LabelText({children}: {children: React.ReactNode}) { +export function LabelText({ + children, + style, +}: { + children: React.ReactNode + style?: StyleProp<TextStyle> +}) { const t = useTheme() return ( <Text style={[ a.font_bold, - a.pt_md, - a.pb_sm, + a.p_sm, t.atoms.text_contrast_low, - { - paddingHorizontal: 10, - }, + a.leading_snug, + {paddingHorizontal: 10}, + style, ]}> {children} </Text> diff --git a/src/components/PostControls/PostMenu/PostMenuItems.tsx b/src/components/PostControls/PostMenu/PostMenuItems.tsx index 7f33f3348..01ddd0bcf 100644 --- a/src/components/PostControls/PostMenu/PostMenuItems.tsx +++ b/src/components/PostControls/PostMenu/PostMenuItems.tsx @@ -48,7 +48,7 @@ import { useProfileMuteMutationQueue, } from '#/state/queries/profile' import {useToggleReplyVisibilityMutation} from '#/state/queries/threadgate' -import {useSession} from '#/state/session' +import {useRequireAuth, useSession} from '#/state/session' import {useMergedThreadgateHiddenReplies} from '#/state/threadgate-hidden-replies' import * as Toast from '#/view/com/util/Toast' import {useDialogControl} from '#/components/Dialog' @@ -113,6 +113,7 @@ let PostMenuItems = ({ const {mutateAsync: deletePostMutate} = usePostDeleteMutation() const {mutateAsync: pinPostMutate, isPending: isPinPending} = usePinnedPostMutation() + const requireSignIn = useRequireAuth() const hiddenPosts = useHiddenPosts() const {hidePost} = useHiddenPostsApi() const feedFeedback = useFeedFeedbackContext() @@ -397,6 +398,8 @@ let PostMenuItems = ({ openLink(url) } + const onSignIn = () => requireSignIn(() => {}) + const gate = useGate() const isDiscoverDebugUser = IS_INTERNAL || @@ -434,7 +437,7 @@ let PostMenuItems = ({ )} <Menu.Group> - {(!hideInPWI || hasSession) && ( + {!hideInPWI || hasSession ? ( <> <Menu.Item testID="postDropdownTranslateBtn" @@ -452,6 +455,14 @@ let PostMenuItems = ({ <Menu.ItemIcon icon={ClipboardIcon} position="right" /> </Menu.Item> </> + ) : ( + <Menu.Item + testID="postDropdownSignInBtn" + label={_(msg`Sign in to view post`)} + onPress={onSignIn}> + <Menu.ItemText>{_(msg`Sign in to view post`)}</Menu.ItemText> + <Menu.ItemIcon icon={Eye} position="right" /> + </Menu.Item> )} </Menu.Group> diff --git a/src/components/PostControls/ShareMenu/ShareMenuItems.tsx b/src/components/PostControls/ShareMenu/ShareMenuItems.tsx index c090c3e2d..1c04f3174 100644 --- a/src/components/PostControls/ShareMenu/ShareMenuItems.tsx +++ b/src/components/PostControls/ShareMenu/ShareMenuItems.tsx @@ -14,6 +14,8 @@ import {isIOS} from '#/platform/detection' import {useProfileShadow} from '#/state/cache/profile-shadow' import {useSession} from '#/state/session' import * as Toast from '#/view/com/util/Toast' +import {atoms as a} from '#/alf' +import {Admonition} from '#/components/Admonition' import {useDialogControl} from '#/components/Dialog' import {SendViaChatDialog} from '#/components/dms/dialogs/ShareViaChatDialog' import {ArrowOutOfBoxModified_Stroke2_Corner2_Rounded as ArrowOutOfBoxIcon} from '#/components/icons/ArrowOutOfBox' @@ -21,7 +23,6 @@ import {ChainLink_Stroke2_Corner0_Rounded as ChainLinkIcon} from '#/components/i import {Clipboard_Stroke2_Corner2_Rounded as ClipboardIcon} from '#/components/icons/Clipboard' import {PaperPlane_Stroke2_Corner0_Rounded as PaperPlaneIcon} from '#/components/icons/PaperPlane' import * as Menu from '#/components/Menu' -import * as Prompt from '#/components/Prompt' import {useDevMode} from '#/storage/hooks/dev-mode' import {RecentChats} from './RecentChats' import {type ShareMenuItemsProps} from './ShareMenuItems.types' @@ -30,11 +31,9 @@ let ShareMenuItems = ({ post, onShare: onShareProp, }: ShareMenuItemsProps): React.ReactNode => { - const {hasSession, currentAccount} = useSession() + const {hasSession} = useSession() const {_} = useLingui() const navigation = useNavigation<NavigationProp>() - const pwiWarningShareControl = useDialogControl() - const pwiWarningCopyControl = useDialogControl() const sendViaChatControl = useDialogControl() const [devModeEnabled] = useDevMode() @@ -52,9 +51,6 @@ let ShareMenuItems = ({ ) }, [postAuthor]) - const showLoggedOutWarning = - postAuthor.did !== currentAccount?.did && hideInPWI - const onSharePost = () => { logger.metric('share:press:nativeShare', {}, {statsig: true}) const url = toShareUrl(href) @@ -117,13 +113,7 @@ let ShareMenuItems = ({ <Menu.Item testID="postDropdownShareBtn" label={_(msg`Share via...`)} - onPress={() => { - if (showLoggedOutWarning) { - pwiWarningShareControl.open() - } else { - onSharePost() - } - }}> + onPress={onSharePost}> <Menu.ItemText> <Trans>Share via...</Trans> </Menu.ItemText> @@ -133,13 +123,7 @@ let ShareMenuItems = ({ <Menu.Item testID="postDropdownShareBtn" label={_(msg`Copy link to post`)} - onPress={() => { - if (showLoggedOutWarning) { - pwiWarningCopyControl.open() - } else { - onCopyLink() - } - }}> + onPress={onCopyLink}> <Menu.ItemText> <Trans>Copy link to post</Trans> </Menu.ItemText> @@ -147,6 +131,16 @@ let ShareMenuItems = ({ </Menu.Item> </Menu.Group> + {hideInPWI && ( + <Menu.Group> + <Menu.ContainerItem> + <Admonition type="warning" style={[a.flex_1, a.border_0, a.p_0]}> + <Trans>This post is only visible to logged-in users.</Trans> + </Admonition> + </Menu.ContainerItem> + </Menu.Group> + )} + {devModeEnabled && ( <Menu.Group> <Menu.Item @@ -171,26 +165,6 @@ let ShareMenuItems = ({ )} </Menu.Outer> - <Prompt.Basic - control={pwiWarningShareControl} - title={_(msg`Note about sharing`)} - description={_( - msg`This post is only visible to logged-in users. It won't be visible to people who aren't signed in.`, - )} - onConfirm={onSharePost} - confirmButtonCta={_(msg`Share anyway`)} - /> - - <Prompt.Basic - control={pwiWarningCopyControl} - title={_(msg`Note about sharing`)} - description={_( - msg`This post is only visible to logged-in users. It won't be visible to people who aren't signed in.`, - )} - onConfirm={onCopyLink} - confirmButtonCta={_(msg`Copy anyway`)} - /> - <SendViaChatDialog control={sendViaChatControl} onSelectChat={onSelectChatToShareTo} diff --git a/src/components/PostControls/ShareMenu/ShareMenuItems.web.tsx b/src/components/PostControls/ShareMenu/ShareMenuItems.web.tsx index 0da259678..8d52a2fdf 100644 --- a/src/components/PostControls/ShareMenu/ShareMenuItems.web.tsx +++ b/src/components/PostControls/ShareMenu/ShareMenuItems.web.tsx @@ -22,7 +22,6 @@ import {Clipboard_Stroke2_Corner2_Rounded as ClipboardIcon} from '#/components/i import {CodeBrackets_Stroke2_Corner0_Rounded as CodeBracketsIcon} from '#/components/icons/CodeBrackets' import {PaperPlane_Stroke2_Corner0_Rounded as Send} from '#/components/icons/PaperPlane' import * as Menu from '#/components/Menu' -import * as Prompt from '#/components/Prompt' import {useDevMode} from '#/storage/hooks/dev-mode' import {type ShareMenuItemsProps} from './ShareMenuItems.types' @@ -32,11 +31,10 @@ let ShareMenuItems = ({ timestamp, onShare: onShareProp, }: ShareMenuItemsProps): React.ReactNode => { - const {hasSession, currentAccount} = useSession() + const {hasSession} = useSession() const {gtMobile} = useBreakpoints() const {_} = useLingui() const navigation = useNavigation<NavigationProp>() - const loggedOutWarningPromptControl = useDialogControl() const embedPostControl = useDialogControl() const sendViaChatControl = useDialogControl() const [devModeEnabled] = useDevMode() @@ -56,9 +54,6 @@ let ShareMenuItems = ({ ) }, [postAuthor]) - const showLoggedOutWarning = - postAuthor.did !== currentAccount?.did && hideInPWI - const onCopyLink = () => { logger.metric('share:press:copyLink', {}, {statsig: true}) const url = toShareUrl(href) @@ -84,92 +79,86 @@ let ShareMenuItems = ({ shareText(postAuthor.did) } + const copyLinkItem = ( + <Menu.Item + testID="postDropdownShareBtn" + label={_(msg`Copy link to post`)} + onPress={onCopyLink}> + <Menu.ItemText> + <Trans>Copy link to post</Trans> + </Menu.ItemText> + <Menu.ItemIcon icon={ChainLinkIcon} position="right" /> + </Menu.Item> + ) + return ( <> <Menu.Outer> - <Menu.Group> + {!hideInPWI && copyLinkItem} + + {hasSession && ( <Menu.Item - testID="postDropdownShareBtn" - label={_(msg`Copy link to post`)} + testID="postDropdownSendViaDMBtn" + label={_(msg`Send via direct message`)} onPress={() => { - if (showLoggedOutWarning) { - loggedOutWarningPromptControl.open() - } else { - onCopyLink() - } + logger.metric('share:press:openDmSearch', {}, {statsig: true}) + sendViaChatControl.open() }}> <Menu.ItemText> - <Trans>Copy link to post</Trans> + <Trans>Send via direct message</Trans> </Menu.ItemText> - <Menu.ItemIcon icon={ChainLinkIcon} position="right" /> + <Menu.ItemIcon icon={Send} position="right" /> + </Menu.Item> + )} + + {canEmbed && ( + <Menu.Item + testID="postDropdownEmbedBtn" + label={_(msg`Embed post`)} + onPress={() => { + logger.metric('share:press:embed', {}, {statsig: true}) + embedPostControl.open() + }}> + <Menu.ItemText>{_(msg`Embed post`)}</Menu.ItemText> + <Menu.ItemIcon icon={CodeBracketsIcon} position="right" /> </Menu.Item> + )} + + {hideInPWI && ( + <> + {hasSession && <Menu.Divider />} + {copyLinkItem} + <Menu.LabelText style={{maxWidth: 220}}> + <Trans>Note: This post is only visible to logged-in users.</Trans> + </Menu.LabelText> + </> + )} - {hasSession && ( + {devModeEnabled && ( + <> + <Menu.Divider /> <Menu.Item - testID="postDropdownSendViaDMBtn" - label={_(msg`Send via direct message`)} - onPress={() => { - logger.metric('share:press:openDmSearch', {}, {statsig: true}) - sendViaChatControl.open() - }}> + testID="postAtUriShareBtn" + label={_(msg`Copy post at:// URI`)} + onPress={onShareATURI}> <Menu.ItemText> - <Trans>Send via direct message</Trans> + <Trans>Copy post at:// URI</Trans> </Menu.ItemText> - <Menu.ItemIcon icon={Send} position="right" /> + <Menu.ItemIcon icon={ClipboardIcon} position="right" /> </Menu.Item> - )} - - {canEmbed && ( <Menu.Item - testID="postDropdownEmbedBtn" - label={_(msg`Embed post`)} - onPress={() => { - logger.metric('share:press:embed', {}, {statsig: true}) - embedPostControl.open() - }}> - <Menu.ItemText>{_(msg`Embed post`)}</Menu.ItemText> - <Menu.ItemIcon icon={CodeBracketsIcon} position="right" /> + testID="postAuthorDIDShareBtn" + label={_(msg`Copy author DID`)} + onPress={onShareAuthorDID}> + <Menu.ItemText> + <Trans>Copy author DID</Trans> + </Menu.ItemText> + <Menu.ItemIcon icon={ClipboardIcon} position="right" /> </Menu.Item> - )} - </Menu.Group> - - {devModeEnabled && ( - <> - <Menu.Divider /> - <Menu.Group> - <Menu.Item - testID="postAtUriShareBtn" - label={_(msg`Copy post at:// URI`)} - onPress={onShareATURI}> - <Menu.ItemText> - <Trans>Copy post at:// URI</Trans> - </Menu.ItemText> - <Menu.ItemIcon icon={ClipboardIcon} position="right" /> - </Menu.Item> - <Menu.Item - testID="postAuthorDIDShareBtn" - label={_(msg`Copy author DID`)} - onPress={onShareAuthorDID}> - <Menu.ItemText> - <Trans>Copy author DID</Trans> - </Menu.ItemText> - <Menu.ItemIcon icon={ClipboardIcon} position="right" /> - </Menu.Item> - </Menu.Group> </> )} </Menu.Outer> - <Prompt.Basic - control={loggedOutWarningPromptControl} - title={_(msg`Note about sharing`)} - description={_( - msg`This post is only visible to logged-in users. It won't be visible to people who aren't signed in.`, - )} - onConfirm={onCopyLink} - confirmButtonCta={_(msg`Share anyway`)} - /> - {canEmbed && ( <EmbedDialog control={embedPostControl} |