Bluesky app fork with some witchin' additions 馃挮
at main 177 lines 5.1 kB view raw
1import {useCallback, useMemo} from 'react' 2import {View} from 'react-native' 3import {msg, Trans} from '@lingui/macro' 4import {useLingui} from '@lingui/react' 5 6import {useOpenLink} from '#/lib/hooks/useOpenLink' 7import {shareUrl} from '#/lib/sharing' 8import {isPossiblyAUrl, splitApexDomain} from '#/lib/strings/url-helpers' 9import {atoms as a, useBreakpoints, useTheme, web} from '#/alf' 10import {Button, ButtonText} from '#/components/Button' 11import * as Dialog from '#/components/Dialog' 12import {Text} from '#/components/Typography' 13import {useGlobalDialogsControlContext} from './Context' 14 15export function LinkWarningDialog() { 16 const {linkWarningDialogControl} = useGlobalDialogsControlContext() 17 18 return ( 19 <Dialog.Outer 20 control={linkWarningDialogControl.control} 21 nativeOptions={{preventExpansion: true}} 22 webOptions={{alignCenter: true}} 23 onClose={linkWarningDialogControl.clear}> 24 <Dialog.Handle /> 25 <LinkWarningDialogInner link={linkWarningDialogControl.value} /> 26 </Dialog.Outer> 27 ) 28} 29 30export function CustomLinkWarningDialog({ 31 control, 32 link, 33}: { 34 control: Dialog.DialogControlProps 35 link?: {href: string; displayText: string; share?: boolean} 36}) { 37 return ( 38 <Dialog.Outer control={control} nativeOptions={{preventExpansion: true}}> 39 <Dialog.Handle /> 40 <LinkWarningDialogInner link={link} /> 41 </Dialog.Outer> 42 ) 43} 44 45function LinkWarningDialogInner({ 46 link, 47}: { 48 link?: {href: string; displayText: string; share?: boolean} 49}) { 50 const control = Dialog.useDialogContext() 51 const {_} = useLingui() 52 const t = useTheme() 53 const openLink = useOpenLink() 54 const {gtMobile} = useBreakpoints() 55 56 const potentiallyMisleading = useMemo( 57 () => link && isPossiblyAUrl(link.displayText), 58 [link], 59 ) 60 61 const onPressVisit = useCallback(() => { 62 control.close(() => { 63 if (!link) return 64 if (link.share) { 65 shareUrl(link.href) 66 } else { 67 openLink(link.href, undefined, true) 68 } 69 }) 70 }, [control, link, openLink]) 71 72 const onCancel = useCallback(() => { 73 control.close() 74 }, [control]) 75 76 return ( 77 <Dialog.ScrollableInner 78 style={web({maxWidth: 450})} 79 label={ 80 potentiallyMisleading 81 ? _(msg`Potentially misleading link warning`) 82 : _(msg`Leaving Witchsky`) 83 }> 84 <View style={[a.gap_2xl]}> 85 <View style={[a.gap_sm]}> 86 <Text style={[a.font_bold, a.text_2xl]}> 87 {potentiallyMisleading ? ( 88 <Trans>Potentially misleading link</Trans> 89 ) : ( 90 <Trans>Leaving Witchsky</Trans> 91 )} 92 </Text> 93 <Text style={[t.atoms.text_contrast_high, a.text_md, a.leading_snug]}> 94 <Trans>This link is taking you to the following website:</Trans> 95 </Text> 96 {link && <LinkBox href={link.href} />} 97 {potentiallyMisleading && ( 98 <Text 99 style={[t.atoms.text_contrast_high, a.text_md, a.leading_snug]}> 100 <Trans>Make sure this is where you intend to go!</Trans> 101 </Text> 102 )} 103 </View> 104 <View 105 style={[ 106 a.flex_1, 107 a.gap_sm, 108 gtMobile && [a.flex_row_reverse, a.justify_start], 109 ]}> 110 <Button 111 label={link?.share ? _(msg`Share link`) : _(msg`Visit site`)} 112 accessibilityHint={_(msg`Opens link ${link?.href ?? ''}`)} 113 onPress={onPressVisit} 114 size="large" 115 variant="solid" 116 color={potentiallyMisleading ? 'secondary_inverted' : 'primary'}> 117 <ButtonText> 118 {link?.share ? ( 119 <Trans>Share link</Trans> 120 ) : ( 121 <Trans>Visit site</Trans> 122 )} 123 </ButtonText> 124 </Button> 125 <Button 126 label={_(msg`Go back`)} 127 onPress={onCancel} 128 size="large" 129 variant="ghost" 130 color="secondary"> 131 <ButtonText> 132 <Trans>Go back</Trans> 133 </ButtonText> 134 </Button> 135 </View> 136 </View> 137 <Dialog.Close /> 138 </Dialog.ScrollableInner> 139 ) 140} 141 142function LinkBox({href}: {href: string}) { 143 const t = useTheme() 144 const [scheme, hostname, rest] = useMemo(() => { 145 try { 146 const urlp = new URL(href) 147 const [subdomain, apexdomain] = splitApexDomain(urlp.hostname) 148 return [ 149 urlp.protocol + '//' + subdomain, 150 apexdomain, 151 urlp.pathname.replace(/\/$/, '') + urlp.search + urlp.hash, 152 ] 153 } catch { 154 return ['', href, ''] 155 } 156 }, [href]) 157 return ( 158 <View 159 style={[ 160 t.atoms.bg, 161 t.atoms.border_contrast_medium, 162 a.px_md, 163 {paddingVertical: 10}, 164 a.rounded_sm, 165 a.border, 166 ]}> 167 <Text style={[a.text_md, a.leading_snug, t.atoms.text_contrast_medium]}> 168 {scheme} 169 <Text 170 style={[a.text_md, a.leading_snug, t.atoms.text, a.font_semi_bold]}> 171 {hostname} 172 </Text> 173 {rest} 174 </Text> 175 </View> 176 ) 177}