diff --git a/rspack.config.ts b/rspack.config.ts index 6d7102e2c..99e47d15f 100644 --- a/rspack.config.ts +++ b/rspack.config.ts @@ -89,7 +89,13 @@ function getTranspileModuleDirs({ } const transpileModuleDirs = getTranspileModuleDirs(TRANSPILE_MODULES) +const REANIMATED_BABEL_MODULES = ['react-native-keyboard-controller'] +const reanimatedBabelModuleDirs = REANIMATED_BABEL_MODULES.map(pkg => + path.resolve(__dirname, 'node_modules', ...pkg.split('/')), +).filter(existsSync) const SWC_TRANSPILE_EXCLUDE = /node_modules[\\/]react-native-uuid[\\/]/ +const REANIMATED_BABEL_EXCLUDE = + /node_modules[\\/]react-native-keyboard-controller[\\/]/ /** @type {import('@rspack/core').Configuration} */ module.exports = { @@ -211,12 +217,41 @@ module.exports = { }, }, }, + // Some published packages ship raw `"worklet"` functions and must go + // through Babel with the Reanimated plugin on web, matching Expo's + // webpack pipeline. SWC alone leaves those functions unworkletized. + { + test: /\.[jt]sx?$/, + include: reanimatedBabelModuleDirs, + use: { + loader: 'babel-loader', + options: { + configFile: false, + babelrc: false, + cacheDirectory: true, + cacheCompression: false, + sourceType: 'unambiguous', + presets: [ + [ + 'babel-preset-expo', + { + lazyImports: true, + native: { + disableImportExportTransform: true, + }, + }, + ], + ], + plugins: ['react-native-reanimated/plugin'], + }, + }, + }, // node_modules that ship untranspiled JSX/Flow: use rspack's builtin // SWC loader which is much faster than babel for simple transforms. { test: /\.jsx?$/, include: transpileModuleDirs, - exclude: SWC_TRANSPILE_EXCLUDE, + exclude: [SWC_TRANSPILE_EXCLUDE, REANIMATED_BABEL_EXCLUDE], use: { loader: 'swc-loader', // rspack swc-loader doesn't support flow yet options: { @@ -237,7 +272,7 @@ module.exports = { { test: /\.tsx?$/, include: transpileModuleDirs, - exclude: SWC_TRANSPILE_EXCLUDE, + exclude: [SWC_TRANSPILE_EXCLUDE, REANIMATED_BABEL_EXCLUDE], use: { loader: 'swc-loader', options: { diff --git a/src/components/AvatarStack.tsx b/src/components/AvatarStack.tsx index 513998141..0995fc706 100644 --- a/src/components/AvatarStack.tsx +++ b/src/components/AvatarStack.tsx @@ -2,6 +2,7 @@ import {View} from 'react-native' import {moderateProfile} from '@atproto/api' import {logger} from '#/logger' +import {useEnableSquareAvatars} from '#/state/preferences/enable-square-avatars' import {useModerationOpts} from '#/state/preferences/moderation-opts' import {useProfilesQuery} from '#/state/queries/profile' import {UserAvatar} from '#/view/com/util/UserAvatar' @@ -22,6 +23,7 @@ export function AvatarStack({ const translation = size / 3 // overlap by 1/3 const t = useTheme() const moderationOpts = useModerationOpts() + const enableSquareAvatars = useEnableSquareAvatars() const isPending = (numPending && profiles.length === 0) || !moderationOpts @@ -57,7 +59,7 @@ export function AvatarStack({ left: i * -translation, borderWidth: 1, borderColor: backgroundColor ?? t.atoms.bg.backgroundColor, - borderRadius: 999, + borderRadius: enableSquareAvatars ? (size > 32 ? 8 : 3) : 999, zIndex: 3 - i, }, ]}> @@ -97,7 +99,9 @@ export function AvatarStackWithFetch({ const orderedProfiles = profiles .map(did => data?.profiles?.find(profile => profile.did === did)) - .filter(Boolean) + .filter((profile): profile is NonNullable => + Boolean(profile), + ) return ( - + diff --git a/src/screens/PostThread/components/ThreadItemAnchor.tsx b/src/screens/PostThread/components/ThreadItemAnchor.tsx index f568e7e08..e924ab492 100644 --- a/src/screens/PostThread/components/ThreadItemAnchor.tsx +++ b/src/screens/PostThread/components/ThreadItemAnchor.tsx @@ -26,6 +26,7 @@ import {useDisableLikesMetrics} from '#/state/preferences/disable-likes-metrics' import {useDisableQuotesMetrics} from '#/state/preferences/disable-quotes-metrics' import {useDisableRepostsMetrics} from '#/state/preferences/disable-reposts-metrics' import {useDisableSavesMetrics} from '#/state/preferences/disable-saves-metrics' +import {useEnableSquareAvatars} from '#/state/preferences/enable-square-avatars' import {useEnableSquareButtons} from '#/state/preferences/enable-square-buttons' import {useHideScaryFollowButtons} from '#/state/preferences/hide-scary-follow-buttons' import {useShowViaClient} from '#/state/preferences/show-via-client' @@ -593,14 +594,8 @@ function ExpandedPostDetails({ {niceDate(i18n, post.indexedAt, 'dot separated')} + {showViaClient && via ? ` ยท ${truncateVia(via)}` : null} - {showViaClient && via ? ( - - {truncateVia(via)} - - ) : null} {isRootPost && ( )} @@ -718,10 +713,15 @@ function getThreadAuthor( } export function ThreadItemAnchorSkeleton() { + const enableSquareAvatars = useEnableSquareAvatars() + return ( - + diff --git a/src/screens/PostThread/components/ThreadItemAnchorNoUnauthenticated.tsx b/src/screens/PostThread/components/ThreadItemAnchorNoUnauthenticated.tsx index 5adc248a4..58f2668f1 100644 --- a/src/screens/PostThread/components/ThreadItemAnchorNoUnauthenticated.tsx +++ b/src/screens/PostThread/components/ThreadItemAnchorNoUnauthenticated.tsx @@ -1,6 +1,7 @@ import {View} from 'react-native' import {Trans} from '@lingui/react/macro' +import {useEnableSquareAvatars} from '#/state/preferences/enable-square-avatars' import {atoms as a, useTheme} from '#/alf' import {Lock_Stroke2_Corner0_Rounded as LockIcon} from '#/components/icons/Lock' import * as Skele from '#/components/Skeleton' @@ -8,11 +9,14 @@ import {Text} from '#/components/Typography' export function ThreadItemAnchorNoUnauthenticated() { const t = useTheme() + const enableSquareAvatars = useEnableSquareAvatars() return ( - + diff --git a/src/screens/PostThread/components/ThreadItemPost.tsx b/src/screens/PostThread/components/ThreadItemPost.tsx index 841c2af74..303a8e9e2 100644 --- a/src/screens/PostThread/components/ThreadItemPost.tsx +++ b/src/screens/PostThread/components/ThreadItemPost.tsx @@ -17,6 +17,7 @@ import { type Shadow, usePostShadow, } from '#/state/cache/post-shadow' +import {useEnableSquareAvatars} from '#/state/preferences/enable-square-avatars' import {type ThreadItem} from '#/state/queries/usePostThread/types' import {useSession} from '#/state/session' import {type OnPostSuccessData} from '#/state/shell/composer' @@ -387,6 +388,7 @@ function SubtleHoverWrapper({children}: {children: ReactNode}) { } export function ThreadItemPostSkeleton({index}: {index: number}) { + const enableSquareAvatars = useEnableSquareAvatars() const even = index % 2 === 0 return ( - + diff --git a/src/screens/PostThread/components/ThreadItemPostNoUnauthenticated.tsx b/src/screens/PostThread/components/ThreadItemPostNoUnauthenticated.tsx index a35261d8a..6f3380360 100644 --- a/src/screens/PostThread/components/ThreadItemPostNoUnauthenticated.tsx +++ b/src/screens/PostThread/components/ThreadItemPostNoUnauthenticated.tsx @@ -1,6 +1,7 @@ import {View} from 'react-native' import {Trans} from '@lingui/react/macro' +import {useEnableSquareAvatars} from '#/state/preferences/enable-square-avatars' import {type ThreadItem} from '#/state/queries/usePostThread/types' import { LINEAR_AVI_WIDTH, @@ -18,6 +19,7 @@ export function ThreadItemPostNoUnauthenticated({ item: Extract }) { const t = useTheme() + const enableSquareAvatars = useEnableSquareAvatars() return ( @@ -39,7 +41,9 @@ export function ThreadItemPostNoUnauthenticated({ - + diff --git a/src/screens/PostThread/components/ThreadItemReplyComposer.tsx b/src/screens/PostThread/components/ThreadItemReplyComposer.tsx index d93612be8..6caa1b036 100644 --- a/src/screens/PostThread/components/ThreadItemReplyComposer.tsx +++ b/src/screens/PostThread/components/ThreadItemReplyComposer.tsx @@ -1,18 +1,23 @@ import {View} from 'react-native' +import {useEnableSquareAvatars} from '#/state/preferences/enable-square-avatars' import {atoms as a, useBreakpoints, useTheme} from '#/alf' import * as Skele from '#/components/Skeleton' export function ThreadItemReplyComposerSkeleton() { const t = useTheme() const {gtMobile} = useBreakpoints() + const enableSquareAvatars = useEnableSquareAvatars() if (!gtMobile) return null return ( - + diff --git a/src/screens/PostThread/components/ThreadItemTreePost.tsx b/src/screens/PostThread/components/ThreadItemTreePost.tsx index 6ee116d16..8acc1ca53 100644 --- a/src/screens/PostThread/components/ThreadItemTreePost.tsx +++ b/src/screens/PostThread/components/ThreadItemTreePost.tsx @@ -17,6 +17,7 @@ import { type Shadow, usePostShadow, } from '#/state/cache/post-shadow' +import {useEnableSquareAvatars} from '#/state/preferences/enable-square-avatars' import {type ThreadItem} from '#/state/queries/usePostThread/types' import {useSession} from '#/state/session' import {type OnPostSuccessData} from '#/state/shell/composer' @@ -413,6 +414,7 @@ function SubtleHoverWrapper({children}: {children: React.ReactNode}) { export function ThreadItemTreePostSkeleton({index}: {index: number}) { const t = useTheme() + const enableSquareAvatars = useEnableSquareAvatars() const even = index % 2 === 0 return ( - + diff --git a/src/view/com/composer/Composer.tsx b/src/view/com/composer/Composer.tsx index 8901421a4..aa19a2872 100644 --- a/src/view/com/composer/Composer.tsx +++ b/src/view/com/composer/Composer.tsx @@ -212,7 +212,7 @@ export const ComposePost = ({ }: Props & { cancelRef?: RefObject }) => { - const {accounts} = useSession() + const {accounts, currentAccount} = useSession() const t = useTheme() const ax = useAnalytics() const agent = useAgent() diff --git a/src/view/com/util/LoadingPlaceholder.tsx b/src/view/com/util/LoadingPlaceholder.tsx index 73520cfd8..0f61b5c6f 100644 --- a/src/view/com/util/LoadingPlaceholder.tsx +++ b/src/view/com/util/LoadingPlaceholder.tsx @@ -8,6 +8,7 @@ import { } from 'react-native' import {s} from '#/lib/styles' +import {useEnableSquareAvatars} from '#/state/preferences/enable-square-avatars' import {useEnableSquareButtons} from '#/state/preferences/enable-square-buttons' import {atoms as a, useTheme} from '#/alf' import {Bubble_Stroke2_Corner2_Rounded as Bubble} from '#/components/icons/Bubble' @@ -48,6 +49,7 @@ export function PostLoadingPlaceholder({ style?: StyleProp }) { const t = useTheme() + const enableSquareAvatars = useEnableSquareAvatars() return ( @@ -136,6 +139,7 @@ export function NotificationLoadingPlaceholder({ style?: StyleProp }) { const t = useTheme() + const enableSquareAvatars = useEnableSquareAvatars() return ( @@ -146,7 +150,10 @@ export function NotificationLoadingPlaceholder({ diff --git a/src/view/shell/desktop/LeftNav.tsx b/src/view/shell/desktop/LeftNav.tsx index 3482c3758..b4ac0c549 100644 --- a/src/view/shell/desktop/LeftNav.tsx +++ b/src/view/shell/desktop/LeftNav.tsx @@ -19,6 +19,7 @@ import { import {sanitizeDisplayName} from '#/lib/strings/display-names' import {isInvalidHandle, sanitizeHandle} from '#/lib/strings/handles' import {emitSoftReset} from '#/state/events' +import {useEnableSquareAvatars} from '#/state/preferences/enable-square-avatars' import {useEnableSquareButtons} from '#/state/preferences/enable-square-buttons' import {useFetchHandle} from '#/state/queries/handle' import {useUnreadMessageCount} from '#/state/queries/messages/list-conversations' @@ -109,6 +110,7 @@ function ProfileCard() { const {isActive: live} = useActorStatus(profile) const enableSquareButtons = useEnableSquareButtons() + const enableSquareAvatars = useEnableSquareAvatars() return ( @@ -208,7 +210,10 @@ function ProfileCard() { )}