diff options
author | Samuel Newman <mozzius@protonmail.com> | 2025-06-18 16:17:54 +0300 |
---|---|---|
committer | GitHub <noreply@github.com> | 2025-06-18 06:17:54 -0700 |
commit | 4da86e5864e10b14880900b78cb94d33c199b7da (patch) | |
tree | 2ace2cc361d2c84a145b9e163c06733f0b6ef241 /src/components/dialogs/LinkWarning.tsx | |
parent | dd86402763518ae94ced8274dda886f92ec7b51e (diff) | |
download | voidsky-4da86e5864e10b14880900b78cb94d33c199b7da.tar.zst |
Modernise link warning dialog (#8243)
* add link warning dialog * add copy for if sharing * delete old modal * get web working
Diffstat (limited to 'src/components/dialogs/LinkWarning.tsx')
-rw-r--r-- | src/components/dialogs/LinkWarning.tsx | 161 |
1 files changed, 161 insertions, 0 deletions
diff --git a/src/components/dialogs/LinkWarning.tsx b/src/components/dialogs/LinkWarning.tsx new file mode 100644 index 000000000..9ae871812 --- /dev/null +++ b/src/components/dialogs/LinkWarning.tsx @@ -0,0 +1,161 @@ +import {useCallback, useMemo} 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 {shareUrl} from '#/lib/sharing' +import {isPossiblyAUrl, splitApexDomain} from '#/lib/strings/url-helpers' +import {atoms as a, useBreakpoints, useTheme, web} from '#/alf' +import {Button, ButtonText} from '#/components/Button' +import * as Dialog from '#/components/Dialog' +import {Text} from '#/components/Typography' +import {useGlobalDialogsControlContext} from './Context' + +export function LinkWarningDialog() { + const {linkWarningDialogControl} = useGlobalDialogsControlContext() + + return ( + <Dialog.Outer + control={linkWarningDialogControl.control} + nativeOptions={{preventExpansion: true}} + webOptions={{alignCenter: true}} + onClose={linkWarningDialogControl.clear}> + <Dialog.Handle /> + <InAppBrowserConsentInner link={linkWarningDialogControl.value} /> + </Dialog.Outer> + ) +} + +function InAppBrowserConsentInner({ + link, +}: { + link?: {href: string; displayText: string; share?: boolean} +}) { + const control = Dialog.useDialogContext() + const {_} = useLingui() + const t = useTheme() + const openLink = useOpenLink() + const {gtMobile} = useBreakpoints() + + const potentiallyMisleading = useMemo( + () => link && isPossiblyAUrl(link.displayText), + [link], + ) + + const onPressVisit = useCallback(() => { + control.close(() => { + if (!link) return + if (link.share) { + shareUrl(link.href) + } else { + openLink(link.href, undefined, true) + } + }) + }, [control, link, openLink]) + + const onCancel = useCallback(() => { + control.close() + }, [control]) + + return ( + <Dialog.ScrollableInner + style={web({maxWidth: 450})} + label={ + potentiallyMisleading + ? _(msg`Potentially misleading link warning`) + : _(msg`Leaving Bluesky`) + }> + <View style={[a.gap_2xl]}> + <View style={[a.gap_sm]}> + <Text style={[a.font_heavy, a.text_2xl]}> + {potentiallyMisleading ? ( + <Trans>Potentially misleading link</Trans> + ) : ( + <Trans>Leaving Bluesky</Trans> + )} + </Text> + <Text style={[t.atoms.text_contrast_high, a.text_md, a.leading_snug]}> + <Trans>This link is taking you to the following website:</Trans> + </Text> + {link && <LinkBox href={link.href} />} + {potentiallyMisleading && ( + <Text + style={[t.atoms.text_contrast_high, a.text_md, a.leading_snug]}> + <Trans>Make sure this is where you intend to go!</Trans> + </Text> + )} + </View> + <View + style={[ + a.flex_1, + a.gap_sm, + gtMobile && [a.flex_row_reverse, a.justify_start], + ]}> + <Button + label={link?.share ? _(msg`Share link`) : _(msg`Visit site`)} + accessibilityHint={_(msg`Opens link ${link?.href ?? ''}`)} + onPress={onPressVisit} + size="large" + variant="solid" + color={potentiallyMisleading ? 'secondary_inverted' : 'primary'}> + <ButtonText> + {link?.share ? ( + <Trans>Share link</Trans> + ) : ( + <Trans>Visit site</Trans> + )} + </ButtonText> + </Button> + <Button + label={_(msg`Go back`)} + onPress={onCancel} + size="large" + variant="ghost" + color="secondary"> + <ButtonText> + <Trans>Go back</Trans> + </ButtonText> + </Button> + </View> + </View> + <Dialog.Close /> + </Dialog.ScrollableInner> + ) +} + +function LinkBox({href}: {href: string}) { + const t = useTheme() + const [scheme, hostname, rest] = useMemo(() => { + try { + const urlp = new URL(href) + const [subdomain, apexdomain] = splitApexDomain(urlp.hostname) + return [ + urlp.protocol + '//' + subdomain, + apexdomain, + urlp.pathname.replace(/\/$/, '') + urlp.search + urlp.hash, + ] + } catch { + return ['', href, ''] + } + }, [href]) + return ( + <View + style={[ + t.atoms.bg, + t.atoms.border_contrast_medium, + a.px_md, + {paddingVertical: 10}, + a.rounded_sm, + a.border, + ]}> + <Text style={[a.text_md, a.leading_snug, t.atoms.text_contrast_medium]}> + {scheme} + <Text style={[a.text_md, a.leading_snug, t.atoms.text, a.font_bold]}> + {hostname} + </Text> + {rest} + </Text> + </View> + ) +} |