attempt to upgrade Links
This commit is contained in:
+37
-24
@@ -1,20 +1,24 @@
|
|||||||
import React, {ComponentProps, memo, useMemo} from 'react'
|
import {memo, useCallback, useMemo} from 'react'
|
||||||
import {
|
import {
|
||||||
GestureResponderEvent,
|
type GestureResponderEvent,
|
||||||
Platform,
|
Platform,
|
||||||
Pressable,
|
Pressable,
|
||||||
StyleProp,
|
type StyleProp,
|
||||||
TextProps,
|
type TextProps,
|
||||||
TextStyle,
|
type TextStyle,
|
||||||
TouchableOpacity,
|
type TouchableOpacity,
|
||||||
View,
|
View,
|
||||||
ViewStyle,
|
type ViewStyle,
|
||||||
} from 'react-native'
|
} from 'react-native'
|
||||||
import {sanitizeUrl} from '@braintree/sanitize-url'
|
import {sanitizeUrl} from '@braintree/sanitize-url'
|
||||||
import {StackActions, useLinkProps} from '@react-navigation/native'
|
import {
|
||||||
|
StackActions,
|
||||||
|
useLinkBuilder,
|
||||||
|
useLinkProps,
|
||||||
|
} from '@react-navigation/native'
|
||||||
|
|
||||||
import {
|
import {
|
||||||
DebouncedNavigationProp,
|
type DebouncedNavigationProp,
|
||||||
useNavigationDeduped,
|
useNavigationDeduped,
|
||||||
} from '#/lib/hooks/useNavigationDeduped'
|
} from '#/lib/hooks/useNavigationDeduped'
|
||||||
import {useOpenLink} from '#/lib/hooks/useOpenLink'
|
import {useOpenLink} from '#/lib/hooks/useOpenLink'
|
||||||
@@ -24,7 +28,7 @@ import {
|
|||||||
isExternalUrl,
|
isExternalUrl,
|
||||||
linkRequiresWarning,
|
linkRequiresWarning,
|
||||||
} from '#/lib/strings/url-helpers'
|
} from '#/lib/strings/url-helpers'
|
||||||
import {TypographyVariant} from '#/lib/ThemeContext'
|
import {type TypographyVariant} from '#/lib/ThemeContext'
|
||||||
import {isAndroid, isWeb} from '#/platform/detection'
|
import {isAndroid, isWeb} from '#/platform/detection'
|
||||||
import {emitSoftReset} from '#/state/events'
|
import {emitSoftReset} from '#/state/events'
|
||||||
import {useModalControls} from '#/state/modals'
|
import {useModalControls} from '#/state/modals'
|
||||||
@@ -38,7 +42,7 @@ type Event =
|
|||||||
| React.MouseEvent<HTMLAnchorElement, MouseEvent>
|
| React.MouseEvent<HTMLAnchorElement, MouseEvent>
|
||||||
| GestureResponderEvent
|
| GestureResponderEvent
|
||||||
|
|
||||||
interface Props extends ComponentProps<typeof TouchableOpacity> {
|
interface Props extends React.ComponentProps<typeof TouchableOpacity> {
|
||||||
testID?: string
|
testID?: string
|
||||||
style?: StyleProp<ViewStyle>
|
style?: StyleProp<ViewStyle>
|
||||||
href?: string
|
href?: string
|
||||||
@@ -77,7 +81,7 @@ export const Link = memo(function Link({
|
|||||||
const anchorHref = asAnchor ? sanitizeUrl(href) : undefined
|
const anchorHref = asAnchor ? sanitizeUrl(href) : undefined
|
||||||
const openLink = useOpenLink()
|
const openLink = useOpenLink()
|
||||||
|
|
||||||
const onPress = React.useCallback(
|
const onPress = useCallback(
|
||||||
(e?: Event) => {
|
(e?: Event) => {
|
||||||
onBeforePress?.()
|
onBeforePress?.()
|
||||||
if (typeof href === 'string') {
|
if (typeof href === 'string') {
|
||||||
@@ -164,9 +168,9 @@ export const TextLink = memo(function TextLink({
|
|||||||
text,
|
text,
|
||||||
numberOfLines,
|
numberOfLines,
|
||||||
lineHeight,
|
lineHeight,
|
||||||
dataSet,
|
dataSet: dataSetProp,
|
||||||
title,
|
title,
|
||||||
onPress,
|
onPress: onPressProp,
|
||||||
onBeforePress,
|
onBeforePress,
|
||||||
disableMismatchWarning,
|
disableMismatchWarning,
|
||||||
navigationAction,
|
navigationAction,
|
||||||
@@ -187,7 +191,12 @@ export const TextLink = memo(function TextLink({
|
|||||||
anchorNoUnderline?: boolean
|
anchorNoUnderline?: boolean
|
||||||
onBeforePress?: () => void
|
onBeforePress?: () => void
|
||||||
} & TextProps) {
|
} & TextProps) {
|
||||||
const {...props} = useLinkProps({to: sanitizeUrl(href)})
|
const {buildAction} = useLinkBuilder()
|
||||||
|
const sanitized = sanitizeUrl(href)
|
||||||
|
const {onPress: _, ...props} = useLinkProps({
|
||||||
|
href: sanitized,
|
||||||
|
action: buildAction(sanitized),
|
||||||
|
})
|
||||||
const navigation = useNavigationDeduped()
|
const navigation = useNavigationDeduped()
|
||||||
const {openModal, closeModal} = useModalControls()
|
const {openModal, closeModal} = useModalControls()
|
||||||
const openLink = useOpenLink()
|
const openLink = useOpenLink()
|
||||||
@@ -196,12 +205,15 @@ export const TextLink = memo(function TextLink({
|
|||||||
console.error('Unable to detect mismatching label')
|
console.error('Unable to detect mismatching label')
|
||||||
}
|
}
|
||||||
|
|
||||||
if (anchorNoUnderline) {
|
const dataSet = useMemo(() => {
|
||||||
dataSet = dataSet ?? {}
|
const ds = {...dataSetProp}
|
||||||
dataSet.noUnderline = 1
|
if (anchorNoUnderline) {
|
||||||
}
|
ds.noUnderline = 1
|
||||||
|
}
|
||||||
|
return ds
|
||||||
|
}, [dataSetProp, anchorNoUnderline])
|
||||||
|
|
||||||
props.onPress = React.useCallback(
|
const onPress = useCallback(
|
||||||
(e?: Event) => {
|
(e?: Event) => {
|
||||||
const requiresWarning =
|
const requiresWarning =
|
||||||
!disableMismatchWarning &&
|
!disableMismatchWarning &&
|
||||||
@@ -224,10 +236,10 @@ export const TextLink = memo(function TextLink({
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
onBeforePress?.()
|
onBeforePress?.()
|
||||||
if (onPress) {
|
if (onPressProp) {
|
||||||
e?.preventDefault?.()
|
e?.preventDefault?.()
|
||||||
// @ts-ignore function signature differs by platform -prf
|
// @ts-expect-error function signature differs by platform -prf
|
||||||
return onPress()
|
return onPressProp()
|
||||||
}
|
}
|
||||||
return onPressInner(
|
return onPressInner(
|
||||||
closeModal,
|
closeModal,
|
||||||
@@ -240,7 +252,7 @@ export const TextLink = memo(function TextLink({
|
|||||||
},
|
},
|
||||||
[
|
[
|
||||||
onBeforePress,
|
onBeforePress,
|
||||||
onPress,
|
onPressProp,
|
||||||
closeModal,
|
closeModal,
|
||||||
openModal,
|
openModal,
|
||||||
navigation,
|
navigation,
|
||||||
@@ -273,6 +285,7 @@ export const TextLink = memo(function TextLink({
|
|||||||
title={title}
|
title={title}
|
||||||
// @ts-ignore web only -prf
|
// @ts-ignore web only -prf
|
||||||
hrefAttrs={hrefAttrs} // hack to get open in new tab to work on safari. without this, safari will open in a new window
|
hrefAttrs={hrefAttrs} // hack to get open in new tab to work on safari. without this, safari will open in a new window
|
||||||
|
onPress={onPress}
|
||||||
{...props}
|
{...props}
|
||||||
{...orgProps}>
|
{...orgProps}>
|
||||||
{text}
|
{text}
|
||||||
|
|||||||
@@ -1,10 +1,10 @@
|
|||||||
import React from 'react'
|
import {useCallback, useMemo, useState} from 'react'
|
||||||
import {StyleSheet, View} from 'react-native'
|
import {StyleSheet, View} from 'react-native'
|
||||||
import {type AppBskyActorDefs} from '@atproto/api'
|
import {type AppBskyActorDefs} from '@atproto/api'
|
||||||
import {msg, plural, Trans} from '@lingui/macro'
|
import {msg, plural, Trans} from '@lingui/macro'
|
||||||
import {useLingui} from '@lingui/react'
|
import {useLingui} from '@lingui/react'
|
||||||
import {
|
import {
|
||||||
useLinkProps,
|
useLinkTo,
|
||||||
useNavigation,
|
useNavigation,
|
||||||
useNavigationState,
|
useNavigationState,
|
||||||
} from '@react-navigation/native'
|
} from '@react-navigation/native'
|
||||||
@@ -326,7 +326,7 @@ function NavItem({count, hasNew, href, icon, iconFilled, label}: NavItemProps) {
|
|||||||
const {_} = useLingui()
|
const {_} = useLingui()
|
||||||
const {currentAccount} = useSession()
|
const {currentAccount} = useSession()
|
||||||
const {leftNavMinimal} = useLayoutBreakpoints()
|
const {leftNavMinimal} = useLayoutBreakpoints()
|
||||||
const [pathName] = React.useMemo(() => router.matchPath(href), [href])
|
const [pathName] = useMemo(() => router.matchPath(href), [href])
|
||||||
const currentRouteInfo = useNavigationState(state => {
|
const currentRouteInfo = useNavigationState(state => {
|
||||||
if (!state) {
|
if (!state) {
|
||||||
return {name: 'Home'}
|
return {name: 'Home'}
|
||||||
@@ -339,8 +339,8 @@ function NavItem({count, hasNew, href, icon, iconFilled, label}: NavItemProps) {
|
|||||||
(currentRouteInfo.params as CommonNavigatorParams['Profile']).name ===
|
(currentRouteInfo.params as CommonNavigatorParams['Profile']).name ===
|
||||||
currentAccount?.handle
|
currentAccount?.handle
|
||||||
: isTab(currentRouteInfo.name, pathName)
|
: isTab(currentRouteInfo.name, pathName)
|
||||||
const {onPress} = useLinkProps({to: href})
|
const linkTo = useLinkTo()
|
||||||
const onPressWrapped = React.useCallback(
|
const onPressWrapped = useCallback(
|
||||||
(e: React.MouseEvent<HTMLAnchorElement, MouseEvent>) => {
|
(e: React.MouseEvent<HTMLAnchorElement, MouseEvent>) => {
|
||||||
if (e.ctrlKey || e.metaKey || e.altKey) {
|
if (e.ctrlKey || e.metaKey || e.altKey) {
|
||||||
return
|
return
|
||||||
@@ -349,10 +349,10 @@ function NavItem({count, hasNew, href, icon, iconFilled, label}: NavItemProps) {
|
|||||||
if (isCurrent) {
|
if (isCurrent) {
|
||||||
emitSoftReset()
|
emitSoftReset()
|
||||||
} else {
|
} else {
|
||||||
onPress()
|
linkTo(href)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
[onPress, isCurrent],
|
[linkTo, href, isCurrent],
|
||||||
)
|
)
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@@ -468,7 +468,7 @@ function ComposeBtn() {
|
|||||||
const {openComposer} = useOpenComposer()
|
const {openComposer} = useOpenComposer()
|
||||||
const {_} = useLingui()
|
const {_} = useLingui()
|
||||||
const {leftNavMinimal} = useLayoutBreakpoints()
|
const {leftNavMinimal} = useLayoutBreakpoints()
|
||||||
const [isFetchingHandle, setIsFetchingHandle] = React.useState(false)
|
const [isFetchingHandle, setIsFetchingHandle] = useState(false)
|
||||||
const fetchHandle = useFetchHandle()
|
const fetchHandle = useFetchHandle()
|
||||||
|
|
||||||
const getProfileHandle = async () => {
|
const getProfileHandle = async () => {
|
||||||
|
|||||||
Reference in New Issue
Block a user