mirror of https://git.lenooby09.tech/LeNooby09/social-app.git
0
fork

Configure Feed

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

Add error boundary and ATProto Embed

authored by

Paul Frazee and committed by danabra.mov 5e14462a 18b7c466

+126 -8
+1
package.json
··· 165 165 "react-avatar-editor": "^13.0.0", 166 166 "react-compiler-runtime": "file:./lib/react-compiler-runtime", 167 167 "react-dom": "^18.2.0", 168 + "react-error-boundary": "^4.0.13", 168 169 "react-keyed-flatten-children": "^3.0.0", 169 170 "react-native": "0.74.1", 170 171 "react-native-compressor": "^1.8.24",
+59
src/components/appcom/vocabulary/Embed.tsx
··· 1 + import React from 'react' 2 + import {View} from 'react-native' 3 + import {AtUri} from '@atproto/api' 4 + import {z} from 'zod' 5 + 6 + import {usePostQuery} from '#/state/queries/post' 7 + import {useProfileQuery} from '#/state/queries/profile' 8 + import {useResolveDidQuery} from '#/state/queries/resolve-uri' 9 + import {Post as PostInner} from '#/view/com/post/Post' 10 + import {ProfileCardWithFollowBtn} from '#/view/com/profile/ProfileCard' 11 + import {Text} from '#/components/Typography' 12 + 13 + const embedProps = z.object({ 14 + uri: z.string(), 15 + }) 16 + 17 + export type ProfileCardProps = z.infer<typeof embedProps> 18 + 19 + export function Embed(props: React.PropsWithChildren<ProfileCardProps>) { 20 + const propsParsed = embedProps.parse(props) 21 + const urip = new AtUri(propsParsed.uri) 22 + console.log(urip) 23 + 24 + if (!urip.pathname || urip.pathname === '/') { 25 + return <Actor actor={urip.host} /> 26 + } 27 + if (urip.collection === 'app.bsky.feed.post') { 28 + return <Post uri={urip.toString()} /> 29 + } 30 + return <Unknown urip={urip} /> 31 + } 32 + 33 + function Actor({actor}: {actor: string}) { 34 + const {data: did} = useResolveDidQuery(actor) 35 + const {data: profile} = useProfileQuery({did}) 36 + 37 + if (profile) { 38 + return <ProfileCardWithFollowBtn noBg noBorder profile={profile} /> 39 + } 40 + // TODO error, loading 41 + return <View /> 42 + } 43 + 44 + function Post({uri}: {uri: string}) { 45 + const {data: post} = usePostQuery(uri) 46 + if (post) { 47 + return <PostInner post={post} hideTopBorder /> 48 + } 49 + // TODO error, loading 50 + return <View /> 51 + } 52 + 53 + function Unknown({urip}: {urip: AtUri}) { 54 + return ( 55 + <View style={{paddingVertical: 10, paddingHorizontal: 15}}> 56 + <Text>Unsupported record type: {urip.collection}</Text> 57 + </View> 58 + ) 59 + }
+26 -7
src/components/appcom/vocabulary/index.tsx
··· 1 1 import React from 'react' 2 + import {View} from 'react-native' 3 + import {ErrorBoundary} from 'react-error-boundary' 4 + import {ZodError} from 'zod' 2 5 6 + import {Text} from '#/components/Typography' 3 7 import type {AppComNode} from '../types' 4 8 import {Box} from './Box' 9 + import {Embed} from './Embed' 5 10 import {Expandable} from './Expandable' 6 11 import {Label} from './Label' 7 12 import {Stack} from './Stack' ··· 9 14 10 15 export const VOCAB: Record<string, React.ComponentType<any>> = { 11 16 Box, 17 + Embed, 12 18 Expandable, 13 19 Label, 14 20 Stack, ··· 22 28 return <></> 23 29 } 24 30 return ( 25 - <Com {...node.props}> 26 - {node.children?.length 27 - ? node.children.map((child, i) => ( 28 - <AppComponent key={child.key || String(i)} node={child} /> 29 - )) 30 - : null} 31 - </Com> 31 + <ErrorBoundary fallbackRender={fallbackRender}> 32 + <Com {...node.props}> 33 + {node.children?.length 34 + ? node.children.map((child, i) => ( 35 + <AppComponent key={child.key || String(i)} node={child} /> 36 + )) 37 + : null} 38 + </Com> 39 + </ErrorBoundary> 40 + ) 41 + } 42 + function fallbackRender({error}: {error: Error}) { 43 + const msg = 44 + error instanceof ZodError 45 + ? `${error.issues[0].path.join('.')}: ${error.issues[0].message}` 46 + : error.toString() 47 + return ( 48 + <View> 49 + <Text>{msg}</Text> 50 + </View> 32 51 ) 33 52 }
+33 -1
src/view/screens/DebugAppcom.tsx
··· 74 74 h('Label', {text: 'Display TODO'}), 75 75 h('Label', {text: 'Inputs TODO'}), 76 76 h('Label', {text: 'Forms TODO'}), 77 - h('Label', {text: 'ATProto TODO'}), 77 + h('Stack', {gap: 10, pad: {t: 20}}, [ 78 + h('Box', {pad: {x: 10}}, [ 79 + h('Label', {text: 'Embed (Actor)', size: 10, weight: 'bold'}), 80 + ]), 81 + h('Box', {border: 'secondary', corner: 8}, [ 82 + h('Embed', {uri: 'bsky.app'}), 83 + ]), 84 + h('Box', {border: 'secondary', corner: 8}, [ 85 + h('Embed', {uri: 'at://atproto.com/'}), 86 + ]), 87 + h('Box', {border: 'secondary', corner: 8}, [ 88 + h('Embed', {uri: 'at://pfrazee.com'}), 89 + ]), 90 + h('Box', {pad: {x: 10}}, [ 91 + h('Label', {text: 'Embed (Post)', size: 10, weight: 'bold'}), 92 + ]), 93 + h('Box', {border: 'secondary', corner: 8}, [ 94 + h('Embed', {uri: 'at://pfrazee.com/app.bsky.feed.post/3ku7fbojcqs25'}), 95 + ]), 96 + h('Box', {border: 'secondary', corner: 8}, [ 97 + h('Embed', {uri: 'at://bsky.app/app.bsky.feed.post/3ku73zs755e27'}), 98 + ]), 99 + h('Box', {pad: {x: 10}}, [ 100 + h('Label', { 101 + text: 'Embed (Unsupported record type)', 102 + size: 10, 103 + weight: 'bold', 104 + }), 105 + ]), 106 + h('Box', {border: 'secondary', corner: 8}, [ 107 + h('Embed', {uri: 'at://pfrazee.com/com.example.unknown/123'}), 108 + ]), 109 + ]), 78 110 ]), 79 111 ]) 80 112
+7
yarn.lock
··· 18820 18820 loose-envify "^1.1.0" 18821 18821 scheduler "^0.23.0" 18822 18822 18823 + react-error-boundary@^4.0.13: 18824 + version "4.0.13" 18825 + resolved "https://registry.yarnpkg.com/react-error-boundary/-/react-error-boundary-4.0.13.tgz#80386b7b27b1131c5fbb7368b8c0d983354c7947" 18826 + integrity sha512-b6PwbdSv8XeOSYvjt8LpgpKrZ0yGdtZokYwkwV2wlcZbxgopHX/hgPl5VgpnoVOWd868n1hktM8Qm4b+02MiLQ== 18827 + dependencies: 18828 + "@babel/runtime" "^7.12.5" 18829 + 18823 18830 react-error-overlay@^6.0.11: 18824 18831 version "6.0.11" 18825 18832 resolved "https://registry.yarnpkg.com/react-error-overlay/-/react-error-overlay-6.0.11.tgz#92835de5841c5cf08ba00ddd2d677b6d17ff9adb"