Bluesky app fork with some witchin' additions 馃挮
at readme-update 162 lines 4.8 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 <InAppBrowserConsentInner link={linkWarningDialogControl.value} /> 26 </Dialog.Outer> 27 ) 28} 29 30function InAppBrowserConsentInner({ 31 link, 32}: { 33 link?: {href: string; displayText: string; share?: boolean} 34}) { 35 const control = Dialog.useDialogContext() 36 const {_} = useLingui() 37 const t = useTheme() 38 const openLink = useOpenLink() 39 const {gtMobile} = useBreakpoints() 40 41 const potentiallyMisleading = useMemo( 42 () => link && isPossiblyAUrl(link.displayText), 43 [link], 44 ) 45 46 const onPressVisit = useCallback(() => { 47 control.close(() => { 48 if (!link) return 49 if (link.share) { 50 shareUrl(link.href) 51 } else { 52 openLink(link.href, undefined, true) 53 } 54 }) 55 }, [control, link, openLink]) 56 57 const onCancel = useCallback(() => { 58 control.close() 59 }, [control]) 60 61 return ( 62 <Dialog.ScrollableInner 63 style={web({maxWidth: 450})} 64 label={ 65 potentiallyMisleading 66 ? _(msg`Potentially misleading link warning`) 67 : _(msg`Leaving Witchsky`) 68 }> 69 <View style={[a.gap_2xl]}> 70 <View style={[a.gap_sm]}> 71 <Text style={[a.font_bold, a.text_2xl]}> 72 {potentiallyMisleading ? ( 73 <Trans>Potentially misleading link</Trans> 74 ) : ( 75 <Trans>Leaving Witchsky</Trans> 76 )} 77 </Text> 78 <Text style={[t.atoms.text_contrast_high, a.text_md, a.leading_snug]}> 79 <Trans>This link is taking you to the following website:</Trans> 80 </Text> 81 {link && <LinkBox href={link.href} />} 82 {potentiallyMisleading && ( 83 <Text 84 style={[t.atoms.text_contrast_high, a.text_md, a.leading_snug]}> 85 <Trans>Make sure this is where you intend to go!</Trans> 86 </Text> 87 )} 88 </View> 89 <View 90 style={[ 91 a.flex_1, 92 a.gap_sm, 93 gtMobile && [a.flex_row_reverse, a.justify_start], 94 ]}> 95 <Button 96 label={link?.share ? _(msg`Share link`) : _(msg`Visit site`)} 97 accessibilityHint={_(msg`Opens link ${link?.href ?? ''}`)} 98 onPress={onPressVisit} 99 size="large" 100 variant="solid" 101 color={potentiallyMisleading ? 'secondary_inverted' : 'primary'}> 102 <ButtonText> 103 {link?.share ? ( 104 <Trans>Share link</Trans> 105 ) : ( 106 <Trans>Visit site</Trans> 107 )} 108 </ButtonText> 109 </Button> 110 <Button 111 label={_(msg`Go back`)} 112 onPress={onCancel} 113 size="large" 114 variant="ghost" 115 color="secondary"> 116 <ButtonText> 117 <Trans>Go back</Trans> 118 </ButtonText> 119 </Button> 120 </View> 121 </View> 122 <Dialog.Close /> 123 </Dialog.ScrollableInner> 124 ) 125} 126 127function LinkBox({href}: {href: string}) { 128 const t = useTheme() 129 const [scheme, hostname, rest] = useMemo(() => { 130 try { 131 const urlp = new URL(href) 132 const [subdomain, apexdomain] = splitApexDomain(urlp.hostname) 133 return [ 134 urlp.protocol + '//' + subdomain, 135 apexdomain, 136 urlp.pathname.replace(/\/$/, '') + urlp.search + urlp.hash, 137 ] 138 } catch { 139 return ['', href, ''] 140 } 141 }, [href]) 142 return ( 143 <View 144 style={[ 145 t.atoms.bg, 146 t.atoms.border_contrast_medium, 147 a.px_md, 148 {paddingVertical: 10}, 149 a.rounded_sm, 150 a.border, 151 ]}> 152 <Text style={[a.text_md, a.leading_snug, t.atoms.text_contrast_medium]}> 153 {scheme} 154 <Text 155 style={[a.text_md, a.leading_snug, t.atoms.text, a.font_semi_bold]}> 156 {hostname} 157 </Text> 158 {rest} 159 </Text> 160 </View> 161 ) 162}