Bluesky app fork with some witchin' additions 馃挮
at main 171 lines 4.0 kB view raw
1import {View} from 'react-native' 2import {msg} from '@lingui/core/macro' 3import {useLingui} from '@lingui/react' 4 5import { 6 usePdsLabelEnabled, 7 usePdsLabelHideBskyPds, 8} from '#/state/preferences/pds-label' 9import {usePdsFaviconQuery, usePdsLabelQuery} from '#/state/queries/pds-label' 10import {atoms as a, useBreakpoints} from '#/alf' 11import {Button} from '#/components/Button' 12import * as Dialog from '#/components/Dialog' 13import {PdsBadgeIcon, PdsDialog} from '#/components/PdsDialog' 14import {IS_WEB} from '#/env' 15 16export function PdsBadge({ 17 did, 18 handle, 19 size, 20 interactive = true, 21}: { 22 did: string 23 handle?: string 24 size: 'lg' | 'md' | 'sm' 25 interactive?: boolean 26}) { 27 const enabled = usePdsLabelEnabled() 28 const hideBskyPds = usePdsLabelHideBskyPds() 29 const {data, isLoading} = usePdsLabelQuery(enabled ? did : undefined) 30 const {data: faviconUrl} = usePdsFaviconQuery( 31 data && !data.isBsky && !data.isBridged ? data.pdsUrl : undefined, 32 ) 33 34 const isBskyHandle = 35 !!handle && (handle.endsWith('.bsky.social') || handle === 'bsky.social') 36 37 if (!enabled) return null 38 if (isLoading) return <PdsBadgeLoading size={size} isBsky={isBskyHandle} /> 39 if (!data) return null 40 if (hideBskyPds && data.isBsky) return null 41 42 return ( 43 <PdsBadgeInner 44 pdsUrl={data.pdsUrl} 45 faviconUrl={faviconUrl} 46 isBsky={data.isBsky} 47 isBridged={data.isBridged} 48 size={size} 49 interactive={interactive} 50 /> 51 ) 52} 53 54function PdsBadgeLoading({ 55 size, 56 isBsky = false, 57}: { 58 size: 'lg' | 'md' | 'sm' 59 isBsky?: boolean 60}) { 61 const {gtPhone} = useBreakpoints() 62 let dimensions = 12 63 if (size === 'lg') { 64 dimensions = gtPhone ? 20 : 18 65 } else if (size === 'md') { 66 dimensions = 14 67 } 68 return ( 69 <View style={{width: dimensions, height: dimensions}}> 70 <PdsBadgeIcon 71 faviconUrl={undefined} 72 isBsky={isBsky} 73 isBridged={false} 74 size={dimensions} 75 borderRadius={Math.round(dimensions * 0.25)} 76 /> 77 </View> 78 ) 79} 80 81function PdsBadgeInner({ 82 pdsUrl, 83 faviconUrl, 84 isBsky, 85 isBridged, 86 size, 87 interactive, 88}: { 89 pdsUrl: string 90 faviconUrl: string | undefined 91 isBsky: boolean 92 isBridged: boolean 93 size: 'lg' | 'md' | 'sm' 94 interactive: boolean 95}) { 96 const {_} = useLingui() 97 const {gtPhone} = useBreakpoints() 98 const dialogControl = Dialog.useDialogControl() 99 100 let dimensions = 12 101 if (size === 'lg') { 102 dimensions = gtPhone ? 20 : 18 103 } else if (size === 'md') { 104 dimensions = 14 105 } 106 107 const icon = ( 108 <PdsBadgeIcon 109 faviconUrl={faviconUrl} 110 isBsky={isBsky} 111 isBridged={isBridged} 112 size={dimensions} 113 borderRadius={Math.round(dimensions * 0.25)} 114 /> 115 ) 116 117 if (!interactive) { 118 return ( 119 <View 120 style={[ 121 a.justify_center, 122 a.align_center, 123 {width: dimensions, height: dimensions}, 124 ]}> 125 {icon} 126 </View> 127 ) 128 } 129 130 return ( 131 <> 132 <Button 133 label={_(msg`View PDS information`)} 134 hitSlop={20} 135 onPress={evt => { 136 evt.preventDefault() 137 dialogControl.open() 138 if (IS_WEB) { 139 ;(document.activeElement as HTMLElement | null)?.blur() 140 } 141 }}> 142 {({hovered}) => ( 143 <View style={{width: dimensions, height: dimensions}}> 144 <View 145 style={[ 146 a.justify_center, 147 a.align_center, 148 a.transition_transform, 149 { 150 position: 'absolute', 151 top: 0, 152 left: 0, 153 right: 0, 154 bottom: 0, 155 transform: [{scale: hovered ? 1.1 : 1}], 156 }, 157 ]}> 158 {icon} 159 </View> 160 </View> 161 )} 162 </Button> 163 164 <PdsDialog 165 control={dialogControl} 166 pdsUrl={pdsUrl} 167 faviconUrl={faviconUrl} 168 /> 169 </> 170 ) 171}