Bluesky app fork with some witchin' additions 馃挮
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

fix: placeholder square avatars, error from build system, lint errors, via text spacing

- starter pack edit screen was broken because of the different web bundler
- enableSquareAvatars support for AvatarStack background outline
- psl? (lint error fix)
- lot of placeholders (skeleton loaders lol) that needed to have square avatars
- added ` 路 ` between via value and date

+115 -21
+37 -2
rspack.config.ts
··· 89 89 } 90 90 91 91 const transpileModuleDirs = getTranspileModuleDirs(TRANSPILE_MODULES) 92 + const REANIMATED_BABEL_MODULES = ['react-native-keyboard-controller'] 93 + const reanimatedBabelModuleDirs = REANIMATED_BABEL_MODULES.map(pkg => 94 + path.resolve(__dirname, 'node_modules', ...pkg.split('/')), 95 + ).filter(existsSync) 92 96 const SWC_TRANSPILE_EXCLUDE = /node_modules[\\/]react-native-uuid[\\/]/ 97 + const REANIMATED_BABEL_EXCLUDE = 98 + /node_modules[\\/]react-native-keyboard-controller[\\/]/ 93 99 94 100 /** @type {import('@rspack/core').Configuration} */ 95 101 module.exports = { ··· 211 217 }, 212 218 }, 213 219 }, 220 + // Some published packages ship raw `"worklet"` functions and must go 221 + // through Babel with the Reanimated plugin on web, matching Expo's 222 + // webpack pipeline. SWC alone leaves those functions unworkletized. 223 + { 224 + test: /\.[jt]sx?$/, 225 + include: reanimatedBabelModuleDirs, 226 + use: { 227 + loader: 'babel-loader', 228 + options: { 229 + configFile: false, 230 + babelrc: false, 231 + cacheDirectory: true, 232 + cacheCompression: false, 233 + sourceType: 'unambiguous', 234 + presets: [ 235 + [ 236 + 'babel-preset-expo', 237 + { 238 + lazyImports: true, 239 + native: { 240 + disableImportExportTransform: true, 241 + }, 242 + }, 243 + ], 244 + ], 245 + plugins: ['react-native-reanimated/plugin'], 246 + }, 247 + }, 248 + }, 214 249 // node_modules that ship untranspiled JSX/Flow: use rspack's builtin 215 250 // SWC loader which is much faster than babel for simple transforms. 216 251 { 217 252 test: /\.jsx?$/, 218 253 include: transpileModuleDirs, 219 - exclude: SWC_TRANSPILE_EXCLUDE, 254 + exclude: [SWC_TRANSPILE_EXCLUDE, REANIMATED_BABEL_EXCLUDE], 220 255 use: { 221 256 loader: 'swc-loader', // rspack swc-loader doesn't support flow yet 222 257 options: { ··· 237 272 { 238 273 test: /\.tsx?$/, 239 274 include: transpileModuleDirs, 240 - exclude: SWC_TRANSPILE_EXCLUDE, 275 + exclude: [SWC_TRANSPILE_EXCLUDE, REANIMATED_BABEL_EXCLUDE], 241 276 use: { 242 277 loader: 'swc-loader', 243 278 options: {
+6 -2
src/components/AvatarStack.tsx
··· 2 2 import {moderateProfile} from '@atproto/api' 3 3 4 4 import {logger} from '#/logger' 5 + import {useEnableSquareAvatars} from '#/state/preferences/enable-square-avatars' 5 6 import {useModerationOpts} from '#/state/preferences/moderation-opts' 6 7 import {useProfilesQuery} from '#/state/queries/profile' 7 8 import {UserAvatar} from '#/view/com/util/UserAvatar' ··· 22 23 const translation = size / 3 // overlap by 1/3 23 24 const t = useTheme() 24 25 const moderationOpts = useModerationOpts() 26 + const enableSquareAvatars = useEnableSquareAvatars() 25 27 26 28 const isPending = (numPending && profiles.length === 0) || !moderationOpts 27 29 ··· 57 59 left: i * -translation, 58 60 borderWidth: 1, 59 61 borderColor: backgroundColor ?? t.atoms.bg.backgroundColor, 60 - borderRadius: 999, 62 + borderRadius: enableSquareAvatars ? (size > 32 ? 8 : 3) : 999, 61 63 zIndex: 3 - i, 62 64 }, 63 65 ]}> ··· 97 99 98 100 const orderedProfiles = profiles 99 101 .map(did => data?.profiles?.find(profile => profile.did === did)) 100 - .filter(Boolean) 102 + .filter((profile): profile is NonNullable<typeof profile> => 103 + Boolean(profile), 104 + ) 101 105 102 106 return ( 103 107 <AvatarStack
+18
src/global.d.ts
··· 1 1 // TS6.0 enables noUncheckedSideEffectImports 2 2 declare module '*.css' 3 + 4 + declare module 'psl' { 5 + export type ParsedDomain = { 6 + input: string 7 + tld: string | null 8 + sld: string | null 9 + domain: string | null 10 + subdomain: string | null 11 + listed: boolean 12 + error?: Error 13 + } 14 + 15 + const psl: { 16 + parse(domain: string): ParsedDomain 17 + } 18 + 19 + export default psl 20 + }
+3 -1
src/screens/Bookmarks/index.tsx
··· 21 21 type CommonNavigatorParams, 22 22 type NativeStackScreenProps, 23 23 } from '#/lib/routes/types' 24 + import {useEnableSquareAvatars} from '#/state/preferences/enable-square-avatars' 24 25 import {useBookmarkMutation} from '#/state/queries/bookmarks/useBookmarkMutation' 25 26 import {useBookmarksQuery} from '#/state/queries/bookmarks/useBookmarksQuery' 26 27 import {Post} from '#/view/com/post/Post' ··· 208 209 }) { 209 210 const t = useTheme() 210 211 const {_} = useLingui() 212 + const enableSquareAvatars = useEnableSquareAvatars() 211 213 const {mutateAsync: bookmark} = useBookmarkMutation() 212 214 const cleanError = useCleanError() 213 215 ··· 236 238 !hideTopBorder && a.border_t, 237 239 t.atoms.border_contrast_low, 238 240 ]}> 239 - <Skele.Circle size={42}> 241 + <Skele.Circle size={42} style={enableSquareAvatars && {borderRadius: 8}}> 240 242 <QuestionIcon size="lg" fill={t.atoms.text_contrast_low.color} /> 241 243 </Skele.Circle> 242 244 <View style={[a.flex_1, a.gap_2xs]}>
+8 -8
src/screens/PostThread/components/ThreadItemAnchor.tsx
··· 26 26 import {useDisableQuotesMetrics} from '#/state/preferences/disable-quotes-metrics' 27 27 import {useDisableRepostsMetrics} from '#/state/preferences/disable-reposts-metrics' 28 28 import {useDisableSavesMetrics} from '#/state/preferences/disable-saves-metrics' 29 + import {useEnableSquareAvatars} from '#/state/preferences/enable-square-avatars' 29 30 import {useEnableSquareButtons} from '#/state/preferences/enable-square-buttons' 30 31 import {useHideScaryFollowButtons} from '#/state/preferences/hide-scary-follow-buttons' 31 32 import {useShowViaClient} from '#/state/preferences/show-via-client' ··· 593 594 <View style={[a.flex_row, a.align_center, a.flex_wrap, a.gap_sm]}> 594 595 <Text style={[a.text_sm, t.atoms.text_contrast_medium]}> 595 596 {niceDate(i18n, post.indexedAt, 'dot separated')} 597 + {showViaClient && via ? ` 路 ${truncateVia(via)}` : null} 596 598 </Text> 597 - {showViaClient && via ? ( 598 - <Text 599 - numberOfLines={1} 600 - style={[a.text_sm, t.atoms.text_contrast_medium, {maxWidth: 160}]}> 601 - {truncateVia(via)} 602 - </Text> 603 - ) : null} 604 599 {isRootPost && ( 605 600 <WhoCanReply post={post} isThreadAuthor={isThreadAuthor} /> 606 601 )} ··· 718 713 } 719 714 720 715 export function ThreadItemAnchorSkeleton() { 716 + const enableSquareAvatars = useEnableSquareAvatars() 717 + 721 718 return ( 722 719 <View style={[a.p_lg, a.gap_md]}> 723 720 <Skele.Row style={[a.align_center, a.gap_md]}> 724 - <Skele.Circle size={42} /> 721 + <Skele.Circle 722 + size={42} 723 + style={enableSquareAvatars && {borderRadius: 8}} 724 + /> 725 725 726 726 <Skele.Col> 727 727 <Skele.Text style={[a.text_lg, {width: '20%'}]} />
+5 -1
src/screens/PostThread/components/ThreadItemAnchorNoUnauthenticated.tsx
··· 1 1 import {View} from 'react-native' 2 2 import {Trans} from '@lingui/react/macro' 3 3 4 + import {useEnableSquareAvatars} from '#/state/preferences/enable-square-avatars' 4 5 import {atoms as a, useTheme} from '#/alf' 5 6 import {Lock_Stroke2_Corner0_Rounded as LockIcon} from '#/components/icons/Lock' 6 7 import * as Skele from '#/components/Skeleton' ··· 8 9 9 10 export function ThreadItemAnchorNoUnauthenticated() { 10 11 const t = useTheme() 12 + const enableSquareAvatars = useEnableSquareAvatars() 11 13 12 14 return ( 13 15 <View style={[a.p_lg, a.gap_md]}> 14 16 <Skele.Row style={[a.align_center, a.gap_md]}> 15 - <Skele.Circle size={42}> 17 + <Skele.Circle 18 + size={42} 19 + style={enableSquareAvatars && {borderRadius: 8}}> 16 20 <LockIcon size="md" fill={t.atoms.text_contrast_medium.color} /> 17 21 </Skele.Circle> 18 22
+6 -1
src/screens/PostThread/components/ThreadItemPost.tsx
··· 17 17 type Shadow, 18 18 usePostShadow, 19 19 } from '#/state/cache/post-shadow' 20 + import {useEnableSquareAvatars} from '#/state/preferences/enable-square-avatars' 20 21 import {type ThreadItem} from '#/state/queries/usePostThread/types' 21 22 import {useSession} from '#/state/session' 22 23 import {type OnPostSuccessData} from '#/state/shell/composer' ··· 387 388 } 388 389 389 390 export function ThreadItemPostSkeleton({index}: {index: number}) { 391 + const enableSquareAvatars = useEnableSquareAvatars() 390 392 const even = index % 2 === 0 391 393 return ( 392 394 <View ··· 395 397 a.gap_md, 396 398 ]}> 397 399 <Skele.Row style={[a.align_start, a.gap_md]}> 398 - <Skele.Circle size={LINEAR_AVI_WIDTH} /> 400 + <Skele.Circle 401 + size={LINEAR_AVI_WIDTH} 402 + style={enableSquareAvatars && {borderRadius: 8}} 403 + /> 399 404 400 405 <Skele.Col style={[a.gap_xs]}> 401 406 <Skele.Row style={[a.gap_sm]}>
+5 -1
src/screens/PostThread/components/ThreadItemPostNoUnauthenticated.tsx
··· 1 1 import {View} from 'react-native' 2 2 import {Trans} from '@lingui/react/macro' 3 3 4 + import {useEnableSquareAvatars} from '#/state/preferences/enable-square-avatars' 4 5 import {type ThreadItem} from '#/state/queries/usePostThread/types' 5 6 import { 6 7 LINEAR_AVI_WIDTH, ··· 18 19 item: Extract<ThreadItem, {type: 'threadPostNoUnauthenticated'}> 19 20 }) { 20 21 const t = useTheme() 22 + const enableSquareAvatars = useEnableSquareAvatars() 21 23 22 24 return ( 23 25 <View style={[{paddingHorizontal: OUTER_SPACE}]}> ··· 39 41 </View> 40 42 </View> 41 43 <Skele.Row style={[a.align_center, a.gap_md]}> 42 - <Skele.Circle size={LINEAR_AVI_WIDTH}> 44 + <Skele.Circle 45 + size={LINEAR_AVI_WIDTH} 46 + style={enableSquareAvatars && {borderRadius: 8}}> 43 47 <LockIcon size="md" fill={t.atoms.text_contrast_medium.color} /> 44 48 </Skele.Circle> 45 49
+6 -1
src/screens/PostThread/components/ThreadItemReplyComposer.tsx
··· 1 1 import {View} from 'react-native' 2 2 3 + import {useEnableSquareAvatars} from '#/state/preferences/enable-square-avatars' 3 4 import {atoms as a, useBreakpoints, useTheme} from '#/alf' 4 5 import * as Skele from '#/components/Skeleton' 5 6 6 7 export function ThreadItemReplyComposerSkeleton() { 7 8 const t = useTheme() 8 9 const {gtMobile} = useBreakpoints() 10 + const enableSquareAvatars = useEnableSquareAvatars() 9 11 10 12 if (!gtMobile) return null 11 13 12 14 return ( 13 15 <View style={[a.px_sm, a.py_xs, a.border_t, t.atoms.border_contrast_low]}> 14 16 <View style={[a.flex_row, a.align_center, a.gap_sm, a.px_sm, a.py_sm]}> 15 - <Skele.Circle size={24} /> 17 + <Skele.Circle 18 + size={24} 19 + style={enableSquareAvatars && {borderRadius: 8}} 20 + /> 16 21 <Skele.Text style={[a.text_md, {maxWidth: 119}]} /> 17 22 </View> 18 23 </View>
+6 -1
src/screens/PostThread/components/ThreadItemTreePost.tsx
··· 17 17 type Shadow, 18 18 usePostShadow, 19 19 } from '#/state/cache/post-shadow' 20 + import {useEnableSquareAvatars} from '#/state/preferences/enable-square-avatars' 20 21 import {type ThreadItem} from '#/state/queries/usePostThread/types' 21 22 import {useSession} from '#/state/session' 22 23 import {type OnPostSuccessData} from '#/state/shell/composer' ··· 413 414 414 415 export function ThreadItemTreePostSkeleton({index}: {index: number}) { 415 416 const t = useTheme() 417 + const enableSquareAvatars = useEnableSquareAvatars() 416 418 const even = index % 2 === 0 417 419 return ( 418 420 <View ··· 422 424 t.atoms.border_contrast_low, 423 425 ]}> 424 426 <Skele.Row style={[a.align_start, a.gap_xs]}> 425 - <Skele.Circle size={TREE_AVI_WIDTH} /> 427 + <Skele.Circle 428 + size={TREE_AVI_WIDTH} 429 + style={enableSquareAvatars && {borderRadius: 8}} 430 + /> 426 431 427 432 <Skele.Col style={[a.gap_xs]}> 428 433 <Skele.Row style={[a.gap_sm]}>
+1 -1
src/view/com/composer/Composer.tsx
··· 212 212 }: Props & { 213 213 cancelRef?: RefObject<CancelRef | null> 214 214 }) => { 215 - const {accounts} = useSession() 215 + const {accounts, currentAccount} = useSession() 216 216 const t = useTheme() 217 217 const ax = useAnalytics() 218 218 const agent = useAgent()
+8 -1
src/view/com/util/LoadingPlaceholder.tsx
··· 8 8 } from 'react-native' 9 9 10 10 import {s} from '#/lib/styles' 11 + import {useEnableSquareAvatars} from '#/state/preferences/enable-square-avatars' 11 12 import {useEnableSquareButtons} from '#/state/preferences/enable-square-buttons' 12 13 import {atoms as a, useTheme} from '#/alf' 13 14 import {Bubble_Stroke2_Corner2_Rounded as Bubble} from '#/components/icons/Bubble' ··· 48 49 style?: StyleProp<ViewStyle> 49 50 }) { 50 51 const t = useTheme() 52 + const enableSquareAvatars = useEnableSquareAvatars() 51 53 return ( 52 54 <View style={[styles.post, style]}> 53 55 <LoadingPlaceholder ··· 59 61 position: 'relative', 60 62 top: -6, 61 63 }, 64 + enableSquareAvatars && {borderRadius: 8}, 62 65 ]} 63 66 /> 64 67 <View style={[a.flex_1]}> ··· 136 139 style?: StyleProp<ViewStyle> 137 140 }) { 138 141 const t = useTheme() 142 + const enableSquareAvatars = useEnableSquareAvatars() 139 143 return ( 140 144 <View style={[styles.notification, style]}> 141 145 <View style={[{width: 60}, a.align_end, a.pr_sm, a.pt_2xs]}> ··· 146 150 <LoadingPlaceholder 147 151 width={35} 148 152 height={35} 149 - style={styles.smallAvatar} 153 + style={[ 154 + styles.smallAvatar, 155 + enableSquareAvatars && {borderRadius: 8}, 156 + ]} 150 157 /> 151 158 </View> 152 159 <LoadingPlaceholder width="90%" height={6} style={[s.mb5]} />
+6 -1
src/view/shell/desktop/LeftNav.tsx
··· 19 19 import {sanitizeDisplayName} from '#/lib/strings/display-names' 20 20 import {isInvalidHandle, sanitizeHandle} from '#/lib/strings/handles' 21 21 import {emitSoftReset} from '#/state/events' 22 + import {useEnableSquareAvatars} from '#/state/preferences/enable-square-avatars' 22 23 import {useEnableSquareButtons} from '#/state/preferences/enable-square-buttons' 23 24 import {useFetchHandle} from '#/state/queries/handle' 24 25 import {useUnreadMessageCount} from '#/state/queries/messages/list-conversations' ··· 109 110 const {isActive: live} = useActorStatus(profile) 110 111 111 112 const enableSquareButtons = useEnableSquareButtons() 113 + const enableSquareAvatars = useEnableSquareAvatars() 112 114 113 115 return ( 114 116 <View style={[a.my_md, !leftNavMinimal && [a.w_full, a.align_start]]}> ··· 208 210 <LoadingPlaceholder 209 211 width={size} 210 212 height={size} 211 - style={[{borderRadius: size}, !leftNavMinimal && a.ml_lg]} 213 + style={[ 214 + {borderRadius: enableSquareAvatars ? 8 : size}, 215 + !leftNavMinimal && a.ml_lg, 216 + ]} 212 217 /> 213 218 )} 214 219 <Prompt.Basic