Fix link warnings (#3058)

* fix problems where www.bsky.app shows as a potential danger

* never default to disabling warning

* remove more defaults

* update storybook cases

* oops

* reverse
This commit is contained in:
Hailey 2024-02-29 15:23:28 -08:00 committed by GitHub
parent 1a5afccdb8
commit 39d324ab8b
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
6 changed files with 24 additions and 44 deletions

View file

@ -49,7 +49,7 @@ type BaseLinkProps = Pick<
* *
* Note: atm this only works for `InlineLink`s with a string child. * Note: atm this only works for `InlineLink`s with a string child.
*/ */
warnOnMismatchingTextChild?: boolean disableMismatchWarning?: boolean
/** /**
* Callback for when the link is pressed. Prevent default and return `false` * Callback for when the link is pressed. Prevent default and return `false`
@ -69,7 +69,7 @@ export function useLink({
to, to,
displayText, displayText,
action = 'push', action = 'push',
warnOnMismatchingTextChild, disableMismatchWarning,
onPress: outerOnPress, onPress: outerOnPress,
}: BaseLinkProps & { }: BaseLinkProps & {
displayText: string displayText: string
@ -90,7 +90,7 @@ export function useLink({
if (exitEarlyIfFalse === false) return if (exitEarlyIfFalse === false) return
const requiresWarning = Boolean( const requiresWarning = Boolean(
warnOnMismatchingTextChild && !disableMismatchWarning &&
displayText && displayText &&
isExternal && isExternal &&
linkRequiresWarning(href, displayText), linkRequiresWarning(href, displayText),
@ -148,7 +148,7 @@ export function useLink({
}, },
[ [
outerOnPress, outerOnPress,
warnOnMismatchingTextChild, disableMismatchWarning,
displayText, displayText,
isExternal, isExternal,
href, href,
@ -167,7 +167,7 @@ export function useLink({
} }
} }
export type LinkProps = Omit<BaseLinkProps, 'warnOnMismatchingTextChild'> & export type LinkProps = Omit<BaseLinkProps, 'disableMismatchWarning'> &
Omit<ButtonProps, 'onPress' | 'disabled' | 'label'> Omit<ButtonProps, 'onPress' | 'disabled' | 'label'>
/** /**
@ -226,7 +226,7 @@ export function InlineLink({
children, children,
to, to,
action = 'push', action = 'push',
warnOnMismatchingTextChild, disableMismatchWarning,
style, style,
onPress: outerOnPress, onPress: outerOnPress,
download, download,
@ -239,7 +239,7 @@ export function InlineLink({
to, to,
displayText: stringChildren ? children : '', displayText: stringChildren ? children : '',
action, action,
warnOnMismatchingTextChild, disableMismatchWarning,
onPress: outerOnPress, onPress: outerOnPress,
}) })
const { const {

View file

@ -105,8 +105,7 @@ export function RichText({
to={link.uri} to={link.uri}
style={[...styles, {pointerEvents: 'auto'}]} style={[...styles, {pointerEvents: 'auto'}]}
// @ts-ignore TODO // @ts-ignore TODO
dataSet={WORD_WRAP} dataSet={WORD_WRAP}>
warnOnMismatchingLabel>
{toShortUrl(segment.text)} {toShortUrl(segment.text)}
</InlineLink>, </InlineLink>,
) )

View file

@ -157,17 +157,11 @@ export function linkRequiresWarning(uri: string, label: string) {
const host = urip.hostname.toLowerCase() const host = urip.hostname.toLowerCase()
if (host === 'bsky.app') { // Hosts that end with bsky.app or bsky.social should be trusted by default.
if (host.endsWith('bsky.app') || host.endsWith('bsky.social')) {
// if this is a link to internal content, // if this is a link to internal content,
// warn if it represents itself as a URL to another app // warn if it represents itself as a URL to another app
if ( return !!labelDomain && labelDomain !== host && isPossiblyAUrl(labelDomain)
labelDomain &&
labelDomain !== 'bsky.app' &&
isPossiblyAUrl(labelDomain)
) {
return true
}
return false
} else { } else {
// if this is a link to external content, // if this is a link to external content,
// warn if the label doesnt match the target // warn if the label doesnt match the target

View file

@ -159,7 +159,7 @@ export const TextLink = memo(function TextLink({
dataSet, dataSet,
title, title,
onPress, onPress,
warnOnMismatchingLabel, disableMismatchWarning,
navigationAction, navigationAction,
...orgProps ...orgProps
}: { }: {
@ -172,7 +172,7 @@ export const TextLink = memo(function TextLink({
lineHeight?: number lineHeight?: number
dataSet?: any dataSet?: any
title?: string title?: string
warnOnMismatchingLabel?: boolean disableMismatchWarning?: boolean
navigationAction?: 'push' | 'replace' | 'navigate' navigationAction?: 'push' | 'replace' | 'navigate'
} & TextProps) { } & TextProps) {
const {...props} = useLinkProps({to: sanitizeUrl(href)}) const {...props} = useLinkProps({to: sanitizeUrl(href)})
@ -180,14 +180,14 @@ export const TextLink = memo(function TextLink({
const {openModal, closeModal} = useModalControls() const {openModal, closeModal} = useModalControls()
const openLink = useOpenLink() const openLink = useOpenLink()
if (warnOnMismatchingLabel && typeof text !== 'string') { if (!disableMismatchWarning && typeof text !== 'string') {
console.error('Unable to detect mismatching label') console.error('Unable to detect mismatching label')
} }
props.onPress = React.useCallback( props.onPress = React.useCallback(
(e?: Event) => { (e?: Event) => {
const requiresWarning = const requiresWarning =
warnOnMismatchingLabel && !disableMismatchWarning &&
linkRequiresWarning(href, typeof text === 'string' ? text : '') linkRequiresWarning(href, typeof text === 'string' ? text : '')
if (requiresWarning) { if (requiresWarning) {
e?.preventDefault?.() e?.preventDefault?.()
@ -227,7 +227,7 @@ export const TextLink = memo(function TextLink({
navigation, navigation,
href, href,
text, text,
warnOnMismatchingLabel, disableMismatchWarning,
navigationAction, navigationAction,
openLink, openLink,
], ],

View file

@ -114,7 +114,6 @@ export function RichText({
href={link.uri} href={link.uri}
style={[style, lineHeightStyle, pal.link, {pointerEvents: 'auto'}]} style={[style, lineHeightStyle, pal.link, {pointerEvents: 'auto'}]}
dataSet={WORD_WRAP} dataSet={WORD_WRAP}
warnOnMismatchingLabel
selectable={selectable} selectable={selectable}
/>, />,
) )

View file

@ -4,7 +4,7 @@ import {View} from 'react-native'
import {useTheme, atoms as a} from '#/alf' import {useTheme, atoms as a} from '#/alf'
import {ButtonText} from '#/components/Button' import {ButtonText} from '#/components/Button'
import {InlineLink, Link} from '#/components/Link' import {InlineLink, Link} from '#/components/Link'
import {H1, H3, Text} from '#/components/Typography' import {H1, Text} from '#/components/Typography'
export function Links() { export function Links() {
const t = useTheme() const t = useTheme()
@ -13,31 +13,19 @@ export function Links() {
<H1>Links</H1> <H1>Links</H1>
<View style={[a.gap_md, a.align_start]}> <View style={[a.gap_md, a.align_start]}>
<InlineLink <InlineLink to="https://google.com" style={[a.text_lg]}>
to="https://bsky.social" https://google.com
warnOnMismatchingTextChild
style={[a.text_md]}>
External
</InlineLink> </InlineLink>
<InlineLink to="https://bsky.social" style={[a.text_md, t.atoms.text]}> <InlineLink to="https://google.com" style={[a.text_lg]}>
<H3>External with custom children</H3> External with custom children (google.com)
</InlineLink> </InlineLink>
<InlineLink <InlineLink
to="https://bsky.social" to="https://bsky.social"
style={[a.text_md, t.atoms.text_contrast_low]}> style={[a.text_md, t.atoms.text_contrast_low]}>
External with custom children Internal (bsky.social)
</InlineLink> </InlineLink>
<InlineLink <InlineLink to="https://bsky.app/profile/bsky.app" style={[a.text_md]}>
to="https://bsky.social" Internal (bsky.app)
warnOnMismatchingTextChild
style={[a.text_lg]}>
https://bsky.social
</InlineLink>
<InlineLink
to="https://bsky.app/profile/bsky.app"
warnOnMismatchingTextChild
style={[a.text_md]}>
Internal
</InlineLink> </InlineLink>
<Link <Link