From 840cb09ce87eae6dc399caf0c6aae4291aba235c Mon Sep 17 00:00:00 2001 From: Samuel Newman Date: Fri, 11 Oct 2024 16:01:17 +0300 Subject: [PATCH] wip move to alf --- src/components/Link.tsx | 42 ++--- src/components/dialogs/LinkWarningDialog.tsx | 152 +++++++++++++++++++ 2 files changed, 174 insertions(+), 20 deletions(-) create mode 100644 src/components/dialogs/LinkWarningDialog.tsx diff --git a/src/components/Link.tsx b/src/components/Link.tsx index 447833a239..f49795750f 100644 --- a/src/components/Link.tsx +++ b/src/components/Link.tsx @@ -1,4 +1,4 @@ -import React from 'react' +import React, {useCallback, useState} from 'react' import { GestureResponderEvent, Pressable, @@ -20,10 +20,11 @@ import { } from '#/lib/strings/url-helpers' import {isNative, isWeb} from '#/platform/detection' import {shouldClickOpenNewTab} from '#/platform/urls' -import {useModalControls} from '#/state/modals' import {useOpenLink} from '#/state/preferences/in-app-browser' +import {useCloseAllActiveElements} from '#/state/util' import {atoms as a, flatten, TextStyleProp, useTheme, web} from '#/alf' import {Button, ButtonProps} from '#/components/Button' +import {useDialogControl} from '#/components/Dialog' import {useInteractionState} from '#/components/hooks/useInteractionState' import {Text, TextProps} from '#/components/Typography' import {router} from '#/routes' @@ -87,10 +88,20 @@ export function useLink({ typeof to === 'string' ? convertBskyAppUrlIfNeeded(sanitizeUrl(to)) : to, }) const isExternal = isExternalUrl(href) - const {openModal, closeModal} = useModalControls() const openLink = useOpenLink() + const dismissEverything = useCloseAllActiveElements() + const [_warningMode, setWarningMode] = useState<'open' | 'share'>('open') + const linkWarningControl = useDialogControl() - const onPress = React.useCallback( + const showWarningDialog = useCallback( + (mode: 'open' | 'share') => { + setWarningMode(mode) + linkWarningControl.open() + }, + [linkWarningControl], + ) + + const onPress = useCallback( (e: GestureResponderEvent) => { const exitEarlyIfFalse = outerOnPress?.(e) @@ -108,11 +119,7 @@ export function useLink({ } if (requiresWarning) { - openModal({ - name: 'link-warning', - text: displayText, - href: href, - }) + showWarningDialog('open') } else { if (isExternal) { openLink(href) @@ -128,7 +135,7 @@ export function useLink({ ) { openLink(href) } else { - closeModal() // close any active modals + dismissEverything() // close any active dialogs if (action === 'push') { navigation.dispatch(StackActions.push(...router.matchPath(href))) @@ -152,15 +159,15 @@ export function useLink({ displayText, isExternal, href, - openModal, openLink, - closeModal, action, navigation, + showWarningDialog, + dismissEverything, ], ) - const handleLongPress = React.useCallback(() => { + const handleLongPress = useCallback(() => { const requiresWarning = Boolean( !disableMismatchWarning && displayText && @@ -169,16 +176,11 @@ export function useLink({ ) if (requiresWarning) { - openModal({ - name: 'link-warning', - text: displayText, - href: href, - share: true, - }) + showWarningDialog('share') } else { shareUrl(href) } - }, [disableMismatchWarning, displayText, href, isExternal, openModal]) + }, [disableMismatchWarning, displayText, href, isExternal, showWarningDialog]) const onLongPress = isNative && isExternal && shareOnLongPress ? handleLongPress : undefined diff --git a/src/components/dialogs/LinkWarningDialog.tsx b/src/components/dialogs/LinkWarningDialog.tsx new file mode 100644 index 0000000000..6e3c7c5aa6 --- /dev/null +++ b/src/components/dialogs/LinkWarningDialog.tsx @@ -0,0 +1,152 @@ +import React 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, useTheme} from '#/alf' +import {Button, ButtonText} from '#/components/Button' +import * as Dialog from '#/components/Dialog' +import {Text} from '#/components/Typography' + +export function LinkWarningDialog({ + control, + linkText, + linkHref, + mode = 'open', +}: { + control: Dialog.DialogControlProps + linkText: string + linkHref: string + mode?: 'open' | 'share' +}) { + return ( + + + + + ) +} + +function DialogInner({ + linkText, + linkHref, + mode, +}: { + linkText: string + linkHref: string + mode: 'open' | 'share' +}) { + const control = Dialog.useDialogContext() + const {_} = useLingui() + const potentiallyMisleading = isPossiblyAUrl(linkText) + const openLink = useOpenLink() + + const share = mode === 'share' + + const onPressVisit = () => { + control.close(() => { + if (share) { + shareUrl(linkHref) + } else { + openLink(linkHref) + } + }) + } + return ( + + + {potentiallyMisleading ? ( + <> + {/* */} + + Potentially Misleading Link + + + ) : ( + + Leaving Bluesky + + )} + + + + + This link is taking you to the following website: + + + + + {potentiallyMisleading && ( + + Make sure this is where you intend to go! + + )} + + + + + + + + ) +} + +function LinkBox({href}: {href: string}) { + const t = useTheme() + const [scheme, hostname, rest] = React.useMemo(() => { + try { + const urlp = new URL(href) + const [subdomain, apexdomain] = splitApexDomain(urlp.hostname) + return [ + urlp.protocol + '//' + subdomain, + apexdomain, + urlp.pathname + urlp.search + urlp.hash, + ] + } catch { + return ['', href, ''] + } + }, [href]) + return ( + + + {scheme} + {hostname} + {rest} + + + ) +}