This repository has no description
0

Configure Feed

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

feat: handle unavailable bluesky posts

+90 -70
+41 -7
src/webapp/features/cards/components/urlCardContent/UrlCardContent.tsx
··· 8 8 import BlueskyPost from '@/features/platforms/bluesky/components/blueskyPost/BlueskyPost'; 9 9 import { Suspense } from 'react'; 10 10 import { ErrorBoundary } from 'react-error-boundary'; 11 + import { Stack, Text, Group, Alert, Anchor, Tooltip } from '@mantine/core'; 12 + import BlueskyPlatformIcon from '@/features/platforms/bluesky/components/blueskyPlatformIcon/BlueskyPlatformIcon'; 11 13 import BlueskyPostSkeleton from '@/features/platforms/bluesky/components/blueskyPost/Skeleton.BlueskyPost'; 12 14 import { useUserSettings } from '@/features/settings/lib/queries/useUserSettings'; 13 15 import IframeEmbed from '@/features/platforms/common/components/IframeEmbed/IframeEmbed'; ··· 87 89 ) { 88 90 return ( 89 91 <ErrorBoundary 90 - fallback={ 91 - <LinkCardContent 92 - cardContent={props.cardContent} 93 - uri={props.uri} 94 - authorHandle={props.authorHandle} 95 - /> 96 - } 92 + fallbackRender={({ error }) => { 93 + if (error?.status === 404 || error?.error === 'NotFound') { 94 + const platformName = 95 + platform.type === SupportedPlatform.BLUESKY_POST 96 + ? 'Bluesky' 97 + : 'Blacksky'; 98 + return ( 99 + <Stack justify="space-between" gap="xs"> 100 + <Group gap="xs" justify="flex-end" wrap="nowrap" w="100%"> 101 + <Tooltip label={`View on ${platformName}`}> 102 + <Anchor 103 + href={props.url} 104 + target="_blank" 105 + onClick={(e) => e.stopPropagation()} 106 + > 107 + <BlueskyPlatformIcon platform={platform.type} /> 108 + </Anchor> 109 + </Tooltip> 110 + </Group> 111 + <Alert 112 + component={'button'} 113 + variant="light" 114 + color="gray" 115 + p={'sm'} 116 + title="Post not found" 117 + style={{ cursor: 'pointer' }} 118 + /> 119 + </Stack> 120 + ); 121 + } 122 + 123 + return ( 124 + <LinkCardContent 125 + cardContent={props.cardContent} 126 + uri={props.uri} 127 + authorHandle={props.authorHandle} 128 + /> 129 + ); 130 + }} 97 131 > 98 132 <Suspense fallback={<BlueskyPostSkeleton />}> 99 133 <BlueskyPost
+39
src/webapp/features/platforms/bluesky/components/blueskyPlatformIcon/BlueskyPlatformIcon.tsx
··· 1 + import { Image } from '@mantine/core'; 2 + import { FaBluesky } from 'react-icons/fa6'; 3 + import BlackskyLogo from '@/assets/icons/blacksky-logo.svg'; 4 + import BlackskyLogoWhite from '@/assets/icons/blacksky-logo-white.svg'; 5 + import { SupportedPlatform } from '@/lib/utils/link'; 6 + 7 + interface Props { 8 + platform: SupportedPlatform; 9 + size?: number; 10 + } 11 + 12 + export default function BlueskyPlatformIcon({ platform, size = 18 }: Props) { 13 + if (platform === SupportedPlatform.BLUESKY_POST) { 14 + return <FaBluesky fill="#0085ff" size={size} />; 15 + } 16 + 17 + if (platform !== SupportedPlatform.BLACKSKY_POST) { 18 + return null; 19 + } 20 + 21 + return ( 22 + <> 23 + <Image 24 + src={BlackskyLogo.src} 25 + alt="Blacksky logo" 26 + w={size} 27 + h={'auto'} 28 + darkHidden 29 + /> 30 + <Image 31 + src={BlackskyLogoWhite.src} 32 + alt="Blacksky logo" 33 + w={size} 34 + h={'auto'} 35 + lightHidden 36 + /> 37 + </> 38 + ); 39 + }
+5 -28
src/webapp/features/platforms/bluesky/components/blueskyPost/BlueskyPost.tsx
··· 2 2 3 3 import { AppBskyFeedDefs, AppBskyFeedPost } from '@atproto/api'; 4 4 import { ReactElement } from 'react'; 5 - import { Group, Stack, Text, Box, Image, Anchor, Tooltip } from '@mantine/core'; 5 + import { Group, Stack, Text, Box, Anchor, Tooltip } from '@mantine/core'; 6 6 import RichTextRenderer from '@/components/contentDisplay/richTextRenderer/RichTextRenderer'; 7 7 import useGetBlueskyPost from '../../lib/queries/useGetBlueskyPost'; 8 8 import PostEmbed from '../postEmbed/PostEmbed'; ··· 11 11 getPostModerationUI, 12 12 getModerationReasonText, 13 13 } from '../../lib/moderation'; 14 - import { FaBluesky } from 'react-icons/fa6'; 14 + 15 15 import BotLabel from '@/features/profile/components/botLabel/BotLabel'; 16 16 import { isBotAccount } from '../../lib/utils/account'; 17 17 import { detectUrlPlatform, SupportedPlatform } from '@/lib/utils/link'; 18 18 import { getPostUriFromUrl } from '@/lib/utils/atproto'; 19 - import BlackskyLogo from '@/assets/icons/blacksky-logo.svg'; 20 - import BlackskyLogoWhite from '@/assets/icons/blacksky-logo-white.svg'; 19 + import BlueskyPlatformIcon from '../blueskyPlatformIcon/BlueskyPlatformIcon'; 21 20 import { useUserSettings } from '@/features/settings/lib/queries/useUserSettings'; 22 21 import { LinkAvatar } from '@/components/link/MantineLink'; 23 22 ··· 32 31 const { data, error } = useGetBlueskyPost({ uri }); 33 32 const showEmbed = settings.cardView === 'grid'; 34 33 const platform = detectUrlPlatform(props.url); 35 - const platformIcon = 36 - platform.type === SupportedPlatform.BLUESKY_POST ? ( 37 - <FaBluesky fill="#0085ff" size={18} /> 38 - ) : ( 39 - <> 40 - <Image 41 - src={BlackskyLogo.src} 42 - alt="Blacksky logo" 43 - w={18} 44 - h={'auto'} 45 - darkHidden 46 - /> 47 - <Image 48 - src={BlackskyLogoWhite.src} 49 - alt="Blacksky logo" 50 - w={18} 51 - h={'auto'} 52 - lightHidden 53 - /> 54 - </> 55 - ); 34 + const platformIcon = <BlueskyPlatformIcon platform={platform.type} />; 56 35 57 36 if ( 58 37 !data.thread || 59 38 !AppBskyFeedDefs.isThreadViewPost(data.thread) || 60 - AppBskyFeedDefs.isNotFoundPost(data.thread.post) || 61 - AppBskyFeedDefs.isBlockedPost(data.thread.post) || 62 - error 39 + AppBskyFeedDefs.isBlockedPost(data.thread.post) 63 40 ) { 64 41 return props.fallbackCardContent; 65 42 }
+4 -34
src/webapp/features/platforms/bluesky/components/blueskySemblePost/BlueskySemblePost.tsx
··· 5 5 import RichTextRenderer from '@/components/contentDisplay/richTextRenderer/RichTextRenderer'; 6 6 import { detectUrlPlatform, SupportedPlatform } from '@/lib/utils/link'; 7 7 import { getFormattedDate } from '@/lib/utils/time'; 8 - import { 9 - Stack, 10 - Tooltip, 11 - Anchor, 12 - Card, 13 - Group, 14 - Box, 15 - Image, 16 - Text, 17 - } from '@mantine/core'; 18 - import { FaBluesky } from 'react-icons/fa6'; 8 + import { Stack, Tooltip, Anchor, Card, Group, Box, Text } from '@mantine/core'; 9 + import BlueskyPlatformIcon from '../blueskyPlatformIcon/BlueskyPlatformIcon'; 19 10 import PostEmbed from '../postEmbed/PostEmbed'; 20 11 import ContentHider from '../contentHider/ContentHider'; 21 12 import { 22 13 getPostModerationUI, 23 14 getModerationReasonText, 24 15 } from '../../lib/moderation'; 25 - import BlackskyLogo from '@/assets/icons/blacksky-logo.svg'; 26 - import BlackskyLogoWhite from '@/assets/icons/blacksky-logo-white.svg'; 16 + 27 17 import { Suspense } from 'react'; 28 18 import UrlTypeBadge from '@/features/semble/components/urlTypeBadge/UrlTypeBadge'; 29 19 import UrlTypeBadgeSkeleton from '@/features/semble/components/urlTypeBadge/Skeleton.UrlTypeBadge'; ··· 40 30 const data = await getBlueskyPost(postUri); 41 31 42 32 const platform = detectUrlPlatform(props.url); 43 - const platformIcon = 44 - platform.type === SupportedPlatform.BLUESKY_POST ? ( 45 - <FaBluesky fill="#0085ff" size={18} /> 46 - ) : ( 47 - <> 48 - <Image 49 - src={BlackskyLogo.src} 50 - alt="Blacksky logo" 51 - w={18} 52 - h={'auto'} 53 - darkHidden 54 - /> 55 - <Image 56 - src={BlackskyLogoWhite.src} 57 - alt="Blacksky logo" 58 - w={18} 59 - h={'auto'} 60 - lightHidden 61 - /> 62 - </> 63 - ); 33 + const platformIcon = <BlueskyPlatformIcon platform={platform.type} />; 64 34 65 35 if ( 66 36 !data.thread ||
+1 -1
src/webapp/next-env.d.ts
··· 1 1 /// <reference types="next" /> 2 2 /// <reference types="next/image-types/global" /> 3 - import "./.next/types/routes.d.ts"; 3 + import "./.next/dev/types/routes.d.ts"; 4 4 5 5 // NOTE: This file should not be edited 6 6 // see https://nextjs.org/docs/app/api-reference/config/typescript for more information.