Skip to content

Commit

Permalink
custom bottom sheet link
Browse files Browse the repository at this point in the history
  • Loading branch information
haileyok committed Oct 2, 2024
1 parent 65bfd89 commit 87c83dd
Show file tree
Hide file tree
Showing 6 changed files with 164 additions and 26 deletions.
92 changes: 92 additions & 0 deletions src/components/BottomSheetLink.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
import React from 'react'
import {BlueskyBottomSheetPressable} from '@haileyok/bluesky-bottom-sheet'
import {StackActions, useNavigation} from '@react-navigation/native'

import {NavigationProp} from '#/lib/routes/types'
import {flatten, useTheme} from '#/alf'
import {useDialogContext} from '#/components/Dialog'
import {useInteractionState} from '#/components/hooks/useInteractionState'
import {InlineLinkProps, useLink} from '#/components/Link'
import {Text} from '#/components/Typography'
import {router} from '#/routes'

export function BottomSheetInlineLinkText({
children,
to,
action = 'push',
disableMismatchWarning,
style,
onPress: outerOnPress,
label,
shareOnLongPress,
disableUnderline,
...rest
}: InlineLinkProps) {
const t = useTheme()
const stringChildren = typeof children === 'string'
const navigation = useNavigation<NavigationProp>()
const dialog = useDialogContext()

const {href, isExternal, onLongPress} = useLink({
to,
displayText: stringChildren ? children : '',
action,
disableMismatchWarning,
onPress: outerOnPress,
shareOnLongPress,
})
const {
state: pressed,
onIn: onPressIn,
onOut: onPressOut,
} = useInteractionState()

const onPress = () => {
if (isExternal) {
return
}

dialog.close()

if (action === 'push') {
navigation.dispatch(StackActions.push(...router.matchPath(href)))
} else if (action === 'replace') {
navigation.dispatch(StackActions.replace(...router.matchPath(href)))
} else if (action === 'navigate') {
// @ts-ignore
navigation.navigate(...router.matchPath(href))
} else {
throw Error('Unsupported navigator action.')
}
}

const flattenedStyle = flatten(style) || {}

// eslint-disable-next-line bsky-internal/avoid-unwrapped-text
return (
<BlueskyBottomSheetPressable
onPress={onPress}
onLongPress={onLongPress}
onPressIn={onPressIn}
onPressOut={onPressOut}
role="link"
accessibilityLabel={label}
accessibilityHint=""
style={{flexDirection: 'row'}}>
<Text
{...rest}
style={[
{color: t.palette.primary_500},
pressed &&
!disableUnderline && {
textDecorationLine: 'underline',
textDecorationColor:
flattenedStyle.color ?? t.palette.primary_500,
},
flattenedStyle,
]}>
{children}
</Text>
</BlueskyBottomSheetPressable>
)
}
3 changes: 3 additions & 0 deletions src/components/BottomSheetLink.web.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
import {Link as BottomSheetLink} from './Link'

export {BottomSheetLink}
46 changes: 43 additions & 3 deletions src/components/Link.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import {shouldClickOpenNewTab} from '#/platform/urls'
import {useModalControls} from '#/state/modals'
import {useOpenLink} from '#/state/preferences/in-app-browser'
import {atoms as a, flatten, TextStyleProp, useTheme, web} from '#/alf'
import {BottomSheetButton} from '#/components/BottomSheetButton'
import {Button, ButtonProps} from '#/components/Button'
import {useInteractionState} from '#/components/hooks/useInteractionState'
import {Text, TextProps} from '#/components/Typography'
Expand Down Expand Up @@ -103,17 +104,17 @@ export function useLink({
linkRequiresWarning(href, displayText),
)

if (requiresWarning) {
if (isWeb) {
e.preventDefault()
}

if (requiresWarning) {
openModal({
name: 'link-warning',
text: displayText,
href: href,
})
} else {
e.preventDefault()

if (isExternal) {
openLink(href)
} else {
Expand Down Expand Up @@ -241,6 +242,45 @@ export function Link({
)
}

export function BottomSheetLink({
children,
to,
action = 'push',
onPress: outerOnPress,
download,
...rest
}: LinkProps) {
const {href, isExternal, onPress} = useLink({
to,
displayText: typeof children === 'string' ? children : '',
action,
onPress: outerOnPress,
})

return (
<BottomSheetButton
{...rest}
style={[a.justify_start, flatten(rest.style)]}
role="link"
accessibilityRole="link"
href={href}
onPress={download ? undefined : onPress}
{...web({
hrefAttrs: {
target: download ? undefined : isExternal ? 'blank' : undefined,
rel: isExternal ? 'noopener noreferrer' : undefined,
download,
},
dataSet: {
// no underline, only `InlineLink` has underlines
noUnderline: '1',
},
})}>
{children}
</BottomSheetButton>
)
}

export type InlineLinkProps = React.PropsWithChildren<
BaseLinkProps & TextStyleProp & Pick<TextProps, 'selectable'>
> &
Expand Down
8 changes: 4 additions & 4 deletions src/components/ReportDialog/SelectLabelerView.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,10 @@ import {AppBskyLabelerDefs} from '@atproto/api'
import {msg, Trans} from '@lingui/macro'
import {useLingui} from '@lingui/react'

export {useDialogControl as useReportDialogControl} from '#/components/Dialog'
import {getLabelingServiceTitle} from '#/lib/moderation'
import {atoms as a, useBreakpoints, useTheme} from '#/alf'
import {Button, useButtonContext} from '#/components/Button'
import {BottomSheetButton} from '#/components/BottomSheetButton'
import {useButtonContext} from '#/components/Button'
import {Divider} from '#/components/Divider'
import * as LabelingServiceCard from '#/components/LabelingServiceCard'
import {Text} from '#/components/Typography'
Expand Down Expand Up @@ -39,12 +39,12 @@ export function SelectLabelerView({
<View style={[a.gap_sm]}>
{props.labelers.map(labeler => {
return (
<Button
<BottomSheetButton
key={labeler.creator.did}
label={_(msg`Send report to ${labeler.creator.displayName}`)}
onPress={() => props.onSelectLabeler(labeler.creator.did)}>
<LabelerButton labeler={labeler} />
</Button>
</BottomSheetButton>
)
})}
</View>
Expand Down
6 changes: 3 additions & 3 deletions src/components/ReportDialog/SelectReportOptionView.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import {msg, Trans} from '@lingui/macro'
import {useLingui} from '@lingui/react'

import {ReportOption, useReportOptions} from '#/lib/moderation/useReportOptions'
import {Link} from '#/components/Link'
import {BottomSheetLink} from '#/components/Link'
import {DMCA_LINK} from '#/components/ReportDialog/const'
export {useDialogControl as useReportDialogControl} from '#/components/Dialog'

Expand Down Expand Up @@ -125,7 +125,7 @@ export function SelectReportOptionView({
]}>
<Trans>Need to report a copyright violation?</Trans>
</Text>
<Link
<BottomSheetLink
to={DMCA_LINK}
label={_(msg`View details for reporting a copyright violation`)}
size="small"
Expand All @@ -135,7 +135,7 @@ export function SelectReportOptionView({
<Trans>View details</Trans>
</ButtonText>
<ButtonIcon position="right" icon={SquareArrowTopRight} />
</Link>
</BottomSheetLink>
</View>
)}
</View>
Expand Down
35 changes: 19 additions & 16 deletions src/components/moderation/LabelsOnMeDialog.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import {useAgent, useSession} from '#/state/session'
import * as Toast from '#/view/com/util/Toast'
import {atoms as a, useBreakpoints, useTheme} from '#/alf'
import {BottomSheetButton} from '#/components/BottomSheetButton'
import {BottomSheetInlineLinkText} from '#/components/BottomSheetLink'
import {ButtonIcon, ButtonText} from '#/components/Button'
import * as Dialog from '#/components/Dialog'
import {InlineLinkText} from '#/components/Link'
Expand Down Expand Up @@ -157,23 +158,25 @@ function Label({
<Divider />

<View style={[a.px_md, a.py_sm, t.atoms.bg_contrast_25]}>
<Text style={[t.atoms.text_contrast_medium]}>
{isSelfLabel ? (
{isSelfLabel ? (
<Text style={[t.atoms.text_contrast_medium]}>
<Trans>This label was applied by you.</Trans>
) : (
<Trans>
Source:{' '}
<InlineLinkText
label={sourceName}
to={makeProfileLink(
labeler ? labeler.creator : {did: label.src, handle: ''},
)}
onPress={() => control.close()}>
{sourceName}
</InlineLinkText>
</Trans>
)}
</Text>
</Text>
) : (
<View style={{flexDirection: 'row'}}>
<Text style={[t.atoms.text_contrast_medium]}>
<Trans>Source: </Trans>{' '}
</Text>
<BottomSheetInlineLinkText
label={sourceName}
to={makeProfileLink(
labeler ? labeler.creator : {did: label.src, handle: ''},
)}
onPress={() => control.close()}>
{sourceName}
</BottomSheetInlineLinkText>
</View>
)}
</View>
</View>
)
Expand Down

0 comments on commit 87c83dd

Please sign in to comment.