diff --git a/.github/workflows/bundle-deploy-eas-update.yml b/.github/workflows/bundle-deploy-eas-update.yml index a4cae004..e1269078 100644 --- a/.github/workflows/bundle-deploy-eas-update.yml +++ b/.github/workflows/bundle-deploy-eas-update.yml @@ -82,15 +82,16 @@ jobs: uses: expo/expo-github-action/fingerprint@main with: previous-git-commit: ${{ steps.base-commit.outputs.base-commit }} + args: - name: šŸ‘€ Debug fingerprint id: fingerprint-debug run: | - echo "fingerprint-diff=${{ steps.fingerprint.outputs.fingerprint-diff }}" echo "previousGitCommit=${{ steps.fingerprint.outputs.previous-git-commit }} currentGitCommit=${{ steps.fingerprint.outputs.current-git-commit }}" echo "isPreviousFingerprintEmpty=${{ steps.fingerprint.outputs.previous-fingerprint == '' }}" - if [ "${{ steps.fingerprint.outputs.fingerprint-diff }}" != '[]' ]; then + fingerprintDiff="${{ steps.fingerprint.outputs.fingerprint-diff }}" + if [[ $fingerprintDiff =~ "bareRncliAutolinking" || $fingerprintDiff =~ "expoAutolinkingAndroid" || $fingerprintDiff =~ "expoAutolinkingIos" ]]; then echo fingerprint-is-different="true" >> "$GITHUB_OUTPUT" else echo fingerprint-is-different="false" >> "$GITHUB_OUTPUT" @@ -98,37 +99,37 @@ jobs: - name: šŸ”Ø Setup EAS uses: expo/expo-github-action@v8 - if: ${{ steps.fingerprint.outputs.fingerprint-diff == '[]' }} + if: ${{ steps.fingerprint-debug.outputs.fingerprint-is-different == 'false'}} with: expo-version: latest eas-version: latest token: ${{ secrets.EXPO_TOKEN }} - name: ā›ļø Setup Expo - if: ${{ steps.fingerprint.outputs.fingerprint-diff == '[]' }} + if: ${{ steps.fingerprint-debug.outputs.fingerprint-is-different == 'false'}} run: yarn global add eas-cli-local-build-plugin - name: šŸŖ› Setup jq - if: ${{ steps.fingerprint.outputs.fingerprint-diff == '[]' }} + if: ${{ steps.fingerprint-debug.outputs.fingerprint-is-different == 'false'}} uses: dcarbone/install-jq-action@v2 - name: šŸ”¤ Compile Translations - if: ${{ steps.fingerprint.outputs.fingerprint-diff == '[]' }} + if: ${{ steps.fingerprint-debug.outputs.fingerprint-is-different == 'false'}} run: yarn intl:build - name: āœļø Write environment variables - if: ${{ steps.fingerprint.outputs.fingerprint-diff == '[]' }} + if: ${{ steps.fingerprint-debug.outputs.fingerprint-is-different == 'false'}} run: | export json='${{ secrets.GOOGLE_SERVICES_TOKEN }}' echo "${{ secrets.ENV_TOKEN }}" > .env echo "$json" > google-services.json - name: šŸ—ļø Create Bundle - if: ${{ steps.fingerprint.outputs.fingerprint-diff == '[]' }} + if: ${{ steps.fingerprint-debug.outputs.fingerprint-is-different == 'false'}} run: EXPO_PUBLIC_ENV="${{ inputs.channel || 'testflight' }}" yarn export - name: šŸ“¦ Package Bundle and šŸš€ Deploy - if: ${{ steps.fingerprint.outputs.fingerprint-diff == '[]' }} + if: ${{ steps.fingerprint-debug.outputs.fingerprint-is-different == 'false'}} run: yarn use-build-number bash scripts/bundleUpdate.sh env: DENIS_API_KEY: ${{ secrets.DENIS_API_KEY }} diff --git a/.github/workflows/pull-request-commit.yml b/.github/workflows/pull-request-commit.yml index d3aade3f..24c0a791 100644 --- a/.github/workflows/pull-request-commit.yml +++ b/.github/workflows/pull-request-commit.yml @@ -80,7 +80,7 @@ jobs: with: base_path: 'stats-base.json' pr_path: '../stats-new.json' - excluded_assets: '(.+).js.map|(.+).json|(.+).png' + excluded_assets: '(.+).chunk.js|(.+).js.map|(.+).json|(.+).png' - name: šŸ” Find old comment if it exists uses: peter-evans/find-comment@v2 @@ -99,7 +99,7 @@ jobs: const body = ` | Old size | New size | Diff | |----------|----------|-----------------------| - | ${{ steps.get-diff.outputs.base_file_string }} | ${{ steps.get-diff.outputs.pr_file_string }} | ${{ steps.get-diff.outputs.diff_file_string }} (${{ steps.get-diff.outputs.percent }}% | + | ${{ steps.get-diff.outputs.base_file_string }} | ${{ steps.get-diff.outputs.pr_file_string }} | ${{ steps.get-diff.outputs.diff_file_string }} (${{ steps.get-diff.outputs.percent }}%) | `; github.rest.issues.createComment({ diff --git a/package.json b/package.json index 47596926..b9ffbe2d 100644 --- a/package.json +++ b/package.json @@ -39,7 +39,6 @@ "perf:test:results": "NODE_ENV=test flashlight report .perf/results.json", "perf:measure": "NODE_ENV=test flashlight measure", "intl:build": "yarn intl:extract && yarn intl:compile", - "intl:check": "yarn intl:extract && git diff-index -G'(^[^\\*# /])|(^#\\w)|(^\\s+[^\\*#/])' HEAD || (echo '\nāš ļø i18n detected un-extracted translations\n' && exit 1)", "intl:extract": "lingui extract", "intl:compile": "lingui compile", "nuke": "rm -rf ./node_modules && rm -rf ./ios && rm -rf ./android", diff --git a/src/components/Error.tsx b/src/components/Error.tsx index 7df166c3..91b33f48 100644 --- a/src/components/Error.tsx +++ b/src/components/Error.tsx @@ -1,9 +1,9 @@ import React from 'react' import {View} from 'react-native' -import {useNavigation} from '@react-navigation/core' -import {StackActions} from '@react-navigation/native' import {msg, Trans} from '@lingui/macro' import {useLingui} from '@lingui/react' +import {useNavigation} from '@react-navigation/core' +import {StackActions} from '@react-navigation/native' import {NavigationProp} from 'lib/routes/types' import {CenteredView} from 'view/com/util/Views' diff --git a/src/components/LikedByList.tsx b/src/components/LikedByList.tsx index bd121363..239a7044 100644 --- a/src/components/LikedByList.tsx +++ b/src/components/LikedByList.tsx @@ -1,47 +1,54 @@ import React from 'react' -import {View} from 'react-native' import {AppBskyFeedGetLikes as GetLikes} from '@atproto/api' -import {Trans} from '@lingui/macro' +import {msg} from '@lingui/macro' +import {useLingui} from '@lingui/react' import {logger} from '#/logger' -import {List} from '#/view/com/util/List' -import {ProfileCardWithFollowBtn} from '#/view/com/profile/ProfileCard' -import {useResolveUriQuery} from '#/state/queries/resolve-uri' import {useLikedByQuery} from '#/state/queries/post-liked-by' +import {useResolveUriQuery} from '#/state/queries/resolve-uri' import {useInitialNumToRender} from 'lib/hooks/useInitialNumToRender' -import {ListFooter} from '#/components/Lists' +import {cleanError} from 'lib/strings/errors' +import {ProfileCardWithFollowBtn} from '#/view/com/profile/ProfileCard' +import {List} from '#/view/com/util/List' +import {ListFooter, ListMaybePlaceholder} from '#/components/Lists' -import {atoms as a, useTheme} from '#/alf' -import {Loader} from '#/components/Loader' -import {Text} from '#/components/Typography' +function renderItem({item}: {item: GetLikes.Like}) { + return +} + +function keyExtractor(item: GetLikes.Like) { + return item.actor.did +} export function LikedByList({uri}: {uri: string}) { - const t = useTheme() + const {_} = useLingui() + const initialNumToRender = useInitialNumToRender() const [isPTRing, setIsPTRing] = React.useState(false) + const { data: resolvedUri, error: resolveError, - isFetching: isFetchingResolvedUri, + isLoading: isUriLoading, } = useResolveUriQuery(uri) const { data, - isFetching, - isFetched, - isRefetching, + isLoading: isLikedByLoading, + isFetchingNextPage, hasNextPage, fetchNextPage, - isError, error: likedByError, refetch, } = useLikedByQuery(resolvedUri?.uri) + + const error = resolveError || likedByError + const isError = !!resolveError || !!likedByError + const likes = React.useMemo(() => { if (data?.pages) { return data.pages.flatMap(page => page.likes) } return [] }, [data]) - const initialNumToRender = useInitialNumToRender() - const error = resolveError || likedByError const onRefresh = React.useCallback(async () => { setIsPTRing(true) @@ -54,56 +61,47 @@ export function LikedByList({uri}: {uri: string}) { }, [refetch, setIsPTRing]) const onEndReached = React.useCallback(async () => { - if (isFetching || !hasNextPage || isError) return + if (isFetchingNextPage || !hasNextPage || isError) return try { await fetchNextPage() } catch (err) { logger.error('Failed to load more likes', {message: err}) } - }, [isFetching, hasNextPage, isError, fetchNextPage]) + }, [isFetchingNextPage, hasNextPage, isError, fetchNextPage]) - const renderItem = React.useCallback(({item}: {item: GetLikes.Like}) => { + if (likes.length < 1) { return ( - - ) - }, []) - - if (isFetchingResolvedUri || !isFetched) { - return ( - - - + ) } - return likes.length ? ( + return ( item.actor.did} + renderItem={renderItem} + keyExtractor={keyExtractor} refreshing={isPTRing} onRefresh={onRefresh} onEndReached={onEndReached} - onEndReachedThreshold={3} - renderItem={renderItem} - initialNumToRender={initialNumToRender} - ListFooterComponent={() => ( + ListFooterComponent={ - )} + } + onEndReachedThreshold={3} + initialNumToRender={initialNumToRender} + windowSize={11} /> - ) : ( - - - - - Nobody has liked this yet. Maybe you should be the first! - - - - ) } diff --git a/src/components/Lists.tsx b/src/components/Lists.tsx index d3e07202..605626fe 100644 --- a/src/components/Lists.tsx +++ b/src/components/Lists.tsx @@ -1,25 +1,23 @@ import React from 'react' -import {atoms as a, useBreakpoints, useTheme} from '#/alf' import {View} from 'react-native' +import {msg, Trans} from '@lingui/macro' import {useLingui} from '@lingui/react' -import {Trans, msg} from '@lingui/macro' -import {CenteredView} from 'view/com/util/Views' -import {Loader} from '#/components/Loader' import {cleanError} from 'lib/strings/errors' +import {CenteredView} from 'view/com/util/Views' +import {atoms as a, useBreakpoints, useTheme} from '#/alf' import {Button} from '#/components/Button' -import {Text} from '#/components/Typography' import {Error} from '#/components/Error' +import {Loader} from '#/components/Loader' +import {Text} from '#/components/Typography' export function ListFooter({ - isFetching, - isError, + isFetchingNextPage, error, onRetry, height, }: { - isFetching?: boolean - isError?: boolean + isFetchingNextPage?: boolean error?: string onRetry?: () => Promise height?: number @@ -36,32 +34,26 @@ export function ListFooter({ t.atoms.border_contrast_low, {height: height ?? 180, paddingTop: 30}, ]}> - {isFetching ? ( + {isFetchingNextPage ? ( ) : ( - + )} ) } function ListFooterMaybeError({ - isError, error, onRetry, }: { - isError?: boolean error?: string onRetry?: () => Promise }) { const t = useTheme() const {_} = useLingui() - if (!isError) return null + if (!error) return null return ( @@ -128,7 +120,7 @@ export function ListHeaderDesktop({ export function ListMaybePlaceholder({ isLoading, - isEmpty, + noEmpty, isError, emptyTitle, emptyMessage, @@ -138,7 +130,7 @@ export function ListMaybePlaceholder({ onRetry, }: { isLoading: boolean - isEmpty?: boolean + noEmpty?: boolean isError?: boolean emptyTitle?: string emptyMessage?: string @@ -151,16 +143,6 @@ export function ListMaybePlaceholder({ const {_} = useLingui() const {gtMobile, gtTablet} = useBreakpoints() - if (!isLoading && isError) { - return ( - - ) - } - if (isLoading) { return ( + ) + } + + if (!noEmpty) { return ( ) } + + return null } diff --git a/src/lib/icons.tsx b/src/lib/icons.tsx index 8783682d..93b45ea3 100644 --- a/src/lib/icons.tsx +++ b/src/lib/icons.tsx @@ -1,6 +1,6 @@ import React from 'react' import {StyleProp, TextStyle, ViewStyle} from 'react-native' -import Svg, {Path, Rect, Line, Ellipse} from 'react-native-svg' +import Svg, {Ellipse, Line, Path, Rect} from 'react-native-svg' export function GridIcon({ style, diff --git a/src/screens/Hashtag.tsx b/src/screens/Hashtag.tsx index 46452f08..5388593f 100644 --- a/src/screens/Hashtag.tsx +++ b/src/screens/Hashtag.tsx @@ -1,28 +1,30 @@ import React from 'react' import {ListRenderItemInfo, Pressable} from 'react-native' -import {useFocusEffect} from '@react-navigation/native' -import {useSetMinimalShellMode} from 'state/shell' -import {ViewHeader} from 'view/com/util/ViewHeader' -import {NativeStackScreenProps} from '@react-navigation/native-stack' -import {CommonNavigatorParams} from 'lib/routes/types' -import {useSearchPostsQuery} from 'state/queries/search-posts' -import {Post} from 'view/com/post/Post' import {PostView} from '@atproto/api/dist/client/types/app/bsky/feed/defs' +import {msg} from '@lingui/macro' +import {useLingui} from '@lingui/react' +import {useFocusEffect} from '@react-navigation/native' +import {NativeStackScreenProps} from '@react-navigation/native-stack' + +import {HITSLOP_10} from 'lib/constants' +import {useInitialNumToRender} from 'lib/hooks/useInitialNumToRender' +import {CommonNavigatorParams} from 'lib/routes/types' +import {shareUrl} from 'lib/sharing' +import {cleanError} from 'lib/strings/errors' +import {sanitizeHandle} from 'lib/strings/handles' import {enforceLen} from 'lib/strings/helpers' +import {isNative} from 'platform/detection' +import {useSearchPostsQuery} from 'state/queries/search-posts' +import {useSetMinimalShellMode} from 'state/shell' +import {Post} from 'view/com/post/Post' +import {List} from 'view/com/util/List' +import {ViewHeader} from 'view/com/util/ViewHeader' +import {ArrowOutOfBox_Stroke2_Corner0_Rounded} from '#/components/icons/ArrowOutOfBox' import { ListFooter, ListHeaderDesktop, ListMaybePlaceholder, } from '#/components/Lists' -import {List} from 'view/com/util/List' -import {msg} from '@lingui/macro' -import {useLingui} from '@lingui/react' -import {sanitizeHandle} from 'lib/strings/handles' -import {ArrowOutOfBox_Stroke2_Corner0_Rounded} from '#/components/icons/ArrowOutOfBox' -import {shareUrl} from 'lib/sharing' -import {HITSLOP_10} from 'lib/constants' -import {isNative} from 'platform/detection' -import {useInitialNumToRender} from 'lib/hooks/useInitialNumToRender' const renderItem = ({item}: ListRenderItemInfo) => { return @@ -61,9 +63,8 @@ export default function HashtagScreen({ const { data, - isFetching, + isFetchingNextPage, isLoading, - isRefetching, isError, error, refetch, @@ -97,9 +98,9 @@ export default function HashtagScreen({ }, [refetch]) const onEndReached = React.useCallback(() => { - if (isFetching || !hasNextPage || error) return + if (isFetchingNextPage || !hasNextPage || error) return fetchNextPage() - }, [isFetching, hasNextPage, error, fetchNextPage]) + }, [isFetchingNextPage, hasNextPage, error, fetchNextPage]) return ( <> @@ -123,16 +124,16 @@ export default function HashtagScreen({ : undefined } /> - - {!isLoading && posts.length > 0 && ( - + {posts.length < 1 ? ( + + ) : ( + } diff --git a/src/screens/Profile/ProfileLabelerLikedBy.tsx b/src/screens/Profile/ProfileLabelerLikedBy.tsx index 1d216752..8650ac2e 100644 --- a/src/screens/Profile/ProfileLabelerLikedBy.tsx +++ b/src/screens/Profile/ProfileLabelerLikedBy.tsx @@ -4,13 +4,11 @@ import {msg} from '@lingui/macro' import {useLingui} from '@lingui/react' import {useFocusEffect} from '@react-navigation/native' -import {NativeStackScreenProps, CommonNavigatorParams} from '#/lib/routes/types' +import {CommonNavigatorParams, NativeStackScreenProps} from '#/lib/routes/types' +import {makeRecordUri} from '#/lib/strings/url-helpers' +import {useSetMinimalShellMode} from '#/state/shell' import {ViewHeader} from '#/view/com/util/ViewHeader' import {LikedByList} from '#/components/LikedByList' -import {useSetMinimalShellMode} from '#/state/shell' -import {makeRecordUri} from '#/lib/strings/url-helpers' - -import {atoms as a, useBreakpoints} from '#/alf' export function ProfileLabelerLikedByScreen({ route, @@ -19,7 +17,6 @@ export function ProfileLabelerLikedByScreen({ const {name: handleOrDid} = route.params const uri = makeRecordUri(handleOrDid, 'app.bsky.labeler.service', 'self') const {_} = useLingui() - const {gtMobile} = useBreakpoints() useFocusEffect( React.useCallback(() => { @@ -28,17 +25,7 @@ export function ProfileLabelerLikedByScreen({ ) return ( - + diff --git a/src/view/com/post-thread/PostThread.tsx b/src/view/com/post-thread/PostThread.tsx index c1159379..f4bf3b1a 100644 --- a/src/view/com/post-thread/PostThread.tsx +++ b/src/view/com/post-thread/PostThread.tsx @@ -368,47 +368,52 @@ export function PostThread({ ], ) - return ( - <> + if (error || !thread) { + return ( - {!error && thread && ( - - } - initialNumToRender={initialNumToRender} - windowSize={11} + ) + } + + return ( + - )} - + } + initialNumToRender={initialNumToRender} + windowSize={11} + /> ) } diff --git a/src/view/com/profile/ProfileFollowers.tsx b/src/view/com/profile/ProfileFollowers.tsx index b11a33f2..94ca33e6 100644 --- a/src/view/com/profile/ProfileFollowers.tsx +++ b/src/view/com/profile/ProfileFollowers.tsx @@ -1,21 +1,21 @@ import React from 'react' import {AppBskyActorDefs as ActorDefs} from '@atproto/api' -import {List} from '../util/List' -import {ProfileCardWithFollowBtn} from './ProfileCard' +import {msg} from '@lingui/macro' +import {useLingui} from '@lingui/react' + +import {cleanError} from '#/lib/strings/errors' +import {logger} from '#/logger' import {useProfileFollowersQuery} from '#/state/queries/profile-followers' import {useResolveDidQuery} from '#/state/queries/resolve-uri' -import {logger} from '#/logger' -import {cleanError} from '#/lib/strings/errors' import {useInitialNumToRender} from 'lib/hooks/useInitialNumToRender' +import {useSession} from 'state/session' import { ListFooter, ListHeaderDesktop, ListMaybePlaceholder, } from '#/components/Lists' -import {msg} from '@lingui/macro' -import {useLingui} from '@lingui/react' -import {useSession} from 'state/session' -import {View} from 'react-native' +import {List} from '../util/List' +import {ProfileCardWithFollowBtn} from './ProfileCard' function renderItem({item}: {item: ActorDefs.ProfileViewBasic}) { return @@ -39,7 +39,6 @@ export function ProfileFollowers({name}: {name: string}) { const { data, isLoading: isFollowersLoading, - isFetching, isFetchingNextPage, hasNextPage, fetchNextPage, @@ -47,14 +46,8 @@ export function ProfileFollowers({name}: {name: string}) { refetch, } = useProfileFollowersQuery(resolvedDid) - const isError = React.useMemo( - () => !!resolveError || !!error, - [resolveError, error], - ) - - const isMe = React.useMemo(() => { - return resolvedDid === currentAccount?.did - }, [resolvedDid, currentAccount?.did]) + const isError = !!resolveError || !!error + const isMe = resolvedDid === currentAccount?.did const followers = React.useMemo(() => { if (data?.pages) { @@ -73,20 +66,19 @@ export function ProfileFollowers({name}: {name: string}) { setIsPTRing(false) }, [refetch, setIsPTRing]) - const onEndReached = async () => { - if (isFetching || !hasNextPage || !!error) return + const onEndReached = React.useCallback(async () => { + if (isFetchingNextPage || !hasNextPage || !!error) return try { await fetchNextPage() } catch (err) { logger.error('Failed to load more followers', {message: err}) } - } + }, [isFetchingNextPage, hasNextPage, error, fetchNextPage]) - return ( - + if (followers.length < 1) { + return ( - {followers.length > 0 && ( - } - ListFooterComponent={} - // @ts-ignore our .web version only -prf - desktopFixedHeight - initialNumToRender={initialNumToRender} - windowSize={11} + ) + } + + return ( + } + ListFooterComponent={ + - )} - + } + // @ts-ignore our .web version only -prf + desktopFixedHeight + initialNumToRender={initialNumToRender} + windowSize={11} + /> ) } diff --git a/src/view/com/profile/ProfileFollows.tsx b/src/view/com/profile/ProfileFollows.tsx index d99e2b84..9b447c95 100644 --- a/src/view/com/profile/ProfileFollows.tsx +++ b/src/view/com/profile/ProfileFollows.tsx @@ -1,20 +1,21 @@ import React from 'react' import {AppBskyActorDefs as ActorDefs} from '@atproto/api' -import {List} from '../util/List' -import {ProfileCardWithFollowBtn} from './ProfileCard' +import {msg} from '@lingui/macro' +import {useLingui} from '@lingui/react' + +import {cleanError} from '#/lib/strings/errors' +import {logger} from '#/logger' import {useProfileFollowsQuery} from '#/state/queries/profile-follows' import {useResolveDidQuery} from '#/state/queries/resolve-uri' -import {logger} from '#/logger' -import {cleanError} from '#/lib/strings/errors' +import {useInitialNumToRender} from 'lib/hooks/useInitialNumToRender' +import {useSession} from 'state/session' import { ListFooter, ListHeaderDesktop, ListMaybePlaceholder, } from '#/components/Lists' -import {useInitialNumToRender} from 'lib/hooks/useInitialNumToRender' -import {useSession} from 'state/session' -import {msg} from '@lingui/macro' -import {useLingui} from '@lingui/react' +import {List} from '../util/List' +import {ProfileCardWithFollowBtn} from './ProfileCard' function renderItem({item}: {item: ActorDefs.ProfileViewBasic}) { return @@ -38,7 +39,6 @@ export function ProfileFollows({name}: {name: string}) { const { data, isLoading: isFollowsLoading, - isFetching, isFetchingNextPage, hasNextPage, fetchNextPage, @@ -46,14 +46,8 @@ export function ProfileFollows({name}: {name: string}) { refetch, } = useProfileFollowsQuery(resolvedDid) - const isError = React.useMemo( - () => !!resolveError || !!error, - [resolveError, error], - ) - - const isMe = React.useMemo(() => { - return resolvedDid === currentAccount?.did - }, [resolvedDid, currentAccount?.did]) + const isError = !!resolveError || !!error + const isMe = resolvedDid === currentAccount?.did const follows = React.useMemo(() => { if (data?.pages) { @@ -72,20 +66,19 @@ export function ProfileFollows({name}: {name: string}) { setIsPTRing(false) }, [refetch, setIsPTRing]) - const onEndReached = async () => { - if (isFetching || !hasNextPage || !!error) return + const onEndReached = React.useCallback(async () => { + if (isFetchingNextPage || !hasNextPage || !!error) return try { await fetchNextPage() } catch (err) { logger.error('Failed to load more follows', {error: err}) } - } + }, [error, fetchNextPage, hasNextPage, isFetchingNextPage]) - return ( - <> + if (follows.length < 1) { + return ( - {follows.length > 0 && ( - } - ListFooterComponent={} - // @ts-ignore our .web version only -prf - desktopFixedHeight - initialNumToRender={initialNumToRender} - windowSize={11} + ) + } + + return ( + } + ListFooterComponent={ + - )} - + } + // @ts-ignore our .web version only -prf + desktopFixedHeight + initialNumToRender={initialNumToRender} + windowSize={11} + /> ) }